]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/net/ibm_emac/ibm_emac_rgmii.c
53d281cb9a16a3eb67c48a90611ddf57b8185584
[linux-2.6.git] / drivers / net / ibm_emac / ibm_emac_rgmii.c
1 /*
2  * drivers/net/ibm_emac/ibm_emac_rgmii.c
3  *
4  * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
5  *
6  * Copyright (c) 2004, 2005 Zultys Technologies.
7  * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
8  *
9  * Based on original work by
10  *      Matt Porter <mporter@kernel.crashing.org>
11  *      Copyright 2004 MontaVista Software, Inc.
12  * 
13  * This program is free software; you can redistribute  it and/or modify it
14  * under  the terms of  the GNU General  Public License as published by the
15  * Free Software Foundation;  either version 2 of the  License, or (at your
16  * option) any later version.
17  *
18  */
19 #include <linux/kernel.h>
20 #include <linux/ethtool.h>
21 #include <asm/io.h>
22
23 #include "ibm_emac_core.h"
24 #include "ibm_emac_debug.h"
25
26 /* RGMIIx_FER */
27 #define RGMII_FER_MASK(idx)     (0x7 << ((idx) * 4))
28 #define RGMII_FER_RTBI(idx)     (0x4 << ((idx) * 4))
29 #define RGMII_FER_RGMII(idx)    (0x5 << ((idx) * 4))
30 #define RGMII_FER_TBI(idx)      (0x6 << ((idx) * 4))
31 #define RGMII_FER_GMII(idx)     (0x7 << ((idx) * 4))
32
33 /* RGMIIx_SSR */
34 #define RGMII_SSR_MASK(idx)     (0x7 << ((idx) * 8))
35 #define RGMII_SSR_100(idx)      (0x2 << ((idx) * 8))
36 #define RGMII_SSR_1000(idx)     (0x4 << ((idx) * 8))
37
38 /* RGMII bridge supports only GMII/TBI and RGMII/RTBI PHYs */
39 static inline int rgmii_valid_mode(int phy_mode)
40 {
41         return  phy_mode == PHY_MODE_GMII ||
42                 phy_mode == PHY_MODE_RGMII ||
43                 phy_mode == PHY_MODE_TBI ||
44                 phy_mode == PHY_MODE_RTBI;
45 }
46
47 static inline const char *rgmii_mode_name(int mode)
48 {
49         switch (mode) {
50         case PHY_MODE_RGMII:
51                 return "RGMII";
52         case PHY_MODE_TBI:
53                 return "TBI";
54         case PHY_MODE_GMII:
55                 return "GMII";
56         case PHY_MODE_RTBI:
57                 return "RTBI";
58         default:
59                 BUG();
60         }
61 }
62
63 static inline u32 rgmii_mode_mask(int mode, int input)
64 {
65         switch (mode) {
66         case PHY_MODE_RGMII:
67                 return RGMII_FER_RGMII(input);
68         case PHY_MODE_TBI:
69                 return RGMII_FER_TBI(input);
70         case PHY_MODE_GMII:
71                 return RGMII_FER_GMII(input);
72         case PHY_MODE_RTBI:
73                 return RGMII_FER_RTBI(input);
74         default:
75                 BUG();
76         }
77 }
78
79 static int __init rgmii_init(struct ocp_device *ocpdev, int input, int mode)
80 {
81         struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
82         struct rgmii_regs *p;
83
84         RGMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, mode);
85
86         if (!dev) {
87                 dev = kzalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL);
88                 if (!dev) {
89                         printk(KERN_ERR
90                                "rgmii%d: couldn't allocate device structure!\n",
91                                ocpdev->def->index);
92                         return -ENOMEM;
93                 }
94
95                 p = (struct rgmii_regs *)ioremap(ocpdev->def->paddr,
96                                                  sizeof(struct rgmii_regs));
97                 if (!p) {
98                         printk(KERN_ERR
99                                "rgmii%d: could not ioremap device registers!\n",
100                                ocpdev->def->index);
101                         kfree(dev);
102                         return -ENOMEM;
103                 }
104
105                 dev->base = p;
106                 ocp_set_drvdata(ocpdev, dev);
107
108                 /* Disable all inputs by default */
109                 out_be32(&p->fer, 0);
110         } else
111                 p = dev->base;
112
113         /* Enable this input */
114         out_be32(&p->fer, in_be32(&p->fer) | rgmii_mode_mask(mode, input));
115
116         printk(KERN_NOTICE "rgmii%d: input %d in %s mode\n",
117                ocpdev->def->index, input, rgmii_mode_name(mode));
118
119         ++dev->users;
120         return 0;
121 }
122
123 int __init rgmii_attach(void *emac)
124 {
125         struct ocp_enet_private *dev = emac;
126         struct ocp_func_emac_data *emacdata = dev->def->additions;
127
128         /* Check if we need to attach to a RGMII */
129         if (emacdata->rgmii_idx >= 0 && rgmii_valid_mode(emacdata->phy_mode)) {
130                 dev->rgmii_input = emacdata->rgmii_mux;
131                 dev->rgmii_dev =
132                     ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_RGMII,
133                                     emacdata->rgmii_idx);
134                 if (!dev->rgmii_dev) {
135                         printk(KERN_ERR "emac%d: unknown rgmii%d!\n",
136                                dev->def->index, emacdata->rgmii_idx);
137                         return -ENODEV;
138                 }
139                 if (rgmii_init
140                     (dev->rgmii_dev, dev->rgmii_input, emacdata->phy_mode)) {
141                         printk(KERN_ERR
142                                "emac%d: rgmii%d initialization failed!\n",
143                                dev->def->index, emacdata->rgmii_idx);
144                         return -ENODEV;
145                 }
146         }
147         return 0;
148 }
149
150 void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed)
151 {
152         struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
153         u32 ssr = in_be32(&dev->base->ssr) & ~RGMII_SSR_MASK(input);
154
155         RGMII_DBG("%d: speed(%d, %d)" NL, ocpdev->def->index, input, speed);
156
157         if (speed == SPEED_1000)
158                 ssr |= RGMII_SSR_1000(input);
159         else if (speed == SPEED_100)
160                 ssr |= RGMII_SSR_100(input);
161
162         out_be32(&dev->base->ssr, ssr);
163 }
164
165 void __exit __rgmii_fini(struct ocp_device *ocpdev, int input)
166 {
167         struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
168         BUG_ON(!dev || dev->users == 0);
169
170         RGMII_DBG("%d: fini(%d)" NL, ocpdev->def->index, input);
171
172         /* Disable this input */
173         out_be32(&dev->base->fer,
174                  in_be32(&dev->base->fer) & ~RGMII_FER_MASK(input));
175
176         if (!--dev->users) {
177                 /* Free everything if this is the last user */
178                 ocp_set_drvdata(ocpdev, NULL);
179                 iounmap((void *)dev->base);
180                 kfree(dev);
181         }
182 }
183
184 int __rgmii_get_regs_len(struct ocp_device *ocpdev)
185 {
186         return sizeof(struct emac_ethtool_regs_subhdr) +
187             sizeof(struct rgmii_regs);
188 }
189
190 void *rgmii_dump_regs(struct ocp_device *ocpdev, void *buf)
191 {
192         struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
193         struct emac_ethtool_regs_subhdr *hdr = buf;
194         struct rgmii_regs *regs = (struct rgmii_regs *)(hdr + 1);
195
196         hdr->version = 0;
197         hdr->index = ocpdev->def->index;
198         memcpy_fromio(regs, dev->base, sizeof(struct rgmii_regs));
199         return regs + 1;
200 }