7537ee3f6622ca55a6bd654173f9ff4802f10f7b
[linux-2.6-microblaze.git] / drivers / net / ethernet / marvell / mvmdio.c
1 /*
2  * Driver for the MDIO interface of Marvell network interfaces.
3  *
4  * Since the MDIO interface of Marvell network interfaces is shared
5  * between all network interfaces, having a single driver allows to
6  * handle concurrent accesses properly (you may have four Ethernet
7  * ports, but they in fact share the same SMI interface to access
8  * the MDIO bus). This driver is currently used by the mvneta and
9  * mv643xx_eth drivers.
10  *
11  * Copyright (C) 2012 Marvell
12  *
13  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
14  *
15  * This file is licensed under the terms of the GNU General Public
16  * License version 2. This program is licensed "as is" without any
17  * warranty of any kind, whether express or implied.
18  */
19
20 #include <linux/acpi.h>
21 #include <linux/clk.h>
22 #include <linux/delay.h>
23 #include <linux/fwnode_mdio.h>
24 #include <linux/interrupt.h>
25 #include <linux/io.h>
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/of_device.h>
29 #include <linux/of_mdio.h>
30 #include <linux/phy.h>
31 #include <linux/platform_device.h>
32 #include <linux/sched.h>
33 #include <linux/wait.h>
34
35 #define MVMDIO_SMI_DATA_SHIFT           0
36 #define MVMDIO_SMI_PHY_ADDR_SHIFT       16
37 #define MVMDIO_SMI_PHY_REG_SHIFT        21
38 #define MVMDIO_SMI_READ_OPERATION       BIT(26)
39 #define MVMDIO_SMI_WRITE_OPERATION      0
40 #define MVMDIO_SMI_READ_VALID           BIT(27)
41 #define MVMDIO_SMI_BUSY                 BIT(28)
42 #define MVMDIO_ERR_INT_CAUSE            0x007C
43 #define  MVMDIO_ERR_INT_SMI_DONE        0x00000010
44 #define MVMDIO_ERR_INT_MASK             0x0080
45
46 #define MVMDIO_XSMI_MGNT_REG            0x0
47 #define  MVMDIO_XSMI_PHYADDR_SHIFT      16
48 #define  MVMDIO_XSMI_DEVADDR_SHIFT      21
49 #define  MVMDIO_XSMI_WRITE_OPERATION    (0x5 << 26)
50 #define  MVMDIO_XSMI_READ_OPERATION     (0x7 << 26)
51 #define  MVMDIO_XSMI_READ_VALID         BIT(29)
52 #define  MVMDIO_XSMI_BUSY               BIT(30)
53 #define MVMDIO_XSMI_ADDR_REG            0x8
54
55 /*
56  * SMI Timeout measurements:
57  * - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt)
58  * - Armada 370       (Globalscale Mirabox):   41us to 43us (Polled)
59  */
60 #define MVMDIO_SMI_TIMEOUT              1000 /* 1000us = 1ms */
61 #define MVMDIO_SMI_POLL_INTERVAL_MIN    45
62 #define MVMDIO_SMI_POLL_INTERVAL_MAX    55
63
64 #define MVMDIO_XSMI_POLL_INTERVAL_MIN   150
65 #define MVMDIO_XSMI_POLL_INTERVAL_MAX   160
66
67 struct orion_mdio_dev {
68         void __iomem *regs;
69         struct clk *clk[4];
70         /*
71          * If we have access to the error interrupt pin (which is
72          * somewhat misnamed as it not only reflects internal errors
73          * but also reflects SMI completion), use that to wait for
74          * SMI access completion instead of polling the SMI busy bit.
75          */
76         int err_interrupt;
77         wait_queue_head_t smi_busy_wait;
78 };
79
80 enum orion_mdio_bus_type {
81         BUS_TYPE_SMI,
82         BUS_TYPE_XSMI
83 };
84
85 struct orion_mdio_ops {
86         int (*is_done)(struct orion_mdio_dev *);
87         unsigned int poll_interval_min;
88         unsigned int poll_interval_max;
89 };
90
91 /* Wait for the SMI unit to be ready for another operation
92  */
93 static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops,
94                                  struct mii_bus *bus)
95 {
96         struct orion_mdio_dev *dev = bus->priv;
97         unsigned long timeout = usecs_to_jiffies(MVMDIO_SMI_TIMEOUT);
98         unsigned long end = jiffies + timeout;
99         int timedout = 0;
100
101         while (1) {
102                 if (ops->is_done(dev))
103                         return 0;
104                 else if (timedout)
105                         break;
106
107                 if (dev->err_interrupt <= 0) {
108                         usleep_range(ops->poll_interval_min,
109                                      ops->poll_interval_max);
110
111                         if (time_is_before_jiffies(end))
112                                 ++timedout;
113                 } else {
114                         /* wait_event_timeout does not guarantee a delay of at
115                          * least one whole jiffie, so timeout must be no less
116                          * than two.
117                          */
118                         if (timeout < 2)
119                                 timeout = 2;
120                         wait_event_timeout(dev->smi_busy_wait,
121                                            ops->is_done(dev), timeout);
122
123                         ++timedout;
124                 }
125         }
126
127         dev_err(bus->parent, "Timeout: SMI busy for too long\n");
128         return  -ETIMEDOUT;
129 }
130
131 static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
132 {
133         return !(readl(dev->regs) & MVMDIO_SMI_BUSY);
134 }
135
136 static const struct orion_mdio_ops orion_mdio_smi_ops = {
137         .is_done = orion_mdio_smi_is_done,
138         .poll_interval_min = MVMDIO_SMI_POLL_INTERVAL_MIN,
139         .poll_interval_max = MVMDIO_SMI_POLL_INTERVAL_MAX,
140 };
141
142 static int orion_mdio_smi_read(struct mii_bus *bus, int mii_id,
143                                int regnum)
144 {
145         struct orion_mdio_dev *dev = bus->priv;
146         u32 val;
147         int ret;
148
149         if (regnum & MII_ADDR_C45)
150                 return -EOPNOTSUPP;
151
152         ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus);
153         if (ret < 0)
154                 return ret;
155
156         writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
157                 (regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
158                 MVMDIO_SMI_READ_OPERATION),
159                dev->regs);
160
161         ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus);
162         if (ret < 0)
163                 return ret;
164
165         val = readl(dev->regs);
166         if (!(val & MVMDIO_SMI_READ_VALID)) {
167                 dev_err(bus->parent, "SMI bus read not valid\n");
168                 return -ENODEV;
169         }
170
171         return val & GENMASK(15, 0);
172 }
173
174 static int orion_mdio_smi_write(struct mii_bus *bus, int mii_id,
175                                 int regnum, u16 value)
176 {
177         struct orion_mdio_dev *dev = bus->priv;
178         int ret;
179
180         if (regnum & MII_ADDR_C45)
181                 return -EOPNOTSUPP;
182
183         ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus);
184         if (ret < 0)
185                 return ret;
186
187         writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
188                 (regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
189                 MVMDIO_SMI_WRITE_OPERATION            |
190                 (value << MVMDIO_SMI_DATA_SHIFT)),
191                dev->regs);
192
193         return 0;
194 }
195
196 static int orion_mdio_xsmi_is_done(struct orion_mdio_dev *dev)
197 {
198         return !(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_BUSY);
199 }
200
201 static const struct orion_mdio_ops orion_mdio_xsmi_ops = {
202         .is_done = orion_mdio_xsmi_is_done,
203         .poll_interval_min = MVMDIO_XSMI_POLL_INTERVAL_MIN,
204         .poll_interval_max = MVMDIO_XSMI_POLL_INTERVAL_MAX,
205 };
206
207 static int orion_mdio_xsmi_read(struct mii_bus *bus, int mii_id,
208                                 int regnum)
209 {
210         struct orion_mdio_dev *dev = bus->priv;
211         u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
212         int ret;
213
214         if (!(regnum & MII_ADDR_C45))
215                 return -EOPNOTSUPP;
216
217         ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
218         if (ret < 0)
219                 return ret;
220
221         writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
222         writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
223                (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
224                MVMDIO_XSMI_READ_OPERATION,
225                dev->regs + MVMDIO_XSMI_MGNT_REG);
226
227         ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
228         if (ret < 0)
229                 return ret;
230
231         if (!(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) &
232               MVMDIO_XSMI_READ_VALID)) {
233                 dev_err(bus->parent, "XSMI bus read not valid\n");
234                 return -ENODEV;
235         }
236
237         return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
238 }
239
240 static int orion_mdio_xsmi_write(struct mii_bus *bus, int mii_id,
241                                 int regnum, u16 value)
242 {
243         struct orion_mdio_dev *dev = bus->priv;
244         u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
245         int ret;
246
247         if (!(regnum & MII_ADDR_C45))
248                 return -EOPNOTSUPP;
249
250         ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
251         if (ret < 0)
252                 return ret;
253
254         writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
255         writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
256                (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
257                MVMDIO_XSMI_WRITE_OPERATION | value,
258                dev->regs + MVMDIO_XSMI_MGNT_REG);
259
260         return 0;
261 }
262
263 static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id)
264 {
265         struct orion_mdio_dev *dev = dev_id;
266
267         if (readl(dev->regs + MVMDIO_ERR_INT_CAUSE) &
268                         MVMDIO_ERR_INT_SMI_DONE) {
269                 writel(~MVMDIO_ERR_INT_SMI_DONE,
270                                 dev->regs + MVMDIO_ERR_INT_CAUSE);
271                 wake_up(&dev->smi_busy_wait);
272                 return IRQ_HANDLED;
273         }
274
275         return IRQ_NONE;
276 }
277
278 static int orion_mdio_probe(struct platform_device *pdev)
279 {
280         enum orion_mdio_bus_type type;
281         struct resource *r;
282         struct mii_bus *bus;
283         struct orion_mdio_dev *dev;
284         int i, ret;
285
286         type = (enum orion_mdio_bus_type)device_get_match_data(&pdev->dev);
287
288         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
289         if (!r) {
290                 dev_err(&pdev->dev, "No SMI register address given\n");
291                 return -ENODEV;
292         }
293
294         bus = devm_mdiobus_alloc_size(&pdev->dev,
295                                       sizeof(struct orion_mdio_dev));
296         if (!bus)
297                 return -ENOMEM;
298
299         switch (type) {
300         case BUS_TYPE_SMI:
301                 bus->read = orion_mdio_smi_read;
302                 bus->write = orion_mdio_smi_write;
303                 break;
304         case BUS_TYPE_XSMI:
305                 bus->read = orion_mdio_xsmi_read;
306                 bus->write = orion_mdio_xsmi_write;
307                 break;
308         }
309
310         bus->name = "orion_mdio_bus";
311         snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii",
312                  dev_name(&pdev->dev));
313         bus->parent = &pdev->dev;
314
315         dev = bus->priv;
316         dev->regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
317         if (!dev->regs) {
318                 dev_err(&pdev->dev, "Unable to remap SMI register\n");
319                 return -ENODEV;
320         }
321
322         init_waitqueue_head(&dev->smi_busy_wait);
323
324         if (pdev->dev.of_node) {
325                 for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
326                         dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
327                         if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) {
328                                 ret = -EPROBE_DEFER;
329                                 goto out_clk;
330                         }
331                         if (IS_ERR(dev->clk[i]))
332                                 break;
333                         clk_prepare_enable(dev->clk[i]);
334                 }
335
336                 if (!IS_ERR(of_clk_get(pdev->dev.of_node,
337                                        ARRAY_SIZE(dev->clk))))
338                         dev_warn(&pdev->dev,
339                                  "unsupported number of clocks, limiting to the first "
340                                  __stringify(ARRAY_SIZE(dev->clk)) "\n");
341         } else {
342                 dev->clk[0] = clk_get(&pdev->dev, NULL);
343                 if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) {
344                         ret = -EPROBE_DEFER;
345                         goto out_clk;
346                 }
347                 if (!IS_ERR(dev->clk[0]))
348                         clk_prepare_enable(dev->clk[0]);
349         }
350
351
352         dev->err_interrupt = platform_get_irq_optional(pdev, 0);
353         if (dev->err_interrupt > 0 &&
354             resource_size(r) < MVMDIO_ERR_INT_MASK + 4) {
355                 dev_err(&pdev->dev,
356                         "disabling interrupt, resource size is too small\n");
357                 dev->err_interrupt = 0;
358         }
359         if (dev->err_interrupt > 0) {
360                 ret = devm_request_irq(&pdev->dev, dev->err_interrupt,
361                                         orion_mdio_err_irq,
362                                         IRQF_SHARED, pdev->name, dev);
363                 if (ret)
364                         goto out_mdio;
365
366                 writel(MVMDIO_ERR_INT_SMI_DONE,
367                         dev->regs + MVMDIO_ERR_INT_MASK);
368
369         } else if (dev->err_interrupt == -EPROBE_DEFER) {
370                 ret = -EPROBE_DEFER;
371                 goto out_mdio;
372         }
373
374         ret = fwnode_mdiobus_register(bus, pdev->dev.fwnode);
375         if (ret < 0) {
376                 dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret);
377                 goto out_mdio;
378         }
379
380         platform_set_drvdata(pdev, bus);
381
382         return 0;
383
384 out_mdio:
385         if (dev->err_interrupt > 0)
386                 writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
387
388 out_clk:
389         for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
390                 if (IS_ERR(dev->clk[i]))
391                         break;
392                 clk_disable_unprepare(dev->clk[i]);
393                 clk_put(dev->clk[i]);
394         }
395
396         return ret;
397 }
398
399 static int orion_mdio_remove(struct platform_device *pdev)
400 {
401         struct mii_bus *bus = platform_get_drvdata(pdev);
402         struct orion_mdio_dev *dev = bus->priv;
403         int i;
404
405         if (dev->err_interrupt > 0)
406                 writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
407         mdiobus_unregister(bus);
408
409         for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
410                 if (IS_ERR(dev->clk[i]))
411                         break;
412                 clk_disable_unprepare(dev->clk[i]);
413                 clk_put(dev->clk[i]);
414         }
415
416         return 0;
417 }
418
419 static const struct of_device_id orion_mdio_match[] = {
420         { .compatible = "marvell,orion-mdio", .data = (void *)BUS_TYPE_SMI },
421         { .compatible = "marvell,xmdio", .data = (void *)BUS_TYPE_XSMI },
422         { }
423 };
424 MODULE_DEVICE_TABLE(of, orion_mdio_match);
425
426 static const struct acpi_device_id orion_mdio_acpi_match[] = {
427         { "MRVL0100", BUS_TYPE_SMI },
428         { "MRVL0101", BUS_TYPE_XSMI },
429         { },
430 };
431 MODULE_DEVICE_TABLE(acpi, orion_mdio_acpi_match);
432
433 static struct platform_driver orion_mdio_driver = {
434         .probe = orion_mdio_probe,
435         .remove = orion_mdio_remove,
436         .driver = {
437                 .name = "orion-mdio",
438                 .of_match_table = orion_mdio_match,
439                 .acpi_match_table = ACPI_PTR(orion_mdio_acpi_match),
440         },
441 };
442
443 module_platform_driver(orion_mdio_driver);
444
445 MODULE_DESCRIPTION("Marvell MDIO interface driver");
446 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
447 MODULE_LICENSE("GPL");
448 MODULE_ALIAS("platform:orion-mdio");