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>
65 * - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt)
66 * - Armada 370 (Globalscale Mirabox): 41us to 43us (Polled)
95 struct mii_bus *bus) in orion_mdio_wait_ready() argument
97 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_wait_ready()
101 if (dev->err_interrupt <= 0) { in orion_mdio_wait_ready()
102 if (!read_poll_timeout_atomic(ops->is_done, done, done, 2, in orion_mdio_wait_ready()
112 if (wait_event_timeout(dev->smi_busy_wait, in orion_mdio_wait_ready()
113 ops->is_done(dev), timeout)) in orion_mdio_wait_ready()
117 dev_err(bus->parent, "Timeout: SMI busy for too long\n"); in orion_mdio_wait_ready()
118 return -ETIMEDOUT; in orion_mdio_wait_ready()
123 return !(readl(dev->regs) & MVMDIO_SMI_BUSY); in orion_mdio_smi_is_done()
130 static int orion_mdio_smi_read(struct mii_bus *bus, int mii_id, in orion_mdio_smi_read() argument
133 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_smi_read()
137 ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus); in orion_mdio_smi_read()
144 dev->regs); in orion_mdio_smi_read()
146 ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus); in orion_mdio_smi_read()
150 val = readl(dev->regs); in orion_mdio_smi_read()
152 dev_err(bus->parent, "SMI bus read not valid\n"); in orion_mdio_smi_read()
153 return -ENODEV; in orion_mdio_smi_read()
159 static int orion_mdio_smi_write(struct mii_bus *bus, int mii_id, in orion_mdio_smi_write() argument
162 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_smi_write()
165 ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus); in orion_mdio_smi_write()
173 dev->regs); in orion_mdio_smi_write()
180 return !(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_BUSY); in orion_mdio_xsmi_is_done()
187 static int orion_mdio_xsmi_read_c45(struct mii_bus *bus, int mii_id, in orion_mdio_xsmi_read_c45() argument
190 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_xsmi_read_c45()
193 ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus); in orion_mdio_xsmi_read_c45()
197 writel(regnum, dev->regs + MVMDIO_XSMI_ADDR_REG); in orion_mdio_xsmi_read_c45()
201 dev->regs + MVMDIO_XSMI_MGNT_REG); in orion_mdio_xsmi_read_c45()
203 ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus); in orion_mdio_xsmi_read_c45()
207 if (!(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & in orion_mdio_xsmi_read_c45()
209 dev_err(bus->parent, "XSMI bus read not valid\n"); in orion_mdio_xsmi_read_c45()
210 return -ENODEV; in orion_mdio_xsmi_read_c45()
213 return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0); in orion_mdio_xsmi_read_c45()
216 static int orion_mdio_xsmi_write_c45(struct mii_bus *bus, int mii_id, in orion_mdio_xsmi_write_c45() argument
219 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_xsmi_write_c45()
222 ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus); in orion_mdio_xsmi_write_c45()
226 writel(regnum, dev->regs + MVMDIO_XSMI_ADDR_REG); in orion_mdio_xsmi_write_c45()
230 dev->regs + MVMDIO_XSMI_MGNT_REG); in orion_mdio_xsmi_write_c45()
235 static void orion_mdio_xsmi_set_mdc_freq(struct mii_bus *bus) in orion_mdio_xsmi_set_mdc_freq() argument
237 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_xsmi_set_mdc_freq()
241 if (device_property_read_u32(bus->parent, "clock-frequency", &freq)) in orion_mdio_xsmi_set_mdc_freq()
244 mg_core = of_clk_get_by_name(bus->parent->of_node, "mg_core_clk"); in orion_mdio_xsmi_set_mdc_freq()
246 dev_err(bus->parent, in orion_mdio_xsmi_set_mdc_freq()
263 cfg = readl(dev->regs + MVMDIO_XSMI_CFG_REG); in orion_mdio_xsmi_set_mdc_freq()
266 writel(cfg, dev->regs + MVMDIO_XSMI_CFG_REG); in orion_mdio_xsmi_set_mdc_freq()
273 if (readl(dev->regs + MVMDIO_ERR_INT_CAUSE) & in orion_mdio_err_irq()
276 dev->regs + MVMDIO_ERR_INT_CAUSE); in orion_mdio_err_irq()
277 wake_up(&dev->smi_busy_wait); in orion_mdio_err_irq()
288 struct mii_bus *bus; in orion_mdio_probe() local
292 type = (uintptr_t)device_get_match_data(&pdev->dev); in orion_mdio_probe()
296 dev_err(&pdev->dev, "No SMI register address given\n"); in orion_mdio_probe()
297 return -ENODEV; in orion_mdio_probe()
300 bus = devm_mdiobus_alloc_size(&pdev->dev, in orion_mdio_probe()
302 if (!bus) in orion_mdio_probe()
303 return -ENOMEM; in orion_mdio_probe()
307 bus->read = orion_mdio_smi_read; in orion_mdio_probe()
308 bus->write = orion_mdio_smi_write; in orion_mdio_probe()
311 bus->read_c45 = orion_mdio_xsmi_read_c45; in orion_mdio_probe()
312 bus->write_c45 = orion_mdio_xsmi_write_c45; in orion_mdio_probe()
316 bus->name = "orion_mdio_bus"; in orion_mdio_probe()
317 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", in orion_mdio_probe()
318 dev_name(&pdev->dev)); in orion_mdio_probe()
319 bus->parent = &pdev->dev; in orion_mdio_probe()
321 dev = bus->priv; in orion_mdio_probe()
322 dev->regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); in orion_mdio_probe()
323 if (!dev->regs) { in orion_mdio_probe()
324 dev_err(&pdev->dev, "Unable to remap SMI register\n"); in orion_mdio_probe()
325 return -ENODEV; in orion_mdio_probe()
328 init_waitqueue_head(&dev->smi_busy_wait); in orion_mdio_probe()
330 if (pdev->dev.of_node) { in orion_mdio_probe()
331 for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { in orion_mdio_probe()
332 dev->clk[i] = of_clk_get(pdev->dev.of_node, i); in orion_mdio_probe()
333 if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) { in orion_mdio_probe()
334 ret = -EPROBE_DEFER; in orion_mdio_probe()
337 if (IS_ERR(dev->clk[i])) in orion_mdio_probe()
339 clk_prepare_enable(dev->clk[i]); in orion_mdio_probe()
342 if (!IS_ERR(of_clk_get(pdev->dev.of_node, in orion_mdio_probe()
343 ARRAY_SIZE(dev->clk)))) in orion_mdio_probe()
344 dev_warn(&pdev->dev, in orion_mdio_probe()
346 __stringify(ARRAY_SIZE(dev->clk)) "\n"); in orion_mdio_probe()
349 orion_mdio_xsmi_set_mdc_freq(bus); in orion_mdio_probe()
351 dev->clk[0] = clk_get(&pdev->dev, NULL); in orion_mdio_probe()
352 if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) { in orion_mdio_probe()
353 ret = -EPROBE_DEFER; in orion_mdio_probe()
356 if (!IS_ERR(dev->clk[0])) in orion_mdio_probe()
357 clk_prepare_enable(dev->clk[0]); in orion_mdio_probe()
361 dev->err_interrupt = platform_get_irq_optional(pdev, 0); in orion_mdio_probe()
362 if (dev->err_interrupt > 0 && in orion_mdio_probe()
364 dev_err(&pdev->dev, in orion_mdio_probe()
366 dev->err_interrupt = 0; in orion_mdio_probe()
368 if (dev->err_interrupt > 0) { in orion_mdio_probe()
369 ret = devm_request_irq(&pdev->dev, dev->err_interrupt, in orion_mdio_probe()
371 IRQF_SHARED, pdev->name, dev); in orion_mdio_probe()
376 dev->regs + MVMDIO_ERR_INT_MASK); in orion_mdio_probe()
378 } else if (dev->err_interrupt == -EPROBE_DEFER) { in orion_mdio_probe()
379 ret = -EPROBE_DEFER; in orion_mdio_probe()
383 /* For the platforms not supporting DT/ACPI fall-back in orion_mdio_probe()
386 if (is_acpi_node(pdev->dev.fwnode)) in orion_mdio_probe()
387 ret = acpi_mdiobus_register(bus, pdev->dev.fwnode); in orion_mdio_probe()
389 ret = of_mdiobus_register(bus, pdev->dev.of_node); in orion_mdio_probe()
391 dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); in orion_mdio_probe()
395 platform_set_drvdata(pdev, bus); in orion_mdio_probe()
400 if (dev->err_interrupt > 0) in orion_mdio_probe()
401 writel(0, dev->regs + MVMDIO_ERR_INT_MASK); in orion_mdio_probe()
404 for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { in orion_mdio_probe()
405 if (IS_ERR(dev->clk[i])) in orion_mdio_probe()
407 clk_disable_unprepare(dev->clk[i]); in orion_mdio_probe()
408 clk_put(dev->clk[i]); in orion_mdio_probe()
416 struct mii_bus *bus = platform_get_drvdata(pdev); in orion_mdio_remove() local
417 struct orion_mdio_dev *dev = bus->priv; in orion_mdio_remove()
420 if (dev->err_interrupt > 0) in orion_mdio_remove()
421 writel(0, dev->regs + MVMDIO_ERR_INT_MASK); in orion_mdio_remove()
422 mdiobus_unregister(bus); in orion_mdio_remove()
424 for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { in orion_mdio_remove()
425 if (IS_ERR(dev->clk[i])) in orion_mdio_remove()
427 clk_disable_unprepare(dev->clk[i]); in orion_mdio_remove()
428 clk_put(dev->clk[i]); in orion_mdio_remove()
433 { .compatible = "marvell,orion-mdio", .data = (void *)BUS_TYPE_SMI },
452 .name = "orion-mdio",
460 MODULE_DESCRIPTION("Marvell MDIO interface driver");
461 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
463 MODULE_ALIAS("platform:orion-mdio");