Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 216854
b: refs/heads/master
c: 5365efb
h: refs/heads/master
v: v3
  • Loading branch information
Benoît Cousson authored and Paul Walmsley committed Sep 21, 2010
1 parent 0203088 commit 21bbe16
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cf21405fd51b416f071edb546631a6ecd2112263
refs/heads/master: 5365efbe29250a227502256cc912351fe2157b42
168 changes: 160 additions & 8 deletions trunk/arch/arm/mach-omap2/omap_hwmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@
#include <plat/powerdomain.h>
#include <plat/clock.h>
#include <plat/omap_hwmod.h>
#include <plat/prcm.h>

#include "cm.h"
#include "prm.h"

/* Maximum microseconds to wait for OMAP module to reset */
#define MAX_MODULE_RESET_WAIT 10000
/* Maximum microseconds to wait for OMAP module to softreset */
#define MAX_MODULE_SOFTRESET_WAIT 10000

/* Name of the OMAP hwmod for the MPU */
#define MPU_INITIATOR_NAME "mpu"
Expand Down Expand Up @@ -833,6 +835,130 @@ static int _wait_target_ready(struct omap_hwmod *oh)
return ret;
}

/**
* _lookup_hardreset - return the register bit shift for this hwmod/reset line
* @oh: struct omap_hwmod *
* @name: name of the reset line in the context of this hwmod
*
* Return the bit position of the reset line that match the
* input name. Return -ENOENT if not found.
*/
static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name)
{
int i;

for (i = 0; i < oh->rst_lines_cnt; i++) {
const char *rst_line = oh->rst_lines[i].name;
if (!strcmp(rst_line, name)) {
u8 shift = oh->rst_lines[i].rst_shift;
pr_debug("omap_hwmod: %s: _lookup_hardreset: %s: %d\n",
oh->name, rst_line, shift);

return shift;
}
}

return -ENOENT;
}

/**
* _assert_hardreset - assert the HW reset line of submodules
* contained in the hwmod module.
* @oh: struct omap_hwmod *
* @name: name of the reset line to lookup and assert
*
* Some IP like dsp, ipu or iva contain processor that require
* an HW reset line to be assert / deassert in order to enable fully
* the IP.
*/
static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
{
u8 shift;

if (!oh)
return -EINVAL;

shift = _lookup_hardreset(oh, name);
if (IS_ERR_VALUE(shift))
return shift;

if (cpu_is_omap24xx() || cpu_is_omap34xx())
return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
shift);
else if (cpu_is_omap44xx())
return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
shift);
else
return -EINVAL;
}

/**
* _deassert_hardreset - deassert the HW reset line of submodules contained
* in the hwmod module.
* @oh: struct omap_hwmod *
* @name: name of the reset line to look up and deassert
*
* Some IP like dsp, ipu or iva contain processor that require
* an HW reset line to be assert / deassert in order to enable fully
* the IP.
*/
static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
{
u8 shift;
int r;

if (!oh)
return -EINVAL;

shift = _lookup_hardreset(oh, name);
if (IS_ERR_VALUE(shift))
return shift;

if (cpu_is_omap24xx() || cpu_is_omap34xx())
r = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
shift);
else if (cpu_is_omap44xx())
r = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
shift);
else
return -EINVAL;

if (r == -EBUSY)
pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);

return r;
}

/**
* _read_hardreset - read the HW reset line state of submodules
* contained in the hwmod module
* @oh: struct omap_hwmod *
* @name: name of the reset line to look up and read
*
* Return the state of the reset line.
*/
static int _read_hardreset(struct omap_hwmod *oh, const char *name)
{
u8 shift;

if (!oh)
return -EINVAL;

shift = _lookup_hardreset(oh, name);
if (IS_ERR_VALUE(shift))
return shift;

if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
shift);
} else if (cpu_is_omap44xx()) {
return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
shift);
} else {
return -EINVAL;
}
}

