aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2010-07-26 18:34:30 -0400
committerPaul Walmsley <paul@pwsan.com>2010-07-26 18:34:30 -0400
commit97d60162f64ef068b639d8a77ef3bc148baa53ad (patch)
tree33bdb47ec9f97e6404c864d59dbb362cae700a23 /arch/arm/mach-omap2/omap_hwmod.c
parent848240223c35fcc71c424ad51a8e8aef42d3879c (diff)
OMAP: hwmod: allow omap_hwmod_late_init() caller to skip module idle in _setup()
On kernels that don't use the omap_device_enable() calls to enable devices, leave all on-chip devices enabled in hwmod _setup(). Otherwise, accesses to those devices are likely to fail, crashing the system. It's expected that kernels built without CONFIG_PM_RUNTIME will be the primary use-case for this. This functionality is controlled by adding an extra parameter to omap_hwmod_late_init(). This patch is based on the patch "OMAP: hwmod: don't auto-disable hwmod when !CONFIG_PM_RUNTIME" by Kevin Hilman <khilman@deeprootsystems.com>. Cc: Kevin Hilman <khilman@deeprootsystems.com> 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.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index a23a60ad4059..b2c8e8760c80 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -764,6 +764,7 @@ static struct omap_hwmod *_lookup(const char *name)
764/** 764/**
765 * _init_clocks - clk_get() all clocks associated with this hwmod 765 * _init_clocks - clk_get() all clocks associated with this hwmod
766 * @oh: struct omap_hwmod * 766 * @oh: struct omap_hwmod *
767 * @data: not used; pass NULL
767 * 768 *
768 * Called by omap_hwmod_late_init() (after omap2_clk_init()). 769 * Called by omap_hwmod_late_init() (after omap2_clk_init()).
769 * Resolves all clock names embedded in the hwmod. Must be called 770 * Resolves all clock names embedded in the hwmod. Must be called
@@ -771,7 +772,7 @@ static struct omap_hwmod *_lookup(const char *name)
771 * has not yet been registered or if the clocks have already been 772 * has not yet been registered or if the clocks have already been
772 * initialized, 0 on success, or a non-zero error on failure. 773 * initialized, 0 on success, or a non-zero error on failure.
773 */ 774 */
774static int _init_clocks(struct omap_hwmod *oh) 775static int _init_clocks(struct omap_hwmod *oh, void *data)
775{ 776{
776 int ret = 0; 777 int ret = 0;
777 778
@@ -996,19 +997,25 @@ static int _shutdown(struct omap_hwmod *oh)
996/** 997/**
997 * _setup - do initial configuration of omap_hwmod 998 * _setup - do initial configuration of omap_hwmod
998 * @oh: struct omap_hwmod * 999 * @oh: struct omap_hwmod *
1000 * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
999 * 1001 *
1000 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh 1002 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
1001 * OCP_SYSCONFIG register. Must be called with omap_hwmod_mutex 1003 * OCP_SYSCONFIG register. Must be called with omap_hwmod_mutex held.
1002 * held. Returns -EINVAL if the hwmod is in the wrong state or returns 1004 * @skip_setup_idle is intended to be used on a system that will not
1003 * 0. 1005 * call omap_hwmod_enable() to enable devices (e.g., a system without
1006 * PM runtime). Returns -EINVAL if the hwmod is in the wrong state or
1007 * returns 0.
1004 */ 1008 */
1005static int _setup(struct omap_hwmod *oh) 1009static int _setup(struct omap_hwmod *oh, void *data)
1006{ 1010{
1007 int i, r; 1011 int i, r;
1012 u8 skip_setup_idle;
1008 1013
1009 if (!oh) 1014 if (!oh || !data)
1010 return -EINVAL; 1015 return -EINVAL;
1011 1016
1017 skip_setup_idle = *(u8 *)data;
1018
1012 /* Set iclk autoidle mode */ 1019 /* Set iclk autoidle mode */
1013 if (oh->slaves_cnt > 0) { 1020 if (oh->slaves_cnt > 0) {
1014 for (i = 0; i < oh->slaves_cnt; i++) { 1021 for (i = 0; i < oh->slaves_cnt; i++) {
@@ -1050,7 +1057,7 @@ static int _setup(struct omap_hwmod *oh)
1050 } 1057 }
1051 } 1058 }
1052 1059
1053 if (!(oh->flags & HWMOD_INIT_NO_IDLE)) 1060 if (!(oh->flags & HWMOD_INIT_NO_IDLE) && !skip_setup_idle)
1054 _omap_hwmod_idle(oh); 1061 _omap_hwmod_idle(oh);
1055 1062
1056 return 0; 1063 return 0;
@@ -1164,6 +1171,7 @@ struct omap_hwmod *omap_hwmod_lookup(const char *name)
1164/** 1171/**
1165 * omap_hwmod_for_each - call function for each registered omap_hwmod 1172 * omap_hwmod_for_each - call function for each registered omap_hwmod
1166 * @fn: pointer to a callback function 1173 * @fn: pointer to a callback function
1174 * @data: void * data to pass to callback function
1167 * 1175 *
1168 * Call @fn for each registered omap_hwmod, passing @data to each 1176 * Call @fn for each registered omap_hwmod, passing @data to each
1169 * function. @fn must return 0 for success or any other value for 1177 * function. @fn must return 0 for success or any other value for
@@ -1172,7 +1180,8 @@ struct omap_hwmod *omap_hwmod_lookup(const char *name)
1172 * caller of omap_hwmod_for_each(). @fn is called with 1180 * caller of omap_hwmod_for_each(). @fn is called with
1173 * omap_hwmod_for_each() held. 1181 * omap_hwmod_for_each() held.
1174 */ 1182 */
1175int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh)) 1183int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
1184 void *data)
1176{ 1185{
1177 struct omap_hwmod *temp_oh; 1186 struct omap_hwmod *temp_oh;
1178 int ret; 1187 int ret;
@@ -1182,7 +1191,7 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh))
1182 1191
1183 mutex_lock(&omap_hwmod_mutex); 1192 mutex_lock(&omap_hwmod_mutex);
1184 list_for_each_entry(temp_oh, &omap_hwmod_list, node) { 1193 list_for_each_entry(temp_oh, &omap_hwmod_list, node) {
1185 ret = (*fn)(temp_oh); 1194 ret = (*fn)(temp_oh, data);
1186 if (ret) 1195 if (ret)
1187 break; 1196 break;
1188 } 1197 }
@@ -1229,24 +1238,28 @@ int omap_hwmod_init(struct omap_hwmod **ohs)
1229 1238
1230/** 1239/**
1231 * omap_hwmod_late_init - do some post-clock framework initialization 1240 * omap_hwmod_late_init - do some post-clock framework initialization
1241 * @skip_setup_idle: if 1, do not idle hwmods in _setup()
1232 * 1242 *
1233 * Must be called after omap2_clk_init(). Resolves the struct clk names 1243 * Must be called after omap2_clk_init(). Resolves the struct clk names
1234 * to struct clk pointers for each registered omap_hwmod. Also calls 1244 * to struct clk pointers for each registered omap_hwmod. Also calls
1235 * _setup() on each hwmod. Returns 0. 1245 * _setup() on each hwmod. Returns 0.
1236 */ 1246 */
1237int omap_hwmod_late_init(void) 1247int omap_hwmod_late_init(u8 skip_setup_idle)
1238{ 1248{
1239 int r; 1249 int r;
1240 1250
1241 /* XXX check return value */ 1251 /* XXX check return value */
1242 r = omap_hwmod_for_each(_init_clocks); 1252 r = omap_hwmod_for_each(_init_clocks, NULL);
1243 WARN(r, "omap_hwmod: omap_hwmod_late_init(): _init_clocks failed\n"); 1253 WARN(r, "omap_hwmod: omap_hwmod_late_init(): _init_clocks failed\n");
1244 1254
1245 mpu_oh = omap_hwmod_lookup(MPU_INITIATOR_NAME); 1255 mpu_oh = omap_hwmod_lookup(MPU_INITIATOR_NAME);
1246 WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n", 1256 WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
1247 MPU_INITIATOR_NAME); 1257 MPU_INITIATOR_NAME);
1248 1258
1249 omap_hwmod_for_each(_setup); 1259 if (skip_setup_idle)
1260 pr_debug("omap_hwmod: will leave hwmods enabled during setup\n");
1261
1262 omap_hwmod_for_each(_setup, &skip_setup_idle);
1250 1263
1251 return 0; 1264 return 0;
1252} 1265}