Skip to content

Commit

Permalink
Merge tag 'omap-fixes-a-for-3.10-rc' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…linux/kernel/git/pjw/omap-pending into fixes

From Paul Walmsley:
Fix the OMAP serial driver to work correctly on OMAP4 when booting
with DT.

* tag 'omap-fixes-a-for-3.10-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending:
  ARM: OMAP2+: hwmod: Remove sysc slave idle and auto idle apis
  SERIAL: OMAP: Remove the slave idle handling from the driver
  ARM: OMAP2+: serial: Remove the un-used slave idle hooks
  ARM: OMAP2+: hwmod-data: UART IP needs software control to manage sidle modes
  ARM: OMAP2+: hwmod: Add a new flag to handle SIDLE in SWSUP only in active
  ARM: OMAP2+: hwmod: Fix sidle programming in _enable_sysc()/_idle_sysc()

Signed-off-by: Olof Johansson <olof@lixom.net>
  • Loading branch information
Olof Johansson committed May 22, 2013
2 parents 8d9849b + 3260c76 commit 25625c9
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 145 deletions.
111 changes: 26 additions & 85 deletions arch/arm/mach-omap2/omap_hwmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -1356,13 +1356,27 @@ static void _enable_sysc(struct omap_hwmod *oh)

clkdm = _get_clkdm(oh);
if (sf & SYSC_HAS_SIDLEMODE) {
if (oh->flags & HWMOD_SWSUP_SIDLE ||
oh->flags & HWMOD_SWSUP_SIDLE_ACT) {
idlemode = HWMOD_IDLEMODE_NO;
} else {
if (sf & SYSC_HAS_ENAWAKEUP)
_enable_wakeup(oh, &v);
if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
idlemode = HWMOD_IDLEMODE_SMART_WKUP;
else
idlemode = HWMOD_IDLEMODE_SMART;
}

/*
* This is special handling for some IPs like
* 32k sync timer. Force them to idle!
*/
clkdm_act = (clkdm && clkdm->flags & CLKDM_ACTIVE_WITH_MPU);
if (clkdm_act && !(oh->class->sysc->idlemodes &
(SIDLE_SMART | SIDLE_SMART_WKUP)))
idlemode = HWMOD_IDLEMODE_FORCE;
else
idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ?
HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;

_set_slave_idlemode(oh, idlemode, &v);
}

Expand Down Expand Up @@ -1391,10 +1405,6 @@ static void _enable_sysc(struct omap_hwmod *oh)
(sf & SYSC_HAS_CLOCKACTIVITY))
_set_clockactivity(oh, oh->class->sysc->clockact, &v);

/* If slave is in SMARTIDLE, also enable wakeup */
if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
_enable_wakeup(oh, &v);

_write_sysconfig(v, oh);

/*
Expand Down Expand Up @@ -1430,13 +1440,16 @@ static void _idle_sysc(struct omap_hwmod *oh)
sf = oh->class->sysc->sysc_flags;

if (sf & SYSC_HAS_SIDLEMODE) {
/* XXX What about HWMOD_IDLEMODE_SMART_WKUP? */
if (oh->flags & HWMOD_SWSUP_SIDLE ||
!(oh->class->sysc->idlemodes &
(SIDLE_SMART | SIDLE_SMART_WKUP)))
if (oh->flags & HWMOD_SWSUP_SIDLE) {
idlemode = HWMOD_IDLEMODE_FORCE;
else
idlemode = HWMOD_IDLEMODE_SMART;
} else {
if (sf & SYSC_HAS_ENAWAKEUP)
_enable_wakeup(oh, &v);
if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
idlemode = HWMOD_IDLEMODE_SMART_WKUP;
else
idlemode = HWMOD_IDLEMODE_SMART;
}
_set_slave_idlemode(oh, idlemode, &v);
}

Expand All @@ -1455,10 +1468,6 @@ static void _idle_sysc(struct omap_hwmod *oh)
_set_master_standbymode(oh, idlemode, &v);
}

/* If slave is in SMARTIDLE, also enable wakeup */
if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
_enable_wakeup(oh, &v);

