Lines Matching +full:mdio +full:- +full:parent +full:- +full:bus

2  * Driver for the MDIO interface of Marvell network interfaces.
4 * Since the MDIO interface of Marvell network interfaces is shared
8 * the MDIO bus). This driver is currently used by the mvneta and
13 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
55 * - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt)
56 * - Armada 370 (Globalscale Mirabox): 41us to 43us (Polled)
92 struct mii_bus *bus) in orion_mdio_wait_ready() argument
94 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_wait_ready()
100 if (ops->is_done(dev)) in orion_mdio_wait_ready()
105 if (dev->err_interrupt <= 0) { in orion_mdio_wait_ready()
106 usleep_range(ops->poll_interval_min, in orion_mdio_wait_ready()
107 ops->poll_interval_max); in orion_mdio_wait_ready()
118 wait_event_timeout(dev->smi_busy_wait, in orion_mdio_wait_ready()
119 ops->is_done(dev), timeout); in orion_mdio_wait_ready()
125 dev_err(bus->parent, "Timeout: SMI busy for too long\n"); in orion_mdio_wait_ready()
126 return -ETIMEDOUT; in orion_mdio_wait_ready()
131 return !(readl(dev->regs) & MVMDIO_SMI_BUSY); in orion_mdio_smi_is_done()
140 static int orion_mdio_smi_read(struct mii_bus *bus, int mii_id, in orion_mdio_smi_read() argument
143 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_smi_read()
148 return -EOPNOTSUPP; in orion_mdio_smi_read()
150 ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus); in orion_mdio_smi_read()
157 dev->regs); in orion_mdio_smi_read()
159 ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus); in orion_mdio_smi_read()
163 val = readl(dev->regs); in orion_mdio_smi_read()
165 dev_err(bus->parent, "SMI bus read not valid\n"); in orion_mdio_smi_read()
166 return -ENODEV; in orion_mdio_smi_read()
172 static int orion_mdio_smi_write(struct mii_bus *bus, int mii_id, in orion_mdio_smi_write() argument
175 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_smi_write()
179 return -EOPNOTSUPP; in orion_mdio_smi_write()
181 ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus); in orion_mdio_smi_write()
189 dev->regs); in orion_mdio_smi_write()
196 return !(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_BUSY); in orion_mdio_xsmi_is_done()
205 static int orion_mdio_xsmi_read(struct mii_bus *bus, int mii_id, in orion_mdio_xsmi_read() argument
208 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_xsmi_read()
213 return -EOPNOTSUPP; in orion_mdio_xsmi_read()
215 ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus); in orion_mdio_xsmi_read()
219 writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG); in orion_mdio_xsmi_read()
223 dev->regs + MVMDIO_XSMI_MGNT_REG); in orion_mdio_xsmi_read()
225 ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus); in orion_mdio_xsmi_read()
229 if (!(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & in orion_mdio_xsmi_read()
231 dev_err(bus->parent, "XSMI bus read not valid\n"); in orion_mdio_xsmi_read()
232 return -ENODEV; in orion_mdio_xsmi_read()
235 return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0); in orion_mdio_xsmi_read()
238 static int orion_mdio_xsmi_write(struct mii_bus *bus, int mii_id, in orion_mdio_xsmi_write() argument
241 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_xsmi_write()
246 return -EOPNOTSUPP; in orion_mdio_xsmi_write()
248 ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus); in orion_mdio_xsmi_write()
252 writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG); in orion_mdio_xsmi_write()
256 dev->regs + MVMDIO_XSMI_MGNT_REG); in orion_mdio_xsmi_write()
265 if (readl(dev->regs + MVMDIO_ERR_INT_CAUSE) & in orion_mdio_err_irq()
268 dev->regs + MVMDIO_ERR_INT_CAUSE); in orion_mdio_err_irq()
269 wake_up(&dev->smi_busy_wait); in orion_mdio_err_irq()
280 struct mii_bus *bus; in orion_mdio_probe() local
284 type = (enum orion_mdio_bus_type)of_device_get_match_data(&pdev->dev); in orion_mdio_probe()
288 dev_err(&pdev->dev, "No SMI register address given\n"); in orion_mdio_probe()
289 return -ENODEV; in orion_mdio_probe()
292 bus = devm_mdiobus_alloc_size(&pdev->dev, in orion_mdio_probe()
294 if (!bus) in orion_mdio_probe()
295 return -ENOMEM; in orion_mdio_probe()
299 bus->read = orion_mdio_smi_read; in orion_mdio_probe()
300 bus->write = orion_mdio_smi_write; in orion_mdio_probe()
303 bus->read = orion_mdio_xsmi_read; in orion_mdio_probe()
304 bus->write = orion_mdio_xsmi_write; in orion_mdio_probe()
308 bus->name = "orion_mdio_bus"; in orion_mdio_probe()
309 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", in orion_mdio_probe()
310 dev_name(&pdev->dev)); in orion_mdio_probe()
311 bus->parent = &pdev->dev; in orion_mdio_probe()
313 dev = bus->priv; in orion_mdio_probe()
314 dev->regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); in orion_mdio_probe()
315 if (!dev->regs) { in orion_mdio_probe()
316 dev_err(&pdev->dev, "Unable to remap SMI register\n"); in orion_mdio_probe()
317 return -ENODEV; in orion_mdio_probe()
320 init_waitqueue_head(&dev->smi_busy_wait); in orion_mdio_probe()
322 if (pdev->dev.of_node) { in orion_mdio_probe()
323 for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { in orion_mdio_probe()
324 dev->clk[i] = of_clk_get(pdev->dev.of_node, i); in orion_mdio_probe()
325 if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) { in orion_mdio_probe()
326 ret = -EPROBE_DEFER; in orion_mdio_probe()
329 if (IS_ERR(dev->clk[i])) in orion_mdio_probe()
331 clk_prepare_enable(dev->clk[i]); in orion_mdio_probe()
334 if (!IS_ERR(of_clk_get(pdev->dev.of_node, in orion_mdio_probe()
335 ARRAY_SIZE(dev->clk)))) in orion_mdio_probe()
336 dev_warn(&pdev->dev, in orion_mdio_probe()
338 __stringify(ARRAY_SIZE(dev->clk)) "\n"); in orion_mdio_probe()
340 dev->clk[0] = clk_get(&pdev->dev, NULL); in orion_mdio_probe()
341 if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) { in orion_mdio_probe()
342 ret = -EPROBE_DEFER; in orion_mdio_probe()
345 if (!IS_ERR(dev->clk[0])) in orion_mdio_probe()
346 clk_prepare_enable(dev->clk[0]); in orion_mdio_probe()
350 dev->err_interrupt = platform_get_irq_optional(pdev, 0); in orion_mdio_probe()
351 if (dev->err_interrupt > 0 && in orion_mdio_probe()
353 dev_err(&pdev->dev, in orion_mdio_probe()
355 dev->err_interrupt = 0; in orion_mdio_probe()
357 if (dev->err_interrupt > 0) { in orion_mdio_probe()
358 ret = devm_request_irq(&pdev->dev, dev->err_interrupt, in orion_mdio_probe()
360 IRQF_SHARED, pdev->name, dev); in orion_mdio_probe()
365 dev->regs + MVMDIO_ERR_INT_MASK); in orion_mdio_probe()
367 } else if (dev->err_interrupt == -EPROBE_DEFER) { in orion_mdio_probe()
368 ret = -EPROBE_DEFER; in orion_mdio_probe()
372 ret = of_mdiobus_register(bus, pdev->dev.of_node); in orion_mdio_probe()
374 dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); in orion_mdio_probe()
378 platform_set_drvdata(pdev, bus); in orion_mdio_probe()
383 if (dev->err_interrupt > 0) in orion_mdio_probe()
384 writel(0, dev->regs + MVMDIO_ERR_INT_MASK); in orion_mdio_probe()
387 for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { in orion_mdio_probe()
388 if (IS_ERR(dev->clk[i])) in orion_mdio_probe()
390 clk_disable_unprepare(dev->clk[i]); in orion_mdio_probe()
391 clk_put(dev->clk[i]); in orion_mdio_probe()
399 struct mii_bus *bus = platform_get_drvdata(pdev); in orion_mdio_remove() local
400 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_remove()
403 if (dev->err_interrupt > 0) in orion_mdio_remove()
404 writel(0, dev->regs + MVMDIO_ERR_INT_MASK); in orion_mdio_remove()
405 mdiobus_unregister(bus); in orion_mdio_remove()
407 for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { in orion_mdio_remove()
408 if (IS_ERR(dev->clk[i])) in orion_mdio_remove()
410 clk_disable_unprepare(dev->clk[i]); in orion_mdio_remove()
411 clk_put(dev->clk[i]); in orion_mdio_remove()
418 { .compatible = "marvell,orion-mdio", .data = (void *)BUS_TYPE_SMI },
428 .name = "orion-mdio",
435 MODULE_DESCRIPTION("Marvell MDIO interface driver");
436 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
438 MODULE_ALIAS("platform:orion-mdio");