@@ -9,5 +9,6 @@
#define __ASM_ARCH_CLK_H_
unsigned long get_uart_clk(int dev_index);
+unsigned long get_pwm_clk(void);
#endif
new file mode 100644
@@ -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
@@ -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
@@ -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;