1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * OMAP2+ PRM driver
4 *
5 * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
6 * Tero Kristo <t-kristo@ti.com>
7 */
8
9 #include <linux/kernel.h>
10 #include <linux/clk.h>
11 #include <linux/device.h>
12 #include <linux/io.h>
13 #include <linux/iopoll.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_clock.h>
18 #include <linux/pm_domain.h>
19 #include <linux/reset-controller.h>
20 #include <linux/delay.h>
21 #if IS_ENABLED(CONFIG_SUSPEND)
22 #include <linux/suspend.h>
23 #endif
24 #include <linux/platform_data/ti-prm.h>
25
26 enum omap_prm_domain_mode {
27 OMAP_PRMD_OFF,
28 OMAP_PRMD_RETENTION,
29 OMAP_PRMD_ON_INACTIVE,
30 OMAP_PRMD_ON_ACTIVE,
31 };
32
33 struct omap_prm_domain_map {
34 unsigned int usable_modes; /* Mask of hardware supported modes */
35 unsigned long statechange:1; /* Optional low-power state change */
36 unsigned long logicretstate:1; /* Optional logic off mode */
37 };
38
39 struct omap_prm_domain {
40 struct device *dev;
41 struct omap_prm *prm;
42 struct generic_pm_domain pd;
43 u16 pwrstctrl;
44 u16 pwrstst;
45 const struct omap_prm_domain_map *cap;
46 u32 pwrstctrl_saved;
47 unsigned int uses_pm_clk:1;
48 };
49
50 struct omap_rst_map {
51 s8 rst;
52 s8 st;
53 };
54
55 struct omap_prm_data {
56 u32 base;
57 const char *name;
58 const char *clkdm_name;
59 u16 pwrstctrl;
60 u16 pwrstst;
61 const struct omap_prm_domain_map *dmap;
62 u16 rstctrl;
63 u16 rstst;
64 const struct omap_rst_map *rstmap;
65 u8 flags;
66 };
67
68 struct omap_prm {
69 const struct omap_prm_data *data;
70 void __iomem *base;
71 struct omap_prm_domain *prmd;
72 };
73
74 struct omap_reset_data {
75 struct reset_controller_dev rcdev;
76 struct omap_prm *prm;
77 u32 mask;
78 spinlock_t lock;
79 struct clockdomain *clkdm;
80 struct device *dev;
81 };
82
83 #define genpd_to_prm_domain(gpd) container_of(gpd, struct omap_prm_domain, pd)
84 #define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev)
85
86 #define OMAP_MAX_RESETS 8
87 #define OMAP_RESET_MAX_WAIT 10000
88
89 #define OMAP_PRM_HAS_RSTCTRL BIT(0)
90 #define OMAP_PRM_HAS_RSTST BIT(1)
91 #define OMAP_PRM_HAS_NO_CLKDM BIT(2)
92 #define OMAP_PRM_RET_WHEN_IDLE BIT(3)
93 #define OMAP_PRM_ON_WHEN_STANDBY BIT(4)
94
95 #define OMAP_PRM_HAS_RESETS (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST)
96
97 #define PRM_STATE_MAX_WAIT 10000
98 #define PRM_LOGICRETSTATE BIT(2)
99 #define PRM_LOWPOWERSTATECHANGE BIT(4)
100 #define PRM_POWERSTATE_MASK OMAP_PRMD_ON_ACTIVE
101
102 #define PRM_ST_INTRANSITION BIT(20)
103
104 static const struct omap_prm_domain_map omap_prm_all = {
105 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) |
106 BIT(OMAP_PRMD_RETENTION) | BIT(OMAP_PRMD_OFF),
107 .statechange = 1,
108 .logicretstate = 1,
109 };
110
111 static const struct omap_prm_domain_map omap_prm_noinact = {
112 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION) |
113 BIT(OMAP_PRMD_OFF),
114 .statechange = 1,
115 .logicretstate = 1,
116 };
117
118 static const struct omap_prm_domain_map omap_prm_nooff = {
119 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) |
120 BIT(OMAP_PRMD_RETENTION),
121 .statechange = 1,
122 .logicretstate = 1,
123 };
124
125 static const struct omap_prm_domain_map omap_prm_onoff_noauto = {
126 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_OFF),
127 .statechange = 1,
128 };
129
130 static const struct omap_prm_domain_map omap_prm_alwon = {
131 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE),
132 };
133
134 static const struct omap_prm_domain_map omap_prm_reton = {
135 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION),
136 .statechange = 1,
137 .logicretstate = 1,
138 };
139
140 static const struct omap_rst_map rst_map_0[] = {
141 { .rst = 0, .st = 0 },
142 { .rst = -1 },
143 };
144
145 static const struct omap_rst_map rst_map_01[] = {
146 { .rst = 0, .st = 0 },
147 { .rst = 1, .st = 1 },
148 { .rst = -1 },
149 };
150
151 static const struct omap_rst_map rst_map_012[] = {
152 { .rst = 0, .st = 0 },
153 { .rst = 1, .st = 1 },
154 { .rst = 2, .st = 2 },
155 { .rst = -1 },
156 };
157
158 static const struct omap_prm_data omap4_prm_data[] = {
159 {
160 .name = "mpu", .base = 0x4a306300,
161 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
162 },
163 {
164 .name = "tesla", .base = 0x4a306400,
165 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
166 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
167 },
168 {
169 .name = "abe", .base = 0x4a306500,
170 .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_all,
171 },
172 {
173 .name = "always_on_core", .base = 0x4a306600,
174 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
175 },
176 {
177 .name = "core", .base = 0x4a306700,
178 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
179 .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ducati",
180 .rstmap = rst_map_012,
181 .flags = OMAP_PRM_RET_WHEN_IDLE,
182 },
183 {
184 .name = "ivahd", .base = 0x4a306f00,
185 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
186 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012
187 },
188 {
189 .name = "cam", .base = 0x4a307000,
190 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
191 },
192 {
193 .name = "dss", .base = 0x4a307100,
194 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact
195 },
196 {
197 .name = "gfx", .base = 0x4a307200,
198 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
199 },
200 {
201 .name = "l3init", .base = 0x4a307300,
202 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton
203 },
204 {
205 .name = "l4per", .base = 0x4a307400,
206 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
207 .flags = OMAP_PRM_RET_WHEN_IDLE,
208 },
209 {
210 .name = "cefuse", .base = 0x4a307600,
211 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
212 },
213 {
214 .name = "wkup", .base = 0x4a307700,
215 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
216 },
217 {
218 .name = "emu", .base = 0x4a307900,
219 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
220 },
221 {
222 .name = "device", .base = 0x4a307b00,
223 .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01,
224 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
225 },
226 { },
227 };
228
229 static const struct omap_prm_data omap5_prm_data[] = {
230 {
231 .name = "mpu", .base = 0x4ae06300,
232 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
233 },
234 {
235 .name = "dsp", .base = 0x4ae06400,
236 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
237 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
238 },
239 {
240 .name = "abe", .base = 0x4ae06500,
241 .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_nooff,
242 },
243 {
244 .name = "coreaon", .base = 0x4ae06600,
245 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
246 },
247 {
248 .name = "core", .base = 0x4ae06700,
249 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
250 .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu",
251 .rstmap = rst_map_012
252 },
253 {
254 .name = "iva", .base = 0x4ae07200,
255 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
256 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012
257 },
258 {
259 .name = "cam", .base = 0x4ae07300,
260 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
261 },
262 {
263 .name = "dss", .base = 0x4ae07400,
264 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact
265 },
266 {
267 .name = "gpu", .base = 0x4ae07500,
268 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
269 },
270 {
271 .name = "l3init", .base = 0x4ae07600,
272 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton
273 },
274 {
275 .name = "custefuse", .base = 0x4ae07700,
276 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
277 },
278 {
279 .name = "wkupaon", .base = 0x4ae07800,
280 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
281 },
282 {
283 .name = "emu", .base = 0x4ae07a00,
284 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
285 },
286 {
287 .name = "device", .base = 0x4ae07c00,
288 .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01,
289 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
290 },
291 { },
292 };
293
294 static const struct omap_prm_data dra7_prm_data[] = {
295 {
296 .name = "mpu", .base = 0x4ae06300,
297 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
298 },
299 {
300 .name = "dsp1", .base = 0x4ae06400,
301 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
302 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01,
303 },
304 {
305 .name = "ipu", .base = 0x4ae06500,
306 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
307 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012,
308 .clkdm_name = "ipu1"
309 },
310 {
311 .name = "coreaon", .base = 0x4ae06628,
312 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
313 },
314 {
315 .name = "core", .base = 0x4ae06700,
316 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
317 .rstctrl = 0x210, .rstst = 0x214, .rstmap = rst_map_012,
318 .clkdm_name = "ipu2"
319 },
320 {
321 .name = "iva", .base = 0x4ae06f00,
322 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
323 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012,
324 },
325 {
326 .name = "cam", .base = 0x4ae07000,
327 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
328 },
329 {
330 .name = "dss", .base = 0x4ae07100,
331 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
332 },
333 {
334 .name = "gpu", .base = 0x4ae07200,
335 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
336 },
337 {
338 .name = "l3init", .base = 0x4ae07300,
339 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
340 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01,
341 .clkdm_name = "pcie"
342 },
343 {
344 .name = "l4per", .base = 0x4ae07400,
345 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
346 },
347 {
348 .name = "custefuse", .base = 0x4ae07600,
349 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
350 },
351 {
352 .name = "wkupaon", .base = 0x4ae07724,
353 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
354 },
355 {
356 .name = "emu", .base = 0x4ae07900,
357 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
358 },
359 {
360 .name = "dsp2", .base = 0x4ae07b00,
361 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
362 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
363 },
364 {
365 .name = "eve1", .base = 0x4ae07b40,
366 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
367 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
368 },
369 {
370 .name = "eve2", .base = 0x4ae07b80,
371 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
372 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
373 },
374 {
375 .name = "eve3", .base = 0x4ae07bc0,
376 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
377 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
378 },
379 {
380 .name = "eve4", .base = 0x4ae07c00,
381 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
382 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
383 },
384 {
385 .name = "rtc", .base = 0x4ae07c60,
386 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
387 },
388 {
389 .name = "vpe", .base = 0x4ae07c80,
390 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
391 },
392 { },
393 };
394
395 static const struct omap_rst_map am3_per_rst_map[] = {
396 { .rst = 1 },
397 { .rst = -1 },
398 };
399
400 static const struct omap_rst_map am3_wkup_rst_map[] = {
401 { .rst = 3, .st = 5 },
402 { .rst = -1 },
403 };
404
405 static const struct omap_prm_data am3_prm_data[] = {
406 {
407 .name = "per", .base = 0x44e00c00,
408 .pwrstctrl = 0xc, .pwrstst = 0x8, .dmap = &omap_prm_noinact,
409 .rstctrl = 0x0, .rstmap = am3_per_rst_map,
410 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_ON_WHEN_STANDBY,
411 .clkdm_name = "pruss_ocp",
412 },
413 {
414 .name = "wkup", .base = 0x44e00d00,
415 .pwrstctrl = 0x4, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
416 .rstctrl = 0x0, .rstst = 0xc, .rstmap = am3_wkup_rst_map,
417 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
418 },
419 {
420 .name = "mpu", .base = 0x44e00e00,
421 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
422 },
423 {
424 .name = "device", .base = 0x44e00f00,
425 .rstctrl = 0x0, .rstst = 0x8, .rstmap = rst_map_01,
426 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
427 },
428 {
429 .name = "rtc", .base = 0x44e01000,
430 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
431 },
432 {
433 .name = "gfx", .base = 0x44e01100,
434 .pwrstctrl = 0, .pwrstst = 0x10, .dmap = &omap_prm_noinact,
435 .rstctrl = 0x4, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3",
436 },
437 {
438 .name = "cefuse", .base = 0x44e01200,
439 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
440 },
441 { },
442 };
443
444 static const struct omap_rst_map am4_per_rst_map[] = {
445 { .rst = 1, .st = 0 },
446 { .rst = -1 },
447 };
448
449 static const struct omap_rst_map am4_device_rst_map[] = {
450 { .rst = 0, .st = 1 },
451 { .rst = 1, .st = 0 },
452 { .rst = -1 },
453 };
454
455 static const struct omap_prm_data am4_prm_data[] = {
456 {
457 .name = "mpu", .base = 0x44df0300,
458 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
459 },
460 {
461 .name = "gfx", .base = 0x44df0400,
462 .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
463 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3",
464 },
465 {
466 .name = "rtc", .base = 0x44df0500,
467 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
468 },
469 {
470 .name = "tamper", .base = 0x44df0600,
471 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
472 },
473 {
474 .name = "cefuse", .base = 0x44df0700,
475 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
476 },
477 {
478 .name = "per", .base = 0x44df0800,
479 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
480 .rstctrl = 0x10, .rstst = 0x14, .rstmap = am4_per_rst_map,
481 .clkdm_name = "pruss_ocp"
482 },
483 {
484 .name = "wkup", .base = 0x44df2000,
485 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
486 .rstctrl = 0x10, .rstst = 0x14, .rstmap = am3_wkup_rst_map,
487 .flags = OMAP_PRM_HAS_NO_CLKDM
488 },
489 {
490 .name = "device", .base = 0x44df4000,
491 .rstctrl = 0x0, .rstst = 0x4, .rstmap = am4_device_rst_map,
492 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
493 },
494 { },
495 };
496
497 static const struct of_device_id omap_prm_id_table[] = {
498 { .compatible = "ti,omap4-prm-inst", .data = omap4_prm_data },
499 { .compatible = "ti,omap5-prm-inst", .data = omap5_prm_data },
500 { .compatible = "ti,dra7-prm-inst", .data = dra7_prm_data },
501 { .compatible = "ti,am3-prm-inst", .data = am3_prm_data },
502 { .compatible = "ti,am4-prm-inst", .data = am4_prm_data },
503 { },
504 };
505
506 #ifdef DEBUG
omap_prm_domain_show_state(struct omap_prm_domain * prmd,const char * desc)507 static void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
508 const char *desc)
509 {
510 dev_dbg(prmd->dev, "%s %s: %08x/%08x\n",
511 prmd->pd.name, desc,
512 readl_relaxed(prmd->prm->base + prmd->pwrstctrl),
513 readl_relaxed(prmd->prm->base + prmd->pwrstst));
514 }
515 #else
omap_prm_domain_show_state(struct omap_prm_domain * prmd,const char * desc)516 static inline void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
517 const char *desc)
518 {
519 }
520 #endif
521
omap_prm_domain_power_on(struct generic_pm_domain * domain)522 static int omap_prm_domain_power_on(struct generic_pm_domain *domain)
523 {
524 struct omap_prm_domain *prmd;
525 int ret;
526 u32 v, mode;
527
528 prmd = genpd_to_prm_domain(domain);
529 if (!prmd->cap)
530 return 0;
531
532 omap_prm_domain_show_state(prmd, "on: previous state");
533
534 if (prmd->pwrstctrl_saved)
535 v = prmd->pwrstctrl_saved;
536 else
537 v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl);
538
539 if (prmd->prm->data->flags & OMAP_PRM_RET_WHEN_IDLE)
540 mode = OMAP_PRMD_RETENTION;
541 else
542 mode = OMAP_PRMD_ON_ACTIVE;
543
544 writel_relaxed((v & ~PRM_POWERSTATE_MASK) | mode,
545 prmd->prm->base + prmd->pwrstctrl);
546
547 /* wait for the transition bit to get cleared */
548 ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst,
549 v, !(v & PRM_ST_INTRANSITION), 1,
550 PRM_STATE_MAX_WAIT);
551 if (ret)
552 dev_err(prmd->dev, "%s: %s timed out\n",
553 prmd->pd.name, __func__);
554
555 omap_prm_domain_show_state(prmd, "on: new state");
556
557 return ret;
558 }
559
560 /* No need to check for holes in the mask for the lowest mode */
omap_prm_domain_find_lowest(struct omap_prm_domain * prmd)561 static int omap_prm_domain_find_lowest(struct omap_prm_domain *prmd)
562 {
563 return __ffs(prmd->cap->usable_modes);
564 }
565
omap_prm_domain_power_off(struct generic_pm_domain * domain)566 static int omap_prm_domain_power_off(struct generic_pm_domain *domain)
567 {
568 struct omap_prm_domain *prmd;
569 int ret;
570 u32 v;
571
572 prmd = genpd_to_prm_domain(domain);
573 if (!prmd->cap)
574 return 0;
575
576 omap_prm_domain_show_state(prmd, "off: previous state");
577
578 v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl);
579 prmd->pwrstctrl_saved = v;
580
581 v &= ~PRM_POWERSTATE_MASK;
582 v |= omap_prm_domain_find_lowest(prmd);
583
584 if (prmd->cap->statechange)
585 v |= PRM_LOWPOWERSTATECHANGE;
586 if (prmd->cap->logicretstate)
587 v &= ~PRM_LOGICRETSTATE;
588 else
589 v |= PRM_LOGICRETSTATE;
590
591 writel_relaxed(v, prmd->prm->base + prmd->pwrstctrl);
592
593 /* wait for the transition bit to get cleared */
594 ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst,
595 v, !(v & PRM_ST_INTRANSITION), 1,
596 PRM_STATE_MAX_WAIT);
597 if (ret)
598 dev_warn(prmd->dev, "%s: %s timed out\n",
599 __func__, prmd->pd.name);
600
601 omap_prm_domain_show_state(prmd, "off: new state");
602
603 return 0;
604 }
605
606 /*
607 * Note that ti-sysc already manages the module clocks separately so
608 * no need to manage those. Interconnect instances need clocks managed
609 * for simple-pm-bus.
610 */
omap_prm_domain_attach_clock(struct device * dev,struct omap_prm_domain * prmd)611 static int omap_prm_domain_attach_clock(struct device *dev,
612 struct omap_prm_domain *prmd)
613 {
614 struct device_node *np = dev->of_node;
615 int error;
616
617 if (!of_device_is_compatible(np, "simple-pm-bus"))
618 return 0;
619
620 if (!of_property_present(np, "clocks"))
621 return 0;
622
623 error = pm_clk_create(dev);
624 if (error)
625 return error;
626
627 error = of_pm_clk_add_clks(dev);
628 if (error < 0) {
629 pm_clk_destroy(dev);
630 return error;
631 }
632
633 prmd->uses_pm_clk = 1;
634
635 return 0;
636 }
637
omap_prm_domain_attach_dev(struct generic_pm_domain * domain,struct device * dev)638 static int omap_prm_domain_attach_dev(struct generic_pm_domain *domain,
639 struct device *dev)
640 {
641 struct generic_pm_domain_data *genpd_data;
642 struct of_phandle_args pd_args;
643 struct omap_prm_domain *prmd;
644 struct device_node *np;
645 int ret;
646
647 prmd = genpd_to_prm_domain(domain);
648 np = dev->of_node;
649
650 ret = of_parse_phandle_with_args(np, "power-domains",
651 "#power-domain-cells", 0, &pd_args);
652 if (ret < 0)
653 return ret;
654
655 if (pd_args.args_count != 0)
656 dev_warn(dev, "%s: unusupported #power-domain-cells: %i\n",
657 prmd->pd.name, pd_args.args_count);
658
659 genpd_data = dev_gpd_data(dev);
660 genpd_data->data = NULL;
661
662 ret = omap_prm_domain_attach_clock(dev, prmd);
663 if (ret)
664 return ret;
665
666 return 0;
667 }
668
omap_prm_domain_detach_dev(struct generic_pm_domain * domain,struct device * dev)669 static void omap_prm_domain_detach_dev(struct generic_pm_domain *domain,
670 struct device *dev)
671 {
672 struct generic_pm_domain_data *genpd_data;
673 struct omap_prm_domain *prmd;
674
675 prmd = genpd_to_prm_domain(domain);
676 if (prmd->uses_pm_clk)
677 pm_clk_destroy(dev);
678 genpd_data = dev_gpd_data(dev);
679 genpd_data->data = NULL;
680 }
681
omap_prm_domain_init(struct device * dev,struct omap_prm * prm)682 static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm)
683 {
684 struct omap_prm_domain *prmd;
685 struct device_node *np = dev->of_node;
686 const struct omap_prm_data *data;
687 const char *name;
688 int error;
689
690 if (!of_property_present(dev->of_node, "#power-domain-cells"))
691 return 0;
692
693 of_node_put(dev->of_node);
694
695 prmd = devm_kzalloc(dev, sizeof(*prmd), GFP_KERNEL);
696 if (!prmd)
697 return -ENOMEM;
698
699 data = prm->data;
700 name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s",
701 data->name);
702 if (!name)
703 return -ENOMEM;
704
705 prmd->dev = dev;
706 prmd->prm = prm;
707 prmd->cap = prmd->prm->data->dmap;
708 prmd->pwrstctrl = prmd->prm->data->pwrstctrl;
709 prmd->pwrstst = prmd->prm->data->pwrstst;
710
711 prmd->pd.name = name;
712 prmd->pd.power_on = omap_prm_domain_power_on;
713 prmd->pd.power_off = omap_prm_domain_power_off;
714 prmd->pd.attach_dev = omap_prm_domain_attach_dev;
715 prmd->pd.detach_dev = omap_prm_domain_detach_dev;
716 prmd->pd.flags = GENPD_FLAG_PM_CLK;
717
718 pm_genpd_init(&prmd->pd, NULL, true);
719 error = of_genpd_add_provider_simple(np, &prmd->pd);
720 if (error)
721 pm_genpd_remove(&prmd->pd);
722 else
723 prm->prmd = prmd;
724
725 return error;
726 }
727
_is_valid_reset(struct omap_reset_data * reset,unsigned long id)728 static bool _is_valid_reset(struct omap_reset_data *reset, unsigned long id)
729 {
730 if (reset->mask & BIT(id))
731 return true;
732
733 return false;
734 }
735
omap_reset_get_st_bit(struct omap_reset_data * reset,unsigned long id)736 static int omap_reset_get_st_bit(struct omap_reset_data *reset,
737 unsigned long id)
738 {
739 const struct omap_rst_map *map = reset->prm->data->rstmap;
740
741 while (map->rst >= 0) {
742 if (map->rst == id)
743 return map->st;
744
745 map++;
746 }
747
748 return id;
749 }
750
omap_reset_status(struct reset_controller_dev * rcdev,unsigned long id)751 static int omap_reset_status(struct reset_controller_dev *rcdev,
752 unsigned long id)
753 {
754 struct omap_reset_data *reset = to_omap_reset_data(rcdev);
755 u32 v;
756 int st_bit = omap_reset_get_st_bit(reset, id);
757 bool has_rstst = reset->prm->data->rstst ||
758 (reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
759
760 /* Check if we have rstst */
761 if (!has_rstst)
762 return -ENOTSUPP;
763
764 /* Check if hw reset line is asserted */
765 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
766 if (v & BIT(id))
767 return 1;
768
769 /*
770 * Check reset status, high value means reset sequence has been
771 * completed successfully so we can return 0 here (reset deasserted)
772 */
773 v = readl_relaxed(reset->prm->base + reset->prm->data->rstst);
774 v >>= st_bit;
775 v &= 1;
776
777 return !v;
778 }
779
omap_reset_assert(struct reset_controller_dev * rcdev,unsigned long id)780 static int omap_reset_assert(struct reset_controller_dev *rcdev,
781 unsigned long id)
782 {
783 struct omap_reset_data *reset = to_omap_reset_data(rcdev);
784 u32 v;
785 unsigned long flags;
786
787 /* assert the reset control line */
788 spin_lock_irqsave(&reset->lock, flags);
789 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
790 v |= 1 << id;
791 writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
792 spin_unlock_irqrestore(&reset->lock, flags);
793
794 return 0;
795 }
796
omap_reset_deassert(struct reset_controller_dev * rcdev,unsigned long id)797 static int omap_reset_deassert(struct reset_controller_dev *rcdev,
798 unsigned long id)
799 {
800 struct omap_reset_data *reset = to_omap_reset_data(rcdev);
801 u32 v;
802 int st_bit;
803 bool has_rstst;
804 unsigned long flags;
805 struct ti_prm_platform_data *pdata = dev_get_platdata(reset->dev);
806 int ret = 0;
807
808 /* Nothing to do if the reset is already deasserted */
809 if (!omap_reset_status(rcdev, id))
810 return 0;
811
812 has_rstst = reset->prm->data->rstst ||
813 (reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
814
815 if (has_rstst) {
816 st_bit = omap_reset_get_st_bit(reset, id);
817
818 /* Clear the reset status by writing 1 to the status bit */
819 v = 1 << st_bit;
820 writel_relaxed(v, reset->prm->base + reset->prm->data->rstst);
821 }
822
823 if (reset->clkdm)
824 pdata->clkdm_deny_idle(reset->clkdm);
825
826 /* de-assert the reset control line */
827 spin_lock_irqsave(&reset->lock, flags);
828 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
829 v &= ~(1 << id);
830 writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
831 spin_unlock_irqrestore(&reset->lock, flags);
832
833 /* wait for the reset bit to clear */
834 ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
835 reset->prm->data->rstctrl,
836 v, !(v & BIT(id)), 1,
837 OMAP_RESET_MAX_WAIT);
838 if (ret)
839 pr_err("%s: timedout waiting for %s:%lu\n", __func__,
840 reset->prm->data->name, id);
841
842 /* wait for the status to be set */
843 if (has_rstst) {
844 ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
845 reset->prm->data->rstst,
846 v, v & BIT(st_bit), 1,
847 OMAP_RESET_MAX_WAIT);
848 if (ret)
849 pr_err("%s: timedout waiting for %s:%lu\n", __func__,
850 reset->prm->data->name, id);
851 }
852
853 if (reset->clkdm)
854 pdata->clkdm_allow_idle(reset->clkdm);
855
856 return ret;
857 }
858
859 static const struct reset_control_ops omap_reset_ops = {
860 .assert = omap_reset_assert,
861 .deassert = omap_reset_deassert,
862 .status = omap_reset_status,
863 };
864
omap_prm_reset_xlate(struct reset_controller_dev * rcdev,const struct of_phandle_args * reset_spec)865 static int omap_prm_reset_xlate(struct reset_controller_dev *rcdev,
866 const struct of_phandle_args *reset_spec)
867 {
868 struct omap_reset_data *reset = to_omap_reset_data(rcdev);
869
870 if (!_is_valid_reset(reset, reset_spec->args[0]))
871 return -EINVAL;
872
873 return reset_spec->args[0];
874 }
875
omap_prm_reset_init(struct platform_device * pdev,struct omap_prm * prm)876 static int omap_prm_reset_init(struct platform_device *pdev,
877 struct omap_prm *prm)
878 {
879 struct omap_reset_data *reset;
880 const struct omap_rst_map *map;
881 struct ti_prm_platform_data *pdata = dev_get_platdata(&pdev->dev);
882 char buf[32];
883 u32 v;
884
885 /*
886 * Check if we have controllable resets. If either rstctrl is non-zero
887 * or OMAP_PRM_HAS_RSTCTRL flag is set, we have reset control register
888 * for the domain.
889 */
890 if (!prm->data->rstctrl && !(prm->data->flags & OMAP_PRM_HAS_RSTCTRL))
891 return 0;
892
893 /* Check if we have the pdata callbacks in place */
894 if (!pdata || !pdata->clkdm_lookup || !pdata->clkdm_deny_idle ||
895 !pdata->clkdm_allow_idle)
896 return -EINVAL;
897
898 map = prm->data->rstmap;
899 if (!map)
900 return -EINVAL;
901
902 reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
903 if (!reset)
904 return -ENOMEM;
905
906 reset->rcdev.owner = THIS_MODULE;
907 reset->rcdev.ops = &omap_reset_ops;
908 reset->rcdev.of_node = pdev->dev.of_node;
909 reset->rcdev.nr_resets = OMAP_MAX_RESETS;
910 reset->rcdev.of_xlate = omap_prm_reset_xlate;
911 reset->rcdev.of_reset_n_cells = 1;
912 reset->dev = &pdev->dev;
913 spin_lock_init(&reset->lock);
914
915 reset->prm = prm;
916
917 sprintf(buf, "%s_clkdm", prm->data->clkdm_name ? prm->data->clkdm_name :
918 prm->data->name);
919
920 if (!(prm->data->flags & OMAP_PRM_HAS_NO_CLKDM)) {
921 reset->clkdm = pdata->clkdm_lookup(buf);
922 if (!reset->clkdm)
923 return -EINVAL;
924 }
925
926 while (map->rst >= 0) {
927 reset->mask |= BIT(map->rst);
928 map++;
929 }
930
931 /* Quirk handling to assert rst_map_012 bits on reset and avoid errors */
932 if (prm->data->rstmap == rst_map_012) {
933 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
934 if ((v & reset->mask) != reset->mask) {
935 dev_dbg(&pdev->dev, "Asserting all resets: %08x\n", v);
936 writel_relaxed(reset->mask, reset->prm->base +
937 reset->prm->data->rstctrl);
938 }
939 }
940
941 return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
942 }
943
omap_prm_probe(struct platform_device * pdev)944 static int omap_prm_probe(struct platform_device *pdev)
945 {
946 struct resource *res;
947 const struct omap_prm_data *data;
948 struct omap_prm *prm;
949 int ret;
950
951 data = of_device_get_match_data(&pdev->dev);
952 if (!data)
953 return -ENOTSUPP;
954
955 prm = devm_kzalloc(&pdev->dev, sizeof(*prm), GFP_KERNEL);
956 if (!prm)
957 return -ENOMEM;
958
959 prm->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
960 if (IS_ERR(prm->base))
961 return PTR_ERR(prm->base);
962
963 while (data->base != res->start) {
964 if (!data->base)
965 return -EINVAL;
966 data++;
967 }
968
969 prm->data = data;
970
971 ret = omap_prm_domain_init(&pdev->dev, prm);
972 if (ret)
973 return ret;
974
975 ret = omap_prm_reset_init(pdev, prm);
976 if (ret)
977 goto err_domain;
978
979 return 0;
980
981 err_domain:
982 of_genpd_del_provider(pdev->dev.of_node);
983 pm_genpd_remove(&prm->prmd->pd);
984
985 return ret;
986 }
987
988 static struct platform_driver omap_prm_driver = {
989 .probe = omap_prm_probe,
990 .driver = {
991 .name = KBUILD_MODNAME,
992 .of_match_table = omap_prm_id_table,
993 },
994 };
995 builtin_platform_driver(omap_prm_driver);
996