diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 70 |
1 files changed, 50 insertions, 20 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 4424fee5cd5a..84cc0bdda3ae 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -1437,6 +1437,7 @@ static int _reset(struct omap_hwmod *oh) | |||
1437 | static int _enable(struct omap_hwmod *oh) | 1437 | static int _enable(struct omap_hwmod *oh) |
1438 | { | 1438 | { |
1439 | int r; | 1439 | int r; |
1440 | int hwsup = 0; | ||
1440 | 1441 | ||
1441 | pr_debug("omap_hwmod: %s: enabling\n", oh->name); | 1442 | pr_debug("omap_hwmod: %s: enabling\n", oh->name); |
1442 | 1443 | ||
@@ -1448,14 +1449,6 @@ static int _enable(struct omap_hwmod *oh) | |||
1448 | return -EINVAL; | 1449 | return -EINVAL; |
1449 | } | 1450 | } |
1450 | 1451 | ||
1451 | /* Mux pins for device runtime if populated */ | ||
1452 | if (oh->mux && (!oh->mux->enabled || | ||
1453 | ((oh->_state == _HWMOD_STATE_IDLE) && | ||
1454 | oh->mux->pads_dynamic))) | ||
1455 | omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); | ||
1456 | |||
1457 | _add_initiator_dep(oh, mpu_oh); | ||
1458 | _enable_clocks(oh); | ||
1459 | 1452 | ||
1460 | /* | 1453 | /* |
1461 | * If an IP contains only one HW reset line, then de-assert it in order | 1454 | * If an IP contains only one HW reset line, then de-assert it in order |
@@ -1466,23 +1459,56 @@ static int _enable(struct omap_hwmod *oh) | |||
1466 | oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1) | 1459 | oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1) |
1467 | _deassert_hardreset(oh, oh->rst_lines[0].name); | 1460 | _deassert_hardreset(oh, oh->rst_lines[0].name); |
1468 | 1461 | ||
1469 | r = _wait_target_ready(oh); | 1462 | /* Mux pins for device runtime if populated */ |
1470 | if (r) { | 1463 | if (oh->mux && (!oh->mux->enabled || |
1471 | pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", | 1464 | ((oh->_state == _HWMOD_STATE_IDLE) && |
1472 | oh->name, r); | 1465 | oh->mux->pads_dynamic))) |
1473 | _disable_clocks(oh); | 1466 | omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); |
1467 | |||
1468 | _add_initiator_dep(oh, mpu_oh); | ||
1474 | 1469 | ||
1475 | return r; | 1470 | if (oh->clkdm) { |
1471 | /* | ||
1472 | * A clockdomain must be in SW_SUP before enabling | ||
1473 | * completely the module. The clockdomain can be set | ||
1474 | * in HW_AUTO only when the module become ready. | ||
1475 | */ | ||
1476 | hwsup = clkdm_in_hwsup(oh->clkdm); | ||
1477 | r = clkdm_hwmod_enable(oh->clkdm, oh); | ||
1478 | if (r) { | ||
1479 | WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n", | ||
1480 | oh->name, oh->clkdm->name, r); | ||
1481 | return r; | ||
1482 | } | ||
1476 | } | 1483 | } |
1484 | |||
1485 | _enable_clocks(oh); | ||
1477 | _enable_module(oh); | 1486 | _enable_module(oh); |
1478 | 1487 | ||
1479 | oh->_state = _HWMOD_STATE_ENABLED; | 1488 | r = _wait_target_ready(oh); |
1489 | if (!r) { | ||
1490 | /* | ||
1491 | * Set the clockdomain to HW_AUTO only if the target is ready, | ||
1492 | * assuming that the previous state was HW_AUTO | ||
1493 | */ | ||
1494 | if (oh->clkdm && hwsup) | ||
1495 | clkdm_allow_idle(oh->clkdm); | ||
1480 | 1496 | ||
1481 | /* Access the sysconfig only if the target is ready */ | 1497 | oh->_state = _HWMOD_STATE_ENABLED; |
1482 | if (oh->class->sysc) { | 1498 | |
1483 | if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED)) | 1499 | /* Access the sysconfig only if the target is ready */ |
1484 | _update_sysc_cache(oh); | 1500 | if (oh->class->sysc) { |
1485 | _enable_sysc(oh); | 1501 | if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED)) |
1502 | _update_sysc_cache(oh); | ||
1503 | _enable_sysc(oh); | ||
1504 | } | ||
1505 | } else { | ||
1506 | _disable_clocks(oh); | ||
1507 | pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", | ||
1508 | oh->name, r); | ||
1509 | |||
1510 | if (oh->clkdm) | ||
1511 | clkdm_hwmod_disable(oh->clkdm, oh); | ||
1486 | } | 1512 | } |
1487 | 1513 | ||
1488 | return r; | 1514 | return r; |
@@ -1523,6 +1549,8 @@ static int _idle(struct omap_hwmod *oh) | |||
1523 | * transition to complete properly. | 1549 | * transition to complete properly. |
1524 | */ | 1550 | */ |
1525 | _disable_clocks(oh); | 1551 | _disable_clocks(oh); |
1552 | if (oh->clkdm) | ||
1553 | clkdm_hwmod_disable(oh->clkdm, oh); | ||
1526 | 1554 | ||
1527 | /* Mux pins for device idle if populated */ | 1555 | /* Mux pins for device idle if populated */ |
1528 | if (oh->mux && oh->mux->pads_dynamic) | 1556 | if (oh->mux && oh->mux->pads_dynamic) |
@@ -1620,6 +1648,8 @@ static int _shutdown(struct omap_hwmod *oh) | |||
1620 | pr_warn("omap_hwmod: %s: _wait_target_disable failed\n", | 1648 | pr_warn("omap_hwmod: %s: _wait_target_disable failed\n", |
1621 | oh->name); | 1649 | oh->name); |
1622 | _disable_clocks(oh); | 1650 | _disable_clocks(oh); |
1651 | if (oh->clkdm) | ||
1652 | clkdm_hwmod_disable(oh->clkdm, oh); | ||
1623 | } | 1653 | } |
1624 | /* XXX Should this code also force-disable the optional clocks? */ | 1654 | /* XXX Should this code also force-disable the optional clocks? */ |
1625 | 1655 | ||