Lines Matching +full:smi +full:- +full:mdio
2 * Driver for the MDIO interface of Marvell network interfaces.
4 * Since the MDIO interface of Marvell network interfaces is shared
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
13 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
56 * SMI Timeout measurements:
57 * - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt)
58 * - Armada 370 (Globalscale Mirabox): 41us to 43us (Polled)
73 * but also reflects SMI completion), use that to wait for
74 * SMI access completion instead of polling the SMI busy bit.
91 /* Wait for the SMI unit to be ready for another operation
96 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_wait_ready()
102 if (ops->is_done(dev)) in orion_mdio_wait_ready()
107 if (dev->err_interrupt <= 0) { in orion_mdio_wait_ready()
108 usleep_range(ops->poll_interval_min, in orion_mdio_wait_ready()
109 ops->poll_interval_max); in orion_mdio_wait_ready()
120 wait_event_timeout(dev->smi_busy_wait, in orion_mdio_wait_ready()
121 ops->is_done(dev), timeout); in orion_mdio_wait_ready()
127 dev_err(bus->parent, "Timeout: SMI busy for too long\n"); in orion_mdio_wait_ready()
128 return -ETIMEDOUT; in orion_mdio_wait_ready()
133 return !(readl(dev->regs) & MVMDIO_SMI_BUSY); in orion_mdio_smi_is_done()
145 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_smi_read()
150 return -EOPNOTSUPP; in orion_mdio_smi_read()
159 dev->regs); in orion_mdio_smi_read()
165 val = readl(dev->regs); in orion_mdio_smi_read()
167 dev_err(bus->parent, "SMI bus read not valid\n"); in orion_mdio_smi_read()
168 return -ENODEV; in orion_mdio_smi_read()
177 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_smi_write()
181 return -EOPNOTSUPP; in orion_mdio_smi_write()
191 dev->regs); in orion_mdio_smi_write()
198 return !(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_BUSY); in orion_mdio_xsmi_is_done()
210 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_xsmi_read()
215 return -EOPNOTSUPP; in orion_mdio_xsmi_read()
221 writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG); in orion_mdio_xsmi_read()
225 dev->regs + MVMDIO_XSMI_MGNT_REG); in orion_mdio_xsmi_read()
231 if (!(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & in orion_mdio_xsmi_read()
233 dev_err(bus->parent, "XSMI bus read not valid\n"); in orion_mdio_xsmi_read()
234 return -ENODEV; in orion_mdio_xsmi_read()
237 return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0); in orion_mdio_xsmi_read()
243 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_xsmi_write()
248 return -EOPNOTSUPP; in orion_mdio_xsmi_write()
254 writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG); in orion_mdio_xsmi_write()
258 dev->regs + MVMDIO_XSMI_MGNT_REG); in orion_mdio_xsmi_write()
267 if (readl(dev->regs + MVMDIO_ERR_INT_CAUSE) & in orion_mdio_err_irq()
270 dev->regs + MVMDIO_ERR_INT_CAUSE); in orion_mdio_err_irq()
271 wake_up(&dev->smi_busy_wait); in orion_mdio_err_irq()
286 type = (enum orion_mdio_bus_type)device_get_match_data(&pdev->dev); in orion_mdio_probe()
290 dev_err(&pdev->dev, "No SMI register address given\n"); in orion_mdio_probe()
291 return -ENODEV; in orion_mdio_probe()
294 bus = devm_mdiobus_alloc_size(&pdev->dev, in orion_mdio_probe()
297 return -ENOMEM; in orion_mdio_probe()
301 bus->read = orion_mdio_smi_read; in orion_mdio_probe()
302 bus->write = orion_mdio_smi_write; in orion_mdio_probe()
305 bus->read = orion_mdio_xsmi_read; in orion_mdio_probe()
306 bus->write = orion_mdio_xsmi_write; in orion_mdio_probe()
310 bus->name = "orion_mdio_bus"; in orion_mdio_probe()
311 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", in orion_mdio_probe()
312 dev_name(&pdev->dev)); in orion_mdio_probe()
313 bus->parent = &pdev->dev; in orion_mdio_probe()
315 dev = bus->priv; in orion_mdio_probe()
316 dev->regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); in orion_mdio_probe()
317 if (!dev->regs) { in orion_mdio_probe()
318 dev_err(&pdev->dev, "Unable to remap SMI register\n"); in orion_mdio_probe()
319 return -ENODEV; in orion_mdio_probe()
322 init_waitqueue_head(&dev->smi_busy_wait); in orion_mdio_probe()
324 if (pdev->dev.of_node) { in orion_mdio_probe()
325 for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { in orion_mdio_probe()
326 dev->clk[i] = of_clk_get(pdev->dev.of_node, i); in orion_mdio_probe()
327 if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) { in orion_mdio_probe()
328 ret = -EPROBE_DEFER; in orion_mdio_probe()
331 if (IS_ERR(dev->clk[i])) in orion_mdio_probe()
333 clk_prepare_enable(dev->clk[i]); in orion_mdio_probe()
336 if (!IS_ERR(of_clk_get(pdev->dev.of_node, in orion_mdio_probe()
337 ARRAY_SIZE(dev->clk)))) in orion_mdio_probe()
338 dev_warn(&pdev->dev, in orion_mdio_probe()
340 __stringify(ARRAY_SIZE(dev->clk)) "\n"); in orion_mdio_probe()
342 dev->clk[0] = clk_get(&pdev->dev, NULL); in orion_mdio_probe()
343 if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) { in orion_mdio_probe()
344 ret = -EPROBE_DEFER; in orion_mdio_probe()
347 if (!IS_ERR(dev->clk[0])) in orion_mdio_probe()
348 clk_prepare_enable(dev->clk[0]); in orion_mdio_probe()
352 dev->err_interrupt = platform_get_irq_optional(pdev, 0); in orion_mdio_probe()
353 if (dev->err_interrupt > 0 && in orion_mdio_probe()
355 dev_err(&pdev->dev, in orion_mdio_probe()
357 dev->err_interrupt = 0; in orion_mdio_probe()
359 if (dev->err_interrupt > 0) { in orion_mdio_probe()
360 ret = devm_request_irq(&pdev->dev, dev->err_interrupt, in orion_mdio_probe()
362 IRQF_SHARED, pdev->name, dev); in orion_mdio_probe()
367 dev->regs + MVMDIO_ERR_INT_MASK); in orion_mdio_probe()
369 } else if (dev->err_interrupt == -EPROBE_DEFER) { in orion_mdio_probe()
370 ret = -EPROBE_DEFER; in orion_mdio_probe()
374 /* For the platforms not supporting DT/ACPI fall-back in orion_mdio_probe()
377 if (is_acpi_node(pdev->dev.fwnode)) in orion_mdio_probe()
378 ret = acpi_mdiobus_register(bus, pdev->dev.fwnode); in orion_mdio_probe()
380 ret = of_mdiobus_register(bus, pdev->dev.of_node); in orion_mdio_probe()
382 dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); in orion_mdio_probe()
391 if (dev->err_interrupt > 0) in orion_mdio_probe()
392 writel(0, dev->regs + MVMDIO_ERR_INT_MASK); in orion_mdio_probe()
395 for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { in orion_mdio_probe()
396 if (IS_ERR(dev->clk[i])) in orion_mdio_probe()
398 clk_disable_unprepare(dev->clk[i]); in orion_mdio_probe()
399 clk_put(dev->clk[i]); in orion_mdio_probe()
408 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_remove()
411 if (dev->err_interrupt > 0) in orion_mdio_remove()
412 writel(0, dev->regs + MVMDIO_ERR_INT_MASK); in orion_mdio_remove()
415 for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { in orion_mdio_remove()
416 if (IS_ERR(dev->clk[i])) in orion_mdio_remove()
418 clk_disable_unprepare(dev->clk[i]); in orion_mdio_remove()
419 clk_put(dev->clk[i]); in orion_mdio_remove()
426 { .compatible = "marvell,orion-mdio", .data = (void *)BUS_TYPE_SMI },
445 .name = "orion-mdio",
453 MODULE_DESCRIPTION("Marvell MDIO interface driver");
454 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
456 MODULE_ALIAS("platform:orion-mdio");