[U-Boot,v3,4/7] MSCC: add support for Luton SoCs

Message ID 20181205171054.926-5-gregory.clement@bootlin.com
State Under Review
Delegated to: Daniel Schwierzeck
Headers show
Series
  • ] Add support for the SoCs found in Microsemi switches
Related show

Commit Message

Gregory CLEMENT Dec. 5, 2018, 5:10 p.m.
As the Ocelots SoCs, this family of SoCs are found in the Microsemi
Switches solution.

Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
---
 arch/mips/mach-mscc/Kconfig                   |  13 +
 arch/mips/mach-mscc/Makefile                  |   1 +
 arch/mips/mach-mscc/cpu.c                     |  14 +-
 arch/mips/mach-mscc/dram.c                    |   2 +
 arch/mips/mach-mscc/include/mach/common.h     |   4 +
 arch/mips/mach-mscc/include/mach/ddr.h        | 112 +++++++-
 .../mips/mach-mscc/include/mach/luton/luton.h |  24 ++
 .../include/mach/luton/luton_devcpu_gcb.h     |  14 +
 .../include/mach/luton/luton_icpu_cfg.h       | 245 ++++++++++++++++++
 arch/mips/mach-mscc/lowlevel_init.S           |   7 +
 arch/mips/mach-mscc/lowlevel_init_luton.S     |  62 +++++
 11 files changed, 494 insertions(+), 4 deletions(-)
 create mode 100644 arch/mips/mach-mscc/include/mach/luton/luton.h
 create mode 100644 arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
 create mode 100644 arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h
 create mode 100644 arch/mips/mach-mscc/lowlevel_init_luton.S

Comments

