diff options
author | Tony Lindgren <tony@atomide.com> | 2012-11-13 22:52:38 +0100 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2012-11-13 22:52:38 +0100 |
commit | 9dc57643738f9fbe45c10cc062903d5dfda5bdd9 (patch) | |
tree | 1579e10fe2cf0b5473080c74e1184976372df8f2 /arch/arm/plat-omap/include | |
parent | Merge branch 'omap-for-v3.8/cleanup-headers-prepare-multiplatform-v3' into om... (diff) | |
parent | ARM: OMAP: Remove __omap_dm_timer_set_source function (diff) | |
download | linux-9dc57643738f9fbe45c10cc062903d5dfda5bdd9.tar.xz linux-9dc57643738f9fbe45c10cc062903d5dfda5bdd9.zip |
Merge branch 'fixes-timer' of github.com:jonhunter/linux into omap-for-v3.8/timer
Diffstat (limited to 'arch/arm/plat-omap/include')
-rw-r--r-- | arch/arm/plat-omap/include/plat/dmtimer.h | 72 |
1 files changed, 52 insertions, 20 deletions
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index f8943c8f9dbf..05a36e16f3f4 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -32,7 +32,6 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/clk.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/platform_device.h> @@ -55,6 +54,10 @@ #define OMAP_TIMER_TRIGGER_OVERFLOW 0x01 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02 +/* posted mode types */ +#define OMAP_TIMER_NONPOSTED 0x00 +#define OMAP_TIMER_POSTED 0x01 + /* timer capabilities used in hwmod database */ #define OMAP_TIMER_SECURE 0x80000000 #define OMAP_TIMER_ALWON 0x40000000 @@ -62,6 +65,16 @@ #define OMAP_TIMER_NEEDS_RESET 0x10000000 #define OMAP_TIMER_HAS_DSP_IRQ 0x08000000 +/* + * timer errata flags + * + * Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This + * errata prevents us from using posted mode on these devices, unless the + * timer counter register is never read. For more details please refer to + * the OMAP3/4/5 errata documents. + */ +#define OMAP_TIMER_ERRATA_I103_I767 0x80000000 + struct omap_timer_capability_dev_attr { u32 timer_capability; }; @@ -70,8 +83,6 @@ struct omap_dm_timer; struct timer_regs { u32 tidr; - u32 tistat; - u32 tisr; u32 tier; u32 twer; u32 tclr; @@ -93,6 +104,7 @@ struct timer_regs { 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; int (*get_context_loss_count)(struct device *); }; @@ -122,6 +134,7 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, i int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler); int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value); +int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask); unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); @@ -269,6 +282,7 @@ struct omap_dm_timer { int ctx_loss_count; int revision; u32 capability; + u32 errata; struct platform_device *pdev; struct list_head node; }; @@ -307,7 +321,7 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer) 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 = NULL; + timer->irq_dis = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET; timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET; timer->func_base = timer->io_base; } else { @@ -340,28 +354,46 @@ static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer, l |= 1 << 2; __raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET); - - /* Match hardware reset default of posted mode */ - __omap_dm_timer_write(timer, 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) +/* + * __omap_dm_timer_enable_posted - enables write posted mode + * @timer: pointer to timer instance handle + * + * Enables the write posted mode for the timer. When posted mode is enabled + * writes to certain timer registers are immediately acknowledged by the + * internal bus and hence prevents stalling the CPU waiting for the write to + * complete. Enabling this feature can improve performance for writing to the + * timer registers. + */ +static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer) { - int ret; + if (timer->posted) + return; - clk_disable(timer_fck); - ret = clk_set_parent(timer_fck, parent); - clk_enable(timer_fck); + if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) + return; - /* - * When the functional clock disappears, too quick writes seem - * to cause an abort. XXX Is this still necessary? - */ - __delay(300000); + __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, + OMAP_TIMER_CTRL_POSTED, 0); + timer->context.tsicr = OMAP_TIMER_CTRL_POSTED; + timer->posted = OMAP_TIMER_POSTED; +} - return ret; +/** + * __omap_dm_timer_override_errata - override errata flags for a timer + * @timer: pointer to timer handle + * @errata: errata flags to be ignored + * + * For a given timer, override a timer errata by clearing the flags + * specified by the errata argument. A specific erratum should only be + * overridden for a timer if the timer is used in such a way the erratum + * has no impact. + */ +static inline void __omap_dm_timer_override_errata(struct omap_dm_timer *timer, + u32 errata) +{ + timer->errata &= ~errata; } static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer, |