root/drivers/net/dsa/lan9303_mdio.c

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

DEFINITIONS

This source file includes following definitions.
  1. lan9303_mdio_real_write
  2. lan9303_mdio_write
  3. lan9303_mdio_real_read
  4. lan9303_mdio_read
  5. lan9303_mdio_phy_write
  6. lan9303_mdio_phy_read
  7. lan9303_mdio_probe
  8. lan9303_mdio_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2017 Pengutronix, Juergen Borleis <kernel@pengutronix.de>
   4  *
   5  * Partially based on a patch from
   6  * Copyright (c) 2014 Stefan Roese <sr@denx.de>
   7  */
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/mdio.h>
  11 #include <linux/phy.h>
  12 #include <linux/of.h>
  13 
  14 #include "lan9303.h"
  15 
  16 /* Generate phy-addr and -reg from the input address */
  17 #define PHY_ADDR(x) ((((x) >> 6) + 0x10) & 0x1f)
  18 #define PHY_REG(x) (((x) >> 1) & 0x1f)
  19 
  20 struct lan9303_mdio {
  21         struct mdio_device *device;
  22         struct lan9303 chip;
  23 };
  24 
  25 static void lan9303_mdio_real_write(struct mdio_device *mdio, int reg, u16 val)
  26 {
  27         mdio->bus->write(mdio->bus, PHY_ADDR(reg), PHY_REG(reg), val);
  28 }
  29 
  30 static int lan9303_mdio_write(void *ctx, uint32_t reg, uint32_t val)
  31 {
  32         struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;
  33 
  34         reg <<= 2; /* reg num to offset */
  35         mutex_lock(&sw_dev->device->bus->mdio_lock);
  36         lan9303_mdio_real_write(sw_dev->device, reg, val & 0xffff);
  37         lan9303_mdio_real_write(sw_dev->device, reg + 2, (val >> 16) & 0xffff);
  38         mutex_unlock(&sw_dev->device->bus->mdio_lock);
  39 
  40         return 0;
  41 }
  42 
  43 static u16 lan9303_mdio_real_read(struct mdio_device *mdio, int reg)
  44 {
  45         return mdio->bus->read(mdio->bus, PHY_ADDR(reg), PHY_REG(reg));
  46 }
  47 
  48 static int lan9303_mdio_read(void *ctx, uint32_t reg, uint32_t *val)
  49 {
  50         struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;
  51 
  52         reg <<= 2; /* reg num to offset */
  53         mutex_lock(&sw_dev->device->bus->mdio_lock);
  54         *val = lan9303_mdio_real_read(sw_dev->device, reg);
  55         *val |= (lan9303_mdio_real_read(sw_dev->device, reg + 2) << 16);
  56         mutex_unlock(&sw_dev->device->bus->mdio_lock);
  57 
  58         return 0;
  59 }
  60 
  61 static int lan9303_mdio_phy_write(struct lan9303 *chip, int phy, int reg,
  62                                   u16 val)
  63 {
  64         struct lan9303_mdio *sw_dev = dev_get_drvdata(chip->dev);
  65 
  66         return mdiobus_write_nested(sw_dev->device->bus, phy, reg, val);
  67 }
  68 
  69 static int lan9303_mdio_phy_read(struct lan9303 *chip, int phy,  int reg)
  70 {
  71         struct lan9303_mdio *sw_dev = dev_get_drvdata(chip->dev);
  72 
  73         return mdiobus_read_nested(sw_dev->device->bus, phy, reg);
  74 }
  75 
  76 static const struct lan9303_phy_ops lan9303_mdio_phy_ops = {
  77         .phy_read = lan9303_mdio_phy_read,
  78         .phy_write = lan9303_mdio_phy_write,
  79 };
  80 
  81 static const struct regmap_config lan9303_mdio_regmap_config = {
  82         .reg_bits = 8,
  83         .val_bits = 32,
  84         .reg_stride = 1,
  85         .can_multi_write = true,
  86         .max_register = 0x0ff, /* address bits 0..1 are not used */
  87         .reg_format_endian = REGMAP_ENDIAN_LITTLE,
  88 
  89         .volatile_table = &lan9303_register_set,
  90         .wr_table = &lan9303_register_set,
  91         .rd_table = &lan9303_register_set,
  92 
  93         .reg_read = lan9303_mdio_read,
  94         .reg_write = lan9303_mdio_write,
  95 
  96         .cache_type = REGCACHE_NONE,
  97 };
  98 
  99 static int lan9303_mdio_probe(struct mdio_device *mdiodev)
 100 {
 101         struct lan9303_mdio *sw_dev;
 102         int ret;
 103 
 104         sw_dev = devm_kzalloc(&mdiodev->dev, sizeof(struct lan9303_mdio),
 105                               GFP_KERNEL);
 106         if (!sw_dev)
 107                 return -ENOMEM;
 108 
 109         sw_dev->chip.regmap = devm_regmap_init(&mdiodev->dev, NULL, sw_dev,
 110                                                &lan9303_mdio_regmap_config);
 111         if (IS_ERR(sw_dev->chip.regmap)) {
 112                 ret = PTR_ERR(sw_dev->chip.regmap);
 113                 dev_err(&mdiodev->dev, "regmap init failed: %d\n", ret);
 114                 return ret;
 115         }
 116 
 117         /* link forward and backward */
 118         sw_dev->device = mdiodev;
 119         dev_set_drvdata(&mdiodev->dev, sw_dev);
 120         sw_dev->chip.dev = &mdiodev->dev;
 121 
 122         sw_dev->chip.ops = &lan9303_mdio_phy_ops;
 123 
 124         ret = lan9303_probe(&sw_dev->chip, mdiodev->dev.of_node);
 125         if (ret != 0)
 126                 return ret;
 127 
 128         dev_info(&mdiodev->dev, "LAN9303 MDIO driver loaded successfully\n");
 129 
 130         return 0;
 131 }
 132 
 133 static void lan9303_mdio_remove(struct mdio_device *mdiodev)
 134 {
 135         struct lan9303_mdio *sw_dev = dev_get_drvdata(&mdiodev->dev);
 136 
 137         if (!sw_dev)
 138                 return;
 139 
 140         lan9303_remove(&sw_dev->chip);
 141 }
 142 
 143 /*-------------------------------------------------------------------------*/
 144 
 145 static const struct of_device_id lan9303_mdio_of_match[] = {
 146         { .compatible = "smsc,lan9303-mdio" },
 147         { /* sentinel */ },
 148 };
 149 MODULE_DEVICE_TABLE(of, lan9303_mdio_of_match);
 150 
 151 static struct mdio_driver lan9303_mdio_driver = {
 152         .mdiodrv.driver = {
 153                 .name = "LAN9303_MDIO",
 154                 .of_match_table = of_match_ptr(lan9303_mdio_of_match),
 155         },
 156         .probe  = lan9303_mdio_probe,
 157         .remove = lan9303_mdio_remove,
 158 };
 159 mdio_module_driver(lan9303_mdio_driver);
 160 
 161 MODULE_AUTHOR("Stefan Roese <sr@denx.de>, Juergen Borleis <kernel@pengutronix.de>");
 162 MODULE_DESCRIPTION("Driver for SMSC/Microchip LAN9303 three port ethernet switch in MDIO managed mode");
 163 MODULE_LICENSE("GPL v2");

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