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.c248
1 files changed, 193 insertions, 55 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index e282e35769fd..e39772beaedd 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * omap_hwmod implementation for OMAP2/3/4 2 * omap_hwmod implementation for OMAP2/3/4
3 * 3 *
4 * Copyright (C) 2009-2010 Nokia Corporation 4 * Copyright (C) 2009-2011 Nokia Corporation
5 * 5 *
6 * Paul Walmsley, Benoît Cousson, Kevin Hilman 6 * Paul Walmsley, Benoît Cousson, Kevin Hilman
7 * 7 *
@@ -162,9 +162,6 @@ static LIST_HEAD(omap_hwmod_list);
162/* mpu_oh: used to add/remove MPU initiator from sleepdep list */ 162/* mpu_oh: used to add/remove MPU initiator from sleepdep list */
163static struct omap_hwmod *mpu_oh; 163static struct omap_hwmod *mpu_oh;
164 164
165/* inited: 0 if omap_hwmod_init() has not yet been called; 1 otherwise */
166static u8 inited;
167
168 165
169/* Private functions */ 166/* Private functions */
170 167
@@ -460,14 +457,18 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
460 * will be accessed by a particular initiator (e.g., if a module will 457 * will be accessed by a particular initiator (e.g., if a module will
461 * be accessed by the IVA, there should be a sleepdep between the IVA 458 * be accessed by the IVA, there should be a sleepdep between the IVA
462 * initiator and the module). Only applies to modules in smart-idle 459 * initiator and the module). Only applies to modules in smart-idle
463 * mode. Returns -EINVAL upon error or passes along 460 * mode. If the clockdomain is marked as not needing autodeps, return
464 * clkdm_add_sleepdep() value upon success. 461 * 0 without doing anything. Otherwise, returns -EINVAL upon error or
462 * passes along clkdm_add_sleepdep() value upon success.
465 */ 463 */
466static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) 464static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
467{ 465{
468 if (!oh->_clk) 466 if (!oh->_clk)
469 return -EINVAL; 467 return -EINVAL;
470 468
469 if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
470 return 0;
471
471 return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm); 472 return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
472} 473}
473 474
@@ -480,14 +481,18 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
480 * be accessed by a particular initiator (e.g., if a module will not 481 * be accessed by a particular initiator (e.g., if a module will not
481 * be accessed by the IVA, there should be no sleepdep between the IVA 482 * be accessed by the IVA, there should be no sleepdep between the IVA
482 * initiator and the module). Only applies to modules in smart-idle 483 * initiator and the module). Only applies to modules in smart-idle
483 * mode. Returns -EINVAL upon error or passes along 484 * mode. If the clockdomain is marked as not needing autodeps, return
484 * clkdm_del_sleepdep() value upon success. 485 * 0 without doing anything. Returns -EINVAL upon error or passes
486 * along clkdm_del_sleepdep() value upon success.
485 */ 487 */
486static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) 488static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
487{ 489{
488 if (!oh->_clk) 490 if (!oh->_clk)
489 return -EINVAL; 491 return -EINVAL;
490 492
493 if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
494 return 0;
495
491 return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm); 496 return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
492} 497}
493 498
@@ -904,18 +909,16 @@ static struct omap_hwmod *_lookup(const char *name)
904 * @oh: struct omap_hwmod * 909 * @oh: struct omap_hwmod *
905 * @data: not used; pass NULL 910 * @data: not used; pass NULL
906 * 911 *
907 * Called by omap_hwmod_late_init() (after omap2_clk_init()). 912 * Called by omap_hwmod_setup_*() (after omap2_clk_init()).
908 * Resolves all clock names embedded in the hwmod. Returns -EINVAL if 913 * Resolves all clock names embedded in the hwmod. Returns 0 on
909 * the omap_hwmod has not yet been registered or if the clocks have 914 * success, or a negative error code on failure.
910 * already been initialized, 0 on success, or a non-zero error on
911 * failure.
912 */ 915 */
913static int _init_clocks(struct omap_hwmod *oh, void *data) 916static int _init_clocks(struct omap_hwmod *oh, void *data)
914{ 917{
915 int ret = 0; 918 int ret = 0;
916 919
917 if (!oh || (oh->_state != _HWMOD_STATE_REGISTERED)) 920 if (oh->_state != _HWMOD_STATE_REGISTERED)
918 return -EINVAL; 921 return 0;
919 922
920 pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name); 923 pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name);
921 924
@@ -1288,6 +1291,42 @@ static int _idle(struct omap_hwmod *oh)
1288} 1291}
1289 1292
1290/** 1293/**
1294 * omap_hwmod_set_ocp_autoidle - set the hwmod's OCP autoidle bit
1295 * @oh: struct omap_hwmod *
1296 * @autoidle: desired AUTOIDLE bitfield value (0 or 1)
1297 *
1298 * Sets the IP block's OCP autoidle bit in hardware, and updates our
1299 * local copy. Intended to be used by drivers that require
1300 * direct manipulation of the AUTOIDLE bits.
1301 * Returns -EINVAL if @oh is null or is not in the ENABLED state, or passes
1302 * along the return value from _set_module_autoidle().
1303 *
1304 * Any users of this function should be scrutinized carefully.
1305 */
1306int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle)
1307{
1308 u32 v;
1309 int retval = 0;
1310 unsigned long flags;
1311
1312 if (!oh || oh->_state != _HWMOD_STATE_ENABLED)
1313 return -EINVAL;
1314
1315 spin_lock_irqsave(&oh->_lock, flags);
1316
1317 v = oh->_sysc_cache;
1318
1319 retval = _set_module_autoidle(oh, autoidle, &v);
1320
1321 if (!retval)
1322 _write_sysconfig(v, oh);
1323
1324 spin_unlock_irqrestore(&oh->_lock, flags);
1325
1326 return retval;
1327}
1328
1329/**
1291 * _shutdown - shutdown an omap_hwmod 1330 * _shutdown - shutdown an omap_hwmod
1292 * @oh: struct omap_hwmod * 1331 * @oh: struct omap_hwmod *
1293 * 1332 *
@@ -1354,14 +1393,16 @@ static int _shutdown(struct omap_hwmod *oh)
1354 * @oh: struct omap_hwmod * 1393 * @oh: struct omap_hwmod *
1355 * 1394 *
1356 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh 1395 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
1357 * OCP_SYSCONFIG register. Returns -EINVAL if the hwmod is in the 1396 * OCP_SYSCONFIG register. Returns 0.
1358 * wrong state or returns 0.
1359 */ 1397 */
1360static int _setup(struct omap_hwmod *oh, void *data) 1398static int _setup(struct omap_hwmod *oh, void *data)
1361{ 1399{
1362 int i, r; 1400 int i, r;
1363 u8 postsetup_state; 1401 u8 postsetup_state;
1364 1402
1403 if (oh->_state != _HWMOD_STATE_CLKS_INITED)
1404 return 0;
1405
1365 /* Set iclk autoidle mode */ 1406 /* Set iclk autoidle mode */
1366 if (oh->slaves_cnt > 0) { 1407 if (oh->slaves_cnt > 0) {
1367 for (i = 0; i < oh->slaves_cnt; i++) { 1408 for (i = 0; i < oh->slaves_cnt; i++) {
@@ -1455,7 +1496,7 @@ static int _setup(struct omap_hwmod *oh, void *data)
1455 */ 1496 */
1456static int __init _register(struct omap_hwmod *oh) 1497static int __init _register(struct omap_hwmod *oh)
1457{ 1498{
1458 int ret, ms_id; 1499 int ms_id;
1459 1500
1460 if (!oh || !oh->name || !oh->class || !oh->class->name || 1501 if (!oh || !oh->name || !oh->class || !oh->class->name ||
1461 (oh->_state != _HWMOD_STATE_UNKNOWN)) 1502 (oh->_state != _HWMOD_STATE_UNKNOWN))
@@ -1467,12 +1508,10 @@ static int __init _register(struct omap_hwmod *oh)
1467 return -EEXIST; 1508 return -EEXIST;
1468 1509
1469 ms_id = _find_mpu_port_index(oh); 1510 ms_id = _find_mpu_port_index(oh);
1470 if (!IS_ERR_VALUE(ms_id)) { 1511 if (!IS_ERR_VALUE(ms_id))
1471 oh->_mpu_port_index = ms_id; 1512 oh->_mpu_port_index = ms_id;
1472 oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index); 1513 else
1473 } else {
1474 oh->_int_flags |= _HWMOD_NO_MPU_PORT; 1514 oh->_int_flags |= _HWMOD_NO_MPU_PORT;
1475 }
1476 1515
1477 list_add_tail(&oh->node, &omap_hwmod_list); 1516 list_add_tail(&oh->node, &omap_hwmod_list);
1478 1517
@@ -1480,9 +1519,14 @@ static int __init _register(struct omap_hwmod *oh)
1480 1519
1481 oh->_state = _HWMOD_STATE_REGISTERED; 1520 oh->_state = _HWMOD_STATE_REGISTERED;
1482 1521
1483 ret = 0; 1522 /*
1523 * XXX Rather than doing a strcmp(), this should test a flag
1524 * set in the hwmod data, inserted by the autogenerator code.
1525 */
1526 if (!strcmp(oh->name, MPU_INITIATOR_NAME))
1527 mpu_oh = oh;
1484 1528
1485 return ret; 1529 return 0;
1486} 1530}
1487 1531
1488 1532
@@ -1585,65 +1629,132 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
1585 return ret; 1629 return ret;
1586} 1630}
1587 1631
1588
1589/** 1632/**
1590 * omap_hwmod_init - init omap_hwmod code and register hwmods 1633 * omap_hwmod_register - register an array of hwmods
1591 * @ohs: pointer to an array of omap_hwmods to register 1634 * @ohs: pointer to an array of omap_hwmods to register
1592 * 1635 *
1593 * Intended to be called early in boot before the clock framework is 1636 * Intended to be called early in boot before the clock framework is
1594 * initialized. If @ohs is not null, will register all omap_hwmods 1637 * initialized. If @ohs is not null, will register all omap_hwmods
1595 * listed in @ohs that are valid for this chip. Returns -EINVAL if 1638 * listed in @ohs that are valid for this chip. Returns 0.
1596 * omap_hwmod_init() has already been called or 0 otherwise. 1639 */
1640int __init omap_hwmod_register(struct omap_hwmod **ohs)
1641{
1642 int r, i;
1643
1644 if (!ohs)
1645 return 0;
1646
1647 i = 0;
1648 do {
1649 if (!omap_chip_is(ohs[i]->omap_chip))
1650 continue;
1651
1652 r = _register(ohs[i]);
1653 WARN(r, "omap_hwmod: %s: _register returned %d\n", ohs[i]->name,
1654 r);
1655 } while (ohs[++i]);
1656
1657 return 0;
1658}
1659
1660/*
1661 * _populate_mpu_rt_base - populate the virtual address for a hwmod
1662 *
1663 * Must be called only from omap_hwmod_setup_*() so ioremap works properly.
1664 * Assumes the caller takes care of locking if needed.
1597 */ 1665 */
1598int __init omap_hwmod_init(struct omap_hwmod **ohs) 1666static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data)
1667{
1668 if (oh->_state != _HWMOD_STATE_REGISTERED)
1669 return 0;
1670
1671 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
1672 return 0;
1673
1674 oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
1675 if (!oh->_mpu_rt_va)
1676 pr_warning("omap_hwmod: %s found no _mpu_rt_va for %s\n",
1677 __func__, oh->name);
1678
1679 return 0;
1680}
1681
1682/**
1683 * omap_hwmod_setup_one - set up a single hwmod
1684 * @oh_name: const char * name of the already-registered hwmod to set up
1685 *
1686 * Must be called after omap2_clk_init(). Resolves the struct clk
1687 * names to struct clk pointers for each registered omap_hwmod. Also
1688 * calls _setup() on each hwmod. Returns -EINVAL upon error or 0 upon
1689 * success.
1690 */
1691int __init omap_hwmod_setup_one(const char *oh_name)
1599{ 1692{
1600 struct omap_hwmod *oh; 1693 struct omap_hwmod *oh;
1601 int r; 1694 int r;
1602 1695
1603 if (inited) 1696 pr_debug("omap_hwmod: %s: %s\n", oh_name, __func__);
1697
1698 if (!mpu_oh) {
1699 pr_err("omap_hwmod: %s: cannot setup_one: MPU initiator hwmod %s not yet registered\n",
1700 oh_name, MPU_INITIATOR_NAME);
1604 return -EINVAL; 1701 return -EINVAL;
1702 }
1605 1703
1606 inited = 1; 1704 oh = _lookup(oh_name);
1705 if (!oh) {
1706 WARN(1, "omap_hwmod: %s: hwmod not yet registered\n", oh_name);
1707 return -EINVAL;
1708 }
1607 1709
1608 if (!ohs) 1710 if (mpu_oh->_state == _HWMOD_STATE_REGISTERED && oh != mpu_oh)
1609 return 0; 1711 omap_hwmod_setup_one(MPU_INITIATOR_NAME);
1610 1712
1611 oh = *ohs; 1713 r = _populate_mpu_rt_base(oh, NULL);
1612 while (oh) { 1714 if (IS_ERR_VALUE(r)) {
1613 if (omap_chip_is(oh->omap_chip)) { 1715 WARN(1, "omap_hwmod: %s: couldn't set mpu_rt_base\n", oh_name);
1614 r = _register(oh); 1716 return -EINVAL;
1615 WARN(r, "omap_hwmod: %s: _register returned " 1717 }
1616 "%d\n", oh->name, r); 1718
1617 } 1719 r = _init_clocks(oh, NULL);
1618 oh = *++ohs; 1720 if (IS_ERR_VALUE(r)) {
1721 WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh_name);
1722 return -EINVAL;
1619 } 1723 }
1620 1724
1725 _setup(oh, NULL);
1726
1621 return 0; 1727 return 0;
1622} 1728}
1623 1729
1624/** 1730/**
1625 * omap_hwmod_late_init - do some post-clock framework initialization 1731 * omap_hwmod_setup - do some post-clock framework initialization
1626 * 1732 *
1627 * Must be called after omap2_clk_init(). Resolves the struct clk names 1733 * Must be called after omap2_clk_init(). Resolves the struct clk names
1628 * to struct clk pointers for each registered omap_hwmod. Also calls 1734 * to struct clk pointers for each registered omap_hwmod. Also calls
1629 * _setup() on each hwmod. Returns 0. 1735 * _setup() on each hwmod. Returns 0 upon success.
1630 */ 1736 */
1631int omap_hwmod_late_init(void) 1737static int __init omap_hwmod_setup_all(void)
1632{ 1738{
1633 int r; 1739 int r;
1634 1740
1635 /* XXX check return value */ 1741 if (!mpu_oh) {
1636 r = omap_hwmod_for_each(_init_clocks, NULL); 1742 pr_err("omap_hwmod: %s: MPU initiator hwmod %s not yet registered\n",
1637 WARN(r, "omap_hwmod: omap_hwmod_late_init(): _init_clocks failed\n"); 1743 __func__, MPU_INITIATOR_NAME);
1744 return -EINVAL;
1745 }
1746
1747 r = omap_hwmod_for_each(_populate_mpu_rt_base, NULL);
1638 1748
1639 mpu_oh = omap_hwmod_lookup(MPU_INITIATOR_NAME); 1749 r = omap_hwmod_for_each(_init_clocks, NULL);
1640 WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n", 1750 WARN(IS_ERR_VALUE(r),
1641 MPU_INITIATOR_NAME); 1751 "omap_hwmod: %s: _init_clocks failed\n", __func__);
1642 1752
1643 omap_hwmod_for_each(_setup, NULL); 1753 omap_hwmod_for_each(_setup, NULL);
1644 1754
1645 return 0; 1755 return 0;
1646} 1756}
1757core_initcall(omap_hwmod_setup_all);
1647 1758
1648/** 1759/**
1649 * omap_hwmod_enable - enable an omap_hwmod 1760 * omap_hwmod_enable - enable an omap_hwmod
@@ -1862,6 +1973,7 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
1862 os = oh->slaves[i]; 1973 os = oh->slaves[i];
1863 1974
1864 for (j = 0; j < os->addr_cnt; j++) { 1975 for (j = 0; j < os->addr_cnt; j++) {
1976 (res + r)->name = (os->addr + j)->name;
1865 (res + r)->start = (os->addr + j)->pa_start; 1977 (res + r)->start = (os->addr + j)->pa_start;
1866 (res + r)->end = (os->addr + j)->pa_end; 1978 (res + r)->end = (os->addr + j)->pa_end;
1867 (res + r)->flags = IORESOURCE_MEM; 1979 (res + r)->flags = IORESOURCE_MEM;
@@ -2162,11 +2274,11 @@ int omap_hwmod_for_each_by_class(const char *classname,
2162 * @oh: struct omap_hwmod * 2274 * @oh: struct omap_hwmod *
2163 * @state: state that _setup() should leave the hwmod in 2275 * @state: state that _setup() should leave the hwmod in
2164 * 2276 *
2165 * Sets the hwmod state that @oh will enter at the end of _setup() (called by 2277 * Sets the hwmod state that @oh will enter at the end of _setup()
2166 * omap_hwmod_late_init()). Only valid to call between calls to 2278 * (called by omap_hwmod_setup_*()). Only valid to call between
2167 * omap_hwmod_init() and omap_hwmod_late_init(). Returns 0 upon success or 2279 * calling omap_hwmod_register() and omap_hwmod_setup_*(). Returns
2168 * -EINVAL if there is a problem with the arguments or if the hwmod is 2280 * 0 upon success or -EINVAL if there is a problem with the arguments
2169 * in the wrong state. 2281 * or if the hwmod is in the wrong state.
2170 */ 2282 */
2171int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state) 2283int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
2172{ 2284{
@@ -2218,3 +2330,29 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
2218 2330
2219 return ret; 2331 return ret;
2220} 2332}
2333
2334/**
2335 * omap_hwmod_no_setup_reset - prevent a hwmod from being reset upon setup
2336 * @oh: struct omap_hwmod *
2337 *
2338 * Prevent the hwmod @oh from being reset during the setup process.
2339 * Intended for use by board-*.c files on boards with devices that
2340 * cannot tolerate being reset. Must be called before the hwmod has
2341 * been set up. Returns 0 upon success or negative error code upon
2342 * failure.
2343 */
2344int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
2345{
2346 if (!oh)
2347 return -EINVAL;
2348
2349 if (oh->_state != _HWMOD_STATE_REGISTERED) {
2350 pr_err("omap_hwmod: %s: cannot prevent setup reset; in wrong state\n",
2351 oh->name);
2352 return -EINVAL;
2353 }
2354
2355 oh->flags |= HWMOD_INIT_NO_RESET;
2356
2357 return 0;
2358}