_write_sysconfig(v, oh);
}

Expand Down Expand Up @@ -2245,42 +2254,6 @@ static int _idle(struct omap_hwmod *oh)
return 0;
}

/**
* omap_hwmod_set_ocp_autoidle - set the hwmod's OCP autoidle bit
* @oh: struct omap_hwmod *
* @autoidle: desired AUTOIDLE bitfield value (0 or 1)
*
* Sets the IP block's OCP autoidle bit in hardware, and updates our
* local copy. Intended to be used by drivers that require
* direct manipulation of the AUTOIDLE bits.
* Returns -EINVAL if @oh is null or is not in the ENABLED state, or passes
* along the return value from _set_module_autoidle().
*
* Any users of this function should be scrutinized carefully.
*/
int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle)
{
u32 v;
int retval = 0;
unsigned long flags;

if (!oh || oh->_state != _HWMOD_STATE_ENABLED)
return -EINVAL;

spin_lock_irqsave(&oh->_lock, flags);

v = oh->_sysc_cache;

retval = _set_module_autoidle(oh, autoidle, &v);

if (!retval)
_write_sysconfig(v, oh);

spin_unlock_irqrestore(&oh->_lock, flags);

return retval;
}

/**
* _shutdown - shutdown an omap_hwmod
* @oh: struct omap_hwmod *
Expand Down Expand Up @@ -3179,38 +3152,6 @@ int omap_hwmod_softreset(struct omap_hwmod *oh)
return ret;
}

/**
* omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode
* @oh: struct omap_hwmod *
* @idlemode: SIDLEMODE field bits (shifted to bit 0)
*
* Sets the IP block's OCP slave idlemode in hardware, and updates our
* local copy. Intended to be used by drivers that have some erratum
* that requires direct manipulation of the SIDLEMODE bits. Returns
* -EINVAL if @oh is null, or passes along the return value from
* _set_slave_idlemode().
*
* XXX Does this function have any current users? If not, we should
* remove it; it is better to let the rest of the hwmod code handle this.
* Any users of this function should be scrutinized carefully.
*/
int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode)
{
u32 v;
int retval = 0;

if (!oh)
return -EINVAL;

v = oh->_sysc_cache;

retval = _set_slave_idlemode(oh, idlemode, &v);
if (!retval)
_write_sysconfig(v, oh);

return retval;
}

