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