Lines Matching +full:mdio +full:- +full:gpio
1 // SPDX-License-Identifier: GPL-2.0+
3 * Fixed MDIO bus (MDIO bus emulation with fixed PHYs)
8 * Copyright (c) 2006-2007 MontaVista Software, Inc.
21 #include <linux/gpio/consumer.h>
51 struct phy_device *phydev = dev->phydev; in fixed_phy_change_carrier()
54 if (!phydev || !phydev->mdio.bus) in fixed_phy_change_carrier()
55 return -EINVAL; in fixed_phy_change_carrier()
57 list_for_each_entry(fp, &fmb->phys, node) { in fixed_phy_change_carrier()
58 if (fp->addr == phydev->mdio.addr) { in fixed_phy_change_carrier()
59 fp->no_carrier = !new_carrier; in fixed_phy_change_carrier()
63 return -EINVAL; in fixed_phy_change_carrier()
69 if (!fp->no_carrier && fp->link_gpiod) in fixed_phy_update()
70 fp->status.link = !!gpiod_get_value_cansleep(fp->link_gpiod); in fixed_phy_update()
75 struct fixed_mdio_bus *fmb = bus->priv; in fixed_mdio_read()
78 list_for_each_entry(fp, &fmb->phys, node) { in fixed_mdio_read()
79 if (fp->addr == phy_addr) { in fixed_mdio_read()
82 fp->status.link = !fp->no_carrier; in fixed_mdio_read()
85 if (fp->link_update) in fixed_mdio_read()
86 fp->link_update(fp->phydev->attached_dev, in fixed_mdio_read()
87 &fp->status); in fixed_mdio_read()
89 /* Check the GPIO for change in status */ in fixed_mdio_read()
91 state = fp->status; in fixed_mdio_read()
109 * May be useful for PHY's that need to be software-driven.
118 if (!phydev || !phydev->mdio.bus) in fixed_phy_set_link_update()
119 return -EINVAL; in fixed_phy_set_link_update()
121 list_for_each_entry(fp, &fmb->phys, node) { in fixed_phy_set_link_update()
122 if (fp->addr == phydev->mdio.addr) { in fixed_phy_set_link_update()
123 fp->link_update = link_update; in fixed_phy_set_link_update()
124 fp->phydev = phydev; in fixed_phy_set_link_update()
129 return -ENOENT; in fixed_phy_set_link_update()
147 return -ENOMEM; in fixed_phy_add_gpiod()
150 fmb->mii_bus->irq[phy_addr] = irq; in fixed_phy_add_gpiod()
152 fp->addr = phy_addr; in fixed_phy_add_gpiod()
153 fp->status = *status; in fixed_phy_add_gpiod()
154 fp->link_gpiod = gpiod; in fixed_phy_add_gpiod()
158 list_add_tail(&fp->node, &fmb->phys); in fixed_phy_add_gpiod()
177 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { in fixed_phy_del()
178 if (fp->addr == phy_addr) { in fixed_phy_del()
179 list_del(&fp->node); in fixed_phy_del()
180 if (fp->link_gpiod) in fixed_phy_del()
181 gpiod_put(fp->link_gpiod); in fixed_phy_del()
198 fixed_link_node = of_get_child_by_name(np, "fixed-link"); in fixed_phy_get_gpiod()
205 * the GPIO descriptor from the device tree like this. in fixed_phy_get_gpiod()
208 "link", 0, GPIOD_IN, "mdio"); in fixed_phy_get_gpiod()
209 if (IS_ERR(gpiod) && PTR_ERR(gpiod) != -EPROBE_DEFER) { in fixed_phy_get_gpiod()
210 if (PTR_ERR(gpiod) != -ENOENT) in fixed_phy_get_gpiod()
211 pr_err("error getting GPIO for fixed link %pOF, proceed without\n", in fixed_phy_get_gpiod()
236 if (!fmb->mii_bus || fmb->mii_bus->state != MDIOBUS_REGISTERED) in __fixed_phy_register()
237 return ERR_PTR(-EPROBE_DEFER); in __fixed_phy_register()
239 /* Check if we have a GPIO associated with this fixed phy */ in __fixed_phy_register()
247 phy_addr = ida_alloc_max(&phy_fixed_ida, PHY_MAX_ADDR - 1, GFP_KERNEL); in __fixed_phy_register()
257 phy = get_phy_device(fmb->mii_bus, phy_addr, false); in __fixed_phy_register()
260 return ERR_PTR(-EINVAL); in __fixed_phy_register()
264 phy->link = status->link; in __fixed_phy_register()
265 if (status->link) { in __fixed_phy_register()
266 phy->speed = status->speed; in __fixed_phy_register()
267 phy->duplex = status->duplex; in __fixed_phy_register()
268 phy->pause = status->pause; in __fixed_phy_register()
269 phy->asym_pause = status->asym_pause; in __fixed_phy_register()
273 phy->mdio.dev.of_node = np; in __fixed_phy_register()
274 phy->is_pseudo_fixed_link = true; in __fixed_phy_register()
276 switch (status->speed) { in __fixed_phy_register()
279 phy->supported); in __fixed_phy_register()
281 phy->supported); in __fixed_phy_register()
285 phy->supported); in __fixed_phy_register()
287 phy->supported); in __fixed_phy_register()
292 phy->supported); in __fixed_phy_register()
294 phy->supported); in __fixed_phy_register()
330 of_node_put(phy->mdio.dev.of_node); in fixed_phy_unregister()
331 fixed_phy_del(phy->mdio.addr); in fixed_phy_unregister()
340 pdev = platform_device_register_simple("Fixed MDIO bus", 0, NULL, 0); in fixed_mdio_bus_init()
344 fmb->mii_bus = mdiobus_alloc(); in fixed_mdio_bus_init()
345 if (fmb->mii_bus == NULL) { in fixed_mdio_bus_init()
346 ret = -ENOMEM; in fixed_mdio_bus_init()
350 snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "fixed-0"); in fixed_mdio_bus_init()
351 fmb->mii_bus->name = "Fixed MDIO Bus"; in fixed_mdio_bus_init()
352 fmb->mii_bus->priv = fmb; in fixed_mdio_bus_init()
353 fmb->mii_bus->parent = &pdev->dev; in fixed_mdio_bus_init()
354 fmb->mii_bus->read = &fixed_mdio_read; in fixed_mdio_bus_init()
355 fmb->mii_bus->write = &fixed_mdio_write; in fixed_mdio_bus_init()
356 fmb->mii_bus->phy_mask = ~0; in fixed_mdio_bus_init()
358 ret = mdiobus_register(fmb->mii_bus); in fixed_mdio_bus_init()
365 mdiobus_free(fmb->mii_bus); in fixed_mdio_bus_init()
377 mdiobus_unregister(fmb->mii_bus); in fixed_mdio_bus_exit()
378 mdiobus_free(fmb->mii_bus); in fixed_mdio_bus_exit()
381 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { in fixed_mdio_bus_exit()
382 list_del(&fp->node); in fixed_mdio_bus_exit()
389 MODULE_DESCRIPTION("Fixed MDIO bus (MDIO bus emulation with fixed PHYs)");