From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lubomir Rintel Date: Tue, 17 Nov 2020 22:00:16 +0100 Subject: [PATCH RFC 18/20] mips/mach-jz47xx: Add Ingenic JZ4730 support In-Reply-To: <20201117210018.751469-1-lkundrak@v3.sk> References: <20201117210018.751469-1-lkundrak@v3.sk> Message-ID: <20201117210018.751469-19-lkundrak@v3.sk> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 --- 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 + * + * Derived from work that's Copyright (c) 2003 + * Wolfgang Denk + */ + +#include +#include +#include +#include + +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 + * + * Based on code that's (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr at denx.de. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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