|
@@ -98,12 +98,30 @@ int omap_dm_timers_active(void);
|
|
* used by dmtimer.c and sys_timer related code.
|
|
* 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
|
|
|
|
|
|
+/*
|
|
|
|
+ * The interrupt registers are different between v1 and v2 ip.
|
|
|
|
+ * These registers are offsets from timer->iobase.
|
|
|
|
+ */
|
|
|
|
+#define OMAP_TIMER_ID_OFFSET 0x00
|
|
|
|
+#define OMAP_TIMER_OCP_CFG_OFFSET 0x10
|
|
|
|
+
|
|
|
|
+#define OMAP_TIMER_V1_SYS_STAT_OFFSET 0x14
|
|
|
|
+#define OMAP_TIMER_V1_STAT_OFFSET 0x18
|
|
|
|
+#define OMAP_TIMER_V1_INT_EN_OFFSET 0x1c
|
|
|
|
+
|
|
|
|
+#define OMAP_TIMER_V2_IRQSTATUS_RAW 0x24
|
|
|
|
+#define OMAP_TIMER_V2_IRQSTATUS 0x28
|
|
|
|
+#define OMAP_TIMER_V2_IRQENABLE_SET 0x2c
|
|
|
|
+#define OMAP_TIMER_V2_IRQENABLE_CLR 0x30
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * The functional registers have a different base on v1 and v2 ip.
|
|
|
|
+ * These registers are offsets from timer->func_base. The func_base
|
|
|
|
+ * is samae as io_base for v1 and io_base + 0x14 for v2 ip.
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+#define OMAP_TIMER_V2_FUNC_OFFSET 0x14
|
|
|
|
+
|
|
#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20
|
|
#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20
|
|
#define _OMAP_TIMER_CTRL_OFFSET 0x24
|
|
#define _OMAP_TIMER_CTRL_OFFSET 0x24
|
|
#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
|
|
#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
|
|
@@ -147,21 +165,6 @@ int omap_dm_timers_active(void);
|
|
/* register offsets with the write pending bit encoded */
|
|
/* register offsets with the write pending bit encoded */
|
|
#define WPSHIFT 16
|
|
#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 \
|
|
#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \
|
|
| (WP_NONE << WPSHIFT))
|
|
| (WP_NONE << WPSHIFT))
|
|
|
|
|
|
@@ -213,7 +216,14 @@ struct omap_dm_timer {
|
|
#ifdef CONFIG_ARCH_OMAP2PLUS
|
|
#ifdef CONFIG_ARCH_OMAP2PLUS
|
|
struct clk *iclk, *fclk;
|
|
struct clk *iclk, *fclk;
|
|
#endif
|
|
#endif
|
|
- void __iomem *io_base;
|
|
|
|
|
|
+ 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 long rate;
|
|
unsigned reserved:1;
|
|
unsigned reserved:1;
|
|
unsigned enabled:1;
|
|
unsigned enabled:1;
|
|
@@ -223,35 +233,59 @@ struct omap_dm_timer {
|
|
extern u32 sys_timer_reserved;
|
|
extern u32 sys_timer_reserved;
|
|
void omap_dm_timer_prepare(struct omap_dm_timer *timer);
|
|
void omap_dm_timer_prepare(struct omap_dm_timer *timer);
|
|
|
|
|
|
-static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg,
|
|
|
|
|
|
+static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
|
|
int posted)
|
|
int posted)
|
|
{
|
|
{
|
|
if (posted)
|
|
if (posted)
|
|
- while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
|
|
|
|
- & (reg >> WPSHIFT))
|
|
|
|
|
|
+ while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
|
|
cpu_relax();
|
|
cpu_relax();
|
|
|
|
|
|
- return __raw_readl(base + (reg & 0xff));
|
|
|
|
|
|
+ return __raw_readl(timer->func_base + (reg & 0xff));
|
|
}
|
|
}
|
|
|
|
|
|
-static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
|
|
|
|
- int posted)
|
|
|
|
|
|
+static inline void __omap_dm_timer_write(struct omap_dm_timer *timer,
|
|
|
|
+ u32 reg, u32 val, int posted)
|
|
{
|
|
{
|
|
if (posted)
|
|
if (posted)
|
|
- while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
|
|
|
|
- & (reg >> WPSHIFT))
|
|
|
|
|
|
+ while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
|
|
cpu_relax();
|
|
cpu_relax();
|
|
|
|
|
|
- __raw_writel(val, base + (reg & 0xff));
|
|
|
|
|
|
+ __raw_writel(val, timer->func_base + (reg & 0xff));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
|
|
|
|
+{
|
|
|
|
+ u32 tidr;
|
|
|
|
+
|
|
|
|
+ /* Assume v1 ip if bits [31:16] are zero */
|
|
|
|
+ tidr = __raw_readl(timer->io_base);
|
|
|
|
+ if (!(tidr >> 16)) {
|
|
|
|
+ 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 = 0;
|
|
|
|
+ timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
|
|
|
|
+ timer->func_base = timer->io_base;
|
|
|
|
+ } else {
|
|
|
|
+ timer->sys_stat = 0;
|
|
|
|
+ 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;
|
|
|
|
+ timer->pend = timer->io_base +
|
|
|
|
+ _OMAP_TIMER_WRITE_PEND_OFFSET +
|
|
|
|
+ OMAP_TIMER_V2_FUNC_OFFSET;
|
|
|
|
+ timer->func_base = timer->io_base + OMAP_TIMER_V2_FUNC_OFFSET;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/* Assumes the source clock has been set by caller */
|
|
/* Assumes the source clock has been set by caller */
|
|
-static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
|
|
|
|
- int wakeup)
|
|
|
|
|
|
+static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
|
|
|
|
+ int autoidle, int wakeup)
|
|
{
|
|
{
|
|
u32 l;
|
|
u32 l;
|
|
|
|
|
|
- l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0);
|
|
|
|
|
|
+ l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
|
|
l |= 0x02 << 3; /* Set to smart-idle mode */
|
|
l |= 0x02 << 3; /* Set to smart-idle mode */
|
|
l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
|
|
l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
|
|
|
|
|
|
@@ -261,10 +295,10 @@ static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
|
|
if (wakeup)
|
|
if (wakeup)
|
|
l |= 1 << 2;
|
|
l |= 1 << 2;
|
|
|
|
|
|
- __omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0);
|
|
|
|
|
|
+ __raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
|
|
|
|
|
|
/* Match hardware reset default of posted mode */
|
|
/* Match hardware reset default of posted mode */
|
|
- __omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG,
|
|
|
|
|
|
+ __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
|
|
OMAP_TIMER_CTRL_POSTED, 0);
|
|
OMAP_TIMER_CTRL_POSTED, 0);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -286,18 +320,18 @@ static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
|
|
|
|
- unsigned long rate)
|
|
|
|
|
|
+static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
|
|
|
|
+ int posted, unsigned long rate)
|
|
{
|
|
{
|
|
u32 l;
|
|
u32 l;
|
|
|
|
|
|
- l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
|
|
|
|
|
|
+ l = __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
|
|
if (l & OMAP_TIMER_CTRL_ST) {
|
|
if (l & OMAP_TIMER_CTRL_ST) {
|
|
l &= ~0x1;
|
|
l &= ~0x1;
|
|
- __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, l, posted);
|
|
|
|
|
|
+ __omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, l, posted);
|
|
#ifdef CONFIG_ARCH_OMAP2PLUS
|
|
#ifdef CONFIG_ARCH_OMAP2PLUS
|
|
/* Readback to make sure write has completed */
|
|
/* Readback to make sure write has completed */
|
|
- __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
|
|
|
|
|
|
+ __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
|
|
/*
|
|
/*
|
|
* Wait for functional clock period x 3.5 to make sure that
|
|
* Wait for functional clock period x 3.5 to make sure that
|
|
* timer is stopped
|
|
* timer is stopped
|
|
@@ -307,34 +341,34 @@ static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
|
|
}
|
|
}
|
|
|
|
|
|
/* Ack possibly pending interrupt */
|
|
/* Ack possibly pending interrupt */
|
|
- __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG,
|
|
|
|
- OMAP_TIMER_INT_OVERFLOW, 0);
|
|
|
|
|
|
+ __raw_writel(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat);
|
|
}
|
|
}
|
|
|
|
|
|
-static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
|
|
|
|
- unsigned int load, int posted)
|
|
|
|
|
|
+static inline void __omap_dm_timer_load_start(struct omap_dm_timer *timer,
|
|
|
|
+ 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);
|
|
|
|
|
|
+ __omap_dm_timer_write(timer, OMAP_TIMER_COUNTER_REG, load, posted);
|
|
|
|
+ __omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, ctrl, posted);
|
|
}
|
|
}
|
|
|
|
|
|
-static inline void __omap_dm_timer_int_enable(void __iomem *base,
|
|
|
|
|
|
+static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer,
|
|
unsigned int value)
|
|
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);
|
|
|
|
|
|
+ __raw_writel(value, timer->irq_ena);
|
|
|
|
+ __omap_dm_timer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
|
|
}
|
|
}
|
|
|
|
|
|
-static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base,
|
|
|
|
- int posted)
|
|
|
|
|
|
+static inline unsigned int
|
|
|
|
+__omap_dm_timer_read_counter(struct omap_dm_timer *timer, int posted)
|
|
{
|
|
{
|
|
- return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted);
|
|
|
|
|
|
+ return __omap_dm_timer_read(timer, OMAP_TIMER_COUNTER_REG, posted);
|
|
}
|
|
}
|
|
|
|
|
|
-static inline void __omap_dm_timer_write_status(void __iomem *base,
|
|
|
|
|
|
+static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer,
|
|
unsigned int value)
|
|
unsigned int value)
|
|
{
|
|
{
|
|
- __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0);
|
|
|
|
|
|
+ __raw_writel(value, timer->irq_stat);
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* __ASM_ARCH_DMTIMER_H */
|
|
#endif /* __ASM_ARCH_DMTIMER_H */
|