[U-Boot] [PATCH v11 2/6] arm: faraday: add FTTMR010 timer support
Kuo-Jung Su
dantesu at gmail.com
Wed Mar 26 07:03:15 CET 2014
From: Kuo-Jung Su <dantesu at faraday-tech.com>
Faraday FTTMR010 is a simple APB device which supports
generic timer functions.
Signed-off-by: Kuo-Jung Su <dantesu at faraday-tech.com>
CC: Albert Aribaud <albert.u.boot at aribaud.net>
---
Changes for v11:
- Directly specify the timer object in 'arch/arm/cpu/faraday/<soc>/Makefile'
instead of using CONFIG_FTTMR010 in 'arch/arm/cpu/faraday/Makefile'
Changes for v8, v9, v10:
- Nothing updates
Changes for v7:
- Update license to use SPDX identifiers.
Changes for v6:
- Nothing updates
Changes for v5:
- Drop IRQ dependant implementation
- Use gd->arch.timer_rate_hz for timer clock source
- Use gd->arch.tbl for timestamp
Changes for v4:
- Coding Style cleanup.
- Break up from [arm: add Faraday A36x SoC platform support]
Changes for v3:
- Coding Style cleanup.
- Drop macros for wirtel()/readl(), call them directly.
- Always insert a blank line between declarations and code.
- Add '__iomem' to all the declaration of HW register pointers.
Changes for v2:
- Coding Style cleanup.
- Use readl(), writel(), clrsetbits_le32() to replace REG() macros.
- Use structure based hardware registers to replace the macro constants.
- Replace BIT() with BIT_MASK().
arch/arm/cpu/faraday/fttmr010.c | 123 +++++++++++++++++++++++++++++++++++++++
include/faraday/fttmr010.h | 17 ++++++
2 files changed, 140 insertions(+)
create mode 100644 arch/arm/cpu/faraday/fttmr010.c
diff --git a/arch/arm/cpu/faraday/fttmr010.c b/arch/arm/cpu/faraday/fttmr010.c
new file mode 100644
index 0000000..28b0086
--- /dev/null
+++ b/arch/arm/cpu/faraday/fttmr010.c
@@ -0,0 +1,123 @@
+/*
+ * (C) Copyright 2013
+ * Faraday Technology Corporation. <http://www.faraday-tech.com/tw/>
+ * Kuo-Jung Su <dantesu at gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <faraday/fttmr010.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct fttmr010 *regs = (void __iomem *)CONFIG_FTTMR010_BASE;
+
+void udelay_masked(unsigned long usec)
+{
+ ulong freq = gd->arch.timer_rate_hz;
+
+ /* Disable Timer2 */
+ clrbits_le32(®s->cr, FTTMR010_TM2_CRMASK);
+ /* Disable Timer2 interrupts */
+ writel(FTTMR010_TM2_ISRMASK, ®s->interrupt_mask);
+ /* Clear Timer2 interrupts */
+ writel(FTTMR010_TM2_ISRMASK, ®s->interrupt_state);
+
+ /* Configure Timer2 */
+ writel((freq / 1000000) * usec, ®s->timer2_counter);
+ writel(0, ®s->timer2_load);
+ writel(0, ®s->timer2_match1);
+ writel(0, ®s->timer2_match2);
+
+ /* Enable Timer2 */
+ setbits_le32(®s->cr,
+ FTTMR010_TM2_OFENABLE | FTTMR010_TM2_ENABLE);
+
+ /* Wait until timeout */
+ while (!(readl(®s->interrupt_state) & FTTMR010_TM2_ISRMASK))
+ ;
+}
+
+void reset_timer_masked(void)
+{
+ ulong freq = gd->arch.timer_rate_hz;
+
+ /* Disable Timer1 */
+ clrbits_le32(®s->cr, FTTMR010_TM1_CRMASK);
+
+ /* Disable & Clear Timer1 interrupts */
+ writel(FTTMR010_TM1_ISRMASK, ®s->interrupt_mask);
+ writel(FTTMR010_TM1_ISRMASK, ®s->interrupt_state);
+
+ /* Setup a longest periodic timer */
+ writel((0xffffffff / freq) * freq, ®s->timer1_counter);
+ writel((0xffffffff / freq) * freq, ®s->timer1_load);
+
+ writel(0, ®s->timer1_match1);
+ writel(0, ®s->timer1_match2);
+
+ /* Disable match interrupts */
+ writel(FTTMR010_TM1_MATCH1 | FTTMR010_TM1_MATCH2,
+ ®s->interrupt_mask);
+
+ /* Enable Timer1 with overflow interrupt */
+ setbits_le32(®s->cr,
+ FTTMR010_TM1_OFENABLE | FTTMR010_TM1_ENABLE);
+}
+
+ulong get_timer_masked(void)
+{
+ ulong freq = gd->arch.timer_rate_hz;
+ ulong secs = 0xffffffff / freq;
+ ulong ms = freq / CONFIG_SYS_HZ;
+
+ if (readl(®s->interrupt_state) & FTTMR010_TM1_ISRMASK) {
+ writel(FTTMR010_TM1_ISRMASK, ®s->interrupt_state);
+ gd->arch.tbl += secs * CONFIG_SYS_HZ;
+ }
+
+ return gd->arch.tbl
+ + ((secs * freq) - readl(®s->timer1_counter)) / ms;
+}
+
+int timer_init(void)
+{
+ gd->arch.tbl = 0;
+ reset_timer_masked();
+ return 0;
+}
+
+void reset_timer(void)
+{
+ reset_timer_masked();
+}
+
+ulong get_timer(ulong base)
+{
+ return get_timer_masked() - base;
+}
+
+void __udelay(unsigned long usec)
+{
+ udelay_masked(usec);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+ return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+ return CONFIG_SYS_HZ;
+}
diff --git a/include/faraday/fttmr010.h b/include/faraday/fttmr010.h
index 2ab68d1..21ab113 100644
--- a/include/faraday/fttmr010.h
+++ b/include/faraday/fttmr010.h
@@ -45,6 +45,16 @@ struct fttmr010 {
#define FTTMR010_TM1_CLOCK (1 << 1)
#define FTTMR010_TM1_ENABLE (1 << 0)
+#define FTTMR010_TM1_CRMASK \
+ (FTTMR010_TM1_UPDOWN | FTTMR010_TM1_OFENABLE \
+ | FTTMR010_TM1_CLOCK | FTTMR010_TM1_ENABLE)
+#define FTTMR010_TM2_CRMASK \
+ (FTTMR010_TM2_UPDOWN | FTTMR010_TM2_OFENABLE \
+ | FTTMR010_TM2_CLOCK | FTTMR010_TM2_ENABLE)
+#define FTTMR010_TM3_CRMASK \
+ (FTTMR010_TM3_UPDOWN | FTTMR010_TM3_OFENABLE \
+ | FTTMR010_TM3_CLOCK | FTTMR010_TM3_ENABLE)
+
/*
* Timer Interrupt State & Mask Registers
*/
@@ -58,4 +68,11 @@ struct fttmr010 {
#define FTTMR010_TM1_MATCH2 (1 << 1)
#define FTTMR010_TM1_MATCH1 (1 << 0)
+#define FTTMR010_TM1_ISRMASK \
+ (FTTMR010_TM1_OVERFLOW | FTTMR010_TM1_MATCH2 | FTTMR010_TM1_MATCH1)
+#define FTTMR010_TM2_ISRMASK \
+ (FTTMR010_TM2_OVERFLOW | FTTMR010_TM2_MATCH2 | FTTMR010_TM2_MATCH1)
+#define FTTMR010_TM3_ISRMASK \
+ (FTTMR010_TM3_OVERFLOW | FTTMR010_TM3_MATCH2 | FTTMR010_TM3_MATCH1)
+
#endif /* __FTTMR010_H */
--
1.7.9.5
More information about the U-Boot
mailing list