/**
* _reset - reset an omap_hwmod
* @oh: struct omap_hwmod *
Expand Down Expand Up @@ -869,20 +995,20 @@ static int _reset(struct omap_hwmod *oh)

omap_test_timeout((omap_hwmod_readl(oh, oh->class->sysc->syss_offs) &
SYSS_RESETDONE_MASK),
MAX_MODULE_RESET_WAIT, c);
MAX_MODULE_SOFTRESET_WAIT, c);

if (c == MAX_MODULE_RESET_WAIT)
WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n",
oh->name, MAX_MODULE_RESET_WAIT);
if (c == MAX_MODULE_SOFTRESET_WAIT)
WARN(1, "omap_hwmod: %s: softreset failed (waited %d usec)\n",
oh->name, MAX_MODULE_SOFTRESET_WAIT);
else
pr_debug("omap_hwmod: %s: reset in %d usec\n", oh->name, c);
pr_debug("omap_hwmod: %s: softreset in %d usec\n", oh->name, c);

/*
* XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
* _wait_target_ready() or _reset()
*/

return (c == MAX_MODULE_RESET_WAIT) ? -ETIMEDOUT : 0;
return (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
}

/**
Expand All @@ -907,6 +1033,15 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)

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

/*
* If an IP contains only one HW reset line, then de-assert it in order
* to allow to enable the clocks. Otherwise the PRCM will return
* Intransition status, and the init will failed.
*/
if ((oh->_state == _HWMOD_STATE_INITIALIZED ||
oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
_deassert_hardreset(oh, oh->rst_lines[0].name);

/* XXX mux balls */

_add_initiator_dep(oh, mpu_oh);
Expand Down Expand Up @@ -981,6 +1116,13 @@ static int _shutdown(struct omap_hwmod *oh)
if (oh->class->sysc)
_sysc_shutdown(oh);

/*
* If an IP contains only one HW reset line, then assert it
* before disabling the clocks and shutting down the IP.
*/
if (oh->rst_lines_cnt == 1)
_assert_hardreset(oh, oh->rst_lines[0].name);

/* clocks and deps are already disabled in idle */
if (oh->_state == _HWMOD_STATE_ENABLED) {
_del_initiator_dep(oh, mpu_oh);
Expand Down Expand Up @@ -1038,6 +1180,16 @@ static int _setup(struct omap_hwmod *oh, void *data)
mutex_init(&oh->_mutex);
oh->_state = _HWMOD_STATE_INITIALIZED;

/*
* In the case of hwmod with hardreset that should not be
* de-assert at boot time, we have to keep the module
* initialized, because we cannot enable it properly with the
* reset asserted. Exit without warning because that behavior is
* expected.
*/
if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt == 1)
return 0;

r = _omap_hwmod_enable(oh);
if (r) {
pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
Expand Down
17 changes: 17 additions & 0 deletions trunk/arch/arm/plat-omap/include/plat/omap_hwmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,19 @@ struct omap_hwmod_dma_info {
u16 dma_req;
};

/**
* struct omap_hwmod_rst_info - IPs reset lines use by hwmod
* @name: name of the reset line (module local name)
* @rst_shift: Offset of the reset bit
*
* @name should be something short, e.g., "cpu0" or "rst". It is defined
* locally to the hwmod.
*/
struct omap_hwmod_rst_info {
const char *name;
u8 rst_shift;
};

/**
* struct omap_hwmod_opt_clk - optional clocks used by this hwmod
* @role: "sys", "32k", "tv", etc -- for use in clk_get()
Expand Down Expand Up @@ -328,10 +341,12 @@ struct omap_hwmod_omap2_prcm {
/**
* struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
* @clkctrl_reg: PRCM address of the clock control register
* @rstctrl_reg: adress of the XXX_RSTCTRL register located in the PRM
* @submodule_wkdep_bit: bit shift of the WKDEP range
*/
struct omap_hwmod_omap4_prcm {
void __iomem *clkctrl_reg;
void __iomem *rstctrl_reg;
u8 submodule_wkdep_bit;
};

Expand Down Expand Up @@ -451,6 +466,7 @@ struct omap_hwmod {
struct omap_device *od;
struct omap_hwmod_irq_info *mpu_irqs;
struct omap_hwmod_dma_info *sdma_reqs;
struct omap_hwmod_rst_info *rst_lines;
union {
struct omap_hwmod_omap2_prcm omap2;
struct omap_hwmod_omap4_prcm omap4;
Expand All @@ -472,6 +488,7 @@ struct omap_hwmod {
u8 response_lat;
u8 mpu_irqs_cnt;
u8 sdma_reqs_cnt;
u8 rst_lines_cnt;
u8 opt_clks_cnt;
u8 masters_cnt;
u8 slaves_cnt;
Expand Down

0 comments on commit 21bbe16

Please sign in to comment.