/**
* omap_hwmod_lookup - look up a registered omap_hwmod by name
* @name: name of the omap_hwmod to look up
Expand Down
7 changes: 4 additions & 3 deletions arch/arm/mach-omap2/omap_hwmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,9 @@ struct omap_hwmod_omap4_prcm {
* is kept in force-standby mode. Failing to do so causes PM problems
* with musb on OMAP3630 at least. Note that musb has a dedicated register
* to control MSTANDBY signal when MIDLEMODE is set to force-standby.
* HWMOD_SWSUP_SIDLE_ACT: omap_hwmod code should manually bring the module
* out of idle, but rely on smart-idle to the put it back in idle,
* so the wakeups are still functional (Only known case for now is UART)
*/
#define HWMOD_SWSUP_SIDLE (1 << 0)
#define HWMOD_SWSUP_MSTANDBY (1 << 1)
Expand All @@ -476,6 +479,7 @@ struct omap_hwmod_omap4_prcm {
#define HWMOD_EXT_OPT_MAIN_CLK (1 << 9)
#define HWMOD_BLOCK_WFI (1 << 10)
#define HWMOD_FORCE_MSTANDBY (1 << 11)
#define HWMOD_SWSUP_SIDLE_ACT (1 << 12)

/*
* omap_hwmod._int_flags definitions
Expand Down Expand Up @@ -641,9 +645,6 @@ int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name);
int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
int omap_hwmod_disable_clocks(struct omap_hwmod *oh);

int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle);

int omap_hwmod_reset(struct omap_hwmod *oh);
void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);

Expand Down
3 changes: 3 additions & 0 deletions arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ struct omap_hwmod omap2xxx_uart1_hwmod = {
.mpu_irqs = omap2_uart1_mpu_irqs,
.sdma_reqs = omap2_uart1_sdma_reqs,
.main_clk = "uart1_fck",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = CORE_MOD,
Expand All @@ -531,6 +532,7 @@ struct omap_hwmod omap2xxx_uart2_hwmod = {
.mpu_irqs = omap2_uart2_mpu_irqs,
.sdma_reqs = omap2_uart2_sdma_reqs,
.main_clk = "uart2_fck",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = CORE_MOD,
Expand All @@ -550,6 +552,7 @@ struct omap_hwmod omap2xxx_uart3_hwmod = {
.mpu_irqs = omap2_uart3_mpu_irqs,
.sdma_reqs = omap2_uart3_sdma_reqs,
.main_clk = "uart3_fck",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = CORE_MOD,
Expand Down
6 changes: 6 additions & 0 deletions arch/arm/mach-omap2/omap_hwmod_33xx_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -1995,6 +1995,7 @@ static struct omap_hwmod am33xx_uart1_hwmod = {
.name = "uart1",
.class = &uart_class,
.clkdm_name = "l4_wkup_clkdm",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.mpu_irqs = am33xx_uart1_irqs,
.sdma_reqs = uart1_edma_reqs,
.main_clk = "dpll_per_m2_div4_wkupdm_ck",
Expand All @@ -2015,6 +2016,7 @@ static struct omap_hwmod am33xx_uart2_hwmod = {
.name = "uart2",
.class = &uart_class,
.clkdm_name = "l4ls_clkdm",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.mpu_irqs = am33xx_uart2_irqs,
.sdma_reqs = uart1_edma_reqs,
.main_clk = "dpll_per_m2_div4_ck",
Expand Down Expand Up @@ -2042,6 +2044,7 @@ static struct omap_hwmod am33xx_uart3_hwmod = {
.name = "uart3",
.class = &uart_class,
.clkdm_name = "l4ls_clkdm",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.mpu_irqs = am33xx_uart3_irqs,
.sdma_reqs = uart3_edma_reqs,
.main_clk = "dpll_per_m2_div4_ck",
Expand All @@ -2062,6 +2065,7 @@ static struct omap_hwmod am33xx_uart4_hwmod = {
.name = "uart4",
.class = &uart_class,
.clkdm_name = "l4ls_clkdm",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.mpu_irqs = am33xx_uart4_irqs,
.sdma_reqs = uart1_edma_reqs,
.main_clk = "dpll_per_m2_div4_ck",
Expand All @@ -2082,6 +2086,7 @@ static struct omap_hwmod am33xx_uart5_hwmod = {
.name = "uart5",
.class = &uart_class,
.clkdm_name = "l4ls_clkdm",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.mpu_irqs = am33xx_uart5_irqs,
.sdma_reqs = uart1_edma_reqs,
.main_clk = "dpll_per_m2_div4_ck",
Expand All @@ -2102,6 +2107,7 @@ static struct omap_hwmod am33xx_uart6_hwmod = {
.name = "uart6",
.class = &uart_class,
.clkdm_name = "l4ls_clkdm",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.mpu_irqs = am33xx_uart6_irqs,
.sdma_reqs = uart1_edma_reqs,
.main_clk = "dpll_per_m2_div4_ck",
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = {
.mpu_irqs = omap2_uart1_mpu_irqs,
.sdma_reqs = omap2_uart1_sdma_reqs,
.main_clk = "uart1_fck",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = CORE_MOD,
Expand All @@ -508,6 +509,7 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = {
.mpu_irqs = omap2_uart2_mpu_irqs,
.sdma_reqs = omap2_uart2_sdma_reqs,
.main_clk = "uart2_fck",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = CORE_MOD,
Expand All @@ -526,6 +528,7 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
.mpu_irqs = omap2_uart3_mpu_irqs,
.sdma_reqs = omap2_uart3_sdma_reqs,
.main_clk = "uart3_fck",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = OMAP3430_PER_MOD,
Expand Down Expand Up @@ -555,6 +558,7 @@ static struct omap_hwmod omap36xx_uart4_hwmod = {
.mpu_irqs = uart4_mpu_irqs,
.sdma_reqs = uart4_sdma_reqs,
.main_clk = "uart4_fck",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = OMAP3430_PER_MOD,
Expand Down
6 changes: 5 additions & 1 deletion arch/arm/mach-omap2/omap_hwmod_44xx_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -3434,6 +3434,7 @@ static struct omap_hwmod omap44xx_uart1_hwmod = {
.name = "uart1",
.class = &omap44xx_uart_hwmod_class,
.clkdm_name = "l4_per_clkdm",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.mpu_irqs = omap44xx_uart1_irqs,
.sdma_reqs = omap44xx_uart1_sdma_reqs,
.main_clk = "func_48m_fclk",
Expand Down Expand Up @@ -3462,6 +3463,7 @@ static struct omap_hwmod omap44xx_uart2_hwmod = {
.name = "uart2",
.class = &omap44xx_uart_hwmod_class,
.clkdm_name = "l4_per_clkdm",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.mpu_irqs = omap44xx_uart2_irqs,
.sdma_reqs = omap44xx_uart2_sdma_reqs,
.main_clk = "func_48m_fclk",
Expand Down Expand Up @@ -3490,7 +3492,8 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
.name = "uart3",
.class = &omap44xx_uart_hwmod_class,
.clkdm_name = "l4_per_clkdm",
.flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
.flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET |
HWMOD_SWSUP_SIDLE_ACT,
.mpu_irqs = omap44xx_uart3_irqs,
.sdma_reqs = omap44xx_uart3_sdma_reqs,
.main_clk = "func_48m_fclk",
Expand Down Expand Up @@ -3519,6 +3522,7 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
.name = "uart4",
.class = &omap44xx_uart_hwmod_class,
.clkdm_name = "l4_per_clkdm",
.flags = HWMOD_SWSUP_SIDLE_ACT,
.mpu_irqs = omap44xx_uart4_irqs,
.sdma_reqs = omap44xx_uart4_sdma_reqs,
.main_clk = "func_48m_fclk",
Expand Down
31 changes: 0 additions & 31 deletions arch/arm/mach-omap2/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,38 +95,9 @@ static void omap_uart_enable_wakeup(struct device *dev, bool enable)
omap_hwmod_disable_wakeup(od->hwmods[0]);
}

/*
* Errata i291: [UART]:Cannot Acknowledge Idle Requests
* in Smartidle Mode When Configured for DMA Operations.
* WA: configure uart in force idle mode.
*/
static void omap_uart_set_noidle(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct omap_device *od = to_omap_device(pdev);

omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
}

static void omap_uart_set_smartidle(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct omap_device *od = to_omap_device(pdev);
u8 idlemode;

if (od->hwmods[0]->class->sysc->idlemodes & SIDLE_SMART_WKUP)
idlemode = HWMOD_IDLEMODE_SMART_WKUP;
else
idlemode = HWMOD_IDLEMODE_SMART;

omap_hwmod_set_slave_idlemode(od->hwmods[0], idlemode);
}

#else
static void omap_uart_enable_wakeup(struct device *dev, bool enable)
{}
static void omap_uart_set_noidle(struct device *dev) {}
static void omap_uart_set_smartidle(struct device *dev) {}
#endif /* CONFIG_PM */

#ifdef CONFIG_OMAP_MUX
Expand Down Expand Up @@ -299,8 +270,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
omap_up.flags = UPF_BOOT_AUTOCONF;
omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
omap_up.set_forceidle = omap_uart_set_smartidle;
omap_up.set_noidle = omap_uart_set_noidle;
omap_up.enable_wakeup = omap_uart_enable_wakeup;
omap_up.dma_rx_buf_size = info->dma_rx_buf_size;
omap_up.dma_rx_timeout = info->dma_rx_timeout;
Expand Down
Loading

0 comments on commit 25625c9

Please sign in to comment.