[U-Boot] [RFC PATCH 10/13] arm: nexell: add timer support

Andre Przywara
2017-11-30T01:25:08Z

From: Amit Singh Tomar <amittomer25@gmail.com>

Nexell based SoCs (S5P4414 and S5P6818) contain the same timer block as
present on Samsungs SoCs.

Add this timer code when compiling for Nexell SoC and provide the
necessary glue functions to make the Samsung timer driver happy.

Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
arch/arm/include/asm/arch-nexell/clk.h | 1 +
arch/arm/include/asm/arch-nexell/pwm.h | 62 ++++++++++++++++++++++++++++++++++
arch/arm/mach-nexell/Makefile | 2 ++
arch/arm/mach-nexell/board.c | 37 +++++++++++++++++---
4 files changed, 97 insertions(+), 5 deletions(-)
create mode 100644 arch/arm/include/asm/arch-nexell/pwm.h

diff --git a/arch/arm/include/asm/arch-nexell/clk.h b/arch/arm/include/asm/arch-nexell/clk.h
index bfd145f555..8cf56ef52c 100644
--- a/arch/arm/include/asm/arch-nexell/clk.h
+++ b/arch/arm/include/asm/arch-nexell/clk.h
@@ -9,5 +9,6 @@
#define __ASM_ARCH_CLK_H_

unsigned long get_uart_clk(int dev_index);
+unsigned long get_pwm_clk(void);

#endif
diff --git a/arch/arm/include/asm/arch-nexell/pwm.h b/arch/arm/include/asm/arch-nexell/pwm.h
new file mode 100644
index 0000000000..7290c61366
--- /dev/null
+++ b/arch/arm/include/asm/arch-nexell/pwm.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ * Minkyu Kang <mk7.kang@samsung.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __ASM_ARM_ARCH_PWM_H_
+#define __ASM_ARM_ARCH_PWM_H_
+
+#define PRESCALER_0 (8 - 1) /* prescaler of timer 0, 1 */
+#define PRESCALER_1 (16 - 1) /* prescaler of timer 2, 3, 4 */
+
+/* Divider MUX */
+#define MUX_DIV_1 0 /* 1/1 period */
+#define MUX_DIV_2 1 /* 1/2 period */
+#define MUX_DIV_4 2 /* 1/4 period */
+#define MUX_DIV_8 3 /* 1/8 period */
+#define MUX_DIV_16 4 /* 1/16 period */
+
+#define MUX_DIV_SHIFT(x) (x * 4)
+
+#define TCON_OFFSET(x) ((x + 1) * (!!x) << 2)
+
+#define TCON_START(x) (1 << TCON_OFFSET(x))
+#define TCON_UPDATE(x) (1 << (TCON_OFFSET(x) + 1))
+#define TCON_INVERTER(x) (1 << (TCON_OFFSET(x) + 2))
+#define TCON_AUTO_RELOAD(x) (1 << (TCON_OFFSET(x) + 3))
+#define TCON4_AUTO_RELOAD (1 << 22)
+
+#define NEXELL_TIMER_BASE 0xc0017000
+
+#ifndef __ASSEMBLY__
+struct s5p_timer {
+ unsigned int tcfg0;
+ unsigned int tcfg1;
+ unsigned int tcon;
+ unsigned int tcntb0;
+ unsigned int tcmpb0;
+ unsigned int tcnto0;
+ unsigned int tcntb1;
+ unsigned int tcmpb1;
+ unsigned int tcnto1;
+ unsigned int tcntb2;
+ unsigned int tcmpb2;
+ unsigned int tcnto2;
+ unsigned int tcntb3;
+ unsigned int tcmpb3;
+ unsigned int tcnto3;
+ unsigned int tcntb4;
+ unsigned int tcnto4;
+ unsigned int tintcstat;
+};
+#endif /* __ASSEMBLY__ */
+
+static inline unsigned long samsung_get_base_timer(void)
+{
+ return NEXELL_TIMER_BASE;
+}
+
+#endif
diff --git a/arch/arm/mach-nexell/Makefile b/arch/arm/mach-nexell/Makefile
index c4c8293cbc..c59ad631e6 100644
--- a/arch/arm/mach-nexell/Makefile
+++ b/arch/arm/mach-nexell/Makefile
@@ -6,3 +6,5 @@

obj-y := board.o
obj-$(CONFIG_ARM64) += mmu-arm64.o
+obj-y += ../cpu/armv7/s5p-common/timer.o
+obj-y += ../cpu/armv7/s5p-common/pwm.o
diff --git a/arch/arm/mach-nexell/board.c b/arch/arm/mach-nexell/board.c
index 54a9d8c1f5..e9b4f94630 100644
--- a/arch/arm/mach-nexell/board.c
+++ b/arch/arm/mach-nexell/board.c
@@ -10,9 +10,27 @@
DECLARE_GLOBAL_DATA_PTR;

#define NEXELL_PLLSETREG0 0xc0010008UL
+#define NEXELL_CLKDIVREG1 0xc0010024UL
+#define IP_RESET1 0xc0012004UL

#define OSC_FREQ 24000000

+int arch_cpu_init(void)
+{
+ u32 val;
+
+ /*
+ * Reset timer block #4.
+ * Ideally this should be done through the reset driver, but
+ * unfortunately our timer driver is not DM driven.
+ */
+ val = readl(IP_RESET1);
+ val |= BIT(4);
+ writel(val, IP_RESET1);
+
+ return 0;
+}
+
/* TODO: dummy implementation for now, add proper reset code */
void reset_cpu(ulong addr)
{
@@ -35,11 +53,6 @@ int dram_init(void)
return 0;
}

-ulong get_tbclk(void)
-{
- return CONFIG_SYS_HZ;
-}
-
static unsigned long get_pll_freq(int pll_index)
{
uint32_t reg;
@@ -85,6 +98,20 @@ unsigned long get_uart_clk(int dev_index)
return get_level1_clk_freq(clock_ofs[dev_index]);
}

+/* This is reading the PCLK frequency, which drives the PWM timer. */
+unsigned long get_pwm_clk(void)
+{
+ uint32_t reg;
+ unsigned int pll_index, div;
+
+ reg = readl(NEXELL_CLKDIVREG1);
+ pll_index = reg & 0x7;
+ div = ((reg >> 3) & 0x3f) + 1; /* BCLK divider */
+ div *= ((reg >> 9) & 0x3f) + 1; /* PCLK divider */
+
+ return get_pll_freq(pll_index) / div;
+}
+
int board_init(void)
{
return 0;
--
2.14.1