aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c63
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 */
434static 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 */
1828static int _ocp_softreset(struct omap_hwmod *oh) 1872static 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) {