diff options
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 137 |
1 files changed, 80 insertions, 57 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 5b07ad0251d..503832e20d5 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -1769,6 +1769,56 @@ static int _shutdown(struct omap_hwmod *oh) | |||
1769 | } | 1769 | } |
1770 | 1770 | ||
1771 | /** | 1771 | /** |
1772 | * _init_mpu_rt_base - populate the virtual address for a hwmod | ||
1773 | * @oh: struct omap_hwmod * to locate the virtual address | ||
1774 | * | ||
1775 | * Cache the virtual address used by the MPU to access this IP block's | ||
1776 | * registers. This address is needed early so the OCP registers that | ||
1777 | * are part of the device's address space can be ioremapped properly. | ||
1778 | * No return value. | ||
1779 | */ | ||
1780 | static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data) | ||
1781 | { | ||
1782 | if (oh->_int_flags & _HWMOD_NO_MPU_PORT) | ||
1783 | return; | ||
1784 | |||
1785 | oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index); | ||
1786 | } | ||
1787 | |||
1788 | /** | ||
1789 | * _init - initialize internal data for the hwmod @oh | ||
1790 | * @oh: struct omap_hwmod * | ||
1791 | * @n: (unused) | ||
1792 | * | ||
1793 | * Look up the clocks and the address space used by the MPU to access | ||
1794 | * registers belonging to the hwmod @oh. @oh must already be | ||
1795 | * registered at this point. This is the first of two phases for | ||
1796 | * hwmod initialization. Code called here does not touch any hardware | ||
1797 | * registers, it simply prepares internal data structures. Returns 0 | ||
1798 | * upon success or if the hwmod isn't registered, or -EINVAL upon | ||
1799 | * failure. | ||
1800 | */ | ||
1801 | static int __init _init(struct omap_hwmod *oh, void *data) | ||
1802 | { | ||
1803 | int r; | ||
1804 | |||
1805 | if (oh->_state != _HWMOD_STATE_REGISTERED) | ||
1806 | return 0; | ||
1807 | |||
1808 | _init_mpu_rt_base(oh, NULL); | ||
1809 | |||
1810 | r = _init_clocks(oh, NULL); | ||
1811 | if (IS_ERR_VALUE(r)) { | ||
1812 | WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh->name); | ||
1813 | return -EINVAL; | ||
1814 | } | ||
1815 | |||
1816 | oh->_state = _HWMOD_STATE_INITIALIZED; | ||
1817 | |||
1818 | return 0; | ||
1819 | } | ||
1820 | |||
1821 | /** | ||
1772 | * _setup - do initial configuration of omap_hwmod | 1822 | * _setup - do initial configuration of omap_hwmod |
1773 | * @oh: struct omap_hwmod * | 1823 | * @oh: struct omap_hwmod * |
1774 | * | 1824 | * |
@@ -1780,7 +1830,7 @@ static int _setup(struct omap_hwmod *oh, void *data) | |||
1780 | int i, r; | 1830 | int i, r; |
1781 | u8 postsetup_state; | 1831 | u8 postsetup_state; |
1782 | 1832 | ||
1783 | if (oh->_state != _HWMOD_STATE_CLKS_INITED) | 1833 | if (oh->_state != _HWMOD_STATE_INITIALIZED) |
1784 | return 0; | 1834 | return 0; |
1785 | 1835 | ||
1786 | /* Set iclk autoidle mode */ | 1836 | /* Set iclk autoidle mode */ |
@@ -2052,96 +2102,69 @@ int __init omap_hwmod_register(struct omap_hwmod **ohs) | |||
2052 | return 0; | 2102 | return 0; |
2053 | } | 2103 | } |
2054 | 2104 | ||
2055 | /* | 2105 | /** |
2056 | * _populate_mpu_rt_base - populate the virtual address for a hwmod | 2106 | * _ensure_mpu_hwmod_is_setup - ensure the MPU SS hwmod is init'ed and set up |
2107 | * @oh: pointer to the hwmod currently being set up (usually not the MPU) | ||
2057 | * | 2108 | * |
2058 | * Must be called only from omap_hwmod_setup_*() so ioremap works properly. | 2109 | * If the hwmod data corresponding to the MPU subsystem IP block |
2059 | * Assumes the caller takes care of locking if needed. | 2110 | * hasn't been initialized and set up yet, do so now. This must be |
2111 | * done first since sleep dependencies may be added from other hwmods | ||
2112 | * to the MPU. Intended to be called only by omap_hwmod_setup*(). No | ||
2113 | * return value. | ||
2060 | */ | 2114 | */ |
2061 | static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data) | 2115 | static void __init _ensure_mpu_hwmod_is_setup(struct omap_hwmod *oh) |
2062 | { | 2116 | { |
2063 | if (oh->_state != _HWMOD_STATE_REGISTERED) | 2117 | if (!mpu_oh || mpu_oh->_state == _HWMOD_STATE_UNKNOWN) |
2064 | return 0; | 2118 | pr_err("omap_hwmod: %s: MPU initiator hwmod %s not yet registered\n", |
2065 | 2119 | __func__, MPU_INITIATOR_NAME); | |
2066 | if (oh->_int_flags & _HWMOD_NO_MPU_PORT) | 2120 | else if (mpu_oh->_state == _HWMOD_STATE_REGISTERED && oh != mpu_oh) |
2067 | return 0; | 2121 | omap_hwmod_setup_one(MPU_INITIATOR_NAME); |
2068 | |||
2069 | oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index); | ||
2070 | |||
2071 | return 0; | ||
2072 | } | 2122 | } |
2073 | 2123 | ||
2074 | /** | 2124 | /** |
2075 | * omap_hwmod_setup_one - set up a single hwmod | 2125 | * omap_hwmod_setup_one - set up a single hwmod |
2076 | * @oh_name: const char * name of the already-registered hwmod to set up | 2126 | * @oh_name: const char * name of the already-registered hwmod to set up |
2077 | * | 2127 | * |
2078 | * Must be called after omap2_clk_init(). Resolves the struct clk | 2128 | * Initialize and set up a single hwmod. Intended to be used for a |
2079 | * names to struct clk pointers for each registered omap_hwmod. Also | 2129 | * small number of early devices, such as the timer IP blocks used for |
2080 | * calls _setup() on each hwmod. Returns -EINVAL upon error or 0 upon | 2130 | * the scheduler clock. Must be called after omap2_clk_init(). |
2081 | * success. | 2131 | * Resolves the struct clk names to struct clk pointers for each |
2132 | * registered omap_hwmod. Also calls _setup() on each hwmod. Returns | ||
2133 | * -EINVAL upon error or 0 upon success. | ||
2082 | */ | 2134 | */ |
2083 | int __init omap_hwmod_setup_one(const char *oh_name) | 2135 | int __init omap_hwmod_setup_one(const char *oh_name) |
2084 | { | 2136 | { |
2085 | struct omap_hwmod *oh; | 2137 | struct omap_hwmod *oh; |
2086 | int r; | ||
2087 | 2138 | ||
2088 | pr_debug("omap_hwmod: %s: %s\n", oh_name, __func__); | 2139 | pr_debug("omap_hwmod: %s: %s\n", oh_name, __func__); |
2089 | 2140 | ||
2090 | if (!mpu_oh) { | ||
2091 | pr_err("omap_hwmod: %s: cannot setup_one: MPU initiator hwmod %s not yet registered\n", | ||
2092 | oh_name, MPU_INITIATOR_NAME); | ||
2093 | return -EINVAL; | ||
2094 | } | ||
2095 | |||
2096 | oh = _lookup(oh_name); | 2141 | oh = _lookup(oh_name); |
2097 | if (!oh) { | 2142 | if (!oh) { |
2098 | WARN(1, "omap_hwmod: %s: hwmod not yet registered\n", oh_name); | 2143 | WARN(1, "omap_hwmod: %s: hwmod not yet registered\n", oh_name); |
2099 | return -EINVAL; | 2144 | return -EINVAL; |
2100 | } | 2145 | } |
2101 | 2146 | ||
2102 | if (mpu_oh->_state == _HWMOD_STATE_REGISTERED && oh != mpu_oh) | 2147 | _ensure_mpu_hwmod_is_setup(oh); |
2103 | omap_hwmod_setup_one(MPU_INITIATOR_NAME); | ||
2104 | |||
2105 | r = _populate_mpu_rt_base(oh, NULL); | ||
2106 | if (IS_ERR_VALUE(r)) { | ||
2107 | WARN(1, "omap_hwmod: %s: couldn't set mpu_rt_base\n", oh_name); | ||
2108 | return -EINVAL; | ||
2109 | } | ||
2110 | |||
2111 | r = _init_clocks(oh, NULL); | ||
2112 | if (IS_ERR_VALUE(r)) { | ||
2113 | WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh_name); | ||
2114 | return -EINVAL; | ||
2115 | } | ||
2116 | 2148 | ||
2149 | _init(oh, NULL); | ||
2117 | _setup(oh, NULL); | 2150 | _setup(oh, NULL); |
2118 | 2151 | ||
2119 | return 0; | 2152 | return 0; |
2120 | } | 2153 | } |
2121 | 2154 | ||
2122 | /** | 2155 | /** |
2123 | * omap_hwmod_setup - do some post-clock framework initialization | 2156 | * omap_hwmod_setup_all - set up all registered IP blocks |
2124 | * | 2157 | * |
2125 | * Must be called after omap2_clk_init(). Resolves the struct clk names | 2158 | * Initialize and set up all IP blocks registered with the hwmod code. |
2126 | * to struct clk pointers for each registered omap_hwmod. Also calls | 2159 | * Must be called after omap2_clk_init(). Resolves the struct clk |
2127 | * _setup() on each hwmod. Returns 0 upon success. | 2160 | * names to struct clk pointers for each registered omap_hwmod. Also |
2161 | * calls _setup() on each hwmod. Returns 0 upon success. | ||
2128 | */ | 2162 | */ |
2129 | static int __init omap_hwmod_setup_all(void) | 2163 | static int __init omap_hwmod_setup_all(void) |
2130 | { | 2164 | { |
2131 | int r; | 2165 | _ensure_mpu_hwmod_is_setup(NULL); |
2132 | |||
2133 | if (!mpu_oh) { | ||
2134 | pr_err("omap_hwmod: %s: MPU initiator hwmod %s not yet registered\n", | ||
2135 | __func__, MPU_INITIATOR_NAME); | ||
2136 | return -EINVAL; | ||
2137 | } | ||
2138 | |||
2139 | r = omap_hwmod_for_each(_populate_mpu_rt_base, NULL); | ||
2140 | |||
2141 | r = omap_hwmod_for_each(_init_clocks, NULL); | ||
2142 | WARN(IS_ERR_VALUE(r), | ||
2143 | "omap_hwmod: %s: _init_clocks failed\n", __func__); | ||
2144 | 2166 | ||
2167 | omap_hwmod_for_each(_init, NULL); | ||
2145 | omap_hwmod_for_each(_setup, NULL); | 2168 | omap_hwmod_for_each(_setup, NULL); |
2146 | 2169 | ||
2147 | return 0; | 2170 | return 0; |