From e74984e46e899c22137a385869fb4f3ae756e3df Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 29 Mar 2011 15:54:48 -0700 Subject: omap: Set separate timer init functions to avoid cpu_is_omap tests This is needed for the following patches so we can initialize the rest of the hardware timers later on. As with the init_irq calls, there's no need to do cpu_is_omap calls during the timer init as we only care about the major omap generation. This means that we can initialize the sys_timer with the .timer entries alone. Note that for now we just set stubs for the various sys_timer entries that will get populated in a later patch. The following patches will also remove the omap_dm_timer_init calls and change the init for the rest of the hardware timers to happen with an arch_initcall. Signed-off-by: Tony Lindgren Reviewed-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/dmtimer.h | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/arm/plat-omap/include/plat/dmtimer.h') diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index d6c70d2f4030..330bd17bb5e7 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -57,7 +57,6 @@ #define OMAP_TIMER_IP_VERSION_1 0x1 struct omap_dm_timer; extern struct omap_dm_timer *gptimer_wakeup; -extern struct sys_timer omap_timer; struct clk; int omap_dm_timer_init(void); -- cgit v1.2.1 From ec97489d199b3dcfc44042ccf89b37a264d14565 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 29 Mar 2011 15:54:48 -0700 Subject: omap: Move dmtimer defines to dmtimer.h These will be needed when dmtimer platform init code gets split for omap1 and omap2+. These will also be needed for separate sys_timer init and driver init for the rest of the hardware timers in the following patches. No functional changes. Signed-off-by: Tony Lindgren Reviewed-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/dmtimer.h | 125 ++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) (limited to 'arch/arm/plat-omap/include/plat/dmtimer.h') diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 330bd17bb5e7..32031056165d 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -92,5 +92,130 @@ void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value int omap_dm_timers_active(void); +/* + * Do not use the defines below, they are not needed. They should be only + * used by dmtimer.c and sys_timer related code. + */ + +/* register offsets */ +#define _OMAP_TIMER_ID_OFFSET 0x00 +#define _OMAP_TIMER_OCP_CFG_OFFSET 0x10 +#define _OMAP_TIMER_SYS_STAT_OFFSET 0x14 +#define _OMAP_TIMER_STAT_OFFSET 0x18 +#define _OMAP_TIMER_INT_EN_OFFSET 0x1c +#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20 +#define _OMAP_TIMER_CTRL_OFFSET 0x24 +#define OMAP_TIMER_CTRL_GPOCFG (1 << 14) +#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13) +#define OMAP_TIMER_CTRL_PT (1 << 12) +#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8) +#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8) +#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8) +#define OMAP_TIMER_CTRL_SCPWM (1 << 7) +#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */ +#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */ +#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* prescaler value shift */ +#define OMAP_TIMER_CTRL_POSTED (1 << 2) +#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */ +#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */ +#define _OMAP_TIMER_COUNTER_OFFSET 0x28 +#define _OMAP_TIMER_LOAD_OFFSET 0x2c +#define _OMAP_TIMER_TRIGGER_OFFSET 0x30 +#define _OMAP_TIMER_WRITE_PEND_OFFSET 0x34 +#define WP_NONE 0 /* no write pending bit */ +#define WP_TCLR (1 << 0) +#define WP_TCRR (1 << 1) +#define WP_TLDR (1 << 2) +#define WP_TTGR (1 << 3) +#define WP_TMAR (1 << 4) +#define WP_TPIR (1 << 5) +#define WP_TNIR (1 << 6) +#define WP_TCVR (1 << 7) +#define WP_TOCR (1 << 8) +#define WP_TOWR (1 << 9) +#define _OMAP_TIMER_MATCH_OFFSET 0x38 +#define _OMAP_TIMER_CAPTURE_OFFSET 0x3c +#define _OMAP_TIMER_IF_CTRL_OFFSET 0x40 +#define _OMAP_TIMER_CAPTURE2_OFFSET 0x44 /* TCAR2, 34xx only */ +#define _OMAP_TIMER_TICK_POS_OFFSET 0x48 /* TPIR, 34xx only */ +#define _OMAP_TIMER_TICK_NEG_OFFSET 0x4c /* TNIR, 34xx only */ +#define _OMAP_TIMER_TICK_COUNT_OFFSET 0x50 /* TCVR, 34xx only */ +#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET 0x54 /* TOCR, 34xx only */ +#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET 0x58 /* TOWR, 34xx only */ + +/* register offsets with the write pending bit encoded */ +#define WPSHIFT 16 + +#define OMAP_TIMER_ID_REG (_OMAP_TIMER_ID_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_OCP_CFG_REG (_OMAP_TIMER_OCP_CFG_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_SYS_STAT_REG (_OMAP_TIMER_SYS_STAT_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_STAT_REG (_OMAP_TIMER_STAT_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_INT_EN_REG (_OMAP_TIMER_INT_EN_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_CTRL_REG (_OMAP_TIMER_CTRL_OFFSET \ + | (WP_TCLR << WPSHIFT)) + +#define OMAP_TIMER_COUNTER_REG (_OMAP_TIMER_COUNTER_OFFSET \ + | (WP_TCRR << WPSHIFT)) + +#define OMAP_TIMER_LOAD_REG (_OMAP_TIMER_LOAD_OFFSET \ + | (WP_TLDR << WPSHIFT)) + +#define OMAP_TIMER_TRIGGER_REG (_OMAP_TIMER_TRIGGER_OFFSET \ + | (WP_TTGR << WPSHIFT)) + +#define OMAP_TIMER_WRITE_PEND_REG (_OMAP_TIMER_WRITE_PEND_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_MATCH_REG (_OMAP_TIMER_MATCH_OFFSET \ + | (WP_TMAR << WPSHIFT)) + +#define OMAP_TIMER_CAPTURE_REG (_OMAP_TIMER_CAPTURE_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_IF_CTRL_REG (_OMAP_TIMER_IF_CTRL_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_CAPTURE2_REG (_OMAP_TIMER_CAPTURE2_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_TICK_POS_REG (_OMAP_TIMER_TICK_POS_OFFSET \ + | (WP_TPIR << WPSHIFT)) + +#define OMAP_TIMER_TICK_NEG_REG (_OMAP_TIMER_TICK_NEG_OFFSET \ + | (WP_TNIR << WPSHIFT)) + +#define OMAP_TIMER_TICK_COUNT_REG (_OMAP_TIMER_TICK_COUNT_OFFSET \ + | (WP_TCVR << WPSHIFT)) + +#define OMAP_TIMER_TICK_INT_MASK_SET_REG \ + (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT)) + +#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 irq; +#ifdef CONFIG_ARCH_OMAP2PLUS + struct clk *iclk, *fclk; +#endif + void __iomem *io_base; + unsigned reserved:1; + unsigned enabled:1; + unsigned posted:1; +}; #endif /* __ASM_ARCH_DMTIMER_H */ -- cgit v1.2.1 From caf64f2fdc48472995d40656eb1a75524c464447 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 29 Mar 2011 15:54:48 -0700 Subject: omap: Make a subset of dmtimer functions into inline functions This will allow us to share the code between system timer and dmtimer device driver code without having to initialize all the dmtimers early. This change will also make the timer_set_next_event more efficient as the inline functions will optimize the code better for the timer reprogramming. Signed-off-by: Tony Lindgren Reviewed-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/dmtimer.h | 119 ++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) (limited to 'arch/arm/plat-omap/include/plat/dmtimer.h') diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 32031056165d..54664a7498af 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -32,6 +32,9 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include + #ifndef __ASM_ARCH_DMTIMER_H #define __ASM_ARCH_DMTIMER_H @@ -218,4 +221,120 @@ struct omap_dm_timer { unsigned posted:1; }; +void omap_dm_timer_prepare(struct omap_dm_timer *timer); + +static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg, + int posted) +{ + if (posted) + while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)) + & (reg >> WPSHIFT)) + cpu_relax(); + + return __raw_readl(base + (reg & 0xff)); +} + +static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val, + int posted) +{ + if (posted) + while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)) + & (reg >> WPSHIFT)) + cpu_relax(); + + __raw_writel(val, base + (reg & 0xff)); +} + +/* Assumes the source clock has been set by caller */ +static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle, + int wakeup) +{ + u32 l; + + l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0); + 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; + + __omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0); + + /* Match hardware reset default of posted mode */ + __omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG, + OMAP_TIMER_CTRL_POSTED, 0); +} + +static inline int __omap_dm_timer_set_source(struct clk *timer_fck, + struct clk *parent) +{ + int ret; + + clk_disable(timer_fck); + ret = clk_set_parent(timer_fck, parent); + clk_enable(timer_fck); + + /* + * When the functional clock disappears, too quick writes seem + * to cause an abort. XXX Is this still necessary? + */ + __delay(300000); + + return ret; +} + +static inline void __omap_dm_timer_stop(void __iomem *base, int posted, + unsigned long rate) +{ + u32 l; + + l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted); + if (l & OMAP_TIMER_CTRL_ST) { + l &= ~0x1; + __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, l, posted); +#ifdef CONFIG_ARCH_OMAP2PLUS + /* Readback to make sure write has completed */ + __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted); + /* + * Wait for functional clock period x 3.5 to make sure that + * timer is stopped + */ + udelay(3500000 / rate + 1); +#endif + } + + /* Ack possibly pending interrupt */ + __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, + OMAP_TIMER_INT_OVERFLOW, 0); +} + +static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl, + unsigned int load, int posted) +{ + __omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG, load, posted); + __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, ctrl, posted); +} + +static inline void __omap_dm_timer_int_enable(void __iomem *base, + unsigned int value) +{ + __omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG, value, 0); + __omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG, value, 0); +} + +static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base, + int posted) +{ + return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted); +} + +static inline void __omap_dm_timer_write_status(void __iomem *base, + unsigned int value) +{ + __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0); +} + #endif /* __ASM_ARCH_DMTIMER_H */ -- cgit v1.2.1 From aa56188998942dfd1d6d85484c87f79268508bba Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 29 Mar 2011 15:54:48 -0700 Subject: omap2+: Use dmtimer macros for clockevent This patch makes timer-gp.c to use only a subset of dmtimer functions without the need to initialize dmtimer code early. Also note that now with the inline functions, timer_set_next_event becomes more efficient in the lines of assembly code. Signed-off-by: Tony Lindgren Reviewed-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/dmtimer.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/plat-omap/include/plat/dmtimer.h') diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 54664a7498af..dd8b3ffb7521 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -216,6 +216,7 @@ struct omap_dm_timer { struct clk *iclk, *fclk; #endif void __iomem *io_base; + unsigned long rate; unsigned reserved:1; unsigned enabled:1; unsigned posted:1; -- cgit v1.2.1 From 98e182a26bbbf5575457622337684ef61493e864 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 29 Mar 2011 15:54:49 -0700 Subject: omap2+: Remove gptimer_wakeup for now This removes the support for setting the wake-up timer for debugging. Later on we can reserve gptimer1 for PM code only and have similar functionality. Signed-off-by: Tony Lindgren Reviewed-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/dmtimer.h | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/arm/plat-omap/include/plat/dmtimer.h') diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index dd8b3ffb7521..8adcb187fe71 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -59,7 +59,6 @@ */ #define OMAP_TIMER_IP_VERSION_1 0x1 struct omap_dm_timer; -extern struct omap_dm_timer *gptimer_wakeup; struct clk; int omap_dm_timer_init(void); -- cgit v1.2.1 From 11a0186f3ef6aa6a9b8b81f5a501b6063fa47500 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 29 Mar 2011 15:54:49 -0700 Subject: omap2+: Reserve clocksource and timesource and initialize dmtimer later There's no need to initialize the dmtimer framework early. Just mark the clocksource and timesource as reserved, and initialize dmtimer with an arch_initcall. Signed-off-by: Tony Lindgren Reviewed-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/dmtimer.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/arm/plat-omap/include/plat/dmtimer.h') diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 8adcb187fe71..d0f3a2d22fd3 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -61,8 +61,6 @@ struct omap_dm_timer; struct clk; -int omap_dm_timer_init(void); - struct omap_dm_timer *omap_dm_timer_request(void); struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); void omap_dm_timer_free(struct omap_dm_timer *timer); @@ -221,6 +219,7 @@ struct omap_dm_timer { unsigned posted:1; }; +extern u32 sys_timer_reserved; void omap_dm_timer_prepare(struct omap_dm_timer *timer); static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg, -- cgit v1.2.1