Merge tag 'cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[firefly-linux-kernel-4.4.55.git] / arch / arm / plat-omap / include / plat / dmtimer.h
index 3f5b9cfd9c0b1707fc6740baaa9d15069def05fe..a3fbc48c332ecd0ebcf02023d43209d8d1a00690 100644 (file)
@@ -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>
 #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
 #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;
 };
 
-struct omap_dm_timer;
-
 struct timer_regs {
        u32 tidr;
-       u32 tistat;
-       u32 tisr;
        u32 tier;
        u32 twer;
        u32 tclr;
@@ -90,16 +99,35 @@ struct timer_regs {
        u32 towr;
 };
 
-struct dmtimer_platform_data {
-       /* set_timer_src - Only used for OMAP1 devices */
-       int (*set_timer_src)(struct platform_device *pdev, int source);
-       u32 timer_capability;
+struct omap_dm_timer {
+       int id;
+       int irq;
+       struct clk *fclk;
+
+       void __iomem    *io_base;
+       void __iomem    *irq_stat;      /* TISR/IRQSTATUS interrupt status */
+       void __iomem    *irq_ena;       /* irq enable */
+       void __iomem    *irq_dis;       /* irq disable, only on v2 ip */
+       void __iomem    *pend;          /* write pending */
+       void __iomem    *func_base;     /* function register base */
+
+       unsigned long rate;
+       unsigned reserved:1;
+       unsigned posted:1;
+       struct timer_regs context;
        int (*get_context_loss_count)(struct device *);
+       int ctx_loss_count;
+       int revision;
+       u32 capability;
+       u32 errata;
+       struct platform_device *pdev;
+       struct list_head node;
 };
 
 int omap_dm_timer_reserve_systimer(int id);
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
+struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap);
 int omap_dm_timer_free(struct omap_dm_timer *timer);
 void omap_dm_timer_enable(struct omap_dm_timer *timer);
 void 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
 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);
@@ -246,34 +275,6 @@ int omap_dm_timers_active(void);
 #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 id;
-       int irq;
-       struct clk *fclk;
-
-       void __iomem    *io_base;
-       void __iomem    *sys_stat;      /* TISTAT timer status */
-       void __iomem    *irq_stat;      /* TISR/IRQSTATUS interrupt status */
-       void __iomem    *irq_ena;       /* irq enable */
-       void __iomem    *irq_dis;       /* irq disable, only on v2 ip */
-       void __iomem    *pend;          /* write pending */
-       void __iomem    *func_base;     /* function register base */
-
-       unsigned long rate;
-       unsigned reserved:1;
-       unsigned posted:1;
-       struct timer_regs context;
-       int (*get_context_loss_count)(struct device *);
-       int ctx_loss_count;
-       int revision;
-       u32 capability;
-       struct platform_device *pdev;
-       struct list_head node;
-};
-
-int omap_dm_timer_prepare(struct omap_dm_timer *timer);
-
 static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
                                                int posted)
 {
@@ -302,16 +303,13 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
        tidr = __raw_readl(timer->io_base);
        if (!(tidr >> 16)) {
                timer->revision = 1;
-               timer->sys_stat = timer->io_base +
-                               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 {
                timer->revision = 2;
-               timer->sys_stat = NULL;
                timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
                timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
                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)
        }
 }
 
-/* Assumes the source clock has been set by caller */
-static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
-                                       int autoidle, int wakeup)
+/*
+ * __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)
 {
-       u32 l;
+       if (timer->posted)
+               return;
 
-       l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
-       l |= 0x02 << 3;  /* Set to smart-idle mode */
-       l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
+       if (timer->errata & OMAP_TIMER_ERRATA_I103_I767)
+               return;
 
-       if (autoidle)
-               l |= 0x1 << 0;
-
-       if (wakeup)
-               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);
+                             OMAP_TIMER_CTRL_POSTED, 0);
+       timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;
+       timer->posted = OMAP_TIMER_POSTED;
 }
 
-static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
-                                               struct clk *parent)
+/**
+ * __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)
 {
-       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;
+       timer->errata &= ~errata;
 }
 
 static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,