aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c69
1 files changed, 46 insertions, 23 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 4997c1a8b59d..5b07ad0251d7 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2,7 +2,7 @@
2 * omap_hwmod implementation for OMAP2/3/4 2 * omap_hwmod implementation for OMAP2/3/4
3 * 3 *
4 * Copyright (C) 2009-2011 Nokia Corporation 4 * Copyright (C) 2009-2011 Nokia Corporation
5 * Copyright (C) 2011 Texas Instruments, Inc. 5 * Copyright (C) 2011-2012 Texas Instruments, Inc.
6 * 6 *
7 * Paul Walmsley, Benoît Cousson, Kevin Hilman 7 * Paul Walmsley, Benoît Cousson, Kevin Hilman
8 * 8 *
@@ -1382,9 +1382,9 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
1382 * @oh: struct omap_hwmod * 1382 * @oh: struct omap_hwmod *
1383 * 1383 *
1384 * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be 1384 * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be
1385 * enabled for this to work. Returns -EINVAL if the hwmod cannot be 1385 * enabled for this to work. Returns -ENOENT if the hwmod cannot be
1386 * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if 1386 * reset this way, -EINVAL if the hwmod is in the wrong state,
1387 * the module did not reset in time, or 0 upon success. 1387 * -ETIMEDOUT if the module did not reset in time, or 0 upon success.
1388 * 1388 *
1389 * In OMAP3 a specific SYSSTATUS register is used to get the reset status. 1389 * In OMAP3 a specific SYSSTATUS register is used to get the reset status.
1390 * Starting in OMAP4, some IPs do not have SYSSTATUS registers and instead 1390 * Starting in OMAP4, some IPs do not have SYSSTATUS registers and instead
@@ -1401,7 +1401,7 @@ static int _ocp_softreset(struct omap_hwmod *oh)
1401 1401
1402 if (!oh->class->sysc || 1402 if (!oh->class->sysc ||
1403 !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET)) 1403 !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
1404 return -EINVAL; 1404 return -ENOENT;
1405 1405
1406 /* clocks must be on for this operation */ 1406 /* clocks must be on for this operation */
1407 if (oh->_state != _HWMOD_STATE_ENABLED) { 1407 if (oh->_state != _HWMOD_STATE_ENABLED) {
@@ -1462,37 +1462,60 @@ dis_opt_clks:
1462 * _reset - reset an omap_hwmod 1462 * _reset - reset an omap_hwmod
1463 * @oh: struct omap_hwmod * 1463 * @oh: struct omap_hwmod *
1464 * 1464 *
1465 * Resets an omap_hwmod @oh. The default software reset mechanism for 1465 * Resets an omap_hwmod @oh. If the module has a custom reset
1466 * most OMAP IP blocks is triggered via the OCP_SYSCONFIG.SOFTRESET 1466 * function pointer defined, then call it to reset the IP block, and
1467 * bit. However, some hwmods cannot be reset via this method: some 1467 * pass along its return value to the caller. Otherwise, if the IP
1468 * are not targets and therefore have no OCP header registers to 1468 * block has an OCP_SYSCONFIG register with a SOFTRESET bitfield
1469 * access; others (like the IVA) have idiosyncratic reset sequences. 1469 * associated with it, call a function to reset the IP block via that
1470 * So for these relatively rare cases, custom reset code can be 1470 * method, and pass along the return value to the caller. Finally, if
1471 * supplied in the struct omap_hwmod_class .reset function pointer. 1471 * the IP block has some hardreset lines associated with it, assert
1472 * Passes along the return value from either _reset() or the custom 1472 * all of those, but do _not_ deassert them. (This is because driver
1473 * reset function - these must return -EINVAL if the hwmod cannot be 1473 * authors have expressed an apparent requirement to control the
1474 * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if 1474 * deassertion of the hardreset lines themselves.)
1475 * the module did not reset in time, or 0 upon success. 1475 *
1476 * The default software reset mechanism for most OMAP IP blocks is
1477 * triggered via the OCP_SYSCONFIG.SOFTRESET bit. However, some
1478 * hwmods cannot be reset via this method. Some are not targets and
1479 * therefore have no OCP header registers to access. Others (like the
1480 * IVA) have idiosyncratic reset sequences. So for these relatively
1481 * rare cases, custom reset code can be supplied in the struct
1482 * omap_hwmod_class .reset function pointer. Passes along the return
1483 * value from either _ocp_softreset() or the custom reset function -
1484 * these must return -EINVAL if the hwmod cannot be reset this way or
1485 * if the hwmod is in the wrong state, -ETIMEDOUT if the module did
1486 * not reset in time, or 0 upon success.
1476 */ 1487 */
1477static int _reset(struct omap_hwmod *oh) 1488static int _reset(struct omap_hwmod *oh)
1478{ 1489{
1479 int ret; 1490 int i, r;
1480 1491
1481 pr_debug("omap_hwmod: %s: resetting\n", oh->name); 1492 pr_debug("omap_hwmod: %s: resetting\n", oh->name);
1482 1493
1494 if (oh->class->reset) {
1495 r = oh->class->reset(oh);
1496 } else {
1497 if (oh->rst_lines_cnt > 0) {
1498 for (i = 0; i < oh->rst_lines_cnt; i++)
1499 _assert_hardreset(oh, oh->rst_lines[i].name);
1500 return 0;
1501 } else {
1502 r = _ocp_softreset(oh);
1503 if (r == -ENOENT)
1504 r = 0;
1505 }
1506 }
1507
1483 /* 1508 /*
1484 * XXX We're not resetting modules with hardreset lines 1509 * OCP_SYSCONFIG bits need to be reprogrammed after a
1485 * automatically here. Should we do this also, or just expect 1510 * softreset. The _enable() function should be split to avoid
1486 * those modules to define custom reset functions? 1511 * the rewrite of the OCP_SYSCONFIG register.
1487 */ 1512 */
1488 ret = (oh->class->reset) ? oh->class->reset(oh) : _ocp_softreset(oh);
1489
1490 if (oh->class->sysc) { 1513 if (oh->class->sysc) {
1491 _update_sysc_cache(oh); 1514 _update_sysc_cache(oh);
1492 _enable_sysc(oh); 1515 _enable_sysc(oh);
1493 } 1516 }
1494 1517
1495 return ret; 1518 return r;
1496} 1519}
1497 1520
1498/** 1521/**