- pinmux setup functions for debug uart - lowlevel initialization: sdram, pll, spi, debug uart
note that, this SoC have NO useable ram after reset, do not use nested call when doing lowlevel_init. Signed-off-by: Du Huanpeng <d...@hodcarrier.org> --- arch/mips/mach-lsmips/cpu.c | 19 +++ arch/mips/mach-lsmips/include/mach/serial.h | 16 +++ arch/mips/mach-lsmips/ls1c300/gpio.c | 66 +++++++++ arch/mips/mach-lsmips/ls1c300/init.c | 62 ++++++++ arch/mips/mach-lsmips/ls1c300/lowlevel_init.S | 135 ++++++++++++++++++ arch/mips/mach-lsmips/ls1c300/sdram.S | 96 +++++++++++++ arch/mips/mach-lsmips/ls1c300/serial.c | 109 ++++++++++++++ arch/mips/mach-lsmips/spl.c | 47 ++++++ include/configs/ls1c300.h | 34 +++++ 9 files changed, 584 insertions(+) create mode 100644 arch/mips/mach-lsmips/cpu.c create mode 100644 arch/mips/mach-lsmips/include/mach/serial.h create mode 100644 arch/mips/mach-lsmips/ls1c300/gpio.c create mode 100644 arch/mips/mach-lsmips/ls1c300/init.c create mode 100644 arch/mips/mach-lsmips/ls1c300/lowlevel_init.S create mode 100644 arch/mips/mach-lsmips/ls1c300/sdram.S create mode 100644 arch/mips/mach-lsmips/ls1c300/serial.c create mode 100644 arch/mips/mach-lsmips/spl.c create mode 100644 include/configs/ls1c300.h diff --git a/arch/mips/mach-lsmips/cpu.c b/arch/mips/mach-lsmips/cpu.c new file mode 100644 index 0000000000..339088b435 --- /dev/null +++ b/arch/mips/mach-lsmips/cpu.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Stefan Roese <s...@denx.de> + */ + +#include <common.h> +#include <init.h> +#include <malloc.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <linux/sizes.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + gd->ram_size = get_ram_size((void *)CFG_SYS_SDRAM_BASE, SZ_256M); + return 0; +} diff --git a/arch/mips/mach-lsmips/include/mach/serial.h b/arch/mips/mach-lsmips/include/mach/serial.h new file mode 100644 index 0000000000..4da1cb434c --- /dev/null +++ b/arch/mips/mach-lsmips/include/mach/serial.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 MediaTek Inc. + * + * Author: Gao Weijie <weijie....@mediatek.com> + * + * Copyright (C) 2022 Du Huanpeng <d...@hodcarrier.org> + */ + +#ifndef __LSMIPS_SERIAL_H_ +#define __LSMIPS_SERIAL_H_ + +void lsmips_spl_serial_init(void); +int gpio_set_alternate(int gpio, int func); + +#endif /* __LSMIPS_SERIAL_H_ */ diff --git a/arch/mips/mach-lsmips/ls1c300/gpio.c b/arch/mips/mach-lsmips/ls1c300/gpio.c new file mode 100644 index 0000000000..2195738b2b --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/gpio.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Du Huanpeng <d...@hodcarrier.org> + */ + +#include <linux/errno.h> +#include <asm/bitops.h> + +#define CBUS_FIRST0 0xbfd011c0 +#define CBUS_SECOND0 0xbfd011d0 +#define CBUS_THIRD0 0xbfd011e0 +#define CBUS_FOURTHT0 0xbfd011f0 +#define CBUS_FIFTHT0 0xbfd01200 + +#define CBUS_FIRST1 0xbfd011c4 +#define CBUS_SECOND1 0xbfd011d4 +#define CBUS_THIRD1 0xbfd011e4 +#define CBUS_FOURTHT1 0xbfd011f4 +#define CBUS_FIFTHT1 0xbfd01204 + +#define CBUS_FIRST2 0xbfd011c8 +#define CBUS_SECOND2 0xbfd011d8 +#define CBUS_THIRD2 0xbfd011e8 +#define CBUS_FOURTHT2 0xbfd011f8 +#define CBUS_FIFTHT2 0xbfd01208 + +#define CBUS_FIRST3 0xbfd011cc +#define CBUS_SECOND3 0xbfd011dc +#define CBUS_THIRD3 0xbfd011ec +#define CBUS_FOURTHT3 0xbfd011fc +#define CBUS_FIFTHT3 0xbfd0120c + +/* + * pinmux for debug uart and spl only, for others, please + * use a pinctrl driver and device-tree for pin muxing. + * + * @gpio: gpio number + * @func: alternate function 1 to 5, 0 for GPIO. + */ + +int gpio_set_alternate(int gpio, int func) +{ + volatile void __iomem *addr; + int i; + + if (gpio < 0 || gpio > 104) + return -ENODEV; + if (func < 0 || func > 5) + return -EINVAL; + + if (func) { + i = func - 1; + addr = (void *)CBUS_FIRST0 + i * 16; + set_bit(gpio, addr); + } else { + /* GPIO, clear CBUS 1 ~ 5 */ + i = 5; + } + + while (i--) { + addr = (void *)CBUS_FIRST0 + 16 * i; + clear_bit(gpio, addr); + } + + return 0; +} diff --git a/arch/mips/mach-lsmips/ls1c300/init.c b/arch/mips/mach-lsmips/ls1c300/init.c new file mode 100644 index 0000000000..0d5576fddf --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/init.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 MediaTek Inc. + * + * Author: Gao Weijie <weijie....@mediatek.com> + * + * based on: arch/mips/mach-mtmips/mt7628/init.c + * Copyright (C) 2020-2022 Du Huanpeng <d...@hodcarrier.org> + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <dm/uclass.h> +#include <dt-bindings/clock/ls1c300-clk.h> +#include <linux/io.h> +#include <linux/sizes.h> + +DECLARE_GLOBAL_DATA_PTR; + +int print_cpuinfo(void) +{ + struct udevice *udev; + struct clk clk; + int ret; + ulong xtal; + char buf[SZ_32]; + + printf("CPU: Loongson ls1c300b\n"); + + ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(ls1c300_clk), &udev); + if (ret) { + printf("error: clock driver not found.\n"); + return 0; + } + + clk.dev = udev; + + ret = clk_request(udev, &clk); + if (ret < 0) + return ret; + + clk.id = CLK_XTAL; + xtal = clk_get_rate(&clk); + + clk.id = CLK_CPU_THROT; + gd->cpu_clk = clk_get_rate(&clk); + + clk.id = CLK_APB; + gd->mem_clk = clk_get_rate(&clk); + + printf("Clock: CPU: %sMHz, ", strmhz(buf, gd->cpu_clk)); + printf("SDRAM: %sMHz, ", strmhz(buf, gd->mem_clk)); + printf("XTAL: %sMHz\n", strmhz(buf, xtal)); + + return 0; +} + +ulong notrace get_tbclk(void) +{ + return gd->cpu_clk / 2; +} diff --git a/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S new file mode 100644 index 0000000000..4b453df621 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 MediaTek Inc. + * + * Author: Gao Weijie <weijie....@mediatek.com> + * + * Copyright (C) 2020-2023 Du Huanpeng <d...@hodcarrier.org> + */ + +#include <config.h> +#include <asm-offsets.h> +#include <asm/cacheops.h> +#include <asm/regdef.h> +#include <asm/mipsregs.h> +#include <asm/addrspace.h> +#include <asm/asm.h> +#include <linux/sizes.h> + +/* PLL control register */ +#define NAND_BASE 0xbfe70000 +#define START_FREQ 0x8030 +#define CLK_DIV_PARAM 0x8034 +#define CPU_THROT 0xc010 + +/* START_FREQ */ +#define PLL_VALID 31 +#define Reserved_24 24 +#define FRAC_N 16 +#define M_PLL 8 +#define Reserved_4 4 +#define RST_TIME 2 +#define SDRAM_DIV 0 + #define SDRAM_DIV2 0 + #define SDRAM_DIV4 1 + #define SDRAM_DIV3 2 + +/* CLK_DIV_PARAM */ +#define PIX_DIV 24 +#define CAM_DIV 16 +#define CPU_DIV 8 +#define PIX_DIV_VALID 5 +#define PIX_SEL 4 +#define CAM_DIV_VALID 3 +#define CAM_SEL 2 +#define CPU_DIV_VALID 1 +#define CPU_SEL 0 + +/* Document: + * Freq_PLL = XIN *(M_PLL + FRAC_N)/4 + */ +#define XIN 24000000 +#define PLL_VALID_1 (1<<PLL_VALID) +#define PREP_M_PLL(Freq_PLL) (((Freq_PLL * 4) / XIN) << M_PLL) +#define PREP_SDRAM_DIV(div) (div<<SDRAM_DIV) +#define PREP_CPU_DIV(div1) ((0x80|div1)<<CPU_DIV | (div1&&div1)<<CPU_DIV_VALID) +#define PREP_PIX_DIV(div2) (div2<<PIX_DIV) +#define PREP_CAM_DIV(div3) (div3<<CAM_DIV) + +/* PLL @264MHz, CPU @132MHz, SDRAM @66MHz */ +#define CFG_START_FREQ (PLL_VALID_1 | PREP_M_PLL(264000000) | SDRAM_DIV2) +#define CFG_CLK_DIV_PARAM (PREP_CPU_DIV(2) | PREP_PIX_DIV(0x24) | PREP_CAM_DIV(0x24)) +#define CFG_CPU_THROT 15 + +/* SPI0 control register */ +#define SPI0_BASE 0xbfe80000 +#define SPCR 0 +#define SPSR 1 +#define TxFIFO 2 +#define RxFIFO 2 +#define SPER 3 +#define SFC_PARAM 4 + #define CLK_DIV 4 + #define DUAL_IO 3 + #define FAST_READ 2 + #define BURST_EN 1 + #define MEMORY_EN 0 +#define SFC_SOFTCS 5 +#define SFC_TIMING 6 + #define T_FAST 2 + #define T_CSH 0 + + .set noreorder +LEAF(ls1c300_pll_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT) + li t0, NAND_BASE + li t1, CFG_START_FREQ + li t2, CFG_CLK_DIV_PARAM + li t3, CFG_CPU_THROT + + sw t3, CPU_THROT (t0) + sw t2, CLK_DIV_PARAM (t0) + sw t1, START_FREQ (t0) + + ori t2, 1<<CPU_SEL + sw t2, CLK_DIV_PARAM (t0) +#endif + li v0, 264000000 + jr ra + nop +END(ls1c300_pll_init) + +LEAF(ls1c300_spi_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT) + li t0, SPI0_BASE + li t1, (1<<MEMORY_EN) | (1<<BURST_EN) | (1<<FAST_READ) | (1<<DUAL_IO) + sb t1, SFC_PARAM (t0) + li t2, (1<<T_FAST) | (1<<T_CSH) + sb t2, SFC_TIMING (t0) +#endif + jr ra + nop +END(ls1c300_spi_init) + +NESTED(lowlevel_init, 0, ra) + /* Save ra and do real lowlevel initialization */ + move s0, ra + /* Setup PLL @264MHz */ + PTR_LA t9, ls1c300_pll_init + jalr t9 + nop + + /* Setup SPI Dual IO@33MHz */ + PTR_LA t9, ls1c300_spi_init + jalr t9 + nop + + /* Setup external SDRAM @66MHz */ + PTR_LA t9, ls1c300_sdram_init + jalr t9 + nop + + move ra, s0 + jr ra + nop +END(lowlevel_init) diff --git a/arch/mips/mach-lsmips/ls1c300/sdram.S b/arch/mips/mach-lsmips/ls1c300/sdram.S new file mode 100644 index 0000000000..4797b1d8a2 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/sdram.S @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020-2022 Du Huanpeng <d...@hodcarrier.org> + */ + +#include <config.h> +#include <asm-offsets.h> +#include <asm/cacheops.h> +#include <asm/regdef.h> +#include <asm/mipsregs.h> +#include <asm/addrspace.h> +#include <asm/asm.h> +#include <linux/sizes.h> + +/* sdram control 64 bit register */ +#define SD_CONFIG 0xbfd00000 +#define SD_CONFIGHI 0x414 +#define SD_CONFIGLO 0x410 + +#define CONFIG_VALID 41 +#define HANG_UP 40 +#define DEF_SEL 39 +#define TWR 37 +#define TREF 25 +#define TRAS 21 +#define TRFC 17 +#define TRP 14 +#define TCL 11 +#define TRCD 8 + +#define SD_BIT 6 + #define SD_8BIT (0<<SD_BIT) + #define SD_16BIT (1<<SD_BIT) + #define SD_32BIT (2<<SD_BIT) +#define SD_CSIZE 3 + #define SD_CSIZE_512 (0<<SD_CSIZE) + #define SD_CSIZE_1K (1<<SD_CSIZE) + #define SD_CSIZE_2K (2<<SD_CSIZE) + #define SD_CSIZE_4K (3<<SD_CSIZE) + #define SD_CSIZE_256 (7<<SD_CSIZE) +#define SD_RSIZE 0 + #define SD_RSIZE_2K (0<<SD_RSIZE) + #define SD_RSIZE_4K (1<<SD_RSIZE) + #define SD_RSIZE_8K (2<<SD_RSIZE) + #define SD_RSIZE_16K (3<<SD_RSIZE) + +#define SD_CFG_1(tWR, tREF, tRAS, tRFC, tRP, tCL, tRCD) \ + ((tWR<<TWR)|(tREF<<TREF)|(tRAS<<TRAS)|(tRFC<<TRFC)|(tRP<<TRP)|(tCL<<TCL)|(tRCD<<TRCD)) +#define CFG_SD_0(b, c, r) \ + ((b<<SD_BIT)|(c<<SD_CSIZE)|(r<<SD_RSIZE)) +/* + * recommended values by ls1c300 user manual, + * tweak to fit your board. + */ +#define SD_CONFIG_133MHz SD_CFG_1(2, 0x818, 6, 8, 3, 3, 3) +#define SD_CONFIG_100MHz SD_CFG_1(2, 0x620, 5, 6, 2, 3, 2) +#define SD_CONFIG_75MHz SD_CFG_1(1, 0x494, 4, 5, 2, 2, 2) +#define SD_CONFIG_33MHz SD_CFG_1(1, 0x204, 2, 2, 1, 2, 1) + +#define SD_CONFIG_66MHz SD_CFG_1(1, 0x401, 4, 4, 2, 2, 2) + +#define SD_CONFIG64 (SD_CONFIG_66MHz | SD_16BIT | SD_CSIZE_1K | SD_RSIZE_8K) +#define CFG_SDCONFIGHI (SD_CONFIG64 /(1<<32)) +#define CFG_SDCONFIGLO (SD_CONFIG64 %(1<<32)) + + .set noreorder +/* + * Loongson ls1c300 SoC do not have onchip sram for initial stack, + * initialize the external sdram on reset as early as possiable. + */ +LEAF(ls1c300_sdram_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT) + li t0, SD_CONFIG + li t1, CFG_SDCONFIGLO + li t2, CFG_SDCONFIGHI + +/* store twice as the hardware manual required. */ + sw t1, SD_CONFIGLO (t0) + sw t2, SD_CONFIGHI (t0) + sync + + sw t1, SD_CONFIGLO (t0) + sw t2, SD_CONFIGHI (t0) + sync + + ori t2, 1<<(CONFIG_VALID-32) + sw t1, SD_CONFIGLO (t0) + sw t2, SD_CONFIGHI (t0) + sync +#endif + li v0, SZ_64M + jr ra + nop +END(ls1c300_sdram_init) + + diff --git a/arch/mips/mach-lsmips/ls1c300/serial.c b/arch/mips/mach-lsmips/ls1c300/serial.c new file mode 100644 index 0000000000..93fd653385 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/serial.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 MediaTek Inc. + * + * Author: Gao Weijie <weijie....@mediatek.com> + * + * Copyright (C) 2020-2022 Du Huanpeng <d...@hodcarrier.org> + */ + +#include <mach/serial.h> +#include <linux/kernel.h> + +struct uart_pin_config { + char port; + char af; + char rx; + char tx; +}; + +struct uart_pin_config con[] = { +#if CONFIG_CONS_INDEX == 0 + { 0, 2, 74, 75 }, + { 0, 3, 23, 24 }, + { 0, 3, 99, 100 }, + +#elif CONFIG_CONS_INDEX == 1 + { 1, 1, 17, 18 }, + { 1, 1, 101, 102 }, + { 1, 2, 40, 41 }, + { 1, 4, 2, 3 }, + +#elif CONFIG_CONS_INDEX == 2 + { 2, 2, 36, 37 }, + { 2, 2, 42, 43 }, + { 2, 3, 27, 28 }, + { 2, 3, 103, 104 }, + { 2, 4, 4, 5 }, + +#elif CONFIG_CONS_INDEX == 3 + { 3, 2, 17, 18 }, + { 3, 2, 33, 34 }, + { 3, 2, 44, 45 }, + { 3, 4, 0, 1 }, + +#elif CONFIG_CONS_INDEX == 4 + { 4, 5, 23, 24 }, + { 4, 5, 58, 59 }, + { 4, 5, 80, 79 }, + +#elif CONFIG_CONS_INDEX == 5 + { 5, 5, 25, 26 }, + { 5, 5, 60, 61 }, + { 5, 5, 81, 78 }, + +#elif CONFIG_CONS_INDEX == 6 + { 6, 5, 27, 46 }, + { 6, 5, 62, 63 }, + +#elif CONFIG_CONS_INDEX == 7 + { 7, 5, 57, 56 }, + { 7, 5, 64, 65 }, + { 7, 5, 87, 88 }, + +#elif CONFIG_CONS_INDEX == 8 + { 8, 5, 55, 54 }, + { 8, 5, 66, 67 }, + { 8, 5, 89, 90 }, + +#elif CONFIG_CONS_INDEX == 9 + { 9, 5, 53, 52 }, + { 9, 5, 68, 69 }, + { 9, 5, 85, 86 }, + +#elif CONFIG_CONS_INDEX == 10 + { 10, 5, 51, 50 }, + { 10, 5, 70, 71 }, + { 10, 5, 84, 82 }, + +#elif CONFIG_CONS_INDEX == 11 + { 11, 5, 49, 48 }, + { 11, 5, 72, 73 }, +#endif /* CONFIG_CONS_INDEX */ +}; + +#define UART2_RX 36 +#define UART2_TX 37 +#define AFUNC 2 + +void lsmips_spl_serial_init(void) +{ +#if defined(CONFIG_SPL_SERIAL) + int pin_rx, pin_tx; + int afunc; + + if (CONFIG_CONS_PIN < ARRAY_SIZE(con)) { + pin_rx = con[CONFIG_CONS_PIN].rx; + pin_tx = con[CONFIG_CONS_PIN].tx; + afunc = con[CONFIG_CONS_PIN].af; + } else { + pin_rx = UART2_RX; + pin_tx = UART2_TX; + afunc = AFUNC; + } + + gpio_set_alternate(pin_rx, afunc); + gpio_set_alternate(pin_tx, afunc); +#endif /* CONFIG_SPL_SERIAL */ + return; +} diff --git a/arch/mips/mach-lsmips/spl.c b/arch/mips/mach-lsmips/spl.c new file mode 100644 index 0000000000..c7c28989f2 --- /dev/null +++ b/arch/mips/mach-lsmips/spl.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. + * + * Author: Gao Weijie <weijie....@mediatek.com> + * + * Copyright (C) 2022 Du Huanpeng <d...@hodcarrier.org> + */ + +#include <common.h> +#include <init.h> +#include <spl.h> +#include <asm/sections.h> +#include <linux/libfdt.h> +#include <linux/sizes.h> +#include <mach/serial.h> + +void __noreturn board_init_f(ulong dummy) +{ + spl_init(); + +#ifdef CONFIG_SPL_SERIAL + /* + * lsmips_spl_serial_init() is useful if debug uart is enabled, + * or DM based serial is not enabled. + */ + lsmips_spl_serial_init(); + preloader_console_init(); +#endif + + board_init_r(NULL, 0); +} + +void board_boot_order(u32 *spl_boot_list) +{ + spl_boot_list[0] = BOOT_DEVICE_NOR; +} + +unsigned long spl_nor_get_uboot_base(void) +{ + void *uboot_base = __image_copy_end; + + if (fdt_magic(uboot_base) == FDT_MAGIC) + return (unsigned long)uboot_base + fdt_totalsize(uboot_base); + + return (unsigned long)uboot_base; +} diff --git a/include/configs/ls1c300.h b/include/configs/ls1c300.h new file mode 100644 index 0000000000..4d07b07759 --- /dev/null +++ b/include/configs/ls1c300.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 MediaTek Inc. + * + * Author: Gao Weijie <weijie....@mediatek.com> + * based on: include/configs/mt7628.h + * Copyright (C) 2022-2023 Du Huanpeng <d...@hodcarrier.org> + */ + +#ifndef __CONFIG_LS1C300_H__ +#define __CONFIG_LS1C300_H__ + +#define CFG_SYS_SDRAM_BASE 0x80000000 +#define CFG_SYS_INIT_SP_OFFSET 0x2000 + +/* Serial SPL */ +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL) +#define CFG_SYS_NS16550_CLK 66000000 +#define CFG_SYS_NS16550_COM1 0xbfe44000 +#define CFG_SYS_NS16550_COM2 0xbfe48000 +#define CFG_SYS_NS16550_COM3 0xbfe4c000 +#define CFG_SYS_NS16550_COM4 0xbfe4c400 +#define CFG_SYS_NS16550_COM5 0xbfe4c500 +#define CFG_SYS_NS16550_COM6 0xbfe4c600 +#endif + +/* Serial common */ +#define CFG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 } + +/* SPL */ +#define CFG_MALLOC_F_ADDR 0x80100000 /* FIXME: find a proper place */ +#define CFG_SYS_UBOOT_BASE 0xbd000000 + +#endif /* __CONFIG_LS1C300_H__ */ -- 2.34.1