diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-05-13 17:29:12 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-08-11 05:41:59 -0400 |
commit | 9aa3283595451ca093500ff0977b106e1f465586 (patch) | |
tree | 89cd128f037b029b67f73fbff7d8cc38177c2b27 /drivers/net/ethernet/ibm/emac/rgmii.c | |
parent | 86387e1ac4fcaa45ff5578013a78593d1a0ba279 (diff) |
ehea/ibm*: Move the IBM drivers
Move the IBM drivers into drivers/net/ethernet/ibm/ and make the
necessary Kconfig and Makefile changes.
- Renamed ibm_new_emac to emac
- Cleaned up Makefile and Kconfig options which referred to
IBM_NEW_EMAC to IBM_EMAC
- ibmlana driver is a National Semiconductor SONIC driver so
it was not moved
CC: Christoph Raisch <raisch@de.ibm.com>
CC: Santiago Leon <santil@linux.vnet.ibm.com>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: David Gibson <dwg@au1.ibm.com>
CC: Kyle Lucke <klucke@us.ibm.com>
CC: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/ibm/emac/rgmii.c')
-rw-r--r-- | drivers/net/ethernet/ibm/emac/rgmii.c | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c new file mode 100644 index 000000000000..4fa53f3def64 --- /dev/null +++ b/drivers/net/ethernet/ibm/emac/rgmii.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /* | ||
2 | * drivers/net/ibm_newemac/rgmii.c | ||
3 | * | ||
4 | * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support. | ||
5 | * | ||
6 | * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. | ||
7 | * <benh@kernel.crashing.org> | ||
8 | * | ||
9 | * Based on the arch/ppc version of the driver: | ||
10 | * | ||
11 | * Copyright (c) 2004, 2005 Zultys Technologies. | ||
12 | * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | ||
13 | * | ||
14 | * Based on original work by | ||
15 | * Matt Porter <mporter@kernel.crashing.org> | ||
16 | * Copyright 2004 MontaVista Software, Inc. | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or modify it | ||
19 | * under the terms of the GNU General Public License as published by the | ||
20 | * Free Software Foundation; either version 2 of the License, or (at your | ||
21 | * option) any later version. | ||
22 | * | ||
23 | */ | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/ethtool.h> | ||
27 | #include <asm/io.h> | ||
28 | |||
29 | #include "emac.h" | ||
30 | #include "debug.h" | ||
31 | |||
32 | // XXX FIXME: Axon seems to support a subset of the RGMII, we | ||
33 | // thus need to take that into account and possibly change some | ||
34 | // of the bit settings below that don't seem to quite match the | ||
35 | // AXON spec | ||
36 | |||
37 | /* RGMIIx_FER */ | ||
38 | #define RGMII_FER_MASK(idx) (0x7 << ((idx) * 4)) | ||
39 | #define RGMII_FER_RTBI(idx) (0x4 << ((idx) * 4)) | ||
40 | #define RGMII_FER_RGMII(idx) (0x5 << ((idx) * 4)) | ||
41 | #define RGMII_FER_TBI(idx) (0x6 << ((idx) * 4)) | ||
42 | #define RGMII_FER_GMII(idx) (0x7 << ((idx) * 4)) | ||
43 | #define RGMII_FER_MII(idx) RGMII_FER_GMII(idx) | ||
44 | |||
45 | /* RGMIIx_SSR */ | ||
46 | #define RGMII_SSR_MASK(idx) (0x7 << ((idx) * 8)) | ||
47 | #define RGMII_SSR_100(idx) (0x2 << ((idx) * 8)) | ||
48 | #define RGMII_SSR_1000(idx) (0x4 << ((idx) * 8)) | ||
49 | |||
50 | /* RGMII bridge supports only GMII/TBI and RGMII/RTBI PHYs */ | ||
51 | static inline int rgmii_valid_mode(int phy_mode) | ||
52 | { | ||
53 | return phy_mode == PHY_MODE_GMII || | ||
54 | phy_mode == PHY_MODE_MII || | ||
55 | phy_mode == PHY_MODE_RGMII || | ||
56 | phy_mode == PHY_MODE_TBI || | ||
57 | phy_mode == PHY_MODE_RTBI; | ||
58 | } | ||
59 | |||
60 | static inline const char *rgmii_mode_name(int mode) | ||
61 | { | ||
62 | switch (mode) { | ||
63 | case PHY_MODE_RGMII: | ||
64 | return "RGMII"; | ||
65 | case PHY_MODE_TBI: | ||
66 | return "TBI"; | ||
67 | case PHY_MODE_GMII: | ||
68 | return "GMII"; | ||
69 | case PHY_MODE_MII: | ||
70 | return "MII"; | ||
71 | case PHY_MODE_RTBI: | ||
72 | return "RTBI"; | ||
73 | default: | ||
74 | BUG(); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | static inline u32 rgmii_mode_mask(int mode, int input) | ||
79 | { | ||
80 | switch (mode) { | ||
81 | case PHY_MODE_RGMII: | ||
82 | return RGMII_FER_RGMII(input); | ||
83 | case PHY_MODE_TBI: | ||
84 | return RGMII_FER_TBI(input); | ||
85 | case PHY_MODE_GMII: | ||
86 | return RGMII_FER_GMII(input); | ||
87 | case PHY_MODE_MII: | ||
88 | return RGMII_FER_MII(input); | ||
89 | case PHY_MODE_RTBI: | ||
90 | return RGMII_FER_RTBI(input); | ||
91 | default: | ||
92 | BUG(); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | int __devinit rgmii_attach(struct platform_device *ofdev, int input, int mode) | ||
97 | { | ||
98 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | ||
99 | struct rgmii_regs __iomem *p = dev->base; | ||
100 | |||
101 | RGMII_DBG(dev, "attach(%d)" NL, input); | ||
102 | |||
103 | /* Check if we need to attach to a RGMII */ | ||
104 | if (input < 0 || !rgmii_valid_mode(mode)) { | ||
105 | printk(KERN_ERR "%s: unsupported settings !\n", | ||
106 | ofdev->dev.of_node->full_name); | ||
107 | return -ENODEV; | ||
108 | } | ||
109 | |||
110 | mutex_lock(&dev->lock); | ||
111 | |||
112 | /* Enable this input */ | ||
113 | out_be32(&p->fer, in_be32(&p->fer) | rgmii_mode_mask(mode, input)); | ||
114 | |||
115 | printk(KERN_NOTICE "%s: input %d in %s mode\n", | ||
116 | ofdev->dev.of_node->full_name, input, rgmii_mode_name(mode)); | ||
117 | |||
118 | ++dev->users; | ||
119 | |||
120 | mutex_unlock(&dev->lock); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | void rgmii_set_speed(struct platform_device *ofdev, int input, int speed) | ||
126 | { | ||
127 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | ||
128 | struct rgmii_regs __iomem *p = dev->base; | ||
129 | u32 ssr; | ||
130 | |||
131 | mutex_lock(&dev->lock); | ||
132 | |||
133 | ssr = in_be32(&p->ssr) & ~RGMII_SSR_MASK(input); | ||
134 | |||
135 | RGMII_DBG(dev, "speed(%d, %d)" NL, input, speed); | ||
136 | |||
137 | if (speed == SPEED_1000) | ||
138 | ssr |= RGMII_SSR_1000(input); | ||
139 | else if (speed == SPEED_100) | ||
140 | ssr |= RGMII_SSR_100(input); | ||
141 | |||
142 | out_be32(&p->ssr, ssr); | ||
143 | |||
144 | mutex_unlock(&dev->lock); | ||
145 | } | ||
146 | |||
147 | void rgmii_get_mdio(struct platform_device *ofdev, int input) | ||
148 | { | ||
149 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | ||
150 | struct rgmii_regs __iomem *p = dev->base; | ||
151 | u32 fer; | ||
152 | |||
153 | RGMII_DBG2(dev, "get_mdio(%d)" NL, input); | ||
154 | |||
155 | if (!(dev->flags & EMAC_RGMII_FLAG_HAS_MDIO)) | ||
156 | return; | ||
157 | |||
158 | mutex_lock(&dev->lock); | ||
159 | |||
160 | fer = in_be32(&p->fer); | ||
161 | fer |= 0x00080000u >> input; | ||
162 | out_be32(&p->fer, fer); | ||
163 | (void)in_be32(&p->fer); | ||
164 | |||
165 | DBG2(dev, " fer = 0x%08x\n", fer); | ||
166 | } | ||
167 | |||
168 | void rgmii_put_mdio(struct platform_device *ofdev, int input) | ||
169 | { | ||
170 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | ||
171 | struct rgmii_regs __iomem *p = dev->base; | ||
172 | u32 fer; | ||
173 | |||
174 | RGMII_DBG2(dev, "put_mdio(%d)" NL, input); | ||
175 | |||
176 | if (!(dev->flags & EMAC_RGMII_FLAG_HAS_MDIO)) | ||
177 | return; | ||
178 | |||
179 | fer = in_be32(&p->fer); | ||
180 | fer &= ~(0x00080000u >> input); | ||
181 | out_be32(&p->fer, fer); | ||
182 | (void)in_be32(&p->fer); | ||
183 | |||
184 | DBG2(dev, " fer = 0x%08x\n", fer); | ||
185 | |||
186 | mutex_unlock(&dev->lock); | ||
187 | } | ||
188 | |||
189 | void rgmii_detach(struct platform_device *ofdev, int input) | ||
190 | { | ||
191 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | ||
192 | struct rgmii_regs __iomem *p; | ||
193 | |||
194 | BUG_ON(!dev || dev->users == 0); | ||
195 | p = dev->base; | ||
196 | |||
197 | mutex_lock(&dev->lock); | ||
198 | |||
199 | RGMII_DBG(dev, "detach(%d)" NL, input); | ||
200 | |||
201 | /* Disable this input */ | ||
202 | out_be32(&p->fer, in_be32(&p->fer) & ~RGMII_FER_MASK(input)); | ||
203 | |||
204 | --dev->users; | ||
205 | |||
206 | mutex_unlock(&dev->lock); | ||
207 | } | ||
208 | |||
209 | int rgmii_get_regs_len(struct platform_device *ofdev) | ||
210 | { | ||
211 | return sizeof(struct emac_ethtool_regs_subhdr) + | ||
212 | sizeof(struct rgmii_regs); | ||
213 | } | ||
214 | |||
215 | void *rgmii_dump_regs(struct platform_device *ofdev, void *buf) | ||
216 | { | ||
217 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | ||
218 | struct emac_ethtool_regs_subhdr *hdr = buf; | ||
219 | struct rgmii_regs *regs = (struct rgmii_regs *)(hdr + 1); | ||
220 | |||
221 | hdr->version = 0; | ||
222 | hdr->index = 0; /* for now, are there chips with more than one | ||
223 | * rgmii ? if yes, then we'll add a cell_index | ||
224 | * like we do for emac | ||
225 | */ | ||
226 | memcpy_fromio(regs, dev->base, sizeof(struct rgmii_regs)); | ||
227 | return regs + 1; | ||
228 | } | ||
229 | |||
230 | |||
231 | static int __devinit rgmii_probe(struct platform_device *ofdev) | ||
232 | { | ||
233 | struct device_node *np = ofdev->dev.of_node; | ||
234 | struct rgmii_instance *dev; | ||
235 | struct resource regs; | ||
236 | int rc; | ||
237 | |||
238 | rc = -ENOMEM; | ||
239 | dev = kzalloc(sizeof(struct rgmii_instance), GFP_KERNEL); | ||
240 | if (dev == NULL) { | ||
241 | printk(KERN_ERR "%s: could not allocate RGMII device!\n", | ||
242 | np->full_name); | ||
243 | goto err_gone; | ||
244 | } | ||
245 | |||
246 | mutex_init(&dev->lock); | ||
247 | dev->ofdev = ofdev; | ||
248 | |||
249 | rc = -ENXIO; | ||
250 | if (of_address_to_resource(np, 0, ®s)) { | ||
251 | printk(KERN_ERR "%s: Can't get registers address\n", | ||
252 | np->full_name); | ||
253 | goto err_free; | ||
254 | } | ||
255 | |||
256 | rc = -ENOMEM; | ||
257 | dev->base = (struct rgmii_regs __iomem *)ioremap(regs.start, | ||
258 | sizeof(struct rgmii_regs)); | ||
259 | if (dev->base == NULL) { | ||
260 | printk(KERN_ERR "%s: Can't map device registers!\n", | ||
261 | np->full_name); | ||
262 | goto err_free; | ||
263 | } | ||
264 | |||
265 | /* Check for RGMII flags */ | ||
266 | if (of_get_property(ofdev->dev.of_node, "has-mdio", NULL)) | ||
267 | dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO; | ||
268 | |||
269 | /* CAB lacks the right properties, fix this up */ | ||
270 | if (of_device_is_compatible(ofdev->dev.of_node, "ibm,rgmii-axon")) | ||
271 | dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO; | ||
272 | |||
273 | DBG2(dev, " Boot FER = 0x%08x, SSR = 0x%08x\n", | ||
274 | in_be32(&dev->base->fer), in_be32(&dev->base->ssr)); | ||
275 | |||
276 | /* Disable all inputs by default */ | ||
277 | out_be32(&dev->base->fer, 0); | ||
278 | |||
279 | printk(KERN_INFO | ||
280 | "RGMII %s initialized with%s MDIO support\n", | ||
281 | ofdev->dev.of_node->full_name, | ||
282 | (dev->flags & EMAC_RGMII_FLAG_HAS_MDIO) ? "" : "out"); | ||
283 | |||
284 | wmb(); | ||
285 | dev_set_drvdata(&ofdev->dev, dev); | ||
286 | |||
287 | return 0; | ||
288 | |||
289 | err_free: | ||
290 | kfree(dev); | ||
291 | err_gone: | ||
292 | return rc; | ||
293 | } | ||
294 | |||
295 | static int __devexit rgmii_remove(struct platform_device *ofdev) | ||
296 | { | ||
297 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | ||
298 | |||
299 | dev_set_drvdata(&ofdev->dev, NULL); | ||
300 | |||
301 | WARN_ON(dev->users != 0); | ||
302 | |||
303 | iounmap(dev->base); | ||
304 | kfree(dev); | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static struct of_device_id rgmii_match[] = | ||
310 | { | ||
311 | { | ||
312 | .compatible = "ibm,rgmii", | ||
313 | }, | ||
314 | { | ||
315 | .type = "emac-rgmii", | ||
316 | }, | ||
317 | {}, | ||
318 | }; | ||
319 | |||
320 | static struct platform_driver rgmii_driver = { | ||
321 | .driver = { | ||
322 | .name = "emac-rgmii", | ||
323 | .owner = THIS_MODULE, | ||
324 | .of_match_table = rgmii_match, | ||
325 | }, | ||
326 | .probe = rgmii_probe, | ||
327 | .remove = rgmii_remove, | ||
328 | }; | ||
329 | |||
330 | int __init rgmii_init(void) | ||
331 | { | ||
332 | return platform_driver_register(&rgmii_driver); | ||
333 | } | ||
334 | |||
335 | void rgmii_exit(void) | ||
336 | { | ||
337 | platform_driver_unregister(&rgmii_driver); | ||
338 | } | ||