aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap2/cminst44xx.c25
-rw-r--r--arch/arm/mach-omap2/cminst44xx.h1
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c40
3 files changed, 66 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index 9033dd4937c1..0fe3f147f262 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -284,3 +284,28 @@ int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs,
284 return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; 284 return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
285} 285}
286 286
287/**
288 * omap4_cminst_wait_module_idle - wait for a module to be in 'disabled'
289 * state
290 * @part: PRCM partition ID that the CM_CLKCTRL register exists in
291 * @inst: CM instance register offset (*_INST macro)
292 * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
293 * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
294 *
295 * Wait for the module IDLEST to be disabled. Some PRCM transition,
296 * like reset assertion or parent clock de-activation must wait the
297 * module to be fully disabled.
298 */
299int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
300{
301 int i = 0;
302
303 if (!clkctrl_offs)
304 return 0;
305
306 omap_test_timeout((_clkctrl_idlest(part, inst, cdoffs, clkctrl_offs) ==
307 CLKCTRL_IDLEST_DISABLED),
308 MAX_MODULE_READY_TIME, i);
309
310 return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
311}
diff --git a/arch/arm/mach-omap2/cminst44xx.h b/arch/arm/mach-omap2/cminst44xx.h
index 8eba2ae87ad4..a98540081f97 100644
--- a/arch/arm/mach-omap2/cminst44xx.h
+++ b/arch/arm/mach-omap2/cminst44xx.h
@@ -18,6 +18,7 @@ extern void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs);
18extern void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs); 18extern void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs);
19 19
20extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs); 20extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
21extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
21 22
22/* 23/*
23 * In an ideal world, we would not export these low-level functions, 24 * In an ideal world, we would not export these low-level functions,
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 00241ea5bf09..d21f49b87646 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1102,6 +1102,36 @@ static int _wait_target_ready(struct omap_hwmod *oh)
1102} 1102}
1103 1103
1104/** 1104/**
1105 * _wait_target_disable - wait for a module to be disabled
1106 * @oh: struct omap_hwmod *
1107 *
1108 * Wait for a module @oh to enter slave idle. Returns 0 if the module
1109 * does not have an IDLEST bit or if the module successfully enters
1110 * slave idle; otherwise, pass along the return value of the
1111 * appropriate *_cm*_wait_module_idle() function.
1112 */
1113static int _wait_target_disable(struct omap_hwmod *oh)
1114{
1115 /* TODO: For now just handle OMAP4+ */
1116 if (cpu_is_omap24xx() || cpu_is_omap34xx())
1117 return 0;
1118
1119 if (!oh)
1120 return -EINVAL;
1121
1122 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
1123 return 0;
1124
1125 if (oh->flags & HWMOD_NO_IDLEST)
1126 return 0;
1127
1128 return omap4_cminst_wait_module_idle(oh->clkdm->prcm_partition,
1129 oh->clkdm->cm_inst,
1130 oh->clkdm->clkdm_offs,
1131 oh->prcm.omap4.clkctrl_offs);
1132}
1133
1134/**
1105 * _lookup_hardreset - fill register bit info for this hwmod/reset line 1135 * _lookup_hardreset - fill register bit info for this hwmod/reset line
1106 * @oh: struct omap_hwmod * 1136 * @oh: struct omap_hwmod *
1107 * @name: name of the reset line in the context of this hwmod 1137 * @name: name of the reset line in the context of this hwmod
@@ -1410,6 +1440,8 @@ static int _enable(struct omap_hwmod *oh)
1410 */ 1440 */
1411static int _idle(struct omap_hwmod *oh) 1441static int _idle(struct omap_hwmod *oh)
1412{ 1442{
1443 int ret;
1444
1413 pr_debug("omap_hwmod: %s: idling\n", oh->name); 1445 pr_debug("omap_hwmod: %s: idling\n", oh->name);
1414 1446
1415 if (oh->_state != _HWMOD_STATE_ENABLED) { 1447 if (oh->_state != _HWMOD_STATE_ENABLED) {
@@ -1422,6 +1454,10 @@ static int _idle(struct omap_hwmod *oh)
1422 _idle_sysc(oh); 1454 _idle_sysc(oh);
1423 _del_initiator_dep(oh, mpu_oh); 1455 _del_initiator_dep(oh, mpu_oh);
1424 _disable_clocks(oh); 1456 _disable_clocks(oh);
1457 ret = _wait_target_disable(oh);
1458 if (ret)
1459 pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
1460 oh->name);
1425 1461
1426 /* Mux pins for device idle if populated */ 1462 /* Mux pins for device idle if populated */
1427 if (oh->mux && oh->mux->pads_dynamic) 1463 if (oh->mux && oh->mux->pads_dynamic)
@@ -1514,6 +1550,10 @@ static int _shutdown(struct omap_hwmod *oh)
1514 _del_initiator_dep(oh, mpu_oh); 1550 _del_initiator_dep(oh, mpu_oh);
1515 /* XXX what about the other system initiators here? dma, dsp */ 1551 /* XXX what about the other system initiators here? dma, dsp */
1516 _disable_clocks(oh); 1552 _disable_clocks(oh);
1553 ret = _wait_target_disable(oh);
1554 if (ret)
1555 pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
1556 oh->name);
1517 } 1557 }
1518 /* XXX Should this code also force-disable the optional clocks? */ 1558 /* XXX Should this code also force-disable the optional clocks? */
1519 1559