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/idr.h> 27 28 #define MII_REGS_NUM 29 29 30 struct fixed_mdio_bus { 31 struct mii_bus *mii_bus; 32 struct list_head phys; 33 }; 34 35 struct fixed_phy { 36 int addr; 37 u16 regs[MII_REGS_NUM]; 38 struct phy_device *phydev; 39 struct fixed_phy_status status; 40 int (*link_update)(struct net_device *, struct fixed_phy_status *); 41 struct list_head node; 42 int link_gpio; 43 }; 44 45 static struct platform_device *pdev; 46 static struct fixed_mdio_bus platform_fmb = { 47 .phys = LIST_HEAD_INIT(platform_fmb.phys), 48 }; 49 50 static int fixed_phy_update_regs(struct fixed_phy *fp) 51 { 52 u16 bmsr = BMSR_ANEGCAPABLE; 53 u16 bmcr = 0; 54 u16 lpagb = 0; 55 u16 lpa = 0; 56 57 if (gpio_is_valid(fp->link_gpio)) 58 fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); 59 60 if (fp->status.duplex) { 61 switch (fp->status.speed) { 62 case 1000: 63 bmsr |= BMSR_ESTATEN; 64 break; 65 case 100: 66 bmsr |= BMSR_100FULL; 67 break; 68 case 10: 69 bmsr |= BMSR_10FULL; 70 break; 71 default: 72 break; 73 } 74 } else { 75 switch (fp->status.speed) { 76 case 1000: 77 bmsr |= BMSR_ESTATEN; 78 break; 79 case 100: 80 bmsr |= BMSR_100HALF; 81 break; 82 case 10: 83 bmsr |= BMSR_10HALF; 84 break; 85 default: 86 break; 87 } 88 } 89 90 if (fp->status.link) { 91 bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; 92 93 if (fp->status.duplex) { 94 bmcr |= BMCR_FULLDPLX; 95 96 switch (fp->status.speed) { 97 case 1000: 98 bmcr |= BMCR_SPEED1000; 99 lpagb |= LPA_1000FULL; 100 break; 101 case 100: 102 bmcr |= BMCR_SPEED100; 103 lpa |= LPA_100FULL; 104 break; 105 case 10: 106 lpa |= LPA_10FULL; 107 break; 108 default: 109 pr_warn("fixed phy: unknown speed\n"); 110 return -EINVAL; 111 } 112 } else { 113 switch (fp->status.speed) { 114 case 1000: 115 bmcr |= BMCR_SPEED1000; 116 lpagb |= LPA_1000HALF; 117 break; 118 case 100: 119 bmcr |= BMCR_SPEED100; 120 lpa |= LPA_100HALF; 121 break; 122 case 10: 123 lpa |= LPA_10HALF; 124 break; 125 default: 126 pr_warn("fixed phy: unknown speed\n"); 127 return -EINVAL; 128 } 129 } 130 131 if (fp->status.pause) 132 lpa |= LPA_PAUSE_CAP; 133 134 if (fp->status.asym_pause) 135 lpa |= LPA_PAUSE_ASYM; 136 } 137 138 fp->regs[MII_PHYSID1] = 0; 139 fp->regs[MII_PHYSID2] = 0; 140 141 fp->regs[MII_BMSR] = bmsr; 142 fp->regs[MII_BMCR] = bmcr; 143 fp->regs[MII_LPA] = lpa; 144 fp->regs[MII_STAT1000] = lpagb; 145 146 return 0; 147 } 148 149 static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) 150 { 151 struct fixed_mdio_bus *fmb = bus->priv; 152 struct fixed_phy *fp; 153 154 if (reg_num >= MII_REGS_NUM) 155 return -1; 156 157 /* We do not support emulating Clause 45 over Clause 22 register reads 158 * return an error instead of bogus data. 159 */ 160 switch (reg_num) { 161 case MII_MMD_CTRL: 162 case MII_MMD_DATA: 163 return -1; 164 default: 165 break; 166 } 167 168 list_for_each_entry(fp, &fmb->phys, node) { 169 if (fp->addr == phy_addr) { 170 /* Issue callback if user registered it. */ 171 if (fp->link_update) { 172 fp->link_update(fp->phydev->attached_dev, 173 &fp->status); 174 fixed_phy_update_regs(fp); 175 } 176 return fp->regs[reg_num]; 177 } 178 } 179 180 return 0xFFFF; 181 } 182 183 static int fixed_mdio_write(struct mii_bus *bus, int phy_addr, int reg_num, 184 u16 val) 185 { 186 return 0; 187 } 188 189 /* 190 * If something weird is required to be done with link/speed, 191 * network driver is able to assign a function to implement this. 192 * May be useful for PHY's that need to be software-driven. 193 */ 194 int fixed_phy_set_link_update(struct phy_device *phydev, 195 int (*link_update)(struct net_device *, 196 struct fixed_phy_status *)) 197 { 198 struct fixed_mdio_bus *fmb = &platform_fmb; 199 struct fixed_phy *fp; 200 201 if (!phydev || !phydev->mdio.bus) 202 return -EINVAL; 203 204 list_for_each_entry(fp, &fmb->phys, node) { 205 if (fp->addr == phydev->mdio.addr) { 206 fp->link_update = link_update; 207 fp->phydev = phydev; 208 return 0; 209 } 210 } 211 212 return -ENOENT; 213 } 214 EXPORT_SYMBOL_GPL(fixed_phy_set_link_update); 215 216 int fixed_phy_update_state(struct phy_device *phydev, 217 const struct fixed_phy_status *status, 218 const struct fixed_phy_status *changed) 219 { 220 struct fixed_mdio_bus *fmb = &platform_fmb; 221 struct fixed_phy *fp; 222 223 if (!phydev || phydev->mdio.bus != fmb->mii_bus) 224 return -EINVAL; 225 226 list_for_each_entry(fp, &fmb->phys, node) { 227 if (fp->addr == phydev->mdio.addr) { 228 #define _UPD(x) if (changed->x) \ 229 fp->status.x = status->x 230 _UPD(link); 231 _UPD(speed); 232 _UPD(duplex); 233 _UPD(pause); 234 _UPD(asym_pause); 235 #undef _UPD 236 fixed_phy_update_regs(fp); 237 return 0; 238 } 239 } 240 241 return -ENOENT; 242 } 243 EXPORT_SYMBOL(fixed_phy_update_state); 244 245 int fixed_phy_add(unsigned int irq, int phy_addr, 246 struct fixed_phy_status *status, 247 int link_gpio) 248 { 249 int ret; 250 struct fixed_mdio_bus *fmb = &platform_fmb; 251 struct fixed_phy *fp; 252 253 fp = kzalloc(sizeof(*fp), GFP_KERNEL); 254 if (!fp) 255 return -ENOMEM; 256 257 memset(fp->regs, 0xFF, sizeof(fp->regs[0]) * MII_REGS_NUM); 258 259 if (irq != PHY_POLL) 260 fmb->mii_bus->irq[phy_addr] = irq; 261 262 fp->addr = phy_addr; 263 fp->status = *status; 264 fp->link_gpio = link_gpio; 265 266 if (gpio_is_valid(fp->link_gpio)) { 267 ret = gpio_request_one(fp->link_gpio, GPIOF_DIR_IN, 268 "fixed-link-gpio-link"); 269 if (ret) 270 goto err_regs; 271 } 272 273 ret = fixed_phy_update_regs(fp); 274 if (ret) 275 goto err_gpio; 276 277 list_add_tail(&fp->node, &fmb->phys); 278 279 return 0; 280 281 err_gpio: 282 if (gpio_is_valid(fp->link_gpio)) 283 gpio_free(fp->link_gpio); 284 err_regs: 285 kfree(fp); 286 return ret; 287 } 288 EXPORT_SYMBOL_GPL(fixed_phy_add); 289 290 static DEFINE_IDA(phy_fixed_ida); 291 292 static void fixed_phy_del(int phy_addr) 293 { 294 struct fixed_mdio_bus *fmb = &platform_fmb; 295 struct fixed_phy *fp, *tmp; 296 297 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { 298 if (fp->addr == phy_addr) { 299 list_del(&fp->node); 300 if (gpio_is_valid(fp->link_gpio)) 301 gpio_free(fp->link_gpio); 302 kfree(fp); 303 ida_simple_remove(&phy_fixed_ida, phy_addr); 304 return; 305 } 306 } 307 } 308 309 struct phy_device *fixed_phy_register(unsigned int irq, 310 struct fixed_phy_status *status, 311 int link_gpio, 312 struct device_node *np) 313 { 314 struct fixed_mdio_bus *fmb = &platform_fmb; 315 struct phy_device *phy; 316 int phy_addr; 317 int ret; 318 319 if (!fmb->mii_bus || fmb->mii_bus->state != MDIOBUS_REGISTERED) 320 return ERR_PTR(-EPROBE_DEFER); 321 322 /* Get the next available PHY address, up to PHY_MAX_ADDR */ 323 phy_addr = ida_simple_get(&phy_fixed_ida, 0, PHY_MAX_ADDR, GFP_KERNEL); 324 if (phy_addr < 0) 325 return ERR_PTR(phy_addr); 326 327 ret = fixed_phy_add(irq, phy_addr, status, link_gpio); 328 if (ret < 0) { 329 ida_simple_remove(&phy_fixed_ida, phy_addr); 330 return ERR_PTR(ret); 331 } 332 333 phy = get_phy_device(fmb->mii_bus, phy_addr, false); 334 if (IS_ERR(phy)) { 335 fixed_phy_del(phy_addr); 336 return ERR_PTR(-EINVAL); 337 } 338 339 /* propagate the fixed link values to struct phy_device */ 340 phy->link = status->link; 341 if (status->link) { 342 phy->speed = status->speed; 343 phy->duplex = status->duplex; 344 phy->pause = status->pause; 345 phy->asym_pause = status->asym_pause; 346 } 347 348 of_node_get(np); 349 phy->mdio.dev.of_node = np; 350 phy->is_pseudo_fixed_link = true; 351 352 switch (status->speed) { 353 case SPEED_1000: 354 phy->supported = PHY_1000BT_FEATURES; 355 break; 356 case SPEED_100: 357 phy->supported = PHY_100BT_FEATURES; 358 break; 359 case SPEED_10: 360 default: 361 phy->supported = PHY_10BT_FEATURES; 362 } 363 364 ret = phy_device_register(phy); 365 if (ret) { 366 phy_device_free(phy); 367 of_node_put(np); 368 fixed_phy_del(phy_addr); 369 return ERR_PTR(ret); 370 } 371 372 return phy; 373 } 374 EXPORT_SYMBOL_GPL(fixed_phy_register); 375 376 void fixed_phy_unregister(struct phy_device *phy) 377 { 378 phy_device_remove(phy); 379 380 fixed_phy_del(phy->mdio.addr); 381 } 382 EXPORT_SYMBOL_GPL(fixed_phy_unregister); 383 384 static int __init fixed_mdio_bus_init(void) 385 { 386 struct fixed_mdio_bus *fmb = &platform_fmb; 387 int ret; 388 389 pdev = platform_device_register_simple("Fixed MDIO bus", 0, NULL, 0); 390 if (IS_ERR(pdev)) { 391 ret = PTR_ERR(pdev); 392 goto err_pdev; 393 } 394 395 fmb->mii_bus = mdiobus_alloc(); 396 if (fmb->mii_bus == NULL) { 397 ret = -ENOMEM; 398 goto err_mdiobus_reg; 399 } 400 401 snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "fixed-0"); 402 fmb->mii_bus->name = "Fixed MDIO Bus"; 403 fmb->mii_bus->priv = fmb; 404 fmb->mii_bus->parent = &pdev->dev; 405 fmb->mii_bus->read = &fixed_mdio_read; 406 fmb->mii_bus->write = &fixed_mdio_write; 407 408 ret = mdiobus_register(fmb->mii_bus); 409 if (ret) 410 goto err_mdiobus_alloc; 411 412 return 0; 413 414 err_mdiobus_alloc: 415 mdiobus_free(fmb->mii_bus); 416 err_mdiobus_reg: 417 platform_device_unregister(pdev); 418 err_pdev: 419 return ret; 420 } 421 module_init(fixed_mdio_bus_init); 422 423 static void __exit fixed_mdio_bus_exit(void) 424 { 425 struct fixed_mdio_bus *fmb = &platform_fmb; 426 struct fixed_phy *fp, *tmp; 427 428 mdiobus_unregister(fmb->mii_bus); 429 mdiobus_free(fmb->mii_bus); 430 platform_device_unregister(pdev); 431 432 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { 433 list_del(&fp->node); 434 kfree(fp); 435 } 436 ida_destroy(&phy_fixed_ida); 437 } 438 module_exit(fixed_mdio_bus_exit); 439 440 MODULE_DESCRIPTION("Fixed MDIO bus (MDIO bus emulation with fixed PHYs)"); 441 MODULE_AUTHOR("Vitaly Bordug"); 442 MODULE_LICENSE("GPL"); 443