1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Rockchip Generic Register Files setup
4 *
5 * Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de>
6 */
7
8 #include <linux/bitfield.h>
9 #include <linux/err.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/module.h>
12 #include <linux/of_device.h>
13 #include <linux/platform_device.h>
14 #include <linux/regmap.h>
15
16 struct rockchip_grf;
17
18 struct rockchip_grf_funcs {
19 int (*reset)(struct rockchip_grf *grf);
20 };
21
22 struct rockchip_grf {
23 struct regmap *regmap;
24 const struct rockchip_grf_funcs *funcs;
25 };
26
rockchip_edp_phy_grf_probe(struct platform_device * pdev)27 static int rockchip_edp_phy_grf_probe(struct platform_device *pdev)
28 {
29 struct device *dev = &pdev->dev;
30 struct rockchip_grf *grf;
31 int ret;
32
33 grf = devm_kzalloc(dev, sizeof(*grf), GFP_KERNEL);
34 if (!grf)
35 return -ENOMEM;
36
37 grf->funcs = of_device_get_match_data(dev);
38 if (!grf->funcs)
39 return -ENODEV;
40
41 grf->regmap = syscon_node_to_regmap(dev->of_node);
42 if (IS_ERR(grf->regmap)) {
43 ret = PTR_ERR(grf->regmap);
44 dev_err(dev, "failed to get grf: %d\n", ret);
45 return ret;
46 }
47
48 ret = grf->funcs->reset(grf);
49 if (ret)
50 return ret;
51
52 platform_set_drvdata(pdev, grf);
53
54 return 0;
55 }
56
rockchip_edp_phy_grf_resume(struct device * dev)57 static int __maybe_unused rockchip_edp_phy_grf_resume(struct device *dev)
58 {
59 struct rockchip_grf *grf = dev_get_drvdata(dev);
60
61 return grf->funcs->reset(grf);
62 }
63
64 static const struct dev_pm_ops rockchip_edp_phy_grf_pm_ops = {
65 SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, rockchip_edp_phy_grf_resume)
66 };
67
rk3568_edp_phy_grf_reset(struct rockchip_grf * grf)68 static int rk3568_edp_phy_grf_reset(struct rockchip_grf *grf)
69 {
70 u32 status;
71 int ret;
72
73 ret = regmap_read(grf->regmap, 0x0030, &status);
74 if (ret < 0)
75 return ret;
76
77 if (!FIELD_GET(0x1, status)) {
78 regmap_write(grf->regmap, 0x0028, 0x00070007);
79 regmap_write(grf->regmap, 0x0000, 0x0ff10ff1);
80 }
81
82 return 0;
83 }
84
85 static const struct rockchip_grf_funcs rk3568_edp_phy_grf_funcs = {
86 .reset = rk3568_edp_phy_grf_reset,
87 };
88
89 static const struct of_device_id rockchip_edp_phy_grf_match[] = {
90 {
91 .compatible = "rockchip,rk3568-edp-phy-grf",
92 .data = &rk3568_edp_phy_grf_funcs,
93 },
94 {}
95 };
96 MODULE_DEVICE_TABLE(of, rockchip_edp_phy_grf_match);
97
98 static struct platform_driver rockchip_edp_phy_grf_driver = {
99 .driver = {
100 .name = "rockchip-edp-phy-grf",
101 .of_match_table = rockchip_edp_phy_grf_match,
102 .pm = &rockchip_edp_phy_grf_pm_ops,
103 },
104 .probe = rockchip_edp_phy_grf_probe,
105 };
106
107 #define HIWORD_UPDATE(val, mask, shift) \
108 ((val) << (shift) | (mask) << ((shift) + 16))
109
110 struct rockchip_grf_value {
111 const char *desc;
112 u32 reg;
113 u32 val;
114 };
115
116 struct rockchip_grf_info {
117 const struct rockchip_grf_value *values;
118 int num_values;
119 };
120
121 #define PX30_GRF_SOC_CON5 0x414
122
123 static const struct rockchip_grf_value px30_defaults[] __initconst = {
124 /*
125 * Postponing auto jtag/sdmmc switching by 5 seconds.
126 * The counter value is calculated based on 24MHz clock.
127 */
128 { "jtag switching delay", PX30_GRF_SOC_CON5, 0x7270E00},
129 };
130
131 static const struct rockchip_grf_info px30_grf __initconst = {
132 .values = px30_defaults,
133 .num_values = ARRAY_SIZE(px30_defaults),
134 };
135
136 #define RK3036_GRF_SOC_CON0 0x140
137
138 static const struct rockchip_grf_value rk3036_defaults[] __initconst = {
139 /*
140 * Disable auto jtag/sdmmc switching that causes issues with the
141 * clock-framework and the mmc controllers making them unreliable.
142 */
143 { "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) },
144 };
145
146 static const struct rockchip_grf_info rk3036_grf __initconst = {
147 .values = rk3036_defaults,
148 .num_values = ARRAY_SIZE(rk3036_defaults),
149 };
150
151 #define RK3128_GRF_SOC_CON0 0x140
152
153 static const struct rockchip_grf_value rk3128_defaults[] __initconst = {
154 { "jtag switching", RK3128_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 8) },
155 };
156
157 static const struct rockchip_grf_info rk3128_grf __initconst = {
158 .values = rk3128_defaults,
159 .num_values = ARRAY_SIZE(rk3128_defaults),
160 };
161
162 #define RK3228_GRF_SOC_CON6 0x418
163
164 static const struct rockchip_grf_value rk3228_defaults[] __initconst = {
165 { "jtag switching", RK3228_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 8) },
166 };
167
168 static const struct rockchip_grf_info rk3228_grf __initconst = {
169 .values = rk3228_defaults,
170 .num_values = ARRAY_SIZE(rk3228_defaults),
171 };
172
173 #define RK3288_GRF_SOC_CON0 0x244
174 #define RK3288_GRF_SOC_CON2 0x24c
175
176 static const struct rockchip_grf_value rk3288_defaults[] __initconst = {
177 { "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) },
178 { "pwm select", RK3288_GRF_SOC_CON2, HIWORD_UPDATE(1, 1, 0) },
179 };
180
181 static const struct rockchip_grf_info rk3288_grf __initconst = {
182 .values = rk3288_defaults,
183 .num_values = ARRAY_SIZE(rk3288_defaults),
184 };
185
186 #define RK3328_GRF_SOC_CON4 0x410
187
188 static const struct rockchip_grf_value rk3328_defaults[] __initconst = {
189 { "jtag switching", RK3328_GRF_SOC_CON4, HIWORD_UPDATE(0, 1, 12) },
190 };
191
192 static const struct rockchip_grf_info rk3328_grf __initconst = {
193 .values = rk3328_defaults,
194 .num_values = ARRAY_SIZE(rk3328_defaults),
195 };
196
197 #define RK3308_GRF_SOC_CON3 0x30c
198 #define RK3308_GRF_SOC_CON13 0x608
199
200 static const struct rockchip_grf_value rk3308_defaults[] __initconst = {
201 { "uart dma mask", RK3308_GRF_SOC_CON3, HIWORD_UPDATE(0, 0x1f, 10) },
202 { "uart2 auto switching", RK3308_GRF_SOC_CON13, HIWORD_UPDATE(0, 0x1, 12) },
203 };
204
205 static const struct rockchip_grf_info rk3308_grf __initconst = {
206 .values = rk3308_defaults,
207 .num_values = ARRAY_SIZE(rk3308_defaults),
208 };
209
210 #define RK3368_GRF_SOC_CON15 0x43c
211
212 static const struct rockchip_grf_value rk3368_defaults[] __initconst = {
213 { "jtag switching", RK3368_GRF_SOC_CON15, HIWORD_UPDATE(0, 1, 13) },
214 };
215
216 static const struct rockchip_grf_info rk3368_grf __initconst = {
217 .values = rk3368_defaults,
218 .num_values = ARRAY_SIZE(rk3368_defaults),
219 };
220
221 #define RK3399_GRF_SOC_CON7 0xe21c
222
223 static const struct rockchip_grf_value rk3399_defaults[] __initconst = {
224 { "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) },
225 };
226
227 static const struct rockchip_grf_info rk3399_grf __initconst = {
228 .values = rk3399_defaults,
229 .num_values = ARRAY_SIZE(rk3399_defaults),
230 };
231
232 #define RK3588_SYS_GRF_SOC_CON7 0x031c
233
234 static const struct rockchip_grf_value rk3588_sys_grf_defaults[] __initconst = {
235 { "Connect EDP hpd to IO", RK3588_SYS_GRF_SOC_CON7, HIWORD_UPDATE(0x3, 0x3, 14) },
236 };
237
238 static const struct rockchip_grf_info rk3588_sys_grf __initconst = {
239 .values = rk3588_sys_grf_defaults,
240 .num_values = ARRAY_SIZE(rk3588_sys_grf_defaults),
241 };
242
243 #define DELAY_ONE_SECOND 0x16E3600
244
245 #define RV1126_GRF1_SDDETFLT_CON 0x10254
246 #define RV1126_GRF1_UART2RX_LOW_CON 0x10258
247 #define RV1126_GRF1_IOFUNC_CON1 0x10264
248 #define RV1126_GRF1_IOFUNC_CON3 0x1026C
249 #define RV1126_JTAG_GROUP0 0x0 /* mux to sdmmc*/
250 #define RV1126_JTAG_GROUP1 0x1 /* mux to uart2 */
251 #define FORCE_JTAG_ENABLE 0x1
252 #define FORCE_JTAG_DISABLE 0x0
253
254 static const struct rockchip_grf_value rv1126_defaults[] __initconst = {
255 { "jtag group0 force", RV1126_GRF1_IOFUNC_CON3,
256 HIWORD_UPDATE(FORCE_JTAG_DISABLE, 1, 4) },
257 { "jtag group1 force", RV1126_GRF1_IOFUNC_CON3,
258 HIWORD_UPDATE(FORCE_JTAG_DISABLE, 1, 5) },
259 { "jtag group1 tms low delay", RV1126_GRF1_UART2RX_LOW_CON, DELAY_ONE_SECOND },
260 { "switch to jtag groupx", RV1126_GRF1_IOFUNC_CON1, HIWORD_UPDATE(RV1126_JTAG_GROUP0, 1, 15) },
261 { "jtag group0 switching delay", RV1126_GRF1_SDDETFLT_CON, DELAY_ONE_SECOND * 5 },
262 };
263
264 static const struct rockchip_grf_info rv1126_grf __initconst = {
265 .values = rv1126_defaults,
266 .num_values = ARRAY_SIZE(rv1126_defaults),
267 };
268
269 static const struct of_device_id rockchip_grf_dt_match[] __initconst = {
270 {
271 .compatible = "rockchip,px30-grf",
272 .data = (void *)&px30_grf,
273 }, {
274 .compatible = "rockchip,rk3036-grf",
275 .data = (void *)&rk3036_grf,
276 }, {
277 .compatible = "rockchip,rk3128-grf",
278 .data = (void *)&rk3128_grf,
279 }, {
280 .compatible = "rockchip,rk3228-grf",
281 .data = (void *)&rk3228_grf,
282 }, {
283 .compatible = "rockchip,rk3288-grf",
284 .data = (void *)&rk3288_grf,
285 }, {
286 .compatible = "rockchip,rk3308-grf",
287 .data = (void *)&rk3308_grf,
288 }, {
289 .compatible = "rockchip,rk3328-grf",
290 .data = (void *)&rk3328_grf,
291 }, {
292 .compatible = "rockchip,rk3368-grf",
293 .data = (void *)&rk3368_grf,
294 }, {
295 .compatible = "rockchip,rk3399-grf",
296 .data = (void *)&rk3399_grf,
297 }, {
298 .compatible = "rockchip,rk3588-sys-grf",
299 .data = (void *)&rk3588_sys_grf,
300 }, {
301 .compatible = "rockchip,rv1126-grf",
302 .data = (void *)&rv1126_grf,
303 },
304 { /* sentinel */ },
305 };
306
rockchip_grf_init(void)307 static int __init rockchip_grf_init(void)
308 {
309 const struct rockchip_grf_info *grf_info;
310 const struct of_device_id *match;
311 struct device_node *np;
312 struct regmap *grf;
313 int ret, i;
314
315 ret = platform_driver_register(&rockchip_edp_phy_grf_driver);
316 if (ret)
317 return ret;
318
319 np = of_find_matching_node_and_match(NULL, rockchip_grf_dt_match,
320 &match);
321 if (!np)
322 return 0;
323 if (!match || !match->data) {
324 pr_err("%s: missing grf data\n", __func__);
325 of_node_put(np);
326 return -EINVAL;
327 }
328
329 grf_info = match->data;
330
331 grf = syscon_node_to_regmap(np);
332 of_node_put(np);
333 if (IS_ERR(grf)) {
334 pr_err("%s: could not get grf syscon\n", __func__);
335 return PTR_ERR(grf);
336 }
337
338 for (i = 0; i < grf_info->num_values; i++) {
339 const struct rockchip_grf_value *val = &grf_info->values[i];
340
341 pr_debug("%s: adjusting %s in %#6x to %#10x\n", __func__,
342 val->desc, val->reg, val->val);
343 ret = regmap_write(grf, val->reg, val->val);
344 if (ret < 0)
345 pr_err("%s: write to %#6x failed with %d\n",
346 __func__, val->reg, ret);
347 }
348
349 return 0;
350 }
351 postcore_initcall(rockchip_grf_init);
352
353 MODULE_DESCRIPTION("Rockchip GRF");
354 MODULE_LICENSE("GPL");
355