On Thu, 2021-06-03 at 13:58 +0300, Andy Shevchenko wrote: > On Thu, Jun 3, 2021 at 1:01 PM Sander Vanheule <sander@xxxxxxxxxxxxx> wrote: > > +static int rtl8231_reg_read(void *context, unsigned int reg, unsigned int > > *val) > > +{ > > + struct mdio_device *mdio_dev = context; > > + int ret; > > + > > + ret = mdiobus_read(mdio_dev->bus, mdio_dev->addr, > > RTL8231_REAL_REG(reg)); > > + > > + if (ret < 0) > > + return ret; > > + > > + *val = ret & 0xffff; > > + > > + return 0; > > +} > > + > > +static int rtl8231_reg_write(void *context, unsigned int reg, unsigned int > > val) > > +{ > > + struct mdio_device *mdio_dev = context; > > + > > + return mdiobus_write(mdio_dev->bus, mdio_dev->addr, > > RTL8231_REAL_REG(reg), val); > > +} > > Hmm... Maybe we can amend regmap-mdio to avoid duplication of the > above? Something like xlate in gpio-regmap or so? (+Cc Mark for the regmap discussion) It turns out that I can't use both devm_regmap_init_mdio and the overrides regmap_config.reg_read/write. This appears to be in contrast to what the documentation for these two overrides suggest. devm_regmap_init_mdio provides a bus for the regmap, which causes the overrides to be ignored in regmap.c Then I tried to use the paging support provided by regmap, by adding the following config: static struct regmap_range_cfg rtl8231_reg_ranges[] = { { /* Specify an unused register with an empty mask */ .selector_reg = 0x1f, .selector_mask = 0x00, .selector_shift = 0, .range_min = 0x00, .range_max = RTL8231_VREG(RTL8231_REG_COUNT - 1), .window_start = 0x00, .window_len = 0x20, }, }; This also doesn't work, because the used _regmap_bus_reg_read/write don't resolve register pages. The patch below fixes this, but maybe this missing functionality is intentional, and I should actually implement regmap_bus.read/write? ----8<---- diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 0d185ec018a5..20b6a2e0d2e3 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1881,6 +1881,15 @@ static int _regmap_bus_reg_write(void *context, unsigned int reg, unsigned int val) { struct regmap *map = context; + struct regmap_range_node *range; + int ret; + + range = _regmap_range_lookup(map, reg); + if (range) { + ret = _regmap_select_page(map, ®, range, 1); + if (ret != 0) + return ret; + } return map->bus->reg_write(map->bus_context, reg, val); } @@ -2651,6 +2660,15 @@ static int _regmap_bus_reg_read(void *context, unsigned int reg, unsigned int *val) { struct regmap *map = context; + struct regmap_range_node *range; + int ret; + + range = _regmap_range_lookup(map, reg); + if (range) { + ret = _regmap_select_page(map, ®, range, 1); + if (ret != 0) + return ret; + } return map->bus->reg_read(map->bus_context, reg, val); } -- Best, Sander