1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
6 * Tero Kristo <t-kristo@ti.com>
9 #include <linux/kernel.h>
10 #include <linux/clk.h>
11 #include <linux/device.h>
13 #include <linux/iopoll.h>
14 #include <linux/module.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>
22 #include <linux/platform_data/ti-prm.h>
24 enum omap_prm_domain_mode
{
27 OMAP_PRMD_ON_INACTIVE
,
31 struct omap_prm_domain_map
{
32 unsigned int usable_modes
; /* Mask of hardware supported modes */
33 unsigned long statechange
:1; /* Optional low-power state change */
34 unsigned long logicretstate
:1; /* Optional logic off mode */
37 struct omap_prm_domain
{
40 struct generic_pm_domain pd
;
43 const struct omap_prm_domain_map
*cap
;
45 unsigned int uses_pm_clk
:1;
53 struct omap_prm_data
{
56 const char *clkdm_name
;
59 const struct omap_prm_domain_map
*dmap
;
62 const struct omap_rst_map
*rstmap
;
67 const struct omap_prm_data
*data
;
69 struct omap_prm_domain
*prmd
;
72 struct omap_reset_data
{
73 struct reset_controller_dev rcdev
;
77 struct clockdomain
*clkdm
;
81 #define genpd_to_prm_domain(gpd) container_of(gpd, struct omap_prm_domain, pd)
82 #define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev)
84 #define OMAP_MAX_RESETS 8
85 #define OMAP_RESET_MAX_WAIT 10000
87 #define OMAP_PRM_HAS_RSTCTRL BIT(0)
88 #define OMAP_PRM_HAS_RSTST BIT(1)
89 #define OMAP_PRM_HAS_NO_CLKDM BIT(2)
90 #define OMAP_PRM_RET_WHEN_IDLE BIT(3)
92 #define OMAP_PRM_HAS_RESETS (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST)
94 #define PRM_STATE_MAX_WAIT 10000
95 #define PRM_LOGICRETSTATE BIT(2)
96 #define PRM_LOWPOWERSTATECHANGE BIT(4)
97 #define PRM_POWERSTATE_MASK OMAP_PRMD_ON_ACTIVE
99 #define PRM_ST_INTRANSITION BIT(20)
101 static const struct omap_prm_domain_map omap_prm_all
= {
102 .usable_modes
= BIT(OMAP_PRMD_ON_ACTIVE
) | BIT(OMAP_PRMD_ON_INACTIVE
) |
103 BIT(OMAP_PRMD_RETENTION
) | BIT(OMAP_PRMD_OFF
),
108 static const struct omap_prm_domain_map omap_prm_noinact
= {
109 .usable_modes
= BIT(OMAP_PRMD_ON_ACTIVE
) | BIT(OMAP_PRMD_RETENTION
) |
115 static const struct omap_prm_domain_map omap_prm_nooff
= {
116 .usable_modes
= BIT(OMAP_PRMD_ON_ACTIVE
) | BIT(OMAP_PRMD_ON_INACTIVE
) |
117 BIT(OMAP_PRMD_RETENTION
),
122 static const struct omap_prm_domain_map omap_prm_onoff_noauto
= {
123 .usable_modes
= BIT(OMAP_PRMD_ON_ACTIVE
) | BIT(OMAP_PRMD_OFF
),
127 static const struct omap_prm_domain_map omap_prm_alwon
= {
128 .usable_modes
= BIT(OMAP_PRMD_ON_ACTIVE
),
131 static const struct omap_prm_domain_map omap_prm_reton
= {
132 .usable_modes
= BIT(OMAP_PRMD_ON_ACTIVE
) | BIT(OMAP_PRMD_RETENTION
),
137 static const struct omap_rst_map rst_map_0
[] = {
138 { .rst
= 0, .st
= 0 },
142 static const struct omap_rst_map rst_map_01
[] = {
143 { .rst
= 0, .st
= 0 },
144 { .rst
= 1, .st
= 1 },
148 static const struct omap_rst_map rst_map_012
[] = {
149 { .rst
= 0, .st
= 0 },
150 { .rst
= 1, .st
= 1 },
151 { .rst
= 2, .st
= 2 },
155 static const struct omap_prm_data omap4_prm_data
[] = {
157 .name
= "mpu", .base
= 0x4a306300,
158 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_reton
,
161 .name
= "tesla", .base
= 0x4a306400,
162 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_noinact
,
163 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_01
166 .name
= "abe", .base
= 0x4a306500,
167 .pwrstctrl
= 0, .pwrstst
= 0x4, .dmap
= &omap_prm_all
,
170 .name
= "always_on_core", .base
= 0x4a306600,
171 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
174 .name
= "core", .base
= 0x4a306700,
175 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_reton
,
176 .rstctrl
= 0x210, .rstst
= 0x214, .clkdm_name
= "ducati",
177 .rstmap
= rst_map_012
,
178 .flags
= OMAP_PRM_RET_WHEN_IDLE
,
181 .name
= "ivahd", .base
= 0x4a306f00,
182 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_noinact
,
183 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_012
186 .name
= "cam", .base
= 0x4a307000,
187 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
190 .name
= "dss", .base
= 0x4a307100,
191 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_noinact
194 .name
= "gfx", .base
= 0x4a307200,
195 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
198 .name
= "l3init", .base
= 0x4a307300,
199 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_reton
202 .name
= "l4per", .base
= 0x4a307400,
203 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_reton
,
204 .flags
= OMAP_PRM_RET_WHEN_IDLE
,
207 .name
= "cefuse", .base
= 0x4a307600,
208 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
211 .name
= "wkup", .base
= 0x4a307700,
212 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
215 .name
= "emu", .base
= 0x4a307900,
216 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
219 .name
= "device", .base
= 0x4a307b00,
220 .rstctrl
= 0x0, .rstst
= 0x4, .rstmap
= rst_map_01
,
221 .flags
= OMAP_PRM_HAS_RSTCTRL
| OMAP_PRM_HAS_NO_CLKDM
226 static const struct omap_prm_data omap5_prm_data
[] = {
228 .name
= "mpu", .base
= 0x4ae06300,
229 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_reton
,
232 .name
= "dsp", .base
= 0x4ae06400,
233 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_noinact
,
234 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_01
237 .name
= "abe", .base
= 0x4ae06500,
238 .pwrstctrl
= 0, .pwrstst
= 0x4, .dmap
= &omap_prm_nooff
,
241 .name
= "coreaon", .base
= 0x4ae06600,
242 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
245 .name
= "core", .base
= 0x4ae06700,
246 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_reton
,
247 .rstctrl
= 0x210, .rstst
= 0x214, .clkdm_name
= "ipu",
248 .rstmap
= rst_map_012
251 .name
= "iva", .base
= 0x4ae07200,
252 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_noinact
,
253 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_012
256 .name
= "cam", .base
= 0x4ae07300,
257 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
260 .name
= "dss", .base
= 0x4ae07400,
261 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_noinact
264 .name
= "gpu", .base
= 0x4ae07500,
265 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
268 .name
= "l3init", .base
= 0x4ae07600,
269 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_reton
272 .name
= "custefuse", .base
= 0x4ae07700,
273 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
276 .name
= "wkupaon", .base
= 0x4ae07800,
277 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
280 .name
= "emu", .base
= 0x4ae07a00,
281 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
284 .name
= "device", .base
= 0x4ae07c00,
285 .rstctrl
= 0x0, .rstst
= 0x4, .rstmap
= rst_map_01
,
286 .flags
= OMAP_PRM_HAS_RSTCTRL
| OMAP_PRM_HAS_NO_CLKDM
291 static const struct omap_prm_data dra7_prm_data
[] = {
293 .name
= "mpu", .base
= 0x4ae06300,
294 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_reton
,
297 .name
= "dsp1", .base
= 0x4ae06400,
298 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
299 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_01
,
302 .name
= "ipu", .base
= 0x4ae06500,
303 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
304 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_012
,
308 .name
= "coreaon", .base
= 0x4ae06628,
309 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
312 .name
= "core", .base
= 0x4ae06700,
313 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
314 .rstctrl
= 0x210, .rstst
= 0x214, .rstmap
= rst_map_012
,
318 .name
= "iva", .base
= 0x4ae06f00,
319 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
320 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_012
,
323 .name
= "cam", .base
= 0x4ae07000,
324 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
327 .name
= "dss", .base
= 0x4ae07100,
328 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
331 .name
= "gpu", .base
= 0x4ae07200,
332 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
335 .name
= "l3init", .base
= 0x4ae07300,
336 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
337 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_01
,
341 .name
= "l4per", .base
= 0x4ae07400,
342 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
345 .name
= "custefuse", .base
= 0x4ae07600,
346 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
349 .name
= "wkupaon", .base
= 0x4ae07724,
350 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
353 .name
= "emu", .base
= 0x4ae07900,
354 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
357 .name
= "dsp2", .base
= 0x4ae07b00,
358 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
359 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_01
362 .name
= "eve1", .base
= 0x4ae07b40,
363 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
364 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_01
367 .name
= "eve2", .base
= 0x4ae07b80,
368 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
369 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_01
372 .name
= "eve3", .base
= 0x4ae07bc0,
373 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
374 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_01
377 .name
= "eve4", .base
= 0x4ae07c00,
378 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
379 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_01
382 .name
= "rtc", .base
= 0x4ae07c60,
383 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
386 .name
= "vpe", .base
= 0x4ae07c80,
387 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
392 static const struct omap_rst_map am3_per_rst_map
[] = {
397 static const struct omap_rst_map am3_wkup_rst_map
[] = {
398 { .rst
= 3, .st
= 5 },
402 static const struct omap_prm_data am3_prm_data
[] = {
404 .name
= "per", .base
= 0x44e00c00,
405 .pwrstctrl
= 0xc, .pwrstst
= 0x8, .dmap
= &omap_prm_noinact
,
406 .rstctrl
= 0x0, .rstmap
= am3_per_rst_map
,
407 .flags
= OMAP_PRM_HAS_RSTCTRL
, .clkdm_name
= "pruss_ocp"
410 .name
= "wkup", .base
= 0x44e00d00,
411 .pwrstctrl
= 0x4, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
412 .rstctrl
= 0x0, .rstst
= 0xc, .rstmap
= am3_wkup_rst_map
,
413 .flags
= OMAP_PRM_HAS_RSTCTRL
| OMAP_PRM_HAS_NO_CLKDM
416 .name
= "mpu", .base
= 0x44e00e00,
417 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_noinact
,
420 .name
= "device", .base
= 0x44e00f00,
421 .rstctrl
= 0x0, .rstst
= 0x8, .rstmap
= rst_map_01
,
422 .flags
= OMAP_PRM_HAS_RSTCTRL
| OMAP_PRM_HAS_NO_CLKDM
425 .name
= "rtc", .base
= 0x44e01000,
426 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
429 .name
= "gfx", .base
= 0x44e01100,
430 .pwrstctrl
= 0, .pwrstst
= 0x10, .dmap
= &omap_prm_noinact
,
431 .rstctrl
= 0x4, .rstst
= 0x14, .rstmap
= rst_map_0
, .clkdm_name
= "gfx_l3",
434 .name
= "cefuse", .base
= 0x44e01200,
435 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
440 static const struct omap_rst_map am4_per_rst_map
[] = {
441 { .rst
= 1, .st
= 0 },
445 static const struct omap_rst_map am4_device_rst_map
[] = {
446 { .rst
= 0, .st
= 1 },
447 { .rst
= 1, .st
= 0 },
451 static const struct omap_prm_data am4_prm_data
[] = {
453 .name
= "mpu", .base
= 0x44df0300,
454 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_noinact
,
457 .name
= "gfx", .base
= 0x44df0400,
458 .pwrstctrl
= 0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
459 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= rst_map_0
, .clkdm_name
= "gfx_l3",
462 .name
= "rtc", .base
= 0x44df0500,
463 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
466 .name
= "tamper", .base
= 0x44df0600,
467 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
470 .name
= "cefuse", .base
= 0x44df0700,
471 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_onoff_noauto
,
474 .name
= "per", .base
= 0x44df0800,
475 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_noinact
,
476 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= am4_per_rst_map
,
477 .clkdm_name
= "pruss_ocp"
480 .name
= "wkup", .base
= 0x44df2000,
481 .pwrstctrl
= 0x0, .pwrstst
= 0x4, .dmap
= &omap_prm_alwon
,
482 .rstctrl
= 0x10, .rstst
= 0x14, .rstmap
= am3_wkup_rst_map
,
483 .flags
= OMAP_PRM_HAS_NO_CLKDM
486 .name
= "device", .base
= 0x44df4000,
487 .rstctrl
= 0x0, .rstst
= 0x4, .rstmap
= am4_device_rst_map
,
488 .flags
= OMAP_PRM_HAS_RSTCTRL
| OMAP_PRM_HAS_NO_CLKDM
493 static const struct of_device_id omap_prm_id_table
[] = {
494 { .compatible
= "ti,omap4-prm-inst", .data
= omap4_prm_data
},
495 { .compatible
= "ti,omap5-prm-inst", .data
= omap5_prm_data
},
496 { .compatible
= "ti,dra7-prm-inst", .data
= dra7_prm_data
},
497 { .compatible
= "ti,am3-prm-inst", .data
= am3_prm_data
},
498 { .compatible
= "ti,am4-prm-inst", .data
= am4_prm_data
},
503 static void omap_prm_domain_show_state(struct omap_prm_domain
*prmd
,
506 dev_dbg(prmd
->dev
, "%s %s: %08x/%08x\n",
508 readl_relaxed(prmd
->prm
->base
+ prmd
->pwrstctrl
),
509 readl_relaxed(prmd
->prm
->base
+ prmd
->pwrstst
));
512 static inline void omap_prm_domain_show_state(struct omap_prm_domain
*prmd
,
518 static int omap_prm_domain_power_on(struct generic_pm_domain
*domain
)
520 struct omap_prm_domain
*prmd
;
524 prmd
= genpd_to_prm_domain(domain
);
528 omap_prm_domain_show_state(prmd
, "on: previous state");
530 if (prmd
->pwrstctrl_saved
)
531 v
= prmd
->pwrstctrl_saved
;
533 v
= readl_relaxed(prmd
->prm
->base
+ prmd
->pwrstctrl
);
535 if (prmd
->prm
->data
->flags
& OMAP_PRM_RET_WHEN_IDLE
)
536 mode
= OMAP_PRMD_RETENTION
;
538 mode
= OMAP_PRMD_ON_ACTIVE
;
540 writel_relaxed((v
& ~PRM_POWERSTATE_MASK
) | mode
,
541 prmd
->prm
->base
+ prmd
->pwrstctrl
);
543 /* wait for the transition bit to get cleared */
544 ret
= readl_relaxed_poll_timeout(prmd
->prm
->base
+ prmd
->pwrstst
,
545 v
, !(v
& PRM_ST_INTRANSITION
), 1,
548 dev_err(prmd
->dev
, "%s: %s timed out\n",
549 prmd
->pd
.name
, __func__
);
551 omap_prm_domain_show_state(prmd
, "on: new state");
556 /* No need to check for holes in the mask for the lowest mode */
557 static int omap_prm_domain_find_lowest(struct omap_prm_domain
*prmd
)
559 return __ffs(prmd
->cap
->usable_modes
);
562 static int omap_prm_domain_power_off(struct generic_pm_domain
*domain
)
564 struct omap_prm_domain
*prmd
;
568 prmd
= genpd_to_prm_domain(domain
);
572 omap_prm_domain_show_state(prmd
, "off: previous state");
574 v
= readl_relaxed(prmd
->prm
->base
+ prmd
->pwrstctrl
);
575 prmd
->pwrstctrl_saved
= v
;
577 v
&= ~PRM_POWERSTATE_MASK
;
578 v
|= omap_prm_domain_find_lowest(prmd
);
580 if (prmd
->cap
->statechange
)
581 v
|= PRM_LOWPOWERSTATECHANGE
;
582 if (prmd
->cap
->logicretstate
)
583 v
&= ~PRM_LOGICRETSTATE
;
585 v
|= PRM_LOGICRETSTATE
;
587 writel_relaxed(v
, prmd
->prm
->base
+ prmd
->pwrstctrl
);
589 /* wait for the transition bit to get cleared */
590 ret
= readl_relaxed_poll_timeout(prmd
->prm
->base
+ prmd
->pwrstst
,
591 v
, !(v
& PRM_ST_INTRANSITION
), 1,
594 dev_warn(prmd
->dev
, "%s: %s timed out\n",
595 __func__
, prmd
->pd
.name
);
597 omap_prm_domain_show_state(prmd
, "off: new state");
603 * Note that ti-sysc already manages the module clocks separately so
604 * no need to manage those. Interconnect instances need clocks managed
607 static int omap_prm_domain_attach_clock(struct device
*dev
,
608 struct omap_prm_domain
*prmd
)
610 struct device_node
*np
= dev
->of_node
;
613 if (!of_device_is_compatible(np
, "simple-pm-bus"))
616 if (!of_property_read_bool(np
, "clocks"))
619 error
= pm_clk_create(dev
);
623 error
= of_pm_clk_add_clks(dev
);
629 prmd
->uses_pm_clk
= 1;
634 static int omap_prm_domain_attach_dev(struct generic_pm_domain
*domain
,
637 struct generic_pm_domain_data
*genpd_data
;
638 struct of_phandle_args pd_args
;
639 struct omap_prm_domain
*prmd
;
640 struct device_node
*np
;
643 prmd
= genpd_to_prm_domain(domain
);
646 ret
= of_parse_phandle_with_args(np
, "power-domains",
647 "#power-domain-cells", 0, &pd_args
);
651 if (pd_args
.args_count
!= 0)
652 dev_warn(dev
, "%s: unusupported #power-domain-cells: %i\n",
653 prmd
->pd
.name
, pd_args
.args_count
);
655 genpd_data
= dev_gpd_data(dev
);
656 genpd_data
->data
= NULL
;
658 ret
= omap_prm_domain_attach_clock(dev
, prmd
);
665 static void omap_prm_domain_detach_dev(struct generic_pm_domain
*domain
,
668 struct generic_pm_domain_data
*genpd_data
;
669 struct omap_prm_domain
*prmd
;
671 prmd
= genpd_to_prm_domain(domain
);
672 if (prmd
->uses_pm_clk
)
674 genpd_data
= dev_gpd_data(dev
);
675 genpd_data
->data
= NULL
;
678 static int omap_prm_domain_init(struct device
*dev
, struct omap_prm
*prm
)
680 struct omap_prm_domain
*prmd
;
681 struct device_node
*np
= dev
->of_node
;
682 const struct omap_prm_data
*data
;
686 if (!of_property_present(dev
->of_node
, "#power-domain-cells"))
689 of_node_put(dev
->of_node
);
691 prmd
= devm_kzalloc(dev
, sizeof(*prmd
), GFP_KERNEL
);
696 name
= devm_kasprintf(dev
, GFP_KERNEL
, "prm_%s",
703 prmd
->cap
= prmd
->prm
->data
->dmap
;
704 prmd
->pwrstctrl
= prmd
->prm
->data
->pwrstctrl
;
705 prmd
->pwrstst
= prmd
->prm
->data
->pwrstst
;
707 prmd
->pd
.name
= name
;
708 prmd
->pd
.power_on
= omap_prm_domain_power_on
;
709 prmd
->pd
.power_off
= omap_prm_domain_power_off
;
710 prmd
->pd
.attach_dev
= omap_prm_domain_attach_dev
;
711 prmd
->pd
.detach_dev
= omap_prm_domain_detach_dev
;
712 prmd
->pd
.flags
= GENPD_FLAG_PM_CLK
;
714 pm_genpd_init(&prmd
->pd
, NULL
, true);
715 error
= of_genpd_add_provider_simple(np
, &prmd
->pd
);
717 pm_genpd_remove(&prmd
->pd
);
724 static bool _is_valid_reset(struct omap_reset_data
*reset
, unsigned long id
)
726 if (reset
->mask
& BIT(id
))
732 static int omap_reset_get_st_bit(struct omap_reset_data
*reset
,
735 const struct omap_rst_map
*map
= reset
->prm
->data
->rstmap
;
737 while (map
->rst
>= 0) {
747 static int omap_reset_status(struct reset_controller_dev
*rcdev
,
750 struct omap_reset_data
*reset
= to_omap_reset_data(rcdev
);
752 int st_bit
= omap_reset_get_st_bit(reset
, id
);
753 bool has_rstst
= reset
->prm
->data
->rstst
||
754 (reset
->prm
->data
->flags
& OMAP_PRM_HAS_RSTST
);
756 /* Check if we have rstst */
760 /* Check if hw reset line is asserted */
761 v
= readl_relaxed(reset
->prm
->base
+ reset
->prm
->data
->rstctrl
);
766 * Check reset status, high value means reset sequence has been
767 * completed successfully so we can return 0 here (reset deasserted)
769 v
= readl_relaxed(reset
->prm
->base
+ reset
->prm
->data
->rstst
);
776 static int omap_reset_assert(struct reset_controller_dev
*rcdev
,
779 struct omap_reset_data
*reset
= to_omap_reset_data(rcdev
);
783 /* assert the reset control line */
784 spin_lock_irqsave(&reset
->lock
, flags
);
785 v
= readl_relaxed(reset
->prm
->base
+ reset
->prm
->data
->rstctrl
);
787 writel_relaxed(v
, reset
->prm
->base
+ reset
->prm
->data
->rstctrl
);
788 spin_unlock_irqrestore(&reset
->lock
, flags
);
793 static int omap_reset_deassert(struct reset_controller_dev
*rcdev
,
796 struct omap_reset_data
*reset
= to_omap_reset_data(rcdev
);
801 struct ti_prm_platform_data
*pdata
= dev_get_platdata(reset
->dev
);
804 /* Nothing to do if the reset is already deasserted */
805 if (!omap_reset_status(rcdev
, id
))
808 has_rstst
= reset
->prm
->data
->rstst
||
809 (reset
->prm
->data
->flags
& OMAP_PRM_HAS_RSTST
);
812 st_bit
= omap_reset_get_st_bit(reset
, id
);
814 /* Clear the reset status by writing 1 to the status bit */
816 writel_relaxed(v
, reset
->prm
->base
+ reset
->prm
->data
->rstst
);
820 pdata
->clkdm_deny_idle(reset
->clkdm
);
822 /* de-assert the reset control line */
823 spin_lock_irqsave(&reset
->lock
, flags
);
824 v
= readl_relaxed(reset
->prm
->base
+ reset
->prm
->data
->rstctrl
);
826 writel_relaxed(v
, reset
->prm
->base
+ reset
->prm
->data
->rstctrl
);
827 spin_unlock_irqrestore(&reset
->lock
, flags
);
829 /* wait for the reset bit to clear */
830 ret
= readl_relaxed_poll_timeout_atomic(reset
->prm
->base
+
831 reset
->prm
->data
->rstctrl
,
832 v
, !(v
& BIT(id
)), 1,
833 OMAP_RESET_MAX_WAIT
);
835 pr_err("%s: timedout waiting for %s:%lu\n", __func__
,
836 reset
->prm
->data
->name
, id
);
838 /* wait for the status to be set */
840 ret
= readl_relaxed_poll_timeout_atomic(reset
->prm
->base
+
841 reset
->prm
->data
->rstst
,
842 v
, v
& BIT(st_bit
), 1,
843 OMAP_RESET_MAX_WAIT
);
845 pr_err("%s: timedout waiting for %s:%lu\n", __func__
,
846 reset
->prm
->data
->name
, id
);
850 pdata
->clkdm_allow_idle(reset
->clkdm
);
855 static const struct reset_control_ops omap_reset_ops
= {
856 .assert = omap_reset_assert
,
857 .deassert
= omap_reset_deassert
,
858 .status
= omap_reset_status
,
861 static int omap_prm_reset_xlate(struct reset_controller_dev
*rcdev
,
862 const struct of_phandle_args
*reset_spec
)
864 struct omap_reset_data
*reset
= to_omap_reset_data(rcdev
);
866 if (!_is_valid_reset(reset
, reset_spec
->args
[0]))
869 return reset_spec
->args
[0];
872 static int omap_prm_reset_init(struct platform_device
*pdev
,
873 struct omap_prm
*prm
)
875 struct omap_reset_data
*reset
;
876 const struct omap_rst_map
*map
;
877 struct ti_prm_platform_data
*pdata
= dev_get_platdata(&pdev
->dev
);
882 * Check if we have controllable resets. If either rstctrl is non-zero
883 * or OMAP_PRM_HAS_RSTCTRL flag is set, we have reset control register
886 if (!prm
->data
->rstctrl
&& !(prm
->data
->flags
& OMAP_PRM_HAS_RSTCTRL
))
889 /* Check if we have the pdata callbacks in place */
890 if (!pdata
|| !pdata
->clkdm_lookup
|| !pdata
->clkdm_deny_idle
||
891 !pdata
->clkdm_allow_idle
)
894 map
= prm
->data
->rstmap
;
898 reset
= devm_kzalloc(&pdev
->dev
, sizeof(*reset
), GFP_KERNEL
);
902 reset
->rcdev
.owner
= THIS_MODULE
;
903 reset
->rcdev
.ops
= &omap_reset_ops
;
904 reset
->rcdev
.of_node
= pdev
->dev
.of_node
;
905 reset
->rcdev
.nr_resets
= OMAP_MAX_RESETS
;
906 reset
->rcdev
.of_xlate
= omap_prm_reset_xlate
;
907 reset
->rcdev
.of_reset_n_cells
= 1;
908 reset
->dev
= &pdev
->dev
;
909 spin_lock_init(&reset
->lock
);
913 sprintf(buf
, "%s_clkdm", prm
->data
->clkdm_name
? prm
->data
->clkdm_name
:
916 if (!(prm
->data
->flags
& OMAP_PRM_HAS_NO_CLKDM
)) {
917 reset
->clkdm
= pdata
->clkdm_lookup(buf
);
922 while (map
->rst
>= 0) {
923 reset
->mask
|= BIT(map
->rst
);
927 /* Quirk handling to assert rst_map_012 bits on reset and avoid errors */
928 if (prm
->data
->rstmap
== rst_map_012
) {
929 v
= readl_relaxed(reset
->prm
->base
+ reset
->prm
->data
->rstctrl
);
930 if ((v
& reset
->mask
) != reset
->mask
) {
931 dev_dbg(&pdev
->dev
, "Asserting all resets: %08x\n", v
);
932 writel_relaxed(reset
->mask
, reset
->prm
->base
+
933 reset
->prm
->data
->rstctrl
);
937 return devm_reset_controller_register(&pdev
->dev
, &reset
->rcdev
);
940 static int omap_prm_probe(struct platform_device
*pdev
)
942 struct resource
*res
;
943 const struct omap_prm_data
*data
;
944 struct omap_prm
*prm
;
947 data
= of_device_get_match_data(&pdev
->dev
);
951 prm
= devm_kzalloc(&pdev
->dev
, sizeof(*prm
), GFP_KERNEL
);
955 prm
->base
= devm_platform_get_and_ioremap_resource(pdev
, 0, &res
);
956 if (IS_ERR(prm
->base
))
957 return PTR_ERR(prm
->base
);
959 while (data
->base
!= res
->start
) {
967 ret
= omap_prm_domain_init(&pdev
->dev
, prm
);
971 ret
= omap_prm_reset_init(pdev
, prm
);
978 of_genpd_del_provider(pdev
->dev
.of_node
);
979 pm_genpd_remove(&prm
->prmd
->pd
);
984 static struct platform_driver omap_prm_driver
= {
985 .probe
= omap_prm_probe
,
987 .name
= KBUILD_MODNAME
,
988 .of_match_table
= omap_prm_id_table
,
991 builtin_platform_driver(omap_prm_driver
);