All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gregory CLEMENT <gregory.clement@bootlin.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 2/6] MSCC: add support for VCoreIII SoCs
Date: Thu, 27 Sep 2018 12:14:14 +0200	[thread overview]
Message-ID: <875zyrdz7t.fsf@bootlin.com> (raw)
In-Reply-To: <0057072a-0991-a73a-aa21-b2a1bfcb1971@gmail.com> (Daniel Schwierzeck's message of "Wed, 26 Sep 2018 21:25:18 +0200")

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@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@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

  reply	other threads:[~2018-09-27 10:14 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-25 13:01 [U-Boot] [PATCH 0/6] Add support for VCore III SoCs found in Microsemi switches Gregory CLEMENT
2018-09-25 13:01 ` [U-Boot] [PATCH 1/6] MIPS: move create_tlb() in an proper header: mipsregs.h Gregory CLEMENT
2018-09-25 13:01 ` [U-Boot] [PATCH 3/6] MSCC: add board support for the VCoreIII based evaluation boards Gregory CLEMENT
2018-09-26 19:28   ` Daniel Schwierzeck
2018-10-09 11:22     ` Gregory CLEMENT
2018-09-26 23:03   ` Marek Vasut
2018-10-09 11:23     ` Gregory CLEMENT
2018-09-25 13:01 ` [U-Boot] [PATCH 4/6] MSCC: add device tree for Ocelot and Luton (boards and SoCs) Gregory CLEMENT
2018-09-26 19:31   ` Daniel Schwierzeck
2018-10-09 11:23     ` Gregory CLEMENT
2018-09-25 13:01 ` [U-Boot] [PATCH 5/6] MSCC: add configuration for Ocelot and Luton based boards Gregory CLEMENT
2018-09-26 19:31   ` Daniel Schwierzeck
2018-10-09 11:24     ` Gregory CLEMENT
2018-09-25 13:01 ` [U-Boot] [PATCH 6/6] MIPS: bootm: Add support for Vcore III linux kernel Gregory CLEMENT
2018-09-26 19:40   ` Daniel Schwierzeck
2018-10-09 11:28     ` Gregory CLEMENT
2018-09-25 15:22 ` [U-Boot] [PATCH 0/6] Add support for VCore III SoCs found in Microsemi switches Gregory CLEMENT
2018-09-25 15:25 ` [U-Boot] [PATCH 2/6] MSCC: add support for VCoreIII SoCs Gregory CLEMENT
     [not found] ` <20180925130108.19211-3-gregory.clement@bootlin.com>
2018-09-26 19:25   ` Daniel Schwierzeck
2018-09-27 10:14     ` Gregory CLEMENT [this message]
2018-09-27 11:57       ` Alexandre Belloni
2018-10-09 11:20     ` Gregory CLEMENT

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=875zyrdz7t.fsf@bootlin.com \
    --to=gregory.clement@bootlin.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.