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 the
8  * MDIO bus). Moreover, this MDIO interface code is similar between
9  * the mv643xx_eth driver and the mvneta driver. For now, it is only
10  * used by the mvneta driver, but it could later be used by the
11  * mv643xx_eth driver as well.
12  *
13  * Copyright (C) 2012 Marvell
14  *
15  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
16  *
17  * This file is licensed under the terms of the GNU General Public
18  * License version 2. This program is licensed "as is" without any
19  * warranty of any kind, whether express or implied.
20  */
21 
22 #include <linux/init.h>
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/mutex.h>
26 #include <linux/phy.h>
27 #include <linux/of_address.h>
28 #include <linux/of_mdio.h>
29 #include <linux/platform_device.h>
30 #include <linux/delay.h>
31 
32 #define MVMDIO_SMI_DATA_SHIFT              0
33 #define MVMDIO_SMI_PHY_ADDR_SHIFT          16
34 #define MVMDIO_SMI_PHY_REG_SHIFT           21
35 #define MVMDIO_SMI_READ_OPERATION          BIT(26)
36 #define MVMDIO_SMI_WRITE_OPERATION         0
37 #define MVMDIO_SMI_READ_VALID              BIT(27)
38 #define MVMDIO_SMI_BUSY                    BIT(28)
39 
40 struct orion_mdio_dev {
41 	struct mutex lock;
42 	void __iomem *smireg;
43 };
44 
45 /* Wait for the SMI unit to be ready for another operation
46  */
47 static int orion_mdio_wait_ready(struct mii_bus *bus)
48 {
49 	struct orion_mdio_dev *dev = bus->priv;
50 	int count;
51 	u32 val;
52 
53 	count = 0;
54 	while (1) {
55 		val = readl(dev->smireg);
56 		if (!(val & MVMDIO_SMI_BUSY))
57 			break;
58 
59 		if (count > 100) {
60 			dev_err(bus->parent, "Timeout: SMI busy for too long\n");
61 			return -ETIMEDOUT;
62 		}
63 
64 		udelay(10);
65 		count++;
66 	}
67 
68 	return 0;
69 }
70 
71 static int orion_mdio_read(struct mii_bus *bus, int mii_id,
72 			   int regnum)
73 {
74 	struct orion_mdio_dev *dev = bus->priv;
75 	int count;
76 	u32 val;
77 	int ret;
78 
79 	mutex_lock(&dev->lock);
80 
81 	ret = orion_mdio_wait_ready(bus);
82 	if (ret < 0) {
83 		mutex_unlock(&dev->lock);
84 		return ret;
85 	}
86 
87 	writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
88 		(regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
89 		MVMDIO_SMI_READ_OPERATION),
90 	       dev->smireg);
91 
92 	/* Wait for the value to become available */
93 	count = 0;
94 	while (1) {
95 		val = readl(dev->smireg);
96 		if (val & MVMDIO_SMI_READ_VALID)
97 			break;
98 
99 		if (count > 100) {
100 			dev_err(bus->parent, "Timeout when reading PHY\n");
101 			mutex_unlock(&dev->lock);
102 			return -ETIMEDOUT;
103 		}
104 
105 		udelay(10);
106 		count++;
107 	}
108 
109 	mutex_unlock(&dev->lock);
110 
111 	return val & 0xFFFF;
112 }
113 
114 static int orion_mdio_write(struct mii_bus *bus, int mii_id,
115 			    int regnum, u16 value)
116 {
117 	struct orion_mdio_dev *dev = bus->priv;
118 	int ret;
119 
120 	mutex_lock(&dev->lock);
121 
122 	ret = orion_mdio_wait_ready(bus);
123 	if (ret < 0) {
124 		mutex_unlock(&dev->lock);
125 		return ret;
126 	}
127 
128 	writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
129 		(regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
130 		MVMDIO_SMI_WRITE_OPERATION            |
131 		(value << MVMDIO_SMI_DATA_SHIFT)),
132 	       dev->smireg);
133 
134 	mutex_unlock(&dev->lock);
135 
136 	return 0;
137 }
138 
139 static int orion_mdio_reset(struct mii_bus *bus)
140 {
141 	return 0;
142 }
143 
144 static int orion_mdio_probe(struct platform_device *pdev)
145 {
146 	struct device_node *np = pdev->dev.of_node;
147 	struct mii_bus *bus;
148 	struct orion_mdio_dev *dev;
149 	int i, ret;
150 
151 	bus = mdiobus_alloc_size(sizeof(struct orion_mdio_dev));
152 	if (!bus) {
153 		dev_err(&pdev->dev, "Cannot allocate MDIO bus\n");
154 		return -ENOMEM;
155 	}
156 
157 	bus->name = "orion_mdio_bus";
158 	bus->read = orion_mdio_read;
159 	bus->write = orion_mdio_write;
160 	bus->reset = orion_mdio_reset;
161 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii",
162 		 dev_name(&pdev->dev));
163 	bus->parent = &pdev->dev;
164 
165 	bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
166 	if (!bus->irq) {
167 		dev_err(&pdev->dev, "Cannot allocate PHY IRQ array\n");
168 		mdiobus_free(bus);
169 		return -ENOMEM;
170 	}
171 
172 	for (i = 0; i < PHY_MAX_ADDR; i++)
173 		bus->irq[i] = PHY_POLL;
174 
175 	dev = bus->priv;
176 	dev->smireg = of_iomap(pdev->dev.of_node, 0);
177 	if (!dev->smireg) {
178 		dev_err(&pdev->dev, "No SMI register address given in DT\n");
179 		kfree(bus->irq);
180 		mdiobus_free(bus);
181 		return -ENODEV;
182 	}
183 
184 	mutex_init(&dev->lock);
185 
186 	ret = of_mdiobus_register(bus, np);
187 	if (ret < 0) {
188 		dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret);
189 		iounmap(dev->smireg);
190 		kfree(bus->irq);
191 		mdiobus_free(bus);
192 		return ret;
193 	}
194 
195 	platform_set_drvdata(pdev, bus);
196 
197 	return 0;
198 }
199 
200 static int orion_mdio_remove(struct platform_device *pdev)
201 {
202 	struct mii_bus *bus = platform_get_drvdata(pdev);
203 	mdiobus_unregister(bus);
204 	kfree(bus->irq);
205 	mdiobus_free(bus);
206 	return 0;
207 }
208 
209 static const struct of_device_id orion_mdio_match[] = {
210 	{ .compatible = "marvell,orion-mdio" },
211 	{ }
212 };
213 MODULE_DEVICE_TABLE(of, orion_mdio_match);
214 
215 static struct platform_driver orion_mdio_driver = {
216 	.probe = orion_mdio_probe,
217 	.remove = orion_mdio_remove,
218 	.driver = {
219 		.name = "orion-mdio",
220 		.of_match_table = orion_mdio_match,
221 	},
222 };
223 
224 module_platform_driver(orion_mdio_driver);
225 
226 MODULE_DESCRIPTION("Marvell MDIO interface driver");
227 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
228 MODULE_LICENSE("GPL");
229