diff options
author | Omar Ramirez Luna <omar.luna@linaro.org> | 2012-09-23 19:28:20 -0400 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2012-09-23 19:28:20 -0400 |
commit | eb05f691290e99ee0bd1672317d6add789523c1e (patch) | |
tree | 1df79aa4c0faddd49c10afb81e4dc20bab2c5b7b /arch/arm/mach-omap2/omap_hwmod.c | |
parent | 46b3af27894a3b414712bef313c4aacb605fccf7 (diff) |
ARM: OMAP: hwmod: partially un-reset hwmods might not be properly enabled
Some IP blocks might not be using/controlling more than one
reset line, this check loosens the restriction to fully use
hwmod framework for those drivers.
E.g.: ipu has reset lines: mmu_cache, cpu0 and cpu1.
- As of now cpu1 is not used and hence (with previous check) the
IP block isn't fully enabled by hwmod code.
- Usually ipu and dsp processors configure their mmu module first
and then enable the processors, this involves:
* Deasserting mmu reset line, and enabling the module.
* Deasserting cpu0 reset line, and enabling the processor.
The ones portrayed in this example are controlled through
rproc_fw_boot in drivers/remoteproc/remoteproc_core.c
While at it, prevent _omap4_module_disable if all the hardreset
lines on an IP block are not under reset.
This will allow the driver to:
a. Deassert the reset line.
b. Enable the hwmod through runtime PM default callbacks.
c. Do its usecase.
d. Disable hwmod through runtime PM.
e. Assert the reset line.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
[paul@pwsan.com: updated to apply]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 4f6b50f220c5..8d933528b708 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -1634,25 +1634,28 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name) | |||
1634 | } | 1634 | } |
1635 | 1635 | ||
1636 | /** | 1636 | /** |
1637 | * _are_any_hardreset_lines_asserted - return true if part of @oh is hard-reset | 1637 | * _are_all_hardreset_lines_asserted - return true if the @oh is hard-reset |
1638 | * @oh: struct omap_hwmod * | 1638 | * @oh: struct omap_hwmod * |
1639 | * | 1639 | * |
1640 | * If any hardreset line associated with @oh is asserted, then return true. | 1640 | * If all hardreset lines associated with @oh are asserted, then return true. |
1641 | * Otherwise, if @oh has no hardreset lines associated with it, or if | 1641 | * Otherwise, if part of @oh is out hardreset or if no hardreset lines |
1642 | * no hardreset lines associated with @oh are asserted, then return false. | 1642 | * associated with @oh are asserted, then return false. |
1643 | * This function is used to avoid executing some parts of the IP block | 1643 | * This function is used to avoid executing some parts of the IP block |
1644 | * enable/disable sequence if a hardreset line is set. | 1644 | * enable/disable sequence if its hardreset line is set. |
1645 | */ | 1645 | */ |
1646 | static bool _are_any_hardreset_lines_asserted(struct omap_hwmod *oh) | 1646 | static bool _are_all_hardreset_lines_asserted(struct omap_hwmod *oh) |
1647 | { | 1647 | { |
1648 | int i; | 1648 | int i, rst_cnt = 0; |
1649 | 1649 | ||
1650 | if (oh->rst_lines_cnt == 0) | 1650 | if (oh->rst_lines_cnt == 0) |
1651 | return false; | 1651 | return false; |
1652 | 1652 | ||
1653 | for (i = 0; i < oh->rst_lines_cnt; i++) | 1653 | for (i = 0; i < oh->rst_lines_cnt; i++) |
1654 | if (_read_hardreset(oh, oh->rst_lines[i].name) > 0) | 1654 | if (_read_hardreset(oh, oh->rst_lines[i].name) > 0) |
1655 | return true; | 1655 | rst_cnt++; |
1656 | |||
1657 | if (oh->rst_lines_cnt == rst_cnt) | ||
1658 | return true; | ||
1656 | 1659 | ||
1657 | return false; | 1660 | return false; |
1658 | } | 1661 | } |
@@ -1671,6 +1674,13 @@ static int _omap4_disable_module(struct omap_hwmod *oh) | |||
1671 | if (!oh->clkdm || !oh->prcm.omap4.modulemode) | 1674 | if (!oh->clkdm || !oh->prcm.omap4.modulemode) |
1672 | return -EINVAL; | 1675 | return -EINVAL; |
1673 | 1676 | ||
1677 | /* | ||
1678 | * Since integration code might still be doing something, only | ||
1679 | * disable if all lines are under hardreset. | ||
1680 | */ | ||
1681 | if (!_are_all_hardreset_lines_asserted(oh)) | ||
1682 | return 0; | ||
1683 | |||
1674 | pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__); | 1684 | pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__); |
1675 | 1685 | ||
1676 | omap4_cminst_module_disable(oh->clkdm->prcm_partition, | 1686 | omap4_cminst_module_disable(oh->clkdm->prcm_partition, |
@@ -1678,9 +1688,6 @@ static int _omap4_disable_module(struct omap_hwmod *oh) | |||
1678 | oh->clkdm->clkdm_offs, | 1688 | oh->clkdm->clkdm_offs, |
1679 | oh->prcm.omap4.clkctrl_offs); | 1689 | oh->prcm.omap4.clkctrl_offs); |
1680 | 1690 | ||
1681 | if (_are_any_hardreset_lines_asserted(oh)) | ||
1682 | return 0; | ||
1683 | |||
1684 | v = _omap4_wait_target_disable(oh); | 1691 | v = _omap4_wait_target_disable(oh); |
1685 | if (v) | 1692 | if (v) |
1686 | pr_warn("omap_hwmod: %s: _wait_target_disable failed\n", | 1693 | pr_warn("omap_hwmod: %s: _wait_target_disable failed\n", |
@@ -1708,7 +1715,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh) | |||
1708 | am33xx_cm_module_disable(oh->clkdm->cm_inst, oh->clkdm->clkdm_offs, | 1715 | am33xx_cm_module_disable(oh->clkdm->cm_inst, oh->clkdm->clkdm_offs, |
1709 | oh->prcm.omap4.clkctrl_offs); | 1716 | oh->prcm.omap4.clkctrl_offs); |
1710 | 1717 | ||
1711 | if (_are_any_hardreset_lines_asserted(oh)) | 1718 | if (_are_all_hardreset_lines_asserted(oh)) |
1712 | return 0; | 1719 | return 0; |
1713 | 1720 | ||
1714 | v = _am33xx_wait_target_disable(oh); | 1721 | v = _am33xx_wait_target_disable(oh); |
@@ -1936,7 +1943,7 @@ static int _enable(struct omap_hwmod *oh) | |||
1936 | } | 1943 | } |
1937 | 1944 | ||
1938 | /* | 1945 | /* |
1939 | * If an IP block contains HW reset lines and any of them are | 1946 | * If an IP block contains HW reset lines and all of them are |
1940 | * asserted, we let integration code associated with that | 1947 | * asserted, we let integration code associated with that |
1941 | * block handle the enable. We've received very little | 1948 | * block handle the enable. We've received very little |
1942 | * information on what those driver authors need, and until | 1949 | * information on what those driver authors need, and until |
@@ -1944,7 +1951,7 @@ static int _enable(struct omap_hwmod *oh) | |||
1944 | * posted to the public lists, this is probably the best we | 1951 | * posted to the public lists, this is probably the best we |
1945 | * can do. | 1952 | * can do. |
1946 | */ | 1953 | */ |
1947 | if (_are_any_hardreset_lines_asserted(oh)) | 1954 | if (_are_all_hardreset_lines_asserted(oh)) |
1948 | return 0; | 1955 | return 0; |
1949 | 1956 | ||
1950 | /* Mux pins for device runtime if populated */ | 1957 | /* Mux pins for device runtime if populated */ |
@@ -2025,7 +2032,7 @@ static int _idle(struct omap_hwmod *oh) | |||
2025 | return -EINVAL; | 2032 | return -EINVAL; |
2026 | } | 2033 | } |
2027 | 2034 | ||
2028 | if (_are_any_hardreset_lines_asserted(oh)) | 2035 | if (_are_all_hardreset_lines_asserted(oh)) |
2029 | return 0; | 2036 | return 0; |
2030 | 2037 | ||
2031 | if (oh->class->sysc) | 2038 | if (oh->class->sysc) |
@@ -2113,7 +2120,7 @@ static int _shutdown(struct omap_hwmod *oh) | |||
2113 | return -EINVAL; | 2120 | return -EINVAL; |
2114 | } | 2121 | } |
2115 | 2122 | ||
2116 | if (_are_any_hardreset_lines_asserted(oh)) | 2123 | if (_are_all_hardreset_lines_asserted(oh)) |
2117 | return 0; | 2124 | return 0; |
2118 | 2125 | ||
2119 | pr_debug("omap_hwmod: %s: disabling\n", oh->name); | 2126 | pr_debug("omap_hwmod: %s: disabling\n", oh->name); |