Patchwork [U-Boot,v5,10/14] arm: add Faraday FTTMR010 timer support

login
register
mail settings
Submitter Kuo-Jung Su
Date June 17, 2013, 12:07 p.m.
Message ID <1371470824-3228-11-git-send-email-dantesu@gmail.com>
Download mbox | patch
Permalink /patch/251835/
State Superseded
Delegated to: Albert ARIBAUD
Headers show

Comments

Kuo-Jung Su - June 17, 2013, 12:07 p.m.
From: Kuo-Jung Su <dantesu@faraday-tech.com>

Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com>
CC: Albert Aribaud <albert.u.boot@aribaud.net>
---
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/Makefile   |    1 +
 arch/arm/cpu/faraday/fttmr010.c |  136 +++++++++++++++++++++++++++++++++++++++
 include/faraday/fttmr010.h      |   17 +++++
 3 files changed, 154 insertions(+)
 create mode 100644 arch/arm/cpu/faraday/fttmr010.c

--
1.7.9.5

Patch

diff --git a/arch/arm/cpu/faraday/Makefile b/arch/arm/cpu/faraday/Makefile
index 35926c2..658d9ed 100644
--- a/arch/arm/cpu/faraday/Makefile
+++ b/arch/arm/cpu/faraday/Makefile
@@ -27,6 +27,7 @@  LIB	= $(obj)lib$(CPU).o

 src-y  := cpu.o
 src-$(CONFIG_FTINTC020)   += ftintc020.o
+src-$(CONFIG_FTTMR010)    += fttmr010.o

 START	= start.o
 COBJS	= $(src-y)
diff --git a/arch/arm/cpu/faraday/fttmr010.c b/arch/arm/cpu/faraday/fttmr010.c
new file mode 100644
index 0000000..9d6f7ac
--- /dev/null
+++ b/arch/arm/cpu/faraday/fttmr010.c
@@ -0,0 +1,136 @@ 
+/*
+ * arch/arm/cpu/faraday/fttmr010.c
+ *
+ * (C) Copyright 2013 Faraday Technology
+ * Dante Su <dantesu@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#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(&regs->cr, FTTMR010_TM2_CRMASK);
+	/* Disable Timer2 interrupts */
+	writel(FTTMR010_TM2_ISRMASK, &regs->interrupt_mask);
+	/* Clear Timer2 interrupts */
+	writel(FTTMR010_TM2_ISRMASK, &regs->interrupt_state);
+
+	/* Configure Timer2 */
+	writel((freq / 1000000) * usec, &regs->timer2_counter);
+	writel(0, &regs->timer2_load);
+	writel(0, &regs->timer2_match1);
+	writel(0, &regs->timer2_match2);
+
+	/* Enable Timer2 */
+	setbits_le32(&regs->cr,
+		FTTMR010_TM2_OFENABLE | FTTMR010_TM2_ENABLE);
+
+	/* Wait until timeout */
+	while (!(readl(&regs->interrupt_state) & FTTMR010_TM2_ISRMASK))
+		;
+}
+
+void reset_timer_masked(void)
+{
+	ulong freq = gd->arch.timer_rate_hz;
+
+	/* Disable Timer1 */
+	clrbits_le32(&regs->cr, FTTMR010_TM1_CRMASK);
+
+	/* Disable & Clear Timer1 interrupts */
+	writel(FTTMR010_TM1_ISRMASK, &regs->interrupt_mask);
+	writel(FTTMR010_TM1_ISRMASK, &regs->interrupt_state);
+
+	/* Setup a longest periodic timer */
+	writel((0xffffffff / freq) * freq, &regs->timer1_counter);
+	writel((0xffffffff / freq) * freq, &regs->timer1_load);
+
+	writel(0, &regs->timer1_match1);
+	writel(0, &regs->timer1_match2);
+
+	/* Disable match interrupts */
+	writel(FTTMR010_TM1_MATCH1 | FTTMR010_TM1_MATCH2,
+		&regs->interrupt_mask);
+
+	/* Enable Timer1 with overflow interrupt */
+	setbits_le32(&regs->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(&regs->interrupt_state) & FTTMR010_TM1_ISRMASK) {
+		writel(FTTMR010_TM1_ISRMASK, &regs->interrupt_state);
+		gd->arch.tbl += secs * CONFIG_SYS_HZ;
+	}
+
+	return gd->arch.tbl
+		+ ((secs * freq) - readl(&regs->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 72abcb3..ef10f31 100644
--- a/include/faraday/fttmr010.h
+++ b/include/faraday/fttmr010.h
@@ -57,6 +57,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
  */
@@ -70,4 +80,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 */