1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Fixed MDIO bus (MDIO bus emulation with fixed PHYs) 4 * 5 * Author: Vitaly Bordug <vbordug@ru.mvista.com> 6 * Anton Vorontsov <avorontsov@ru.mvista.com> 7 * 8 * Copyright (c) 2006-2007 MontaVista Software, Inc. 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/list.h> 14 #include <linux/mii.h> 15 #include <linux/phy.h> 16 #include <linux/phy_fixed.h> 17 #include <linux/err.h> 18 #include <linux/slab.h> 19 #include <linux/of.h> 20 #include <linux/gpio/consumer.h> 21 #include <linux/idr.h> 22 #include <linux/netdevice.h> 23 #include <linux/linkmode.h> 24 25 #include "swphy.h" 26 27 struct fixed_mdio_bus { 28 struct mii_bus *mii_bus; 29 struct list_head phys; 30 }; 31 32 struct fixed_phy { 33 int addr; 34 struct phy_device *phydev; 35 struct fixed_phy_status status; 36 bool no_carrier; 37 int (*link_update)(struct net_device *, struct fixed_phy_status *); 38 struct list_head node; 39 struct gpio_desc *link_gpiod; 40 }; 41 42 static struct fixed_mdio_bus platform_fmb = { 43 .phys = LIST_HEAD_INIT(platform_fmb.phys), 44 }; 45 46 int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier) 47 { 48 struct fixed_mdio_bus *fmb = &platform_fmb; 49 struct phy_device *phydev = dev->phydev; 50 struct fixed_phy *fp; 51 52 if (!phydev || !phydev->mdio.bus) 53 return -EINVAL; 54 55 list_for_each_entry(fp, &fmb->phys, node) { 56 if (fp->addr == phydev->mdio.addr) { 57 fp->no_carrier = !new_carrier; 58 return 0; 59 } 60 } 61 return -EINVAL; 62 } 63 EXPORT_SYMBOL_GPL(fixed_phy_change_carrier); 64 65 static void fixed_phy_update(struct fixed_phy *fp) 66 { 67 if (!fp->no_carrier && fp->link_gpiod) 68 fp->status.link = !!gpiod_get_value_cansleep(fp->link_gpiod); 69 } 70 71 static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) 72 { 73 struct fixed_mdio_bus *fmb = bus->priv; 74 struct fixed_phy *fp; 75 76 list_for_each_entry(fp, &fmb->phys, node) { 77 if (fp->addr == phy_addr) { 78 fp->status.link = !fp->no_carrier; 79 80 /* Issue callback if user registered it. */ 81 if (fp->link_update) 82 fp->link_update(fp->phydev->attached_dev, 83 &fp->status); 84 85 /* Check the GPIO for change in status */ 86 fixed_phy_update(fp); 87 88 return swphy_read_reg(reg_num, &fp->status); 89 } 90 } 91 92 return 0xFFFF; 93 } 94 95 static int fixed_mdio_write(struct mii_bus *bus, int phy_addr, int reg_num, 96 u16 val) 97 { 98 return 0; 99 } 100 101 /* 102 * If something weird is required to be done with link/speed, 103 * network driver is able to assign a function to implement this. 104 * May be useful for PHY's that need to be software-driven. 105 */ 106 int fixed_phy_set_link_update(struct phy_device *phydev, 107 int (*link_update)(struct net_device *, 108 struct fixed_phy_status *)) 109 { 110 struct fixed_mdio_bus *fmb = &platform_fmb; 111 struct fixed_phy *fp; 112 113 if (!phydev || !phydev->mdio.bus) 114 return -EINVAL; 115 116 list_for_each_entry(fp, &fmb->phys, node) { 117 if (fp->addr == phydev->mdio.addr) { 118 fp->link_update = link_update; 119 fp->phydev = phydev; 120 return 0; 121 } 122 } 123 124 return -ENOENT; 125 } 126 EXPORT_SYMBOL_GPL(fixed_phy_set_link_update); 127 128 static int fixed_phy_add_gpiod(unsigned int irq, int phy_addr, 129 const struct fixed_phy_status *status, 130 struct gpio_desc *gpiod) 131 { 132 int ret; 133 struct fixed_mdio_bus *fmb = &platform_fmb; 134 struct fixed_phy *fp; 135 136 ret = swphy_validate_state(status); 137 if (ret < 0) 138 return ret; 139 140 fp = kzalloc(sizeof(*fp), GFP_KERNEL); 141 if (!fp) 142 return -ENOMEM; 143 144 if (irq != PHY_POLL) 145 fmb->mii_bus->irq[phy_addr] = irq; 146 147 fp->addr = phy_addr; 148 fp->status = *status; 149 fp->link_gpiod = gpiod; 150 151 fixed_phy_update(fp); 152 153 list_add_tail(&fp->node, &fmb->phys); 154 155 return 0; 156 } 157 158 void fixed_phy_add(const struct fixed_phy_status *status) 159 { 160 fixed_phy_add_gpiod(PHY_POLL, 0, status, NULL); 161 } 162 EXPORT_SYMBOL_GPL(fixed_phy_add); 163 164 static DEFINE_IDA(phy_fixed_ida); 165 166 static void fixed_phy_del(int phy_addr) 167 { 168 struct fixed_mdio_bus *fmb = &platform_fmb; 169 struct fixed_phy *fp, *tmp; 170 171 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { 172 if (fp->addr == phy_addr) { 173 list_del(&fp->node); 174 if (fp->link_gpiod) 175 gpiod_put(fp->link_gpiod); 176 kfree(fp); 177 ida_free(&phy_fixed_ida, phy_addr); 178 return; 179 } 180 } 181 } 182 183 #ifdef CONFIG_OF_GPIO 184 static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np) 185 { 186 struct device_node *fixed_link_node; 187 struct gpio_desc *gpiod; 188 189 if (!np) 190 return NULL; 191 192 fixed_link_node = of_get_child_by_name(np, "fixed-link"); 193 if (!fixed_link_node) 194 return NULL; 195 196 /* 197 * As the fixed link is just a device tree node without any 198 * Linux device associated with it, we simply have obtain 199 * the GPIO descriptor from the device tree like this. 200 */ 201 gpiod = fwnode_gpiod_get_index(of_fwnode_handle(fixed_link_node), 202 "link", 0, GPIOD_IN, "mdio"); 203 if (IS_ERR(gpiod) && PTR_ERR(gpiod) != -EPROBE_DEFER) { 204 if (PTR_ERR(gpiod) != -ENOENT) 205 pr_err("error getting GPIO for fixed link %pOF, proceed without\n", 206 fixed_link_node); 207 gpiod = NULL; 208 } 209 of_node_put(fixed_link_node); 210 211 return gpiod; 212 } 213 #else 214 static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np) 215 { 216 return NULL; 217 } 218 #endif 219 220 struct phy_device *fixed_phy_register(const struct fixed_phy_status *status, 221 struct device_node *np) 222 { 223 struct fixed_mdio_bus *fmb = &platform_fmb; 224 struct gpio_desc *gpiod; 225 struct phy_device *phy; 226 int phy_addr; 227 int ret; 228 229 if (!fmb->mii_bus || fmb->mii_bus->state != MDIOBUS_REGISTERED) 230 return ERR_PTR(-EPROBE_DEFER); 231 232 /* Check if we have a GPIO associated with this fixed phy */ 233 gpiod = fixed_phy_get_gpiod(np); 234 if (IS_ERR(gpiod)) 235 return ERR_CAST(gpiod); 236 237 /* Get the next available PHY address, up to PHY_MAX_ADDR */ 238 phy_addr = ida_alloc_max(&phy_fixed_ida, PHY_MAX_ADDR - 1, GFP_KERNEL); 239 if (phy_addr < 0) 240 return ERR_PTR(phy_addr); 241 242 ret = fixed_phy_add_gpiod(PHY_POLL, phy_addr, status, gpiod); 243 if (ret < 0) { 244 ida_free(&phy_fixed_ida, phy_addr); 245 return ERR_PTR(ret); 246 } 247 248 phy = get_phy_device(fmb->mii_bus, phy_addr, false); 249 if (IS_ERR(phy)) { 250 fixed_phy_del(phy_addr); 251 return ERR_PTR(-EINVAL); 252 } 253 254 /* propagate the fixed link values to struct phy_device */ 255 phy->link = status->link; 256 if (status->link) { 257 phy->speed = status->speed; 258 phy->duplex = status->duplex; 259 phy->pause = status->pause; 260 phy->asym_pause = status->asym_pause; 261 } 262 263 of_node_get(np); 264 phy->mdio.dev.of_node = np; 265 phy->is_pseudo_fixed_link = true; 266 267 switch (status->speed) { 268 case SPEED_1000: 269 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, 270 phy->supported); 271 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 272 phy->supported); 273 fallthrough; 274 case SPEED_100: 275 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, 276 phy->supported); 277 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, 278 phy->supported); 279 fallthrough; 280 case SPEED_10: 281 default: 282 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, 283 phy->supported); 284 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, 285 phy->supported); 286 } 287 288 phy_advertise_supported(phy); 289 290 ret = phy_device_register(phy); 291 if (ret) { 292 phy_device_free(phy); 293 of_node_put(np); 294 fixed_phy_del(phy_addr); 295 return ERR_PTR(ret); 296 } 297 298 return phy; 299 } 300 EXPORT_SYMBOL_GPL(fixed_phy_register); 301 302 void fixed_phy_unregister(struct phy_device *phy) 303 { 304 phy_device_remove(phy); 305 of_node_put(phy->mdio.dev.of_node); 306 fixed_phy_del(phy->mdio.addr); 307 phy_device_free(phy); 308 } 309 EXPORT_SYMBOL_GPL(fixed_phy_unregister); 310 311 static int __init fixed_mdio_bus_init(void) 312 { 313 struct fixed_mdio_bus *fmb = &platform_fmb; 314 int ret; 315 316 fmb->mii_bus = mdiobus_alloc(); 317 if (!fmb->mii_bus) 318 return -ENOMEM; 319 320 snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "fixed-0"); 321 fmb->mii_bus->name = "Fixed MDIO Bus"; 322 fmb->mii_bus->priv = fmb; 323 fmb->mii_bus->read = &fixed_mdio_read; 324 fmb->mii_bus->write = &fixed_mdio_write; 325 fmb->mii_bus->phy_mask = ~0; 326 327 ret = mdiobus_register(fmb->mii_bus); 328 if (ret) 329 goto err_mdiobus_alloc; 330 331 return 0; 332 333 err_mdiobus_alloc: 334 mdiobus_free(fmb->mii_bus); 335 return ret; 336 } 337 module_init(fixed_mdio_bus_init); 338 339 static void __exit fixed_mdio_bus_exit(void) 340 { 341 struct fixed_mdio_bus *fmb = &platform_fmb; 342 struct fixed_phy *fp, *tmp; 343 344 mdiobus_unregister(fmb->mii_bus); 345 mdiobus_free(fmb->mii_bus); 346 347 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { 348 list_del(&fp->node); 349 kfree(fp); 350 } 351 ida_destroy(&phy_fixed_ida); 352 } 353 module_exit(fixed_mdio_bus_exit); 354 355 MODULE_DESCRIPTION("Fixed MDIO bus (MDIO bus emulation with fixed PHYs)"); 356 MODULE_AUTHOR("Vitaly Bordug"); 357 MODULE_LICENSE("GPL"); 358