xref: /linux/drivers/pmdomain/ti/omap_prm.c (revision cf1b04aaef8b83f668fac10bfc4d4d76ba6e6fa1)
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
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
516 static inline void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
517 					      const char *desc)
518 {
519 }
520 #endif
521 
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 */
561 static int omap_prm_domain_find_lowest(struct omap_prm_domain *prmd)
562 {
563 	return __ffs(prmd->cap->usable_modes);
564 }
565 
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  */
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 
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 	of_node_put(pd_args.np);
659 
660 	genpd_data = dev_gpd_data(dev);
661 	genpd_data->data = NULL;
662 
663 	ret = omap_prm_domain_attach_clock(dev, prmd);
664 	if (ret)
665 		return ret;
666 
667 	return 0;
668 }
669 
670 static void omap_prm_domain_detach_dev(struct generic_pm_domain *domain,
671 				       struct device *dev)
672 {
673 	struct generic_pm_domain_data *genpd_data;
674 	struct omap_prm_domain *prmd;
675 
676 	prmd = genpd_to_prm_domain(domain);
677 	if (prmd->uses_pm_clk)
678 		pm_clk_destroy(dev);
679 	genpd_data = dev_gpd_data(dev);
680 	genpd_data->data = NULL;
681 }
682 
683 static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm)
684 {
685 	struct omap_prm_domain *prmd;
686 	struct device_node *np = dev->of_node;
687 	const struct omap_prm_data *data;
688 	const char *name;
689 	int error;
690 
691 	if (!of_property_present(dev->of_node, "#power-domain-cells"))
692 		return 0;
693 
694 	of_node_put(dev->of_node);
695 
696 	prmd = devm_kzalloc(dev, sizeof(*prmd), GFP_KERNEL);
697 	if (!prmd)
698 		return -ENOMEM;
699 
700 	data = prm->data;
701 	name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s",
702 			      data->name);
703 	if (!name)
704 		return -ENOMEM;
705 
706 	prmd->dev = dev;
707 	prmd->prm = prm;
708 	prmd->cap = prmd->prm->data->dmap;
709 	prmd->pwrstctrl = prmd->prm->data->pwrstctrl;
710 	prmd->pwrstst = prmd->prm->data->pwrstst;
711 
712 	prmd->pd.name = name;
713 	prmd->pd.power_on = omap_prm_domain_power_on;
714 	prmd->pd.power_off = omap_prm_domain_power_off;
715 	prmd->pd.attach_dev = omap_prm_domain_attach_dev;
716 	prmd->pd.detach_dev = omap_prm_domain_detach_dev;
717 	prmd->pd.flags = GENPD_FLAG_PM_CLK;
718 
719 	pm_genpd_init(&prmd->pd, NULL, true);
720 	error = of_genpd_add_provider_simple(np, &prmd->pd);
721 	if (error)
722 		pm_genpd_remove(&prmd->pd);
723 	else
724 		prm->prmd = prmd;
725 
726 	return error;
727 }
728 
729 static bool _is_valid_reset(struct omap_reset_data *reset, unsigned long id)
730 {
731 	if (reset->mask & BIT(id))
732 		return true;
733 
734 	return false;
735 }
736 
737 static int omap_reset_get_st_bit(struct omap_reset_data *reset,
738 				 unsigned long id)
739 {
740 	const struct omap_rst_map *map = reset->prm->data->rstmap;
741 
742 	while (map->rst >= 0) {
743 		if (map->rst == id)
744 			return map->st;
745 
746 		map++;
747 	}
748 
749 	return id;
750 }
751 
752 static int omap_reset_status(struct reset_controller_dev *rcdev,
753 			     unsigned long id)
754 {
755 	struct omap_reset_data *reset = to_omap_reset_data(rcdev);
756 	u32 v;
757 	int st_bit = omap_reset_get_st_bit(reset, id);
758 	bool has_rstst = reset->prm->data->rstst ||
759 		(reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
760 
761 	/* Check if we have rstst */
762 	if (!has_rstst)
763 		return -ENOTSUPP;
764 
765 	/* Check if hw reset line is asserted */
766 	v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
767 	if (v & BIT(id))
768 		return 1;
769 
770 	/*
771 	 * Check reset status, high value means reset sequence has been
772 	 * completed successfully so we can return 0 here (reset deasserted)
773 	 */
774 	v = readl_relaxed(reset->prm->base + reset->prm->data->rstst);
775 	v >>= st_bit;
776 	v &= 1;
777 
778 	return !v;
779 }
780 
781 static int omap_reset_assert(struct reset_controller_dev *rcdev,
782 			     unsigned long id)
783 {
784 	struct omap_reset_data *reset = to_omap_reset_data(rcdev);
785 	u32 v;
786 	unsigned long flags;
787 
788 	/* assert the reset control line */
789 	spin_lock_irqsave(&reset->lock, flags);
790 	v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
791 	v |= 1 << id;
792 	writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
793 	spin_unlock_irqrestore(&reset->lock, flags);
794 
795 	return 0;
796 }
797 
798 static int omap_reset_deassert(struct reset_controller_dev *rcdev,
799 			       unsigned long id)
800 {
801 	struct omap_reset_data *reset = to_omap_reset_data(rcdev);
802 	u32 v;
803 	int st_bit;
804 	bool has_rstst;
805 	unsigned long flags;
806 	struct ti_prm_platform_data *pdata = dev_get_platdata(reset->dev);
807 	int ret = 0;
808 
809 	/* Nothing to do if the reset is already deasserted */
810 	if (!omap_reset_status(rcdev, id))
811 		return 0;
812 
813 	has_rstst = reset->prm->data->rstst ||
814 		(reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
815 
816 	if (has_rstst) {
817 		st_bit = omap_reset_get_st_bit(reset, id);
818 
819 		/* Clear the reset status by writing 1 to the status bit */
820 		v = 1 << st_bit;
821 		writel_relaxed(v, reset->prm->base + reset->prm->data->rstst);
822 	}
823 
824 	if (reset->clkdm)
825 		pdata->clkdm_deny_idle(reset->clkdm);
826 
827 	/* de-assert the reset control line */
828 	spin_lock_irqsave(&reset->lock, flags);
829 	v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
830 	v &= ~(1 << id);
831 	writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
832 	spin_unlock_irqrestore(&reset->lock, flags);
833 
834 	/* wait for the reset bit to clear */
835 	ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
836 						reset->prm->data->rstctrl,
837 						v, !(v & BIT(id)), 1,
838 						OMAP_RESET_MAX_WAIT);
839 	if (ret)
840 		pr_err("%s: timedout waiting for %s:%lu\n", __func__,
841 		       reset->prm->data->name, id);
842 
843 	/* wait for the status to be set */
844 	if (has_rstst) {
845 		ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
846 						 reset->prm->data->rstst,
847 						 v, v & BIT(st_bit), 1,
848 						 OMAP_RESET_MAX_WAIT);
849 		if (ret)
850 			pr_err("%s: timedout waiting for %s:%lu\n", __func__,
851 			       reset->prm->data->name, id);
852 	}
853 
854 	if (reset->clkdm)
855 		pdata->clkdm_allow_idle(reset->clkdm);
856 
857 	return ret;
858 }
859 
860 static const struct reset_control_ops omap_reset_ops = {
861 	.assert		= omap_reset_assert,
862 	.deassert	= omap_reset_deassert,
863 	.status		= omap_reset_status,
864 };
865 
866 static int omap_prm_reset_xlate(struct reset_controller_dev *rcdev,
867 				const struct of_phandle_args *reset_spec)
868 {
869 	struct omap_reset_data *reset = to_omap_reset_data(rcdev);
870 
871 	if (!_is_valid_reset(reset, reset_spec->args[0]))
872 		return -EINVAL;
873 
874 	return reset_spec->args[0];
875 }
876 
877 static int omap_prm_reset_init(struct platform_device *pdev,
878 			       struct omap_prm *prm)
879 {
880 	struct omap_reset_data *reset;
881 	const struct omap_rst_map *map;
882 	struct ti_prm_platform_data *pdata = dev_get_platdata(&pdev->dev);
883 	char buf[32];
884 	u32 v;
885 
886 	/*
887 	 * Check if we have controllable resets. If either rstctrl is non-zero
888 	 * or OMAP_PRM_HAS_RSTCTRL flag is set, we have reset control register
889 	 * for the domain.
890 	 */
891 	if (!prm->data->rstctrl && !(prm->data->flags & OMAP_PRM_HAS_RSTCTRL))
892 		return 0;
893 
894 	/* Check if we have the pdata callbacks in place */
895 	if (!pdata || !pdata->clkdm_lookup || !pdata->clkdm_deny_idle ||
896 	    !pdata->clkdm_allow_idle)
897 		return -EINVAL;
898 
899 	map = prm->data->rstmap;
900 	if (!map)
901 		return -EINVAL;
902 
903 	reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
904 	if (!reset)
905 		return -ENOMEM;
906 
907 	reset->rcdev.owner = THIS_MODULE;
908 	reset->rcdev.ops = &omap_reset_ops;
909 	reset->rcdev.of_node = pdev->dev.of_node;
910 	reset->rcdev.nr_resets = OMAP_MAX_RESETS;
911 	reset->rcdev.of_xlate = omap_prm_reset_xlate;
912 	reset->rcdev.of_reset_n_cells = 1;
913 	reset->dev = &pdev->dev;
914 	spin_lock_init(&reset->lock);
915 
916 	reset->prm = prm;
917 
918 	sprintf(buf, "%s_clkdm", prm->data->clkdm_name ? prm->data->clkdm_name :
919 		prm->data->name);
920 
921 	if (!(prm->data->flags & OMAP_PRM_HAS_NO_CLKDM)) {
922 		reset->clkdm = pdata->clkdm_lookup(buf);
923 		if (!reset->clkdm)
924 			return -EINVAL;
925 	}
926 
927 	while (map->rst >= 0) {
928 		reset->mask |= BIT(map->rst);
929 		map++;
930 	}
931 
932 	/* Quirk handling to assert rst_map_012 bits on reset and avoid errors */
933 	if (prm->data->rstmap == rst_map_012) {
934 		v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
935 		if ((v & reset->mask) != reset->mask) {
936 			dev_dbg(&pdev->dev, "Asserting all resets: %08x\n", v);
937 			writel_relaxed(reset->mask, reset->prm->base +
938 				       reset->prm->data->rstctrl);
939 		}
940 	}
941 
942 	return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
943 }
944 
945 static int omap_prm_probe(struct platform_device *pdev)
946 {
947 	struct resource *res;
948 	const struct omap_prm_data *data;
949 	struct omap_prm *prm;
950 	int ret;
951 
952 	data = of_device_get_match_data(&pdev->dev);
953 	if (!data)
954 		return -ENOTSUPP;
955 
956 	prm = devm_kzalloc(&pdev->dev, sizeof(*prm), GFP_KERNEL);
957 	if (!prm)
958 		return -ENOMEM;
959 
960 	prm->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
961 	if (IS_ERR(prm->base))
962 		return PTR_ERR(prm->base);
963 
964 	while (data->base != res->start) {
965 		if (!data->base)
966 			return -EINVAL;
967 		data++;
968 	}
969 
970 	prm->data = data;
971 
972 	ret = omap_prm_domain_init(&pdev->dev, prm);
973 	if (ret)
974 		return ret;
975 
976 	ret = omap_prm_reset_init(pdev, prm);
977 	if (ret)
978 		goto err_domain;
979 
980 	return 0;
981 
982 err_domain:
983 	of_genpd_del_provider(pdev->dev.of_node);
984 	pm_genpd_remove(&prm->prmd->pd);
985 
986 	return ret;
987 }
988 
989 static struct platform_driver omap_prm_driver = {
990 	.probe = omap_prm_probe,
991 	.driver = {
992 		.name		= KBUILD_MODNAME,
993 		.of_match_table	= omap_prm_id_table,
994 	},
995 };
996 builtin_platform_driver(omap_prm_driver);
997