aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c70
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)
1437static int _enable(struct omap_hwmod *oh) 1437static 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