[U-Boot] [RFC PATCH 09/13] arm: nexell: add UART support

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

The Nexell S5P6818 SoC uses a UART very similar to those used in the
Samsung S5P SoCs.
Enable the driver in the config and add the necessary glue headers
and clock functions to make the S5P driver happy.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
arch/arm/Kconfig | 3 ++
arch/arm/include/asm/arch-nexell/clk.h | 13 +++++++++
arch/arm/mach-nexell/board.c | 50 ++++++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+)
create mode 100644 arch/arm/include/asm/arch-nexell/clk.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b0f3ee7289..9c317ddf3f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -656,6 +656,9 @@ config ARCH_NEXELL
bool "Nexell S5P support"
select ARM64
select ENABLE_ARM_SOC_BOOT0_HOOK
+ select DM
+ select DM_SERIAL
+ select SAMSUNG_UART

config ARCH_QEMU
bool "QEMU Virtual Platform"
diff --git a/arch/arm/include/asm/arch-nexell/clk.h b/arch/arm/include/asm/arch-nexell/clk.h
new file mode 100644
index 0000000000..bfd145f555
--- /dev/null
+++ b/arch/arm/include/asm/arch-nexell/clk.h
@@ -0,0 +1,13 @@
+/*
+ * (C) Copyright 2017 ARM Ltd.
+ * Andre Przywara <andre.przywara@arm.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __ASM_ARCH_CLK_H_
+#define __ASM_ARCH_CLK_H_
+
+unsigned long get_uart_clk(int dev_index);
+
+#endif
diff --git a/arch/arm/mach-nexell/board.c b/arch/arm/mach-nexell/board.c
index f0d258b71c..54a9d8c1f5 100644
--- a/arch/arm/mach-nexell/board.c
+++ b/arch/arm/mach-nexell/board.c
@@ -5,9 +5,14 @@
*/

#include <common.h>
+#include <asm/io.h>

DECLARE_GLOBAL_DATA_PTR;

+#define NEXELL_PLLSETREG0 0xc0010008UL
+
+#define OSC_FREQ 24000000
+
/* TODO: dummy implementation for now, add proper reset code */
void reset_cpu(ulong addr)
{
@@ -35,6 +40,51 @@ ulong get_tbclk(void)
return CONFIG_SYS_HZ;
}

+static unsigned long get_pll_freq(int pll_index)
+{
+ uint32_t reg;
+ unsigned int pdiv, mdiv, sdiv, plloutdiv;
+ unsigned int multfreq;
+
+ if (pll_index < 0 || pll_index > 3)
+ return 0;
+
+ reg = readl(NEXELL_PLLSETREG0 + pll_index * 4);
+ sdiv = reg & 0xff;
+ mdiv = (reg >> 8) & 0x3ff;
+ pdiv = (reg >> 18) & 0x3f;
+ plloutdiv = ((reg >> 24) & 0xf) + 1;
+
+ multfreq = (OSC_FREQ / 1000) * mdiv;
+ return (1000 * (multfreq / (pdiv * 2 * sdiv))) / plloutdiv;
+}
+
+static unsigned long get_level1_clk_freq(uintptr_t base_addr)
+{
+ uint32_t reg;
+ unsigned int pll_index, div;
+
+ reg = readl(base_addr + 0x4);
+ pll_index = (reg >> 2) & 0x7;
+ if (pll_index > 3)
+ return -1UL;
+
+ div = ((reg >> 5) & 0xff) + 1;
+
+ return get_pll_freq(pll_index) / div;
+}
+
+unsigned long get_uart_clk(int dev_index)
+{
+ uintptr_t clock_ofs[6] = {0xc00a9000, 0xc00a8000, 0xc00aa000,
+ 0xc00ab000, 0xc006e000, 0xc0084000};
+
+ if (dev_index < 0 || dev_index > 5)
+ return 0;
+
+ return get_level1_clk_freq(clock_ofs[dev_index]);
+}
+
int board_init(void)
{
return 0;
--
2.14.1