forked from Minki/linux
omap: hwmod: Handle modules with 16bit registers
Some modules which have 16bit registers can cause imprecise aborts if a __raw_readl/writel is used to read/write 32 bits. Add an additional flag to identify modules which have such hard requirement, and handle it in the hwmod framework. Signed-off-by: Rajendra Nayak <rnayak@ti.com> Acked-by: Paul Walmsley <paul@pwsan.com> Tested-by: Kevin Hilman <khilman@deeprootsystems.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
This commit is contained in:
parent
c710e19222
commit
cc7a1d2a54
@ -184,7 +184,7 @@ static int _update_sysc_cache(struct omap_hwmod *oh)
|
|||||||
|
|
||||||
/* XXX ensure module interface clock is up */
|
/* XXX ensure module interface clock is up */
|
||||||
|
|
||||||
oh->_sysc_cache = omap_hwmod_readl(oh, oh->class->sysc->sysc_offs);
|
oh->_sysc_cache = omap_hwmod_read(oh, oh->class->sysc->sysc_offs);
|
||||||
|
|
||||||
if (!(oh->class->sysc->sysc_flags & SYSC_NO_CACHE))
|
if (!(oh->class->sysc->sysc_flags & SYSC_NO_CACHE))
|
||||||
oh->_int_flags |= _HWMOD_SYSCONFIG_LOADED;
|
oh->_int_flags |= _HWMOD_SYSCONFIG_LOADED;
|
||||||
@ -211,7 +211,7 @@ static void _write_sysconfig(u32 v, struct omap_hwmod *oh)
|
|||||||
|
|
||||||
if (oh->_sysc_cache != v) {
|
if (oh->_sysc_cache != v) {
|
||||||
oh->_sysc_cache = v;
|
oh->_sysc_cache = v;
|
||||||
omap_hwmod_writel(v, oh, oh->class->sysc->sysc_offs);
|
omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1133,12 +1133,12 @@ static int _reset(struct omap_hwmod *oh)
|
|||||||
_write_sysconfig(v, oh);
|
_write_sysconfig(v, oh);
|
||||||
|
|
||||||
if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
|
if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
|
||||||
omap_test_timeout((omap_hwmod_readl(oh,
|
omap_test_timeout((omap_hwmod_read(oh,
|
||||||
oh->class->sysc->syss_offs)
|
oh->class->sysc->syss_offs)
|
||||||
& SYSS_RESETDONE_MASK),
|
& SYSS_RESETDONE_MASK),
|
||||||
MAX_MODULE_SOFTRESET_WAIT, c);
|
MAX_MODULE_SOFTRESET_WAIT, c);
|
||||||
else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS)
|
else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS)
|
||||||
omap_test_timeout(!(omap_hwmod_readl(oh,
|
omap_test_timeout(!(omap_hwmod_read(oh,
|
||||||
oh->class->sysc->sysc_offs)
|
oh->class->sysc->sysc_offs)
|
||||||
& SYSC_TYPE2_SOFTRESET_MASK),
|
& SYSC_TYPE2_SOFTRESET_MASK),
|
||||||
MAX_MODULE_SOFTRESET_WAIT, c);
|
MAX_MODULE_SOFTRESET_WAIT, c);
|
||||||
@ -1378,14 +1378,20 @@ static int _setup(struct omap_hwmod *oh, void *data)
|
|||||||
|
|
||||||
/* Public functions */
|
/* Public functions */
|
||||||
|
|
||||||
u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs)
|
u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs)
|
||||||
{
|
{
|
||||||
return __raw_readl(oh->_mpu_rt_va + reg_offs);
|
if (oh->flags & HWMOD_16BIT_REG)
|
||||||
|
return __raw_readw(oh->_mpu_rt_va + reg_offs);
|
||||||
|
else
|
||||||
|
return __raw_readl(oh->_mpu_rt_va + reg_offs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs)
|
void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs)
|
||||||
{
|
{
|
||||||
__raw_writel(v, oh->_mpu_rt_va + reg_offs);
|
if (oh->flags & HWMOD_16BIT_REG)
|
||||||
|
__raw_writew(v, oh->_mpu_rt_va + reg_offs);
|
||||||
|
else
|
||||||
|
__raw_writel(v, oh->_mpu_rt_va + reg_offs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1732,7 +1738,7 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
|
|||||||
* Forces posted writes to complete on the OCP thread handling
|
* Forces posted writes to complete on the OCP thread handling
|
||||||
* register writes
|
* register writes
|
||||||
*/
|
*/
|
||||||
omap_hwmod_readl(oh, oh->class->sysc->sysc_offs);
|
omap_hwmod_read(oh, oh->class->sysc->sysc_offs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -370,6 +370,7 @@ struct omap_hwmod_omap4_prcm {
|
|||||||
* This is needed for devices like DSS that require optional clocks enabled
|
* This is needed for devices like DSS that require optional clocks enabled
|
||||||
* in order to complete the reset. Optional clocks will be disabled
|
* in order to complete the reset. Optional clocks will be disabled
|
||||||
* again after the reset.
|
* again after the reset.
|
||||||
|
* HWMOD_16BIT_REG: Module has 16bit registers
|
||||||
*/
|
*/
|
||||||
#define HWMOD_SWSUP_SIDLE (1 << 0)
|
#define HWMOD_SWSUP_SIDLE (1 << 0)
|
||||||
#define HWMOD_SWSUP_MSTANDBY (1 << 1)
|
#define HWMOD_SWSUP_MSTANDBY (1 << 1)
|
||||||
@ -379,6 +380,7 @@ struct omap_hwmod_omap4_prcm {
|
|||||||
#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5)
|
#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5)
|
||||||
#define HWMOD_NO_IDLEST (1 << 6)
|
#define HWMOD_NO_IDLEST (1 << 6)
|
||||||
#define HWMOD_CONTROL_OPT_CLKS_IN_RESET (1 << 7)
|
#define HWMOD_CONTROL_OPT_CLKS_IN_RESET (1 << 7)
|
||||||
|
#define HWMOD_16BIT_REG (1 << 8)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* omap_hwmod._int_flags definitions
|
* omap_hwmod._int_flags definitions
|
||||||
@ -527,8 +529,8 @@ int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
|
|||||||
int omap_hwmod_reset(struct omap_hwmod *oh);
|
int omap_hwmod_reset(struct omap_hwmod *oh);
|
||||||
void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
|
void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
|
||||||
|
|
||||||
void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs);
|
void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
|
||||||
u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs);
|
u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
|
||||||
|
|
||||||
int omap_hwmod_count_resources(struct omap_hwmod *oh);
|
int omap_hwmod_count_resources(struct omap_hwmod *oh);
|
||||||
int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
|
int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
|
||||||
|
Loading…
Reference in New Issue
Block a user