[U-Boot] [PATCH 2/6] MSCC: add support for VCoreIII SoCs
Gregory CLEMENT
gregory.clement at bootlin.com
Thu Sep 27 10:14:14 UTC 2018
Hi Daniel,
First thanks for you prompt review, it is much appreciate. :)
This week I am at kernel recipes conference, so I won't be able to fully
address your comments but I will do it next week.
However, here are some answers:
On mer., sept. 26 2018, Daniel Schwierzeck <daniel.schwierzeck at gmail.com> wrote:
> Hi Gregory,
>
> On 25.09.2018 15:01, Gregory CLEMENT wrote:
>> These families of SoCs are found in the Microsemi Switches solution.
>>
>> Currently the support for two families support is added:
>> - Ocelot (VSC7513, VSC7514) already supported in Linux
>> - Luton (Luton10: VSC7423, VSC7424, VSC7428 and Luton26: VSC7425,
>> VSC7426, VSC7426, VSC7427, VSC7429)
>
> Is this some polished version of the original vendor U-Boot?
No the original vendor version was RedBoot
> Could you maybe add Ocelot and Luton in separate patches?
Yes sure the intent to have a uniq patch was to justify the common code
between both SoC.
>
>>
>> Signed-off-by: Gregory CLEMENT <gregory.clement at bootlin.com>
>> ---
[..]
>> +endif
>
> from the code below I assume you have a MIPS24k core? If so you should
> use the automatic cache size detection
Yes it is a MIPS24k core. I will have a look on the automatic cache size
detection.
>
>> +
>> +menu "MSCC VCore-III platforms"
>> + depends on ARCH_MSCC
>> +
>> +config SOC_VCOREIII
>> + select SUPPORTS_LITTLE_ENDIAN
>> + select SUPPORTS_BIG_ENDIAN
>> + select SUPPORTS_CPU_MIPS32_R1
>> + select SUPPORTS_CPU_MIPS32_R2
>> + select ROM_EXCEPTION_VECTORS
>> + select MIPS_TUNE_24KC
>> + bool
>
> sort this alpahetically
OK
>
>> +
[...]
>> +void vcoreiii_tlb_init(void)
>> +{
>> + register int tlbix = 0;
>> +
>> + init_tlb();
>> +
>> + /* 0x70000000 size 32M (0x02000000) */
>> + create_tlb(tlbix++, MSCC_IO_ORIGIN1_OFFSET, SZ_16M, MMU_REGIO_RW, MMU_REGIO_RW);
>> +#ifdef CONFIG_SOC_LUTON
>> + create_tlb(tlbix++, MSCC_IO_ORIGIN2_OFFSET, SZ_16M, MMU_REGIO_RW, MMU_REGIO_RW);
>> +#endif
>> + /* 0x40000000 - 0x43ffffff - NON-CACHED! */
>> + /* Flash CS0-3, each 16M = 64M total (16 x 4 below ) */
>> + create_tlb(tlbix++, MSCC_FLASH_TO, SZ_16M, MMU_REGIO_RO, MMU_REGIO_RO);
>> + create_tlb(tlbix++, MSCC_FLASH_TO+SZ_32M, SZ_16M, MMU_REGIO_RO, MMU_REGIO_RO);
>> +
>> + /* 0x20000000 - up */
>> +#if CONFIG_SYS_SDRAM_SIZE <= SZ_64M
>> + create_tlb(tlbix++, MSCC_DDR_TO, SZ_64M, MMU_REGIO_RW, MMU_REGIO_INVAL);
>> +#elif CONFIG_SYS_SDRAM_SIZE <= SZ_128M
>> + create_tlb(tlbix++, MSCC_DDR_TO, SZ_64M, MMU_REGIO_RW, MMU_REGIO_RW);
>> +#elif CONFIG_SYS_SDRAM_SIZE <= SZ_256M
>> + create_tlb(tlbix++, MSCC_DDR_TO, SZ_256M, MMU_REGIO_RW, MMU_REGIO_INVAL);
>> +#elif CONFIG_SYS_SDRAM_SIZE <= SZ_512M
>> + create_tlb(tlbix++, MSCC_DDR_TO, SZ_256M, MMU_REGIO_RW, MMU_REGIO_RW);
>> +#else /* 1024M */
>> + create_tlb(tlbix++, MSCC_DDR_TO, SZ_512M, MMU_REGIO_RW, MMU_REGIO_RW);
>> +#endif
>
> can't you leave that to the kernel? U-Boot is only running in kernel
> mode and doesn't need MMU mappings.
You should be right, I will check it.
>
>> +}
>> +
>> +int mach_cpu_init(void)
>> +{
>> + /* Speed up NOR flash access */
>> +#ifdef CONFIG_SOC_LUTON
>> + writel(ICPU_SPI_MST_CFG_FAST_READ_ENA +
>> +#else
>> + writel(
>> +#endif
>> + ICPU_SPI_MST_CFG_CS_DESELECT_TIME(0x19) +
>> + ICPU_SPI_MST_CFG_CLK_DIV(9), REG_CFG(ICPU_SPI_MST_CFG));
>> +
>> + /* Disable all IRQs - map to destination map 0 */
>> + writel(0, REG_CFG(ICPU_INTR_ENA));
>> +#ifdef CONFIG_SOC_OCELOT
>> + writel(~0, REG_CFG(ICPU_DST_INTR_MAP(0)));
>> + writel(0, REG_CFG(ICPU_DST_INTR_MAP(1)));
>> + writel(0, REG_CFG(ICPU_DST_INTR_MAP(2)));
>> + writel(0, REG_CFG(ICPU_DST_INTR_MAP(3)));
>> +#else
>> + writel(ICPU_INTR_IRQ0_ENA_IRQ0_ENA, REG_CFG(ICPU_INTR_IRQ0_ENA));
>> +#endif
>
> do you really need to disable interrupts after a cold or warm boot?
I think it is needed, but I will check.
>
>> + return 0;
>> +}
>> diff --git a/arch/mips/mach-mscc/dram.c b/arch/mips/mach-mscc/dram.c
>> new file mode 100644
>> index 0000000000..2db9001fe9
>> --- /dev/null
>> +++ b/arch/mips/mach-mscc/dram.c
>> @@ -0,0 +1,62 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +/*
>> + * Copyright (c) 2018 Microsemi Corporation
>> + */
>> +
>> +#include <common.h>
>> +
>> +#include <asm/io.h>
>> +#include <asm/types.h>
>> +
>> +#include <mach/tlb.h>
>> +#include <mach/ddr.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +int vcoreiii_ddr_init(void)
>> +{
>> + int res;
>> + if (!(readl(REG_CFG(ICPU_MEMCTRL_STAT)) &
>> + ICPU_MEMCTRL_STAT_INIT_DONE)) {
>> + hal_vcoreiii_init_memctl();
>> + hal_vcoreiii_wait_memctl();
>> + if (hal_vcoreiii_init_dqs() != 0 ||
>> + hal_vcoreiii_train_bytelane(0) != 0
>> +#ifdef CONFIG_SOC_OCELOT
>> + || hal_vcoreiii_train_bytelane(1) != 0
>> +#endif
>> + )
>> + hal_vcoreiii_ddr_failed();
>> + }
>> +
>> +#if (CONFIG_SYS_TEXT_BASE != 0x20000000)
>> + res = dram_check();
>> + if (res == 0)
>> + hal_vcoreiii_ddr_verified();
>> + else
>> + hal_vcoreiii_ddr_failed();
>> +
>> + /* Clear boot-mode and read-back to activate/verify */
>> + writel(readl(REG_CFG(ICPU_GENERAL_CTRL))& ~ICPU_GENERAL_CTRL_BOOT_MODE_ENA,
>> + REG_CFG(ICPU_GENERAL_CTRL));
>
> clrbits_32()?
I missed this function, thanks to point it!
>
>> + readl(REG_CFG(ICPU_GENERAL_CTRL));
>> +#else
>> + res = 0;
>> +#endif
>> + return res;
>> +}
>> +
>> +int print_cpuinfo(void)
>> +{
>> + printf("MSCC VCore-III MIPS 24Kec\n");
>> +
>> + return 0;
>> +}
>> +
>> +int dram_init(void)
>> +{
>> + while (vcoreiii_ddr_init());
>> +
>> + gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
>> + return 0;
>> +}
>> diff --git a/arch/mips/mach-mscc/include/ioremap.h b/arch/mips/mach-mscc/include/ioremap.h
>> new file mode 100644
>> index 0000000000..684f89168c
>> --- /dev/null
>> +++ b/arch/mips/mach-mscc/include/ioremap.h
>> @@ -0,0 +1,49 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +/*
>> + * Copyright (c) 2018 Microsemi Corporation
>> + */
>> +
>> +#ifndef __ASM_MACH_MSCC_IOREMAP_H
>> +#define __ASM_MACH_MSCC_IOREMAP_H
>> +
>> +#include <linux/types.h>
>> +#include <mach/common.h>
>> +
>> +/*
>> + * Allow physical addresses to be fixed up to help peripherals located
>> + * outside the low 32-bit range -- generic pass-through version.
>> + */
>> +static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr,
>> + phys_addr_t size)
>> +{
>> + return phys_addr;
>> +}
>> +
>> +static inline int is_vcoreiii_internal_registers(phys_addr_t offset)
>> +{
>> +#if defined(CONFIG_ARCH_MSCC)
>> + if ((offset >= MSCC_IO_ORIGIN1_OFFSET && offset < (MSCC_IO_ORIGIN1_OFFSET+MSCC_IO_ORIGIN1_SIZE)) ||
>> + (offset >= MSCC_IO_ORIGIN2_OFFSET && offset < (MSCC_IO_ORIGIN2_OFFSET+MSCC_IO_ORIGIN2_SIZE)))
>> + return 1;
>> +#endif
>> +
>> + return 0;
>> +}
>> +
>> +static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size,
>> + unsigned long flags)
>> +{
>> + if (is_vcoreiii_internal_registers(offset))
>> + return (void __iomem *)offset;
>> +
>> + return NULL;
>> +}
>> +
>> +static inline int plat_iounmap(const volatile void __iomem *addr)
>> +{
>> + return is_vcoreiii_internal_registers((unsigned long)addr);
>> +}
>> +
>> +#define _page_cachable_default _CACHE_CACHABLE_NONCOHERENT
>> +
>> +#endif /* __ASM_MACH_MSCC_IOREMAP_H */
>> diff --git a/arch/mips/mach-mscc/include/mach/cache.h b/arch/mips/mach-mscc/include/mach/cache.h
>> new file mode 100644
>> index 0000000000..f3d09014f3
>> --- /dev/null
>> +++ b/arch/mips/mach-mscc/include/mach/cache.h
>> @@ -0,0 +1,36 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +/*
>> + * Copyright (c) 2018 Microsemi Corporation
>> + */
>> +#define MIPS32_CACHE_OP(which, op) (which | (op << 2))
>> +
>> +#define MIPS32_WHICH_ICACHE 0x0
>> +#define MIPS32_WHICH_DCACHE 0x1
>> +
>> +#define MIPS32_INDEX_INVALIDATE 0x0
>> +#define MIPS32_INDEX_LOAD_TAG 0x1
>> +#define MIPS32_INDEX_STORE_TAG 0x2
>> +#define MIPS32_HIT_INVALIDATE 0x4
>> +#define MIPS32_ICACHE_FILL 0x5
>> +#define MIPS32_DCACHE_HIT_INVALIDATE 0x5
>> +#define MIPS32_DCACHE_HIT_WRITEBACK 0x6
>> +#define MIPS32_FETCH_AND_LOCK 0x7
>> +
>> +#define ICACHE_LOAD_LOCK (MIPS32_CACHE_OP(MIPS32_WHICH_ICACHE, MIPS32_FETCH_AND_LOCK))
>> +
>> +#define CACHE_LINE_LEN 32
>
> you can use ARCH_DMA_MINALIGN for this
OK
>
>> +
>> +/* Prefetch and lock instructions into cache */
>> +static inline void icache_lock(void *func, size_t len)
>> +{
>> + int i, lines = ((len - 1) / CACHE_LINE_LEN) + 1;
>> + for (i = 0; i < lines; i++) {
>> + asm volatile (" cache %0, %1(%2)"
>> + : /* No Output */
>> + : "I" ICACHE_LOAD_LOCK,
>> + "n" (i*CACHE_LINE_LEN),
>> + "r" (func)
>> + : /* No Clobbers */);
>> + }
>> +}
>
> could you try to implement this in a generic way in
> arch/mips/lib/cache.c or arch/mips/include/asm/cacheops.h?
I will do it
[...]
>> +static inline void hal_vcoreiii_ddr_failed(void)
>> +{
>> + register u32 reset;
>> +
>> + writel(readl(REG_CFG(ICPU_GPR(6))) + 1, REG_CFG(ICPU_GPR(6)));
>> +
>> + writel(readl(REG_GCB(PERF_GPIO_OE)) & ~BIT(19),
>> + REG_GCB(PERF_GPIO_OE));
>> +
>> + /* Jump to reset - does not return */
>> + reset = KSEG0ADDR(_machine_restart);
>> + icache_lock((void*)reset, 128); // Reset while running from cache
>> + asm volatile ("jr %0" : : "r" (reset));
>> +
>> + while(1)
>> + ;
>
> can't you just use panic() or hang()?
Indeed panic would be a better option.
>
>> +}
>> +/*
>> + * DDR memory sanity checking done, possibly enable ECC.
>> + *
>> + * NB: Assumes inlining as no stack is available!
>> + */
>> +static inline void hal_vcoreiii_ddr_verified(void)
>> +{
>> +#ifdef MIPS_VCOREIII_MEMORY_ECC
>> + /* Finally, enable ECC */
>> + u32 val = readl(REG_CFG(ICPU_MEMCTRL_CFG));
>
> shouldn't it "register u32 val" like in the other functions?
Right
>
>> + sleep_100ns(10000);
>> +#ifdef CONFIG_SOC_OCELOT
>> + /* Establish data contents in DDR RAM for training */
>> + ((volatile u32 *)MSCC_DDR_TO)[0] = 0xcacafefe;
>> + ((volatile u32 *)MSCC_DDR_TO)[1] = 0x22221111;
>> + ((volatile u32 *)MSCC_DDR_TO)[2] = 0x44443333;
>> + ((volatile u32 *)MSCC_DDR_TO)[3] = 0x66665555;
>> + ((volatile u32 *)MSCC_DDR_TO)[4] = 0x88887777;
>> + ((volatile u32 *)MSCC_DDR_TO)[5] = 0xaaaa9999;
>> + ((volatile u32 *)MSCC_DDR_TO)[6] = 0xccccbbbb;
>> + ((volatile u32 *)MSCC_DDR_TO)[7] = 0xeeeedddd;
>> +#else
>> + ((volatile u32 *)MSCC_DDR_TO)[0] = 0xff;
>> +#endif
>
> use writel() or at least __raw_writel()
Yes of course, this part was not poperly converted from redboot.
>
[...]
>> +#define MSCC_IO_ORIGIN1_OFFSET 0x60000000
>> +#define MSCC_IO_ORIGIN1_SIZE 0x01000000
>> +#define MSCC_IO_ORIGIN2_OFFSET 0x70000000
>> +#define MSCC_IO_ORIGIN2_SIZE 0x00200000
>> +#ifndef MSCC_IO_OFFSET1
>> +#define MSCC_IO_OFFSET1(offset) (MSCC_IO_ORIGIN1_OFFSET + offset)
>> +#endif
>> +#ifndef MSCC_IO_OFFSET2
>> +#define MSCC_IO_OFFSET2(offset) (MSCC_IO_ORIGIN2_OFFSET + offset)
>> +#endif
>> +#define BASE_CFG 0x70000000
>> +#define BASE_UART 0x70100000
>> +#define BASE_DEVCPU_GCB 0x60070000
>> +#define BASE_MACRO 0x600a0000
>> +
>> +#define REG_OFFSET(t, o) ((volatile unsigned long *)(t + (o)))
>> +#define REG_CFG(x) REG_OFFSET(BASE_CFG, x)
>> +#define REG_GCB(x) REG_OFFSET(BASE_DEVCPU_GCB, x)
>> +#define REG_MACRO(x) REG_OFFSET(BASE_MACRO, x)
>
> No header files with offsets please except when needed for ASM code.
> This should come from device-tree.
Most of this value are used before the device tree was available.
But I will double check if some of them are used after the device tree
is parsed.
[...]
>
> No header files with thousand of register definitions please. Only
> define what you need per driver.
Actually it should no more the case with the other version I sent on
hte mailing list, after this one was rejected as being too large
>> +static inline void init_tlb(void)
>> +{
>> + register int i, max;
>> +
>> + max = get_tlb_count();
>> + for(i = 0; i < max; i++)
>> + create_tlb(i, i * SZ_1M, SZ_4K, MMU_REGIO_INVAL, MMU_REGIO_INVAL);
>> +}
>
> again can't you leave the setup of MMU mappings to the kernel?
I will check again
>
>> +
>> +#endif /* __ASM_MACH_TLB_H */
>> diff --git a/arch/mips/mach-mscc/lowlevel_init.S b/arch/mips/mach-mscc/lowlevel_init.S
>> new file mode 100644
>> index 0000000000..87439439f0
>> --- /dev/null
>> +++ b/arch/mips/mach-mscc/lowlevel_init.S
>> @@ -0,0 +1,29 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +/*
>> + * Copyright (c) 2018 Microsemi Corporation
>> + */
>> +
>> +#include <asm/asm.h>
>> +#include <asm/regdef.h>
>> +
>> + .text
>
> don't set .text in ASM files. The LEAF() and NODE() macros are hacked to
> place the code in .text.FUNCNAME to allow section garbage collect.
OK
>
>> + .set noreorder
>> + .extern vcoreiii_tlb_init
>> +#ifdef CONFIG_SOC_LUTON
>> + .extern pll_init
>> +#endif
>> +
>> +LEAF(lowlevel_init)
>> + // As we have no stack yet, we can assume the restricted
>> + // luxury of the sX-registers without saving them
>> + move s0,ra
>
> various coding style issues like C++ comments and wrong indentation
I will fix it
>
>> +
>> + jal vcoreiii_tlb_init
>> + nop
>> +#ifdef CONFIG_SOC_LUTON
>> + jal pll_init
>> + nop
>> +#endif
>> + jr s0
>> + nop
>
> please indent instructions in the delay slot by one space
OK
> - Daniel
Thanks again for your review.
Gregory
--
Gregory Clement, Bootlin
Embedded Linux and Kernel engineering
http://bootlin.com
More information about the U-Boot
mailing list