0001
0002
0003 #include <linux/errno.h>
0004 #include <linux/mdio.h>
0005 #include <linux/module.h>
0006 #include <linux/regmap.h>
0007
0008 #define REGVAL_MASK GENMASK(15, 0)
0009 #define REGNUM_C22_MASK GENMASK(4, 0)
0010
0011 #define REGNUM_C45_MASK GENMASK(20, 0)
0012
0013 static int regmap_mdio_read(struct mdio_device *mdio_dev, u32 reg, unsigned int *val)
0014 {
0015 int ret;
0016
0017 ret = mdiodev_read(mdio_dev, reg);
0018 if (ret < 0)
0019 return ret;
0020
0021 *val = ret & REGVAL_MASK;
0022 return 0;
0023 }
0024
0025 static int regmap_mdio_write(struct mdio_device *mdio_dev, u32 reg, unsigned int val)
0026 {
0027 return mdiodev_write(mdio_dev, reg, val);
0028 }
0029
0030 static int regmap_mdio_c22_read(void *context, unsigned int reg, unsigned int *val)
0031 {
0032 struct mdio_device *mdio_dev = context;
0033
0034 if (unlikely(reg & ~REGNUM_C22_MASK))
0035 return -ENXIO;
0036
0037 return regmap_mdio_read(mdio_dev, reg, val);
0038 }
0039
0040 static int regmap_mdio_c22_write(void *context, unsigned int reg, unsigned int val)
0041 {
0042 struct mdio_device *mdio_dev = context;
0043
0044 if (unlikely(reg & ~REGNUM_C22_MASK))
0045 return -ENXIO;
0046
0047 return mdiodev_write(mdio_dev, reg, val);
0048 }
0049
0050 static const struct regmap_bus regmap_mdio_c22_bus = {
0051 .reg_write = regmap_mdio_c22_write,
0052 .reg_read = regmap_mdio_c22_read,
0053 };
0054
0055 static int regmap_mdio_c45_read(void *context, unsigned int reg, unsigned int *val)
0056 {
0057 struct mdio_device *mdio_dev = context;
0058
0059 if (unlikely(reg & ~REGNUM_C45_MASK))
0060 return -ENXIO;
0061
0062 return regmap_mdio_read(mdio_dev, MII_ADDR_C45 | reg, val);
0063 }
0064
0065 static int regmap_mdio_c45_write(void *context, unsigned int reg, unsigned int val)
0066 {
0067 struct mdio_device *mdio_dev = context;
0068
0069 if (unlikely(reg & ~REGNUM_C45_MASK))
0070 return -ENXIO;
0071
0072 return regmap_mdio_write(mdio_dev, MII_ADDR_C45 | reg, val);
0073 }
0074
0075 static const struct regmap_bus regmap_mdio_c45_bus = {
0076 .reg_write = regmap_mdio_c45_write,
0077 .reg_read = regmap_mdio_c45_read,
0078 };
0079
0080 struct regmap *__regmap_init_mdio(struct mdio_device *mdio_dev,
0081 const struct regmap_config *config, struct lock_class_key *lock_key,
0082 const char *lock_name)
0083 {
0084 const struct regmap_bus *bus;
0085
0086 if (config->reg_bits == 5 && config->val_bits == 16)
0087 bus = ®map_mdio_c22_bus;
0088 else if (config->reg_bits == 21 && config->val_bits == 16)
0089 bus = ®map_mdio_c45_bus;
0090 else
0091 return ERR_PTR(-EOPNOTSUPP);
0092
0093 return __regmap_init(&mdio_dev->dev, bus, mdio_dev, config, lock_key, lock_name);
0094 }
0095 EXPORT_SYMBOL_GPL(__regmap_init_mdio);
0096
0097 struct regmap *__devm_regmap_init_mdio(struct mdio_device *mdio_dev,
0098 const struct regmap_config *config, struct lock_class_key *lock_key,
0099 const char *lock_name)
0100 {
0101 const struct regmap_bus *bus;
0102
0103 if (config->reg_bits == 5 && config->val_bits == 16)
0104 bus = ®map_mdio_c22_bus;
0105 else if (config->reg_bits == 21 && config->val_bits == 16)
0106 bus = ®map_mdio_c45_bus;
0107 else
0108 return ERR_PTR(-EOPNOTSUPP);
0109
0110 return __devm_regmap_init(&mdio_dev->dev, bus, mdio_dev, config, lock_key, lock_name);
0111 }
0112 EXPORT_SYMBOL_GPL(__devm_regmap_init_mdio);
0113
0114 MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");
0115 MODULE_DESCRIPTION("Regmap MDIO Module");
0116 MODULE_LICENSE("GPL v2");