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.c483
1 files changed, 292 insertions, 191 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 5a30658444d0..e282e35769fd 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -116,7 +116,6 @@
116 * - Open Core Protocol Specification 2.2 116 * - Open Core Protocol Specification 2.2
117 * 117 *
118 * To do: 118 * To do:
119 * - pin mux handling
120 * - handle IO mapping 119 * - handle IO mapping
121 * - bus throughput & module latency measurement code 120 * - bus throughput & module latency measurement code
122 * 121 *
@@ -135,17 +134,21 @@
135#include <linux/err.h> 134#include <linux/err.h>
136#include <linux/list.h> 135#include <linux/list.h>
137#include <linux/mutex.h> 136#include <linux/mutex.h>
137#include <linux/spinlock.h>
138 138
139#include <plat/common.h> 139#include <plat/common.h>
140#include <plat/cpu.h> 140#include <plat/cpu.h>
141#include <plat/clockdomain.h> 141#include "clockdomain.h"
142#include <plat/powerdomain.h> 142#include "powerdomain.h"
143#include <plat/clock.h> 143#include <plat/clock.h>
144#include <plat/omap_hwmod.h> 144#include <plat/omap_hwmod.h>
145#include <plat/prcm.h> 145#include <plat/prcm.h>
146 146
147#include "cm.h" 147#include "cm2xxx_3xxx.h"
148#include "prm.h" 148#include "cm44xx.h"
149#include "prm2xxx_3xxx.h"
150#include "prm44xx.h"
151#include "mux.h"
149 152
150/* Maximum microseconds to wait for OMAP module to softreset */ 153/* Maximum microseconds to wait for OMAP module to softreset */
151#define MAX_MODULE_SOFTRESET_WAIT 10000 154#define MAX_MODULE_SOFTRESET_WAIT 10000
@@ -156,8 +159,6 @@
156/* omap_hwmod_list contains all registered struct omap_hwmods */ 159/* omap_hwmod_list contains all registered struct omap_hwmods */
157static LIST_HEAD(omap_hwmod_list); 160static LIST_HEAD(omap_hwmod_list);
158 161
159static DEFINE_MUTEX(omap_hwmod_mutex);
160
161/* mpu_oh: used to add/remove MPU initiator from sleepdep list */ 162/* mpu_oh: used to add/remove MPU initiator from sleepdep list */
162static struct omap_hwmod *mpu_oh; 163static struct omap_hwmod *mpu_oh;
163 164
@@ -209,10 +210,9 @@ static void _write_sysconfig(u32 v, struct omap_hwmod *oh)
209 210
210 /* XXX ensure module interface clock is up */ 211 /* XXX ensure module interface clock is up */
211 212
212 if (oh->_sysc_cache != v) { 213 /* Module might have lost context, always update cache and register */
213 oh->_sysc_cache = v; 214 oh->_sysc_cache = v;
214 omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs); 215 omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
215 }
216} 216}
217 217
218/** 218/**
@@ -388,12 +388,13 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
388 * Allow the hardware module @oh to send wakeups. Returns -EINVAL 388 * Allow the hardware module @oh to send wakeups. Returns -EINVAL
389 * upon error or 0 upon success. 389 * upon error or 0 upon success.
390 */ 390 */
391static int _enable_wakeup(struct omap_hwmod *oh) 391static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
392{ 392{
393 u32 v, wakeup_mask; 393 u32 wakeup_mask;
394 394
395 if (!oh->class->sysc || 395 if (!oh->class->sysc ||
396 !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) 396 !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
397 (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)))
397 return -EINVAL; 398 return -EINVAL;
398 399
399 if (!oh->class->sysc->sysc_fields) { 400 if (!oh->class->sysc->sysc_fields) {
@@ -403,9 +404,10 @@ static int _enable_wakeup(struct omap_hwmod *oh)
403 404
404 wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift); 405 wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
405 406
406 v = oh->_sysc_cache; 407 *v |= wakeup_mask;
407 v |= wakeup_mask; 408
408 _write_sysconfig(v, oh); 409 if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
410 _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
409 411
410 /* XXX test pwrdm_get_wken for this hwmod's subsystem */ 412 /* XXX test pwrdm_get_wken for this hwmod's subsystem */
411 413
@@ -421,12 +423,13 @@ static int _enable_wakeup(struct omap_hwmod *oh)
421 * Prevent the hardware module @oh to send wakeups. Returns -EINVAL 423 * Prevent the hardware module @oh to send wakeups. Returns -EINVAL
422 * upon error or 0 upon success. 424 * upon error or 0 upon success.
423 */ 425 */
424static int _disable_wakeup(struct omap_hwmod *oh) 426static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
425{ 427{
426 u32 v, wakeup_mask; 428 u32 wakeup_mask;
427 429
428 if (!oh->class->sysc || 430 if (!oh->class->sysc ||
429 !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) 431 !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
432 (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)))
430 return -EINVAL; 433 return -EINVAL;
431 434
432 if (!oh->class->sysc->sysc_fields) { 435 if (!oh->class->sysc->sysc_fields) {
@@ -436,9 +439,10 @@ static int _disable_wakeup(struct omap_hwmod *oh)
436 439
437 wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift); 440 wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
438 441
439 v = oh->_sysc_cache; 442 *v &= ~wakeup_mask;
440 v &= ~wakeup_mask; 443
441 _write_sysconfig(v, oh); 444 if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
445 _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v);
442 446
443 /* XXX test pwrdm_get_wken for this hwmod's subsystem */ 447 /* XXX test pwrdm_get_wken for this hwmod's subsystem */
444 448
@@ -675,7 +679,7 @@ static void _disable_optional_clocks(struct omap_hwmod *oh)
675 * Returns the array index of the OCP slave port that the MPU 679 * Returns the array index of the OCP slave port that the MPU
676 * addresses the device on, or -EINVAL upon error or not found. 680 * addresses the device on, or -EINVAL upon error or not found.
677 */ 681 */
678static int _find_mpu_port_index(struct omap_hwmod *oh) 682static int __init _find_mpu_port_index(struct omap_hwmod *oh)
679{ 683{
680 int i; 684 int i;
681 int found = 0; 685 int found = 0;
@@ -709,7 +713,7 @@ static int _find_mpu_port_index(struct omap_hwmod *oh)
709 * Return the virtual address of the base of the register target of 713 * Return the virtual address of the base of the register target of
710 * device @oh, or NULL on error. 714 * device @oh, or NULL on error.
711 */ 715 */
712static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index) 716static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
713{ 717{
714 struct omap_hwmod_ocp_if *os; 718 struct omap_hwmod_ocp_if *os;
715 struct omap_hwmod_addr_space *mem; 719 struct omap_hwmod_addr_space *mem;
@@ -786,11 +790,11 @@ static void _enable_sysc(struct omap_hwmod *oh)
786 (sf & SYSC_HAS_CLOCKACTIVITY)) 790 (sf & SYSC_HAS_CLOCKACTIVITY))
787 _set_clockactivity(oh, oh->class->sysc->clockact, &v); 791 _set_clockactivity(oh, oh->class->sysc->clockact, &v);
788 792
789 _write_sysconfig(v, oh);
790
791 /* If slave is in SMARTIDLE, also enable wakeup */ 793 /* If slave is in SMARTIDLE, also enable wakeup */
792 if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE)) 794 if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
793 _enable_wakeup(oh); 795 _enable_wakeup(oh, &v);
796
797 _write_sysconfig(v, oh);
794 798
795 /* 799 /*
796 * Set the autoidle bit only after setting the smartidle bit 800 * Set the autoidle bit only after setting the smartidle bit
@@ -836,6 +840,10 @@ static void _idle_sysc(struct omap_hwmod *oh)
836 _set_master_standbymode(oh, idlemode, &v); 840 _set_master_standbymode(oh, idlemode, &v);
837 } 841 }
838 842
843 /* If slave is in SMARTIDLE, also enable wakeup */
844 if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
845 _enable_wakeup(oh, &v);
846
839 _write_sysconfig(v, oh); 847 _write_sysconfig(v, oh);
840} 848}
841 849
@@ -874,7 +882,6 @@ static void _shutdown_sysc(struct omap_hwmod *oh)
874 * @name: find an omap_hwmod by name 882 * @name: find an omap_hwmod by name
875 * 883 *
876 * Return a pointer to an omap_hwmod by name, or NULL if not found. 884 * Return a pointer to an omap_hwmod by name, or NULL if not found.
877 * Caller must hold omap_hwmod_mutex.
878 */ 885 */
879static struct omap_hwmod *_lookup(const char *name) 886static struct omap_hwmod *_lookup(const char *name)
880{ 887{
@@ -1089,7 +1096,7 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
1089} 1096}
1090 1097
1091/** 1098/**
1092 * _reset - reset an omap_hwmod 1099 * _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit
1093 * @oh: struct omap_hwmod * 1100 * @oh: struct omap_hwmod *
1094 * 1101 *
1095 * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be 1102 * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be
@@ -1098,12 +1105,13 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
1098 * the module did not reset in time, or 0 upon success. 1105 * the module did not reset in time, or 0 upon success.
1099 * 1106 *
1100 * In OMAP3 a specific SYSSTATUS register is used to get the reset status. 1107 * In OMAP3 a specific SYSSTATUS register is used to get the reset status.
1101 * Starting in OMAP4, some IPs does not have SYSSTATUS register and instead 1108 * Starting in OMAP4, some IPs do not have SYSSTATUS registers and instead
1102 * use the SYSCONFIG softreset bit to provide the status. 1109 * use the SYSCONFIG softreset bit to provide the status.
1103 * 1110 *
1104 * Note that some IP like McBSP does have a reset control but no reset status. 1111 * Note that some IP like McBSP do have reset control but don't have
1112 * reset status.
1105 */ 1113 */
1106static int _reset(struct omap_hwmod *oh) 1114static int _ocp_softreset(struct omap_hwmod *oh)
1107{ 1115{
1108 u32 v; 1116 u32 v;
1109 int c = 0; 1117 int c = 0;
@@ -1124,7 +1132,7 @@ static int _reset(struct omap_hwmod *oh)
1124 if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET) 1132 if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
1125 _enable_optional_clocks(oh); 1133 _enable_optional_clocks(oh);
1126 1134
1127 pr_debug("omap_hwmod: %s: resetting\n", oh->name); 1135 pr_debug("omap_hwmod: %s: resetting via OCP SOFTRESET\n", oh->name);
1128 1136
1129 v = oh->_sysc_cache; 1137 v = oh->_sysc_cache;
1130 ret = _set_softreset(oh, &v); 1138 ret = _set_softreset(oh, &v);
@@ -1164,17 +1172,41 @@ dis_opt_clks:
1164} 1172}
1165 1173
1166/** 1174/**
1167 * _omap_hwmod_enable - enable an omap_hwmod 1175 * _reset - reset an omap_hwmod
1176 * @oh: struct omap_hwmod *
1177 *
1178 * Resets an omap_hwmod @oh. The default software reset mechanism for
1179 * most OMAP IP blocks is triggered via the OCP_SYSCONFIG.SOFTRESET
1180 * bit. However, some hwmods cannot be reset via this method: some
1181 * are not targets and therefore have no OCP header registers to
1182 * access; others (like the IVA) have idiosyncratic reset sequences.
1183 * So for these relatively rare cases, custom reset code can be
1184 * supplied in the struct omap_hwmod_class .reset function pointer.
1185 * Passes along the return value from either _reset() or the custom
1186 * reset function - these must return -EINVAL if the hwmod cannot be
1187 * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if
1188 * the module did not reset in time, or 0 upon success.
1189 */
1190static int _reset(struct omap_hwmod *oh)
1191{
1192 int ret;
1193
1194 pr_debug("omap_hwmod: %s: resetting\n", oh->name);
1195
1196 ret = (oh->class->reset) ? oh->class->reset(oh) : _ocp_softreset(oh);
1197
1198 return ret;
1199}
1200
1201/**
1202 * _enable - enable an omap_hwmod
1168 * @oh: struct omap_hwmod * 1203 * @oh: struct omap_hwmod *
1169 * 1204 *
1170 * Enables an omap_hwmod @oh such that the MPU can access the hwmod's 1205 * Enables an omap_hwmod @oh such that the MPU can access the hwmod's
1171 * register target. (This function has a full name -- 1206 * register target. Returns -EINVAL if the hwmod is in the wrong
1172 * _omap_hwmod_enable() rather than simply _enable() -- because it is 1207 * state or passes along the return value of _wait_target_ready().
1173 * currently required by the pm34xx.c idle loop.) Returns -EINVAL if
1174 * the hwmod is in the wrong state or passes along the return value of
1175 * _wait_target_ready().
1176 */ 1208 */
1177int _omap_hwmod_enable(struct omap_hwmod *oh) 1209static int _enable(struct omap_hwmod *oh)
1178{ 1210{
1179 int r; 1211 int r;
1180 1212
@@ -1197,7 +1229,9 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
1197 oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1) 1229 oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
1198 _deassert_hardreset(oh, oh->rst_lines[0].name); 1230 _deassert_hardreset(oh, oh->rst_lines[0].name);
1199 1231
1200 /* XXX mux balls */ 1232 /* Mux pins for device runtime if populated */
1233 if (oh->mux)
1234 omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
1201 1235
1202 _add_initiator_dep(oh, mpu_oh); 1236 _add_initiator_dep(oh, mpu_oh);
1203 _enable_clocks(oh); 1237 _enable_clocks(oh);
@@ -1213,6 +1247,7 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
1213 _enable_sysc(oh); 1247 _enable_sysc(oh);
1214 } 1248 }
1215 } else { 1249 } else {
1250 _disable_clocks(oh);
1216 pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", 1251 pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
1217 oh->name, r); 1252 oh->name, r);
1218 } 1253 }
@@ -1221,16 +1256,14 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
1221} 1256}
1222 1257
1223/** 1258/**
1224 * _omap_hwmod_idle - idle an omap_hwmod 1259 * _idle - idle an omap_hwmod
1225 * @oh: struct omap_hwmod * 1260 * @oh: struct omap_hwmod *
1226 * 1261 *
1227 * Idles an omap_hwmod @oh. This should be called once the hwmod has 1262 * Idles an omap_hwmod @oh. This should be called once the hwmod has
1228 * no further work. (This function has a full name -- 1263 * no further work. Returns -EINVAL if the hwmod is in the wrong
1229 * _omap_hwmod_idle() rather than simply _idle() -- because it is 1264 * state or returns 0.
1230 * currently required by the pm34xx.c idle loop.) Returns -EINVAL if
1231 * the hwmod is in the wrong state or returns 0.
1232 */ 1265 */
1233int _omap_hwmod_idle(struct omap_hwmod *oh) 1266static int _idle(struct omap_hwmod *oh)
1234{ 1267{
1235 if (oh->_state != _HWMOD_STATE_ENABLED) { 1268 if (oh->_state != _HWMOD_STATE_ENABLED) {
1236 WARN(1, "omap_hwmod: %s: idle state can only be entered from " 1269 WARN(1, "omap_hwmod: %s: idle state can only be entered from "
@@ -1245,6 +1278,10 @@ int _omap_hwmod_idle(struct omap_hwmod *oh)
1245 _del_initiator_dep(oh, mpu_oh); 1278 _del_initiator_dep(oh, mpu_oh);
1246 _disable_clocks(oh); 1279 _disable_clocks(oh);
1247 1280
1281 /* Mux pins for device idle if populated */
1282 if (oh->mux)
1283 omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
1284
1248 oh->_state = _HWMOD_STATE_IDLE; 1285 oh->_state = _HWMOD_STATE_IDLE;
1249 1286
1250 return 0; 1287 return 0;
@@ -1261,6 +1298,9 @@ int _omap_hwmod_idle(struct omap_hwmod *oh)
1261 */ 1298 */
1262static int _shutdown(struct omap_hwmod *oh) 1299static int _shutdown(struct omap_hwmod *oh)
1263{ 1300{
1301 int ret;
1302 u8 prev_state;
1303
1264 if (oh->_state != _HWMOD_STATE_IDLE && 1304 if (oh->_state != _HWMOD_STATE_IDLE &&
1265 oh->_state != _HWMOD_STATE_ENABLED) { 1305 oh->_state != _HWMOD_STATE_ENABLED) {
1266 WARN(1, "omap_hwmod: %s: disabled state can only be entered " 1306 WARN(1, "omap_hwmod: %s: disabled state can only be entered "
@@ -1270,6 +1310,18 @@ static int _shutdown(struct omap_hwmod *oh)
1270 1310
1271 pr_debug("omap_hwmod: %s: disabling\n", oh->name); 1311 pr_debug("omap_hwmod: %s: disabling\n", oh->name);
1272 1312
1313 if (oh->class->pre_shutdown) {
1314 prev_state = oh->_state;
1315 if (oh->_state == _HWMOD_STATE_IDLE)
1316 _enable(oh);
1317 ret = oh->class->pre_shutdown(oh);
1318 if (ret) {
1319 if (prev_state == _HWMOD_STATE_IDLE)
1320 _idle(oh);
1321 return ret;
1322 }
1323 }
1324
1273 if (oh->class->sysc) 1325 if (oh->class->sysc)
1274 _shutdown_sysc(oh); 1326 _shutdown_sysc(oh);
1275 1327
@@ -1288,7 +1340,9 @@ static int _shutdown(struct omap_hwmod *oh)
1288 } 1340 }
1289 /* XXX Should this code also force-disable the optional clocks? */ 1341 /* XXX Should this code also force-disable the optional clocks? */
1290 1342
1291 /* XXX mux any associated balls to safe mode */ 1343 /* Mux pins to safe mode or use populated off mode values */
1344 if (oh->mux)
1345 omap_hwmod_mux(oh->mux, _HWMOD_STATE_DISABLED);
1292 1346
1293 oh->_state = _HWMOD_STATE_DISABLED; 1347 oh->_state = _HWMOD_STATE_DISABLED;
1294 1348
@@ -1298,23 +1352,15 @@ static int _shutdown(struct omap_hwmod *oh)
1298/** 1352/**
1299 * _setup - do initial configuration of omap_hwmod 1353 * _setup - do initial configuration of omap_hwmod
1300 * @oh: struct omap_hwmod * 1354 * @oh: struct omap_hwmod *
1301 * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
1302 * 1355 *
1303 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh 1356 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
1304 * OCP_SYSCONFIG register. @skip_setup_idle is intended to be used on 1357 * OCP_SYSCONFIG register. Returns -EINVAL if the hwmod is in the
1305 * a system that will not call omap_hwmod_enable() to enable devices 1358 * wrong state or returns 0.
1306 * (e.g., a system without PM runtime). Returns -EINVAL if the hwmod
1307 * is in the wrong state or returns 0.
1308 */ 1359 */
1309static int _setup(struct omap_hwmod *oh, void *data) 1360static int _setup(struct omap_hwmod *oh, void *data)
1310{ 1361{
1311 int i, r; 1362 int i, r;
1312 u8 skip_setup_idle; 1363 u8 postsetup_state;
1313
1314 if (!oh || !data)
1315 return -EINVAL;
1316
1317 skip_setup_idle = *(u8 *)data;
1318 1364
1319 /* Set iclk autoidle mode */ 1365 /* Set iclk autoidle mode */
1320 if (oh->slaves_cnt > 0) { 1366 if (oh->slaves_cnt > 0) {
@@ -1334,7 +1380,6 @@ static int _setup(struct omap_hwmod *oh, void *data)
1334 } 1380 }
1335 } 1381 }
1336 1382
1337 mutex_init(&oh->_mutex);
1338 oh->_state = _HWMOD_STATE_INITIALIZED; 1383 oh->_state = _HWMOD_STATE_INITIALIZED;
1339 1384
1340 /* 1385 /*
@@ -1347,7 +1392,7 @@ static int _setup(struct omap_hwmod *oh, void *data)
1347 if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt == 1) 1392 if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt == 1)
1348 return 0; 1393 return 0;
1349 1394
1350 r = _omap_hwmod_enable(oh); 1395 r = _enable(oh);
1351 if (r) { 1396 if (r) {
1352 pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n", 1397 pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
1353 oh->name, oh->_state); 1398 oh->name, oh->_state);
@@ -1359,7 +1404,7 @@ static int _setup(struct omap_hwmod *oh, void *data)
1359 1404
1360 /* 1405 /*
1361 * OCP_SYSCONFIG bits need to be reprogrammed after a softreset. 1406 * OCP_SYSCONFIG bits need to be reprogrammed after a softreset.
1362 * The _omap_hwmod_enable() function should be split to 1407 * The _enable() function should be split to
1363 * avoid the rewrite of the OCP_SYSCONFIG register. 1408 * avoid the rewrite of the OCP_SYSCONFIG register.
1364 */ 1409 */
1365 if (oh->class->sysc) { 1410 if (oh->class->sysc) {
@@ -1368,12 +1413,77 @@ static int _setup(struct omap_hwmod *oh, void *data)
1368 } 1413 }
1369 } 1414 }
1370 1415
1371 if (!(oh->flags & HWMOD_INIT_NO_IDLE) && !skip_setup_idle) 1416 postsetup_state = oh->_postsetup_state;
1372 _omap_hwmod_idle(oh); 1417 if (postsetup_state == _HWMOD_STATE_UNKNOWN)
1418 postsetup_state = _HWMOD_STATE_ENABLED;
1419
1420 /*
1421 * XXX HWMOD_INIT_NO_IDLE does not belong in hwmod data -
1422 * it should be set by the core code as a runtime flag during startup
1423 */
1424 if ((oh->flags & HWMOD_INIT_NO_IDLE) &&
1425 (postsetup_state == _HWMOD_STATE_IDLE))
1426 postsetup_state = _HWMOD_STATE_ENABLED;
1427
1428 if (postsetup_state == _HWMOD_STATE_IDLE)
1429 _idle(oh);
1430 else if (postsetup_state == _HWMOD_STATE_DISABLED)
1431 _shutdown(oh);
1432 else if (postsetup_state != _HWMOD_STATE_ENABLED)
1433 WARN(1, "hwmod: %s: unknown postsetup state %d! defaulting to enabled\n",
1434 oh->name, postsetup_state);
1373 1435
1374 return 0; 1436 return 0;
1375} 1437}
1376 1438
1439/**
1440 * _register - register a struct omap_hwmod
1441 * @oh: struct omap_hwmod *
1442 *
1443 * Registers the omap_hwmod @oh. Returns -EEXIST if an omap_hwmod
1444 * already has been registered by the same name; -EINVAL if the
1445 * omap_hwmod is in the wrong state, if @oh is NULL, if the
1446 * omap_hwmod's class field is NULL; if the omap_hwmod is missing a
1447 * name, or if the omap_hwmod's class is missing a name; or 0 upon
1448 * success.
1449 *
1450 * XXX The data should be copied into bootmem, so the original data
1451 * should be marked __initdata and freed after init. This would allow
1452 * unneeded omap_hwmods to be freed on multi-OMAP configurations. Note
1453 * that the copy process would be relatively complex due to the large number
1454 * of substructures.
1455 */
1456static int __init _register(struct omap_hwmod *oh)
1457{
1458 int ret, ms_id;
1459
1460 if (!oh || !oh->name || !oh->class || !oh->class->name ||
1461 (oh->_state != _HWMOD_STATE_UNKNOWN))
1462 return -EINVAL;
1463
1464 pr_debug("omap_hwmod: %s: registering\n", oh->name);
1465
1466 if (_lookup(oh->name))
1467 return -EEXIST;
1468
1469 ms_id = _find_mpu_port_index(oh);
1470 if (!IS_ERR_VALUE(ms_id)) {
1471 oh->_mpu_port_index = ms_id;
1472 oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
1473 } else {
1474 oh->_int_flags |= _HWMOD_NO_MPU_PORT;
1475 }
1476
1477 list_add_tail(&oh->node, &omap_hwmod_list);
1478
1479 spin_lock_init(&oh->_lock);
1480
1481 oh->_state = _HWMOD_STATE_REGISTERED;
1482
1483 ret = 0;
1484
1485 return ret;
1486}
1377 1487
1378 1488
1379/* Public functions */ 1489/* Public functions */
@@ -1427,59 +1537,6 @@ int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode)
1427} 1537}
1428 1538
1429/** 1539/**
1430 * omap_hwmod_register - register a struct omap_hwmod
1431 * @oh: struct omap_hwmod *
1432 *
1433 * Registers the omap_hwmod @oh. Returns -EEXIST if an omap_hwmod
1434 * already has been registered by the same name; -EINVAL if the
1435 * omap_hwmod is in the wrong state, if @oh is NULL, if the
1436 * omap_hwmod's class field is NULL; if the omap_hwmod is missing a
1437 * name, or if the omap_hwmod's class is missing a name; or 0 upon
1438 * success.
1439 *
1440 * XXX The data should be copied into bootmem, so the original data
1441 * should be marked __initdata and freed after init. This would allow
1442 * unneeded omap_hwmods to be freed on multi-OMAP configurations. Note
1443 * that the copy process would be relatively complex due to the large number
1444 * of substructures.
1445 */
1446int omap_hwmod_register(struct omap_hwmod *oh)
1447{
1448 int ret, ms_id;
1449
1450 if (!oh || !oh->name || !oh->class || !oh->class->name ||
1451 (oh->_state != _HWMOD_STATE_UNKNOWN))
1452 return -EINVAL;
1453
1454 mutex_lock(&omap_hwmod_mutex);
1455
1456 pr_debug("omap_hwmod: %s: registering\n", oh->name);
1457
1458 if (_lookup(oh->name)) {
1459 ret = -EEXIST;
1460 goto ohr_unlock;
1461 }
1462
1463 ms_id = _find_mpu_port_index(oh);
1464 if (!IS_ERR_VALUE(ms_id)) {
1465 oh->_mpu_port_index = ms_id;
1466 oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
1467 } else {
1468 oh->_int_flags |= _HWMOD_NO_MPU_PORT;
1469 }
1470
1471 list_add_tail(&oh->node, &omap_hwmod_list);
1472
1473 oh->_state = _HWMOD_STATE_REGISTERED;
1474
1475 ret = 0;
1476
1477ohr_unlock:
1478 mutex_unlock(&omap_hwmod_mutex);
1479 return ret;
1480}
1481
1482/**
1483 * omap_hwmod_lookup - look up a registered omap_hwmod by name 1540 * omap_hwmod_lookup - look up a registered omap_hwmod by name
1484 * @name: name of the omap_hwmod to look up 1541 * @name: name of the omap_hwmod to look up
1485 * 1542 *
@@ -1493,9 +1550,7 @@ struct omap_hwmod *omap_hwmod_lookup(const char *name)
1493 if (!name) 1550 if (!name)
1494 return NULL; 1551 return NULL;
1495 1552
1496 mutex_lock(&omap_hwmod_mutex);
1497 oh = _lookup(name); 1553 oh = _lookup(name);
1498 mutex_unlock(&omap_hwmod_mutex);
1499 1554
1500 return oh; 1555 return oh;
1501} 1556}
@@ -1521,13 +1576,11 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
1521 if (!fn) 1576 if (!fn)
1522 return -EINVAL; 1577 return -EINVAL;
1523 1578
1524 mutex_lock(&omap_hwmod_mutex);
1525 list_for_each_entry(temp_oh, &omap_hwmod_list, node) { 1579 list_for_each_entry(temp_oh, &omap_hwmod_list, node) {
1526 ret = (*fn)(temp_oh, data); 1580 ret = (*fn)(temp_oh, data);
1527 if (ret) 1581 if (ret)
1528 break; 1582 break;
1529 } 1583 }
1530 mutex_unlock(&omap_hwmod_mutex);
1531 1584
1532 return ret; 1585 return ret;
1533} 1586}
@@ -1542,7 +1595,7 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
1542 * listed in @ohs that are valid for this chip. Returns -EINVAL if 1595 * listed in @ohs that are valid for this chip. Returns -EINVAL if
1543 * omap_hwmod_init() has already been called or 0 otherwise. 1596 * omap_hwmod_init() has already been called or 0 otherwise.
1544 */ 1597 */
1545int omap_hwmod_init(struct omap_hwmod **ohs) 1598int __init omap_hwmod_init(struct omap_hwmod **ohs)
1546{ 1599{
1547 struct omap_hwmod *oh; 1600 struct omap_hwmod *oh;
1548 int r; 1601 int r;
@@ -1558,8 +1611,8 @@ int omap_hwmod_init(struct omap_hwmod **ohs)
1558 oh = *ohs; 1611 oh = *ohs;
1559 while (oh) { 1612 while (oh) {
1560 if (omap_chip_is(oh->omap_chip)) { 1613 if (omap_chip_is(oh->omap_chip)) {
1561 r = omap_hwmod_register(oh); 1614 r = _register(oh);
1562 WARN(r, "omap_hwmod: %s: omap_hwmod_register returned " 1615 WARN(r, "omap_hwmod: %s: _register returned "
1563 "%d\n", oh->name, r); 1616 "%d\n", oh->name, r);
1564 } 1617 }
1565 oh = *++ohs; 1618 oh = *++ohs;
@@ -1570,13 +1623,12 @@ int omap_hwmod_init(struct omap_hwmod **ohs)
1570 1623
1571/** 1624/**
1572 * omap_hwmod_late_init - do some post-clock framework initialization 1625 * omap_hwmod_late_init - do some post-clock framework initialization
1573 * @skip_setup_idle: if 1, do not idle hwmods in _setup()
1574 * 1626 *
1575 * Must be called after omap2_clk_init(). Resolves the struct clk names 1627 * Must be called after omap2_clk_init(). Resolves the struct clk names
1576 * to struct clk pointers for each registered omap_hwmod. Also calls 1628 * to struct clk pointers for each registered omap_hwmod. Also calls
1577 * _setup() on each hwmod. Returns 0. 1629 * _setup() on each hwmod. Returns 0.
1578 */ 1630 */
1579int omap_hwmod_late_init(u8 skip_setup_idle) 1631int omap_hwmod_late_init(void)
1580{ 1632{
1581 int r; 1633 int r;
1582 1634
@@ -1588,36 +1640,7 @@ int omap_hwmod_late_init(u8 skip_setup_idle)
1588 WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n", 1640 WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
1589 MPU_INITIATOR_NAME); 1641 MPU_INITIATOR_NAME);
1590 1642
1591 if (skip_setup_idle) 1643 omap_hwmod_for_each(_setup, NULL);
1592 pr_debug("omap_hwmod: will leave hwmods enabled during setup\n");
1593
1594 omap_hwmod_for_each(_setup, &skip_setup_idle);
1595
1596 return 0;
1597}
1598
1599/**
1600 * omap_hwmod_unregister - unregister an omap_hwmod
1601 * @oh: struct omap_hwmod *
1602 *
1603 * Unregisters a previously-registered omap_hwmod @oh. There's probably
1604 * no use case for this, so it is likely to be removed in a later version.
1605 *
1606 * XXX Free all of the bootmem-allocated structures here when that is
1607 * implemented. Make it clear that core code is the only code that is
1608 * expected to unregister modules.
1609 */
1610int omap_hwmod_unregister(struct omap_hwmod *oh)
1611{
1612 if (!oh)
1613 return -EINVAL;
1614
1615 pr_debug("omap_hwmod: %s: unregistering\n", oh->name);
1616
1617 mutex_lock(&omap_hwmod_mutex);
1618 iounmap(oh->_mpu_rt_va);
1619 list_del(&oh->node);
1620 mutex_unlock(&omap_hwmod_mutex);
1621 1644
1622 return 0; 1645 return 0;
1623} 1646}
@@ -1632,18 +1655,18 @@ int omap_hwmod_unregister(struct omap_hwmod *oh)
1632int omap_hwmod_enable(struct omap_hwmod *oh) 1655int omap_hwmod_enable(struct omap_hwmod *oh)
1633{ 1656{
1634 int r; 1657 int r;
1658 unsigned long flags;
1635 1659
1636 if (!oh) 1660 if (!oh)
1637 return -EINVAL; 1661 return -EINVAL;
1638 1662
1639 mutex_lock(&oh->_mutex); 1663 spin_lock_irqsave(&oh->_lock, flags);
1640 r = _omap_hwmod_enable(oh); 1664 r = _enable(oh);
1641 mutex_unlock(&oh->_mutex); 1665 spin_unlock_irqrestore(&oh->_lock, flags);
1642 1666
1643 return r; 1667 return r;
1644} 1668}
1645 1669
1646
1647/** 1670/**
1648 * omap_hwmod_idle - idle an omap_hwmod 1671 * omap_hwmod_idle - idle an omap_hwmod
1649 * @oh: struct omap_hwmod * 1672 * @oh: struct omap_hwmod *
@@ -1653,12 +1676,14 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
1653 */ 1676 */
1654int omap_hwmod_idle(struct omap_hwmod *oh) 1677int omap_hwmod_idle(struct omap_hwmod *oh)
1655{ 1678{
1679 unsigned long flags;
1680
1656 if (!oh) 1681 if (!oh)
1657 return -EINVAL; 1682 return -EINVAL;
1658 1683
1659 mutex_lock(&oh->_mutex); 1684 spin_lock_irqsave(&oh->_lock, flags);
1660 _omap_hwmod_idle(oh); 1685 _idle(oh);
1661 mutex_unlock(&oh->_mutex); 1686 spin_unlock_irqrestore(&oh->_lock, flags);
1662 1687
1663 return 0; 1688 return 0;
1664} 1689}
@@ -1673,12 +1698,14 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
1673 */ 1698 */
1674int omap_hwmod_shutdown(struct omap_hwmod *oh) 1699int omap_hwmod_shutdown(struct omap_hwmod *oh)
1675{ 1700{
1701 unsigned long flags;
1702
1676 if (!oh) 1703 if (!oh)
1677 return -EINVAL; 1704 return -EINVAL;
1678 1705
1679 mutex_lock(&oh->_mutex); 1706 spin_lock_irqsave(&oh->_lock, flags);
1680 _shutdown(oh); 1707 _shutdown(oh);
1681 mutex_unlock(&oh->_mutex); 1708 spin_unlock_irqrestore(&oh->_lock, flags);
1682 1709
1683 return 0; 1710 return 0;
1684} 1711}
@@ -1691,9 +1718,11 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
1691 */ 1718 */
1692int omap_hwmod_enable_clocks(struct omap_hwmod *oh) 1719int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
1693{ 1720{
1694 mutex_lock(&oh->_mutex); 1721 unsigned long flags;
1722
1723 spin_lock_irqsave(&oh->_lock, flags);
1695 _enable_clocks(oh); 1724 _enable_clocks(oh);
1696 mutex_unlock(&oh->_mutex); 1725 spin_unlock_irqrestore(&oh->_lock, flags);
1697 1726
1698 return 0; 1727 return 0;
1699} 1728}
@@ -1706,9 +1735,11 @@ int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
1706 */ 1735 */
1707int omap_hwmod_disable_clocks(struct omap_hwmod *oh) 1736int omap_hwmod_disable_clocks(struct omap_hwmod *oh)
1708{ 1737{
1709 mutex_lock(&oh->_mutex); 1738 unsigned long flags;
1739
1740 spin_lock_irqsave(&oh->_lock, flags);
1710 _disable_clocks(oh); 1741 _disable_clocks(oh);
1711 mutex_unlock(&oh->_mutex); 1742 spin_unlock_irqrestore(&oh->_lock, flags);
1712 1743
1713 return 0; 1744 return 0;
1714} 1745}
@@ -1752,13 +1783,14 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
1752int omap_hwmod_reset(struct omap_hwmod *oh) 1783int omap_hwmod_reset(struct omap_hwmod *oh)
1753{ 1784{
1754 int r; 1785 int r;
1786 unsigned long flags;
1755 1787
1756 if (!oh) 1788 if (!oh)
1757 return -EINVAL; 1789 return -EINVAL;
1758 1790
1759 mutex_lock(&oh->_mutex); 1791 spin_lock_irqsave(&oh->_lock, flags);
1760 r = _reset(oh); 1792 r = _reset(oh);
1761 mutex_unlock(&oh->_mutex); 1793 spin_unlock_irqrestore(&oh->_lock, flags);
1762 1794
1763 return r; 1795 return r;
1764} 1796}
@@ -1955,13 +1987,18 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
1955 */ 1987 */
1956int omap_hwmod_enable_wakeup(struct omap_hwmod *oh) 1988int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
1957{ 1989{
1990 unsigned long flags;
1991 u32 v;
1992
1958 if (!oh->class->sysc || 1993 if (!oh->class->sysc ||
1959 !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) 1994 !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
1960 return -EINVAL; 1995 return -EINVAL;
1961 1996
1962 mutex_lock(&oh->_mutex); 1997 spin_lock_irqsave(&oh->_lock, flags);
1963 _enable_wakeup(oh); 1998 v = oh->_sysc_cache;
1964 mutex_unlock(&oh->_mutex); 1999 _enable_wakeup(oh, &v);
2000 _write_sysconfig(v, oh);
2001 spin_unlock_irqrestore(&oh->_lock, flags);
1965 2002
1966 return 0; 2003 return 0;
1967} 2004}
@@ -1980,13 +2017,18 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
1980 */ 2017 */
1981int omap_hwmod_disable_wakeup(struct omap_hwmod *oh) 2018int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
1982{ 2019{
2020 unsigned long flags;
2021 u32 v;
2022
1983 if (!oh->class->sysc || 2023 if (!oh->class->sysc ||
1984 !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) 2024 !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
1985 return -EINVAL; 2025 return -EINVAL;
1986 2026
1987 mutex_lock(&oh->_mutex); 2027 spin_lock_irqsave(&oh->_lock, flags);
1988 _disable_wakeup(oh); 2028 v = oh->_sysc_cache;
1989 mutex_unlock(&oh->_mutex); 2029 _disable_wakeup(oh, &v);
2030 _write_sysconfig(v, oh);
2031 spin_unlock_irqrestore(&oh->_lock, flags);
1990 2032
1991 return 0; 2033 return 0;
1992} 2034}
@@ -2006,13 +2048,14 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
2006int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name) 2048int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name)
2007{ 2049{
2008 int ret; 2050 int ret;
2051 unsigned long flags;
2009 2052
2010 if (!oh) 2053 if (!oh)
2011 return -EINVAL; 2054 return -EINVAL;
2012 2055
2013 mutex_lock(&oh->_mutex); 2056 spin_lock_irqsave(&oh->_lock, flags);
2014 ret = _assert_hardreset(oh, name); 2057 ret = _assert_hardreset(oh, name);
2015 mutex_unlock(&oh->_mutex); 2058 spin_unlock_irqrestore(&oh->_lock, flags);
2016 2059
2017 return ret; 2060 return ret;
2018} 2061}
@@ -2032,13 +2075,14 @@ int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name)
2032int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name) 2075int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name)
2033{ 2076{
2034 int ret; 2077 int ret;
2078 unsigned long flags;
2035 2079
2036 if (!oh) 2080 if (!oh)
2037 return -EINVAL; 2081 return -EINVAL;
2038 2082
2039 mutex_lock(&oh->_mutex); 2083 spin_lock_irqsave(&oh->_lock, flags);
2040 ret = _deassert_hardreset(oh, name); 2084 ret = _deassert_hardreset(oh, name);
2041 mutex_unlock(&oh->_mutex); 2085 spin_unlock_irqrestore(&oh->_lock, flags);
2042 2086
2043 return ret; 2087 return ret;
2044} 2088}
@@ -2057,13 +2101,14 @@ int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name)
2057int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name) 2101int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name)
2058{ 2102{
2059 int ret; 2103 int ret;
2104 unsigned long flags;
2060 2105
2061 if (!oh) 2106 if (!oh)
2062 return -EINVAL; 2107 return -EINVAL;
2063 2108
2064 mutex_lock(&oh->_mutex); 2109 spin_lock_irqsave(&oh->_lock, flags);
2065 ret = _read_hardreset(oh, name); 2110 ret = _read_hardreset(oh, name);
2066 mutex_unlock(&oh->_mutex); 2111 spin_unlock_irqrestore(&oh->_lock, flags);
2067 2112
2068 return ret; 2113 return ret;
2069} 2114}
@@ -2075,9 +2120,8 @@ int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name)
2075 * @fn: callback function pointer to call for each hwmod in class @classname 2120 * @fn: callback function pointer to call for each hwmod in class @classname
2076 * @user: arbitrary context data to pass to the callback function 2121 * @user: arbitrary context data to pass to the callback function
2077 * 2122 *
2078 * For each omap_hwmod of class @classname, call @fn. Takes 2123 * For each omap_hwmod of class @classname, call @fn.
2079 * omap_hwmod_mutex to prevent the hwmod list from changing during the 2124 * If the callback function returns something other than
2080 * iteration. If the callback function returns something other than
2081 * zero, the iterator is terminated, and the callback function's return 2125 * zero, the iterator is terminated, and the callback function's return
2082 * value is passed back to the caller. Returns 0 upon success, -EINVAL 2126 * value is passed back to the caller. Returns 0 upon success, -EINVAL
2083 * if @classname or @fn are NULL, or passes back the error code from @fn. 2127 * if @classname or @fn are NULL, or passes back the error code from @fn.
@@ -2096,8 +2140,6 @@ int omap_hwmod_for_each_by_class(const char *classname,
2096 pr_debug("omap_hwmod: %s: looking for modules of class %s\n", 2140 pr_debug("omap_hwmod: %s: looking for modules of class %s\n",
2097 __func__, classname); 2141 __func__, classname);
2098 2142
2099 mutex_lock(&omap_hwmod_mutex);
2100
2101 list_for_each_entry(temp_oh, &omap_hwmod_list, node) { 2143 list_for_each_entry(temp_oh, &omap_hwmod_list, node) {
2102 if (!strcmp(temp_oh->class->name, classname)) { 2144 if (!strcmp(temp_oh->class->name, classname)) {
2103 pr_debug("omap_hwmod: %s: %s: calling callback fn\n", 2145 pr_debug("omap_hwmod: %s: %s: calling callback fn\n",
@@ -2108,8 +2150,6 @@ int omap_hwmod_for_each_by_class(const char *classname,
2108 } 2150 }
2109 } 2151 }
2110 2152
2111 mutex_unlock(&omap_hwmod_mutex);
2112
2113 if (ret) 2153 if (ret)
2114 pr_debug("omap_hwmod: %s: iterator terminated early: %d\n", 2154 pr_debug("omap_hwmod: %s: iterator terminated early: %d\n",
2115 __func__, ret); 2155 __func__, ret);
@@ -2117,3 +2157,64 @@ int omap_hwmod_for_each_by_class(const char *classname,
2117 return ret; 2157 return ret;
2118} 2158}
2119 2159
2160/**
2161 * omap_hwmod_set_postsetup_state - set the post-_setup() state for this hwmod
2162 * @oh: struct omap_hwmod *
2163 * @state: state that _setup() should leave the hwmod in
2164 *
2165 * Sets the hwmod state that @oh will enter at the end of _setup() (called by
2166 * omap_hwmod_late_init()). Only valid to call between calls to
2167 * omap_hwmod_init() and omap_hwmod_late_init(). Returns 0 upon success or
2168 * -EINVAL if there is a problem with the arguments or if the hwmod is
2169 * in the wrong state.
2170 */
2171int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
2172{
2173 int ret;
2174 unsigned long flags;
2175
2176 if (!oh)
2177 return -EINVAL;
2178
2179 if (state != _HWMOD_STATE_DISABLED &&
2180 state != _HWMOD_STATE_ENABLED &&
2181 state != _HWMOD_STATE_IDLE)
2182 return -EINVAL;
2183
2184 spin_lock_irqsave(&oh->_lock, flags);
2185
2186 if (oh->_state != _HWMOD_STATE_REGISTERED) {
2187 ret = -EINVAL;
2188 goto ohsps_unlock;
2189 }
2190
2191 oh->_postsetup_state = state;
2192 ret = 0;
2193
2194ohsps_unlock:
2195 spin_unlock_irqrestore(&oh->_lock, flags);
2196
2197 return ret;
2198}
2199
2200/**
2201 * omap_hwmod_get_context_loss_count - get lost context count
2202 * @oh: struct omap_hwmod *
2203 *
2204 * Query the powerdomain of of @oh to get the context loss
2205 * count for this device.
2206 *
2207 * Returns the context loss count of the powerdomain assocated with @oh
2208 * upon success, or zero if no powerdomain exists for @oh.
2209 */
2210u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
2211{
2212 struct powerdomain *pwrdm;
2213 int ret = 0;
2214
2215 pwrdm = omap_hwmod_get_pwrdm(oh);
2216 if (pwrdm)
2217 ret = pwrdm_get_context_loss_count(pwrdm);
2218
2219 return ret;
2220}