Daniel Schwierzeck Dec. 10, 2018, 5:03 p.m. | #1
Am 05.12.18 um 18:10 schrieb Gregory CLEMENT:
> As the Ocelots SoCs, this family of SoCs are found in the Microsemi
> Switches solution.
> 
> Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
> ---
>  arch/mips/mach-mscc/Kconfig                   |  13 +
>  arch/mips/mach-mscc/Makefile                  |   1 +
>  arch/mips/mach-mscc/cpu.c                     |  14 +-
>  arch/mips/mach-mscc/dram.c                    |   2 +
>  arch/mips/mach-mscc/include/mach/common.h     |   4 +
>  arch/mips/mach-mscc/include/mach/ddr.h        | 112 +++++++-
>  .../mips/mach-mscc/include/mach/luton/luton.h |  24 ++
>  .../include/mach/luton/luton_devcpu_gcb.h     |  14 +
>  .../include/mach/luton/luton_icpu_cfg.h       | 245 ++++++++++++++++++
>  arch/mips/mach-mscc/lowlevel_init.S           |   7 +
>  arch/mips/mach-mscc/lowlevel_init_luton.S     |  62 +++++
>  11 files changed, 494 insertions(+), 4 deletions(-)
>  create mode 100644 arch/mips/mach-mscc/include/mach/luton/luton.h
>  create mode 100644 arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
>  create mode 100644 arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h
>  create mode 100644 arch/mips/mach-mscc/lowlevel_init_luton.S
> 
> diff --git a/arch/mips/mach-mscc/Kconfig b/arch/mips/mach-mscc/Kconfig
> index 7f1b270207..a8cace0e79 100644
> --- a/arch/mips/mach-mscc/Kconfig
> +++ b/arch/mips/mach-mscc/Kconfig
> @@ -21,6 +21,12 @@ config SOC_OCELOT
>  	help
>  	  This supports MSCC Ocelot family of SOCs.
>  
> +config SOC_LUTON
> +	bool
> +	select SOC_VCOREIII
> +	help
> +	  This supports MSCC Luton family of SOCs.
> +
>  config SYS_CONFIG_NAME
>  	default "vcoreiii"
>  
> @@ -41,6 +47,13 @@ config TARGET_OCELOT_PCB123
>  	  When selected, CONFIG_DEFAULT_DEVICE_TREE should be set to
>  	  ocelot_pcb123
>  
> +config TARGET_LUTON_PCB091
> +	bool "MSCC PCB091 Reference Board"
> +	select SOC_LUTON
> +	select MSCC_BITBANG_SPI_GPIO
> +	help
> +	  When selected, CONFIG_DEFAULT_DEVICE_TREE should be set to
> +	  luton_pcb091
>  endchoice
>  
>  choice
> diff --git a/arch/mips/mach-mscc/Makefile b/arch/mips/mach-mscc/Makefile
> index d14ec33838..6c60f26ca4 100644
> --- a/arch/mips/mach-mscc/Makefile
> +++ b/arch/mips/mach-mscc/Makefile
> @@ -3,3 +3,4 @@
>  CFLAGS_cpu.o += -finline-limit=64000
>  
>  obj-y += cpu.o dram.o reset.o lowlevel_init.o
> +obj-$(CONFIG_SOC_LUTON) += lowlevel_init_luton.o
> diff --git a/arch/mips/mach-mscc/cpu.c b/arch/mips/mach-mscc/cpu.c
> index b503e1407b..5be8ff69d5 100644
> --- a/arch/mips/mach-mscc/cpu.c
> +++ b/arch/mips/mach-mscc/cpu.c
> @@ -48,6 +48,10 @@ void vcoreiii_tlb_init(void)
>  	 */
>  	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
>  
>  #if  CONFIG_SYS_TEXT_BASE == MSCC_FLASH_TO
>  	/*
> @@ -75,6 +79,14 @@ void vcoreiii_tlb_init(void)
>  int mach_cpu_init(void)
>  {
>  	/* Speed up NOR flash access */
> +#ifdef CONFIG_SOC_LUTON
> +	writel(ICPU_PI_MST_CFG_TRISTATE_CTRL +
> +	       ICPU_PI_MST_CFG_CLK_DIV(4), BASE_CFG + ICPU_PI_MST_CFG);
> +
> +	writel(ICPU_SPI_MST_CFG_FAST_READ_ENA +
> +	       ICPU_SPI_MST_CFG_CS_DESELECT_TIME(0x19) +
> +	       ICPU_SPI_MST_CFG_CLK_DIV(9), BASE_CFG + ICPU_SPI_MST_CFG);
> +#else
>  	writel(ICPU_SPI_MST_CFG_CS_DESELECT_TIME(0x19) +
>  	       ICPU_SPI_MST_CFG_CLK_DIV(9), BASE_CFG + ICPU_SPI_MST_CFG);
>  	/*
> @@ -85,6 +97,6 @@ int mach_cpu_init(void)
>  	writel(0, BASE_CFG + ICPU_DST_INTR_MAP(1));
>  	writel(0, BASE_CFG + ICPU_DST_INTR_MAP(2));
>  	writel(0, BASE_CFG + ICPU_DST_INTR_MAP(3));
> -
> +#endif
>  	return 0;
>  }
> diff --git a/arch/mips/mach-mscc/dram.c b/arch/mips/mach-mscc/dram.c
> index 5acee6f918..309007c14e 100644
> --- a/arch/mips/mach-mscc/dram.c
> +++ b/arch/mips/mach-mscc/dram.c
> @@ -19,9 +19,11 @@ static inline int vcoreiii_train_bytelane(void)
>  
>  	ret = hal_vcoreiii_train_bytelane(0);
>  
> +#ifdef CONFIG_SOC_OCELOT
>  	if (ret)
>  		return ret;
>  	ret = hal_vcoreiii_train_bytelane(1);
> +#endif
>  
>  	return ret;
>  }
> diff --git a/arch/mips/mach-mscc/include/mach/common.h b/arch/mips/mach-mscc/include/mach/common.h
> index 842462aeed..931ecd7985 100644
> --- a/arch/mips/mach-mscc/include/mach/common.h
> +++ b/arch/mips/mach-mscc/include/mach/common.h
> @@ -10,6 +10,10 @@
>  #include <mach/ocelot/ocelot.h>
>  #include <mach/ocelot/ocelot_devcpu_gcb.h>
>  #include <mach/ocelot/ocelot_icpu_cfg.h>
> +#elif defined(CONFIG_SOC_LUTON)
> +#include <mach/luton/luton.h>
> +#include <mach/luton/luton_devcpu_gcb.h>
> +#include <mach/luton/luton_icpu_cfg.h>
>  #else
>  #error Unsupported platform
>  #endif
> diff --git a/arch/mips/mach-mscc/include/mach/ddr.h b/arch/mips/mach-mscc/include/mach/ddr.h
> index 4bdea90506..97eff2a196 100644
> --- a/arch/mips/mach-mscc/include/mach/ddr.h
> +++ b/arch/mips/mach-mscc/include/mach/ddr.h
> @@ -598,6 +598,98 @@ static inline int dram_check(void)
>  	}
>  	return 0;
>  }
> +#else				/* Luton */
> +
> +static inline void sleep_100ns(u32 val)
> +{
> +}
> +
> +static inline void hal_vcoreiii_ddr_reset_assert(void)
> +{
> +	setbits_le32(BASE_CFG + ICPU_MEMPHY_CFG, ICPU_MEMPHY_CFG_PHY_RST);
> +	setbits_le32(BASE_CFG + ICPU_RESET, ICPU_RESET_MEM_RST_FORCE);
> +}
> +
> +static inline void hal_vcoreiii_ddr_reset_release(void)
> +{
> +}
> +
> +static inline void hal_vcoreiii_ddr_failed(void)
> +{
> +	register u32 memphy_cfg = readl(BASE_CFG + ICPU_MEMPHY_CFG);
> +
> +	/* Do a fifo reset and start over */
> +	writel(memphy_cfg | ICPU_MEMPHY_CFG_PHY_FIFO_RST,
> +	       BASE_CFG + ICPU_MEMPHY_CFG);
> +	writel(memphy_cfg & ~ICPU_MEMPHY_CFG_PHY_FIFO_RST,
> +	       BASE_CFG + ICPU_MEMPHY_CFG);
> +	writel(memphy_cfg | ICPU_MEMPHY_CFG_PHY_FIFO_RST,
> +	       BASE_CFG + ICPU_MEMPHY_CFG);
> +}
> +
> +static inline void hal_vcoreiii_ddr_verified(void)
> +{
> +}
> +
> +static inline int look_for(u32 data)
> +{
> +	register u32 byte = ((volatile u8 *)MSCC_DDR_TO)[0];

__raw_readl() ?

> +
> +	if (data != byte) {
> +		if (!incr_dly(0))
> +			return DDR_TRAIN_ERROR;
> +		return DDR_TRAIN_CONTINUE;
> +	}
> +
> +	return DDR_TRAIN_OK;
> +}
> +
> +/* This algorithm is converted from the TCL training algorithm used
> + * during silicon simulation.
> + * NB: Assumes inlining as no stack is available!
> + */
> +static inline int hal_vcoreiii_train_bytelane(u32 bytelane)
> +{
> +	register int res;
> +
> +	set_dly(bytelane, 0);	// Start training at DQS=0

no C++ style comments

> +	while ((res = look_for(0xff)) == DDR_TRAIN_CONTINUE)
> +		;
> +	if (res != DDR_TRAIN_OK)
> +		return res;
> +
> +	set_dly(bytelane, 0);	// Start training at DQS=0
> +	while ((res = look_for(0x00)) == DDR_TRAIN_CONTINUE)
> +
> +		;
> +
> +	if (res != DDR_TRAIN_OK)
> +		return res;
> +
> +	adjust_dly(-3);
> +
> +	return DDR_TRAIN_OK;
> +}
> +
> +static inline int hal_vcoreiii_init_dqs(void)
> +{
> +	return 0;
> +}
> +
> +static inline int dram_check(void)
> +{
> +#define DDR ((volatile u32 *) MSCC_DDR_TO)
> +	register u32 i;
> +
> +	for (i = 0; i < 8; i++) {
> +		DDR[i] = ~i;
> +		if (DDR[i] != ~i)

__raw_readl(), __raw_writel() ?


> +			return 1;
> +	}
> +
> +	return 0;
> +}
> +#endif
>  
>  /*
>   * NB: Called *early* to init memory controller - assumes inlining as
> @@ -630,12 +722,12 @@ static inline void hal_vcoreiii_init_memctl(void)
>  	/* Wait for ZCAL to clear */
>  	while (readl(BASE_CFG + ICPU_MEMPHY_ZCAL) & ICPU_MEMPHY_ZCAL_ZCAL_ENA)
>  		;
> -
> +#ifdef CONFIG_SOC_OCELOT
>  	/* Check no ZCAL_ERR */
>  	if (readl(BASE_CFG + ICPU_MEMPHY_ZCAL_STAT)
>  	    & ICPU_MEMPHY_ZCAL_STAT_ZCAL_ERR)
>  		hal_vcoreiii_ddr_failed();
> -
> +#endif
>  	/* Drive CL, CK, ODT */
>  	setbits_le32(BASE_CFG + ICPU_MEMPHY_CFG, ICPU_MEMPHY_CFG_PHY_ODT_OE |
>  		     ICPU_MEMPHY_CFG_PHY_CK_OE | ICPU_MEMPHY_CFG_PHY_CL_OE);
> @@ -644,7 +736,12 @@ static inline void hal_vcoreiii_init_memctl(void)
>  	writel(MSCC_MEMPARM_MEMCFG, BASE_CFG + ICPU_MEMCTRL_CFG);
>  	writel(MSCC_MEMPARM_PERIOD, BASE_CFG + ICPU_MEMCTRL_REF_PERIOD);
>  
> +#ifdef CONFIG_SOC_OCELOT
>  	writel(MSCC_MEMPARM_TIMING0, BASE_CFG + ICPU_MEMCTRL_TIMING0);
> +#else /* Luton */
> +	clrbits_le32(BASE_CFG + ICPU_MEMCTRL_TIMING0, ((1 << 20) - 1));
> +	setbits_le32(BASE_CFG + ICPU_MEMCTRL_TIMING0, MSCC_MEMPARM_TIMING0);
> +#endif
>  
>  	writel(MSCC_MEMPARM_TIMING1, BASE_CFG + ICPU_MEMCTRL_TIMING1);
>  	writel(MSCC_MEMPARM_TIMING2, BASE_CFG + ICPU_MEMCTRL_TIMING2);
> @@ -654,6 +751,7 @@ static inline void hal_vcoreiii_init_memctl(void)
>  	writel(MSCC_MEMPARM_MR2, BASE_CFG + ICPU_MEMCTRL_MR2_VAL);
>  	writel(MSCC_MEMPARM_MR3, BASE_CFG + ICPU_MEMCTRL_MR3_VAL);
>  
> +#ifdef CONFIG_SOC_OCELOT
>  	/* Termination setup - enable ODT */
>  	writel(ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_ENA |
>  	       /* Assert ODT0 for any write */
> @@ -664,6 +762,11 @@ static inline void hal_vcoreiii_init_memctl(void)
>  	hal_vcoreiii_ddr_reset_release();
>  
>  	writel(readl(BASE_CFG + ICPU_GPR(7)) + 1, BASE_CFG + ICPU_GPR(7));
> +#else				/* Luton */
> +	/* Termination setup - disable ODT */
> +	writel(0, BASE_CFG + ICPU_MEMCTRL_TERMRES_CTRL);
> +
> +#endif
>  }
>  
>  static inline void hal_vcoreiii_wait_memctl(void)
> @@ -677,7 +780,7 @@ static inline void hal_vcoreiii_wait_memctl(void)
>  
>  	/* Settle...? */
>  	sleep_100ns(10000);
> -
> +#ifdef CONFIG_SOC_OCELOT
>  	/* Establish data contents in DDR RAM for training */
>  
>  	__raw_writel(0xcacafefe, ((void __iomem *)MSCC_DDR_TO));
> @@ -688,5 +791,8 @@ static inline void hal_vcoreiii_wait_memctl(void)
>  	__raw_writel(0xaaaa9999, ((void __iomem *)MSCC_DDR_TO + 0x14));
>  	__raw_writel(0xccccbbbb, ((void __iomem *)MSCC_DDR_TO + 0x18));
>  	__raw_writel(0xeeeedddd, ((void __iomem *)MSCC_DDR_TO + 0x1C));
> +#else
> +	__raw_writel(0xff, ((void __iomem *)MSCC_DDR_TO));
> +#endif
>  }
>  #endif				/* __ASM_MACH_DDR_H */
> diff --git a/arch/mips/mach-mscc/include/mach/luton/luton.h b/arch/mips/mach-mscc/include/mach/luton/luton.h
> new file mode 100644
> index 0000000000..19f02ede66
> --- /dev/null
> +++ b/arch/mips/mach-mscc/include/mach/luton/luton.h
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */

this line should begin with a //. Please fix all files in this patch.

