^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/of_mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) struct mdiobus_devres {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) struct mii_bus *mii;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static void devm_mdiobus_free(struct device *dev, void *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct mdiobus_devres *dr = this;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) mdiobus_free(dr->mii);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * devm_mdiobus_alloc_size - Resource-managed mdiobus_alloc_size()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * @dev: Device to allocate mii_bus for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * @sizeof_priv: Space to allocate for private structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Managed mdiobus_alloc_size. mii_bus allocated with this function is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * automatically freed on driver detach.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * RETURNS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Pointer to allocated mii_bus on success, NULL on out-of-memory error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct mdiobus_devres *dr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) dr = devres_alloc(devm_mdiobus_free, sizeof(*dr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (!dr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) dr->mii = mdiobus_alloc_size(sizeof_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (!dr->mii) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) devres_free(dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) devres_add(dev, dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return dr->mii;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) EXPORT_SYMBOL(devm_mdiobus_alloc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static void devm_mdiobus_unregister(struct device *dev, void *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct mdiobus_devres *dr = this;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) mdiobus_unregister(dr->mii);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static int mdiobus_devres_match(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void *this, void *match_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct mdiobus_devres *res = this;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct mii_bus *mii = match_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return mii == res->mii;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * __devm_mdiobus_register - Resource-managed variant of mdiobus_register()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * @dev: Device to register mii_bus for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * @bus: MII bus structure to register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * @owner: Owning module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * Returns 0 on success, negative error number on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int __devm_mdiobus_register(struct device *dev, struct mii_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct module *owner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct mdiobus_devres *dr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (WARN_ON(!devres_find(dev, devm_mdiobus_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) mdiobus_devres_match, bus)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) dr = devres_alloc(devm_mdiobus_unregister, sizeof(*dr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (!dr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ret = __mdiobus_register(bus, owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) devres_free(dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) dr->mii = bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) devres_add(dev, dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) EXPORT_SYMBOL(__devm_mdiobus_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #if IS_ENABLED(CONFIG_OF_MDIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * @dev: Device to register mii_bus for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * @mdio: MII bus structure to register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @np: Device node to parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct mdiobus_devres *dr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (WARN_ON(!devres_find(dev, devm_mdiobus_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) mdiobus_devres_match, mdio)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) dr = devres_alloc(devm_mdiobus_unregister, sizeof(*dr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (!dr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ret = of_mdiobus_register(mdio, np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) devres_free(dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) dr->mii = mdio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) devres_add(dev, dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) EXPORT_SYMBOL(devm_of_mdiobus_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #endif /* CONFIG_OF_MDIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) MODULE_LICENSE("GPL");