root/drivers/net/phy/fixed_phy.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fixed_phy_change_carrier
  2. fixed_phy_update
  3. fixed_mdio_read
  4. fixed_mdio_write
  5. fixed_phy_set_link_update
  6. fixed_phy_add_gpiod
  7. fixed_phy_add
  8. fixed_phy_del
  9. fixed_phy_get_gpiod
  10. fixed_phy_get_gpiod
  11. __fixed_phy_register
  12. fixed_phy_register
  13. fixed_phy_register_with_gpiod
  14. fixed_phy_unregister
  15. fixed_mdio_bus_init
  16. fixed_mdio_bus_exit

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

/* [<][>][^][v][top][bottom][index][help] */