> +/*
> + * Microsemi Ocelot Switch driver
> + *
> + * Copyright (c) 2018 Microsemi Corporation
> + */
> +
> +#ifndef _MSCC_OCELOT_H_
> +#define _MSCC_OCELOT_H_
> +
> +#include <linux/bitops.h>
> +#include <dm.h>
> +
> +/*
> + * Target offset base(s)
> + */
> +#define MSCC_IO_ORIGIN1_OFFSET 0x60000000
> +#define MSCC_IO_ORIGIN1_SIZE   0x01000000
> +#define MSCC_IO_ORIGIN2_OFFSET 0x70000000
> +#define MSCC_IO_ORIGIN2_SIZE   0x00200000
> +#define BASE_CFG        ((void __iomem *)0x70000000)
> +#define BASE_DEVCPU_GCB ((void __iomem *)0x60070000)
> +
> +#endif
> diff --git a/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h b/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
> new file mode 100644
> index 0000000000..8c0b612325
> --- /dev/null
> +++ b/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/*
> + * Copyright (c) 2018 Microsemi Corporation
> + */
> +
> +#ifndef _MSCC_OCELOT_DEVCPU_GCB_H_
> +#define _MSCC_OCELOT_DEVCPU_GCB_H_
> +
> +#define PERF_SOFT_RST                                     0x90
> +
> +#define PERF_SOFT_RST_SOFT_SWC_RST                        BIT(1)
> +#define PERF_SOFT_RST_SOFT_CHIP_RST                       BIT(0)
> +
> +#endif
> diff --git a/arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h b/arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h
> new file mode 100644
> index 0000000000..9233f037bb
> --- /dev/null
> +++ b/arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h
> @@ -0,0 +1,245 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/*
> + * Copyright (c) 2018 Microsemi Corporation
> + */
> +
> +#ifndef _MSCC_OCELOT_ICPU_CFG_H_
> +#define _MSCC_OCELOT_ICPU_CFG_H_
> +
> +#define ICPU_GPR(x) (0x4 * (x))
> +#define ICPU_GPR_RSZ                                      0x4
> +
> +#define ICPU_RESET                                        0x20
> +
> +#define ICPU_RESET_CORE_RST_CPU_ONLY                      BIT(3)
> +#define ICPU_RESET_CORE_RST_PROTECT                       BIT(2)
> +#define ICPU_RESET_CORE_RST_FORCE                         BIT(1)
> +#define ICPU_RESET_MEM_RST_FORCE                          BIT(0)
> +
> +#define ICPU_GENERAL_CTRL                                 0x24
> +
> +#define ICPU_GENERAL_CTRL_SWC_CLEAR_IF                    BIT(6)
> +#define ICPU_GENERAL_CTRL_CPU_BUSIF_SLEEP_DIS             BIT(5)
> +#define ICPU_GENERAL_CTRL_CPU_BUSIF_WERR_ENA              BIT(4)
> +#define ICPU_GENERAL_CTRL_IF_MASTER_DIS                   BIT(3)
> +#define ICPU_GENERAL_CTRL_IF_MASTER_SPI_ENA               BIT(2)
> +#define ICPU_GENERAL_CTRL_IF_MASTER_PI_ENA                BIT(1)
> +
> +#define ICPU_GENERAL_CTRL_BOOT_MODE_ENA                   BIT(0)
> +
> +#define ICPU_PI_MST_CFG                                   0x2c
> +
> +#define ICPU_PI_MST_CFG_ATE_MODE_DIS                      BIT(7)
> +#define ICPU_PI_MST_CFG_CLK_POL                           BIT(6)
> +#define ICPU_PI_MST_CFG_TRISTATE_CTRL                     BIT(5)
> +#define ICPU_PI_MST_CFG_CLK_DIV(x)                        ((x) & GENMASK(4, 0))
> +#define ICPU_PI_MST_CFG_CLK_DIV_M                         GENMASK(4, 0)
> +
> +#define ICPU_SPI_MST_CFG                                  0x50
> +
> +#define ICPU_SPI_MST_CFG_FAST_READ_ENA                    BIT(10)
> +#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME(x)              (((x) << 5) & GENMASK(9, 5))
> +#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME_M               GENMASK(9, 5)
> +#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME_X(x)            (((x) & GENMASK(9, 5)) >> 5)
> +#define ICPU_SPI_MST_CFG_CLK_DIV(x)                       ((x) & GENMASK(4, 0))
> +#define ICPU_SPI_MST_CFG_CLK_DIV_M                        GENMASK(4, 0)
> +
> +#define ICPU_SW_MODE                                      0x64
> +
> +#define ICPU_SW_MODE_SW_PIN_CTRL_MODE                     BIT(13)
> +#define ICPU_SW_MODE_SW_SPI_SCK                           BIT(12)
> +#define ICPU_SW_MODE_SW_SPI_SCK_OE                        BIT(11)
> +#define ICPU_SW_MODE_SW_SPI_SDO                           BIT(10)
> +#define ICPU_SW_MODE_SW_SPI_SDO_OE                        BIT(9)
> +#define ICPU_SW_MODE_SW_SPI_CS(x)                         (((x) << 5) & GENMASK(8, 5))
> +#define ICPU_SW_MODE_SW_SPI_CS_M                          GENMASK(8, 5)
> +#define ICPU_SW_MODE_SW_SPI_CS_X(x)                       (((x) & GENMASK(8, 5)) >> 5)
> +#define ICPU_SW_MODE_SW_SPI_CS_OE(x)                      (((x) << 1) & GENMASK(4, 1))
> +#define ICPU_SW_MODE_SW_SPI_CS_OE_M                       GENMASK(4, 1)
> +#define ICPU_SW_MODE_SW_SPI_CS_OE_X(x)                    (((x) & GENMASK(4, 1)) >> 1)
> +#define ICPU_SW_MODE_SW_SPI_SDI                           BIT(0)
> +
> +#define ICPU_INTR_ENA                                     0x88
> +
> +#define ICPU_INTR_IRQ0_ENA                                0x98
> +#define ICPU_INTR_IRQ0_ENA_IRQ0_ENA                       BIT(0)
> +
> +#define ICPU_MEMCTRL_CTRL                                 0x234
> +
> +#define ICPU_MEMCTRL_CTRL_PWR_DOWN                        BIT(3)
> +#define ICPU_MEMCTRL_CTRL_MDSET                           BIT(2)
> +#define ICPU_MEMCTRL_CTRL_STALL_REF_ENA                   BIT(1)
> +#define ICPU_MEMCTRL_CTRL_INITIALIZE                      BIT(0)
> +
> +#define ICPU_MEMCTRL_CFG                                  0x238
> +
> +#define ICPU_MEMCTRL_CFG_DDR_512MBYTE_PLUS                BIT(16)
> +#define ICPU_MEMCTRL_CFG_DDR_ECC_ERR_ENA                  BIT(15)
> +#define ICPU_MEMCTRL_CFG_DDR_ECC_COR_ENA                  BIT(14)
> +#define ICPU_MEMCTRL_CFG_DDR_ECC_ENA                      BIT(13)
> +#define ICPU_MEMCTRL_CFG_DDR_WIDTH                        BIT(12)
> +#define ICPU_MEMCTRL_CFG_DDR_MODE                         BIT(11)
> +#define ICPU_MEMCTRL_CFG_BURST_SIZE                       BIT(10)
> +#define ICPU_MEMCTRL_CFG_BURST_LEN                        BIT(9)
> +#define ICPU_MEMCTRL_CFG_BANK_CNT                         BIT(8)
> +#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR(x)                  (((x) << 4) & GENMASK(7, 4))
> +#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR_M                   GENMASK(7, 4)
> +#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR_X(x)                (((x) & GENMASK(7, 4)) >> 4)
> +#define ICPU_MEMCTRL_CFG_MSB_COL_ADDR(x)                  ((x) & GENMASK(3, 0))
> +#define ICPU_MEMCTRL_CFG_MSB_COL_ADDR_M                   GENMASK(3, 0)
> +
> +#define ICPU_MEMCTRL_STAT                                 0x23C
> +
> +#define ICPU_MEMCTRL_STAT_RDATA_MASKED                    BIT(5)
> +#define ICPU_MEMCTRL_STAT_RDATA_DUMMY                     BIT(4)
> +#define ICPU_MEMCTRL_STAT_RDATA_ECC_ERR                   BIT(3)
> +#define ICPU_MEMCTRL_STAT_RDATA_ECC_COR                   BIT(2)
> +#define ICPU_MEMCTRL_STAT_PWR_DOWN_ACK                    BIT(1)
> +#define ICPU_MEMCTRL_STAT_INIT_DONE                       BIT(0)
> +
> +#define ICPU_MEMCTRL_REF_PERIOD                           0x240
> +
> +#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF(x)           (((x) << 16) & GENMASK(19, 16))
> +#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF_M            GENMASK(19, 16)
> +#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF_X(x)         (((x) & GENMASK(19, 16)) >> 16)
> +#define ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD(x)             ((x) & GENMASK(15, 0))
> +#define ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD_M              GENMASK(15, 0)
> +
> +#define ICPU_MEMCTRL_TIMING0                              0x248
> +
> +#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY(x)              (((x) << 28) & GENMASK(31, 28))
> +#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY_M               GENMASK(31, 28)
> +#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY_X(x)            (((x) & GENMASK(31, 28)) >> 28)
> +#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY(x)          (((x) << 24) & GENMASK(27, 24))
> +#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY_M           GENMASK(27, 24)
> +#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY_X(x)        (((x) & GENMASK(27, 24)) >> 24)
> +#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY(x)          (((x) << 20) & GENMASK(23, 20))
> +#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY_M           GENMASK(23, 20)
> +#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY_X(x)        (((x) & GENMASK(23, 20)) >> 20)
> +#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY(x)          (((x) << 16) & GENMASK(19, 16))
> +#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY_M           GENMASK(19, 16)
> +#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY_X(x)        (((x) & GENMASK(19, 16)) >> 16)
> +#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY(x)           (((x) << 12) & GENMASK(15, 12))
> +#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY_M            GENMASK(15, 12)
> +#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY_X(x)         (((x) & GENMASK(15, 12)) >> 12)
> +#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY(x)           (((x) << 8) & GENMASK(11, 8))
> +#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY_M            GENMASK(11, 8)
> +#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY_X(x)         (((x) & GENMASK(11, 8)) >> 8)
> +#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY(x)           (((x) << 4) & GENMASK(7, 4))
> +#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY_M            GENMASK(7, 4)
> +#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY_X(x)         (((x) & GENMASK(7, 4)) >> 4)
> +#define ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY(x)           ((x) & GENMASK(3, 0))
> +#define ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY_M            GENMASK(3, 0)
> +
> +#define ICPU_MEMCTRL_TIMING1                              0x24c
> +
> +#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY(x)  (((x) << 24) & GENMASK(31, 24))
> +#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY_M   GENMASK(31, 24)
> +#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY_X(x) (((x) & GENMASK(31, 24)) >> 24)
> +#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY(x)             (((x) << 16) & GENMASK(23, 16))
> +#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY_M              GENMASK(23, 16)
> +#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY_X(x)           (((x) & GENMASK(23, 16)) >> 16)
> +#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY(x)          (((x) << 12) & GENMASK(15, 12))
> +#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY_M           GENMASK(15, 12)
> +#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY_X(x)        (((x) & GENMASK(15, 12)) >> 12)
> +#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY(x)            (((x) << 8) & GENMASK(11, 8))
> +#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY_M             GENMASK(11, 8)
> +#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY_X(x)          (((x) & GENMASK(11, 8)) >> 8)
> +#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY(x)            (((x) << 4) & GENMASK(7, 4))
> +#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY_M             GENMASK(7, 4)
> +#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY_X(x)          (((x) & GENMASK(7, 4)) >> 4)
> +#define ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY(x)              ((x) & GENMASK(3, 0))
> +#define ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY_M               GENMASK(3, 0)
> +
> +#define ICPU_MEMCTRL_TIMING2                              0x250
> +
> +#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY(x)             (((x) << 28) & GENMASK(31, 28))
> +#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY_M              GENMASK(31, 28)
> +#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY_X(x)           (((x) & GENMASK(31, 28)) >> 28)
> +#define ICPU_MEMCTRL_TIMING2_MDSET_DLY(x)                 (((x) << 24) & GENMASK(27, 24))
> +#define ICPU_MEMCTRL_TIMING2_MDSET_DLY_M                  GENMASK(27, 24)
> +#define ICPU_MEMCTRL_TIMING2_MDSET_DLY_X(x)               (((x) & GENMASK(27, 24)) >> 24)
> +#define ICPU_MEMCTRL_TIMING2_REF_DLY(x)                   (((x) << 16) & GENMASK(23, 16))
> +#define ICPU_MEMCTRL_TIMING2_REF_DLY_M                    GENMASK(23, 16)
> +#define ICPU_MEMCTRL_TIMING2_REF_DLY_X(x)                 (((x) & GENMASK(23, 16)) >> 16)
> +#define ICPU_MEMCTRL_TIMING2_FOUR_HUNDRED_NS_DLY(x)       ((x) & GENMASK(15, 0))
> +#define ICPU_MEMCTRL_TIMING2_FOUR_HUNDRED_NS_DLY_M        GENMASK(15, 0)
> +
> +#define ICPU_MEMCTRL_TIMING3                              0x254
> +
> +#define ICPU_MEMCTRL_TIMING3_RMW_DLY(x)                   (((x) << 16) & GENMASK(19, 16))
> +#define ICPU_MEMCTRL_TIMING3_RMW_DLY_M                    GENMASK(19, 16)
> +#define ICPU_MEMCTRL_TIMING3_RMW_DLY_X(x)                 (((x) & GENMASK(19, 16)) >> 16)
> +#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY(x)                (((x) << 12) & GENMASK(15, 12))
> +#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY_M                 GENMASK(15, 12)
> +#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY_X(x)              (((x) & GENMASK(15, 12)) >> 12)
> +#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY(x)                (((x) << 8) & GENMASK(11, 8))
> +#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY_M                 GENMASK(11, 8)
> +#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY_X(x)              (((x) & GENMASK(11, 8)) >> 8)
> +#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY(x)          (((x) << 4) & GENMASK(7, 4))
> +#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY_M           GENMASK(7, 4)
> +#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY_X(x)        (((x) & GENMASK(7, 4)) >> 4)
> +#define ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY(x)    ((x) & GENMASK(3, 0))
> +#define ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY_M     GENMASK(3, 0)
> +
> +#define ICPU_MEMCTRL_MR0_VAL                              0x258
> +
> +#define ICPU_MEMCTRL_MR1_VAL                              0x25c
> +
> +#define ICPU_MEMCTRL_MR2_VAL                              0x260
> +
> +#define ICPU_MEMCTRL_MR3_VAL                              0x264
> +
> +#define ICPU_MEMCTRL_TERMRES_CTRL                         0x268
> +
> +#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_EXT              BIT(11)
> +#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA(x)           (((x) << 7) & GENMASK(10, 7))
> +#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA_M            GENMASK(10, 7)
> +#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA_X(x)         (((x) & GENMASK(10, 7)) >> 7)
> +#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_EXT              BIT(6)
> +#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA(x)           (((x) << 2) & GENMASK(5, 2))
> +#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA_M            GENMASK(5, 2)
> +#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA_X(x)         (((x) & GENMASK(5, 2)) >> 2)
> +#define ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_EXT        BIT(1)
> +#define ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_ENA        BIT(0)
> +
> +#define ICPU_MEMCTRL_DQS_DLY(x) (0x270)
> +
> +#define ICPU_MEMCTRL_DQS_DLY_TRAIN_DQ_ENA                 BIT(11)
> +#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1(x)              (((x) << 8) & GENMASK(10, 8))
> +#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1_M               GENMASK(10, 8)
> +#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1_X(x)            (((x) & GENMASK(10, 8)) >> 8)
> +#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0(x)              (((x) << 5) & GENMASK(7, 5))
> +#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0_M               GENMASK(7, 5)
> +#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0_X(x)            (((x) & GENMASK(7, 5)) >> 5)
> +#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY(x)                   ((x) & GENMASK(4, 0))
> +#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_M                    GENMASK(4, 0)
> +
> +#define ICPU_MEMPHY_CFG                                   0x278
> +
> +#define ICPU_MEMPHY_CFG_PHY_FLUSH_DIS                     BIT(10)
> +#define ICPU_MEMPHY_CFG_PHY_RD_ADJ_DIS                    BIT(9)
> +#define ICPU_MEMPHY_CFG_PHY_DQS_EXT                       BIT(8)
> +#define ICPU_MEMPHY_CFG_PHY_FIFO_RST                      BIT(7)
> +#define ICPU_MEMPHY_CFG_PHY_DLL_BL_RST                    BIT(6)
> +#define ICPU_MEMPHY_CFG_PHY_DLL_CL_RST                    BIT(5)
> +#define ICPU_MEMPHY_CFG_PHY_ODT_OE                        BIT(4)
> +#define ICPU_MEMPHY_CFG_PHY_CK_OE                         BIT(3)
> +#define ICPU_MEMPHY_CFG_PHY_CL_OE                         BIT(2)
> +#define ICPU_MEMPHY_CFG_PHY_SSTL_ENA                      BIT(1)
> +#define ICPU_MEMPHY_CFG_PHY_RST                           BIT(0)
> +#define ICPU_MEMPHY_DQ_DLY_TRM                            0x180
> +#define ICPU_MEMPHY_DQ_DLY_TRM_RSZ                        0x4
> +
> +#define ICPU_MEMPHY_ZCAL                                  0x294
> +
> +#define ICPU_MEMPHY_ZCAL_ZCAL_CLK_SEL                     BIT(9)
> +#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT(x)                 (((x) << 5) & GENMASK(8, 5))
> +#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT_M                  GENMASK(8, 5)
> +#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT_X(x)               (((x) & GENMASK(8, 5)) >> 5)
> +#define ICPU_MEMPHY_ZCAL_ZCAL_PROG(x)                     (((x) << 1) & GENMASK(4, 1))
> +#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_M                      GENMASK(4, 1)
> +#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_X(x)                   (((x) & GENMASK(4, 1)) >> 1)
> +#define ICPU_MEMPHY_ZCAL_ZCAL_ENA                         BIT(0)
> +
> +#endif
> diff --git a/arch/mips/mach-mscc/lowlevel_init.S b/arch/mips/mach-mscc/lowlevel_init.S
> index 8e4f0d02c8..1624bd6f55 100644
> --- a/arch/mips/mach-mscc/lowlevel_init.S
> +++ b/arch/mips/mach-mscc/lowlevel_init.S
> @@ -8,6 +8,9 @@
>  
>      .set noreorder
>      .extern     vcoreiii_tlb_init
> +#ifdef CONFIG_SOC_LUTON
> +    .extern     pll_init
> +#endif
>  
>  LEAF(lowlevel_init)
>  	/*
> @@ -18,6 +21,10 @@ LEAF(lowlevel_init)
>  
>  	jal	vcoreiii_tlb_init
>  	nop
> +#ifdef CONFIG_SOC_LUTON
> +	jal	pll_init
> +	nop
> +#endif
>  	jr	s0
>  	nop
>  	END(lowlevel_init)
> diff --git a/arch/mips/mach-mscc/lowlevel_init_luton.S b/arch/mips/mach-mscc/lowlevel_init_luton.S
> new file mode 100644
> index 0000000000..6b298a99da
> --- /dev/null
> +++ b/arch/mips/mach-mscc/lowlevel_init_luton.S
> @@ -0,0 +1,62 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/*
> + * Copyright (c) 2018 Microsemi Corporation
> + */
> +
> +#include <asm/asm.h>
> +#include <asm/regdef.h>
> +
> +#define BASE_MACRO      0x600a0000
> +#define REG_OFFSET(t, o) (t + (o*4))
> +#define REG_MACRO(x) REG_OFFSET(BASE_MACRO, x)
> +#define BIT(nr)			(1 << (nr))
> +
> +#define MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0 REG_MACRO(6)
> +#define MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0_LOCK_STATUS BIT(0)
> +#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2 REG_MACRO(2)
> +#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0 REG_MACRO(0)
> +#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV (0x3F << 6)
> +#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV_ENC(x) (x << 6)
> +
> +    .set noreorder
> +LEAF(pll_init)
> +	/* Make sure PLL is locked */
> +	lw	v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0
> +	andi	v1, v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0_LOCK_STATUS
> +	bne	v1, zero, 1f
> +	 nop
> +
> +	/* Black magic from frontend */
> +	li	v1, 0x00610400
> +	sw	v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
> +
> +	li	v1, 0x00610c00
> +	sw	v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
> +
> +	li	v1, 0x00610800
> +	sw	v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
> +
> +	li	v1, 0x00610000
> +	sw	v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
> +
> +	/* Wait for lock */
> +2:	lw	v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0
> +	andi	v1, v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0_LOCK_STATUS
> +	# Keep looping if zero (no lock bit yet)

