Skip to content

Commit

Permalink
ARM: OMAP: hwmod: partially un-reset hwmods might not be properly ena…
Browse files Browse the repository at this point in the history
…bled

Some IP blocks might not be using/controlling more than one
reset line, this check loosens the restriction to fully use
hwmod framework for those drivers.

E.g.: ipu has reset lines: mmu_cache, cpu0 and cpu1.
- As of now cpu1 is not used and hence (with previous check) the
  IP block isn't fully enabled by hwmod code.
- Usually ipu and dsp processors configure their mmu module first
  and then enable the processors, this involves:
    * Deasserting mmu reset line, and enabling the module.
    * Deasserting cpu0 reset line, and enabling the processor.
  The ones portrayed in this example are controlled through
  rproc_fw_boot in drivers/remoteproc/remoteproc_core.c

While at it, prevent _omap4_module_disable if all the hardreset
lines on an IP block are not under reset.

This will allow the driver to:
  a. Deassert the reset line.
  b. Enable the hwmod through runtime PM default callbacks.
  c. Do its usecase.
  d. Disable hwmod through runtime PM.
  e. Assert the reset line.

Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
[paul@pwsan.com: updated to apply]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
  • Loading branch information
Omar Ramirez Luna authored and Paul Walmsley committed Sep 23, 2012
1 parent 46b3af2 commit eb05f69
Showing 1 changed file with 23 additions and 16 deletions.
39 changes: 23 additions & 16 deletions arch/arm/mach-omap2/omap_hwmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -1634,25 +1634,28 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
}

/**
* _are_any_hardreset_lines_asserted - return true if part of @oh is hard-reset
* _are_all_hardreset_lines_asserted - return true if the @oh is hard-reset
* @oh: struct omap_hwmod *
*
* If any hardreset line associated with @oh is asserted, then return true.
* Otherwise, if @oh has no hardreset lines associated with it, or if
* no hardreset lines associated with @oh are asserted, then return false.
* If all hardreset lines associated with @oh are asserted, then return true.
* Otherwise, if part of @oh is out hardreset or if no hardreset lines
* associated with @oh are asserted, then return false.
* This function is used to avoid executing some parts of the IP block
* enable/disable sequence if a hardreset line is set.
* enable/disable sequence if its hardreset line is set.
*/
static bool _are_any_hardreset_lines_asserted(struct omap_hwmod *oh)
static bool _are_all_hardreset_lines_asserted(struct omap_hwmod *oh)
{
int i;
int i, rst_cnt = 0;

if (oh->rst_lines_cnt == 0)
return false;

for (i = 0; i < oh->rst_lines_cnt; i++)
if (_read_hardreset(oh, oh->rst_lines[i].name) > 0)
return true;
rst_cnt++;

if (oh->rst_lines_cnt == rst_cnt)
return true;

return false;
}
Expand All @@ -1671,16 +1674,20 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
if (!oh->clkdm || !oh->prcm.omap4.modulemode)
return -EINVAL;

/*
* Since integration code might still be doing something, only
* disable if all lines are under hardreset.
*/
if (!_are_all_hardreset_lines_asserted(oh))
return 0;

pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);

omap4_cminst_module_disable(oh->clkdm->prcm_partition,
oh->clkdm->cm_inst,
oh->clkdm->clkdm_offs,
oh->prcm.omap4.clkctrl_offs);

if (_are_any_hardreset_lines_asserted(oh))
return 0;

v = _omap4_wait_target_disable(oh);
if (v)
pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
Expand Down Expand Up @@ -1708,7 +1715,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh)
am33xx_cm_module_disable(oh->clkdm->cm_inst, oh->clkdm->clkdm_offs,
oh->prcm.omap4.clkctrl_offs);

if (_are_any_hardreset_lines_asserted(oh))
if (_are_all_hardreset_lines_asserted(oh))
return 0;

v = _am33xx_wait_target_disable(oh);
Expand Down Expand Up @@ -1936,15 +1943,15 @@ static int _enable(struct omap_hwmod *oh)
}

/*
* If an IP block contains HW reset lines and any of them are
* If an IP block contains HW reset lines and all of them are
* asserted, we let integration code associated with that
* block handle the enable. We've received very little
* information on what those driver authors need, and until
* detailed information is provided and the driver code is
* posted to the public lists, this is probably the best we
* can do.
*/
if (_are_any_hardreset_lines_asserted(oh))
if (_are_all_hardreset_lines_asserted(oh))
return 0;

/* Mux pins for device runtime if populated */
Expand Down Expand Up @@ -2025,7 +2032,7 @@ static int _idle(struct omap_hwmod *oh)
return -EINVAL;
}

if (_are_any_hardreset_lines_asserted(oh))
if (_are_all_hardreset_lines_asserted(oh))
return 0;

if (oh->class->sysc)
Expand Down Expand Up @@ -2113,7 +2120,7 @@ static int _shutdown(struct omap_hwmod *oh)
return -EINVAL;
}

if (_are_any_hardreset_lines_asserted(oh))
if (_are_all_hardreset_lines_asserted(oh))
return 0;

pr_debug("omap_hwmod: %s: disabling\n", oh->name);
Expand Down

0 comments on commit eb05f69

Please sign in to comment.