^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* MDIO Bus interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Andy Fleming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2004 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/ethtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/mii.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/of_gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/of_mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define CREATE_TRACE_POINTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <trace/events/mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include "mdio-boardinfo.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int mdiobus_register_gpiod(struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Deassert the optional reset signal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) mdiodev->reset_gpio = gpiod_get_optional(&mdiodev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) "reset", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (IS_ERR(mdiodev->reset_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return PTR_ERR(mdiodev->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (mdiodev->reset_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) gpiod_set_consumer_name(mdiodev->reset_gpio, "PHY reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static int mdiobus_register_reset(struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct reset_control *reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) reset = reset_control_get_optional_exclusive(&mdiodev->dev, "phy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (IS_ERR(reset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return PTR_ERR(reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) mdiodev->reset_ctrl = reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int mdiobus_register_device(struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (mdiodev->bus->mdio_map[mdiodev->addr])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) err = mdiobus_register_gpiod(mdiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) err = mdiobus_register_reset(mdiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Assert the reset signal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) mdio_device_reset(mdiodev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) EXPORT_SYMBOL(mdiobus_register_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int mdiobus_unregister_device(struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) reset_control_put(mdiodev->reset_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) mdiodev->bus->mdio_map[mdiodev->addr] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) EXPORT_SYMBOL(mdiobus_unregister_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct mdio_device *mdiodev = bus->mdio_map[addr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (!(mdiodev->flags & MDIO_DEVICE_FLAG_PHY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return container_of(mdiodev, struct phy_device, mdio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) EXPORT_SYMBOL(mdiobus_get_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) bool mdiobus_is_registered_device(struct mii_bus *bus, int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return bus->mdio_map[addr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) EXPORT_SYMBOL(mdiobus_is_registered_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * mdiobus_alloc_size - allocate a mii_bus structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * @size: extra amount of memory to allocate for private storage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * If non-zero, then bus->priv is points to that memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * Description: called by a bus driver to allocate an mii_bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * structure to fill in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct mii_bus *mdiobus_alloc_size(size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct mii_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) size_t aligned_size = ALIGN(sizeof(*bus), NETDEV_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) size_t alloc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* If we alloc extra space, it should be aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) alloc_size = aligned_size + size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) alloc_size = sizeof(*bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) bus = kzalloc(alloc_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (!bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) bus->state = MDIOBUS_ALLOCATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) bus->priv = (void *)bus + aligned_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* Initialise the interrupts to polling and 64-bit seqcounts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) for (i = 0; i < PHY_MAX_ADDR; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) bus->irq[i] = PHY_POLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u64_stats_init(&bus->stats[i].syncp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) EXPORT_SYMBOL(mdiobus_alloc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * mdiobus_release - mii_bus device release callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * @d: the target struct device that contains the mii_bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * Description: called when the last reference to an mii_bus is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * dropped, to free the underlying memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void mdiobus_release(struct device *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct mii_bus *bus = to_mii_bus(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) BUG_ON(bus->state != MDIOBUS_RELEASED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* for compatibility with error handling in drivers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) bus->state != MDIOBUS_ALLOCATED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) kfree(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct mdio_bus_stat_attr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) int addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) unsigned int field_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static u64 mdio_bus_get_stat(struct mdio_bus_stats *s, unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) const char *p = (const char *)s + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned int start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) u64 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) start = u64_stats_fetch_begin(&s->syncp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) val = u64_stats_read((const u64_stats_t *)p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) } while (u64_stats_fetch_retry(&s->syncp, start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static u64 mdio_bus_get_global_stat(struct mii_bus *bus, unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) u64 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) for (i = 0; i < PHY_MAX_ADDR; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) val += mdio_bus_get_stat(&bus->stats[i], offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static ssize_t mdio_bus_stat_field_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct mii_bus *bus = to_mii_bus(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct mdio_bus_stat_attr *sattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct dev_ext_attribute *eattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) eattr = container_of(attr, struct dev_ext_attribute, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) sattr = eattr->var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (sattr->addr < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) val = mdio_bus_get_global_stat(bus, sattr->field_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) val = mdio_bus_get_stat(&bus->stats[sattr->addr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) sattr->field_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return sprintf(buf, "%llu\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static ssize_t mdio_bus_device_stat_field_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct mdio_device *mdiodev = to_mdio_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct mii_bus *bus = mdiodev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct mdio_bus_stat_attr *sattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct dev_ext_attribute *eattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int addr = mdiodev->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) eattr = container_of(attr, struct dev_ext_attribute, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) sattr = eattr->var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) val = mdio_bus_get_stat(&bus->stats[addr], sattr->field_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return sprintf(buf, "%llu\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) #define MDIO_BUS_STATS_ATTR_DECL(field, file) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static struct dev_ext_attribute dev_attr_mdio_bus_##field = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .attr = { .attr = { .name = file, .mode = 0444 }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .show = mdio_bus_stat_field_show, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .var = &((struct mdio_bus_stat_attr) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) -1, offsetof(struct mdio_bus_stats, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static struct dev_ext_attribute dev_attr_mdio_bus_device_##field = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .attr = { .attr = { .name = file, .mode = 0444 }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .show = mdio_bus_device_stat_field_show, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .var = &((struct mdio_bus_stat_attr) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) -1, offsetof(struct mdio_bus_stats, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #define MDIO_BUS_STATS_ATTR(field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) MDIO_BUS_STATS_ATTR_DECL(field, __stringify(field))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) MDIO_BUS_STATS_ATTR(transfers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) MDIO_BUS_STATS_ATTR(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) MDIO_BUS_STATS_ATTR(writes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) MDIO_BUS_STATS_ATTR(reads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) #define MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, file) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static struct dev_ext_attribute dev_attr_mdio_bus_addr_##field##_##addr = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .attr = { .attr = { .name = file, .mode = 0444 }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .show = mdio_bus_stat_field_show, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .var = &((struct mdio_bus_stat_attr) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) addr, offsetof(struct mdio_bus_stats, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) #define MDIO_BUS_STATS_ADDR_ATTR(field, addr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) __stringify(field) "_" __stringify(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) #define MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(addr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) MDIO_BUS_STATS_ADDR_ATTR(transfers, addr); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) MDIO_BUS_STATS_ADDR_ATTR(errors, addr); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) MDIO_BUS_STATS_ADDR_ATTR(writes, addr); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) MDIO_BUS_STATS_ADDR_ATTR(reads, addr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(19);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(22);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(23);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(26);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(27);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(29);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) #define MDIO_BUS_STATS_ADDR_ATTR_GROUP(addr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) &dev_attr_mdio_bus_addr_transfers_##addr.attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) &dev_attr_mdio_bus_addr_errors_##addr.attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) &dev_attr_mdio_bus_addr_writes_##addr.attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) &dev_attr_mdio_bus_addr_reads_##addr.attr.attr \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static struct attribute *mdio_bus_statistics_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) &dev_attr_mdio_bus_transfers.attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) &dev_attr_mdio_bus_errors.attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) &dev_attr_mdio_bus_writes.attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) &dev_attr_mdio_bus_reads.attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) MDIO_BUS_STATS_ADDR_ATTR_GROUP(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) MDIO_BUS_STATS_ADDR_ATTR_GROUP(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MDIO_BUS_STATS_ADDR_ATTR_GROUP(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) MDIO_BUS_STATS_ADDR_ATTR_GROUP(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) MDIO_BUS_STATS_ADDR_ATTR_GROUP(4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) MDIO_BUS_STATS_ADDR_ATTR_GROUP(5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) MDIO_BUS_STATS_ADDR_ATTR_GROUP(6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) MDIO_BUS_STATS_ADDR_ATTR_GROUP(7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) MDIO_BUS_STATS_ADDR_ATTR_GROUP(8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) MDIO_BUS_STATS_ADDR_ATTR_GROUP(9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) MDIO_BUS_STATS_ADDR_ATTR_GROUP(10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) MDIO_BUS_STATS_ADDR_ATTR_GROUP(11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) MDIO_BUS_STATS_ADDR_ATTR_GROUP(12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) MDIO_BUS_STATS_ADDR_ATTR_GROUP(13),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) MDIO_BUS_STATS_ADDR_ATTR_GROUP(14),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) MDIO_BUS_STATS_ADDR_ATTR_GROUP(15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) MDIO_BUS_STATS_ADDR_ATTR_GROUP(16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) MDIO_BUS_STATS_ADDR_ATTR_GROUP(17),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) MDIO_BUS_STATS_ADDR_ATTR_GROUP(18),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) MDIO_BUS_STATS_ADDR_ATTR_GROUP(19),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) MDIO_BUS_STATS_ADDR_ATTR_GROUP(20),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) MDIO_BUS_STATS_ADDR_ATTR_GROUP(21),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) MDIO_BUS_STATS_ADDR_ATTR_GROUP(22),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) MDIO_BUS_STATS_ADDR_ATTR_GROUP(23),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) MDIO_BUS_STATS_ADDR_ATTR_GROUP(24),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) MDIO_BUS_STATS_ADDR_ATTR_GROUP(25),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) MDIO_BUS_STATS_ADDR_ATTR_GROUP(26),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) MDIO_BUS_STATS_ADDR_ATTR_GROUP(27),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) MDIO_BUS_STATS_ADDR_ATTR_GROUP(28),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) MDIO_BUS_STATS_ADDR_ATTR_GROUP(29),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) MDIO_BUS_STATS_ADDR_ATTR_GROUP(30),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) MDIO_BUS_STATS_ADDR_ATTR_GROUP(31),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static const struct attribute_group mdio_bus_statistics_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .name = "statistics",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .attrs = mdio_bus_statistics_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static const struct attribute_group *mdio_bus_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) &mdio_bus_statistics_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static struct class mdio_bus_class = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) .name = "mdio_bus",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) .dev_release = mdiobus_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) .dev_groups = mdio_bus_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * mdio_find_bus - Given the name of a mdiobus, find the mii_bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * @mdio_name: The name of a mdiobus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * Returns a reference to the mii_bus, or NULL if none found. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * embedded struct device will have its reference count incremented,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * and this must be put_deviced'ed once the bus is finished with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct mii_bus *mdio_find_bus(const char *mdio_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct device *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) d = class_find_device_by_name(&mdio_bus_class, mdio_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return d ? to_mii_bus(d) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) EXPORT_SYMBOL(mdio_find_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) #if IS_ENABLED(CONFIG_OF_MDIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * @mdio_bus_np: Pointer to the mii_bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * Returns a reference to the mii_bus, or NULL if none found. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * embedded struct device will have its reference count incremented,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * and this must be put once the bus is finished with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * Because the association of a device_node and mii_bus is made via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * of_mdiobus_register(), the mii_bus cannot be found before it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * registered with of_mdiobus_register().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct device *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!mdio_bus_np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) d = class_find_device_by_of_node(&mdio_bus_class, mdio_bus_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return d ? to_mii_bus(d) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) EXPORT_SYMBOL(of_mdio_find_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* Walk the list of subnodes of a mdio bus and look for a node that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * matches the mdio device's address with its 'reg' property. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * found, set the of_node pointer for the mdio device. This allows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * auto-probed phy devices to be supplied with information passed in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * via DT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static void of_mdiobus_link_mdiodev(struct mii_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct device *dev = &mdiodev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct device_node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (dev->of_node || !bus->dev.of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) for_each_available_child_of_node(bus->dev.of_node, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) int addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) addr = of_mdio_parse_addr(dev, child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (addr < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (addr == mdiodev->addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) dev->of_node = child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) dev->fwnode = of_fwnode_handle(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) #else /* !IS_ENABLED(CONFIG_OF_MDIO) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static inline void of_mdiobus_link_mdiodev(struct mii_bus *mdio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * mdiobus_create_device_from_board_info - create a full MDIO device given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * a mdio_board_info structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * @bus: MDIO bus to create the devices on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * @bi: mdio_board_info structure describing the devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * Returns 0 on success or < 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static int mdiobus_create_device(struct mii_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct mdio_board_info *bi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct mdio_device *mdiodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) mdiodev = mdio_device_create(bus, bi->mdio_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (IS_ERR(mdiodev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) strncpy(mdiodev->modalias, bi->modalias,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) sizeof(mdiodev->modalias));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) mdiodev->bus_match = mdio_device_bus_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) mdiodev->dev.platform_data = (void *)bi->platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) ret = mdio_device_register(mdiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) mdio_device_free(mdiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * @bus: target mii_bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * @owner: module containing bus accessor functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * Description: Called by a bus driver to bring up all the PHYs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * on a given bus, and attach them to the bus. Drivers should use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * mdiobus_register() rather than __mdiobus_register() unless they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * need to pass a specific owner module. MDIO devices which are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * PHYs will not be brought up by this function. They are expected to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * to be explicitly listed in DT and instantiated by of_mdiobus_register().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * Returns 0 on success or < 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) int __mdiobus_register(struct mii_bus *bus, struct module *owner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct mdio_device *mdiodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct gpio_desc *gpiod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (NULL == bus || NULL == bus->name ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) NULL == bus->read || NULL == bus->write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) BUG_ON(bus->state != MDIOBUS_ALLOCATED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) bus->state != MDIOBUS_UNREGISTERED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) bus->owner = owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) bus->dev.parent = bus->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) bus->dev.class = &mdio_bus_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) bus->dev.groups = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) dev_set_name(&bus->dev, "%s", bus->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* We need to set state to MDIOBUS_UNREGISTERED to correctly release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * the device in mdiobus_free()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * State will be updated later in this function in case of success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) bus->state = MDIOBUS_UNREGISTERED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) err = device_register(&bus->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) pr_err("mii_bus %s failed to register\n", bus->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mutex_init(&bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) mutex_init(&bus->shared_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /* de-assert bus level PHY GPIO reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) gpiod = devm_gpiod_get_optional(&bus->dev, "reset", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (IS_ERR(gpiod)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) dev_err(&bus->dev, "mii_bus %s couldn't get reset GPIO\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) bus->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) device_del(&bus->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return PTR_ERR(gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) } else if (gpiod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) bus->reset_gpiod = gpiod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) gpiod_set_value_cansleep(gpiod, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) fsleep(bus->reset_delay_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) gpiod_set_value_cansleep(gpiod, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (bus->reset_post_delay_us > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) fsleep(bus->reset_post_delay_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (bus->reset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) err = bus->reset(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) goto error_reset_gpiod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) for (i = 0; i < PHY_MAX_ADDR; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if ((bus->phy_mask & (1 << i)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) struct phy_device *phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) phydev = mdiobus_scan(bus, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (IS_ERR(phydev) && (PTR_ERR(phydev) != -ENODEV)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) err = PTR_ERR(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) mdiobus_setup_mdiodev_from_board_info(bus, mdiobus_create_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) bus->state = MDIOBUS_REGISTERED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) dev_dbg(&bus->dev, "probed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) while (--i >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) mdiodev = bus->mdio_map[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (!mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) mdiodev->device_remove(mdiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) mdiodev->device_free(mdiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) error_reset_gpiod:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* Put PHYs in RESET to save power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (bus->reset_gpiod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) gpiod_set_value_cansleep(bus->reset_gpiod, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) device_del(&bus->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) EXPORT_SYMBOL(__mdiobus_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) void mdiobus_unregister(struct mii_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) struct mdio_device *mdiodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (WARN_ON_ONCE(bus->state != MDIOBUS_REGISTERED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) bus->state = MDIOBUS_UNREGISTERED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) for (i = 0; i < PHY_MAX_ADDR; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) mdiodev = bus->mdio_map[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (!mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (mdiodev->reset_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) gpiod_put(mdiodev->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) mdiodev->device_remove(mdiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) mdiodev->device_free(mdiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* Put PHYs in RESET to save power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (bus->reset_gpiod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) gpiod_set_value_cansleep(bus->reset_gpiod, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) device_del(&bus->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) EXPORT_SYMBOL(mdiobus_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * mdiobus_free - free a struct mii_bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * @bus: mii_bus to free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * This function releases the reference to the underlying device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * object in the mii_bus. If this is the last reference, the mii_bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * will be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) void mdiobus_free(struct mii_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /* For compatibility with error handling in drivers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (bus->state == MDIOBUS_ALLOCATED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) kfree(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) BUG_ON(bus->state != MDIOBUS_UNREGISTERED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) bus->state = MDIOBUS_RELEASED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) put_device(&bus->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) EXPORT_SYMBOL(mdiobus_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * mdiobus_scan - scan a bus for MDIO devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * @bus: mii_bus to scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * @addr: address on bus to scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * This function scans the MDIO bus, looking for devices which can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * identified using a vendor/product ID in registers 2 and 3. Not all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * MDIO devices have such registers, but PHY devices typically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * do. Hence this function assumes anything found is a PHY, or can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * treated as a PHY. Other MDIO devices, such as switches, will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * probably not be found during the scan.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct phy_device *phydev = ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) switch (bus->probe_capabilities) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) case MDIOBUS_NO_CAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) case MDIOBUS_C22:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) phydev = get_phy_device(bus, addr, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) case MDIOBUS_C45:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) phydev = get_phy_device(bus, addr, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) case MDIOBUS_C22_C45:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) phydev = get_phy_device(bus, addr, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (IS_ERR(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) phydev = get_phy_device(bus, addr, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (IS_ERR(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * For DT, see if the auto-probed phy has a correspoding child
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * in the bus node, and set the of_node pointer in this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) of_mdiobus_link_mdiodev(bus, &phydev->mdio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) err = phy_device_register(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) phy_device_free(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) EXPORT_SYMBOL(mdiobus_scan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static void mdiobus_stats_acct(struct mdio_bus_stats *stats, bool op, int ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) u64_stats_update_begin(&stats->syncp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) u64_stats_inc(&stats->transfers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) u64_stats_inc(&stats->errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) u64_stats_inc(&stats->reads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) u64_stats_inc(&stats->writes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) u64_stats_update_end(&stats->syncp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * __mdiobus_read - Unlocked version of the mdiobus_read function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * @bus: the mii_bus struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * @addr: the phy address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * @regnum: register number to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * Read a MDIO bus register. Caller must hold the mdio bus lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * NOTE: MUST NOT be called from interrupt context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) retval = bus->read(bus, addr, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) trace_mdio_access(bus, 1, addr, regnum, retval, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) mdiobus_stats_acct(&bus->stats[addr], true, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) EXPORT_SYMBOL(__mdiobus_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * __mdiobus_write - Unlocked version of the mdiobus_write function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) * @bus: the mii_bus struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * @addr: the phy address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * @regnum: register number to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * @val: value to write to @regnum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * Write a MDIO bus register. Caller must hold the mdio bus lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * NOTE: MUST NOT be called from interrupt context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) err = bus->write(bus, addr, regnum, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) trace_mdio_access(bus, 0, addr, regnum, val, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) mdiobus_stats_acct(&bus->stats[addr], false, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) EXPORT_SYMBOL(__mdiobus_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * __mdiobus_modify_changed - Unlocked version of the mdiobus_modify function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) * @bus: the mii_bus struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * @addr: the phy address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * @regnum: register number to modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * @mask: bit mask of bits to clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * @set: bit mask of bits to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * Read, modify, and if any change, write the register value back to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * device. Any error returns a negative number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * NOTE: MUST NOT be called from interrupt context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) u16 mask, u16 set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) int new, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) ret = __mdiobus_read(bus, addr, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) new = (ret & ~mask) | set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (new == ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) ret = __mdiobus_write(bus, addr, regnum, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return ret < 0 ? ret : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) EXPORT_SYMBOL_GPL(__mdiobus_modify_changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * mdiobus_read_nested - Nested version of the mdiobus_read function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * @bus: the mii_bus struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * @addr: the phy address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * @regnum: register number to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * In case of nested MDIO bus access avoid lockdep false positives by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * using mutex_lock_nested().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * NOTE: MUST NOT be called from interrupt context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * because the bus read/write functions may wait for an interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * to conclude the operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) retval = __mdiobus_read(bus, addr, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) mutex_unlock(&bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) EXPORT_SYMBOL(mdiobus_read_nested);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * mdiobus_read - Convenience function for reading a given MII mgmt register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * @bus: the mii_bus struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * @addr: the phy address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * @regnum: register number to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * NOTE: MUST NOT be called from interrupt context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * because the bus read/write functions may wait for an interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * to conclude the operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) mutex_lock(&bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) retval = __mdiobus_read(bus, addr, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) mutex_unlock(&bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) EXPORT_SYMBOL(mdiobus_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * mdiobus_write_nested - Nested version of the mdiobus_write function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * @bus: the mii_bus struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * @addr: the phy address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * @regnum: register number to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * @val: value to write to @regnum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) * In case of nested MDIO bus access avoid lockdep false positives by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * using mutex_lock_nested().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * NOTE: MUST NOT be called from interrupt context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * because the bus read/write functions may wait for an interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * to conclude the operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) err = __mdiobus_write(bus, addr, regnum, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) mutex_unlock(&bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) EXPORT_SYMBOL(mdiobus_write_nested);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) * mdiobus_write - Convenience function for writing a given MII mgmt register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) * @bus: the mii_bus struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * @addr: the phy address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * @regnum: register number to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * @val: value to write to @regnum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * NOTE: MUST NOT be called from interrupt context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * because the bus read/write functions may wait for an interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * to conclude the operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) mutex_lock(&bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) err = __mdiobus_write(bus, addr, regnum, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) mutex_unlock(&bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) EXPORT_SYMBOL(mdiobus_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * mdiobus_modify - Convenience function for modifying a given mdio device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) * register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * @bus: the mii_bus struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * @addr: the phy address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * @regnum: register number to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * @mask: bit mask of bits to clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) * @set: bit mask of bits to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) mutex_lock(&bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) err = __mdiobus_modify_changed(bus, addr, regnum, mask, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) mutex_unlock(&bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return err < 0 ? err : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) EXPORT_SYMBOL_GPL(mdiobus_modify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) * mdio_bus_match - determine if given MDIO driver supports the given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) * MDIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * @dev: target MDIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * @drv: given MDIO driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) * Description: Given a MDIO device, and a MDIO driver, return 1 if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * the driver supports the device. Otherwise, return 0. This may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) * require calling the devices own match function, since different classes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) * of MDIO devices have different match criteria.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) static int mdio_bus_match(struct device *dev, struct device_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) struct mdio_device *mdio = to_mdio_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (of_driver_match_device(dev, drv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (mdio->bus_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return mdio->bus_match(dev, drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) static int mdio_uevent(struct device *dev, struct kobj_uevent_env *env)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) /* Some devices have extra OF data and an OF-style MODALIAS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) rc = of_device_uevent_modalias(dev, env);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (rc != -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) static struct attribute *mdio_bus_device_statistics_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) &dev_attr_mdio_bus_device_transfers.attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) &dev_attr_mdio_bus_device_errors.attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) &dev_attr_mdio_bus_device_writes.attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) &dev_attr_mdio_bus_device_reads.attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) static const struct attribute_group mdio_bus_device_statistics_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) .name = "statistics",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .attrs = mdio_bus_device_statistics_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) static const struct attribute_group *mdio_bus_dev_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) &mdio_bus_device_statistics_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct bus_type mdio_bus_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) .name = "mdio_bus",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) .dev_groups = mdio_bus_dev_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) .match = mdio_bus_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .uevent = mdio_uevent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) EXPORT_SYMBOL(mdio_bus_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) int __init mdio_bus_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ret = class_register(&mdio_bus_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) ret = bus_register(&mdio_bus_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) class_unregister(&mdio_bus_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) EXPORT_SYMBOL_GPL(mdio_bus_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) #if IS_ENABLED(CONFIG_PHYLIB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) void mdio_bus_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) class_unregister(&mdio_bus_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) bus_unregister(&mdio_bus_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) EXPORT_SYMBOL_GPL(mdio_bus_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) module_init(mdio_bus_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /* no module_exit, intentional */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) MODULE_DESCRIPTION("MDIO bus/device layer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) #endif