aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2012-11-21 12:46:19 -0500
committerTony Lindgren <tony@atomide.com>2012-11-21 12:46:19 -0500
commit48b0023607c4e524e893a7a378a1dd42234c41a7 (patch)
treedec8ce3b8dab55ecbc65f71f716236fdab95acd3 /arch/arm/plat-omap
parent9dc57643738f9fbe45c10cc062903d5dfda5bdd9 (diff)
parent258e84af9799b8c81cf856dcbd8e2d4cc082741d (diff)
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 @@
43#include <linux/pm_runtime.h> 43#include <linux/pm_runtime.h>
44#include <linux/of.h> 44#include <linux/of.h>
45#include <linux/of_device.h> 45#include <linux/of_device.h>
46#include <linux/platform_device.h>
47#include <linux/platform_data/dmtimer-omap.h>
46 48
47#include <plat/dmtimer.h> 49#include <plat/dmtimer.h>
48 50
@@ -99,32 +101,39 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
99 timer->context.tclr); 101 timer->context.tclr);
100} 102}
101 103
102static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) 104static int omap_dm_timer_reset(struct omap_dm_timer *timer)
103{ 105{
104 int c; 106 u32 l, timeout = 100000;
105 107
106 if (!timer->sys_stat) 108 if (timer->revision != 1)
107 return; 109 return -EINVAL;
108 110
109 c = 0; 111 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
110 while (!(__raw_readl(timer->sys_stat) & 1)) { 112
111 c++; 113 do {
112 if (c > 100000) { 114 l = __omap_dm_timer_read(timer,
113 printk(KERN_ERR "Timer failed to reset\n"); 115 OMAP_TIMER_V1_SYS_STAT_OFFSET, 0);
114 return; 116 } while (!l && timeout--);
115 } 117
118 if (!timeout) {
119 dev_err(&timer->pdev->dev, "Timer failed to reset\n");
120 return -ETIMEDOUT;
116 } 121 }
117}
118 122
119static void omap_dm_timer_reset(struct omap_dm_timer *timer) 123 /* Configure timer for smart-idle mode */
120{ 124 l = __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
121 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); 125 l |= 0x2 << 0x3;
122 omap_dm_timer_wait_for_reset(timer); 126 __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l, 0);
123 __omap_dm_timer_reset(timer, 0, 0); 127
128 timer->posted = 0;
129
130 return 0;
124} 131}
125 132
126int omap_dm_timer_prepare(struct omap_dm_timer *timer) 133static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
127{ 134{
135 int rc;
136
128 /* 137 /*
129 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so 138 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
130 * do not call clk_get() for these devices. 139 * do not call clk_get() for these devices.
@@ -140,8 +149,13 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer)
140 149
141 omap_dm_timer_enable(timer); 150 omap_dm_timer_enable(timer);
142 151
143 if (timer->capability & OMAP_TIMER_NEEDS_RESET) 152 if (timer->capability & OMAP_TIMER_NEEDS_RESET) {
144 omap_dm_timer_reset(timer); 153 rc = omap_dm_timer_reset(timer);
154 if (rc) {
155 omap_dm_timer_disable(timer);
156 return rc;
157 }
158 }
145 159
146 __omap_dm_timer_enable_posted(timer); 160 __omap_dm_timer_enable_posted(timer);
147 omap_dm_timer_disable(timer); 161 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 {
79 u32 timer_capability; 79 u32 timer_capability;
80}; 80};
81 81
82struct omap_dm_timer;
83
84struct timer_regs { 82struct timer_regs {
85 u32 tidr; 83 u32 tidr;
86 u32 tier; 84 u32 tier;
@@ -101,12 +99,29 @@ struct timer_regs {
101 u32 towr; 99 u32 towr;
102}; 100};
103 101
104struct dmtimer_platform_data { 102struct omap_dm_timer {
105 /* set_timer_src - Only used for OMAP1 devices */ 103 int id;
106 int (*set_timer_src)(struct platform_device *pdev, int source); 104 int irq;
107 u32 timer_errata; 105 struct clk *fclk;
108 u32 timer_capability; 106
107 void __iomem *io_base;
108 void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
109 void __iomem *irq_ena; /* irq enable */
110 void __iomem *irq_dis; /* irq disable, only on v2 ip */
111 void __iomem *pend; /* write pending */
112 void __iomem *func_base; /* function register base */
113
114 unsigned long rate;
115 unsigned reserved:1;
116 unsigned posted:1;
117 struct timer_regs context;
109 int (*get_context_loss_count)(struct device *); 118 int (*get_context_loss_count)(struct device *);
119 int ctx_loss_count;
120 int revision;
121 u32 capability;
122 u32 errata;
123 struct platform_device *pdev;
124 struct list_head node;
110}; 125};
111 126
112int omap_dm_timer_reserve_systimer(int id); 127int omap_dm_timer_reserve_systimer(int id);
@@ -260,35 +275,6 @@ int omap_dm_timers_active(void);
260#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \ 275#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
261 (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT)) 276 (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
262 277
263struct omap_dm_timer {
264 unsigned long phys_base;
265 int id;
266 int irq;
267 struct clk *fclk;
268
269 void __iomem *io_base;
270 void __iomem *sys_stat; /* TISTAT timer status */
271 void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
272 void __iomem *irq_ena; /* irq enable */
273 void __iomem *irq_dis; /* irq disable, only on v2 ip */
274 void __iomem *pend; /* write pending */
275 void __iomem *func_base; /* function register base */
276
277 unsigned long rate;
278 unsigned reserved:1;
279 unsigned posted:1;
280 struct timer_regs context;
281 int (*get_context_loss_count)(struct device *);
282 int ctx_loss_count;
283 int revision;
284 u32 capability;
285 u32 errata;
286 struct platform_device *pdev;
287 struct list_head node;
288};
289
290int omap_dm_timer_prepare(struct omap_dm_timer *timer);
291
292static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg, 278static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
293 int posted) 279 int posted)
294{ 280{
@@ -317,8 +303,6 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
317 tidr = __raw_readl(timer->io_base); 303 tidr = __raw_readl(timer->io_base);
318 if (!(tidr >> 16)) { 304 if (!(tidr >> 16)) {
319 timer->revision = 1; 305 timer->revision = 1;
320 timer->sys_stat = timer->io_base +
321 OMAP_TIMER_V1_SYS_STAT_OFFSET;
322 timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET; 306 timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
323 timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET; 307 timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
324 timer->irq_dis = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET; 308 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)
326 timer->func_base = timer->io_base; 310 timer->func_base = timer->io_base;
327 } else { 311 } else {
328 timer->revision = 2; 312 timer->revision = 2;
329 timer->sys_stat = NULL;
330 timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS; 313 timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
331 timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET; 314 timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
332 timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR; 315 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)
337 } 320 }
338} 321}
339 322
340/* Assumes the source clock has been set by caller */
341static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
342 int autoidle, int wakeup)
343{
344 u32 l;
345
346 l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
347 l |= 0x02 << 3; /* Set to smart-idle mode */
348 l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
349
350 if (autoidle)
351 l |= 0x1 << 0;
352
353 if (wakeup)
354 l |= 1 << 2;
355
356 __raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
357}
358
359/* 323/*
360 * __omap_dm_timer_enable_posted - enables write posted mode 324 * __omap_dm_timer_enable_posted - enables write posted mode
361 * @timer: pointer to timer instance handle 325 * @timer: pointer to timer instance handle