From mboxrd@z Thu Jan 1 00:00:00 1970 From: Diana Craciun Date: Tue, 3 Jun 2014 17:36:44 +0300 Subject: [U-Boot] [PATCH 1/9] arm: ls102xa: Add Freescale LS102xA SoC support In-Reply-To: <1401434582-18032-2-git-send-email-b18965@freescale.com> References: <1401434582-18032-1-git-send-email-b18965@freescale.com> <1401434582-18032-2-git-send-email-b18965@freescale.com> Message-ID: <538DDD7C.4060801@freescale.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 05/30/2014 10:22 AM, Alison Wang wrote: > The QorIQ LS1 family is built on Layerscape architecture, > the industry's first software-aware, core-agnostic networking > architecture to offer unprecedented efficiency and scale. > > Freescale LS102xA is a set of SoCs combines two ARM > Cortex-A7 cores that have been optimized for high > reliability and pack the highest level of integration > available for sub-3 W embedded communications processors > with Layerscape architecture and with a comprehensive > enablement model focused on ease of programmability. > > Signed-off-by: Alison Wang > Signed-off-by: Jason Jin > Signed-off-by: Jingchang Lu > Signed-off-by: Prabhakar Kushwaha > --- > arch/arm/cpu/armv7/ls102xa/Makefile | 11 + > arch/arm/cpu/armv7/ls102xa/clock.c | 131 +++++++ > arch/arm/cpu/armv7/ls102xa/cpu.c | 102 ++++++ > arch/arm/cpu/armv7/ls102xa/fdt.c | 82 +++++ > arch/arm/cpu/armv7/ls102xa/timer.c | 129 +++++++ > arch/arm/include/asm/arch-ls102xa/clock.h | 23 ++ > arch/arm/include/asm/arch-ls102xa/config.h | 70 ++++ > arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h | 420 ++++++++++++++++++++++ > arch/arm/include/asm/arch-ls102xa/imx-regs.h | 53 +++ > arch/arm/include/asm/config.h | 4 + > arch/arm/include/asm/io.h | 8 +- > drivers/watchdog/Makefile | 2 +- > 12 files changed, 1033 insertions(+), 2 deletions(-) > create mode 100644 arch/arm/cpu/armv7/ls102xa/Makefile > create mode 100644 arch/arm/cpu/armv7/ls102xa/clock.c > create mode 100644 arch/arm/cpu/armv7/ls102xa/cpu.c > create mode 100644 arch/arm/cpu/armv7/ls102xa/fdt.c > create mode 100644 arch/arm/cpu/armv7/ls102xa/timer.c > create mode 100644 arch/arm/include/asm/arch-ls102xa/clock.h > create mode 100644 arch/arm/include/asm/arch-ls102xa/config.h > create mode 100644 arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h > create mode 100644 arch/arm/include/asm/arch-ls102xa/imx-regs.h > > diff --git a/arch/arm/cpu/armv7/ls102xa/Makefile b/arch/arm/cpu/armv7/ls102xa/Makefile > new file mode 100644 > index 0000000..7ef793a > --- /dev/null > +++ b/arch/arm/cpu/armv7/ls102xa/Makefile > @@ -0,0 +1,11 @@ > +# > +# Copyright 2014 Freescale Semiconductor, Inc. > +# > +# SPDX-License-Identifier: GPL-2.0+ > +# > + > +obj-y += cpu.o > +obj-y += clock.o > +obj-y += timer.o > + > +obj-$(CONFIG_OF_LIBFDT) += fdt.o > diff --git a/arch/arm/cpu/armv7/ls102xa/clock.c b/arch/arm/cpu/armv7/ls102xa/clock.c > new file mode 100644 > index 0000000..75bb0e9 > --- /dev/null > +++ b/arch/arm/cpu/armv7/ls102xa/clock.c > @@ -0,0 +1,131 @@ > +/* > + * Copyright 2014 Freescale Semiconductor, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +DECLARE_GLOBAL_DATA_PTR; > + > +#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS > +#define CONFIG_SYS_FSL_NUM_CC_PLLS 2 > +#endif > + > +void get_sys_info(struct sys_info *sys_info) > +{ > + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); > +#ifdef CONFIG_FSL_IFC > + struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR; > + u32 ccr; > +#endif > + struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_LS1_CLK_ADDR); > + unsigned int cpu; > + const u8 core_cplx_pll[6] = { > + [0] = 0, /* CC1 PPL / 1 */ > + [1] = 0, /* CC1 PPL / 2 */ > + [4] = 1, /* CC2 PPL / 1 */ > + [5] = 1, /* CC2 PPL / 2 */ > + }; > + > + const u8 core_cplx_pll_div[6] = { > + [0] = 1, /* CC1 PPL / 1 */ > + [1] = 2, /* CC1 PPL / 2 */ > + [4] = 1, /* CC2 PPL / 1 */ > + [5] = 2, /* CC2 PPL / 2 */ > + }; > + > + uint i; > + uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS]; > + uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS]; > + unsigned long sysclk = CONFIG_SYS_CLK_FREQ; > + > + sys_info->freq_systembus = sysclk; > +#ifdef CONFIG_DDR_CLK_FREQ > + sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ; > +#else > + sys_info->freq_ddrbus = sysclk; > +#endif > + > + sys_info->freq_systembus *= (in_be32(&gur->rcwsr[0]) >> > + RCWSR0_SYS_PLL_RAT_SHIFT) & RCWSR0_SYS_PLL_RAT_MASK; > + sys_info->freq_ddrbus *= (in_be32(&gur->rcwsr[0]) >> > + RCWSR0_MEM_PLL_RAT_SHIFT) & RCWSR0_MEM_PLL_RAT_MASK; > + > + for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) { > + ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0x3f; > + if (ratio[i] > 4) > + freq_c_pll[i] = sysclk * ratio[i]; > + else > + freq_c_pll[i] = sys_info->freq_systembus * ratio[i]; > + } > + > + for (cpu = 0; cpu < CONFIG_MAX_CPUS; cpu++) { > + u32 c_pll_sel = (in_be32(&clk->clkcsr[cpu].clkcncsr) >> 27) > + & 0xf; > + u32 cplx_pll = core_cplx_pll[c_pll_sel]; > + > + sys_info->freq_processor[cpu] = > + freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel]; > + } > + > +#if defined(CONFIG_FSL_IFC) > + ccr = in_be32(&ifc_regs->ifc_ccr); > + ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1; > + > + sys_info->freq_localbus = sys_info->freq_systembus / ccr; > +#endif > +} > + > + > +int get_clocks(void) > +{ > + struct sys_info sys_info; > + > + get_sys_info(&sys_info); > + gd->cpu_clk = sys_info.freq_processor[0]; > + gd->bus_clk = sys_info.freq_systembus; > + gd->mem_clk = sys_info.freq_ddrbus * 2; > + > +#if defined(CONFIG_FSL_ESDHC) > + gd->arch.sdhc_clk = gd->bus_clk; > +#endif > + > + return 0; > +} > + > +ulong get_bus_freq(ulong dummy) > +{ > + return gd->bus_clk; > +} > + > +ulong get_ddr_freq(ulong dummy) > +{ > + return gd->mem_clk; > +} > + > +int get_serial_clock(void) > +{ > + return gd->bus_clk / 2; > +} > + > +unsigned int mxc_get_clock(enum mxc_clock clk) > +{ > + switch (clk) { > + case MXC_I2C_CLK: > + return get_bus_freq(0) / 2; > + case MXC_ESDHC_CLK: > + return get_bus_freq(0); > + case MXC_DSPI_CLK: > + return get_bus_freq(0) / 2; > + case MXC_UART_CLK: > + return get_bus_freq(0) / 2; > + default: > + printf("Unsupported clock\n"); > + } > + return 0; > +} > diff --git a/arch/arm/cpu/armv7/ls102xa/cpu.c b/arch/arm/cpu/armv7/ls102xa/cpu.c > new file mode 100644 > index 0000000..72d198f > --- /dev/null > +++ b/arch/arm/cpu/armv7/ls102xa/cpu.c > @@ -0,0 +1,102 @@ > +/* > + * Copyright 2014 Freescale Semiconductor, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +DECLARE_GLOBAL_DATA_PTR; > + > +#if defined(CONFIG_DISPLAY_CPUINFO) > +int print_cpuinfo(void) > +{ > + char buf[32]; > + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); > + unsigned int svr, major, minor, ver, i; > + > + svr = in_be32(&gur->svr); > + major = SVR_MAJ(svr); > + minor = SVR_MIN(svr); > + > + puts("CPU: Freescale LayerScape "); > + > + ver = SVR_SOC_VER(svr); > + switch (ver) { > + case SOC_VER_SLS1020: > + puts("SLS1020"); > + break; > + case SOC_VER_LS1020: > + puts("LS1020"); > + break; > + case SOC_VER_LS1021: > + puts("LS1021"); > + break; > + case SOC_VER_LS1022: > + puts("LS1022"); > + break; > + default: > + puts("Unknown"); > + break; > + } > + > + if (IS_E_PROCESSOR(svr) && (ver != SOC_VER_SLS1020)) > + puts("E"); > + > + printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr); > + > + puts("Clock Configuration:"); > + > + printf("\n CPU0(ARMV7):%-4s MHz, ", strmhz(buf, gd->cpu_clk)); > + printf("\n Bus:%-4s MHz, ", strmhz(buf, gd->bus_clk)); > + printf("DDR:%-4s MHz, ", strmhz(buf, gd->mem_clk)); > + puts("\n"); > + > + /* Display the RCW, so that no one gets confused as to what RCW > + * we're actually using for this boot. > + */ > + puts("Reset Configuration Word (RCW):"); > + for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) { > + u32 rcw = in_be32(&gur->rcwsr[i]); > + > + if ((i % 4) == 0) > + printf("\n %08x:", i * 4); > + printf(" %08x", rcw); > + } > + puts("\n"); > + > + return 0; > +} > +#endif > + > +void enable_caches(void) > +{ > +#ifndef CONFIG_SYS_ICACHE_OFF > + icache_enable(); > +#endif > +#ifndef CONFIG_SYS_DCACHE_OFF > + dcache_enable(); > +#endif > +} > + > +#ifdef CONFIG_FSL_ESDHC > +int cpu_mmc_init(bd_t *bis) > +{ > + return fsl_esdhc_mmc_init(bis); > +} > +#endif > + > +int cpu_eth_init(bd_t *bis) > +{ > +#ifdef CONFIG_TSEC_ENET > + tsec_standard_init(bis); > +#endif > + > + return 0; > +} > diff --git a/arch/arm/cpu/armv7/ls102xa/fdt.c b/arch/arm/cpu/armv7/ls102xa/fdt.c > new file mode 100644 > index 0000000..042d457 > --- /dev/null > +++ b/arch/arm/cpu/armv7/ls102xa/fdt.c > @@ -0,0 +1,82 @@ > +/* > + * Copyright 2014 Freescale Semiconductor, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#ifdef CONFIG_FSL_ESDHC > +#include > +#endif > + > +DECLARE_GLOBAL_DATA_PTR; > + > +void fdt_add_enet_stashing(void *fdt) > +{ > + do_fixup_by_compat(fdt, "fsl,etsec2", "bd-stash", NULL, 0, 1); > + do_fixup_by_compat_u32(fdt, "fsl,etsec2", "rx-stash-len", 96, 1); > + do_fixup_by_compat_u32(fdt, "fsl,etsec2", "rx-stash-idx", 0, 1); > +} > + > +void ft_cpu_setup(void *blob, bd_t *bd) > +{ > + int off; > + int val; > + unsigned long busclk = get_bus_freq(0); > + > + fdt_fixup_ethernet(blob); > + > + fdt_add_enet_stashing(blob); > + > + off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); > + while (off != -FDT_ERR_NOTFOUND) { > + val = gd->cpu_clk; > + fdt_setprop(blob, off, "clock-frequency", &val, 4); > + off = fdt_node_offset_by_prop_value(blob, off, > + "device_type", "cpu", 4); > + } > + > + do_fixup_by_prop_u32(blob, > + "device_type", "soc", 4, "bus-frequency", busclk / 2, 1); > + > +#ifdef CONFIG_SYS_NS16550 > + do_fixup_by_compat_u32(blob, "ns16550", > + "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); > +#endif > + > + do_fixup_by_compat_u32(blob, "fsl,sys-clock", > + "clock-frequency", CONFIG_SYS_CLK_FREQ, 1); > + > +#if defined(CONFIG_FSL_ESDHC) > + fdt_fixup_esdhc(blob, bd); > +#endif > + > + /* > + * platform bus clock = system bus clock/2 > + * Here busclk = system bus clock > + * We are using the platform bus clock as 1588 Timer reference > + * clock source select > + */ > + do_fixup_by_compat_u32(blob, "fsl,gianfar-ptp-timer", > + "timer-frequency", busclk / 2, 1); > + > + /* > + * clock-freq should change to clock-frequency and > + * flexcan-v1.0 should change to p1010-flexcan respectively > + * in the future. > + */ > + do_fixup_by_compat_u32(blob, "fsl,flexcan-v1.0", > + "clock_freq", busclk / 2, 1); > + > + do_fixup_by_compat_u32(blob, "fsl,flexcan-v1.0", > + "clock-frequency", busclk / 2, 1); > + > + do_fixup_by_compat_u32(blob, "fsl,p1010-flexcan", > + "clock-frequency", busclk / 2, 1); > +} > diff --git a/arch/arm/cpu/armv7/ls102xa/timer.c b/arch/arm/cpu/armv7/ls102xa/timer.c > new file mode 100644 > index 0000000..db5eb65 > --- /dev/null > +++ b/arch/arm/cpu/armv7/ls102xa/timer.c > @@ -0,0 +1,129 @@ > +/* > + * Copyright 2014 Freescale Semiconductor, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +DECLARE_GLOBAL_DATA_PTR; > + > +/* > + * This function is intended for SHORT delays only. > + * It will overflow at around 10 seconds @ 400MHz, > + * or 20 seconds @ 200MHz. > + */ > +unsigned long usec2ticks(unsigned long usec) > +{ > + ulong ticks; > + > + if (usec < 1000) > + ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000; > + else > + ticks = ((usec / 10) * (get_tbclk() / 100000)); > + > + return ticks; > +} > + > +static inline unsigned long long tick_to_time(unsigned long long tick) > +{ > + unsigned long freq; > + > + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq)); > + > + tick *= CONFIG_SYS_HZ; > + do_div(tick, freq); > + > + return tick; > +} > + > +static inline unsigned long long us_to_tick(unsigned long long usec) > +{ > + unsigned long freq; > + > + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq)); > + > + usec = usec * freq + 999999; > + do_div(usec, 1000000); > + > + return usec; > +} > + > +int timer_init(void) > +{ > + struct sctr_regs *sctr = (struct sctr_regs *)SCTR_BASE_ADDR; > + unsigned long ctrl, val, freq; > + > + /* Enable System Counter */ > + writel(SYS_COUNTER_CTRL_ENABLE, &sctr->cntcr); > + > + freq = GENERIC_TIMER_CLK; > + asm("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq)); > + > + /* Set PL1 Physical Timer Ctrl */ > + ctrl = ARCH_TIMER_CTRL_ENABLE; > + asm("mcr p15, 0, %0, c14, c2, 1" : : "r" (ctrl)); > + > + /* Set PL1 Physical Comp Value */ > + val = TIMER_COMP_VAL; > + asm("mcrr p15, 2, %Q0, %R0, c14" : : "r" (val)); > + > + gd->arch.tbl = 0; > + gd->arch.tbu = 0; > + > + return 0; > +} > + > +unsigned long long get_ticks(void) > +{ > + unsigned long long now; > + > + asm("mrrc p15, 0, %Q0, %R0, c14" : "=r" (now)); > + > + /* increment tbu if tbl has rolled over */ > + if (now < gd->arch.tbl) > + gd->arch.tbu++; > + gd->arch.tbl = now; > + > + return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl; > +} > + > +unsigned long get_timer_masked(void) > +{ > + return tick_to_time(get_ticks()); > +} > + > +unsigned long get_timer(ulong base) > +{ > + return get_timer_masked() - base; > +} > + > +/* delay x useconds and preserve advance timstamp value */ > +void __udelay(unsigned long usec) > +{ > + unsigned long long start; > + unsigned long tmo; > + > + start = get_ticks(); /* get current timestamp */ > + tmo = us_to_tick(usec); /* convert usecs to ticks */ > + > + while ((get_ticks() - start) < tmo) > + ; /* loop till time has passed */ > +} > + > +/* > + * This function is derived from PowerPC code (timebase clock frequency). > + * On ARM it returns the number of timer ticks per second. > + */ > +unsigned long get_tbclk(void) > +{ > + unsigned long freq; > + > + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq)); > + > + return freq; > +} > diff --git a/arch/arm/include/asm/arch-ls102xa/clock.h b/arch/arm/include/asm/arch-ls102xa/clock.h > new file mode 100644 > index 0000000..fd36bb0 > --- /dev/null > +++ b/arch/arm/include/asm/arch-ls102xa/clock.h > @@ -0,0 +1,23 @@ > +/* > + * Copyright 2014 Freescale Semiconductor, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + * > + */ > + > +#ifndef __ASM_ARCH_LS102XA_CLOCK_H_ > +#define __ASM_ARCH_LS102XA_CLOCK_H_ > + > +#include > + > +enum mxc_clock { > + MXC_ARM_CLK = 0, > + MXC_UART_CLK, > + MXC_ESDHC_CLK, > + MXC_I2C_CLK, > + MXC_DSPI_CLK, > +}; > + > +unsigned int mxc_get_clock(enum mxc_clock clk); > + > +#endif /* __ASM_ARCH_LS102XA_CLOCK_H_ */ > diff --git a/arch/arm/include/asm/arch-ls102xa/config.h b/arch/arm/include/asm/arch-ls102xa/config.h > new file mode 100644 > index 0000000..2e90c94 > --- /dev/null > +++ b/arch/arm/include/asm/arch-ls102xa/config.h > @@ -0,0 +1,70 @@ > +/* > + * Copyright 2014, Freescale Semiconductor > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef _ASM_ARMV7_LS102xA_CONFIG_ > +#define _ASM_ARMV7_LS102xA_CONFIG_ > + > +#define CONFIG_SYS_IMMR 0x01000000 > + > +#define CONFIG_SYS_FSL_DDR_ADDR (CONFIG_SYS_IMMR + 0x00080000) > +#define CONFIG_SYS_IFC_ADDR (CONFIG_SYS_IMMR + 0x00530000) > +#define CONFIG_SYS_FSL_ESDHC_ADDR (CONFIG_SYS_IMMR + 0x00560000) > +#define CONFIG_SYS_FSL_SCFG_ADDR (CONFIG_SYS_IMMR + 0x00570000) > +#define CONFIG_SYS_FSL_SERDES_ADDR (CONFIG_SYS_IMMR + 0x00ea0000) > +#define CONFIG_SYS_FSL_GUTS_ADDR (CONFIG_SYS_IMMR + 0x00ee0000) > +#define CONFIG_SYS_FSL_LS1_CLK_ADDR (CONFIG_SYS_IMMR + 0x00ee1000) > +#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_IMMR + 0x011c0500) > +#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_IMMR + 0x011d0500) > + > +#define CONFIG_SYS_CCI400_ADDR 0x01180000 > + > +#define CONFIG_SYS_TSEC1_OFFSET 0x01d10000 > +#define CONFIG_SYS_TSEC2_OFFSET 0x01d50000 > +#define CONFIG_SYS_TSEC3_OFFSET 0x01d90000 > +#define CONFIG_SYS_MDIO1_OFFSET 0x01d24000 > + > +#define TSEC_BASE_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_TSEC1_OFFSET) > +#define MDIO_BASE_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MDIO1_OFFSET) > + > +#define CONFIG_SYS_FSL_ESDHC_ADDR (CONFIG_SYS_IMMR + 0x00560000) > + > +#define SCTR_BASE_ADDR (CONFIG_SYS_IMMR + 0x01b00000) > + > +#define I2C1_BASE_ADDR (CONFIG_SYS_IMMR + 0x01180000) > +#define I2C2_BASE_ADDR (CONFIG_SYS_IMMR + 0x01190000) > +#define I2C3_BASE_ADDR (CONFIG_SYS_IMMR + 0x011a0000) > + > +#define WDOG1_BASE_ADDR (CONFIG_SYS_IMMR + 0x01ad0000) > + > +#define QSPI0_BASE_ADDR (CONFIG_SYS_IMMR + 0x00550000) > +#define DSPI1_BASE_ADDR (CONFIG_SYS_IMMR + 0x01100000) > + > +#define LPUART_BASE (CONFIG_SYS_IMMR + 0x01950000) > + > +#define CONFIG_SYS_FSL_DDR_BE > +#define CONFIG_VERY_BIG_RAM > +#define CONFIG_SYS_FSL_DDRC_ARM_GEN3 > +#define CONFIG_SYS_FSL_DDR > +#define CONFIG_SYS_LS1_DDR_BLOCK1_SIZE ((phys_size_t)2 << 30) > +#define CONFIG_MAX_MEM_MAPPED CONFIG_SYS_LS1_DDR_BLOCK1_SIZE > + > +#define CONFIG_SYS_FSL_IFC_BE > +#define CONFIG_SYS_FSL_ESDHC_BE > +#define CONFIG_SYS_FSL_WDOG_BE > +#define CONFIG_SYS_FSL_DSPI_BE > +#define CONFIG_SYS_FSL_QSPI_BE > + > +#define CONFIG_SYS_FSL_SRDS_1 > + What about CONFIG_ARMV7_VIRT? This config allows the kernel to be entered in the HYP mode which is a prerequisite for running KVM which we need to support. Diana