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/interrupt.h> 28 #include <linux/platform_device.h> 29 #include <linux/delay.h> 30 #include <linux/io.h> 31 #include <linux/clk.h> 32 #include <linux/of_mdio.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 struct orion_mdio_dev { 48 struct mutex lock; 49 void __iomem *regs; 50 struct clk *clk; 51 /* 52 * If we have access to the error interrupt pin (which is 53 * somewhat misnamed as it not only reflects internal errors 54 * but also reflects SMI completion), use that to wait for 55 * SMI access completion instead of polling the SMI busy bit. 56 */ 57 int err_interrupt; 58 wait_queue_head_t smi_busy_wait; 59 }; 60 61 static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev) 62 { 63 return !(readl(dev->regs) & MVMDIO_SMI_BUSY); 64 } 65 66 /* Wait for the SMI unit to be ready for another operation 67 */ 68 static int orion_mdio_wait_ready(struct mii_bus *bus) 69 { 70 struct orion_mdio_dev *dev = bus->priv; 71 int count; 72 73 if (dev->err_interrupt <= 0) { 74 count = 0; 75 while (1) { 76 if (orion_mdio_smi_is_done(dev)) 77 break; 78 79 if (count > 100) { 80 dev_err(bus->parent, 81 "Timeout: SMI busy for too long\n"); 82 return -ETIMEDOUT; 83 } 84 85 udelay(10); 86 count++; 87 } 88 } else { 89 if (!orion_mdio_smi_is_done(dev)) { 90 wait_event_timeout(dev->smi_busy_wait, 91 orion_mdio_smi_is_done(dev), 92 msecs_to_jiffies(100)); 93 if (!orion_mdio_smi_is_done(dev)) 94 return -ETIMEDOUT; 95 } 96 } 97 98 return 0; 99 } 100 101 static int orion_mdio_read(struct mii_bus *bus, int mii_id, 102 int regnum) 103 { 104 struct orion_mdio_dev *dev = bus->priv; 105 int count; 106 u32 val; 107 int ret; 108 109 mutex_lock(&dev->lock); 110 111 ret = orion_mdio_wait_ready(bus); 112 if (ret < 0) { 113 mutex_unlock(&dev->lock); 114 return ret; 115 } 116 117 writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) | 118 (regnum << MVMDIO_SMI_PHY_REG_SHIFT) | 119 MVMDIO_SMI_READ_OPERATION), 120 dev->regs); 121 122 /* Wait for the value to become available */ 123 count = 0; 124 while (1) { 125 val = readl(dev->regs); 126 if (val & MVMDIO_SMI_READ_VALID) 127 break; 128 129 if (count > 100) { 130 dev_err(bus->parent, "Timeout when reading PHY\n"); 131 mutex_unlock(&dev->lock); 132 return -ETIMEDOUT; 133 } 134 135 udelay(10); 136 count++; 137 } 138 139 mutex_unlock(&dev->lock); 140 141 return val & 0xFFFF; 142 } 143 144 static int orion_mdio_write(struct mii_bus *bus, int mii_id, 145 int regnum, u16 value) 146 { 147 struct orion_mdio_dev *dev = bus->priv; 148 int ret; 149 150 mutex_lock(&dev->lock); 151 152 ret = orion_mdio_wait_ready(bus); 153 if (ret < 0) { 154 mutex_unlock(&dev->lock); 155 return ret; 156 } 157 158 writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) | 159 (regnum << MVMDIO_SMI_PHY_REG_SHIFT) | 160 MVMDIO_SMI_WRITE_OPERATION | 161 (value << MVMDIO_SMI_DATA_SHIFT)), 162 dev->regs); 163 164 mutex_unlock(&dev->lock); 165 166 return 0; 167 } 168 169 static int orion_mdio_reset(struct mii_bus *bus) 170 { 171 return 0; 172 } 173 174 static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id) 175 { 176 struct orion_mdio_dev *dev = dev_id; 177 178 if (readl(dev->regs + MVMDIO_ERR_INT_CAUSE) & 179 MVMDIO_ERR_INT_SMI_DONE) { 180 writel(~MVMDIO_ERR_INT_SMI_DONE, 181 dev->regs + MVMDIO_ERR_INT_CAUSE); 182 wake_up(&dev->smi_busy_wait); 183 return IRQ_HANDLED; 184 } 185 186 return IRQ_NONE; 187 } 188 189 static int orion_mdio_probe(struct platform_device *pdev) 190 { 191 struct resource *r; 192 struct mii_bus *bus; 193 struct orion_mdio_dev *dev; 194 int i, ret; 195 196 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 197 if (!r) { 198 dev_err(&pdev->dev, "No SMI register address given\n"); 199 return -ENODEV; 200 } 201 202 bus = mdiobus_alloc_size(sizeof(struct orion_mdio_dev)); 203 if (!bus) { 204 dev_err(&pdev->dev, "Cannot allocate MDIO bus\n"); 205 return -ENOMEM; 206 } 207 208 bus->name = "orion_mdio_bus"; 209 bus->read = orion_mdio_read; 210 bus->write = orion_mdio_write; 211 bus->reset = orion_mdio_reset; 212 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", 213 dev_name(&pdev->dev)); 214 bus->parent = &pdev->dev; 215 216 bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); 217 if (!bus->irq) { 218 mdiobus_free(bus); 219 return -ENOMEM; 220 } 221 222 for (i = 0; i < PHY_MAX_ADDR; i++) 223 bus->irq[i] = PHY_POLL; 224 225 dev = bus->priv; 226 dev->regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); 227 if (!dev->regs) { 228 dev_err(&pdev->dev, "Unable to remap SMI register\n"); 229 ret = -ENODEV; 230 goto out_mdio; 231 } 232 233 init_waitqueue_head(&dev->smi_busy_wait); 234 235 dev->clk = devm_clk_get(&pdev->dev, NULL); 236 if (!IS_ERR(dev->clk)) 237 clk_prepare_enable(dev->clk); 238 239 dev->err_interrupt = platform_get_irq(pdev, 0); 240 if (dev->err_interrupt != -ENXIO) { 241 ret = devm_request_irq(&pdev->dev, dev->err_interrupt, 242 orion_mdio_err_irq, 243 IRQF_SHARED, pdev->name, dev); 244 if (ret) 245 goto out_mdio; 246 247 writel(MVMDIO_ERR_INT_SMI_DONE, 248 dev->regs + MVMDIO_ERR_INT_MASK); 249 } 250 251 mutex_init(&dev->lock); 252 253 if (pdev->dev.of_node) 254 ret = of_mdiobus_register(bus, pdev->dev.of_node); 255 else 256 ret = mdiobus_register(bus); 257 if (ret < 0) { 258 dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); 259 goto out_mdio; 260 } 261 262 platform_set_drvdata(pdev, bus); 263 264 return 0; 265 266 out_mdio: 267 if (!IS_ERR(dev->clk)) 268 clk_disable_unprepare(dev->clk); 269 kfree(bus->irq); 270 mdiobus_free(bus); 271 return ret; 272 } 273 274 static int orion_mdio_remove(struct platform_device *pdev) 275 { 276 struct mii_bus *bus = platform_get_drvdata(pdev); 277 struct orion_mdio_dev *dev = bus->priv; 278 279 writel(0, dev->regs + MVMDIO_ERR_INT_MASK); 280 mdiobus_unregister(bus); 281 kfree(bus->irq); 282 mdiobus_free(bus); 283 if (!IS_ERR(dev->clk)) 284 clk_disable_unprepare(dev->clk); 285 286 return 0; 287 } 288 289 static const struct of_device_id orion_mdio_match[] = { 290 { .compatible = "marvell,orion-mdio" }, 291 { } 292 }; 293 MODULE_DEVICE_TABLE(of, orion_mdio_match); 294 295 static struct platform_driver orion_mdio_driver = { 296 .probe = orion_mdio_probe, 297 .remove = orion_mdio_remove, 298 .driver = { 299 .name = "orion-mdio", 300 .of_match_table = orion_mdio_match, 301 }, 302 }; 303 304 module_platform_driver(orion_mdio_driver); 305 306 MODULE_DESCRIPTION("Marvell MDIO interface driver"); 307 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); 308 MODULE_LICENSE("GPL"); 309 MODULE_ALIAS("platform:orion-mdio"); 310