aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2012-11-21 09:46:19 -0800
committerTony Lindgren <tony@atomide.com>2012-11-21 09:46:19 -0800
commit48b0023607c4e524e893a7a378a1dd42234c41a7 (patch)
treedec8ce3b8dab55ecbc65f71f716236fdab95acd3 /arch/arm/plat-omap
parentMerge branch 'fixes-timer' of github.com:jonhunter/linux into omap-for-v3.8/timer (diff)
parentARM: OMAP2+: Fix compiler warning for 32k timer (diff)
downloadlinux-dev-48b0023607c4e524e893a7a378a1dd42234c41a7.tar.xz
linux-dev-48b0023607c4e524e893a7a378a1dd42234c41a7.zip
Merge branch 'cleanup-timer' of git://github.com/jonhunter/linux into omap-for-v3.8/timer
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/dmtimer.c54
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h80
2 files changed, 56 insertions, 78 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 9deeb3064d33..89585c293554 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -43,6 +43,8 @@
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/dmtimer-omap.h>
#include <plat/dmtimer.h>
@@ -99,32 +101,39 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
timer->context.tclr);
}
-static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
+static int omap_dm_timer_reset(struct omap_dm_timer *timer)
{
- int c;
+ u32 l, timeout = 100000;
- if (!timer->sys_stat)
- return;
+ if (timer->revision != 1)
+ return -EINVAL;
- c = 0;
- while (!(__raw_readl(timer->sys_stat) & 1)) {
- c++;
- if (c > 100000) {
- printk(KERN_ERR "Timer failed to reset\n");
- return;
- }
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
+
+ do {
+ l = __omap_dm_timer_read(timer,
+ OMAP_TIMER_V1_SYS_STAT_OFFSET, 0);
+ } while (!l && timeout--);
+
+ if (!timeout) {
+ dev_err(&timer->pdev->dev, "Timer failed to reset\n");
+ return -ETIMEDOUT;
}
-}
-static void omap_dm_timer_reset(struct omap_dm_timer *timer)
-{
- omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
- omap_dm_timer_wait_for_reset(timer);
- __omap_dm_timer_reset(timer, 0, 0);
+ /* Configure timer for smart-idle mode */
+ l = __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
+ l |= 0x2 << 0x3;
+ __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l, 0);
+
+ timer->posted = 0;
+
+ return 0;
}
-int omap_dm_timer_prepare(struct omap_dm_timer *timer)
+static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
{
+ int rc;
+
/*
* FIXME: OMAP1 devices do not use the clock framework for dmtimers so
* do not call clk_get() for these devices.
@@ -140,8 +149,13 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer)
omap_dm_timer_enable(timer);
- if (timer->capability & OMAP_TIMER_NEEDS_RESET)
- omap_dm_timer_reset(timer);
+ if (timer->capability & OMAP_TIMER_NEEDS_RESET) {
+ rc = omap_dm_timer_reset(timer);
+ if (rc) {
+ omap_dm_timer_disable(timer);
+ return rc;
+ }
+ }
__omap_dm_timer_enable_posted(timer);
omap_dm_timer_disable(timer);
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 05a36e16f3f4..a3fbc48c332e 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -79,8 +79,6 @@ struct omap_timer_capability_dev_attr {
u32 timer_capability;
};
-struct omap_dm_timer;
-
struct timer_regs {
u32 tidr;
u32 tier;
@@ -101,12 +99,29 @@ struct timer_regs {
u32 towr;
};
-struct dmtimer_platform_data {
- /* set_timer_src - Only used for OMAP1 devices */
- int (*set_timer_src)(struct platform_device *pdev, int source);
- u32 timer_errata;
- u32 timer_capability;
+struct omap_dm_timer {
+ int id;
+ int irq;
+ struct clk *fclk;
+
+ void __iomem *io_base;
+ void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
+ void __iomem *irq_ena; /* irq enable */
+ void __iomem *irq_dis; /* irq disable, only on v2 ip */
+ void __iomem *pend; /* write pending */
+ void __iomem *func_base; /* function register base */
+
+ unsigned long rate;
+ unsigned reserved:1;
+ unsigned posted:1;
+ struct timer_regs context;
int (*get_context_loss_count)(struct device *);
+ int ctx_loss_count;
+ int revision;
+ u32 capability;
+ u32 errata;
+ struct platform_device *pdev;
+ struct list_head node;
};
int omap_dm_timer_reserve_systimer(int id);
@@ -260,35 +275,6 @@ int omap_dm_timers_active(void);
#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
-struct omap_dm_timer {
- unsigned long phys_base;
- int id;
- int irq;
- struct clk *fclk;
-
- void __iomem *io_base;
- void __iomem *sys_stat; /* TISTAT timer status */
- void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
- void __iomem *irq_ena; /* irq enable */
- void __iomem *irq_dis; /* irq disable, only on v2 ip */
- void __iomem *pend; /* write pending */
- void __iomem *func_base; /* function register base */
-
- unsigned long rate;
- unsigned reserved:1;
- unsigned posted:1;
- struct timer_regs context;
- int (*get_context_loss_count)(struct device *);
- int ctx_loss_count;
- int revision;
- u32 capability;
- u32 errata;
- struct platform_device *pdev;
- struct list_head node;
-};
-
-int omap_dm_timer_prepare(struct omap_dm_timer *timer);
-
static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
int posted)
{
@@ -317,8 +303,6 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
tidr = __raw_readl(timer->io_base);
if (!(tidr >> 16)) {
timer->revision = 1;
- timer->sys_stat = timer->io_base +
- OMAP_TIMER_V1_SYS_STAT_OFFSET;
timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
timer->irq_dis = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
@@ -326,7 +310,6 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
timer->func_base = timer->io_base;
} else {
timer->revision = 2;
- timer->sys_stat = NULL;
timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
@@ -337,25 +320,6 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
}
}
-/* Assumes the source clock has been set by caller */
-static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
- int autoidle, int wakeup)
-{
- u32 l;
-
- l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
- l |= 0x02 << 3; /* Set to smart-idle mode */
- l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
-
- if (autoidle)
- l |= 0x1 << 0;
-
- if (wakeup)
- l |= 1 << 2;
-
- __raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
-}
-
/*
* __omap_dm_timer_enable_posted - enables write posted mode
* @timer: pointer to timer instance handle