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 29 #include "swphy.h" 30 31 struct fixed_mdio_bus { 32 struct mii_bus *mii_bus; 33 struct list_head phys; 34 }; 35 36 struct fixed_phy { 37 int addr; 38 struct phy_device *phydev; 39 seqcount_t seqcount; 40 struct fixed_phy_status status; 41 int (*link_update)(struct net_device *, struct fixed_phy_status *); 42 struct list_head node; 43 int link_gpio; 44 }; 45 46 static struct platform_device *pdev; 47 static struct fixed_mdio_bus platform_fmb = { 48 .phys = LIST_HEAD_INIT(platform_fmb.phys), 49 }; 50 51 static void fixed_phy_update(struct fixed_phy *fp) 52 { 53 if (gpio_is_valid(fp->link_gpio)) 54 fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); 55 } 56 57 static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) 58 { 59 struct fixed_mdio_bus *fmb = bus->priv; 60 struct fixed_phy *fp; 61 62 list_for_each_entry(fp, &fmb->phys, node) { 63 if (fp->addr == phy_addr) { 64 struct fixed_phy_status state; 65 int s; 66 67 do { 68 s = read_seqcount_begin(&fp->seqcount); 69 /* Issue callback if user registered it. */ 70 if (fp->link_update) { 71 fp->link_update(fp->phydev->attached_dev, 72 &fp->status); 73 fixed_phy_update(fp); 74 } 75 state = fp->status; 76 } while (read_seqcount_retry(&fp->seqcount, s)); 77 78 return swphy_read_reg(reg_num, &state); 79 } 80 } 81 82 return 0xFFFF; 83 } 84 85 static int fixed_mdio_write(struct mii_bus *bus, int phy_addr, int reg_num, 86 u16 val) 87 { 88 return 0; 89 } 90 91 /* 92 * If something weird is required to be done with link/speed, 93 * network driver is able to assign a function to implement this. 94 * May be useful for PHY's that need to be software-driven. 95 */ 96 int fixed_phy_set_link_update(struct phy_device *phydev, 97 int (*link_update)(struct net_device *, 98 struct fixed_phy_status *)) 99 { 100 struct fixed_mdio_bus *fmb = &platform_fmb; 101 struct fixed_phy *fp; 102 103 if (!phydev || !phydev->mdio.bus) 104 return -EINVAL; 105 106 list_for_each_entry(fp, &fmb->phys, node) { 107 if (fp->addr == phydev->mdio.addr) { 108 fp->link_update = link_update; 109 fp->phydev = phydev; 110 return 0; 111 } 112 } 113 114 return -ENOENT; 115 } 116 EXPORT_SYMBOL_GPL(fixed_phy_set_link_update); 117 118 int fixed_phy_update_state(struct phy_device *phydev, 119 const struct fixed_phy_status *status, 120 const struct fixed_phy_status *changed) 121 { 122 struct fixed_mdio_bus *fmb = &platform_fmb; 123 struct fixed_phy *fp; 124 125 if (!phydev || phydev->mdio.bus != fmb->mii_bus) 126 return -EINVAL; 127 128 list_for_each_entry(fp, &fmb->phys, node) { 129 if (fp->addr == phydev->mdio.addr) { 130 write_seqcount_begin(&fp->seqcount); 131 #define _UPD(x) if (changed->x) \ 132 fp->status.x = status->x 133 _UPD(link); 134 _UPD(speed); 135 _UPD(duplex); 136 _UPD(pause); 137 _UPD(asym_pause); 138 #undef _UPD 139 fixed_phy_update(fp); 140 write_seqcount_end(&fp->seqcount); 141 return 0; 142 } 143 } 144 145 return -ENOENT; 146 } 147 EXPORT_SYMBOL(fixed_phy_update_state); 148 149 int fixed_phy_add(unsigned int irq, int phy_addr, 150 struct fixed_phy_status *status, 151 int link_gpio) 152 { 153 int ret; 154 struct fixed_mdio_bus *fmb = &platform_fmb; 155 struct fixed_phy *fp; 156 157 ret = swphy_validate_state(status); 158 if (ret < 0) 159 return ret; 160 161 fp = kzalloc(sizeof(*fp), GFP_KERNEL); 162 if (!fp) 163 return -ENOMEM; 164 165 seqcount_init(&fp->seqcount); 166 167 if (irq != PHY_POLL) 168 fmb->mii_bus->irq[phy_addr] = irq; 169 170 fp->addr = phy_addr; 171 fp->status = *status; 172 fp->link_gpio = link_gpio; 173 174 if (gpio_is_valid(fp->link_gpio)) { 175 ret = gpio_request_one(fp->link_gpio, GPIOF_DIR_IN, 176 "fixed-link-gpio-link"); 177 if (ret) 178 goto err_regs; 179 } 180 181 fixed_phy_update(fp); 182 183 list_add_tail(&fp->node, &fmb->phys); 184 185 return 0; 186 187 err_regs: 188 kfree(fp); 189 return ret; 190 } 191 EXPORT_SYMBOL_GPL(fixed_phy_add); 192 193 static DEFINE_IDA(phy_fixed_ida); 194 195 static void fixed_phy_del(int phy_addr) 196 { 197 struct fixed_mdio_bus *fmb = &platform_fmb; 198 struct fixed_phy *fp, *tmp; 199 200 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { 201 if (fp->addr == phy_addr) { 202 list_del(&fp->node); 203 if (gpio_is_valid(fp->link_gpio)) 204 gpio_free(fp->link_gpio); 205 kfree(fp); 206 ida_simple_remove(&phy_fixed_ida, phy_addr); 207 return; 208 } 209 } 210 } 211 212 struct phy_device *fixed_phy_register(unsigned int irq, 213 struct fixed_phy_status *status, 214 int link_gpio, 215 struct device_node *np) 216 { 217 struct fixed_mdio_bus *fmb = &platform_fmb; 218 struct phy_device *phy; 219 int phy_addr; 220 int ret; 221 222 if (!fmb->mii_bus || fmb->mii_bus->state != MDIOBUS_REGISTERED) 223 return ERR_PTR(-EPROBE_DEFER); 224 225 /* Get the next available PHY address, up to PHY_MAX_ADDR */ 226 phy_addr = ida_simple_get(&phy_fixed_ida, 0, PHY_MAX_ADDR, GFP_KERNEL); 227 if (phy_addr < 0) 228 return ERR_PTR(phy_addr); 229 230 ret = fixed_phy_add(irq, phy_addr, status, link_gpio); 231 if (ret < 0) { 232 ida_simple_remove(&phy_fixed_ida, phy_addr); 233 return ERR_PTR(ret); 234 } 235 236 phy = get_phy_device(fmb->mii_bus, phy_addr, false); 237 if (IS_ERR(phy)) { 238 fixed_phy_del(phy_addr); 239 return ERR_PTR(-EINVAL); 240 } 241 242 /* propagate the fixed link values to struct phy_device */ 243 phy->link = status->link; 244 if (status->link) { 245 phy->speed = status->speed; 246 phy->duplex = status->duplex; 247 phy->pause = status->pause; 248 phy->asym_pause = status->asym_pause; 249 } 250 251 of_node_get(np); 252 phy->mdio.dev.of_node = np; 253 phy->is_pseudo_fixed_link = true; 254 255 switch (status->speed) { 256 case SPEED_1000: 257 phy->supported = PHY_1000BT_FEATURES; 258 break; 259 case SPEED_100: 260 phy->supported = PHY_100BT_FEATURES; 261 break; 262 case SPEED_10: 263 default: 264 phy->supported = PHY_10BT_FEATURES; 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 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 ret = PTR_ERR(pdev); 295 goto err_pdev; 296 } 297 298 fmb->mii_bus = mdiobus_alloc(); 299 if (fmb->mii_bus == NULL) { 300 ret = -ENOMEM; 301 goto err_mdiobus_reg; 302 } 303 304 snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "fixed-0"); 305 fmb->mii_bus->name = "Fixed MDIO Bus"; 306 fmb->mii_bus->priv = fmb; 307 fmb->mii_bus->parent = &pdev->dev; 308 fmb->mii_bus->read = &fixed_mdio_read; 309 fmb->mii_bus->write = &fixed_mdio_write; 310 311 ret = mdiobus_register(fmb->mii_bus); 312 if (ret) 313 goto err_mdiobus_alloc; 314 315 return 0; 316 317 err_mdiobus_alloc: 318 mdiobus_free(fmb->mii_bus); 319 err_mdiobus_reg: 320 platform_device_unregister(pdev); 321 err_pdev: 322 return ret; 323 } 324 module_init(fixed_mdio_bus_init); 325 326 static void __exit fixed_mdio_bus_exit(void) 327 { 328 struct fixed_mdio_bus *fmb = &platform_fmb; 329 struct fixed_phy *fp, *tmp; 330 331 mdiobus_unregister(fmb->mii_bus); 332 mdiobus_free(fmb->mii_bus); 333 platform_device_unregister(pdev); 334 335 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { 336 list_del(&fp->node); 337 kfree(fp); 338 } 339 ida_destroy(&phy_fixed_ida); 340 } 341 module_exit(fixed_mdio_bus_exit); 342 343 MODULE_DESCRIPTION("Fixed MDIO bus (MDIO bus emulation with fixed PHYs)"); 344 MODULE_AUTHOR("Vitaly Bordug"); 345 MODULE_LICENSE("GPL"); 346