[RFC PATCH] mips: dts: add initial support for ls1c300 SoC

Sean Anderson seanga2 at gmail.com
Wed Apr 6 19:05:27 CEST 2022


On 4/6/22 5:22 AM, dhu at hodcarrier.org wrote:
> Hi, Sean,
> thank you for the comments, I have fix most issues and sent a v2 patch.
> 
>>   > See Techinical Reference Manual for details: https://www.loongson.cn/
>>   
>>   Can you provide a direct link please? I looked around a bit but I don't
>>   read Chinese and I was unable to figure out where to find more
>>   documentation on this CPU.
> I can't find direct link too, register is required to access this documents.

That's fine.

A link to the CPU repo https://github.com/trivialmips/nontrivial-mips would be nice.

>>   How does this boot? JTAG?
> use a flash programer and write the u-boot-with-spl.bin to the spi nor
> flash. or load the ELF file `u-boot' by the shipped bootloader via tftp.

Please add a binding for the SPI device at least (since that seems to be what
you are using).

>>   > +#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 */
>>   > +#define NAND_BASE	0xbfe78000
>>   > +#define START_FREQ	0xbfe78030
>>   > +#define CLK_DIV_PARAM	0xbfe78034
>>   > +
>>   > +/* SPI */
>>   > +#define SPI0_BASE	0xbfe80000
>>   > +
>>   > +/* SDRAM */
>>   > +#define	SD_CONFIG	0xbfd00000
>>   > +#define	SD_CONFIGL	0xbfd00410
>>   > +#define	SD_CONFIGH	0xbfd00414
>>   > +
>>   > +	.set noreorder
>>   > +
>>   > +/*	PLL: 264MHz	CPU: 132MHz	SDRAM: 66MHz	*/
>>   > +LEAF(ls1c300_pll_init)
>>   > +#ifndef CONFIG_SKIP_LOWLEVEL_INIT
>>   > +	li	t0, NAND_BASE
>>   > +	li	t2, 555844098
>>   > +	sw	t2, 0x34 (t0)
>>   > +
>>   > +	li	t1, 2147494924
>>   > +	sw	t1, 0x30 (t0)
>>   > +
>>   > +	ori	t2, 1
>>   > +	sw	t2, 0x34 (t0)
>>   > +#endif
>>   > +/* TODO: recalc rate to v0 */
>>   > +	li	v0, 132000000
>>   > +	jr	ra
>>   > +	  nop
>>   > +END(ls1c300_pll_init)
>>   
>>   Why does this need to be done in assembly? Ditto for the rest.
> this SoC don't have onchip sram to use for initial stack. assembly code
> prepare a working ram for C stack and heap use.
> stack is needed in C nested call and the heap is needed in lzma
> decompress.
> the spi runs at clock about 0.75MHz on reset, this is very slow,
> I tweat it to 33MHz.

Can you put this in a comment or in the commit message?

>>   
>>   > +
>>   > +/* SPI: Dual IO at 33MHz */
>>   > +LEAF(ls1c300_spi_init)
>>   > +#ifndef CONFIG_SKIP_LOWLEVEL_INIT
>>   > +	li	t0, SPI0_BASE
>>   > +	li	t1, 0x07
>>   > +	li	t2, 0x05
>>   > +	sb	t1, 0x4(t0)
>>   > +	sb	t1, 0x6(t0)
>>   > +#endif
>>   > +	jr	ra
>>   > +	  nop
>>   > +END(ls1c300_spi_init)
>>   > +
>>   > +/* SDRAM: 66MHz */
>>   > +// 8M x 16Bit x 4 Banks */
>>   > +// Organization | Row Address | Column Address
>>   > +// 32Mx16       | A0~A12      | A0-A9
>>   > +
>>   > +// 128Mx4       | A0~A12      | A0-A9, A11, A12
>>   > +// 64Mx8        | A0~A12      | A0-A9, A11
>>   > +// 32Mx16       | A0~A12      | A0-A9
>>   > +
>>   > +LEAF(ls1c300_sdram_init)
>>   > +#ifndef CONFIG_SKIP_LOWLEVEL_INIT
>>   > +	li	t0, SD_CONFIG
>>   > +	li	t1, 0x028A924A
>>   > +	li	t2, 0x00000028

Can you add some comments on which fields you have initialized here? This
is an area where other people may need to modify (because e.g. they have
a different sdram config).

>>   > +sdram_cfg:
>>   > +	sw	t1, 0x410(t0)
>>   > +	sw	t2, 0x414(t0)
>>   > +	nop
>>   > +	sw	t1, 0x410(t0)
>>   > +	sw	t2, 0x414(t0)
>>   > +	ori	t2, 0x200
>>   > +	sw	t1, 0x410(t0)
>>   > +	sw	t2, 0x414(t0)
>>   > +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
>>   > +	li	v0, SZ_64M
>>   > +	jr	ra
>>   > +	 nop
>>   > +END(ls1c300_sdram_init)
>>   > +
>>   > +
>>   > +/*
>>   > + *	SDRAM at 132MHzCPU at 297MHzSPI at 33MHz
>>   > + *	SDRAM at 100MHzCPU at 300MHzSPI at 50MHz
>>   > + *	SDRAM at 66MHzCPU at 132MHzSPI at 33MHz  <--
>>   > + */
>>   > +
>>   > +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 at 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/serial.c b/arch/mips/mach-lsmips/ls1c300/serial.c
>>   > new file mode 100644
>>   > index 0000000000..88bc18ef85
>>   > --- /dev/null
>>   > +++ b/arch/mips/mach-lsmips/ls1c300/serial.c
>>   > @@ -0,0 +1,112 @@
>>   > +// SPDX-License-Identifier: GPL-2.0
>>   > +/*
>>   > + * Copyright (C) 2020 MediaTek Inc.
>>   > + *
>>   > + * Author:  Gao Weijie <weijie.gao at mediatek.com>
>>   > + *
>>   > + * Copyright (C) 2020-2022 Du Huanpeng <dhu at hodcarrier.org>
>>   > + */
>>   > +
>>   > +#include <common.h>
>>   > +#include <asm/io.h>
>>   > +#include <mach/serial.h>
>>   > +#include <linux/kernel.h>
>>   > +#include "ls1c300.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)
>>   > +{
>>   > +#ifdef CONFIG_SPL_SERIAL
>>   > +	int pin_rx, pin_tx;
>>   > +	int afunc;
>>   > +
>>   > +	if (CONFIG_CONS_PIN_SELECT < ARRAY_SIZE(con)) {
>>   > +		pin_rx = con[CONFIG_CONS_PIN_SELECT].rx;
>>   > +		pin_tx = con[CONFIG_CONS_PIN_SELECT].tx;
>>   > +		afunc = con[CONFIG_CONS_PIN_SELECT].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 ;
>>   > +}
>>   
>>   Please use a pinctrl driver for this. In particular, you may be able to use
>>   pinctrl-simple, which can be configured through the device tree.
> this muxing is used in SPL at the very beginning. DM is not avaiable.

You can use DM in SPL. How much space do you have in your flash? More than 64-128k
is enough to use SPL_DM. More than 512k is enough to skip SPL entirely. Presumably
since you are using the combined SPL/U-Boot image you have enough space to skip it.

>>   
>>   > 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.gao at mediatek.com>
>>   > + *
>>   > + * Copyright (C) 2022 Du Huanpeng <dhu at 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/board/loongson/ls1c300-eval/Kconfig b/board/loongson/ls1c300-eval/Kconfig
>>   > new file mode 100644
>>   > index 0000000000..e427570a83
>>   > --- /dev/null
>>   > +++ b/board/loongson/ls1c300-eval/Kconfig
>>   > @@ -0,0 +1,12 @@
>>   > +if BOARD_LS1C300
>>   > +
>>   > +config SYS_BOARD
>>   > +	default "ls1c300-eval"
>>   > +
>>   > +config SYS_VENDOR
>>   > +	default "loongson"
>>   > +
>>   > +config SYS_CONFIG_NAME
>>   > +	default "ls1c300"
>>   > +
>>   > +endif
>>   > diff --git a/board/loongson/ls1c300-eval/MAINTAINERS b/board/loongson/ls1c300-eval/MAINTAINERS
>>   > new file mode 100644
>>   > index 0000000000..5420198dab
>>   > --- /dev/null
>>   > +++ b/board/loongson/ls1c300-eval/MAINTAINERS
>>   > @@ -0,0 +1,7 @@
>>   > +LS1C300_EVAL BOARD
>>   > +M:	Du Huanpeng<dhu at hodcarrier.org>
>>   > +S:	Maintained
>>   > +F:	board/loongson/ls1c300-eval
>>   > +F:	include/configs/ls1c300.h
>>   > +F:	configs/ls1c300_defconfig
>>   > +F:	arch/mips/dts/ls1c300-eval.dts
>>   > diff --git a/board/loongson/ls1c300-eval/Makefile b/board/loongson/ls1c300-eval/Makefile
>>   > new file mode 100644
>>   > index 0000000000..db129c5aba
>>   > --- /dev/null
>>   > +++ b/board/loongson/ls1c300-eval/Makefile
>>   > @@ -0,0 +1,3 @@
>>   > +# SPDX-License-Identifier: GPL-2.0
>>   > +
>>   > +obj-y += board.o
>>   > diff --git a/board/loongson/ls1c300-eval/board.c b/board/loongson/ls1c300-eval/board.c
>>   > new file mode 100644
>>   > index 0000000000..2f588a0dcb
>>   > --- /dev/null
>>   > +++ b/board/loongson/ls1c300-eval/board.c
>>   > @@ -0,0 +1,20 @@
>>   > +// SPDX-License-Identifier: GPL-2.0
>>   > +/*
>>   > + * Copyright (C) 2020-2022 Du Huanpeng <dhu at hodcarrier.org>
>>   > + */
>>   > +
>>   > +#include <common.h>
>>   > +#include <mach/serial.h>
>>   > +
>>   > +#ifdef CONFIG_DEBUG_UART_BOARD_INIT
>>   > +
>>   > +#define UART2_RX	36
>>   > +#define UART2_TX	37
>>   > +#define AFUNC		2
>>   > +
>>   > +void board_debug_uart_init(void)
>>   > +{
>>   > +	gpio_set_alternate(UART2_TX, AFUNC);
>>   > +	gpio_set_alternate(UART2_RX, AFUNC);
>>   > +}
>>   > +#endif
>>   > diff --git a/configs/ls1c300_defconfig b/configs/ls1c300_defconfig
>>   > new file mode 100644
>>   > index 0000000000..c47fe5b98f
>>   > --- /dev/null
>>   > +++ b/configs/ls1c300_defconfig
>>   > @@ -0,0 +1,65 @@
>>   > +CONFIG_MIPS=y
>>   > +CONFIG_SYS_MALLOC_F_LEN=0x40000
>>   > +CONFIG_SPL_LIBCOMMON_SUPPORT=y
>>   > +CONFIG_SPL_LIBGENERIC_SUPPORT=y
>>   > +CONFIG_NR_DRAM_BANKS=1
>>   > +CONFIG_ENV_SIZE=0x1000
>>   > +CONFIG_ENV_OFFSET=0x30000
>>   > +CONFIG_ENV_SECT_SIZE=0x10000
>>   > +CONFIG_DEFAULT_DEVICE_TREE="ls1c300-eval"
>>   > +CONFIG_SPL_SERIAL=y
>>   > +CONFIG_SPL_SIZE_LIMIT=0x100000
>>   > +CONFIG_SPL=y
>>   > +CONFIG_DEBUG_UART_BOARD_INIT=y
>>   > +CONFIG_DEBUG_UART_BASE=0xbfe48000
>>   > +CONFIG_DEBUG_UART_CLOCK=66000000
>>   
>>   Do you have normal uart working?
> the normal uart works with  ns16550 uart driver. so no extra serial driver for this SoC.

Typically the debug uart should be disabled in the defconfig. Just document the parameters.

>>   
>>   > +CONFIG_ARCH_LSMIPS=y
>>   > +CONFIG_SPL_PAYLOAD="u-boot.img"
>>   > +# CONFIG_MIPS_CACHE_SETUP is not set
>>   > +# CONFIG_MIPS_CACHE_DISABLE is not set
>>   > +CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y
>>   > +CONFIG_MIPS_BOOT_FDT=y
>>   > +CONFIG_DEBUG_UART=y
>>   > +CONFIG_SYS_LOAD_ADDR=0x80010000
>>   > +CONFIG_FIT=y
>>   > +# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
>>   > +CONFIG_LOGLEVEL=9
>>   > +CONFIG_DISPLAY_BOARDINFO_LATE=y
>>   > +CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK=y
>>   > +CONFIG_SPL_SYS_MALLOC_SIMPLE=y
>>   > +CONFIG_SPL_NOR_SUPPORT=y
>>   > +# CONFIG_CMD_ELF is not set
>>   > +# CONFIG_CMD_XIMG is not set
>>   > +# CONFIG_CMD_CRC32 is not set
>>   > +CONFIG_CMD_CLK=y
>>   > +# CONFIG_CMD_DM is not set
>>   > +CONFIG_CMD_GPIO=y
>>   > +# CONFIG_CMD_LOADS is not set
>>   > +CONFIG_CMD_SPI=y
>>   > +CONFIG_CMD_WDT=y
>>   > +# CONFIG_PARTITIONS is not set
>>   > +CONFIG_OF_EMBED=y
>>   > +CONFIG_ENV_IS_IN_SPI_FLASH=y
>>   
>>   Where is the spi flash driver?
> TODO :).
> 
>>   > +static int lsmips_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
>>   > +{
>>   > +	struct lsmips_wdt_priv *priv = dev_get_priv(dev);
>>   > +	unsigned int timeout;
>>   > +
>>   > +	timeout = U32_MAX / (priv->clock / 1000);
>>   > +
>>   > +	if (timeout < timeout_ms)
>>   > +		timeout = U32_MAX;
>>   > +	else
>>   > +		timeout = timeout_ms * (priv->clock / 1000);
>>   
>>   why not start with this?
>>   
>>   Also, please multiply first for better precision. And use MSEC_PER_SEC instead of 1000.
> I want to avoid overflow first, so I do the division first.
> the macro MSEC_PER_SEC seems not defined in public header, I find it is
> private defined in multiple place, so I don't want to use this macro
> this time.

Define it. Make the code better.

>>   > +#ifndef __DT_BINDINGS_LS1C300_CLK_H__
>>   > +#define __DT_BINDINGS_LS1C300_CLK_H__
>>   > +
>>   > +/* Base clocks */
>>   > +#define CLK_XTAL	0
>>   > +#define CLK_PLL		1
>>   > +#define CLK_CPU		2
>>   > +#define CLK_CPU_THROT	7
>>   > +#define CLK_SDRAM	3
>>   > +
>>   > +#define CLK_CAMERA	4
>>   > +#define CLK_DC		5
>>   > +#define CLK_PIX		5
>>   > +#define CLK_AXIMUX	6
>>   > +
>>   > +/* Peripheral clocks */
>>   > +#define CLK_UART0	3
>>   > +#define CLK_UART1	3
>>   > +#define CLK_UART2	3
>>   > +#define CLK_UART3	3
>>   > +#define CLK_UART4	3
>>   > +#define CLK_UART5	3
>>   > +#define CLK_UART6	3
>>   > +#define CLK_UART7	3
>>   > +#define CLK_UART8	3
>>   > +#define CLK_UART9	3
>>   > +#define CLK_UART10	3
>>   > +#define CLK_UART11	3
>>   > +#define CLK_CAN0	3
>>   > +#define CLK_CAN1	3
>>   > +#define CLK_I2C0	3
>>   > +#define CLK_PWM		3
>>   > +#define CLK_I2S		3
>>   > +#define CLK_RTC		3
>>   > +#define CLK_I2C1	3
>>   > +#define CLK_SDIO	3
>>   > +#define CLK_I2C2	3
>>   > +#define CLK_ADC		3
>>   > +#define CLK_NAND	3
>>   > +
>>   > +#define CLK_WDT		3
>>   
>>   So are these different clocks? Why do they all have the same id?
> they are all the same clock, the apb bus clock.

OK, then just define CLK_APB to 3. Adding a prefix like LS1C300_CLK_APB
would be nice.

--Sean



More information about the U-Boot mailing list