diff options
author | Kevin Hilman <khilman@ti.com> | 2012-06-18 14:12:24 -0400 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2012-06-18 14:12:24 -0400 |
commit | 8f6aa8ee114fb52a425e247e27e271ee35d7d3b3 (patch) | |
tree | 10724b6a72f97a9953508eb8e616963b042b5401 /arch/arm/mach-omap2/omap_hwmod.c | |
parent | baa2607f56f1589eb21c01fe16aa5f5c3f9dad31 (diff) |
ARM: OMAP2+: hwmod: use init-time function pointer for wait_target_ready
Rather than using cpu_is* checking at runtime, initialize an SoC specific
function pointer for wait_target_ready().
While here, downgrade the BUG() to a WARN_ON() so it gives a noisy
warning instead of causing a kernel panic.
Signed-off-by: Kevin Hilman <khilman@ti.com>
[paul@pwsan.com: convert to use soc_ops function pointers; add kerneldoc;
move soc_ops functions to their own section in the code; integrated
the _wait_target_ready() function with the OMAP2/OMAP4 variants;
renamed the wait_module_ready field to wait_target_ready]
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 | 115 |
1 files changed, 66 insertions, 49 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 2b845836f7d..d1f784cd5f0 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -178,6 +178,7 @@ | |||
178 | struct omap_hwmod_soc_ops { | 178 | struct omap_hwmod_soc_ops { |
179 | void (*enable_module)(struct omap_hwmod *oh); | 179 | void (*enable_module)(struct omap_hwmod *oh); |
180 | int (*disable_module)(struct omap_hwmod *oh); | 180 | int (*disable_module)(struct omap_hwmod *oh); |
181 | int (*wait_target_ready)(struct omap_hwmod *oh); | ||
181 | }; | 182 | }; |
182 | 183 | ||
183 | /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ | 184 | /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ |
@@ -1362,53 +1363,6 @@ static int _init_clocks(struct omap_hwmod *oh, void *data) | |||
1362 | } | 1363 | } |
1363 | 1364 | ||
1364 | /** | 1365 | /** |
1365 | * _wait_target_ready - wait for a module to leave slave idle | ||
1366 | * @oh: struct omap_hwmod * | ||
1367 | * | ||
1368 | * Wait for a module @oh to leave slave idle. Returns 0 if the module | ||
1369 | * does not have an IDLEST bit or if the module successfully leaves | ||
1370 | * slave idle; otherwise, pass along the return value of the | ||
1371 | * appropriate *_cm*_wait_module_ready() function. | ||
1372 | */ | ||
1373 | static int _wait_target_ready(struct omap_hwmod *oh) | ||
1374 | { | ||
1375 | struct omap_hwmod_ocp_if *os; | ||
1376 | int ret; | ||
1377 | |||
1378 | if (!oh) | ||
1379 | return -EINVAL; | ||
1380 | |||
1381 | if (oh->flags & HWMOD_NO_IDLEST) | ||
1382 | return 0; | ||
1383 | |||
1384 | os = _find_mpu_rt_port(oh); | ||
1385 | if (!os) | ||
1386 | return 0; | ||
1387 | |||
1388 | /* XXX check module SIDLEMODE */ | ||
1389 | |||
1390 | /* XXX check clock enable states */ | ||
1391 | |||
1392 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { | ||
1393 | ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, | ||
1394 | oh->prcm.omap2.idlest_reg_id, | ||
1395 | oh->prcm.omap2.idlest_idle_bit); | ||
1396 | } else if (cpu_is_omap44xx()) { | ||
1397 | if (!oh->clkdm) | ||
1398 | return -EINVAL; | ||
1399 | |||
1400 | ret = omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition, | ||
1401 | oh->clkdm->cm_inst, | ||
1402 | oh->clkdm->clkdm_offs, | ||
1403 | oh->prcm.omap4.clkctrl_offs); | ||
1404 | } else { | ||
1405 | BUG(); | ||
1406 | }; | ||
1407 | |||
1408 | return ret; | ||
1409 | } | ||
1410 | |||
1411 | /** | ||
1412 | * _lookup_hardreset - fill register bit info for this hwmod/reset line | 1366 | * _lookup_hardreset - fill register bit info for this hwmod/reset line |
1413 | * @oh: struct omap_hwmod * | 1367 | * @oh: struct omap_hwmod * |
1414 | * @name: name of the reset line in the context of this hwmod | 1368 | * @name: name of the reset line in the context of this hwmod |
@@ -1826,7 +1780,8 @@ static int _enable(struct omap_hwmod *oh) | |||
1826 | if (soc_ops.enable_module) | 1780 | if (soc_ops.enable_module) |
1827 | soc_ops.enable_module(oh); | 1781 | soc_ops.enable_module(oh); |
1828 | 1782 | ||
1829 | r = _wait_target_ready(oh); | 1783 | r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) : |
1784 | -EINVAL; | ||
1830 | if (!r) { | 1785 | if (!r) { |
1831 | /* | 1786 | /* |
1832 | * Set the clockdomain to HW_AUTO only if the target is ready, | 1787 | * Set the clockdomain to HW_AUTO only if the target is ready, |
@@ -2443,6 +2398,63 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois) | |||
2443 | return 0; | 2398 | return 0; |
2444 | } | 2399 | } |
2445 | 2400 | ||
2401 | /* Static functions intended only for use in soc_ops field function pointers */ | ||
2402 | |||
2403 | /** | ||
2404 | * _omap2_wait_target_ready - wait for a module to leave slave idle | ||
2405 | * @oh: struct omap_hwmod * | ||
2406 | * | ||
2407 | * Wait for a module @oh to leave slave idle. Returns 0 if the module | ||
2408 | * does not have an IDLEST bit or if the module successfully leaves | ||
2409 | * slave idle; otherwise, pass along the return value of the | ||
2410 | * appropriate *_cm*_wait_module_ready() function. | ||
2411 | */ | ||
2412 | static int _omap2_wait_target_ready(struct omap_hwmod *oh) | ||
2413 | { | ||
2414 | if (!oh) | ||
2415 | return -EINVAL; | ||
2416 | |||
2417 | if (oh->flags & HWMOD_NO_IDLEST) | ||
2418 | return 0; | ||
2419 | |||
2420 | if (!_find_mpu_rt_port(oh)) | ||
2421 | return 0; | ||
2422 | |||
2423 | /* XXX check module SIDLEMODE, hardreset status, enabled clocks */ | ||
2424 | |||
2425 | return omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, | ||
2426 | oh->prcm.omap2.idlest_reg_id, | ||
2427 | oh->prcm.omap2.idlest_idle_bit); | ||
2428 | } | ||
2429 | |||
2430 | /** | ||
2431 | * _omap4_wait_target_ready - wait for a module to leave slave idle | ||
2432 | * @oh: struct omap_hwmod * | ||
2433 | * | ||
2434 | * Wait for a module @oh to leave slave idle. Returns 0 if the module | ||
2435 | * does not have an IDLEST bit or if the module successfully leaves | ||
2436 | * slave idle; otherwise, pass along the return value of the | ||
2437 | * appropriate *_cm*_wait_module_ready() function. | ||
2438 | */ | ||
2439 | static int _omap4_wait_target_ready(struct omap_hwmod *oh) | ||
2440 | { | ||
2441 | if (!oh || !oh->clkdm) | ||
2442 | return -EINVAL; | ||
2443 | |||
2444 | if (oh->flags & HWMOD_NO_IDLEST) | ||
2445 | return 0; | ||
2446 | |||
2447 | if (!_find_mpu_rt_port(oh)) | ||
2448 | return 0; | ||
2449 | |||
2450 | /* XXX check module SIDLEMODE, hardreset status */ | ||
2451 | |||
2452 | return omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition, | ||
2453 | oh->clkdm->cm_inst, | ||
2454 | oh->clkdm->clkdm_offs, | ||
2455 | oh->prcm.omap4.clkctrl_offs); | ||
2456 | } | ||
2457 | |||
2446 | /* Public functions */ | 2458 | /* Public functions */ |
2447 | 2459 | ||
2448 | u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs) | 2460 | u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs) |
@@ -3429,9 +3441,14 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) | |||
3429 | */ | 3441 | */ |
3430 | void __init omap_hwmod_init(void) | 3442 | void __init omap_hwmod_init(void) |
3431 | { | 3443 | { |
3432 | if (cpu_is_omap44xx()) { | 3444 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { |
3445 | soc_ops.wait_target_ready = _omap2_wait_target_ready; | ||
3446 | } else if (cpu_is_omap44xx()) { | ||
3433 | soc_ops.enable_module = _omap4_enable_module; | 3447 | soc_ops.enable_module = _omap4_enable_module; |
3434 | soc_ops.disable_module = _omap4_disable_module; | 3448 | soc_ops.disable_module = _omap4_disable_module; |
3449 | soc_ops.wait_target_ready = _omap4_wait_target_ready; | ||
3450 | } else { | ||
3451 | WARN(1, "omap_hwmod: unknown SoC type\n"); | ||
3435 | } | 3452 | } |
3436 | 3453 | ||
3437 | inited = true; | 3454 | inited = true; |