aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Fleming <afleming@freescale.com>2009-02-04 19:42:12 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-04 19:42:35 -0500
commit1577ecef766650a57fceb171acee2b13cbfaf1d3 (patch)
treeb66df11d8815f95f815e65c3c3ffd32df81b8d43
parent9c46f6d42f1b5627c49a5906cb5b315ad8716ff0 (diff)
netdev: Merge UCC and gianfar MDIO bus drivers
The MDIO bus drivers for the UCC and gianfar ethernet controllers are essentially the same. There's no reason to duplicate that much code. Signed-off-by: Andy Fleming <afleming@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/Kconfig9
-rw-r--r--drivers/net/Makefile5
-rw-r--r--drivers/net/fsl_pq_mdio.c463
-rw-r--r--drivers/net/fsl_pq_mdio.h45
-rw-r--r--drivers/net/gianfar.c23
-rw-r--r--drivers/net/gianfar.h13
-rw-r--r--drivers/net/gianfar_mii.h54
-rw-r--r--drivers/net/ucc_geth.c16
-rw-r--r--drivers/net/ucc_geth.h14
-rw-r--r--drivers/net/ucc_geth_ethtool.c1
-rw-r--r--drivers/net/ucc_geth_mii.c295
-rw-r--r--drivers/net/ucc_geth_mii.h101
12 files changed, 549 insertions, 490 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 49f4d50abc56..62bc0223a8ed 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2272,9 +2272,17 @@ config GELIC_WIRELESS_OLD_PSK_INTERFACE
2272 2272
2273 If unsure, say N. 2273 If unsure, say N.
2274 2274
2275config FSL_PQ_MDIO
2276 tristate "Freescale PQ MDIO"
2277 depends on FSL_SOC
2278 select PHYLIB
2279 help
2280 This driver supports the MDIO bus used by the gianfar and UCC drivers.
2281
2275config GIANFAR 2282config GIANFAR
2276 tristate "Gianfar Ethernet" 2283 tristate "Gianfar Ethernet"
2277 depends on FSL_SOC 2284 depends on FSL_SOC
2285 select FSL_PQ_MDIO
2278 select PHYLIB 2286 select PHYLIB
2279 select CRC32 2287 select CRC32
2280 help 2288 help
@@ -2284,6 +2292,7 @@ config GIANFAR
2284config UCC_GETH 2292config UCC_GETH
2285 tristate "Freescale QE Gigabit Ethernet" 2293 tristate "Freescale QE Gigabit Ethernet"
2286 depends on QUICC_ENGINE 2294 depends on QUICC_ENGINE
2295 select FSL_PQ_MDIO
2287 select PHYLIB 2296 select PHYLIB
2288 help 2297 help
2289 This driver supports the Gigabit Ethernet mode of the QUICC Engine, 2298 This driver supports the Gigabit Ethernet mode of the QUICC Engine,
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a3c5c002f224..ad87ba72cf1f 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -24,11 +24,12 @@ obj-$(CONFIG_JME) += jme.o
24 24
25gianfar_driver-objs := gianfar.o \ 25gianfar_driver-objs := gianfar.o \
26 gianfar_ethtool.o \ 26 gianfar_ethtool.o \
27 gianfar_mii.o \
28 gianfar_sysfs.o 27 gianfar_sysfs.o
29 28
30obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o 29obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
31ucc_geth_driver-objs := ucc_geth.o ucc_geth_mii.o ucc_geth_ethtool.o 30ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
31
32obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o
32 33
33# 34#
34# link order important here 35# link order important here
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c
new file mode 100644
index 000000000000..c434a156d7a9
--- /dev/null
+++ b/drivers/net/fsl_pq_mdio.c
@@ -0,0 +1,463 @@
1/*
2 * Freescale PowerQUICC Ethernet Driver -- MIIM bus implementation
3 * Provides Bus interface for MIIM regs
4 *
5 * Author: Andy Fleming <afleming@freescale.com>
6 *
7 * Copyright (c) 2002-2004,2008 Freescale Semiconductor, Inc.
8 *
9 * Based on gianfar_mii.c and ucc_geth_mii.c (Li Yang, Kim Phillips)
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 */
17
18#include <linux/kernel.h>
19#include <linux/string.h>
20#include <linux/errno.h>
21#include <linux/unistd.h>
22#include <linux/slab.h>
23#include <linux/interrupt.h>
24#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/netdevice.h>
27#include <linux/etherdevice.h>
28#include <linux/skbuff.h>
29#include <linux/spinlock.h>
30#include <linux/mm.h>
31#include <linux/module.h>
32#include <linux/platform_device.h>
33#include <linux/crc32.h>
34#include <linux/mii.h>
35#include <linux/phy.h>
36#include <linux/of.h>
37#include <linux/of_platform.h>
38
39#include <asm/io.h>
40#include <asm/irq.h>
41#include <asm/uaccess.h>
42#include <asm/ucc.h>
43
44#include "gianfar.h"
45#include "fsl_pq_mdio.h"
46
47/*
48 * Write value to the PHY at mii_id at register regnum,
49 * on the bus attached to the local interface, which may be different from the
50 * generic mdio bus (tied to a single interface), waiting until the write is
51 * done before returning. This is helpful in programming interfaces like
52 * the TBI which control interfaces like onchip SERDES and are always tied to
53 * the local mdio pins, which may not be the same as system mdio bus, used for
54 * controlling the external PHYs, for example.
55 */
56int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id,
57 int regnum, u16 value)
58{
59 /* Set the PHY address and the register address we want to write */
60 out_be32(&regs->miimadd, (mii_id << 8) | regnum);
61
62 /* Write out the value we want */
63 out_be32(&regs->miimcon, value);
64
65 /* Wait for the transaction to finish */
66 while (in_be32(&regs->miimind) & MIIMIND_BUSY)
67 cpu_relax();
68
69 return 0;
70}
71
72/*
73 * Read the bus for PHY at addr mii_id, register regnum, and
74 * return the value. Clears miimcom first. All PHY operation
75 * done on the bus attached to the local interface,
76 * which may be different from the generic mdio bus
77 * This is helpful in programming interfaces like
78 * the TBI which, in turn, control interfaces like onchip SERDES
79 * and are always tied to the local mdio pins, which may not be the
80 * same as system mdio bus, used for controlling the external PHYs, for eg.
81 */
82int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs,
83 int mii_id, int regnum)
84{
85 u16 value;
86
87 /* Set the PHY address and the register address we want to read */
88 out_be32(&regs->miimadd, (mii_id << 8) | regnum);
89
90 /* Clear miimcom, and then initiate a read */
91 out_be32(&regs->miimcom, 0);
92 out_be32(&regs->miimcom, MII_READ_COMMAND);
93
94 /* Wait for the transaction to finish */
95 while (in_be32(&regs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
96 cpu_relax();
97
98 /* Grab the value of the register from miimstat */
99 value = in_be32(&regs->miimstat);
100
101 return value;
102}
103
104/*
105 * Write value to the PHY at mii_id at register regnum,
106 * on the bus, waiting until the write is done before returning.
107 */
108int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
109{
110 struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv;
111
112 /* Write to the local MII regs */
113 return(fsl_pq_local_mdio_write(regs, mii_id, regnum, value));
114}
115
116/*
117 * Read the bus for PHY at addr mii_id, register regnum, and
118 * return the value. Clears miimcom first.
119 */
120int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
121{
122 struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv;
123
124 /* Read the local MII regs */
125 return(fsl_pq_local_mdio_read(regs, mii_id, regnum));
126}
127
128/* Reset the MIIM registers, and wait for the bus to free */
129static int fsl_pq_mdio_reset(struct mii_bus *bus)
130{
131 struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv;
132 unsigned int timeout = PHY_INIT_TIMEOUT;
133
134 mutex_lock(&bus->mdio_lock);
135
136 /* Reset the management interface */
137 out_be32(&regs->miimcfg, MIIMCFG_RESET);
138
139 /* Setup the MII Mgmt clock speed */
140 out_be32(&regs->miimcfg, MIIMCFG_INIT_VALUE);
141
142 /* Wait until the bus is free */
143 while ((in_be32(&regs->miimind) & MIIMIND_BUSY) && timeout--)
144 cpu_relax();
145
146 mutex_unlock(&bus->mdio_lock);
147
148 if(timeout == 0) {
149 printk(KERN_ERR "%s: The MII Bus is stuck!\n",
150 bus->name);
151 return -EBUSY;
152 }
153
154 return 0;
155}
156
157/* Allocate an array which provides irq #s for each PHY on the given bus */
158static int *create_irq_map(struct device_node *np)
159{
160 int *irqs;
161 int i;
162 struct device_node *child = NULL;
163
164 irqs = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
165
166 if (!irqs)
167 return NULL;
168
169 for (i = 0; i < PHY_MAX_ADDR; i++)
170 irqs[i] = PHY_POLL;
171
172 while ((child = of_get_next_child(np, child)) != NULL) {
173 int irq = irq_of_parse_and_map(child, 0);
174 const u32 *id;
175
176 if (irq == NO_IRQ)
177 continue;
178
179 id = of_get_property(child, "reg", NULL);
180
181 if (!id)
182 continue;
183
184 if (*id < PHY_MAX_ADDR && *id >= 0)
185 irqs[*id] = irq;
186 else
187 printk(KERN_WARNING "%s: "
188 "%d is not a valid PHY address\n",
189 np->full_name, *id);
190 }
191
192 return irqs;
193}
194
195void fsl_pq_mdio_bus_name(char *name, struct device_node *np)
196{
197 const u32 *reg;
198
199 reg = of_get_property(np, "reg", NULL);
200
201 snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0);
202}
203
204/* Scan the bus in reverse, looking for an empty spot */
205static int fsl_pq_mdio_find_free(struct mii_bus *new_bus)
206{
207 int i;
208
209 for (i = PHY_MAX_ADDR; i > 0; i--) {
210 u32 phy_id;
211
212 if (get_phy_id(new_bus, i, &phy_id))
213 return -1;
214
215 if (phy_id == 0xffffffff)
216 break;
217 }
218
219 return i;
220}
221
222
223#ifdef CONFIG_GIANFAR
224static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs)
225{
226 struct gfar __iomem *enet_regs;
227
228 /*
229 * This is mildly evil, but so is our hardware for doing this.
230 * Also, we have to cast back to struct gfar because of
231 * definition weirdness done in gianfar.h.
232 */
233 enet_regs = (struct gfar __iomem *)
234 ((char __iomem *)regs - offsetof(struct gfar, gfar_mii_regs));
235
236 return &enet_regs->tbipa;
237}
238#endif
239
240
241#ifdef CONFIG_UCC_GETH
242static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id)
243{
244 struct device_node *np = NULL;
245 int err = 0;
246
247 for_each_compatible_node(np, NULL, "ucc_geth") {
248 struct resource tempres;
249
250 err = of_address_to_resource(np, 0, &tempres);
251 if (err)
252 continue;
253
254 /* if our mdio regs fall within this UCC regs range */
255 if ((start >= tempres.start) && (end <= tempres.end)) {
256 /* Find the id of the UCC */
257 const u32 *id;
258
259 id = of_get_property(np, "cell-index", NULL);
260 if (!id) {
261 id = of_get_property(np, "device-id", NULL);
262 if (!id)
263 continue;
264 }
265
266 *ucc_id = *id;
267
268 return 0;
269 }
270 }
271
272 if (err)
273 return err;
274 else
275 return -EINVAL;
276}
277#endif
278
279
280static int fsl_pq_mdio_probe(struct of_device *ofdev,
281 const struct of_device_id *match)
282{
283 struct device_node *np = ofdev->node;
284 struct device_node *tbi;
285 struct fsl_pq_mdio __iomem *regs;
286 u32 __iomem *tbipa;
287 struct mii_bus *new_bus;
288 int tbiaddr = -1;
289 u64 addr, size;
290 int err = 0;
291
292 new_bus = mdiobus_alloc();
293 if (NULL == new_bus)
294 return -ENOMEM;
295
296 new_bus->name = "Freescale PowerQUICC MII Bus",
297 new_bus->read = &fsl_pq_mdio_read,
298 new_bus->write = &fsl_pq_mdio_write,
299 new_bus->reset = &fsl_pq_mdio_reset,
300 fsl_pq_mdio_bus_name(new_bus->id, np);
301
302 /* Set the PHY base address */
303 addr = of_translate_address(np, of_get_address(np, 0, &size, NULL));
304 regs = ioremap(addr, size);
305
306 if (NULL == regs) {
307 err = -ENOMEM;
308 goto err_free_bus;
309 }
310
311 new_bus->priv = (void __force *)regs;
312
313 new_bus->irq = create_irq_map(np);
314
315 if (NULL == new_bus->irq) {
316 err = -ENOMEM;
317 goto err_unmap_regs;
318 }
319
320 new_bus->parent = &ofdev->dev;
321 dev_set_drvdata(&ofdev->dev, new_bus);
322
323 if (of_device_is_compatible(np, "fsl,gianfar-mdio") ||
324 of_device_is_compatible(np, "gianfar")) {
325#ifdef CONFIG_GIANFAR
326 tbipa = get_gfar_tbipa(regs);
327#else
328 err = -ENODEV;
329 goto err_free_irqs;
330#endif
331 } else if (of_device_is_compatible(np, "fsl,ucc-mdio") ||
332 of_device_is_compatible(np, "ucc_geth_phy")) {
333#ifdef CONFIG_UCC_GETH
334 u32 id;
335
336 tbipa = &regs->utbipar;
337
338 if ((err = get_ucc_id_for_range(addr, addr + size, &id)))
339 goto err_free_irqs;
340
341 ucc_set_qe_mux_mii_mng(id - 1);
342#else
343 err = -ENODEV;
344 goto err_free_irqs;
345#endif
346 } else {
347 err = -ENODEV;
348 goto err_free_irqs;
349 }
350
351 for_each_child_of_node(np, tbi) {
352 if (!strncmp(tbi->type, "tbi-phy", 8))
353 break;
354 }
355
356 if (tbi) {
357 const u32 *prop = of_get_property(tbi, "reg", NULL);
358
359 if (prop)
360 tbiaddr = *prop;
361 }
362
363 if (tbiaddr == -1) {
364 out_be32(tbipa, 0);
365
366 tbiaddr = fsl_pq_mdio_find_free(new_bus);
367 }
368
369 /*
370 * We define TBIPA at 0 to be illegal, opting to fail for boards that
371 * have PHYs at 1-31, rather than change tbipa and rescan.
372 */
373 if (tbiaddr == 0) {
374 err = -EBUSY;
375
376 goto err_free_irqs;
377 }
378
379 out_be32(tbipa, tbiaddr);
380
381 /*
382 * The TBIPHY-only buses will find PHYs at every address,
383 * so we mask them all but the TBI
384 */
385 if (!of_device_is_compatible(np, "fsl,gianfar-mdio"))
386 new_bus->phy_mask = ~(1 << tbiaddr);
387
388 err = mdiobus_register(new_bus);
389
390 if (err) {
391 printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
392 new_bus->name);
393 goto err_free_irqs;
394 }
395
396 return 0;
397
398err_free_irqs:
399 kfree(new_bus->irq);
400err_unmap_regs:
401 iounmap(regs);
402err_free_bus:
403 kfree(new_bus);
404
405 return err;
406}
407
408
409static int fsl_pq_mdio_remove(struct of_device *ofdev)
410{
411 struct device *device = &ofdev->dev;
412 struct mii_bus *bus = dev_get_drvdata(device);
413
414 mdiobus_unregister(bus);
415
416 dev_set_drvdata(device, NULL);
417
418 iounmap((void __iomem *)bus->priv);
419 bus->priv = NULL;
420 mdiobus_free(bus);
421
422 return 0;
423}
424
425static struct of_device_id fsl_pq_mdio_match[] = {
426 {
427 .type = "mdio",
428 .compatible = "ucc_geth_phy",
429 },
430 {
431 .type = "mdio",
432 .compatible = "gianfar",
433 },
434 {
435 .compatible = "fsl,ucc-mdio",
436 },
437 {
438 .compatible = "fsl,gianfar-tbi",
439 },
440 {
441 .compatible = "fsl,gianfar-mdio",
442 },
443 {},
444};
445
446static struct of_platform_driver fsl_pq_mdio_driver = {
447 .name = "fsl-pq_mdio",
448 .probe = fsl_pq_mdio_probe,
449 .remove = fsl_pq_mdio_remove,
450 .match_table = fsl_pq_mdio_match,
451};
452
453int __init fsl_pq_mdio_init(void)
454{
455 return of_register_platform_driver(&fsl_pq_mdio_driver);
456}
457
458void fsl_pq_mdio_exit(void)
459{
460 of_unregister_platform_driver(&fsl_pq_mdio_driver);
461}
462subsys_initcall_sync(fsl_pq_mdio_init);
463module_exit(fsl_pq_mdio_exit);
diff --git a/drivers/net/fsl_pq_mdio.h b/drivers/net/fsl_pq_mdio.h
new file mode 100644
index 000000000000..36dad527410b
--- /dev/null
+++ b/drivers/net/fsl_pq_mdio.h
@@ -0,0 +1,45 @@
1/*
2 * Freescale PowerQUICC MDIO Driver -- MII Management Bus Implementation
3 * Driver for the MDIO bus controller on Freescale PowerQUICC processors
4 *
5 * Author: Andy Fleming
6 *
7 * Copyright (c) 2002-2004,2008 Freescale Semiconductor, Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 */
15#ifndef __FSL_PQ_MDIO_H
16#define __FSL_PQ_MDIO_H
17
18#define MIIMIND_BUSY 0x00000001
19#define MIIMIND_NOTVALID 0x00000004
20#define MIIMCFG_INIT_VALUE 0x00000007
21#define MIIMCFG_RESET 0x80000000
22
23#define MII_READ_COMMAND 0x00000001
24
25struct fsl_pq_mdio {
26 u32 miimcfg; /* MII management configuration reg */
27 u32 miimcom; /* MII management command reg */
28 u32 miimadd; /* MII management address reg */
29 u32 miimcon; /* MII management control reg */
30 u32 miimstat; /* MII management status reg */
31 u32 miimind; /* MII management indication reg */
32 u8 reserved[28]; /* Space holder */
33 u32 utbipar; /* TBI phy address reg (only on UCC) */
34} __attribute__ ((packed));
35
36
37int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
38int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
39int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id,
40 int regnum, u16 value);
41int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, int mii_id, int regnum);
42int __init fsl_pq_mdio_init(void);
43void fsl_pq_mdio_exit(void);
44void fsl_pq_mdio_bus_name(char *name, struct device_node *np);
45#endif /* FSL_PQ_MDIO_H */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index eb8302c5ba8c..bd21b6d5f13c 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -93,7 +93,7 @@
93#include <linux/of.h> 93#include <linux/of.h>
94 94
95#include "gianfar.h" 95#include "gianfar.h"
96#include "gianfar_mii.h" 96#include "fsl_pq_mdio.h"
97 97
98#define TX_TIMEOUT (1*HZ) 98#define TX_TIMEOUT (1*HZ)
99#undef BRIEF_GFAR_ERRORS 99#undef BRIEF_GFAR_ERRORS
@@ -253,7 +253,7 @@ static int gfar_of_init(struct net_device *dev)
253 of_node_put(phy); 253 of_node_put(phy);
254 of_node_put(mdio); 254 of_node_put(mdio);
255 255
256 gfar_mdio_bus_name(bus_name, mdio); 256 fsl_pq_mdio_bus_name(bus_name, mdio);
257 snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x", 257 snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x",
258 bus_name, *id); 258 bus_name, *id);
259 } 259 }
@@ -420,7 +420,7 @@ static int gfar_probe(struct of_device *ofdev,
420 priv->hash_width = 8; 420 priv->hash_width = 8;
421 421
422 priv->hash_regs[0] = &priv->regs->gaddr0; 422 priv->hash_regs[0] = &priv->regs->gaddr0;
423 priv->hash_regs[1] = &priv->regs->gaddr1; 423 priv->hash_regs[1] = &priv->regs->gaddr1;
424 priv->hash_regs[2] = &priv->regs->gaddr2; 424 priv->hash_regs[2] = &priv->regs->gaddr2;
425 priv->hash_regs[3] = &priv->regs->gaddr3; 425 priv->hash_regs[3] = &priv->regs->gaddr3;
426 priv->hash_regs[4] = &priv->regs->gaddr4; 426 priv->hash_regs[4] = &priv->regs->gaddr4;
@@ -836,7 +836,7 @@ void stop_gfar(struct net_device *dev)
836 free_irq(priv->interruptTransmit, dev); 836 free_irq(priv->interruptTransmit, dev);
837 free_irq(priv->interruptReceive, dev); 837 free_irq(priv->interruptReceive, dev);
838 } else { 838 } else {
839 free_irq(priv->interruptTransmit, dev); 839 free_irq(priv->interruptTransmit, dev);
840 } 840 }
841 841
842 free_skb_resources(priv); 842 free_skb_resources(priv);
@@ -1829,6 +1829,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
1829 skb_put(skb, pkt_len); 1829 skb_put(skb, pkt_len);
1830 dev->stats.rx_bytes += pkt_len; 1830 dev->stats.rx_bytes += pkt_len;
1831 1831
1832 if (in_irq() || irqs_disabled())
1833 printk("Interrupt problem!\n");
1832 gfar_process_frame(dev, skb, amount_pull); 1834 gfar_process_frame(dev, skb, amount_pull);
1833 1835
1834 } else { 1836 } else {
@@ -2302,23 +2304,12 @@ static struct of_platform_driver gfar_driver = {
2302 2304
2303static int __init gfar_init(void) 2305static int __init gfar_init(void)
2304{ 2306{
2305 int err = gfar_mdio_init(); 2307 return of_register_platform_driver(&gfar_driver);
2306
2307 if (err)
2308 return err;
2309
2310 err = of_register_platform_driver(&gfar_driver);
2311
2312 if (err)
2313 gfar_mdio_exit();
2314
2315 return err;
2316} 2308}
2317 2309
2318static void __exit gfar_exit(void) 2310static void __exit gfar_exit(void)
2319{ 2311{
2320 of_unregister_platform_driver(&gfar_driver); 2312 of_unregister_platform_driver(&gfar_driver);
2321 gfar_mdio_exit();
2322} 2313}
2323 2314
2324module_init(gfar_init); 2315module_init(gfar_init);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 7820720ceeed..3cb901b2e240 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -46,7 +46,6 @@
46#include <linux/workqueue.h> 46#include <linux/workqueue.h>
47#include <linux/ethtool.h> 47#include <linux/ethtool.h>
48#include <linux/fsl_devices.h> 48#include <linux/fsl_devices.h>
49#include "gianfar_mii.h"
50 49
51/* The maximum number of packets to be handled in one call of gfar_poll */ 50/* The maximum number of packets to be handled in one call of gfar_poll */
52#define GFAR_DEV_WEIGHT 64 51#define GFAR_DEV_WEIGHT 64
@@ -126,9 +125,12 @@ extern const char gfar_driver_version[];
126#define DEFAULT_RX_COALESCE 0 125#define DEFAULT_RX_COALESCE 0
127#define DEFAULT_RXCOUNT 0 126#define DEFAULT_RXCOUNT 0
128 127
129#define MIIMCFG_INIT_VALUE 0x00000007 128#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
130#define MIIMCFG_RESET 0x80000000 129 | SUPPORTED_10baseT_Full \
131#define MIIMIND_BUSY 0x00000001 130 | SUPPORTED_100baseT_Half \
131 | SUPPORTED_100baseT_Full \
132 | SUPPORTED_Autoneg \
133 | SUPPORTED_MII)
132 134
133/* TBI register addresses */ 135/* TBI register addresses */
134#define MII_TBICON 0x11 136#define MII_TBICON 0x11
@@ -826,9 +828,6 @@ extern void gfar_halt(struct net_device *dev);
826extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, 828extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
827 int enable, u32 regnum, u32 read); 829 int enable, u32 regnum, u32 read);
828void gfar_init_sysfs(struct net_device *dev); 830void gfar_init_sysfs(struct net_device *dev);
829int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id,
830 int regnum, u16 value);
831int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum);
832 831
833extern const struct ethtool_ops gfar_ethtool_ops; 832extern const struct ethtool_ops gfar_ethtool_ops;
834 833
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
deleted file mode 100644
index 65c242cd468a..000000000000
--- a/drivers/net/gianfar_mii.h
+++ /dev/null
@@ -1,54 +0,0 @@
1/*
2 * drivers/net/gianfar_mii.h
3 *
4 * Gianfar Ethernet Driver -- MII Management Bus Implementation
5 * Driver for the MDIO bus controller in the Gianfar register space
6 *
7 * Author: Andy Fleming
8 * Maintainer: Kumar Gala
9 *
10 * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 */
18#ifndef __GIANFAR_MII_H
19#define __GIANFAR_MII_H
20
21struct gfar_private; /* forward ref */
22
23#define MIIMIND_BUSY 0x00000001
24#define MIIMIND_NOTVALID 0x00000004
25
26#define MII_READ_COMMAND 0x00000001
27
28#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
29 | SUPPORTED_10baseT_Full \
30 | SUPPORTED_100baseT_Half \
31 | SUPPORTED_100baseT_Full \
32 | SUPPORTED_Autoneg \
33 | SUPPORTED_MII)
34
35struct gfar_mii {
36 u32 miimcfg; /* 0x.520 - MII Management Config Register */
37 u32 miimcom; /* 0x.524 - MII Management Command Register */
38 u32 miimadd; /* 0x.528 - MII Management Address Register */
39 u32 miimcon; /* 0x.52c - MII Management Control Register */
40 u32 miimstat; /* 0x.530 - MII Management Status Register */
41 u32 miimind; /* 0x.534 - MII Management Indicator Register */
42};
43
44int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
45int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
46int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id,
47 int regnum, u16 value);
48int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum);
49struct mii_bus *gfar_get_miibus(const struct gfar_private *priv);
50int __init gfar_mdio_init(void);
51void gfar_mdio_exit(void);
52
53void gfar_mdio_bus_name(char *name, struct device_node *np);
54#endif /* GIANFAR_PHY_H */
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 4a8d5747204a..1c095c63f98f 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -39,7 +39,7 @@
39#include <asm/ucc_fast.h> 39#include <asm/ucc_fast.h>
40 40
41#include "ucc_geth.h" 41#include "ucc_geth.h"
42#include "ucc_geth_mii.h" 42#include "fsl_pq_mdio.h"
43 43
44#undef DEBUG 44#undef DEBUG
45 45
@@ -1557,7 +1557,7 @@ static int init_phy(struct net_device *dev)
1557 of_node_put(phy); 1557 of_node_put(phy);
1558 of_node_put(mdio); 1558 of_node_put(mdio);
1559 1559
1560 uec_mdio_bus_name(bus_name, mdio); 1560 fsl_pq_mdio_bus_name(bus_name, mdio);
1561 snprintf(phy_id, sizeof(phy_id), "%s:%02x", 1561 snprintf(phy_id, sizeof(phy_id), "%s:%02x",
1562 bus_name, *id); 1562 bus_name, *id);
1563 1563
@@ -3657,7 +3657,8 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
3657 if (err) 3657 if (err)
3658 return -1; 3658 return -1;
3659 3659
3660 snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", res.start); 3660 snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x",
3661 res.start&0xfffff);
3661 } 3662 }
3662 3663
3663 /* get the phy interface type, or default to MII */ 3664 /* get the phy interface type, or default to MII */
@@ -3803,11 +3804,6 @@ static int __init ucc_geth_init(void)
3803{ 3804{
3804 int i, ret; 3805 int i, ret;
3805 3806
3806 ret = uec_mdio_init();
3807
3808 if (ret)
3809 return ret;
3810
3811 if (netif_msg_drv(&debug)) 3807 if (netif_msg_drv(&debug))
3812 printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); 3808 printk(KERN_INFO "ucc_geth: " DRV_DESC "\n");
3813 for (i = 0; i < 8; i++) 3809 for (i = 0; i < 8; i++)
@@ -3816,16 +3812,12 @@ static int __init ucc_geth_init(void)
3816 3812
3817 ret = of_register_platform_driver(&ucc_geth_driver); 3813 ret = of_register_platform_driver(&ucc_geth_driver);
3818 3814
3819 if (ret)
3820 uec_mdio_exit();
3821
3822 return ret; 3815 return ret;
3823} 3816}
3824 3817
3825static void __exit ucc_geth_exit(void) 3818static void __exit ucc_geth_exit(void)
3826{ 3819{
3827 of_unregister_platform_driver(&ucc_geth_driver); 3820 of_unregister_platform_driver(&ucc_geth_driver);
3828 uec_mdio_exit();
3829} 3821}
3830 3822
3831module_init(ucc_geth_init); 3823module_init(ucc_geth_init);
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index 16cbe42ba43c..66d18971fa0c 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -28,8 +28,6 @@
28#include <asm/ucc.h> 28#include <asm/ucc.h>
29#include <asm/ucc_fast.h> 29#include <asm/ucc_fast.h>
30 30
31#include "ucc_geth_mii.h"
32
33#define DRV_DESC "QE UCC Gigabit Ethernet Controller" 31#define DRV_DESC "QE UCC Gigabit Ethernet Controller"
34#define DRV_NAME "ucc_geth" 32#define DRV_NAME "ucc_geth"
35#define DRV_VERSION "1.1" 33#define DRV_VERSION "1.1"
@@ -184,6 +182,18 @@ struct ucc_geth {
184#define UCCE_RX_EVENTS (UCCE_RXF | UCC_GETH_UCCE_BSY) 182#define UCCE_RX_EVENTS (UCCE_RXF | UCC_GETH_UCCE_BSY)
185#define UCCE_TX_EVENTS (UCCE_TXB | UCC_GETH_UCCE_TXE) 183#define UCCE_TX_EVENTS (UCCE_TXB | UCC_GETH_UCCE_TXE)
186 184
185/* TBI defines */
186#define ENET_TBI_MII_CR 0x00 /* Control */
187#define ENET_TBI_MII_SR 0x01 /* Status */
188#define ENET_TBI_MII_ANA 0x04 /* AN advertisement */
189#define ENET_TBI_MII_ANLPBPA 0x05 /* AN link partner base page ability */
190#define ENET_TBI_MII_ANEX 0x06 /* AN expansion */
191#define ENET_TBI_MII_ANNPT 0x07 /* AN next page transmit */
192#define ENET_TBI_MII_ANLPANP 0x08 /* AN link partner ability next page */
193#define ENET_TBI_MII_EXST 0x0F /* Extended status */
194#define ENET_TBI_MII_JD 0x10 /* Jitter diagnostics */
195#define ENET_TBI_MII_TBICON 0x11 /* TBI control */
196
187/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */ 197/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
188#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control 198#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control
189 Rx */ 199 Rx */
diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c
index 68a7f5414133..a755bea559b9 100644
--- a/drivers/net/ucc_geth_ethtool.c
+++ b/drivers/net/ucc_geth_ethtool.c
@@ -39,7 +39,6 @@
39#include <asm/types.h> 39#include <asm/types.h>
40 40
41#include "ucc_geth.h" 41#include "ucc_geth.h"
42#include "ucc_geth_mii.h"
43 42
44static char hw_stat_gstrings[][ETH_GSTRING_LEN] = { 43static char hw_stat_gstrings[][ETH_GSTRING_LEN] = {
45 "tx-64-frames", 44 "tx-64-frames",
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
deleted file mode 100644
index 54635911305c..000000000000
--- a/drivers/net/ucc_geth_mii.c
+++ /dev/null
@@ -1,295 +0,0 @@
1/*
2 * drivers/net/ucc_geth_mii.c
3 *
4 * QE UCC Gigabit Ethernet Driver -- MII Management Bus Implementation
5 * Provides Bus interface for MII Management regs in the UCC register space
6 *
7 * Copyright (C) 2007 Freescale Semiconductor, Inc.
8 *
9 * Authors: Li Yang <leoli@freescale.com>
10 * Kim Phillips <kim.phillips@freescale.com>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 */
18
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/string.h>
22#include <linux/errno.h>
23#include <linux/unistd.h>
24#include <linux/slab.h>
25#include <linux/interrupt.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/netdevice.h>
29#include <linux/etherdevice.h>
30#include <linux/skbuff.h>
31#include <linux/spinlock.h>
32#include <linux/mm.h>
33#include <linux/module.h>
34#include <linux/platform_device.h>
35#include <linux/crc32.h>
36#include <linux/mii.h>
37#include <linux/phy.h>
38#include <linux/fsl_devices.h>
39#include <linux/of_platform.h>
40
41#include <asm/io.h>
42#include <asm/irq.h>
43#include <asm/uaccess.h>
44#include <asm/ucc.h>
45
46#include "ucc_geth_mii.h"
47#include "ucc_geth.h"
48
49#define DEBUG
50#ifdef DEBUG
51#define vdbg(format, arg...) printk(KERN_DEBUG , format "\n" , ## arg)
52#else
53#define vdbg(format, arg...) do {} while(0)
54#endif
55
56#define MII_DRV_DESC "QE UCC Ethernet Controller MII Bus"
57#define MII_DRV_NAME "fsl-uec_mdio"
58
59/* Write value to the PHY for this device to the register at regnum, */
60/* waiting until the write is done before it returns. All PHY */
61/* configuration has to be done through the master UEC MIIM regs */
62int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
63{
64 struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
65
66 /* Setting up the MII Mangement Address Register */
67 out_be32(&regs->miimadd,
68 (mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | regnum);
69
70 /* Setting up the MII Mangement Control Register with the value */
71 out_be32(&regs->miimcon, value);
72
73 /* Wait till MII management write is complete */
74 while ((in_be32(&regs->miimind)) & MIIMIND_BUSY)
75 cpu_relax();
76
77 return 0;
78}
79
80/* Reads from register regnum in the PHY for device dev, */
81/* returning the value. Clears miimcom first. All PHY */
82/* configuration has to be done through the TSEC1 MIIM regs */
83int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
84{
85 struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
86 u16 value;
87
88 /* Setting up the MII Mangement Address Register */
89 out_be32(&regs->miimadd,
90 (mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | regnum);
91
92 /* Clear miimcom, perform an MII management read cycle */
93 out_be32(&regs->miimcom, 0);
94 out_be32(&regs->miimcom, MIIMCOM_READ_CYCLE);
95
96 /* Wait till MII management write is complete */
97 while ((in_be32(&regs->miimind)) & (MIIMIND_BUSY | MIIMIND_NOT_VALID))
98 cpu_relax();
99
100 /* Read MII management status */
101 value = in_be32(&regs->miimstat);
102
103 return value;
104}
105
106/* Reset the MIIM registers, and wait for the bus to free */
107static int uec_mdio_reset(struct mii_bus *bus)
108{
109 struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
110 unsigned int timeout = PHY_INIT_TIMEOUT;
111
112 mutex_lock(&bus->mdio_lock);
113
114 /* Reset the management interface */
115 out_be32(&regs->miimcfg, MIIMCFG_RESET_MANAGEMENT);
116
117 /* Setup the MII Mgmt clock speed */
118 out_be32(&regs->miimcfg, MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112);
119
120 /* Wait until the bus is free */
121 while ((in_be32(&regs->miimind) & MIIMIND_BUSY) && timeout--)
122 cpu_relax();
123
124 mutex_unlock(&bus->mdio_lock);
125
126 if (timeout <= 0) {
127 printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name);
128 return -EBUSY;
129 }
130
131 return 0;
132}
133
134static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *match)
135{
136 struct device *device = &ofdev->dev;
137 struct device_node *np = ofdev->node, *tempnp = NULL;
138 struct device_node *child = NULL;
139 struct ucc_mii_mng __iomem *regs;
140 struct mii_bus *new_bus;
141 struct resource res;
142 int k, err = 0;
143
144 new_bus = mdiobus_alloc();
145 if (NULL == new_bus)
146 return -ENOMEM;
147
148 new_bus->name = "UCC Ethernet Controller MII Bus";
149 new_bus->read = &uec_mdio_read;
150 new_bus->write = &uec_mdio_write;
151 new_bus->reset = &uec_mdio_reset;
152
153 memset(&res, 0, sizeof(res));
154
155 err = of_address_to_resource(np, 0, &res);
156 if (err)
157 goto reg_map_fail;
158
159 uec_mdio_bus_name(new_bus->id, np);
160
161 new_bus->irq = kmalloc(32 * sizeof(int), GFP_KERNEL);
162
163 if (NULL == new_bus->irq) {
164 err = -ENOMEM;
165 goto reg_map_fail;
166 }
167
168 for (k = 0; k < 32; k++)
169 new_bus->irq[k] = PHY_POLL;
170
171 while ((child = of_get_next_child(np, child)) != NULL) {
172 int irq = irq_of_parse_and_map(child, 0);
173 if (irq != NO_IRQ) {
174 const u32 *id = of_get_property(child, "reg", NULL);
175 new_bus->irq[*id] = irq;
176 }
177 }
178
179 /* Set the base address */
180 regs = ioremap(res.start, sizeof(struct ucc_mii_mng));
181
182 if (NULL == regs) {
183 err = -ENOMEM;
184 goto ioremap_fail;
185 }
186
187 new_bus->priv = (void __force *)regs;
188
189 new_bus->parent = device;
190 dev_set_drvdata(device, new_bus);
191
192 /* Read MII management master from device tree */
193 while ((tempnp = of_find_compatible_node(tempnp, "network", "ucc_geth"))
194 != NULL) {
195 struct resource tempres;
196
197 err = of_address_to_resource(tempnp, 0, &tempres);
198 if (err)
199 goto bus_register_fail;
200
201 /* if our mdio regs fall within this UCC regs range */
202 if ((res.start >= tempres.start) &&
203 (res.end <= tempres.end)) {
204 /* set this UCC to be the MII master */
205 const u32 *id;
206
207 id = of_get_property(tempnp, "cell-index", NULL);
208 if (!id) {
209 id = of_get_property(tempnp, "device-id", NULL);
210 if (!id)
211 goto bus_register_fail;
212 }
213
214 ucc_set_qe_mux_mii_mng(*id - 1);
215
216 /* assign the TBI an address which won't
217 * conflict with the PHYs */
218 out_be32(&regs->utbipar, UTBIPAR_INIT_TBIPA);
219 break;
220 }
221 }
222
223 err = mdiobus_register(new_bus);
224 if (0 != err) {
225 printk(KERN_ERR "%s: Cannot register as MDIO bus\n",
226 new_bus->name);
227 goto bus_register_fail;
228 }
229
230 return 0;
231
232bus_register_fail:
233 iounmap(regs);
234ioremap_fail:
235 kfree(new_bus->irq);
236reg_map_fail:
237 mdiobus_free(new_bus);
238
239 return err;
240}
241
242static int uec_mdio_remove(struct of_device *ofdev)
243{
244 struct device *device = &ofdev->dev;
245 struct mii_bus *bus = dev_get_drvdata(device);
246
247 mdiobus_unregister(bus);
248
249 dev_set_drvdata(device, NULL);
250
251 iounmap((void __iomem *)bus->priv);
252 bus->priv = NULL;
253 mdiobus_free(bus);
254
255 return 0;
256}
257
258static struct of_device_id uec_mdio_match[] = {
259 {
260 .type = "mdio",
261 .compatible = "ucc_geth_phy",
262 },
263 {
264 .compatible = "fsl,ucc-mdio",
265 },
266 {},
267};
268
269static struct of_platform_driver uec_mdio_driver = {
270 .name = MII_DRV_NAME,
271 .probe = uec_mdio_probe,
272 .remove = uec_mdio_remove,
273 .match_table = uec_mdio_match,
274};
275
276int __init uec_mdio_init(void)
277{
278 return of_register_platform_driver(&uec_mdio_driver);
279}
280
281/* called from __init ucc_geth_init, therefore can not be __exit */
282void uec_mdio_exit(void)
283{
284 of_unregister_platform_driver(&uec_mdio_driver);
285}
286
287void uec_mdio_bus_name(char *name, struct device_node *np)
288{
289 const u32 *reg;
290
291 reg = of_get_property(np, "reg", NULL);
292
293 snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0);
294}
295
diff --git a/drivers/net/ucc_geth_mii.h b/drivers/net/ucc_geth_mii.h
deleted file mode 100644
index 840cf80235b7..000000000000
--- a/drivers/net/ucc_geth_mii.h
+++ /dev/null
@@ -1,101 +0,0 @@
1/*
2 * drivers/net/ucc_geth_mii.h
3 *
4 * QE UCC Gigabit Ethernet Driver -- MII Management Bus Implementation
5 * Provides Bus interface for MII Management regs in the UCC register space
6 *
7 * Copyright (C) 2007 Freescale Semiconductor, Inc.
8 *
9 * Authors: Li Yang <leoli@freescale.com>
10 * Kim Phillips <kim.phillips@freescale.com>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 */
18#ifndef __UEC_MII_H
19#define __UEC_MII_H
20
21/* UCC GETH MIIMCFG (MII Management Configuration Register) */
22#define MIIMCFG_RESET_MANAGEMENT 0x80000000 /* Reset
23 management */
24#define MIIMCFG_NO_PREAMBLE 0x00000010 /* Preamble
25 suppress */
26#define MIIMCFG_CLOCK_DIVIDE_SHIFT (31 - 31) /* clock divide
27 << shift */
28#define MIIMCFG_CLOCK_DIVIDE_MAX 0xf /* max clock divide */
29#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_2 0x00000000
30#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_4 0x00000001
31#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_6 0x00000002
32#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_8 0x00000003
33#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_10 0x00000004
34#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_14 0x00000005
35#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_16 0x00000008
36#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_20 0x00000006
37#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_28 0x00000007
38#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_32 0x00000009
39#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_48 0x0000000a
40#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_64 0x0000000b
41#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_80 0x0000000c
42#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112 0x0000000d
43#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_160 0x0000000e
44#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_224 0x0000000f
45
46/* UCC GETH MIIMCOM (MII Management Command Register) */
47#define MIIMCOM_SCAN_CYCLE 0x00000002 /* Scan cycle */
48#define MIIMCOM_READ_CYCLE 0x00000001 /* Read cycle */
49
50/* UCC GETH MIIMADD (MII Management Address Register) */
51#define MIIMADD_PHY_ADDRESS_SHIFT (31 - 23) /* PHY Address
52 << shift */
53#define MIIMADD_PHY_REGISTER_SHIFT (31 - 31) /* PHY Register
54 << shift */
55
56/* UCC GETH MIIMCON (MII Management Control Register) */
57#define MIIMCON_PHY_CONTROL_SHIFT (31 - 31) /* PHY Control
58 << shift */
59#define MIIMCON_PHY_STATUS_SHIFT (31 - 31) /* PHY Status
60 << shift */
61
62/* UCC GETH MIIMIND (MII Management Indicator Register) */
63#define MIIMIND_NOT_VALID 0x00000004 /* Not valid */
64#define MIIMIND_SCAN 0x00000002 /* Scan in
65 progress */
66#define MIIMIND_BUSY 0x00000001
67
68/* Initial TBI Physical Address */
69#define UTBIPAR_INIT_TBIPA 0x1f
70
71struct ucc_mii_mng {
72 u32 miimcfg; /* MII management configuration reg */
73 u32 miimcom; /* MII management command reg */
74 u32 miimadd; /* MII management address reg */
75 u32 miimcon; /* MII management control reg */
76 u32 miimstat; /* MII management status reg */
77 u32 miimind; /* MII management indication reg */
78 u8 notcare[28]; /* Space holder */
79 u32 utbipar; /* TBI phy address reg */
80} __attribute__ ((packed));
81
82/* TBI / MII Set Register */
83enum enet_tbi_mii_reg {
84 ENET_TBI_MII_CR = 0x00, /* Control */
85 ENET_TBI_MII_SR = 0x01, /* Status */
86 ENET_TBI_MII_ANA = 0x04, /* AN advertisement */
87 ENET_TBI_MII_ANLPBPA = 0x05, /* AN link partner base page ability */
88 ENET_TBI_MII_ANEX = 0x06, /* AN expansion */
89 ENET_TBI_MII_ANNPT = 0x07, /* AN next page transmit */
90 ENET_TBI_MII_ANLPANP = 0x08, /* AN link partner ability next page */
91 ENET_TBI_MII_EXST = 0x0F, /* Extended status */
92 ENET_TBI_MII_JD = 0x10, /* Jitter diagnostics */
93 ENET_TBI_MII_TBICON = 0x11 /* TBI control */
94};
95
96int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
97int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
98int __init uec_mdio_init(void);
99void uec_mdio_exit(void);
100void uec_mdio_bus_name(char *name, struct device_node *np);
101#endif /* __UEC_MII_H */