aboutsummaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2014-06-02 23:41:46 +0530
committerGary S. Robertson <gary.robertson@linaro.org>2015-01-19 19:14:01 -0600
commitdbc876606a3324b4be6af84eeed515131ce230b1 (patch)
tree5386b79e1cb6b30ab695cc76ffbd7ef9cee930e6 /arch/arm
parent09a1b3920044ef7837f643518413d718ba55c669 (diff)
clockevent: drivers: don't disable events for unsupported modes
'->set_dev_mode()' callback of clockevent drivers gets called when core tries to change 'mode' of a clockevent device. Clockevent drivers should change to the requested mode unless mode isn't supported by driver. Ideally, drivers shouldn't change state/mode of clockevent devices when the requested mode isn't supported by driver and the clockevent device should continue to work as if nothing happened. But, few clockevent drivers are always disabling events from their ->set_dev_mode() callbacks and they stay disabled for 'default case' (we reach here for unsupported modes only) as well. For these drivers, clockevents core wouldn't be sure about state/mode of clockevent device once ->set_dev_mode() failed and we *may* see some strange behavior as the clockevent device isn't configured to the right mode by kernel again. This patch tries to make sure such drivers don't left events disabled for unsupported modes. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Santosh Shukla <santosh.shukla@linaro.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/common/timer-sp.c8
-rw-r--r--arch/arm/kernel/smp_twd.c7
-rw-r--r--arch/arm/mach-at91/at91rm9200_time.c1
-rw-r--r--arch/arm/mach-clps711x/common.c3
-rw-r--r--arch/arm/mach-cns3xxx/core.c8
-rw-r--r--arch/arm/mach-imx/epit.c9
-rw-r--r--arch/arm/mach-imx/time.c9
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c9
-rw-r--r--arch/arm/mach-ixp4xx/common.c7
-rw-r--r--arch/arm/mach-netx/time.c13
-rw-r--r--arch/arm/mach-omap1/timer32k.c5
-rw-r--r--arch/arm/mach-omap2/timer.c5
-rw-r--r--arch/arm/mach-spear/time.c10
-rw-r--r--arch/arm/mach-w90x900/time.c5
-rw-r--r--arch/arm/plat-iop/time.c7
-rw-r--r--arch/arm/plat-orion/time.c8
16 files changed, 57 insertions, 57 deletions
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
index 0dc511c1b16b..765543a51d93 100644
--- a/arch/arm/common/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -131,12 +131,10 @@ static int sp804_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE;
- int ret = 0;
-
- writel(ctrl, clkevt_base + TIMER_CTRL);
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
+ writel(ctrl, clkevt_base + TIMER_CTRL);
writel(clkevt_reload, clkevt_base + TIMER_LOAD);
ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
break;
@@ -155,11 +153,11 @@ static int sp804_set_mode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_RESUME:
break;
default:
- ret = -ENOSYS;
+ return -ENOSYS;
}
writel(ctrl, clkevt_base + TIMER_CTRL);
- return ret;
+ return 0;
}
static int sp804_set_next_event(unsigned long next,
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index fc6593c44746..9ecf1ed9dced 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -40,7 +40,6 @@ static int twd_set_mode(enum clock_event_mode mode,
struct clock_event_device *clk)
{
unsigned long ctrl;
- int ret = 0;
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
@@ -53,18 +52,18 @@ static int twd_set_mode(enum clock_event_mode mode,
/* period set, and timer enabled in 'next_event' hook */
ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
break;
- default:
- ret = -ENOSYS;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME:
case CLOCK_EVT_MODE_ONESHOT_STOPPED:
ctrl = 0;
break;
+ default:
+ return -ENOSYS;
}
writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL);
- return ret;
+ return 0;
}
static int twd_set_next_event(unsigned long evt,
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index 84b3bb352f75..875b2dee7891 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -142,6 +142,7 @@ clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
irqmask = 0;
break;
default:
+ /* irqmask retains value from last call */
ret = -ENOSYS;
}
at91_st_write(AT91_ST_IER, irqmask);
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index 8c4a9dbf95c1..0f40eada1b2d 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -267,8 +267,6 @@ static u64 notrace clps711x_sched_clock_read(void)
static int clps711x_clockevent_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- disable_irq(IRQ_TC2OI);
-
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
enable_irq(IRQ_TC2OI);
@@ -276,6 +274,7 @@ static int clps711x_clockevent_set_mode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_RESUME:
+ disable_irq(IRQ_TC2OI);
/* Left event sources disabled, no more interrupts appear */
break;
default:
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index d83098cce3ca..71e1e732e0f8 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -86,7 +86,7 @@ static int cns3xxx_timer_set_mode(enum clock_event_mode mode,
{
unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
int pclk = cns3xxx_cpu_clock() / 8;
- int reload, ret = 0;
+ int reload;
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
@@ -98,18 +98,18 @@ static int cns3xxx_timer_set_mode(enum clock_event_mode mode,
/* period set, and timer enabled in 'next_event' hook */
ctrl |= (1 << 2) | (1 << 9);
break;
- default:
- ret = -ENOSYS;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME:
case CLOCK_EVT_MODE_ONESHOT_STOPPED:
ctrl = 0;
break;
+ default:
+ return -ENOSYS;
}
writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
- return ret;
+ return 0;
}
static int cns3xxx_timer_set_next_event(unsigned long evt,
diff --git a/arch/arm/mach-imx/epit.c b/arch/arm/mach-imx/epit.c
index 239d6fc8b9e8..8f74753385f1 100644
--- a/arch/arm/mach-imx/epit.c
+++ b/arch/arm/mach-imx/epit.c
@@ -127,8 +127,6 @@ static int epit_set_mode(enum clock_event_mode mode,
epit_irq_acknowledge();
}
- /* Remember timer mode */
- clockevent_mode = mode;
local_irq_restore(flags);
switch (mode) {
@@ -150,8 +148,15 @@ static int epit_set_mode(enum clock_event_mode mode,
/* Left event sources disabled, no more interrupts appear */
break;
default:
+ /* Enable interrupts again */
+ local_irq_save(flags);
+ epit_irq_enable();
+ local_irq_restore(flags);
return -ENOSYS;
}
+
+ /* Remember timer mode */
+ clockevent_mode = mode;
return 0;
}
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index ba091981f204..4ac1b147d3fb 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -200,8 +200,6 @@ static int mxc_set_mode(enum clock_event_mode mode,
clock_event_mode_label[mode]);
#endif /* DEBUG */
- /* Remember timer mode */
- clockevent_mode = mode;
local_irq_restore(flags);
switch (mode) {
@@ -223,8 +221,15 @@ static int mxc_set_mode(enum clock_event_mode mode,
/* Left event sources disabled, no more interrupts appear */
break;
default:
+ /* Enable interrupts again */
+ local_irq_save(flags);
+ gpt_irq_enable();
+ local_irq_restore(flags);
return -ENOSYS;
}
+
+ /* Remember timer mode */
+ clockevent_mode = mode;
return 0;
}
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index cf99de805e3d..dccac71af23f 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -312,20 +312,17 @@ static int clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device
{
u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
- /* Disable timer */
- writel(ctrl, clkevt_base + TIMER_CTRL);
-
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
+ writel(ctrl, clkevt_base + TIMER_CTRL);
/* Enable the timer and start the periodic tick */
writel(timer_reload, clkevt_base + TIMER_LOAD);
ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
- writel(ctrl, clkevt_base + TIMER_CTRL);
break;
case CLOCK_EVT_MODE_ONESHOT:
+ writel(ctrl, clkevt_base + TIMER_CTRL);
/* Leave the timer disabled, .set_next_event will enable it */
ctrl &= ~TIMER_CTRL_PERIODIC;
- writel(ctrl, clkevt_base + TIMER_CTRL);
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
@@ -336,6 +333,8 @@ static int clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device
default:
return -ENOSYS;
}
+
+ writel(ctrl, clkevt_base + TIMER_CTRL);
return 0;
}
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index bfeb36af005c..e1b6f96a13e4 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -517,7 +517,6 @@ static int ixp4xx_set_mode(enum clock_event_mode mode,
{
unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
- int ret = 0;
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
@@ -536,15 +535,15 @@ static int ixp4xx_set_mode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_RESUME:
opts |= IXP4XX_OST_ENABLE;
break;
- default:
- ret = -ENOSYS;
case CLOCK_EVT_MODE_UNUSED:
osrt = opts = 0;
break;
+ default:
+ return -ENOSYS;
}
*IXP4XX_OSRT1 = osrt | opts;
- return ret;
+ return 0;
}
static struct clock_event_device clockevent_ixp4xx = {
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
index 311f4beed6a2..8baa83deb206 100644
--- a/arch/arm/mach-netx/time.c
+++ b/arch/arm/mach-netx/time.c
@@ -35,13 +35,10 @@ static int netx_set_mode(enum clock_event_mode mode,
struct clock_event_device *clk)
{
u32 tmode;
- int ret = 0;
-
- /* disable timer */
- writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
+ writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
writel(LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
tmode = NETX_GPIO_COUNTER_CTRL_RST_EN |
NETX_GPIO_COUNTER_CTRL_IRQ_EN |
@@ -49,24 +46,24 @@ static int netx_set_mode(enum clock_event_mode mode,
break;
case CLOCK_EVT_MODE_ONESHOT:
+ writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
writel(0, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
tmode = NETX_GPIO_COUNTER_CTRL_IRQ_EN |
NETX_GPIO_COUNTER_CTRL_RUN;
break;
- default:
- ret = -ENOSYS;
- /* fall through */
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_RESUME:
case CLOCK_EVT_MODE_ONESHOT_STOPPED:
tmode = 0;
break;
+ default:
+ return -ENOSYS;
}
writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
- return ret;
+ return 0;
}
static int netx_set_next_event(unsigned long evt,
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index df0b45d6d5a1..1cc57bb3ea2a 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -122,18 +122,17 @@ static int omap_32k_timer_set_next_event(unsigned long delta,
static int omap_32k_timer_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- omap_32k_timer_stop();
-
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
+ omap_32k_timer_stop();
omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
break;
case CLOCK_EVT_MODE_ONESHOT:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_ONESHOT_STOPPED:
- break;
case CLOCK_EVT_MODE_RESUME:
+ omap_32k_timer_stop();
break;
default:
return -ENOSYS;
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 1282a886abd2..c4f71e9c3960 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -106,10 +106,9 @@ static int omap2_gp_timer_set_mode(enum clock_event_mode mode,
{
u32 period;
- __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
-
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
+ __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
period = clkev.rate / HZ;
period -= 1;
/* Looks like we need to first set the load value separately */
@@ -120,11 +119,11 @@ static int omap2_gp_timer_set_mode(enum clock_event_mode mode,
0xffffffff - period, OMAP_TIMER_POSTED);
break;
case CLOCK_EVT_MODE_ONESHOT:
- break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_ONESHOT_STOPPED:
case CLOCK_EVT_MODE_RESUME:
+ __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
break;
default:
return -ENOSYS;
diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c
index b65fe2235044..d26d303e5c8a 100644
--- a/arch/arm/mach-spear/time.c
+++ b/arch/arm/mach-spear/time.c
@@ -112,10 +112,11 @@ static int clockevent_set_mode(enum clock_event_mode mode,
/* stop the timer */
val = readw(gpt_base + CR(CLKEVT));
val &= ~CTRL_ENABLE;
- writew(val, gpt_base + CR(CLKEVT));
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
+ writew(val, gpt_base + CR(CLKEVT));
+
period = clk_get_rate(gpt_clk) / HZ;
period >>= CTRL_PRESCALER16;
writew(period, gpt_base + LOAD(CLKEVT));
@@ -123,24 +124,25 @@ static int clockevent_set_mode(enum clock_event_mode mode,
val = readw(gpt_base + CR(CLKEVT));
val &= ~CTRL_ONE_SHOT;
val |= CTRL_ENABLE | CTRL_INT_ENABLE;
- writew(val, gpt_base + CR(CLKEVT));
break;
case CLOCK_EVT_MODE_ONESHOT:
+ writew(val, gpt_base + CR(CLKEVT));
+
val = readw(gpt_base + CR(CLKEVT));
val |= CTRL_ONE_SHOT;
- writew(val, gpt_base + CR(CLKEVT));
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_ONESHOT_STOPPED:
case CLOCK_EVT_MODE_RESUME:
-
break;
default:
return -ENOSYS;
}
+
+ writew(val, gpt_base + CR(CLKEVT));
return 0;
}
diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c
index a097b71c2dc8..560e299e6ada 100644
--- a/arch/arm/mach-w90x900/time.c
+++ b/arch/arm/mach-w90x900/time.c
@@ -52,7 +52,6 @@ static int nuc900_clockevent_setmode(enum clock_event_mode mode,
struct clock_event_device *clk)
{
unsigned int val;
- int ret = 0;
val = __raw_readl(REG_TCSR0);
val &= ~(0x03 << 27);
@@ -76,11 +75,11 @@ static int nuc900_clockevent_setmode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_RESUME:
break;
default:
- ret = -ENOSYS;
+ return -ENOSYS;
}
__raw_writel(val, REG_TCSR0);
- return ret;
+ return 0;
}
static int nuc900_clockevent_setnextevent(unsigned long evt,
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c
index 96596458e28e..c9882ad11201 100644
--- a/arch/arm/plat-iop/time.c
+++ b/arch/arm/plat-iop/time.c
@@ -81,7 +81,6 @@ static int iop_set_mode(enum clock_event_mode mode,
struct clock_event_device *unused)
{
u32 tmr = read_tmr0();
- int ret = 0;
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
@@ -97,17 +96,17 @@ static int iop_set_mode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_RESUME:
tmr |= IOP_TMR_EN;
break;
- default:
- ret = -ENOSYS;
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_ONESHOT_STOPPED:
tmr &= ~IOP_TMR_EN;
break;
+ default:
+ return -ENOSYS;
}
write_tmr0(tmr);
- return ret;
+ return 0;
}
static struct clock_event_device iop_clockevent = {
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
index cda982aa4f42..32417f3408b5 100644
--- a/arch/arm/plat-orion/time.c
+++ b/arch/arm/plat-orion/time.c
@@ -110,7 +110,6 @@ static int
orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
{
unsigned long flags;
- int ret = 0;
u32 u;
local_irq_save(flags);
@@ -136,8 +135,6 @@ orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
timer_base + TIMER_CTRL_OFF);
break;
- default:
- ret = -ENOSYS;
case CLOCK_EVT_MODE_ONESHOT:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
@@ -160,9 +157,12 @@ orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
*/
writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
break;
+ default:
+ local_irq_restore(flags);
+ return -ENOSYS;
}
local_irq_restore(flags);
- return ret;
+ return 0;
}
static struct clock_event_device orion_clkevt = {