diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 139 |
1 files changed, 83 insertions, 56 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 6c6d31b432d2..bd9fc10ea737 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -781,39 +781,6 @@ static int _omap4_wait_target_disable(struct omap_hwmod *oh) | |||
781 | } | 781 | } |
782 | 782 | ||
783 | /** | 783 | /** |
784 | * _omap4_disable_module - enable CLKCTRL modulemode on OMAP4 | ||
785 | * @oh: struct omap_hwmod * | ||
786 | * | ||
787 | * Disable the PRCM module mode related to the hwmod @oh. | ||
788 | * Return EINVAL if the modulemode is not supported and 0 in case of success. | ||
789 | */ | ||
790 | static int _omap4_disable_module(struct omap_hwmod *oh) | ||
791 | { | ||
792 | int v; | ||
793 | |||
794 | /* The module mode does not exist prior OMAP4 */ | ||
795 | if (!cpu_is_omap44xx()) | ||
796 | return -EINVAL; | ||
797 | |||
798 | if (!oh->clkdm || !oh->prcm.omap4.modulemode) | ||
799 | return -EINVAL; | ||
800 | |||
801 | pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__); | ||
802 | |||
803 | omap4_cminst_module_disable(oh->clkdm->prcm_partition, | ||
804 | oh->clkdm->cm_inst, | ||
805 | oh->clkdm->clkdm_offs, | ||
806 | oh->prcm.omap4.clkctrl_offs); | ||
807 | |||
808 | v = _omap4_wait_target_disable(oh); | ||
809 | if (v) | ||
810 | pr_warn("omap_hwmod: %s: _wait_target_disable failed\n", | ||
811 | oh->name); | ||
812 | |||
813 | return 0; | ||
814 | } | ||
815 | |||
816 | /** | ||
817 | * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh | 784 | * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh |
818 | * @oh: struct omap_hwmod *oh | 785 | * @oh: struct omap_hwmod *oh |
819 | * | 786 | * |
@@ -1378,6 +1345,66 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name) | |||
1378 | } | 1345 | } |
1379 | 1346 | ||
1380 | /** | 1347 | /** |
1348 | * _are_any_hardreset_lines_asserted - return true if part of @oh is hard-reset | ||
1349 | * @oh: struct omap_hwmod * | ||
1350 | * | ||
1351 | * If any hardreset line associated with @oh is asserted, then return true. | ||
1352 | * Otherwise, if @oh has no hardreset lines associated with it, or if | ||
1353 | * no hardreset lines associated with @oh are asserted, then return false. | ||
1354 | * This function is used to avoid executing some parts of the IP block | ||
1355 | * enable/disable sequence if a hardreset line is set. | ||
1356 | */ | ||
1357 | static bool _are_any_hardreset_lines_asserted(struct omap_hwmod *oh) | ||
1358 | { | ||
1359 | int i; | ||
1360 | |||
1361 | if (oh->rst_lines_cnt == 0) | ||
1362 | return false; | ||
1363 | |||
1364 | for (i = 0; i < oh->rst_lines_cnt; i++) | ||
1365 | if (_read_hardreset(oh, oh->rst_lines[i].name) > 0) | ||
1366 | return true; | ||
1367 | |||
1368 | return false; | ||
1369 | } | ||
1370 | |||
1371 | /** | ||
1372 | * _omap4_disable_module - enable CLKCTRL modulemode on OMAP4 | ||
1373 | * @oh: struct omap_hwmod * | ||
1374 | * | ||
1375 | * Disable the PRCM module mode related to the hwmod @oh. | ||
1376 | * Return EINVAL if the modulemode is not supported and 0 in case of success. | ||
1377 | */ | ||
1378 | static int _omap4_disable_module(struct omap_hwmod *oh) | ||
1379 | { | ||
1380 | int v; | ||
1381 | |||
1382 | /* The module mode does not exist prior OMAP4 */ | ||
1383 | if (!cpu_is_omap44xx()) | ||
1384 | return -EINVAL; | ||
1385 | |||
1386 | if (!oh->clkdm || !oh->prcm.omap4.modulemode) | ||
1387 | return -EINVAL; | ||
1388 | |||
1389 | pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__); | ||
1390 | |||
1391 | omap4_cminst_module_disable(oh->clkdm->prcm_partition, | ||
1392 | oh->clkdm->cm_inst, | ||
1393 | oh->clkdm->clkdm_offs, | ||
1394 | oh->prcm.omap4.clkctrl_offs); | ||
1395 | |||
1396 | if (_are_any_hardreset_lines_asserted(oh)) | ||
1397 | return 0; | ||
1398 | |||
1399 | v = _omap4_wait_target_disable(oh); | ||
1400 | if (v) | ||
1401 | pr_warn("omap_hwmod: %s: _wait_target_disable failed\n", | ||
1402 | oh->name); | ||
1403 | |||
1404 | return 0; | ||
1405 | } | ||
1406 | |||
1407 | /** | ||
1381 | * _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit | 1408 | * _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit |
1382 | * @oh: struct omap_hwmod * | 1409 | * @oh: struct omap_hwmod * |
1383 | * | 1410 | * |
@@ -1528,7 +1555,7 @@ static int _reset(struct omap_hwmod *oh) | |||
1528 | */ | 1555 | */ |
1529 | static int _enable(struct omap_hwmod *oh) | 1556 | static int _enable(struct omap_hwmod *oh) |
1530 | { | 1557 | { |
1531 | int r, i; | 1558 | int r; |
1532 | int hwsup = 0; | 1559 | int hwsup = 0; |
1533 | 1560 | ||
1534 | pr_debug("omap_hwmod: %s: enabling\n", oh->name); | 1561 | pr_debug("omap_hwmod: %s: enabling\n", oh->name); |
@@ -1560,14 +1587,16 @@ static int _enable(struct omap_hwmod *oh) | |||
1560 | } | 1587 | } |
1561 | 1588 | ||
1562 | /* | 1589 | /* |
1563 | * If an IP contains HW reset lines, then de-assert them in order | 1590 | * If an IP block contains HW reset lines and any of them are |
1564 | * to allow the module state transition. Otherwise the PRCM will return | 1591 | * asserted, we let integration code associated with that |
1565 | * Intransition status, and the init will failed. | 1592 | * block handle the enable. We've received very little |
1593 | * information on what those driver authors need, and until | ||
1594 | * detailed information is provided and the driver code is | ||
1595 | * posted to the public lists, this is probably the best we | ||
1596 | * can do. | ||
1566 | */ | 1597 | */ |
1567 | if (oh->_state == _HWMOD_STATE_INITIALIZED || | 1598 | if (_are_any_hardreset_lines_asserted(oh)) |
1568 | oh->_state == _HWMOD_STATE_DISABLED) | 1599 | return 0; |
1569 | for (i = 0; i < oh->rst_lines_cnt; i++) | ||
1570 | _deassert_hardreset(oh, oh->rst_lines[i].name); | ||
1571 | 1600 | ||
1572 | /* Mux pins for device runtime if populated */ | 1601 | /* Mux pins for device runtime if populated */ |
1573 | if (oh->mux && (!oh->mux->enabled || | 1602 | if (oh->mux && (!oh->mux->enabled || |
@@ -1642,6 +1671,9 @@ static int _idle(struct omap_hwmod *oh) | |||
1642 | return -EINVAL; | 1671 | return -EINVAL; |
1643 | } | 1672 | } |
1644 | 1673 | ||
1674 | if (_are_any_hardreset_lines_asserted(oh)) | ||
1675 | return 0; | ||
1676 | |||
1645 | if (oh->class->sysc) | 1677 | if (oh->class->sysc) |
1646 | _idle_sysc(oh); | 1678 | _idle_sysc(oh); |
1647 | _del_initiator_dep(oh, mpu_oh); | 1679 | _del_initiator_dep(oh, mpu_oh); |
@@ -1724,6 +1756,9 @@ static int _shutdown(struct omap_hwmod *oh) | |||
1724 | return -EINVAL; | 1756 | return -EINVAL; |
1725 | } | 1757 | } |
1726 | 1758 | ||
1759 | if (_are_any_hardreset_lines_asserted(oh)) | ||
1760 | return 0; | ||
1761 | |||
1727 | pr_debug("omap_hwmod: %s: disabling\n", oh->name); | 1762 | pr_debug("omap_hwmod: %s: disabling\n", oh->name); |
1728 | 1763 | ||
1729 | if (oh->class->pre_shutdown) { | 1764 | if (oh->class->pre_shutdown) { |
@@ -1866,21 +1901,13 @@ static int __init _setup_reset(struct omap_hwmod *oh) | |||
1866 | if (oh->_state != _HWMOD_STATE_INITIALIZED) | 1901 | if (oh->_state != _HWMOD_STATE_INITIALIZED) |
1867 | return -EINVAL; | 1902 | return -EINVAL; |
1868 | 1903 | ||
1869 | /* | 1904 | if (oh->rst_lines_cnt == 0) { |
1870 | * In the case of hwmod with hardreset that should not be | 1905 | r = _enable(oh); |
1871 | * de-assert at boot time, we have to keep the module | 1906 | if (r) { |
1872 | * initialized, because we cannot enable it properly with the | 1907 | pr_warning("omap_hwmod: %s: cannot be enabled for reset (%d)\n", |
1873 | * reset asserted. Exit without warning because that behavior | 1908 | oh->name, oh->_state); |
1874 | * is expected. | 1909 | return -EINVAL; |
1875 | */ | 1910 | } |
1876 | if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt > 0) | ||
1877 | return 0; | ||
1878 | |||
1879 | r = _enable(oh); | ||
1880 | if (r) { | ||
1881 | pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n", | ||
1882 | oh->name, oh->_state); | ||
1883 | return 0; | ||
1884 | } | 1911 | } |
1885 | 1912 | ||
1886 | if (!(oh->flags & HWMOD_INIT_NO_RESET)) | 1913 | if (!(oh->flags & HWMOD_INIT_NO_RESET)) |