aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2012-09-23 22:31:35 -0400
committerTony Lindgren <tony@atomide.com>2012-09-23 22:31:35 -0400
commit9cd68fa707cf6372f33eb51a5719dd7626efe5f6 (patch)
tree66cde27bd288e011a6e4cff87d342666399a1266 /arch/arm/mach-omap2/omap_hwmod.c
parent5698bd757d55b1bb87edd1a9744ab09c142abfc2 (diff)
parent76a5d9bfc42d60e9a672e0cae776157a60970f4e (diff)
Merge tag 'omap-devel-b-c-2-for-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending into devel-late
OMAP patches intended for the 3.7 merge window: - Runtime PM conversions for the GPMC and RNG IP blocks - Preparation patches for the OMAP common clock framework conversion - clkdev alias additions required by other drivers - Performance Monitoring Unit (PMU) support for OMAP2, 3, and non-4430 OMAP4 - OMAP hwmod code and data improvements - Preparation patches for the IOMMU runtime PM conversion - Preparation patches for OMAP4 full-chip retention support Based on a merge of v3.6-rc6, the omap-cleanup-b-for-3.7 tag (7852ec0536ca39cefffc6301dc77f8ae55592926),the cleanup-fixes-for-v3.7 tag (de6ca33a96a6bf61fcb91d3d399703e19ead9d1e), and the omap-devel-am33xx-for-v3.7 tag (11964f53eb4d9ce59a058be9999d9cfcb1ced878), due to dependencies. These patches have been tested for meaningful warnings from checkpatch, sparse, smatch, and cppcheck. Basic build, boot[1], and PM test logs are available here: http://www.pwsan.com/omap/testlogs/hwmod_prcm_clock_a_3.7/20120923173830/ ... 1. Note that the N800 boot fails due to a known issue present in the base commit: http://www.spinics.net/lists/arm-kernel/msg196034.html
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c336
1 files changed, 294 insertions, 42 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 37afbd173c2c..6af64bbd9e1d 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -139,18 +139,20 @@
139#include <linux/slab.h> 139#include <linux/slab.h>
140#include <linux/bootmem.h> 140#include <linux/bootmem.h>
141 141
142#include "common.h"
143#include <plat/cpu.h>
144#include "clockdomain.h"
145#include "powerdomain.h"
146#include <plat/clock.h> 142#include <plat/clock.h>
147#include <plat/omap_hwmod.h> 143#include <plat/omap_hwmod.h>
148#include <plat/prcm.h> 144#include <plat/prcm.h>
149 145
146#include "soc.h"
147#include "common.h"
148#include "clockdomain.h"
149#include "powerdomain.h"
150#include "cm2xxx_3xxx.h" 150#include "cm2xxx_3xxx.h"
151#include "cminst44xx.h" 151#include "cminst44xx.h"
152#include "cm33xx.h"
152#include "prm2xxx_3xxx.h" 153#include "prm2xxx_3xxx.h"
153#include "prm44xx.h" 154#include "prm44xx.h"
155#include "prm33xx.h"
154#include "prminst44xx.h" 156#include "prminst44xx.h"
155#include "mux.h" 157#include "mux.h"
156#include "pm.h" 158#include "pm.h"
@@ -677,16 +679,25 @@ static int _init_main_clk(struct omap_hwmod *oh)
677 if (!oh->main_clk) 679 if (!oh->main_clk)
678 return 0; 680 return 0;
679 681
680 oh->_clk = omap_clk_get_by_name(oh->main_clk); 682 oh->_clk = clk_get(NULL, oh->main_clk);
681 if (!oh->_clk) { 683 if (IS_ERR(oh->_clk)) {
682 pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n", 684 pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n",
683 oh->name, oh->main_clk); 685 oh->name, oh->main_clk);
684 return -EINVAL; 686 return -EINVAL;
685 } 687 }
688 /*
689 * HACK: This needs a re-visit once clk_prepare() is implemented
690 * to do something meaningful. Today its just a no-op.
691 * If clk_prepare() is used at some point to do things like
692 * voltage scaling etc, then this would have to be moved to
693 * some point where subsystems like i2c and pmic become
694 * available.
695 */
696 clk_prepare(oh->_clk);
686 697
687 if (!oh->_clk->clkdm) 698 if (!oh->_clk->clkdm)
688 pr_warning("omap_hwmod: %s: missing clockdomain for %s.\n", 699 pr_debug("omap_hwmod: %s: missing clockdomain for %s.\n",
689 oh->main_clk, oh->_clk->name); 700 oh->name, oh->main_clk);
690 701
691 return ret; 702 return ret;
692} 703}
@@ -713,13 +724,22 @@ static int _init_interface_clks(struct omap_hwmod *oh)
713 if (!os->clk) 724 if (!os->clk)
714 continue; 725 continue;
715 726
716 c = omap_clk_get_by_name(os->clk); 727 c = clk_get(NULL, os->clk);
717 if (!c) { 728 if (IS_ERR(c)) {
718 pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n", 729 pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
719 oh->name, os->clk); 730 oh->name, os->clk);
720 ret = -EINVAL; 731 ret = -EINVAL;
721 } 732 }
722 os->_clk = c; 733 os->_clk = c;
734 /*
735 * HACK: This needs a re-visit once clk_prepare() is implemented
736 * to do something meaningful. Today its just a no-op.
737 * If clk_prepare() is used at some point to do things like
738 * voltage scaling etc, then this would have to be moved to
739 * some point where subsystems like i2c and pmic become
740 * available.
741 */
742 clk_prepare(os->_clk);
723 } 743 }
724 744
725 return ret; 745 return ret;
@@ -740,13 +760,22 @@ static int _init_opt_clks(struct omap_hwmod *oh)
740 int ret = 0; 760 int ret = 0;
741 761
742 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) { 762 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
743 c = omap_clk_get_by_name(oc->clk); 763 c = clk_get(NULL, oc->clk);
744 if (!c) { 764 if (IS_ERR(c)) {
745 pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n", 765 pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
746 oh->name, oc->clk); 766 oh->name, oc->clk);
747 ret = -EINVAL; 767 ret = -EINVAL;
748 } 768 }
749 oc->_clk = c; 769 oc->_clk = c;
770 /*
771 * HACK: This needs a re-visit once clk_prepare() is implemented
772 * to do something meaningful. Today its just a no-op.
773 * If clk_prepare() is used at some point to do things like
774 * voltage scaling etc, then this would have to be moved to
775 * some point where subsystems like i2c and pmic become
776 * available.
777 */
778 clk_prepare(oc->_clk);
750 } 779 }
751 780
752 return ret; 781 return ret;
@@ -825,7 +854,7 @@ static void _enable_optional_clocks(struct omap_hwmod *oh)
825 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) 854 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
826 if (oc->_clk) { 855 if (oc->_clk) {
827 pr_debug("omap_hwmod: enable %s:%s\n", oc->role, 856 pr_debug("omap_hwmod: enable %s:%s\n", oc->role,
828 oc->_clk->name); 857 __clk_get_name(oc->_clk));
829 clk_enable(oc->_clk); 858 clk_enable(oc->_clk);
830 } 859 }
831} 860}
@@ -840,7 +869,7 @@ static void _disable_optional_clocks(struct omap_hwmod *oh)
840 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) 869 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
841 if (oc->_clk) { 870 if (oc->_clk) {
842 pr_debug("omap_hwmod: disable %s:%s\n", oc->role, 871 pr_debug("omap_hwmod: disable %s:%s\n", oc->role,
843 oc->_clk->name); 872 __clk_get_name(oc->_clk));
844 clk_disable(oc->_clk); 873 clk_disable(oc->_clk);
845 } 874 }
846} 875}
@@ -868,6 +897,26 @@ static void _omap4_enable_module(struct omap_hwmod *oh)
868} 897}
869 898
870/** 899/**
900 * _am33xx_enable_module - enable CLKCTRL modulemode on AM33XX
901 * @oh: struct omap_hwmod *
902 *
903 * Enables the PRCM module mode related to the hwmod @oh.
904 * No return value.
905 */
906static void _am33xx_enable_module(struct omap_hwmod *oh)
907{
908 if (!oh->clkdm || !oh->prcm.omap4.modulemode)
909 return;
910
911 pr_debug("omap_hwmod: %s: %s: %d\n",
912 oh->name, __func__, oh->prcm.omap4.modulemode);
913
914 am33xx_cm_module_enable(oh->prcm.omap4.modulemode, oh->clkdm->cm_inst,
915 oh->clkdm->clkdm_offs,
916 oh->prcm.omap4.clkctrl_offs);
917}
918
919/**
871 * _omap4_wait_target_disable - wait for a module to be disabled on OMAP4 920 * _omap4_wait_target_disable - wait for a module to be disabled on OMAP4
872 * @oh: struct omap_hwmod * 921 * @oh: struct omap_hwmod *
873 * 922 *
@@ -878,10 +927,10 @@ static void _omap4_enable_module(struct omap_hwmod *oh)
878 */ 927 */
879static int _omap4_wait_target_disable(struct omap_hwmod *oh) 928static int _omap4_wait_target_disable(struct omap_hwmod *oh)
880{ 929{
881 if (!oh || !oh->clkdm) 930 if (!oh)
882 return -EINVAL; 931 return -EINVAL;
883 932
884 if (oh->_int_flags & _HWMOD_NO_MPU_PORT) 933 if (oh->_int_flags & _HWMOD_NO_MPU_PORT || !oh->clkdm)
885 return 0; 934 return 0;
886 935
887 if (oh->flags & HWMOD_NO_IDLEST) 936 if (oh->flags & HWMOD_NO_IDLEST)
@@ -894,6 +943,31 @@ static int _omap4_wait_target_disable(struct omap_hwmod *oh)
894} 943}
895 944
896/** 945/**
946 * _am33xx_wait_target_disable - wait for a module to be disabled on AM33XX
947 * @oh: struct omap_hwmod *
948 *
949 * Wait for a module @oh to enter slave idle. Returns 0 if the module
950 * does not have an IDLEST bit or if the module successfully enters
951 * slave idle; otherwise, pass along the return value of the
952 * appropriate *_cm*_wait_module_idle() function.
953 */
954static int _am33xx_wait_target_disable(struct omap_hwmod *oh)
955{
956 if (!oh)
957 return -EINVAL;
958
959 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
960 return 0;
961
962 if (oh->flags & HWMOD_NO_IDLEST)
963 return 0;
964
965 return am33xx_cm_wait_module_idle(oh->clkdm->cm_inst,
966 oh->clkdm->clkdm_offs,
967 oh->prcm.omap4.clkctrl_offs);
968}
969
970/**
897 * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh 971 * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh
898 * @oh: struct omap_hwmod *oh 972 * @oh: struct omap_hwmod *oh
899 * 973 *
@@ -1380,8 +1454,10 @@ static struct omap_hwmod *_lookup(const char *name)
1380 */ 1454 */
1381static int _init_clkdm(struct omap_hwmod *oh) 1455static int _init_clkdm(struct omap_hwmod *oh)
1382{ 1456{
1383 if (!oh->clkdm_name) 1457 if (!oh->clkdm_name) {
1458 pr_debug("omap_hwmod: %s: missing clockdomain\n", oh->name);
1384 return 0; 1459 return 0;
1460 }
1385 1461
1386 oh->clkdm = clkdm_lookup(oh->clkdm_name); 1462 oh->clkdm = clkdm_lookup(oh->clkdm_name);
1387 if (!oh->clkdm) { 1463 if (!oh->clkdm) {
@@ -1438,8 +1514,8 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
1438 * Return the bit position of the reset line that match the 1514 * Return the bit position of the reset line that match the
1439 * input name. Return -ENOENT if not found. 1515 * input name. Return -ENOENT if not found.
1440 */ 1516 */
1441static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name, 1517static int _lookup_hardreset(struct omap_hwmod *oh, const char *name,
1442 struct omap_hwmod_rst_info *ohri) 1518 struct omap_hwmod_rst_info *ohri)
1443{ 1519{
1444 int i; 1520 int i;
1445 1521
@@ -1475,7 +1551,7 @@ static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name,
1475static int _assert_hardreset(struct omap_hwmod *oh, const char *name) 1551static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
1476{ 1552{
1477 struct omap_hwmod_rst_info ohri; 1553 struct omap_hwmod_rst_info ohri;
1478 u8 ret = -EINVAL; 1554 int ret = -EINVAL;
1479 1555
1480 if (!oh) 1556 if (!oh)
1481 return -EINVAL; 1557 return -EINVAL;
@@ -1484,7 +1560,7 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
1484 return -ENOSYS; 1560 return -ENOSYS;
1485 1561
1486 ret = _lookup_hardreset(oh, name, &ohri); 1562 ret = _lookup_hardreset(oh, name, &ohri);
1487 if (IS_ERR_VALUE(ret)) 1563 if (ret < 0)
1488 return ret; 1564 return ret;
1489 1565
1490 ret = soc_ops.assert_hardreset(oh, &ohri); 1566 ret = soc_ops.assert_hardreset(oh, &ohri);
@@ -1509,6 +1585,7 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
1509{ 1585{
1510 struct omap_hwmod_rst_info ohri; 1586 struct omap_hwmod_rst_info ohri;
1511 int ret = -EINVAL; 1587 int ret = -EINVAL;
1588 int hwsup = 0;
1512 1589
1513 if (!oh) 1590 if (!oh)
1514 return -EINVAL; 1591 return -EINVAL;
@@ -1520,10 +1597,46 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
1520 if (IS_ERR_VALUE(ret)) 1597 if (IS_ERR_VALUE(ret))
1521 return ret; 1598 return ret;
1522 1599
1600 if (oh->clkdm) {
1601 /*
1602 * A clockdomain must be in SW_SUP otherwise reset
1603 * might not be completed. The clockdomain can be set
1604 * in HW_AUTO only when the module become ready.
1605 */
1606 hwsup = clkdm_in_hwsup(oh->clkdm);
1607 ret = clkdm_hwmod_enable(oh->clkdm, oh);
1608 if (ret) {
1609 WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
1610 oh->name, oh->clkdm->name, ret);
1611 return ret;
1612 }
1613 }
1614
1615 _enable_clocks(oh);
1616 if (soc_ops.enable_module)
1617 soc_ops.enable_module(oh);
1618
1523 ret = soc_ops.deassert_hardreset(oh, &ohri); 1619 ret = soc_ops.deassert_hardreset(oh, &ohri);
1620
1621 if (soc_ops.disable_module)
1622 soc_ops.disable_module(oh);
1623 _disable_clocks(oh);
1624
1524 if (ret == -EBUSY) 1625 if (ret == -EBUSY)
1525 pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name); 1626 pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
1526 1627
1628 if (!ret) {
1629 /*
1630 * Set the clockdomain to HW_AUTO, assuming that the
1631 * previous state was HW_AUTO.
1632 */
1633 if (oh->clkdm && hwsup)
1634 clkdm_allow_idle(oh->clkdm);
1635 } else {
1636 if (oh->clkdm)
1637 clkdm_hwmod_disable(oh->clkdm, oh);
1638 }
1639
1527 return ret; 1640 return ret;
1528} 1641}
1529 1642
@@ -1542,7 +1655,7 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
1542static int _read_hardreset(struct omap_hwmod *oh, const char *name) 1655static int _read_hardreset(struct omap_hwmod *oh, const char *name)
1543{ 1656{
1544 struct omap_hwmod_rst_info ohri; 1657 struct omap_hwmod_rst_info ohri;
1545 u8 ret = -EINVAL; 1658 int ret = -EINVAL;
1546 1659
1547 if (!oh) 1660 if (!oh)
1548 return -EINVAL; 1661 return -EINVAL;
@@ -1551,32 +1664,35 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
1551 return -ENOSYS; 1664 return -ENOSYS;
1552 1665
1553 ret = _lookup_hardreset(oh, name, &ohri); 1666 ret = _lookup_hardreset(oh, name, &ohri);
1554 if (IS_ERR_VALUE(ret)) 1667 if (ret < 0)
1555 return ret; 1668 return ret;
1556 1669
1557 return soc_ops.is_hardreset_asserted(oh, &ohri); 1670 return soc_ops.is_hardreset_asserted(oh, &ohri);
1558} 1671}
1559 1672
1560/** 1673/**
1561 * _are_any_hardreset_lines_asserted - return true if part of @oh is hard-reset 1674 * _are_all_hardreset_lines_asserted - return true if the @oh is hard-reset
1562 * @oh: struct omap_hwmod * 1675 * @oh: struct omap_hwmod *
1563 * 1676 *
1564 * If any hardreset line associated with @oh is asserted, then return true. 1677 * If all hardreset lines associated with @oh are asserted, then return true.
1565 * Otherwise, if @oh has no hardreset lines associated with it, or if 1678 * Otherwise, if part of @oh is out hardreset or if no hardreset lines
1566 * no hardreset lines associated with @oh are asserted, then return false. 1679 * associated with @oh are asserted, then return false.
1567 * This function is used to avoid executing some parts of the IP block 1680 * This function is used to avoid executing some parts of the IP block
1568 * enable/disable sequence if a hardreset line is set. 1681 * enable/disable sequence if its hardreset line is set.
1569 */ 1682 */
1570static bool _are_any_hardreset_lines_asserted(struct omap_hwmod *oh) 1683static bool _are_all_hardreset_lines_asserted(struct omap_hwmod *oh)
1571{ 1684{
1572 int i; 1685 int i, rst_cnt = 0;
1573 1686
1574 if (oh->rst_lines_cnt == 0) 1687 if (oh->rst_lines_cnt == 0)
1575 return false; 1688 return false;
1576 1689
1577 for (i = 0; i < oh->rst_lines_cnt; i++) 1690 for (i = 0; i < oh->rst_lines_cnt; i++)
1578 if (_read_hardreset(oh, oh->rst_lines[i].name) > 0) 1691 if (_read_hardreset(oh, oh->rst_lines[i].name) > 0)
1579 return true; 1692 rst_cnt++;
1693
1694 if (oh->rst_lines_cnt == rst_cnt)
1695 return true;
1580 1696
1581 return false; 1697 return false;
1582} 1698}
@@ -1595,6 +1711,13 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
1595 if (!oh->clkdm || !oh->prcm.omap4.modulemode) 1711 if (!oh->clkdm || !oh->prcm.omap4.modulemode)
1596 return -EINVAL; 1712 return -EINVAL;
1597 1713
1714 /*
1715 * Since integration code might still be doing something, only
1716 * disable if all lines are under hardreset.
1717 */
1718 if (!_are_all_hardreset_lines_asserted(oh))
1719 return 0;
1720
1598 pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__); 1721 pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
1599 1722
1600 omap4_cminst_module_disable(oh->clkdm->prcm_partition, 1723 omap4_cminst_module_disable(oh->clkdm->prcm_partition,
@@ -1602,10 +1725,37 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
1602 oh->clkdm->clkdm_offs, 1725 oh->clkdm->clkdm_offs,
1603 oh->prcm.omap4.clkctrl_offs); 1726 oh->prcm.omap4.clkctrl_offs);
1604 1727
1605 if (_are_any_hardreset_lines_asserted(oh)) 1728 v = _omap4_wait_target_disable(oh);
1729 if (v)
1730 pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
1731 oh->name);
1732
1733 return 0;
1734}
1735
1736/**
1737 * _am33xx_disable_module - enable CLKCTRL modulemode on AM33XX
1738 * @oh: struct omap_hwmod *
1739 *
1740 * Disable the PRCM module mode related to the hwmod @oh.
1741 * Return EINVAL if the modulemode is not supported and 0 in case of success.
1742 */
1743static int _am33xx_disable_module(struct omap_hwmod *oh)
1744{
1745 int v;
1746
1747 if (!oh->clkdm || !oh->prcm.omap4.modulemode)
1748 return -EINVAL;
1749
1750 pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
1751
1752 am33xx_cm_module_disable(oh->clkdm->cm_inst, oh->clkdm->clkdm_offs,
1753 oh->prcm.omap4.clkctrl_offs);
1754
1755 if (_are_all_hardreset_lines_asserted(oh))
1606 return 0; 1756 return 0;
1607 1757
1608 v = _omap4_wait_target_disable(oh); 1758 v = _am33xx_wait_target_disable(oh);
1609 if (v) 1759 if (v)
1610 pr_warn("omap_hwmod: %s: _wait_target_disable failed\n", 1760 pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
1611 oh->name); 1761 oh->name);
@@ -1641,8 +1791,8 @@ static int _ocp_softreset(struct omap_hwmod *oh)
1641 1791
1642 /* clocks must be on for this operation */ 1792 /* clocks must be on for this operation */
1643 if (oh->_state != _HWMOD_STATE_ENABLED) { 1793 if (oh->_state != _HWMOD_STATE_ENABLED) {
1644 pr_warning("omap_hwmod: %s: reset can only be entered from " 1794 pr_warn("omap_hwmod: %s: reset can only be entered from enabled state\n",
1645 "enabled state\n", oh->name); 1795 oh->name);
1646 return -EINVAL; 1796 return -EINVAL;
1647 } 1797 }
1648 1798
@@ -1830,7 +1980,7 @@ static int _enable(struct omap_hwmod *oh)
1830 } 1980 }
1831 1981
1832 /* 1982 /*
1833 * If an IP block contains HW reset lines and any of them are 1983 * If an IP block contains HW reset lines and all of them are
1834 * asserted, we let integration code associated with that 1984 * asserted, we let integration code associated with that
1835 * block handle the enable. We've received very little 1985 * block handle the enable. We've received very little
1836 * information on what those driver authors need, and until 1986 * information on what those driver authors need, and until
@@ -1838,7 +1988,7 @@ static int _enable(struct omap_hwmod *oh)
1838 * posted to the public lists, this is probably the best we 1988 * posted to the public lists, this is probably the best we
1839 * can do. 1989 * can do.
1840 */ 1990 */
1841 if (_are_any_hardreset_lines_asserted(oh)) 1991 if (_are_all_hardreset_lines_asserted(oh))
1842 return 0; 1992 return 0;
1843 1993
1844 /* Mux pins for device runtime if populated */ 1994 /* Mux pins for device runtime if populated */
@@ -1857,7 +2007,8 @@ static int _enable(struct omap_hwmod *oh)
1857 * completely the module. The clockdomain can be set 2007 * completely the module. The clockdomain can be set
1858 * in HW_AUTO only when the module become ready. 2008 * in HW_AUTO only when the module become ready.
1859 */ 2009 */
1860 hwsup = clkdm_in_hwsup(oh->clkdm); 2010 hwsup = clkdm_in_hwsup(oh->clkdm) &&
2011 !clkdm_missing_idle_reporting(oh->clkdm);
1861 r = clkdm_hwmod_enable(oh->clkdm, oh); 2012 r = clkdm_hwmod_enable(oh->clkdm, oh);
1862 if (r) { 2013 if (r) {
1863 WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n", 2014 WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
@@ -1919,7 +2070,7 @@ static int _idle(struct omap_hwmod *oh)
1919 return -EINVAL; 2070 return -EINVAL;
1920 } 2071 }
1921 2072
1922 if (_are_any_hardreset_lines_asserted(oh)) 2073 if (_are_all_hardreset_lines_asserted(oh))
1923 return 0; 2074 return 0;
1924 2075
1925 if (oh->class->sysc) 2076 if (oh->class->sysc)
@@ -2007,7 +2158,7 @@ static int _shutdown(struct omap_hwmod *oh)
2007 return -EINVAL; 2158 return -EINVAL;
2008 } 2159 }
2009 2160
2010 if (_are_any_hardreset_lines_asserted(oh)) 2161 if (_are_all_hardreset_lines_asserted(oh))
2011 return 0; 2162 return 0;
2012 2163
2013 pr_debug("omap_hwmod: %s: disabling\n", oh->name); 2164 pr_debug("omap_hwmod: %s: disabling\n", oh->name);
@@ -2531,10 +2682,10 @@ static int _omap2_wait_target_ready(struct omap_hwmod *oh)
2531 */ 2682 */
2532static int _omap4_wait_target_ready(struct omap_hwmod *oh) 2683static int _omap4_wait_target_ready(struct omap_hwmod *oh)
2533{ 2684{
2534 if (!oh || !oh->clkdm) 2685 if (!oh)
2535 return -EINVAL; 2686 return -EINVAL;
2536 2687
2537 if (oh->flags & HWMOD_NO_IDLEST) 2688 if (oh->flags & HWMOD_NO_IDLEST || !oh->clkdm)
2538 return 0; 2689 return 0;
2539 2690
2540 if (!_find_mpu_rt_port(oh)) 2691 if (!_find_mpu_rt_port(oh))
@@ -2549,6 +2700,33 @@ static int _omap4_wait_target_ready(struct omap_hwmod *oh)
2549} 2700}
2550 2701
2551/** 2702/**
2703 * _am33xx_wait_target_ready - wait for a module to leave slave idle
2704 * @oh: struct omap_hwmod *
2705 *
2706 * Wait for a module @oh to leave slave idle. Returns 0 if the module
2707 * does not have an IDLEST bit or if the module successfully leaves
2708 * slave idle; otherwise, pass along the return value of the
2709 * appropriate *_cm*_wait_module_ready() function.
2710 */
2711static int _am33xx_wait_target_ready(struct omap_hwmod *oh)
2712{
2713 if (!oh || !oh->clkdm)
2714 return -EINVAL;
2715
2716 if (oh->flags & HWMOD_NO_IDLEST)
2717 return 0;
2718
2719 if (!_find_mpu_rt_port(oh))
2720 return 0;
2721
2722 /* XXX check module SIDLEMODE, hardreset status */
2723
2724 return am33xx_cm_wait_module_ready(oh->clkdm->cm_inst,
2725 oh->clkdm->clkdm_offs,
2726 oh->prcm.omap4.clkctrl_offs);
2727}
2728
2729/**
2552 * _omap2_assert_hardreset - call OMAP2 PRM hardreset fn with hwmod args 2730 * _omap2_assert_hardreset - call OMAP2 PRM hardreset fn with hwmod args
2553 * @oh: struct omap_hwmod * to assert hardreset 2731 * @oh: struct omap_hwmod * to assert hardreset
2554 * @ohri: hardreset line data 2732 * @ohri: hardreset line data
@@ -2679,6 +2857,72 @@ static int _omap4_is_hardreset_asserted(struct omap_hwmod *oh,
2679 oh->prcm.omap4.rstctrl_offs); 2857 oh->prcm.omap4.rstctrl_offs);
2680} 2858}
2681 2859
2860/**
2861 * _am33xx_assert_hardreset - call AM33XX PRM hardreset fn with hwmod args
2862 * @oh: struct omap_hwmod * to assert hardreset
2863 * @ohri: hardreset line data
2864 *
2865 * Call am33xx_prminst_assert_hardreset() with parameters extracted
2866 * from the hwmod @oh and the hardreset line data @ohri. Only
2867 * intended for use as an soc_ops function pointer. Passes along the
2868 * return value from am33xx_prminst_assert_hardreset(). XXX This
2869 * function is scheduled for removal when the PRM code is moved into
2870 * drivers/.
2871 */
2872static int _am33xx_assert_hardreset(struct omap_hwmod *oh,
2873 struct omap_hwmod_rst_info *ohri)
2874
2875{
2876 return am33xx_prm_assert_hardreset(ohri->rst_shift,
2877 oh->clkdm->pwrdm.ptr->prcm_offs,
2878 oh->prcm.omap4.rstctrl_offs);
2879}
2880
2881/**
2882 * _am33xx_deassert_hardreset - call AM33XX PRM hardreset fn with hwmod args
2883 * @oh: struct omap_hwmod * to deassert hardreset
2884 * @ohri: hardreset line data
2885 *
2886 * Call am33xx_prminst_deassert_hardreset() with parameters extracted
2887 * from the hwmod @oh and the hardreset line data @ohri. Only
2888 * intended for use as an soc_ops function pointer. Passes along the
2889 * return value from am33xx_prminst_deassert_hardreset(). XXX This
2890 * function is scheduled for removal when the PRM code is moved into
2891 * drivers/.
2892 */
2893static int _am33xx_deassert_hardreset(struct omap_hwmod *oh,
2894 struct omap_hwmod_rst_info *ohri)
2895{
2896 if (ohri->st_shift)
2897 pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
2898 oh->name, ohri->name);
2899
2900 return am33xx_prm_deassert_hardreset(ohri->rst_shift,
2901 oh->clkdm->pwrdm.ptr->prcm_offs,
2902 oh->prcm.omap4.rstctrl_offs,
2903 oh->prcm.omap4.rstst_offs);
2904}
2905
2906/**
2907 * _am33xx_is_hardreset_asserted - call AM33XX PRM hardreset fn with hwmod args
2908 * @oh: struct omap_hwmod * to test hardreset
2909 * @ohri: hardreset line data
2910 *
2911 * Call am33xx_prminst_is_hardreset_asserted() with parameters
2912 * extracted from the hwmod @oh and the hardreset line data @ohri.
2913 * Only intended for use as an soc_ops function pointer. Passes along
2914 * the return value from am33xx_prminst_is_hardreset_asserted(). XXX
2915 * This function is scheduled for removal when the PRM code is moved
2916 * into drivers/.
2917 */
2918static int _am33xx_is_hardreset_asserted(struct omap_hwmod *oh,
2919 struct omap_hwmod_rst_info *ohri)
2920{
2921 return am33xx_prm_is_hardreset_asserted(ohri->rst_shift,
2922 oh->clkdm->pwrdm.ptr->prcm_offs,
2923 oh->prcm.omap4.rstctrl_offs);
2924}
2925
2682/* Public functions */ 2926/* Public functions */
2683 2927
2684u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs) 2928u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs)
@@ -3678,6 +3922,14 @@ void __init omap_hwmod_init(void)
3678 soc_ops.deassert_hardreset = _omap4_deassert_hardreset; 3922 soc_ops.deassert_hardreset = _omap4_deassert_hardreset;
3679 soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; 3923 soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
3680 soc_ops.init_clkdm = _init_clkdm; 3924 soc_ops.init_clkdm = _init_clkdm;
3925 } else if (soc_is_am33xx()) {
3926 soc_ops.enable_module = _am33xx_enable_module;
3927 soc_ops.disable_module = _am33xx_disable_module;
3928 soc_ops.wait_target_ready = _am33xx_wait_target_ready;
3929 soc_ops.assert_hardreset = _am33xx_assert_hardreset;
3930 soc_ops.deassert_hardreset = _am33xx_deassert_hardreset;
3931 soc_ops.is_hardreset_asserted = _am33xx_is_hardreset_asserted;
3932 soc_ops.init_clkdm = _init_clkdm;
3681 } else { 3933 } else {
3682 WARN(1, "omap_hwmod: unknown SoC type\n"); 3934 WARN(1, "omap_hwmod: unknown SoC type\n");
3683 } 3935 }