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>
This commit is contained in:
parent
aecae81a35
commit
0fbb96964b
10 changed files with 46 additions and 30 deletions
|
@ -79,7 +79,7 @@ static struct regmap *regmap_alloc(int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
#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 **mapp)
|
||||||
{
|
{
|
||||||
struct regmap_range *range;
|
struct regmap_range *range;
|
||||||
|
@ -89,9 +89,24 @@ int regmap_init_mem_plat(struct udevice *dev, fdt_val_t *reg, int count,
|
||||||
if (!map)
|
if (!map)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (range = map->ranges; count > 0; reg += 2, range++, count--) {
|
if (size == sizeof(fdt32_t)) {
|
||||||
range->start = *reg;
|
fdt32_t *ptr = (fdt32_t *)reg;
|
||||||
range->size = reg[1];
|
|
||||||
|
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;
|
*mapp = map;
|
||||||
|
|
|
@ -49,17 +49,30 @@ static int syscon_pre_probe(struct udevice *dev)
|
||||||
if (device_get_uclass_id(dev->parent) == UCLASS_PCI)
|
if (device_get_uclass_id(dev->parent) == UCLASS_PCI)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
/*
|
/*
|
||||||
* With OF_PLATDATA we really have no way of knowing the format of
|
* 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
|
* the device-specific platform data. So we assume that it starts with
|
||||||
* a 'reg' member, and this holds a single address and size. Drivers
|
* a 'reg' member that holds a single address and size. Drivers
|
||||||
* using OF_PLATDATA will need to ensure that this is true.
|
* 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);
|
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
|
#else
|
||||||
return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
|
return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -801,7 +801,7 @@ static int rk3066_dmc_conv_of_plat(struct udevice *dev)
|
||||||
memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
|
memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
|
||||||
/* RK3066 supports dual-channel, set default channel num to 2. */
|
/* RK3066 supports dual-channel, set default channel num to 2. */
|
||||||
plat->num_channels = 1;
|
plat->num_channels = 1;
|
||||||
ret = regmap_init_mem_plat(dev, of_plat->reg,
|
ret = regmap_init_mem_plat(dev, of_plat->reg, sizeof(of_plat->reg[0]),
|
||||||
ARRAY_SIZE(of_plat->reg) / 2, &plat->map);
|
ARRAY_SIZE(of_plat->reg) / 2, &plat->map);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -867,7 +867,7 @@ static int conv_of_plat(struct udevice *dev)
|
||||||
memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
|
memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
|
||||||
/* rk3188 supports dual-channel, set default channel num to 2 */
|
/* rk3188 supports dual-channel, set default channel num to 2 */
|
||||||
plat->num_channels = 1;
|
plat->num_channels = 1;
|
||||||
ret = regmap_init_mem_plat(dev, of_plat->reg,
|
ret = regmap_init_mem_plat(dev, of_plat->reg, sizeof(of_plat->reg[0]),
|
||||||
ARRAY_SIZE(of_plat->reg) / 2, &plat->map);
|
ARRAY_SIZE(of_plat->reg) / 2, &plat->map);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -769,7 +769,7 @@ static int conv_of_plat(struct udevice *dev)
|
||||||
memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
|
memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
|
||||||
|
|
||||||
plat->num_channels = 1;
|
plat->num_channels = 1;
|
||||||
ret = regmap_init_mem_plat(dev, of_plat->reg,
|
ret = regmap_init_mem_plat(dev, of_plat->reg, sizeof(of_plat->reg[0]),
|
||||||
ARRAY_SIZE(of_plat->reg) / 2, &plat->map);
|
ARRAY_SIZE(of_plat->reg) / 2, &plat->map);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -1029,7 +1029,7 @@ static int conv_of_plat(struct udevice *dev)
|
||||||
memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
|
memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
|
||||||
/* Rk3288 supports dual-channel, set default channel num to 2 */
|
/* Rk3288 supports dual-channel, set default channel num to 2 */
|
||||||
plat->num_channels = 2;
|
plat->num_channels = 2;
|
||||||
ret = regmap_init_mem_plat(dev, of_plat->reg,
|
ret = regmap_init_mem_plat(dev, of_plat->reg, sizeof(of_plat->reg[0]),
|
||||||
ARRAY_SIZE(of_plat->reg) / 2, &plat->map);
|
ARRAY_SIZE(of_plat->reg) / 2, &plat->map);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -54,7 +54,7 @@ static int conv_of_plat(struct udevice *dev)
|
||||||
struct dtd_rockchip_rk3328_dmc *dtplat = &plat->dtplat;
|
struct dtd_rockchip_rk3328_dmc *dtplat = &plat->dtplat;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = regmap_init_mem_plat(dev, dtplat->reg,
|
ret = regmap_init_mem_plat(dev, dtplat->reg, sizeof(dtplat->reg[0]),
|
||||||
ARRAY_SIZE(dtplat->reg) / 2, &plat->map);
|
ARRAY_SIZE(dtplat->reg) / 2, &plat->map);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -3050,7 +3050,7 @@ static int conv_of_plat(struct udevice *dev)
|
||||||
struct dtd_rockchip_rk3399_dmc *dtplat = &plat->dtplat;
|
struct dtd_rockchip_rk3399_dmc *dtplat = &plat->dtplat;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = regmap_init_mem_plat(dev, dtplat->reg,
|
ret = regmap_init_mem_plat(dev, dtplat->reg, sizeof(dtplat->reg[0]),
|
||||||
ARRAY_SIZE(dtplat->reg) / 2, &plat->map);
|
ARRAY_SIZE(dtplat->reg) / 2, &plat->map);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -378,17 +378,18 @@ int regmap_init_mem(ofnode node, struct regmap **mapp);
|
||||||
*
|
*
|
||||||
* @dev: Device that uses this map
|
* @dev: Device that uses this map
|
||||||
* @reg: List of address, size pairs
|
* @reg: List of address, size pairs
|
||||||
|
* @size: Size of one reg array item
|
||||||
* @count: Number of pairs (e.g. 1 if the regmap has a single entry)
|
* @count: Number of pairs (e.g. 1 if the regmap has a single entry)
|
||||||
* @mapp: Returns allocated map
|
* @mapp: Returns allocated map
|
||||||
* Return: 0 if OK, -ve on error
|
* Return: 0 if OK, -ve on error
|
||||||
*
|
*
|
||||||
* This creates a new regmap with a list of regions passed in, rather than
|
* This creates a new regmap with a list of regions passed in, rather than
|
||||||
* using the device tree. It only supports 32-bit machines.
|
* using the device tree.
|
||||||
*
|
*
|
||||||
* Use regmap_uninit() to free it.
|
* Use regmap_uninit() to free it.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
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 **mapp);
|
||||||
|
|
||||||
int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index);
|
int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index);
|
||||||
|
|
|
@ -25,19 +25,6 @@ struct syscon_ops {
|
||||||
|
|
||||||
#define syscon_get_ops(dev) ((struct syscon_ops *)(dev)->driver->ops)
|
#define syscon_get_ops(dev) ((struct syscon_ops *)(dev)->driver->ops)
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
|
||||||
/*
|
|
||||||
* We don't support 64-bit machines. If they are so resource-contrained that
|
|
||||||
* they need to use OF_PLATDATA, something is horribly wrong with the
|
|
||||||
* education of our hardware engineers.
|
|
||||||
*
|
|
||||||
* Update: 64-bit is now supported and we have an education crisis.
|
|
||||||
*/
|
|
||||||
struct syscon_base_plat {
|
|
||||||
fdt_val_t reg[2];
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* syscon_get_regmap() - Get access to a register map
|
* syscon_get_regmap() - Get access to a register map
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue