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