
Hi Neil,
On Fri, Apr 27, 2018 at 3:00 PM, Neil Armstrong narmstrong@baylibre.com wrote:
Hi Mario,
On 27/04/2018 14:51, Mario Six wrote:
The regmap functions currently assume that all register map accesses have a data width of 32 bits, but there are maps that have different widths.
Implement a size parameter for the regmap_read and regmap_write functions to specify the width of a desired read or write operation on a regmap.
This changes the regmap API which is based on the Linux API.
Linux passes a struct defining the regmap access type instead, I think the same should happen here.
OK, I see what you mean.
I see that the Linux API also has regmap_raw_read/regmap_raw_write functions, which do have size parameters, so I think those would suite this use case rather nicely (and won't break the existing API).
Neil
Best regards, Mario
Correct all current clients of the regmap API to use 32 bit width reads and writes to keep backwards compatibility.
Signed-off-by: Mario Six mario.six@gdsys.cc
v1 -> v2: New in v2
drivers/clk/at91/clk-utmi.c | 6 +++-- drivers/clk/clk_boston.c | 3 ++- drivers/core/regmap.c | 45 ++++++++++++++++++++++++------- drivers/phy/meson-gxl-usb2.c | 18 ++++++------- drivers/phy/meson-gxl-usb3.c | 22 +++++++-------- drivers/power/regulator/pbias_regulator.c | 5 ++-- drivers/reset/reset-meson.c | 14 +++++----- drivers/sysreset/sysreset_syscon.c | 2 +- include/regmap.h | 11 ++++++-- 9 files changed, 82 insertions(+), 44 deletions(-)
diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index 875bf293f9..1da625cab1 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c @@ -68,13 +68,15 @@ static int utmi_clk_enable(struct clk *clk) }
if (plat->regmap_sfr) {
err = regmap_read(plat->regmap_sfr, AT91_SFR_UTMICKTRIM, &tmp);
err = regmap_read(plat->regmap_sfr, AT91_SFR_UTMICKTRIM, &tmp,
REGMAP_SIZE_32); if (err) return -EINVAL; tmp &= ~AT91_UTMICKTRIM_FREQ; tmp |= utmi_ref_clk_freq;
err = regmap_write(plat->regmap_sfr, AT91_SFR_UTMICKTRIM, tmp);
err = regmap_write(plat->regmap_sfr, AT91_SFR_UTMICKTRIM, tmp,
REGMAP_SIZE_32); if (err) return -EINVAL; } else if (utmi_ref_clk_freq) {
diff --git a/drivers/clk/clk_boston.c b/drivers/clk/clk_boston.c index 5c05e3d78d..e09fd06fa0 100644 --- a/drivers/clk/clk_boston.c +++ b/drivers/clk/clk_boston.c @@ -33,7 +33,8 @@ static ulong clk_boston_get_rate(struct clk *clk) uint mmcmdiv; int err;
err = regmap_read(state->regmap, BOSTON_PLAT_MMCMDIV, &mmcmdiv);
err = regmap_read(state->regmap, BOSTON_PLAT_MMCMDIV, &mmcmdiv,
REGMAP_SIZE_32); if (err) return 0;
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 8a0e00ff9a..c2cdff3979 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -130,20 +130,47 @@ int regmap_uninit(struct regmap *map) return 0; }
-int regmap_read(struct regmap *map, uint offset, uint *valp) +int regmap_read(struct regmap *map, ulong offset, ulong *valp,
enum regmap_size_t size)
{
uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
*valp = le32_to_cpu(readl(ptr));
void *ptr;
switch (size) {
case REGMAP_SIZE_8:
ptr = map_physmem(map->base + offset, 1, MAP_NOCACHE);
*valp = readb(ptr);
break;
case REGMAP_SIZE_16:
ptr = map_physmem(map->base + offset, 2, MAP_NOCACHE);
*valp = le16_to_cpu(readw(ptr));
break;
case REGMAP_SIZE_32:
ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
*valp = le32_to_cpu(readl(ptr));
break;
} return 0;
}
-int regmap_write(struct regmap *map, uint offset, uint val) +int regmap_write(struct regmap *map, ulong offset, ulong val,
enum regmap_size_t size)
{
uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
writel(cpu_to_le32(val), ptr);
void *ptr;
switch (size) {
case REGMAP_SIZE_8:
ptr = map_physmem(map->base + offset, 1, MAP_NOCACHE);
writel((u8)val, ptr);
break;
case REGMAP_SIZE_16:
ptr = map_physmem(map->base + offset, 2, MAP_NOCACHE);
writel(cpu_to_le16((u16)val), ptr);
break;
case REGMAP_SIZE_32:
ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
writel(cpu_to_le32((u32)val), ptr);
break;
} return 0;
} diff --git a/drivers/phy/meson-gxl-usb2.c b/drivers/phy/meson-gxl-usb2.c index 15c9c89fd9..704b78747c 100644 --- a/drivers/phy/meson-gxl-usb2.c +++ b/drivers/phy/meson-gxl-usb2.c @@ -111,15 +111,15 @@ static void phy_meson_gxl_usb2_reset(struct phy_meson_gxl_usb2_priv *priv) { uint val;
regmap_read(priv->regmap, U2P_R0, &val);
regmap_read(priv->regmap, U2P_R0, &val, REGMAP_SIZE_32); /* reset the PHY and wait until settings are stabilized */ val |= U2P_R0_POWER_ON_RESET;
regmap_write(priv->regmap, U2P_R0, val);
regmap_write(priv->regmap, U2P_R0, val, REGMAP_SIZE_32); udelay(RESET_COMPLETE_TIME); val &= ~U2P_R0_POWER_ON_RESET;
regmap_write(priv->regmap, U2P_R0, val);
regmap_write(priv->regmap, U2P_R0, val, REGMAP_SIZE_32); udelay(RESET_COMPLETE_TIME);
}
@@ -128,11 +128,11 @@ phy_meson_gxl_usb2_set_host_mode(struct phy_meson_gxl_usb2_priv *priv) { uint val;
regmap_read(priv->regmap, U2P_R0, &val);
regmap_read(priv->regmap, U2P_R0, &val, REGMAP_SIZE_32); val |= U2P_R0_DM_PULLDOWN; val |= U2P_R0_DP_PULLDOWN; val &= ~U2P_R0_ID_PULLUP;
regmap_write(priv->regmap, U2P_R0, val);
regmap_write(priv->regmap, U2P_R0, val, REGMAP_SIZE_32); phy_meson_gxl_usb2_reset(priv);
} @@ -143,10 +143,10 @@ static int phy_meson_gxl_usb2_power_on(struct phy *phy) struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev); uint val;
regmap_read(priv->regmap, U2P_R0, &val);
regmap_read(priv->regmap, U2P_R0, &val, REGMAP_SIZE_32); /* power on the PHY by taking it out of reset mode */ val &= ~U2P_R0_POWER_ON_RESET;
regmap_write(priv->regmap, U2P_R0, val);
regmap_write(priv->regmap, U2P_R0, val, REGMAP_SIZE_32); phy_meson_gxl_usb2_set_host_mode(priv);
@@ -167,10 +167,10 @@ static int phy_meson_gxl_usb2_power_off(struct phy *phy) struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev); uint val;
regmap_read(priv->regmap, U2P_R0, &val);
regmap_read(priv->regmap, U2P_R0, &val, REGMAP_SIZE_32); /* power off the PHY by putting it into reset mode */ val |= U2P_R0_POWER_ON_RESET;
regmap_write(priv->regmap, U2P_R0, val);
regmap_write(priv->regmap, U2P_R0, val, REGMAP_SIZE_32);
#if CONFIG_IS_ENABLED(DM_REGULATOR) if (priv->phy_supply) { diff --git a/drivers/phy/meson-gxl-usb3.c b/drivers/phy/meson-gxl-usb3.c index a385fbdf12..33c24fd989 100644 --- a/drivers/phy/meson-gxl-usb3.c +++ b/drivers/phy/meson-gxl-usb3.c @@ -100,13 +100,13 @@ phy_meson_gxl_usb3_set_host_mode(struct phy_meson_gxl_usb3_priv *priv) { uint val;
regmap_read(priv->regmap, USB_R0, &val);
regmap_read(priv->regmap, USB_R0, &val, REGMAP_SIZE_32); val &= ~USB_R0_U2D_ACT;
regmap_write(priv->regmap, USB_R0, val);
regmap_write(priv->regmap, USB_R0, val, REGMAP_SIZE_32);
regmap_read(priv->regmap, USB_R4, &val);
regmap_read(priv->regmap, USB_R4, &val, REGMAP_SIZE_32); val &= ~USB_R4_P21_SLEEP_M0;
regmap_write(priv->regmap, USB_R4, val);
regmap_write(priv->regmap, USB_R4, val, REGMAP_SIZE_32); return 0;
} @@ -117,12 +117,12 @@ static int phy_meson_gxl_usb3_power_on(struct phy *phy) struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); uint val;
regmap_read(priv->regmap, USB_R5, &val);
regmap_read(priv->regmap, USB_R5, &val, REGMAP_SIZE_32); val |= USB_R5_ID_DIG_EN_0; val |= USB_R5_ID_DIG_EN_1; val &= ~USB_R5_ID_DIG_TH_MASK; val |= FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff);
regmap_write(priv->regmap, USB_R5, val);
regmap_write(priv->regmap, USB_R5, val, REGMAP_SIZE_32); return phy_meson_gxl_usb3_set_host_mode(priv);
} @@ -133,10 +133,10 @@ static int phy_meson_gxl_usb3_power_off(struct phy *phy) struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); uint val;
regmap_read(priv->regmap, USB_R5, &val);
regmap_read(priv->regmap, USB_R5, &val, REGMAP_SIZE_32); val &= ~USB_R5_ID_DIG_EN_0; val &= ~USB_R5_ID_DIG_EN_1;
regmap_write(priv->regmap, USB_R5, val);
regmap_write(priv->regmap, USB_R5, val, REGMAP_SIZE_32); return 0;
} @@ -147,10 +147,10 @@ static int phy_meson_gxl_usb3_init(struct phy *phy) struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); uint val;
regmap_read(priv->regmap, USB_R1, &val);
regmap_read(priv->regmap, USB_R1, &val, REGMAP_SIZE_32); val &= ~USB_R1_U3H_FLADJ_30MHZ_REG_MASK; val |= FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20);
regmap_write(priv->regmap, USB_R1, val);
regmap_write(priv->regmap, USB_R1, val, REGMAP_SIZE_32); return 0;
} @@ -169,7 +169,7 @@ int meson_gxl_usb3_phy_probe(struct udevice *dev) ret = regmap_init_mem(dev, &priv->regmap); if (ret) return ret;
#if CONFIG_IS_ENABLED(CLK) ret = clk_get_by_index(dev, 0, &priv->clk); if (ret < 0) diff --git a/drivers/power/regulator/pbias_regulator.c b/drivers/power/regulator/pbias_regulator.c index adf589b224..386da3a58f 100644 --- a/drivers/power/regulator/pbias_regulator.c +++ b/drivers/power/regulator/pbias_regulator.c @@ -46,7 +46,7 @@ static int pbias_write(struct udevice *dev, uint reg, const uint8_t *buff, if (len != 4) return -EINVAL;
return regmap_write(priv->regmap, priv->offset, val);
return regmap_write(priv->regmap, priv->offset, val, REGMAP_SIZE_32);
}
static int pbias_read(struct udevice *dev, uint reg, uint8_t *buff, int len) @@ -56,7 +56,8 @@ static int pbias_read(struct udevice *dev, uint reg, uint8_t *buff, int len) if (len != 4) return -EINVAL;
return regmap_read(priv->regmap, priv->offset, (u32 *)buff);
return regmap_read(priv->regmap, priv->offset, (u32 *)buff,
REGMAP_SIZE_32);
}
static int pbias_ofdata_to_platdata(struct udevice *dev) diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index 5324f86f5f..c31f302143 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -41,12 +41,12 @@ static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert) uint reg_offset = LEVEL_OFFSET + (bank << 2); uint val;
regmap_read(priv->regmap, reg_offset, &val);
regmap_read(priv->regmap, reg_offset, &val, REGMAP_SIZE_32); if (assert) val &= ~BIT(offset); else val |= BIT(offset);
regmap_write(priv->regmap, reg_offset, val);
regmap_write(priv->regmap, reg_offset, val, REGMAP_SIZE_32); return 0;
} @@ -68,15 +68,15 @@ struct reset_ops meson_reset_ops = { .rst_deassert = meson_reset_deassert, };
-static const struct udevice_id meson_reset_ids[] = {
{ .compatible = "amlogic,meson-gxbb-reset" },
{ }
-}; +static const struct udevice_id meson_reset_ids[] = {
{ .compatible = "amlogic,meson-gxbb-reset" },
{ }
+};
static int meson_reset_probe(struct udevice *dev) { struct meson_reset_priv *priv = dev_get_priv(dev);
return regmap_init_mem(dev, &priv->regmap);
}
diff --git a/drivers/sysreset/sysreset_syscon.c b/drivers/sysreset/sysreset_syscon.c index 22c602a4d2..0c374a7443 100644 --- a/drivers/sysreset/sysreset_syscon.c +++ b/drivers/sysreset/sysreset_syscon.c @@ -25,7 +25,7 @@ static int syscon_reboot_request(struct udevice *dev, enum sysreset_t type) { struct syscon_reboot_priv *priv = dev_get_priv(dev);
regmap_write(priv->regmap, priv->offset, priv->mask);
regmap_write(priv->regmap, priv->offset, priv->mask, REGMAP_SIZE_32); return -EINPROGRESS;
} diff --git a/include/regmap.h b/include/regmap.h index 493a5d8eff..a6e2fafd27 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -8,6 +8,13 @@ #ifndef __REGMAP_H #define __REGMAP_H
+/* Access sizes for fpgamap reads and writes */ +enum regmap_size_t {
REGMAP_SIZE_8 = 1,
REGMAP_SIZE_16 = 2,
REGMAP_SIZE_32 = 4,
+};
/**
- struct regmap_range - a register map range
@@ -37,8 +44,8 @@ struct regmap {
- Interface to provide access to registers either through a direct memory
- bus or through a peripheral bus like I2C, SPI.
*/ -int regmap_write(struct regmap *map, uint offset, uint val); -int regmap_read(struct regmap *map, uint offset, uint *valp); +int regmap_write(struct regmap *map, ulong offset, ulong val, enum regmap_size_t size); +int regmap_read(struct regmap *map, ulong offset, ulong *valp, enum regmap_size_t size);
#define regmap_write32(map, ptr, member, val) \ regmap_write(map, (uint32_t *)(ptr)->member - (uint32_t *)(ptr), val)