rockchip: rk3288: syscon_rk3288: store syscon platdata in regmap

The Rockchip SoC rk3288 has 2 types of device trees floating around.
A 64bit reg size when synced from Linux and a 32bit for U-boot.
A pre-probe function in the syscon class driver assumes only 32bit.
For other odd reg structures the regmap must be defined in the individual
syscon driver. Store rk3288 platdata in a regmap before pre-probe
during bind.

Signed-off-by: Johan Jonker <jbx6244@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
diff --git a/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c b/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c
index 9c1ae88..8b2c2f3 100644
--- a/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c
@@ -6,7 +6,10 @@
 
 #include <common.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <log.h>
+#include <malloc.h>
+#include <regmap.h>
 #include <syscon.h>
 #include <asm/arch-rockchip/clock.h>
 
@@ -25,6 +28,103 @@
 };
 
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
+#if IS_ENABLED(CONFIG_FDT_64BIT)
+struct rockchip_rk3288_noc_plat {
+	struct dtd_rockchip_rk3288_noc dtplat;
+};
+
+struct rockchip_rk3288_grf_plat {
+	struct dtd_rockchip_rk3288_grf dtplat;
+};
+
+struct rockchip_rk3288_sgrf_plat {
+	struct dtd_rockchip_rk3288_sgrf dtplat;
+};
+
+struct rockchip_rk3288_pmu_plat {
+	struct dtd_rockchip_rk3288_pmu dtplat;
+};
+
+static int rk3288_noc_bind_of_plat(struct udevice *dev)
+{
+	struct rockchip_rk3288_noc_plat *plat = dev_get_plat(dev);
+	struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
+	int size = dev->uclass->uc_drv->per_device_auto;
+
+	if (size && !priv) {
+		priv = calloc(1, size);
+		if (!priv)
+			return -ENOMEM;
+		dev_set_uclass_priv(dev, priv);
+	}
+
+	dev->driver_data = dev->driver->of_match->data;
+	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
+
+	return regmap_init_mem_plat(dev, plat->dtplat.reg, sizeof(plat->dtplat.reg[0]),
+				    ARRAY_SIZE(plat->dtplat.reg) / 2, &priv->regmap);
+}
+
+static int rk3288_grf_bind_of_plat(struct udevice *dev)
+{
+	struct rockchip_rk3288_grf_plat *plat = dev_get_plat(dev);
+	struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
+	int size = dev->uclass->uc_drv->per_device_auto;
+
+	if (size && !priv) {
+		priv = calloc(1, size);
+		if (!priv)
+			return -ENOMEM;
+		dev_set_uclass_priv(dev, priv);
+	}
+
+	dev->driver_data = dev->driver->of_match->data;
+	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
+
+	return regmap_init_mem_plat(dev, plat->dtplat.reg, sizeof(plat->dtplat.reg[0]),
+				    ARRAY_SIZE(plat->dtplat.reg) / 2, &priv->regmap);
+}
+
+static int rk3288_sgrf_bind_of_plat(struct udevice *dev)
+{
+	struct rockchip_rk3288_sgrf_plat *plat = dev_get_plat(dev);
+	struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
+	int size = dev->uclass->uc_drv->per_device_auto;
+
+	if (size && !priv) {
+		priv = calloc(1, size);
+		if (!priv)
+			return -ENOMEM;
+		dev_set_uclass_priv(dev, priv);
+	}
+
+	dev->driver_data = dev->driver->of_match->data;
+	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
+
+	return regmap_init_mem_plat(dev, plat->dtplat.reg, sizeof(plat->dtplat.reg[0]),
+				    ARRAY_SIZE(plat->dtplat.reg) / 2, &priv->regmap);
+}
+
+static int rk3288_pmu_bind_of_plat(struct udevice *dev)
+{
+	struct rockchip_rk3288_pmu_plat *plat = dev_get_plat(dev);
+	struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
+	int size = dev->uclass->uc_drv->per_device_auto;
+
+	if (size && !priv) {
+		priv = calloc(1, size);
+		if (!priv)
+			return -ENOMEM;
+		dev_set_uclass_priv(dev, priv);
+	}
+
+	dev->driver_data = dev->driver->of_match->data;
+	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
+
+	return regmap_init_mem_plat(dev, plat->dtplat.reg, sizeof(plat->dtplat.reg[0]),
+				    ARRAY_SIZE(plat->dtplat.reg) / 2, &priv->regmap);
+}
+#else
 static int rk3288_syscon_bind_of_plat(struct udevice *dev)
 {
 	dev->driver_data = dev->driver->of_match->data;
@@ -32,32 +132,53 @@
 
 	return 0;
 }
+#endif
 
 U_BOOT_DRIVER(rockchip_rk3288_noc) = {
 	.name = "rockchip_rk3288_noc",
 	.id = UCLASS_SYSCON,
 	.of_match = rk3288_syscon_ids,
+#if IS_ENABLED(CONFIG_FDT_64BIT)
+	.bind = rk3288_noc_bind_of_plat,
+	.plat_auto = sizeof(struct rockchip_rk3288_noc_plat),
+#else
 	.bind = rk3288_syscon_bind_of_plat,
+#endif
 };
 
 U_BOOT_DRIVER(rockchip_rk3288_grf) = {
 	.name = "rockchip_rk3288_grf",
 	.id = UCLASS_SYSCON,
 	.of_match = rk3288_syscon_ids + 1,
+#if IS_ENABLED(CONFIG_FDT_64BIT)
+	.bind = rk3288_grf_bind_of_plat,
+	.plat_auto = sizeof(struct rockchip_rk3288_grf_plat),
+#else
 	.bind = rk3288_syscon_bind_of_plat,
+#endif
 };
 
 U_BOOT_DRIVER(rockchip_rk3288_sgrf) = {
 	.name = "rockchip_rk3288_sgrf",
 	.id = UCLASS_SYSCON,
 	.of_match = rk3288_syscon_ids + 2,
+#if IS_ENABLED(CONFIG_FDT_64BIT)
+	.bind = rk3288_sgrf_bind_of_plat,
+	.plat_auto = sizeof(struct rockchip_rk3288_sgrf_plat),
+#else
 	.bind = rk3288_syscon_bind_of_plat,
+#endif
 };
 
 U_BOOT_DRIVER(rockchip_rk3288_pmu) = {
 	.name = "rockchip_rk3288_pmu",
 	.id = UCLASS_SYSCON,
 	.of_match = rk3288_syscon_ids + 3,
+#if IS_ENABLED(CONFIG_FDT_64BIT)
+	.bind = rk3288_pmu_bind_of_plat,
+	.plat_auto = sizeof(struct rockchip_rk3288_pmu_plat),
+#else
 	.bind = rk3288_syscon_bind_of_plat,
+#endif
 };
 #endif