diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 63 |
1 files changed, 49 insertions, 14 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index a8090907fe35..4653efb87a27 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -422,6 +422,38 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v) | |||
422 | } | 422 | } |
423 | 423 | ||
424 | /** | 424 | /** |
425 | * _wait_softreset_complete - wait for an OCP softreset to complete | ||
426 | * @oh: struct omap_hwmod * to wait on | ||
427 | * | ||
428 | * Wait until the IP block represented by @oh reports that its OCP | ||
429 | * softreset is complete. This can be triggered by software (see | ||
430 | * _ocp_softreset()) or by hardware upon returning from off-mode (one | ||
431 | * example is HSMMC). Waits for up to MAX_MODULE_SOFTRESET_WAIT | ||
432 | * microseconds. Returns the number of microseconds waited. | ||
433 | */ | ||
434 | static int _wait_softreset_complete(struct omap_hwmod *oh) | ||
435 | { | ||
436 | struct omap_hwmod_class_sysconfig *sysc; | ||
437 | u32 softrst_mask; | ||
438 | int c = 0; | ||
439 | |||
440 | sysc = oh->class->sysc; | ||
441 | |||
442 | if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS) | ||
443 | omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs) | ||
444 | & SYSS_RESETDONE_MASK), | ||
445 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
446 | else if (sysc->sysc_flags & SYSC_HAS_RESET_STATUS) { | ||
447 | softrst_mask = (0x1 << sysc->sysc_fields->srst_shift); | ||
448 | omap_test_timeout(!(omap_hwmod_read(oh, sysc->sysc_offs) | ||
449 | & softrst_mask), | ||
450 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
451 | } | ||
452 | |||
453 | return c; | ||
454 | } | ||
455 | |||
456 | /** | ||
425 | * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v | 457 | * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v |
426 | * @oh: struct omap_hwmod * | 458 | * @oh: struct omap_hwmod * |
427 | * | 459 | * |
@@ -1306,6 +1338,18 @@ static void _enable_sysc(struct omap_hwmod *oh) | |||
1306 | if (!oh->class->sysc) | 1338 | if (!oh->class->sysc) |
1307 | return; | 1339 | return; |
1308 | 1340 | ||
1341 | /* | ||
1342 | * Wait until reset has completed, this is needed as the IP | ||
1343 | * block is reset automatically by hardware in some cases | ||
1344 | * (off-mode for example), and the drivers require the | ||
1345 | * IP to be ready when they access it | ||
1346 | */ | ||
1347 | if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET) | ||
1348 | _enable_optional_clocks(oh); | ||
1349 | _wait_softreset_complete(oh); | ||
1350 | if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET) | ||
1351 | _disable_optional_clocks(oh); | ||
1352 | |||
1309 | v = oh->_sysc_cache; | 1353 | v = oh->_sysc_cache; |
1310 | sf = oh->class->sysc->sysc_flags; | 1354 | sf = oh->class->sysc->sysc_flags; |
1311 | 1355 | ||
@@ -1827,7 +1871,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh) | |||
1827 | */ | 1871 | */ |
1828 | static int _ocp_softreset(struct omap_hwmod *oh) | 1872 | static int _ocp_softreset(struct omap_hwmod *oh) |
1829 | { | 1873 | { |
1830 | u32 v, softrst_mask; | 1874 | u32 v; |
1831 | int c = 0; | 1875 | int c = 0; |
1832 | int ret = 0; | 1876 | int ret = 0; |
1833 | 1877 | ||
@@ -1857,19 +1901,7 @@ static int _ocp_softreset(struct omap_hwmod *oh) | |||
1857 | if (oh->class->sysc->srst_udelay) | 1901 | if (oh->class->sysc->srst_udelay) |
1858 | udelay(oh->class->sysc->srst_udelay); | 1902 | udelay(oh->class->sysc->srst_udelay); |
1859 | 1903 | ||
1860 | if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS) | 1904 | c = _wait_softreset_complete(oh); |
1861 | omap_test_timeout((omap_hwmod_read(oh, | ||
1862 | oh->class->sysc->syss_offs) | ||
1863 | & SYSS_RESETDONE_MASK), | ||
1864 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
1865 | else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) { | ||
1866 | softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift); | ||
1867 | omap_test_timeout(!(omap_hwmod_read(oh, | ||
1868 | oh->class->sysc->sysc_offs) | ||
1869 | & softrst_mask), | ||
1870 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
1871 | } | ||
1872 | |||
1873 | if (c == MAX_MODULE_SOFTRESET_WAIT) | 1905 | if (c == MAX_MODULE_SOFTRESET_WAIT) |
1874 | pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n", | 1906 | pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n", |
1875 | oh->name, MAX_MODULE_SOFTRESET_WAIT); | 1907 | oh->name, MAX_MODULE_SOFTRESET_WAIT); |
@@ -2415,6 +2447,9 @@ static int __init _setup_reset(struct omap_hwmod *oh) | |||
2415 | if (oh->_state != _HWMOD_STATE_INITIALIZED) | 2447 | if (oh->_state != _HWMOD_STATE_INITIALIZED) |
2416 | return -EINVAL; | 2448 | return -EINVAL; |
2417 | 2449 | ||
2450 | if (oh->flags & HWMOD_EXT_OPT_MAIN_CLK) | ||
2451 | return -EPERM; | ||
2452 | |||
2418 | if (oh->rst_lines_cnt == 0) { | 2453 | if (oh->rst_lines_cnt == 0) { |
2419 | r = _enable(oh); | 2454 | r = _enable(oh); |
2420 | if (r) { | 2455 | if (r) { |