diff options
author | Paul Walmsley <paul@pwsan.com> | 2010-12-14 14:42:35 -0500 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2010-12-21 21:55:12 -0500 |
commit | 2092e5ccf89db09ebde94e9aabd3c86d5fa05c6c (patch) | |
tree | c286d08314b82afe63485a79e13013492186e218 /arch/arm/mach-omap2/omap_hwmod.c | |
parent | e4dc8f507c3066d6fcece988d99b6d766c46af85 (diff) |
OMAP2+: hwmod: add postsetup state
Allow board files and OMAP core code to control the state that some or
all of the hwmods end up in at the end of _setup() (called by
omap_hwmod_late_init() ). Reimplement the old skip_setup_idle code in
terms of this new postsetup state code.
There are two use-cases for this patch: the !CONFIG_PM_RUNTIME case,
in which all IP blocks should stay enabled after _setup() finishes;
and the MPU watchdog case, in which the watchdog IP block should enter
idle if watchdog coverage of kernel initialization is desired, and
should be disabled otherwise.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: BenoƮt Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Charulatha Varadarajan <charu@ti.com>
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 82 |
1 files changed, 63 insertions, 19 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index c051fa493594..683428fa91f4 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -1313,23 +1313,15 @@ static int _shutdown(struct omap_hwmod *oh) | |||
1313 | /** | 1313 | /** |
1314 | * _setup - do initial configuration of omap_hwmod | 1314 | * _setup - do initial configuration of omap_hwmod |
1315 | * @oh: struct omap_hwmod * | 1315 | * @oh: struct omap_hwmod * |
1316 | * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1 | ||
1317 | * | 1316 | * |
1318 | * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh | 1317 | * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh |
1319 | * OCP_SYSCONFIG register. @skip_setup_idle is intended to be used on | 1318 | * OCP_SYSCONFIG register. Returns -EINVAL if the hwmod is in the |
1320 | * a system that will not call omap_hwmod_enable() to enable devices | 1319 | * wrong state or returns 0. |
1321 | * (e.g., a system without PM runtime). Returns -EINVAL if the hwmod | ||
1322 | * is in the wrong state or returns 0. | ||
1323 | */ | 1320 | */ |
1324 | static int _setup(struct omap_hwmod *oh, void *data) | 1321 | static int _setup(struct omap_hwmod *oh, void *data) |
1325 | { | 1322 | { |
1326 | int i, r; | 1323 | int i, r; |
1327 | u8 skip_setup_idle; | 1324 | u8 postsetup_state; |
1328 | |||
1329 | if (!oh || !data) | ||
1330 | return -EINVAL; | ||
1331 | |||
1332 | skip_setup_idle = *(u8 *)data; | ||
1333 | 1325 | ||
1334 | /* Set iclk autoidle mode */ | 1326 | /* Set iclk autoidle mode */ |
1335 | if (oh->slaves_cnt > 0) { | 1327 | if (oh->slaves_cnt > 0) { |
@@ -1349,7 +1341,6 @@ static int _setup(struct omap_hwmod *oh, void *data) | |||
1349 | } | 1341 | } |
1350 | } | 1342 | } |
1351 | 1343 | ||
1352 | mutex_init(&oh->_mutex); | ||
1353 | oh->_state = _HWMOD_STATE_INITIALIZED; | 1344 | oh->_state = _HWMOD_STATE_INITIALIZED; |
1354 | 1345 | ||
1355 | /* | 1346 | /* |
@@ -1383,8 +1374,25 @@ static int _setup(struct omap_hwmod *oh, void *data) | |||
1383 | } | 1374 | } |
1384 | } | 1375 | } |
1385 | 1376 | ||
1386 | if (!(oh->flags & HWMOD_INIT_NO_IDLE) && !skip_setup_idle) | 1377 | postsetup_state = oh->_postsetup_state; |
1378 | if (postsetup_state == _HWMOD_STATE_UNKNOWN) | ||
1379 | postsetup_state = _HWMOD_STATE_ENABLED; | ||
1380 | |||
1381 | /* | ||
1382 | * XXX HWMOD_INIT_NO_IDLE does not belong in hwmod data - | ||
1383 | * it should be set by the core code as a runtime flag during startup | ||
1384 | */ | ||
1385 | if ((oh->flags & HWMOD_INIT_NO_IDLE) && | ||
1386 | (postsetup_state == _HWMOD_STATE_IDLE)) | ||
1387 | postsetup_state = _HWMOD_STATE_ENABLED; | ||
1388 | |||
1389 | if (postsetup_state == _HWMOD_STATE_IDLE) | ||
1387 | _omap_hwmod_idle(oh); | 1390 | _omap_hwmod_idle(oh); |
1391 | else if (postsetup_state == _HWMOD_STATE_DISABLED) | ||
1392 | _shutdown(oh); | ||
1393 | else if (postsetup_state != _HWMOD_STATE_ENABLED) | ||
1394 | WARN(1, "hwmod: %s: unknown postsetup state %d! defaulting to enabled\n", | ||
1395 | oh->name, postsetup_state); | ||
1388 | 1396 | ||
1389 | return 0; | 1397 | return 0; |
1390 | } | 1398 | } |
@@ -1485,6 +1493,8 @@ int omap_hwmod_register(struct omap_hwmod *oh) | |||
1485 | 1493 | ||
1486 | list_add_tail(&oh->node, &omap_hwmod_list); | 1494 | list_add_tail(&oh->node, &omap_hwmod_list); |
1487 | 1495 | ||
1496 | mutex_init(&oh->_mutex); | ||
1497 | |||
1488 | oh->_state = _HWMOD_STATE_REGISTERED; | 1498 | oh->_state = _HWMOD_STATE_REGISTERED; |
1489 | 1499 | ||
1490 | ret = 0; | 1500 | ret = 0; |
@@ -1585,13 +1595,12 @@ int omap_hwmod_init(struct omap_hwmod **ohs) | |||
1585 | 1595 | ||
1586 | /** | 1596 | /** |
1587 | * omap_hwmod_late_init - do some post-clock framework initialization | 1597 | * omap_hwmod_late_init - do some post-clock framework initialization |
1588 | * @skip_setup_idle: if 1, do not idle hwmods in _setup() | ||
1589 | * | 1598 | * |
1590 | * Must be called after omap2_clk_init(). Resolves the struct clk names | 1599 | * Must be called after omap2_clk_init(). Resolves the struct clk names |
1591 | * to struct clk pointers for each registered omap_hwmod. Also calls | 1600 | * to struct clk pointers for each registered omap_hwmod. Also calls |
1592 | * _setup() on each hwmod. Returns 0. | 1601 | * _setup() on each hwmod. Returns 0. |
1593 | */ | 1602 | */ |
1594 | int omap_hwmod_late_init(u8 skip_setup_idle) | 1603 | int omap_hwmod_late_init(void) |
1595 | { | 1604 | { |
1596 | int r; | 1605 | int r; |
1597 | 1606 | ||
@@ -1603,10 +1612,7 @@ int omap_hwmod_late_init(u8 skip_setup_idle) | |||
1603 | WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n", | 1612 | WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n", |
1604 | MPU_INITIATOR_NAME); | 1613 | MPU_INITIATOR_NAME); |
1605 | 1614 | ||
1606 | if (skip_setup_idle) | 1615 | omap_hwmod_for_each(_setup, NULL); |
1607 | pr_debug("omap_hwmod: will leave hwmods enabled during setup\n"); | ||
1608 | |||
1609 | omap_hwmod_for_each(_setup, &skip_setup_idle); | ||
1610 | 1616 | ||
1611 | return 0; | 1617 | return 0; |
1612 | } | 1618 | } |
@@ -2132,3 +2138,41 @@ int omap_hwmod_for_each_by_class(const char *classname, | |||
2132 | return ret; | 2138 | return ret; |
2133 | } | 2139 | } |
2134 | 2140 | ||
2141 | /** | ||
2142 | * omap_hwmod_set_postsetup_state - set the post-_setup() state for this hwmod | ||
2143 | * @oh: struct omap_hwmod * | ||
2144 | * @state: state that _setup() should leave the hwmod in | ||
2145 | * | ||
2146 | * Sets the hwmod state that @oh will enter at the end of _setup() (called by | ||
2147 | * omap_hwmod_late_init()). Only valid to call between calls to | ||
2148 | * omap_hwmod_init() and omap_hwmod_late_init(). Returns 0 upon success or | ||
2149 | * -EINVAL if there is a problem with the arguments or if the hwmod is | ||
2150 | * in the wrong state. | ||
2151 | */ | ||
2152 | int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state) | ||
2153 | { | ||
2154 | int ret; | ||
2155 | |||
2156 | if (!oh) | ||
2157 | return -EINVAL; | ||
2158 | |||
2159 | if (state != _HWMOD_STATE_DISABLED && | ||
2160 | state != _HWMOD_STATE_ENABLED && | ||
2161 | state != _HWMOD_STATE_IDLE) | ||
2162 | return -EINVAL; | ||
2163 | |||
2164 | mutex_lock(&oh->_mutex); | ||
2165 | |||
2166 | if (oh->_state != _HWMOD_STATE_REGISTERED) { | ||
2167 | ret = -EINVAL; | ||
2168 | goto ohsps_unlock; | ||
2169 | } | ||
2170 | |||
2171 | oh->_postsetup_state = state; | ||
2172 | ret = 0; | ||
2173 | |||
2174 | ohsps_unlock: | ||
2175 | mutex_unlock(&oh->_mutex); | ||
2176 | |||
2177 | return ret; | ||
2178 | } | ||