core: remap: fix regmap_init_mem_plat() reg size handeling
authorJohan Jonker <jbx6244@gmail.com>
Mon, 13 Mar 2023 00:30:46 +0000 (01:30 +0100)
committerKever Yang <kever.yang@rock-chips.com>
Sat, 6 May 2023 09:28:18 +0000 (17:28 +0800)
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>
drivers/core/regmap.c
drivers/core/syscon-uclass.c
drivers/ram/rockchip/sdram_rk3066.c
drivers/ram/rockchip/sdram_rk3188.c
drivers/ram/rockchip/sdram_rk322x.c
drivers/ram/rockchip/sdram_rk3288.c
drivers/ram/rockchip/sdram_rk3328.c
drivers/ram/rockchip/sdram_rk3399.c
include/regmap.h
include/syscon.h

index e33bb9d..dd32328 100644 (file)
@@ -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;
index 25fdb66..a47b8bd 100644 (file)
@@ -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
index a2425f2..39c0be5 100644 (file)
@@ -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));
        /* RK3066 supports dual-channel, set default channel num to 2. */
        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);
        if (ret)
                return ret;
index 272b1b2..ad9f936 100644 (file)
@@ -867,7 +867,7 @@ static int conv_of_plat(struct udevice *dev)
        memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
        /* rk3188 supports dual-channel, set default channel num to 2 */
        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);
        if (ret)
                return ret;
index 1b204fb..892766a 100644 (file)
@@ -769,7 +769,7 @@ static int conv_of_plat(struct udevice *dev)
        memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
 
        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);
        if (ret)
                return ret;
index 83778ad..c99118f 100644 (file)
@@ -1029,7 +1029,7 @@ static int conv_of_plat(struct udevice *dev)
        memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
        /* Rk3288 supports dual-channel, set default channel num to 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);
        if (ret)
                return ret;
index 184c93f..b5ca8ca 100644 (file)
@@ -54,7 +54,7 @@ static int conv_of_plat(struct udevice *dev)
        struct dtd_rockchip_rk3328_dmc *dtplat = &plat->dtplat;
        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);
        if (ret)
                return ret;
index 8993245..2bf8d48 100644 (file)
@@ -3050,7 +3050,7 @@ static int conv_of_plat(struct udevice *dev)
        struct dtd_rockchip_rk3399_dmc *dtplat = &plat->dtplat;
        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);
        if (ret)
                return ret;
index e81a360..22b0434 100644 (file)
@@ -378,17 +378,18 @@ int regmap_init_mem(ofnode node, struct regmap **mapp);
  *
  * @dev:       Device that uses this map
  * @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)
  * @mapp:      Returns allocated map
  * Return: 0 if OK, -ve on error
  *
  * 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.
  *
  */
-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);
 
 int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index);
index f5e6cc1..7a5ee3f 100644 (file)
@@ -25,19 +25,6 @@ struct syscon_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
  *