diff options
author | Paul Walmsley <paul@pwsan.com> | 2010-07-26 18:34:30 -0400 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2010-07-26 18:34:30 -0400 |
commit | 97d60162f64ef068b639d8a77ef3bc148baa53ad (patch) | |
tree | 33bdb47ec9f97e6404c864d59dbb362cae700a23 /arch/arm/mach-omap2/omap_hwmod.c | |
parent | 848240223c35fcc71c424ad51a8e8aef42d3879c (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.c | 37 |
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 | */ |
774 | static int _init_clocks(struct omap_hwmod *oh) | 775 | static 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 | */ |
1005 | static int _setup(struct omap_hwmod *oh) | 1009 | static 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 | */ |
1175 | int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh)) | 1183 | int 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 | */ |
1237 | int omap_hwmod_late_init(void) | 1247 | int 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 | } |