diff options
author | Johan Jonker <jbx6244@gmail.com> | 2023-03-13 01:30:46 +0100 |
---|---|---|
committer | Kever Yang <kever.yang@rock-chips.com> | 2023-05-06 17:28:18 +0800 |
commit | 0fbb96964b8574ca8012b2022cd0e431977fd340 (patch) | |
tree | e09485fee0bd6e656e655a72c7efe7396a9d3218 /drivers/core | |
parent | aecae81a35ddf24ae086a68f9c40836a1a174171 (diff) |
core: remap: fix regmap_init_mem_plat() reg size handeling
The fdt_addr_t and phys_addr_t size have been decoupled.
A 32bit CPU can expect 64-bit data from the device tree parser,
so convert regmap_init_mem_plat() input to handel both. The
syscon class driver also makes use of the regmap_init_mem_plat()
function, but has no way of knowing the format of the
device-specific platform data. In case of odd reg structures other
then that the syscon class driver assumes the regmap must be
filled in the individual syscon driver before pre-probe.
Also fix the ARRAY_SIZE divider in the syscon class driver.
Signed-off-by: Johan Jonker <jbx6244@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/core')
-rw-r--r-- | drivers/core/regmap.c | 23 | ||||
-rw-r--r-- | drivers/core/syscon-uclass.c | 23 |
2 files changed, 37 insertions, 9 deletions
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index e33bb9d798..dd32328098 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -79,7 +79,7 @@ static struct regmap *regmap_alloc(int count) } #if CONFIG_IS_ENABLED(OF_PLATDATA) -int regmap_init_mem_plat(struct udevice *dev, fdt_val_t *reg, int count, +int regmap_init_mem_plat(struct udevice *dev, void *reg, int size, int count, struct regmap **mapp) { struct regmap_range *range; @@ -89,9 +89,24 @@ int regmap_init_mem_plat(struct udevice *dev, fdt_val_t *reg, int count, if (!map) return -ENOMEM; - for (range = map->ranges; count > 0; reg += 2, range++, count--) { - range->start = *reg; - range->size = reg[1]; + if (size == sizeof(fdt32_t)) { + fdt32_t *ptr = (fdt32_t *)reg; + + for (range = map->ranges; count > 0; + ptr += 2, range++, count--) { + range->start = *ptr; + range->size = ptr[1]; + } + } else if (size == sizeof(fdt64_t)) { + fdt64_t *ptr = (fdt64_t *)reg; + + for (range = map->ranges; count > 0; + ptr += 2, range++, count--) { + range->start = *ptr; + range->size = ptr[1]; + } + } else { + return -EINVAL; } *mapp = map; diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c index 25fdb66eaa..a47b8bd3c0 100644 --- a/drivers/core/syscon-uclass.c +++ b/drivers/core/syscon-uclass.c @@ -49,17 +49,30 @@ static int syscon_pre_probe(struct udevice *dev) if (device_get_uclass_id(dev->parent) == UCLASS_PCI) return 0; +#if CONFIG_IS_ENABLED(OF_PLATDATA) /* * With OF_PLATDATA we really have no way of knowing the format of * the device-specific platform data. So we assume that it starts with - * a 'reg' member, and this holds a single address and size. Drivers - * using OF_PLATDATA will need to ensure that this is true. + * a 'reg' member that holds a single address and size. Drivers + * using OF_PLATDATA will need to ensure that this is true. In case of + * odd reg structures other then the syscon_base_plat structure + * below the regmap must be defined in the individual syscon driver. */ -#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct syscon_base_plat { + phys_addr_t reg[2]; + }; + struct syscon_base_plat *plat = dev_get_plat(dev); - return regmap_init_mem_plat(dev, plat->reg, ARRAY_SIZE(plat->reg), - &priv->regmap); + /* + * Return if the regmap is already defined in the individual + * syscon driver. + */ + if (priv->regmap) + return 0; + + return regmap_init_mem_plat(dev, plat->reg, sizeof(plat->reg[0]), + ARRAY_SIZE(plat->reg) / 2, &priv->regmap); #else return regmap_init_mem(dev_ofnode(dev), &priv->regmap); #endif |