should be a C style comment

> +	beq	v1, zero, 2b
> +	 nop
> +
> +	/* Setup PLL CPU clock divider for 416MHz */
> +1:	lw	v0, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0
> +
> +	/* Keep reserved bits */
> +	li	v1, ~MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV
> +	and	v0, v0, v1
> +
> +	/* Set code 6 ~ 416.66 MHz */
> +	ori	v0, v0, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV_ENC(6)
> +
> +	sw	v0, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0
> +	jr      ra
> +	 nop
> +	END(pll_init)
>

Patch

diff --git a/arch/mips/mach-mscc/Kconfig b/arch/mips/mach-mscc/Kconfig
index 7f1b270207..a8cace0e79 100644
--- a/arch/mips/mach-mscc/Kconfig
+++ b/arch/mips/mach-mscc/Kconfig
@@ -21,6 +21,12 @@  config SOC_OCELOT
 	help
 	  This supports MSCC Ocelot family of SOCs.
 
+config SOC_LUTON
+	bool
+	select SOC_VCOREIII
+	help
+	  This supports MSCC Luton family of SOCs.
+
 config SYS_CONFIG_NAME
 	default "vcoreiii"
 
@@ -41,6 +47,13 @@  config TARGET_OCELOT_PCB123
 	  When selected, CONFIG_DEFAULT_DEVICE_TREE should be set to
 	  ocelot_pcb123
 
