aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ucc_geth_mii.c
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 /drivers/net/ucc_geth_mii.c
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>
Diffstat (limited to 'drivers/net/ucc_geth_mii.c')
-rw-r--r--drivers/net/ucc_geth_mii.c295
1 files changed, 0 insertions, 295 deletions
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