OMAP2+: hwmod: use status bit info for reset line

On OMAP2 and OMAP3 the reset ctrl shift doesn't match the
status bit, as it does on OMAP4, when handling the reset lines.

This patch adds a new member in the reset info structure, so now it
can be added as part of hwmod data, and checked accordingly for
OMAP2 or 3; otherwise, there could be cases when the shift masks
doesn't match both of the registers, and a successful reset might
throw an error message or vice versa.

Signed-off-by: Omar Ramirez Luna <omar.ramirez@ti.com>
[paul@pwsan.com: added a warning if st_shift used on OMAP4; renamed 'r'
 variable; improved some documentation]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
This commit is contained in:
omar ramirez 2011-03-04 13:32:44 -07:00 committed by Paul Walmsley
parent 4d2274c543
commit cc1226e763
4 changed files with 58 additions and 42 deletions

View File

@ -972,25 +972,29 @@ static int _wait_target_ready(struct omap_hwmod *oh)
} }
/** /**
* _lookup_hardreset - return the register bit shift for this hwmod/reset line * _lookup_hardreset - fill register bit info for this hwmod/reset line
* @oh: struct omap_hwmod * * @oh: struct omap_hwmod *
* @name: name of the reset line in the context of this hwmod * @name: name of the reset line in the context of this hwmod
* @ohri: struct omap_hwmod_rst_info * that this function will fill in
* *
* Return the bit position of the reset line that match the * Return the bit position of the reset line that match the
* input name. Return -ENOENT if not found. * input name. Return -ENOENT if not found.
*/ */
static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name) static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name,
struct omap_hwmod_rst_info *ohri)
{ {
int i; int i;
for (i = 0; i < oh->rst_lines_cnt; i++) { for (i = 0; i < oh->rst_lines_cnt; i++) {
const char *rst_line = oh->rst_lines[i].name; const char *rst_line = oh->rst_lines[i].name;
if (!strcmp(rst_line, name)) { if (!strcmp(rst_line, name)) {
u8 shift = oh->rst_lines[i].rst_shift; ohri->rst_shift = oh->rst_lines[i].rst_shift;
pr_debug("omap_hwmod: %s: _lookup_hardreset: %s: %d\n", ohri->st_shift = oh->rst_lines[i].st_shift;
oh->name, rst_line, shift); pr_debug("omap_hwmod: %s: %s: %s: rst %d st %d\n",
oh->name, __func__, rst_line, ohri->rst_shift,
ohri->st_shift);
return shift; return 0;
} }
} }
@ -1009,21 +1013,22 @@ static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name)
*/ */
static int _assert_hardreset(struct omap_hwmod *oh, const char *name) static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
{ {
u8 shift; struct omap_hwmod_rst_info ohri;
u8 ret;
if (!oh) if (!oh)
return -EINVAL; return -EINVAL;
shift = _lookup_hardreset(oh, name); ret = _lookup_hardreset(oh, name, &ohri);
if (IS_ERR_VALUE(shift)) if (IS_ERR_VALUE(ret))
return shift; return ret;
if (cpu_is_omap24xx() || cpu_is_omap34xx()) if (cpu_is_omap24xx() || cpu_is_omap34xx())
return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs, return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
shift); ohri.rst_shift);
else if (cpu_is_omap44xx()) else if (cpu_is_omap44xx())
return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg, return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
shift); ohri.rst_shift);
else else
return -EINVAL; return -EINVAL;
} }
@ -1040,29 +1045,34 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
*/ */
static int _deassert_hardreset(struct omap_hwmod *oh, const char *name) static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
{ {
u8 shift; struct omap_hwmod_rst_info ohri;
int r; int ret;
if (!oh) if (!oh)
return -EINVAL; return -EINVAL;
shift = _lookup_hardreset(oh, name); ret = _lookup_hardreset(oh, name, &ohri);
if (IS_ERR_VALUE(shift)) if (IS_ERR_VALUE(ret))
return shift; return ret;
if (cpu_is_omap24xx() || cpu_is_omap34xx()) if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
r = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs, ret = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
shift); ohri.rst_shift,
else if (cpu_is_omap44xx()) ohri.st_shift);
r = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg, } else if (cpu_is_omap44xx()) {
shift); if (ohri.st_shift)
else pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
oh->name, name);
ret = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
ohri.rst_shift);
} else {
return -EINVAL; return -EINVAL;
}
if (r == -EBUSY) if (ret == -EBUSY)
pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name); pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
return r; return ret;
} }
/** /**
@ -1075,21 +1085,22 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
*/ */
static int _read_hardreset(struct omap_hwmod *oh, const char *name) static int _read_hardreset(struct omap_hwmod *oh, const char *name)
{ {
u8 shift; struct omap_hwmod_rst_info ohri;
u8 ret;
if (!oh) if (!oh)
return -EINVAL; return -EINVAL;
shift = _lookup_hardreset(oh, name); ret = _lookup_hardreset(oh, name, &ohri);
if (IS_ERR_VALUE(shift)) if (IS_ERR_VALUE(ret))
return shift; return ret;
if (cpu_is_omap24xx() || cpu_is_omap34xx()) { if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs, return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
shift); ohri.st_shift);
} else if (cpu_is_omap44xx()) { } else if (cpu_is_omap44xx()) {
return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg, return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
shift); ohri.rst_shift);
} else { } else {
return -EINVAL; return -EINVAL;
} }

