]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
regmap: mdio: Add clause-45 support
authorSander Vanheule <sander@svanheule.net>
Thu, 3 Jun 2021 18:25:10 +0000 (20:25 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 8 Jun 2021 12:37:43 +0000 (13:37 +0100)
Modern ethernet phys support the so-called clause-45 register access
mode, which allows for register address widths of 16 bit.

Also allow for 16-bit register address widths, and return a regmap for
clause-45 access in that case.

Signed-off-by: Sander Vanheule <sander@svanheule.net>
Link: https://lore.kernel.org/r/9cc263e3e7d5865edd90453b4183f1cf363cb636.1622743333.git.sander@svanheule.net
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/base/regmap/regmap-mdio.c

index aee34bf2400e5173caf42e65b4ea719abd54736e..cfb23afb19ebf47213d0b9039ad7ba7a6df878b6 100644 (file)
@@ -7,13 +7,14 @@
 
 #define REGVAL_MASK            GENMASK(15, 0)
 #define REGNUM_C22_MASK                GENMASK(4, 0)
+/* Clause-45 mask includes the device type (5 bit) and actual register number (16 bit) */
+#define REGNUM_C45_MASK                GENMASK(20, 0)
 
-static int regmap_mdio_read(void *context, unsigned int reg, unsigned int *val)
+static int regmap_mdio_read(struct mdio_device *mdio_dev, u32 reg, unsigned int *val)
 {
-       struct mdio_device *mdio_dev = context;
        int ret;
 
-       ret = mdiobus_read(mdio_dev->bus, mdio_dev->addr, reg & REGNUM_C22_MASK);
+       ret = mdiobus_read(mdio_dev->bus, mdio_dev->addr, reg);
        if (ret < 0)
                return ret;
 
@@ -21,27 +22,63 @@ static int regmap_mdio_read(void *context, unsigned int reg, unsigned int *val)
        return 0;
 }
 
-static int regmap_mdio_write(void *context, unsigned int reg, unsigned int val)
+static int regmap_mdio_write(struct mdio_device *mdio_dev, u32 reg, unsigned int val)
+{
+       return mdiobus_write(mdio_dev->bus, mdio_dev->addr, reg, val);
+}
+
+static int regmap_mdio_c22_read(void *context, unsigned int reg, unsigned int *val)
+{
+       struct mdio_device *mdio_dev = context;
+
+       return regmap_mdio_read(mdio_dev, reg & REGNUM_C22_MASK, val);
+}
+
+static int regmap_mdio_c22_write(void *context, unsigned int reg, unsigned int val)
 {
        struct mdio_device *mdio_dev = context;
 
-       return mdiobus_write(mdio_dev->bus, mdio_dev->addr, reg & REGNUM_C22_MASK, val);
+       return regmap_mdio_write(mdio_dev, reg & REGNUM_C22_MASK, val);
 }
 
-static const struct regmap_bus regmap_mdio_bus = {
-       .reg_write = regmap_mdio_write,
-       .reg_read = regmap_mdio_read,
+static const struct regmap_bus regmap_mdio_c22_bus = {
+       .reg_write = regmap_mdio_c22_write,
+       .reg_read = regmap_mdio_c22_read,
+};
+
+static int regmap_mdio_c45_read(void *context, unsigned int reg, unsigned int *val)
+{
+       struct mdio_device *mdio_dev = context;
+
+       return regmap_mdio_read(mdio_dev, MII_ADDR_C45 | (reg & REGNUM_C45_MASK), val);
+}
+
+static int regmap_mdio_c45_write(void *context, unsigned int reg, unsigned int val)
+{
+       struct mdio_device *mdio_dev = context;
+
+       return regmap_mdio_write(mdio_dev, MII_ADDR_C45 | (reg & REGNUM_C45_MASK), val);
+}
+
+static const struct regmap_bus regmap_mdio_c45_bus = {
+       .reg_write = regmap_mdio_c45_write,
+       .reg_read = regmap_mdio_c45_read,
 };
 
 struct regmap *__regmap_init_mdio(struct mdio_device *mdio_dev,
        const struct regmap_config *config, struct lock_class_key *lock_key,
        const char *lock_name)
 {
-       if (config->reg_bits != 5 || config->val_bits != 16)
+       struct regmap_bus *bus;
+
+       if (config->reg_bits == 5 && config->val_bits == 16)
+               bus = &regmap_mdio_c22_bus;
+       else if (config->reg_bits == 21 && config->val_bits == 16)
+               bus = &regmap_mdio_c45_bus;
+       else
                return ERR_PTR(-EOPNOTSUPP);
 
-       return __regmap_init(&mdio_dev->dev, &regmap_mdio_bus, mdio_dev, config,
-               lock_key, lock_name);
+       return __regmap_init(&mdio_dev->dev, bus, mdio_dev, config, lock_key, lock_name);
 }
 EXPORT_SYMBOL_GPL(__regmap_init_mdio);
 
@@ -49,11 +86,16 @@ struct regmap *__devm_regmap_init_mdio(struct mdio_device *mdio_dev,
        const struct regmap_config *config, struct lock_class_key *lock_key,
        const char *lock_name)
 {
-       if (config->reg_bits != 5 || config->val_bits != 16)
+       const struct regmap_bus *bus;
+
+       if (config->reg_bits == 5 && config->val_bits == 16)
+               bus = &regmap_mdio_c22_bus;
+       else if (config->reg_bits == 21 && config->val_bits == 16)
+               bus = &regmap_mdio_c45_bus;
+       else
                return ERR_PTR(-EOPNOTSUPP);
 
-       return __devm_regmap_init(&mdio_dev->dev, &regmap_mdio_bus, mdio_dev,
-               config, lock_key, lock_name);
+       return __devm_regmap_init(&mdio_dev->dev, bus, mdio_dev, config, lock_key, lock_name);
 }
 EXPORT_SYMBOL_GPL(__devm_regmap_init_mdio);