diff options
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index b969ab1d258b..70267d2cf5e5 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 | * |
| @@ -1282,6 +1314,18 @@ static void _enable_sysc(struct omap_hwmod *oh) | |||
| 1282 | if (!oh->class->sysc) | 1314 | if (!oh->class->sysc) |
| 1283 | return; | 1315 | return; |
| 1284 | 1316 | ||
| 1317 | /* | ||
| 1318 | * Wait until reset has completed, this is needed as the IP | ||
| 1319 | * block is reset automatically by hardware in some cases | ||
| 1320 | * (off-mode for example), and the drivers require the | ||
| 1321 | * IP to be ready when they access it | ||
| 1322 | */ | ||
| 1323 | if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET) | ||
| 1324 | _enable_optional_clocks(oh); | ||
| 1325 | _wait_softreset_complete(oh); | ||
| 1326 | if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET) | ||
| 1327 | _disable_optional_clocks(oh); | ||
| 1328 | |||
| 1285 | v = oh->_sysc_cache; | 1329 | v = oh->_sysc_cache; |
| 1286 | sf = oh->class->sysc->sysc_flags; | 1330 | sf = oh->class->sysc->sysc_flags; |
| 1287 | 1331 | ||
| @@ -1804,7 +1848,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh) | |||
| 1804 | */ | 1848 | */ |
| 1805 | static int _ocp_softreset(struct omap_hwmod *oh) | 1849 | static int _ocp_softreset(struct omap_hwmod *oh) |
| 1806 | { | 1850 | { |
| 1807 | u32 v, softrst_mask; | 1851 | u32 v; |
| 1808 | int c = 0; | 1852 | int c = 0; |
| 1809 | int ret = 0; | 1853 | int ret = 0; |
| 1810 | 1854 | ||
| @@ -1834,19 +1878,7 @@ static int _ocp_softreset(struct omap_hwmod *oh) | |||
| 1834 | if (oh->class->sysc->srst_udelay) | 1878 | if (oh->class->sysc->srst_udelay) |
| 1835 | udelay(oh->class->sysc->srst_udelay); | 1879 | udelay(oh->class->sysc->srst_udelay); |
| 1836 | 1880 | ||
| 1837 | if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS) | 1881 | c = _wait_softreset_complete(oh); |
| 1838 | omap_test_timeout((omap_hwmod_read(oh, | ||
| 1839 | oh->class->sysc->syss_offs) | ||
| 1840 | & SYSS_RESETDONE_MASK), | ||
| 1841 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
| 1842 | else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) { | ||
| 1843 | softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift); | ||
| 1844 | omap_test_timeout(!(omap_hwmod_read(oh, | ||
| 1845 | oh->class->sysc->sysc_offs) | ||
| 1846 | & softrst_mask), | ||
| 1847 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
| 1848 | } | ||
| 1849 | |||
| 1850 | if (c == MAX_MODULE_SOFTRESET_WAIT) | 1882 | if (c == MAX_MODULE_SOFTRESET_WAIT) |
| 1851 | pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n", | 1883 | pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n", |
| 1852 | oh->name, MAX_MODULE_SOFTRESET_WAIT); | 1884 | oh->name, MAX_MODULE_SOFTRESET_WAIT); |
