1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 
7 #include <common.h>
8 #include <dm.h>
9 #include <dt-structs.h>
10 #include <log.h>
11 #include <malloc.h>
12 #include <regmap.h>
13 #include <syscon.h>
14 #include <asm/arch-rockchip/clock.h>
15 
16 static const struct udevice_id rk3288_syscon_ids[] = {
17 	{ .compatible = "rockchip,rk3288-noc", .data = ROCKCHIP_SYSCON_NOC },
18 	{ .compatible = "rockchip,rk3288-grf", .data = ROCKCHIP_SYSCON_GRF },
19 	{ .compatible = "rockchip,rk3288-sgrf", .data = ROCKCHIP_SYSCON_SGRF },
20 	{ .compatible = "rockchip,rk3288-pmu", .data = ROCKCHIP_SYSCON_PMU },
21 	{ }
22 };
23 
24 U_BOOT_DRIVER(syscon_rk3288) = {
25 	.name = "rk3288_syscon",
26 	.id = UCLASS_SYSCON,
27 	.of_match = rk3288_syscon_ids,
28 };
29 
30 #if CONFIG_IS_ENABLED(OF_PLATDATA)
31 #if IS_ENABLED(CONFIG_FDT_64BIT)
32 struct rockchip_rk3288_noc_plat {
33 	struct dtd_rockchip_rk3288_noc dtplat;
34 };
35 
36 struct rockchip_rk3288_grf_plat {
37 	struct dtd_rockchip_rk3288_grf dtplat;
38 };
39 
40 struct rockchip_rk3288_sgrf_plat {
41 	struct dtd_rockchip_rk3288_sgrf dtplat;
42 };
43 
44 struct rockchip_rk3288_pmu_plat {
45 	struct dtd_rockchip_rk3288_pmu dtplat;
46 };
47 
rk3288_noc_bind_of_plat(struct udevice * dev)48 static int rk3288_noc_bind_of_plat(struct udevice *dev)
49 {
50 	struct rockchip_rk3288_noc_plat *plat = dev_get_plat(dev);
51 	struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
52 	int size = dev->uclass->uc_drv->per_device_auto;
53 
54 	if (size && !priv) {
55 		priv = calloc(1, size);
56 		if (!priv)
57 			return -ENOMEM;
58 		dev_set_uclass_priv(dev, priv);
59 	}
60 
61 	dev->driver_data = dev->driver->of_match->data;
62 	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
63 
64 	return regmap_init_mem_plat(dev, plat->dtplat.reg, sizeof(plat->dtplat.reg[0]),
65 				    ARRAY_SIZE(plat->dtplat.reg) / 2, &priv->regmap);
66 }
67 
rk3288_grf_bind_of_plat(struct udevice * dev)68 static int rk3288_grf_bind_of_plat(struct udevice *dev)
69 {
70 	struct rockchip_rk3288_grf_plat *plat = dev_get_plat(dev);
71 	struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
72 	int size = dev->uclass->uc_drv->per_device_auto;
73 
74 	if (size && !priv) {
75 		priv = calloc(1, size);
76 		if (!priv)
77 			return -ENOMEM;
78 		dev_set_uclass_priv(dev, priv);
79 	}
80 
81 	dev->driver_data = dev->driver->of_match->data;
82 	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
83 
84 	return regmap_init_mem_plat(dev, plat->dtplat.reg, sizeof(plat->dtplat.reg[0]),
85 				    ARRAY_SIZE(plat->dtplat.reg) / 2, &priv->regmap);
86 }
87 
rk3288_sgrf_bind_of_plat(struct udevice * dev)88 static int rk3288_sgrf_bind_of_plat(struct udevice *dev)
89 {
90 	struct rockchip_rk3288_sgrf_plat *plat = dev_get_plat(dev);
91 	struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
92 	int size = dev->uclass->uc_drv->per_device_auto;
93 
94 	if (size && !priv) {
95 		priv = calloc(1, size);
96 		if (!priv)
97 			return -ENOMEM;
98 		dev_set_uclass_priv(dev, priv);
99 	}
100 
101 	dev->driver_data = dev->driver->of_match->data;
102 	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
103 
104 	return regmap_init_mem_plat(dev, plat->dtplat.reg, sizeof(plat->dtplat.reg[0]),
105 				    ARRAY_SIZE(plat->dtplat.reg) / 2, &priv->regmap);
106 }
107 
rk3288_pmu_bind_of_plat(struct udevice * dev)108 static int rk3288_pmu_bind_of_plat(struct udevice *dev)
109 {
110 	struct rockchip_rk3288_pmu_plat *plat = dev_get_plat(dev);
111 	struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
112 	int size = dev->uclass->uc_drv->per_device_auto;
113 
114 	if (size && !priv) {
115 		priv = calloc(1, size);
116 		if (!priv)
117 			return -ENOMEM;
118 		dev_set_uclass_priv(dev, priv);
119 	}
120 
121 	dev->driver_data = dev->driver->of_match->data;
122 	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
123 
124 	return regmap_init_mem_plat(dev, plat->dtplat.reg, sizeof(plat->dtplat.reg[0]),
125 				    ARRAY_SIZE(plat->dtplat.reg) / 2, &priv->regmap);
126 }
127 #else
rk3288_syscon_bind_of_plat(struct udevice * dev)128 static int rk3288_syscon_bind_of_plat(struct udevice *dev)
129 {
130 	dev->driver_data = dev->driver->of_match->data;
131 	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
132 
133 	return 0;
134 }
135 #endif
136 
137 U_BOOT_DRIVER(rockchip_rk3288_noc) = {
138 	.name = "rockchip_rk3288_noc",
139 	.id = UCLASS_SYSCON,
140 	.of_match = rk3288_syscon_ids,
141 #if IS_ENABLED(CONFIG_FDT_64BIT)
142 	.bind = rk3288_noc_bind_of_plat,
143 	.plat_auto = sizeof(struct rockchip_rk3288_noc_plat),
144 #else
145 	.bind = rk3288_syscon_bind_of_plat,
146 #endif
147 };
148 
149 U_BOOT_DRIVER(rockchip_rk3288_grf) = {
150 	.name = "rockchip_rk3288_grf",
151 	.id = UCLASS_SYSCON,
152 	.of_match = rk3288_syscon_ids + 1,
153 #if IS_ENABLED(CONFIG_FDT_64BIT)
154 	.bind = rk3288_grf_bind_of_plat,
155 	.plat_auto = sizeof(struct rockchip_rk3288_grf_plat),
156 #else
157 	.bind = rk3288_syscon_bind_of_plat,
158 #endif
159 };
160 
161 U_BOOT_DRIVER(rockchip_rk3288_sgrf) = {
162 	.name = "rockchip_rk3288_sgrf",
163 	.id = UCLASS_SYSCON,
164 	.of_match = rk3288_syscon_ids + 2,
165 #if IS_ENABLED(CONFIG_FDT_64BIT)
166 	.bind = rk3288_sgrf_bind_of_plat,
167 	.plat_auto = sizeof(struct rockchip_rk3288_sgrf_plat),
168 #else
169 	.bind = rk3288_syscon_bind_of_plat,
170 #endif
171 };
172 
173 U_BOOT_DRIVER(rockchip_rk3288_pmu) = {
174 	.name = "rockchip_rk3288_pmu",
175 	.id = UCLASS_SYSCON,
176 	.of_match = rk3288_syscon_ids + 3,
177 #if IS_ENABLED(CONFIG_FDT_64BIT)
178 	.bind = rk3288_pmu_bind_of_plat,
179 	.plat_auto = sizeof(struct rockchip_rk3288_pmu_plat),
180 #else
181 	.bind = rk3288_syscon_bind_of_plat,
182 #endif
183 };
184 #endif
185