Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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 /* Clause-45 mask includes the device type (5 bit) and actual register number (16 bit) */
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 = &regmap_mdio_c22_bus;
0088     else if (config->reg_bits == 21 && config->val_bits == 16)
0089         bus = &regmap_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 = &regmap_mdio_c22_bus;
0105     else if (config->reg_bits == 21 && config->val_bits == 16)
0106         bus = &regmap_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");