[PATCH RFC 18/20] mips/mach-jz47xx: Add Ingenic JZ4730 support

Lubomir Rintel lkundrak at v3.sk
Tue Nov 17 22:00:16 CET 2020


This adds support for the Ingenic JZ4730 SoC. There's not much more than
the build machinery and SPL stage because the main stage is entirely DT
driven.

The SPL is fairly unsophisticated since it has to fit into 4096 bytes. The
serial support didn't fit, and the pinmux and PLL init duplicates some
functionality of full drivers for space reasons. A regular NAND flash
driver is used though.

Signed-off-by: Lubomir Rintel <lkundrak at v3.sk>
---
 arch/mips/mach-jz47xx/Kconfig                |  39 +++
 arch/mips/mach-jz47xx/Makefile               |   2 +
 arch/mips/mach-jz47xx/jz4730/Kconfig         |  87 ++++++
 arch/mips/mach-jz47xx/jz4730/Makefile        |   3 +
 arch/mips/mach-jz47xx/jz4730/lowlevel_init.S |  37 +++
 arch/mips/mach-jz47xx/jz4730/spl.c           | 293 +++++++++++++++++++
 6 files changed, 461 insertions(+)
 create mode 100644 arch/mips/mach-jz47xx/jz4730/Kconfig
 create mode 100644 arch/mips/mach-jz47xx/jz4730/Makefile
 create mode 100644 arch/mips/mach-jz47xx/jz4730/lowlevel_init.S
 create mode 100644 arch/mips/mach-jz47xx/jz4730/spl.c

diff --git a/arch/mips/mach-jz47xx/Kconfig b/arch/mips/mach-jz47xx/Kconfig
index dcaac016286..6fba38c7363 100644
--- a/arch/mips/mach-jz47xx/Kconfig
+++ b/arch/mips/mach-jz47xx/Kconfig
@@ -4,6 +4,41 @@ menu "Ingenic JZ47xx platforms"
 config SYS_SOC
 	default "jz47xx"
 
+config SPL_TEXT_BASE
+	default 0x80000000 if ARCH_JZ47XX
+
+config SYS_TEXT_BASE
+	default 0x80100000 if ARCH_JZ47XX
+
+config SOC_JZ4730
+	bool
+	select MIPS_INIT_STACK_IN_SRAM
+	select SUPPORTS_CPU_MIPS32_R1
+	select SUPPORTS_LITTLE_ENDIAN
+	select SYS_RELOC_GD_ENV_ADDR
+	select SPL_INIT_STACK_WITHOUT_MALLOC_F if SPL
+	select SPL_LIBCOMMON_SUPPORT if SPL
+	select SPL_LIBGENERIC_SUPPORT if SPL
+	select SPL_LOADER_SUPPORT if SPL
+	imply CLK
+	imply CMD_DM
+	imply DM_GPIO
+	imply DM_MMC
+	imply DM_MTD
+	imply DM_SERIAL
+	imply FIT
+	imply MMC
+	imply MTD
+	imply MTD_RAW_NAND
+	imply PINCTRL
+	imply SPL
+	imply SYS_NS16550
+	imply SYSRESET
+	imply SYSRESET_WATCHDOG
+	imply TIMER
+	help
+	  Support for Ingenic JZ4730 family SoCs.
+
 config SOC_JZ4780
 	bool
 	select SUPPORTS_LITTLE_ENDIAN
@@ -21,6 +56,10 @@ config TARGET_JZ4780_CI20
 
 endchoice
 
+source "arch/mips/mach-jz47xx/jz4730/Kconfig"
+
+source "board/skytone/alpha400/Kconfig"
+
 source "board/imgtec/ci20/Kconfig"
 
 endmenu
diff --git a/arch/mips/mach-jz47xx/Makefile b/arch/mips/mach-jz47xx/Makefile
index dbb8229f785..9c57577440d 100644
--- a/arch/mips/mach-jz47xx/Makefile
+++ b/arch/mips/mach-jz47xx/Makefile
@@ -2,4 +2,6 @@
 
 extra-$(CONFIG_SPL_BUILD)	:= start.o
 
