Skip to content

Commit 747834a

Browse files
author
Paul Walmsley
committed
ARM: OMAP2+: hwmod: revise hardreset behavior
Change the way that hardreset lines are handled by the hwmod code. Hardreset lines are generally associated with initiator IP blocks. Prior to this change, the hwmod code expected to control hardreset lines itself, asserting them on shutdown and deasserting them upon enable. But driver authors inside TI have commented to us that their drivers require direct control over these lines. Unfortunately, these drivers haven't been posted publicly yet, so it's hard to determine exactly what is needed, a priori. This change attempts to set forth some reasonable semantics that should be an improvement over the current code. The semantics implemented by this patch are as follows: - If the hwmod is not marked with HWMOD_INIT_NO_RESET, then assert all associated hardreset lines during IP block setup. This is intended to place the IP blocks into a known state that will not interfere with other devices during kernel boot. - IP blocks with hardreset lines will not be automatically enabled or idled during setup. Instead, they will be left in the INITIALIZED state. - When the hwmod code is asked to enable, idle, or shutdown an IP block with asserted hardreset lines, the hwmod code will do nothing. The driver integration code must do the remaining work needed to control these IP blocks. Once this driver integration code is posted to the lists, hopefully we can consolidate it and move it inside the hwmod code. Custom reset functions for IP blocks with hardreset lines still should be supported and are strongly endorsed. It is intended that every subsystem with hardreset lines should have a custom reset function that can place their subsystem into quiescent idle with the hardreset lines deasserted. This reverts most of commit 5365efb ("OMAP: hwmod: Add hardreset management support"). Later code reorganizations caused the sequencing of the code from this patch to be changed, anyway. Signed-off-by: Paul Walmsley <[email protected]> Cc: Benoît Cousson <[email protected]>
1 parent 64813c3 commit 747834a

File tree

1 file changed

+83
-56
lines changed

1 file changed

+83
-56
lines changed

arch/arm/mach-omap2/omap_hwmod.c

Lines changed: 83 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -780,39 +780,6 @@ static int _omap4_wait_target_disable(struct omap_hwmod *oh)
780780
oh->prcm.omap4.clkctrl_offs);
781781
}
782782

783-
/**
784-
* _omap4_disable_module - enable CLKCTRL modulemode on OMAP4
785-
* @oh: struct omap_hwmod *
786-
*
787-
* Disable the PRCM module mode related to the hwmod @oh.
788-
* Return EINVAL if the modulemode is not supported and 0 in case of success.
789-
*/
790-
static int _omap4_disable_module(struct omap_hwmod *oh)
791-
{
792-
int v;
793-
794-
/* The module mode does not exist prior OMAP4 */
795-
if (!cpu_is_omap44xx())
796-
return -EINVAL;
797-
798-
if (!oh->clkdm || !oh->prcm.omap4.modulemode)
799-
return -EINVAL;
800-
801-
pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
802-
803-
omap4_cminst_module_disable(oh->clkdm->prcm_partition,
804-
oh->clkdm->cm_inst,
805-
oh->clkdm->clkdm_offs,
806-
oh->prcm.omap4.clkctrl_offs);
807-
808-
v = _omap4_wait_target_disable(oh);
809-
if (v)
810-
pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
811-
oh->name);
812-
813-
return 0;
814-
}
815-
816783
/**
817784
* _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh
818785
* @oh: struct omap_hwmod *oh
@@ -1377,6 +1344,66 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
13771344
}
13781345
}
13791346

1347+
/**
1348+
* _are_any_hardreset_lines_asserted - return true if part of @oh is hard-reset
1349+
* @oh: struct omap_hwmod *
1350+
*
1351+
* If any hardreset line associated with @oh is asserted, then return true.
1352+
* Otherwise, if @oh has no hardreset lines associated with it, or if
1353+
* no hardreset lines associated with @oh are asserted, then return false.
1354+
* This function is used to avoid executing some parts of the IP block
1355+
* enable/disable sequence if a hardreset line is set.
1356+
*/
1357+
static bool _are_any_hardreset_lines_asserted(struct omap_hwmod *oh)
1358+
{
1359+
int i;
1360+
1361+
if (oh->rst_lines_cnt == 0)
1362+
return false;
1363+
1364+
for (i = 0; i < oh->rst_lines_cnt; i++)
1365+
if (_read_hardreset(oh, oh->rst_lines[i].name) > 0)
1366+
return true;
1367+
1368+
return false;
1369+
}
1370+
1371+
/**
1372+
* _omap4_disable_module - enable CLKCTRL modulemode on OMAP4
1373+
* @oh: struct omap_hwmod *
1374+
*
1375+
* Disable the PRCM module mode related to the hwmod @oh.
1376+
* Return EINVAL if the modulemode is not supported and 0 in case of success.
1377+
*/
1378+
static int _omap4_disable_module(struct omap_hwmod *oh)
1379+
{
1380+
int v;
1381+
1382+
/* The module mode does not exist prior OMAP4 */
1383+
if (!cpu_is_omap44xx())
1384+
return -EINVAL;
1385+
1386+
if (!oh->clkdm || !oh->prcm.omap4.modulemode)
1387+
return -EINVAL;
1388+
1389+
pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
1390+
1391+
omap4_cminst_module_disable(oh->clkdm->prcm_partition,
1392+
oh->clkdm->cm_inst,
1393+
oh->clkdm->clkdm_offs,
1394+
oh->prcm.omap4.clkctrl_offs);
1395+
1396+
if (_are_any_hardreset_lines_asserted(oh))
1397+
return 0;
1398+
1399+
v = _omap4_wait_target_disable(oh);
1400+
if (v)
1401+
pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
1402+
oh->name);
1403+
1404+
return 0;
1405+
}
1406+
13801407
/**
13811408
* _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit
13821409
* @oh: struct omap_hwmod *
@@ -1528,7 +1555,7 @@ static int _reset(struct omap_hwmod *oh)
15281555
*/
15291556
static int _enable(struct omap_hwmod *oh)
15301557
{
1531-
int r, i;
1558+
int r;
15321559
int hwsup = 0;
15331560

15341561
pr_debug("omap_hwmod: %s: enabling\n", oh->name);
@@ -1560,14 +1587,16 @@ static int _enable(struct omap_hwmod *oh)
15601587
}
15611588

