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.c154
1 files changed, 100 insertions, 54 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 9e89a58711b..f76f133780c 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
@@ -904,18 +901,16 @@ static struct omap_hwmod *_lookup(const char *name)
904 * @oh: struct omap_hwmod * 901 * @oh: struct omap_hwmod *
905 * @data: not used; pass NULL 902 * @data: not used; pass NULL
906 * 903 *
907 * Called by omap_hwmod_late_init() (after omap2_clk_init()). 904 * Called by omap_hwmod_setup_*() (after omap2_clk_init()).
908 * Resolves all clock names embedded in the hwmod. Returns -EINVAL if 905 * 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 906 * success, or a negative error code on failure.
910 * already been initialized, 0 on success, or a non-zero error on
911 * failure.
912 */ 907 */
913static int _init_clocks(struct omap_hwmod *oh, void *data) 908static int _init_clocks(struct omap_hwmod *oh, void *data)
914{ 909{
915 int ret = 0; 910 int ret = 0;
916 911
917 if (!oh || (oh->_state != _HWMOD_STATE_REGISTERED)) 912 if (oh->_state != _HWMOD_STATE_REGISTERED)
918 return -EINVAL; 913 return 0;
919 914
920 pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name); 915 pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name);
921 916
@@ -1354,14 +1349,16 @@ static int _shutdown(struct omap_hwmod *oh)
1354 * @oh: struct omap_hwmod * 1349 * @oh: struct omap_hwmod *
1355 * 1350 *
1356 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh 1351 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
1357 * OCP_SYSCONFIG register. Returns -EINVAL if the hwmod is in the 1352 * OCP_SYSCONFIG register. Returns 0.
1358 * wrong state or returns 0.
1359 */ 1353 */
1360static int _setup(struct omap_hwmod *oh, void *data) 1354static int _setup(struct omap_hwmod *oh, void *data)
1361{ 1355{
1362 int i, r; 1356 int i, r;
1363 u8 postsetup_state; 1357 u8 postsetup_state;
1364 1358
1359 if (oh->_state != _HWMOD_STATE_CLKS_INITED)
1360 return 0;
1361
1365 /* Set iclk autoidle mode */ 1362 /* Set iclk autoidle mode */
1366 if (oh->slaves_cnt > 0) { 1363 if (oh->slaves_cnt > 0) {
1367 for (i = 0; i < oh->slaves_cnt; i++) { 1364 for (i = 0; i < oh->slaves_cnt; i++) {
@@ -1455,7 +1452,7 @@ static int _setup(struct omap_hwmod *oh, void *data)
1455 */ 1452 */
1456static int __init _register(struct omap_hwmod *oh) 1453static int __init _register(struct omap_hwmod *oh)
1457{ 1454{
1458 int ret, ms_id; 1455 int ms_id;
1459 1456
1460 if (!oh || !oh->name || !oh->class || !oh->class->name || 1457 if (!oh || !oh->name || !oh->class || !oh->class->name ||
1461 (oh->_state != _HWMOD_STATE_UNKNOWN)) 1458 (oh->_state != _HWMOD_STATE_UNKNOWN))
@@ -1478,9 +1475,14 @@ static int __init _register(struct omap_hwmod *oh)
1478 1475
1479 oh->_state = _HWMOD_STATE_REGISTERED; 1476 oh->_state = _HWMOD_STATE_REGISTERED;
1480 1477
1481 ret = 0; 1478 /*
1479 * XXX Rather than doing a strcmp(), this should test a flag
1480 * set in the hwmod data, inserted by the autogenerator code.
1481 */
1482 if (!strcmp(oh->name, MPU_INITIATOR_NAME))
1483 mpu_oh = oh;
1482 1484
1483 return ret; 1485 return 0;
1484} 1486}
1485 1487
1486 1488
@@ -1583,38 +1585,30 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
1583 return ret; 1585 return ret;
1584} 1586}
1585 1587
1586
1587/** 1588/**
1588 * omap_hwmod_init - init omap_hwmod code and register hwmods 1589 * omap_hwmod_register - register an array of hwmods
1589 * @ohs: pointer to an array of omap_hwmods to register 1590 * @ohs: pointer to an array of omap_hwmods to register
1590 * 1591 *
1591 * Intended to be called early in boot before the clock framework is 1592 * Intended to be called early in boot before the clock framework is
1592 * initialized. If @ohs is not null, will register all omap_hwmods 1593 * initialized. If @ohs is not null, will register all omap_hwmods
1593 * listed in @ohs that are valid for this chip. Returns -EINVAL if 1594 * listed in @ohs that are valid for this chip. Returns 0.
1594 * omap_hwmod_init() has already been called or 0 otherwise.
1595 */ 1595 */
1596int __init omap_hwmod_init(struct omap_hwmod **ohs) 1596int __init omap_hwmod_register(struct omap_hwmod **ohs)
1597{ 1597{
1598 struct omap_hwmod *oh; 1598 int r, i;
1599 int r;
1600
1601 if (inited)
1602 return -EINVAL;
1603
1604 inited = 1;
1605 1599
1606 if (!ohs) 1600 if (!ohs)
1607 return 0; 1601 return 0;
1608 1602
1609 oh = *ohs; 1603 i = 0;
1610 while (oh) { 1604 do {
1611 if (omap_chip_is(oh->omap_chip)) { 1605 if (!omap_chip_is(ohs[i]->omap_chip))
1612 r = _register(oh); 1606 continue;
1613 WARN(r, "omap_hwmod: %s: _register returned " 1607
1614 "%d\n", oh->name, r); 1608 r = _register(ohs[i]);
1615 } 1609 WARN(r, "omap_hwmod: %s: _register returned %d\n", ohs[i]->name,
1616 oh = *++ohs; 1610 r);
1617 } 1611 } while (ohs[++i]);
1618 1612
1619 return 0; 1613 return 0;
1620} 1614}
@@ -1622,12 +1616,14 @@ int __init omap_hwmod_init(struct omap_hwmod **ohs)
1622/* 1616/*
1623 * _populate_mpu_rt_base - populate the virtual address for a hwmod 1617 * _populate_mpu_rt_base - populate the virtual address for a hwmod
1624 * 1618 *
1625 * Must be called only from omap_hwmod_late_init so ioremap works properly. 1619 * Must be called only from omap_hwmod_setup_*() so ioremap works properly.
1626 * Assumes the caller takes care of locking if needed. 1620 * Assumes the caller takes care of locking if needed.
1627 *
1628 */ 1621 */
1629static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data) 1622static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data)
1630{ 1623{
1624 if (oh->_state != _HWMOD_STATE_REGISTERED)
1625 return 0;
1626
1631 if (oh->_int_flags & _HWMOD_NO_MPU_PORT) 1627 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
1632 return 0; 1628 return 0;
1633 1629
@@ -1640,31 +1636,81 @@ static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data)
1640} 1636}
1641 1637
1642/** 1638/**
1643 * omap_hwmod_late_init - do some post-clock framework initialization 1639 * omap_hwmod_setup_one - set up a single hwmod
1640 * @oh_name: const char * name of the already-registered hwmod to set up
1641 *
1642 * Must be called after omap2_clk_init(). Resolves the struct clk
1643 * names to struct clk pointers for each registered omap_hwmod. Also
1644 * calls _setup() on each hwmod. Returns -EINVAL upon error or 0 upon
1645 * success.
1646 */
1647int __init omap_hwmod_setup_one(const char *oh_name)
1648{
1649 struct omap_hwmod *oh;
1650 int r;
1651
1652 pr_debug("omap_hwmod: %s: %s\n", oh_name, __func__);
1653
1654 if (!mpu_oh) {
1655 pr_err("omap_hwmod: %s: cannot setup_one: MPU initiator hwmod %s not yet registered\n",
1656 oh_name, MPU_INITIATOR_NAME);
1657 return -EINVAL;
1658 }
1659
1660 oh = _lookup(oh_name);
1661 if (!oh) {
1662 WARN(1, "omap_hwmod: %s: hwmod not yet registered\n", oh_name);
1663 return -EINVAL;
1664 }
1665
1666 if (mpu_oh->_state == _HWMOD_STATE_REGISTERED && oh != mpu_oh)
1667 omap_hwmod_setup_one(MPU_INITIATOR_NAME);
1668
1669 r = _populate_mpu_rt_base(oh, NULL);
1670 if (IS_ERR_VALUE(r)) {
1671 WARN(1, "omap_hwmod: %s: couldn't set mpu_rt_base\n", oh_name);
1672 return -EINVAL;
1673 }
1674
1675 r = _init_clocks(oh, NULL);
1676 if (IS_ERR_VALUE(r)) {
1677 WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh_name);
1678 return -EINVAL;
1679 }
1680
1681 _setup(oh, NULL);
1682
1683 return 0;
1684}
1685
1686/**
1687 * omap_hwmod_setup - do some post-clock framework initialization
1644 * 1688 *
1645 * Must be called after omap2_clk_init(). Resolves the struct clk names 1689 * Must be called after omap2_clk_init(). Resolves the struct clk names
1646 * to struct clk pointers for each registered omap_hwmod. Also calls 1690 * to struct clk pointers for each registered omap_hwmod. Also calls
1647 * _setup() on each hwmod. Returns 0. 1691 * _setup() on each hwmod. Returns 0 upon success.
1648 */ 1692 */
1649static int __init omap_hwmod_late_init(void) 1693static int __init omap_hwmod_setup_all(void)
1650{ 1694{
1651 int r; 1695 int r;
1652 1696
1697 if (!mpu_oh) {
1698 pr_err("omap_hwmod: %s: MPU initiator hwmod %s not yet registered\n",
1699 __func__, MPU_INITIATOR_NAME);
1700 return -EINVAL;
1701 }
1702
1653 r = omap_hwmod_for_each(_populate_mpu_rt_base, NULL); 1703 r = omap_hwmod_for_each(_populate_mpu_rt_base, NULL);
1654 1704
1655 /* XXX check return value */
1656 r = omap_hwmod_for_each(_init_clocks, NULL); 1705 r = omap_hwmod_for_each(_init_clocks, NULL);
1657 WARN(r, "omap_hwmod: omap_hwmod_late_init(): _init_clocks failed\n"); 1706 WARN(IS_ERR_VALUE(r),
1658 1707 "omap_hwmod: %s: _init_clocks failed\n", __func__);
1659 mpu_oh = omap_hwmod_lookup(MPU_INITIATOR_NAME);
1660 WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
1661 MPU_INITIATOR_NAME);
1662 1708
1663 omap_hwmod_for_each(_setup, NULL); 1709 omap_hwmod_for_each(_setup, NULL);
1664 1710
1665 return 0; 1711 return 0;
1666} 1712}
1667core_initcall(omap_hwmod_late_init); 1713core_initcall(omap_hwmod_setup_all);
1668 1714
1669/** 1715/**
1670 * omap_hwmod_enable - enable an omap_hwmod 1716 * omap_hwmod_enable - enable an omap_hwmod
@@ -2183,11 +2229,11 @@ int omap_hwmod_for_each_by_class(const char *classname,
2183 * @oh: struct omap_hwmod * 2229 * @oh: struct omap_hwmod *
2184 * @state: state that _setup() should leave the hwmod in 2230 * @state: state that _setup() should leave the hwmod in
2185 * 2231 *
2186 * Sets the hwmod state that @oh will enter at the end of _setup() (called by 2232 * Sets the hwmod state that @oh will enter at the end of _setup()
2187 * omap_hwmod_late_init()). Only valid to call between calls to 2233 * (called by omap_hwmod_setup_*()). Only valid to call between
2188 * omap_hwmod_init() and omap_hwmod_late_init(). Returns 0 upon success or 2234 * calling omap_hwmod_register() and omap_hwmod_setup_*(). Returns
2189 * -EINVAL if there is a problem with the arguments or if the hwmod is 2235 * 0 upon success or -EINVAL if there is a problem with the arguments
2190 * in the wrong state. 2236 * or if the hwmod is in the wrong state.
2191 */ 2237 */
2192int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state) 2238int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
2193{ 2239{