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/idr.h> 21 #include <linux/netdevice.h> 22 #include <linux/linkmode.h> 23 24 #include "swphy.h" 25 26 struct fixed_phy { 27 int addr; 28 struct phy_device *phydev; 29 struct fixed_phy_status status; 30 int (*link_update)(struct net_device *, struct fixed_phy_status *); 31 struct list_head node; 32 }; 33 34 static struct mii_bus *fmb_mii_bus; 35 static LIST_HEAD(fmb_phys); 36 37 static struct fixed_phy *fixed_phy_find(int addr) 38 { 39 struct fixed_phy *fp; 40 41 list_for_each_entry(fp, &fmb_phys, node) { 42 if (fp->addr == addr) 43 return fp; 44 } 45 46 return NULL; 47 } 48 49 int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier) 50 { 51 struct phy_device *phydev = dev->phydev; 52 struct fixed_phy *fp; 53 54 if (!phydev || !phydev->mdio.bus) 55 return -EINVAL; 56 57 fp = fixed_phy_find(phydev->mdio.addr); 58 if (!fp) 59 return -EINVAL; 60 61 fp->status.link = new_carrier; 62 63 return 0; 64 } 65 EXPORT_SYMBOL_GPL(fixed_phy_change_carrier); 66 67 static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) 68 { 69 struct fixed_phy *fp; 70 71 fp = fixed_phy_find(phy_addr); 72 if (!fp) 73 return 0xffff; 74 75 if (fp->link_update) 76 fp->link_update(fp->phydev->attached_dev, &fp->status); 77 78 return swphy_read_reg(reg_num, &fp->status); 79 } 80 81 static int fixed_mdio_write(struct mii_bus *bus, int phy_addr, int reg_num, 82 u16 val) 83 { 84 return 0; 85 } 86 87 /* 88 * If something weird is required to be done with link/speed, 89 * network driver is able to assign a function to implement this. 90 * May be useful for PHY's that need to be software-driven. 91 */ 92 int fixed_phy_set_link_update(struct phy_device *phydev, 93 int (*link_update)(struct net_device *, 94 struct fixed_phy_status *)) 95 { 96 struct fixed_phy *fp; 97 98 if (!phydev || !phydev->mdio.bus) 99 return -EINVAL; 100 101 fp = fixed_phy_find(phydev->mdio.addr); 102 if (!fp) 103 return -ENOENT; 104 105 fp->link_update = link_update; 106 fp->phydev = phydev; 107 108 return 0; 109 } 110 EXPORT_SYMBOL_GPL(fixed_phy_set_link_update); 111 112 static int __fixed_phy_add(int phy_addr, 113 const struct fixed_phy_status *status) 114 { 115 struct fixed_phy *fp; 116 int ret; 117 118 ret = swphy_validate_state(status); 119 if (ret < 0) 120 return ret; 121 122 fp = kzalloc(sizeof(*fp), GFP_KERNEL); 123 if (!fp) 124 return -ENOMEM; 125 126 fp->addr = phy_addr; 127 fp->status = *status; 128 129 list_add_tail(&fp->node, &fmb_phys); 130 131 return 0; 132 } 133 134 static DEFINE_IDA(phy_fixed_ida); 135 136 static void fixed_phy_del(int phy_addr) 137 { 138 struct fixed_phy *fp; 139 140 fp = fixed_phy_find(phy_addr); 141 if (!fp) 142 return; 143 144 list_del(&fp->node); 145 kfree(fp); 146 ida_free(&phy_fixed_ida, phy_addr); 147 } 148 149 struct phy_device *fixed_phy_register(const struct fixed_phy_status *status, 150 struct device_node *np) 151 { 152 struct phy_device *phy; 153 int phy_addr; 154 int ret; 155 156 if (!fmb_mii_bus || fmb_mii_bus->state != MDIOBUS_REGISTERED) 157 return ERR_PTR(-EPROBE_DEFER); 158 159 /* Get the next available PHY address, up to PHY_MAX_ADDR */ 160 phy_addr = ida_alloc_max(&phy_fixed_ida, PHY_MAX_ADDR - 1, GFP_KERNEL); 161 if (phy_addr < 0) 162 return ERR_PTR(phy_addr); 163 164 ret = __fixed_phy_add(phy_addr, status); 165 if (ret < 0) { 166 ida_free(&phy_fixed_ida, phy_addr); 167 return ERR_PTR(ret); 168 } 169 170 phy = get_phy_device(fmb_mii_bus, phy_addr, false); 171 if (IS_ERR(phy)) { 172 fixed_phy_del(phy_addr); 173 return ERR_PTR(-EINVAL); 174 } 175 176 /* propagate the fixed link values to struct phy_device */ 177 phy->link = status->link; 178 if (status->link) { 179 phy->speed = status->speed; 180 phy->duplex = status->duplex; 181 phy->pause = status->pause; 182 phy->asym_pause = status->asym_pause; 183 } 184 185 of_node_get(np); 186 phy->mdio.dev.of_node = np; 187 phy->is_pseudo_fixed_link = true; 188 189 switch (status->speed) { 190 case SPEED_1000: 191 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, 192 phy->supported); 193 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 194 phy->supported); 195 fallthrough; 196 case SPEED_100: 197 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, 198 phy->supported); 199 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, 200 phy->supported); 201 fallthrough; 202 case SPEED_10: 203 default: 204 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, 205 phy->supported); 206 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, 207 phy->supported); 208 } 209 210 phy_advertise_supported(phy); 211 212 ret = phy_device_register(phy); 213 if (ret) { 214 phy_device_free(phy); 215 of_node_put(np); 216 fixed_phy_del(phy_addr); 217 return ERR_PTR(ret); 218 } 219 220 return phy; 221 } 222 EXPORT_SYMBOL_GPL(fixed_phy_register); 223 224 struct phy_device *fixed_phy_register_100fd(void) 225 { 226 static const struct fixed_phy_status status = { 227 .link = true, 228 .speed = SPEED_100, 229 .duplex = DUPLEX_FULL, 230 }; 231 232 return fixed_phy_register(&status, NULL); 233 } 234 EXPORT_SYMBOL_GPL(fixed_phy_register_100fd); 235 236 void fixed_phy_unregister(struct phy_device *phy) 237 { 238 phy_device_remove(phy); 239 of_node_put(phy->mdio.dev.of_node); 240 fixed_phy_del(phy->mdio.addr); 241 phy_device_free(phy); 242 } 243 EXPORT_SYMBOL_GPL(fixed_phy_unregister); 244 245 static int __init fixed_mdio_bus_init(void) 246 { 247 int ret; 248 249 fmb_mii_bus = mdiobus_alloc(); 250 if (!fmb_mii_bus) 251 return -ENOMEM; 252 253 snprintf(fmb_mii_bus->id, MII_BUS_ID_SIZE, "fixed-0"); 254 fmb_mii_bus->name = "Fixed MDIO Bus"; 255 fmb_mii_bus->read = &fixed_mdio_read; 256 fmb_mii_bus->write = &fixed_mdio_write; 257 fmb_mii_bus->phy_mask = ~0; 258 259 ret = mdiobus_register(fmb_mii_bus); 260 if (ret) 261 goto err_mdiobus_alloc; 262 263 return 0; 264 265 err_mdiobus_alloc: 266 mdiobus_free(fmb_mii_bus); 267 return ret; 268 } 269 module_init(fixed_mdio_bus_init); 270 271 static void __exit fixed_mdio_bus_exit(void) 272 { 273 struct fixed_phy *fp, *tmp; 274 275 mdiobus_unregister(fmb_mii_bus); 276 mdiobus_free(fmb_mii_bus); 277 278 list_for_each_entry_safe(fp, tmp, &fmb_phys, node) { 279 list_del(&fp->node); 280 kfree(fp); 281 } 282 ida_destroy(&phy_fixed_ida); 283 } 284 module_exit(fixed_mdio_bus_exit); 285 286 MODULE_DESCRIPTION("Fixed MDIO bus (MDIO bus emulation with fixed PHYs)"); 287 MODULE_AUTHOR("Vitaly Bordug"); 288 MODULE_LICENSE("GPL"); 289