+config TARGET_LUTON_PCB091
+	bool "MSCC PCB091 Reference Board"
+	select SOC_LUTON
+	select MSCC_BITBANG_SPI_GPIO
+	help
+	  When selected, CONFIG_DEFAULT_DEVICE_TREE should be set to
+	  luton_pcb091
 endchoice
 
 choice
diff --git a/arch/mips/mach-mscc/Makefile b/arch/mips/mach-mscc/Makefile
index d14ec33838..6c60f26ca4 100644
--- a/arch/mips/mach-mscc/Makefile
+++ b/arch/mips/mach-mscc/Makefile
@@ -3,3 +3,4 @@ 
 CFLAGS_cpu.o += -finline-limit=64000
 
 obj-y += cpu.o dram.o reset.o lowlevel_init.o
+obj-$(CONFIG_SOC_LUTON) += lowlevel_init_luton.o
diff --git a/arch/mips/mach-mscc/cpu.c b/arch/mips/mach-mscc/cpu.c
index b503e1407b..5be8ff69d5 100644
--- a/arch/mips/mach-mscc/cpu.c
+++ b/arch/mips/mach-mscc/cpu.c
@@ -48,6 +48,10 @@  void vcoreiii_tlb_init(void)
 	 */
 	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
 
 #if  CONFIG_SYS_TEXT_BASE == MSCC_FLASH_TO
 	/*
@@ -75,6 +79,14 @@  void vcoreiii_tlb_init(void)
 int mach_cpu_init(void)
 {
 	/* Speed up NOR flash access */