15621589
/*
1563-
* If an IP contains HW reset lines, then de-assert them in order
1564-
* to allow the module state transition. Otherwise the PRCM will return
1565-
* Intransition status, and the init will failed.
1590+
* If an IP block contains HW reset lines and any of them are
1591+
* asserted, we let integration code associated with that
1592+
* block handle the enable. We've received very little
1593+
* information on what those driver authors need, and until
1594+
* detailed information is provided and the driver code is
1595+
* posted to the public lists, this is probably the best we
1596+
* can do.
15661597
*/
1567-
if (oh->_state == _HWMOD_STATE_INITIALIZED ||
1568-
oh->_state == _HWMOD_STATE_DISABLED)
1569-
for (i = 0; i < oh->rst_lines_cnt; i++)
1570-
_deassert_hardreset(oh, oh->rst_lines[i].name);
1598+
if (_are_any_hardreset_lines_asserted(oh))
1599+
return 0;
15711600

15721601
/* Mux pins for device runtime if populated */
15731602
if (oh->mux && (!oh->mux->enabled ||
@@ -1642,6 +1671,9 @@ static int _idle(struct omap_hwmod *oh)
16421671
return -EINVAL;
16431672
}
16441673

1674+
if (_are_any_hardreset_lines_asserted(oh))
1675+
return 0;
1676+
16451677
if (oh->class->sysc)
16461678
_idle_sysc(oh);
16471679
_del_initiator_dep(oh, mpu_oh);
@@ -1724,6 +1756,9 @@ static int _shutdown(struct omap_hwmod *oh)
17241756
return -EINVAL;
17251757
}
17261758

1759+
if (_are_any_hardreset_lines_asserted(oh))
1760+
return 0;
1761+
17271762
pr_debug("omap_hwmod: %s: disabling\n", oh->name);
17281763

17291764
if (oh->class->pre_shutdown) {
@@ -1866,21 +1901,13 @@ static int __init _setup_reset(struct omap_hwmod *oh)
18661901
if (oh->_state != _HWMOD_STATE_INITIALIZED)
18671902
return -EINVAL;
18681903

1869-
/*
1870-
* In the case of hwmod with hardreset that should not be
1871-
* de-assert at boot time, we have to keep the module
1872-
* initialized, because we cannot enable it properly with the
1873-
* reset asserted. Exit without warning because that behavior
1874-
* is expected.
1875-
*/
1876-
if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt > 0)
1877-
return 0;
1878-
1879-
r = _enable(oh);
1880-
if (r) {
1881-
pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
1882-
oh->name, oh->_state);
1883-
return 0;
1904+
if (oh->rst_lines_cnt == 0) {
1905+
r = _enable(oh);
1906+
if (r) {
1907+
pr_warning("omap_hwmod: %s: cannot be enabled for reset (%d)\n",
1908+
oh->name, oh->_state);
1909+
return -EINVAL;
1910+
}
18841911
}
18851912

18861913
if (!(oh->flags & HWMOD_INIT_NO_RESET))

0 commit comments

Comments
 (0)