+obj-$(CONFIG_SOC_JZ4730)	+= jz4730/
+
 obj-$(CONFIG_SOC_JZ4780)	+= jz4780/
diff --git a/arch/mips/mach-jz47xx/jz4730/Kconfig b/arch/mips/mach-jz47xx/jz4730/Kconfig
new file mode 100644
index 00000000000..392903d208c
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4730/Kconfig
@@ -0,0 +1,87 @@
+if SOC_JZ4730
+
+config SYS_DCACHE_SIZE
+	default 16384
+
+config SYS_DCACHE_LINE_SIZE
+	default 32
+
+config SYS_ICACHE_SIZE
+	default 16384
+
+config SYS_ICACHE_LINE_SIZE
+	default 32
+
+config SYS_MALLOC_F_LEN
+	default 0x1000
+
+config SPL_SIZE_LIMIT
+	default 4096
+
+config MIPS_CACHE_SETUP
+	default n
+
+config MIPS_CACHE_DISABLE
+	default n
+
+config JZ4730_SDRAM_BANK_SIZE
+	int
+	help
+	  Megabytes per bank.
+
+config JZ4730_SDRAM_ROW
+	int
+	help
+	  Row address.
+
+config JZ4730_SDRAM_COL
+	int
+	help
+	  Column address.
+
+config JZ4730_SDRAM_BANKS_PER_CHIP
+	int
+	help
+	  Banks per chip.
+
+config JZ4730_SDRAM_WIDTH
+	int
+	help
+	  Data bus width.
+
+config JZ4730_SDRAM_CAS
+	int
+	help
+	  CAS latency: 2 or 3.
+
+config JZ4730_SDRAM_TRAS
+	int
+	help
+	  RAS# Active Time.
+
+config JZ4730_SDRAM_RCD
+	int
+	help
+	  RAS# to CAS# Delay.
+
+config JZ4730_SDRAM_TPC
+	int
+	help
+	  RAS# Precharge Time.
+
+config JZ4730_SDRAM_TRW
+	int
+	help
+	  Write Latency Time.
+
+config JZ4730_SDRAM_TREF
+	int
+	help
+	  Refresh period: 8192 refresh cycles/64ms.
+
+config JZ4730_SDRAM_CKS
+	int
+	help
+	  CKO Divider.
+
+endif
diff --git a/arch/mips/mach-jz47xx/jz4730/Makefile b/arch/mips/mach-jz47xx/jz4730/Makefile
new file mode 100644
index 00000000000..9a979fa0550
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4730/Makefile
@@ -0,0 +1,3 @@
+obj-y += lowlevel_init.o
+
+obj-$(CONFIG_SPL_BUILD) += spl.o
diff --git a/arch/mips/mach-jz47xx/jz4730/lowlevel_init.S b/arch/mips/mach-jz47xx/jz4730/lowlevel_init.S
new file mode 100644
index 00000000000..fa7bfe89a3c
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4730/lowlevel_init.S
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Lubomir Rintel <lkundrak at v3.sk>
+ *
+ * Derived from work that's Copyright (c) 2003
+ * Wolfgang Denk <wd at denx.de>
+ */
+
+#include <config.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/asm.h>
+
+LEAF(lowlevel_init)
+
+        /* Invalidate BTB */
+        mfc0    t0, CP0_CONFIG, 7
+        nop
+        ori     t0, 2
+        mtc0    t0, CP0_CONFIG, 7
+        nop
+
+        /*
+         * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1
+         */
+        li      t0, 0x0040FC04
+        mtc0    t0, CP0_STATUS
+
+        /* CAUSE register */
+        /* IV=1, use the specical interrupt vector (0x200) */
+        li      t1, 0x00800000
+        mtc0    t1, CP0_CAUSE
+
+        jr      ra
+         nop
+
+	END(lowlevel_init)
diff --git a/arch/mips/mach-jz47xx/jz4730/spl.c b/arch/mips/mach-jz47xx/jz4730/spl.c
new file mode 100644
index 00000000000..ea823e00f11
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4730/spl.c
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * JZ4730 Secondary Program Load.
+ *
+ * Copyright (C) 2020 Lubomir Rintel <lkundrak at v3.sk>
+ *
+ * Based on code that's (C) Copyright 2006
+ * Stefan Roese, DENX Software Engineering, sr at denx.de.
+ */
+
+#include <asm/io.h>
+#include <asm/sections.h>
+#include <common.h>
+#include <cpu_func.h>
+#include <hang.h>
+#include <init.h>
+#include <linux/bitops.h>
+#include <spl.h>
+
+#define C0_CONFIG7_BTBV			BIT(1)
+
+static void early_init(void)
+{
+	/*
+	 * Enable and clear the branch target buffer
+	 */
+	write_c0_config7(read_c0_config7() | C0_CONFIG7_BTBV);
+
+	/*
+	 * Clear the BSS
+	 */
+	memset(__bss_start, 0, (char *)&__bss_end - __bss_start);
+}
+
+#define EMC_BASE			(void __iomem *)0xb3010000
+#define EMC_BCR				0x00
+#define EMC_DMCR			0x80
+#define EMC_RTCSR			0x84
+#define EMC_RTCNT			0x88
+#define EMC_RTCOR			0x8c
+#define EMC_DMAR1			0x90
+#define EMC_DMAR2			0x94
+
+#define EMC_BCR_BRE			BIT(1)
+
+#define EMC_DMCR_BW_SHIFT		31
+#define EMC_DMCR_CA_SHIFT		26
+#define EMC_DMCR_RFSH			BIT(24)
+#define EMC_DMCR_MRSET			BIT(23)
+#define EMC_DMCR_RA_SHIFT		20
+#define EMC_DMCR_BA_SHIFT		19
+#define EMC_DMCR_EPIN			BIT(17)
+#define EMC_DMCR_TRAS_SHIFT		13
+#define EMC_DMCR_RCD_SHIFT		11
+#define EMC_DMCR_TPC_SHIFT		8
+#define EMC_DMCR_TRWL_SHIFT		5
+#define EMC_DMCR_TRC_SHIFT		2
+#define EMC_DMCR_TCL_SHIFT		0
+
+#define EMC_RTCSR_CKS_SHIFT		0
+
+#define EMC_SDMR_CAS_SHIFT		4
+#define EMC_SDMR_BL_SHIFT		0
+
+#define EMC_SDMR0			0xa000
+#define EMC_SDMR1			0xb000
+
+void sdram_init(void)
+{
+	register unsigned int dmcr, sdmode, tmp, ns;
+
+	/*
+	 * Enable SPLIT
+	 */
+	writel(EMC_BCR_BRE, EMC_BASE + EMC_BCR);
+
+	writew(0 << EMC_RTCSR_CKS_SHIFT, EMC_BASE + EMC_RTCSR);
+	writew(0, EMC_BASE + EMC_RTCOR);
+	writew(0, EMC_BASE + EMC_RTCNT);
+
+	/*
+	 * Megabytes per bank
+	 */
+	tmp = 0x20f0;
+	tmp |= CONFIG_JZ4730_SDRAM_BANK_SIZE / 2;
+	writel(tmp, EMC_BASE + EMC_DMAR1);
+	tmp |= (CONFIG_JZ4730_SDRAM_BANK_SIZE / 2) << 8;
+	writel(tmp, EMC_BASE + EMC_DMAR2);
+
+	/*
+	 * Basic DMCR register value
+	 */
+	dmcr = (CONFIG_JZ4730_SDRAM_ROW - 11) << EMC_DMCR_RA_SHIFT;
+	dmcr |= (CONFIG_JZ4730_SDRAM_ROW - 11) << EMC_DMCR_RA_SHIFT;
+	dmcr |= (CONFIG_JZ4730_SDRAM_COL - 8) << EMC_DMCR_CA_SHIFT;
+	dmcr |= (CONFIG_JZ4730_SDRAM_BANKS_PER_CHIP / 2 - 1) << EMC_DMCR_BA_SHIFT;
+	dmcr |= (CONFIG_JZ4730_SDRAM_WIDTH == 32 ? 0 : 1) << EMC_DMCR_BW_SHIFT;
+	dmcr |= EMC_DMCR_EPIN;
+	dmcr |= (CONFIG_JZ4730_SDRAM_CAS - 1) << EMC_DMCR_TCL_SHIFT;
+
+	/*
+	 * SDRAM timimg parameters
+	 */
+	ns = 1000000000 / (CONFIG_CPU_FREQ_HZ / 3);
+	tmp = CONFIG_JZ4730_SDRAM_TRAS / ns;
+	if (tmp < 4)
+		tmp = 4;
+	if (tmp > 11)
+		tmp = 11;
+	dmcr |= (tmp - 4) << EMC_DMCR_TRAS_SHIFT;
+	tmp = CONFIG_JZ4730_SDRAM_RCD / ns;
+	if (tmp > 3)
+		tmp = 3;
+	dmcr |= tmp << EMC_DMCR_RCD_SHIFT;
+	tmp = CONFIG_JZ4730_SDRAM_TPC / ns;
+	if (tmp > 7)
+		tmp = 7;
+	dmcr |= tmp << EMC_DMCR_TPC_SHIFT;
+	tmp = CONFIG_JZ4730_SDRAM_TRW / ns;
+	if (tmp > 3)
+		tmp = 3;
+	dmcr |= tmp << EMC_DMCR_TRWL_SHIFT;
+	tmp = (CONFIG_JZ4730_SDRAM_TRAS + CONFIG_JZ4730_SDRAM_TPC) / ns;
+	if (tmp > 14)
+		tmp = 14;
+	dmcr |= ((tmp + 1) >> 1) << EMC_DMCR_TRC_SHIFT;
+
+	/*
+	 * SDRAM mode values
+	 */
+	sdmode = (generic_ffs(4) - 1) << EMC_SDMR_BL_SHIFT;
+	sdmode |= CONFIG_JZ4730_SDRAM_CAS << EMC_SDMR_CAS_SHIFT;
+	sdmode <<= (CONFIG_JZ4730_SDRAM_WIDTH == 32) ? 2 : 1;
+
+	/*
+	 * Precharge phase
+	 */
+	writel(dmcr, EMC_BASE + EMC_DMCR);
+
+	/*
+	 * Set refresh registers
+	 */
+	tmp = CONFIG_JZ4730_SDRAM_TREF / ns;
+	tmp = tmp / 64 + 1;
+	if (tmp > 0xff)
+		tmp = 0xff;
+
+	writew(tmp, EMC_BASE + EMC_RTCOR);
+
+	/*
+	 * CKO Divisor
+	 */
+	switch (CONFIG_JZ4730_SDRAM_CKS) {
+	case 4:
+		writew(1 << EMC_RTCSR_CKS_SHIFT, EMC_BASE + EMC_RTCSR);
+		break;
+	case 16:
+		writew(2 << EMC_RTCSR_CKS_SHIFT, EMC_BASE + EMC_RTCSR);
+		break;
+	case 64:
+		writew(3 << EMC_RTCSR_CKS_SHIFT, EMC_BASE + EMC_RTCSR);
+		break;
+	case 256:
+		writew(4 << EMC_RTCSR_CKS_SHIFT, EMC_BASE + EMC_RTCSR);
+		break;
+	case 1024:
+		writew(5 << EMC_RTCSR_CKS_SHIFT, EMC_BASE + EMC_RTCSR);
+		break;
+	case 2048:
+		writew(6 << EMC_RTCSR_CKS_SHIFT, EMC_BASE + EMC_RTCSR);
+		break;
+	case 4096:
+		writew(7 << EMC_RTCSR_CKS_SHIFT, EMC_BASE + EMC_RTCSR);
+		break;
+	}
+
+	/*
+	 * Precharge all chip-selects
+	 */
+	writeb(0, EMC_BASE + (EMC_SDMR0 | sdmode));
+	writeb(0, EMC_BASE + (EMC_SDMR1 | sdmode));
+
+	/*
+	 * Wait for precharge, > 200us
+	 */
+	tmp = (CONFIG_CPU_FREQ_HZ / 1000000) * 200;
+	while (tmp--)
+		;
+
+	/*
+	 * Enable refresh and set SDRAM mode
+	 */
+	writel(dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET, EMC_BASE + EMC_DMCR);
+
+	/*
+	 * Write sdram mode register for each chip-select
+	 */
+	writeb(0, EMC_BASE + (EMC_SDMR0 | sdmode));
+	writeb(0, EMC_BASE + (EMC_SDMR1 | sdmode));
+}
+
+#define CPM_BASE			(void __iomem *)0xb0000000
+#define CPM_CFCR			0x00
+#define CPM_PLCR1			0x10
+
+#define CPM_CFCR_CCLK_PLL_SHIFT		0
+#define CPM_CFCR_HCLK_PLL_SHIFT		4
+#define CPM_CFCR_PCLK_PLL_SHIFT		8
+#define CPM_CFCR_LCD_PLL_SHIFT		12
+#define CPM_CFCR_MCLK_PLL_SHIFT		16
+#define CPM_CFCR_MCLK_COKEN1		BIT(22)
+#define CPM_CFCR_UHC_IN_SHIFT		25
+
+#define CPM_PLCR1_PLL_STABLE_TIME_SHIFT	0
+#define CPM_PLCR1_PLL_ENABLE		BIT(8)
+#define CPM_PLCR1_PLL_OD_SHIFT		16
+#define CPM_PLCR1_PLL_N_SHIFT		18
+#define CPM_PLCR1_PLL_M_SHIFT		23
+
+static void clock_init(void)
+{
+	u32 val;
+
+	/*
+	 * Clock divisors
+	 */
+	val = CPM_CFCR_MCLK_COKEN1;
+	val |= 0 << CPM_CFCR_CCLK_PLL_SHIFT;
+	val |= 2 << CPM_CFCR_HCLK_PLL_SHIFT;
+	val |= 2 << CPM_CFCR_PCLK_PLL_SHIFT;
+	val |= 2 << CPM_CFCR_LCD_PLL_SHIFT;
+	val |= 2 << CPM_CFCR_MCLK_PLL_SHIFT;
+	val |= (CONFIG_CPU_FREQ_HZ / 48000000 - 1) << CPM_CFCR_UHC_IN_SHIFT;
+	writel(val, CPM_BASE + CPM_CFCR);
+
+	/*
+	 * Main PLL
+	 */
+	val = (CONFIG_CPU_FREQ_HZ * 2 / CONFIG_SYS_CLK - 2) << CPM_PLCR1_PLL_M_SHIFT;
+	val |= 0 << CPM_PLCR1_PLL_N_SHIFT;
+	val |= 0 << CPM_PLCR1_PLL_OD_SHIFT;
+	val |= 0x20 << CPM_PLCR1_PLL_STABLE_TIME_SHIFT;
+	val |= CPM_PLCR1_PLL_ENABLE;
+	writel(val, CPM_BASE + CPM_PLCR1);
+}
+
+#define PINCTRL_BASE	(void __iomem *)0xb0010000
+#define PINCTRL_ALR(n)	(0x10 + (n) * 0x30)
+#define PINCTRL_AUR(n)	(0x14 + (n) * 0x30)
+
+static void pinmux_init(void)
+{
+	/*
+	 * NAND Read Enable function on GP79
+	 */
+	clrbits_32(PINCTRL_BASE + PINCTRL_ALR(2), 0xc0000000);
+	setbits_32(PINCTRL_BASE + PINCTRL_ALR(2), 0x40000000);
+
+	/*
+	 * NAND Write Enable on GP80, NAND Ready/Busy on GP81 and
+	 * SDRAM CS1 on GP82
+	 */
+	clrbits_32(PINCTRL_BASE + PINCTRL_AUR(2), 0x0000003f);
+	setbits_32(PINCTRL_BASE + PINCTRL_AUR(2), 0x00000015);
+
+	/*
+	 * UART0 RX/TX on GP126/GP127
+	 */
+	clrbits_32(PINCTRL_BASE + PINCTRL_AUR(3), 0xf0000000);
+	setbits_32(PINCTRL_BASE + PINCTRL_AUR(3), 0x50000000);
+}
+
+void __noreturn board_init_f(ulong dummy)
+{
+	early_init();
+
+	spl_init();
+
+	pinmux_init();
+
+	clock_init();
+
+	sdram_init();
+
+	board_init_r(NULL, 0);
+
+	hang();
+}
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_NAND;
+}
-- 
2.28.0



More information about the U-Boot mailing list