diff options
Diffstat (limited to 'arch/arm/plat-omap/dmtimer.c')
| -rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 209 | 
1 files changed, 26 insertions, 183 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index ee9f6ebba29..8dfb8186b2c 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -41,127 +41,6 @@  #include <plat/dmtimer.h>  #include <mach/irqs.h> -/* 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; -}; -  static int dm_timer_count;  #ifdef CONFIG_ARCH_OMAP1 @@ -291,11 +170,7 @@ static spinlock_t dm_timer_lock;   */  static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)  { -	if (timer->posted) -		while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)) -				& (reg >> WPSHIFT)) -			cpu_relax(); -	return readl(timer->io_base + (reg & 0xff)); +	return __omap_dm_timer_read(timer->io_base, reg, timer->posted);  }  /* @@ -307,11 +182,7 @@ static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)  static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,  						u32 value)  { -	if (timer->posted) -		while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)) -				& (reg >> WPSHIFT)) -			cpu_relax(); -	writel(value, timer->io_base + (reg & 0xff)); +	__omap_dm_timer_write(timer->io_base, reg, value, timer->posted);  }  static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) @@ -330,7 +201,7 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)  static void omap_dm_timer_reset(struct omap_dm_timer *timer)  { -	u32 l; +	int autoidle = 0, wakeup = 0;  	if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {  		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); @@ -338,28 +209,21 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)  	}  	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); -	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG); -	l |= 0x02 << 3;  /* Set to smart-idle mode */ -	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */ -  	/* Enable autoidle on OMAP2 / OMAP3 */  	if (cpu_is_omap24xx() || cpu_is_omap34xx()) -		l |= 0x1 << 0; +		autoidle = 1;  	/*  	 * Enable wake-up on OMAP2 CPUs.  	 */  	if (cpu_class_is_omap2()) -		l |= 1 << 2; -	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); +		wakeup = 1; -	/* Match hardware reset default of posted mode */ -	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, -			OMAP_TIMER_CTRL_POSTED); +	__omap_dm_timer_reset(timer->io_base, autoidle, wakeup);  	timer->posted = 1;  } -static void omap_dm_timer_prepare(struct omap_dm_timer *timer) +void omap_dm_timer_prepare(struct omap_dm_timer *timer)  {  	omap_dm_timer_enable(timer);  	omap_dm_timer_reset(timer); @@ -531,25 +395,13 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start);  void omap_dm_timer_stop(struct omap_dm_timer *timer)  { -	u32 l; +	unsigned long rate = 0; -	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); -	if (l & OMAP_TIMER_CTRL_ST) { -		l &= ~0x1; -		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);  #ifdef CONFIG_ARCH_OMAP2PLUS -		/* Readback to make sure write has completed */ -		omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); -		 /* -		  * Wait for functional clock period x 3.5 to make sure that -		  * timer is stopped -		  */ -		udelay(3500000 / clk_get_rate(timer->fclk) + 1); +	rate = clk_get_rate(timer->fclk);  #endif -	} -	/* Ack possibly pending interrupt */ -	omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, -			OMAP_TIMER_INT_OVERFLOW); + +	__omap_dm_timer_stop(timer->io_base, timer->posted, rate);  }  EXPORT_SYMBOL_GPL(omap_dm_timer_stop); @@ -572,22 +424,11 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);  int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)  { -	int ret = -EINVAL; -  	if (source < 0 || source >= 3)  		return -EINVAL; -	clk_disable(timer->fclk); -	ret = clk_set_parent(timer->fclk, dm_source_clocks[source]); -	clk_enable(timer->fclk); - -	/* -	 * When the functional clock disappears, too quick writes seem -	 * to cause an abort. XXX Is this still necessary? -	 */ -	__delay(300000); - -	return ret; +	return __omap_dm_timer_set_source(timer->fclk, +						dm_source_clocks[source]);  }  EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); @@ -625,8 +466,7 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,  	}  	l |= OMAP_TIMER_CTRL_ST; -	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load); -	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); +	__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);  }  EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start); @@ -679,8 +519,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);  void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,  				  unsigned int value)  { -	omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); -	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value); +	__omap_dm_timer_int_enable(timer->io_base, value);  }  EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable); @@ -696,17 +535,13 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);  void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)  { -	omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value); +	__omap_dm_timer_write_status(timer->io_base, value);  }  EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);  unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)  { -	unsigned int l; - -	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); - -	return l; +	return __omap_dm_timer_read_counter(timer->io_base, timer->posted);  }  EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter); @@ -737,7 +572,7 @@ int omap_dm_timers_active(void)  }  EXPORT_SYMBOL_GPL(omap_dm_timers_active); -int __init omap_dm_timer_init(void) +static int __init omap_dm_timer_init(void)  {  	struct omap_dm_timer *timer;  	int i, map_size = SZ_8K;	/* Module 4KB + L4 4KB except on omap1 */ @@ -790,8 +625,16 @@ int __init omap_dm_timer_init(void)  			sprintf(clk_name, "gpt%d_fck", i + 1);  			timer->fclk = clk_get(NULL, clk_name);  		} + +		/* One or two timers may be set up early for sys_timer */ +		if (sys_timer_reserved & (1  << i)) { +			timer->reserved = 1; +			timer->posted = 1; +		}  #endif  	}  	return 0;  } + +arch_initcall(omap_dm_timer_init);  |