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