+#ifdef CONFIG_SOC_LUTON
+	writel(ICPU_PI_MST_CFG_TRISTATE_CTRL +
+	       ICPU_PI_MST_CFG_CLK_DIV(4), BASE_CFG + ICPU_PI_MST_CFG);
+
+	writel(ICPU_SPI_MST_CFG_FAST_READ_ENA +
+	       ICPU_SPI_MST_CFG_CS_DESELECT_TIME(0x19) +
+	       ICPU_SPI_MST_CFG_CLK_DIV(9), BASE_CFG + ICPU_SPI_MST_CFG);
+#else
 	writel(ICPU_SPI_MST_CFG_CS_DESELECT_TIME(0x19) +
 	       ICPU_SPI_MST_CFG_CLK_DIV(9), BASE_CFG + ICPU_SPI_MST_CFG);
 	/*
@@ -85,6 +97,6 @@  int mach_cpu_init(void)
 	writel(0, BASE_CFG + ICPU_DST_INTR_MAP(1));
 	writel(0, BASE_CFG + ICPU_DST_INTR_MAP(2));
 	writel(0, BASE_CFG + ICPU_DST_INTR_MAP(3));
-
+#endif
 	return 0;
 }
diff --git a/arch/mips/mach-mscc/dram.c b/arch/mips/mach-mscc/dram.c
index 5acee6f918..309007c14e 100644
--- a/arch/mips/mach-mscc/dram.c
+++ b/arch/mips/mach-mscc/dram.c
@@ -19,9 +19,11 @@  static inline int vcoreiii_train_bytelane(void)
 
 	ret = hal_vcoreiii_train_bytelane(0);
 
+#ifdef CONFIG_SOC_OCELOT
 	if (ret)
 		return ret;
 	ret = hal_vcoreiii_train_bytelane(1);
+#endif
 
 	return ret;
 }
diff --git a/arch/mips/mach-mscc/include/mach/common.h b/arch/mips/mach-mscc/include/mach/common.h
index 842462aeed..931ecd7985 100644
--- a/arch/mips/mach-mscc/include/mach/common.h
+++ b/arch/mips/mach-mscc/include/mach/common.h
@@ -10,6 +10,10 @@ 
 #include <mach/ocelot/ocelot.h>
 #include <mach/ocelot/ocelot_devcpu_gcb.h>
 #include <mach/ocelot/ocelot_icpu_cfg.h>
+#elif defined(CONFIG_SOC_LUTON)
+#include <mach/luton/luton.h>
+#include <mach/luton/luton_devcpu_gcb.h>
+#include <mach/luton/luton_icpu_cfg.h>
 #else
 #error Unsupported platform
 #endif
diff --git a/arch/mips/mach-mscc/include/mach/ddr.h b/arch/mips/mach-mscc/include/mach/ddr.h
index 4bdea90506..97eff2a196 100644
--- a/arch/mips/mach-mscc/include/mach/ddr.h
+++ b/arch/mips/mach-mscc/include/mach/ddr.h
@@ -598,6 +598,98 @@  static inline int dram_check(void)
 	}
 	return 0;
 }
+#else				/* Luton */
+
+static inline void sleep_100ns(u32 val)
+{
+}
+
+static inline void hal_vcoreiii_ddr_reset_assert(void)
+{
+	setbits_le32(BASE_CFG + ICPU_MEMPHY_CFG, ICPU_MEMPHY_CFG_PHY_RST);
+	setbits_le32(BASE_CFG + ICPU_RESET, ICPU_RESET_MEM_RST_FORCE);
+}
+
+static inline void hal_vcoreiii_ddr_reset_release(void)
+{
+}
+
+static inline void hal_vcoreiii_ddr_failed(void)
+{
+	register u32 memphy_cfg = readl(BASE_CFG + ICPU_MEMPHY_CFG);
+
+	/* Do a fifo reset and start over */
+	writel(memphy_cfg | ICPU_MEMPHY_CFG_PHY_FIFO_RST,
+	       BASE_CFG + ICPU_MEMPHY_CFG);
+	writel(memphy_cfg & ~ICPU_MEMPHY_CFG_PHY_FIFO_RST,
+	       BASE_CFG + ICPU_MEMPHY_CFG);
+	writel(memphy_cfg | ICPU_MEMPHY_CFG_PHY_FIFO_RST,
+	       BASE_CFG + ICPU_MEMPHY_CFG);
+}
+
+static inline void hal_vcoreiii_ddr_verified(void)
+{
+}
+
+static inline int look_for(u32 data)
+{
+	register u32 byte = ((volatile u8 *)MSCC_DDR_TO)[0];
+
+	if (data != byte) {
+		if (!incr_dly(0))
+			return DDR_TRAIN_ERROR;
+		return DDR_TRAIN_CONTINUE;
+	}
+
+	return DDR_TRAIN_OK;
+}
+
+/* This algorithm is converted from the TCL training algorithm used
+ * during silicon simulation.
+ * NB: Assumes inlining as no stack is available!
+ */
+static inline int hal_vcoreiii_train_bytelane(u32 bytelane)
+{
+	register int res;
+
+	set_dly(bytelane, 0);	// Start training at DQS=0
+	while ((res = look_for(0xff)) == DDR_TRAIN_CONTINUE)
+		;
+	if (res != DDR_TRAIN_OK)
+		return res;
+
+	set_dly(bytelane, 0);	// Start training at DQS=0
+	while ((res = look_for(0x00)) == DDR_TRAIN_CONTINUE)
+
+		;
+
+	if (res != DDR_TRAIN_OK)
+		return res;
+
+	adjust_dly(-3);
+
+	return DDR_TRAIN_OK;
+}
+
+static inline int hal_vcoreiii_init_dqs(void)
+{
+	return 0;
+}
+
+static inline int dram_check(void)
+{
+#define DDR ((volatile u32 *) MSCC_DDR_TO)
+	register u32 i;
+
+	for (i = 0; i < 8; i++) {
+		DDR[i] = ~i;
+		if (DDR[i] != ~i)
+			return 1;
+	}
+
+	return 0;
+}
+#endif
 
 /*
  * NB: Called *early* to init memory controller - assumes inlining as
@@ -630,12 +722,12 @@  static inline void hal_vcoreiii_init_memctl(void)
 	/* Wait for ZCAL to clear */
 	while (readl(BASE_CFG + ICPU_MEMPHY_ZCAL) & ICPU_MEMPHY_ZCAL_ZCAL_ENA)
 		;
-
+#ifdef CONFIG_SOC_OCELOT
 	/* Check no ZCAL_ERR */
 	if (readl(BASE_CFG + ICPU_MEMPHY_ZCAL_STAT)
 	    & ICPU_MEMPHY_ZCAL_STAT_ZCAL_ERR)
 		hal_vcoreiii_ddr_failed();
-
+#endif
 	/* Drive CL, CK, ODT */
 	setbits_le32(BASE_CFG + ICPU_MEMPHY_CFG, ICPU_MEMPHY_CFG_PHY_ODT_OE |
 		     ICPU_MEMPHY_CFG_PHY_CK_OE | ICPU_MEMPHY_CFG_PHY_CL_OE);
@@ -644,7 +736,12 @@  static inline void hal_vcoreiii_init_memctl(void)
 	writel(MSCC_MEMPARM_MEMCFG, BASE_CFG + ICPU_MEMCTRL_CFG);
 	writel(MSCC_MEMPARM_PERIOD, BASE_CFG + ICPU_MEMCTRL_REF_PERIOD);
 
+#ifdef CONFIG_SOC_OCELOT
 	writel(MSCC_MEMPARM_TIMING0, BASE_CFG + ICPU_MEMCTRL_TIMING0);
+#else /* Luton */
+	clrbits_le32(BASE_CFG + ICPU_MEMCTRL_TIMING0, ((1 << 20) - 1));
+	setbits_le32(BASE_CFG + ICPU_MEMCTRL_TIMING0, MSCC_MEMPARM_TIMING0);
+#endif
 
 	writel(MSCC_MEMPARM_TIMING1, BASE_CFG + ICPU_MEMCTRL_TIMING1);
 	writel(MSCC_MEMPARM_TIMING2, BASE_CFG + ICPU_MEMCTRL_TIMING2);
@@ -654,6 +751,7 @@  static inline void hal_vcoreiii_init_memctl(void)
 	writel(MSCC_MEMPARM_MR2, BASE_CFG + ICPU_MEMCTRL_MR2_VAL);
 	writel(MSCC_MEMPARM_MR3, BASE_CFG + ICPU_MEMCTRL_MR3_VAL);
 
+#ifdef CONFIG_SOC_OCELOT
 	/* Termination setup - enable ODT */
 	writel(ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_ENA |
 	       /* Assert ODT0 for any write */
@@ -664,6 +762,11 @@  static inline void hal_vcoreiii_init_memctl(void)
 	hal_vcoreiii_ddr_reset_release();
 
 	writel(readl(BASE_CFG + ICPU_GPR(7)) + 1, BASE_CFG + ICPU_GPR(7));
+#else				/* Luton */
+	/* Termination setup - disable ODT */
+	writel(0, BASE_CFG + ICPU_MEMCTRL_TERMRES_CTRL);
+
+#endif
 }
 
 static inline void hal_vcoreiii_wait_memctl(void)
@@ -677,7 +780,7 @@  static inline void hal_vcoreiii_wait_memctl(void)
 
 	/* Settle...? */
 	sleep_100ns(10000);
-
+#ifdef CONFIG_SOC_OCELOT
 	/* Establish data contents in DDR RAM for training */
 
 	__raw_writel(0xcacafefe, ((void __iomem *)MSCC_DDR_TO));
@@ -688,5 +791,8 @@  static inline void hal_vcoreiii_wait_memctl(void)
 	__raw_writel(0xaaaa9999, ((void __iomem *)MSCC_DDR_TO + 0x14));
 	__raw_writel(0xccccbbbb, ((void __iomem *)MSCC_DDR_TO + 0x18));
 	__raw_writel(0xeeeedddd, ((void __iomem *)MSCC_DDR_TO + 0x1C));
+#else
+	__raw_writel(0xff, ((void __iomem *)MSCC_DDR_TO));
+#endif
 }
 #endif				/* __ASM_MACH_DDR_H */