View File

@ -118,7 +118,8 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
/** /**
* omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait
* @prm_mod: PRM submodule base (e.g. CORE_MOD) * @prm_mod: PRM submodule base (e.g. CORE_MOD)
* @shift: register bit shift corresponding to the reset line to deassert * @rst_shift: register bit shift corresponding to the reset line to deassert
* @st_shift: register bit shift for the status of the deasserted submodule
* *
* Some IPs like dsp or iva contain processors that require an HW * Some IPs like dsp or iva contain processors that require an HW
* reset line to be asserted / deasserted in order to fully enable the * reset line to be asserted / deasserted in order to fully enable the
@ -129,27 +130,28 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
* -EINVAL upon an argument error, -EEXIST if the submodule was already out * -EINVAL upon an argument error, -EEXIST if the submodule was already out
* of reset, or -EBUSY if the submodule did not exit reset promptly. * of reset, or -EBUSY if the submodule did not exit reset promptly.
*/ */
int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift) int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
{ {
u32 mask; u32 rst, st;
int c; int c;
if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
return -EINVAL; return -EINVAL;
mask = 1 << shift; rst = 1 << rst_shift;
st = 1 << st_shift;
/* Check the current status to avoid de-asserting the line twice */ /* Check the current status to avoid de-asserting the line twice */
if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0) if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, rst) == 0)
return -EEXIST; return -EEXIST;
/* Clear the reset status by writing 1 to the status bit */ /* Clear the reset status by writing 1 to the status bit */
omap2_prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST); omap2_prm_rmw_mod_reg_bits(0xffffffff, st, prm_mod, OMAP2_RM_RSTST);
/* de-assert the reset control line */ /* de-assert the reset control line */
omap2_prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL); omap2_prm_rmw_mod_reg_bits(rst, 0, prm_mod, OMAP2_RM_RSTCTRL);
/* wait the status to be set */ /* wait the status to be set */
omap_test_timeout(omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST, omap_test_timeout(omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
mask), st),
MAX_MODULE_HARDRESET_WAIT, c); MAX_MODULE_HARDRESET_WAIT, c);
return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;

View File

@ -282,7 +282,8 @@ static inline int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
"not suppose to be used on omap4\n"); "not suppose to be used on omap4\n");
return 0; return 0;
} }
static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift) static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift,
u8 st_shift)
{ {
WARN(1, "prm: omap2xxx/omap3xxx specific function and " WARN(1, "prm: omap2xxx/omap3xxx specific function and "
"not suppose to be used on omap4\n"); "not suppose to be used on omap4\n");
@ -300,7 +301,7 @@ extern u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
/* These omap2_ PRM functions apply to both OMAP2 and 3 */ /* These omap2_ PRM functions apply to both OMAP2 and 3 */
extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift); extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift); extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift); extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
#endif /* CONFIG_ARCH_OMAP4 */ #endif /* CONFIG_ARCH_OMAP4 */
#endif #endif

View File

@ -124,6 +124,7 @@ struct omap_hwmod_dma_info {
* struct omap_hwmod_rst_info - IPs reset lines use by hwmod * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
* @name: name of the reset line (module local name) * @name: name of the reset line (module local name)
* @rst_shift: Offset of the reset bit * @rst_shift: Offset of the reset bit
* @st_shift: Offset of the reset status bit (OMAP2/3 only)
* *
* @name should be something short, e.g., "cpu0" or "rst". It is defined * @name should be something short, e.g., "cpu0" or "rst". It is defined
* locally to the hwmod. * locally to the hwmod.
@ -131,6 +132,7 @@ struct omap_hwmod_dma_info {
struct omap_hwmod_rst_info { struct omap_hwmod_rst_info {
const char *name; const char *name;
u8 rst_shift; u8 rst_shift;
u8 st_shift;
}; };
/** /**