xref: /linux/drivers/pmdomain/ti/omap_prm.c (revision 418da6ee1ea62090f6b66d95b8fcf7db2f42c00f)
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