diff --git a/arch/mips/mach-mscc/include/mach/luton/luton.h b/arch/mips/mach-mscc/include/mach/luton/luton.h
new file mode 100644
index 0000000000..19f02ede66
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/luton/luton.h
@@ -0,0 +1,24 @@ 
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_H_
+#define _MSCC_OCELOT_H_
+
+#include <linux/bitops.h>
+#include <dm.h>
+
+/*
+ * Target offset base(s)
+ */
+#define MSCC_IO_ORIGIN1_OFFSET 0x60000000
+#define MSCC_IO_ORIGIN1_SIZE   0x01000000
+#define MSCC_IO_ORIGIN2_OFFSET 0x70000000
+#define MSCC_IO_ORIGIN2_SIZE   0x00200000
+#define BASE_CFG        ((void __iomem *)0x70000000)
+#define BASE_DEVCPU_GCB ((void __iomem *)0x60070000)
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h b/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
new file mode 100644
index 0000000000..8c0b612325
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
@@ -0,0 +1,14 @@ 
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_DEVCPU_GCB_H_
+#define _MSCC_OCELOT_DEVCPU_GCB_H_
+
+#define PERF_SOFT_RST                                     0x90
+
+#define PERF_SOFT_RST_SOFT_SWC_RST                        BIT(1)
+#define PERF_SOFT_RST_SOFT_CHIP_RST                       BIT(0)
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h b/arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h
new file mode 100644
index 0000000000..9233f037bb
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h
@@ -0,0 +1,245 @@ 
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_ICPU_CFG_H_
+#define _MSCC_OCELOT_ICPU_CFG_H_
+
+#define ICPU_GPR(x) (0x4 * (x))
+#define ICPU_GPR_RSZ                                      0x4
+
+#define ICPU_RESET                                        0x20
+
+#define ICPU_RESET_CORE_RST_CPU_ONLY                      BIT(3)
+#define ICPU_RESET_CORE_RST_PROTECT                       BIT(2)
+#define ICPU_RESET_CORE_RST_FORCE                         BIT(1)
+#define ICPU_RESET_MEM_RST_FORCE                          BIT(0)
+
+#define ICPU_GENERAL_CTRL                                 0x24
+
+#define ICPU_GENERAL_CTRL_SWC_CLEAR_IF                    BIT(6)
+#define ICPU_GENERAL_CTRL_CPU_BUSIF_SLEEP_DIS             BIT(5)
+#define ICPU_GENERAL_CTRL_CPU_BUSIF_WERR_ENA              BIT(4)
+#define ICPU_GENERAL_CTRL_IF_MASTER_DIS                   BIT(3)
+#define ICPU_GENERAL_CTRL_IF_MASTER_SPI_ENA               BIT(2)
+#define ICPU_GENERAL_CTRL_IF_MASTER_PI_ENA                BIT(1)
+
+#define ICPU_GENERAL_CTRL_BOOT_MODE_ENA                   BIT(0)
+
+#define ICPU_PI_MST_CFG                                   0x2c
+
+#define ICPU_PI_MST_CFG_ATE_MODE_DIS                      BIT(7)
+#define ICPU_PI_MST_CFG_CLK_POL                           BIT(6)
+#define ICPU_PI_MST_CFG_TRISTATE_CTRL                     BIT(5)
+#define ICPU_PI_MST_CFG_CLK_DIV(x)                        ((x) & GENMASK(4, 0))
+#define ICPU_PI_MST_CFG_CLK_DIV_M                         GENMASK(4, 0)
+
+#define ICPU_SPI_MST_CFG                                  0x50
+
+#define ICPU_SPI_MST_CFG_FAST_READ_ENA                    BIT(10)
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME(x)              (((x) << 5) & GENMASK(9, 5))
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME_M               GENMASK(9, 5)
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME_X(x)            (((x) & GENMASK(9, 5)) >> 5)
+#define ICPU_SPI_MST_CFG_CLK_DIV(x)                       ((x) & GENMASK(4, 0))
+#define ICPU_SPI_MST_CFG_CLK_DIV_M                        GENMASK(4, 0)
+
+#define ICPU_SW_MODE                                      0x64
+
+#define ICPU_SW_MODE_SW_PIN_CTRL_MODE                     BIT(13)
+#define ICPU_SW_MODE_SW_SPI_SCK                           BIT(12)
+#define ICPU_SW_MODE_SW_SPI_SCK_OE                        BIT(11)
+#define ICPU_SW_MODE_SW_SPI_SDO                           BIT(10)
+#define ICPU_SW_MODE_SW_SPI_SDO_OE                        BIT(9)
+#define ICPU_SW_MODE_SW_SPI_CS(x)                         (((x) << 5) & GENMASK(8, 5))
+#define ICPU_SW_MODE_SW_SPI_CS_M                          GENMASK(8, 5)
+#define ICPU_SW_MODE_SW_SPI_CS_X(x)                       (((x) & GENMASK(8, 5)) >> 5)
+#define ICPU_SW_MODE_SW_SPI_CS_OE(x)                      (((x) << 1) & GENMASK(4, 1))
+#define ICPU_SW_MODE_SW_SPI_CS_OE_M                       GENMASK(4, 1)
+#define ICPU_SW_MODE_SW_SPI_CS_OE_X(x)                    (((x) & GENMASK(4, 1)) >> 1)
+#define ICPU_SW_MODE_SW_SPI_SDI                           BIT(0)
+
+#define ICPU_INTR_ENA                                     0x88
+
+#define ICPU_INTR_IRQ0_ENA                                0x98
+#define ICPU_INTR_IRQ0_ENA_IRQ0_ENA                       BIT(0)
+
+#define ICPU_MEMCTRL_CTRL                                 0x234
+
+#define ICPU_MEMCTRL_CTRL_PWR_DOWN                        BIT(3)
+#define ICPU_MEMCTRL_CTRL_MDSET                           BIT(2)
+#define ICPU_MEMCTRL_CTRL_STALL_REF_ENA                   BIT(1)
+#define ICPU_MEMCTRL_CTRL_INITIALIZE                      BIT(0)
+
+#define ICPU_MEMCTRL_CFG                                  0x238
+
+#define ICPU_MEMCTRL_CFG_DDR_512MBYTE_PLUS                BIT(16)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_ERR_ENA                  BIT(15)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_COR_ENA                  BIT(14)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_ENA                      BIT(13)
+#define ICPU_MEMCTRL_CFG_DDR_WIDTH                        BIT(12)
+#define ICPU_MEMCTRL_CFG_DDR_MODE                         BIT(11)
+#define ICPU_MEMCTRL_CFG_BURST_SIZE                       BIT(10)
+#define ICPU_MEMCTRL_CFG_BURST_LEN                        BIT(9)
+#define ICPU_MEMCTRL_CFG_BANK_CNT                         BIT(8)
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR(x)                  (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR_M                   GENMASK(7, 4)
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR_X(x)                (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_CFG_MSB_COL_ADDR(x)                  ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_CFG_MSB_COL_ADDR_M                   GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_STAT                                 0x23C
+
+#define ICPU_MEMCTRL_STAT_RDATA_MASKED                    BIT(5)
+#define ICPU_MEMCTRL_STAT_RDATA_DUMMY                     BIT(4)
+#define ICPU_MEMCTRL_STAT_RDATA_ECC_ERR                   BIT(3)
+#define ICPU_MEMCTRL_STAT_RDATA_ECC_COR                   BIT(2)
+#define ICPU_MEMCTRL_STAT_PWR_DOWN_ACK                    BIT(1)
+#define ICPU_MEMCTRL_STAT_INIT_DONE                       BIT(0)
+
+#define ICPU_MEMCTRL_REF_PERIOD                           0x240
+
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF(x)           (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF_M            GENMASK(19, 16)
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF_X(x)         (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD(x)             ((x) & GENMASK(15, 0))
+#define ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD_M              GENMASK(15, 0)
+
+#define ICPU_MEMCTRL_TIMING0                              0x248
+
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY(x)              (((x) << 28) & GENMASK(31, 28))
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY_M               GENMASK(31, 28)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY_X(x)            (((x) & GENMASK(31, 28)) >> 28)
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY(x)          (((x) << 24) & GENMASK(27, 24))
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY_M           GENMASK(27, 24)
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY_X(x)        (((x) & GENMASK(27, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY(x)          (((x) << 20) & GENMASK(23, 20))
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY_M           GENMASK(23, 20)
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY_X(x)        (((x) & GENMASK(23, 20)) >> 20)
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY(x)          (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY_M           GENMASK(19, 16)
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY_X(x)        (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY(x)           (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY_M            GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY_X(x)         (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY(x)           (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY_M            GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY_X(x)         (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY(x)           (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY_M            GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY_X(x)         (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY(x)           ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY_M            GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_TIMING1                              0x24c
+
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY(x)  (((x) << 24) & GENMASK(31, 24))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY_M   GENMASK(31, 24)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY_X(x) (((x) & GENMASK(31, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY(x)             (((x) << 16) & GENMASK(23, 16))
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY_M              GENMASK(23, 16)
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY_X(x)           (((x) & GENMASK(23, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY(x)          (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY_M           GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY_X(x)        (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY(x)            (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY_M             GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY_X(x)          (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY(x)            (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY_M             GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY_X(x)          (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY(x)              ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY_M               GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_TIMING2                              0x250
+
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY(x)             (((x) << 28) & GENMASK(31, 28))
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY_M              GENMASK(31, 28)
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY_X(x)           (((x) & GENMASK(31, 28)) >> 28)
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY(x)                 (((x) << 24) & GENMASK(27, 24))
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY_M                  GENMASK(27, 24)
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY_X(x)               (((x) & GENMASK(27, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING2_REF_DLY(x)                   (((x) << 16) & GENMASK(23, 16))
+#define ICPU_MEMCTRL_TIMING2_REF_DLY_M                    GENMASK(23, 16)
+#define ICPU_MEMCTRL_TIMING2_REF_DLY_X(x)                 (((x) & GENMASK(23, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING2_FOUR_HUNDRED_NS_DLY(x)       ((x) & GENMASK(15, 0))
+#define ICPU_MEMCTRL_TIMING2_FOUR_HUNDRED_NS_DLY_M        GENMASK(15, 0)
+
+#define ICPU_MEMCTRL_TIMING3                              0x254
+
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY(x)                   (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY_M                    GENMASK(19, 16)
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY_X(x)                 (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY(x)                (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY_M                 GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY_X(x)              (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY(x)                (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY_M                 GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY_X(x)              (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY(x)          (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY_M           GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY_X(x)        (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY(x)    ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY_M     GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_MR0_VAL                              0x258
+
+#define ICPU_MEMCTRL_MR1_VAL                              0x25c
+
+#define ICPU_MEMCTRL_MR2_VAL                              0x260
+
+#define ICPU_MEMCTRL_MR3_VAL                              0x264
+
+#define ICPU_MEMCTRL_TERMRES_CTRL                         0x268
+
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_EXT              BIT(11)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA(x)           (((x) << 7) & GENMASK(10, 7))
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA_M            GENMASK(10, 7)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA_X(x)         (((x) & GENMASK(10, 7)) >> 7)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_EXT              BIT(6)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA(x)           (((x) << 2) & GENMASK(5, 2))
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA_M            GENMASK(5, 2)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA_X(x)         (((x) & GENMASK(5, 2)) >> 2)
+#define ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_EXT        BIT(1)
+#define ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_ENA        BIT(0)
+
+#define ICPU_MEMCTRL_DQS_DLY(x) (0x270)
+
+#define ICPU_MEMCTRL_DQS_DLY_TRAIN_DQ_ENA                 BIT(11)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1(x)              (((x) << 8) & GENMASK(10, 8))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1_M               GENMASK(10, 8)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1_X(x)            (((x) & GENMASK(10, 8)) >> 8)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0(x)              (((x) << 5) & GENMASK(7, 5))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0_M               GENMASK(7, 5)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0_X(x)            (((x) & GENMASK(7, 5)) >> 5)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY(x)                   ((x) & GENMASK(4, 0))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_M                    GENMASK(4, 0)
+
+#define ICPU_MEMPHY_CFG                                   0x278
+
+#define ICPU_MEMPHY_CFG_PHY_FLUSH_DIS                     BIT(10)
+#define ICPU_MEMPHY_CFG_PHY_RD_ADJ_DIS                    BIT(9)
+#define ICPU_MEMPHY_CFG_PHY_DQS_EXT                       BIT(8)
+#define ICPU_MEMPHY_CFG_PHY_FIFO_RST                      BIT(7)
+#define ICPU_MEMPHY_CFG_PHY_DLL_BL_RST                    BIT(6)
+#define ICPU_MEMPHY_CFG_PHY_DLL_CL_RST                    BIT(5)
+#define ICPU_MEMPHY_CFG_PHY_ODT_OE                        BIT(4)
+#define ICPU_MEMPHY_CFG_PHY_CK_OE                         BIT(3)
+#define ICPU_MEMPHY_CFG_PHY_CL_OE                         BIT(2)
+#define ICPU_MEMPHY_CFG_PHY_SSTL_ENA                      BIT(1)
+#define ICPU_MEMPHY_CFG_PHY_RST                           BIT(0)
+#define ICPU_MEMPHY_DQ_DLY_TRM                            0x180
+#define ICPU_MEMPHY_DQ_DLY_TRM_RSZ                        0x4
+
+#define ICPU_MEMPHY_ZCAL                                  0x294
+
+#define ICPU_MEMPHY_ZCAL_ZCAL_CLK_SEL                     BIT(9)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT(x)                 (((x) << 5) & GENMASK(8, 5))
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT_M                  GENMASK(8, 5)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT_X(x)               (((x) & GENMASK(8, 5)) >> 5)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG(x)                     (((x) << 1) & GENMASK(4, 1))
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_M                      GENMASK(4, 1)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_X(x)                   (((x) & GENMASK(4, 1)) >> 1)
+#define ICPU_MEMPHY_ZCAL_ZCAL_ENA                         BIT(0)
+
+#endif
diff --git a/arch/mips/mach-mscc/lowlevel_init.S b/arch/mips/mach-mscc/lowlevel_init.S
index 8e4f0d02c8..1624bd6f55 100644
--- a/arch/mips/mach-mscc/lowlevel_init.S
+++ b/arch/mips/mach-mscc/lowlevel_init.S
@@ -8,6 +8,9 @@ 
 
     .set noreorder
     .extern     vcoreiii_tlb_init
+#ifdef CONFIG_SOC_LUTON
+    .extern     pll_init
+#endif
 
 LEAF(lowlevel_init)
 	/*
@@ -18,6 +21,10 @@  LEAF(lowlevel_init)
 
 	jal	vcoreiii_tlb_init
 	nop
+#ifdef CONFIG_SOC_LUTON
+	jal	pll_init
+	nop
+#endif
 	jr	s0
 	nop
 	END(lowlevel_init)
diff --git a/arch/mips/mach-mscc/lowlevel_init_luton.S b/arch/mips/mach-mscc/lowlevel_init_luton.S
new file mode 100644
index 0000000000..6b298a99da
--- /dev/null
+++ b/arch/mips/mach-mscc/lowlevel_init_luton.S
@@ -0,0 +1,62 @@ 
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#define BASE_MACRO      0x600a0000
+#define REG_OFFSET(t, o) (t + (o*4))
+#define REG_MACRO(x) REG_OFFSET(BASE_MACRO, x)
+#define BIT(nr)			(1 << (nr))
+
+#define MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0 REG_MACRO(6)
+#define MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0_LOCK_STATUS BIT(0)
+#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2 REG_MACRO(2)
+#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0 REG_MACRO(0)
+#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV (0x3F << 6)
+#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV_ENC(x) (x << 6)
+
+    .set noreorder
+LEAF(pll_init)
+	/* Make sure PLL is locked */
+	lw	v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0
+	andi	v1, v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0_LOCK_STATUS
+	bne	v1, zero, 1f
+	 nop
+
+	/* Black magic from frontend */
+	li	v1, 0x00610400
+	sw	v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
+
+	li	v1, 0x00610c00
+	sw	v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
+
+	li	v1, 0x00610800
+	sw	v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
+
+	li	v1, 0x00610000
+	sw	v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
+
+	/* Wait for lock */
+2:	lw	v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0
+	andi	v1, v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0_LOCK_STATUS
+	# Keep looping if zero (no lock bit yet)
+	beq	v1, zero, 2b
+	 nop
+
+	/* Setup PLL CPU clock divider for 416MHz */
+1:	lw	v0, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0
+
+	/* Keep reserved bits */
+	li	v1, ~MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV
+	and	v0, v0, v1
+
+	/* Set code 6 ~ 416.66 MHz */
+	ori	v0, v0, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV_ENC(6)
+
+	sw	v0, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0
+	jr      ra
+	 nop
+	END(pll_init)