aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/include
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2012-11-30 01:30:11 -0500
committerOlof Johansson <olof@lixom.net>2012-11-30 01:30:11 -0500
commitc8a1ceccf394b2f99feed2b702732140e9f0f92d (patch)
tree6632d05aae22e99d7f128104b536bfdfc225a696 /arch/arm/plat-omap/include
parent4c929c8a8837f4e5acdec5883a1b64a240751e2f (diff)
parent26f01998b0657a61167a819f1c37cb9f9e9d674b (diff)
Merge tag 'omap-for-v3.8/cleanup-timer-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/cleanup
Timer clean-up to get us closer to moving timer code to drivers, and to get rid of CONFIG_OMAP_32K_TIMER and rely on the board or devicetree provided timer configuration. Note that these changes are on top of the recent timer fixes. By Jon Hunter (32) and others via Tony Lindgren * tag 'omap-for-v3.8/cleanup-timer-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (71 commits) ARM: OMAP3: cm-t3517: use GPTIMER for system clock ARM: OMAP2+: timer: remove CONFIG_OMAP_32K_TIMER ARM: OMAP2+: Fix compiler warning for 32k timer ARM: OMAP: Remove unnecessary inclusion of dmtimer.h ARM: OMAP: Add platform data header for DMTIMERs ARM: OMAP: Remove unnecessary omap_dm_timer structure declaration ARM: OMAP2+: Remove unnecessary local variable in timer code ARM: OMAP: Don't store timers physical address ARM: OMAP: Define omap_dm_timer_prepare function as static ARM: OMAP: Clean-up dmtimer reset code ARM: OMAP: Remove __omap_dm_timer_set_source function ARM: OMAP: Remove unnecessary call to clk_get() ARM: OMAP: Add dmtimer interrupt disable function ARM: OMAP: Fix spurious interrupts when using timer match feature ARM: OMAP: Don't restore DMTIMER interrupt status register ARM: OMAP: Don't restore of DMTIMER TISTAT register ARM: OMAP: Fix dmtimer reset for timer1 ARM: OMAP2+: Don't use __omap_dm_timer_reset() ARM: OMAP2/3: Define HWMOD software reset status for DMTIMERs ARM: OMAP3: Correct HWMOD DMTIMER SYSC register declarations ... Change/change conflict in arch/arm/mach-omap2/board-cm-t3517.c. Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/plat-omap/include')
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h143
1 files changed, 70 insertions, 73 deletions
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 3f5b9cfd9c0b..a3fbc48c332e 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -32,7 +32,6 @@
32 * 675 Mass Ave, Cambridge, MA 02139, USA. 32 * 675 Mass Ave, Cambridge, MA 02139, USA.
33 */ 33 */
34 34
35#include <linux/clk.h>
36#include <linux/delay.h> 35#include <linux/delay.h>
37#include <linux/io.h> 36#include <linux/io.h>
38#include <linux/platform_device.h> 37#include <linux/platform_device.h>
@@ -55,6 +54,10 @@
55#define OMAP_TIMER_TRIGGER_OVERFLOW 0x01 54#define OMAP_TIMER_TRIGGER_OVERFLOW 0x01
56#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02 55#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02
57 56
57/* posted mode types */
58#define OMAP_TIMER_NONPOSTED 0x00
59#define OMAP_TIMER_POSTED 0x01
60
58/* timer capabilities used in hwmod database */ 61/* timer capabilities used in hwmod database */
59#define OMAP_TIMER_SECURE 0x80000000 62#define OMAP_TIMER_SECURE 0x80000000
60#define OMAP_TIMER_ALWON 0x40000000 63#define OMAP_TIMER_ALWON 0x40000000
@@ -62,16 +65,22 @@
62#define OMAP_TIMER_NEEDS_RESET 0x10000000 65#define OMAP_TIMER_NEEDS_RESET 0x10000000
63#define OMAP_TIMER_HAS_DSP_IRQ 0x08000000 66#define OMAP_TIMER_HAS_DSP_IRQ 0x08000000
64 67
68/*
69 * timer errata flags
70 *
71 * Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This
72 * errata prevents us from using posted mode on these devices, unless the
73 * timer counter register is never read. For more details please refer to
74 * the OMAP3/4/5 errata documents.
75 */
76#define OMAP_TIMER_ERRATA_I103_I767 0x80000000
77
65struct omap_timer_capability_dev_attr { 78struct omap_timer_capability_dev_attr {
66 u32 timer_capability; 79 u32 timer_capability;
67}; 80};
68 81
69struct omap_dm_timer;
70
71struct timer_regs { 82struct timer_regs {
72 u32 tidr; 83 u32 tidr;
73 u32 tistat;
74 u32 tisr;
75 u32 tier; 84 u32 tier;
76 u32 twer; 85 u32 twer;
77 u32 tclr; 86 u32 tclr;
@@ -90,16 +99,35 @@ struct timer_regs {
90 u32 towr; 99 u32 towr;
91}; 100};
92 101
93struct dmtimer_platform_data { 102struct omap_dm_timer {
94 /* set_timer_src - Only used for OMAP1 devices */ 103 int id;
95 int (*set_timer_src)(struct platform_device *pdev, int source); 104 int irq;
96 u32 timer_capability; 105 struct clk *fclk;
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;
97 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;
98}; 125};
99 126
100int omap_dm_timer_reserve_systimer(int id); 127int omap_dm_timer_reserve_systimer(int id);
101struct omap_dm_timer *omap_dm_timer_request(void); 128struct omap_dm_timer *omap_dm_timer_request(void);
102struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); 129struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
130struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap);
103int omap_dm_timer_free(struct omap_dm_timer *timer); 131int omap_dm_timer_free(struct omap_dm_timer *timer);
104void omap_dm_timer_enable(struct omap_dm_timer *timer); 132void omap_dm_timer_enable(struct omap_dm_timer *timer);
105void omap_dm_timer_disable(struct omap_dm_timer *timer); 133void omap_dm_timer_disable(struct omap_dm_timer *timer);
@@ -121,6 +149,7 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, i
121int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler); 149int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
122 150
123int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value); 151int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
152int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask);
124 153
125unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); 154unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
126int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); 155int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
@@ -246,34 +275,6 @@ int omap_dm_timers_active(void);
246#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \ 275#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
247 (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT)) 276 (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
248 277
249struct omap_dm_timer {
250 unsigned long phys_base;
251 int id;
252 int irq;
253 struct clk *fclk;
254
255 void __iomem *io_base;
256 void __iomem *sys_stat; /* TISTAT timer status */
257 void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
258 void __iomem *irq_ena; /* irq enable */
259 void __iomem *irq_dis; /* irq disable, only on v2 ip */
260 void __iomem *pend; /* write pending */
261 void __iomem *func_base; /* function register base */
262
263 unsigned long rate;
264 unsigned reserved:1;
265 unsigned posted:1;
266 struct timer_regs context;
267 int (*get_context_loss_count)(struct device *);
268 int ctx_loss_count;
269 int revision;
270 u32 capability;
271 struct platform_device *pdev;
272 struct list_head node;
273};
274
275int omap_dm_timer_prepare(struct omap_dm_timer *timer);
276
277static 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,
278 int posted) 279 int posted)
279{ 280{
@@ -302,16 +303,13 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
302 tidr = __raw_readl(timer->io_base); 303 tidr = __raw_readl(timer->io_base);
303 if (!(tidr >> 16)) { 304 if (!(tidr >> 16)) {
304 timer->revision = 1; 305 timer->revision = 1;
305 timer->sys_stat = timer->io_base +
306 OMAP_TIMER_V1_SYS_STAT_OFFSET;
307 timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET; 306 timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
308 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;
309 timer->irq_dis = NULL; 308 timer->irq_dis = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
310 timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET; 309 timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
311 timer->func_base = timer->io_base; 310 timer->func_base = timer->io_base;
312 } else { 311 } else {
313 timer->revision = 2; 312 timer->revision = 2;
314 timer->sys_stat = NULL;
315 timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS; 313 timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
316 timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET; 314 timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
317 timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR; 315 timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
@@ -322,45 +320,44 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
322 } 320 }
323} 321}
324 322
325/* Assumes the source clock has been set by caller */ 323/*
326static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer, 324 * __omap_dm_timer_enable_posted - enables write posted mode
327 int autoidle, int wakeup) 325 * @timer: pointer to timer instance handle
326 *
327 * Enables the write posted mode for the timer. When posted mode is enabled
328 * writes to certain timer registers are immediately acknowledged by the
329 * internal bus and hence prevents stalling the CPU waiting for the write to
330 * complete. Enabling this feature can improve performance for writing to the
331 * timer registers.
332 */
333static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
328{ 334{
329 u32 l; 335 if (timer->posted)
336 return;
330 337
331 l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET); 338 if (timer->errata & OMAP_TIMER_ERRATA_I103_I767)
332 l |= 0x02 << 3; /* Set to smart-idle mode */ 339 return;
333 l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
334 340
335 if (autoidle)
336 l |= 0x1 << 0;
337
338 if (wakeup)
339 l |= 1 << 2;
340
341 __raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
342
343 /* Match hardware reset default of posted mode */
344 __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, 341 __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
345 OMAP_TIMER_CTRL_POSTED, 0); 342 OMAP_TIMER_CTRL_POSTED, 0);
343 timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;
344 timer->posted = OMAP_TIMER_POSTED;
346} 345}
347 346
348static inline int __omap_dm_timer_set_source(struct clk *timer_fck, 347/**
349 struct clk *parent) 348 * __omap_dm_timer_override_errata - override errata flags for a timer
349 * @timer: pointer to timer handle
350 * @errata: errata flags to be ignored
351 *
352 * For a given timer, override a timer errata by clearing the flags
353 * specified by the errata argument. A specific erratum should only be
354 * overridden for a timer if the timer is used in such a way the erratum
355 * has no impact.
356 */
357static inline void __omap_dm_timer_override_errata(struct omap_dm_timer *timer,
358 u32 errata)
350{ 359{
351 int ret; 360 timer->errata &= ~errata;
352
353 clk_disable(timer_fck);
354 ret = clk_set_parent(timer_fck, parent);
355 clk_enable(timer_fck);
356
357 /*
358 * When the functional clock disappears, too quick writes seem
359 * to cause an abort. XXX Is this still necessary?
360 */
361 __delay(300000);
362
363 return ret;
364} 361}
365 362
366static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer, 363static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,