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