diff options
author | 2015-08-28 09:58:54 +0800 | |
---|---|---|
committer | 2015-09-01 12:44:00 +0800 | |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/u-boot/arch/arm/cpu | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/arch/arm/cpu')
458 files changed, 74962 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/arch/arm/cpu/Makefile b/qemu/roms/u-boot/arch/arm/cpu/Makefile new file mode 100644 index 000000000..35d8d387b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_AT91FAMILY) += at91-common/ +obj-$(CONFIG_TEGRA20) += tegra20-common/ +obj-$(CONFIG_TEGRA30) += tegra30-common/ +obj-$(CONFIG_TEGRA114) += tegra114-common/ +obj-$(CONFIG_TEGRA124) += tegra124-common/ +obj-$(CONFIG_TEGRA) += tegra-common/ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm1136/Makefile new file mode 100644 index 000000000..3279f125f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y = start.o +obj-y = cpu.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/config.mk b/qemu/roms/u-boot/arch/arm/cpu/arm1136/config.mk new file mode 100644 index 000000000..a82c6cec9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/config.mk @@ -0,0 +1,9 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# Make ARMv5 to allow more compilers to work, even though its v6. +PLATFORM_CPPFLAGS += -march=armv5 diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm1136/cpu.c new file mode 100644 index 000000000..a7aed4b2b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/cpu.c @@ -0,0 +1,160 @@ +/* + * (C) Copyright 2004 Texas Insturments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +static void cache_flush(void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + disable_interrupts (); + +#ifdef CONFIG_LCD + { + extern void lcd_disable(void); + extern void lcd_panel_disable(void); + + lcd_disable(); /* proper disable of lcd & panel */ + lcd_panel_disable(); + } +#endif + + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + /* flush I/D-cache */ + cache_flush(); + + return 0; +} + +static void cache_flush(void) +{ + unsigned long i = 0; + /* clean entire data cache */ + asm volatile("mcr p15, 0, %0, c7, c10, 0" : : "r" (i)); + /* invalidate both caches and flush btb */ + asm volatile("mcr p15, 0, %0, c7, c7, 0" : : "r" (i)); + /* mem barrier to sync things */ + asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (i)); +} + +#ifndef CONFIG_SYS_DCACHE_OFF + +#ifndef CONFIG_SYS_CACHELINE_SIZE +#define CONFIG_SYS_CACHELINE_SIZE 32 +#endif + +void invalidate_dcache_all(void) +{ + asm volatile("mcr p15, 0, %0, c7, c6, 0" : : "r" (0)); +} + +void flush_dcache_all(void) +{ + asm volatile("mcr p15, 0, %0, c7, c10, 0" : : "r" (0)); + asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); +} + +static int check_cache_range(unsigned long start, unsigned long stop) +{ + int ok = 1; + + if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (!ok) + debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", + start, stop); + + return ok; +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + if (!check_cache_range(start, stop)) + return; + + while (start < stop) { + asm volatile("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)); + start += CONFIG_SYS_CACHELINE_SIZE; + } +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + if (!check_cache_range(start, stop)) + return; + + while (start < stop) { + asm volatile("mcr p15, 0, %0, c7, c14, 1" : : "r" (start)); + start += CONFIG_SYS_CACHELINE_SIZE; + } + + asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); +} + +void flush_cache(unsigned long start, unsigned long size) +{ + flush_dcache_range(start, start + size); +} + +#else /* #ifndef CONFIG_SYS_DCACHE_OFF */ +void invalidate_dcache_all(void) +{ +} + +void flush_dcache_all(void) +{ +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void flush_cache(unsigned long start, unsigned long size) +{ +} +#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ + +#if !defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF) +void enable_caches(void) +{ +#ifndef CONFIG_SYS_ICACHE_OFF + icache_enable(); +#endif +#ifndef CONFIG_SYS_DCACHE_OFF + dcache_enable(); +#endif +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/Makefile new file mode 100644 index 000000000..9670ed938 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/Makefile @@ -0,0 +1,10 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += generic.o +obj-y += timer.o +obj-y += devices.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/devices.c new file mode 100644 index 000000000..ae5db86da --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/devices.c @@ -0,0 +1,51 @@ +/* + * + * (C) Copyright 2009 Magnus Lilja <lilja.magnus@gmail.com> + * + * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> + +void mx31_uart1_hw_init(void) +{ + /* setup pins for UART1 */ + mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX); + mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX); + mx31_gpio_mux(MUX_RTS1__UART1_RTS_B); + mx31_gpio_mux(MUX_CTS1__UART1_CTS_B); +} + +void mx31_uart2_hw_init(void) +{ + /* setup pins for UART2 */ + mx31_gpio_mux(MUX_RXD2__UART2_RXD_MUX); + mx31_gpio_mux(MUX_TXD2__UART2_TXD_MUX); + mx31_gpio_mux(MUX_RTS2__UART2_RTS_B); + mx31_gpio_mux(MUX_CTS2__UART2_CTS_B); +} + +#ifdef CONFIG_MXC_SPI +/* + * Note: putting several spi setups here makes no sense as they may differ + * at board level (physical pin SS0 of CSPI2 may aswell be used as SS0 of CSPI3) + */ +void mx31_spi2_hw_init(void) +{ + /* SPI2 */ + mx31_gpio_mux(MUX_CSPI2_SS2__CSPI2_SS2_B); + mx31_gpio_mux(MUX_CSPI2_SCLK__CSPI2_CLK); + mx31_gpio_mux(MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B); + mx31_gpio_mux(MUX_CSPI2_MOSI__CSPI2_MOSI); + mx31_gpio_mux(MUX_CSPI2_MISO__CSPI2_MISO); + mx31_gpio_mux(MUX_CSPI2_SS0__CSPI2_SS0_B); + mx31_gpio_mux(MUX_CSPI2_SS1__CSPI2_SS1_B); + + /* start SPI2 clock */ + __REG(CCM_CGR2) = __REG(CCM_CGR2) | (3 << 4); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/generic.c b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/generic.c new file mode 100644 index 000000000..060d46b82 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/generic.c @@ -0,0 +1,219 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> + +static u32 mx31_decode_pll(u32 reg, u32 infreq) +{ + u32 mfi = GET_PLL_MFI(reg); + s32 mfn = GET_PLL_MFN(reg); + u32 mfd = GET_PLL_MFD(reg); + u32 pd = GET_PLL_PD(reg); + + mfi = mfi <= 5 ? 5 : mfi; + mfn = mfn >= 512 ? mfn - 1024 : mfn; + mfd += 1; + pd += 1; + + return lldiv(2 * (u64)infreq * (mfi * mfd + mfn), + mfd * pd); +} + +static u32 mx31_get_mpl_dpdgck_clk(void) +{ + u32 infreq; + + if ((readl(CCM_CCMR) & CCMR_PRCS_MASK) == CCMR_FPM) + infreq = MXC_CLK32 * 1024; + else + infreq = MXC_HCLK; + + return mx31_decode_pll(readl(CCM_MPCTL), infreq); +} + +static u32 mx31_get_mcu_main_clk(void) +{ + /* For now we assume mpl_dpdgck_clk == mcu_main_clk + * which should be correct for most boards + */ + return mx31_get_mpl_dpdgck_clk(); +} + +static u32 mx31_get_ipg_clk(void) +{ + u32 freq = mx31_get_mcu_main_clk(); + u32 pdr0 = readl(CCM_PDR0); + + freq /= GET_PDR0_MAX_PODF(pdr0) + 1; + freq /= GET_PDR0_IPG_PODF(pdr0) + 1; + + return freq; +} + +/* hsp is the clock for the ipu */ +static u32 mx31_get_hsp_clk(void) +{ + u32 freq = mx31_get_mcu_main_clk(); + u32 pdr0 = readl(CCM_PDR0); + + freq /= GET_PDR0_HSP_PODF(pdr0) + 1; + + return freq; +} + +void mx31_dump_clocks(void) +{ + u32 cpufreq = mx31_get_mcu_main_clk(); + printf("mx31 cpu clock: %dMHz\n", cpufreq / 1000000); + printf("ipg clock : %dHz\n", mx31_get_ipg_clk()); + printf("hsp clock : %dHz\n", mx31_get_hsp_clk()); +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return mx31_get_mcu_main_clk(); + case MXC_IPG_CLK: + case MXC_IPG_PERCLK: + case MXC_CSPI_CLK: + case MXC_UART_CLK: + case MXC_ESDHC_CLK: + case MXC_I2C_CLK: + return mx31_get_ipg_clk(); + case MXC_IPU_CLK: + return mx31_get_hsp_clk(); + } + return -1; +} + +u32 imx_get_uartclk(void) +{ + return mxc_get_clock(MXC_UART_CLK); +} + +void mx31_gpio_mux(unsigned long mode) +{ + unsigned long reg, shift, tmp; + + reg = IOMUXC_BASE + (mode & 0x1fc); + shift = (~mode & 0x3) * 8; + + tmp = readl(reg); + tmp &= ~(0xff << shift); + tmp |= ((mode >> IOMUX_MODE_POS) & 0xff) << shift; + writel(tmp, reg); +} + +void mx31_set_pad(enum iomux_pins pin, u32 config) +{ + u32 field, l, reg; + + pin &= IOMUX_PADNUM_MASK; + reg = (IOMUXC_BASE + 0x154) + (pin + 2) / 3 * 4; + field = (pin + 2) % 3; + + l = readl(reg); + l &= ~(0x1ff << (field * 10)); + l |= config << (field * 10); + writel(l, reg); + +} + +void mx31_set_gpr(enum iomux_gp_func gp, char en) +{ + u32 l; + struct iomuxc_regs *iomuxc = (struct iomuxc_regs *)IOMUXC_BASE; + + l = readl(&iomuxc->gpr); + if (en) + l |= gp; + else + l &= ~gp; + + writel(l, &iomuxc->gpr); +} + +void mxc_setup_weimcs(int cs, const struct mxc_weimcs *weimcs) +{ + struct mx31_weim *weim = (struct mx31_weim *) WEIM_BASE; + struct mx31_weim_cscr *cscr = &weim->cscr[cs]; + + writel(weimcs->upper, &cscr->upper); + writel(weimcs->lower, &cscr->lower); + writel(weimcs->additional, &cscr->additional); +} + +struct mx3_cpu_type mx31_cpu_type[] = { + { .srev = 0x00, .v = 0x10 }, + { .srev = 0x10, .v = 0x11 }, + { .srev = 0x11, .v = 0x11 }, + { .srev = 0x12, .v = 0x1F }, + { .srev = 0x13, .v = 0x1F }, + { .srev = 0x14, .v = 0x12 }, + { .srev = 0x15, .v = 0x12 }, + { .srev = 0x28, .v = 0x20 }, + { .srev = 0x29, .v = 0x20 }, +}; + +u32 get_cpu_rev(void) +{ + u32 i, srev; + + /* read SREV register from IIM module */ + struct iim_regs *iim = (struct iim_regs *)MX31_IIM_BASE_ADDR; + srev = readl(&iim->iim_srev); + + for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++) + if (srev == mx31_cpu_type[i].srev) + return mx31_cpu_type[i].v; + + return srev | 0x8000; +} + +static char *get_reset_cause(void) +{ + /* read RCSR register from CCM module */ + struct clock_control_regs *ccm = + (struct clock_control_regs *)CCM_BASE; + + u32 cause = readl(&ccm->rcsr) & 0x07; + + switch (cause) { + case 0x0000: + return "POR"; + case 0x0001: + return "RST"; + case 0x0002: + return "WDOG"; + case 0x0006: + return "JTAG"; + case 0x0007: + return "ARM11P power gating"; + default: + return "unknown reset"; + } +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + u32 srev = get_cpu_rev(); + + printf("CPU: Freescale i.MX31 rev %d.%d%s at %d MHz.\n", + (srev & 0xF0) >> 4, (srev & 0x0F), + ((srev & 0x8000) ? " unknown" : ""), + mx31_get_mcu_main_clk() / 1000000); + printf("Reset cause: %s\n", get_reset_cause()); + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/timer.c new file mode 100644 index 000000000..f111242e5 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx31/timer.c @@ -0,0 +1,147 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <div64.h> +#include <watchdog.h> +#include <asm/io.h> + +#define TIMER_BASE 0x53f90000 /* General purpose timer 1 */ + +/* General purpose timers registers */ +#define GPTCR __REG(TIMER_BASE) /* Control register */ +#define GPTPR __REG(TIMER_BASE + 0x4) /* Prescaler register */ +#define GPTSR __REG(TIMER_BASE + 0x8) /* Status register */ +#define GPTCNT __REG(TIMER_BASE + 0x24) /* Counter register */ + +/* General purpose timers bitfields */ +#define GPTCR_SWR (1 << 15) /* Software reset */ +#define GPTCR_FRR (1 << 9) /* Freerun / restart */ +#define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source */ +#define GPTCR_TEN 1 /* Timer enable */ + +DECLARE_GLOBAL_DATA_PTR; + +/* + * "time" is measured in 1 / CONFIG_SYS_HZ seconds, + * "tick" is internal timer period + */ + +#ifdef CONFIG_MX31_TIMER_HIGH_PRECISION +/* ~0.4% error - measured with stop-watch on 100s boot-delay */ +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, MXC_CLK32); + return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ + time *= MXC_CLK32; + do_div(time, CONFIG_SYS_HZ); + return time; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us = us * MXC_CLK32 + 999999; + do_div(us, 1000000); + return us; +} +#else +/* ~2% error */ +#define TICK_PER_TIME ((MXC_CLK32 + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ) +#define US_PER_TICK (1000000 / MXC_CLK32) + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + do_div(tick, TICK_PER_TIME); + return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ + return time * TICK_PER_TIME; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us += US_PER_TICK - 1; + do_div(us, US_PER_TICK); + return us; +} +#endif + +/* The 32768Hz 32-bit timer overruns in 131072 seconds */ +int timer_init(void) +{ + int i; + + /* setup GP Timer 1 */ + GPTCR = GPTCR_SWR; + for (i = 0; i < 100; i++) + GPTCR = 0; /* We have no udelay by now */ + GPTPR = 0; /* 32Khz */ + /* Freerun Mode, PERCLK1 input */ + GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; + + return 0; +} + +unsigned long long get_ticks(void) +{ + ulong now = GPTCNT; /* current tick value */ + + if (now >= gd->arch.lastinc) /* normal mode (non roll) */ + /* move stamp forward with absolut diff ticks */ + gd->arch.tbl += (now - gd->arch.lastinc); + else /* we have rollover of incrementer */ + gd->arch.tbl += (0xFFFFFFFF - gd->arch.lastinc) + now; + gd->arch.lastinc = now; + return gd->arch.tbl; +} + +ulong get_timer_masked(void) +{ + /* + * get_ticks() returns a long long (64 bit), it wraps in + * 2^64 / MXC_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ + * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in + * 5 * 10^6 days - long enough. + */ + return tick_to_time(get_ticks()); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* delay x useconds AND preserve advance timestamp value */ +void __udelay(unsigned long usec) +{ + unsigned long long tmp; + ulong tmo; + + tmo = us_to_tick(usec); + tmp = get_ticks() + tmo; /* get current timestamp */ + + while (get_ticks() < tmp) /* loop till event */ + /*NOP*/; +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return MXC_CLK32; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/Makefile new file mode 100644 index 000000000..c533215c3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/Makefile @@ -0,0 +1,12 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2008-2009 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += generic.o +obj-y += timer.o +obj-y += mx35_sdram.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/generic.c b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/generic.c new file mode 100644 index 000000000..8d3f92cae --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/generic.c @@ -0,0 +1,547 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (C) Copyright 2008-2010 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/crm_regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> +#endif +#include <netdev.h> +#include <spl.h> + +#define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel)) +#define CLK_CODE_ARM(c) (((c) >> 16) & 0xFF) +#define CLK_CODE_AHB(c) (((c) >> 8) & 0xFF) +#define CLK_CODE_PATH(c) ((c) & 0xFF) + +#define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o)) + +#ifdef CONFIG_FSL_ESDHC +DECLARE_GLOBAL_DATA_PTR; +#endif + +static int g_clk_mux_auto[8] = { + CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1, + CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1, +}; + +static int g_clk_mux_consumer[16] = { + CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1, + -1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0), + CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1, + -1, -1, CLK_CODE(4, 2, 0), -1, +}; + +static int hsp_div_table[3][16] = { + {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1}, + {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1}, +}; + +u32 get_cpu_rev(void) +{ + int reg; + struct iim_regs *iim = + (struct iim_regs *)IIM_BASE_ADDR; + reg = readl(&iim->iim_srev); + if (!reg) { + reg = readw(ROMPATCH_REV); + reg <<= 4; + } else { + reg += CHIP_REV_1_0; + } + + return 0x35000 + (reg & 0xFF); +} + +static u32 get_arm_div(u32 pdr0, u32 *fi, u32 *fd) +{ + int *pclk_mux; + if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { + pclk_mux = g_clk_mux_consumer + + ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> + MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); + } else { + pclk_mux = g_clk_mux_auto + + ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> + MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); + } + + if ((*pclk_mux) == -1) + return -1; + + if (fi && fd) { + if (!CLK_CODE_PATH(*pclk_mux)) { + *fi = *fd = 1; + return CLK_CODE_ARM(*pclk_mux); + } + if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { + *fi = 3; + *fd = 4; + } else { + *fi = 2; + *fd = 3; + } + } + return CLK_CODE_ARM(*pclk_mux); +} + +static int get_ahb_div(u32 pdr0) +{ + int *pclk_mux; + + pclk_mux = g_clk_mux_consumer + + ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> + MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); + + if ((*pclk_mux) == -1) + return -1; + + return CLK_CODE_AHB(*pclk_mux); +} + +static u32 decode_pll(u32 reg, u32 infreq) +{ + u32 mfi = (reg >> 10) & 0xf; + s32 mfn = reg & 0x3ff; + u32 mfd = (reg >> 16) & 0x3ff; + u32 pd = (reg >> 26) & 0xf; + + mfi = mfi <= 5 ? 5 : mfi; + mfn = mfn >= 512 ? mfn - 1024 : mfn; + mfd += 1; + pd += 1; + + return lldiv(2 * (u64)infreq * (mfi * mfd + mfn), + mfd * pd); +} + +static u32 get_mcu_main_clk(void) +{ + u32 arm_div = 0, fi = 0, fd = 0; + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd); + fi *= decode_pll(readl(&ccm->mpctl), MXC_HCLK); + return fi / (arm_div * fd); +} + +static u32 get_ipg_clk(void) +{ + u32 freq = get_mcu_main_clk(); + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + u32 pdr0 = readl(&ccm->pdr0); + + return freq / (get_ahb_div(pdr0) * 2); +} + +static u32 get_ipg_per_clk(void) +{ + u32 freq = get_mcu_main_clk(); + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + u32 pdr0 = readl(&ccm->pdr0); + u32 pdr4 = readl(&ccm->pdr4); + u32 div; + if (pdr0 & MXC_CCM_PDR0_PER_SEL) { + div = CCM_GET_DIVIDER(pdr4, + MXC_CCM_PDR4_PER0_PODF_MASK, + MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1; + } else { + div = CCM_GET_DIVIDER(pdr0, + MXC_CCM_PDR0_PER_PODF_MASK, + MXC_CCM_PDR0_PER_PODF_OFFSET) + 1; + div *= get_ahb_div(pdr0); + } + return freq / div; +} + +u32 imx_get_uartclk(void) +{ + u32 freq; + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + u32 pdr4 = readl(&ccm->pdr4); + + if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) + freq = get_mcu_main_clk(); + else + freq = decode_pll(readl(&ccm->ppctl), MXC_HCLK); + freq /= CCM_GET_DIVIDER(pdr4, + MXC_CCM_PDR4_UART_PODF_MASK, + MXC_CCM_PDR4_UART_PODF_OFFSET) + 1; + return freq; +} + +unsigned int mxc_get_main_clock(enum mxc_main_clock clk) +{ + u32 nfc_pdf, hsp_podf; + u32 pll, ret_val = 0, usb_podf; + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + + u32 reg = readl(&ccm->pdr0); + u32 reg4 = readl(&ccm->pdr4); + + reg |= 0x1; + + switch (clk) { + case CPU_CLK: + ret_val = get_mcu_main_clk(); + break; + case AHB_CLK: + ret_val = get_mcu_main_clk(); + break; + case HSP_CLK: + if (reg & CLKMODE_CONSUMER) { + hsp_podf = (reg >> 20) & 0x3; + pll = get_mcu_main_clk(); + hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF]; + if (hsp_podf > 0) { + ret_val = pll / hsp_podf; + } else { + puts("mismatch HSP with ARM clock setting\n"); + ret_val = 0; + } + } else { + ret_val = get_mcu_main_clk(); + } + break; + case IPG_CLK: + ret_val = get_ipg_clk(); + break; + case IPG_PER_CLK: + ret_val = get_ipg_per_clk(); + break; + case NFC_CLK: + nfc_pdf = (reg4 >> 28) & 0xF; + pll = get_mcu_main_clk(); + /* AHB/nfc_pdf */ + ret_val = pll / (nfc_pdf + 1); + break; + case USB_CLK: + usb_podf = (reg4 >> 22) & 0x3F; + if (reg4 & 0x200) + pll = get_mcu_main_clk(); + else + pll = decode_pll(readl(&ccm->ppctl), MXC_HCLK); + + ret_val = pll / (usb_podf + 1); + break; + default: + printf("Unknown clock: %d\n", clk); + break; + } + + return ret_val; +} +unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk) +{ + u32 ret_val = 0, pdf, pre_pdf, clk_sel; + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + u32 mpdr2 = readl(&ccm->pdr2); + u32 mpdr3 = readl(&ccm->pdr3); + u32 mpdr4 = readl(&ccm->pdr4); + + switch (clk) { + case UART1_BAUD: + case UART2_BAUD: + case UART3_BAUD: + clk_sel = mpdr3 & (1 << 14); + pdf = (mpdr4 >> 10) & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); + break; + case SSI1_BAUD: + pre_pdf = (mpdr2 >> 24) & 0x7; + pdf = mpdr2 & 0x3F; + clk_sel = mpdr2 & (1 << 6); + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / + ((pre_pdf + 1) * (pdf + 1)); + break; + case SSI2_BAUD: + pre_pdf = (mpdr2 >> 27) & 0x7; + pdf = (mpdr2 >> 8) & 0x3F; + clk_sel = mpdr2 & (1 << 6); + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / + ((pre_pdf + 1) * (pdf + 1)); + break; + case CSI_BAUD: + clk_sel = mpdr2 & (1 << 7); + pdf = (mpdr2 >> 16) & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); + break; + case MSHC_CLK: + pre_pdf = readl(&ccm->pdr1); + clk_sel = (pre_pdf & 0x80); + pdf = (pre_pdf >> 22) & 0x3F; + pre_pdf = (pre_pdf >> 28) & 0x7; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / + ((pre_pdf + 1) * (pdf + 1)); + break; + case ESDHC1_CLK: + clk_sel = mpdr3 & 0x40; + pdf = mpdr3 & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); + break; + case ESDHC2_CLK: + clk_sel = mpdr3 & 0x40; + pdf = (mpdr3 >> 8) & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); + break; + case ESDHC3_CLK: + clk_sel = mpdr3 & 0x40; + pdf = (mpdr3 >> 16) & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); + break; + case SPDIF_CLK: + clk_sel = mpdr3 & 0x400000; + pre_pdf = (mpdr3 >> 29) & 0x7; + pdf = (mpdr3 >> 23) & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / + ((pre_pdf + 1) * (pdf + 1)); + break; + default: + printf("%s(): This clock: %d not supported yet\n", + __func__, clk); + break; + } + + return ret_val; +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return get_mcu_main_clk(); + case MXC_AHB_CLK: + break; + case MXC_IPG_CLK: + return get_ipg_clk(); + case MXC_IPG_PERCLK: + case MXC_I2C_CLK: + return get_ipg_per_clk(); + case MXC_UART_CLK: + return imx_get_uartclk(); + case MXC_ESDHC1_CLK: + return mxc_get_peri_clock(ESDHC1_CLK); + case MXC_ESDHC2_CLK: + return mxc_get_peri_clock(ESDHC2_CLK); + case MXC_ESDHC3_CLK: + return mxc_get_peri_clock(ESDHC3_CLK); + case MXC_USB_CLK: + return mxc_get_main_clock(USB_CLK); + case MXC_FEC_CLK: + return get_ipg_clk(); + case MXC_CSPI_CLK: + return get_ipg_clk(); + } + return -1; +} + +#ifdef CONFIG_FEC_MXC +/* + * The MX35 has no fuse for MAC, return a NULL MAC + */ +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + memset(mac, 0, 6); +} + +u32 imx_get_fecclk(void) +{ + return mxc_get_clock(MXC_IPG_CLK); +} +#endif + +int do_mx35_showclocks(cmd_tbl_t *cmdtp, + int flag, int argc, char * const argv[]) +{ + u32 cpufreq = get_mcu_main_clk(); + printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000); + printf("ipg clock : %dHz\n", get_ipg_clk()); + printf("ipg per clock : %dHz\n", get_ipg_per_clk()); + printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); + + return 0; +} + +U_BOOT_CMD( + clocks, CONFIG_SYS_MAXARGS, 1, do_mx35_showclocks, + "display clocks", + "" +); + +#if defined(CONFIG_DISPLAY_CPUINFO) +static char *get_reset_cause(void) +{ + /* read RCSR register from CCM module */ + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + + u32 cause = readl(&ccm->rcsr) & 0x0F; + + switch (cause) { + case 0x0000: + return "POR"; + case 0x0002: + return "JTAG"; + case 0x0004: + return "RST"; + case 0x0008: + return "WDOG"; + default: + return "unknown reset"; + } +} + +int print_cpuinfo(void) +{ + u32 srev = get_cpu_rev(); + + printf("CPU: Freescale i.MX35 rev %d.%d at %d MHz.\n", + (srev & 0xF0) >> 4, (srev & 0x0F), + get_mcu_main_clk() / 1000000); + + printf("Reset cause: %s\n", get_reset_cause()); + + return 0; +} +#endif + +/* + * Initializes on-chip ethernet controllers. + * to override, implement board_eth_init() + */ +int cpu_eth_init(bd_t *bis) +{ + int rc = -ENODEV; + +#if defined(CONFIG_FEC_MXC) + rc = fecmxc_initialize(bis); +#endif + + return rc; +} + +#ifdef CONFIG_FSL_ESDHC +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ + return fsl_esdhc_mmc_init(bis); +} +#endif + +int get_clocks(void) +{ +#ifdef CONFIG_FSL_ESDHC +#if CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC2_BASE_ADDR + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); +#elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC3_BASE_ADDR + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); +#else + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK); +#endif +#endif + return 0; +} + +#define RCSR_MEM_CTL_WEIM 0 +#define RCSR_MEM_CTL_NAND 1 +#define RCSR_MEM_CTL_ATA 2 +#define RCSR_MEM_CTL_EXPANSION 3 +#define RCSR_MEM_TYPE_NOR 0 +#define RCSR_MEM_TYPE_ONENAND 2 +#define RCSR_MEM_TYPE_SD 0 +#define RCSR_MEM_TYPE_I2C 2 +#define RCSR_MEM_TYPE_SPI 3 + +u32 spl_boot_device(void) +{ + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + + u32 rcsr = readl(&ccm->rcsr); + u32 mem_type, mem_ctl; + + /* In external mode, no boot device is returned */ + if ((rcsr >> 10) & 0x03) + return BOOT_DEVICE_NONE; + + mem_ctl = (rcsr >> 25) & 0x03; + mem_type = (rcsr >> 23) & 0x03; + + switch (mem_ctl) { + case RCSR_MEM_CTL_WEIM: + switch (mem_type) { + case RCSR_MEM_TYPE_NOR: + return BOOT_DEVICE_NOR; + case RCSR_MEM_TYPE_ONENAND: + return BOOT_DEVICE_ONENAND; + default: + return BOOT_DEVICE_NONE; + } + case RCSR_MEM_CTL_NAND: + return BOOT_DEVICE_NAND; + case RCSR_MEM_CTL_EXPANSION: + switch (mem_type) { + case RCSR_MEM_TYPE_SD: + return BOOT_DEVICE_MMC1; + case RCSR_MEM_TYPE_I2C: + return BOOT_DEVICE_I2C; + case RCSR_MEM_TYPE_SPI: + return BOOT_DEVICE_SPI; + default: + return BOOT_DEVICE_NONE; + } + } + + return BOOT_DEVICE_NONE; +} + +#ifdef CONFIG_SPL_BUILD +u32 spl_boot_mode(void) +{ + switch (spl_boot_device()) { + case BOOT_DEVICE_MMC1: +#ifdef CONFIG_SPL_FAT_SUPPORT + return MMCSD_MODE_FAT; +#else + return MMCSD_MODE_RAW; +#endif + break; + case BOOT_DEVICE_NAND: + return 0; + break; + default: + puts("spl: ERROR: unsupported device\n"); + hang(); + } +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/mx35_sdram.c b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/mx35_sdram.c new file mode 100644 index 000000000..d358f5f2f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/mx35_sdram.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2012, Stefano Babic <sbabic@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/imx-regs.h> +#include <linux/types.h> +#include <asm/arch/sys_proto.h> + +#define ESDCTL_DDR2_EMR2 0x04000000 +#define ESDCTL_DDR2_EMR3 0x06000000 +#define ESDCTL_PRECHARGE 0x00000400 +#define ESDCTL_DDR2_EN_DLL 0x02000400 +#define ESDCTL_DDR2_RESET_DLL 0x00000333 +#define ESDCTL_DDR2_MR 0x00000233 +#define ESDCTL_DDR2_OCD_DEFAULT 0x02000780 + +enum { + SMODE_NORMAL = 0, + SMODE_PRECHARGE, + SMODE_AUTO_REFRESH, + SMODE_LOAD_REG, + SMODE_MANUAL_REFRESH +}; + +#define set_mode(x, en, m) (x | (en << 31) | (m << 28)) + +static inline void dram_wait(unsigned int count) +{ + volatile unsigned int wait = count; + + while (wait--) + ; + +} + +void mx3_setup_sdram_bank(u32 start_address, u32 ddr2_config, + u32 row, u32 col, u32 dsize, u32 refresh) +{ + struct esdc_regs *esdc = (struct esdc_regs *)ESDCTL_BASE_ADDR; + u32 *cfg_reg, *ctl_reg; + u32 val; + u32 ctlval; + + switch (start_address) { + case CSD0_BASE_ADDR: + cfg_reg = &esdc->esdcfg0; + ctl_reg = &esdc->esdctl0; + break; + case CSD1_BASE_ADDR: + cfg_reg = &esdc->esdcfg1; + ctl_reg = &esdc->esdctl1; + break; + default: + return; + } + + /* The MX35 supports 11 up to 14 rows */ + if (row < 11 || row > 14 || col < 8 || col > 10) + return; + ctlval = (row - 11) << 24 | (col - 8) << 20 | (dsize << 16); + + /* Initialize MISC register for DDR2 */ + val = ESDC_MISC_RST | ESDC_MISC_MDDR_EN | ESDC_MISC_MDDR_DL_RST | + ESDC_MISC_DDR_EN | ESDC_MISC_DDR2_EN; + writel(val, &esdc->esdmisc); + val &= ~(ESDC_MISC_RST | ESDC_MISC_MDDR_DL_RST); + writel(val, &esdc->esdmisc); + + /* + * according to DDR2 specs, wait a while before + * the PRECHARGE_ALL command + */ + dram_wait(0x20000); + + /* Load DDR2 config and timing */ + writel(ddr2_config, cfg_reg); + + /* Precharge ALL */ + writel(set_mode(ctlval, 1, SMODE_PRECHARGE), + ctl_reg); + writel(0xda, start_address + ESDCTL_PRECHARGE); + + /* Load mode */ + writel(set_mode(ctlval, 1, SMODE_LOAD_REG), + ctl_reg); + writeb(0xda, start_address + ESDCTL_DDR2_EMR2); /* EMRS2 */ + writeb(0xda, start_address + ESDCTL_DDR2_EMR3); /* EMRS3 */ + writeb(0xda, start_address + ESDCTL_DDR2_EN_DLL); /* Enable DLL */ + writeb(0xda, start_address + ESDCTL_DDR2_RESET_DLL); /* Reset DLL */ + + /* Precharge ALL */ + writel(set_mode(ctlval, 1, SMODE_PRECHARGE), + ctl_reg); + writel(0xda, start_address + ESDCTL_PRECHARGE); + + /* Set mode auto refresh : at least two refresh are required */ + writel(set_mode(ctlval, 1, SMODE_AUTO_REFRESH), + ctl_reg); + writel(0xda, start_address); + writel(0xda, start_address); + + writel(set_mode(ctlval, 1, SMODE_LOAD_REG), + ctl_reg); + writeb(0xda, start_address + ESDCTL_DDR2_MR); + writeb(0xda, start_address + ESDCTL_DDR2_OCD_DEFAULT); + + /* OCD mode exit */ + writeb(0xda, start_address + ESDCTL_DDR2_EN_DLL); /* Enable DLL */ + + /* Set normal mode */ + writel(set_mode(ctlval, 1, SMODE_NORMAL) | refresh, + ctl_reg); + + dram_wait(0x20000); + + /* Do not set delay lines, only for MDDR */ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/timer.c new file mode 100644 index 000000000..cc6166f93 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/mx35/timer.c @@ -0,0 +1,130 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <div64.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/crm_regs.h> +#include <asm/arch/clock.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp (gd->arch.tbl) +#define lastinc (gd->arch.lastinc) + +/* General purpose timers bitfields */ +#define GPTCR_SWR (1<<15) /* Software reset */ +#define GPTCR_FRR (1<<9) /* Freerun / restart */ +#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ +#define GPTCR_TEN (1) /* Timer enable */ + +/* + * "time" is measured in 1 / CONFIG_SYS_HZ seconds, + * "tick" is internal timer period + */ +/* ~0.4% error - measured with stop-watch on 100s boot-delay */ +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, MXC_CLK32); + + return tick; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us = us * MXC_CLK32 + 999999; + do_div(us, 1000000); + + return us; +} + +/* + * nothing really to do with interrupts, just starts up a counter. + * The 32KHz 32-bit timer overruns in 134217 seconds + */ +int timer_init(void) +{ + int i; + struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR; + struct ccm_regs *ccm = (struct ccm_regs *)CCM_BASE_ADDR; + + /* setup GP Timer 1 */ + writel(GPTCR_SWR, &gpt->ctrl); + + writel(readl(&ccm->cgr1) | 3 << MXC_CCM_CGR1_GPT_OFFSET, &ccm->cgr1); + + for (i = 0; i < 100; i++) + writel(0, &gpt->ctrl); /* We have no udelay by now */ + writel(0, &gpt->pre); /* prescaler = 1 */ + /* Freerun Mode, 32KHz input */ + writel(readl(&gpt->ctrl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR, + &gpt->ctrl); + writel(readl(&gpt->ctrl) | GPTCR_TEN, &gpt->ctrl); + + return 0; +} + +unsigned long long get_ticks(void) +{ + struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR; + ulong now = readl(&gpt->counter); /* current tick value */ + + if (now >= lastinc) { + /* + * normal mode (non roll) + * move stamp forward with absolut diff ticks + */ + timestamp += (now - lastinc); + } else { + /* we have rollover of incrementer */ + timestamp += (0xFFFFFFFF - lastinc) + now; + } + lastinc = now; + return timestamp; +} + +ulong get_timer_masked(void) +{ + /* + * get_ticks() returns a long long (64 bit), it wraps in + * 2^64 / MXC_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ + * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in + * 5 * 10^6 days - long enough. + */ + return tick_to_time(get_ticks()); +} + +ulong 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 tmp; + ulong tmo; + + tmo = us_to_tick(usec); + tmp = get_ticks() + tmo; /* get current timestamp */ + + while (get_ticks() < tmp) /* loop till event */ + /*NOP*/; +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return MXC_CLK32; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/start.S b/qemu/roms/u-boot/arch/arm/cpu/arm1136/start.S new file mode 100644 index 000000000..3e2358e13 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/start.S @@ -0,0 +1,346 @@ +/* + * armboot - Startup Code for OMP2420/ARM1136 CPU-core + * + * Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com> + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> +.globl _start +_start: b reset +#ifdef CONFIG_SPL_BUILD + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + +_hang: + .word do_hang + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 /* now 16*4=64 */ +#else + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq +_pad: .word 0x12345678 /* now 16*4=64 */ +#endif /* CONFIG_SPL_BUILD */ +.global _end_vect +_end_vect: + + .balignl 16,0xdeadbeef +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* the mask ROM code should have PLL and others stable */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + bx lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* Invalidate I+D+BTB caches */ + mcr p15, 0, r0, c8, c7, 0 /* Invalidate Unified TLB */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) + bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) + orr r0, r0, #0x00000002 @ set bit 2 (A) Align + orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache + mcr p15, 0, r0, c1, c0, 0 + + /* + * Jump to board specific initialization... The Mask ROM will have already initialized + * basic memory. Go here to bump up clock rate and handle wake up conditions. + */ + mov ip, lr /* persevere link reg across call */ + bl lowlevel_init /* go setup pll,mux,memory */ + mov lr, ip /* restore link */ + mov pc, lr /* back to my caller */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + +#ifndef CONFIG_SPL_BUILD +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current user stack + stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 + + ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort stack + ldmia r2, {r2 - r3} @ get values for "aborted" pc and cpsr (into parm regs) + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp @ save current stack into r0 (param register) + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter in banked mode) + + str lr, [r13] @ save caller lr in position 0 of saved stack + mrs lr, spsr @ get the spsr + str lr, [r13, #4] @ save spsr in position 1 of saved stack + + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 @ switch modes, make sure moves will execute + mov lr, pc @ capture return pc + movs pc, lr @ jump to next instruction & switch modes. + .endm + + .macro get_bad_stack_swi + sub r13, r13, #4 @ space on current stack for scratch reg. + str r0, [r13] @ save R0's value. + ldr r0, IRQ_STACK_START_IN @ get data regions start + str lr, [r0] @ save caller lr in position 0 of saved stack + mrs lr, spsr @ get the spsr + str lr, [r0, #4] @ save spsr in position 1 of saved stack + ldr lr, [r0] @ restore lr + ldr r0, [r13] @ restore r0 + add r13, r13, #4 @ pop stack entry + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm +#endif /* CONFIG_SPL_BUILD */ + +/* + * exception handlers + */ +#ifdef CONFIG_SPL_BUILD + .align 5 +do_hang: + bl hang /* hang and never return */ +#else /* !CONFIG_SPL_BUILD */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack_swi + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif + .align 5 +.global arm1136_cache_flush +arm1136_cache_flush: +#if !defined(CONFIG_SYS_ICACHE_OFF) + mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache +#endif +#if !defined(CONFIG_SYS_DCACHE_OFF) + mcr p15, 0, r1, c7, c14, 0 @ invalidate D cache +#endif + mov pc, lr @ back to caller +#endif /* CONFIG_SPL_BUILD */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1136/u-boot-spl.lds b/qemu/roms/u-boot/arch/arm/cpu/arm1136/u-boot-spl.lds new file mode 100644 index 000000000..0299902f2 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1136/u-boot-spl.lds @@ -0,0 +1,50 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : + { + __start = .; + arch/arm/cpu/arm1136/start.o (.text*) + *(.text*) + } >.sram + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram + . = ALIGN(4); + __image_copy_end = .; + + .end : + { + *(.__end) + } + + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } >.sdram +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm1176/Makefile new file mode 100644 index 000000000..deec42744 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/Makefile @@ -0,0 +1,12 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2008 +# Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y = start.o +obj-y = cpu.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/Makefile new file mode 100644 index 000000000..0ad36906d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/Makefile @@ -0,0 +1,16 @@ +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +obj-y := lowlevel_init.o +obj-y += init.o reset.o timer.o mbox.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/init.c b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/init.c new file mode 100644 index 000000000..e90d3bba1 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/init.c @@ -0,0 +1,24 @@ +/* + * (C) Copyright 2012 Stephen Warren + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> + +int arch_cpu_init(void) +{ + icache_enable(); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/lowlevel_init.S new file mode 100644 index 000000000..c7b084328 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/lowlevel_init.S @@ -0,0 +1,19 @@ +/* + * (C) Copyright 2012 Stephen Warren + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +.globl lowlevel_init +lowlevel_init: + mov pc, lr diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/mbox.c b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/mbox.c new file mode 100644 index 000000000..3b17a31ea --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/mbox.c @@ -0,0 +1,153 @@ +/* + * (C) Copyright 2012 Stephen Warren + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/mbox.h> + +#define TIMEOUT 1000 /* ms */ + +int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv) +{ + struct bcm2835_mbox_regs *regs = + (struct bcm2835_mbox_regs *)BCM2835_MBOX_PHYSADDR; + ulong endtime = get_timer(0) + TIMEOUT; + u32 val; + + debug("time: %lu timeout: %lu\n", get_timer(0), endtime); + + if (send & BCM2835_CHAN_MASK) { + printf("mbox: Illegal mbox data 0x%08x\n", send); + return -1; + } + + /* Drain any stale responses */ + + for (;;) { + val = readl(®s->status); + if (val & BCM2835_MBOX_STATUS_RD_EMPTY) + break; + if (get_timer(0) >= endtime) { + printf("mbox: Timeout draining stale responses\n"); + return -1; + } + val = readl(®s->read); + } + + /* Wait for space to send */ + + for (;;) { + val = readl(®s->status); + if (!(val & BCM2835_MBOX_STATUS_WR_FULL)) + break; + if (get_timer(0) >= endtime) { + printf("mbox: Timeout waiting for send space\n"); + return -1; + } + } + + /* Send the request */ + + val = BCM2835_MBOX_PACK(chan, send); + debug("mbox: TX raw: 0x%08x\n", val); + writel(val, ®s->write); + + /* Wait for the response */ + + for (;;) { + val = readl(®s->status); + if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY)) + break; + if (get_timer(0) >= endtime) { + printf("mbox: Timeout waiting for response\n"); + return -1; + } + } + + /* Read the response */ + + val = readl(®s->read); + debug("mbox: RX raw: 0x%08x\n", val); + + /* Validate the response */ + + if (BCM2835_MBOX_UNPACK_CHAN(val) != chan) { + printf("mbox: Response channel mismatch\n"); + return -1; + } + + *recv = BCM2835_MBOX_UNPACK_DATA(val); + + return 0; +} + +#ifdef DEBUG +void dump_buf(struct bcm2835_mbox_hdr *buffer) +{ + u32 *p; + u32 words; + int i; + + p = (u32 *)buffer; + words = buffer->buf_size / 4; + for (i = 0; i < words; i++) + printf(" 0x%04x: 0x%08x\n", i * 4, p[i]); +} +#endif + +int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer) +{ + int ret; + u32 rbuffer; + struct bcm2835_mbox_tag_hdr *tag; + int tag_index; + +#ifdef DEBUG + printf("mbox: TX buffer\n"); + dump_buf(buffer); +#endif + + ret = bcm2835_mbox_call_raw(chan, (u32)buffer, &rbuffer); + if (ret) + return ret; + if (rbuffer != (u32)buffer) { + printf("mbox: Response buffer mismatch\n"); + return -1; + } + +#ifdef DEBUG + printf("mbox: RX buffer\n"); + dump_buf(buffer); +#endif + + /* Validate overall response status */ + + if (buffer->code != BCM2835_MBOX_RESP_CODE_SUCCESS) { + printf("mbox: Header response code invalid\n"); + return -1; + } + + /* Validate each tag's response status */ + + tag = (void *)(buffer + 1); + tag_index = 0; + while (tag->tag) { + if (!(tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE)) { + printf("mbox: Tag %d missing val_len response bit\n", + tag_index); + return -1; + } + /* + * Clear the reponse bit so clients can just look right at the + * length field without extra processing + */ + tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE; + tag = (void *)(((u8 *)tag) + sizeof(*tag) + tag->val_buf_size); + tag_index++; + } + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/reset.c b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/reset.c new file mode 100644 index 000000000..8c37ad9fd --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/reset.c @@ -0,0 +1,35 @@ +/* + * (C) Copyright 2012 Stephen Warren + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/wdog.h> + +#define RESET_TIMEOUT 10 + +void reset_cpu(ulong addr) +{ + struct bcm2835_wdog_regs *regs = + (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR; + uint32_t rstc; + + rstc = readl(®s->rstc); + rstc &= ~BCM2835_WDOG_RSTC_WRCFG_MASK; + rstc |= BCM2835_WDOG_RSTC_WRCFG_FULL_RESET; + + writel(BCM2835_WDOG_PASSWORD | RESET_TIMEOUT, ®s->wdog); + writel(BCM2835_WDOG_PASSWORD | rstc, ®s->rstc); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/timer.c new file mode 100644 index 000000000..017907cfb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/bcm2835/timer.c @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2012 Stephen Warren + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/timer.h> + +ulong get_timer_us(ulong base) +{ + struct bcm2835_timer_regs *regs = + (struct bcm2835_timer_regs *)BCM2835_TIMER_PHYSADDR; + + return readl(®s->clo) - base; +} + +ulong get_timer(ulong base) +{ + ulong us = get_timer_us(0); + us /= (1000000 / CONFIG_SYS_HZ); + us -= base; + return us; +} + +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} + +void __udelay(unsigned long usec) +{ + ulong endtime; + signed long diff; + + endtime = get_timer_us(0) + usec; + + do { + ulong now = get_timer_us(0); + diff = endtime - now; + } while (diff >= 0); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/config.mk b/qemu/roms/u-boot/arch/arm/cpu/arm1176/config.mk new file mode 100644 index 000000000..5dc2ebb27 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/config.mk @@ -0,0 +1,9 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# Make ARMv5 to allow more compilers to work, even though its v6. +PLATFORM_CPPFLAGS += -march=armv5t diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm1176/cpu.c new file mode 100644 index 000000000..2d8165121 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/cpu.c @@ -0,0 +1,51 @@ +/* + * (C) Copyright 2004 Texas Insturments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +static void cache_flush (void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + disable_interrupts (); + + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + /* flush I/D-cache */ + cache_flush(); + + return 0; +} + +/* flush I/D-cache */ +static void cache_flush (void) +{ + /* invalidate both caches and flush btb */ + asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (0)); + /* mem barrier to sync things */ + asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (0)); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/start.S b/qemu/roms/u-boot/arch/arm/cpu/arm1176/start.S new file mode 100644 index 000000000..ce620115d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/start.S @@ -0,0 +1,331 @@ +/* + * armboot - Startup Code for ARM1176 CPU-core + * + * Copyright (c) 2007 Samsung Electronics + * + * Copyright (C) 2008 + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * 2007-09-21 - Restructured codes by jsgood (jsgood.yang@samsung.com) + * 2007-09-21 - Added MoviNAND and OneNAND boot codes by + * jsgood (jsgood.yang@samsung.com) + * Base codes by scsuh (sc.suh) + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> + +#ifndef CONFIG_SYS_PHY_UBOOT_BASE +#define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE +#endif + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + +.globl _start +_start: b reset +#ifndef CONFIG_SPL_BUILD + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: + .word undefined_instruction +_software_interrupt: + .word software_interrupt +_prefetch_abort: + .word prefetch_abort +_data_abort: + .word data_abort +_not_used: + .word not_used +_irq: + .word irq +_fiq: + .word fiq +_pad: + .word 0x12345678 /* now 16*4=64 */ +#else + . = _start + 64 +#endif + +.global _end_vect +_end_vect: + .balignl 16,0xdeadbeef +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0, cpsr + bic r0, r0, #0x3f + orr r0, r0, #0xd3 + msr cpsr, r0 + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +cpu_init_crit: + /* + * When booting from NAND - it has definitely been a reset, so, no need + * to flush caches and disable the MMU + */ +#ifndef CONFIG_SPL_BUILD + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) + bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) + orr r0, r0, #0x00000002 @ set bit 2 (A) Align + orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache + + /* Prepare to disable the MMU */ + adr r2, mmu_disable_phys + sub r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - CONFIG_SYS_TEXT_BASE) + b mmu_disable + + .align 5 + /* Run in a single cache-line */ +mmu_disable: + mcr p15, 0, r0, c1, c0, 0 + nop + nop + mov pc, r2 +mmu_disable_phys: + +#ifdef CONFIG_DISABLE_TCM + /* + * Disable the TCMs + */ + mrc p15, 0, r0, c0, c0, 2 /* Return TCM details */ + cmp r0, #0 + beq skip_tcmdisable + mov r1, #0 + mov r2, #1 + tst r0, r2 + mcrne p15, 0, r1, c9, c1, 1 /* Disable Instruction TCM if present*/ + tst r0, r2, LSL #16 + mcrne p15, 0, r1, c9, c1, 0 /* Disable Data TCM if present*/ +skip_tcmdisable: +#endif +#endif + +#ifdef CONFIG_PERIPORT_REMAP + /* Peri port setup */ + ldr r0, =CONFIG_PERIPORT_BASE + orr r0, r0, #CONFIG_PERIPORT_SIZE + mcr p15,0,r0,c15,c2,4 +#endif + + /* + * Go setup Memory and board specific bits prior to relocation. + */ + bl lowlevel_init /* go setup pll,mux,memory */ + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +#ifndef CONFIG_SPL_BUILD +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + */ + + .macro bad_save_user_regs + /* carve out a frame on current user stack */ + sub sp, sp, #S_FRAME_SIZE + /* Save user registers (now in svc mode) r0-r12 */ + stmia sp, {r0 - r12} + + ldr r2, IRQ_STACK_START_IN + /* get values for "aborted" pc and cpsr (into parm regs) */ + ldmia r2, {r2 - r3} + /* grab pointer to old stack */ + add r0, sp, #S_FRAME_SIZE + + add r5, sp, #S_SP + mov r1, lr + /* save sp_SVC, lr_SVC, pc, cpsr */ + stmia r5, {r0 - r3} + /* save current stack into r0 (param register) */ + mov r0, sp + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + + /* save caller lr in position 0 of saved stack */ + str lr, [r13] + /* get the spsr */ + mrs lr, spsr + /* save spsr in position 1 of saved stack */ + str lr, [r13, #4] + + /* prepare SVC-Mode */ + mov r13, #MODE_SVC + @ msr spsr_c, r13 + /* switch modes, make sure moves will execute */ + msr spsr, r13 + /* capture return pc */ + mov lr, pc + /* jump to next instruction & switch modes. */ + movs pc, lr + .endm + + .macro get_bad_stack_swi + /* space on current stack for scratch reg. */ + sub r13, r13, #4 + /* save R0's value. */ + str r0, [r13] + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + /* save caller lr in position 0 of saved stack */ + str lr, [r0] + /* get the spsr */ + mrs lr, spsr + /* save spsr in position 1 of saved stack */ + str lr, [r0, #4] + /* restore lr */ + ldr lr, [r0] + /* restore r0 */ + ldr r0, [r13] + /* pop stack entry */ + add r13, r13, #4 + .endm + +/* + * exception handlers + */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack_swi + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq +#endif /* CONFIG_SPL_BUILD */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/Makefile new file mode 100644 index 000000000..a4c1edfc7 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/Makefile @@ -0,0 +1,6 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += aemif.o clock.o init.o mux.o timer.o +obj-y += lowlevel_init.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/aemif.c b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/aemif.c new file mode 100644 index 000000000..a0f57289e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/aemif.c @@ -0,0 +1,78 @@ +/* + * TNETV107X: Asynchronous EMIF Configuration + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/mux.h> + +#define ASYNC_EMIF_BASE TNETV107X_ASYNC_EMIF_CNTRL_BASE +#define ASYNC_EMIF_CONFIG(cs) (ASYNC_EMIF_BASE+0x10+(cs)*4) +#define ASYNC_EMIF_ONENAND_CONTROL (ASYNC_EMIF_BASE+0x5c) +#define ASYNC_EMIF_NAND_CONTROL (ASYNC_EMIF_BASE+0x60) +#define ASYNC_EMIF_WAITCYCLE_CONFIG (ASYNC_EMIF_BASE+0x4) + +#define CONFIG_SELECT_STROBE(v) ((v) ? 1 << 31 : 0) +#define CONFIG_EXTEND_WAIT(v) ((v) ? 1 << 30 : 0) +#define CONFIG_WR_SETUP(v) (((v) & 0x0f) << 26) +#define CONFIG_WR_STROBE(v) (((v) & 0x3f) << 20) +#define CONFIG_WR_HOLD(v) (((v) & 0x07) << 17) +#define CONFIG_RD_SETUP(v) (((v) & 0x0f) << 13) +#define CONFIG_RD_STROBE(v) (((v) & 0x3f) << 7) +#define CONFIG_RD_HOLD(v) (((v) & 0x07) << 4) +#define CONFIG_TURN_AROUND(v) (((v) & 0x03) << 2) +#define CONFIG_WIDTH(v) (((v) & 0x03) << 0) + +#define NUM_CS 4 + +#define set_config_field(reg, field, val) \ + do { \ + if (val != -1) { \ + reg &= ~CONFIG_##field(0xffffffff); \ + reg |= CONFIG_##field(val); \ + } \ + } while (0) + +void configure_async_emif(int cs, struct async_emif_config *cfg) +{ + unsigned long tmp; + + if (cfg->mode == ASYNC_EMIF_MODE_NAND) { + tmp = __raw_readl(ASYNC_EMIF_NAND_CONTROL); + tmp |= (1 << cs); + __raw_writel(tmp, ASYNC_EMIF_NAND_CONTROL); + + } else if (cfg->mode == ASYNC_EMIF_MODE_ONENAND) { + tmp = __raw_readl(ASYNC_EMIF_ONENAND_CONTROL); + tmp |= (1 << cs); + __raw_writel(tmp, ASYNC_EMIF_ONENAND_CONTROL); + } + + tmp = __raw_readl(ASYNC_EMIF_CONFIG(cs)); + + set_config_field(tmp, SELECT_STROBE, cfg->select_strobe); + set_config_field(tmp, EXTEND_WAIT, cfg->extend_wait); + set_config_field(tmp, WR_SETUP, cfg->wr_setup); + set_config_field(tmp, WR_STROBE, cfg->wr_strobe); + set_config_field(tmp, WR_HOLD, cfg->wr_hold); + set_config_field(tmp, RD_SETUP, cfg->rd_setup); + set_config_field(tmp, RD_STROBE, cfg->rd_strobe); + set_config_field(tmp, RD_HOLD, cfg->rd_hold); + set_config_field(tmp, TURN_AROUND, cfg->turn_around); + set_config_field(tmp, WIDTH, cfg->width); + + __raw_writel(tmp, ASYNC_EMIF_CONFIG(cs)); +} + +void init_async_emif(int num_cs, struct async_emif_config *config) +{ + int cs; + + clk_enable(TNETV107X_LPSC_AEMIF); + + for (cs = 0; cs < num_cs; cs++) + configure_async_emif(cs, config + cs); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/clock.c b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/clock.c new file mode 100644 index 000000000..3708b6f59 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/clock.c @@ -0,0 +1,432 @@ +/* + * TNETV107X: Clock management APIs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm-generic/errno.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/arch/clock.h> + +#define CLOCK_BASE TNETV107X_CLOCK_CONTROL_BASE +#define PSC_BASE TNETV107X_PSC_BASE + +#define BIT(x) (1 << (x)) + +#define MAX_PREDIV 64 +#define MAX_POSTDIV 8 +#define MAX_MULT 512 +#define MAX_DIV (MAX_PREDIV * MAX_POSTDIV) + +/* LPSC registers */ +#define PSC_PTCMD 0x120 +#define PSC_PTSTAT 0x128 +#define PSC_MDSTAT(n) (0x800 + (n) * 4) +#define PSC_MDCTL(n) (0xA00 + (n) * 4) + +#define PSC_MDCTL_LRSTZ BIT(8) + +#define psc_reg_read(reg) __raw_readl((u32 *)(PSC_BASE + (reg))) +#define psc_reg_write(reg, val) __raw_writel(val, (u32 *)(PSC_BASE + (reg))) + +/* SSPLL registers */ +struct sspll_regs { + u32 modes; + u32 postdiv; + u32 prediv; + u32 mult_factor; + u32 divider_range; + u32 bw_divider; + u32 spr_amount; + u32 spr_rate_div; + u32 diag; +}; + +/* SSPLL base addresses */ +static struct sspll_regs *sspll_regs[] = { + (struct sspll_regs *)(CLOCK_BASE + 0x040), + (struct sspll_regs *)(CLOCK_BASE + 0x080), + (struct sspll_regs *)(CLOCK_BASE + 0x0c0), +}; + +#define sspll_reg(pll, reg) (&(sspll_regs[pll]->reg)) +#define sspll_reg_read(pll, reg) __raw_readl(sspll_reg(pll, reg)) +#define sspll_reg_write(pll, reg, val) __raw_writel(val, sspll_reg(pll, reg)) + + +/* PLL Control Registers */ +struct pllctl_regs { + u32 ctl; /* 00 */ + u32 ocsel; /* 04 */ + u32 secctl; /* 08 */ + u32 __pad0; + u32 mult; /* 10 */ + u32 prediv; /* 14 */ + u32 div1; /* 18 */ + u32 div2; /* 1c */ + u32 div3; /* 20 */ + u32 oscdiv1; /* 24 */ + u32 postdiv; /* 28 */ + u32 bpdiv; /* 2c */ + u32 wakeup; /* 30 */ + u32 __pad1; + u32 cmd; /* 38 */ + u32 stat; /* 3c */ + u32 alnctl; /* 40 */ + u32 dchange; /* 44 */ + u32 cken; /* 48 */ + u32 ckstat; /* 4c */ + u32 systat; /* 50 */ + u32 ckctl; /* 54 */ + u32 __pad2[2]; + u32 div4; /* 60 */ + u32 div5; /* 64 */ + u32 div6; /* 68 */ + u32 div7; /* 6c */ + u32 div8; /* 70 */ +}; + +struct lpsc_map { + int pll, div; +}; + +static struct pllctl_regs *pllctl_regs[] = { + (struct pllctl_regs *)(CLOCK_BASE + 0x700), + (struct pllctl_regs *)(CLOCK_BASE + 0x300), + (struct pllctl_regs *)(CLOCK_BASE + 0x500), +}; + +#define pllctl_reg(pll, reg) (&(pllctl_regs[pll]->reg)) +#define pllctl_reg_read(pll, reg) __raw_readl(pllctl_reg(pll, reg)) +#define pllctl_reg_write(pll, reg, val) __raw_writel(val, pllctl_reg(pll, reg)) + +#define pllctl_reg_rmw(pll, reg, mask, val) \ + pllctl_reg_write(pll, reg, \ + (pllctl_reg_read(pll, reg) & ~(mask)) | val) + +#define pllctl_reg_setbits(pll, reg, mask) \ + pllctl_reg_rmw(pll, reg, 0, mask) + +#define pllctl_reg_clrbits(pll, reg, mask) \ + pllctl_reg_rmw(pll, reg, mask, 0) + +/* PLLCTL Bits */ +#define PLLCTL_CLKMODE BIT(8) +#define PLLCTL_PLLSELB BIT(7) +#define PLLCTL_PLLENSRC BIT(5) +#define PLLCTL_PLLDIS BIT(4) +#define PLLCTL_PLLRST BIT(3) +#define PLLCTL_PLLPWRDN BIT(1) +#define PLLCTL_PLLEN BIT(0) + +#define PLLDIV_ENABLE BIT(15) + +static int pll_div_offset[] = { +#define div_offset(reg) offsetof(struct pllctl_regs, reg) + div_offset(div1), div_offset(div2), div_offset(div3), + div_offset(div4), div_offset(div5), div_offset(div6), + div_offset(div7), div_offset(div8), +}; + +static unsigned long pll_bypass_mask[] = { 1, 4, 2 }; +static unsigned long pll_div_mask[] = { 0x01ff, 0x00ff, 0x00ff }; + +/* Mappings from PLL+DIV to subsystem clocks */ +#define sys_arm1176_clk {SYS_PLL, 0} +#define sys_dsp_clk {SYS_PLL, 1} +#define sys_ddr_clk {SYS_PLL, 2} +#define sys_full_clk {SYS_PLL, 3} +#define sys_lcd_clk {SYS_PLL, 4} +#define sys_vlynq_ref_clk {SYS_PLL, 5} +#define sys_tsc_clk {SYS_PLL, 6} +#define sys_half_clk {SYS_PLL, 7} + +#define eth_clk_5 {ETH_PLL, 0} +#define eth_clk_50 {ETH_PLL, 1} +#define eth_clk_125 {ETH_PLL, 2} +#define eth_clk_250 {ETH_PLL, 3} +#define eth_clk_25 {ETH_PLL, 4} + +#define tdm_clk {TDM_PLL, 0} +#define tdm_extra_clk {TDM_PLL, 1} +#define tdm1_clk {TDM_PLL, 2} + +static const struct lpsc_map lpsc_clk_map[] = { + [TNETV107X_LPSC_ARM] = sys_arm1176_clk, + [TNETV107X_LPSC_GEM] = sys_dsp_clk, + [TNETV107X_LPSC_DDR2_PHY] = sys_ddr_clk, + [TNETV107X_LPSC_TPCC] = sys_full_clk, + [TNETV107X_LPSC_TPTC0] = sys_full_clk, + [TNETV107X_LPSC_TPTC1] = sys_full_clk, + [TNETV107X_LPSC_RAM] = sys_full_clk, + [TNETV107X_LPSC_MBX_LITE] = sys_arm1176_clk, + [TNETV107X_LPSC_LCD] = sys_lcd_clk, + [TNETV107X_LPSC_ETHSS] = eth_clk_125, + [TNETV107X_LPSC_AEMIF] = sys_full_clk, + [TNETV107X_LPSC_CHIP_CFG] = sys_half_clk, + [TNETV107X_LPSC_TSC] = sys_tsc_clk, + [TNETV107X_LPSC_ROM] = sys_half_clk, + [TNETV107X_LPSC_UART2] = sys_half_clk, + [TNETV107X_LPSC_PKTSEC] = sys_half_clk, + [TNETV107X_LPSC_SECCTL] = sys_half_clk, + [TNETV107X_LPSC_KEYMGR] = sys_half_clk, + [TNETV107X_LPSC_KEYPAD] = sys_half_clk, + [TNETV107X_LPSC_GPIO] = sys_half_clk, + [TNETV107X_LPSC_MDIO] = sys_half_clk, + [TNETV107X_LPSC_SDIO0] = sys_half_clk, + [TNETV107X_LPSC_UART0] = sys_half_clk, + [TNETV107X_LPSC_UART1] = sys_half_clk, + [TNETV107X_LPSC_TIMER0] = sys_half_clk, + [TNETV107X_LPSC_TIMER1] = sys_half_clk, + [TNETV107X_LPSC_WDT_ARM] = sys_half_clk, + [TNETV107X_LPSC_WDT_DSP] = sys_half_clk, + [TNETV107X_LPSC_SSP] = sys_half_clk, + [TNETV107X_LPSC_TDM0] = tdm_clk, + [TNETV107X_LPSC_VLYNQ] = sys_vlynq_ref_clk, + [TNETV107X_LPSC_MCDMA] = sys_half_clk, + [TNETV107X_LPSC_USB0] = sys_half_clk, + [TNETV107X_LPSC_TDM1] = tdm1_clk, + [TNETV107X_LPSC_DEBUGSS] = sys_half_clk, + [TNETV107X_LPSC_ETHSS_RGMII] = eth_clk_250, + [TNETV107X_LPSC_SYSTEM] = sys_half_clk, + [TNETV107X_LPSC_IMCOP] = sys_dsp_clk, + [TNETV107X_LPSC_SPARE] = sys_half_clk, + [TNETV107X_LPSC_SDIO1] = sys_half_clk, + [TNETV107X_LPSC_USB1] = sys_half_clk, + [TNETV107X_LPSC_USBSS] = sys_half_clk, + [TNETV107X_LPSC_DDR2_EMIF1_VRST] = sys_ddr_clk, + [TNETV107X_LPSC_DDR2_EMIF2_VCTL_RST] = sys_ddr_clk, +}; + +static const unsigned long pll_ext_freq[] = { + [SYS_PLL] = CONFIG_PLL_SYS_EXT_FREQ, + [ETH_PLL] = CONFIG_PLL_ETH_EXT_FREQ, + [TDM_PLL] = CONFIG_PLL_TDM_EXT_FREQ, +}; + +static unsigned long pll_freq_get(int pll) +{ + unsigned long mult = 1, prediv = 1, postdiv = 1; + unsigned long ref = CONFIG_SYS_INT_OSC_FREQ; + unsigned long ret; + u32 bypass; + + bypass = __raw_readl((u32 *)(CLOCK_BASE)); + if (!(bypass & pll_bypass_mask[pll])) { + mult = sspll_reg_read(pll, mult_factor); + prediv = sspll_reg_read(pll, prediv) + 1; + postdiv = sspll_reg_read(pll, postdiv) + 1; + } + + if (pllctl_reg_read(pll, ctl) & PLLCTL_CLKMODE) + ref = pll_ext_freq[pll]; + + if (!(pllctl_reg_read(pll, ctl) & PLLCTL_PLLEN)) + return ref; + + ret = (unsigned long)(ref + ((unsigned long long)ref * mult) / 256); + ret /= (prediv * postdiv); + + return ret; +} + +static unsigned long __pll_div_freq_get(int pll, unsigned int fpll, + int div) +{ + int divider = 1; + unsigned long divreg; + + divreg = __raw_readl((void *)pllctl_regs[pll] + pll_div_offset[div]); + + if (divreg & PLLDIV_ENABLE) + divider = (divreg & pll_div_mask[pll]) + 1; + + return fpll / divider; +} + +static unsigned long pll_div_freq_get(int pll, int div) +{ + unsigned int fpll = pll_freq_get(pll); + + return __pll_div_freq_get(pll, fpll, div); +} + +static void __pll_div_freq_set(int pll, unsigned int fpll, int div, + unsigned long hz) +{ + int divider = (fpll / hz - 1); + + divider &= pll_div_mask[pll]; + divider |= PLLDIV_ENABLE; + + __raw_writel(divider, (void *)pllctl_regs[pll] + pll_div_offset[div]); + pllctl_reg_setbits(pll, alnctl, (1 << div)); + pllctl_reg_setbits(pll, dchange, (1 << div)); +} + +static unsigned long pll_div_freq_set(int pll, int div, unsigned long hz) +{ + unsigned int fpll = pll_freq_get(pll); + + __pll_div_freq_set(pll, fpll, div, hz); + + pllctl_reg_write(pll, cmd, 1); + + /* Wait until new divider takes effect */ + while (pllctl_reg_read(pll, stat) & 0x01); + + return __pll_div_freq_get(pll, fpll, div); +} + +unsigned long clk_get_rate(unsigned int clk) +{ + return pll_div_freq_get(lpsc_clk_map[clk].pll, lpsc_clk_map[clk].div); +} + +unsigned long clk_round_rate(unsigned int clk, unsigned long hz) +{ + unsigned long fpll, divider, pll; + + pll = lpsc_clk_map[clk].pll; + fpll = pll_freq_get(pll); + divider = (fpll / hz - 1); + divider &= pll_div_mask[pll]; + + return fpll / (divider + 1); +} + +int clk_set_rate(unsigned int clk, unsigned long _hz) +{ + unsigned long hz; + + hz = clk_round_rate(clk, _hz); + if (hz != _hz) + return -EINVAL; /* Cannot set to target freq */ + + pll_div_freq_set(lpsc_clk_map[clk].pll, lpsc_clk_map[clk].div, hz); + return 0; +} + +void lpsc_control(int mod, unsigned long state, int lrstz) +{ + u32 mdctl; + + mdctl = psc_reg_read(PSC_MDCTL(mod)); + mdctl &= ~0x1f; + mdctl |= state; + + if (lrstz == 0) + mdctl &= ~PSC_MDCTL_LRSTZ; + else if (lrstz == 1) + mdctl |= PSC_MDCTL_LRSTZ; + + psc_reg_write(PSC_MDCTL(mod), mdctl); + + psc_reg_write(PSC_PTCMD, 1); + + /* wait for power domain transition to end */ + while (psc_reg_read(PSC_PTSTAT) & 1); + + /* Wait for module state change */ + while ((psc_reg_read(PSC_MDSTAT(mod)) & 0x1f) != state); +} + +int lpsc_status(unsigned int id) +{ + return psc_reg_read(PSC_MDSTAT(id)) & 0x1f; +} + +static void init_pll(const struct pll_init_data *data) +{ + unsigned long fpll; + unsigned long best_pre = 0, best_post = 0, best_mult = 0; + unsigned long div, prediv, postdiv, mult; + unsigned long delta, actual; + long best_delta = -1; + int i; + u32 tmp; + + if (data->pll == SYS_PLL) + return; /* cannot reconfigure system pll on the fly */ + + tmp = pllctl_reg_read(data->pll, ctl); + if (data->internal_osc) { + tmp &= ~PLLCTL_CLKMODE; + fpll = CONFIG_SYS_INT_OSC_FREQ; + } else { + tmp |= PLLCTL_CLKMODE; + fpll = pll_ext_freq[data->pll]; + } + pllctl_reg_write(data->pll, ctl, tmp); + + mult = data->pll_freq / fpll; + for (mult = MAX(mult, 1); mult <= MAX_MULT; mult++) { + div = (fpll * mult) / data->pll_freq; + if (div < 1 || div > MAX_DIV) + continue; + + for (postdiv = 1; postdiv <= min(div, MAX_POSTDIV); postdiv++) { + prediv = div / postdiv; + if (prediv < 1 || prediv > MAX_PREDIV) + continue; + + actual = (fpll / prediv) * (mult / postdiv); + delta = (actual - data->pll_freq); + if (delta < 0) + delta = -delta; + if ((delta < best_delta) || (best_delta == -1)) { + best_delta = delta; + best_mult = mult; + best_pre = prediv; + best_post = postdiv; + if (delta == 0) + goto done; + } + } + } +done: + + if (best_delta == -1) { + printf("pll cannot derive %lu from %lu\n", + data->pll_freq, fpll); + return; + } + + fpll = fpll * best_mult; + fpll /= best_pre * best_post; + + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLENSRC); + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLEN); + + pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLRST); + + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLPWRDN); + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLDIS); + + sspll_reg_write(data->pll, mult_factor, (best_mult - 1) << 8); + sspll_reg_write(data->pll, prediv, best_pre - 1); + sspll_reg_write(data->pll, postdiv, best_post - 1); + + for (i = 0; i < 10; i++) + if (data->div_freq[i]) + __pll_div_freq_set(data->pll, fpll, i, + data->div_freq[i]); + + pllctl_reg_write(data->pll, cmd, 1); + + /* Wait until pll "go" operation completes */ + while (pllctl_reg_read(data->pll, stat) & 0x01); + + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLRST); + pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLEN); +} + +void init_plls(int num_pll, struct pll_init_data *config) +{ + int i; + + for (i = 0; i < num_pll; i++) + init_pll(&config[i]); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/init.c b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/init.c new file mode 100644 index 000000000..d8708267d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/init.c @@ -0,0 +1,22 @@ +/* + * TNETV107X: Architecture initialization + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> + +void chip_configuration_unlock(void) +{ + __raw_writel(TNETV107X_KICK0_MAGIC, TNETV107X_KICK0); + __raw_writel(TNETV107X_KICK1_MAGIC, TNETV107X_KICK1); +} + +int arch_cpu_init(void) +{ + icache_enable(); + chip_configuration_unlock(); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/lowlevel_init.S new file mode 100644 index 000000000..a8bce4784 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/lowlevel_init.S @@ -0,0 +1,10 @@ +/* + * TNETV107X: Low-level pre-relocation initialization + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.globl lowlevel_init +lowlevel_init: + /* nothing for now, maybe needed for more exotic boot modes */ + mov pc, lr diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/mux.c b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/mux.c new file mode 100644 index 000000000..310d84dfb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/mux.c @@ -0,0 +1,319 @@ +/* + * TNETV107X: Pinmux configuration + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/mux.h> + +#define MUX_MODE_1 0x00 +#define MUX_MODE_2 0x04 +#define MUX_MODE_3 0x0c +#define MUX_MODE_4 0x1c + +#define MUX_DEBUG 0 + +static const struct pin_config pin_table[] = { + /* reg shift mode */ + TNETV107X_MUX_CFG(0, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(0, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(0, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(0, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(0, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(0, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(0, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(0, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(0, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(0, 20, MUX_MODE_2), + TNETV107X_MUX_CFG(0, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(0, 25, MUX_MODE_2), + TNETV107X_MUX_CFG(1, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(1, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(1, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(1, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(1, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(1, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(1, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(1, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(1, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(1, 20, MUX_MODE_2), + TNETV107X_MUX_CFG(1, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(1, 25, MUX_MODE_2), + TNETV107X_MUX_CFG(2, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(2, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(2, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(2, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(2, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(2, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(2, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(2, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(2, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(2, 20, MUX_MODE_2), + TNETV107X_MUX_CFG(2, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(2, 25, MUX_MODE_2), + TNETV107X_MUX_CFG(3, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(3, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(3, 0, MUX_MODE_4), + TNETV107X_MUX_CFG(3, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(3, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(3, 5, MUX_MODE_4), + TNETV107X_MUX_CFG(3, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(3, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(3, 10, MUX_MODE_4), + TNETV107X_MUX_CFG(3, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(3, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(3, 15, MUX_MODE_4), + TNETV107X_MUX_CFG(3, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(3, 20, MUX_MODE_2), + TNETV107X_MUX_CFG(3, 20, MUX_MODE_4), + TNETV107X_MUX_CFG(3, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(3, 25, MUX_MODE_2), + TNETV107X_MUX_CFG(3, 25, MUX_MODE_4), + TNETV107X_MUX_CFG(4, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(4, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(4, 0, MUX_MODE_4), + TNETV107X_MUX_CFG(4, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(4, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(4, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(4, 15, MUX_MODE_4), + TNETV107X_MUX_CFG(4, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(4, 20, MUX_MODE_3), + TNETV107X_MUX_CFG(4, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(4, 25, MUX_MODE_4), + TNETV107X_MUX_CFG(5, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(5, 0, MUX_MODE_4), + TNETV107X_MUX_CFG(5, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(5, 5, MUX_MODE_4), + TNETV107X_MUX_CFG(5, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(5, 10, MUX_MODE_4), + TNETV107X_MUX_CFG(5, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(5, 15, MUX_MODE_4), + TNETV107X_MUX_CFG(5, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(5, 20, MUX_MODE_4), + TNETV107X_MUX_CFG(5, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(5, 25, MUX_MODE_4), + TNETV107X_MUX_CFG(6, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(6, 0, MUX_MODE_4), + TNETV107X_MUX_CFG(6, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(6, 5, MUX_MODE_4), + TNETV107X_MUX_CFG(6, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(6, 10, MUX_MODE_4), + TNETV107X_MUX_CFG(6, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(6, 15, MUX_MODE_4), + TNETV107X_MUX_CFG(6, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(6, 20, MUX_MODE_4), + TNETV107X_MUX_CFG(6, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(6, 25, MUX_MODE_4), + TNETV107X_MUX_CFG(7, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(7, 0, MUX_MODE_4), + TNETV107X_MUX_CFG(7, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(7, 5, MUX_MODE_4), + TNETV107X_MUX_CFG(7, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(7, 10, MUX_MODE_4), + TNETV107X_MUX_CFG(7, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(7, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(7, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(7, 20, MUX_MODE_2), + TNETV107X_MUX_CFG(7, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(7, 25, MUX_MODE_2), + TNETV107X_MUX_CFG(8, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(8, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(8, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(8, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(8, 5, MUX_MODE_4), + TNETV107X_MUX_CFG(8, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(8, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(9, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(9, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(9, 0, MUX_MODE_4), + TNETV107X_MUX_CFG(9, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(9, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(9, 5, MUX_MODE_4), + TNETV107X_MUX_CFG(9, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(9, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(9, 10, MUX_MODE_4), + TNETV107X_MUX_CFG(9, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(9, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(9, 15, MUX_MODE_4), + TNETV107X_MUX_CFG(9, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(9, 20, MUX_MODE_2), + TNETV107X_MUX_CFG(9, 20, MUX_MODE_4), + TNETV107X_MUX_CFG(10, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(10, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(10, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(10, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(10, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(10, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(10, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(10, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(10, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(10, 20, MUX_MODE_2), + TNETV107X_MUX_CFG(10, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(10, 25, MUX_MODE_2), + TNETV107X_MUX_CFG(11, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(11, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(12, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(12, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(12, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(12, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(12, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(12, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(13, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(13, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(13, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(13, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(14, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(14, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(14, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(14, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(14, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(14, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(15, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(15, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(15, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(15, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(15, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(15, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(15, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(15, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(16, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(16, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(16, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(16, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(16, 10, MUX_MODE_3), + TNETV107X_MUX_CFG(16, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(16, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(17, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(17, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(17, 0, MUX_MODE_3), + TNETV107X_MUX_CFG(17, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(17, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(17, 5, MUX_MODE_3), + TNETV107X_MUX_CFG(17, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(17, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(17, 10, MUX_MODE_3), + TNETV107X_MUX_CFG(17, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(17, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(17, 15, MUX_MODE_3), + TNETV107X_MUX_CFG(18, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(18, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(18, 0, MUX_MODE_3), + TNETV107X_MUX_CFG(18, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(18, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(18, 5, MUX_MODE_3), + TNETV107X_MUX_CFG(18, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(18, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(18, 10, MUX_MODE_3), + TNETV107X_MUX_CFG(18, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(18, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(18, 15, MUX_MODE_3), + TNETV107X_MUX_CFG(19, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(19, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(19, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(19, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(19, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(19, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(20, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(20, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(20, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(20, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(20, 15, MUX_MODE_3), + TNETV107X_MUX_CFG(20, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(20, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(21, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(21, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(21, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(21, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(21, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(21, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(22, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(22, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(22, 5, MUX_MODE_3), + TNETV107X_MUX_CFG(22, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(22, 10, MUX_MODE_3), + TNETV107X_MUX_CFG(22, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(22, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(22, 15, MUX_MODE_3), + TNETV107X_MUX_CFG(22, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(22, 20, MUX_MODE_3), + TNETV107X_MUX_CFG(22, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(22, 25, MUX_MODE_3), + TNETV107X_MUX_CFG(23, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(23, 0, MUX_MODE_3), + TNETV107X_MUX_CFG(23, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(23, 5, MUX_MODE_3), + TNETV107X_MUX_CFG(23, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(23, 10, MUX_MODE_3), + TNETV107X_MUX_CFG(24, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(24, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(24, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(24, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(24, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(24, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(24, 10, MUX_MODE_3), + TNETV107X_MUX_CFG(24, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(24, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(24, 15, MUX_MODE_3), + TNETV107X_MUX_CFG(24, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(24, 20, MUX_MODE_2), + TNETV107X_MUX_CFG(24, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(24, 25, MUX_MODE_2), + TNETV107X_MUX_CFG(25, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(25, 0, MUX_MODE_2), + TNETV107X_MUX_CFG(25, 0, MUX_MODE_3), + TNETV107X_MUX_CFG(25, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(25, 5, MUX_MODE_2), + TNETV107X_MUX_CFG(25, 5, MUX_MODE_3), + TNETV107X_MUX_CFG(25, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(25, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(25, 10, MUX_MODE_3), + TNETV107X_MUX_CFG(25, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(25, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(25, 15, MUX_MODE_3), + TNETV107X_MUX_CFG(25, 15, MUX_MODE_4), + TNETV107X_MUX_CFG(26, 0, MUX_MODE_1), + TNETV107X_MUX_CFG(26, 5, MUX_MODE_1), + TNETV107X_MUX_CFG(26, 10, MUX_MODE_1), + TNETV107X_MUX_CFG(26, 10, MUX_MODE_2), + TNETV107X_MUX_CFG(26, 15, MUX_MODE_1), + TNETV107X_MUX_CFG(26, 15, MUX_MODE_2), + TNETV107X_MUX_CFG(26, 20, MUX_MODE_1), + TNETV107X_MUX_CFG(26, 20, MUX_MODE_2), + TNETV107X_MUX_CFG(26, 25, MUX_MODE_1), + TNETV107X_MUX_CFG(26, 25, MUX_MODE_2), +}; + +const int pin_table_size = sizeof(pin_table) / sizeof(pin_table[0]); + +int mux_select_pin(short index) +{ + const struct pin_config *cfg; + unsigned long mask, mode, reg; + + if (index >= pin_table_size) + return 0; + + cfg = &pin_table[index]; + + mask = 0x1f << cfg->mask_offset; + mode = cfg->mode << cfg->mask_offset; + + reg = __raw_readl(TNETV107X_PINMUX(cfg->reg_index)); + reg = (reg & ~mask) | mode; + __raw_writel(reg, TNETV107X_PINMUX(cfg->reg_index)); + + return 1; +} + +int mux_select_pins(const short *pins) +{ + int i, ret = 1; + + for (i = 0; pins[i] >= 0; i++) + ret &= mux_select_pin(pins[i]); + + return ret; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/timer.c new file mode 100644 index 000000000..6e0dd0d2b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm1176/tnetv107x/timer.c @@ -0,0 +1,93 @@ +/* + * TNETV107X: Timer implementation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> + +struct timer_regs { + u_int32_t pid12; + u_int32_t pad[3]; + u_int32_t tim12; + u_int32_t tim34; + u_int32_t prd12; + u_int32_t prd34; + u_int32_t tcr; + u_int32_t tgcr; + u_int32_t wdtcr; +}; + +#define regs ((struct timer_regs *)CONFIG_SYS_TIMERBASE) + +#define TIMER_LOAD_VAL (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ) +#define TIM_CLK_DIV 16 + +static ulong timestamp; +static ulong lastinc; + +int timer_init(void) +{ + clk_enable(TNETV107X_LPSC_TIMER0); + + lastinc = timestamp = 0; + + /* We are using timer34 in unchained 32-bit mode, full speed */ + __raw_writel(0x0, ®s->tcr); + __raw_writel(0x0, ®s->tgcr); + __raw_writel(0x06 | ((TIM_CLK_DIV - 1) << 8), ®s->tgcr); + __raw_writel(0x0, ®s->tim34); + __raw_writel(TIMER_LOAD_VAL, ®s->prd34); + __raw_writel(2 << 22, ®s->tcr); + + return 0; +} + +static ulong get_timer_raw(void) +{ + ulong now = __raw_readl(®s->tim34); + + if (now >= lastinc) + timestamp += now - lastinc; + else + timestamp += now + TIMER_LOAD_VAL - lastinc; + + lastinc = now; + + return timestamp; +} + +ulong get_timer(ulong base) +{ + return (get_timer_raw() / (TIMER_LOAD_VAL / TIM_CLK_DIV)) - base; +} + +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +void __udelay(unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + tmo = CONFIG_SYS_HZ_CLOCK / 1000; + tmo *= usec; + tmo /= (1000 * TIM_CLK_DIV); + + endtime = get_timer_raw() + tmo; + + do { + ulong now = get_timer_raw(); + diff = endtime - now; + } while (diff >= 0); +} + +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm720t/Makefile new file mode 100644 index 000000000..6badb3bb8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/Makefile @@ -0,0 +1,11 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y = start.o +obj-y = interrupts.o cpu.o + +obj-$(CONFIG_TEGRA) += tegra-common/ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/config.mk b/qemu/roms/u-boot/arch/arm/cpu/arm720t/config.mk new file mode 100644 index 000000000..772fb413e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/config.mk @@ -0,0 +1,9 @@ +# +# (C) Copyright 2002 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +PLATFORM_CPPFLAGS += -march=armv4 -mtune=arm7tdmi diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm720t/cpu.c new file mode 100644 index 000000000..745fccdfb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/cpu.c @@ -0,0 +1,22 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * cleanup_before_linux() - Prepare the CPU to jump to Linux + * + * This function is called just before we call Linux, it + * prepares the processor for linux + */ +int cleanup_before_linux(void) +{ + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/interrupts.c b/qemu/roms/u-boot/arch/arm/cpu/arm720t/interrupts.c new file mode 100644 index 000000000..e8ba1ae09 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/interrupts.c @@ -0,0 +1,33 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#ifdef CONFIG_USE_IRQ +void do_irq (struct pt_regs *pt_regs) +{ +} +#endif + +#if defined(CONFIG_TEGRA) +static ulong timestamp; +static ulong lastdec; + +int timer_init (void) +{ + /* No timer routines for tegra as yet */ + lastdec = 0; + timestamp = 0; + + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/start.S b/qemu/roms/u-boot/arch/arm/cpu/arm720t/start.S new file mode 100644 index 000000000..1a3484269 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/start.S @@ -0,0 +1,307 @@ +/* + * armboot - Startup Code for ARM720 CPU-core + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> +#include <asm/hardware.h> + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + + +.globl _start +_start: b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +#ifdef CONFIG_SPL_BUILD +_undefined_instruction: .word _undefined_instruction +_software_interrupt: .word _software_interrupt +_prefetch_abort: .word _prefetch_abort +_data_abort: .word _data_abort +_not_used: .word _not_used +_irq: .word _irq +_fiq: .word _fiq +_pad: .word 0x12345678 /* now 16*4=64 */ +#else +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq +_pad: .word 0x12345678 /* now 16*4=64 */ +#endif /* CONFIG_SPL_BUILD */ + + .balignl 16,0xdeadbeef + + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from RAM! + * relocate armboot to ram + * setup stack + * jump to second stage + * + ************************************************************************* + */ + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + + mov ip, lr + /* + * before relocating, we have to setup RAM timing + * because memory timing is board-dependent, you will + * find a lowlevel_init.S in your board directory. + */ + bl lowlevel_init + mov lr, ip + + mov pc, lr +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + + +#ifndef CONFIG_SPL_BUILD +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC + + ldr r2, IRQ_STACK_START_IN + ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 + add r0, sp, #S_FRAME_SIZE @ restore sp_SVC + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r + mov r0, sp + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + + str lr, [r13] @ save caller lr / spsr + mrs lr, spsr + str lr, [r13, #4] + + mov r13, #MODE_SVC @ prepare SVC-Mode + msr spsr_c, r13 + mov lr, pc + movs pc, lr + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif +#endif /* CONFIG_SPL_BUILD */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/Makefile new file mode 100644 index 000000000..a9c2b675a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/Makefile @@ -0,0 +1,11 @@ +# +# (C) Copyright 2010,2011 Nvidia Corporation. +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_SPL_BUILD) += spl.o +obj-y += cpu.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/cpu.c new file mode 100644 index 000000000..168f525ec --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/cpu.c @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/gp_padctrl.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/scu.h> +#include "cpu.h" + +int get_num_cpus(void) +{ + struct apb_misc_gp_ctlr *gp; + uint rev; + + gp = (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; + rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT; + + switch (rev) { + case CHIPID_TEGRA20: + return 2; + break; + case CHIPID_TEGRA30: + case CHIPID_TEGRA114: + default: + return 4; + break; + } +} + +/* + * Timing tables for each SOC for all four oscillator options. + */ +struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = { + /* + * T20: 1 GHz + * + * Register Field Bits Width + * ------------------------------ + * PLLX_BASE p 22:20 3 + * PLLX_BASE n 17: 8 10 + * PLLX_BASE m 4: 0 5 + * PLLX_MISC cpcon 11: 8 4 + */ + { + { .n = 1000, .m = 13, .p = 0, .cpcon = 12 }, /* OSC: 13.0 MHz */ + { .n = 625, .m = 12, .p = 0, .cpcon = 8 }, /* OSC: 19.2 MHz */ + { .n = 1000, .m = 12, .p = 0, .cpcon = 12 }, /* OSC: 12.0 MHz */ + { .n = 1000, .m = 26, .p = 0, .cpcon = 12 }, /* OSC: 26.0 MHz */ + }, + /* + * T25: 1.2 GHz + * + * Register Field Bits Width + * ------------------------------ + * PLLX_BASE p 22:20 3 + * PLLX_BASE n 17: 8 10 + * PLLX_BASE m 4: 0 5 + * PLLX_MISC cpcon 11: 8 4 + */ + { + { .n = 923, .m = 10, .p = 0, .cpcon = 12 }, /* OSC: 13.0 MHz */ + { .n = 750, .m = 12, .p = 0, .cpcon = 8 }, /* OSC: 19.2 MHz */ + { .n = 600, .m = 6, .p = 0, .cpcon = 12 }, /* OSC: 12.0 MHz */ + { .n = 600, .m = 13, .p = 0, .cpcon = 12 }, /* OSC: 26.0 MHz */ + }, + /* + * T30: 1.4 GHz + * + * Register Field Bits Width + * ------------------------------ + * PLLX_BASE p 22:20 3 + * PLLX_BASE n 17: 8 10 + * PLLX_BASE m 4: 0 5 + * PLLX_MISC cpcon 11: 8 4 + */ + { + { .n = 862, .m = 8, .p = 0, .cpcon = 8 }, /* OSC: 13.0 MHz */ + { .n = 583, .m = 8, .p = 0, .cpcon = 4 }, /* OSC: 19.2 MHz */ + { .n = 700, .m = 6, .p = 0, .cpcon = 8 }, /* OSC: 12.0 MHz */ + { .n = 700, .m = 13, .p = 0, .cpcon = 8 }, /* OSC: 26.0 MHz */ + }, + /* + * T114: 700 MHz + * + * Register Field Bits Width + * ------------------------------ + * PLLX_BASE p 23:20 4 + * PLLX_BASE n 15: 8 8 + * PLLX_BASE m 7: 0 8 + */ + { + { .n = 108, .m = 1, .p = 1 }, /* OSC: 13.0 MHz */ + { .n = 73, .m = 1, .p = 1 }, /* OSC: 19.2 MHz */ + { .n = 116, .m = 1, .p = 1 }, /* OSC: 12.0 MHz */ + { .n = 108, .m = 2, .p = 1 }, /* OSC: 26.0 MHz */ + }, + + /* + * T124: 700 MHz + * + * Register Field Bits Width + * ------------------------------ + * PLLX_BASE p 23:20 4 + * PLLX_BASE n 15: 8 8 + * PLLX_BASE m 7: 0 8 + */ + { + { .n = 108, .m = 1, .p = 1 }, /* OSC: 13.0 MHz */ + { .n = 73, .m = 1, .p = 1 }, /* OSC: 19.2 MHz */ + { .n = 116, .m = 1, .p = 1 }, /* OSC: 12.0 MHz */ + { .n = 108, .m = 2, .p = 1 }, /* OSC: 26.0 MHz */ + }, +}; + +static inline void pllx_set_iddq(void) +{ +#if defined(CONFIG_TEGRA124) + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + /* Disable IDDQ */ + reg = readl(&clkrst->crc_pllx_misc3); + reg &= ~PLLX_IDDQ_MASK; + writel(reg, &clkrst->crc_pllx_misc3); + udelay(2); + debug("%s: IDDQ: PLLX IDDQ = 0x%08X\n", __func__, + readl(&clkrst->crc_pllx_misc3)); +#endif +} + +int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm, + u32 divp, u32 cpcon) +{ + int chip = tegra_get_chip(); + u32 reg; + + /* If PLLX is already enabled, just return */ + if (readl(&pll->pll_base) & PLL_ENABLE_MASK) { + debug("pllx_set_rate: PLLX already enabled, returning\n"); + return 0; + } + + debug(" pllx_set_rate entry\n"); + + pllx_set_iddq(); + + /* Set BYPASS, m, n and p to PLLX_BASE */ + reg = PLL_BYPASS_MASK | (divm << PLL_DIVM_SHIFT); + reg |= ((divn << PLL_DIVN_SHIFT) | (divp << PLL_DIVP_SHIFT)); + writel(reg, &pll->pll_base); + + /* Set cpcon to PLLX_MISC */ + if (chip == CHIPID_TEGRA20 || chip == CHIPID_TEGRA30) + reg = (cpcon << PLL_CPCON_SHIFT); + else + reg = 0; + + /* Set dccon to PLLX_MISC if freq > 600MHz */ + if (divn > 600) + reg |= (1 << PLL_DCCON_SHIFT); + writel(reg, &pll->pll_misc); + + /* Disable BYPASS */ + reg = readl(&pll->pll_base); + reg &= ~PLL_BYPASS_MASK; + writel(reg, &pll->pll_base); + debug("pllx_set_rate: base = 0x%08X\n", reg); + + /* Set lock_enable to PLLX_MISC */ + reg = readl(&pll->pll_misc); + reg |= PLL_LOCK_ENABLE_MASK; + writel(reg, &pll->pll_misc); + debug("pllx_set_rate: misc = 0x%08X\n", reg); + + /* Enable PLLX last, once it's all configured */ + reg = readl(&pll->pll_base); + reg |= PLL_ENABLE_MASK; + writel(reg, &pll->pll_base); + debug("pllx_set_rate: base final = 0x%08X\n", reg); + + return 0; +} + +void init_pllx(void) +{ + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + struct clk_pll_simple *pll = &clkrst->crc_pll_simple[SIMPLE_PLLX]; + int soc_type, sku_info, chip_sku; + enum clock_osc_freq osc; + struct clk_pll_table *sel; + + debug("init_pllx entry\n"); + + /* get SOC (chip) type */ + soc_type = tegra_get_chip(); + debug(" init_pllx: SoC = 0x%02X\n", soc_type); + + /* get SKU info */ + sku_info = tegra_get_sku_info(); + debug(" init_pllx: SKU info byte = 0x%02X\n", sku_info); + + /* get chip SKU, combo of the above info */ + chip_sku = tegra_get_chip_sku(); + debug(" init_pllx: Chip SKU = %d\n", chip_sku); + + /* get osc freq */ + osc = clock_get_osc_freq(); + debug(" init_pllx: osc = %d\n", osc); + + /* set pllx */ + sel = &tegra_pll_x_table[chip_sku][osc]; + pllx_set_rate(pll, sel->n, sel->m, sel->p, sel->cpcon); +} + +void enable_cpu_clock(int enable) +{ + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 clk; + + /* + * NOTE: + * Regardless of whether the request is to enable or disable the CPU + * clock, every processor in the CPU complex except the master (CPU 0) + * will have it's clock stopped because the AVP only talks to the + * master. + */ + + if (enable) { + /* Initialize PLLX */ + init_pllx(); + + /* Wait until all clocks are stable */ + udelay(PLL_STABILIZATION_DELAY); + + writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol); + writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div); + } + + /* + * Read the register containing the individual CPU clock enables and + * always stop the clocks to CPUs > 0. + */ + clk = readl(&clkrst->crc_clk_cpu_cmplx); + clk |= 1 << CPU1_CLK_STP_SHIFT; + if (get_num_cpus() == 4) + clk |= (1 << CPU2_CLK_STP_SHIFT) + (1 << CPU3_CLK_STP_SHIFT); + + /* Stop/Unstop the CPU clock */ + clk &= ~CPU0_CLK_STP_MASK; + clk |= !enable << CPU0_CLK_STP_SHIFT; + writel(clk, &clkrst->crc_clk_cpu_cmplx); + + clock_enable(PERIPH_ID_CPU); +} + +static int is_cpu_powered(void) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0; +} + +static void remove_cpu_io_clamps(void) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 reg; + + /* Remove the clamps on the CPU I/O signals */ + reg = readl(&pmc->pmc_remove_clamping); + reg |= CPU_CLMP; + writel(reg, &pmc->pmc_remove_clamping); + + /* Give I/O signals time to stabilize */ + udelay(IO_STABILIZATION_DELAY); +} + +void powerup_cpu(void) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 reg; + int timeout = IO_STABILIZATION_DELAY; + + if (!is_cpu_powered()) { + /* Toggle the CPU power state (OFF -> ON) */ + reg = readl(&pmc->pmc_pwrgate_toggle); + reg &= PARTID_CP; + reg |= START_CP; + writel(reg, &pmc->pmc_pwrgate_toggle); + + /* Wait for the power to come up */ + while (!is_cpu_powered()) { + if (timeout-- == 0) + printf("CPU failed to power up!\n"); + else + udelay(10); + } + + /* + * Remove the I/O clamps from CPU power partition. + * Recommended only on a Warm boot, if the CPU partition gets + * power gated. Shouldn't cause any harm when called after a + * cold boot according to HW, probably just redundant. + */ + remove_cpu_io_clamps(); + } +} + +void reset_A9_cpu(int reset) +{ + /* + * NOTE: Regardless of whether the request is to hold the CPU in reset + * or take it out of reset, every processor in the CPU complex + * except the master (CPU 0) will be held in reset because the + * AVP only talks to the master. The AVP does not know that there + * are multiple processors in the CPU complex. + */ + int mask = crc_rst_cpu | crc_rst_de | crc_rst_debug; + int num_cpus = get_num_cpus(); + int cpu; + + debug("reset_a9_cpu entry\n"); + /* Hold CPUs 1 onwards in reset, and CPU 0 if asked */ + for (cpu = 1; cpu < num_cpus; cpu++) + reset_cmplx_set_enable(cpu, mask, 1); + reset_cmplx_set_enable(0, mask, reset); + + /* Enable/Disable master CPU reset */ + reset_set_enable(PERIPH_ID_CPU, reset); +} + +void clock_enable_coresight(int enable) +{ + u32 rst, src = 2; + + debug("clock_enable_coresight entry\n"); + clock_set_enable(PERIPH_ID_CORESIGHT, enable); + reset_set_enable(PERIPH_ID_CORESIGHT, !enable); + + if (enable) { + /* + * Put CoreSight on PLLP_OUT0 and divide it down as per + * PLLP base frequency based on SoC type (T20/T30+). + * Clock divider request would setup CSITE clock as 144MHz + * for PLLP base 216MHz and 204MHz for PLLP base 408MHz + */ + src = CLK_DIVIDER(NVBL_PLLP_KHZ, CSITE_KHZ); + clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src); + + /* Unlock the CPU CoreSight interfaces */ + rst = CORESIGHT_UNLOCK; + writel(rst, CSITE_CPU_DBG0_LAR); + writel(rst, CSITE_CPU_DBG1_LAR); + if (get_num_cpus() == 4) { + writel(rst, CSITE_CPU_DBG2_LAR); + writel(rst, CSITE_CPU_DBG3_LAR); + } + } +} + +void halt_avp(void) +{ + for (;;) { + writel(HALT_COP_EVENT_JTAG | (FLOW_MODE_STOP << 29), + FLOW_CTLR_HALT_COP_EVENTS); + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/cpu.h b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/cpu.h new file mode 100644 index 000000000..b4ca44fce --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/cpu.h @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2010-2014 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <asm/types.h> + +/* Stabilization delays, in usec */ +#define PLL_STABILIZATION_DELAY (300) +#define IO_STABILIZATION_DELAY (1000) + +#if defined(CONFIG_TEGRA20) +#define NVBL_PLLP_KHZ 216000 +#define CSITE_KHZ 144000 +#elif defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114) || \ + defined(CONFIG_TEGRA124) +#define NVBL_PLLP_KHZ 408000 +#define CSITE_KHZ 204000 +#else +#error "Unknown Tegra chip!" +#endif + +#define PLLX_ENABLED (1 << 30) +#define CCLK_BURST_POLICY 0x20008888 +#define SUPER_CCLK_DIVIDER 0x80000000 + +/* Calculate clock fractional divider value from ref and target frequencies */ +#define CLK_DIVIDER(REF, FREQ) ((((REF) * 2) / FREQ) - 2) + +/* Calculate clock frequency value from reference and clock divider value */ +#define CLK_FREQUENCY(REF, REG) (((REF) * 2) / (REG + 2)) + +/* AVP/CPU ID */ +#define PG_UP_TAG_0_PID_CPU 0x55555555 /* CPU aka "a9" aka "mpcore" */ +#define PG_UP_TAG_0 0x0 + +#define CORESIGHT_UNLOCK 0xC5ACCE55; + +#define EXCEP_VECTOR_CPU_RESET_VECTOR (NV_PA_EVP_BASE + 0x100) +#define CSITE_CPU_DBG0_LAR (NV_PA_CSITE_BASE + 0x10FB0) +#define CSITE_CPU_DBG1_LAR (NV_PA_CSITE_BASE + 0x12FB0) +#define CSITE_CPU_DBG2_LAR (NV_PA_CSITE_BASE + 0x14FB0) +#define CSITE_CPU_DBG3_LAR (NV_PA_CSITE_BASE + 0x16FB0) + +#define FLOW_CTLR_HALT_COP_EVENTS (NV_PA_FLOW_BASE + 4) +#define FLOW_MODE_STOP 2 +#define HALT_COP_EVENT_JTAG (1 << 28) +#define HALT_COP_EVENT_IRQ_1 (1 << 11) +#define HALT_COP_EVENT_FIQ_1 (1 << 9) + +#define FLOW_MODE_NONE 0 + +#define SIMPLE_PLLX (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE) + +struct clk_pll_table { + u16 n; + u16 m; + u8 p; + u8 cpcon; +}; + +void clock_enable_coresight(int enable); +void enable_cpu_clock(int enable); +void halt_avp(void) __attribute__ ((noreturn)); +void init_pllx(void); +void powerup_cpu(void); +void reset_A9_cpu(int reset); +void start_cpu(u32 reset_vector); +int tegra_get_chip(void); +int tegra_get_sku_info(void); +int tegra_get_chip_sku(void); +void adjust_pllp_out_freqs(void); +void pmic_enable_cpu_vdd(void); diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/spl.c b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/spl.c new file mode 100644 index 000000000..347954102 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra-common/spl.c @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2012 + * NVIDIA Inc, <www.nvidia.com> + * + * Allen Martin <amartin@nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <spl.h> + +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/apb_misc.h> +#include <asm/arch-tegra/board.h> +#include <asm/arch/spl.h> +#include "cpu.h" + +void spl_board_init(void) +{ + struct apb_misc_pp_ctlr *apb_misc = + (struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE; + + /* enable JTAG */ + writel(0xC0, &apb_misc->cfg_ctl); + + board_init_uart_f(); + + /* Initialize periph GPIOs */ + gpio_early_init_uart(); + + clock_early_init(); + preloader_console_init(); +} + +u32 spl_boot_device(void) +{ + return BOOT_DEVICE_RAM; +} + +void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) +{ + debug("image entry point: 0x%X\n", spl_image->entry_point); + + start_cpu((u32)spl_image->entry_point); + halt_avp(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra114/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra114/Makefile new file mode 100644 index 000000000..ea3e55ea6 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra114/Makefile @@ -0,0 +1,21 @@ +# +# Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +#obj-y += cpu.o t11x.o +obj-y += cpu.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra114/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra114/cpu.c new file mode 100644 index 000000000..5ed3bb9d9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra114/cpu.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/flow.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/pmc.h> +#include "../tegra-common/cpu.h" + +/* Tegra114-specific CPU init code */ +static void enable_cpu_power_rail(void) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + debug("enable_cpu_power_rail entry\n"); + + /* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */ + pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SCL_PZ6); + pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SDA_PZ7); + + /* + * Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (102MHz), + * set it for 25ms (102MHz * .025) + */ + reg = 0x26E8F0; + writel(reg, &pmc->pmc_cpupwrgood_timer); + + /* Set polarity to 0 (normal) and enable CPUPWRREQ_OE */ + clrbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_POL); + setbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_OE); + + /* + * Set CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2_0_CAR2PMC_CPU_ACK_WIDTH + * to 408 to satisfy the requirement of having at least 16 CPU clock + * cycles before clamp removal. + */ + + clrbits_le32(&clkrst->crc_cpu_softrst_ctrl2, 0xFFF); + setbits_le32(&clkrst->crc_cpu_softrst_ctrl2, 408); +} + +static void enable_cpu_clocks(void) +{ + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + debug("enable_cpu_clocks entry\n"); + + /* Wait for PLL-X to lock */ + do { + reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); + } while ((reg & PLL_LOCK_MASK) == 0); + + /* Wait until all clocks are stable */ + udelay(PLL_STABILIZATION_DELAY); + + writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol); + writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div); + + /* Always enable the main CPU complex clocks */ + clock_enable(PERIPH_ID_CPU); + clock_enable(PERIPH_ID_CPULP); + clock_enable(PERIPH_ID_CPUG); +} + +static void remove_cpu_resets(void) +{ + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + debug("remove_cpu_resets entry\n"); + /* Take the slow non-CPU partition out of reset */ + reg = readl(&clkrst->crc_rst_cpulp_cmplx_clr); + writel((reg | CLR_NONCPURESET), &clkrst->crc_rst_cpulp_cmplx_clr); + + /* Take the fast non-CPU partition out of reset */ + reg = readl(&clkrst->crc_rst_cpug_cmplx_clr); + writel((reg | CLR_NONCPURESET), &clkrst->crc_rst_cpug_cmplx_clr); + + /* Clear the SW-controlled reset of the slow cluster */ + reg = readl(&clkrst->crc_rst_cpulp_cmplx_clr); + reg |= (CLR_CPURESET0+CLR_DBGRESET0+CLR_CORERESET0+CLR_CXRESET0); + writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr); + + /* Clear the SW-controlled reset of the fast cluster */ + reg = readl(&clkrst->crc_rst_cpug_cmplx_clr); + reg |= (CLR_CPURESET0+CLR_DBGRESET0+CLR_CORERESET0+CLR_CXRESET0); + reg |= (CLR_CPURESET1+CLR_DBGRESET1+CLR_CORERESET1+CLR_CXRESET1); + reg |= (CLR_CPURESET2+CLR_DBGRESET2+CLR_CORERESET2+CLR_CXRESET2); + reg |= (CLR_CPURESET3+CLR_DBGRESET3+CLR_CORERESET3+CLR_CXRESET3); + writel(reg, &clkrst->crc_rst_cpug_cmplx_clr); +} + +/** + * The T114 requires some special clock initialization, including setting up + * the DVC I2C, turning on MSELECT and selecting the G CPU cluster + */ +void t114_init_clocks(void) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; + u32 val; + + debug("t114_init_clocks entry\n"); + + /* Set active CPU cluster to G */ + clrbits_le32(&flow->cluster_control, 1); + + writel(SUPER_SCLK_ENB_MASK, &clkrst->crc_super_sclk_div); + + debug("Setting up PLLX\n"); + init_pllx(); + + val = (1 << CLK_SYS_RATE_AHB_RATE_SHIFT); + writel(val, &clkrst->crc_clk_sys_rate); + + /* Enable clocks to required peripherals. TBD - minimize this list */ + debug("Enabling clocks\n"); + + clock_set_enable(PERIPH_ID_CACHE2, 1); + clock_set_enable(PERIPH_ID_GPIO, 1); + clock_set_enable(PERIPH_ID_TMR, 1); + clock_set_enable(PERIPH_ID_RTC, 1); + clock_set_enable(PERIPH_ID_CPU, 1); + clock_set_enable(PERIPH_ID_EMC, 1); + clock_set_enable(PERIPH_ID_I2C5, 1); + clock_set_enable(PERIPH_ID_FUSE, 1); + clock_set_enable(PERIPH_ID_PMC, 1); + clock_set_enable(PERIPH_ID_APBDMA, 1); + clock_set_enable(PERIPH_ID_MEM, 1); + clock_set_enable(PERIPH_ID_IRAMA, 1); + clock_set_enable(PERIPH_ID_IRAMB, 1); + clock_set_enable(PERIPH_ID_IRAMC, 1); + clock_set_enable(PERIPH_ID_IRAMD, 1); + clock_set_enable(PERIPH_ID_CORESIGHT, 1); + clock_set_enable(PERIPH_ID_MSELECT, 1); + clock_set_enable(PERIPH_ID_EMC1, 1); + clock_set_enable(PERIPH_ID_MC1, 1); + clock_set_enable(PERIPH_ID_DVFS, 1); + + /* + * Set MSELECT clock source as PLLP (00), and ask for a clock + * divider that would set the MSELECT clock at 102MHz for a + * PLLP base of 408MHz. + */ + clock_ll_set_source_divisor(PERIPH_ID_MSELECT, 0, + CLK_DIVIDER(NVBL_PLLP_KHZ, 102000)); + + /* I2C5 (DVC) gets CLK_M and a divisor of 17 */ + clock_ll_set_source_divisor(PERIPH_ID_I2C5, 3, 16); + + /* Give clocks time to stabilize */ + udelay(1000); + + /* Take required peripherals out of reset */ + debug("Taking periphs out of reset\n"); + reset_set_enable(PERIPH_ID_CACHE2, 0); + reset_set_enable(PERIPH_ID_GPIO, 0); + reset_set_enable(PERIPH_ID_TMR, 0); + reset_set_enable(PERIPH_ID_COP, 0); + reset_set_enable(PERIPH_ID_EMC, 0); + reset_set_enable(PERIPH_ID_I2C5, 0); + reset_set_enable(PERIPH_ID_FUSE, 0); + reset_set_enable(PERIPH_ID_APBDMA, 0); + reset_set_enable(PERIPH_ID_MEM, 0); + reset_set_enable(PERIPH_ID_CORESIGHT, 0); + reset_set_enable(PERIPH_ID_MSELECT, 0); + reset_set_enable(PERIPH_ID_EMC1, 0); + reset_set_enable(PERIPH_ID_MC1, 0); + reset_set_enable(PERIPH_ID_DVFS, 0); + + debug("t114_init_clocks exit\n"); +} + +static bool is_partition_powered(u32 partid) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 reg; + + /* Get power gate status */ + reg = readl(&pmc->pmc_pwrgate_status); + return !!(reg & (1 << partid)); +} + +static bool is_clamp_enabled(u32 partid) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 reg; + + /* Get clamp status. */ + reg = readl(&pmc->pmc_clamp_status); + return !!(reg & (1 << partid)); +} + +static void power_partition(u32 partid) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + debug("%s: part ID = %08X\n", __func__, partid); + /* Is the partition already on? */ + if (!is_partition_powered(partid)) { + /* No, toggle the partition power state (OFF -> ON) */ + debug("power_partition, toggling state\n"); + writel(START_CP | partid, &pmc->pmc_pwrgate_toggle); + + /* Wait for the power to come up */ + while (!is_partition_powered(partid)) + ; + + /* Wait for the clamp status to be cleared */ + while (is_clamp_enabled(partid)) + ; + + /* Give I/O signals time to stabilize */ + udelay(IO_STABILIZATION_DELAY); + } +} + +void powerup_cpus(void) +{ + debug("powerup_cpus entry\n"); + + /* We boot to the fast cluster */ + debug("powerup_cpus entry: G cluster\n"); + /* Power up the fast cluster rail partition */ + power_partition(CRAIL); + + /* Power up the fast cluster non-CPU partition */ + power_partition(C0NC); + + /* Power up the fast cluster CPU0 partition */ + power_partition(CE0); +} + +void start_cpu(u32 reset_vector) +{ + u32 imme, inst; + + debug("start_cpu entry, reset_vector = %x\n", reset_vector); + + t114_init_clocks(); + + /* Enable VDD_CPU */ + enable_cpu_power_rail(); + + /* Get the CPU(s) running */ + enable_cpu_clocks(); + + /* Enable CoreSight */ + clock_enable_coresight(1); + + /* Take CPU(s) out of reset */ + remove_cpu_resets(); + + /* Set the entry point for CPU execution from reset */ + + /* + * A01P with patched boot ROM; vector hard-coded to 0x4003fffc. + * See nvbug 1193357 for details. + */ + + /* mov r0, #lsb(reset_vector) */ + imme = reset_vector & 0xffff; + inst = imme & 0xfff; + inst |= ((imme >> 12) << 16); + inst |= 0xe3000000; + writel(inst, 0x4003fff0); + + /* movt r0, #msb(reset_vector) */ + imme = (reset_vector >> 16) & 0xffff; + inst = imme & 0xfff; + inst |= ((imme >> 12) << 16); + inst |= 0xe3400000; + writel(inst, 0x4003fff4); + + /* bx r0 */ + writel(0xe12fff10, 0x4003fff8); + + /* b -12 */ + imme = (u32)-20; + inst = (imme >> 2) & 0xffffff; + inst |= 0xea000000; + writel(inst, 0x4003fffc); + + /* Write to orignal location for compatibility */ + writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); + + /* If the CPU(s) don't already have power, power 'em up */ + powerup_cpus(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra124/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra124/Makefile new file mode 100644 index 000000000..61abf45d3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra124/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2013-2014 +# NVIDIA Corporation <www.nvidia.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += cpu.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra124/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra124/cpu.c new file mode 100644 index 000000000..6ff6aeb54 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra124/cpu.c @@ -0,0 +1,265 @@ +/* + * (C) Copyright 2013 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/ahb.h> +#include <asm/arch/clock.h> +#include <asm/arch/flow.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/ap.h> +#include "../tegra-common/cpu.h" + +/* Tegra124-specific CPU init code */ + +static void enable_cpu_power_rail(void) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + debug("enable_cpu_power_rail entry\n"); + + /* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */ + pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SCL_PZ6); + pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SDA_PZ7); + + pmic_enable_cpu_vdd(); + + /* + * Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (102MHz), + * set it for 5ms as per SysEng (102MHz*5ms = 510000 (7C830h). + */ + writel(0x7C830, &pmc->pmc_cpupwrgood_timer); + + /* Set polarity to 0 (normal) and enable CPUPWRREQ_OE */ + clrbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_POL); + setbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_OE); +} + +static void enable_cpu_clocks(void) +{ + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + debug("enable_cpu_clocks entry\n"); + + /* Wait for PLL-X to lock */ + do { + reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); + debug("%s: PLLX base = 0x%08X\n", __func__, reg); + } while ((reg & PLL_LOCK_MASK) == 0); + + debug("%s: PLLX locked, delay for stable clocks\n", __func__); + /* Wait until all clocks are stable */ + udelay(PLL_STABILIZATION_DELAY); + + debug("%s: Setting CCLK_BURST and DIVIDER\n", __func__); + writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol); + writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div); + + debug("%s: Enabling clock to all CPUs\n", __func__); + /* Enable the clock to all CPUs */ + reg = CLR_CPU3_CLK_STP | CLR_CPU2_CLK_STP | CLR_CPU1_CLK_STP | + CLR_CPU0_CLK_STP; + writel(reg, &clkrst->crc_clk_cpu_cmplx_clr); + + debug("%s: Enabling main CPU complex clocks\n", __func__); + /* Always enable the main CPU complex clocks */ + clock_enable(PERIPH_ID_CPU); + clock_enable(PERIPH_ID_CPULP); + clock_enable(PERIPH_ID_CPUG); + + debug("%s: Done\n", __func__); +} + +static void remove_cpu_resets(void) +{ + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + debug("remove_cpu_resets entry\n"); + + /* Take the slow and fast partitions out of reset */ + reg = CLR_NONCPURESET; + writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr); + writel(reg, &clkrst->crc_rst_cpug_cmplx_clr); + + /* Clear the SW-controlled reset of the slow cluster */ + reg = CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 | + CLR_L2RESET | CLR_PRESETDBG; + writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr); + + /* Clear the SW-controlled reset of the fast cluster */ + reg = CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 | + CLR_CPURESET1 | CLR_DBGRESET1 | CLR_CORERESET1 | CLR_CXRESET1 | + CLR_CPURESET2 | CLR_DBGRESET2 | CLR_CORERESET2 | CLR_CXRESET2 | + CLR_CPURESET3 | CLR_DBGRESET3 | CLR_CORERESET3 | CLR_CXRESET3 | + CLR_L2RESET | CLR_PRESETDBG; + writel(reg, &clkrst->crc_rst_cpug_cmplx_clr); +} + +/** + * The Tegra124 requires some special clock initialization, including setting up + * the DVC I2C, turning on MSELECT and selecting the G CPU cluster + */ +void tegra124_init_clocks(void) +{ + struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 val; + + debug("tegra124_init_clocks entry\n"); + + /* Set active CPU cluster to G */ + clrbits_le32(&flow->cluster_control, 1); + + /* Change the oscillator drive strength */ + val = readl(&clkrst->crc_osc_ctrl); + val &= ~OSC_XOFS_MASK; + val |= (OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT); + writel(val, &clkrst->crc_osc_ctrl); + + /* Update same value in PMC_OSC_EDPD_OVER XOFS field for warmboot */ + val = readl(&pmc->pmc_osc_edpd_over); + val &= ~PMC_XOFS_MASK; + val |= (OSC_DRIVE_STRENGTH << PMC_XOFS_SHIFT); + writel(val, &pmc->pmc_osc_edpd_over); + + /* Set HOLD_CKE_LOW_EN to 1 */ + setbits_le32(&pmc->pmc_cntrl2, HOLD_CKE_LOW_EN); + + debug("Setting up PLLX\n"); + init_pllx(); + + val = (1 << CLK_SYS_RATE_AHB_RATE_SHIFT); + writel(val, &clkrst->crc_clk_sys_rate); + + /* Enable clocks to required peripherals. TBD - minimize this list */ + debug("Enabling clocks\n"); + + clock_set_enable(PERIPH_ID_CACHE2, 1); + clock_set_enable(PERIPH_ID_GPIO, 1); + clock_set_enable(PERIPH_ID_TMR, 1); + clock_set_enable(PERIPH_ID_CPU, 1); + clock_set_enable(PERIPH_ID_EMC, 1); + clock_set_enable(PERIPH_ID_I2C5, 1); + clock_set_enable(PERIPH_ID_APBDMA, 1); + clock_set_enable(PERIPH_ID_MEM, 1); + clock_set_enable(PERIPH_ID_CORESIGHT, 1); + clock_set_enable(PERIPH_ID_MSELECT, 1); + clock_set_enable(PERIPH_ID_DVFS, 1); + + /* + * Set MSELECT clock source as PLLP (00), and ask for a clock + * divider that would set the MSELECT clock at 102MHz for a + * PLLP base of 408MHz. + */ + clock_ll_set_source_divisor(PERIPH_ID_MSELECT, 0, + CLK_DIVIDER(NVBL_PLLP_KHZ, 102000)); + + /* Give clock time to stabilize */ + udelay(IO_STABILIZATION_DELAY); + + /* I2C5 (DVC) gets CLK_M and a divisor of 17 */ + clock_ll_set_source_divisor(PERIPH_ID_I2C5, 3, 16); + + /* Give clock time to stabilize */ + udelay(IO_STABILIZATION_DELAY); + + /* Take required peripherals out of reset */ + debug("Taking periphs out of reset\n"); + reset_set_enable(PERIPH_ID_CACHE2, 0); + reset_set_enable(PERIPH_ID_GPIO, 0); + reset_set_enable(PERIPH_ID_TMR, 0); + reset_set_enable(PERIPH_ID_COP, 0); + reset_set_enable(PERIPH_ID_EMC, 0); + reset_set_enable(PERIPH_ID_I2C5, 0); + reset_set_enable(PERIPH_ID_APBDMA, 0); + reset_set_enable(PERIPH_ID_MEM, 0); + reset_set_enable(PERIPH_ID_CORESIGHT, 0); + reset_set_enable(PERIPH_ID_MSELECT, 0); + reset_set_enable(PERIPH_ID_DVFS, 0); + + debug("tegra124_init_clocks exit\n"); +} + +static bool is_partition_powered(u32 partid) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 reg; + + /* Get power gate status */ + reg = readl(&pmc->pmc_pwrgate_status); + return !!(reg & (1 << partid)); +} + +static void power_partition(u32 partid) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + debug("%s: part ID = %08X\n", __func__, partid); + /* Is the partition already on? */ + if (!is_partition_powered(partid)) { + /* No, toggle the partition power state (OFF -> ON) */ + debug("power_partition, toggling state\n"); + writel(START_CP | partid, &pmc->pmc_pwrgate_toggle); + + /* Wait for the power to come up */ + while (!is_partition_powered(partid)) + ; + + /* Give I/O signals time to stabilize */ + udelay(IO_STABILIZATION_DELAY); + } +} + +void powerup_cpus(void) +{ + debug("powerup_cpus entry\n"); + + /* We boot to the fast cluster */ + debug("powerup_cpus entry: G cluster\n"); + + /* Power up the fast cluster rail partition */ + debug("powerup_cpus: CRAIL\n"); + power_partition(CRAIL); + + /* Power up the fast cluster non-CPU partition */ + debug("powerup_cpus: C0NC\n"); + power_partition(C0NC); + + /* Power up the fast cluster CPU0 partition */ + debug("powerup_cpus: CE0\n"); + power_partition(CE0); + + debug("powerup_cpus: done\n"); +} + +void start_cpu(u32 reset_vector) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + debug("start_cpu entry, reset_vector = %x\n", reset_vector); + + tegra124_init_clocks(); + + /* Set power-gating timer multiplier */ + writel((MULT_8 << TIMER_MULT_SHIFT) | (MULT_8 << TIMER_MULT_CPU_SHIFT), + &pmc->pmc_pwrgate_timer_mult); + + enable_cpu_power_rail(); + enable_cpu_clocks(); + clock_enable_coresight(1); + remove_cpu_resets(); + writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); + powerup_cpus(); + debug("start_cpu exit, should continue @ reset_vector\n"); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra20/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra20/Makefile new file mode 100644 index 000000000..12243fa9b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra20/Makefile @@ -0,0 +1,10 @@ +# +# (C) Copyright 2010,2011 Nvidia Corporation. +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += cpu.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra20/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra20/cpu.c new file mode 100644 index 000000000..253389955 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra20/cpu.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/pmc.h> +#include "../tegra-common/cpu.h" + +static void enable_cpu_power_rail(void) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 reg; + + reg = readl(&pmc->pmc_cntrl); + reg |= CPUPWRREQ_OE; + writel(reg, &pmc->pmc_cntrl); + + /* + * The TI PMU65861C needs a 3.75ms delay between enabling + * the power rail and enabling the CPU clock. This delay + * between SM1EN and SM1 is for switching time + the ramp + * up of the voltage to the CPU (VDD_CPU from PMU). + */ + udelay(3750); +} + +void start_cpu(u32 reset_vector) +{ + /* Enable VDD_CPU */ + enable_cpu_power_rail(); + + /* Hold the CPUs in reset */ + reset_A9_cpu(1); + + /* Disable the CPU clock */ + enable_cpu_clock(0); + + /* Enable CoreSight */ + clock_enable_coresight(1); + + /* + * Set the entry point for CPU execution from reset, + * if it's a non-zero value. + */ + if (reset_vector) + writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); + + /* Enable the CPU clock */ + enable_cpu_clock(1); + + /* If the CPU doesn't already have power, power it up */ + powerup_cpu(); + + /* Take the CPU out of reset */ + reset_A9_cpu(0); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra30/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra30/Makefile new file mode 100644 index 000000000..6ff4c5521 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra30/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +obj-y += cpu.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra30/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra30/cpu.c new file mode 100644 index 000000000..a80648389 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm720t/tegra30/cpu.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/flow.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/tegra_i2c.h> +#include "../tegra-common/cpu.h" + +/* Tegra30-specific CPU init code */ +void tegra_i2c_ll_write_addr(uint addr, uint config) +{ + struct i2c_ctlr *reg = (struct i2c_ctlr *)TEGRA_DVC_BASE; + + writel(addr, ®->cmd_addr0); + writel(config, ®->cnfg); +} + +void tegra_i2c_ll_write_data(uint data, uint config) +{ + struct i2c_ctlr *reg = (struct i2c_ctlr *)TEGRA_DVC_BASE; + + writel(data, ®->cmd_data1); + writel(config, ®->cnfg); +} + +#define TPS65911_I2C_ADDR 0x5A +#define TPS65911_VDDCTRL_OP_REG 0x28 +#define TPS65911_VDDCTRL_SR_REG 0x27 +#define TPS65911_VDDCTRL_OP_DATA (0x2300 | TPS65911_VDDCTRL_OP_REG) +#define TPS65911_VDDCTRL_SR_DATA (0x0100 | TPS65911_VDDCTRL_SR_REG) +#define I2C_SEND_2_BYTES 0x0A02 + +static void enable_cpu_power_rail(void) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 reg; + + debug("enable_cpu_power_rail entry\n"); + reg = readl(&pmc->pmc_cntrl); + reg |= CPUPWRREQ_OE; + writel(reg, &pmc->pmc_cntrl); + + /* + * Bring up CPU VDD via the TPS65911x PMIC on the DVC I2C bus. + * First set VDD to 1.4V, then enable the VDD regulator. + */ + tegra_i2c_ll_write_addr(TPS65911_I2C_ADDR, 2); + tegra_i2c_ll_write_data(TPS65911_VDDCTRL_OP_DATA, I2C_SEND_2_BYTES); + udelay(1000); + tegra_i2c_ll_write_data(TPS65911_VDDCTRL_SR_DATA, I2C_SEND_2_BYTES); + udelay(10 * 1000); +} + +/** + * The T30 requires some special clock initialization, including setting up + * the dvc i2c, turning on mselect and selecting the G CPU cluster + */ +void t30_init_clocks(void) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; + u32 val; + + debug("t30_init_clocks entry\n"); + /* Set active CPU cluster to G */ + clrbits_le32(flow->cluster_control, 1 << 0); + + writel(SUPER_SCLK_ENB_MASK, &clkrst->crc_super_sclk_div); + + val = (0 << CLK_SYS_RATE_HCLK_DISABLE_SHIFT) | + (1 << CLK_SYS_RATE_AHB_RATE_SHIFT) | + (0 << CLK_SYS_RATE_PCLK_DISABLE_SHIFT) | + (0 << CLK_SYS_RATE_APB_RATE_SHIFT); + writel(val, &clkrst->crc_clk_sys_rate); + + /* Put i2c, mselect in reset and enable clocks */ + reset_set_enable(PERIPH_ID_DVC_I2C, 1); + clock_set_enable(PERIPH_ID_DVC_I2C, 1); + reset_set_enable(PERIPH_ID_MSELECT, 1); + clock_set_enable(PERIPH_ID_MSELECT, 1); + + /* Switch MSELECT clock to PLLP (00) and use a divisor of 2 */ + clock_ll_set_source_divisor(PERIPH_ID_MSELECT, 0, 2); + + /* + * Our high-level clock routines are not available prior to + * relocation. We use the low-level functions which require a + * hard-coded divisor. Use CLK_M with divide by (n + 1 = 17) + */ + clock_ll_set_source_divisor(PERIPH_ID_DVC_I2C, 3, 16); + + /* + * Give clocks time to stabilize, then take i2c and mselect out of + * reset + */ + udelay(1000); + reset_set_enable(PERIPH_ID_DVC_I2C, 0); + reset_set_enable(PERIPH_ID_MSELECT, 0); +} + +static void set_cpu_running(int run) +{ + struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; + + debug("set_cpu_running entry, run = %d\n", run); + writel(run ? FLOW_MODE_NONE : FLOW_MODE_STOP, &flow->halt_cpu_events); +} + +void start_cpu(u32 reset_vector) +{ + debug("start_cpu entry, reset_vector = %x\n", reset_vector); + t30_init_clocks(); + + /* Enable VDD_CPU */ + enable_cpu_power_rail(); + + set_cpu_running(0); + + /* Hold the CPUs in reset */ + reset_A9_cpu(1); + + /* Disable the CPU clock */ + enable_cpu_clock(0); + + /* Enable CoreSight */ + clock_enable_coresight(1); + + /* + * Set the entry point for CPU execution from reset, + * if it's a non-zero value. + */ + if (reset_vector) + writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); + + /* Enable the CPU clock */ + enable_cpu_clock(1); + + /* If the CPU doesn't already have power, power it up */ + powerup_cpu(); + + /* Take the CPU out of reset */ + reset_A9_cpu(0); + + set_cpu_running(1); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm920t/Makefile new file mode 100644 index 000000000..aac8043f6 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/Makefile @@ -0,0 +1,11 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y = start.o + +obj-y += cpu.o +obj-$(CONFIG_USE_IRQ) += interrupts.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/a320/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm920t/a320/Makefile new file mode 100644 index 000000000..bbdab588c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/a320/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += reset.o +obj-y += timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/a320/reset.S b/qemu/roms/u-boot/arch/arm/cpu/arm920t/a320/reset.S new file mode 100644 index 000000000..81f9dc983 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/a320/reset.S @@ -0,0 +1,10 @@ +/* + * (C) Copyright 2009 Faraday Technology + * Po-Yu Chuang <ratbert@faraday-tech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.global reset_cpu +reset_cpu: + b reset_cpu diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/a320/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/a320/timer.c new file mode 100644 index 000000000..1ac5b6012 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/a320/timer.c @@ -0,0 +1,118 @@ +/* + * (C) Copyright 2009 Faraday Technology + * Po-Yu Chuang <ratbert@faraday-tech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <faraday/ftpmu010.h> +#include <faraday/fttmr010.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define TIMER_CLOCK 32768 +#define TIMER_LOAD_VAL 0xffffffff + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, gd->arch.timer_rate_hz); + + return tick; +} + +static inline unsigned long long usec_to_tick(unsigned long long usec) +{ + usec *= gd->arch.timer_rate_hz; + do_div(usec, 1000000); + + return usec; +} + +int timer_init(void) +{ + struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE; + unsigned int cr; + + debug("%s()\n", __func__); + + /* disable timers */ + writel(0, &tmr->cr); + + /* use 32768Hz oscillator for RTC, WDT, TIMER */ + ftpmu010_32768osc_enable(); + + /* setup timer */ + writel(TIMER_LOAD_VAL, &tmr->timer3_load); + writel(TIMER_LOAD_VAL, &tmr->timer3_counter); + writel(0, &tmr->timer3_match1); + writel(0, &tmr->timer3_match2); + + /* we don't want timer to issue interrupts */ + writel(FTTMR010_TM3_MATCH1 | + FTTMR010_TM3_MATCH2 | + FTTMR010_TM3_OVERFLOW, + &tmr->interrupt_mask); + + cr = readl(&tmr->cr); + cr |= FTTMR010_TM3_CLOCK; /* use external clock */ + cr |= FTTMR010_TM3_ENABLE; + writel(cr, &tmr->cr); + + gd->arch.timer_rate_hz = TIMER_CLOCK; + gd->arch.tbu = gd->arch.tbl = 0; + + return 0; +} + +/* + * Get the current 64 bit timer tick count + */ +unsigned long long get_ticks(void) +{ + struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE; + ulong now = TIMER_LOAD_VAL - readl(&tmr->timer3_counter); + + /* 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; +} + +void __udelay(unsigned long usec) +{ + unsigned long long start; + ulong tmo; + + start = get_ticks(); /* get current timestamp */ + tmo = usec_to_tick(usec); /* convert usecs to ticks */ + while ((get_ticks() - start) < tmo) + ; /* loop till time has passed */ +} + +/* + * get_timer(base) can be used to check for timeouts or + * to measure elasped time relative to an event: + * + * ulong start_time = get_timer(0) sets start_time to the current + * time value. + * get_timer(start_time) returns the time elapsed since then. + * + * The time is used in CONFIG_SYS_HZ units! + */ +ulong get_timer(ulong base) +{ + return tick_to_time(get_ticks()) - base; +} + +/* + * Return the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return gd->arch.timer_rate_hz; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/Makefile new file mode 100644 index 000000000..561b4b4cb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/Makefile @@ -0,0 +1,13 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += lowlevel_init.o +obj-y += reset.o +obj-y += timer.o +obj-y += clock.o +obj-y += cpu.o +obj-y += at91rm9200_devices.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/at91rm9200_devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/at91rm9200_devices.c new file mode 100644 index 000000000..fc54327c0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/at91rm9200_devices.c @@ -0,0 +1,67 @@ +/* + * [partely copied from arch/arm/cpu/arm926ejs/at91/arm9260_devices.c] + * + * (C) Copyright 2011 + * Andreas Bießmann <andreas.devel@googlemail.com> + * + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/gpio.h> + +/* + * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all + * peripheral pins. Good to have if hardware is soldered optionally + * or in case of SPI no slave is selected. Avoid lines to float + * needlessly. Use a short local PUP define. + * + * Due to errata "TXD floats when CTS is inactive" pullups are always + * on for TXD pins. + */ +#ifdef CONFIG_AT91_GPIO_PULLUP +# define PUP CONFIG_AT91_GPIO_PULLUP +#else +# define PUP 0 +#endif + +void at91_serial0_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 17, 1); /* TXD0 */ + at91_set_a_periph(AT91_PIO_PORTA, 18, PUP); /* RXD0 */ + writel(1 << ATMEL_ID_USART0, &pmc->pcer); +} + +void at91_serial1_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 20, PUP); /* RXD1 */ + at91_set_a_periph(AT91_PIO_PORTB, 21, 1); /* TXD1 */ + writel(1 << ATMEL_ID_USART1, &pmc->pcer); +} + +void at91_serial2_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 22, PUP); /* RXD2 */ + at91_set_a_periph(AT91_PIO_PORTA, 23, 1); /* TXD2 */ + writel(1 << ATMEL_ID_USART2, &pmc->pcer); +} + +void at91_seriald_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTA, 30, PUP); /* DRXD */ + at91_set_a_periph(AT91_PIO_PORTA, 31, 1); /* DTXD */ + /* writing SYS to PCER has no effect on AT91RM9200 */ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/clock.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/clock.c new file mode 100644 index 000000000..2813bf782 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/clock.c @@ -0,0 +1,157 @@ +/* + * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c] + * + * Copyright (C) 2011 Andreas Bießmann + * Copyright (C) 2005 David Brownell + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/clk.h> + +#if !defined(CONFIG_AT91FAMILY) +# error You need to define CONFIG_AT91FAMILY in your board config! +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static unsigned long at91_css_to_rate(unsigned long css) +{ + switch (css) { + case AT91_PMC_MCKR_CSS_SLOW: + return CONFIG_SYS_AT91_SLOW_CLOCK; + case AT91_PMC_MCKR_CSS_MAIN: + return gd->arch.main_clk_rate_hz; + case AT91_PMC_MCKR_CSS_PLLA: + return gd->arch.plla_rate_hz; + case AT91_PMC_MCKR_CSS_PLLB: + return gd->arch.pllb_rate_hz; + } + + return 0; +} + +#ifdef CONFIG_USB_ATMEL +static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq) +{ + unsigned i, div = 0, mul = 0, diff = 1 << 30; + unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00; + + /* PLL output max 240 MHz (or 180 MHz per errata) */ + if (out_freq > 240000000) + goto fail; + + for (i = 1; i < 256; i++) { + int diff1; + unsigned input, mul1; + + /* + * PLL input between 1MHz and 32MHz per spec, but lower + * frequences seem necessary in some cases so allow 100K. + * Warning: some newer products need 2MHz min. + */ + input = main_freq / i; + if (input < 100000) + continue; + if (input > 32000000) + continue; + + mul1 = out_freq / input; + if (mul1 > 2048) + continue; + if (mul1 < 2) + goto fail; + + diff1 = out_freq - input * mul1; + if (diff1 < 0) + diff1 = -diff1; + if (diff > diff1) { + diff = diff1; + div = i; + mul = mul1; + if (diff == 0) + break; + } + } + if (i == 256 && diff > (out_freq >> 5)) + goto fail; + return ret | ((mul - 1) << 16) | div; +fail: + return 0; +} +#endif + +static u32 at91_pll_rate(u32 freq, u32 reg) +{ + unsigned mul, div; + + div = reg & 0xff; + mul = (reg >> 16) & 0x7ff; + if (div && mul) { + freq /= div; + freq *= mul + 1; + } else + freq = 0; + + return freq; +} + +int at91_clock_init(unsigned long main_clock) +{ + unsigned freq, mckr; + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; +#ifndef CONFIG_SYS_AT91_MAIN_CLOCK + unsigned tmp; + /* + * When the bootloader initialized the main oscillator correctly, + * there's no problem using the cycle counter. But if it didn't, + * or when using oscillator bypass mode, we must be told the speed + * of the main clock. + */ + if (!main_clock) { + do { + tmp = readl(&pmc->mcfr); + } while (!(tmp & AT91_PMC_MCFR_MAINRDY)); + tmp &= AT91_PMC_MCFR_MAINF_MASK; + main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16); + } +#endif + gd->arch.main_clk_rate_hz = main_clock; + + /* report if PLLA is more than mildly overclocked */ + gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar)); + +#ifdef CONFIG_USB_ATMEL + /* + * USB clock init: choose 48 MHz PLLB value, + * disable 48MHz clock during usb peripheral suspend. + * + * REVISIT: assumes MCK doesn't derive from PLLB! + */ + gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | + AT91_PMC_PLLBR_USBDIV_2; + gd->arch.pllb_rate_hz = at91_pll_rate(main_clock, + gd->arch.at91_pllb_usb_init); +#endif + + /* + * MCK and CPU derive from one of those primary clocks. + * For now, assume this parentage won't change. + */ + mckr = readl(&pmc->mckr); + gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); + freq = gd->arch.mck_rate_hz; + + freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */ + /* mdiv */ + gd->arch.mck_rate_hz = freq / + (1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); + gd->arch.cpu_clk_rate_hz = freq; + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/cpu.c new file mode 100644 index 000000000..b0f411b1c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/cpu.c @@ -0,0 +1,26 @@ +/* + * [origin: arch/arm/cpu/arm926ejs/at91/cpu.c] + * + * (C) Copyright 2011 + * Andreas Bießmann, andreas.devel@googlemail.com + * (C) Copyright 2010 + * Reinhard Meyer, reinhard.meyer@emk-elektronik.de + * (C) Copyright 2009 + * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/clk.h> + +#ifndef CONFIG_SYS_AT91_MAIN_CLOCK +#define CONFIG_SYS_AT91_MAIN_CLOCK 0 +#endif + +int arch_cpu_init(void) +{ + return at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/lowlevel_init.S new file mode 100644 index 000000000..d2934a352 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/lowlevel_init.S @@ -0,0 +1,152 @@ +/* + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * Modified for the at91rm9200dk board by + * (C) Copyright 2004 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + +#include <asm/arch/hardware.h> +#include <asm/arch/at91_mc.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_pio.h> + +#define ARM920T_CONTROL 0xC0000000 /* @ set bit 31 (iA) and 30 (nF) */ + +_MTEXT_BASE: +#undef START_FROM_MEM +#ifdef START_FROM_MEM + .word CONFIG_SYS_TEXT_BASE-PHYS_FLASH_1 +#else + .word CONFIG_SYS_TEXT_BASE +#endif + +.globl lowlevel_init +lowlevel_init: + ldr r1, =AT91_ASM_PMC_MOR + /* Main oscillator Enable register */ +#ifdef CONFIG_SYS_USE_MAIN_OSCILLATOR + ldr r0, =0x0000FF01 /* Enable main oscillator */ +#else + ldr r0, =0x0000FF00 /* Disable main oscillator */ +#endif + str r0, [r1] /*AT91C_CKGR_MOR] */ + /* Add loop to compensate Main Oscillator startup time */ + ldr r0, =0x00000010 +LoopOsc: + subs r0, r0, #1 + bhi LoopOsc + + /* memory control configuration */ + /* this isn't very elegant, but what the heck */ + ldr r0, =SMRDATA + ldr r1, _MTEXT_BASE + sub r0, r0, r1 + ldr r2, =SMRDATAE + sub r2, r2, r1 +pllloop: + /* the address */ + ldr r1, [r0], #4 + /* the value */ + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne pllloop + /* delay - this is all done by guess */ + ldr r0, =0x00010000 + /* (vs reading PMC_SR for LOCKA, LOCKB ... or MOSCS earlier) */ +lock: + subs r0, r0, #1 + bhi lock + ldr r0, =SMRDATA1 + ldr r1, _MTEXT_BASE + sub r0, r0, r1 + ldr r2, =SMRDATA1E + sub r2, r2, r1 +sdinit: + /* the address */ + ldr r1, [r0], #4 + /* the value */ + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne sdinit + + /* switch from FastBus to Asynchronous clock mode */ + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #ARM920T_CONTROL + mcr p15, 0, r0, c1, c0, 0 + + /* everything is fine now */ + mov pc, lr + + .ltorg + +SMRDATA: + .word AT91_ASM_MC_EBI_CFG + .word CONFIG_SYS_EBI_CFGR_VAL + .word AT91_ASM_MC_SMC_CSR0 + .word CONFIG_SYS_SMC_CSR0_VAL + .word AT91_ASM_PMC_PLLAR + .word CONFIG_SYS_PLLAR_VAL + .word AT91_ASM_PMC_PLLBR + .word CONFIG_SYS_PLLBR_VAL + .word AT91_ASM_PMC_MCKR + .word CONFIG_SYS_MCKR_VAL +SMRDATAE: + /* here there's a delay */ +SMRDATA1: + .word AT91_ASM_PIOC_ASR + .word CONFIG_SYS_PIOC_ASR_VAL + .word AT91_ASM_PIOC_BSR + .word CONFIG_SYS_PIOC_BSR_VAL + .word AT91_ASM_PIOC_PDR + .word CONFIG_SYS_PIOC_PDR_VAL + .word AT91_ASM_MC_EBI_CSA + .word CONFIG_SYS_EBI_CSA_VAL + .word AT91_ASM_MC_SDRAMC_CR + .word CONFIG_SYS_SDRC_CR_VAL + .word AT91_ASM_MC_SDRAMC_MR + .word CONFIG_SYS_SDRC_MR_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word AT91_ASM_MC_SDRAMC_MR + .word CONFIG_SYS_SDRC_MR_VAL1 + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word AT91_ASM_MC_SDRAMC_MR + .word CONFIG_SYS_SDRC_MR_VAL2 + .word CONFIG_SYS_SDRAM1 + .word CONFIG_SYS_SDRAM_VAL + .word AT91_ASM_MC_SDRAMC_TR + .word CONFIG_SYS_SDRC_TR_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word AT91_ASM_MC_SDRAMC_MR + .word CONFIG_SYS_SDRC_MR_VAL3 + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL +SMRDATA1E: + /* SMRDATA1 is 176 bytes long */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/reset.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/reset.c new file mode 100644 index 000000000..d47777a36 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/reset.c @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc. <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_st.h> + +void __attribute__((weak)) board_reset(void) +{ + /* true empty function for defining weak symbol */ +} + +void reset_cpu(ulong ignored) +{ + at91_st_t *st = (at91_st_t *) ATMEL_BASE_ST; + + board_reset(); + + /* Reset the cpu by setting up the watchdog timer */ + writel(AT91_ST_WDMR_RSTEN | AT91_ST_WDMR_EXTEN | AT91_ST_WDMR_WDV(2), + &st->wdmr); + writel(AT91_ST_CR_WDRST, &st->cr); + /* and let it timeout */ + while (1) + ; + /* Never reached */ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/timer.c new file mode 100644 index 000000000..6aa299472 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/at91/timer.c @@ -0,0 +1,127 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc. <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_tc.h> +#include <asm/arch/at91_pmc.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* the number of clocks per CONFIG_SYS_HZ */ +#define TIMER_LOAD_VAL (CONFIG_SYS_HZ_CLOCK/CONFIG_SYS_HZ) + +int timer_init(void) +{ + at91_tc_t *tc = (at91_tc_t *) ATMEL_BASE_TC; + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + /* enables TC1.0 clock */ + writel(1 << ATMEL_ID_TC0, &pmc->pcer); /* enable clock */ + + writel(0, &tc->bcr); + writel(AT91_TC_BMR_TC0XC0S_NONE | AT91_TC_BMR_TC1XC1S_NONE | + AT91_TC_BMR_TC2XC2S_NONE , &tc->bmr); + + writel(AT91_TC_CCR_CLKDIS, &tc->tc[0].ccr); + /* set to MCLK/2 and restart the timer + when the value in TC_RC is reached */ + writel(AT91_TC_CMR_TCCLKS_CLOCK1 | AT91_TC_CMR_CPCTRG, &tc->tc[0].cmr); + + writel(0xFFFFFFFF, &tc->tc[0].idr); /* disable interrupts */ + writel(TIMER_LOAD_VAL, &tc->tc[0].rc); + + writel(AT91_TC_CCR_SWTRG | AT91_TC_CCR_CLKEN, &tc->tc[0].ccr); + gd->arch.lastinc = 0; + gd->arch.tbl = 0; + + return 0; +} + +/* + * timer without interrupts + */ +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void __udelay(unsigned long usec) +{ + udelay_masked(usec); +} + +ulong get_timer_raw(void) +{ + at91_tc_t *tc = (at91_tc_t *) ATMEL_BASE_TC; + u32 now; + + now = readl(&tc->tc[0].cv) & 0x0000ffff; + + if (now >= gd->arch.lastinc) { + /* normal mode */ + gd->arch.tbl += now - gd->arch.lastinc; + } else { + /* we have an overflow ... */ + gd->arch.tbl += now + TIMER_LOAD_VAL - gd->arch.lastinc; + } + gd->arch.lastinc = now; + + return gd->arch.tbl; +} + +ulong get_timer_masked(void) +{ + return get_timer_raw()/TIMER_LOAD_VAL; +} + +void udelay_masked(unsigned long usec) +{ + u32 tmo; + u32 endtime; + signed long diff; + + tmo = CONFIG_SYS_HZ_CLOCK / 1000; + tmo *= usec; + tmo /= 1000; + + endtime = get_timer_raw() + tmo; + + do { + u32 now = get_timer_raw(); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/config.mk b/qemu/roms/u-boot/arch/arm/cpu/arm920t/config.mk new file mode 100644 index 000000000..799afff02 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/config.mk @@ -0,0 +1,8 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +PLATFORM_CPPFLAGS += -march=armv4 diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/cpu.c new file mode 100644 index 000000000..d73b51dce --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/cpu.c @@ -0,0 +1,48 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +static void cache_flush(void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + disable_interrupts (); + + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + /* flush I/D-cache */ + cache_flush(); + + return 0; +} + +/* flush I/D-cache */ +static void cache_flush (void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/Makefile new file mode 100644 index 000000000..638333a48 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/Makefile @@ -0,0 +1,21 @@ +# +# Cirrus Logic EP93xx CPU-specific Makefile +# +# Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> +# +# Copyright (C) 2004, 2005 +# Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com> +# +# Copyright (C) 2006 +# Dominic Rath <Dominic.Rath@gmx.de> +# +# Based on an original Makefile, which is +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o led.o speed.o timer.o +obj-y += lowlevel_init.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/cpu.c new file mode 100644 index 000000000..bb5ffd292 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/cpu.c @@ -0,0 +1,37 @@ +/* + * Cirrus Logic EP93xx CPU-specific support. + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * Copyright (C) 2004, 2005 + * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/ep93xx.h> +#include <asm/io.h> + +/* We reset the CPU by generating a 1-->0 transition on DeviceCfg bit 31. */ +extern void reset_cpu(ulong addr) +{ + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + uint32_t value; + + /* Unlock DeviceCfg and set SWRST */ + writel(0xAA, &syscon->sysswlock); + value = readl(&syscon->devicecfg); + value |= SYSCON_DEVICECFG_SWRST; + writel(value, &syscon->devicecfg); + + /* Unlock DeviceCfg and clear SWRST */ + writel(0xAA, &syscon->sysswlock); + value = readl(&syscon->devicecfg); + value &= ~SYSCON_DEVICECFG_SWRST; + writel(value, &syscon->devicecfg); + + /* Dying... */ + while (1) + ; /* noop */ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/led.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/led.c new file mode 100644 index 000000000..614472918 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/led.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2010, 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/io.h> +#include <asm/arch/ep93xx.h> +#include <config.h> +#include <status_led.h> + +static uint8_t saved_state[2] = {STATUS_LED_OFF, STATUS_LED_OFF}; +static uint32_t gpio_pin[2] = {1 << STATUS_LED_GREEN, + 1 << STATUS_LED_RED}; + +inline void switch_LED_on(uint8_t led) +{ + register struct gpio_regs *gpio = (struct gpio_regs *)GPIO_BASE; + + writel(readl(&gpio->pedr) | gpio_pin[led], &gpio->pedr); + saved_state[led] = STATUS_LED_ON; +} + +inline void switch_LED_off(uint8_t led) +{ + register struct gpio_regs *gpio = (struct gpio_regs *)GPIO_BASE; + + writel(readl(&gpio->pedr) & ~gpio_pin[led], &gpio->pedr); + saved_state[led] = STATUS_LED_OFF; +} + +void red_led_on(void) +{ + switch_LED_on(STATUS_LED_RED); +} + +void red_led_off(void) +{ + switch_LED_off(STATUS_LED_RED); +} + +void green_led_on(void) +{ + switch_LED_on(STATUS_LED_GREEN); +} + +void green_led_off(void) +{ + switch_LED_off(STATUS_LED_GREEN); +} + +void __led_init(led_id_t mask, int state) +{ + __led_set(mask, state); +} + +void __led_toggle(led_id_t mask) +{ + if (STATUS_LED_RED == mask) { + if (STATUS_LED_ON == saved_state[STATUS_LED_RED]) + red_led_off(); + else + red_led_on(); + } else if (STATUS_LED_GREEN == mask) { + if (STATUS_LED_ON == saved_state[STATUS_LED_GREEN]) + green_led_off(); + else + green_led_on(); + } +} + +void __led_set(led_id_t mask, int state) +{ + if (STATUS_LED_RED == mask) { + if (STATUS_LED_ON == state) + red_led_on(); + else + red_led_off(); + } else if (STATUS_LED_GREEN == mask) { + if (STATUS_LED_ON == state) + green_led_on(); + else + green_led_off(); + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S new file mode 100644 index 000000000..bf2fa2ac3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S @@ -0,0 +1,49 @@ +/* + * Low-level initialization for EP93xx + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * Copyright (C) 2006 Dominic Rath <Dominic.Rath@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <version.h> +#include <asm/arch/ep93xx.h> + +.globl lowlevel_init +lowlevel_init: + /* backup return address */ + ldr r1, =SYSCON_SCRATCH0 + str lr, [r1] + + /* Turn on both LEDs */ + bl red_led_on + bl green_led_on + + /* Configure flash wait states before we switch to the PLL */ + bl flash_cfg + + /* Set up PLL */ + bl pll_cfg + + /* Turn off the Green LED and leave the Red LED on */ + bl green_led_off + + /* Setup SDRAM */ + bl sdram_cfg + + /* Turn on Green LED, Turn off the Red LED */ + bl green_led_on + bl red_led_off + + /* FIXME: we use async mode for now */ + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0xc0000000 + mcr p15, 0, r0, c1, c0, 0 + + /* restore return address */ + ldr r1, =SYSCON_SCRATCH0 + ldr lr, [r1] + + mov pc, lr diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/speed.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/speed.c new file mode 100644 index 000000000..9dc60b6ff --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/speed.c @@ -0,0 +1,96 @@ +/* + * Cirrus Logic EP93xx PLL support. + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/ep93xx.h> +#include <asm/io.h> +#include <div64.h> + +/* + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ + +/* + * return the PLL output frequency + * + * PLL rate = CONFIG_SYS_CLK_FREQ * (X1FBD + 1) * (X2FBD + 1) + * / (X2IPD + 1) / 2^PS + */ +static ulong get_PLLCLK(uint32_t *pllreg) +{ + uint8_t i; + const uint32_t clkset = readl(pllreg); + uint64_t rate = CONFIG_SYS_CLK_FREQ; + rate *= ((clkset >> SYSCON_CLKSET_PLL_X1FBD1_SHIFT) & 0x1f) + 1; + rate *= ((clkset >> SYSCON_CLKSET_PLL_X2FBD2_SHIFT) & 0x3f) + 1; + do_div(rate, (clkset & 0x1f) + 1); /* X2IPD */ + for (i = 0; i < ((clkset >> SYSCON_CLKSET_PLL_PS_SHIFT) & 3); i++) + rate >>= 1; + + return (ulong)rate; +} + +/* return FCLK frequency */ +ulong get_FCLK() +{ + const uint8_t fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + + const uint32_t clkset1 = readl(&syscon->clkset1); + const uint8_t fclk_div = + fclk_divisors[(clkset1 >> SYSCON_CLKSET1_FCLK_DIV_SHIFT) & 7]; + const ulong fclk_rate = get_PLLCLK(&syscon->clkset1) / fclk_div; + + return fclk_rate; +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + const uint8_t hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + + const uint32_t clkset1 = readl(&syscon->clkset1); + const uint8_t hclk_div = + hclk_divisors[(clkset1 >> SYSCON_CLKSET1_HCLK_DIV_SHIFT) & 7]; + const ulong hclk_rate = get_PLLCLK(&syscon->clkset1) / hclk_div; + + return hclk_rate; +} + +/* return PCLK frequency */ +ulong get_PCLK(void) +{ + const uint8_t pclk_divisors[] = { 1, 2, 4, 8 }; + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + + const uint32_t clkset1 = readl(&syscon->clkset1); + const uint8_t pclk_div = + pclk_divisors[(clkset1 >> SYSCON_CLKSET1_PCLK_DIV_SHIFT) & 3]; + const ulong pclk_rate = get_HCLK() / pclk_div; + + return pclk_rate; +} + +/* return UCLK frequency */ +ulong get_UCLK(void) +{ + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + ulong uclk_rate; + + const uint32_t value = readl(&syscon->pwrcnt); + if (value & SYSCON_PWRCNT_UART_BAUD) + uclk_rate = CONFIG_SYS_CLK_FREQ; + else + uclk_rate = CONFIG_SYS_CLK_FREQ / 2; + + return uclk_rate; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/timer.c new file mode 100644 index 000000000..c2f239aab --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/timer.c @@ -0,0 +1,120 @@ +/* + * Cirrus Logic EP93xx timer support. + * + * Copyright (C) 2009, 2010 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * Copyright (C) 2004, 2005 + * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com> + * + * Based on the original intr.c Cirrus Logic EP93xx Rev D. interrupt support, + * author unknown. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <linux/types.h> +#include <asm/arch/ep93xx.h> +#include <asm/io.h> +#include <div64.h> + +#define TIMER_CLKSEL (1 << 3) +#define TIMER_ENABLE (1 << 7) + +#define TIMER_FREQ 508469 /* ticks / second */ +#define TIMER_MAX_VAL 0xFFFFFFFF + +static struct ep93xx_timer +{ + unsigned long long ticks; + unsigned long last_read; +} timer; + +static inline unsigned long long usecs_to_ticks(unsigned long usecs) +{ + unsigned long long ticks = (unsigned long long)usecs * TIMER_FREQ; + do_div(ticks, 1000 * 1000); + + return ticks; +} + +static inline void read_timer(void) +{ + struct timer_regs *timer_regs = (struct timer_regs *)TIMER_BASE; + const unsigned long now = TIMER_MAX_VAL - readl(&timer_regs->timer3.value); + + if (now >= timer.last_read) + timer.ticks += now - timer.last_read; + else + /* an overflow occurred */ + timer.ticks += TIMER_MAX_VAL - timer.last_read + now; + + timer.last_read = now; +} + +/* + * Get the number of ticks (in CONFIG_SYS_HZ resolution) + */ +unsigned long long get_ticks(void) +{ + unsigned long long sys_ticks; + + read_timer(); + + sys_ticks = timer.ticks * CONFIG_SYS_HZ; + do_div(sys_ticks, TIMER_FREQ); + + return sys_ticks; +} + +unsigned long get_timer_masked(void) +{ + return get_ticks(); +} + +unsigned long get_timer(unsigned long base) +{ + return get_timer_masked() - base; +} + +void __udelay(unsigned long usec) +{ + unsigned long long target; + + read_timer(); + + target = timer.ticks + usecs_to_ticks(usec); + + while (timer.ticks < target) + read_timer(); +} + +int timer_init(void) +{ + struct timer_regs *timer_regs = (struct timer_regs *)TIMER_BASE; + + /* use timer 3 with 508KHz and free running, not enabled now */ + writel(TIMER_CLKSEL, &timer_regs->timer3.control); + + /* set initial timer value */ + writel(TIMER_MAX_VAL, &timer_regs->timer3.load); + + /* Enable the timer */ + writel(TIMER_ENABLE | TIMER_CLKSEL, + &timer_regs->timer3.control); + + /* Reset the timer */ + read_timer(); + timer.ticks = 0; + + return 0; +} + +/* + * 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) +{ + return CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/u-boot.lds b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/u-boot.lds new file mode 100644 index 000000000..96994043e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/u-boot.lds @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.__image_copy_start) + arch/arm/cpu/arm920t/start.o (.text*) + /* the EP93xx expects to find the pattern 'CRUS' at 0x1000 */ + . = 0x1000; + LONG(0x53555243) + *(.text*) + } + + . = ALIGN(4); + .rodata : { *(.rodata*) } + + . = ALIGN(4); + .data : { *(.data*) } + + . = ALIGN(4); + .got : { *(.got) } + + . = .; + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + + .image_copy_end : + { + *(.__image_copy_end) + } + + __bss_start = .; + .bss : { *(.bss*) } + __bss_end = .; + + .end : + { + *(.__end) + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/Makefile new file mode 100644 index 000000000..54ce646d9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/Makefile @@ -0,0 +1,10 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += generic.o +obj-y += speed.o +obj-y += timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/generic.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/generic.c new file mode 100644 index 000000000..1441ab439 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/generic.c @@ -0,0 +1,77 @@ +/* + * arch/arm/mach-imx/generic.c + * + * author: Sascha Hauer + * Created: april 20th, 2004 + * Copyright: Synertronixx GmbH + * + * Common code for i.MX machines + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#ifdef CONFIG_IMX + +#include <asm/arch/imx-regs.h> + +void imx_gpio_mode(int gpio_mode) +{ + unsigned int pin = gpio_mode & GPIO_PIN_MASK; + unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5; + unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10; + unsigned int tmp; + + /* Pullup enable */ + if(gpio_mode & GPIO_PUEN) + PUEN(port) |= (1<<pin); + else + PUEN(port) &= ~(1<<pin); + + /* Data direction */ + if(gpio_mode & GPIO_OUT) + DDIR(port) |= 1<<pin; + else + DDIR(port) &= ~(1<<pin); + + /* Primary / alternate function */ + if(gpio_mode & GPIO_AF) + GPR(port) |= (1<<pin); + else + GPR(port) &= ~(1<<pin); + + /* use as gpio? */ + if( ocr == 3 ) + GIUS(port) |= (1<<pin); + else + GIUS(port) &= ~(1<<pin); + + /* Output / input configuration */ + /* FIXME: I'm not very sure about OCR and ICONF, someone + * should have a look over it + */ + if(pin<16) { + tmp = OCR1(port); + tmp &= ~( 3<<(pin*2)); + tmp |= (ocr << (pin*2)); + OCR1(port) = tmp; + + if( gpio_mode & GPIO_AOUT ) + ICONFA1(port) &= ~( 3<<(pin*2)); + if( gpio_mode & GPIO_BOUT ) + ICONFB1(port) &= ~( 3<<(pin*2)); + } else { + tmp = OCR2(port); + tmp &= ~( 3<<((pin-16)*2)); + tmp |= (ocr << ((pin-16)*2)); + OCR2(port) = tmp; + + if( gpio_mode & GPIO_AOUT ) + ICONFA2(port) &= ~( 3<<((pin-16)*2)); + if( gpio_mode & GPIO_BOUT ) + ICONFB2(port) &= ~( 3<<((pin-16)*2)); + } +} + +#endif /* CONFIG_IMX */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/speed.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/speed.c new file mode 100644 index 000000000..1951313dd --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/speed.c @@ -0,0 +1,86 @@ +/* + * + * (c) 2004 Sascha Hauer <sascha@saschahauer.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + +#include <common.h> +#if defined (CONFIG_IMX) + +#include <asm/arch/imx-regs.h> + +/* ------------------------------------------------------------------------- */ +/* NOTE: This describes the proper use of this file. + * + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * SH FIXME: 16780000 in our case + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ +/* ------------------------------------------------------------------------- */ + +ulong get_systemPLLCLK(void) +{ + /* FIXME: We assume System_SEL = 0 here */ + u32 spctl0 = SPCTL0; + u32 mfi = (spctl0 >> 10) & 0xf; + u32 mfn = spctl0 & 0x3f; + u32 mfd = (spctl0 >> 16) & 0x3f; + u32 pd = (spctl0 >> 26) & 0xf; + + mfi = mfi<=5 ? 5 : mfi; + + return (2*(CONFIG_SYSPLL_CLK_FREQ>>10)*( (mfi<<10) + (mfn<<10)/(mfd+1)))/(pd+1); +} + +ulong get_mcuPLLCLK(void) +{ + /* FIXME: We assume System_SEL = 0 here */ + u32 mpctl0 = MPCTL0; + u32 mfi = (mpctl0 >> 10) & 0xf; + u32 mfn = mpctl0 & 0x3f; + u32 mfd = (mpctl0 >> 16) & 0x3f; + u32 pd = (mpctl0 >> 26) & 0xf; + + mfi = mfi<=5 ? 5 : mfi; + + return (2*(CONFIG_SYS_CLK_FREQ>>10)*( (mfi<<10) + (mfn<<10)/(mfd+1)))/(pd+1); +} + +ulong get_FCLK(void) +{ + return (( CSCR>>15)&1) ? get_mcuPLLCLK()>>1 : get_mcuPLLCLK(); +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + u32 bclkdiv = (( CSCR >> 10 ) & 0xf) + 1; + printf("bclkdiv: %d\n", bclkdiv); + return get_systemPLLCLK() / bclkdiv; +} + +/* return BCLK frequency */ +ulong get_BCLK(void) +{ + return get_HCLK(); +} + +ulong get_PERCLK1(void) +{ + return get_systemPLLCLK() / (((PCDR) & 0xf)+1); +} + +ulong get_PERCLK2(void) +{ + return get_systemPLLCLK() / (((PCDR>>4) & 0xf)+1); +} + +ulong get_PERCLK3(void) +{ + return get_systemPLLCLK() / (((PCDR>>16) & 0x7f)+1); +} + +#endif /* defined (CONFIG_IMX) */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/timer.c new file mode 100644 index 000000000..b62558f92 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/imx/timer.c @@ -0,0 +1,107 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#if defined (CONFIG_IMX) + +#include <asm/arch/imx-regs.h> + +int timer_init (void) +{ + int i; + /* setup GP Timer 1 */ + TCTL1 = TCTL_SWR; + for ( i=0; i<100; i++) TCTL1 = 0; /* We have no udelay by now */ + TPRER1 = get_PERCLK1() / 1000000; /* 1 MHz */ + TCTL1 |= TCTL_FRR | (1<<1); /* Freerun Mode, PERCLK1 input */ + + /* Reset the timer */ + TCTL1 &= ~TCTL_TEN; + TCTL1 |= TCTL_TEN; /* Enable timer */ + + return (0); +} + +/* + * timer without interrupts + */ +ulong get_timer (ulong base) +{ + return get_timer_masked() - base; +} + +ulong get_timer_masked (void) +{ + return TCN1; +} + +void udelay_masked (unsigned long usec) +{ + ulong endtime = get_timer_masked() + usec; + signed long diff; + + do { + ulong now = get_timer_masked (); + diff = endtime - now; + } while (diff >= 0); +} + +void __udelay (unsigned long usec) +{ + udelay_masked(usec); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + ulong tbclk; + + tbclk = CONFIG_SYS_HZ; + + return tbclk; +} + +/* + * Reset the cpu by setting up the watchdog timer and let him time out + */ +void reset_cpu (ulong ignored) +{ + /* Disable watchdog and set Time-Out field to 0 */ + WCR = 0x00000000; + + /* Write Service Sequence */ + WSR = 0x00005555; + WSR = 0x0000AAAA; + + /* Enable watchdog */ + WCR = 0x00000001; + + while (1); + /*NOTREACHED*/ +} + +#endif /* defined (CONFIG_IMX) */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/interrupts.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/interrupts.c new file mode 100644 index 000000000..0e04d3668 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/interrupts.c @@ -0,0 +1,27 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/proc-armv/ptrace.h> + +#if defined (CONFIG_ARCH_INTEGRATOR) +void do_irq (struct pt_regs *pt_regs) +{ + /* ASSUMED to be a timer interrupt */ + /* Just clear it - count handled in */ + /* integratorap.c */ + *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 0x0C) = 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/ks8695/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ks8695/Makefile new file mode 100644 index 000000000..400aa89e9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ks8695/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = lowlevel_init.o +obj-y += timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/ks8695/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ks8695/lowlevel_init.S new file mode 100644 index 000000000..a2a07f2f2 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ks8695/lowlevel_init.S @@ -0,0 +1,189 @@ +/* + * lowlevel_init.S - basic hardware initialization for the KS8695 CPU + * + * Copyright (c) 2004-2005, Greg Ungerer <greg.ungerer@opengear.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <version.h> +#include <asm/arch/platform.h> + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + +/* + ************************************************************************* + * + * Handy dandy macros + * + ************************************************************************* + */ + +/* Delay a bit */ +.macro DELAY_FOR cycles, reg0 + ldr \reg0, =\cycles + subs \reg0, \reg0, #1 + subne pc, pc, #0xc +.endm + +/* + ************************************************************************* + * + * Some local storage. + * + ************************************************************************* + */ + +/* Should we boot with an interactive console or not */ +.globl serial_console + +/* + ************************************************************************* + * + * Raw hardware initialization code. The important thing is to get + * SDRAM setup and running. We do some other basic things here too, + * like getting the PLL set for high speed, and init the LEDs. + * + ************************************************************************* + */ + +.globl lowlevel_init +lowlevel_init: + +#if DEBUG + /* + * enable UART for early debug trace + */ + ldr r1, =(KS8695_IO_BASE+KS8695_UART_DIVISOR) + mov r2, #((25000000+CONFIG_BAUDRATE/2) / CONFIG_BAUDRATE) + str r2, [r1] + ldr r1, =(KS8695_IO_BASE+KS8695_UART_LINE_CTRL) + mov r2, #KS8695_UART_LINEC_WLEN8 + str r2, [r1] /* 8 data bits, no parity, 1 stop */ + ldr r1, =(KS8695_IO_BASE+KS8695_UART_TX_HOLDING) + mov r2, #0x41 + str r2, [r1] /* write 'A' */ +#endif +#if DEBUG + ldr r1, =(KS8695_IO_BASE+KS8695_UART_TX_HOLDING) + mov r2, #0x42 + str r2, [r1] +#endif + + /* + * remap the memory and flash regions. we want to end up with + * ram from address 0, and flash at 32MB. + */ + ldr r1, =(KS8695_IO_BASE+KS8695_MEM_CTRL0) + ldr r2, =0xbfc00040 + str r2, [r1] /* large flash map */ + ldr pc, =(highflash+0x02000000-0x00f00000) /* jump to high flash address */ +highflash: + ldr r2, =0x8fe00040 + str r2, [r1] /* remap flash range */ + + /* + * remap the second select region to the 4MB immediately after + * the first region. This way if you have a larger flash (say 8Mb) + * then you can have it all mapped nicely. Has no effect if you + * only have a 4Mb or smaller flash. + */ + ldr r1, =(KS8695_IO_BASE+KS8695_MEM_CTRL1) + ldr r2, =0x9fe40040 + str r2, [r1] /* remap flash2 region, contiguous */ + ldr r1, =(KS8695_IO_BASE+KS8695_MEM_GENERAL) + ldr r2, =0x30000005 + str r2, [r1] /* enable both flash selects */ + +#ifdef CONFIG_CM41xx + /* + * map the second flash chip, using the external IO lines. + */ + ldr r1, =(KS8695_IO_BASE+KS8695_IO_CTRL0) + ldr r2, =0xafe80b6d + str r2, [r1] /* remap io0 region, contiguous */ + ldr r1, =(KS8695_IO_BASE+KS8695_IO_CTRL1) + ldr r2, =0xbfec0b6d + str r2, [r1] /* remap io1 region, contiguous */ + ldr r1, =(KS8695_IO_BASE+KS8695_MEM_GENERAL) + ldr r2, =0x30050005 + str r2, [r1] /* enable second flash */ +#endif + + /* + * before relocating, we have to setup RAM timing + */ + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_CTRL0) +#if (PHYS_SDRAM_1_SIZE == 0x02000000) + ldr r2, =0x7fc0000e /* 32MB */ +#else + ldr r2, =0x3fc0000e /* 16MB */ +#endif + str r2, [r1] /* configure sdram bank0 setup */ + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_CTRL1) + mov r2, #0 + str r2, [r1] /* configure sdram bank1 setup */ + + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_GENERAL) + ldr r2, =0x0000000a + str r2, [r1] /* set RAS/CAS timing */ + + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_BUFFER) + ldr r2, =0x00030000 + str r2, [r1] /* send NOP command */ + DELAY_FOR 0x100, r0 + ldr r2, =0x00010000 + str r2, [r1] /* send PRECHARGE-ALL */ + DELAY_FOR 0x100, r0 + + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_REFRESH) + ldr r2, =0x00000020 + str r2, [r1] /* set for fast refresh */ + DELAY_FOR 0x100, r0 + ldr r2, =0x00000190 + str r2, [r1] /* set normal refresh timing */ + + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_BUFFER) + ldr r2, =0x00020033 + str r2, [r1] /* send mode command */ + DELAY_FOR 0x100, r0 + ldr r2, =0x01f00000 + str r2, [r1] /* enable sdram fifos */ + + /* + * set pll to top speed + */ + ldr r1, =(KS8695_IO_BASE+KS8695_SYSTEN_BUS_CLOCK) + mov r2, #0 + str r2, [r1] /* set pll clock to 166MHz */ + + ldr r1, =(KS8695_IO_BASE+KS8695_SWITCH_CTRL0) + ldr r2, [r1] /* Get switch ctrl0 register */ + and r2, r2, #0x0fc00000 /* Mask out LED control bits */ + orr r2, r2, #0x01800000 /* Set Link/activity/speed actions */ + str r2, [r1] + +#ifdef CONFIG_CM4008 + ldr r1, =(KS8695_IO_BASE+KS8695_GPIO_MODE) + ldr r2, =0x0000fe30 + str r2, [r1] /* enable LED's as outputs */ + ldr r1, =(KS8695_IO_BASE+KS8695_GPIO_DATA) + ldr r2, =0x0000fe20 + str r2, [r1] /* turn on power LED */ +#endif +#if defined(CONFIG_CM4008) || defined(CONFIG_CM41xx) + ldr r2, [r1] /* get current GPIO input data */ + tst r2, #0x8 /* check if "erase" depressed */ + beq nobutton + mov r2, #0 /* be quiet on boot, no console */ + ldr r1, =serial_console + str r2, [r1] +nobutton: +#endif + + add lr, lr, #0x02000000 /* flash is now mapped high */ + add ip, ip, #0x02000000 /* this is a hack */ + mov pc, lr /* all done, return */ + +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/ks8695/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ks8695/timer.c new file mode 100644 index 000000000..23db5572d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/ks8695/timer.c @@ -0,0 +1,77 @@ +/* + * (C) Copyright 2004-2005, Greg Ungerer <greg.ungerer@opengear.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/platform.h> + +/* + * Initial timer set constants. Nothing complicated, just set for a 1ms + * tick. + */ +#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_1) +#define TIMER_COUNT (TIMER_INTERVAL / 2) +#define TIMER_PULSE TIMER_COUNT + +/* + * Handy KS8695 register access functions. + */ +#define ks8695_read(a) *((volatile ulong *) (KS8695_IO_BASE + (a))) +#define ks8695_write(a,v) *((volatile ulong *) (KS8695_IO_BASE + (a))) = (v) + +ulong timer_ticks; + +int timer_init (void) +{ + /* Set the hadware timer for 1ms */ + ks8695_write(KS8695_TIMER1, TIMER_COUNT); + ks8695_write(KS8695_TIMER1_PCOUNT, TIMER_PULSE); + ks8695_write(KS8695_TIMER_CTRL, 0x2); + timer_ticks = 0; + + return 0; +} + +ulong get_timer_masked(void) +{ + /* Check for timer wrap */ + if (ks8695_read(KS8695_INT_STATUS) & KS8695_INTMASK_TIMERINT1) { + /* Clear interrupt condition */ + ks8695_write(KS8695_INT_STATUS, KS8695_INTMASK_TIMERINT1); + timer_ticks++; + } + return timer_ticks; +} + +ulong get_timer(ulong base) +{ + return (get_timer_masked() - base); +} + +void __udelay(ulong usec) +{ + ulong start = get_timer_masked(); + ulong end; + + /* Only 1ms resolution :-( */ + end = usec / 1000; + while (get_timer(start) < end) + ; +} + +void reset_cpu (ulong ignored) +{ + ulong tc; + + /* Set timer0 to watchdog, and let it timeout */ + tc = ks8695_read(KS8695_TIMER_CTRL) & 0x2; + ks8695_write(KS8695_TIMER_CTRL, tc); + ks8695_write(KS8695_TIMER0, ((10 << 8) | 0xff)); + ks8695_write(KS8695_TIMER_CTRL, (tc | 0x1)); + + /* Should only wait here till watchdog resets */ + for (;;) + ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/Makefile new file mode 100644 index 000000000..e44c549ba --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/Makefile @@ -0,0 +1,11 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_USE_IRQ) += interrupts.o +obj-$(CONFIG_DISPLAY_CPUINFO) += cpu_info.o +obj-y += speed.o +obj-y += timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/cpu_info.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/cpu_info.c new file mode 100644 index 000000000..fede51a16 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/cpu_info.c @@ -0,0 +1,38 @@ +/* + * (C) Copyright 2010 + * David Mueller <d.mueller@elsoft.ch> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/s3c24x0_cpu.h> + +typedef ulong (*getfreq)(void); + +static const getfreq freq_f[] = { + get_FCLK, + get_HCLK, + get_PCLK, +}; + +static const char freq_c[] = { 'F', 'H', 'P' }; + +int print_cpuinfo(void) +{ + int i; + char buf[32]; +/* the S3C2400 seems to be lacking a CHIP ID register */ +#ifndef CONFIG_S3C2400 + ulong cpuid; + struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio(); + + cpuid = readl(&gpio->gstatus1); + printf("CPUID: %8lX\n", cpuid); +#endif + for (i = 0; i < ARRAY_SIZE(freq_f); i++) + printf("%cCLK: %8s MHz\n", freq_c[i], strmhz(buf, freq_f[i]())); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/interrupts.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/interrupts.c new file mode 100644 index 000000000..036e3b906 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/interrupts.c @@ -0,0 +1,26 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#include <asm/arch/s3c24x0_cpu.h> +#include <asm/proc-armv/ptrace.h> + +void do_irq (struct pt_regs *pt_regs) +{ + struct s3c24x0_interrupt *irq = s3c24x0_get_base_interrupt(); + u_int32_t intpnd = readl(&irq->INTPND); + +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/speed.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/speed.c new file mode 100644 index 000000000..3701c5d9a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/speed.c @@ -0,0 +1,102 @@ +/* + * (C) Copyright 2001-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, d.mueller@elsoft.ch + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* This code should work for both the S3C2400 and the S3C2410 + * as they seem to have the same PLL and clock machinery inside. + * The different address mapping is handled by the s3c24xx.h files below. + */ + +#include <common.h> +#ifdef CONFIG_S3C24X0 + +#include <asm/io.h> +#include <asm/arch/s3c24x0_cpu.h> + +#define MPLL 0 +#define UPLL 1 + +/* ------------------------------------------------------------------------- */ +/* NOTE: This describes the proper use of this file. + * + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ +/* ------------------------------------------------------------------------- */ + +static ulong get_PLLCLK(int pllreg) +{ + struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); + ulong r, m, p, s; + + if (pllreg == MPLL) + r = readl(&clk_power->mpllcon); + else if (pllreg == UPLL) + r = readl(&clk_power->upllcon); + else + hang(); + + m = ((r & 0xFF000) >> 12) + 8; + p = ((r & 0x003F0) >> 4) + 2; + s = r & 0x3; + +#if defined(CONFIG_S3C2440) + if (pllreg == MPLL) + return 2 * m * (CONFIG_SYS_CLK_FREQ / (p << s)); +#endif + return (CONFIG_SYS_CLK_FREQ * m) / (p << s); + +} + +/* return FCLK frequency */ +ulong get_FCLK(void) +{ + return get_PLLCLK(MPLL); +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); +#ifdef CONFIG_S3C2440 + switch (readl(&clk_power->clkdivn) & 0x6) { + default: + case 0: + return get_FCLK(); + case 2: + return get_FCLK() / 2; + case 4: + return (readl(&clk_power->camdivn) & (1 << 9)) ? + get_FCLK() / 8 : get_FCLK() / 4; + case 6: + return (readl(&clk_power->camdivn) & (1 << 8)) ? + get_FCLK() / 6 : get_FCLK() / 3; + } +#else + return (readl(&clk_power->clkdivn) & 2) ? get_FCLK() / 2 : get_FCLK(); +#endif +} + +/* return PCLK frequency */ +ulong get_PCLK(void) +{ + struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); + + return (readl(&clk_power->clkdivn) & 1) ? get_HCLK() / 2 : get_HCLK(); +} + +/* return UCLK frequency */ +ulong get_UCLK(void) +{ + return get_PLLCLK(UPLL); +} + +#endif /* CONFIG_S3C24X0 */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/timer.c new file mode 100644 index 000000000..ba1e616b8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/timer.c @@ -0,0 +1,160 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#ifdef CONFIG_S3C24X0 + +#include <asm/io.h> +#include <asm/arch/s3c24x0_cpu.h> + +DECLARE_GLOBAL_DATA_PTR; + +int timer_init(void) +{ + struct s3c24x0_timers *timers = s3c24x0_get_base_timers(); + ulong tmr; + + /* use PWM Timer 4 because it has no output */ + /* prescaler for Timer 4 is 16 */ + writel(0x0f00, &timers->tcfg0); + if (gd->arch.tbu == 0) { + /* + * for 10 ms clock period @ PCLK with 4 bit divider = 1/2 + * (default) and prescaler = 16. Should be 10390 + * @33.25MHz and 15625 @ 50 MHz + */ + gd->arch.tbu = get_PCLK() / (2 * 16 * 100); + gd->arch.timer_rate_hz = get_PCLK() / (2 * 16); + } + /* load value for 10 ms timeout */ + writel(gd->arch.tbu, &timers->tcntb4); + /* auto load, manual update of timer 4 */ + tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000; + writel(tmr, &timers->tcon); + /* auto load, start timer 4 */ + tmr = (tmr & ~0x0700000) | 0x0500000; + writel(tmr, &timers->tcon); + gd->arch.lastinc = 0; + gd->arch.tbl = 0; + + return 0; +} + +/* + * timer without interrupts + */ +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void __udelay (unsigned long usec) +{ + ulong tmo; + ulong start = get_ticks(); + + tmo = usec / 1000; + tmo *= (gd->arch.tbu * 100); + tmo /= 1000; + + while ((ulong) (get_ticks() - start) < tmo) + /*NOP*/; +} + +ulong get_timer_masked(void) +{ + ulong tmr = get_ticks(); + + return tmr / (gd->arch.timer_rate_hz / CONFIG_SYS_HZ); +} + +void udelay_masked(unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + if (usec >= 1000) { + tmo = usec / 1000; + tmo *= (gd->arch.tbu * 100); + tmo /= 1000; + } else { + tmo = usec * (gd->arch.tbu * 100); + tmo /= (1000 * 1000); + } + + endtime = get_ticks() + tmo; + + do { + ulong now = get_ticks(); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + struct s3c24x0_timers *timers = s3c24x0_get_base_timers(); + ulong now = readl(&timers->tcnto4) & 0xffff; + + if (gd->arch.lastinc >= now) { + /* normal mode */ + gd->arch.tbl += gd->arch.lastinc - now; + } else { + /* we have an overflow ... */ + gd->arch.tbl += gd->arch.lastinc + gd->arch.tbu - now; + } + gd->arch.lastinc = now; + + return gd->arch.tbl; +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} + +/* + * reset the cpu by setting up the watchdog timer and let him time out + */ +void reset_cpu(ulong ignored) +{ + struct s3c24x0_watchdog *watchdog; + + watchdog = s3c24x0_get_base_watchdog(); + + /* Disable watchdog */ + writel(0x0000, &watchdog->wtcon); + + /* Initialize watchdog timer count register */ + writel(0x0001, &watchdog->wtcnt); + + /* Enable watchdog timer; assert reset at timer timeout */ + writel(0x0021, &watchdog->wtcon); + + while (1) + /* loop forever and wait for reset to happen */; + + /*NOTREACHED*/ +} + +#endif /* CONFIG_S3C24X0 */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm920t/start.S b/qemu/roms/u-boot/arch/arm/cpu/arm920t/start.S new file mode 100644 index 000000000..7bf094aec --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm920t/start.S @@ -0,0 +1,361 @@ +/* + * armboot - Startup Code for ARM920 CPU-core + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <common.h> +#include <config.h> + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + + +.globl _start +_start: b start_code + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq + + .balignl 16,0xdeadbeef + + +/* + ************************************************************************* + * + * Startup Code (called from the ARM reset exception vector) + * + * do important init only if we don't start from memory! + * relocate armboot to ram + * setup stack + * jump to second stage + * + ************************************************************************* + */ + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual start code + */ + +start_code: + /* + * set the cpu to SVC32 mode + */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0xd3 + msr cpsr, r0 + +#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) + /* + * relocate exception table + */ + ldr r0, =_start + ldr r1, =0x0 + mov r2, #16 +copyex: + subs r2, r2, #1 + ldr r3, [r0], #4 + str r3, [r1], #4 + bne copyex +#endif + +#ifdef CONFIG_S3C24X0 + /* turn off the watchdog */ + +# if defined(CONFIG_S3C2400) +# define pWTCON 0x15300000 +# define INTMSK 0x14400008 /* Interrupt-Controller base addresses */ +# define CLKDIVN 0x14800014 /* clock divisor register */ +#else +# define pWTCON 0x53000000 +# define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */ +# define INTSUBMSK 0x4A00001C +# define CLKDIVN 0x4C000014 /* clock divisor register */ +# endif + + ldr r0, =pWTCON + mov r1, #0x0 + str r1, [r0] + + /* + * mask all IRQs by setting all bits in the INTMR - default + */ + mov r1, #0xffffffff + ldr r0, =INTMSK + str r1, [r0] +# if defined(CONFIG_S3C2410) + ldr r1, =0x3ff + ldr r0, =INTSUBMSK + str r1, [r0] +# endif + + /* FCLK:HCLK:PCLK = 1:2:4 */ + /* default FCLK is 120 MHz ! */ + ldr r0, =CLKDIVN + mov r1, #3 + str r1, [r0] +#endif /* CONFIG_S3C24X0 */ + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) + bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) + orr r0, r0, #0x00000002 @ set bit 2 (A) Align + orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache + mcr p15, 0, r0, c1, c0, 0 + + /* + * before relocating, we have to setup RAM timing + * because memory timing is board-dependend, you will + * find a lowlevel_init.S in your board directory. + */ + mov ip, lr + + bl lowlevel_init + + mov lr, ip + mov pc, lr +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + ldr r2, IRQ_STACK_START_IN + ldmia r2, {r2 - r3} @ get pc, cpsr + add r0, sp, #S_FRAME_SIZE @ restore sp_SVC + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r7, sp, #S_PC + stmdb r7, {sp, lr}^ @ Calling SP, LR + str lr, [r7, #0] @ Save calling PC + mrs r6, spsr + str r6, [r7, #4] @ Save CPSR + str r0, [r7, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + /* return & move spsr_svc into cpsr */ + subs pc, lr, #4 + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + + str lr, [r13] @ save caller lr / spsr + mrs lr, spsr + str lr, [r13, #4] + + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 + mov lr, pc + movs pc, lr + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/Makefile new file mode 100644 index 000000000..125299537 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/Makefile @@ -0,0 +1,15 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y = start.o +obj-y = cpu.o cache.o + +ifdef CONFIG_SPL_BUILD +ifdef CONFIG_SPL_NO_CPU_SUPPORT_CODE +extra-y := +endif +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/Makefile new file mode 100644 index 000000000..fca98ef42 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2010 +# Marvell Semiconductor <www.marvell.com> +# Written-by: Prafulla Wadaskar <prafulla@marvell.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o timer.o dram.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/cpu.c new file mode 100644 index 000000000..8b02d0be0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/cpu.c @@ -0,0 +1,92 @@ +/* + * (C) Copyright 2010 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * Contributor: Mahavir Jain <mjain@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/armada100.h> + +#define UARTCLK14745KHZ (APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(1)) +#define SET_MRVL_ID (1<<8) +#define L2C_RAM_SEL (1<<4) + +int arch_cpu_init(void) +{ + u32 val; + struct armd1cpu_registers *cpuregs = + (struct armd1cpu_registers *) ARMD1_CPU_BASE; + + struct armd1apb1_registers *apb1clkres = + (struct armd1apb1_registers *) ARMD1_APBC1_BASE; + + struct armd1mpmu_registers *mpmu = + (struct armd1mpmu_registers *) ARMD1_MPMU_BASE; + + /* set SEL_MRVL_ID bit in ARMADA100_CPU_CONF register */ + val = readl(&cpuregs->cpu_conf); + val = val | SET_MRVL_ID; + writel(val, &cpuregs->cpu_conf); + + /* Enable Clocks for all hardware units */ + writel(0xFFFFFFFF, &mpmu->acgr); + + /* Turn on AIB and AIB-APB Functional clock */ + writel(APBC_APBCLK | APBC_FNCLK, &apb1clkres->aib); + + /* ensure L2 cache is not mapped as SRAM */ + val = readl(&cpuregs->cpu_conf); + val = val & ~(L2C_RAM_SEL); + writel(val, &cpuregs->cpu_conf); + + /* Enable GPIO clock */ + writel(APBC_APBCLK, &apb1clkres->gpio); + +#ifdef CONFIG_I2C_MV + /* Enable general I2C clock */ + writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi0); + writel(APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi0); + + /* Enable power I2C clock */ + writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi1); + writel(APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi1); +#endif + + /* + * Enable Functional and APB clock at 14.7456MHz + * for configured UART console + */ +#if (CONFIG_SYS_NS16550_COM1 == ARMD1_UART3_BASE) + writel(UARTCLK14745KHZ, &apb1clkres->uart3); +#elif (CONFIG_SYS_NS16550_COM1 == ARMD1_UART2_BASE) + writel(UARTCLK14745KHZ, &apb1clkres->uart2); +#else + writel(UARTCLK14745KHZ, &apb1clkres->uart1); +#endif + icache_enable(); + + return 0; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + u32 id; + struct armd1cpu_registers *cpuregs = + (struct armd1cpu_registers *) ARMD1_CPU_BASE; + + id = readl(&cpuregs->chip_id); + printf("SoC: Armada 88AP%X-%X\n", (id & 0xFFF), (id >> 0x10)); + return 0; +} +#endif + +#ifdef CONFIG_I2C_MV +void i2c_clk_enable(void) +{ +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/dram.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/dram.c new file mode 100644 index 000000000..8d7c71ff6 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/dram.c @@ -0,0 +1,116 @@ +/* + * (C) Copyright 2010 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com>, + * Contributor: Mahavir Jain <mjain@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/armada100.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * ARMADA100 DRAM controller supports upto 8 banks + * for chip select 0 and 1 + */ + +/* + * DDR Memory Control Registers + * Refer Datasheet Appendix A.17 + */ +struct armd1ddr_map_registers { + u32 cs; /* Memory Address Map Register -CS */ + u32 pad[3]; +}; + +struct armd1ddr_registers { + u8 pad[0x100 - 0x000]; + struct armd1ddr_map_registers mmap[2]; +}; + +/* + * armd1_sdram_base - reads SDRAM Base Address Register + */ +u32 armd1_sdram_base(int chip_sel) +{ + struct armd1ddr_registers *ddr_regs = + (struct armd1ddr_registers *)ARMD1_DRAM_BASE; + u32 result = 0; + u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); + + if (!CS_valid) + return 0; + + result = readl(&ddr_regs->mmap[chip_sel].cs) & 0xFF800000; + return result; +} + +/* + * armd1_sdram_size - reads SDRAM size + */ +u32 armd1_sdram_size(int chip_sel) +{ + struct armd1ddr_registers *ddr_regs = + (struct armd1ddr_registers *)ARMD1_DRAM_BASE; + u32 result = 0; + u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); + + if (!CS_valid) + return 0; + + result = readl(&ddr_regs->mmap[chip_sel].cs); + result = (result >> 16) & 0xF; + if (result < 0x7) { + printf("Unknown DRAM Size\n"); + return -1; + } else { + return ((0x8 << (result - 0x7)) * 1024 * 1024); + } +} + +#ifndef CONFIG_SYS_BOARD_DRAM_INIT +int dram_init(void) +{ + int i; + + gd->ram_size = 0; + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = armd1_sdram_base(i); + gd->bd->bi_dram[i].size = armd1_sdram_size(i); + /* + * It is assumed that all memory banks are consecutive + * and without gaps. + * If the gap is found, ram_size will be reported for + * consecutive memory only + */ + if (gd->bd->bi_dram[i].start != gd->ram_size) + break; + + gd->ram_size += gd->bd->bi_dram[i].size; + + } + + for (; i < CONFIG_NR_DRAM_BANKS; i++) { + /* If above loop terminated prematurely, we need to set + * remaining banks' start address & size as 0. Otherwise other + * u-boot functions and Linux kernel gets wrong values which + * could result in crash */ + gd->bd->bi_dram[i].start = 0; + gd->bd->bi_dram[i].size = 0; + } + return 0; +} + +/* + * If this function is not defined here, + * board.c alters dram bank zero configuration defined above. + */ +void dram_init_banksize(void) +{ + dram_init(); +} +#endif /* CONFIG_SYS_BOARD_DRAM_INIT */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/timer.c new file mode 100644 index 000000000..bbd0505bd --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/armada100/timer.c @@ -0,0 +1,194 @@ +/* + * (C) Copyright 2010 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * Contributor: Mahavir Jain <mjain@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/armada100.h> + +/* + * Timer registers + * Refer Section A.6 in Datasheet + */ +struct armd1tmr_registers { + u32 clk_ctrl; /* Timer clk control reg */ + u32 match[9]; /* Timer match registers */ + u32 count[3]; /* Timer count registers */ + u32 status[3]; + u32 ie[3]; + u32 preload[3]; /* Timer preload value */ + u32 preload_ctrl[3]; + u32 wdt_match_en; + u32 wdt_match_r; + u32 wdt_val; + u32 wdt_sts; + u32 icr[3]; + u32 wdt_icr; + u32 cer; /* Timer count enable reg */ + u32 cmr; + u32 ilr[3]; + u32 wcr; + u32 wfar; + u32 wsar; + u32 cvwr; +}; + +#define TIMER 0 /* Use TIMER 0 */ +/* Each timer has 3 match registers */ +#define MATCH_CMP(x) ((3 * TIMER) + x) +#define TIMER_LOAD_VAL 0xffffffff +#define COUNT_RD_REQ 0x1 + +DECLARE_GLOBAL_DATA_PTR; +/* Using gd->arch.tbu from timestamp and gd->arch.tbl for lastdec */ + +/* For preventing risk of instability in reading counter value, + * first set read request to register cvwr and then read same + * register after it captures counter value. + */ +ulong read_timer(void) +{ + struct armd1tmr_registers *armd1timers = + (struct armd1tmr_registers *) ARMD1_TIMER_BASE; + volatile int loop=100; + + writel(COUNT_RD_REQ, &armd1timers->cvwr); + while (loop--); + return(readl(&armd1timers->cvwr)); +} + +ulong get_timer_masked(void) +{ + ulong now = read_timer(); + + if (now >= gd->arch.tbl) { + /* normal mode */ + gd->arch.tbu += now - gd->arch.tbl; + } else { + /* we have an overflow ... */ + gd->arch.tbu += now + TIMER_LOAD_VAL - gd->arch.tbl; + } + gd->arch.tbl = now; + + return gd->arch.tbu; +} + +ulong get_timer(ulong base) +{ + return ((get_timer_masked() / (CONFIG_SYS_HZ_CLOCK / 1000)) - + base); +} + +void __udelay(unsigned long usec) +{ + ulong delayticks; + ulong endtime; + + delayticks = (usec * (CONFIG_SYS_HZ_CLOCK / 1000000)); + endtime = get_timer_masked() + delayticks; + + while (get_timer_masked() < endtime); +} + +/* + * init the Timer + */ +int timer_init(void) +{ + struct armd1apb1_registers *apb1clkres = + (struct armd1apb1_registers *) ARMD1_APBC1_BASE; + struct armd1tmr_registers *armd1timers = + (struct armd1tmr_registers *) ARMD1_TIMER_BASE; + + /* Enable Timer clock at 3.25 MHZ */ + writel(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3), &apb1clkres->timers); + + /* load value into timer */ + writel(0x0, &armd1timers->clk_ctrl); + /* Use Timer 0 Match Resiger 0 */ + writel(TIMER_LOAD_VAL, &armd1timers->match[MATCH_CMP(0)]); + /* Preload value is 0 */ + writel(0x0, &armd1timers->preload[TIMER]); + /* Enable match comparator 0 for Timer 0 */ + writel(0x1, &armd1timers->preload_ctrl[TIMER]); + + /* Enable timer 0 */ + writel(0x1, &armd1timers->cer); + /* init the gd->arch.tbu and gd->arch.tbl value */ + gd->arch.tbl = read_timer(); + gd->arch.tbu = 0; + + return 0; +} + +#define MPMU_APRR_WDTR (1<<4) +#define TMR_WFAR 0xbaba /* WDT Register First key */ +#define TMP_WSAR 0xeb10 /* WDT Register Second key */ + +/* + * This function uses internal Watchdog Timer + * based reset mechanism. + * Steps to write watchdog registers (protected access) + * 1. Write key value to TMR_WFAR reg. + * 2. Write key value to TMP_WSAR reg. + * 3. Perform write operation. + */ +void reset_cpu (unsigned long ignored) +{ + struct armd1mpmu_registers *mpmu = + (struct armd1mpmu_registers *) ARMD1_MPMU_BASE; + struct armd1tmr_registers *armd1timers = + (struct armd1tmr_registers *) ARMD1_TIMER_BASE; + u32 val; + + /* negate hardware reset to the WDT after system reset */ + val = readl(&mpmu->aprr); + val = val | MPMU_APRR_WDTR; + writel(val, &mpmu->aprr); + + /* reset/enable WDT clock */ + writel(APBC_APBCLK | APBC_FNCLK | APBC_RST, &mpmu->wdtpcr); + readl(&mpmu->wdtpcr); + writel(APBC_APBCLK | APBC_FNCLK, &mpmu->wdtpcr); + readl(&mpmu->wdtpcr); + + /* clear previous WDT status */ + writel(TMR_WFAR, &armd1timers->wfar); + writel(TMP_WSAR, &armd1timers->wsar); + writel(0, &armd1timers->wdt_sts); + + /* set match counter */ + writel(TMR_WFAR, &armd1timers->wfar); + writel(TMP_WSAR, &armd1timers->wsar); + writel(0xf, &armd1timers->wdt_match_r); + + /* enable WDT reset */ + writel(TMR_WFAR, &armd1timers->wfar); + writel(TMP_WSAR, &armd1timers->wsar); + writel(0x3, &armd1timers->wdt_match_en); + + while(1); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + return (ulong)CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/Makefile new file mode 100644 index 000000000..698a28dc5 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/Makefile @@ -0,0 +1,29 @@ +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_AT91CAP9) += at91cap9_devices.o +obj-$(CONFIG_AT91SAM9260) += at91sam9260_devices.o +obj-$(CONFIG_AT91SAM9G20) += at91sam9260_devices.o +obj-$(CONFIG_AT91SAM9XE) += at91sam9260_devices.o +obj-$(CONFIG_AT91SAM9261) += at91sam9261_devices.o +obj-$(CONFIG_AT91SAM9G10) += at91sam9261_devices.o +obj-$(CONFIG_AT91SAM9263) += at91sam9263_devices.o +obj-$(CONFIG_AT91SAM9RL) += at91sam9rl_devices.o +obj-$(CONFIG_AT91SAM9M10G45) += at91sam9m10g45_devices.o +obj-$(CONFIG_AT91SAM9G45) += at91sam9m10g45_devices.o +obj-$(CONFIG_AT91SAM9N12) += at91sam9n12_devices.o +obj-$(CONFIG_AT91SAM9X5) += at91sam9x5_devices.o +obj-$(CONFIG_AT91_EFLASH) += eflash.o +obj-$(CONFIG_AT91_LED) += led.o +obj-y += clock.o +obj-y += cpu.o +obj-y += reset.o +obj-y += timer.o + +ifndef CONFIG_SKIP_LOWLEVEL_INIT +obj-y += lowlevel_init.o +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91cap9_devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91cap9_devices.c new file mode 100644 index 000000000..16eeca737 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91cap9_devices.c @@ -0,0 +1,189 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * (C) Copyright 2009 + * Daniel Gorsulowski <daniel.gorsulowski@esd.eu> + * esd electronic system design gmbh <www.esd.eu> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/gpio.h> +#include <asm/arch/io.h> + +void at91_serial0_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; + + at91_set_a_periph(AT91_PIO_PORTA, 22, 1); /* TXD0 */ + at91_set_a_periph(AT91_PIO_PORTA, 23, 0); /* RXD0 */ + writel(1 << AT91CAP9_ID_US0, &pmc->pcer); +} + +void at91_serial1_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; + + at91_set_a_periph(AT91_PIO_PORTD, 0, 1); /* TXD1 */ + at91_set_a_periph(AT91_PIO_PORTD, 1, 0); /* RXD1 */ + writel(1 << AT91CAP9_ID_US1, &pmc->pcer); +} + +void at91_serial2_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; + + at91_set_a_periph(AT91_PIO_PORTD, 2, 1); /* TXD2 */ + at91_set_a_periph(AT91_PIO_PORTD, 3, 0); /* RXD2 */ + writel(1 << AT91CAP9_ID_US2, &pmc->pcer); +} + +void at91_serial3_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; + + at91_set_a_periph(AT91_PIO_PORTC, 30, 0); /* DRXD */ + at91_set_a_periph(AT91_PIO_PORTC, 31, 1); /* DTXD */ + writel(1 << AT91_ID_SYS, &pmc->pcer); +} + +void at91_serial_hw_init(void) +{ +#ifdef CONFIG_USART0 + at91_serial0_hw_init(); +#endif + +#ifdef CONFIG_USART1 + at91_serial1_hw_init(); +#endif + +#ifdef CONFIG_USART2 + at91_serial2_hw_init(); +#endif + +#ifdef CONFIG_USART3 /* DBGU */ + at91_serial3_hw_init(); +#endif +} + +#ifdef CONFIG_HAS_DATAFLASH +void at91_spi0_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; + + at91_set_b_periph(AT91_PIO_PORTA, 0, 0); /* SPI0_MISO */ + at91_set_b_periph(AT91_PIO_PORTA, 1, 0); /* SPI0_MOSI */ + at91_set_b_periph(AT91_PIO_PORTA, 2, 0); /* SPI0_SPCK */ + + /* Enable clock */ + writel(1 << AT91CAP9_ID_SPI0, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_b_periph(AT91_PIO_PORTA, 5, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_b_periph(AT91_PIO_PORTA, 3, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_b_periph(AT91_PIO_PORTD, 0, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_b_periph(AT91_PIO_PORTD, 1, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTA, 5, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTA, 3, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTD, 0, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTD, 1, 1); + } +} + +void at91_spi1_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; + + at91_set_a_periph(AT91_PIO_PORTB, 12, 0); /* SPI1_MISO */ + at91_set_a_periph(AT91_PIO_PORTB, 13, 0); /* SPI1_MOSI */ + at91_set_a_periph(AT91_PIO_PORTB, 14, 0); /* SPI1_SPCK */ + + /* Enable clock */ + writel(1 << AT91CAP9_ID_SPI1, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_a_periph(AT91_PIO_PORTB, 15, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_a_periph(AT91_PIO_PORTB, 16, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_a_periph(AT91_PIO_PORTB, 17, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_a_periph(AT91_PIO_PORTB, 18, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTB, 15, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTB, 16, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTB, 17, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTB, 18, 1); + } + +} +#endif + +#ifdef CONFIG_MACB +void at91_macb_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTB, 21, 0); /* ETXCK_EREFCK */ + at91_set_a_periph(AT91_PIO_PORTB, 22, 0); /* ERXDV */ + at91_set_a_periph(AT91_PIO_PORTB, 25, 0); /* ERX0 */ + at91_set_a_periph(AT91_PIO_PORTB, 26, 0); /* ERX1 */ + at91_set_a_periph(AT91_PIO_PORTB, 27, 0); /* ERXER */ + at91_set_a_periph(AT91_PIO_PORTB, 28, 0); /* ETXEN */ + at91_set_a_periph(AT91_PIO_PORTB, 23, 0); /* ETX0 */ + at91_set_a_periph(AT91_PIO_PORTB, 24, 0); /* ETX1 */ + at91_set_a_periph(AT91_PIO_PORTB, 30, 0); /* EMDIO */ + at91_set_a_periph(AT91_PIO_PORTB, 29, 0); /* EMDC */ + +#ifndef CONFIG_RMII + at91_set_b_periph(AT91_PIO_PORTC, 25, 0); /* ECRS */ + at91_set_b_periph(AT91_PIO_PORTC, 26, 0); /* ECOL */ + at91_set_b_periph(AT91_PIO_PORTC, 22, 0); /* ERX2 */ + at91_set_b_periph(AT91_PIO_PORTC, 23, 0); /* ERX3 */ + at91_set_b_periph(AT91_PIO_PORTC, 27, 0); /* ERXCK */ + at91_set_b_periph(AT91_PIO_PORTC, 20, 0); /* ETX2 */ + at91_set_b_periph(AT91_PIO_PORTC, 21, 0); /* ETX3 */ + at91_set_b_periph(AT91_PIO_PORTC, 24, 0); /* ETXER */ +#endif +} +#endif + +#ifdef CONFIG_AT91_CAN +void at91_can_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; + + at91_set_a_periph(AT91_PIO_PORTA, 12, 0); /* CAN_TX */ + at91_set_a_periph(AT91_PIO_PORTA, 13, 1); /* CAN_RX */ + + /* Enable clock */ + writel(1 << AT91CAP9_ID_CAN, &pmc->pcer); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c new file mode 100644 index 000000000..cae4abcdf --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c @@ -0,0 +1,209 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/gpio.h> + +/* + * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all + * peripheral pins. Good to have if hardware is soldered optionally + * or in case of SPI no slave is selected. Avoid lines to float + * needlessly. Use a short local PUP define. + * + * Due to errata "TXD floats when CTS is inactive" pullups are always + * on for TXD pins. + */ +#ifdef CONFIG_AT91_GPIO_PULLUP +# define PUP CONFIG_AT91_GPIO_PULLUP +#else +# define PUP 0 +#endif + +void at91_serial0_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 4, 1); /* TXD0 */ + at91_set_a_periph(AT91_PIO_PORTB, 5, PUP); /* RXD0 */ + writel(1 << ATMEL_ID_USART0, &pmc->pcer); +} + +void at91_serial1_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 6, 1); /* TXD1 */ + at91_set_a_periph(AT91_PIO_PORTB, 7, PUP); /* RXD1 */ + writel(1 << ATMEL_ID_USART1, &pmc->pcer); +} + +void at91_serial2_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 8, 1); /* TXD2 */ + at91_set_a_periph(AT91_PIO_PORTB, 9, PUP); /* RXD2 */ + writel(1 << ATMEL_ID_USART2, &pmc->pcer); +} + +void at91_seriald_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 14, PUP); /* DRXD */ + at91_set_a_periph(AT91_PIO_PORTB, 15, 1); /* DTXD */ + writel(1 << ATMEL_ID_SYS, &pmc->pcer); +} + +#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI) +void at91_spi0_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 0, PUP); /* SPI0_MISO */ + at91_set_a_periph(AT91_PIO_PORTA, 1, PUP); /* SPI0_MOSI */ + at91_set_a_periph(AT91_PIO_PORTA, 2, PUP); /* SPI0_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI0, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_a_periph(AT91_PIO_PORTA, 3, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_b_periph(AT91_PIO_PORTC, 11, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_b_periph(AT91_PIO_PORTC, 16, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_b_periph(AT91_PIO_PORTC, 17, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTA, 3, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTC, 11, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTC, 16, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTC, 17, 1); + } +} + +void at91_spi1_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 0, PUP); /* SPI1_MISO */ + at91_set_a_periph(AT91_PIO_PORTB, 1, PUP); /* SPI1_MOSI */ + at91_set_a_periph(AT91_PIO_PORTB, 2, PUP); /* SPI1_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI1, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_a_periph(AT91_PIO_PORTB, 3, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_b_periph(AT91_PIO_PORTC, 5, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_b_periph(AT91_PIO_PORTC, 4, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_b_periph(AT91_PIO_PORTC, 3, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTB, 3, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTC, 5, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTC, 4, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTC, 3, 1); + } +} +#endif + +#ifdef CONFIG_MACB +void at91_macb_hw_init(void) +{ + /* Enable EMAC clock */ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + writel(1 << ATMEL_ID_EMAC0, &pmc->pcer); + + at91_set_a_periph(AT91_PIO_PORTA, 19, 0); /* ETXCK_EREFCK */ + at91_set_a_periph(AT91_PIO_PORTA, 17, 0); /* ERXDV */ + at91_set_a_periph(AT91_PIO_PORTA, 14, 0); /* ERX0 */ + at91_set_a_periph(AT91_PIO_PORTA, 15, 0); /* ERX1 */ + at91_set_a_periph(AT91_PIO_PORTA, 18, 0); /* ERXER */ + at91_set_a_periph(AT91_PIO_PORTA, 16, 0); /* ETXEN */ + at91_set_a_periph(AT91_PIO_PORTA, 12, 0); /* ETX0 */ + at91_set_a_periph(AT91_PIO_PORTA, 13, 0); /* ETX1 */ + at91_set_a_periph(AT91_PIO_PORTA, 21, 0); /* EMDIO */ + at91_set_a_periph(AT91_PIO_PORTA, 20, 0); /* EMDC */ + +#ifndef CONFIG_RMII + at91_set_b_periph(AT91_PIO_PORTA, 28, 0); /* ECRS */ + at91_set_b_periph(AT91_PIO_PORTA, 29, 0); /* ECOL */ + at91_set_b_periph(AT91_PIO_PORTA, 25, 0); /* ERX2 */ + at91_set_b_periph(AT91_PIO_PORTA, 26, 0); /* ERX3 */ + at91_set_b_periph(AT91_PIO_PORTA, 27, 0); /* ERXCK */ +#if defined(CONFIG_AT91SAM9260EK) || defined(CONFIG_AFEB9260) + /* + * use PA10, PA11 for ETX2, ETX3. + * PA23 and PA24 are for TWI EEPROM + */ + at91_set_b_periph(AT91_PIO_PORTA, 10, 0); /* ETX2 */ + at91_set_b_periph(AT91_PIO_PORTA, 11, 0); /* ETX3 */ +#else + at91_set_b_periph(AT91_PIO_PORTA, 23, 0); /* ETX2 */ + at91_set_b_periph(AT91_PIO_PORTA, 24, 0); /* ETX3 */ +#if defined(CONFIG_AT91SAM9G20) + /* 9G20 BOOT ROM initializes those pins to multi-drive, undo that */ + at91_set_pio_multi_drive(AT91_PIO_PORTA, 23, 0); + at91_set_pio_multi_drive(AT91_PIO_PORTA, 24, 0); +#endif +#endif + at91_set_b_periph(AT91_PIO_PORTA, 22, 0); /* ETXER */ +#endif +} +#endif + +#if defined(CONFIG_GENERIC_ATMEL_MCI) +void at91_mci_hw_init(void) +{ + /* Enable mci clock */ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + writel(1 << ATMEL_ID_MCI, &pmc->pcer); + + at91_set_a_periph(AT91_PIO_PORTA, 8, 1); /* MCCK */ +#if defined(CONFIG_ATMEL_MCI_PORTB) + at91_set_b_periph(AT91_PIO_PORTA, 1, 1); /* MCCDB */ + at91_set_b_periph(AT91_PIO_PORTA, 0, 1); /* MCDB0 */ + at91_set_b_periph(AT91_PIO_PORTA, 5, 1); /* MCDB1 */ + at91_set_b_periph(AT91_PIO_PORTA, 4, 1); /* MCDB2 */ + at91_set_b_periph(AT91_PIO_PORTA, 3, 1); /* MCDB3 */ +#else + at91_set_a_periph(AT91_PIO_PORTA, 7, 1); /* MCCDA */ + at91_set_a_periph(AT91_PIO_PORTA, 6, 1); /* MCDA0 */ + at91_set_a_periph(AT91_PIO_PORTA, 9, 1); /* MCDA1 */ + at91_set_a_periph(AT91_PIO_PORTA, 10, 1); /* MCDA2 */ + at91_set_a_periph(AT91_PIO_PORTA, 11, 1); /* MCDA3 */ +#endif +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9261_devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9261_devices.c new file mode 100644 index 000000000..a445c7507 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9261_devices.c @@ -0,0 +1,140 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/gpio.h> + +/* + * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all + * peripheral pins. Good to have if hardware is soldered optionally + * or in case of SPI no slave is selected. Avoid lines to float + * needlessly. Use a short local PUP define. + * + * Due to errata "TXD floats when CTS is inactive" pullups are always + * on for TXD pins. + */ +#ifdef CONFIG_AT91_GPIO_PULLUP +# define PUP CONFIG_AT91_GPIO_PULLUP +#else +# define PUP 0 +#endif + +void at91_serial0_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTC, 8, 1); /* TXD0 */ + at91_set_a_periph(AT91_PIO_PORTC, 9, 0); /* RXD0 */ + writel(1 << ATMEL_ID_USART0, &pmc->pcer); +} + +void at91_serial1_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTC, 12, 1); /* TXD1 */ + at91_set_a_periph(AT91_PIO_PORTC, 13, 0); /* RXD1 */ + writel(1 << ATMEL_ID_USART1, &pmc->pcer); +} + +void at91_serial2_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTC, 14, 1); /* TXD2 */ + at91_set_a_periph(AT91_PIO_PORTC, 15, 0); /* RXD2 */ + writel(1 << ATMEL_ID_USART2, &pmc->pcer); +} + +void at91_seriald_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 9, 0); /* DRXD */ + at91_set_a_periph(AT91_PIO_PORTA, 10, 1); /* DTXD */ + writel(1 << ATMEL_ID_SYS, &pmc->pcer); +} + +#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI) +void at91_spi0_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 0, PUP); /* SPI0_MISO */ + at91_set_a_periph(AT91_PIO_PORTA, 1, PUP); /* SPI0_MOSI */ + at91_set_a_periph(AT91_PIO_PORTA, 2, PUP); /* SPI0_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI0, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_a_periph(AT91_PIO_PORTA, 3, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_a_periph(AT91_PIO_PORTA, 4, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_a_periph(AT91_PIO_PORTA, 5, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_a_periph(AT91_PIO_PORTA, 6, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTA, 3, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTA, 4, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTA, 5, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTA, 6, 1); + } +} + +void at91_spi1_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 30, PUP); /* SPI1_MISO */ + at91_set_a_periph(AT91_PIO_PORTB, 31, PUP); /* SPI1_MOSI */ + at91_set_a_periph(AT91_PIO_PORTB, 29, PUP); /* SPI1_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI1, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_a_periph(AT91_PIO_PORTB, 28, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_b_periph(AT91_PIO_PORTA, 24, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_b_periph(AT91_PIO_PORTA, 25, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_a_periph(AT91_PIO_PORTA, 26, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTB, 28, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTA, 24, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTA, 25, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTA, 26, 1); + } +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9263_devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9263_devices.c new file mode 100644 index 000000000..6b51d5f35 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9263_devices.c @@ -0,0 +1,218 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * (C) Copyright 2009-2011 + * Daniel Gorsulowski <daniel.gorsulowski@esd.eu> + * esd electronic system design gmbh <www.esd.eu> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/gpio.h> + +/* + * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all + * peripheral pins. Good to have if hardware is soldered optionally + * or in case of SPI no slave is selected. Avoid lines to float + * needlessly. Use a short local PUP define. + * + * Due to errata "TXD floats when CTS is inactive" pullups are always + * on for TXD pins. + */ +#ifdef CONFIG_AT91_GPIO_PULLUP +# define PUP CONFIG_AT91_GPIO_PULLUP +#else +# define PUP 0 +#endif + +void at91_serial0_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 26, 1); /* TXD0 */ + at91_set_a_periph(AT91_PIO_PORTA, 27, PUP); /* RXD0 */ + writel(1 << ATMEL_ID_USART0, &pmc->pcer); +} + +void at91_serial1_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTD, 0, 1); /* TXD1 */ + at91_set_a_periph(AT91_PIO_PORTD, 1, PUP); /* RXD1 */ + writel(1 << ATMEL_ID_USART1, &pmc->pcer); +} + +void at91_serial2_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTD, 2, 1); /* TXD2 */ + at91_set_a_periph(AT91_PIO_PORTD, 3, PUP); /* RXD2 */ + writel(1 << ATMEL_ID_USART2, &pmc->pcer); +} + +void at91_seriald_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTC, 30, PUP); /* DRXD */ + at91_set_a_periph(AT91_PIO_PORTC, 31, 1); /* DTXD */ + writel(1 << ATMEL_ID_SYS, &pmc->pcer); +} + +#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI) +void at91_spi0_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_b_periph(AT91_PIO_PORTA, 0, PUP); /* SPI0_MISO */ + at91_set_b_periph(AT91_PIO_PORTA, 1, PUP); /* SPI0_MOSI */ + at91_set_b_periph(AT91_PIO_PORTA, 2, PUP); /* SPI0_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI0, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_b_periph(AT91_PIO_PORTA, 5, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_b_periph(AT91_PIO_PORTA, 3, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_b_periph(AT91_PIO_PORTA, 4, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_b_periph(AT91_PIO_PORTB, 11, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTA, 5, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTA, 3, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTA, 4, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTB, 11, 1); + } +} + +void at91_spi1_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 12, PUP); /* SPI1_MISO */ + at91_set_a_periph(AT91_PIO_PORTB, 13, PUP); /* SPI1_MOSI */ + at91_set_a_periph(AT91_PIO_PORTB, 14, PUP); /* SPI1_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI1, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_a_periph(AT91_PIO_PORTB, 15, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_a_periph(AT91_PIO_PORTB, 16, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_a_periph(AT91_PIO_PORTB, 17, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_a_periph(AT91_PIO_PORTB, 18, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTB, 15, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTB, 16, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTB, 17, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTB, 18, 1); + } +} +#endif + +#if defined(CONFIG_GENERIC_ATMEL_MCI) +void at91_mci_hw_init(void) +{ + /* Enable mci clock */ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + writel(1 << ATMEL_ID_MCI1, &pmc->pcer); + + at91_set_a_periph(AT91_PIO_PORTA, 6, PUP); /* MCI1_CK */ + +#if defined(CONFIG_ATMEL_MCI_PORTB) + at91_set_a_periph(AT91_PIO_PORTA, 21, PUP); /* MCI1_CDB */ + at91_set_a_periph(AT91_PIO_PORTA, 22, PUP); /* MCI1_DB0 */ + at91_set_a_periph(AT91_PIO_PORTA, 23, PUP); /* MCI1_DB1 */ + at91_set_a_periph(AT91_PIO_PORTA, 24, PUP); /* MCI1_DB2 */ + at91_set_a_periph(AT91_PIO_PORTA, 25, PUP); /* MCI1_DB3 */ +#else + at91_set_a_periph(AT91_PIO_PORTA, 7, PUP); /* MCI1_CDA */ + at91_set_a_periph(AT91_PIO_PORTA, 8, PUP); /* MCI1_DA0 */ + at91_set_a_periph(AT91_PIO_PORTA, 9, PUP); /* MCI1_DA1 */ + at91_set_a_periph(AT91_PIO_PORTA, 10, PUP); /* MCI1_DA2 */ + at91_set_a_periph(AT91_PIO_PORTA, 11, PUP); /* MCI1_DA3 */ +#endif +} +#endif + +#ifdef CONFIG_MACB +void at91_macb_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTE, 21, 0); /* ETXCK_EREFCK */ + at91_set_b_periph(AT91_PIO_PORTC, 25, 0); /* ERXDV */ + at91_set_a_periph(AT91_PIO_PORTE, 25, 0); /* ERX0 */ + at91_set_a_periph(AT91_PIO_PORTE, 26, 0); /* ERX1 */ + at91_set_a_periph(AT91_PIO_PORTE, 27, 0); /* ERXER */ + at91_set_a_periph(AT91_PIO_PORTE, 28, 0); /* ETXEN */ + at91_set_a_periph(AT91_PIO_PORTE, 23, 0); /* ETX0 */ + at91_set_a_periph(AT91_PIO_PORTE, 24, 0); /* ETX1 */ + at91_set_a_periph(AT91_PIO_PORTE, 30, 0); /* EMDIO */ + at91_set_a_periph(AT91_PIO_PORTE, 29, 0); /* EMDC */ + +#ifndef CONFIG_RMII + at91_set_a_periph(AT91_PIO_PORTE, 22, 0); /* ECRS */ + at91_set_b_periph(AT91_PIO_PORTC, 26, 0); /* ECOL */ + at91_set_b_periph(AT91_PIO_PORTC, 22, 0); /* ERX2 */ + at91_set_b_periph(AT91_PIO_PORTC, 23, 0); /* ERX3 */ + at91_set_b_periph(AT91_PIO_PORTC, 27, 0); /* ERXCK */ + at91_set_b_periph(AT91_PIO_PORTC, 20, 0); /* ETX2 */ + at91_set_b_periph(AT91_PIO_PORTC, 21, 0); /* ETX3 */ + at91_set_b_periph(AT91_PIO_PORTC, 24, 0); /* ETXER */ +#endif +} +#endif + +#ifdef CONFIG_USB_OHCI_NEW +void at91_uhp_hw_init(void) +{ + /* Enable VBus on UHP ports */ + at91_set_pio_output(AT91_PIO_PORTA, 21, 0); + at91_set_pio_output(AT91_PIO_PORTA, 24, 0); +} +#endif + +#ifdef CONFIG_AT91_CAN +void at91_can_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 13, 0); /* CAN_TX */ + at91_set_a_periph(AT91_PIO_PORTA, 14, 1); /* CAN_RX */ + + /* Enable clock */ + writel(1 << ATMEL_ID_CAN, &pmc->pcer); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9m10g45_devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9m10g45_devices.c new file mode 100644 index 000000000..7d7725c4b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9m10g45_devices.c @@ -0,0 +1,167 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/gpio.h> +#include <asm/io.h> + +/* + * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all + * peripheral pins. Good to have if hardware is soldered optionally + * or in case of SPI no slave is selected. Avoid lines to float + * needlessly. Use a short local PUP define. + * + * Due to errata "TXD floats when CTS is inactive" pullups are always + * on for TXD pins. + */ +#ifdef CONFIG_AT91_GPIO_PULLUP +# define PUP CONFIG_AT91_GPIO_PULLUP +#else +# define PUP 0 +#endif + +void at91_serial0_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 19, 1); /* TXD0 */ + at91_set_a_periph(AT91_PIO_PORTB, 18, PUP); /* RXD0 */ + writel(1 << ATMEL_ID_USART0, &pmc->pcer); +} + +void at91_serial1_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 4, 1); /* TXD1 */ + at91_set_a_periph(AT91_PIO_PORTB, 5, PUP); /* RXD1 */ + writel(1 << ATMEL_ID_USART1, &pmc->pcer); +} + +void at91_serial2_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTD, 6, 1); /* TXD2 */ + at91_set_a_periph(AT91_PIO_PORTD, 7, PUP); /* RXD2 */ + writel(1 << ATMEL_ID_USART2, &pmc->pcer); +} + +void at91_seriald_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 12, 0); /* DRXD */ + at91_set_a_periph(AT91_PIO_PORTB, 13, 1); /* DTXD */ + writel(1 << ATMEL_ID_SYS, &pmc->pcer); +} + +#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI) +void at91_spi0_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 0, PUP); /* SPI0_MISO */ + at91_set_a_periph(AT91_PIO_PORTB, 1, PUP); /* SPI0_MOSI */ + at91_set_a_periph(AT91_PIO_PORTB, 2, PUP); /* SPI0_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI0, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_a_periph(AT91_PIO_PORTB, 3, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_b_periph(AT91_PIO_PORTB, 18, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_b_periph(AT91_PIO_PORTB, 19, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_b_periph(AT91_PIO_PORTD, 27, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTB, 3, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTB, 18, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTB, 19, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTD, 27, 1); + } +} + +void at91_spi1_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTB, 14, PUP); /* SPI1_MISO */ + at91_set_a_periph(AT91_PIO_PORTB, 15, PUP); /* SPI1_MOSI */ + at91_set_a_periph(AT91_PIO_PORTB, 16, PUP); /* SPI1_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI1, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_a_periph(AT91_PIO_PORTB, 17, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_b_periph(AT91_PIO_PORTD, 28, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_a_periph(AT91_PIO_PORTD, 18, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_a_periph(AT91_PIO_PORTD, 19, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTB, 17, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTD, 28, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTD, 18, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTD, 19, 1); + } + +} +#endif + +#ifdef CONFIG_MACB +void at91_macb_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTA, 17, 0); /* ETXCK_EREFCK */ + at91_set_a_periph(AT91_PIO_PORTA, 15, 0); /* ERXDV */ + at91_set_a_periph(AT91_PIO_PORTA, 12, 0); /* ERX0 */ + at91_set_a_periph(AT91_PIO_PORTA, 13, 0); /* ERX1 */ + at91_set_a_periph(AT91_PIO_PORTA, 16, 0); /* ERXER */ + at91_set_a_periph(AT91_PIO_PORTA, 14, 0); /* ETXEN */ + at91_set_a_periph(AT91_PIO_PORTA, 10, 0); /* ETX0 */ + at91_set_a_periph(AT91_PIO_PORTA, 11, 0); /* ETX1 */ + at91_set_a_periph(AT91_PIO_PORTA, 19, 0); /* EMDIO */ + at91_set_a_periph(AT91_PIO_PORTA, 18, 0); /* EMDC */ +#ifndef CONFIG_RMII + at91_set_b_periph(AT91_PIO_PORTA, 29, 0); /* ECRS */ + at91_set_b_periph(AT91_PIO_PORTA, 30, 0); /* ECOL */ + at91_set_b_periph(AT91_PIO_PORTA, 8, 0); /* ERX2 */ + at91_set_b_periph(AT91_PIO_PORTA, 9, 0); /* ERX3 */ + at91_set_b_periph(AT91_PIO_PORTA, 28, 0); /* ERXCK */ + at91_set_b_periph(AT91_PIO_PORTA, 6, 0); /* ETX2 */ + at91_set_b_periph(AT91_PIO_PORTA, 7, 0); /* ETX3 */ + at91_set_b_periph(AT91_PIO_PORTA, 27, 0); /* ETXER */ +#endif +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9n12_devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9n12_devices.c new file mode 100644 index 000000000..39f17a1e1 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9n12_devices.c @@ -0,0 +1,161 @@ +/* + * (C) Copyright 2013 Atmel Corporation + * Josh Wu <josh.wu@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_pio.h> + +unsigned int has_lcdc() +{ + return 1; +} + +void at91_serial0_hw_init(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 0, 1); /* TXD0 */ + at91_set_a_periph(AT91_PIO_PORTA, 1, 0); /* RXD0 */ + writel(1 << ATMEL_ID_USART0, &pmc->pcer); +} + +void at91_serial1_hw_init(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 5, 1); /* TXD1 */ + at91_set_a_periph(AT91_PIO_PORTA, 6, 0); /* RXD1 */ + writel(1 << ATMEL_ID_USART1, &pmc->pcer); +} + +void at91_serial2_hw_init(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 7, 1); /* TXD2 */ + at91_set_a_periph(AT91_PIO_PORTA, 8, 0); /* RXD2 */ + writel(1 << ATMEL_ID_USART2, &pmc->pcer); +} + +void at91_serial3_hw_init(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + at91_set_b_periph(AT91_PIO_PORTC, 22, 1); /* TXD3 */ + at91_set_b_periph(AT91_PIO_PORTC, 23, 0); /* RXD3 */ + writel(1 << ATMEL_ID_USART3, &pmc->pcer); +} + +void at91_seriald_hw_init(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 10, 1); /* DTXD */ + at91_set_a_periph(AT91_PIO_PORTA, 9, 0); /* DRXD */ + writel(1 << ATMEL_ID_SYS, &pmc->pcer); +} + +#ifdef CONFIG_ATMEL_SPI +void at91_spi0_hw_init(unsigned long cs_mask) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 11, 0); /* SPI0_MISO */ + at91_set_a_periph(AT91_PIO_PORTA, 12, 0); /* SPI0_MOSI */ + at91_set_a_periph(AT91_PIO_PORTA, 13, 0); /* SPI0_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI0, &pmc->pcer); + + if (cs_mask & (1 << 0)) + at91_set_pio_output(AT91_PIO_PORTA, 14, 1); + if (cs_mask & (1 << 1)) + at91_set_pio_output(AT91_PIO_PORTA, 7, 1); + if (cs_mask & (1 << 2)) + at91_set_pio_output(AT91_PIO_PORTA, 1, 1); + if (cs_mask & (1 << 3)) + at91_set_pio_output(AT91_PIO_PORTB, 3, 1); +} + +void at91_spi1_hw_init(unsigned long cs_mask) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + at91_set_b_periph(AT91_PIO_PORTA, 21, 0); /* SPI1_MISO */ + at91_set_b_periph(AT91_PIO_PORTA, 22, 0); /* SPI1_MOSI */ + at91_set_b_periph(AT91_PIO_PORTA, 23, 0); /* SPI1_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI1, &pmc->pcer); + + if (cs_mask & (1 << 0)) + at91_set_pio_output(AT91_PIO_PORTA, 8, 1); + if (cs_mask & (1 << 1)) + at91_set_pio_output(AT91_PIO_PORTA, 0, 1); + if (cs_mask & (1 << 2)) + at91_set_pio_output(AT91_PIO_PORTA, 31, 1); + if (cs_mask & (1 << 3)) + at91_set_pio_output(AT91_PIO_PORTA, 30, 1); +} +#endif + +void at91_mci_hw_init(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 17, 0); /* MCCK */ + at91_set_a_periph(AT91_PIO_PORTA, 16, 0); /* MCCDA */ + at91_set_a_periph(AT91_PIO_PORTA, 15, 0); /* MCDA0 */ + at91_set_a_periph(AT91_PIO_PORTA, 18, 0); /* MCDA1 */ + at91_set_a_periph(AT91_PIO_PORTA, 19, 0); /* MCDA2 */ + at91_set_a_periph(AT91_PIO_PORTA, 20, 0); /* MCDA3 */ + + writel(1 << ATMEL_ID_HSMCI0, &pmc->pcer); +} + +#ifdef CONFIG_LCD +void at91_lcd_hw_init(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTC, 24, 0); /* LCDDPWR */ + at91_set_a_periph(AT91_PIO_PORTC, 26, 0); /* LCDVSYNC */ + at91_set_a_periph(AT91_PIO_PORTC, 27, 0); /* LCDHSYNC */ + at91_set_a_periph(AT91_PIO_PORTC, 28, 0); /* LCDDOTCK */ + at91_set_a_periph(AT91_PIO_PORTC, 29, 0); /* LCDDEN */ + at91_set_a_periph(AT91_PIO_PORTC, 30, 0); /* LCDDOTCK */ + + at91_set_a_periph(AT91_PIO_PORTC, 0, 0); /* LCDD0 */ + at91_set_a_periph(AT91_PIO_PORTC, 1, 0); /* LCDD1 */ + at91_set_a_periph(AT91_PIO_PORTC, 2, 0); /* LCDD2 */ + at91_set_a_periph(AT91_PIO_PORTC, 3, 0); /* LCDD3 */ + at91_set_a_periph(AT91_PIO_PORTC, 4, 0); /* LCDD4 */ + at91_set_a_periph(AT91_PIO_PORTC, 5, 0); /* LCDD5 */ + at91_set_a_periph(AT91_PIO_PORTC, 6, 0); /* LCDD6 */ + at91_set_a_periph(AT91_PIO_PORTC, 7, 0); /* LCDD7 */ + at91_set_a_periph(AT91_PIO_PORTC, 8, 0); /* LCDD8 */ + at91_set_a_periph(AT91_PIO_PORTC, 9, 0); /* LCDD9 */ + at91_set_a_periph(AT91_PIO_PORTC, 10, 0); /* LCDD10 */ + at91_set_a_periph(AT91_PIO_PORTC, 11, 0); /* LCDD11 */ + at91_set_a_periph(AT91_PIO_PORTC, 12, 0); /* LCDD12 */ + at91_set_a_periph(AT91_PIO_PORTC, 13, 0); /* LCDD13 */ + at91_set_a_periph(AT91_PIO_PORTC, 14, 0); /* LCDD14 */ + at91_set_a_periph(AT91_PIO_PORTC, 15, 0); /* LCDD15 */ + at91_set_a_periph(AT91_PIO_PORTC, 16, 0); /* LCDD16 */ + at91_set_a_periph(AT91_PIO_PORTC, 17, 0); /* LCDD17 */ + at91_set_a_periph(AT91_PIO_PORTC, 18, 0); /* LCDD18 */ + at91_set_a_periph(AT91_PIO_PORTC, 19, 0); /* LCDD19 */ + at91_set_a_periph(AT91_PIO_PORTC, 20, 0); /* LCDD20 */ + at91_set_a_periph(AT91_PIO_PORTC, 21, 0); /* LCDD21 */ + at91_set_a_periph(AT91_PIO_PORTC, 22, 0); /* LCDD22 */ + at91_set_a_periph(AT91_PIO_PORTC, 23, 0); /* LCDD23 */ + + writel(1 << ATMEL_ID_LCDC, &pmc->pcer); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9rl_devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9rl_devices.c new file mode 100644 index 000000000..0ec32c3ab --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9rl_devices.c @@ -0,0 +1,103 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/gpio.h> + +/* + * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all + * peripheral pins. Good to have if hardware is soldered optionally + * or in case of SPI no slave is selected. Avoid lines to float + * needlessly. Use a short local PUP define. + * + * Due to errata "TXD floats when CTS is inactive" pullups are always + * on for TXD pins. + */ +#ifdef CONFIG_AT91_GPIO_PULLUP +# define PUP CONFIG_AT91_GPIO_PULLUP +#else +# define PUP 0 +#endif + +void at91_serial0_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 6, 1); /* TXD0 */ + at91_set_a_periph(AT91_PIO_PORTA, 7, PUP); /* RXD0 */ + writel(1 << ATMEL_ID_USART0, &pmc->pcer); +} + +void at91_serial1_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 11, 1); /* TXD1 */ + at91_set_a_periph(AT91_PIO_PORTA, 12, PUP); /* RXD1 */ + writel(1 << ATMEL_ID_USART1, &pmc->pcer); +} + +void at91_serial2_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 13, 1); /* TXD2 */ + at91_set_a_periph(AT91_PIO_PORTA, 14, PUP); /* RXD2 */ + writel(1 << ATMEL_ID_USART2, &pmc->pcer); +} + +void at91_seriald_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 21, PUP); /* DRXD */ + at91_set_a_periph(AT91_PIO_PORTA, 22, 1); /* DTXD */ + writel(1 << ATMEL_ID_SYS, &pmc->pcer); +} + +#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI) +void at91_spi0_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 25, PUP); /* SPI0_MISO */ + at91_set_a_periph(AT91_PIO_PORTA, 26, PUP); /* SPI0_MOSI */ + at91_set_a_periph(AT91_PIO_PORTA, 27, PUP); /* SPI0_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI, &pmc->pcer); + + if (cs_mask & (1 << 0)) { + at91_set_a_periph(AT91_PIO_PORTA, 28, 1); + } + if (cs_mask & (1 << 1)) { + at91_set_b_periph(AT91_PIO_PORTB, 7, 1); + } + if (cs_mask & (1 << 2)) { + at91_set_a_periph(AT91_PIO_PORTD, 8, 1); + } + if (cs_mask & (1 << 3)) { + at91_set_b_periph(AT91_PIO_PORTD, 9, 1); + } + if (cs_mask & (1 << 4)) { + at91_set_pio_output(AT91_PIO_PORTA, 28, 1); + } + if (cs_mask & (1 << 5)) { + at91_set_pio_output(AT91_PIO_PORTB, 7, 1); + } + if (cs_mask & (1 << 6)) { + at91_set_pio_output(AT91_PIO_PORTD, 8, 1); + } + if (cs_mask & (1 << 7)) { + at91_set_pio_output(AT91_PIO_PORTD, 9, 1); + } +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9x5_devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9x5_devices.c new file mode 100644 index 000000000..6d9457223 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/at91sam9x5_devices.c @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2012 Atmel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/gpio.h> +#include <asm/io.h> + +unsigned int get_chip_id(void) +{ + /* The 0x40 is the offset of cidr in DBGU */ + return readl(ATMEL_BASE_DBGU + 0x40) & ~ARCH_ID_VERSION_MASK; +} + +unsigned int get_extension_chip_id(void) +{ + /* The 0x44 is the offset of exid in DBGU */ + return readl(ATMEL_BASE_DBGU + 0x44); +} + +unsigned int has_emac1() +{ + return cpu_is_at91sam9x25(); +} + +unsigned int has_emac0() +{ + return !(cpu_is_at91sam9g15()); +} + +unsigned int has_lcdc() +{ + return cpu_is_at91sam9g15() || cpu_is_at91sam9g35() + || cpu_is_at91sam9x35(); +} + +char *get_cpu_name() +{ + unsigned int extension_id = get_extension_chip_id(); + + if (cpu_is_at91sam9x5()) { + switch (extension_id) { + case ARCH_EXID_AT91SAM9G15: + return "AT91SAM9G15"; + case ARCH_EXID_AT91SAM9G25: + return "AT91SAM9G25"; + case ARCH_EXID_AT91SAM9G35: + return "AT91SAM9G35"; + case ARCH_EXID_AT91SAM9X25: + return "AT91SAM9X25"; + case ARCH_EXID_AT91SAM9X35: + return "AT91SAM9X35"; + default: + return "Unknown CPU type"; + } + } else { + return "Unknown CPU type"; + } +} + +void at91_seriald_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 9, 0); /* DRXD */ + at91_set_a_periph(AT91_PIO_PORTA, 10, 1); /* DTXD */ + + writel(1 << ATMEL_ID_SYS, &pmc->pcer); +} + +void at91_serial0_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 0, 1); /* TXD */ + at91_set_a_periph(AT91_PIO_PORTA, 1, 0); /* RXD */ + + writel(1 << ATMEL_ID_USART0, &pmc->pcer); +} + +void at91_serial1_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 5, 1); /* TXD */ + at91_set_a_periph(AT91_PIO_PORTA, 6, 0); /* RXD */ + + writel(1 << ATMEL_ID_USART1, &pmc->pcer); +} + +void at91_serial2_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 7, 1); /* TXD */ + at91_set_a_periph(AT91_PIO_PORTA, 8, 0); /* RXD */ + + writel(1 << ATMEL_ID_USART2, &pmc->pcer); +} + +void at91_mci_hw_init(void) +{ + /* Initialize the MCI0 */ + at91_set_a_periph(AT91_PIO_PORTA, 17, 1); /* MCCK */ + at91_set_a_periph(AT91_PIO_PORTA, 16, 1); /* MCCDA */ + at91_set_a_periph(AT91_PIO_PORTA, 15, 1); /* MCDA0 */ + at91_set_a_periph(AT91_PIO_PORTA, 18, 1); /* MCDA1 */ + at91_set_a_periph(AT91_PIO_PORTA, 19, 1); /* MCDA2 */ + at91_set_a_periph(AT91_PIO_PORTA, 20, 1); /* MCDA3 */ + + /* Enable clock for MCI0 */ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + writel(1 << ATMEL_ID_HSMCI0, &pmc->pcer); +} + +#ifdef CONFIG_ATMEL_SPI +void at91_spi0_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 11, 0); /* SPI0_MISO */ + at91_set_a_periph(AT91_PIO_PORTA, 12, 0); /* SPI0_MOSI */ + at91_set_a_periph(AT91_PIO_PORTA, 13, 0); /* SPI0_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI0, &pmc->pcer); + + if (cs_mask & (1 << 0)) + at91_set_a_periph(AT91_PIO_PORTA, 14, 0); + if (cs_mask & (1 << 1)) + at91_set_b_periph(AT91_PIO_PORTA, 7, 0); + if (cs_mask & (1 << 2)) + at91_set_b_periph(AT91_PIO_PORTA, 1, 0); + if (cs_mask & (1 << 3)) + at91_set_b_periph(AT91_PIO_PORTB, 3, 0); + if (cs_mask & (1 << 4)) + at91_set_pio_output(AT91_PIO_PORTA, 14, 0); + if (cs_mask & (1 << 5)) + at91_set_pio_output(AT91_PIO_PORTA, 7, 0); + if (cs_mask & (1 << 6)) + at91_set_pio_output(AT91_PIO_PORTA, 1, 0); + if (cs_mask & (1 << 7)) + at91_set_pio_output(AT91_PIO_PORTB, 3, 0); +} + +void at91_spi1_hw_init(unsigned long cs_mask) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + at91_set_b_periph(AT91_PIO_PORTA, 21, 0); /* SPI1_MISO */ + at91_set_b_periph(AT91_PIO_PORTA, 22, 0); /* SPI1_MOSI */ + at91_set_b_periph(AT91_PIO_PORTA, 23, 0); /* SPI1_SPCK */ + + /* Enable clock */ + writel(1 << ATMEL_ID_SPI1, &pmc->pcer); + + if (cs_mask & (1 << 0)) + at91_set_b_periph(AT91_PIO_PORTA, 8, 0); + if (cs_mask & (1 << 1)) + at91_set_b_periph(AT91_PIO_PORTA, 0, 0); + if (cs_mask & (1 << 2)) + at91_set_b_periph(AT91_PIO_PORTA, 31, 0); + if (cs_mask & (1 << 3)) + at91_set_b_periph(AT91_PIO_PORTA, 30, 0); + if (cs_mask & (1 << 4)) + at91_set_pio_output(AT91_PIO_PORTA, 8, 0); + if (cs_mask & (1 << 5)) + at91_set_pio_output(AT91_PIO_PORTA, 0, 0); + if (cs_mask & (1 << 6)) + at91_set_pio_output(AT91_PIO_PORTA, 31, 0); + if (cs_mask & (1 << 7)) + at91_set_pio_output(AT91_PIO_PORTA, 30, 0); +} +#endif + +#if defined(CONFIG_USB_OHCI_NEW) || defined(CONFIG_USB_EHCI) +void at91_uhp_hw_init(void) +{ + /* Enable VBus on UHP ports */ + at91_set_pio_output(AT91_PIO_PORTD, 18, 0); /* port A */ + at91_set_pio_output(AT91_PIO_PORTD, 19, 0); /* port B */ +#if defined(CONFIG_USB_OHCI_NEW) + /* port C is OHCI only */ + at91_set_pio_output(AT91_PIO_PORTD, 20, 0); /* port C */ +#endif +} +#endif + +#ifdef CONFIG_MACB +void at91_macb_hw_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + + if (has_emac0()) { + /* Enable EMAC0 clock */ + writel(1 << ATMEL_ID_EMAC0, &pmc->pcer); + /* EMAC0 pins setup */ + at91_set_a_periph(AT91_PIO_PORTB, 4, 0); /* ETXCK */ + at91_set_a_periph(AT91_PIO_PORTB, 3, 0); /* ERXDV */ + at91_set_a_periph(AT91_PIO_PORTB, 0, 0); /* ERX0 */ + at91_set_a_periph(AT91_PIO_PORTB, 1, 0); /* ERX1 */ + at91_set_a_periph(AT91_PIO_PORTB, 2, 0); /* ERXER */ + at91_set_a_periph(AT91_PIO_PORTB, 7, 0); /* ETXEN */ + at91_set_a_periph(AT91_PIO_PORTB, 9, 0); /* ETX0 */ + at91_set_a_periph(AT91_PIO_PORTB, 10, 0); /* ETX1 */ + at91_set_a_periph(AT91_PIO_PORTB, 5, 0); /* EMDIO */ + at91_set_a_periph(AT91_PIO_PORTB, 6, 0); /* EMDC */ + } + + if (has_emac1()) { + /* Enable EMAC1 clock */ + writel(1 << ATMEL_ID_EMAC1, &pmc->pcer); + /* EMAC1 pins setup */ + at91_set_b_periph(AT91_PIO_PORTC, 29, 0); /* ETXCK */ + at91_set_b_periph(AT91_PIO_PORTC, 28, 0); /* ECRSDV */ + at91_set_b_periph(AT91_PIO_PORTC, 20, 0); /* ERXO */ + at91_set_b_periph(AT91_PIO_PORTC, 21, 0); /* ERX1 */ + at91_set_b_periph(AT91_PIO_PORTC, 16, 0); /* ERXER */ + at91_set_b_periph(AT91_PIO_PORTC, 27, 0); /* ETXEN */ + at91_set_b_periph(AT91_PIO_PORTC, 18, 0); /* ETX0 */ + at91_set_b_periph(AT91_PIO_PORTC, 19, 0); /* ETX1 */ + at91_set_b_periph(AT91_PIO_PORTC, 31, 0); /* EMDIO */ + at91_set_b_periph(AT91_PIO_PORTC, 30, 0); /* EMDC */ + } + +#ifndef CONFIG_RMII + /* Only emac0 support MII */ + if (has_emac0()) { + at91_set_a_periph(AT91_PIO_PORTB, 16, 0); /* ECRS */ + at91_set_a_periph(AT91_PIO_PORTB, 17, 0); /* ECOL */ + at91_set_a_periph(AT91_PIO_PORTB, 13, 0); /* ERX2 */ + at91_set_a_periph(AT91_PIO_PORTB, 14, 0); /* ERX3 */ + at91_set_a_periph(AT91_PIO_PORTB, 15, 0); /* ERXCK */ + at91_set_a_periph(AT91_PIO_PORTB, 11, 0); /* ETX2 */ + at91_set_a_periph(AT91_PIO_PORTB, 12, 0); /* ETX3 */ + at91_set_a_periph(AT91_PIO_PORTB, 8, 0); /* ETXER */ + } +#endif +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/clock.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/clock.c new file mode 100644 index 000000000..31315b58e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/clock.c @@ -0,0 +1,189 @@ +/* + * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c] + * + * Copyright (C) 2005 David Brownell + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/clk.h> + +#if !defined(CONFIG_AT91FAMILY) +# error You need to define CONFIG_AT91FAMILY in your board config! +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static unsigned long at91_css_to_rate(unsigned long css) +{ + switch (css) { + case AT91_PMC_MCKR_CSS_SLOW: + return CONFIG_SYS_AT91_SLOW_CLOCK; + case AT91_PMC_MCKR_CSS_MAIN: + return gd->arch.main_clk_rate_hz; + case AT91_PMC_MCKR_CSS_PLLA: + return gd->arch.plla_rate_hz; + case AT91_PMC_MCKR_CSS_PLLB: + return gd->arch.pllb_rate_hz; + } + + return 0; +} + +#ifdef CONFIG_USB_ATMEL +static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq) +{ + unsigned i, div = 0, mul = 0, diff = 1 << 30; + unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00; + + /* PLL output max 240 MHz (or 180 MHz per errata) */ + if (out_freq > 240000000) + goto fail; + + for (i = 1; i < 256; i++) { + int diff1; + unsigned input, mul1; + + /* + * PLL input between 1MHz and 32MHz per spec, but lower + * frequences seem necessary in some cases so allow 100K. + * Warning: some newer products need 2MHz min. + */ + input = main_freq / i; +#if defined(CONFIG_AT91SAM9G20) + if (input < 2000000) + continue; +#endif + if (input < 100000) + continue; + if (input > 32000000) + continue; + + mul1 = out_freq / input; +#if defined(CONFIG_AT91SAM9G20) + if (mul > 63) + continue; +#endif + if (mul1 > 2048) + continue; + if (mul1 < 2) + goto fail; + + diff1 = out_freq - input * mul1; + if (diff1 < 0) + diff1 = -diff1; + if (diff > diff1) { + diff = diff1; + div = i; + mul = mul1; + if (diff == 0) + break; + } + } + if (i == 256 && diff > (out_freq >> 5)) + goto fail; + return ret | ((mul - 1) << 16) | div; +fail: + return 0; +} +#endif + +static u32 at91_pll_rate(u32 freq, u32 reg) +{ + unsigned mul, div; + + div = reg & 0xff; + mul = (reg >> 16) & 0x7ff; + if (div && mul) { + freq /= div; + freq *= mul + 1; + } else + freq = 0; + + return freq; +} + +int at91_clock_init(unsigned long main_clock) +{ + unsigned freq, mckr; + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; +#ifndef CONFIG_SYS_AT91_MAIN_CLOCK + unsigned tmp; + /* + * When the bootloader initialized the main oscillator correctly, + * there's no problem using the cycle counter. But if it didn't, + * or when using oscillator bypass mode, we must be told the speed + * of the main clock. + */ + if (!main_clock) { + do { + tmp = readl(&pmc->mcfr); + } while (!(tmp & AT91_PMC_MCFR_MAINRDY)); + tmp &= AT91_PMC_MCFR_MAINF_MASK; + main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16); + } +#endif + gd->arch.main_clk_rate_hz = main_clock; + + /* report if PLLA is more than mildly overclocked */ + gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar)); + +#ifdef CONFIG_USB_ATMEL + /* + * USB clock init: choose 48 MHz PLLB value, + * disable 48MHz clock during usb peripheral suspend. + * + * REVISIT: assumes MCK doesn't derive from PLLB! + */ + gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | + AT91_PMC_PLLBR_USBDIV_2; + gd->arch.pllb_rate_hz = at91_pll_rate(main_clock, + gd->arch.at91_pllb_usb_init); +#endif + + /* + * MCK and CPU derive from one of those primary clocks. + * For now, assume this parentage won't change. + */ + mckr = readl(&pmc->mckr); +#if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \ + || defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5) + /* plla divisor by 2 */ + gd->arch.plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12)); +#endif + gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); + freq = gd->arch.mck_rate_hz; + + freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */ +#if defined(CONFIG_AT91SAM9G20) + /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ + gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ? + freq / ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 7) : freq; + if (mckr & AT91_PMC_MCKR_MDIV_MASK) + freq /= 2; /* processor clock division */ +#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \ + || defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5) + /* mdiv <==> divisor + * 0 <==> 1 + * 1 <==> 2 + * 2 <==> 4 + * 3 <==> 3 + */ + gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) == + (AT91_PMC_MCKR_MDIV_2 | AT91_PMC_MCKR_MDIV_4) + ? freq / 3 + : freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); +#else + gd->arch.mck_rate_hz = freq / + (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); +#endif + gd->arch.cpu_clk_rate_hz = freq; + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/config.mk b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/config.mk new file mode 100644 index 000000000..370630d4d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/config.mk @@ -0,0 +1,2 @@ +PF_CPPFLAGS_TUNE := $(call cc-option,-mtune=arm926ejs,) +PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_TUNE) diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/cpu.c new file mode 100644 index 000000000..da1d35907 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/cpu.c @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2010 + * Reinhard Meyer, reinhard.meyer@emk-elektronik.de + * (C) Copyright 2009 + * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_pit.h> +#include <asm/arch/at91_gpbr.h> +#include <asm/arch/clk.h> + +#ifndef CONFIG_SYS_AT91_MAIN_CLOCK +#define CONFIG_SYS_AT91_MAIN_CLOCK 0 +#endif + +int arch_cpu_init(void) +{ + return at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); +} + +void arch_preboot_os(void) +{ + ulong cpiv; + at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT; + + cpiv = AT91_PIT_MR_PIV_MASK(readl(&pit->piir)); + + /* + * Disable PITC + * Add 0x1000 to current counter to stop it faster + * without waiting for wrapping back to 0 + */ + writel(cpiv + 0x1000, &pit->mr); +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + char buf[32]; + + printf("CPU: %s\n", ATMEL_CPU_NAME); + printf("Crystal frequency: %8s MHz\n", + strmhz(buf, get_main_clk_rate())); + printf("CPU clock : %8s MHz\n", + strmhz(buf, get_cpu_clk_rate())); + printf("Master clock : %8s MHz\n", + strmhz(buf, get_mck_clk_rate())); + + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/eflash.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/eflash.c new file mode 100644 index 000000000..3f3926428 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/eflash.c @@ -0,0 +1,254 @@ +/* + * (C) Copyright 2010 + * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * this driver supports the enhanced embedded flash in the Atmel + * AT91SAM9XE devices with the following geometry: + * + * AT91SAM9XE128: 1 plane of 8 regions of 32 pages (total 256 pages) + * AT91SAM9XE256: 1 plane of 16 regions of 32 pages (total 512 pages) + * AT91SAM9XE512: 1 plane of 32 regions of 32 pages (total 1024 pages) + * (the exact geometry is read from the flash at runtime, so any + * future devices should already be covered) + * + * Regions can be write/erase protected. + * Whole (!) pages can be individually written with erase on the fly. + * Writing partial pages will corrupt the rest of the page. + * + * The flash is presented to u-boot with each region being a sector, + * having the following effects: + * Each sector can be hardware protected (protect on/off). + * Each page in a sector can be rewritten anytime. + * Since pages are erased when written, the "erase" does nothing. + * The first "CONFIG_EFLASH_PROTSECTORS" cannot be unprotected + * by u-Boot commands. + * + * Note: Redundant environment will not work in this flash since + * it does use partial page writes. Make sure the environment spans + * whole pages! + */ + +/* + * optional TODOs (nice to have features): + * + * make the driver coexist with other NOR flash drivers + * (use an index into flash_info[], requires work + * in those other drivers, too) + * Make the erase command fill the sectors with 0xff + * (if the flashes grow larger in the future and + * someone puts a jffs2 into them) + * do a read-modify-write for partially programmed pages + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_eefc.h> +#include <asm/arch/at91_dbu.h> + +/* checks to detect configuration errors */ +#if CONFIG_SYS_MAX_FLASH_BANKS!=1 +#error eflash: this driver can only handle 1 bank +#endif + +/* global structure */ +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; +static u32 pagesize; + +unsigned long flash_init (void) +{ + at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC; + at91_dbu_t *dbu = (at91_dbu_t *) ATMEL_BASE_DBGU; + u32 id, size, nplanes, planesize, nlocks; + u32 addr, i, tmp=0; + + debug("eflash: init\n"); + + flash_info[0].flash_id = FLASH_UNKNOWN; + + /* check if its an AT91ARM9XE SoC */ + if ((readl(&dbu->cidr) & AT91_DBU_CID_ARCH_MASK) != AT91_DBU_CID_ARCH_9XExx) { + puts("eflash: not an AT91SAM9XE\n"); + return 0; + } + + /* now query the eflash for its structure */ + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GETD, &eefc->fcr); + while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0) + ; + id = readl(&eefc->frr); /* word 0 */ + size = readl(&eefc->frr); /* word 1 */ + pagesize = readl(&eefc->frr); /* word 2 */ + nplanes = readl(&eefc->frr); /* word 3 */ + planesize = readl(&eefc->frr); /* word 4 */ + debug("id=%08x size=%u pagesize=%u planes=%u planesize=%u\n", + id, size, pagesize, nplanes, planesize); + for (i=1; i<nplanes; i++) { + tmp = readl(&eefc->frr); /* words 5..4+nplanes-1 */ + }; + nlocks = readl(&eefc->frr); /* word 4+nplanes */ + debug("nlocks=%u\n", nlocks); + /* since we are going to use the lock regions as sectors, check count */ + if (nlocks > CONFIG_SYS_MAX_FLASH_SECT) { + printf("eflash: number of lock regions(%u) "\ + "> CONFIG_SYS_MAX_FLASH_SECT. reducing...\n", + nlocks); + nlocks = CONFIG_SYS_MAX_FLASH_SECT; + } + flash_info[0].size = size; + flash_info[0].sector_count = nlocks; + flash_info[0].flash_id = id; + + addr = ATMEL_BASE_FLASH; + for (i=0; i<nlocks; i++) { + tmp = readl(&eefc->frr); /* words 4+nplanes+1.. */ + flash_info[0].start[i] = addr; + flash_info[0].protect[i] = 0; + addr += tmp; + }; + + /* now read the protection information for all regions */ + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr); + while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0) + ; + for (i=0; i<flash_info[0].sector_count; i++) { + if (i%32 == 0) + tmp = readl(&eefc->frr); + flash_info[0].protect[i] = (tmp >> (i%32)) & 1; +#if defined(CONFIG_EFLASH_PROTSECTORS) + if (i < CONFIG_EFLASH_PROTSECTORS) + flash_info[0].protect[i] = 1; +#endif + } + + return size; +} + +void flash_print_info (flash_info_t *info) +{ + int i; + + puts("AT91SAM9XE embedded flash\n Size: "); + print_size(info->size, " in "); + printf("%d Sectors\n", info->sector_count); + + printf(" Sector Start Addresses:"); + for (i=0; i<info->sector_count; ++i) { + if ((i % 5) == 0) + printf("\n "); + printf(" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + +int flash_real_protect (flash_info_t *info, long sector, int prot) +{ + at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC; + u32 pagenum = (info->start[sector]-ATMEL_BASE_FLASH)/pagesize; + u32 i, tmp=0; + + debug("protect sector=%ld prot=%d\n", sector, prot); + +#if defined(CONFIG_EFLASH_PROTSECTORS) + if (sector < CONFIG_EFLASH_PROTSECTORS) { + if (!prot) { + printf("eflash: sector %lu cannot be unprotected\n", + sector); + } + return 1; /* return anyway, caller does not care for result */ + } +#endif + if (prot) { + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_SLB | + (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr); + } else { + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_CLB | + (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr); + } + while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0) + ; + /* now re-read the protection information for all regions */ + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr); + while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0) + ; + for (i=0; i<info->sector_count; i++) { + if (i%32 == 0) + tmp = readl(&eefc->frr); + info->protect[i] = (tmp >> (i%32)) & 1; + } + return 0; +} + +static u32 erase_write_page (u32 pagenum) +{ + at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC; + + debug("erase+write page=%u\n", pagenum); + + /* give erase and write page command */ + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_EWP | + (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr); + while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0) + ; + /* return status */ + return readl(&eefc->fsr) + & (AT91_EEFC_FSR_FCMDE | AT91_EEFC_FSR_FLOCKE); +} + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + debug("erase first=%d last=%d\n", s_first, s_last); + puts("this flash does not need and support erasing!\n"); + return 0; +} + +/* + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + u32 pagenum; + u32 *src32, *dst32; + u32 i; + + debug("write src=%08lx addr=%08lx cnt=%lx\n", + (ulong)src, addr, cnt); + + /* REQUIRE addr to be on a page start, abort if not */ + if (addr % pagesize) { + printf ("eflash: start %08lx is not on page start\n"\ + " write aborted\n", addr); + return 1; + } + + /* now start copying data */ + pagenum = (addr-ATMEL_BASE_FLASH)/pagesize; + src32 = (u32 *) src; + dst32 = (u32 *) addr; + while (cnt > 0) { + i = pagesize / 4; + /* fill page buffer */ + while (i--) + *dst32++ = *src32++; + /* write page */ + if (erase_write_page(pagenum)) + return 1; + pagenum++; + if (cnt > pagesize) + cnt -= pagesize; + else + cnt = 0; + } + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/led.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/led.c new file mode 100644 index 000000000..46ed05502 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/led.c @@ -0,0 +1,47 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/gpio.h> +#include <asm/arch/gpio.h> + +#ifdef CONFIG_RED_LED +void red_led_on(void) +{ + gpio_set_value(CONFIG_RED_LED, 1); +} + +void red_led_off(void) +{ + gpio_set_value(CONFIG_RED_LED, 0); +} +#endif + +#ifdef CONFIG_GREEN_LED +void green_led_on(void) +{ + gpio_set_value(CONFIG_GREEN_LED, 0); +} + +void green_led_off(void) +{ + gpio_set_value(CONFIG_GREEN_LED, 1); +} +#endif + +#ifdef CONFIG_YELLOW_LED +void yellow_led_on(void) +{ + gpio_set_value(CONFIG_YELLOW_LED, 0); +} + +void yellow_led_off(void) +{ + gpio_set_value(CONFIG_YELLOW_LED, 1); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/lowlevel_init.S new file mode 100644 index 000000000..a9ec81a75 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/lowlevel_init.S @@ -0,0 +1,246 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * Copyright (C) 2008 Ronetix Ilko Iliev (www.ronetix.at) + * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_wdt.h> +#include <asm/arch/at91_pio.h> +#include <asm/arch/at91_matrix.h> +#include <asm/arch/at91sam9_sdramc.h> +#include <asm/arch/at91sam9_smc.h> +#include <asm/arch/at91_rstc.h> +#ifdef CONFIG_ATMEL_LEGACY +#include <asm/arch/at91sam9_matrix.h> +#endif +#ifndef CONFIG_SYS_MATRIX_EBICSA_VAL +#define CONFIG_SYS_MATRIX_EBICSA_VAL CONFIG_SYS_MATRIX_EBI0CSA_VAL +#endif + +.globl lowlevel_init +.type lowlevel_init,function +lowlevel_init: + +POS1: + adr r5, POS1 /* r5 = POS1 run time */ + ldr r0, =POS1 /* r0 = POS1 compile */ + sub r5, r5, r0 /* r0 = CONFIG_SYS_TEXT_BASE-1 */ + + /* memory control configuration 1 */ + ldr r0, =SMRDATA + ldr r2, =SMRDATA1 + add r0, r0, r5 + add r2, r2, r5 +0: + /* the address */ + ldr r1, [r0], #4 + /* the value */ + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne 0b + +/* ---------------------------------------------------------------------------- + * PMC Init Step 1. + * ---------------------------------------------------------------------------- + * - Check if the PLL is already initialized + * ---------------------------------------------------------------------------- + */ + ldr r1, =(AT91_ASM_PMC_MCKR) + ldr r0, [r1] + and r0, r0, #3 + cmp r0, #0 + bne PLL_setup_end + +/* --------------------------------------------------------------------------- + * - Enable the Main Oscillator + * --------------------------------------------------------------------------- + */ + ldr r1, =(AT91_ASM_PMC_MOR) + ldr r2, =(AT91_ASM_PMC_SR) + /* Main oscillator Enable register PMC_MOR: */ + ldr r0, =CONFIG_SYS_MOR_VAL + str r0, [r1] + + /* Reading the PMC Status to detect when the Main Oscillator is enabled */ + mov r4, #AT91_PMC_IXR_MOSCS +MOSCS_Loop: + ldr r3, [r2] + and r3, r4, r3 + cmp r3, #AT91_PMC_IXR_MOSCS + bne MOSCS_Loop + +/* ---------------------------------------------------------------------------- + * PMC Init Step 2. + * ---------------------------------------------------------------------------- + * Setup PLLA + * ---------------------------------------------------------------------------- + */ + ldr r1, =(AT91_ASM_PMC_PLLAR) + ldr r0, =CONFIG_SYS_PLLAR_VAL + str r0, [r1] + + /* Reading the PMC Status register to detect when the PLLA is locked */ + mov r4, #AT91_PMC_IXR_LOCKA +MOSCS_Loop1: + ldr r3, [r2] + and r3, r4, r3 + cmp r3, #AT91_PMC_IXR_LOCKA + bne MOSCS_Loop1 + +/* ---------------------------------------------------------------------------- + * PMC Init Step 3. + * ---------------------------------------------------------------------------- + * - Switch on the Main Oscillator + * ---------------------------------------------------------------------------- + */ + ldr r1, =(AT91_ASM_PMC_MCKR) + + /* -Master Clock Controller register PMC_MCKR */ + ldr r0, =CONFIG_SYS_MCKR1_VAL + str r0, [r1] + + /* Reading the PMC Status to detect when the Master clock is ready */ + mov r4, #AT91_PMC_IXR_MCKRDY +MCKRDY_Loop: + ldr r3, [r2] + and r3, r4, r3 + cmp r3, #AT91_PMC_IXR_MCKRDY + bne MCKRDY_Loop + + ldr r0, =CONFIG_SYS_MCKR2_VAL + str r0, [r1] + + /* Reading the PMC Status to detect when the Master clock is ready */ + mov r4, #AT91_PMC_IXR_MCKRDY +MCKRDY_Loop1: + ldr r3, [r2] + and r3, r4, r3 + cmp r3, #AT91_PMC_IXR_MCKRDY + bne MCKRDY_Loop1 +PLL_setup_end: + +/* ---------------------------------------------------------------------------- + * - memory control configuration 2 + * ---------------------------------------------------------------------------- + */ + ldr r0, =(AT91_ASM_SDRAMC_TR) + ldr r1, [r0] + cmp r1, #0 + bne SDRAM_setup_end + + ldr r0, =SMRDATA1 + ldr r2, =SMRDATA2 + add r0, r0, r5 + add r2, r2, r5 +2: + /* the address */ + ldr r1, [r0], #4 + /* the value */ + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne 2b + +SDRAM_setup_end: + /* everything is fine now */ + mov pc, lr + + .ltorg + +SMRDATA: + .word AT91_ASM_WDT_MR + .word CONFIG_SYS_WDTC_WDMR_VAL + /* configure PIOx as EBI0 D[16-31] */ +#if defined(CONFIG_AT91SAM9263) + .word AT91_ASM_PIOD_PDR + .word CONFIG_SYS_PIOD_PDR_VAL1 + .word AT91_ASM_PIOD_PUDR + .word CONFIG_SYS_PIOD_PPUDR_VAL + .word AT91_ASM_PIOD_ASR + .word CONFIG_SYS_PIOD_PPUDR_VAL +#elif defined(CONFIG_AT91SAM9260) || defined(CONFIG_AT91SAM9261) \ + || defined(CONFIG_AT91SAM9G20) + .word AT91_ASM_PIOC_PDR + .word CONFIG_SYS_PIOC_PDR_VAL1 + .word AT91_ASM_PIOC_PUDR + .word CONFIG_SYS_PIOC_PPUDR_VAL +#endif + .word AT91_ASM_MATRIX_CSA0 + .word CONFIG_SYS_MATRIX_EBICSA_VAL + + /* flash */ + .word AT91_ASM_SMC_MODE0 + .word CONFIG_SYS_SMC0_MODE0_VAL + + .word AT91_ASM_SMC_CYCLE0 + .word CONFIG_SYS_SMC0_CYCLE0_VAL + + .word AT91_ASM_SMC_PULSE0 + .word CONFIG_SYS_SMC0_PULSE0_VAL + + .word AT91_ASM_SMC_SETUP0 + .word CONFIG_SYS_SMC0_SETUP0_VAL + +SMRDATA1: + .word AT91_ASM_SDRAMC_MR + .word CONFIG_SYS_SDRC_MR_VAL1 + .word AT91_ASM_SDRAMC_TR + .word CONFIG_SYS_SDRC_TR_VAL1 + .word AT91_ASM_SDRAMC_CR + .word CONFIG_SYS_SDRC_CR_VAL + .word AT91_ASM_SDRAMC_MDR + .word CONFIG_SYS_SDRC_MDR_VAL + .word AT91_ASM_SDRAMC_MR + .word CONFIG_SYS_SDRC_MR_VAL2 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL1 + .word AT91_ASM_SDRAMC_MR + .word CONFIG_SYS_SDRC_MR_VAL3 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL2 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL3 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL4 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL5 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL6 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL7 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL8 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL9 + .word AT91_ASM_SDRAMC_MR + .word CONFIG_SYS_SDRC_MR_VAL4 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL10 + .word AT91_ASM_SDRAMC_MR + .word CONFIG_SYS_SDRC_MR_VAL5 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL11 + .word AT91_ASM_SDRAMC_TR + .word CONFIG_SYS_SDRC_TR_VAL2 + .word CONFIG_SYS_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL12 + /* User reset enable*/ + .word AT91_ASM_RSTC_MR + .word CONFIG_SYS_RSTC_RMR_VAL +#ifdef CONFIG_SYS_MATRIX_MCFG_REMAP + /* MATRIX_MCFG - REMAP all masters */ + .word AT91_ASM_MATRIX_MCFG + .word 0x1FF +#endif +SMRDATA2: + .word 0 diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/reset.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/reset.c new file mode 100644 index 000000000..e67f47bd0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/reset.c @@ -0,0 +1,29 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_rstc.h> + +/* Reset the cpu by telling the reset controller to do so */ +void reset_cpu(ulong ignored) +{ + at91_rstc_t *rstc = (at91_rstc_t *) ATMEL_BASE_RSTC; + + writel(AT91_RSTC_KEY + | AT91_RSTC_CR_PROCRST /* Processor Reset */ + | AT91_RSTC_CR_PERRST /* Peripheral Reset */ +#ifdef CONFIG_AT91RESET_EXTRST + | AT91_RSTC_CR_EXTRST /* External Reset (assert nRST pin) */ +#endif + , &rstc->cr); + /* never reached */ + while (1) + ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/timer.c new file mode 100644 index 000000000..b0b7fb93f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/at91/timer.c @@ -0,0 +1,120 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pit.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/clk.h> +#include <div64.h> + +#if !defined(CONFIG_AT91FAMILY) +# error You need to define CONFIG_AT91FAMILY in your board config! +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/* + * We're using the AT91CAP9/SAM9 PITC in 32 bit mode, by + * setting the 20 bit counter period to its maximum (0xfffff). + * (See the relevant data sheets to understand that this really works) + * + * We do also mimic the typical powerpc way of incrementing + * two 32 bit registers called tbl and tbu. + * + * Those registers increment at 1/16 the main clock rate. + */ + +#define TIMER_LOAD_VAL 0xfffff + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, gd->arch.timer_rate_hz); + + return tick; +} + +static inline unsigned long long usec_to_tick(unsigned long long usec) +{ + usec *= gd->arch.timer_rate_hz; + do_div(usec, 1000000); + + return usec; +} + +/* + * Use the PITC in full 32 bit incrementing mode + */ +int timer_init(void) +{ + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; + at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT; + + /* Enable PITC Clock */ + writel(1 << ATMEL_ID_SYS, &pmc->pcer); + + /* Enable PITC */ + writel(TIMER_LOAD_VAL | AT91_PIT_MR_EN , &pit->mr); + + gd->arch.timer_rate_hz = gd->arch.mck_rate_hz / 16; + gd->arch.tbu = gd->arch.tbl = 0; + + return 0; +} + +/* + * Get the current 64 bit timer tick count + */ +unsigned long long get_ticks(void) +{ + at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT; + + ulong now = readl(&pit->piir); + + /* 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; +} + +void __udelay(unsigned long usec) +{ + unsigned long long start; + ulong tmo; + + start = get_ticks(); /* get current timestamp */ + tmo = usec_to_tick(usec); /* convert usecs to ticks */ + while ((get_ticks() - start) < tmo) + ; /* loop till time has passed */ +} + +/* + * get_timer(base) can be used to check for timeouts or + * to measure elasped time relative to an event: + * + * ulong start_time = get_timer(0) sets start_time to the current + * time value. + * get_timer(start_time) returns the time elapsed since then. + * + * The time is used in CONFIG_SYS_HZ units! + */ +ulong get_timer(ulong base) +{ + return tick_to_time(get_ticks()) - base; +} + +/* + * Return the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return gd->arch.timer_rate_hz; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/cache.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/cache.c new file mode 100644 index 000000000..e86c2edd3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/cache.c @@ -0,0 +1,105 @@ +/* + * (C) Copyright 2011 + * Ilya Yanok, EmCraft Systems + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <linux/types.h> +#include <common.h> + +#ifndef CONFIG_SYS_DCACHE_OFF + +#ifndef CONFIG_SYS_CACHELINE_SIZE +#define CONFIG_SYS_CACHELINE_SIZE 32 +#endif + +void invalidate_dcache_all(void) +{ + asm volatile("mcr p15, 0, %0, c7, c6, 0\n" : : "r"(0)); +} + +void flush_dcache_all(void) +{ + asm volatile( + "0:" + "mrc p15, 0, r15, c7, c14, 3\n" + "bne 0b\n" + "mcr p15, 0, %0, c7, c10, 4\n" + : : "r"(0) : "memory" + ); +} + +static int check_cache_range(unsigned long start, unsigned long stop) +{ + int ok = 1; + + if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (!ok) + debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", + start, stop); + + return ok; +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + if (!check_cache_range(start, stop)) + return; + + while (start < stop) { + asm volatile("mcr p15, 0, %0, c7, c6, 1\n" : : "r"(start)); + start += CONFIG_SYS_CACHELINE_SIZE; + } +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + if (!check_cache_range(start, stop)) + return; + + while (start < stop) { + asm volatile("mcr p15, 0, %0, c7, c14, 1\n" : : "r"(start)); + start += CONFIG_SYS_CACHELINE_SIZE; + } + + asm volatile("mcr p15, 0, %0, c7, c10, 4\n" : : "r"(0)); +} + +void flush_cache(unsigned long start, unsigned long size) +{ + flush_dcache_range(start, start + size); +} +#else /* #ifndef CONFIG_SYS_DCACHE_OFF */ +void invalidate_dcache_all(void) +{ +} + +void flush_dcache_all(void) +{ +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void flush_cache(unsigned long start, unsigned long size) +{ +} +#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ + +/* + * Stub implementations for l2 cache operations + */ +void __l2_cache_disable(void) {} + +void l2_cache_disable(void) + __attribute__((weak, alias("__l2_cache_disable"))); diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/config.mk b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/config.mk new file mode 100644 index 000000000..bdb3da183 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/config.mk @@ -0,0 +1,8 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +PLATFORM_CPPFLAGS += -march=armv5te diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/cpu.c new file mode 100644 index 000000000..e37e87b68 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/cpu.c @@ -0,0 +1,51 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +static void cache_flush(void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + disable_interrupts (); + + + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + l2_cache_disable(); + + /* flush I/D-cache */ + cache_flush(); + + return 0; +} + +/* flush I/D-cache */ +static void cache_flush (void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/Makefile new file mode 100644 index 000000000..7d67191de --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/Makefile @@ -0,0 +1,28 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += cpu.o misc.o timer.o psc.o pinmux.o reset.o +obj-$(CONFIG_DA850_LOWLEVEL) += da850_lowlevel.o +obj-$(CONFIG_SOC_DM355) += dm355.o +obj-$(CONFIG_SOC_DM365) += dm365.o +obj-$(CONFIG_SOC_DM644X) += dm644x.o +obj-$(CONFIG_SOC_DM646X) += dm646x.o +obj-$(CONFIG_SOC_DA830) += da830_pinmux.o +obj-$(CONFIG_SOC_DA850) += da850_pinmux.o +obj-$(CONFIG_DRIVER_TI_EMAC) += lxt972.o dp83848.o et1011c.o ksz8873.o + +ifdef CONFIG_SPL_BUILD +obj-$(CONFIG_SPL_FRAMEWORK) += spl.o +obj-$(CONFIG_SOC_DM365) += dm365_lowlevel.o +obj-$(CONFIG_SOC_DA8XX) += da850_lowlevel.o +endif + +ifndef CONFIG_SKIP_LOWLEVEL_INIT +obj-y += lowlevel_init.o +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/config.mk b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/config.mk new file mode 100644 index 000000000..69e9d5ab2 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/config.mk @@ -0,0 +1,8 @@ +# +# Copyright (C) 2012, Texas Instruments, Incorporated - http://www.ti.com/ +# +# SPDX-License-Identifier: GPL-2.0+ +# +ifndef CONFIG_SPL_BUILD +ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.ais +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/cpu.c new file mode 100644 index 000000000..ff6114775 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/cpu.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2004 Texas Instruments. + * Copyright (C) 2009 David Brownell + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <netdev.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* offsets from PLL controller base */ +#define PLLC_PLLCTL 0x100 +#define PLLC_PLLM 0x110 +#define PLLC_PREDIV 0x114 +#define PLLC_PLLDIV1 0x118 +#define PLLC_PLLDIV2 0x11c +#define PLLC_PLLDIV3 0x120 +#define PLLC_POSTDIV 0x128 +#define PLLC_BPDIV 0x12c +#define PLLC_PLLDIV4 0x160 +#define PLLC_PLLDIV5 0x164 +#define PLLC_PLLDIV6 0x168 +#define PLLC_PLLDIV7 0x16c +#define PLLC_PLLDIV8 0x170 +#define PLLC_PLLDIV9 0x174 + +#define BIT(x) (1 << (x)) + +/* SOC-specific pll info */ +#ifdef CONFIG_SOC_DM355 +#define ARM_PLLDIV PLLC_PLLDIV1 +#define DDR_PLLDIV PLLC_PLLDIV1 +#endif + +#ifdef CONFIG_SOC_DM644X +#define ARM_PLLDIV PLLC_PLLDIV2 +#define DSP_PLLDIV PLLC_PLLDIV1 +#define DDR_PLLDIV PLLC_PLLDIV2 +#endif + +#ifdef CONFIG_SOC_DM646X +#define DSP_PLLDIV PLLC_PLLDIV1 +#define ARM_PLLDIV PLLC_PLLDIV2 +#define DDR_PLLDIV PLLC_PLLDIV1 +#endif + +#ifdef CONFIG_SOC_DA8XX +unsigned int sysdiv[9] = { + PLLC_PLLDIV1, PLLC_PLLDIV2, PLLC_PLLDIV3, PLLC_PLLDIV4, PLLC_PLLDIV5, + PLLC_PLLDIV6, PLLC_PLLDIV7, PLLC_PLLDIV8, PLLC_PLLDIV9 +}; + +int clk_get(enum davinci_clk_ids id) +{ + int pre_div; + int pllm; + int post_div; + int pll_out; + unsigned int pll_base; + + pll_out = CONFIG_SYS_OSCIN_FREQ; + + if (id == DAVINCI_AUXCLK_CLKID) + goto out; + + if ((id >> 16) == 1) + pll_base = (unsigned int)davinci_pllc1_regs; + else + pll_base = (unsigned int)davinci_pllc0_regs; + + id &= 0xFFFF; + + /* + * Lets keep this simple. Combining operations can result in + * unexpected approximations + */ + pre_div = (readl(pll_base + PLLC_PREDIV) & + DAVINCI_PLLC_DIV_MASK) + 1; + pllm = readl(pll_base + PLLC_PLLM) + 1; + + pll_out /= pre_div; + pll_out *= pllm; + + if (id == DAVINCI_PLLM_CLKID) + goto out; + + post_div = (readl(pll_base + PLLC_POSTDIV) & + DAVINCI_PLLC_DIV_MASK) + 1; + + pll_out /= post_div; + + if (id == DAVINCI_PLLC_CLKID) + goto out; + + pll_out /= (readl(pll_base + sysdiv[id - 1]) & + DAVINCI_PLLC_DIV_MASK) + 1; + +out: + return pll_out; +} + +int set_cpu_clk_info(void) +{ + gd->bd->bi_arm_freq = clk_get(DAVINCI_ARM_CLKID) / 1000000; + /* DDR PHY uses an x2 input clock */ + gd->bd->bi_ddr_freq = cpu_is_da830() ? 0 : + (clk_get(DAVINCI_DDR_CLKID) / 1000000); + gd->bd->bi_dsp_freq = 0; + return 0; +} + +#else /* CONFIG_SOC_DA8XX */ + +static unsigned pll_div(volatile void *pllbase, unsigned offset) +{ + u32 div; + + div = REG(pllbase + offset); + return (div & BIT(15)) ? (1 + (div & 0x1f)) : 1; +} + +static inline unsigned pll_prediv(volatile void *pllbase) +{ +#ifdef CONFIG_SOC_DM355 + /* this register read seems to fail on pll0 */ + if (pllbase == (volatile void *)DAVINCI_PLL_CNTRL0_BASE) + return 8; + else + return pll_div(pllbase, PLLC_PREDIV); +#elif defined(CONFIG_SOC_DM365) + return pll_div(pllbase, PLLC_PREDIV); +#endif + return 1; +} + +static inline unsigned pll_postdiv(volatile void *pllbase) +{ +#if defined(CONFIG_SOC_DM355) || defined(CONFIG_SOC_DM365) + return pll_div(pllbase, PLLC_POSTDIV); +#elif defined(CONFIG_SOC_DM6446) + if (pllbase == (volatile void *)DAVINCI_PLL_CNTRL0_BASE) + return pll_div(pllbase, PLLC_POSTDIV); +#endif + return 1; +} + +static unsigned pll_sysclk_mhz(unsigned pll_addr, unsigned div) +{ + volatile void *pllbase = (volatile void *) pll_addr; +#ifdef CONFIG_SOC_DM646X + unsigned base = CONFIG_REFCLK_FREQ / 1000; +#else + unsigned base = CONFIG_SYS_HZ_CLOCK / 1000; +#endif + + /* the PLL might be bypassed */ + if (readl(pllbase + PLLC_PLLCTL) & BIT(0)) { + base /= pll_prediv(pllbase); +#if defined(CONFIG_SOC_DM365) + base *= 2 * (readl(pllbase + PLLC_PLLM) & 0x0ff); +#else + base *= 1 + (REG(pllbase + PLLC_PLLM) & 0x0ff); +#endif + base /= pll_postdiv(pllbase); + } + return DIV_ROUND_UP(base, 1000 * pll_div(pllbase, div)); +} + +#ifdef DAVINCI_DM6467EVM +unsigned int davinci_arm_clk_get() +{ + return pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, ARM_PLLDIV) * 1000000; +} +#endif + +#if defined(CONFIG_SOC_DM365) +unsigned int davinci_clk_get(unsigned int div) +{ + return pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, div) * 1000000; +} +#endif + +int set_cpu_clk_info(void) +{ + unsigned int pllbase = DAVINCI_PLL_CNTRL0_BASE; +#if defined(CONFIG_SOC_DM365) + pllbase = DAVINCI_PLL_CNTRL1_BASE; +#endif + gd->bd->bi_arm_freq = pll_sysclk_mhz(pllbase, ARM_PLLDIV); + +#ifdef DSP_PLLDIV + gd->bd->bi_dsp_freq = + pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, DSP_PLLDIV); +#else + gd->bd->bi_dsp_freq = 0; +#endif + + pllbase = DAVINCI_PLL_CNTRL1_BASE; +#if defined(CONFIG_SOC_DM365) + pllbase = DAVINCI_PLL_CNTRL0_BASE; +#endif + gd->bd->bi_ddr_freq = pll_sysclk_mhz(pllbase, DDR_PLLDIV) / 2; + + return 0; +} + +#endif /* !CONFIG_SOC_DA8XX */ + +/* + * Initializes on-chip ethernet controllers. + * to override, implement board_eth_init() + */ +int cpu_eth_init(bd_t *bis) +{ +#if defined(CONFIG_DRIVER_TI_EMAC) + davinci_emac_initialize(); +#endif + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/da830_pinmux.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/da830_pinmux.c new file mode 100644 index 000000000..edaab4532 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/da830_pinmux.c @@ -0,0 +1,139 @@ +/* + * Pinmux configurations for the DA830 SoCs + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/davinci_misc.h> +#include <asm/arch/hardware.h> +#include <asm/arch/pinmux_defs.h> + +/* SPI0 pin muxer settings */ +const struct pinmux_config spi0_pins_base[] = { + { pinmux(7), 1, 3 }, /* SPI0_SOMI */ + { pinmux(7), 1, 4 }, /* SPI0_SIMO */ + { pinmux(7), 1, 6 } /* SPI0_CLK */ +}; + +const struct pinmux_config spi0_pins_scs0[] = { + { pinmux(7), 1, 7 } /* SPI0_SCS[0] */ +}; + +const struct pinmux_config spi0_pins_ena[] = { + { pinmux(7), 1, 5 } /* SPI0_ENA */ +}; + +/* NAND pin muxer settings */ +const struct pinmux_config emifa_pins_cs0[] = { + { pinmux(18), 1, 2 } /* EMA_CS[0] */ +}; + +const struct pinmux_config emifa_pins_cs2[] = { + { pinmux(18), 1, 3 } /* EMA_CS[2] */ +}; + +const struct pinmux_config emifa_pins_cs3[] = { + { pinmux(18), 1, 4 } /* EMA_CS[3] */ +}; + +#ifdef CONFIG_USE_NAND +const struct pinmux_config emifa_pins[] = { + { pinmux(13), 1, 6 }, /* EMA_D[0] */ + { pinmux(13), 1, 7 }, /* EMA_D[1] */ + { pinmux(14), 1, 0 }, /* EMA_D[2] */ + { pinmux(14), 1, 1 }, /* EMA_D[3] */ + { pinmux(14), 1, 2 }, /* EMA_D[4] */ + { pinmux(14), 1, 3 }, /* EMA_D[5] */ + { pinmux(14), 1, 4 }, /* EMA_D[6] */ + { pinmux(14), 1, 5 }, /* EMA_D[7] */ + { pinmux(14), 1, 6 }, /* EMA_D[8] */ + { pinmux(14), 1, 7 }, /* EMA_D[9] */ + { pinmux(15), 1, 0 }, /* EMA_D[10] */ + { pinmux(15), 1, 1 }, /* EMA_D[11] */ + { pinmux(15), 1, 2 }, /* EMA_D[12] */ + { pinmux(15), 1, 3 }, /* EMA_D[13] */ + { pinmux(15), 1, 4 }, /* EMA_D[14] */ + { pinmux(15), 1, 5 }, /* EMA_D[15] */ + { pinmux(15), 1, 6 }, /* EMA_A[0] */ + { pinmux(15), 1, 7 }, /* EMA_A[1] */ + { pinmux(16), 1, 0 }, /* EMA_A[2] */ + { pinmux(16), 1, 1 }, /* EMA_A[3] */ + { pinmux(16), 1, 2 }, /* EMA_A[4] */ + { pinmux(16), 1, 3 }, /* EMA_A[5] */ + { pinmux(16), 1, 4 }, /* EMA_A[6] */ + { pinmux(16), 1, 5 }, /* EMA_A[7] */ + { pinmux(16), 1, 6 }, /* EMA_A[8] */ + { pinmux(16), 1, 7 }, /* EMA_A[9] */ + { pinmux(17), 1, 0 }, /* EMA_A[10] */ + { pinmux(17), 1, 1 }, /* EMA_A[11] */ + { pinmux(17), 1, 2 }, /* EMA_A[12] */ + { pinmux(17), 1, 3 }, /* EMA_BA[1] */ + { pinmux(17), 1, 4 }, /* EMA_BA[0] */ + { pinmux(17), 1, 5 }, /* EMA_CLK */ + { pinmux(17), 1, 6 }, /* EMA_SDCKE */ + { pinmux(17), 1, 7 }, /* EMA_CAS */ + { pinmux(18), 1, 0 }, /* EMA_CAS */ + { pinmux(18), 1, 1 }, /* EMA_WE */ + { pinmux(18), 1, 5 }, /* EMA_OE */ + { pinmux(18), 1, 6 }, /* EMA_WE_DQM[1] */ + { pinmux(18), 1, 7 }, /* EMA_WE_DQM[0] */ + { pinmux(10), 1, 0 } /* Tristate */ +}; +#endif + +/* EMAC PHY interface pins */ +const struct pinmux_config emac_pins_rmii[] = { + { pinmux(10), 2, 1 }, /* RMII_TXD[0] */ + { pinmux(10), 2, 2 }, /* RMII_TXD[1] */ + { pinmux(10), 2, 3 }, /* RMII_TXEN */ + { pinmux(10), 2, 4 }, /* RMII_CRS_DV */ + { pinmux(10), 2, 5 }, /* RMII_RXD[0] */ + { pinmux(10), 2, 6 }, /* RMII_RXD[1] */ + { pinmux(10), 2, 7 } /* RMII_RXER */ +}; + +const struct pinmux_config emac_pins_mdio[] = { + { pinmux(11), 2, 0 }, /* MDIO_CLK */ + { pinmux(11), 2, 1 } /* MDIO_D */ +}; + +const struct pinmux_config emac_pins_rmii_clk_source[] = { + { pinmux(9), 0, 5 } /* ref.clk from external source */ +}; + +/* UART2 pin muxer settings */ +const struct pinmux_config uart2_pins_txrx[] = { + { pinmux(8), 2, 7 }, /* UART2_RXD */ + { pinmux(9), 2, 0 } /* UART2_TXD */ +}; + +/* I2C0 pin muxer settings */ +const struct pinmux_config i2c0_pins[] = { + { pinmux(8), 2, 3 }, /* I2C0_SDA */ + { pinmux(8), 2, 4 } /* I2C0_SCL */ +}; + +/* USB0_DRVVBUS pin muxer settings */ +const struct pinmux_config usb_pins[] = { + { pinmux(9), 1, 1 } /* USB0_DRVVBUS */ +}; + +#ifdef CONFIG_DAVINCI_MMC +/* MMC0 pin muxer settings */ +const struct pinmux_config mmc0_pins_8bit[] = { + { pinmux(15), 2, 7 }, /* MMCSD0_CLK */ + { pinmux(16), 2, 0 }, /* MMCSD0_CMD */ + { pinmux(13), 2, 6 }, /* MMCSD0_DAT_0 */ + { pinmux(13), 2, 7 }, /* MMCSD0_DAT_1 */ + { pinmux(14), 2, 0 }, /* MMCSD0_DAT_2 */ + { pinmux(14), 2, 1 }, /* MMCSD0_DAT_3 */ + { pinmux(14), 2, 2 }, /* MMCSD0_DAT_4 */ + { pinmux(14), 2, 3 }, /* MMCSD0_DAT_5 */ + { pinmux(14), 2, 4 }, /* MMCSD0_DAT_6 */ + { pinmux(14), 2, 5 } /* MMCSD0_DAT_7 */ + /* DA830 supports 8-bit mode */ +}; +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c new file mode 100644 index 000000000..b91e948ce --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c @@ -0,0 +1,313 @@ +/* + * SoC-specific lowlevel code for DA850 + * + * Copyright (C) 2011 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <nand.h> +#include <ns16550.h> +#include <post.h> +#include <asm/arch/da850_lowlevel.h> +#include <asm/arch/hardware.h> +#include <asm/arch/davinci_misc.h> +#include <asm/arch/ddr2_defs.h> +#include <asm/arch/emif_defs.h> +#include <asm/arch/pll_defs.h> + +void davinci_enable_uart0(void) +{ + lpsc_on(DAVINCI_LPSC_UART0); + + /* Bringup UART0 out of reset */ + REG(UART0_PWREMU_MGMT) = 0x00006001; +} + +#if defined(CONFIG_SYS_DA850_PLL_INIT) +static void da850_waitloop(unsigned long loopcnt) +{ + unsigned long i; + + for (i = 0; i < loopcnt; i++) + asm(" NOP"); +} + +static int da850_pll_init(struct davinci_pllc_regs *reg, unsigned long pllmult) +{ + if (reg == davinci_pllc0_regs) + /* Unlock PLL registers. */ + clrbits_le32(&davinci_syscfg_regs->cfgchip0, PLL_MASTER_LOCK); + + /* + * Set PLLENSRC '0',bit 5, PLL Enable(PLLEN) selection is controlled + * through MMR + */ + clrbits_le32(®->pllctl, PLLCTL_PLLENSRC); + /* PLLCTL.EXTCLKSRC bit 9 should be left at 0 for Freon */ + clrbits_le32(®->pllctl, PLLCTL_EXTCLKSRC); + + /* Set PLLEN=0 => PLL BYPASS MODE */ + clrbits_le32(®->pllctl, PLLCTL_PLLEN); + + da850_waitloop(150); + + if (reg == davinci_pllc0_regs) { + /* + * Select the Clock Mode bit 8 as External Clock or On Chip + * Oscilator + */ + dv_maskbits(®->pllctl, ~PLLCTL_RES_9); + setbits_le32(®->pllctl, + (CONFIG_SYS_DV_CLKMODE << PLLCTL_CLOCK_MODE_SHIFT)); + } + + /* Clear PLLRST bit to reset the PLL */ + clrbits_le32(®->pllctl, PLLCTL_PLLRST); + + /* Disable the PLL output */ + setbits_le32(®->pllctl, PLLCTL_PLLDIS); + + /* PLL initialization sequence */ + /* + * Power up the PLL- PWRDN bit set to 0 to bring the PLL out of + * power down bit + */ + clrbits_le32(®->pllctl, PLLCTL_PLLPWRDN); + + /* Enable the PLL from Disable Mode PLLDIS bit to 0 */ + clrbits_le32(®->pllctl, PLLCTL_PLLDIS); + +#if defined(CONFIG_SYS_DA850_PLL0_PREDIV) + /* program the prediv */ + if (reg == davinci_pllc0_regs && CONFIG_SYS_DA850_PLL0_PREDIV) + writel((PLL_DIVEN | CONFIG_SYS_DA850_PLL0_PREDIV), + ®->prediv); +#endif + + /* Program the required multiplier value in PLLM */ + writel(pllmult, ®->pllm); + + /* program the postdiv */ + if (reg == davinci_pllc0_regs) + writel((PLL_POSTDEN | CONFIG_SYS_DA850_PLL0_POSTDIV), + ®->postdiv); + else + writel((PLL_POSTDEN | CONFIG_SYS_DA850_PLL1_POSTDIV), + ®->postdiv); + + /* + * Check for the GOSTAT bit in PLLSTAT to clear to 0 to indicate that + * no GO operation is currently in progress + */ + while ((readl(®->pllstat) & PLLCMD_GOSTAT) == PLLCMD_GOSTAT) + ; + + if (reg == davinci_pllc0_regs) { + writel(CONFIG_SYS_DA850_PLL0_PLLDIV1, ®->plldiv1); + writel(CONFIG_SYS_DA850_PLL0_PLLDIV2, ®->plldiv2); + writel(CONFIG_SYS_DA850_PLL0_PLLDIV3, ®->plldiv3); + writel(CONFIG_SYS_DA850_PLL0_PLLDIV4, ®->plldiv4); + writel(CONFIG_SYS_DA850_PLL0_PLLDIV5, ®->plldiv5); + writel(CONFIG_SYS_DA850_PLL0_PLLDIV6, ®->plldiv6); + writel(CONFIG_SYS_DA850_PLL0_PLLDIV7, ®->plldiv7); + } else { + writel(CONFIG_SYS_DA850_PLL1_PLLDIV1, ®->plldiv1); + writel(CONFIG_SYS_DA850_PLL1_PLLDIV2, ®->plldiv2); + writel(CONFIG_SYS_DA850_PLL1_PLLDIV3, ®->plldiv3); + } + + /* + * Set the GOSET bit in PLLCMD to 1 to initiate a new divider + * transition. + */ + setbits_le32(®->pllcmd, PLLCMD_GOSTAT); + + /* + * Wait for the GOSTAT bit in PLLSTAT to clear to 0 + * (completion of phase alignment). + */ + while ((readl(®->pllstat) & PLLCMD_GOSTAT) == PLLCMD_GOSTAT) + ; + + /* Wait for PLL to reset properly. See PLL spec for PLL reset time */ + da850_waitloop(200); + + /* Set the PLLRST bit in PLLCTL to 1 to bring the PLL out of reset */ + setbits_le32(®->pllctl, PLLCTL_PLLRST); + + /* Wait for PLL to lock. See PLL spec for PLL lock time */ + da850_waitloop(2400); + + /* + * Set the PLLEN bit in PLLCTL to 1 to remove the PLL from bypass + * mode + */ + setbits_le32(®->pllctl, PLLCTL_PLLEN); + + + /* + * clear EMIFA and EMIFB clock source settings, let them + * run off SYSCLK + */ + if (reg == davinci_pllc0_regs) + dv_maskbits(&davinci_syscfg_regs->cfgchip3, + ~(PLL_SCSCFG3_DIV45PENA | PLL_SCSCFG3_EMA_CLKSRC)); + + return 0; +} +#endif /* CONFIG_SYS_DA850_PLL_INIT */ + +#if defined(CONFIG_SYS_DA850_DDR_INIT) +static int da850_ddr_setup(void) +{ + unsigned long tmp; + + /* Enable the Clock to DDR2/mDDR */ + lpsc_on(DAVINCI_LPSC_DDR_EMIF); + + tmp = readl(&davinci_syscfg1_regs->vtpio_ctl); + if ((tmp & VTP_POWERDWN) == VTP_POWERDWN) { + /* Begin VTP Calibration */ + clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN); + clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK); + setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ); + clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ); + setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ); + + /* Polling READY bit to see when VTP calibration is done */ + tmp = readl(&davinci_syscfg1_regs->vtpio_ctl); + while ((tmp & VTP_READY) != VTP_READY) + tmp = readl(&davinci_syscfg1_regs->vtpio_ctl); + + setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK); + setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN); + } + setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_IOPWRDWN); + writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr); + + if (CONFIG_SYS_DA850_DDR2_SDBCR & (1 << DV_DDR_SDCR_DDR2EN_SHIFT)) { + /* DDR2 */ + clrbits_le32(&davinci_syscfg1_regs->ddr_slew, + (1 << DDR_SLEW_DDR_PDENA_BIT) | + (1 << DDR_SLEW_CMOSEN_BIT)); + } else { + /* MOBILE DDR */ + setbits_le32(&davinci_syscfg1_regs->ddr_slew, + (1 << DDR_SLEW_DDR_PDENA_BIT) | + (1 << DDR_SLEW_CMOSEN_BIT)); + } + + /* + * SDRAM Configuration Register (SDCR): + * First set the BOOTUNLOCK bit to make configuration bits + * writeable. + */ + setbits_le32(&dv_ddr2_regs_ctrl->sdbcr, DV_DDR_BOOTUNLOCK); + + /* + * Write the new value of these bits and clear BOOTUNLOCK. + * At the same time, set the TIMUNLOCK bit to allow changing + * the timing registers + */ + tmp = CONFIG_SYS_DA850_DDR2_SDBCR; + tmp &= ~DV_DDR_BOOTUNLOCK; + tmp |= DV_DDR_TIMUNLOCK; + writel(tmp, &dv_ddr2_regs_ctrl->sdbcr); + + /* write memory configuration and timing */ + if (!(CONFIG_SYS_DA850_DDR2_SDBCR & (1 << DV_DDR_SDCR_DDR2EN_SHIFT))) { + /* MOBILE DDR only*/ + writel(CONFIG_SYS_DA850_DDR2_SDBCR2, + &dv_ddr2_regs_ctrl->sdbcr2); + } + writel(CONFIG_SYS_DA850_DDR2_SDTIMR, &dv_ddr2_regs_ctrl->sdtimr); + writel(CONFIG_SYS_DA850_DDR2_SDTIMR2, &dv_ddr2_regs_ctrl->sdtimr2); + + /* clear the TIMUNLOCK bit and write the value of the CL field */ + tmp &= ~DV_DDR_TIMUNLOCK; + writel(tmp, &dv_ddr2_regs_ctrl->sdbcr); + + /* + * LPMODEN and MCLKSTOPEN must be set! + * Without this bits set, PSC don;t switch states !! + */ + writel(CONFIG_SYS_DA850_DDR2_SDRCR | + (1 << DV_DDR_SRCR_LPMODEN_SHIFT) | + (1 << DV_DDR_SRCR_MCLKSTOPEN_SHIFT), + &dv_ddr2_regs_ctrl->sdrcr); + + /* SyncReset the Clock to EMIF3A SDRAM */ + lpsc_syncreset(DAVINCI_LPSC_DDR_EMIF); + /* Enable the Clock to EMIF3A SDRAM */ + lpsc_on(DAVINCI_LPSC_DDR_EMIF); + + /* disable self refresh */ + clrbits_le32(&dv_ddr2_regs_ctrl->sdrcr, + DV_DDR_SDRCR_LPMODEN | DV_DDR_SDRCR_MCLKSTOPEN); + writel(CONFIG_SYS_DA850_DDR2_PBBPR, &dv_ddr2_regs_ctrl->pbbpr); + + return 0; +} +#endif /* CONFIG_SYS_DA850_DDR_INIT */ + +__attribute__((weak)) +void board_gpio_init(void) +{ + return; +} + +int arch_cpu_init(void) +{ + /* Unlock kick registers */ + writel(DV_SYSCFG_KICK0_UNLOCK, &davinci_syscfg_regs->kick0); + writel(DV_SYSCFG_KICK1_UNLOCK, &davinci_syscfg_regs->kick1); + + dv_maskbits(&davinci_syscfg_regs->suspsrc, + CONFIG_SYS_DA850_SYSCFG_SUSPSRC); + + /* configure pinmux settings */ + if (davinci_configure_pin_mux_items(pinmuxes, pinmuxes_size)) + return 1; + +#if defined(CONFIG_SYS_DA850_PLL_INIT) + /* PLL setup */ + da850_pll_init(davinci_pllc0_regs, CONFIG_SYS_DA850_PLL0_PLLM); + da850_pll_init(davinci_pllc1_regs, CONFIG_SYS_DA850_PLL1_PLLM); +#endif + /* setup CSn config */ +#if defined(CONFIG_SYS_DA850_CS2CFG) + writel(CONFIG_SYS_DA850_CS2CFG, &davinci_emif_regs->ab1cr); +#endif +#if defined(CONFIG_SYS_DA850_CS3CFG) + writel(CONFIG_SYS_DA850_CS3CFG, &davinci_emif_regs->ab2cr); +#endif + + da8xx_configure_lpsc_items(lpsc, lpsc_size); + + /* GPIO setup */ + board_gpio_init(); + + + NS16550_init((NS16550_t)(CONFIG_SYS_NS16550_COM1), + CONFIG_SYS_NS16550_CLK / 16 / CONFIG_BAUDRATE); + + /* + * Fix Power and Emulation Management Register + * see sprufw3a.pdf page 37 Table 24 + */ + writel((DAVINCI_UART_PWREMU_MGMT_FREE | DAVINCI_UART_PWREMU_MGMT_URRST | + DAVINCI_UART_PWREMU_MGMT_UTRST), +#if (CONFIG_SYS_NS16550_COM1 == DAVINCI_UART0_BASE) + &davinci_uart0_ctrl_regs->pwremu_mgmt); +#else + &davinci_uart2_ctrl_regs->pwremu_mgmt); +#endif + +#if defined(CONFIG_SYS_DA850_DDR_INIT) + da850_ddr_setup(); +#endif + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/da850_pinmux.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/da850_pinmux.c new file mode 100644 index 000000000..6105f6390 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/da850_pinmux.c @@ -0,0 +1,181 @@ +/* + * Pinmux configurations for the DA850 SoCs + * + * Copyright (C) 2011 OMICRON electronics GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/davinci_misc.h> +#include <asm/arch/hardware.h> +#include <asm/arch/pinmux_defs.h> + +/* SPI pin muxer settings */ +const struct pinmux_config spi1_pins_base[] = { + { pinmux(5), 1, 2 }, /* SPI1_CLK */ + { pinmux(5), 1, 4 }, /* SPI1_SOMI */ + { pinmux(5), 1, 5 }, /* SPI1_SIMO */ +}; + +const struct pinmux_config spi1_pins_scs0[] = { + { pinmux(5), 1, 1 }, /* SPI1_SCS[0] */ +}; + +/* UART pin muxer settings */ +const struct pinmux_config uart0_pins_txrx[] = { + { pinmux(3), 2, 4 }, /* UART0_RXD */ + { pinmux(3), 2, 5 }, /* UART0_TXD */ +}; + +const struct pinmux_config uart0_pins_rtscts[] = { + { pinmux(3), 2, 6 }, + { pinmux(3), 2, 7 }, +}; + +const struct pinmux_config uart1_pins_txrx[] = { + { pinmux(4), 2, 6 }, /* UART1_RXD */ + { pinmux(4), 2, 7 }, /* UART1_TXD */ +}; + +const struct pinmux_config uart2_pins_txrx[] = { + { pinmux(4), 2, 4 }, /* UART2_RXD */ + { pinmux(4), 2, 5 }, /* UART2_TXD */ +}; + +const struct pinmux_config uart2_pins_rtscts[] = { + { pinmux(0), 4, 6 }, /* UART2_RTS */ + { pinmux(0), 4, 7 }, /* UART2_CTS */ +}; + +/* EMAC pin muxer settings*/ +const struct pinmux_config emac_pins_rmii[] = { + { pinmux(14), 8, 2 }, /* RMII_TXD[1] */ + { pinmux(14), 8, 3 }, /* RMII_TXD[0] */ + { pinmux(14), 8, 4 }, /* RMII_TXEN */ + { pinmux(14), 8, 5 }, /* RMII_RXD[1] */ + { pinmux(14), 8, 6 }, /* RMII_RXD[0] */ + { pinmux(14), 8, 7 }, /* RMII_RXER */ + { pinmux(15), 0, 0 }, /* RMII_MHz_50_CLK */ + { pinmux(15), 8, 1 }, /* RMII_CRS_DV */ +}; + +const struct pinmux_config emac_pins_mii[] = { + { pinmux(2), 8, 1 }, /* MII_TXEN */ + { pinmux(2), 8, 2 }, /* MII_TXCLK */ + { pinmux(2), 8, 3 }, /* MII_COL */ + { pinmux(2), 8, 4 }, /* MII_TXD[3] */ + { pinmux(2), 8, 5 }, /* MII_TXD[2] */ + { pinmux(2), 8, 6 }, /* MII_TXD[1] */ + { pinmux(2), 8, 7 }, /* MII_TXD[0] */ + { pinmux(3), 8, 0 }, /* MII_RXCLK */ + { pinmux(3), 8, 1 }, /* MII_RXDV */ + { pinmux(3), 8, 2 }, /* MII_RXER */ + { pinmux(3), 8, 3 }, /* MII_CRS */ + { pinmux(3), 8, 4 }, /* MII_RXD[3] */ + { pinmux(3), 8, 5 }, /* MII_RXD[2] */ + { pinmux(3), 8, 6 }, /* MII_RXD[1] */ + { pinmux(3), 8, 7 }, /* MII_RXD[0] */ +}; + +const struct pinmux_config emac_pins_mdio[] = { + { pinmux(4), 8, 0 }, /* MDIO_CLK */ + { pinmux(4), 8, 1 }, /* MDIO_D */ +}; + +/* I2C pin muxer settings */ +const struct pinmux_config i2c0_pins[] = { + { pinmux(4), 2, 2 }, /* I2C0_SCL */ + { pinmux(4), 2, 3 }, /* I2C0_SDA */ +}; + +const struct pinmux_config i2c1_pins[] = { + { pinmux(4), 4, 4 }, /* I2C1_SCL */ + { pinmux(4), 4, 5 }, /* I2C1_SDA */ +}; + +/* EMIFA pin muxer settings */ +const struct pinmux_config emifa_pins_cs2[] = { + { pinmux(7), 1, 0 }, /* EMA_CS2 */ +}; + +const struct pinmux_config emifa_pins_cs3[] = { + { pinmux(7), 1, 1 }, /* EMA_CS[3] */ +}; + +const struct pinmux_config emifa_pins_cs4[] = { + { pinmux(7), 1, 2 }, /* EMA_CS[4] */ +}; + +const struct pinmux_config emifa_pins_nand[] = { + { pinmux(7), 1, 4 }, /* EMA_WE */ + { pinmux(7), 1, 5 }, /* EMA_OE */ + { pinmux(9), 1, 0 }, /* EMA_D[7] */ + { pinmux(9), 1, 1 }, /* EMA_D[6] */ + { pinmux(9), 1, 2 }, /* EMA_D[5] */ + { pinmux(9), 1, 3 }, /* EMA_D[4] */ + { pinmux(9), 1, 4 }, /* EMA_D[3] */ + { pinmux(9), 1, 5 }, /* EMA_D[2] */ + { pinmux(9), 1, 6 }, /* EMA_D[1] */ + { pinmux(9), 1, 7 }, /* EMA_D[0] */ + { pinmux(12), 1, 5 }, /* EMA_A[2] */ + { pinmux(12), 1, 6 }, /* EMA_A[1] */ +}; + +/* NOR pin muxer settings */ +const struct pinmux_config emifa_pins_nor[] = { + { pinmux(5), 1, 6 }, /* EMA_BA[1] */ + { pinmux(6), 1, 6 }, /* EMA_WAIT[1] */ + { pinmux(7), 1, 4 }, /* EMA_WE */ + { pinmux(7), 1, 5 }, /* EMA_OE */ + { pinmux(8), 1, 0 }, /* EMA_D[15] */ + { pinmux(8), 1, 1 }, /* EMA_D[14] */ + { pinmux(8), 1, 2 }, /* EMA_D[13] */ + { pinmux(8), 1, 3 }, /* EMA_D[12] */ + { pinmux(8), 1, 4 }, /* EMA_D[11] */ + { pinmux(8), 1, 5 }, /* EMA_D[10] */ + { pinmux(8), 1, 6 }, /* EMA_D[9] */ + { pinmux(8), 1, 7 }, /* EMA_D[8] */ + { pinmux(9), 1, 0 }, /* EMA_D[7] */ + { pinmux(9), 1, 1 }, /* EMA_D[6] */ + { pinmux(9), 1, 2 }, /* EMA_D[5] */ + { pinmux(9), 1, 3 }, /* EMA_D[4] */ + { pinmux(9), 1, 4 }, /* EMA_D[3] */ + { pinmux(9), 1, 5 }, /* EMA_D[2] */ + { pinmux(9), 1, 6 }, /* EMA_D[1] */ + { pinmux(9), 1, 7 }, /* EMA_D[0] */ + { pinmux(10), 1, 1 }, /* EMA_A[22] */ + { pinmux(10), 1, 2 }, /* EMA_A[21] */ + { pinmux(10), 1, 3 }, /* EMA_A[20] */ + { pinmux(10), 1, 4 }, /* EMA_A[19] */ + { pinmux(10), 1, 5 }, /* EMA_A[18] */ + { pinmux(10), 1, 6 }, /* EMA_A[17] */ + { pinmux(10), 1, 7 }, /* EMA_A[16] */ + { pinmux(11), 1, 0 }, /* EMA_A[15] */ + { pinmux(11), 1, 1 }, /* EMA_A[14] */ + { pinmux(11), 1, 2 }, /* EMA_A[13] */ + { pinmux(11), 1, 3 }, /* EMA_A[12] */ + { pinmux(11), 1, 4 }, /* EMA_A[11] */ + { pinmux(11), 1, 5 }, /* EMA_A[10] */ + { pinmux(11), 1, 6 }, /* EMA_A[9] */ + { pinmux(11), 1, 7 }, /* EMA_A[8] */ + { pinmux(12), 1, 0 }, /* EMA_A[7] */ + { pinmux(12), 1, 1 }, /* EMA_A[6] */ + { pinmux(12), 1, 2 }, /* EMA_A[5] */ + { pinmux(12), 1, 3 }, /* EMA_A[4] */ + { pinmux(12), 1, 4 }, /* EMA_A[3] */ + { pinmux(12), 1, 5 }, /* EMA_A[2] */ + { pinmux(12), 1, 6 }, /* EMA_A[1] */ + { pinmux(12), 1, 7 }, /* EMA_A[0] */ +}; + +/* MMC0 pin muxer settings */ +const struct pinmux_config mmc0_pins[] = { + { pinmux(10), 2, 0 }, /* MMCSD0_CLK */ + { pinmux(10), 2, 1 }, /* MMCSD0_CMD */ + { pinmux(10), 2, 2 }, /* MMCSD0_DAT_0 */ + { pinmux(10), 2, 3 }, /* MMCSD0_DAT_1 */ + { pinmux(10), 2, 4 }, /* MMCSD0_DAT_2 */ + { pinmux(10), 2, 5 }, /* MMCSD0_DAT_3 */ + /* DA850 supports only 4-bit mode, remaining pins are not configured */ +}; diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm355.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm355.c new file mode 100644 index 000000000..f9550a16d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm355.c @@ -0,0 +1,30 @@ +/* + * SoC-specific code for tms320dm355 and similar chips + * + * Copyright (C) 2009 David Brownell + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/hardware.h> + + +void davinci_enable_uart0(void) +{ + lpsc_on(DAVINCI_LPSC_UART0); + + /* Bringup UART0 out of reset */ + REG(UART0_PWREMU_MGMT) = 0x00006001; +} + + +#ifdef CONFIG_SYS_I2C_DAVINCI +void davinci_enable_i2c(void) +{ + lpsc_on(DAVINCI_LPSC_I2C); + + /* Enable I2C pin Mux */ + REG(PINMUX3) |= (1 << 20) | (1 << 19); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm365.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm365.c new file mode 100644 index 000000000..f6ca527e7 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm365.c @@ -0,0 +1,20 @@ +/* + * SoC-specific code for tms320dm365 and similar chips + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/hardware.h> + +void davinci_enable_uart0(void) +{ + lpsc_on(DAVINCI_LPSC_UART0); +} + +#ifdef CONFIG_SYS_I2C_DAVINCI +void davinci_enable_i2c(void) +{ + lpsc_on(DAVINCI_LPSC_I2C); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm365_lowlevel.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm365_lowlevel.c new file mode 100644 index 000000000..ee096fe72 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm365_lowlevel.c @@ -0,0 +1,459 @@ +/* + * SoC-specific lowlevel code for tms320dm365 and similar chips + * Actually used for booting from NAND with nand_spl. + * + * Copyright (C) 2011 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <nand.h> +#include <ns16550.h> +#include <post.h> +#include <asm/arch/dm365_lowlevel.h> +#include <asm/arch/hardware.h> + +void dm365_waitloop(unsigned long loopcnt) +{ + unsigned long i; + + for (i = 0; i < loopcnt; i++) + asm(" NOP"); +} + +int dm365_pll1_init(unsigned long pllmult, unsigned long prediv) +{ + unsigned int clksrc = 0x0; + + /* Power up the PLL */ + clrbits_le32(&dv_pll0_regs->pllctl, PLLCTL_PLLPWRDN); + + clrbits_le32(&dv_pll0_regs->pllctl, PLLCTL_RES_9); + setbits_le32(&dv_pll0_regs->pllctl, + clksrc << PLLCTL_CLOCK_MODE_SHIFT); + + /* + * Set PLLENSRC '0', PLL Enable(PLLEN) selection is controlled + * through MMR + */ + clrbits_le32(&dv_pll0_regs->pllctl, PLLCTL_PLLENSRC); + + /* Set PLLEN=0 => PLL BYPASS MODE */ + clrbits_le32(&dv_pll0_regs->pllctl, PLLCTL_PLLEN); + + dm365_waitloop(150); + + /* PLLRST=1(reset assert) */ + setbits_le32(&dv_pll0_regs->pllctl, PLLCTL_PLLRST); + + dm365_waitloop(300); + + /*Bring PLL out of Reset*/ + clrbits_le32(&dv_pll0_regs->pllctl, PLLCTL_PLLRST); + + /* Program the Multiper and Pre-Divider for PLL1 */ + writel(pllmult, &dv_pll0_regs->pllm); + writel(prediv, &dv_pll0_regs->prediv); + + /* Assert TENABLE = 1, TENABLEDIV = 1, TINITZ = 1 */ + writel(PLLSECCTL_STOPMODE | PLLSECCTL_TENABLEDIV | PLLSECCTL_TENABLE | + PLLSECCTL_TINITZ, &dv_pll0_regs->secctl); + /* Assert TENABLE = 1, TENABLEDIV = 1, TINITZ = 0 */ + writel(PLLSECCTL_STOPMODE | PLLSECCTL_TENABLEDIV | PLLSECCTL_TENABLE, + &dv_pll0_regs->secctl); + /* Assert TENABLE = 0, TENABLEDIV = 0, TINITZ = 0 */ + writel(PLLSECCTL_STOPMODE, &dv_pll0_regs->secctl); + /* Assert TENABLE = 0, TENABLEDIV = 0, TINITZ = 1 */ + writel(PLLSECCTL_STOPMODE | PLLSECCTL_TINITZ, &dv_pll0_regs->secctl); + + /* Program the PostDiv for PLL1 */ + writel(PLL_POSTDEN, &dv_pll0_regs->postdiv); + + /* Post divider setting for PLL1 */ + writel(CONFIG_SYS_DM36x_PLL1_PLLDIV1, &dv_pll0_regs->plldiv1); + writel(CONFIG_SYS_DM36x_PLL1_PLLDIV2, &dv_pll0_regs->plldiv2); + writel(CONFIG_SYS_DM36x_PLL1_PLLDIV3, &dv_pll0_regs->plldiv3); + writel(CONFIG_SYS_DM36x_PLL1_PLLDIV4, &dv_pll0_regs->plldiv4); + writel(CONFIG_SYS_DM36x_PLL1_PLLDIV5, &dv_pll0_regs->plldiv5); + writel(CONFIG_SYS_DM36x_PLL1_PLLDIV6, &dv_pll0_regs->plldiv6); + writel(CONFIG_SYS_DM36x_PLL1_PLLDIV7, &dv_pll0_regs->plldiv7); + writel(CONFIG_SYS_DM36x_PLL1_PLLDIV8, &dv_pll0_regs->plldiv8); + writel(CONFIG_SYS_DM36x_PLL1_PLLDIV9, &dv_pll0_regs->plldiv9); + + dm365_waitloop(300); + + /* Set the GOSET bit */ + writel(PLLCMD_GOSET, &dv_pll0_regs->pllcmd); /* Go */ + + dm365_waitloop(300); + + /* Wait for PLL to LOCK */ + while (!((readl(&dv_sys_module_regs->pll0_config) & PLL0_LOCK) + == PLL0_LOCK)) + ; + + /* Enable the PLL Bit of PLLCTL*/ + setbits_le32(&dv_pll0_regs->pllctl, PLLCTL_PLLEN); + + return 0; +} + +int dm365_pll2_init(unsigned long pllm, unsigned long prediv) +{ + unsigned int clksrc = 0x0; + + /* Power up the PLL*/ + clrbits_le32(&dv_pll1_regs->pllctl, PLLCTL_PLLPWRDN); + + /* + * Select the Clock Mode as Onchip Oscilator or External Clock on + * MXI pin + * VDB has input on MXI pin + */ + clrbits_le32(&dv_pll1_regs->pllctl, PLLCTL_RES_9); + setbits_le32(&dv_pll1_regs->pllctl, + clksrc << PLLCTL_CLOCK_MODE_SHIFT); + + /* + * Set PLLENSRC '0', PLL Enable(PLLEN) selection is controlled + * through MMR + */ + clrbits_le32(&dv_pll1_regs->pllctl, PLLCTL_PLLENSRC); + + /* Set PLLEN=0 => PLL BYPASS MODE */ + clrbits_le32(&dv_pll1_regs->pllctl, PLLCTL_PLLEN); + + dm365_waitloop(50); + + /* PLLRST=1(reset assert) */ + setbits_le32(&dv_pll1_regs->pllctl, PLLCTL_PLLRST); + + dm365_waitloop(300); + + /* Bring PLL out of Reset */ + clrbits_le32(&dv_pll1_regs->pllctl, PLLCTL_PLLRST); + + /* Program the Multiper and Pre-Divider for PLL2 */ + writel(pllm, &dv_pll1_regs->pllm); + writel(prediv, &dv_pll1_regs->prediv); + + writel(PLL_POSTDEN, &dv_pll1_regs->postdiv); + + /* Assert TENABLE = 1, TENABLEDIV = 1, TINITZ = 1 */ + writel(PLLSECCTL_STOPMODE | PLLSECCTL_TENABLEDIV | PLLSECCTL_TENABLE | + PLLSECCTL_TINITZ, &dv_pll1_regs->secctl); + /* Assert TENABLE = 1, TENABLEDIV = 1, TINITZ = 0 */ + writel(PLLSECCTL_STOPMODE | PLLSECCTL_TENABLEDIV | PLLSECCTL_TENABLE, + &dv_pll1_regs->secctl); + /* Assert TENABLE = 0, TENABLEDIV = 0, TINITZ = 0 */ + writel(PLLSECCTL_STOPMODE, &dv_pll1_regs->secctl); + /* Assert TENABLE = 0, TENABLEDIV = 0, TINITZ = 1 */ + writel(PLLSECCTL_STOPMODE | PLLSECCTL_TINITZ, &dv_pll1_regs->secctl); + + /* Post divider setting for PLL2 */ + writel(CONFIG_SYS_DM36x_PLL2_PLLDIV1, &dv_pll1_regs->plldiv1); + writel(CONFIG_SYS_DM36x_PLL2_PLLDIV2, &dv_pll1_regs->plldiv2); + writel(CONFIG_SYS_DM36x_PLL2_PLLDIV3, &dv_pll1_regs->plldiv3); + writel(CONFIG_SYS_DM36x_PLL2_PLLDIV4, &dv_pll1_regs->plldiv4); + writel(CONFIG_SYS_DM36x_PLL2_PLLDIV5, &dv_pll1_regs->plldiv5); + + /* GoCmd for PostDivider to take effect */ + writel(PLLCMD_GOSET, &dv_pll1_regs->pllcmd); + + dm365_waitloop(150); + + /* Wait for PLL to LOCK */ + while (!((readl(&dv_sys_module_regs->pll1_config) & PLL1_LOCK) + == PLL1_LOCK)) + ; + + dm365_waitloop(4100); + + /* Enable the PLL2 */ + setbits_le32(&dv_pll1_regs->pllctl, PLLCTL_PLLEN); + + /* do this after PLL's have been set up */ + writel(CONFIG_SYS_DM36x_PERI_CLK_CTRL, + &dv_sys_module_regs->peri_clkctl); + + return 0; +} + +int dm365_ddr_setup(void) +{ + lpsc_on(DAVINCI_LPSC_DDR_EMIF); + clrbits_le32(&dv_sys_module_regs->vtpiocr, + VPTIO_IOPWRDN | VPTIO_CLRZ | VPTIO_LOCK | VPTIO_PWRDN); + + /* Set bit CLRZ (bit 13) */ + setbits_le32(&dv_sys_module_regs->vtpiocr, VPTIO_CLRZ); + + /* Check VTP READY Status */ + while (!(readl(&dv_sys_module_regs->vtpiocr) & VPTIO_RDY)) + ; + + /* Set bit VTP_IOPWRDWN bit 14 for DDR input buffers) */ + setbits_le32(&dv_sys_module_regs->vtpiocr, VPTIO_IOPWRDN); + + /* Set bit LOCK(bit7) */ + setbits_le32(&dv_sys_module_regs->vtpiocr, VPTIO_LOCK); + + /* + * Powerdown VTP as it is locked (bit 6) + * Set bit VTP_IOPWRDWN bit 14 for DDR input buffers) + */ + setbits_le32(&dv_sys_module_regs->vtpiocr, + VPTIO_IOPWRDN | VPTIO_PWRDN); + + /* Wait for calibration to complete */ + dm365_waitloop(150); + + /* Set the DDR2 to synreset, then enable it again */ + lpsc_syncreset(DAVINCI_LPSC_DDR_EMIF); + lpsc_on(DAVINCI_LPSC_DDR_EMIF); + + writel(CONFIG_SYS_DM36x_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr); + + /* Program SDRAM Bank Config Register */ + writel((CONFIG_SYS_DM36x_DDR2_SDBCR | DV_DDR_BOOTUNLOCK), + &dv_ddr2_regs_ctrl->sdbcr); + writel((CONFIG_SYS_DM36x_DDR2_SDBCR | DV_DDR_TIMUNLOCK), + &dv_ddr2_regs_ctrl->sdbcr); + + /* Program SDRAM Timing Control Register1 */ + writel(CONFIG_SYS_DM36x_DDR2_SDTIMR, &dv_ddr2_regs_ctrl->sdtimr); + /* Program SDRAM Timing Control Register2 */ + writel(CONFIG_SYS_DM36x_DDR2_SDTIMR2, &dv_ddr2_regs_ctrl->sdtimr2); + + writel(CONFIG_SYS_DM36x_DDR2_PBBPR, &dv_ddr2_regs_ctrl->pbbpr); + + writel(CONFIG_SYS_DM36x_DDR2_SDBCR, &dv_ddr2_regs_ctrl->sdbcr); + + /* Program SDRAM Refresh Control Register */ + writel(CONFIG_SYS_DM36x_DDR2_SDRCR, &dv_ddr2_regs_ctrl->sdrcr); + + lpsc_syncreset(DAVINCI_LPSC_DDR_EMIF); + lpsc_on(DAVINCI_LPSC_DDR_EMIF); + + return 0; +} + +static void dm365_vpss_sync_reset(void) +{ + unsigned int PdNum = 0; + + /* VPSS_CLKMD 1:1 */ + setbits_le32(&dv_sys_module_regs->vpss_clkctl, + VPSS_CLK_CTL_VPSS_CLKMD); + + /* LPSC SyncReset DDR Clock Enable */ + writel(((readl(&dv_psc_regs->mdctl[DAVINCI_LPSC_VPSSMASTER]) & + ~PSC_MD_STATE_MSK) | PSC_SYNCRESET), + &dv_psc_regs->mdctl[DAVINCI_LPSC_VPSSMASTER]); + + writel((1 << PdNum), &dv_psc_regs->ptcmd); + + while (!(((readl(&dv_psc_regs->ptstat) >> PdNum) & PSC_GOSTAT) == 0)) + ; + while (!((readl(&dv_psc_regs->mdstat[DAVINCI_LPSC_VPSSMASTER]) & + PSC_MD_STATE_MSK) == PSC_SYNCRESET)) + ; +} + +static void dm365_por_reset(void) +{ + struct davinci_timer *wdog = + (struct davinci_timer *)DAVINCI_WDOG_BASE; + + if (readl(&dv_pll0_regs->rstype) & + (PLL_RSTYPE_POR | PLL_RSTYPE_XWRST)) { + dm365_vpss_sync_reset(); + + writel(DV_TMPBUF_VAL, TMPBUF); + setbits_le32(TMPSTATUS, FLAG_PORRST); + writel(DV_WDT_ENABLE_SYS_RESET, &wdog->na1); + writel(DV_WDT_TRIGGER_SYS_RESET, &wdog->na2); + + while (1); + } +} + +static void dm365_wdt_reset(void) +{ + struct davinci_timer *wdog = + (struct davinci_timer *)DAVINCI_WDOG_BASE; + + if (readl(TMPBUF) != DV_TMPBUF_VAL) { + writel(DV_TMPBUF_VAL, TMPBUF); + setbits_le32(TMPSTATUS, FLAG_PORRST); + setbits_le32(TMPSTATUS, FLAG_FLGOFF); + + dm365_waitloop(100); + + dm365_vpss_sync_reset(); + + writel(DV_WDT_ENABLE_SYS_RESET, &wdog->na1); + writel(DV_WDT_TRIGGER_SYS_RESET, &wdog->na2); + + while (1); + } +} + +static void dm365_wdt_flag_on(void) +{ + /* VPSS_CLKMD 1:2 */ + clrbits_le32(&dv_sys_module_regs->vpss_clkctl, + VPSS_CLK_CTL_VPSS_CLKMD); + writel(0, TMPBUF); + setbits_le32(TMPSTATUS, FLAG_FLGON); +} + +void dm365_psc_init(void) +{ + unsigned char i = 0; + unsigned char lpsc_start; + unsigned char lpsc_end, lpscgroup, lpscmin, lpscmax; + unsigned int PdNum = 0; + + lpscmin = 0; + lpscmax = 2; + + for (lpscgroup = lpscmin; lpscgroup <= lpscmax; lpscgroup++) { + if (lpscgroup == 0) { + /* Enabling LPSC 3 to 28 SCR first */ + lpsc_start = DAVINCI_LPSC_VPSSMSTR; + lpsc_end = DAVINCI_LPSC_TIMER1; + } else if (lpscgroup == 1) { /* Skip locked LPSCs [29-37] */ + lpsc_start = DAVINCI_LPSC_CFG5; + lpsc_end = DAVINCI_LPSC_VPSSMASTER; + } else { + lpsc_start = DAVINCI_LPSC_MJCP; + lpsc_end = DAVINCI_LPSC_HDVICP; + } + + /* NEXT=0x3, Enable LPSC's */ + for (i = lpsc_start; i <= lpsc_end; i++) + setbits_le32(&dv_psc_regs->mdctl[i], PSC_ENABLE); + + /* + * Program goctl to start transition sequence for LPSCs + * CSL_PSC_0_REGS->PTCMD = (1<<PdNum); Kick off Power + * Domain 0 Modules + */ + writel((1 << PdNum), &dv_psc_regs->ptcmd); + + /* + * Wait for GOSTAT = NO TRANSITION from PSC for Powerdomain 0 + */ + while (!(((readl(&dv_psc_regs->ptstat) >> PdNum) & PSC_GOSTAT) + == 0)) + ; + + /* Wait for MODSTAT = ENABLE from LPSC's */ + for (i = lpsc_start; i <= lpsc_end; i++) + while (!((readl(&dv_psc_regs->mdstat[i]) & + PSC_MD_STATE_MSK) == PSC_ENABLE)) + ; + } +} + +static void dm365_emif_init(void) +{ + writel(CONFIG_SYS_DM36x_AWCCR, &davinci_emif_regs->awccr); + writel(CONFIG_SYS_DM36x_AB1CR, &davinci_emif_regs->ab1cr); + + setbits_le32(&davinci_emif_regs->nandfcr, DAVINCI_NANDFCR_CS2NAND); + + writel(CONFIG_SYS_DM36x_AB2CR, &davinci_emif_regs->ab2cr); + + return; +} + +void dm365_pinmux_ctl(unsigned long offset, unsigned long mask, + unsigned long value) +{ + clrbits_le32(&dv_sys_module_regs->pinmux[offset], mask); + setbits_le32(&dv_sys_module_regs->pinmux[offset], (mask & value)); +} + +__attribute__((weak)) +void board_gpio_init(void) +{ + return; +} + +#if defined(CONFIG_POST) +int post_log(char *format, ...) +{ + return 0; +} +#endif + +void dm36x_lowlevel_init(ulong bootflag) +{ + struct davinci_uart_ctrl_regs *davinci_uart_ctrl_regs = + (struct davinci_uart_ctrl_regs *)(CONFIG_SYS_NS16550_COM1 + + DAVINCI_UART_CTRL_BASE); + + /* Mask all interrupts */ + writel(DV_AINTC_INTCTL_IDMODE, &dv_aintc_regs->intctl); + writel(0x0, &dv_aintc_regs->eabase); + writel(0x0, &dv_aintc_regs->eint0); + writel(0x0, &dv_aintc_regs->eint1); + + /* Clear all interrupts */ + writel(0xffffffff, &dv_aintc_regs->fiq0); + writel(0xffffffff, &dv_aintc_regs->fiq1); + writel(0xffffffff, &dv_aintc_regs->irq0); + writel(0xffffffff, &dv_aintc_regs->irq1); + + dm365_por_reset(); + dm365_wdt_reset(); + + /* System PSC setup - enable all */ + dm365_psc_init(); + + /* Setup Pinmux */ + dm365_pinmux_ctl(0, 0xFFFFFFFF, CONFIG_SYS_DM36x_PINMUX0); + dm365_pinmux_ctl(1, 0xFFFFFFFF, CONFIG_SYS_DM36x_PINMUX1); + dm365_pinmux_ctl(2, 0xFFFFFFFF, CONFIG_SYS_DM36x_PINMUX2); + dm365_pinmux_ctl(3, 0xFFFFFFFF, CONFIG_SYS_DM36x_PINMUX3); + dm365_pinmux_ctl(4, 0xFFFFFFFF, CONFIG_SYS_DM36x_PINMUX4); + + /* PLL setup */ + dm365_pll1_init(CONFIG_SYS_DM36x_PLL1_PLLM, + CONFIG_SYS_DM36x_PLL1_PREDIV); + dm365_pll2_init(CONFIG_SYS_DM36x_PLL2_PLLM, + CONFIG_SYS_DM36x_PLL2_PREDIV); + + /* GPIO setup */ + board_gpio_init(); + + NS16550_init((NS16550_t)(CONFIG_SYS_NS16550_COM1), + CONFIG_SYS_NS16550_CLK / 16 / CONFIG_BAUDRATE); + + /* + * Fix Power and Emulation Management Register + * see sprufh2.pdf page 38 Table 22 + */ + writel((DAVINCI_UART_PWREMU_MGMT_FREE | DAVINCI_UART_PWREMU_MGMT_URRST | + DAVINCI_UART_PWREMU_MGMT_UTRST), + &davinci_uart_ctrl_regs->pwremu_mgmt); + + puts("ddr init\n"); + dm365_ddr_setup(); + + puts("emif init\n"); + dm365_emif_init(); + + dm365_wdt_flag_on(); + +#if defined(CONFIG_POST) + /* + * Do memory tests, calls arch_memory_failure_handle() + * if error detected. + */ + memory_post_test(0); +#endif +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm644x.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm644x.c new file mode 100644 index 000000000..c58e271e2 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm644x.c @@ -0,0 +1,81 @@ +/* + * SoC-specific code for tms320dm644x chips + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * Copyright (C) 2008 Lyrtech <www.lyrtech.com> + * Copyright (C) 2004 Texas Instruments. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/hardware.h> + + +#define PINMUX0_EMACEN (1 << 31) +#define PINMUX0_AECS5 (1 << 11) +#define PINMUX0_AECS4 (1 << 10) + +#define PINMUX1_I2C (1 << 7) +#define PINMUX1_UART1 (1 << 1) +#define PINMUX1_UART0 (1 << 0) + + +void davinci_enable_uart0(void) +{ + lpsc_on(DAVINCI_LPSC_UART0); + + /* Bringup UART0 out of reset */ + REG(UART0_PWREMU_MGMT) = 0x00006001; + + /* Enable UART0 MUX lines */ + REG(PINMUX1) |= PINMUX1_UART0; +} + +#ifdef CONFIG_DRIVER_TI_EMAC +void davinci_enable_emac(void) +{ + lpsc_on(DAVINCI_LPSC_EMAC); + lpsc_on(DAVINCI_LPSC_EMAC_WRAPPER); + lpsc_on(DAVINCI_LPSC_MDIO); + + /* Enable GIO3.3V cells used for EMAC */ + REG(VDD3P3V_PWDN) = 0; + + /* Enable EMAC. */ + REG(PINMUX0) |= PINMUX0_EMACEN; +} +#endif + +#ifdef CONFIG_SYS_I2C_DAVINCI +void davinci_enable_i2c(void) +{ + lpsc_on(DAVINCI_LPSC_I2C); + + /* Enable I2C pin Mux */ + REG(PINMUX1) |= PINMUX1_I2C; +} +#endif + +void davinci_errata_workarounds(void) +{ + /* + * Workaround for TMS320DM6446 errata 1.3.22: + * PSC: PTSTAT Register Does Not Clear After Warm/Maximum Reset + * Revision(s) Affected: 1.3 and earlier + */ + REG(PSC_SILVER_BULLET) = 0; + + /* + * Set the PR_OLD_COUNT bits in the Bus Burst Priority Register (PBBPR) + * as suggested in TMS320DM6446 errata 2.1.2: + * + * On DM6446 Silicon Revision 2.1 and earlier, under certain conditions + * low priority modules can occupy the bus and prevent high priority + * modules like the VPSS from getting the required DDR2 throughput. + * A hex value of 0x20 should provide a good ARM (cache enabled) + * performance and still allow good utilization by the VPSS or other + * modules. + */ + REG(VBPR) = 0x20; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm646x.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm646x.c new file mode 100644 index 000000000..cfea8300d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dm646x.c @@ -0,0 +1,26 @@ +/* + * SoC-specific code for TMS320DM646x chips + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/arch/hardware.h> + +void davinci_enable_uart0(void) +{ + lpsc_on(DAVINCI_DM646X_LPSC_UART0); +} + +#ifdef CONFIG_DRIVER_TI_EMAC +void davinci_enable_emac(void) +{ + lpsc_on(DAVINCI_DM646X_LPSC_EMAC); +} +#endif + +#ifdef CONFIG_SYS_I2C_DAVINCI +void davinci_enable_i2c(void) +{ + lpsc_on(DAVINCI_DM646X_LPSC_I2C); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dp83848.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dp83848.c new file mode 100644 index 000000000..603d507c7 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/dp83848.c @@ -0,0 +1,128 @@ +/* + * National Semiconductor DP83848 PHY Driver for TI DaVinci + * (TMS320DM644x) based boards. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * -------------------------------------------------------- + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <net.h> +#include <dp83848.h> +#include <asm/arch/emac_defs.h> +#include "../../../../../drivers/net/davinci_emac.h" + +#ifdef CONFIG_DRIVER_TI_EMAC + +#ifdef CONFIG_CMD_NET + +int dp83848_is_phy_connected(int phy_addr) +{ + u_int16_t id1, id2; + + if (!davinci_eth_phy_read(phy_addr, DP83848_PHYID1_REG, &id1)) + return(0); + if (!davinci_eth_phy_read(phy_addr, DP83848_PHYID2_REG, &id2)) + return(0); + + if ((id1 == DP83848_PHYID1_OUI) && (id2 == DP83848_PHYID2_OUI)) + return(1); + + return(0); +} + +int dp83848_get_link_speed(int phy_addr) +{ + u_int16_t tmp; + volatile emac_regs* emac = (emac_regs *)EMAC_BASE_ADDR; + + if (!davinci_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp)) + return(0); + + if (!(tmp & DP83848_LINK_STATUS)) /* link up? */ + return(0); + + if (!davinci_eth_phy_read(phy_addr, DP83848_PHY_STAT_REG, &tmp)) + return(0); + + /* Speed doesn't matter, there is no setting for it in EMAC... */ + if (tmp & DP83848_DUPLEX) { + /* set DM644x EMAC for Full Duplex */ + emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | + EMAC_MACCONTROL_FULLDUPLEX_ENABLE; + } else { + /*set DM644x EMAC for Half Duplex */ + emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE; + } + + return(1); +} + + +int dp83848_init_phy(int phy_addr) +{ + int ret = 1; + + if (!dp83848_get_link_speed(phy_addr)) { + /* Try another time */ + udelay(100000); + ret = dp83848_get_link_speed(phy_addr); + } + + /* Disable PHY Interrupts */ + davinci_eth_phy_write(phy_addr, DP83848_PHY_INTR_CTRL_REG, 0); + + return(ret); +} + + +int dp83848_auto_negotiate(int phy_addr) +{ + u_int16_t tmp; + + + if (!davinci_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp)) + return(0); + + /* Restart Auto_negotiation */ + tmp &= ~DP83848_AUTONEG; /* remove autonegotiation enable */ + tmp |= DP83848_ISOLATE; /* Electrically isolate PHY */ + davinci_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp); + + /* Set the Auto_negotiation Advertisement Register + * MII advertising for Next page, 100BaseTxFD and HD, + * 10BaseTFD and HD, IEEE 802.3 + */ + tmp = DP83848_NP | DP83848_TX_FDX | DP83848_TX_HDX | + DP83848_10_FDX | DP83848_10_HDX | DP83848_AN_IEEE_802_3; + davinci_eth_phy_write(phy_addr, DP83848_ANA_REG, tmp); + + + /* Read Control Register */ + if (!davinci_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp)) + return(0); + + tmp |= DP83848_SPEED_SELECT | DP83848_AUTONEG | DP83848_DUPLEX_MODE; + davinci_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp); + + /* Restart Auto_negotiation */ + tmp |= DP83848_RESTART_AUTONEG; + davinci_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp); + + /*check AutoNegotiate complete */ + udelay(10000); + if (!davinci_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp)) + return(0); + + if (!(tmp & DP83848_AUTONEG_COMP)) + return(0); + + return (dp83848_get_link_speed(phy_addr)); +} + +#endif /* CONFIG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/et1011c.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/et1011c.c new file mode 100644 index 000000000..9d53875b9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/et1011c.c @@ -0,0 +1,42 @@ +/* + * LSI ET1011C PHY Driver for TI DaVinci(TMS320DM6467) board. + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <net.h> +#include <miiphy.h> +#include <asm/arch/emac_defs.h> +#include "../../../../../drivers/net/davinci_emac.h" + +#ifdef CONFIG_DRIVER_TI_EMAC + +#ifdef CONFIG_CMD_NET + +/* LSI PHYSICAL LAYER TRANSCEIVER ET1011C */ + +#define MII_PHY_CONFIG_REG 22 + +/* PHY Config bits */ +#define PHY_SYS_CLK_EN (1 << 4) + +int et1011c_get_link_speed(int phy_addr) +{ + u_int16_t data; + + if (davinci_eth_phy_read(phy_addr, MII_STATUS_REG, &data) && (data & 0x04)) { + davinci_eth_phy_read(phy_addr, MII_PHY_CONFIG_REG, &data); + /* Enable 125MHz clock sourced from PHY */ + davinci_eth_phy_write(phy_addr, MII_PHY_CONFIG_REG, + data | PHY_SYS_CLK_EN); + return (1); + } + return (0); +} + +#endif /* CONFIG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/ksz8873.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/ksz8873.c new file mode 100644 index 000000000..4af5dd213 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/ksz8873.c @@ -0,0 +1,53 @@ +/* + * Micrel KSZ8873 PHY Driver for TI DaVinci + * (TMS320DM644x) based boards. + * + * Copyright (C) 2011 Heiko Schocher <hsdenx.de> + * + * based on: + * National Semiconductor DP83848 PHY Driver for TI DaVinci + * (TMS320DM644x) based boards. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * -------------------------------------------------------- + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <miiphy.h> +#include <net.h> +#include <asm/arch/emac_defs.h> +#include <asm/io.h> +#include "../../../../../drivers/net/davinci_emac.h" + +int ksz8873_is_phy_connected(int phy_addr) +{ + u_int16_t dummy; + + return davinci_eth_phy_read(phy_addr, MII_PHYSID1, &dummy); +} + +int ksz8873_get_link_speed(int phy_addr) +{ + emac_regs *emac = (emac_regs *)EMAC_BASE_ADDR; + + /* we always have a link to the switch, 100 FD */ + writel((EMAC_MACCONTROL_MIIEN_ENABLE | + EMAC_MACCONTROL_FULLDUPLEX_ENABLE), + &emac->MACCONTROL); + return 1; +} + + +int ksz8873_init_phy(int phy_addr) +{ + return 1; +} + + +int ksz8873_auto_negotiate(int phy_addr) +{ + return dp83848_get_link_speed(phy_addr); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/lowlevel_init.S new file mode 100644 index 000000000..e91623497 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/lowlevel_init.S @@ -0,0 +1,693 @@ +/* + * Low-level board setup code for TI DaVinci SoC based boards. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Partially based on TI sources, original copyrights follow: + */ + +/* + * Board specific setup info + * + * (C) Copyright 2003 + * Texas Instruments, <www.ti.com> + * Kshitij Gupta <Kshitij@ti.com> + * + * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004 + * + * Modified for OMAP 5912 OSK board by Rishi Bhattacharya, Apr 2004 + * + * Modified for DV-EVM board by Rishi Bhattacharya, Apr 2005 + * + * Modified for DV-EVM board by Swaminathan S, Nov 2005 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> + +#define MDSTAT_STATE 0x3f + +.globl lowlevel_init +lowlevel_init: +#ifdef CONFIG_SOC_DM644X + + /*-------------------------------------------------------* + * Mask all IRQs by setting all bits in the EINT default * + *-------------------------------------------------------*/ + mov r1, $0 + ldr r0, =EINT_ENABLE0 + str r1, [r0] + ldr r0, =EINT_ENABLE1 + str r1, [r0] + + /*------------------------------------------------------* + * Put the GEM in reset * + *------------------------------------------------------*/ + + /* Put the GEM in reset */ + ldr r8, PSC_GEM_FLAG_CLEAR + ldr r6, MDCTL_GEM + ldr r7, [r6] + and r7, r7, r8 + str r7, [r6] + + /* Enable the Power Domain Transition Command */ + ldr r6, PTCMD + ldr r7, [r6] + orr r7, r7, $0x02 + str r7, [r6] + + /* Check for Transition Complete(PTSTAT) */ +checkStatClkStopGem: + ldr r6, PTSTAT + ldr r7, [r6] + ands r7, r7, $0x02 + bne checkStatClkStopGem + + /* Check for GEM Reset Completion */ +checkGemStatClkStop: + ldr r6, MDSTAT_GEM + ldr r7, [r6] + ands r7, r7, $0x100 + bne checkGemStatClkStop + + /* Do this for enabling a WDT initiated reset this is a workaround + for a chip bug. Not required under normal situations */ + ldr r6, P1394 + mov r10, $0 + str r10, [r6] + + /*------------------------------------------------------* + * Enable L1 & L2 Memories in Fast mode * + *------------------------------------------------------*/ + ldr r6, DFT_ENABLE + mov r10, $0x01 + str r10, [r6] + + ldr r6, MMARG_BRF0 + ldr r10, MMARG_BRF0_VAL + str r10, [r6] + + ldr r6, DFT_ENABLE + mov r10, $0 + str r10, [r6] + + /*------------------------------------------------------* + * DDR2 PLL Initialization * + *------------------------------------------------------*/ + + /* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */ + mov r10, $0 + ldr r6, PLL2_CTL + ldr r7, PLL_CLKSRC_MASK + ldr r8, [r6] + and r8, r8, r7 + mov r9, r10, lsl $8 + orr r8, r8, r9 + str r8, [r6] + + /* Select the PLLEN source */ + ldr r7, PLL_ENSRC_MASK + and r8, r8, r7 + str r8, [r6] + + /* Bypass the PLL */ + ldr r7, PLL_BYPASS_MASK + and r8, r8, r7 + str r8, [r6] + + /* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */ + mov r10, $0x20 +WaitPPL2Loop: + subs r10, r10, $1 + bne WaitPPL2Loop + + /* Reset the PLL */ + ldr r7, PLL_RESET_MASK + and r8, r8, r7 + str r8, [r6] + + /* Power up the PLL */ + ldr r7, PLL_PWRUP_MASK + and r8, r8, r7 + str r8, [r6] + + /* Enable the PLL from Disable Mode */ + ldr r7, PLL_DISABLE_ENABLE_MASK + and r8, r8, r7 + str r8, [r6] + + /* Program the PLL Multiplier */ + ldr r6, PLL2_PLLM + mov r2, $0x17 /* 162 MHz */ + str r2, [r6] + + /* Program the PLL2 Divisor Value */ + ldr r6, PLL2_DIV2 + mov r3, $0x01 + str r3, [r6] + + /* Program the PLL2 Divisor Value */ + ldr r6, PLL2_DIV1 + mov r4, $0x0b /* 54 MHz */ + str r4, [r6] + + /* PLL2 DIV2 MMR */ + ldr r8, PLL2_DIV_MASK + ldr r6, PLL2_DIV2 + ldr r9, [r6] + and r8, r8, r9 + mov r9, $0x01 + mov r9, r9, lsl $15 + orr r8, r8, r9 + str r8, [r6] + + /* Program the GOSET bit to take new divider values */ + ldr r6, PLL2_PLLCMD + ldr r7, [r6] + orr r7, r7, $0x01 + str r7, [r6] + + /* Wait for Done */ + ldr r6, PLL2_PLLSTAT +doneLoop_0: + ldr r7, [r6] + ands r7, r7, $0x01 + bne doneLoop_0 + + /* PLL2 DIV1 MMR */ + ldr r8, PLL2_DIV_MASK + ldr r6, PLL2_DIV1 + ldr r9, [r6] + and r8, r8, r9 + mov r9, $0x01 + mov r9, r9, lsl $15 + orr r8, r8, r9 + str r8, [r6] + + /* Program the GOSET bit to take new divider values */ + ldr r6, PLL2_PLLCMD + ldr r7, [r6] + orr r7, r7, $0x01 + str r7, [r6] + + /* Wait for Done */ + ldr r6, PLL2_PLLSTAT +doneLoop: + ldr r7, [r6] + ands r7, r7, $0x01 + bne doneLoop + + /* Wait for PLL to Reset Properly */ + mov r10, $0x218 +ResetPPL2Loop: + subs r10, r10, $1 + bne ResetPPL2Loop + + /* Bring PLL out of Reset */ + ldr r6, PLL2_CTL + ldr r8, [r6] + orr r8, r8, $0x08 + str r8, [r6] + + /* Wait for PLL to Lock */ + ldr r10, PLL_LOCK_COUNT +PLL2Lock: + subs r10, r10, $1 + bne PLL2Lock + + /* Enable the PLL */ + ldr r6, PLL2_CTL + ldr r8, [r6] + orr r8, r8, $0x01 + str r8, [r6] + + /*------------------------------------------------------* + * Issue Soft Reset to DDR Module * + *------------------------------------------------------*/ + + /* Shut down the DDR2 LPSC Module */ + ldr r8, PSC_FLAG_CLEAR + ldr r6, MDCTL_DDR2 + ldr r7, [r6] + and r7, r7, r8 + orr r7, r7, $0x03 + str r7, [r6] + + /* Enable the Power Domain Transition Command */ + ldr r6, PTCMD + ldr r7, [r6] + orr r7, r7, $0x01 + str r7, [r6] + + /* Check for Transition Complete(PTSTAT) */ +checkStatClkStop: + ldr r6, PTSTAT + ldr r7, [r6] + ands r7, r7, $0x01 + bne checkStatClkStop + + /* Check for DDR2 Controller Enable Completion */ +checkDDRStatClkStop: + ldr r6, MDSTAT_DDR2 + ldr r7, [r6] + and r7, r7, $MDSTAT_STATE + cmp r7, $0x03 + bne checkDDRStatClkStop + + /*------------------------------------------------------* + * Program DDR2 MMRs for 162MHz Setting * + *------------------------------------------------------*/ + + /* Program PHY Control Register */ + ldr r6, DDRCTL + ldr r7, DDRCTL_VAL + str r7, [r6] + + /* Program SDRAM Bank Config Register */ + ldr r6, SDCFG + ldr r7, SDCFG_VAL + str r7, [r6] + + /* Program SDRAM TIM-0 Config Register */ + ldr r6, SDTIM0 + ldr r7, SDTIM0_VAL_162MHz + str r7, [r6] + + /* Program SDRAM TIM-1 Config Register */ + ldr r6, SDTIM1 + ldr r7, SDTIM1_VAL_162MHz + str r7, [r6] + + /* Program the SDRAM Bank Config Control Register */ + ldr r10, MASK_VAL + ldr r8, SDCFG + ldr r9, SDCFG_VAL + and r9, r9, r10 + str r9, [r8] + + /* Program SDRAM SDREF Config Register */ + ldr r6, SDREF + ldr r7, SDREF_VAL + str r7, [r6] + + /*------------------------------------------------------* + * Issue Soft Reset to DDR Module * + *------------------------------------------------------*/ + + /* Issue a Dummy DDR2 read/write */ + ldr r8, DDR2_START_ADDR + ldr r7, DUMMY_VAL + str r7, [r8] + ldr r7, [r8] + + /* Shut down the DDR2 LPSC Module */ + ldr r8, PSC_FLAG_CLEAR + ldr r6, MDCTL_DDR2 + ldr r7, [r6] + and r7, r7, r8 + orr r7, r7, $0x01 + str r7, [r6] + + /* Enable the Power Domain Transition Command */ + ldr r6, PTCMD + ldr r7, [r6] + orr r7, r7, $0x01 + str r7, [r6] + + /* Check for Transition Complete(PTSTAT) */ +checkStatClkStop2: + ldr r6, PTSTAT + ldr r7, [r6] + ands r7, r7, $0x01 + bne checkStatClkStop2 + + /* Check for DDR2 Controller Enable Completion */ +checkDDRStatClkStop2: + ldr r6, MDSTAT_DDR2 + ldr r7, [r6] + and r7, r7, $MDSTAT_STATE + cmp r7, $0x01 + bne checkDDRStatClkStop2 + + /*------------------------------------------------------* + * Turn DDR2 Controller Clocks On * + *------------------------------------------------------*/ + + /* Enable the DDR2 LPSC Module */ + ldr r6, MDCTL_DDR2 + ldr r7, [r6] + orr r7, r7, $0x03 + str r7, [r6] + + /* Enable the Power Domain Transition Command */ + ldr r6, PTCMD + ldr r7, [r6] + orr r7, r7, $0x01 + str r7, [r6] + + /* Check for Transition Complete(PTSTAT) */ +checkStatClkEn2: + ldr r6, PTSTAT + ldr r7, [r6] + ands r7, r7, $0x01 + bne checkStatClkEn2 + + /* Check for DDR2 Controller Enable Completion */ +checkDDRStatClkEn2: + ldr r6, MDSTAT_DDR2 + ldr r7, [r6] + and r7, r7, $MDSTAT_STATE + cmp r7, $0x03 + bne checkDDRStatClkEn2 + + /* DDR Writes and Reads */ + ldr r6, CFGTEST + mov r3, $0x01 + str r3, [r6] + + /*------------------------------------------------------* + * System PLL Initialization * + *------------------------------------------------------*/ + + /* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */ + mov r2, $0 + ldr r6, PLL1_CTL + ldr r7, PLL_CLKSRC_MASK + ldr r8, [r6] + and r8, r8, r7 + mov r9, r2, lsl $8 + orr r8, r8, r9 + str r8, [r6] + + /* Select the PLLEN source */ + ldr r7, PLL_ENSRC_MASK + and r8, r8, r7 + str r8, [r6] + + /* Bypass the PLL */ + ldr r7, PLL_BYPASS_MASK + and r8, r8, r7 + str r8, [r6] + + /* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */ + mov r10, $0x20 + +WaitLoop: + subs r10, r10, $1 + bne WaitLoop + + /* Reset the PLL */ + ldr r7, PLL_RESET_MASK + and r8, r8, r7 + str r8, [r6] + + /* Disable the PLL */ + orr r8, r8, $0x10 + str r8, [r6] + + /* Power up the PLL */ + ldr r7, PLL_PWRUP_MASK + and r8, r8, r7 + str r8, [r6] + + /* Enable the PLL from Disable Mode */ + ldr r7, PLL_DISABLE_ENABLE_MASK + and r8, r8, r7 + str r8, [r6] + + /* Program the PLL Multiplier */ + ldr r6, PLL1_PLLM + mov r3, $0x15 /* For 594MHz */ + str r3, [r6] + + /* Wait for PLL to Reset Properly */ + mov r10, $0xff + +ResetLoop: + subs r10, r10, $1 + bne ResetLoop + + /* Bring PLL out of Reset */ + ldr r6, PLL1_CTL + orr r8, r8, $0x08 + str r8, [r6] + + /* Wait for PLL to Lock */ + ldr r10, PLL_LOCK_COUNT + +PLL1Lock: + subs r10, r10, $1 + bne PLL1Lock + + /* Enable the PLL */ + orr r8, r8, $0x01 + str r8, [r6] + + nop + nop + nop + nop + + /*------------------------------------------------------* + * AEMIF configuration for NOR Flash (double check) * + *------------------------------------------------------*/ + ldr r0, _PINMUX0 + ldr r1, _DEV_SETTING + str r1, [r0] + + ldr r0, WAITCFG + ldr r1, WAITCFG_VAL + ldr r2, [r0] + orr r2, r2, r1 + str r2, [r0] + + ldr r0, ACFG3 + ldr r1, ACFG3_VAL + ldr r2, [r0] + and r1, r2, r1 + str r1, [r0] + + ldr r0, ACFG4 + ldr r1, ACFG4_VAL + ldr r2, [r0] + and r1, r2, r1 + str r1, [r0] + + ldr r0, ACFG5 + ldr r1, ACFG5_VAL + ldr r2, [r0] + and r1, r2, r1 + str r1, [r0] + + /*--------------------------------------* + * VTP manual Calibration * + *--------------------------------------*/ + ldr r0, VTPIOCR + ldr r1, VTP_MMR0 + str r1, [r0] + + ldr r0, VTPIOCR + ldr r1, VTP_MMR1 + str r1, [r0] + + /* Wait for 33 VTP CLK cycles. VRP operates at 27 MHz */ + ldr r10, VTP_LOCK_COUNT +VTPLock: + subs r10, r10, $1 + bne VTPLock + + ldr r6, DFT_ENABLE + mov r10, $0x01 + str r10, [r6] + + ldr r6, DDRVTPR + ldr r7, [r6] + mov r8, r7, LSL #32-10 + mov r8, r8, LSR #32-10 /* grab low 10 bits */ + ldr r7, VTP_RECAL + orr r8, r7, r8 + ldr r7, VTP_EN + orr r8, r7, r8 + str r8, [r0] + + + /* Wait for 33 VTP CLK cycles. VRP operates at 27 MHz */ + ldr r10, VTP_LOCK_COUNT +VTP1Lock: + subs r10, r10, $1 + bne VTP1Lock + + ldr r1, [r0] + ldr r2, VTP_MASK + and r2, r1, r2 + str r2, [r0] + + ldr r6, DFT_ENABLE + mov r10, $0 + str r10, [r6] + + /* + * Call board-specific lowlevel init. + * That MUST be present and THAT returns + * back to arch calling code with "mov pc, lr." + */ + b dv_board_init + +.ltorg + +_PINMUX0: + .word 0x01c40000 /* Device Configuration Registers */ +_PINMUX1: + .word 0x01c40004 /* Device Configuration Registers */ + +_DEV_SETTING: + .word 0x00000c1f + +WAITCFG: + .word 0x01e00004 +WAITCFG_VAL: + .word 0 +ACFG3: + .word 0x01e00014 +ACFG3_VAL: + .word 0x3ffffffd +ACFG4: + .word 0x01e00018 +ACFG4_VAL: + .word 0x3ffffffd +ACFG5: + .word 0x01e0001c +ACFG5_VAL: + .word 0x3ffffffd + +MDCTL_DDR2: + .word 0x01c41a34 +MDSTAT_DDR2: + .word 0x01c41834 + +PTCMD: + .word 0x01c41120 +PTSTAT: + .word 0x01c41128 + +EINT_ENABLE0: + .word 0x01c48018 +EINT_ENABLE1: + .word 0x01c4801c + +PSC_FLAG_CLEAR: + .word 0xffffffe0 +PSC_GEM_FLAG_CLEAR: + .word 0xfffffeff + +/* DDR2 MMR & CONFIGURATION VALUES, 162 MHZ clock */ +DDRCTL: + .word 0x200000e4 +DDRCTL_VAL: + .word 0x50006405 +SDREF: + .word 0x2000000c +SDREF_VAL: + .word 0x000005c3 +SDCFG: + .word 0x20000008 +SDCFG_VAL: +#ifdef DDR_4BANKS + .word 0x00178622 +#elif defined DDR_8BANKS + .word 0x00178632 +#else +#error "Unknown DDR configuration!!!" +#endif +SDTIM0: + .word 0x20000010 +SDTIM0_VAL_162MHz: + .word 0x28923211 +SDTIM1: + .word 0x20000014 +SDTIM1_VAL_162MHz: + .word 0x0016c722 +VTPIOCR: + .word 0x200000f0 /* VTP IO Control register */ +DDRVTPR: + .word 0x01c42030 /* DDR VPTR MMR */ +VTP_MMR0: + .word 0x201f +VTP_MMR1: + .word 0xa01f +DFT_ENABLE: + .word 0x01c4004c +VTP_LOCK_COUNT: + .word 0x5b0 +VTP_MASK: + .word 0xffffdfff +VTP_RECAL: + .word 0x08000 +VTP_EN: + .word 0x02000 +CFGTEST: + .word 0x80010000 +MASK_VAL: + .word 0x00000fff + +/* GEM Power Up & LPSC Control Register */ +MDCTL_GEM: + .word 0x01c41a9c +MDSTAT_GEM: + .word 0x01c4189c + +/* For WDT reset chip bug */ +P1394: + .word 0x01c41a20 + +PLL_CLKSRC_MASK: + .word 0xfffffeff /* Mask the Clock Mode bit */ +PLL_ENSRC_MASK: + .word 0xffffffdf /* Select the PLLEN source */ +PLL_BYPASS_MASK: + .word 0xfffffffe /* Put the PLL in BYPASS */ +PLL_RESET_MASK: + .word 0xfffffff7 /* Put the PLL in Reset Mode */ +PLL_PWRUP_MASK: + .word 0xfffffffd /* PLL Power up Mask Bit */ +PLL_DISABLE_ENABLE_MASK: + .word 0xffffffef /* Enable the PLL from Disable */ +PLL_LOCK_COUNT: + .word 0x2000 + +/* PLL1-SYSTEM PLL MMRs */ +PLL1_CTL: + .word 0x01c40900 +PLL1_PLLM: + .word 0x01c40910 + +/* PLL2-SYSTEM PLL MMRs */ +PLL2_CTL: + .word 0x01c40d00 +PLL2_PLLM: + .word 0x01c40d10 +PLL2_DIV1: + .word 0x01c40d18 +PLL2_DIV2: + .word 0x01c40d1c +PLL2_PLLCMD: + .word 0x01c40d38 +PLL2_PLLSTAT: + .word 0x01c40d3c +PLL2_DIV_MASK: + .word 0xffff7fff + +MMARG_BRF0: + .word 0x01c42010 /* BRF margin mode 0 (R/W)*/ +MMARG_BRF0_VAL: + .word 0x00444400 + +DDR2_START_ADDR: + .word 0x80000000 +DUMMY_VAL: + .word 0xa55aa55a +#else /* CONFIG_SOC_DM644X */ + mov pc, lr +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/lxt972.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/lxt972.c new file mode 100644 index 000000000..c482fd937 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/lxt972.c @@ -0,0 +1,113 @@ +/* + * Intel LXT971/LXT972 PHY Driver for TI DaVinci + * (TMS320DM644x) based boards. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * -------------------------------------------------------- + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <net.h> +#include <miiphy.h> +#include <lxt971a.h> +#include <asm/arch/emac_defs.h> +#include "../../../../../drivers/net/davinci_emac.h" + +#ifdef CONFIG_DRIVER_TI_EMAC + +#ifdef CONFIG_CMD_NET + +int lxt972_is_phy_connected(int phy_addr) +{ + u_int16_t id1, id2; + + if (!davinci_eth_phy_read(phy_addr, MII_PHYSID1, &id1)) + return(0); + if (!davinci_eth_phy_read(phy_addr, MII_PHYSID2, &id2)) + return(0); + + if ((id1 == (0x0013)) && ((id2 & 0xfff0) == 0x78e0)) + return(1); + + return(0); +} + +int lxt972_get_link_speed(int phy_addr) +{ + u_int16_t stat1, tmp; + volatile emac_regs *emac = (emac_regs *)EMAC_BASE_ADDR; + + if (!davinci_eth_phy_read(phy_addr, PHY_LXT971_STAT2, &stat1)) + return(0); + + if (!(stat1 & PHY_LXT971_STAT2_LINK)) /* link up? */ + return(0); + + if (!davinci_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp)) + return(0); + + tmp |= PHY_LXT971_DIG_CFG_MII_DRIVE; + + davinci_eth_phy_write(phy_addr, PHY_LXT971_DIG_CFG, tmp); + /* Read back */ + if (!davinci_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp)) + return(0); + + /* Speed doesn't matter, there is no setting for it in EMAC... */ + if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) { + /* set DM644x EMAC for Full Duplex */ + emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | + EMAC_MACCONTROL_FULLDUPLEX_ENABLE; + } else { + /*set DM644x EMAC for Half Duplex */ + emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE; + } + + return(1); +} + + +int lxt972_init_phy(int phy_addr) +{ + int ret = 1; + + if (!lxt972_get_link_speed(phy_addr)) { + /* Try another time */ + ret = lxt972_get_link_speed(phy_addr); + } + + /* Disable PHY Interrupts */ + davinci_eth_phy_write(phy_addr, PHY_LXT971_INT_ENABLE, 0); + + return(ret); +} + + +int lxt972_auto_negotiate(int phy_addr) +{ + u_int16_t tmp; + + if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &tmp)) + return(0); + + /* Restart Auto_negotiation */ + tmp |= BMCR_ANRESTART; + davinci_eth_phy_write(phy_addr, MII_BMCR, tmp); + + /*check AutoNegotiate complete */ + udelay (10000); + if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &tmp)) + return(0); + + if (!(tmp & BMSR_ANEGCOMPLETE)) + return(0); + + return (lxt972_get_link_speed(phy_addr)); +} + +#endif /* CONFIG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/misc.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/misc.c new file mode 100644 index 000000000..e18bdfc72 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/misc.c @@ -0,0 +1,138 @@ +/* + * Miscelaneous DaVinci functions. + * + * Copyright (C) 2009 Nick Thompson, GE Fanuc Ltd, <nick.thompson@gefanuc.com> + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * Copyright (C) 2008 Lyrtech <www.lyrtech.com> + * Copyright (C) 2004 Texas Instruments. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <i2c.h> +#include <net.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> +#include <asm/arch/davinci_misc.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SPL_BUILD +int dram_init(void) +{ + /* dram_init must store complete ramsize in gd->ram_size */ + gd->ram_size = get_ram_size( + (void *)CONFIG_SYS_SDRAM_BASE, + CONFIG_MAX_RAM_BANK_SIZE); + return 0; +} + +void dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_dram[0].size = gd->ram_size; +} +#endif + +#ifdef CONFIG_DRIVER_TI_EMAC +/* + * Read ethernet MAC address from EEPROM for DVEVM compatible boards. + * Returns 1 if found, 0 otherwise. + */ +int dvevm_read_mac_address(uint8_t *buf) +{ +#ifdef CONFIG_SYS_I2C_EEPROM_ADDR + /* Read MAC address. */ + if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0x7F00, + CONFIG_SYS_I2C_EEPROM_ADDR_LEN, (uint8_t *) &buf[0], 6)) + goto i2cerr; + + /* Check that MAC address is valid. */ + if (!is_valid_ether_addr(buf)) + goto err; + + return 1; /* Found */ + +i2cerr: + printf("Read from EEPROM @ 0x%02x failed\n", + CONFIG_SYS_I2C_EEPROM_ADDR); +err: +#endif /* CONFIG_SYS_I2C_EEPROM_ADDR */ + + return 0; +} + +/* + * Set the mii mode as MII or RMII + */ +#if defined(CONFIG_SOC_DA8XX) +void davinci_emac_mii_mode_sel(int mode_sel) +{ + int val; + + val = readl(&davinci_syscfg_regs->cfgchip3); + if (mode_sel == 0) + val &= ~(1 << 8); + else + val |= (1 << 8); + writel(val, &davinci_syscfg_regs->cfgchip3); +} +#endif +/* + * If there is no MAC address in the environment, then it will be initialized + * (silently) from the value in the EEPROM. + */ +void davinci_sync_env_enetaddr(uint8_t *rom_enetaddr) +{ + uint8_t env_enetaddr[6]; + int ret; + + ret = eth_getenv_enetaddr_by_index("eth", 0, env_enetaddr); + if (!ret) { + /* + * There is no MAC address in the environment, so we + * initialize it from the value in the EEPROM. + */ + debug("### Setting environment from EEPROM MAC address = " + "\"%pM\"\n", + env_enetaddr); + ret = !eth_setenv_enetaddr("ethaddr", rom_enetaddr); + } + if (!ret) + printf("Failed to set mac address from EEPROM: %d\n", ret); +} +#endif /* CONFIG_DRIVER_TI_EMAC */ + +#if defined(CONFIG_SOC_DA8XX) +#ifndef CONFIG_USE_IRQ +void irq_init(void) +{ + /* + * Mask all IRQs by clearing the global enable and setting + * the enable clear for all the 90 interrupts. + */ + writel(0, &davinci_aintc_regs->ger); + + writel(0, &davinci_aintc_regs->hier); + + writel(0xffffffff, &davinci_aintc_regs->ecr1); + writel(0xffffffff, &davinci_aintc_regs->ecr2); + writel(0xffffffff, &davinci_aintc_regs->ecr3); +} +#endif + +/* + * Enable PSC for various peripherals. + */ +int da8xx_configure_lpsc_items(const struct lpsc_resource *item, + const int n_items) +{ + int i; + + for (i = 0; i < n_items; i++) + lpsc_on(item[i].lpsc_no); + + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/pinmux.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/pinmux.c new file mode 100644 index 000000000..e9d8c87cc --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/pinmux.c @@ -0,0 +1,90 @@ +/* + * DaVinci pinmux functions. + * + * Copyright (C) 2009 Nick Thompson, GE Fanuc Ltd, <nick.thompson@gefanuc.com> + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * Copyright (C) 2008 Lyrtech <www.lyrtech.com> + * Copyright (C) 2004 Texas Instruments. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> +#include <asm/arch/davinci_misc.h> + +/* + * Change the setting of a pin multiplexer field. + * + * Takes an array of pinmux settings similar to: + * + * struct pinmux_config uart_pins[] = { + * { &davinci_syscfg_regs->pinmux[8], 2, 7 }, + * { &davinci_syscfg_regs->pinmux[9], 2, 0 } + * }; + * + * Stepping through the array, each pinmux[n] register has the given value + * set in the pin mux field specified. + * + * The number of pins in the array must be passed (ARRAY_SIZE can provide + * this value conveniently). + * + * Returns 0 if all field numbers and values are in the correct range, + * else returns -1. + */ +int davinci_configure_pin_mux(const struct pinmux_config *pins, + const int n_pins) +{ + int i; + + /* check for invalid pinmux values */ + for (i = 0; i < n_pins; i++) { + if (pins[i].field >= PIN_MUX_NUM_FIELDS || + (pins[i].value & ~PIN_MUX_FIELD_MASK) != 0) + return -1; + } + + /* configure the pinmuxes */ + for (i = 0; i < n_pins; i++) { + const int offset = pins[i].field * PIN_MUX_FIELD_SIZE; + const unsigned int value = pins[i].value << offset; + const unsigned int mask = PIN_MUX_FIELD_MASK << offset; + const dv_reg *mux = pins[i].mux; + + writel(value | (readl(mux) & (~mask)), mux); + } + + return 0; +} + +/* + * Configure multiple pinmux resources. + * + * Takes an pinmux_resource array of pinmux_config and pin counts: + * + * const struct pinmux_resource pinmuxes[] = { + * PINMUX_ITEM(uart_pins), + * PINMUX_ITEM(i2c_pins), + * }; + * + * The number of items in the array must be passed (ARRAY_SIZE can provide + * this value conveniently). + * + * Each item entry is configured in the defined order. If configuration + * of any item fails, -1 is returned and none of the following items are + * configured. On success, 0 is returned. + */ +int davinci_configure_pin_mux_items(const struct pinmux_resource *item, + const int n_items) +{ + int i; + + for (i = 0; i < n_items; i++) { + if (davinci_configure_pin_mux(item[i].pins, + item[i].n_pins) != 0) + return -1; + } + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/psc.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/psc.c new file mode 100644 index 000000000..8d99e2e99 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/psc.c @@ -0,0 +1,160 @@ +/* + * Power and Sleep Controller (PSC) functions. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * Copyright (C) 2008 Lyrtech <www.lyrtech.com> + * Copyright (C) 2004 Texas Instruments. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> + +/* + * The PSC manages three inputs to a "module" which may be a peripheral or + * CPU. Those inputs are the module's: clock; reset signal; and sometimes + * its power domain. For our purposes, we only care whether clock and power + * are active, and the module is out of reset. + * + * DaVinci chips may include two separate power domains: "Always On" and "DSP". + * Chips without a DSP generally have only one domain. + * + * The "Always On" power domain is always on when the chip is on, and is + * powered by the VDD pins (on DM644X). The majority of DaVinci modules + * lie within the "Always On" power domain. + * + * A separate domain called the "DSP" domain houses the C64x+ and other video + * hardware such as VICP. In some chips, the "DSP" domain is not always on. + * The "DSP" power domain is powered by the CVDDDSP pins (on DM644X). + */ + +/* Works on Always On power domain only (no PD argument) */ +static void lpsc_transition(unsigned int id, unsigned int state) +{ + dv_reg_p mdstat, mdctl, ptstat, ptcmd; +#ifdef CONFIG_SOC_DA8XX + struct davinci_psc_regs *psc_regs; +#endif + +#ifndef CONFIG_SOC_DA8XX + if (id >= DAVINCI_LPSC_GEM) + return; /* Don't work on DSP Power Domain */ + + mdstat = REG_P(PSC_MDSTAT_BASE + (id * 4)); + mdctl = REG_P(PSC_MDCTL_BASE + (id * 4)); + ptstat = REG_P(PSC_PTSTAT); + ptcmd = REG_P(PSC_PTCMD); +#else + if (id < DAVINCI_LPSC_PSC1_BASE) { + if (id >= PSC_PSC0_MODULE_ID_CNT) + return; + psc_regs = davinci_psc0_regs; + mdstat = &psc_regs->psc0.mdstat[id]; + mdctl = &psc_regs->psc0.mdctl[id]; + } else { + id -= DAVINCI_LPSC_PSC1_BASE; + if (id >= PSC_PSC1_MODULE_ID_CNT) + return; + psc_regs = davinci_psc1_regs; + mdstat = &psc_regs->psc1.mdstat[id]; + mdctl = &psc_regs->psc1.mdctl[id]; + } + ptstat = &psc_regs->ptstat; + ptcmd = &psc_regs->ptcmd; +#endif + + while (readl(ptstat) & 0x01) + continue; + + if ((readl(mdstat) & PSC_MDSTAT_STATE) == state) + return; /* Already in that state */ + + writel((readl(mdctl) & ~PSC_MDCTL_NEXT) | state, mdctl); + + switch (id) { +#ifdef CONFIG_SOC_DM644X + /* Special treatment for some modules as for sprue14 p.7.4.2 */ + case DAVINCI_LPSC_VPSSSLV: + case DAVINCI_LPSC_EMAC: + case DAVINCI_LPSC_EMAC_WRAPPER: + case DAVINCI_LPSC_MDIO: + case DAVINCI_LPSC_USB: + case DAVINCI_LPSC_ATA: + case DAVINCI_LPSC_VLYNQ: + case DAVINCI_LPSC_UHPI: + case DAVINCI_LPSC_DDR_EMIF: + case DAVINCI_LPSC_AEMIF: + case DAVINCI_LPSC_MMC_SD: + case DAVINCI_LPSC_MEMSTICK: + case DAVINCI_LPSC_McBSP: + case DAVINCI_LPSC_GPIO: + writel(readl(mdctl) | 0x200, mdctl); + break; +#endif + } + + writel(0x01, ptcmd); + + while (readl(ptstat) & 0x01) + continue; + while ((readl(mdstat) & PSC_MDSTAT_STATE) != state) + continue; +} + +void lpsc_on(unsigned int id) +{ + lpsc_transition(id, 0x03); +} + +void lpsc_syncreset(unsigned int id) +{ + lpsc_transition(id, 0x01); +} + +void lpsc_disable(unsigned int id) +{ + lpsc_transition(id, 0x0); +} + +/* Not all DaVinci chips have a DSP power domain. */ +#ifdef CONFIG_SOC_DM644X + +/* If DSPLINK is used, we don't want U-Boot to power on the DSP. */ +#if !defined(CONFIG_SYS_USE_DSPLINK) +void dsp_on(void) +{ + int i; + + if (REG(PSC_PDSTAT1) & 0x1f) + return; /* Already on */ + + REG(PSC_GBLCTL) |= 0x01; + REG(PSC_PDCTL1) |= 0x01; + REG(PSC_PDCTL1) &= ~0x100; + REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_GEM * 4)) |= 0x03; + REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_GEM * 4)) &= 0xfffffeff; + REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_IMCOP * 4)) |= 0x03; + REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_IMCOP * 4)) &= 0xfffffeff; + REG(PSC_PTCMD) = 0x02; + + for (i = 0; i < 100; i++) { + if (REG(PSC_EPCPR) & 0x02) + break; + } + + REG(PSC_CHP_SHRTSW) = 0x01; + REG(PSC_PDCTL1) |= 0x100; + REG(PSC_EPCCR) = 0x02; + + for (i = 0; i < 100; i++) { + if (!(REG(PSC_PTSTAT) & 0x02)) + break; + } + + REG(PSC_GBLCTL) &= ~0x1f; +} +#endif /* CONFIG_SYS_USE_DSPLINK */ + +#endif /* have a DSP */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/reset.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/reset.c new file mode 100644 index 000000000..6b0f15428 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/reset.c @@ -0,0 +1,32 @@ +/* + * Processor reset using WDT. + * + * Copyright (C) 2012 Dmitry Bondar <bond@inmys.ru> + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/timer_defs.h> +#include <asm/arch/hardware.h> + +void reset_cpu(unsigned long a) +{ + struct davinci_timer *const wdttimer = + (struct davinci_timer *)DAVINCI_WDOG_BASE; + writel(0x08, &wdttimer->tgcr); + writel(readl(&wdttimer->tgcr) | 0x03, &wdttimer->tgcr); + writel(0, &wdttimer->tim12); + writel(0, &wdttimer->tim34); + writel(0, &wdttimer->prd12); + writel(0, &wdttimer->prd34); + writel(readl(&wdttimer->tcr) | 0x40, &wdttimer->tcr); + writel(readl(&wdttimer->wdtcr) | 0x4000, &wdttimer->wdtcr); + writel(0xa5c64000, &wdttimer->wdtcr); + writel(0xda7e4000, &wdttimer->wdtcr); + writel(0x4000, &wdttimer->wdtcr); + while (1) + /*nothing*/; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/spl.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/spl.c new file mode 100644 index 000000000..59b304efc --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/spl.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2011 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <config.h> +#include <spl.h> +#include <asm/u-boot.h> +#include <asm/utils.h> +#include <nand.h> +#include <asm/arch/dm365_lowlevel.h> +#include <ns16550.h> +#include <malloc.h> +#include <spi_flash.h> +#include <mmc.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SPL_LIBCOMMON_SUPPORT +void puts(const char *str) +{ + while (*str) + putc(*str++); +} + +void putc(char c) +{ + if (c == '\n') + NS16550_putc((NS16550_t)(CONFIG_SYS_NS16550_COM1), '\r'); + + NS16550_putc((NS16550_t)(CONFIG_SYS_NS16550_COM1), c); +} +#endif /* CONFIG_SPL_LIBCOMMON_SUPPORT */ + +void board_init_f(ulong dummy) +{ + /* First, setup our stack pointer. */ + asm volatile("mov sp, %0\n" : : "r"(CONFIG_SPL_STACK)); + + /* Second, perform our low-level init. */ +#ifdef CONFIG_SOC_DM365 + dm36x_lowlevel_init(0); +#endif +#ifdef CONFIG_SOC_DA8XX + arch_cpu_init(); +#endif + + /* Third, we clear the BSS. */ + memset(__bss_start, 0, __bss_end - __bss_start); + + /* Finally, setup gd and move to the next step. */ + gd = &gdata; + board_init_r(NULL, 0); +} + +void spl_board_init(void) +{ + preloader_console_init(); +} + +u32 spl_boot_mode(void) +{ + return MMCSD_MODE_RAW; +} + +u32 spl_boot_device(void) +{ +#ifdef CONFIG_SPL_NAND_SIMPLE + return BOOT_DEVICE_NAND; +#elif defined(CONFIG_SPL_SPI_LOAD) + return BOOT_DEVICE_SPI; +#elif defined(CONFIG_SPL_MMC_LOAD) + return BOOT_DEVICE_MMC1; +#else + puts("Unknown boot device\n"); + hang(); +#endif +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/timer.c new file mode 100644 index 000000000..c7d0652e8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/davinci/timer.c @@ -0,0 +1,128 @@ +/* + * (C) Copyright 2003 + * Texas Instruments <www.ti.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/timer_defs.h> +#include <div64.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct davinci_timer * const timer = + (struct davinci_timer *)CONFIG_SYS_TIMERBASE; + +#define TIMER_LOAD_VAL 0xffffffff + +#define TIM_CLK_DIV 16 + +int timer_init(void) +{ + /* We are using timer34 in unchained 32-bit mode, full speed */ + writel(0x0, &timer->tcr); + writel(0x0, &timer->tgcr); + writel(0x06 | ((TIM_CLK_DIV - 1) << 8), &timer->tgcr); + writel(0x0, &timer->tim34); + writel(TIMER_LOAD_VAL, &timer->prd34); + writel(2 << 22, &timer->tcr); + gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK / TIM_CLK_DIV; + gd->arch.timer_reset_value = 0; + + return(0); +} + +/* + * Get the current 64 bit timer tick count + */ +unsigned long long get_ticks(void) +{ + unsigned long now = readl(&timer->tim34); + + /* 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; +} + +ulong get_timer(ulong base) +{ + unsigned long long timer_diff; + + timer_diff = get_ticks() - gd->arch.timer_reset_value; + + return lldiv(timer_diff, + (gd->arch.timer_rate_hz / CONFIG_SYS_HZ)) - base; +} + +void __udelay(unsigned long usec) +{ + unsigned long long endtime; + + endtime = lldiv((unsigned long long)usec * gd->arch.timer_rate_hz, + 1000000UL); + endtime += get_ticks(); + + while (get_ticks() < endtime) + ; +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return gd->arch.timer_rate_hz; +} + +#ifdef CONFIG_HW_WATCHDOG +static struct davinci_timer * const wdttimer = + (struct davinci_timer *)CONFIG_SYS_WDTTIMERBASE; + +/* + * See prufw2.pdf for using Timer as a WDT + */ +void davinci_hw_watchdog_enable(void) +{ + writel(0x0, &wdttimer->tcr); + writel(0x0, &wdttimer->tgcr); + /* TIMMODE = 2h */ + writel(0x08 | 0x03 | ((TIM_CLK_DIV - 1) << 8), &wdttimer->tgcr); + writel(CONFIG_SYS_WDT_PERIOD_LOW, &wdttimer->prd12); + writel(CONFIG_SYS_WDT_PERIOD_HIGH, &wdttimer->prd34); + writel(2 << 22, &wdttimer->tcr); + writel(0x0, &wdttimer->tim12); + writel(0x0, &wdttimer->tim34); + /* set WDEN bit, WDKEY 0xa5c6 */ + writel(0xa5c64000, &wdttimer->wdtcr); + /* clear counter register */ + writel(0xda7e4000, &wdttimer->wdtcr); +} + +void davinci_hw_watchdog_reset(void) +{ + writel(0xa5c64000, &wdttimer->wdtcr); + writel(0xda7e4000, &wdttimer->wdtcr); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/Makefile new file mode 100644 index 000000000..c230ce899 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/Makefile @@ -0,0 +1,13 @@ +# +# (C) Copyright 2009 +# Marvell Semiconductor <www.marvell.com> +# Written-by: Prafulla Wadaskar <prafulla@marvell.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o +obj-y += dram.o +obj-y += mpp.o +obj-y += timer.o +obj-y += cache.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/cache.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/cache.c new file mode 100644 index 000000000..e18a3097d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/cache.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2012 Michael Walle + * Michael Walle <michael@walle.cc> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/arch/cpu.h> + +#define FEROCEON_EXTRA_FEATURE_L2C_EN (1<<22) + +void l2_cache_disable() +{ + u32 ctrl; + + ctrl = readfr_extra_feature_reg(); + ctrl &= ~FEROCEON_EXTRA_FEATURE_L2C_EN; + writefr_extra_feature_reg(ctrl); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/cpu.c new file mode 100644 index 000000000..d4711c070 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/cpu.c @@ -0,0 +1,380 @@ +/* + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <netdev.h> +#include <asm/cache.h> +#include <u-boot/md5.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/kirkwood.h> +#include <hush.h> + +#define BUFLEN 16 + +void reset_cpu(unsigned long ignored) +{ + struct kwcpu_registers *cpureg = + (struct kwcpu_registers *)KW_CPU_REG_BASE; + + writel(readl(&cpureg->rstoutn_mask) | (1 << 2), + &cpureg->rstoutn_mask); + writel(readl(&cpureg->sys_soft_rst) | 1, + &cpureg->sys_soft_rst); + while (1) ; +} + +/* + * Generates Ramdom hex number reading some time varient system registers + * and using md5 algorithm + */ +unsigned char get_random_hex(void) +{ + int i; + u32 inbuf[BUFLEN]; + u8 outbuf[BUFLEN]; + + /* + * in case of 88F6281/88F6282/88F6192 A0, + * Bit7 need to reset to generate random values in KW_REG_UNDOC_0x1470 + * Soc reg offsets KW_REG_UNDOC_0x1470 and KW_REG_UNDOC_0x1478 are + * reserved regs and does not have names at this moment + * (no errata available) + */ + writel(readl(KW_REG_UNDOC_0x1478) & ~(1 << 7), KW_REG_UNDOC_0x1478); + for (i = 0; i < BUFLEN; i++) { + inbuf[i] = readl(KW_REG_UNDOC_0x1470); + } + md5((u8 *) inbuf, (BUFLEN * sizeof(u32)), outbuf); + return outbuf[outbuf[7] % 0x0f]; +} + +/* + * Window Size + * Used with the Base register to set the address window size and location. + * Must be programmed from LSB to MSB as sequence of ones followed by + * sequence of zeros. The number of ones specifies the size of the window in + * 64 KByte granularity (e.g., a value of 0x00FF specifies 256 = 16 MByte). + * NOTE: A value of 0x0 specifies 64-KByte size. + */ +unsigned int kw_winctrl_calcsize(unsigned int sizeval) +{ + int i; + unsigned int j = 0; + u32 val = sizeval >> 1; + + for (i = 0; val >= 0x10000; i++) { + j |= (1 << i); + val = val >> 1; + } + return (0x0000ffff & j); +} + +/* + * kw_config_adr_windows - Configure address Windows + * + * There are 8 address windows supported by Kirkwood Soc to addess different + * devices. Each window can be configured for size, BAR and remap addr + * Below configuration is standard for most of the cases + * + * If remap function not used, remap_lo must be set as base + * + * Reference Documentation: + * Mbus-L to Mbus Bridge Registers Configuration. + * (Sec 25.1 and 25.3 of Datasheet) + */ +int kw_config_adr_windows(void) +{ + struct kwwin_registers *winregs = + (struct kwwin_registers *)KW_CPU_WIN_BASE; + + /* Window 0: PCIE MEM address space */ + writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 256, KWCPU_TARGET_PCIE, + KWCPU_ATTR_PCIE_MEM, KWCPU_WIN_ENABLE), &winregs[0].ctrl); + + writel(KW_DEFADR_PCI_MEM, &winregs[0].base); + writel(KW_DEFADR_PCI_MEM, &winregs[0].remap_lo); + writel(0x0, &winregs[0].remap_hi); + + /* Window 1: PCIE IO address space */ + writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_PCIE, + KWCPU_ATTR_PCIE_IO, KWCPU_WIN_ENABLE), &winregs[1].ctrl); + writel(KW_DEFADR_PCI_IO, &winregs[1].base); + writel(KW_DEFADR_PCI_IO_REMAP, &winregs[1].remap_lo); + writel(0x0, &winregs[1].remap_hi); + + /* Window 2: NAND Flash address space */ + writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_NANDFLASH, KWCPU_WIN_ENABLE), &winregs[2].ctrl); + writel(KW_DEFADR_NANDF, &winregs[2].base); + writel(KW_DEFADR_NANDF, &winregs[2].remap_lo); + writel(0x0, &winregs[2].remap_hi); + + /* Window 3: SPI Flash address space */ + writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_SPIFLASH, KWCPU_WIN_ENABLE), &winregs[3].ctrl); + writel(KW_DEFADR_SPIF, &winregs[3].base); + writel(KW_DEFADR_SPIF, &winregs[3].remap_lo); + writel(0x0, &winregs[3].remap_hi); + + /* Window 4: BOOT Memory address space */ + writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_BOOTROM, KWCPU_WIN_ENABLE), &winregs[4].ctrl); + writel(KW_DEFADR_BOOTROM, &winregs[4].base); + + /* Window 5: Security SRAM address space */ + writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_SASRAM, + KWCPU_ATTR_SASRAM, KWCPU_WIN_ENABLE), &winregs[5].ctrl); + writel(KW_DEFADR_SASRAM, &winregs[5].base); + + /* Window 6-7: Disabled */ + writel(KWCPU_WIN_DISABLE, &winregs[6].ctrl); + writel(KWCPU_WIN_DISABLE, &winregs[7].ctrl); + + return 0; +} + +/* + * kw_config_gpio - GPIO configuration + */ +void kw_config_gpio(u32 gpp0_oe_val, u32 gpp1_oe_val, u32 gpp0_oe, u32 gpp1_oe) +{ + struct kwgpio_registers *gpio0reg = + (struct kwgpio_registers *)KW_GPIO0_BASE; + struct kwgpio_registers *gpio1reg = + (struct kwgpio_registers *)KW_GPIO1_BASE; + + /* Init GPIOS to default values as per board requirement */ + writel(gpp0_oe_val, &gpio0reg->dout); + writel(gpp1_oe_val, &gpio1reg->dout); + writel(gpp0_oe, &gpio0reg->oe); + writel(gpp1_oe, &gpio1reg->oe); +} + +/* + * kw_config_mpp - Multi-Purpose Pins Functionality configuration + * + * Each MPP can be configured to different functionality through + * MPP control register, ref (sec 6.1 of kirkwood h/w specification) + * + * There are maximum 64 Multi-Pourpose Pins on Kirkwood + * Each MPP functionality can be configuration by a 4bit value + * of MPP control reg, the value and associated functionality depends + * upon used SoC varient + */ +int kw_config_mpp(u32 mpp0_7, u32 mpp8_15, u32 mpp16_23, u32 mpp24_31, + u32 mpp32_39, u32 mpp40_47, u32 mpp48_55) +{ + u32 *mppreg = (u32 *) KW_MPP_BASE; + + /* program mpp registers */ + writel(mpp0_7, &mppreg[0]); + writel(mpp8_15, &mppreg[1]); + writel(mpp16_23, &mppreg[2]); + writel(mpp24_31, &mppreg[3]); + writel(mpp32_39, &mppreg[4]); + writel(mpp40_47, &mppreg[5]); + writel(mpp48_55, &mppreg[6]); + return 0; +} + +/* + * SYSRSTn Duration Counter Support + * + * Kirkwood SoC implements a hardware-based SYSRSTn duration counter. + * When SYSRSTn is asserted low, a SYSRSTn duration counter is running. + * The SYSRSTn duration counter is useful for implementing a manufacturer + * or factory reset. Upon a long reset assertion that is greater than a + * pre-configured environment variable value for sysrstdelay, + * The counter value is stored in the SYSRSTn Length Counter Register + * The counter is based on the 25-MHz reference clock (40ns) + * It is a 29-bit counter, yielding a maximum counting duration of + * 2^29/25 MHz (21.4 seconds). When the counter reach its maximum value, + * it remains at this value until counter reset is triggered by setting + * bit 31 of KW_REG_SYSRST_CNT + */ +static void kw_sysrst_action(void) +{ + int ret; + char *s = getenv("sysrstcmd"); + + if (!s) { + debug("Error.. %s failed, check sysrstcmd\n", + __FUNCTION__); + return; + } + + debug("Starting %s process...\n", __FUNCTION__); + ret = run_command(s, 0); + if (ret < 0) + debug("Error.. %s failed\n", __FUNCTION__); + else + debug("%s process finished\n", __FUNCTION__); +} + +static void kw_sysrst_check(void) +{ + u32 sysrst_cnt, sysrst_dly; + char *s; + + /* + * no action if sysrstdelay environment variable is not defined + */ + s = getenv("sysrstdelay"); + if (s == NULL) + return; + + /* read sysrstdelay value */ + sysrst_dly = (u32) simple_strtoul(s, NULL, 10); + + /* read SysRst Length counter register (bits 28:0) */ + sysrst_cnt = (0x1fffffff & readl(KW_REG_SYSRST_CNT)); + debug("H/w Rst hold time: %d.%d secs\n", + sysrst_cnt / SYSRST_CNT_1SEC_VAL, + sysrst_cnt % SYSRST_CNT_1SEC_VAL); + + /* clear the counter for next valid read*/ + writel(1 << 31, KW_REG_SYSRST_CNT); + + /* + * sysrst_action: + * if H/w Reset key is pressed and hold for time + * more than sysrst_dly in seconds + */ + if (sysrst_cnt >= SYSRST_CNT_1SEC_VAL * sysrst_dly) + kw_sysrst_action(); +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + char *rev; + u16 devid = (readl(KW_REG_PCIE_DEVID) >> 16) & 0xffff; + u8 revid = readl(KW_REG_PCIE_REVID) & 0xff; + + if ((readl(KW_REG_DEVICE_ID) & 0x03) > 2) { + printf("Error.. %s:Unsupported Kirkwood SoC 88F%04x\n", __FUNCTION__, devid); + return -1; + } + + switch (revid) { + case 0: + rev = "Z0"; + break; + case 2: + rev = "A0"; + break; + case 3: + rev = "A1"; + break; + default: + rev = "??"; + break; + } + + printf("SoC: Kirkwood 88F%04x_%s\n", devid, rev); + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ + +#ifdef CONFIG_ARCH_CPU_INIT +int arch_cpu_init(void) +{ + u32 reg; + struct kwcpu_registers *cpureg = + (struct kwcpu_registers *)KW_CPU_REG_BASE; + + /* Linux expects` the internal registers to be at 0xf1000000 */ + writel(KW_REGS_PHY_BASE, KW_OFFSET_REG); + + /* Enable and invalidate L2 cache in write through mode */ + writel(readl(&cpureg->l2_cfg) | 0x18, &cpureg->l2_cfg); + invalidate_l2_cache(); + + kw_config_adr_windows(); + +#ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8 + /* + * Configures the I/O voltage of the pads connected to Egigabit + * Ethernet interface to 1.8V + * By default it is set to 3.3V + */ + reg = readl(KW_REG_MPP_OUT_DRV_REG); + reg |= (1 << 7); + writel(reg, KW_REG_MPP_OUT_DRV_REG); +#endif +#ifdef CONFIG_KIRKWOOD_EGIGA_INIT + /* + * Set egiga port0/1 in normal functional mode + * This is required becasue on kirkwood by default ports are in reset mode + * OS egiga driver may not have provision to set them in normal mode + * and if u-boot is build without network support, network may fail at OS level + */ + reg = readl(KWGBE_PORT_SERIAL_CONTROL1_REG(0)); + reg &= ~(1 << 4); /* Clear PortReset Bit */ + writel(reg, (KWGBE_PORT_SERIAL_CONTROL1_REG(0))); + reg = readl(KWGBE_PORT_SERIAL_CONTROL1_REG(1)); + reg &= ~(1 << 4); /* Clear PortReset Bit */ + writel(reg, (KWGBE_PORT_SERIAL_CONTROL1_REG(1))); +#endif +#ifdef CONFIG_KIRKWOOD_PCIE_INIT + /* + * Enable PCI Express Port0 + */ + reg = readl(&cpureg->ctrl_stat); + reg |= (1 << 0); /* Set PEX0En Bit */ + writel(reg, &cpureg->ctrl_stat); +#endif + return 0; +} +#endif /* CONFIG_ARCH_CPU_INIT */ + +/* + * SOC specific misc init + */ +#if defined(CONFIG_ARCH_MISC_INIT) +int arch_misc_init(void) +{ + volatile u32 temp; + + /*CPU streaming & write allocate */ + temp = readfr_extra_feature_reg(); + temp &= ~(1 << 28); /* disable wr alloc */ + writefr_extra_feature_reg(temp); + + temp = readfr_extra_feature_reg(); + temp &= ~(1 << 29); /* streaming disabled */ + writefr_extra_feature_reg(temp); + + /* L2Cache settings */ + temp = readfr_extra_feature_reg(); + /* Disable L2C pre fetch - Set bit 24 */ + temp |= (1 << 24); + /* enable L2C - Set bit 22 */ + temp |= (1 << 22); + writefr_extra_feature_reg(temp); + + icache_enable(); + /* Change reset vector to address 0x0 */ + temp = get_cr(); + set_cr(temp & ~CR_V); + + /* checks and execute resset to factory event */ + kw_sysrst_check(); + + return 0; +} +#endif /* CONFIG_ARCH_MISC_INIT */ + +#ifdef CONFIG_MVGBE +int cpu_eth_init(bd_t *bis) +{ + mvgbe_initialize(bis); + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/dram.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/dram.c new file mode 100644 index 000000000..d73ae47c3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/dram.c @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <common.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/kirkwood.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct kw_sdram_bank { + u32 win_bar; + u32 win_sz; +}; + +struct kw_sdram_addr_dec { + struct kw_sdram_bank sdram_bank[4]; +}; + +#define KW_REG_CPUCS_WIN_ENABLE (1 << 0) +#define KW_REG_CPUCS_WIN_WR_PROTECT (1 << 1) +#define KW_REG_CPUCS_WIN_WIN0_CS(x) (((x) & 0x3) << 2) +#define KW_REG_CPUCS_WIN_SIZE(x) (((x) & 0xff) << 24) + +/* + * kw_sdram_bar - reads SDRAM Base Address Register + */ +u32 kw_sdram_bar(enum memory_bank bank) +{ + struct kw_sdram_addr_dec *base = + (struct kw_sdram_addr_dec *)KW_REGISTER(0x1500); + u32 result = 0; + u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz); + + if ((!enable) || (bank > BANK3)) + return 0; + + result = readl(&base->sdram_bank[bank].win_bar); + return result; +} + +/* + * kw_sdram_bs_set - writes SDRAM Bank size + */ +static void kw_sdram_bs_set(enum memory_bank bank, u32 size) +{ + struct kw_sdram_addr_dec *base = + (struct kw_sdram_addr_dec *)KW_REGISTER(0x1500); + /* Read current register value */ + u32 reg = readl(&base->sdram_bank[bank].win_sz); + + /* Clear window size */ + reg &= ~KW_REG_CPUCS_WIN_SIZE(0xFF); + + /* Set new window size */ + reg |= KW_REG_CPUCS_WIN_SIZE((size - 1) >> 24); + + writel(reg, &base->sdram_bank[bank].win_sz); +} + +/* + * kw_sdram_bs - reads SDRAM Bank size + */ +u32 kw_sdram_bs(enum memory_bank bank) +{ + struct kw_sdram_addr_dec *base = + (struct kw_sdram_addr_dec *)KW_REGISTER(0x1500); + u32 result = 0; + u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz); + + if ((!enable) || (bank > BANK3)) + return 0; + result = 0xff000000 & readl(&base->sdram_bank[bank].win_sz); + result += 0x01000000; + return result; +} + +void kw_sdram_size_adjust(enum memory_bank bank) +{ + u32 size; + + /* probe currently equipped RAM size */ + size = get_ram_size((void *)kw_sdram_bar(bank), kw_sdram_bs(bank)); + + /* adjust SDRAM window size accordingly */ + kw_sdram_bs_set(bank, size); +} + +#ifndef CONFIG_SYS_BOARD_DRAM_INIT +int dram_init(void) +{ + int i; + + gd->ram_size = 0; + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = kw_sdram_bar(i); + gd->bd->bi_dram[i].size = kw_sdram_bs(i); + /* + * It is assumed that all memory banks are consecutive + * and without gaps. + * If the gap is found, ram_size will be reported for + * consecutive memory only + */ + if (gd->bd->bi_dram[i].start != gd->ram_size) + break; + + gd->ram_size += gd->bd->bi_dram[i].size; + + } + + for (; i < CONFIG_NR_DRAM_BANKS; i++) { + /* If above loop terminated prematurely, we need to set + * remaining banks' start address & size as 0. Otherwise other + * u-boot functions and Linux kernel gets wrong values which + * could result in crash */ + gd->bd->bi_dram[i].start = 0; + gd->bd->bi_dram[i].size = 0; + } + + return 0; +} + +/* + * If this function is not defined here, + * board.c alters dram bank zero configuration defined above. + */ +void dram_init_banksize(void) +{ + dram_init(); +} +#endif /* CONFIG_SYS_BOARD_DRAM_INIT */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/mpp.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/mpp.c new file mode 100644 index 000000000..0ba6f098c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/mpp.c @@ -0,0 +1,90 @@ +/* + * arch/arm/mach-kirkwood/mpp.c + * + * MPP functions for Marvell Kirkwood SoCs + * Referenced from Linux kernel source + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/kirkwood.h> +#include <asm/arch/mpp.h> + +static u32 kirkwood_variant(void) +{ + switch (readl(KW_REG_DEVICE_ID) & 0x03) { + case 1: + return MPP_F6192_MASK; + case 2: + return MPP_F6281_MASK; + default: + debug("MPP setup: unknown kirkwood variant\n"); + return 0; + } +} + +#define MPP_CTRL(i) (KW_MPP_BASE + (i* 4)) +#define MPP_NR_REGS (1 + MPP_MAX/8) + +void kirkwood_mpp_conf(const u32 *mpp_list, u32 *mpp_save) +{ + u32 mpp_ctrl[MPP_NR_REGS]; + unsigned int variant_mask; + int i; + + variant_mask = kirkwood_variant(); + if (!variant_mask) + return; + + debug( "initial MPP regs:"); + for (i = 0; i < MPP_NR_REGS; i++) { + mpp_ctrl[i] = readl(MPP_CTRL(i)); + debug(" %08x", mpp_ctrl[i]); + } + debug("\n"); + + + while (*mpp_list) { + unsigned int num = MPP_NUM(*mpp_list); + unsigned int sel = MPP_SEL(*mpp_list); + unsigned int sel_save; + int shift; + + if (num > MPP_MAX) { + debug("kirkwood_mpp_conf: invalid MPP " + "number (%u)\n", num); + continue; + } + if (!(*mpp_list & variant_mask)) { + debug("kirkwood_mpp_conf: requested MPP%u config " + "unavailable on this hardware\n", num); + continue; + } + + shift = (num & 7) << 2; + + if (mpp_save) { + sel_save = (mpp_ctrl[num / 8] >> shift) & 0xf; + *mpp_save = num | (sel_save << 8) | variant_mask; + mpp_save++; + } + + mpp_ctrl[num / 8] &= ~(0xf << shift); + mpp_ctrl[num / 8] |= sel << shift; + + mpp_list++; + } + + debug(" final MPP regs:"); + for (i = 0; i < MPP_NR_REGS; i++) { + writel(mpp_ctrl[i], MPP_CTRL(i)); + debug(" %08x", mpp_ctrl[i]); + } + debug("\n"); + +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/timer.c new file mode 100644 index 000000000..a08f4a145 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/kirkwood/timer.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/kirkwood.h> + +#define UBOOT_CNTR 0 /* counter to use for uboot timer */ + +/* Timer reload and current value registers */ +struct kwtmr_val { + u32 reload; /* Timer reload reg */ + u32 val; /* Timer value reg */ +}; + +/* Timer registers */ +struct kwtmr_registers { + u32 ctrl; /* Timer control reg */ + u32 pad[3]; + struct kwtmr_val tmr[2]; + u32 wdt_reload; + u32 wdt_val; +}; + +struct kwtmr_registers *kwtmr_regs = (struct kwtmr_registers *)KW_TIMER_BASE; + +/* + * ARM Timers Registers Map + */ +#define CNTMR_CTRL_REG &kwtmr_regs->ctrl +#define CNTMR_RELOAD_REG(tmrnum) &kwtmr_regs->tmr[tmrnum].reload +#define CNTMR_VAL_REG(tmrnum) &kwtmr_regs->tmr[tmrnum].val + +/* + * ARM Timers Control Register + * CPU_TIMERS_CTRL_REG (CTCR) + */ +#define CTCR_ARM_TIMER_EN_OFFS(cntr) (cntr * 2) +#define CTCR_ARM_TIMER_EN_MASK(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS) +#define CTCR_ARM_TIMER_EN(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS(cntr)) +#define CTCR_ARM_TIMER_DIS(cntr) (0 << CTCR_ARM_TIMER_EN_OFFS(cntr)) + +#define CTCR_ARM_TIMER_AUTO_OFFS(cntr) ((cntr * 2) + 1) +#define CTCR_ARM_TIMER_AUTO_MASK(cntr) (1 << 1) +#define CTCR_ARM_TIMER_AUTO_EN(cntr) (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) +#define CTCR_ARM_TIMER_AUTO_DIS(cntr) (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) + +/* + * ARM Timer\Watchdog Reload Register + * CNTMR_RELOAD_REG (TRR) + */ +#define TRG_ARM_TIMER_REL_OFFS 0 +#define TRG_ARM_TIMER_REL_MASK 0xffffffff + +/* + * ARM Timer\Watchdog Register + * CNTMR_VAL_REG (TVRG) + */ +#define TVR_ARM_TIMER_OFFS 0 +#define TVR_ARM_TIMER_MASK 0xffffffff +#define TVR_ARM_TIMER_MAX 0xffffffff +#define TIMER_LOAD_VAL 0xffffffff + +#define READ_TIMER (readl(CNTMR_VAL_REG(UBOOT_CNTR)) / \ + (CONFIG_SYS_TCLK / 1000)) + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp gd->arch.tbl +#define lastdec gd->arch.lastinc + +ulong get_timer_masked(void) +{ + ulong now = READ_TIMER; + + if (lastdec >= now) { + /* normal mode */ + timestamp += lastdec - now; + } else { + /* we have an overflow ... */ + timestamp += lastdec + + (TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now; + } + lastdec = now; + + return timestamp; +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void __udelay(unsigned long usec) +{ + uint current; + ulong delayticks; + + current = readl(CNTMR_VAL_REG(UBOOT_CNTR)); + delayticks = (usec * (CONFIG_SYS_TCLK / 1000000)); + + if (current < delayticks) { + delayticks -= current; + while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) < current) ; + while ((TIMER_LOAD_VAL - delayticks) < + readl(CNTMR_VAL_REG(UBOOT_CNTR))) ; + } else { + while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) > + (current - delayticks)) ; + } +} + +/* + * init the counter + */ +int timer_init(void) +{ + unsigned int cntmrctrl; + + /* load value into timer */ + writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR)); + writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR)); + + /* enable timer in auto reload mode */ + cntmrctrl = readl(CNTMR_CTRL_REG); + cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR); + cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR); + writel(cntmrctrl, CNTMR_CTRL_REG); + + /* init the timestamp and lastdec value */ + lastdec = READ_TIMER; + timestamp = 0; + + return 0; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + return (ulong)CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/Makefile new file mode 100644 index 000000000..314f004eb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o clk.o devices.o timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/clk.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/clk.c new file mode 100644 index 000000000..b7a44d59d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/clk.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clk.h> +#include <asm/io.h> + +static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; + +unsigned int get_sys_clk_rate(void) +{ + if (readl(&clk->sysclk_ctrl) & CLK_SYSCLK_PLL397) + return RTC_CLK_FREQUENCY * 397; + else + return OSC_CLK_FREQUENCY; +} + +unsigned int get_hclk_pll_rate(void) +{ + unsigned long long fin, fref, fcco, fout; + u32 val, m_div, n_div, p_div; + + /* + * Valid frequency ranges: + * 1 * 10^6 <= Fin <= 20 * 10^6 + * 1 * 10^6 <= Fref <= 27 * 10^6 + * 156 * 10^6 <= Fcco <= 320 * 10^6 + */ + + fref = fin = get_sys_clk_rate(); + if (fin > 20000000ULL || fin < 1000000ULL) + return 0; + + val = readl(&clk->hclkpll_ctrl); + m_div = ((val & CLK_HCLK_PLL_FEEDBACK_DIV_MASK) >> 1) + 1; + n_div = ((val & CLK_HCLK_PLL_PREDIV_MASK) >> 9) + 1; + if (val & CLK_HCLK_PLL_DIRECT) + p_div = 0; + else + p_div = ((val & CLK_HCLK_PLL_POSTDIV_MASK) >> 11) + 1; + p_div = 1 << p_div; + + if (val & CLK_HCLK_PLL_BYPASS) { + do_div(fin, p_div); + return fin; + } + + do_div(fref, n_div); + if (fref > 27000000ULL || fref < 1000000ULL) + return 0; + + fout = fref * m_div; + if (val & CLK_HCLK_PLL_FEEDBACK) { + fcco = fout; + do_div(fout, p_div); + } else + fcco = fout * p_div; + + if (fcco > 320000000ULL || fcco < 156000000ULL) + return 0; + + return fout; +} + +unsigned int get_hclk_clk_div(void) +{ + u32 val; + + val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK; + + return 1 << val; +} + +unsigned int get_hclk_clk_rate(void) +{ + return get_hclk_pll_rate() / get_hclk_clk_div(); +} + +unsigned int get_periph_clk_div(void) +{ + u32 val; + + val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_PERIPH_DIV_MASK; + + return (val >> 2) + 1; +} + +unsigned int get_periph_clk_rate(void) +{ + if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN)) + return get_sys_clk_rate(); + + return get_hclk_pll_rate() / get_periph_clk_div(); +} + +int get_serial_clock(void) +{ + return get_periph_clk_rate(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c new file mode 100644 index 000000000..35095a958 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clk.h> +#include <asm/arch/wdt.h> +#include <asm/io.h> + +static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; +static struct wdt_regs *wdt = (struct wdt_regs *)WDT_BASE; + +void reset_cpu(ulong addr) +{ + /* Enable watchdog clock */ + setbits_le32(&clk->timclk_ctrl, CLK_TIMCLK_WATCHDOG); + + /* Reset pulse length is 13005 peripheral clock frames */ + writel(13000, &wdt->pulse); + + /* Force WDOG_RESET2 and RESOUT_N signal active */ + writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1 | WDTIM_MCTRL_M_RES2, + &wdt->mctrl); + + while (1) + /* NOP */; +} + +#if defined(CONFIG_ARCH_CPU_INIT) +int arch_cpu_init(void) +{ + /* + * It might be necessary to flush data cache, if U-boot is loaded + * from kickstart bootloader, e.g. from S1L loader + */ + flush_dcache_all(); + + return 0; +} +#else +#error "You have to select CONFIG_ARCH_CPU_INIT" +#endif + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + printf("CPU: NXP LPC32XX\n"); + printf("CPU clock: %uMHz\n", get_hclk_pll_rate() / 1000000); + printf("AHB bus clock: %uMHz\n", get_hclk_clk_rate() / 1000000); + printf("Peripheral clock: %uMHz\n", get_periph_clk_rate() / 1000000); + + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/devices.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/devices.c new file mode 100644 index 000000000..b5676578f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/devices.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clk.h> +#include <asm/arch/uart.h> +#include <asm/io.h> + +static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; +static struct uart_ctrl_regs *ctrl = (struct uart_ctrl_regs *)UART_CTRL_BASE; + +void lpc32xx_uart_init(unsigned int uart_id) +{ + if (uart_id < 1 || uart_id > 7) + return; + + /* Disable loopback mode, if it is set by S1L bootloader */ + clrbits_le32(&ctrl->loop, + UART_LOOPBACK(CONFIG_SYS_LPC32XX_UART)); + + if (uart_id < 3 || uart_id > 6) + return; + + /* Enable UART system clock */ + setbits_le32(&clk->uartclk_ctrl, CLK_UART(uart_id)); + + /* Set UART into autoclock mode */ + clrsetbits_le32(&ctrl->clkmode, + UART_CLKMODE_MASK(uart_id), + UART_CLKMODE_AUTO(uart_id)); + + /* Bypass pre-divider of UART clock */ + writel(CLK_UART_X_DIV(1) | CLK_UART_Y_DIV(1), + &clk->u3clk + (uart_id - 3)); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/timer.c new file mode 100644 index 000000000..dc1217e69 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/lpc32xx/timer.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2011 Vladimir Zapolskiy <vz@mleia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clk.h> +#include <asm/arch/timer.h> +#include <asm/io.h> + +static struct timer_regs *timer0 = (struct timer_regs *)TIMER0_BASE; +static struct timer_regs *timer1 = (struct timer_regs *)TIMER1_BASE; +static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; + +static void lpc32xx_timer_clock(u32 bit, int enable) +{ + if (enable) + setbits_le32(&clk->timclk_ctrl1, bit); + else + clrbits_le32(&clk->timclk_ctrl1, bit); +} + +static void lpc32xx_timer_reset(struct timer_regs *timer, u32 freq) +{ + writel(TIMER_TCR_COUNTER_RESET, &timer->tcr); + writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr); + writel(0, &timer->tc); + writel(0, &timer->pr); + + /* Count mode is every rising PCLK edge */ + writel(TIMER_CTCR_MODE_TIMER, &timer->ctcr); + + /* Set prescale counter value */ + writel((get_periph_clk_rate() / freq) - 1, &timer->pr); +} + +static void lpc32xx_timer_count(struct timer_regs *timer, int enable) +{ + if (enable) + writel(TIMER_TCR_COUNTER_ENABLE, &timer->tcr); + else + writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr); +} + +int timer_init(void) +{ + lpc32xx_timer_clock(CLK_TIMCLK_TIMER0, 1); + lpc32xx_timer_reset(timer0, CONFIG_SYS_HZ); + lpc32xx_timer_count(timer0, 1); + + return 0; +} + +ulong get_timer(ulong base) +{ + return readl(&timer0->tc) - base; +} + +void __udelay(unsigned long usec) +{ + lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 1); + lpc32xx_timer_reset(timer1, CONFIG_SYS_HZ * 1000); + lpc32xx_timer_count(timer1, 1); + + while (readl(&timer1->tc) < usec) + /* NOP */; + + lpc32xx_timer_count(timer1, 0); + lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 0); +} + +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/Makefile new file mode 100644 index 000000000..365892c41 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = clock.o reset.o timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/clock.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/clock.c new file mode 100644 index 000000000..1f6f66eba --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/clock.c @@ -0,0 +1,27 @@ +/* + * (C) Copyright 2010 + * Matthias Weisser <weisserm@arcor.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +/* + * Get the peripheral bus frequency depending on pll pin settings + */ +ulong get_bus_freq(ulong dummy) +{ + struct mb86r0x_crg * crg = (struct mb86r0x_crg *) + MB86R0x_CRG_BASE; + uint32_t pllmode; + + pllmode = readl(&crg->crpr) & MB86R0x_CRG_CRPR_PLLMODE; + + if (pllmode == MB86R0x_CRG_CRPR_PLLMODE_X20) + return 40000000; + + return 41164767; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/reset.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/reset.c new file mode 100644 index 000000000..7bd77ff20 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/reset.c @@ -0,0 +1,24 @@ +/* + * (C) Copyright 2010 + * Matthias Weisser <weisserm@arcor.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +/* + * Reset the cpu by setting software reset request bit + */ +void reset_cpu(ulong ignored) +{ + struct mb86r0x_crg * crg = (struct mb86r0x_crg *) + MB86R0x_CRG_BASE; + + writel(MB86R0x_CRSR_SWRSTREQ, &crg->crsr); + while (1) + /* NOP */; + /* Never reached */ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/timer.c new file mode 100644 index 000000000..bb078196d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mb86r0x/timer.c @@ -0,0 +1,115 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * (C) Copyright 2010 + * Matthias Weisser, Graf-Syteco <weisserm@arcor.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <div64.h> +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +#define TIMER_LOAD_VAL 0xffffffff +#define TIMER_FREQ (CONFIG_MB86R0x_IOCLK / 256) + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp gd->arch.tbl +#define lastdec gd->arch.lastinc + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, TIMER_FREQ); + + return tick; +} + +static inline unsigned long long usec_to_tick(unsigned long long usec) +{ + usec *= TIMER_FREQ; + do_div(usec, 1000000); + + return usec; +} + +/* nothing really to do with interrupts, just starts up a counter. */ +int timer_init(void) +{ + struct mb86r0x_timer * timer = (struct mb86r0x_timer *) + MB86R0x_TIMER_BASE; + ulong ctrl = readl(&timer->control); + + writel(TIMER_LOAD_VAL, &timer->load); + + ctrl |= MB86R0x_TIMER_ENABLE | MB86R0x_TIMER_PRS_8S | + MB86R0x_TIMER_SIZE_32; + + writel(ctrl, &timer->control); + + /* capture current value time */ + lastdec = readl(&timer->value); + timestamp = 0; /* start "advancing" time stamp from 0 */ + + return 0; +} + +/* + * timer without interrupts + */ +unsigned long long get_ticks(void) +{ + struct mb86r0x_timer * timer = (struct mb86r0x_timer *) + MB86R0x_TIMER_BASE; + ulong now = readl(&timer->value); + + if (now <= lastdec) { + /* normal mode (non roll) */ + /* move stamp forward with absolut diff ticks */ + timestamp += lastdec - now; + } else { + /* we have rollover of incrementer */ + timestamp += lastdec + TIMER_LOAD_VAL - now; + } + lastdec = now; + return timestamp; +} + +ulong get_timer_masked(void) +{ + return tick_to_time(get_ticks()); +} + +void __udelay(unsigned long usec) +{ + unsigned long long tmp; + ulong tmo; + + tmo = usec_to_tick(usec); + tmp = get_ticks(); /* get current timestamp */ + + while ((get_ticks() - tmp) < tmo) /* loop till event */ + /*NOP*/; +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + ulong tbclk; + + tbclk = TIMER_FREQ; + return tbclk; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/Makefile new file mode 100644 index 000000000..134c69d42 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/Makefile @@ -0,0 +1,7 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ + +obj-y = generic.o timer.o reset.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/generic.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/generic.c new file mode 100644 index 000000000..4e9c0b548 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/generic.c @@ -0,0 +1,249 @@ +/* + * (C) Copyright 2009 DENX Software Engineering + * Author: John Rigby <jrigby@gmail.com> + * + * Based on mx27/generic.c: + * Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org> + * Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> + +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> + +DECLARE_GLOBAL_DATA_PTR; +#endif + +/* + * get the system pll clock in Hz + * + * mfi + mfn / (mfd +1) + * f = 2 * f_ref * -------------------- + * pd + 1 + */ +static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref) +{ + unsigned int mfi = (pll >> CCM_PLL_MFI_SHIFT) + & CCM_PLL_MFI_MASK; + int mfn = (pll >> CCM_PLL_MFN_SHIFT) + & CCM_PLL_MFN_MASK; + unsigned int mfd = (pll >> CCM_PLL_MFD_SHIFT) + & CCM_PLL_MFD_MASK; + unsigned int pd = (pll >> CCM_PLL_PD_SHIFT) + & CCM_PLL_PD_MASK; + + mfi = mfi <= 5 ? 5 : mfi; + mfn = mfn >= 512 ? mfn - 1024 : mfn; + mfd += 1; + pd += 1; + + return lldiv(2 * (u64) f_ref * (mfi * mfd + mfn), + mfd * pd); +} + +static ulong imx_get_mpllclk(void) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong fref = MXC_HCLK; + + return imx_decode_pll(readl(&ccm->mpctl), fref); +} + +static ulong imx_get_armclk(void) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong cctl = readl(&ccm->cctl); + ulong fref = imx_get_mpllclk(); + ulong div; + + if (cctl & CCM_CCTL_ARM_SRC) + fref = lldiv((u64) fref * 3, 4); + + div = ((cctl >> CCM_CCTL_ARM_DIV_SHIFT) + & CCM_CCTL_ARM_DIV_MASK) + 1; + + return fref / div; +} + +static ulong imx_get_ahbclk(void) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong cctl = readl(&ccm->cctl); + ulong fref = imx_get_armclk(); + ulong div; + + div = ((cctl >> CCM_CCTL_AHB_DIV_SHIFT) + & CCM_CCTL_AHB_DIV_MASK) + 1; + + return fref / div; +} + +static ulong imx_get_ipgclk(void) +{ + return imx_get_ahbclk() / 2; +} + +static ulong imx_get_perclk(int clk) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong fref = imx_get_ahbclk(); + ulong div; + + div = readl(&ccm->pcdr[CCM_PERCLK_REG(clk)]); + div = ((div >> CCM_PERCLK_SHIFT(clk)) & CCM_PERCLK_MASK) + 1; + + return fref / div; +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + if (clk >= MXC_CLK_NUM) + return -1; + switch (clk) { + case MXC_ARM_CLK: + return imx_get_armclk(); + case MXC_AHB_CLK: + return imx_get_ahbclk(); + case MXC_IPG_CLK: + case MXC_CSPI_CLK: + case MXC_FEC_CLK: + return imx_get_ipgclk(); + default: + return imx_get_perclk(clk); + } +} + +u32 get_cpu_rev(void) +{ + u32 srev; + u32 system_rev = 0x25000; + + /* read SREV register from IIM module */ + struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; + srev = readl(&iim->iim_srev); + + switch (srev) { + case 0x00: + system_rev |= CHIP_REV_1_0; + break; + case 0x01: + system_rev |= CHIP_REV_1_1; + break; + case 0x02: + system_rev |= CHIP_REV_1_2; + break; + default: + system_rev |= 0x8000; + break; + } + + return system_rev; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +static char *get_reset_cause(void) +{ + /* read RCSR register from CCM module */ + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + + u32 cause = readl(&ccm->rcsr) & 0x0f; + + if (cause == 0) + return "POR"; + else if (cause == 1) + return "RST"; + else if ((cause & 2) == 2) + return "WDOG"; + else if ((cause & 4) == 4) + return "SW RESET"; + else if ((cause & 8) == 8) + return "JTAG"; + else + return "unknown reset"; + +} + +int print_cpuinfo(void) +{ + char buf[32]; + u32 cpurev = get_cpu_rev(); + + printf("CPU: Freescale i.MX25 rev%d.%d%s at %s MHz\n", + (cpurev & 0xF0) >> 4, (cpurev & 0x0F), + ((cpurev & 0x8000) ? " unknown" : ""), + strmhz(buf, imx_get_armclk())); + printf("Reset cause: %s\n\n", get_reset_cause()); + return 0; +} +#endif + +void enable_caches(void) +{ +#ifndef CONFIG_SYS_DCACHE_OFF + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +#endif +} + +#if defined(CONFIG_FEC_MXC) +/* + * Initializes on-chip ethernet controllers. + * to override, implement board_eth_init() + */ +int cpu_eth_init(bd_t *bis) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong val; + + val = readl(&ccm->cgr0); + val |= (1 << 23); + writel(val, &ccm->cgr0); + return fecmxc_initialize(bis); +} +#endif + +int get_clocks(void) +{ +#ifdef CONFIG_FSL_ESDHC +#if CONFIG_SYS_FSL_ESDHC_ADDR == IMX_MMC_SDHC2_BASE + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); +#else + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK); +#endif +#endif + return 0; +} + +#ifdef CONFIG_FSL_ESDHC +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ + return fsl_esdhc_mmc_init(bis); +} +#endif + +#ifdef CONFIG_FEC_MXC +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + int i; + struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; + struct fuse_bank *bank = &iim->bank[0]; + struct fuse_bank0_regs *fuse = + (struct fuse_bank0_regs *)bank->fuse_regs; + + for (i = 0; i < 6; i++) + mac[i] = readl(&fuse->mac_addr[i]) & 0xff; +} +#endif /* CONFIG_FEC_MXC */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/reset.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/reset.c new file mode 100644 index 000000000..5db689dbb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/reset.c @@ -0,0 +1,40 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* + * Reset the cpu by setting up the watchdog timer and let it time out + */ +void reset_cpu(ulong ignored) +{ + struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE; + /* Disable watchdog and set Time-Out field to 0 */ + writew(0, ®s->wcr); + + /* Write Service Sequence */ + writew(WSR_UNLOCK1, ®s->wsr); + writew(WSR_UNLOCK2, ®s->wsr); + + /* Enable watchdog */ + writew(WCR_WDE, ®s->wcr); + + while (1) ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/timer.c new file mode 100644 index 000000000..7f1979173 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx25/timer.c @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + * + * (C) Copyright 2009 DENX Software Engineering + * Author: John Rigby <jrigby@gmail.com> + * Add support for MX25 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* nothing really to do with interrupts, just starts up a counter. */ +/* The 32KHz 32-bit timer overruns in 134217 seconds */ +int timer_init(void) +{ + int i; + struct gpt_regs *gpt = (struct gpt_regs *)IMX_GPT1_BASE; + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + + /* setup GP Timer 1 */ + writel(GPT_CTRL_SWR, &gpt->ctrl); + + writel(readl(&ccm->cgr1) | CCM_CGR1_GPT1, &ccm->cgr1); + + for (i = 0; i < 100; i++) + writel(0, &gpt->ctrl); /* We have no udelay by now */ + writel(0, &gpt->pre); /* prescaler = 1 */ + /* Freerun Mode, 32KHz input */ + writel(readl(&gpt->ctrl) | GPT_CTRL_CLKSOURCE_32 | GPT_CTRL_FRR, + &gpt->ctrl); + writel(readl(&gpt->ctrl) | GPT_CTRL_TEN, &gpt->ctrl); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile new file mode 100644 index 000000000..4976bbb89 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile @@ -0,0 +1,7 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ + +obj-y = generic.o reset.o timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c new file mode 100644 index 000000000..5ee9f07d8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org> + * Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/gpio.h> +#ifdef CONFIG_MXC_MMC +#include <asm/arch/mxcmmc.h> +#endif + +/* + * get the system pll clock in Hz + * + * mfi + mfn / (mfd +1) + * f = 2 * f_ref * -------------------- + * pd + 1 + */ +static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref) +{ + unsigned int mfi = (pll >> 10) & 0xf; + unsigned int mfn = pll & 0x3ff; + unsigned int mfd = (pll >> 16) & 0x3ff; + unsigned int pd = (pll >> 26) & 0xf; + + mfi = mfi <= 5 ? 5 : mfi; + + return lldiv(2 * (u64)f_ref * (mfi * (mfd + 1) + mfn), + (mfd + 1) * (pd + 1)); +} + +static ulong clk_in_32k(void) +{ + return 1024 * CONFIG_MX27_CLK32; +} + +static ulong clk_in_26m(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + if (readl(&pll->cscr) & CSCR_OSC26M_DIV1P5) { + /* divide by 1.5 */ + return 26000000 * 2 / 3; + } else { + return 26000000; + } +} + +static ulong imx_get_mpllclk(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + ulong cscr = readl(&pll->cscr); + ulong fref; + + if (cscr & CSCR_MCU_SEL) + fref = clk_in_26m(); + else + fref = clk_in_32k(); + + return imx_decode_pll(readl(&pll->mpctl0), fref); +} + +static ulong imx_get_armclk(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + ulong cscr = readl(&pll->cscr); + ulong fref = imx_get_mpllclk(); + ulong div; + + if (!(cscr & CSCR_ARM_SRC_MPLL)) + fref = lldiv((fref * 2), 3); + + div = ((cscr >> 12) & 0x3) + 1; + + return lldiv(fref, div); +} + +static ulong imx_get_ahbclk(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + ulong cscr = readl(&pll->cscr); + ulong fref = imx_get_mpllclk(); + ulong div; + + div = ((cscr >> 8) & 0x3) + 1; + + return lldiv(fref * 2, 3 * div); +} + +static __attribute__((unused)) ulong imx_get_spllclk(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + ulong cscr = readl(&pll->cscr); + ulong fref; + + if (cscr & CSCR_SP_SEL) + fref = clk_in_26m(); + else + fref = clk_in_32k(); + + return imx_decode_pll(readl(&pll->spctl0), fref); +} + +static ulong imx_decode_perclk(ulong div) +{ + return lldiv((imx_get_mpllclk() * 2), (div * 3)); +} + +static ulong imx_get_perclk1(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + return imx_decode_perclk((readl(&pll->pcdr1) & 0x3f) + 1); +} + +static ulong imx_get_perclk2(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + return imx_decode_perclk(((readl(&pll->pcdr1) >> 8) & 0x3f) + 1); +} + +static __attribute__((unused)) ulong imx_get_perclk3(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + return imx_decode_perclk(((readl(&pll->pcdr1) >> 16) & 0x3f) + 1); +} + +static __attribute__((unused)) ulong imx_get_perclk4(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + return imx_decode_perclk(((readl(&pll->pcdr1) >> 24) & 0x3f) + 1); +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return imx_get_armclk(); + case MXC_I2C_CLK: + return imx_get_ahbclk()/2; + case MXC_UART_CLK: + return imx_get_perclk1(); + case MXC_FEC_CLK: + return imx_get_ahbclk(); + case MXC_ESDHC_CLK: + return imx_get_perclk2(); + } + return -1; +} + + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo (void) +{ + char buf[32]; + + printf("CPU: Freescale i.MX27 at %s MHz\n\n", + strmhz(buf, imx_get_mpllclk())); + return 0; +} +#endif + +int cpu_eth_init(bd_t *bis) +{ +#if defined(CONFIG_FEC_MXC) + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + /* enable FEC clock */ + writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); + writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0); + return fecmxc_initialize(bis); +#else + return 0; +#endif +} + +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ +#ifdef CONFIG_MXC_MMC + return mxc_mmc_init(bis); +#else + return 0; +#endif +} + +void imx_gpio_mode(int gpio_mode) +{ + struct gpio_port_regs *regs = (struct gpio_port_regs *)IMX_GPIO_BASE; + unsigned int pin = gpio_mode & GPIO_PIN_MASK; + unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT; + unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT; + unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT; + unsigned int tmp; + + /* Pullup enable */ + if (gpio_mode & GPIO_PUEN) { + writel(readl(®s->port[port].puen) | (1 << pin), + ®s->port[port].puen); + } else { + writel(readl(®s->port[port].puen) & ~(1 << pin), + ®s->port[port].puen); + } + + /* Data direction */ + if (gpio_mode & GPIO_OUT) { + writel(readl(®s->port[port].gpio_dir) | 1 << pin, + ®s->port[port].gpio_dir); + } else { + writel(readl(®s->port[port].gpio_dir) & ~(1 << pin), + ®s->port[port].gpio_dir); + } + + /* Primary / alternate function */ + if (gpio_mode & GPIO_AF) { + writel(readl(®s->port[port].gpr) | (1 << pin), + ®s->port[port].gpr); + } else { + writel(readl(®s->port[port].gpr) & ~(1 << pin), + ®s->port[port].gpr); + } + + /* use as gpio? */ + if (!(gpio_mode & (GPIO_PF | GPIO_AF))) { + writel(readl(®s->port[port].gius) | (1 << pin), + ®s->port[port].gius); + } else { + writel(readl(®s->port[port].gius) & ~(1 << pin), + ®s->port[port].gius); + } + + /* Output / input configuration */ + if (pin < 16) { + tmp = readl(®s->port[port].ocr1); + tmp &= ~(3 << (pin * 2)); + tmp |= (ocr << (pin * 2)); + writel(tmp, ®s->port[port].ocr1); + + writel(readl(®s->port[port].iconfa1) & ~(3 << (pin * 2)), + ®s->port[port].iconfa1); + writel(readl(®s->port[port].iconfa1) | aout << (pin * 2), + ®s->port[port].iconfa1); + writel(readl(®s->port[port].iconfb1) & ~(3 << (pin * 2)), + ®s->port[port].iconfb1); + writel(readl(®s->port[port].iconfb1) | bout << (pin * 2), + ®s->port[port].iconfb1); + } else { + pin -= 16; + + tmp = readl(®s->port[port].ocr2); + tmp &= ~(3 << (pin * 2)); + tmp |= (ocr << (pin * 2)); + writel(tmp, ®s->port[port].ocr2); + + writel(readl(®s->port[port].iconfa2) & ~(3 << (pin * 2)), + ®s->port[port].iconfa2); + writel(readl(®s->port[port].iconfa2) | aout << (pin * 2), + ®s->port[port].iconfa2); + writel(readl(®s->port[port].iconfb2) & ~(3 << (pin * 2)), + ®s->port[port].iconfb2); + writel(readl(®s->port[port].iconfb2) | bout << (pin * 2), + ®s->port[port].iconfb2); + } +} + +#ifdef CONFIG_MXC_UART +void mx27_uart1_init_pins(void) +{ + int i; + unsigned int mode[] = { + PE12_PF_UART1_TXD, + PE13_PF_UART1_RXD, + }; + + for (i = 0; i < ARRAY_SIZE(mode); i++) + imx_gpio_mode(mode[i]); + +} +#endif /* CONFIG_MXC_UART */ + +#ifdef CONFIG_FEC_MXC +void mx27_fec_init_pins(void) +{ + int i; + unsigned int mode[] = { + PD0_AIN_FEC_TXD0, + PD1_AIN_FEC_TXD1, + PD2_AIN_FEC_TXD2, + PD3_AIN_FEC_TXD3, + PD4_AOUT_FEC_RX_ER, + PD5_AOUT_FEC_RXD1, + PD6_AOUT_FEC_RXD2, + PD7_AOUT_FEC_RXD3, + PD8_AF_FEC_MDIO, + PD9_AIN_FEC_MDC | GPIO_PUEN, + PD10_AOUT_FEC_CRS, + PD11_AOUT_FEC_TX_CLK, + PD12_AOUT_FEC_RXD0, + PD13_AOUT_FEC_RX_DV, + PD14_AOUT_FEC_CLR, + PD15_AOUT_FEC_COL, + PD16_AIN_FEC_TX_ER, + PF23_AIN_FEC_TX_EN, + }; + + for (i = 0; i < ARRAY_SIZE(mode); i++) + imx_gpio_mode(mode[i]); +} + +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + int i; + struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; + struct fuse_bank *bank = &iim->bank[0]; + struct fuse_bank0_regs *fuse = + (struct fuse_bank0_regs *)bank->fuse_regs; + + for (i = 0; i < 6; i++) + mac[6 - 1 - i] = readl(&fuse->mac_addr[i]) & 0xff; +} +#endif /* CONFIG_FEC_MXC */ + +#ifdef CONFIG_MXC_MMC +void mx27_sd1_init_pins(void) +{ + int i; + unsigned int mode[] = { + PE18_PF_SD1_D0, + PE19_PF_SD1_D1, + PE20_PF_SD1_D2, + PE21_PF_SD1_D3, + PE22_PF_SD1_CMD, + PE23_PF_SD1_CLK, + }; + + for (i = 0; i < ARRAY_SIZE(mode); i++) + imx_gpio_mode(mode[i]); + +} + +void mx27_sd2_init_pins(void) +{ + int i; + unsigned int mode[] = { + PB4_PF_SD2_D0, + PB5_PF_SD2_D1, + PB6_PF_SD2_D2, + PB7_PF_SD2_D3, + PB8_PF_SD2_CMD, + PB9_PF_SD2_CLK, + }; + + for (i = 0; i < ARRAY_SIZE(mode); i++) + imx_gpio_mode(mode[i]); + +} +#endif /* CONFIG_MXC_MMC */ + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif /* CONFIG_SYS_DCACHE_OFF */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c new file mode 100644 index 000000000..f7b4a1c83 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* + * Reset the cpu by setting up the watchdog timer and let it time out + */ +void reset_cpu(ulong ignored) +{ + struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE; + /* Disable watchdog and set Time-Out field to 0 */ + writel(0x00000000, ®s->wcr); + + /* Write Service Sequence */ + writel(0x00005555, ®s->wsr); + writel(0x0000AAAA, ®s->wsr); + + /* Enable watchdog */ + writel(WCR_WDE, ®s->wcr); + + while (1); + /*NOTREACHED*/ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c new file mode 100644 index 000000000..40fe2aafc --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c @@ -0,0 +1,162 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* General purpose timers bitfields */ +#define GPTCR_SWR (1 << 15) /* Software reset */ +#define GPTCR_FRR (1 << 8) /* Freerun / restart */ +#define GPTCR_CLKSOURCE_32 (4 << 1) /* Clock source */ +#define GPTCR_TEN 1 /* Timer enable */ + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp (gd->arch.tbl) +#define lastinc (gd->arch.lastinc) + +/* + * "time" is measured in 1 / CONFIG_SYS_HZ seconds, + * "tick" is internal timer period + */ +#ifdef CONFIG_MX27_TIMER_HIGH_PRECISION +/* ~0.4% error - measured with stop-watch on 100s boot-delay */ +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, CONFIG_MX27_CLK32); + return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ + time *= CONFIG_MX27_CLK32; + do_div(time, CONFIG_SYS_HZ); + return time; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us = us * CONFIG_MX27_CLK32 + 999999; + do_div(us, 1000000); + return us; +} +#else +/* ~2% error */ +#define TICK_PER_TIME ((CONFIG_MX27_CLK32 + CONFIG_SYS_HZ / 2) / \ + CONFIG_SYS_HZ) +#define US_PER_TICK (1000000 / CONFIG_MX27_CLK32) + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + do_div(tick, TICK_PER_TIME); + return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ + return time * TICK_PER_TIME; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us += US_PER_TICK - 1; + do_div(us, US_PER_TICK); + return us; +} +#endif + +/* nothing really to do with interrupts, just starts up a counter. */ +/* The 32768Hz 32-bit timer overruns in 131072 seconds */ +int timer_init(void) +{ + int i; + struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE; + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + /* setup GP Timer 1 */ + writel(GPTCR_SWR, ®s->gpt_tctl); + + writel(readl(&pll->pccr0) | PCCR0_GPT1_EN, &pll->pccr0); + writel(readl(&pll->pccr1) | PCCR1_PERCLK1_EN, &pll->pccr1); + + for (i = 0; i < 100; i++) + writel(0, ®s->gpt_tctl); /* We have no udelay by now */ + writel(0, ®s->gpt_tprer); /* 32Khz */ + /* Freerun Mode, PERCLK1 input */ + writel(readl(®s->gpt_tctl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR, + ®s->gpt_tctl); + writel(readl(®s->gpt_tctl) | GPTCR_TEN, ®s->gpt_tctl); + + return 0; +} + +unsigned long long get_ticks(void) +{ + struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE; + ulong now = readl(®s->gpt_tcn); /* current tick value */ + + if (now >= lastinc) { + /* + * normal mode (non roll) + * move stamp forward with absolut diff ticks + */ + timestamp += (now - lastinc); + } else { + /* we have rollover of incrementer */ + timestamp += (0xFFFFFFFF - lastinc) + now; + } + lastinc = now; + return timestamp; +} + +ulong get_timer_masked(void) +{ + /* + * get_ticks() returns a long long (64 bit), it wraps in + * 2^64 / CONFIG_MX27_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ + * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in + * 5 * 10^6 days - long enough. + */ + return tick_to_time(get_ticks()); +} + +ulong 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 tmp; + ulong tmo; + + tmo = us_to_tick(usec); + tmp = get_ticks() + tmo; /* get current timestamp */ + + while (get_ticks() < tmp) /* loop till event */ + /*NOP*/; +} + +ulong get_tbclk(void) +{ + return CONFIG_MX27_CLK32; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/Makefile new file mode 100644 index 000000000..6c5949455 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/Makefile @@ -0,0 +1,85 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-$(CONFIG_SPL_BUILD) := start.o + +obj-y = clock.o mxs.o iomux.o timer.o + +ifdef CONFIG_SPL_BUILD +obj-y += spl_boot.o spl_lradc_init.o spl_mem_init.o spl_power_init.o +endif + +# Specify the target for use in elftosb call +MKIMAGE_TARGET-$(CONFIG_MX23) = mxsimage.mx23.cfg +MKIMAGE_TARGET-$(CONFIG_MX28) = mxsimage.mx28.cfg + +# Generate HAB-capable IVT +# +# Note on computing the post-IVT size field value for the U-Boot binary. +# The value is the result of adding the following: +# -> The size of U-Boot binary aligned to 64B (u-boot.bin) +# -> The size of IVT block aligned to 64B (u-boot.ivt) +# -> The size of U-Boot signature (u-boot.sig), 3904 B +# -> The 64B hole in front of U-Boot binary for 'struct mxs_spl_data' passing +# +quiet_cmd_mkivt_mxs = MXSIVT $@ +cmd_mkivt_mxs = \ + sz=`expr \`stat -c "%s" $^\` + 64 + 3904 + 128` ; \ + echo -n "0x402000d1 $2 0 0 0 $3 $4 0 $$sz 0 0 0 0 0 0 0" | \ + tr -s " " | xargs -d " " -i printf "%08x\n" "{}" | rev | \ + sed "s/\(.\)\(.\)/\\\\\\\\x\2\1\n/g" | xargs -i printf "{}" >$@ + +# Align binary to 64B +quiet_cmd_mkalign_mxs = MXSALGN $@ +cmd_mkalign_mxs = \ + dd if=$^ of=$@ ibs=64 conv=sync 2>/dev/null && \ + mv $@ $^ + +# Assemble the CSF file +quiet_cmd_mkcsfreq_mxs = MXSCSFR $@ +cmd_mkcsfreq_mxs = \ + ivt=$(word 1,$^) ; \ + bin=$(word 2,$^) ; \ + csf=$(word 3,$^) ; \ + sed "s@VENDOR@$(VENDOR)@g;s@BOARD@$(BOARD)@g" "$$csf" | \ + sed '/^\#\#Blocks/ d' > $@ ; \ + echo " Blocks = $2 0x0 `stat -c '%s' $$bin` \"$$bin\" , \\" >> $@ ; \ + echo " $3 0x0 0x40 \"$$ivt\"" >> $@ + +# Sign files +quiet_cmd_mkcst_mxs = MXSCST $@ +cmd_mkcst_mxs = cst -o $@ < $^ \ + $(if $(KBUILD_VERBOSE:1=), >/dev/null) + +spl/u-boot-spl.ivt: spl/u-boot-spl.bin + $(call if_changed,mkalign_mxs) + $(call if_changed,mkivt_mxs,$(CONFIG_SPL_TEXT_BASE),\ + 0x00008000,0x00008040) + +u-boot.ivt: u-boot.bin + $(call if_changed,mkalign_mxs) + $(call if_changed,mkivt_mxs,$(CONFIG_SYS_TEXT_BASE),\ + 0x40001000,0x40001040) + +spl/u-boot-spl.csf: spl/u-boot-spl.ivt spl/u-boot-spl.bin board/$(VENDOR)/$(BOARD)/sign/u-boot-spl.csf + $(call if_changed,mkcsfreq_mxs,$(CONFIG_SPL_TEXT_BASE),0x8000) + +u-boot.csf: u-boot.ivt u-boot.bin board/$(VENDOR)/$(BOARD)/sign/u-boot.csf + $(call if_changed,mkcsfreq_mxs,$(CONFIG_SYS_TEXT_BASE),0x40001000) + +%.sig: %.csf + $(call if_changed,mkcst_mxs) + +quiet_cmd_mkimage_mxs = MKIMAGE $@ +cmd_mkimage_mxs = $(objtree)/tools/mkimage -n $< -T mxsimage $@ \ + $(if $(KBUILD_VERBOSE:1=), >/dev/null) + +u-boot.sb: $(src)/$(MKIMAGE_TARGET-y) u-boot.bin spl/u-boot-spl.bin FORCE + $(call if_changed,mkimage_mxs) + +u-boot-signed.sb: $(src)/mxsimage-signed.cfg u-boot.ivt u-boot.sig spl/u-boot-spl.ivt spl/u-boot-spl.sig FORCE + $(call if_changed,mkimage_mxs) diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/clock.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/clock.c new file mode 100644 index 000000000..e9d8800f8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/clock.c @@ -0,0 +1,436 @@ +/* + * Freescale i.MX23/i.MX28 clock setup code + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * Based on code from LTIB: + * Copyright (C) 2010 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> + +/* + * The PLL frequency is 480MHz and XTAL frequency is 24MHz + * iMX23: datasheet section 4.2 + * iMX28: datasheet section 10.2 + */ +#define PLL_FREQ_KHZ 480000 +#define PLL_FREQ_COEF 18 +#define XTAL_FREQ_KHZ 24000 + +#define PLL_FREQ_MHZ (PLL_FREQ_KHZ / 1000) +#define XTAL_FREQ_MHZ (XTAL_FREQ_KHZ / 1000) + +#if defined(CONFIG_MX23) +#define MXC_SSPCLK_MAX MXC_SSPCLK0 +#elif defined(CONFIG_MX28) +#define MXC_SSPCLK_MAX MXC_SSPCLK3 +#endif + +static uint32_t mxs_get_pclk(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + uint32_t clkctrl, clkseq, div; + uint8_t clkfrac, frac; + + clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu); + + /* No support of fractional divider calculation */ + if (clkctrl & + (CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) { + return 0; + } + + clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq); + + /* XTAL Path */ + if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) { + div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >> + CLKCTRL_CPU_DIV_XTAL_OFFSET; + return XTAL_FREQ_MHZ / div; + } + + /* REF Path */ + clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]); + frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK; + div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK; + return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div; +} + +static uint32_t mxs_get_hclk(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + uint32_t div; + uint32_t clkctrl; + + clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus); + + /* No support of fractional divider calculation */ + if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN) + return 0; + + div = clkctrl & CLKCTRL_HBUS_DIV_MASK; + return mxs_get_pclk() / div; +} + +static uint32_t mxs_get_emiclk(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + uint32_t clkctrl, clkseq, div; + uint8_t clkfrac, frac; + + clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq); + clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi); + + /* XTAL Path */ + if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) { + div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >> + CLKCTRL_EMI_DIV_XTAL_OFFSET; + return XTAL_FREQ_MHZ / div; + } + + /* REF Path */ + clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]); + frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK; + div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK; + return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div; +} + +static uint32_t mxs_get_gpmiclk(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; +#if defined(CONFIG_MX23) + uint8_t *reg = + &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]; +#elif defined(CONFIG_MX28) + uint8_t *reg = + &clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_GPMI]; +#endif + uint32_t clkctrl, clkseq, div; + uint8_t clkfrac, frac; + + clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq); + clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi); + + /* XTAL Path */ + if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) { + div = clkctrl & CLKCTRL_GPMI_DIV_MASK; + return XTAL_FREQ_MHZ / div; + } + + /* REF Path */ + clkfrac = readb(reg); + frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK; + div = clkctrl & CLKCTRL_GPMI_DIV_MASK; + return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div; +} + +/* + * Set IO clock frequency, in kHz + */ +void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + uint32_t div; + int io_reg; + + if (freq == 0) + return; + + if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1)) + return; + + div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq; + + if (div < 18) + div = 18; + + if (div > 35) + div = 35; + + io_reg = CLKCTRL_FRAC0_IO0 - io; /* Register order is reversed */ + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_set[io_reg]); + writeb(CLKCTRL_FRAC_CLKGATE | (div & CLKCTRL_FRAC_FRAC_MASK), + &clkctrl_regs->hw_clkctrl_frac0[io_reg]); + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_clr[io_reg]); +} + +/* + * Get IO clock, returns IO clock in kHz + */ +static uint32_t mxs_get_ioclk(enum mxs_ioclock io) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + uint8_t ret; + int io_reg; + + if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1)) + return 0; + + io_reg = CLKCTRL_FRAC0_IO0 - io; /* Register order is reversed */ + + ret = readb(&clkctrl_regs->hw_clkctrl_frac0[io_reg]) & + CLKCTRL_FRAC_FRAC_MASK; + + return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret; +} + +/* + * Configure SSP clock frequency, in kHz + */ +void mxs_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + uint32_t clk, clkreg; + + if (ssp > MXC_SSPCLK_MAX) + return; + + clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + + (ssp * sizeof(struct mxs_register_32)); + + clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE); + while (readl(clkreg) & CLKCTRL_SSP_CLKGATE) + ; + + if (xtal) + clk = XTAL_FREQ_KHZ; + else + clk = mxs_get_ioclk(ssp >> 1); + + if (freq > clk) + return; + + /* Calculate the divider and cap it if necessary */ + clk /= freq; + if (clk > CLKCTRL_SSP_DIV_MASK) + clk = CLKCTRL_SSP_DIV_MASK; + + clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk); + while (readl(clkreg) & CLKCTRL_SSP_BUSY) + ; + + if (xtal) + writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp, + &clkctrl_regs->hw_clkctrl_clkseq_set); + else + writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp, + &clkctrl_regs->hw_clkctrl_clkseq_clr); +} + +/* + * Return SSP frequency, in kHz + */ +static uint32_t mxs_get_sspclk(enum mxs_sspclock ssp) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + uint32_t clkreg; + uint32_t clk, tmp; + + if (ssp > MXC_SSPCLK_MAX) + return 0; + + tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq); + if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp)) + return XTAL_FREQ_KHZ; + + clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + + (ssp * sizeof(struct mxs_register_32)); + + tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK; + + if (tmp == 0) + return 0; + + clk = mxs_get_ioclk(ssp >> 1); + + return clk / tmp; +} + +/* + * Set SSP/MMC bus frequency, in kHz) + */ +void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq) +{ + struct mxs_ssp_regs *ssp_regs; + const enum mxs_sspclock clk = mxs_ssp_clock_by_bus(bus); + const uint32_t sspclk = mxs_get_sspclk(clk); + uint32_t reg; + uint32_t divide, rate, tgtclk; + + ssp_regs = mxs_ssp_regs_by_bus(bus); + + /* + * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)), + * CLOCK_DIVIDE has to be an even value from 2 to 254, and + * CLOCK_RATE could be any integer from 0 to 255. + */ + for (divide = 2; divide < 254; divide += 2) { + rate = sspclk / freq / divide; + if (rate <= 256) + break; + } + + tgtclk = sspclk / divide / rate; + while (tgtclk > freq) { + rate++; + tgtclk = sspclk / divide / rate; + } + if (rate > 256) + rate = 256; + + /* Always set timeout the maximum */ + reg = SSP_TIMING_TIMEOUT_MASK | + (divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) | + ((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET); + writel(reg, &ssp_regs->hw_ssp_timing); + + debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n", + bus, tgtclk, freq); +} + +void mxs_set_lcdclk(uint32_t freq) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + uint32_t fp, x, k_rest, k_best, x_best, tk; + int32_t k_best_l = 999, k_best_t = 0, x_best_l = 0xff, x_best_t = 0xff; + + if (freq == 0) + return; + +#if defined(CONFIG_MX23) + writel(CLKCTRL_CLKSEQ_BYPASS_PIX, &clkctrl_regs->hw_clkctrl_clkseq_clr); +#elif defined(CONFIG_MX28) + writel(CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF, &clkctrl_regs->hw_clkctrl_clkseq_clr); +#endif + + /* + * / 18 \ 1 1 + * freq kHz = | 480000000 Hz * -- | * --- * ------ + * \ x / k 1000 + * + * 480000000 Hz 18 + * ------------ * -- + * freq kHz x + * k = ------------------- + * 1000 + */ + + fp = ((PLL_FREQ_KHZ * 1000) / freq) * 18; + + for (x = 18; x <= 35; x++) { + tk = fp / x; + if ((tk / 1000 == 0) || (tk / 1000 > 255)) + continue; + + k_rest = tk % 1000; + + if (k_rest < (k_best_l % 1000)) { + k_best_l = tk; + x_best_l = x; + } + + if (k_rest > (k_best_t % 1000)) { + k_best_t = tk; + x_best_t = x; + } + } + + if (1000 - (k_best_t % 1000) > (k_best_l % 1000)) { + k_best = k_best_l; + x_best = x_best_l; + } else { + k_best = k_best_t; + x_best = x_best_t; + } + + k_best /= 1000; + +#if defined(CONFIG_MX23) + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_PIX]); + writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK), + &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_PIX]); + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_PIX]); + + writel(CLKCTRL_PIX_CLKGATE, + &clkctrl_regs->hw_clkctrl_pix_set); + clrsetbits_le32(&clkctrl_regs->hw_clkctrl_pix, + CLKCTRL_PIX_DIV_MASK | CLKCTRL_PIX_CLKGATE, + k_best << CLKCTRL_PIX_DIV_OFFSET); + + while (readl(&clkctrl_regs->hw_clkctrl_pix) & CLKCTRL_PIX_BUSY) + ; +#elif defined(CONFIG_MX28) + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac1_set[CLKCTRL_FRAC1_PIX]); + writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK), + &clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_PIX]); + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac1_clr[CLKCTRL_FRAC1_PIX]); + + writel(CLKCTRL_DIS_LCDIF_CLKGATE, + &clkctrl_regs->hw_clkctrl_lcdif_set); + clrsetbits_le32(&clkctrl_regs->hw_clkctrl_lcdif, + CLKCTRL_DIS_LCDIF_DIV_MASK | CLKCTRL_DIS_LCDIF_CLKGATE, + k_best << CLKCTRL_DIS_LCDIF_DIV_OFFSET); + + while (readl(&clkctrl_regs->hw_clkctrl_lcdif) & CLKCTRL_DIS_LCDIF_BUSY) + ; +#endif +} + +uint32_t mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return mxs_get_pclk() * 1000000; + case MXC_GPMI_CLK: + return mxs_get_gpmiclk() * 1000000; + case MXC_AHB_CLK: + case MXC_IPG_CLK: + return mxs_get_hclk() * 1000000; + case MXC_EMI_CLK: + return mxs_get_emiclk(); + case MXC_IO0_CLK: + return mxs_get_ioclk(MXC_IOCLK0); + case MXC_IO1_CLK: + return mxs_get_ioclk(MXC_IOCLK1); + case MXC_XTAL_CLK: + return XTAL_FREQ_KHZ * 1000; + case MXC_SSP0_CLK: + return mxs_get_sspclk(MXC_SSPCLK0); +#ifdef CONFIG_MX28 + case MXC_SSP1_CLK: + return mxs_get_sspclk(MXC_SSPCLK1); + case MXC_SSP2_CLK: + return mxs_get_sspclk(MXC_SSPCLK2); + case MXC_SSP3_CLK: + return mxs_get_sspclk(MXC_SSPCLK3); +#endif + } + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/iomux.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/iomux.c new file mode 100644 index 000000000..2e6be06fd --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/iomux.c @@ -0,0 +1,97 @@ +/* + * Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de> + * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH, + * <armlinux@phytec.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/iomux.h> +#include <asm/arch/imx-regs.h> + +#if defined(CONFIG_MX23) +#define DRIVE_OFFSET 0x200 +#define PULL_OFFSET 0x400 +#elif defined(CONFIG_MX28) +#define DRIVE_OFFSET 0x300 +#define PULL_OFFSET 0x600 +#else +#error "Please select CONFIG_MX23 or CONFIG_MX28" +#endif + +/* + * configures a single pad in the iomuxer + */ +int mxs_iomux_setup_pad(iomux_cfg_t pad) +{ + u32 reg, ofs, bp, bm; + void *iomux_base = (void *)MXS_PINCTRL_BASE; + struct mxs_register_32 *mxs_reg; + + /* muxsel */ + ofs = 0x100; + ofs += PAD_BANK(pad) * 0x20 + PAD_PIN(pad) / 16 * 0x10; + bp = PAD_PIN(pad) % 16 * 2; + bm = 0x3 << bp; + reg = readl(iomux_base + ofs); + reg &= ~bm; + reg |= PAD_MUXSEL(pad) << bp; + writel(reg, iomux_base + ofs); + + /* drive */ + ofs = DRIVE_OFFSET; + ofs += PAD_BANK(pad) * 0x40 + PAD_PIN(pad) / 8 * 0x10; + /* mA */ + if (PAD_MA_VALID(pad)) { + bp = PAD_PIN(pad) % 8 * 4; + bm = 0x3 << bp; + reg = readl(iomux_base + ofs); + reg &= ~bm; + reg |= PAD_MA(pad) << bp; + writel(reg, iomux_base + ofs); + } + /* vol */ + if (PAD_VOL_VALID(pad)) { + bp = PAD_PIN(pad) % 8 * 4 + 2; + mxs_reg = (struct mxs_register_32 *)(iomux_base + ofs); + if (PAD_VOL(pad)) + writel(1 << bp, &mxs_reg->reg_set); + else + writel(1 << bp, &mxs_reg->reg_clr); + } + + /* pull */ + if (PAD_PULL_VALID(pad)) { + ofs = PULL_OFFSET; + ofs += PAD_BANK(pad) * 0x10; + bp = PAD_PIN(pad); + mxs_reg = (struct mxs_register_32 *)(iomux_base + ofs); + if (PAD_PULL(pad)) + writel(1 << bp, &mxs_reg->reg_set); + else + writel(1 << bp, &mxs_reg->reg_clr); + } + + return 0; +} + +int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count) +{ + const iomux_cfg_t *p = pad_list; + int i; + int ret; + + for (i = 0; i < count; i++) { + ret = mxs_iomux_setup_pad(*p); + if (ret) + return ret; + p++; + } + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxs.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxs.c new file mode 100644 index 000000000..365542fe0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxs.c @@ -0,0 +1,299 @@ +/* + * Freescale i.MX23/i.MX28 common code + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * Based on code from LTIB: + * Copyright (C) 2010 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/imx-common/dma.h> +#include <asm/arch/gpio.h> +#include <asm/arch/iomux.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> +#include <linux/compiler.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Lowlevel init isn't used on i.MX28, so just have a dummy here */ +inline void lowlevel_init(void) {} + +void reset_cpu(ulong ignored) __attribute__((noreturn)); + +void reset_cpu(ulong ignored) +{ + struct mxs_rtc_regs *rtc_regs = + (struct mxs_rtc_regs *)MXS_RTC_BASE; + struct mxs_lcdif_regs *lcdif_regs = + (struct mxs_lcdif_regs *)MXS_LCDIF_BASE; + + /* + * Shut down the LCD controller as it interferes with BootROM boot mode + * pads sampling. + */ + writel(LCDIF_CTRL_RUN, &lcdif_regs->hw_lcdif_ctrl_clr); + + /* Wait 1 uS before doing the actual watchdog reset */ + writel(1, &rtc_regs->hw_rtc_watchdog); + writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set); + + /* Endless loop, reset will exit from here */ + for (;;) + ; +} + +void enable_caches(void) +{ +#ifndef CONFIG_SYS_ICACHE_OFF + icache_enable(); +#endif +#ifndef CONFIG_SYS_DCACHE_OFF + dcache_enable(); +#endif +} + +/* + * This function will craft a jumptable at 0x0 which will redirect interrupt + * vectoring to proper location of U-Boot in RAM. + * + * The structure of the jumptable will be as follows: + * ldr pc, [pc, #0x18] ..... for each vector, thus repeated 8 times + * <destination address> ... for each previous ldr, thus also repeated 8 times + * + * The "ldr pc, [pc, #0x18]" instruction above loads address from memory at + * offset 0x18 from current value of PC register. Note that PC is already + * incremented by 4 when computing the offset, so the effective offset is + * actually 0x20, this the associated <destination address>. Loading the PC + * register with an address performs a jump to that address. + */ +void mx28_fixup_vt(uint32_t start_addr) +{ + /* ldr pc, [pc, #0x18] */ + const uint32_t ldr_pc = 0xe59ff018; + /* Jumptable location is 0x0 */ + uint32_t *vt = (uint32_t *)0x0; + int i; + + for (i = 0; i < 8; i++) { + vt[i] = ldr_pc; + vt[i + 8] = start_addr + (4 * i); + } +} + +#ifdef CONFIG_ARCH_MISC_INIT +int arch_misc_init(void) +{ + mx28_fixup_vt(gd->relocaddr); + return 0; +} +#endif + +int arch_cpu_init(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + extern uint32_t _start; + + mx28_fixup_vt((uint32_t)&_start); + + /* + * Enable NAND clock + */ + /* Clear bypass bit */ + writel(CLKCTRL_CLKSEQ_BYPASS_GPMI, + &clkctrl_regs->hw_clkctrl_clkseq_set); + + /* Set GPMI clock to ref_gpmi / 12 */ + clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi, + CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1); + + udelay(1000); + + /* + * Configure GPIO unit + */ + mxs_gpio_init(); + +#ifdef CONFIG_APBH_DMA + /* Start APBH DMA */ + mxs_dma_init(); +#endif + + return 0; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +static const char *get_cpu_type(void) +{ + struct mxs_digctl_regs *digctl_regs = + (struct mxs_digctl_regs *)MXS_DIGCTL_BASE; + + switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) { + case HW_DIGCTL_CHIPID_MX23: + return "23"; + case HW_DIGCTL_CHIPID_MX28: + return "28"; + default: + return "??"; + } +} + +static const char *get_cpu_rev(void) +{ + struct mxs_digctl_regs *digctl_regs = + (struct mxs_digctl_regs *)MXS_DIGCTL_BASE; + uint8_t rev = readl(&digctl_regs->hw_digctl_chipid) & 0x000000FF; + + switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) { + case HW_DIGCTL_CHIPID_MX23: + switch (rev) { + case 0x0: + return "1.0"; + case 0x1: + return "1.1"; + case 0x2: + return "1.2"; + case 0x3: + return "1.3"; + case 0x4: + return "1.4"; + default: + return "??"; + } + case HW_DIGCTL_CHIPID_MX28: + switch (rev) { + case 0x1: + return "1.2"; + default: + return "??"; + } + default: + return "??"; + } +} + +int print_cpuinfo(void) +{ + struct mxs_spl_data *data = (struct mxs_spl_data *) + ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf); + + printf("CPU: Freescale i.MX%s rev%s at %d MHz\n", + get_cpu_type(), + get_cpu_rev(), + mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("BOOT: %s\n", mxs_boot_modes[data->boot_mode_idx].mode); + return 0; +} +#endif + +int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + printf("CPU: %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("BUS: %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000); + printf("EMI: %3d MHz\n", mxc_get_clock(MXC_EMI_CLK)); + printf("GPMI: %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000); + return 0; +} + +/* + * Initializes on-chip ethernet controllers. + */ +#if defined(CONFIG_MX28) && defined(CONFIG_CMD_NET) +int cpu_eth_init(bd_t *bis) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + /* Turn on ENET clocks */ + clrbits_le32(&clkctrl_regs->hw_clkctrl_enet, + CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE); + + /* Set up ENET PLL for 50 MHz */ + /* Power on ENET PLL */ + writel(CLKCTRL_PLL2CTRL0_POWER, + &clkctrl_regs->hw_clkctrl_pll2ctrl0_set); + + udelay(10); + + /* Gate on ENET PLL */ + writel(CLKCTRL_PLL2CTRL0_CLKGATE, + &clkctrl_regs->hw_clkctrl_pll2ctrl0_clr); + + /* Enable pad output */ + setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN); + + return 0; +} +#endif + +__weak void mx28_adjust_mac(int dev_id, unsigned char *mac) +{ + mac[0] = 0x00; + mac[1] = 0x04; /* Use FSL vendor MAC address by default */ + + if (dev_id == 1) /* Let MAC1 be MAC0 + 1 by default */ + mac[5] += 1; +} + +#ifdef CONFIG_MX28_FEC_MAC_IN_OCOTP + +#define MXS_OCOTP_MAX_TIMEOUT 1000000 +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + struct mxs_ocotp_regs *ocotp_regs = + (struct mxs_ocotp_regs *)MXS_OCOTP_BASE; + uint32_t data; + + memset(mac, 0, 6); + + writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set); + + if (mxs_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY, + MXS_OCOTP_MAX_TIMEOUT)) { + printf("MXS FEC: Can't get MAC from OCOTP\n"); + return; + } + + data = readl(&ocotp_regs->hw_ocotp_cust0); + + mac[2] = (data >> 24) & 0xff; + mac[3] = (data >> 16) & 0xff; + mac[4] = (data >> 8) & 0xff; + mac[5] = data & 0xff; + mx28_adjust_mac(dev_id, mac); +} +#else +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + memset(mac, 0, 6); +} +#endif + +int mxs_dram_init(void) +{ + struct mxs_spl_data *data = (struct mxs_spl_data *) + ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf); + + if (data->mem_dram_size == 0) { + printf("MXS:\n" + "Error, the RAM size passed up from SPL is 0!\n"); + hang(); + } + + gd->ram_size = data->mem_dram_size; + return 0; +} + +U_BOOT_CMD( + clocks, CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks, + "display clocks", + "" +); diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxs_init.h b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxs_init.h new file mode 100644 index 000000000..1200ae1ad --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxs_init.h @@ -0,0 +1,29 @@ +/* + * Freescale i.MX28 SPL functions + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __M28_INIT_H__ +#define __M28_INIT_H__ + +void early_delay(int delay); + +void mxs_power_init(void); + +#ifdef CONFIG_SPL_MXS_PSWITCH_WAIT +void mxs_power_wait_pswitch(void); +#else +static inline void mxs_power_wait_pswitch(void) { } +#endif + +void mxs_mem_init(void); +uint32_t mxs_mem_get_size(void); + +void mxs_lradc_init(void); +void mxs_lradc_enable_batt_measurement(void); + +#endif /* __M28_INIT_H__ */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxsimage-signed.cfg b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxsimage-signed.cfg new file mode 100644 index 000000000..1520bba3f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxsimage-signed.cfg @@ -0,0 +1,10 @@ +SECTION 0x0 BOOTABLE + TAG LAST + LOAD 0x1000 spl/u-boot-spl.bin + LOAD 0x8000 spl/u-boot-spl.ivt + LOAD 0x8040 spl/u-boot-spl.sig + CALL HAB 0x8000 0x0 + LOAD 0x40002000 u-boot.bin + LOAD 0x40001000 u-boot.ivt + LOAD 0x40001040 u-boot.sig + CALL HAB 0x40001000 0x0 diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx23.cfg b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx23.cfg new file mode 100644 index 000000000..55510e9cd --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx23.cfg @@ -0,0 +1,6 @@ +SECTION 0x0 BOOTABLE + TAG LAST + LOAD 0x1000 spl/u-boot-spl.bin + CALL 0x1000 0x0 + LOAD 0x40002000 u-boot.bin + CALL 0x40002000 0x0 diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx28.cfg b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx28.cfg new file mode 100644 index 000000000..bb78cb0c8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx28.cfg @@ -0,0 +1,8 @@ +SECTION 0x0 BOOTABLE + TAG LAST + LOAD 0x1000 spl/u-boot-spl.bin + LOAD IVT 0x8000 0x1000 + CALL HAB 0x8000 0x0 + LOAD 0x40002000 u-boot.bin + LOAD IVT 0x8000 0x40002000 + CALL HAB 0x8000 0x0 diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_boot.c new file mode 100644 index 000000000..d3e136991 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_boot.c @@ -0,0 +1,170 @@ +/* + * Freescale i.MX28 Boot setup + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> +#include <asm/gpio.h> +#include <linux/compiler.h> + +#include "mxs_init.h" + +DECLARE_GLOBAL_DATA_PTR; +static gd_t gdata __section(".data"); +#ifdef CONFIG_SPL_SERIAL_SUPPORT +static bd_t bdata __section(".data"); +#endif + +/* + * This delay function is intended to be used only in early stage of boot, where + * clock are not set up yet. The timer used here is reset on every boot and + * takes a few seconds to roll. The boot doesn't take that long, so to keep the + * code simple, it doesn't take rolling into consideration. + */ +void early_delay(int delay) +{ + struct mxs_digctl_regs *digctl_regs = + (struct mxs_digctl_regs *)MXS_DIGCTL_BASE; + + uint32_t st = readl(&digctl_regs->hw_digctl_microseconds); + st += delay; + while (st > readl(&digctl_regs->hw_digctl_microseconds)) + ; +} + +#define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL) +static const iomux_cfg_t iomux_boot[] = { +#if defined(CONFIG_MX23) + MX23_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD, + MX23_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD, + MX23_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD, + MX23_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD, + MX23_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD, + MX23_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD, +#elif defined(CONFIG_MX28) + MX28_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD, + MX28_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD, + MX28_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD, + MX28_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD, + MX28_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD, + MX28_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD, +#endif +}; + +static uint8_t mxs_get_bootmode_index(void) +{ + uint8_t bootmode = 0; + int i; + uint8_t masked; + + /* Setup IOMUX of bootmode pads to GPIO */ + mxs_iomux_setup_multiple_pads(iomux_boot, ARRAY_SIZE(iomux_boot)); + +#if defined(CONFIG_MX23) + /* Setup bootmode pins as GPIO input */ + gpio_direction_input(MX23_PAD_LCD_D00__GPIO_1_0); + gpio_direction_input(MX23_PAD_LCD_D01__GPIO_1_1); + gpio_direction_input(MX23_PAD_LCD_D02__GPIO_1_2); + gpio_direction_input(MX23_PAD_LCD_D03__GPIO_1_3); + gpio_direction_input(MX23_PAD_LCD_D05__GPIO_1_5); + + /* Read bootmode pads */ + bootmode |= (gpio_get_value(MX23_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0; + bootmode |= (gpio_get_value(MX23_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1; + bootmode |= (gpio_get_value(MX23_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2; + bootmode |= (gpio_get_value(MX23_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3; + bootmode |= (gpio_get_value(MX23_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5; +#elif defined(CONFIG_MX28) + /* Setup bootmode pins as GPIO input */ + gpio_direction_input(MX28_PAD_LCD_D00__GPIO_1_0); + gpio_direction_input(MX28_PAD_LCD_D01__GPIO_1_1); + gpio_direction_input(MX28_PAD_LCD_D02__GPIO_1_2); + gpio_direction_input(MX28_PAD_LCD_D03__GPIO_1_3); + gpio_direction_input(MX28_PAD_LCD_D04__GPIO_1_4); + gpio_direction_input(MX28_PAD_LCD_D05__GPIO_1_5); + + /* Read bootmode pads */ + bootmode |= (gpio_get_value(MX28_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0; + bootmode |= (gpio_get_value(MX28_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1; + bootmode |= (gpio_get_value(MX28_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2; + bootmode |= (gpio_get_value(MX28_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3; + bootmode |= (gpio_get_value(MX28_PAD_LCD_D04__GPIO_1_4) ? 1 : 0) << 4; + bootmode |= (gpio_get_value(MX28_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5; +#endif + + for (i = 0; i < ARRAY_SIZE(mxs_boot_modes); i++) { + masked = bootmode & mxs_boot_modes[i].boot_mask; + if (masked == mxs_boot_modes[i].boot_pads) + break; + } + + return i; +} + +static void mxs_spl_fixup_vectors(void) +{ + /* + * Copy our vector table to 0x0, since due to HAB, we cannot + * be loaded to 0x0. We want to have working vectoring though, + * thus this fixup. Our vectoring table is PIC, so copying is + * fine. + */ + extern uint32_t _start; + memcpy(0x0, &_start, 0x60); +} + +static void mxs_spl_console_init(void) +{ +#ifdef CONFIG_SPL_SERIAL_SUPPORT + gd->bd = &bdata; + gd->baudrate = CONFIG_BAUDRATE; + serial_init(); + gd->have_console = 1; +#endif +} + +void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr, + const iomux_cfg_t *iomux_setup, + const unsigned int iomux_size) +{ + struct mxs_spl_data *data = (struct mxs_spl_data *) + ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf); + uint8_t bootmode = mxs_get_bootmode_index(); + gd = &gdata; + + mxs_spl_fixup_vectors(); + + mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size); + + mxs_spl_console_init(); + + mxs_power_init(); + + mxs_mem_init(); + data->mem_dram_size = mxs_mem_get_size(); + + data->boot_mode_idx = bootmode; + + mxs_power_wait_pswitch(); +} + +/* Support aparatus */ +inline void board_init_f(unsigned long bootflag) +{ + for (;;) + ; +} + +inline void board_init_r(gd_t *id, ulong dest_addr) +{ + for (;;) + ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c new file mode 100644 index 000000000..cdfcddd82 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c @@ -0,0 +1,70 @@ +/* + * Freescale i.MX28 Battery measurement init + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +#include "mxs_init.h" + +void mxs_lradc_init(void) +{ + struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE; + + writel(LRADC_CTRL0_SFTRST, ®s->hw_lradc_ctrl0_clr); + writel(LRADC_CTRL0_CLKGATE, ®s->hw_lradc_ctrl0_clr); + writel(LRADC_CTRL0_ONCHIP_GROUNDREF, ®s->hw_lradc_ctrl0_clr); + + clrsetbits_le32(®s->hw_lradc_ctrl3, + LRADC_CTRL3_CYCLE_TIME_MASK, + LRADC_CTRL3_CYCLE_TIME_6MHZ); + + clrsetbits_le32(®s->hw_lradc_ctrl4, + LRADC_CTRL4_LRADC7SELECT_MASK | + LRADC_CTRL4_LRADC6SELECT_MASK, + LRADC_CTRL4_LRADC7SELECT_CHANNEL7 | + LRADC_CTRL4_LRADC6SELECT_CHANNEL10); +} + +void mxs_lradc_enable_batt_measurement(void) +{ + struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE; + + /* Check if the channel is present at all. */ + if (!(readl(®s->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT)) + return; + + writel(LRADC_CTRL1_LRADC7_IRQ_EN, ®s->hw_lradc_ctrl1_clr); + writel(LRADC_CTRL1_LRADC7_IRQ, ®s->hw_lradc_ctrl1_clr); + + clrsetbits_le32(®s->hw_lradc_conversion, + LRADC_CONVERSION_SCALE_FACTOR_MASK, + LRADC_CONVERSION_SCALE_FACTOR_LI_ION); + writel(LRADC_CONVERSION_AUTOMATIC, ®s->hw_lradc_conversion_set); + + /* Configure the channel. */ + writel((1 << 7) << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET, + ®s->hw_lradc_ctrl2_clr); + writel(0xffffffff, ®s->hw_lradc_ch7_clr); + clrbits_le32(®s->hw_lradc_ch7, LRADC_CH_NUM_SAMPLES_MASK); + writel(LRADC_CH_ACCUMULATE, ®s->hw_lradc_ch7_clr); + + /* Schedule the channel. */ + writel(1 << 7, ®s->hw_lradc_ctrl0_set); + + /* Start the channel sampling. */ + writel(((1 << 7) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) | + ((1 << 3) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) | + 100, ®s->hw_lradc_delay3); + + writel(0xffffffff, ®s->hw_lradc_ch7_clr); + + writel(LRADC_DELAY_KICK, ®s->hw_lradc_delay3_set); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c new file mode 100644 index 000000000..3baf4ddef --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c @@ -0,0 +1,331 @@ +/* + * Freescale i.MX28 RAM init + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> +#include <linux/compiler.h> + +#include "mxs_init.h" + +static uint32_t dram_vals[] = { +/* + * i.MX28 DDR2 at 200MHz + */ +#if defined(CONFIG_MX28) + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00010101, 0x01010101, + 0x000f0f01, 0x0f02020a, 0x00000000, 0x00010101, + 0x00000100, 0x00000100, 0x00000000, 0x00000002, + 0x01010000, 0x07080403, 0x06005003, 0x0a0000c8, + 0x02009c40, 0x0002030c, 0x0036a609, 0x031a0612, + 0x02030202, 0x00c8001c, 0x00000000, 0x00000000, + 0x00012100, 0xffff0303, 0x00012100, 0xffff0303, + 0x00012100, 0xffff0303, 0x00012100, 0xffff0303, + 0x00000003, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000612, 0x01000F02, + 0x06120612, 0x00000200, 0x00020007, 0xf4004a27, + 0xf4004a27, 0xf4004a27, 0xf4004a27, 0x07000300, + 0x07000300, 0x07400300, 0x07400300, 0x00000005, + 0x00000000, 0x00000000, 0x01000000, 0x01020408, + 0x08040201, 0x000f1133, 0x00000000, 0x00001f04, + 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, + 0x00001f04, 0x00001f04, 0x00001f04, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00010000, 0x00030404, + 0x00000003, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x01010000, + 0x01000000, 0x03030000, 0x00010303, 0x01020202, + 0x00000000, 0x02040303, 0x21002103, 0x00061200, + 0x06120612, 0x04420442, 0x04420442, 0x00040004, + 0x00040004, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff + +/* + * i.MX23 DDR at 133MHz + */ +#elif defined(CONFIG_MX23) + 0x01010001, 0x00010100, 0x01000101, 0x00000001, + 0x00000101, 0x00000000, 0x00010000, 0x01000001, + 0x00000000, 0x00000001, 0x07000200, 0x00070202, + 0x02020000, 0x04040a01, 0x00000201, 0x02040000, + 0x02000000, 0x19000f08, 0x0d0d0000, 0x02021313, + 0x02061521, 0x0000000a, 0x00080008, 0x00200020, + 0x00200020, 0x00200020, 0x000003f7, 0x00000000, + 0x00000000, 0x00000020, 0x00000020, 0x00c80000, + 0x000a23cd, 0x000000c8, 0x00006665, 0x00000000, + 0x00000101, 0x00040001, 0x00000000, 0x00000000, + 0x00010000 +#else +#error Unsupported memory initialization +#endif +}; + +__weak void mxs_adjust_memory_params(uint32_t *dram_vals) +{ +} + +#ifdef CONFIG_MX28 +static void initialize_dram_values(void) +{ + int i; + + mxs_adjust_memory_params(dram_vals); + + for (i = 0; i < ARRAY_SIZE(dram_vals); i++) + writel(dram_vals[i], MXS_DRAM_BASE + (4 * i)); +} +#else +static void initialize_dram_values(void) +{ + int i; + + mxs_adjust_memory_params(dram_vals); + + /* + * HW_DRAM_CTL27, HW_DRAM_CTL28 and HW_DRAM_CTL35 are not initialized as + * per FSL bootlets code. + * + * mx23 Reference Manual marks HW_DRAM_CTL27 and HW_DRAM_CTL28 as + * "reserved". + * HW_DRAM_CTL8 is setup as the last element. + * So skip the initialization of these HW_DRAM_CTL registers. + */ + for (i = 0; i < ARRAY_SIZE(dram_vals); i++) { + if (i == 8 || i == 27 || i == 28 || i == 35) + continue; + writel(dram_vals[i], MXS_DRAM_BASE + (4 * i)); + } + + /* + * Enable tRAS lockout in HW_DRAM_CTL08 ; it must be the last + * element to be set + */ + writel((1 << 24), MXS_DRAM_BASE + (4 * 8)); +} +#endif + +static void mxs_mem_init_clock(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; +#if defined(CONFIG_MX23) + /* Fractional divider for ref_emi is 33 ; 480 * 18 / 33 = 266MHz */ + const unsigned char divider = 33; +#elif defined(CONFIG_MX28) + /* Fractional divider for ref_emi is 21 ; 480 * 18 / 21 = 411MHz */ + const unsigned char divider = 21; +#endif + + /* Gate EMI clock */ + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]); + + /* Set fractional divider for ref_emi */ + writeb(CLKCTRL_FRAC_CLKGATE | (divider & CLKCTRL_FRAC_FRAC_MASK), + &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]); + + /* Ungate EMI clock */ + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_EMI]); + + early_delay(11000); + + /* Set EMI clock divider for EMI clock to 411 / 2 = 205MHz */ + writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) | + (1 << CLKCTRL_EMI_DIV_XTAL_OFFSET), + &clkctrl_regs->hw_clkctrl_emi); + + /* Unbypass EMI */ + writel(CLKCTRL_CLKSEQ_BYPASS_EMI, + &clkctrl_regs->hw_clkctrl_clkseq_clr); + + early_delay(10000); +} + +static void mxs_mem_setup_cpu_and_hbus(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + /* Set fractional divider for ref_cpu to 480 * 18 / 19 = 454MHz + * and ungate CPU clock */ + writeb(19 & CLKCTRL_FRAC_FRAC_MASK, + (uint8_t *)&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]); + + /* Set CPU bypass */ + writel(CLKCTRL_CLKSEQ_BYPASS_CPU, + &clkctrl_regs->hw_clkctrl_clkseq_set); + + /* HBUS = 151MHz */ + writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set); + writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK, + &clkctrl_regs->hw_clkctrl_hbus_clr); + + early_delay(10000); + + /* CPU clock divider = 1 */ + clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu, + CLKCTRL_CPU_DIV_CPU_MASK, 1); + + /* Disable CPU bypass */ + writel(CLKCTRL_CLKSEQ_BYPASS_CPU, + &clkctrl_regs->hw_clkctrl_clkseq_clr); + + early_delay(15000); +} + +static void mxs_mem_setup_vdda(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + writel((0xc << POWER_VDDACTRL_TRG_OFFSET) | + (0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) | + POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW, + &power_regs->hw_power_vddactrl); +} + +uint32_t mxs_mem_get_size(void) +{ + uint32_t sz, da; + uint32_t *vt = (uint32_t *)0x20; + /* The following is "subs pc, r14, #4", used as return from DABT. */ + const uint32_t data_abort_memdetect_handler = 0xe25ef004; + + /* Replace the DABT handler. */ + da = vt[4]; + vt[4] = data_abort_memdetect_handler; + + sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE); + + /* Restore the old DABT handler. */ + vt[4] = da; + + return sz; +} + +#ifdef CONFIG_MX23 +static void mx23_mem_setup_vddmem(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + clrbits_le32(&power_regs->hw_power_vddmemctrl, + POWER_VDDMEMCTRL_ENABLE_ILIMIT); + +} + +static void mx23_mem_init(void) +{ + /* + * Reset/ungate the EMI block. This is essential, otherwise the system + * suffers from memory instability. This thing is mx23 specific and is + * no longer present on mx28. + */ + mxs_reset_block((struct mxs_register_32 *)MXS_EMI_BASE); + + mx23_mem_setup_vddmem(); + + /* + * Configure the DRAM registers + */ + + /* Clear START and SREFRESH bit from DRAM_CTL8 */ + clrbits_le32(MXS_DRAM_BASE + 0x20, (1 << 16) | (1 << 8)); + + initialize_dram_values(); + + /* Set START bit in DRAM_CTL8 */ + setbits_le32(MXS_DRAM_BASE + 0x20, 1 << 16); + + clrbits_le32(MXS_DRAM_BASE + 0x40, 1 << 17); + early_delay(20000); + + /* Adjust EMI port priority. */ + clrsetbits_le32(0x80020000, 0x1f << 16, 0x2); + early_delay(20000); + + setbits_le32(MXS_DRAM_BASE + 0x40, 1 << 19); + setbits_le32(MXS_DRAM_BASE + 0x40, 1 << 11); +} +#endif + +#ifdef CONFIG_MX28 +static void mx28_mem_init(void) +{ + struct mxs_pinctrl_regs *pinctrl_regs = + (struct mxs_pinctrl_regs *)MXS_PINCTRL_BASE; + + /* Set DDR2 mode */ + writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2, + &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set); + + /* + * Configure the DRAM registers + */ + + /* Clear START bit from DRAM_CTL16 */ + clrbits_le32(MXS_DRAM_BASE + 0x40, 1); + + initialize_dram_values(); + + /* Clear SREFRESH bit from DRAM_CTL17 */ + clrbits_le32(MXS_DRAM_BASE + 0x44, 1); + + /* Set START bit in DRAM_CTL16 */ + setbits_le32(MXS_DRAM_BASE + 0x40, 1); + + /* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */ + while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20))) + ; +} +#endif + +void mxs_mem_init(void) +{ + early_delay(11000); + + mxs_mem_init_clock(); + + mxs_mem_setup_vdda(); + +#if defined(CONFIG_MX23) + mx23_mem_init(); +#elif defined(CONFIG_MX28) + mx28_mem_init(); +#endif + + early_delay(10000); + + mxs_mem_setup_cpu_and_hbus(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c new file mode 100644 index 000000000..d25019a51 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c @@ -0,0 +1,1155 @@ +/* + * Freescale i.MX28 Boot PMIC init + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +#include "mxs_init.h" + +/** + * mxs_power_clock2xtal() - Switch CPU core clock source to 24MHz XTAL + * + * This function switches the CPU core clock from PLL to 24MHz XTAL + * oscilator. This is necessary if the PLL is being reconfigured to + * prevent crash of the CPU core. + */ +static void mxs_power_clock2xtal(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + /* Set XTAL as CPU reference clock */ + writel(CLKCTRL_CLKSEQ_BYPASS_CPU, + &clkctrl_regs->hw_clkctrl_clkseq_set); +} + +/** + * mxs_power_clock2pll() - Switch CPU core clock source to PLL + * + * This function switches the CPU core clock from 24MHz XTAL oscilator + * to PLL. This can only be called once the PLL has re-locked and once + * the PLL is stable after reconfiguration. + */ +static void mxs_power_clock2pll(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0, + CLKCTRL_PLL0CTRL0_POWER); + early_delay(100); + setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq, + CLKCTRL_CLKSEQ_BYPASS_CPU); +} + +/** + * mxs_power_set_auto_restart() - Set the auto-restart bit + * + * This function ungates the RTC block and sets the AUTO_RESTART + * bit to work around a design bug on MX28EVK Rev. A . + */ + +static void mxs_power_set_auto_restart(void) +{ + struct mxs_rtc_regs *rtc_regs = + (struct mxs_rtc_regs *)MXS_RTC_BASE; + + writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr); + while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST) + ; + + writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr); + while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE) + ; + + /* Do nothing if flag already set */ + if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART) + return; + + while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK) + ; + + setbits_le32(&rtc_regs->hw_rtc_persistent0, + RTC_PERSISTENT0_AUTO_RESTART); + writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set); + writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr); + while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK) + ; + while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK) + ; +} + +/** + * mxs_power_set_linreg() - Set linear regulators 25mV below DC-DC converter + * + * This function configures the VDDIO, VDDA and VDDD linear regulators output + * to be 25mV below the VDDIO, VDDA and VDDD output from the DC-DC switching + * converter. This is the recommended setting for the case where we use both + * linear regulators and DC-DC converter to power the VDDIO rail. + */ +static void mxs_power_set_linreg(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* Set linear regulator 25mV below switching converter */ + clrsetbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_LINREG_OFFSET_MASK, + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW); + + clrsetbits_le32(&power_regs->hw_power_vddactrl, + POWER_VDDACTRL_LINREG_OFFSET_MASK, + POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW); + + clrsetbits_le32(&power_regs->hw_power_vddioctrl, + POWER_VDDIOCTRL_LINREG_OFFSET_MASK, + POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW); +} + +/** + * mxs_get_batt_volt() - Measure battery input voltage + * + * This function retrieves the battery input voltage and returns it. + */ +static int mxs_get_batt_volt(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t volt = readl(&power_regs->hw_power_battmonitor); + volt &= POWER_BATTMONITOR_BATT_VAL_MASK; + volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET; + volt *= 8; + return volt; +} + +/** + * mxs_is_batt_ready() - Test if the battery provides enough voltage to boot + * + * This function checks if the battery input voltage is higher than 3.6V and + * therefore allows the system to successfully boot using this power source. + */ +static int mxs_is_batt_ready(void) +{ + return (mxs_get_batt_volt() >= 3600); +} + +/** + * mxs_is_batt_good() - Test if battery is operational at all + * + * This function starts recharging the battery and tests if the input current + * provided by the 5V input recharging the battery is also sufficient to power + * the DC-DC converter. + */ +static int mxs_is_batt_good(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t volt = mxs_get_batt_volt(); + + if ((volt >= 2400) && (volt <= 4300)) + return 1; + + clrsetbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, + 0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET); + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, + &power_regs->hw_power_5vctrl_clr); + + clrsetbits_le32(&power_regs->hw_power_charge, + POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK, + POWER_CHARGE_STOP_ILIMIT_10MA | 0x3); + + writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr); + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, + &power_regs->hw_power_5vctrl_clr); + + early_delay(500000); + + volt = mxs_get_batt_volt(); + + if (volt >= 3500) + return 0; + + if (volt >= 2400) + return 1; + + writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK, + &power_regs->hw_power_charge_clr); + writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set); + + return 0; +} + +/** + * mxs_power_setup_5v_detect() - Start the 5V input detection comparator + * + * This function enables the 5V detection comparator and sets the 5V valid + * threshold to 4.4V . We use 4.4V threshold here to make sure that even + * under high load, the voltage drop on the 5V input won't be so critical + * to cause undervolt on the 4P2 linear regulator supplying the DC-DC + * converter and thus making the system crash. + */ +static void mxs_power_setup_5v_detect(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* Start 5V detection */ + clrsetbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_VBUSVALID_TRSH_MASK, + POWER_5VCTRL_VBUSVALID_TRSH_4V4 | + POWER_5VCTRL_PWRUP_VBUS_CMPS); +} + +/** + * mxs_src_power_init() - Preconfigure the power block + * + * This function configures reasonable values for the DC-DC control loop + * and battery monitor. + */ +static void mxs_src_power_init(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* Improve efficieny and reduce transient ripple */ + writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST | + POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set); + + clrsetbits_le32(&power_regs->hw_power_dclimits, + POWER_DCLIMITS_POSLIMIT_BUCK_MASK, + 0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET); + + setbits_le32(&power_regs->hw_power_battmonitor, + POWER_BATTMONITOR_EN_BATADJ); + + /* Increase the RCSCALE level for quick DCDC response to dynamic load */ + clrsetbits_le32(&power_regs->hw_power_loopctrl, + POWER_LOOPCTRL_EN_RCSCALE_MASK, + POWER_LOOPCTRL_RCSCALE_THRESH | + POWER_LOOPCTRL_EN_RCSCALE_8X); + + clrsetbits_le32(&power_regs->hw_power_minpwr, + POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS); + + /* 5V to battery handoff ... FIXME */ + setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER); + early_delay(30); + clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER); +} + +/** + * mxs_power_init_4p2_params() - Configure the parameters of the 4P2 regulator + * + * This function configures the necessary parameters for the 4P2 linear + * regulator to supply the DC-DC converter from 5V input. + */ +static void mxs_power_init_4p2_params(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* Setup 4P2 parameters */ + clrsetbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK, + POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET)); + + clrsetbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_HEADROOM_ADJ_MASK, + 0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET); + + clrsetbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_DROPOUT_CTRL_MASK, + POWER_DCDC4P2_DROPOUT_CTRL_100MV | + POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL); + + clrsetbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, + 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET); +} + +/** + * mxs_enable_4p2_dcdc_input() - Enable or disable the DCDC input from 4P2 + * @xfer: Select if the input shall be enabled or disabled + * + * This function enables or disables the 4P2 input into the DC-DC converter. + */ +static void mxs_enable_4p2_dcdc_input(int xfer) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo; + uint32_t prev_5v_brnout, prev_5v_droop; + + prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) & + POWER_5VCTRL_PWDN_5VBRNOUT; + prev_5v_droop = readl(&power_regs->hw_power_ctrl) & + POWER_CTRL_ENIRQ_VDD5V_DROOP; + + clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT); + writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF, + &power_regs->hw_power_reset); + + clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP); + + if (xfer && (readl(&power_regs->hw_power_5vctrl) & + POWER_5VCTRL_ENABLE_DCDC)) { + return; + } + + /* + * Recording orignal values that will be modified temporarlily + * to handle a chip bug. See chip errata for CQ ENGR00115837 + */ + tmp = readl(&power_regs->hw_power_5vctrl); + vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK; + vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT; + + pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO; + + /* + * Disable mechanisms that get erroneously tripped by when setting + * the DCDC4P2 EN_DCDC + */ + clrbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_VBUSVALID_5VDETECT | + POWER_5VCTRL_VBUSVALID_TRSH_MASK); + + writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set); + + if (xfer) { + setbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_DCDC_XFER); + early_delay(20); + clrbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_DCDC_XFER); + + setbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_ENABLE_DCDC); + } else { + setbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_ENABLE_DCDC); + } + + early_delay(25); + + clrsetbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh); + + if (vbus_5vdetect) + writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set); + + if (!pwd_bo) + clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO); + + while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) + writel(POWER_CTRL_VBUS_VALID_IRQ, + &power_regs->hw_power_ctrl_clr); + + if (prev_5v_brnout) { + writel(POWER_5VCTRL_PWDN_5VBRNOUT, + &power_regs->hw_power_5vctrl_set); + writel(POWER_RESET_UNLOCK_KEY, + &power_regs->hw_power_reset); + } else { + writel(POWER_5VCTRL_PWDN_5VBRNOUT, + &power_regs->hw_power_5vctrl_clr); + writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF, + &power_regs->hw_power_reset); + } + + while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ) + writel(POWER_CTRL_VDD5V_DROOP_IRQ, + &power_regs->hw_power_ctrl_clr); + + if (prev_5v_droop) + clrbits_le32(&power_regs->hw_power_ctrl, + POWER_CTRL_ENIRQ_VDD5V_DROOP); + else + setbits_le32(&power_regs->hw_power_ctrl, + POWER_CTRL_ENIRQ_VDD5V_DROOP); +} + +/** + * mxs_power_init_4p2_regulator() - Start the 4P2 regulator + * + * This function enables the 4P2 regulator and switches the DC-DC converter + * to use the 4P2 input. + */ +static void mxs_power_init_4p2_regulator(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t tmp, tmp2; + + setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2); + + writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set); + + writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, + &power_regs->hw_power_5vctrl_clr); + clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK); + + /* Power up the 4p2 rail and logic/control */ + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, + &power_regs->hw_power_5vctrl_clr); + + /* + * Start charging up the 4p2 capacitor. We ramp of this charge + * gradually to avoid large inrush current from the 5V cable which can + * cause transients/problems + */ + mxs_enable_4p2_dcdc_input(0); + + if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) { + /* + * If we arrived here, we were unable to recover from mx23 chip + * errata 5837. 4P2 is disabled and sufficient battery power is + * not present. Exiting to not enable DCDC power during 5V + * connected state. + */ + clrbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_ENABLE_DCDC); + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, + &power_regs->hw_power_5vctrl_set); + hang(); + } + + /* + * Here we set the 4p2 brownout level to something very close to 4.2V. + * We then check the brownout status. If the brownout status is false, + * the voltage is already close to the target voltage of 4.2V so we + * can go ahead and set the 4P2 current limit to our max target limit. + * If the brownout status is true, we need to ramp us the current limit + * so that we don't cause large inrush current issues. We step up the + * current limit until the brownout status is false or until we've + * reached our maximum defined 4p2 current limit. + */ + clrsetbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_BO_MASK, + 22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */ + + if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) { + setbits_le32(&power_regs->hw_power_5vctrl, + 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET); + } else { + tmp = (readl(&power_regs->hw_power_5vctrl) & + POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >> + POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET; + while (tmp < 0x3f) { + if (!(readl(&power_regs->hw_power_sts) & + POWER_STS_DCDC_4P2_BO)) { + tmp = readl(&power_regs->hw_power_5vctrl); + tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK; + early_delay(100); + writel(tmp, &power_regs->hw_power_5vctrl); + break; + } else { + tmp++; + tmp2 = readl(&power_regs->hw_power_5vctrl); + tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK; + tmp2 |= tmp << + POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET; + writel(tmp2, &power_regs->hw_power_5vctrl); + early_delay(100); + } + } + } + + clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK); + writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr); +} + +/** + * mxs_power_init_dcdc_4p2_source() - Switch DC-DC converter to 4P2 source + * + * This function configures the DC-DC converter to be supplied from the 4P2 + * linear regulator. + */ +static void mxs_power_init_dcdc_4p2_source(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + if (!(readl(&power_regs->hw_power_dcdc4p2) & + POWER_DCDC4P2_ENABLE_DCDC)) { + hang(); + } + + mxs_enable_4p2_dcdc_input(1); + + if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) { + clrbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_ENABLE_DCDC); + writel(POWER_5VCTRL_ENABLE_DCDC, + &power_regs->hw_power_5vctrl_clr); + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, + &power_regs->hw_power_5vctrl_set); + } +} + +/** + * mxs_power_enable_4p2() - Power up the 4P2 regulator + * + * This function drives the process of powering up the 4P2 linear regulator + * and switching the DC-DC converter input over to the 4P2 linear regulator. + */ +static void mxs_power_enable_4p2(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t vdddctrl, vddactrl, vddioctrl; + uint32_t tmp; + + vdddctrl = readl(&power_regs->hw_power_vdddctrl); + vddactrl = readl(&power_regs->hw_power_vddactrl); + vddioctrl = readl(&power_regs->hw_power_vddioctrl); + + setbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG | + POWER_VDDDCTRL_PWDN_BRNOUT); + + setbits_le32(&power_regs->hw_power_vddactrl, + POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG | + POWER_VDDACTRL_PWDN_BRNOUT); + + setbits_le32(&power_regs->hw_power_vddioctrl, + POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT); + + mxs_power_init_4p2_params(); + mxs_power_init_4p2_regulator(); + + /* Shutdown battery (none present) */ + if (!mxs_is_batt_ready()) { + clrbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_BO_MASK); + writel(POWER_CTRL_DCDC4P2_BO_IRQ, + &power_regs->hw_power_ctrl_clr); + writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, + &power_regs->hw_power_ctrl_clr); + } + + mxs_power_init_dcdc_4p2_source(); + + writel(vdddctrl, &power_regs->hw_power_vdddctrl); + early_delay(20); + writel(vddactrl, &power_regs->hw_power_vddactrl); + early_delay(20); + writel(vddioctrl, &power_regs->hw_power_vddioctrl); + + /* + * Check if FET is enabled on either powerout and if so, + * disable load. + */ + tmp = 0; + tmp |= !(readl(&power_regs->hw_power_vdddctrl) & + POWER_VDDDCTRL_DISABLE_FET); + tmp |= !(readl(&power_regs->hw_power_vddactrl) & + POWER_VDDACTRL_DISABLE_FET); + tmp |= !(readl(&power_regs->hw_power_vddioctrl) & + POWER_VDDIOCTRL_DISABLE_FET); + if (tmp) + writel(POWER_CHARGE_ENABLE_LOAD, + &power_regs->hw_power_charge_clr); +} + +/** + * mxs_boot_valid_5v() - Boot from 5V supply + * + * This function configures the power block to boot from valid 5V input. + * This is called only if the 5V is reliable and can properly supply the + * CPU. This function proceeds to configure the 4P2 converter to be supplied + * from the 5V input. + */ +static void mxs_boot_valid_5v(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* + * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V + * disconnect event. FIXME + */ + writel(POWER_5VCTRL_VBUSVALID_5VDETECT, + &power_regs->hw_power_5vctrl_set); + + /* Configure polarity to check for 5V disconnection. */ + writel(POWER_CTRL_POLARITY_VBUSVALID | + POWER_CTRL_POLARITY_VDD5V_GT_VDDIO, + &power_regs->hw_power_ctrl_clr); + + writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ, + &power_regs->hw_power_ctrl_clr); + + mxs_power_enable_4p2(); +} + +/** + * mxs_powerdown() - Shut down the system + * + * This function powers down the CPU completely. + */ +static void mxs_powerdown(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset); + writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF, + &power_regs->hw_power_reset); +} + +/** + * mxs_batt_boot() - Configure the power block to boot from battery input + * + * This function configures the power block to boot from the battery voltage + * supply. + */ +static void mxs_batt_boot(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT); + clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC); + + clrbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_ENABLE_DCDC | POWER_DCDC4P2_ENABLE_4P2); + writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_clr); + + /* 5V to battery handoff. */ + setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER); + early_delay(30); + clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER); + + writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr); + + clrsetbits_le32(&power_regs->hw_power_minpwr, + POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS); + + mxs_power_set_linreg(); + + clrbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG); + + clrbits_le32(&power_regs->hw_power_vddactrl, + POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG); + + clrbits_le32(&power_regs->hw_power_vddioctrl, + POWER_VDDIOCTRL_DISABLE_FET); + + setbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_PWD_CHARGE_4P2_MASK); + + setbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_ENABLE_DCDC); + + clrsetbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, + 0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET); + + mxs_power_enable_4p2(); +} + +/** + * mxs_handle_5v_conflict() - Test if the 5V input is reliable + * + * This function tests if the 5V input can reliably supply the system. If it + * can, then proceed to configuring the system to boot from 5V source, otherwise + * try booting from battery supply. If we can not boot from battery supply + * either, shut down the system. + */ +static void mxs_handle_5v_conflict(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t tmp; + + setbits_le32(&power_regs->hw_power_vddioctrl, + POWER_VDDIOCTRL_BO_OFFSET_MASK); + + for (;;) { + tmp = readl(&power_regs->hw_power_sts); + + if (tmp & POWER_STS_VDDIO_BO) { + /* + * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes + * unreliable + */ + mxs_powerdown(); + break; + } + + if (tmp & POWER_STS_VDD5V_GT_VDDIO) { + mxs_boot_valid_5v(); + break; + } else { + mxs_powerdown(); + break; + } + + if (tmp & POWER_STS_PSWITCH_MASK) { + mxs_batt_boot(); + break; + } + } +} + +/** + * mxs_5v_boot() - Configure the power block to boot from 5V input + * + * This function handles configuration of the power block when supplied by + * a 5V input. + */ +static void mxs_5v_boot(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* + * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID, + * but their implementation always returns 1 so we omit it here. + */ + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + mxs_boot_valid_5v(); + return; + } + + early_delay(1000); + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + mxs_boot_valid_5v(); + return; + } + + mxs_handle_5v_conflict(); +} + +/** + * mxs_init_batt_bo() - Configure battery brownout threshold + * + * This function configures the battery input brownout threshold. The value + * at which the battery brownout happens is configured to 3.0V in the code. + */ +static void mxs_init_batt_bo(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* Brownout at 3V */ + clrsetbits_le32(&power_regs->hw_power_battmonitor, + POWER_BATTMONITOR_BRWNOUT_LVL_MASK, + 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET); + + writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr); + writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr); +} + +/** + * mxs_switch_vddd_to_dcdc_source() - Switch VDDD rail to DC-DC converter + * + * This function turns off the VDDD linear regulator and therefore makes + * the VDDD rail be supplied only by the DC-DC converter. + */ +static void mxs_switch_vddd_to_dcdc_source(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + clrsetbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_LINREG_OFFSET_MASK, + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW); + + clrbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG | + POWER_VDDDCTRL_DISABLE_STEPPING); +} + +/** + * mxs_power_configure_power_source() - Configure power block source + * + * This function is the core of the power configuration logic. The function + * selects the power block input source and configures the whole power block + * accordingly. After the configuration is complete and the system is stable + * again, the function switches the CPU clock source back to PLL. Finally, + * the function switches the voltage rails to DC-DC converter. + */ +static void mxs_power_configure_power_source(void) +{ + int batt_ready, batt_good; + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + struct mxs_lradc_regs *lradc_regs = + (struct mxs_lradc_regs *)MXS_LRADC_BASE; + + mxs_src_power_init(); + + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + batt_ready = mxs_is_batt_ready(); + if (batt_ready) { + /* 5V source detected, good battery detected. */ + mxs_batt_boot(); + } else { + batt_good = mxs_is_batt_good(); + if (!batt_good) { + /* 5V source detected, bad battery detected. */ + writel(LRADC_CONVERSION_AUTOMATIC, + &lradc_regs->hw_lradc_conversion_clr); + clrbits_le32(&power_regs->hw_power_battmonitor, + POWER_BATTMONITOR_BATT_VAL_MASK); + } + mxs_5v_boot(); + } + } else { + /* 5V not detected, booting from battery. */ + mxs_batt_boot(); + } + + mxs_power_clock2pll(); + + mxs_init_batt_bo(); + + mxs_switch_vddd_to_dcdc_source(); + +#ifdef CONFIG_MX23 + /* Fire up the VDDMEM LinReg now that we're all set. */ + writel(POWER_VDDMEMCTRL_ENABLE_LINREG | POWER_VDDMEMCTRL_ENABLE_ILIMIT, + &power_regs->hw_power_vddmemctrl); +#endif +} + +/** + * mxs_enable_output_rail_protection() - Enable power rail protection + * + * This function enables overload protection on the power rails. This is + * triggered if the power rails' voltage drops rapidly due to overload and + * in such case, the supply to the powerrail is cut-off, protecting the + * CPU from damage. Note that under such condition, the system will likely + * crash or misbehave. + */ +static void mxs_enable_output_rail_protection(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | + POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr); + + setbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_PWDN_BRNOUT); + + setbits_le32(&power_regs->hw_power_vddactrl, + POWER_VDDACTRL_PWDN_BRNOUT); + + setbits_le32(&power_regs->hw_power_vddioctrl, + POWER_VDDIOCTRL_PWDN_BRNOUT); +} + +/** + * mxs_get_vddio_power_source_off() - Get VDDIO rail power source + * + * This function tests if the VDDIO rail is supplied by linear regulator + * or by the DC-DC converter. Returns 1 if powered by linear regulator, + * returns 0 if powered by the DC-DC converter. + */ +static int mxs_get_vddio_power_source_off(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t tmp; + + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + tmp = readl(&power_regs->hw_power_vddioctrl); + if (tmp & POWER_VDDIOCTRL_DISABLE_FET) { + if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) == + POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) { + return 1; + } + } + + if (!(readl(&power_regs->hw_power_5vctrl) & + POWER_5VCTRL_ENABLE_DCDC)) { + if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) == + POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) { + return 1; + } + } + } + + return 0; + +} + +/** + * mxs_get_vddd_power_source_off() - Get VDDD rail power source + * + * This function tests if the VDDD rail is supplied by linear regulator + * or by the DC-DC converter. Returns 1 if powered by linear regulator, + * returns 0 if powered by the DC-DC converter. + */ +static int mxs_get_vddd_power_source_off(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t tmp; + + tmp = readl(&power_regs->hw_power_vdddctrl); + if (tmp & POWER_VDDDCTRL_DISABLE_FET) { + if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) == + POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) { + return 1; + } + } + + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + if (!(readl(&power_regs->hw_power_5vctrl) & + POWER_5VCTRL_ENABLE_DCDC)) { + return 1; + } + } + + if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) { + if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) == + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) { + return 1; + } + } + + return 0; +} + +struct mxs_vddx_cfg { + uint32_t *reg; + uint8_t step_mV; + uint16_t lowest_mV; + int (*powered_by_linreg)(void); + uint32_t trg_mask; + uint32_t bo_irq; + uint32_t bo_enirq; + uint32_t bo_offset_mask; + uint32_t bo_offset_offset; +}; + +static const struct mxs_vddx_cfg mxs_vddio_cfg = { + .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)-> + hw_power_vddioctrl), +#if defined(CONFIG_MX23) + .step_mV = 25, +#else + .step_mV = 50, +#endif + .lowest_mV = 2800, + .powered_by_linreg = mxs_get_vddio_power_source_off, + .trg_mask = POWER_VDDIOCTRL_TRG_MASK, + .bo_irq = POWER_CTRL_VDDIO_BO_IRQ, + .bo_enirq = POWER_CTRL_ENIRQ_VDDIO_BO, + .bo_offset_mask = POWER_VDDIOCTRL_BO_OFFSET_MASK, + .bo_offset_offset = POWER_VDDIOCTRL_BO_OFFSET_OFFSET, +}; + +static const struct mxs_vddx_cfg mxs_vddd_cfg = { + .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)-> + hw_power_vdddctrl), + .step_mV = 25, + .lowest_mV = 800, + .powered_by_linreg = mxs_get_vddd_power_source_off, + .trg_mask = POWER_VDDDCTRL_TRG_MASK, + .bo_irq = POWER_CTRL_VDDD_BO_IRQ, + .bo_enirq = POWER_CTRL_ENIRQ_VDDD_BO, + .bo_offset_mask = POWER_VDDDCTRL_BO_OFFSET_MASK, + .bo_offset_offset = POWER_VDDDCTRL_BO_OFFSET_OFFSET, +}; + +#ifdef CONFIG_MX23 +static const struct mxs_vddx_cfg mxs_vddmem_cfg = { + .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)-> + hw_power_vddmemctrl), + .step_mV = 50, + .lowest_mV = 1700, + .powered_by_linreg = NULL, + .trg_mask = POWER_VDDMEMCTRL_TRG_MASK, + .bo_irq = 0, + .bo_enirq = 0, + .bo_offset_mask = 0, + .bo_offset_offset = 0, +}; +#endif + +/** + * mxs_power_set_vddx() - Configure voltage on DC-DC converter rail + * @cfg: Configuration data of the DC-DC converter rail + * @new_target: New target voltage of the DC-DC converter rail + * @new_brownout: New brownout trigger voltage + * + * This function configures the output voltage on the DC-DC converter rail. + * The rail is selected by the @cfg argument. The new voltage target is + * selected by the @new_target and the voltage is specified in mV. The + * new brownout value is selected by the @new_brownout argument and the + * value is also in mV. + */ +static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg, + uint32_t new_target, uint32_t new_brownout) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t cur_target, diff, bo_int = 0; + uint32_t powered_by_linreg = 0; + int adjust_up, tmp; + + new_brownout = DIV_ROUND(new_target - new_brownout, cfg->step_mV); + + cur_target = readl(cfg->reg); + cur_target &= cfg->trg_mask; + cur_target *= cfg->step_mV; + cur_target += cfg->lowest_mV; + + adjust_up = new_target > cur_target; + if (cfg->powered_by_linreg) + powered_by_linreg = cfg->powered_by_linreg(); + + if (adjust_up && cfg->bo_irq) { + if (powered_by_linreg) { + bo_int = readl(cfg->reg); + clrbits_le32(cfg->reg, cfg->bo_enirq); + } + setbits_le32(cfg->reg, cfg->bo_offset_mask); + } + + do { + if (abs(new_target - cur_target) > 100) { + if (adjust_up) + diff = cur_target + 100; + else + diff = cur_target - 100; + } else { + diff = new_target; + } + + diff -= cfg->lowest_mV; + diff /= cfg->step_mV; + + clrsetbits_le32(cfg->reg, cfg->trg_mask, diff); + + if (powered_by_linreg || + (readl(&power_regs->hw_power_sts) & + POWER_STS_VDD5V_GT_VDDIO)) + early_delay(500); + else { + for (;;) { + tmp = readl(&power_regs->hw_power_sts); + if (tmp & POWER_STS_DC_OK) + break; + } + } + + cur_target = readl(cfg->reg); + cur_target &= cfg->trg_mask; + cur_target *= cfg->step_mV; + cur_target += cfg->lowest_mV; + } while (new_target > cur_target); + + if (cfg->bo_irq) { + if (adjust_up && powered_by_linreg) { + writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr); + if (bo_int & cfg->bo_enirq) + setbits_le32(cfg->reg, cfg->bo_enirq); + } + + clrsetbits_le32(cfg->reg, cfg->bo_offset_mask, + new_brownout << cfg->bo_offset_offset); + } +} + +/** + * mxs_setup_batt_detect() - Start the battery voltage measurement logic + * + * This function starts and configures the LRADC block. This allows the + * power initialization code to measure battery voltage and based on this + * knowledge, decide whether to boot at all, boot from battery or boot + * from 5V input. + */ +static void mxs_setup_batt_detect(void) +{ + mxs_lradc_init(); + mxs_lradc_enable_batt_measurement(); + early_delay(10); +} + +/** + * mxs_ungate_power() - Ungate the POWER block + * + * This function ungates clock to the power block. In case the power block + * was still gated at this point, it will not be possible to configure the + * block and therefore the power initialization would fail. This function + * is only needed on i.MX233, on i.MX28 the power block is always ungated. + */ +static void mxs_ungate_power(void) +{ +#ifdef CONFIG_MX23 + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + writel(POWER_CTRL_CLKGATE, &power_regs->hw_power_ctrl_clr); +#endif +} + +/** + * mxs_power_init() - The power block init main function + * + * This function calls all the power block initialization functions in + * proper sequence to start the power block. + */ +void mxs_power_init(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + mxs_ungate_power(); + + mxs_power_clock2xtal(); + mxs_power_set_auto_restart(); + mxs_power_set_linreg(); + mxs_power_setup_5v_detect(); + + mxs_setup_batt_detect(); + + mxs_power_configure_power_source(); + mxs_enable_output_rail_protection(); + + mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150); + mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1000); +#ifdef CONFIG_MX23 + mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700); +#endif + writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | + POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ | + POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ | + POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr); + + writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set); + + early_delay(1000); +} + +#ifdef CONFIG_SPL_MXS_PSWITCH_WAIT +/** + * mxs_power_wait_pswitch() - Wait for power switch to be pressed + * + * This function waits until the power-switch was pressed to start booting + * the board. + */ +void mxs_power_wait_pswitch(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK)) + ; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/start.S b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/start.S new file mode 100644 index 000000000..34a0fcb46 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/start.S @@ -0,0 +1,185 @@ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Groger <mag@sysgo.de> + * Copyright (c) 2002 Alex Zupke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net> + * + * Change to support call back into iMX28 bootrom + * Copyright (c) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <common.h> +#include <version.h> + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + + +.globl _start +_start: + b reset + b undefined_instruction + b software_interrupt + b prefetch_abort + b data_abort + b not_used + b irq + b fiq + +/* + * Vector table, located at address 0x20. + * This table allows the code running AFTER SPL, the U-Boot, to install it's + * interrupt handlers here. The problem is that the U-Boot is loaded into RAM, + * including it's interrupt vectoring table and the table at 0x0 is still the + * SPLs. So if interrupt happens in U-Boot, the SPLs interrupt vectoring table + * is still used. + */ +_vt_reset: + .word _reset +_vt_undefined_instruction: + .word _hang +_vt_software_interrupt: + .word _hang +_vt_prefetch_abort: + .word _hang +_vt_data_abort: + .word _hang +_vt_not_used: + .word _reset +_vt_irq: + .word _hang +_vt_fiq: + .word _hang + +reset: + ldr pc, _vt_reset +undefined_instruction: + ldr pc, _vt_undefined_instruction +software_interrupt: + ldr pc, _vt_software_interrupt +prefetch_abort: + ldr pc, _vt_prefetch_abort +data_abort: + ldr pc, _vt_data_abort +not_used: + ldr pc, _vt_not_used +irq: + ldr pc, _vt_irq +fiq: + ldr pc, _vt_fiq + + .balignl 16,0xdeadbeef + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +_reset: + /* + * If the CPU is configured in "Wait JTAG connection mode", the stack + * pointer is not configured and is zero. This will cause crash when + * trying to push data onto stack right below here. Load the SP and make + * it point to the end of OCRAM if the SP is zero. + */ + cmp sp, #0x00000000 + ldreq sp, =CONFIG_SYS_INIT_SP_ADDR + + /* + * Store all registers on old stack pointer, this will allow us later to + * return to the BootROM and let the BootROM load U-Boot into RAM. + * + * WARNING: Register r0 and r1 are used by the BootROM to pass data + * to the called code. Register r0 will contain arbitrary + * data that are set in the BootStream. In case this code + * was started with CALL instruction, register r1 will contain + * pointer to the return value this function can then set. + * The code below MUST NOT CHANGE register r0 and r1 ! + */ + push {r0-r12,r14} + + /* Save control register c1 */ + mrc p15, 0, r2, c1, c0, 0 + push {r2} + + /* Set the cpu to SVC32 mode and store old CPSR register content. */ + mrs r2, cpsr + push {r2} + bic r2, r2, #0x1f + orr r2, r2, #0xd3 + msr cpsr, r2 + + bl board_init_ll + + /* Restore BootROM's CPU mode (especially FIQ). */ + pop {r2} + msr cpsr,r2 + + /* + * Restore c1 register. Especially set exception vector location + * back to BootROM space which is required by bootrom for USB boot. + */ + pop {r2} + mcr p15, 0, r2, c1, c0, 0 + + pop {r0-r12,r14} + + /* + * In case this code was started by the CALL instruction, the register + * r0 is examined by the BootROM after this code returns. The value in + * r0 must be set to 0 to indicate successful return. + */ + mov r0, #0 + + bx lr + +_hang: +1: + bl 1b /* hang and never return */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/timer.c new file mode 100644 index 000000000..99d3fb873 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/timer.c @@ -0,0 +1,159 @@ +/* + * Freescale i.MX28 timer driver + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * Based on code from LTIB: + * (C) Copyright 2009-2010 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> + +/* Maximum fixed count */ +#if defined(CONFIG_MX23) +#define TIMER_LOAD_VAL 0xffff +#elif defined(CONFIG_MX28) +#define TIMER_LOAD_VAL 0xffffffff +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp (gd->arch.tbl) +#define lastdec (gd->arch.lastinc) + +/* + * This driver uses 1kHz clock source. + */ +#define MXS_INCREMENTER_HZ 1000 + +static inline unsigned long tick_to_time(unsigned long tick) +{ + return tick / (MXS_INCREMENTER_HZ / CONFIG_SYS_HZ); +} + +static inline unsigned long time_to_tick(unsigned long time) +{ + return time * (MXS_INCREMENTER_HZ / CONFIG_SYS_HZ); +} + +/* Calculate how many ticks happen in "us" microseconds */ +static inline unsigned long us_to_tick(unsigned long us) +{ + return (us * MXS_INCREMENTER_HZ) / 1000000; +} + +int timer_init(void) +{ + struct mxs_timrot_regs *timrot_regs = + (struct mxs_timrot_regs *)MXS_TIMROT_BASE; + + /* Reset Timers and Rotary Encoder module */ + mxs_reset_block(&timrot_regs->hw_timrot_rotctrl_reg); + + /* Set fixed_count to 0 */ +#if defined(CONFIG_MX23) + writel(0, &timrot_regs->hw_timrot_timcount0); +#elif defined(CONFIG_MX28) + writel(0, &timrot_regs->hw_timrot_fixed_count0); +#endif + + /* Set UPDATE bit and 1Khz frequency */ + writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD | + TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL, + &timrot_regs->hw_timrot_timctrl0); + + /* Set fixed_count to maximal value */ +#if defined(CONFIG_MX23) + writel(TIMER_LOAD_VAL - 1, &timrot_regs->hw_timrot_timcount0); +#elif defined(CONFIG_MX28) + writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0); +#endif + + return 0; +} + +unsigned long long get_ticks(void) +{ + struct mxs_timrot_regs *timrot_regs = + (struct mxs_timrot_regs *)MXS_TIMROT_BASE; + uint32_t now; + + /* Current tick value */ +#if defined(CONFIG_MX23) + /* Upper bits are the valid ones. */ + now = readl(&timrot_regs->hw_timrot_timcount0) >> + TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET; +#elif defined(CONFIG_MX28) + now = readl(&timrot_regs->hw_timrot_running_count0); +#endif + + if (lastdec >= now) { + /* + * normal mode (non roll) + * move stamp forward with absolut diff ticks + */ + timestamp += (lastdec - now); + } else { + /* we have rollover of decrementer */ + timestamp += (TIMER_LOAD_VAL - now) + lastdec; + + } + lastdec = now; + + return timestamp; +} + +ulong get_timer_masked(void) +{ + return tick_to_time(get_ticks()); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */ +#define MXS_HW_DIGCTL_MICROSECONDS 0x8001c0c0 + +void __udelay(unsigned long usec) +{ + uint32_t old, new, incr; + uint32_t counter = 0; + + old = readl(MXS_HW_DIGCTL_MICROSECONDS); + + while (counter < usec) { + new = readl(MXS_HW_DIGCTL_MICROSECONDS); + + /* Check if the timer wrapped. */ + if (new < old) { + incr = 0xffffffff - old; + incr += new; + } else { + incr = new - old; + } + + /* + * Check if we are close to the maximum time and the counter + * would wrap if incremented. If that's the case, break out + * from the loop as the requested delay time passed. + */ + if (counter + incr < counter) + break; + + counter += incr; + old = new; + } +} + +ulong get_tbclk(void) +{ + return MXS_INCREMENTER_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd new file mode 100644 index 000000000..3a51879d5 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd @@ -0,0 +1,18 @@ +options { + driveTag = 0x00; + flags = 0x01; +} + +sources { + u_boot_spl="spl/u-boot-spl.bin"; + u_boot="u-boot.bin"; +} + +section (0) { + load u_boot_spl > 0x0000; + load ivt (entry = 0x0014) > 0x8000; + call 0x8000; + + load u_boot > 0x40000100; + call 0x40000100; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/u-boot-imx28.bd b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/u-boot-imx28.bd new file mode 100644 index 000000000..c60615a45 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/u-boot-imx28.bd @@ -0,0 +1,14 @@ +sources { + u_boot_spl="spl/u-boot-spl.bin"; + u_boot="u-boot.bin"; +} + +section (0) { + load u_boot_spl > 0x0000; + load ivt (entry = 0x0014) > 0x8000; + hab call 0x8000; + + load u_boot > 0x40000100; + load ivt (entry = 0x40000100) > 0x8000; + hab call 0x8000; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds new file mode 100644 index 000000000..f4bf8ac1d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * January 2004 - Changed to support H4 device + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = CONFIG_SPL_TEXT_BASE; + + . = ALIGN(4); + .text : + { + arch/arm/cpu/arm926ejs/mxs/start.o (.text*) + *(.text*) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + + .rel.dyn : { + __rel_dyn_start = .; + *(.rel*) + __rel_dyn_end = .; + } + + .bss : { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } + + .end : + { + *(.__end) + } + + _image_binary_end = .; + + .dynsym _image_binary_end : { *(.dynsym) } + .dynbss : { *(.dynbss) } + .dynstr : { *(.dynstr*) } + .dynamic : { *(.dynamic*) } + .hash : { *(.hash*) } + .plt : { *(.plt*) } + .interp : { *(.interp*) } + .gnu : { *(.gnu*) } + .ARM.exidx : { *(.ARM.exidx*) } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/Makefile new file mode 100644 index 000000000..cdf1345d5 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = timer.o gpio.o +obj-y += reset.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/gpio.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/gpio.c new file mode 100644 index 000000000..eff5b2b75 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/gpio.c @@ -0,0 +1,83 @@ +/* + * (C) Copyright 2009 Alessandro Rubini + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/gpio.h> + +static unsigned long gpio_base[4] = { + NOMADIK_GPIO0_BASE, + NOMADIK_GPIO1_BASE, + NOMADIK_GPIO2_BASE, + NOMADIK_GPIO3_BASE +}; + +enum gpio_registers { + GPIO_DAT = 0x00, /* data register */ + GPIO_DATS = 0x04, /* data set */ + GPIO_DATC = 0x08, /* data clear */ + GPIO_PDIS = 0x0c, /* pull disable */ + GPIO_DIR = 0x10, /* direction */ + GPIO_DIRS = 0x14, /* direction set */ + GPIO_DIRC = 0x18, /* direction clear */ + GPIO_AFSLA = 0x20, /* alternate function select A */ + GPIO_AFSLB = 0x24, /* alternate function select B */ +}; + +static inline unsigned long gpio_to_base(int gpio) +{ + return gpio_base[gpio / 32]; +} + +static inline u32 gpio_to_bit(int gpio) +{ + return 1 << (gpio & 0x1f); +} + +void nmk_gpio_af(int gpio, int alternate_function) +{ + unsigned long base = gpio_to_base(gpio); + u32 bit = gpio_to_bit(gpio); + u32 afunc, bfunc; + + /* alternate function is 0..3, with one bit per register */ + afunc = readl(base + GPIO_AFSLA) & ~bit; + bfunc = readl(base + GPIO_AFSLB) & ~bit; + if (alternate_function & 1) afunc |= bit; + if (alternate_function & 2) bfunc |= bit; + writel(afunc, base + GPIO_AFSLA); + writel(bfunc, base + GPIO_AFSLB); +} + +void nmk_gpio_dir(int gpio, int dir) +{ + unsigned long base = gpio_to_base(gpio); + u32 bit = gpio_to_bit(gpio); + + if (dir) + writel(bit, base + GPIO_DIRS); + else + writel(bit, base + GPIO_DIRC); +} + +void nmk_gpio_set(int gpio, int val) +{ + unsigned long base = gpio_to_base(gpio); + u32 bit = gpio_to_bit(gpio); + + if (val) + writel(bit, base + GPIO_DATS); + else + writel(bit, base + GPIO_DATC); +} + +int nmk_gpio_get(int gpio) +{ + unsigned long base = gpio_to_base(gpio); + u32 bit = gpio_to_bit(gpio); + + return readl(base + GPIO_DAT) & bit; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/reset.S b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/reset.S new file mode 100644 index 000000000..ec954726a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/reset.S @@ -0,0 +1,14 @@ +#include <config.h> +/* + * Processor reset for Nomadik + */ + + .align 5 +.globl reset_cpu +reset_cpu: + ldr r0, =NOMADIK_SRC_BASE /* System and Reset Controller */ + ldr r1, =0x1 + str r1, [r0, #0x18] + +_loop_forever: + b _loop_forever diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/timer.c new file mode 100644 index 000000000..775d0b748 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/nomadik/timer.c @@ -0,0 +1,71 @@ +/* + * (C) Copyright 2009 Alessandro Rubini + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/mtu.h> + +/* + * The timer is a decrementer, we'll left it free running at 2.4MHz. + * We have 2.4 ticks per microsecond and an overflow in almost 30min + */ +#define TIMER_CLOCK (24 * 100 * 1000) +#define COUNT_TO_USEC(x) ((x) * 5 / 12) /* overflows at 6min */ +#define USEC_TO_COUNT(x) ((x) * 12 / 5) /* overflows at 6min */ +#define TICKS_PER_HZ (TIMER_CLOCK / CONFIG_SYS_HZ) +#define TICKS_TO_HZ(x) ((x) / TICKS_PER_HZ) + +/* macro to read the decrementing 32 bit timer as an increasing count */ +#define READ_TIMER() (0 - readl(CONFIG_SYS_TIMERBASE + MTU_VAL(0))) + +/* Configure a free-running, auto-wrap counter with no prescaler */ +int timer_init(void) +{ + ulong val; + + writel(MTU_CRn_ENA | MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS, + CONFIG_SYS_TIMERBASE + MTU_CR(0)); + + /* Reset the timer */ + writel(0, CONFIG_SYS_TIMERBASE + MTU_LR(0)); + /* + * The load-register isn't really immediate: it changes on clock + * edges, so we must wait for our newly-written value to appear. + * Since we might miss reading 0, wait for any change in value. + */ + val = READ_TIMER(); + while (READ_TIMER() == val) + ; + + return 0; +} + +/* Return how many HZ passed since "base" */ +ulong get_timer(ulong base) +{ + return TICKS_TO_HZ(READ_TIMER()) - base; +} + +/* Delay x useconds */ +void __udelay(unsigned long usec) +{ + ulong ini, end; + + ini = READ_TIMER(); + end = ini + USEC_TO_COUNT(usec); + while ((signed)(end - READ_TIMER()) > 0) + ; +} + +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/Makefile new file mode 100644 index 000000000..add923276 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/Makefile @@ -0,0 +1,10 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = timer.o +obj-$(CONFIG_DISPLAY_CPUINFO) += cpuinfo.o +obj-y += reset.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/cpuinfo.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/cpuinfo.c new file mode 100644 index 000000000..587d99a2b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/cpuinfo.c @@ -0,0 +1,242 @@ +/* + * OMAP1 CPU identification code + * + * Copyright (C) 2004 Nokia Corporation + * Written by Tony Lindgren <tony@atomide.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <common.h> +#include <command.h> +#include <linux/compiler.h> + +#if defined(CONFIG_OMAP) + +#define omap_readw(x) *(volatile unsigned short *)(x) +#define omap_readl(x) *(volatile unsigned long *)(x) + +#define OMAP_DIE_ID_0 0xfffe1800 +#define OMAP_DIE_ID_1 0xfffe1804 +#define OMAP_PRODUCTION_ID_0 0xfffe2000 +#define OMAP_PRODUCTION_ID_1 0xfffe2004 +#define OMAP32_ID_0 0xfffed400 +#define OMAP32_ID_1 0xfffed404 + +struct omap_id { + u16 jtag_id; /* Used to determine OMAP type */ + u8 die_rev; /* Processor revision */ + u32 omap_id; /* OMAP revision */ + u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */ +}; + +/* Register values to detect the OMAP version */ +static struct omap_id omap_ids[] = { + { .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000}, + { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100}, + { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300}, + { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000}, + { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000}, + { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000}, + { .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00}, + { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00}, + { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, + { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, + { .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000}, + { .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00}, + { .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00}, + { .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300}, + { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300}, + { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300}, + { .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000}, + { .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000}, + { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000}, +}; + +/* + * Get OMAP type from PROD_ID. + * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM. + * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense. + * Undocumented register in TEST BLOCK is used as fallback; This seems to + * work on 1510, 1610 & 1710. The official way hopefully will work in future + * processors. + */ +static u16 omap_get_jtag_id(void) +{ + u32 prod_id, omap_id; + + prod_id = omap_readl(OMAP_PRODUCTION_ID_1); + omap_id = omap_readl(OMAP32_ID_1); + + /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */ + if (((prod_id >> 20) == 0) || (prod_id == omap_id)) + prod_id = 0; + else + prod_id &= 0xffff; + + if (prod_id) + return prod_id; + + /* Use OMAP32_ID_1 as fallback */ + prod_id = ((omap_id >> 12) & 0xffff); + + return prod_id; +} + +/* + * Get OMAP revision from DIE_REV. + * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID. + * Undocumented register in the TEST BLOCK is used as fallback. + * REVISIT: This does not seem to work on 1510 + */ +static u8 omap_get_die_rev(void) +{ + u32 die_rev; + + die_rev = omap_readl(OMAP_DIE_ID_1); + + /* Check for broken OMAP_DIE_ID on early 1710 */ + if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id()) + die_rev = 0; + + die_rev = (die_rev >> 17) & 0xf; + if (die_rev) + return die_rev; + + die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf; + + return die_rev; +} + +static unsigned long dpll1(void) +{ + unsigned short pll_ctl_val = omap_readw(DPLL_CTL_REG); + unsigned long rate; + + rate = CONFIG_SYS_CLK_FREQ; /* Base xtal rate */ + if (pll_ctl_val & 0x10) { + /* PLL enabled, apply multiplier and divisor */ + if (pll_ctl_val & 0xf80) + rate *= (pll_ctl_val & 0xf80) >> 7; + rate /= ((pll_ctl_val & 0x60) >> 5) + 1; + } else { + /* PLL disabled, apply bypass divisor */ + switch (pll_ctl_val & 0xc) { + case 0: + break; + case 0x4: + rate /= 2; + break; + default: + rate /= 4; + break; + } + } + + return rate; +} + +static unsigned long armcore(void) +{ + unsigned short arm_ckctl = omap_readw(ARM_CKCTL); + + return (dpll1() >> ((arm_ckctl & 0x0030) >> 4)); +} + +int print_cpuinfo (void) +{ + int i; + u16 jtag_id; + u8 die_rev; + u32 omap_id; + u8 cpu_type; + __maybe_unused u32 system_serial_high; + __maybe_unused u32 system_serial_low; + u32 system_rev = 0; + + jtag_id = omap_get_jtag_id(); + die_rev = omap_get_die_rev(); + omap_id = omap_readl(OMAP32_ID_0); + +#ifdef DEBUG + printf("OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0)); + printf("OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n", + omap_readl(OMAP_DIE_ID_1), + (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf); + printf("OMAP_PRODUCTION_ID_0: 0x%08x\n", omap_readl(OMAP_PRODUCTION_ID_0)); + printf("OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n", + omap_readl(OMAP_PRODUCTION_ID_1), + omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff); + printf("OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0)); + printf("OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1)); + printf("JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev); +#endif + + system_serial_high = omap_readl(OMAP_DIE_ID_0); + system_serial_low = omap_readl(OMAP_DIE_ID_1); + + /* First check only the major version in a safe way */ + for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { + if (jtag_id == (omap_ids[i].jtag_id)) { + system_rev = omap_ids[i].type; + break; + } + } + + /* Check if we can find the die revision */ + for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { + if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) { + system_rev = omap_ids[i].type; + break; + } + } + + /* Finally check also the omap_id */ + for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { + if (jtag_id == omap_ids[i].jtag_id + && die_rev == omap_ids[i].die_rev + && omap_id == omap_ids[i].omap_id) { + system_rev = omap_ids[i].type; + break; + } + } + + /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */ + cpu_type = system_rev >> 24; + + switch (cpu_type) { + case 0x07: + system_rev |= 0x07; + break; + case 0x03: + case 0x15: + system_rev |= 0x15; + break; + case 0x16: + case 0x17: + system_rev |= 0x16; + break; + case 0x24: + system_rev |= 0x24; + break; + default: + printf("Unknown OMAP cpu type: 0x%02x\n", cpu_type); + } + + printf("CPU: OMAP%04x", system_rev >> 16); + if ((system_rev >> 8) & 0xff) + printf("%x", (system_rev >> 8) & 0xff); +#ifdef DEBUG + printf(" revision %i handled as %02xxx id: %08x%08x", + die_rev, system_rev & 0xff, system_serial_low, system_serial_high); +#endif + printf(" at %ld.%01ld MHz (DPLL1=%ld.%01ld MHz)\n", + armcore() / 1000000, (armcore() / 100000) % 10, + dpll1() / 1000000, (dpll1() / 100000) % 10); + + return 0; +} + +#endif /* #if defined(CONFIG_OMAP) */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/reset.S b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/reset.S new file mode 100644 index 000000000..1c557b0d9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/reset.S @@ -0,0 +1,29 @@ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + .align 5 +.globl reset_cpu +reset_cpu: + ldr r1, rstctl1 /* get clkm1 reset ctl */ + mov r3, #0x0 + strh r3, [r1] /* clear it */ + mov r3, #0x8 + strh r3, [r1] /* force dsp+arm reset */ +_loop_forever: + b _loop_forever + +rstctl1: + .word 0xfffece10 diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/timer.c new file mode 100644 index 000000000..b9715656c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/omap/timer.c @@ -0,0 +1,152 @@ +/* + * (C) Copyright 2003 + * Texas Instruments <www.ti.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> + +#define TIMER_CLOCK (CONFIG_SYS_CLK_FREQ / (2 << CONFIG_SYS_PTV)) +#define TIMER_LOAD_VAL 0xffffffff + +/* macro to read the 32 bit timer */ +#define READ_TIMER readl(CONFIG_SYS_TIMERBASE+8) \ + / (TIMER_CLOCK / CONFIG_SYS_HZ) + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp gd->arch.tbl +#define lastdec gd->arch.lastinc + +int timer_init (void) +{ + int32_t val; + + /* Start the decrementer ticking down from 0xffffffff */ + *((int32_t *) (CONFIG_SYS_TIMERBASE + LOAD_TIM)) = TIMER_LOAD_VAL; + val = MPUTIM_ST | MPUTIM_AR | MPUTIM_CLOCK_ENABLE | (CONFIG_SYS_PTV << MPUTIM_PTV_BIT); + *((int32_t *) (CONFIG_SYS_TIMERBASE + CNTL_TIMER)) = val; + + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ +ulong get_timer (ulong base) +{ + return get_timer_masked () - base; +} + +/* delay x useconds AND preserve advance timestamp value */ +void __udelay (unsigned long usec) +{ + ulong tmo, tmp; + + if(usec >= 1000){ /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ + tmo *= CONFIG_SYS_HZ; /* find number of "ticks" to wait to achieve target */ + tmo /= 1000; /* finish normalize. */ + }else{ /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000*1000); + } + + tmp = get_timer (0); /* get current timestamp */ + if( (tmo + tmp + 1) < tmp ) /* if setting this fordward will roll time stamp */ + reset_timer_masked (); /* reset "advancing" timestamp to 0, set lastdec value */ + else + tmo += tmp; /* else, set advancing stamp wake up time */ + + while (get_timer_masked () < tmo)/* loop till event */ + /*NOP*/; +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastdec = READ_TIMER; /* capure current decrementer value time */ + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +ulong get_timer_masked (void) +{ + ulong now = READ_TIMER; /* current tick value */ + + if (lastdec >= now) { /* normal mode (non roll) */ + /* normal mode */ + timestamp += lastdec - now; /* move stamp fordward with absoulte diff ticks */ + } else { /* we have overflow of the count down timer */ + /* nts = ts + ld + (TLV - now) + * ts=old stamp, ld=time that passed before passing through -1 + * (TLV-now) amount of time after passing though -1 + * nts = new "advancing time stamp"...it could also roll and cause problems. + */ + timestamp += lastdec + (TIMER_LOAD_VAL / (TIMER_CLOCK / + CONFIG_SYS_HZ)) - now; + } + lastdec = now; + + return timestamp; +} + +/* waits specified delay value and resets timestamp */ +void udelay_masked (unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + if (usec >= 1000) { /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ + tmo *= CONFIG_SYS_HZ; /* find number of "ticks" to wait to achieve target */ + tmo /= 1000; /* finish normalize. */ + } else { /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000*1000); + } + + endtime = get_timer_masked () + tmo; + + do { + ulong now = get_timer_masked (); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + return CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/Makefile new file mode 100644 index 000000000..546ebcb52 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/Makefile @@ -0,0 +1,18 @@ +# +# Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net> +# +# Based on original Kirkwood support which is +# (C) Copyright 2009 +# Marvell Semiconductor <www.marvell.com> +# Written-by: Prafulla Wadaskar <prafulla@marvell.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o +obj-y += dram.o +obj-y += timer.o + +ifndef CONFIG_SKIP_LOWLEVEL_INIT +obj-y += lowlevel_init.o +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/cpu.c new file mode 100644 index 000000000..b55c5f094 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/cpu.c @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net> + * + * Based on original Kirkwood support which is + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <netdev.h> +#include <asm/cache.h> +#include <asm/io.h> +#include <u-boot/md5.h> +#include <asm/arch/cpu.h> +#include <hush.h> + +#define BUFLEN 16 + +void reset_cpu(unsigned long ignored) +{ + struct orion5x_cpu_registers *cpureg = + (struct orion5x_cpu_registers *)ORION5X_CPU_REG_BASE; + + writel(readl(&cpureg->rstoutn_mask) | (1 << 2), + &cpureg->rstoutn_mask); + writel(readl(&cpureg->sys_soft_rst) | 1, + &cpureg->sys_soft_rst); + while (1) + ; +} + +/* + * Compute Window Size field value from size expressed in bytes + * Used with the Base register to set the address window size and location. + * Must be programmed from LSB to MSB as sequence of ones followed by + * sequence of zeros. The number of ones specifies the size of the window in + * 64 KiB granularity (e.g., a value of 0x00FF specifies 256 = 16 MiB). + * NOTES: + * 1) A sizeval equal to 0x0 specifies 4 GiB. + * 2) A return value of 0x0 specifies 64 KiB. + */ +unsigned int orion5x_winctrl_calcsize(unsigned int sizeval) +{ + /* + * Calculate the number of 64 KiB blocks needed minus one (rounding up). + * For sizeval > 0 this is equivalent to: + * sizeval = (u32) ceil((double) sizeval / 65536.0) - 1 + */ + sizeval = (sizeval - 1) >> 16; + + /* + * Propagate 'one' bits to the right by 'oring' them. + * We need only treat bits 15-0. + */ + sizeval |= sizeval >> 1; /* 'Or' bit 15 onto bit 14 */ + sizeval |= sizeval >> 2; /* 'Or' bits 15-14 onto bits 13-12 */ + sizeval |= sizeval >> 4; /* 'Or' bits 15-12 onto bits 11-8 */ + sizeval |= sizeval >> 8; /* 'Or' bits 15-8 onto bits 7-0*/ + + return sizeval; +} + +/* + * orion5x_config_adr_windows - Configure address Windows + * + * There are 8 address windows supported by Orion5x Soc to addess different + * devices. Each window can be configured for size, BAR and remap addr + * Below configuration is standard for most of the cases + * + * If remap function not used, remap_lo must be set as base + * + * NOTES: + * + * 1) in order to avoid windows with inconsistent control and base values + * (which could prevent access to BOOTCS and hence execution from FLASH) + * always disable window before writing the base value then reenable it + * by writing the control value. + * + * 2) in order to avoid losing access to BOOTCS when disabling window 7, + * first configure window 6 for BOOTCS, then configure window 7 for BOOTCS, + * then configure windows 6 for its own target. + * + * Reference Documentation: + * Mbus-L to Mbus Bridge Registers Configuration. + * (Sec 25.1 and 25.3 of Datasheet) + */ +int orion5x_config_adr_windows(void) +{ + struct orion5x_win_registers *winregs = + (struct orion5x_win_registers *)ORION5X_CPU_WIN_BASE; + +/* Disable window 0, configure it for its intended target, enable it. */ + writel(0, &winregs[0].ctrl); + writel(ORION5X_ADR_PCIE_MEM, &winregs[0].base); + writel(ORION5X_ADR_PCIE_MEM_REMAP_LO, &winregs[0].remap_lo); + writel(ORION5X_ADR_PCIE_MEM_REMAP_HI, &winregs[0].remap_hi); + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_SZ_PCIE_MEM, + ORION5X_TARGET_PCIE, ORION5X_ATTR_PCIE_MEM, + ORION5X_WIN_ENABLE), &winregs[0].ctrl); +/* Disable window 1, configure it for its intended target, enable it. */ + writel(0, &winregs[1].ctrl); + writel(ORION5X_ADR_PCIE_IO, &winregs[1].base); + writel(ORION5X_ADR_PCIE_IO_REMAP_LO, &winregs[1].remap_lo); + writel(ORION5X_ADR_PCIE_IO_REMAP_HI, &winregs[1].remap_hi); + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_SZ_PCIE_IO, + ORION5X_TARGET_PCIE, ORION5X_ATTR_PCIE_IO, + ORION5X_WIN_ENABLE), &winregs[1].ctrl); +/* Disable window 2, configure it for its intended target, enable it. */ + writel(0, &winregs[2].ctrl); + writel(ORION5X_ADR_PCI_MEM, &winregs[2].base); + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_SZ_PCI_MEM, + ORION5X_TARGET_PCI, ORION5X_ATTR_PCI_MEM, + ORION5X_WIN_ENABLE), &winregs[2].ctrl); +/* Disable window 3, configure it for its intended target, enable it. */ + writel(0, &winregs[3].ctrl); + writel(ORION5X_ADR_PCI_IO, &winregs[3].base); + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_SZ_PCI_IO, + ORION5X_TARGET_PCI, ORION5X_ATTR_PCI_IO, + ORION5X_WIN_ENABLE), &winregs[3].ctrl); +/* Disable window 4, configure it for its intended target, enable it. */ + writel(0, &winregs[4].ctrl); + writel(ORION5X_ADR_DEV_CS0, &winregs[4].base); + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_SZ_DEV_CS0, + ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS0, + ORION5X_WIN_ENABLE), &winregs[4].ctrl); +/* Disable window 5, configure it for its intended target, enable it. */ + writel(0, &winregs[5].ctrl); + writel(ORION5X_ADR_DEV_CS1, &winregs[5].base); + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_SZ_DEV_CS1, + ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS1, + ORION5X_WIN_ENABLE), &winregs[5].ctrl); +/* Disable window 6, configure it for FLASH, enable it. */ + writel(0, &winregs[6].ctrl); + writel(ORION5X_ADR_BOOTROM, &winregs[6].base); + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_SZ_BOOTROM, + ORION5X_TARGET_DEVICE, ORION5X_ATTR_BOOTROM, + ORION5X_WIN_ENABLE), &winregs[6].ctrl); +/* Disable window 7, configure it for FLASH, enable it. */ + writel(0, &winregs[7].ctrl); + writel(ORION5X_ADR_BOOTROM, &winregs[7].base); + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_SZ_BOOTROM, + ORION5X_TARGET_DEVICE, ORION5X_ATTR_BOOTROM, + ORION5X_WIN_ENABLE), &winregs[7].ctrl); +/* Disable window 6, configure it for its intended target, enable it. */ + writel(0, &winregs[6].ctrl); + writel(ORION5X_ADR_DEV_CS2, &winregs[6].base); + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_SZ_DEV_CS2, + ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS2, + ORION5X_WIN_ENABLE), &winregs[6].ctrl); + + return 0; +} + +/* + * Orion5x identification is done through PCIE space. + */ + +u32 orion5x_device_id(void) +{ + return readl(PCIE_DEV_ID_OFF) >> 16; +} + +u32 orion5x_device_rev(void) +{ + return readl(PCIE_DEV_REV_OFF) & 0xff; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) + +/* Display device and revision IDs. + * This function must cover all known device/revision + * combinations, not only the one for which u-boot is + * compiled; this way, one can identify actual HW in + * case of a mismatch. + */ +int print_cpuinfo(void) +{ + char dev_str[7]; /* room enough for 0x0000 plus null byte */ + char rev_str[5]; /* room enough for 0x00 plus null byte */ + char *dev_name = NULL; + char *rev_name = NULL; + + u32 dev = orion5x_device_id(); + u32 rev = orion5x_device_rev(); + + if (dev == MV88F5181_DEV_ID) { + dev_name = "MV88F5181"; + if (rev == MV88F5181_REV_B1) + rev_name = "B1"; + else if (rev == MV88F5181L_REV_A1) { + dev_name = "MV88F5181L"; + rev_name = "A1"; + } else if (rev == MV88F5181L_REV_A0) { + dev_name = "MV88F5181L"; + rev_name = "A0"; + } + } else if (dev == MV88F5182_DEV_ID) { + dev_name = "MV88F5182"; + if (rev == MV88F5182_REV_A2) + rev_name = "A2"; + } else if (dev == MV88F5281_DEV_ID) { + dev_name = "MV88F5281"; + if (rev == MV88F5281_REV_D2) + rev_name = "D2"; + else if (rev == MV88F5281_REV_D1) + rev_name = "D1"; + else if (rev == MV88F5281_REV_D0) + rev_name = "D0"; + } else if (dev == MV88F6183_DEV_ID) { + dev_name = "MV88F6183"; + if (rev == MV88F6183_REV_B0) + rev_name = "B0"; + } + if (dev_name == NULL) { + sprintf(dev_str, "0x%04x", dev); + dev_name = dev_str; + } + if (rev_name == NULL) { + sprintf(rev_str, "0x%02x", rev); + rev_name = rev_str; + } + + printf("SoC: Orion5x %s-%s\n", dev_name, rev_name); + + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ + +#ifdef CONFIG_ARCH_CPU_INIT +int arch_cpu_init(void) +{ + /* Enable and invalidate L2 cache in write through mode */ + invalidate_l2_cache(); + + orion5x_config_adr_windows(); + + return 0; +} +#endif /* CONFIG_ARCH_CPU_INIT */ + +/* + * SOC specific misc init + */ +#if defined(CONFIG_ARCH_MISC_INIT) +int arch_misc_init(void) +{ + u32 temp; + + /*CPU streaming & write allocate */ + temp = readfr_extra_feature_reg(); + temp &= ~(1 << 28); /* disable wr alloc */ + writefr_extra_feature_reg(temp); + + temp = readfr_extra_feature_reg(); + temp &= ~(1 << 29); /* streaming disabled */ + writefr_extra_feature_reg(temp); + + /* L2Cache settings */ + temp = readfr_extra_feature_reg(); + /* Disable L2C pre fetch - Set bit 24 */ + temp |= (1 << 24); + /* enable L2C - Set bit 22 */ + temp |= (1 << 22); + writefr_extra_feature_reg(temp); + + icache_enable(); + /* Change reset vector to address 0x0 */ + temp = get_cr(); + set_cr(temp & ~CR_V); + + /* Set CPIOs and MPPs - values provided by board + include file */ + writel(ORION5X_MPP0_7, ORION5X_MPP_BASE+0x00); + writel(ORION5X_MPP8_15, ORION5X_MPP_BASE+0x04); + writel(ORION5X_MPP16_23, ORION5X_MPP_BASE+0x50); + writel(ORION5X_GPIO_OUT_VALUE, ORION5X_GPIO_BASE+0x00); + writel(ORION5X_GPIO_OUT_ENABLE, ORION5X_GPIO_BASE+0x04); + writel(ORION5X_GPIO_IN_POLARITY, ORION5X_GPIO_BASE+0x0c); + + /* initialize timer */ + timer_init_r(); + return 0; +} +#endif /* CONFIG_ARCH_MISC_INIT */ + +#ifdef CONFIG_MVGBE +int cpu_eth_init(bd_t *bis) +{ + mvgbe_initialize(bis); + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/dram.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/dram.c new file mode 100644 index 000000000..9ed93d25b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/dram.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net> + * + * Based on original Kirkwood support which is + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <config.h> +#include <asm/arch/cpu.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * orion5x_sdram_bar - reads SDRAM Base Address Register + */ +u32 orion5x_sdram_bar(enum memory_bank bank) +{ + struct orion5x_ddr_addr_decode_registers *winregs = + (struct orion5x_ddr_addr_decode_registers *) + ORION5X_DRAM_BASE; + + u32 result = 0; + u32 enable = 0x01 & winregs[bank].size; + + if ((!enable) || (bank > BANK3)) + return 0; + + result = winregs[bank].base; + return result; +} +int dram_init (void) +{ + /* dram_init must store complete ramsize in gd->ram_size */ + gd->ram_size = get_ram_size( + (long *) orion5x_sdram_bar(0), + CONFIG_MAX_RAM_BANK_SIZE); + return 0; +} + +void dram_init_banksize (void) +{ + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = orion5x_sdram_bar(i); + gd->bd->bi_dram[i].size = get_ram_size( + (long *) (gd->bd->bi_dram[i].start), + CONFIG_MAX_RAM_BANK_SIZE); + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S new file mode 100644 index 000000000..4dacc296e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net> + * + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include "asm/arch/orion5x.h" + +/* + * Configuration values for SDRAM access setup + */ + +#define SDRAM_CONFIG 0x3148400 +#define SDRAM_MODE 0x62 +#define SDRAM_CONTROL 0x4041000 +#define SDRAM_TIME_CTRL_LOW 0x11602220 +#define SDRAM_TIME_CTRL_HI 0x40c +#define SDRAM_OPEN_PAGE_EN 0x0 +/* DDR 1 2x 32M NANYA NT5DS16M16CS-6K ==> 64MB */ +#define SDRAM_BANK0_SIZE 0x3ff0001 +#define SDRAM_ADDR_CTRL 0x10 + +#define SDRAM_OP_NOP 0x05 +#define SDRAM_OP_SETMODE 0x03 + +#define SDRAM_PAD_CTRL_WR_EN 0x80000000 +#define SDRAM_PAD_CTRL_TUNE_EN 0x00010000 +#define SDRAM_PAD_CTRL_DRVN_MASK 0x0000003f +#define SDRAM_PAD_CTRL_DRVP_MASK 0x00000fc0 + +/* + * For Guideline MEM-3 - Drive Strength value + */ + +#define DDR1_PAD_STRENGTH_DEFAULT 0x00001000 +#define SDRAM_PAD_CTRL_DRV_STR_MASK 0x00003000 + +/* + * For Guideline MEM-4 - DQS Reference Delay Tuning + */ + +#define MSAR_ARMDDRCLCK_MASK 0x000000f0 +#define MSAR_ARMDDRCLCK_H_MASK 0x00000100 + +#define MSAR_ARMDDRCLCK_333_167 0x00000000 +#define MSAR_ARMDDRCLCK_500_167 0x00000030 +#define MSAR_ARMDDRCLCK_667_167 0x00000060 +#define MSAR_ARMDDRCLCK_400_200_1 0x000001E0 +#define MSAR_ARMDDRCLCK_400_200 0x00000010 +#define MSAR_ARMDDRCLCK_600_200 0x00000050 +#define MSAR_ARMDDRCLCK_800_200 0x00000070 + +#define FTDLL_DDR1_166MHZ 0x0047F001 + +#define FTDLL_DDR1_200MHZ 0x0044D001 + +/* + * Low-level init happens right after start.S has switched to SVC32, + * flushed and disabled caches and disabled MMU. We're still running + * from the boot chip select, so the first thing we should do is set + * up RAM for us to relocate into. + */ + +.globl lowlevel_init + +lowlevel_init: + + /* Use 'r4 as the base for internal register accesses */ + ldr r4, =ORION5X_REGS_PHY_BASE + + /* move internal registers from the default 0xD0000000 + * to their intended location, defined by SoC */ + ldr r3, =0xD0000000 + add r3, r3, #0x20000 + str r4, [r3, #0x80] + + /* Use R3 as the base for DRAM registers */ + add r3, r4, #0x01000 + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + str r6, [r3, #0x480] + + /* Use R3 as the base for PCI registers */ + add r3, r4, #0x31000 + + /* Disable arbiter */ + ldr r6, =0x00000030 + str r6, [r3, #0xd00] + + /* Use R3 as the base for DRAM registers */ + add r3, r4, #0x01000 + + /* set all dram windows to 0 */ + mov r6, #0 + str r6, [r3, #0x504] + str r6, [r3, #0x50C] + str r6, [r3, #0x514] + str r6, [r3, #0x51C] + + /* 1) Configure SDRAM */ + ldr r6, =SDRAM_CONFIG + str r6, [r3, #0x400] + + /* 2) Set SDRAM Control reg */ + ldr r6, =SDRAM_CONTROL + str r6, [r3, #0x404] + + /* 3) Write SDRAM address control register */ + ldr r6, =SDRAM_ADDR_CTRL + str r6, [r3, #0x410] + + /* 4) Write SDRAM bank 0 size register */ + ldr r6, =SDRAM_BANK0_SIZE + str r6, [r3, #0x504] + /* keep other banks disabled */ + + /* 5) Write SDRAM open pages control register */ + ldr r6, =SDRAM_OPEN_PAGE_EN + str r6, [r3, #0x414] + + /* 6) Write SDRAM timing Low register */ + ldr r6, =SDRAM_TIME_CTRL_LOW + str r6, [r3, #0x408] + + /* 7) Write SDRAM timing High register */ + ldr r6, =SDRAM_TIME_CTRL_HI + str r6, [r3, #0x40C] + + /* 8) Write SDRAM mode register */ + /* The CPU must not attempt to change the SDRAM Mode register setting */ + /* prior to DRAM controller completion of the DRAM initialization */ + /* sequence. To guarantee this restriction, it is recommended that */ + /* the CPU sets the SDRAM Operation register to NOP command, performs */ + /* read polling until the register is back in Normal operation value, */ + /* and then sets SDRAM Mode register to its new value. */ + + /* 8.1 write 'nop' to SDRAM operation */ + ldr r6, =SDRAM_OP_NOP + str r6, [r3, #0x418] + + /* 8.2 poll SDRAM operation until back in 'normal' mode. */ +1: + ldr r6, [r3, #0x418] + cmp r6, #0 + bne 1b + + /* 8.3 Now its safe to write new value to SDRAM Mode register */ + ldr r6, =SDRAM_MODE + str r6, [r3, #0x41C] + + /* 8.4 Set new mode */ + ldr r6, =SDRAM_OP_SETMODE + str r6, [r3, #0x418] + + /* 8.5 poll SDRAM operation until back in 'normal' mode. */ +2: + ldr r6, [r3, #0x418] + cmp r6, #0 + bne 2b + + /* DDR SDRAM Address/Control Pads Calibration */ + ldr r6, [r3, #0x4C0] + + /* Set Bit [31] to make the register writable */ + orr r6, r6, #SDRAM_PAD_CTRL_WR_EN + str r6, [r3, #0x4C0] + + bic r6, r6, #SDRAM_PAD_CTRL_WR_EN + bic r6, r6, #SDRAM_PAD_CTRL_TUNE_EN + bic r6, r6, #SDRAM_PAD_CTRL_DRVN_MASK + bic r6, r6, #SDRAM_PAD_CTRL_DRVP_MASK + + /* Get the final N locked value of driving strength [22:17] */ + mov r1, r6 + mov r1, r1, LSL #9 + mov r1, r1, LSR #26 /* r1[5:0]<DrvN> = r3[22:17]<LockN> */ + orr r1, r1, r1, LSL #6 /* r1[11:6]<DrvP> = r1[5:0]<DrvN> */ + + /* Write to both <DrvN> bits [5:0] and <DrvP> bits [11:6] */ + orr r6, r6, r1 + str r6, [r3, #0x4C0] + + /* DDR SDRAM Data Pads Calibration */ + ldr r6, [r3, #0x4C4] + + /* Set Bit [31] to make the register writable */ + orr r6, r6, #SDRAM_PAD_CTRL_WR_EN + str r6, [r3, #0x4C4] + + bic r6, r6, #SDRAM_PAD_CTRL_WR_EN + bic r6, r6, #SDRAM_PAD_CTRL_TUNE_EN + bic r6, r6, #SDRAM_PAD_CTRL_DRVN_MASK + bic r6, r6, #SDRAM_PAD_CTRL_DRVP_MASK + + /* Get the final N locked value of driving strength [22:17] */ + mov r1, r6 + mov r1, r1, LSL #9 + mov r1, r1, LSR #26 + orr r1, r1, r1, LSL #6 /* r1[5:0] = r3[22:17]<LockN> */ + + /* Write to both <DrvN> bits [5:0] and <DrvP> bits [11:6] */ + orr r6, r6, r1 + + str r6, [r3, #0x4C4] + + /* Implement Guideline (GL# MEM-3) Drive Strength Value */ + /* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0 */ + + ldr r1, =DDR1_PAD_STRENGTH_DEFAULT + + /* Enable writes to DDR SDRAM Addr/Ctrl Pads Calibration register */ + ldr r6, [r3, #0x4C0] + orr r6, r6, #SDRAM_PAD_CTRL_WR_EN + str r6, [r3, #0x4C0] + + /* Correct strength and disable writes again */ + bic r6, r6, #SDRAM_PAD_CTRL_WR_EN + bic r6, r6, #SDRAM_PAD_CTRL_DRV_STR_MASK + orr r6, r6, r1 + str r6, [r3, #0x4C0] + + /* Enable writes to DDR SDRAM Data Pads Calibration register */ + ldr r6, [r3, #0x4C4] + orr r6, r6, #SDRAM_PAD_CTRL_WR_EN + str r6, [r3, #0x4C4] + + /* Correct strength and disable writes again */ + bic r6, r6, #SDRAM_PAD_CTRL_DRV_STR_MASK + bic r6, r6, #SDRAM_PAD_CTRL_WR_EN + orr r6, r6, r1 + str r6, [r3, #0x4C4] + + /* Implement Guideline (GL# MEM-4) DQS Reference Delay Tuning */ + /* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0 */ + + /* Get the "sample on reset" register for the DDR frequancy */ + ldr r3, =0x10000 + ldr r6, [r3, #0x010] + ldr r1, =MSAR_ARMDDRCLCK_MASK + and r1, r6, r1 + + ldr r6, =FTDLL_DDR1_166MHZ + cmp r1, #MSAR_ARMDDRCLCK_333_167 + beq 3f + cmp r1, #MSAR_ARMDDRCLCK_500_167 + beq 3f + cmp r1, #MSAR_ARMDDRCLCK_667_167 + beq 3f + + ldr r6, =FTDLL_DDR1_200MHZ + cmp r1, #MSAR_ARMDDRCLCK_400_200_1 + beq 3f + cmp r1, #MSAR_ARMDDRCLCK_400_200 + beq 3f + cmp r1, #MSAR_ARMDDRCLCK_600_200 + beq 3f + cmp r1, #MSAR_ARMDDRCLCK_800_200 + beq 3f + + ldr r6, =0 + +3: + /* Use R3 as the base for DRAM registers */ + add r3, r4, #0x01000 + + ldr r2, [r3, #0x484] + orr r2, r2, r6 + str r2, [r3, #0x484] + + /* Return to U-boot via saved link register */ + mov pc, lr diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/timer.c new file mode 100644 index 000000000..ec4f6bee8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/orion5x/timer.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net> + * + * Based on original Kirkwood support which is + * Copyright (C) Marvell International Ltd. and its affiliates + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> + +#define UBOOT_CNTR 0 /* counter to use for uboot timer */ + +/* Timer reload and current value registers */ +struct orion5x_tmr_val { + u32 reload; /* Timer reload reg */ + u32 val; /* Timer value reg */ +}; + +/* Timer registers */ +struct orion5x_tmr_registers { + u32 ctrl; /* Timer control reg */ + u32 pad[3]; + struct orion5x_tmr_val tmr[2]; + u32 wdt_reload; + u32 wdt_val; +}; + +struct orion5x_tmr_registers *orion5x_tmr_regs = + (struct orion5x_tmr_registers *)ORION5X_TIMER_BASE; + +/* + * ARM Timers Registers Map + */ +#define CNTMR_CTRL_REG (&orion5x_tmr_regs->ctrl) +#define CNTMR_RELOAD_REG(tmrnum) (&orion5x_tmr_regs->tmr[tmrnum].reload) +#define CNTMR_VAL_REG(tmrnum) (&orion5x_tmr_regs->tmr[tmrnum].val) + +/* + * ARM Timers Control Register + * CPU_TIMERS_CTRL_REG (CTCR) + */ +#define CTCR_ARM_TIMER_EN_OFFS(cntr) (cntr * 2) +#define CTCR_ARM_TIMER_EN_MASK(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS) +#define CTCR_ARM_TIMER_EN(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS(cntr)) +#define CTCR_ARM_TIMER_DIS(cntr) (0 << CTCR_ARM_TIMER_EN_OFFS(cntr)) + +#define CTCR_ARM_TIMER_AUTO_OFFS(cntr) ((cntr * 2) + 1) +#define CTCR_ARM_TIMER_AUTO_MASK(cntr) (1 << 1) +#define CTCR_ARM_TIMER_AUTO_EN(cntr) (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) +#define CTCR_ARM_TIMER_AUTO_DIS(cntr) (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) + +/* + * ARM Timer\Watchdog Reload Register + * CNTMR_RELOAD_REG (TRR) + */ +#define TRG_ARM_TIMER_REL_OFFS 0 +#define TRG_ARM_TIMER_REL_MASK 0xffffffff + +/* + * ARM Timer\Watchdog Register + * CNTMR_VAL_REG (TVRG) + */ +#define TVR_ARM_TIMER_OFFS 0 +#define TVR_ARM_TIMER_MASK 0xffffffff +#define TVR_ARM_TIMER_MAX 0xffffffff +#define TIMER_LOAD_VAL 0xffffffff + +static inline ulong read_timer(void) +{ + return readl(CNTMR_VAL_REG(UBOOT_CNTR)) + / (CONFIG_SYS_TCLK / 1000); +} + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp gd->arch.tbl +#define lastdec gd->arch.lastinc + +ulong get_timer_masked(void) +{ + ulong now = read_timer(); + + if (lastdec >= now) { + /* normal mode */ + timestamp += lastdec - now; + } else { + /* we have an overflow ... */ + timestamp += lastdec + + (TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now; + } + lastdec = now; + + return timestamp; +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +static inline ulong uboot_cntr_val(void) +{ + return readl(CNTMR_VAL_REG(UBOOT_CNTR)); +} + +void __udelay(unsigned long usec) +{ + uint current; + ulong delayticks; + + current = uboot_cntr_val(); + delayticks = (usec * (CONFIG_SYS_TCLK / 1000000)); + + if (current < delayticks) { + delayticks -= current; + while (uboot_cntr_val() < current) + ; + while ((TIMER_LOAD_VAL - delayticks) < uboot_cntr_val()) + ; + } else { + while (uboot_cntr_val() > (current - delayticks)) + ; + } +} + +/* + * init the counter + */ +int timer_init(void) +{ + unsigned int cntmrctrl; + + /* load value into timer */ + writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR)); + writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR)); + + /* enable timer in auto reload mode */ + cntmrctrl = readl(CNTMR_CTRL_REG); + cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR); + cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR); + writel(cntmrctrl, CNTMR_CTRL_REG); + return 0; +} + +void timer_init_r(void) +{ + /* init the timestamp and lastdec value */ + lastdec = read_timer(); + timestamp = 0; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + return (ulong)CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/Makefile new file mode 100644 index 000000000..988341f8f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2011 +# Marvell Semiconductor <www.marvell.com> +# Written-by: Lei Wen <leiwen@marvell.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o timer.o dram.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/cpu.c new file mode 100644 index 000000000..4e2a177c0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/cpu.c @@ -0,0 +1,85 @@ +/* + * (C) Copyright 2011 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Lei Wen <leiwen@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/pantheon.h> + +#define UARTCLK14745KHZ (APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(1)) +#define SET_MRVL_ID (1<<8) +#define L2C_RAM_SEL (1<<4) + +int arch_cpu_init(void) +{ + u32 val; + struct panthcpu_registers *cpuregs = + (struct panthcpu_registers*) PANTHEON_CPU_BASE; + + struct panthapb_registers *apbclkres = + (struct panthapb_registers*) PANTHEON_APBC_BASE; + + struct panthmpmu_registers *mpmu = + (struct panthmpmu_registers*) PANTHEON_MPMU_BASE; + + struct panthapmu_registers *apmu = + (struct panthapmu_registers *) PANTHEON_APMU_BASE; + + /* set SEL_MRVL_ID bit in PANTHEON_CPU_CONF register */ + val = readl(&cpuregs->cpu_conf); + val = val | SET_MRVL_ID; + writel(val, &cpuregs->cpu_conf); + + /* Turn on clock gating (PMUM_CCGR) */ + writel(0xFFFFFFFF, &mpmu->ccgr); + + /* Turn on clock gating (PMUM_ACGR) */ + writel(0xFFFFFFFF, &mpmu->acgr); + + /* Turn on uart2 clock */ + writel(UARTCLK14745KHZ, &apbclkres->uart0); + + /* Enable GPIO clock */ + writel(APBC_APBCLK, &apbclkres->gpio); + +#ifdef CONFIG_I2C_MV + /* Enable I2C clock */ + writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apbclkres->twsi); + writel(APBC_FNCLK | APBC_APBCLK, &apbclkres->twsi); +#endif + +#ifdef CONFIG_MV_SDHCI + /* Enable mmc clock */ + writel(APMU_PERI_CLK | APMU_AXI_CLK | APMU_PERI_RST | APMU_AXI_RST, + &apmu->sd1); + writel(APMU_PERI_CLK | APMU_AXI_CLK | APMU_PERI_RST | APMU_AXI_RST, + &apmu->sd3); +#endif + + icache_enable(); + + return 0; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + u32 id; + struct panthcpu_registers *cpuregs = + (struct panthcpu_registers*) PANTHEON_CPU_BASE; + + id = readl(&cpuregs->chip_id); + printf("SoC: PANTHEON 88AP%X-%X\n", (id & 0xFFF), (id >> 0x10)); + return 0; +} +#endif + +#ifdef CONFIG_I2C_MV +void i2c_clk_enable(void) +{ +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/dram.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/dram.c new file mode 100644 index 000000000..f77e3d0ab --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/dram.c @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2011 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Lei Wen <leiwen@marvell.com>, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pantheon.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Pantheon DRAM controller supports upto 8 banks + * for chip select 0 and 1 + */ + +/* + * DDR Memory Control Registers + * Refer Datasheet 4.4 + */ +struct panthddr_map_registers { + u32 cs; /* Memory Address Map Register -CS */ + u32 pad[3]; +}; + +struct panthddr_registers { + u8 pad[0x100 - 0x000]; + struct panthddr_map_registers mmap[2]; +}; + +/* + * panth_sdram_base - reads SDRAM Base Address Register + */ +u32 panth_sdram_base(int chip_sel) +{ + struct panthddr_registers *ddr_regs = + (struct panthddr_registers *)PANTHEON_DRAM_BASE; + u32 result = 0; + u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); + + if (!CS_valid) + return 0; + + result = readl(&ddr_regs->mmap[chip_sel].cs) & 0xFF800000; + return result; +} + +/* + * panth_sdram_size - reads SDRAM size + */ +u32 panth_sdram_size(int chip_sel) +{ + struct panthddr_registers *ddr_regs = + (struct panthddr_registers *)PANTHEON_DRAM_BASE; + u32 result = 0; + u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); + + if (!CS_valid) + return 0; + + result = readl(&ddr_regs->mmap[chip_sel].cs); + result = (result >> 16) & 0xF; + if (result < 0x7) { + printf("Unknown DRAM Size\n"); + return -1; + } else { + return ((0x8 << (result - 0x7)) * 1024 * 1024); + } +} + +#ifndef CONFIG_SYS_BOARD_DRAM_INIT +int dram_init(void) +{ + int i; + + gd->ram_size = 0; + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = panth_sdram_base(i); + gd->bd->bi_dram[i].size = panth_sdram_size(i); + /* + * It is assumed that all memory banks are consecutive + * and without gaps. + * If the gap is found, ram_size will be reported for + * consecutive memory only + */ + if (gd->bd->bi_dram[i].start != gd->ram_size) + break; + + gd->ram_size += gd->bd->bi_dram[i].size; + + } + + for (; i < CONFIG_NR_DRAM_BANKS; i++) { + /* + * If above loop terminated prematurely, we need to set + * remaining banks' start address & size as 0. Otherwise other + * u-boot functions and Linux kernel gets wrong values which + * could result in crash + */ + gd->bd->bi_dram[i].start = 0; + gd->bd->bi_dram[i].size = 0; + } + return 0; +} + +/* + * If this function is not defined here, + * board.c alters dram bank zero configuration defined above. + */ +void dram_init_banksize(void) +{ + dram_init(); +} +#endif /* CONFIG_SYS_BOARD_DRAM_INIT */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/timer.c new file mode 100644 index 000000000..6382d3b0c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/timer.c @@ -0,0 +1,201 @@ +/* + * (C) Copyright 2011 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Lei Wen <leiwen@marvell.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/pantheon.h> + +/* + * Timer registers + * Refer 6.2.9 in Datasheet + */ +struct panthtmr_registers { + u32 clk_ctrl; /* Timer clk control reg */ + u32 match[9]; /* Timer match registers */ + u32 count[3]; /* Timer count registers */ + u32 status[3]; + u32 ie[3]; + u32 preload[3]; /* Timer preload value */ + u32 preload_ctrl[3]; + u32 wdt_match_en; + u32 wdt_match_r; + u32 wdt_val; + u32 wdt_sts; + u32 icr[3]; + u32 wdt_icr; + u32 cer; /* Timer count enable reg */ + u32 cmr; + u32 ilr[3]; + u32 wcr; + u32 wfar; + u32 wsar; + u32 cvwr[3]; +}; + +#define TIMER 0 /* Use TIMER 0 */ +/* Each timer has 3 match registers */ +#define MATCH_CMP(x) ((3 * TIMER) + x) +#define TIMER_LOAD_VAL 0xffffffff +#define COUNT_RD_REQ 0x1 + +DECLARE_GLOBAL_DATA_PTR; +/* Using gd->arch.tbu from timestamp and gd->arch.tbl for lastdec */ + +/* + * For preventing risk of instability in reading counter value, + * first set read request to register cvwr and then read same + * register after it captures counter value. + */ +ulong read_timer(void) +{ + struct panthtmr_registers *panthtimers = + (struct panthtmr_registers *) PANTHEON_TIMER_BASE; + volatile int loop=100; + ulong val; + + writel(COUNT_RD_REQ, &panthtimers->cvwr); + while (loop--) + val = readl(&panthtimers->cvwr); + + /* + * This stop gcc complain and prevent loop mistake init to 0 + */ + val = readl(&panthtimers->cvwr); + + return val; +} + +ulong get_timer_masked(void) +{ + ulong now = read_timer(); + + if (now >= gd->arch.tbl) { + /* normal mode */ + gd->arch.tbu += now - gd->arch.tbl; + } else { + /* we have an overflow ... */ + gd->arch.tbu += now + TIMER_LOAD_VAL - gd->arch.tbl; + } + gd->arch.tbl = now; + + return gd->arch.tbu; +} + +ulong get_timer(ulong base) +{ + return ((get_timer_masked() / (CONFIG_SYS_HZ_CLOCK / 1000)) - + base); +} + +void __udelay(unsigned long usec) +{ + ulong delayticks; + ulong endtime; + + delayticks = (usec * (CONFIG_SYS_HZ_CLOCK / 1000000)); + endtime = get_timer_masked() + delayticks; + + while (get_timer_masked() < endtime) + ; +} + +/* + * init the Timer + */ +int timer_init(void) +{ + struct panthapb_registers *apb1clkres = + (struct panthapb_registers *) PANTHEON_APBC_BASE; + struct panthtmr_registers *panthtimers = + (struct panthtmr_registers *) PANTHEON_TIMER_BASE; + + /* Enable Timer clock at 3.25 MHZ */ + writel(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3), &apb1clkres->timers); + + /* load value into timer */ + writel(0x0, &panthtimers->clk_ctrl); + /* Use Timer 0 Match Resiger 0 */ + writel(TIMER_LOAD_VAL, &panthtimers->match[MATCH_CMP(0)]); + /* Preload value is 0 */ + writel(0x0, &panthtimers->preload[TIMER]); + /* Enable match comparator 0 for Timer 0 */ + writel(0x1, &panthtimers->preload_ctrl[TIMER]); + + /* Enable timer 0 */ + writel(0x1, &panthtimers->cer); + /* init the gd->arch.tbu and gd->arch.tbl value */ + gd->arch.tbl = read_timer(); + gd->arch.tbu = 0; + + return 0; +} + +#define MPMU_APRR_WDTR (1<<4) +#define TMR_WFAR 0xbaba /* WDT Register First key */ +#define TMP_WSAR 0xeb10 /* WDT Register Second key */ + +/* + * This function uses internal Watchdog Timer + * based reset mechanism. + * Steps to write watchdog registers (protected access) + * 1. Write key value to TMR_WFAR reg. + * 2. Write key value to TMP_WSAR reg. + * 3. Perform write operation. + */ +void reset_cpu (unsigned long ignored) +{ + struct panthmpmu_registers *mpmu = + (struct panthmpmu_registers *) PANTHEON_MPMU_BASE; + struct panthtmr_registers *panthtimers = + (struct panthtmr_registers *) PANTHEON_WD_TIMER_BASE; + u32 val; + + /* negate hardware reset to the WDT after system reset */ + val = readl(&mpmu->aprr); + val = val | MPMU_APRR_WDTR; + writel(val, &mpmu->aprr); + + /* reset/enable WDT clock */ + writel(APBC_APBCLK, &mpmu->wdtpcr); + + /* clear previous WDT status */ + writel(TMR_WFAR, &panthtimers->wfar); + writel(TMP_WSAR, &panthtimers->wsar); + writel(0, &panthtimers->wdt_sts); + + /* set match counter */ + writel(TMR_WFAR, &panthtimers->wfar); + writel(TMP_WSAR, &panthtimers->wsar); + writel(0xf, &panthtimers->wdt_match_r); + + /* enable WDT reset */ + writel(TMR_WFAR, &panthtimers->wfar); + writel(TMP_WSAR, &panthtimers->wsar); + writel(0x3, &panthtimers->wdt_match_en); + + /*enable functional WDT clock */ + writel(APBC_APBCLK | APBC_FNCLK, &mpmu->wdtpcr); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + return (ulong)CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/Makefile new file mode 100644 index 000000000..3f190bc0c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/Makefile @@ -0,0 +1,21 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := cpu.o \ + reset.o \ + timer.o + +ifdef CONFIG_SPL_BUILD +obj-y += spl.o spl_boot.o +obj-$(CONFIG_SPEAR600) += spear600.o +obj-$(CONFIG_DDR_MT47H64M16) += spr600_mt47h64m16_3_333_cl5_psync.o +obj-$(CONFIG_DDR_MT47H32M16) += spr600_mt47h32m16_333_cl5_psync.o +obj-$(CONFIG_DDR_MT47H32M16) += spr600_mt47h32m16_37e_166_cl4_sync.o +obj-$(CONFIG_DDR_MT47H128M8) += spr600_mt47h128m8_3_266_cl5_async.o +endif + +extra-$(CONFIG_SPL_BUILD) := start.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/cpu.c new file mode 100644 index 000000000..3757ffb2c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/cpu.c @@ -0,0 +1,71 @@ +/* + * (C) Copyright 2010 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_misc.h> + +int arch_cpu_init(void) +{ + struct misc_regs *const misc_p = + (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 periph1_clken, periph_clk_cfg; + + periph1_clken = readl(&misc_p->periph1_clken); + +#if defined(CONFIG_SPEAR3XX) + periph1_clken |= MISC_GPT2ENB; +#elif defined(CONFIG_SPEAR600) + periph1_clken |= MISC_GPT3ENB; +#endif + +#if defined(CONFIG_PL011_SERIAL) + periph1_clken |= MISC_UART0ENB; + + periph_clk_cfg = readl(&misc_p->periph_clk_cfg); + periph_clk_cfg &= ~CONFIG_SPEAR_UARTCLKMSK; + periph_clk_cfg |= CONFIG_SPEAR_UART48M; + writel(periph_clk_cfg, &misc_p->periph_clk_cfg); +#endif +#if defined(CONFIG_DESIGNWARE_ETH) + periph1_clken |= MISC_ETHENB; +#endif +#if defined(CONFIG_DW_UDC) + periph1_clken |= MISC_USBDENB; +#endif +#if defined(CONFIG_DW_I2C) + periph1_clken |= MISC_I2CENB; +#endif +#if defined(CONFIG_ST_SMI) + periph1_clken |= MISC_SMIENB; +#endif +#if defined(CONFIG_NAND_FSMC) + periph1_clken |= MISC_FSMCENB; +#endif + + writel(periph1_clken, &misc_p->periph1_clken); + return 0; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ +#ifdef CONFIG_SPEAR300 + printf("CPU: SPEAr300\n"); +#elif defined(CONFIG_SPEAR310) + printf("CPU: SPEAr310\n"); +#elif defined(CONFIG_SPEAR320) + printf("CPU: SPEAr320\n"); +#elif defined(CONFIG_SPEAR600) + printf("CPU: SPEAr600\n"); +#else +#error CPU not supported in spear platform +#endif + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/reset.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/reset.c new file mode 100644 index 000000000..9546e80bc --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/reset.c @@ -0,0 +1,38 @@ +/* + * (C) Copyright 2009 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_syscntl.h> + +void reset_cpu(ulong ignored) +{ + struct syscntl_regs *syscntl_regs_p = + (struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE; + + printf("System is going to reboot ...\n"); + + /* + * This 1 second delay will allow the above message + * to be printed before reset + */ + udelay((1000 * 1000)); + + /* Going into slow mode before resetting SOC */ + writel(0x02, &syscntl_regs_p->scctrl); + + /* + * Writing any value to the system status register will + * reset the SoC + */ + writel(0x00, &syscntl_regs_p->scsysstat); + + /* system will restart */ + while (1) + ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spear600.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spear600.c new file mode 100644 index 000000000..6474e9d55 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spear600.c @@ -0,0 +1,217 @@ +/* + * (C) Copyright 2000-2009 + * Viresh Kumar, ST Microelectronics, viresh.kumar@st.com + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/arch/spr_misc.h> +#include <asm/arch/spr_defs.h> + +static void sel_1v8(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 ddr1v8, ddr2v5; + + ddr2v5 = readl(&misc_p->ddr_2v5_compensation); + ddr2v5 &= 0x8080ffc0; + ddr2v5 |= 0x78000003; + writel(ddr2v5, &misc_p->ddr_2v5_compensation); + + ddr1v8 = readl(&misc_p->ddr_1v8_compensation); + ddr1v8 &= 0x8080ffc0; + ddr1v8 |= 0x78000010; + writel(ddr1v8, &misc_p->ddr_1v8_compensation); + + while (!(readl(&misc_p->ddr_1v8_compensation) & DDR_COMP_ACCURATE)) + ; +} + +static void sel_2v5(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 ddr1v8, ddr2v5; + + ddr1v8 = readl(&misc_p->ddr_1v8_compensation); + ddr1v8 &= 0x8080ffc0; + ddr1v8 |= 0x78000003; + writel(ddr1v8, &misc_p->ddr_1v8_compensation); + + ddr2v5 = readl(&misc_p->ddr_2v5_compensation); + ddr2v5 &= 0x8080ffc0; + ddr2v5 |= 0x78000010; + writel(ddr2v5, &misc_p->ddr_2v5_compensation); + + while (!(readl(&misc_p->ddr_2v5_compensation) & DDR_COMP_ACCURATE)) + ; +} + +/* + * plat_ddr_init: + */ +void plat_ddr_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 ddrpad; + u32 core3v3, ddr1v8, ddr2v5; + + /* DDR pad register configurations */ + ddrpad = readl(&misc_p->ddr_pad); + ddrpad &= ~DDR_PAD_CNF_MSK; + +#if (CONFIG_DDR_HCLK) + ddrpad |= 0xEAAB; +#elif (CONFIG_DDR_2HCLK) + ddrpad |= 0xEAAD; +#elif (CONFIG_DDR_PLL2) + ddrpad |= 0xEAAD; +#endif + writel(ddrpad, &misc_p->ddr_pad); + + /* Compensation register configurations */ + core3v3 = readl(&misc_p->core_3v3_compensation); + core3v3 &= 0x8080ffe0; + core3v3 |= 0x78000002; + writel(core3v3, &misc_p->core_3v3_compensation); + + ddr1v8 = readl(&misc_p->ddr_1v8_compensation); + ddr1v8 &= 0x8080ffc0; + ddr1v8 |= 0x78000004; + writel(ddr1v8, &misc_p->ddr_1v8_compensation); + + ddr2v5 = readl(&misc_p->ddr_2v5_compensation); + ddr2v5 &= 0x8080ffc0; + ddr2v5 |= 0x78000004; + writel(ddr2v5, &misc_p->ddr_2v5_compensation); + + if ((readl(&misc_p->ddr_pad) & DDR_PAD_SW_CONF) == DDR_PAD_SW_CONF) { + /* Software memory configuration */ + if (readl(&misc_p->ddr_pad) & DDR_PAD_SSTL_SEL) + sel_1v8(); + else + sel_2v5(); + } else { + /* Hardware memory configuration */ + if (readl(&misc_p->ddr_pad) & DDR_PAD_DRAM_TYPE) + sel_1v8(); + else + sel_2v5(); + } +} + +/* + * soc_init: + */ +void soc_init(void) +{ + /* Nothing to be done for SPEAr600 */ +} + +/* + * xxx_boot_selected: + * + * return true if the particular booting option is selected + * return false otherwise + */ +static u32 read_bootstrap(void) +{ + return (readl(CONFIG_SPEAR_BOOTSTRAPCFG) >> CONFIG_SPEAR_BOOTSTRAPSHFT) + & CONFIG_SPEAR_BOOTSTRAPMASK; +} + +int snor_boot_selected(void) +{ + u32 bootstrap = read_bootstrap(); + + if (SNOR_BOOT_SUPPORTED) { + /* Check whether SNOR boot is selected */ + if ((bootstrap & CONFIG_SPEAR_ONLYSNORBOOT) == + CONFIG_SPEAR_ONLYSNORBOOT) + return true; + + if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) == + CONFIG_SPEAR_NORNAND8BOOT) + return true; + + if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) == + CONFIG_SPEAR_NORNAND16BOOT) + return true; + } + + return false; +} + +int nand_boot_selected(void) +{ + u32 bootstrap = read_bootstrap(); + + if (NAND_BOOT_SUPPORTED) { + /* Check whether NAND boot is selected */ + if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) == + CONFIG_SPEAR_NORNAND8BOOT) + return true; + + if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) == + CONFIG_SPEAR_NORNAND16BOOT) + return true; + } + + return false; +} + +int pnor_boot_selected(void) +{ + /* Parallel NOR boot is not selected in any SPEAr600 revision */ + return false; +} + +int usb_boot_selected(void) +{ + u32 bootstrap = read_bootstrap(); + + if (USB_BOOT_SUPPORTED) { + /* Check whether USB boot is selected */ + if (!(bootstrap & CONFIG_SPEAR_USBBOOT)) + return true; + } + + return false; +} + +int tftp_boot_selected(void) +{ + /* TFTP boot is not selected in any SPEAr600 revision */ + return false; +} + +int uart_boot_selected(void) +{ + /* UART boot is not selected in any SPEAr600 revision */ + return false; +} + +int spi_boot_selected(void) +{ + /* SPI boot is not selected in any SPEAr600 revision */ + return false; +} + +int i2c_boot_selected(void) +{ + /* I2C boot is not selected in any SPEAr600 revision */ + return false; +} + +int mmc_boot_selected(void) +{ + return false; +} + +void plat_late_init(void) +{ + spear_late_init(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spl.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spl.c new file mode 100644 index 000000000..b55040435 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spl.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2011 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * Copyright (C) 2012 Stefan Roese <sr@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <version.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_defs.h> +#include <asm/arch/spr_misc.h> +#include <asm/arch/spr_syscntl.h> + +static void ddr_clock_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 clkenb, ddrpll; + + clkenb = readl(&misc_p->periph1_clken); + clkenb &= ~PERIPH_MPMCMSK; + clkenb |= PERIPH_MPMC_WE; + + /* Intentionally done twice */ + writel(clkenb, &misc_p->periph1_clken); + writel(clkenb, &misc_p->periph1_clken); + + ddrpll = readl(&misc_p->pll_ctr_reg); + ddrpll &= ~MEM_CLK_SEL_MSK; +#if (CONFIG_DDR_HCLK) + ddrpll |= MEM_CLK_HCLK; +#elif (CONFIG_DDR_2HCLK) + ddrpll |= MEM_CLK_2HCLK; +#elif (CONFIG_DDR_PLL2) + ddrpll |= MEM_CLK_PLL2; +#else +#error "please define one of CONFIG_DDR_(HCLK|2HCLK|PLL2)" +#endif + writel(ddrpll, &misc_p->pll_ctr_reg); + + writel(readl(&misc_p->periph1_clken) | PERIPH_MPMC_EN, + &misc_p->periph1_clken); +} + +static void mpmc_init_values(void) +{ + u32 i; + u32 *mpmc_reg_p = (u32 *)CONFIG_SPEAR_MPMCBASE; + u32 *mpmc_val_p = &mpmc_conf_vals[0]; + + for (i = 0; i < CONFIG_SPEAR_MPMCREGS; i++, mpmc_reg_p++, mpmc_val_p++) + writel(*mpmc_val_p, mpmc_reg_p); + + mpmc_reg_p = (u32 *)CONFIG_SPEAR_MPMCBASE; + + /* + * MPMC controller start + * MPMC waiting for DLLLOCKREG high + */ + writel(0x01000100, &mpmc_reg_p[7]); + + while (!(readl(&mpmc_reg_p[3]) & 0x10000)) + ; +} + +static void mpmc_init(void) +{ + /* Clock related settings for DDR */ + ddr_clock_init(); + + /* + * DDR pad register bits are different for different SoCs + * Compensation values are also handled separately + */ + plat_ddr_init(); + + /* Initialize mpmc register values */ + mpmc_init_values(); +} + +static void pll_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + + /* Initialize PLLs */ + writel(FREQ_332, &misc_p->pll1_frq); + writel(0x1C0A, &misc_p->pll1_cntl); + writel(0x1C0E, &misc_p->pll1_cntl); + writel(0x1C06, &misc_p->pll1_cntl); + writel(0x1C0E, &misc_p->pll1_cntl); + + writel(FREQ_332, &misc_p->pll2_frq); + writel(0x1C0A, &misc_p->pll2_cntl); + writel(0x1C0E, &misc_p->pll2_cntl); + writel(0x1C06, &misc_p->pll2_cntl); + writel(0x1C0E, &misc_p->pll2_cntl); + + /* wait for pll locks */ + while (!(readl(&misc_p->pll1_cntl) & 0x1)) + ; + while (!(readl(&misc_p->pll2_cntl) & 0x1)) + ; +} + +static void mac_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + + writel(readl(&misc_p->periph1_clken) & (~PERIPH_GMAC), + &misc_p->periph1_clken); + + writel(SYNTH23, &misc_p->gmac_synth_clk); + + switch (get_socrev()) { + case SOC_SPEAR600_AA: + case SOC_SPEAR600_AB: + case SOC_SPEAR600_BA: + case SOC_SPEAR600_BB: + case SOC_SPEAR600_BC: + case SOC_SPEAR600_BD: + writel(0x0, &misc_p->gmac_ctr_reg); + break; + + case SOC_SPEAR300: + case SOC_SPEAR310: + case SOC_SPEAR320: + writel(0x4, &misc_p->gmac_ctr_reg); + break; + } + + writel(readl(&misc_p->periph1_clken) | PERIPH_GMAC, + &misc_p->periph1_clken); + + writel(readl(&misc_p->periph1_rst) | PERIPH_GMAC, + &misc_p->periph1_rst); + writel(readl(&misc_p->periph1_rst) & (~PERIPH_GMAC), + &misc_p->periph1_rst); +} + +static void sys_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + struct syscntl_regs *syscntl_p = + (struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE; + + /* Set system state to SLOW */ + writel(SLOW, &syscntl_p->scctrl); + writel(PLL_TIM << 3, &syscntl_p->scpllctrl); + + /* Initialize PLLs */ + pll_init(); + + /* + * Ethernet configuration + * To be done only if the tftp boot is not selected already + * Boot code ensures the correct configuration in tftp booting + */ + if (!tftp_boot_selected()) + mac_init(); + + writel(RTC_DISABLE | PLLTIMEEN, &misc_p->periph_clk_cfg); + writel(0x555, &misc_p->amba_clk_cfg); + + writel(NORMAL, &syscntl_p->scctrl); + + /* Wait for system to switch to normal mode */ + while (((readl(&syscntl_p->scctrl) >> MODE_SHIFT) & MODE_MASK) + != NORMAL) + ; +} + +/* + * get_socrev + * + * Get SoC Revision. + * @return SOC_SPEARXXX + */ +int get_socrev(void) +{ +#if defined(CONFIG_SPEAR600) + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 soc_id = readl(&misc_p->soc_core_id); + u32 pri_socid = (soc_id >> SOC_PRI_SHFT) & 0xFF; + u32 sec_socid = (soc_id >> SOC_SEC_SHFT) & 0xFF; + + if ((pri_socid == 'B') && (sec_socid == 'B')) + return SOC_SPEAR600_BB; + else if ((pri_socid == 'B') && (sec_socid == 'C')) + return SOC_SPEAR600_BC; + else if ((pri_socid == 'B') && (sec_socid == 'D')) + return SOC_SPEAR600_BD; + else if (soc_id == 0) + return SOC_SPEAR600_BA; + else + return SOC_SPEAR_NA; +#elif defined(CONFIG_SPEAR300) + return SOC_SPEAR300; +#elif defined(CONFIG_SPEAR310) + return SOC_SPEAR310; +#elif defined(CONFIG_SPEAR320) + return SOC_SPEAR320; +#endif +} + +void lowlevel_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + const char *u_boot_rev = U_BOOT_VERSION; + + /* Initialize PLLs */ + sys_init(); + + /* Initialize UART */ + serial_init(); + + /* Print U-Boot SPL version string */ + serial_puts("\nU-Boot SPL "); + /* Avoid a second "U-Boot" coming from this string */ + u_boot_rev = &u_boot_rev[7]; + serial_puts(u_boot_rev); + serial_puts(" ("); + serial_puts(U_BOOT_DATE); + serial_puts(" - "); + serial_puts(U_BOOT_TIME); + serial_puts(")\n"); + +#if defined(CONFIG_OS_BOOT) + writel(readl(&misc_p->periph1_clken) | PERIPH_UART1, + &misc_p->periph1_clken); +#endif + + /* Enable IPs (release reset) */ + writel(PERIPH_RST_ALL, &misc_p->periph1_rst); + + /* Initialize MPMC */ + serial_puts("Configure DDR\n"); + mpmc_init(); + + /* SoC specific initialization */ + soc_init(); +} + +void spear_late_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + + writel(0x80000007, &misc_p->arb_icm_ml1); + writel(0x80000007, &misc_p->arb_icm_ml2); + writel(0x80000007, &misc_p->arb_icm_ml3); + writel(0x80000007, &misc_p->arb_icm_ml4); + writel(0x80000007, &misc_p->arb_icm_ml5); + writel(0x80000007, &misc_p->arb_icm_ml6); + writel(0x80000007, &misc_p->arb_icm_ml7); + writel(0x80000007, &misc_p->arb_icm_ml8); + writel(0x80000007, &misc_p->arb_icm_ml9); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spl_boot.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spl_boot.c new file mode 100644 index 000000000..c846d758c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spl_boot.c @@ -0,0 +1,181 @@ +/* + * (C) Copyright 2000-2009 + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + * + * Copyright (C) 2012 Stefan Roese <sr@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <image.h> +#include <linux/compiler.h> +#include <asm/io.h> +#include <asm/arch/spr_defs.h> +#include <linux/mtd/st_smi.h> + +static const char kernel_name[] = "Linux"; +static const char loader_name[] = "U-Boot"; + +int image_check_header(image_header_t *hdr, const char *name) +{ + if (image_check_magic(hdr) && + (!strncmp(image_get_name(hdr), name, strlen(name))) && + image_check_hcrc(hdr)) { + return 1; + } + return 0; +} + +int image_check_data(image_header_t *hdr) +{ + if (image_check_dcrc(hdr)) + return 1; + + return 0; +} + +/* + * SNOR (Serial NOR flash) related functions + */ +void snor_init(void) +{ + struct smi_regs *const smicntl = + (struct smi_regs * const)CONFIG_SYS_SMI_BASE; + + /* Setting the fast mode values. SMI working at 166/4 = 41.5 MHz */ + writel(HOLD1 | FAST_MODE | BANK_EN | DSEL_TIME | PRESCAL4, + &smicntl->smi_cr1); +} + +static int snor_image_load(u8 *load_addr, void (**image_p)(void), + const char *image_name) +{ + image_header_t *header; + + /* + * Since calculating the crc in the SNOR flash does not + * work, we copy the image to the destination address + * minus the header size. And point the header to this + * new destination. This will not work for address 0 + * of course. + */ + header = (image_header_t *)load_addr; + memcpy((ulong *)(image_get_load(header) - sizeof(image_header_t)), + (const ulong *)load_addr, + image_get_data_size(header) + sizeof(image_header_t)); + header = (image_header_t *)(image_get_load(header) - + sizeof(image_header_t)); + + if (image_check_header(header, image_name)) { + if (image_check_data(header)) { + /* Jump to boot image */ + *image_p = (void *)image_get_load(header); + return 1; + } + } + + return 0; +} + +static void boot_image(void (*image)(void)) +{ + void (*funcp)(void) __noreturn = (void *)image; + + (*funcp)(); +} + +/* + * spl_boot: + * + * All supported booting types of all supported SoCs are listed here. + * Generic readback APIs are provided for each supported booting type + * eg. nand_read_skip_bad + */ +u32 spl_boot(void) +{ + void (*image)(void); + +#ifdef CONFIG_SPEAR_USBTTY + plat_late_init(); + return 1; +#endif + + /* + * All the supported booting devices are listed here. Each of + * the booting type supported by the platform would define the + * macro xxx_BOOT_SUPPORTED to true. + */ + + if (SNOR_BOOT_SUPPORTED && snor_boot_selected()) { + /* SNOR-SMI initialization */ + snor_init(); + + serial_puts("Booting via SNOR\n"); + /* Serial NOR booting */ + if (1 == snor_image_load((u8 *)CONFIG_SYS_UBOOT_BASE, + &image, loader_name)) { + /* Platform related late initialasations */ + plat_late_init(); + + /* Jump to boot image */ + serial_puts("Jumping to U-Boot\n"); + boot_image(image); + return 1; + } + } + + if (NAND_BOOT_SUPPORTED && nand_boot_selected()) { + /* NAND booting */ + /* Not ported from XLoader to SPL yet */ + return 0; + } + + if (PNOR_BOOT_SUPPORTED && pnor_boot_selected()) { + /* PNOR booting */ + /* Not ported from XLoader to SPL yet */ + return 0; + } + + if (MMC_BOOT_SUPPORTED && mmc_boot_selected()) { + /* MMC booting */ + /* Not ported from XLoader to SPL yet */ + return 0; + } + + if (SPI_BOOT_SUPPORTED && spi_boot_selected()) { + /* SPI booting */ + /* Not supported for any platform as of now */ + return 0; + } + + if (I2C_BOOT_SUPPORTED && i2c_boot_selected()) { + /* I2C booting */ + /* Not supported for any platform as of now */ + return 0; + } + + /* + * All booting types without memory are listed as below + * Control has to be returned to BootROM in case of all + * the following booting scenarios + */ + + if (USB_BOOT_SUPPORTED && usb_boot_selected()) { + plat_late_init(); + return 1; + } + + if (TFTP_BOOT_SUPPORTED && tftp_boot_selected()) { + plat_late_init(); + return 1; + } + + if (UART_BOOT_SUPPORTED && uart_boot_selected()) { + plat_late_init(); + return 1; + } + + /* Ideally, the control should not reach here. */ + hang(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h128m8_3_266_cl5_async.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h128m8_3_266_cl5_async.c new file mode 100644 index 000000000..3d6ad04ab --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h128m8_3_266_cl5_async.c @@ -0,0 +1,114 @@ +/* + * (C) Copyright 2000-2009 + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#if (CONFIG_DDR_PLL2) + +const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = { + 0x00000001, + 0x00000000, + 0x01000000, + 0x00000101, + 0x00000001, + 0x01000000, + 0x00010001, + 0x00000100, + 0x00010001, + 0x00000003, + 0x01000201, + 0x06000202, + 0x06060106, + 0x03050502, + 0x03040404, + 0x02020503, + 0x02010106, + 0x03000404, + 0x02030202, + 0x03000204, + 0x0707073f, + 0x07070707, + 0x06060607, + 0x06060606, + 0x05050506, + 0x05050505, + 0x04040405, + 0x04040404, + 0x03030304, + 0x03030303, + 0x02020203, + 0x02020202, + 0x01010102, + 0x01010101, + 0x08080a01, + 0x0000023f, + 0x00040800, + 0x00000000, + 0x00000f02, + 0x00001b1b, + 0x7f000000, + 0x005f0000, + 0x1c040b6a, + 0x00640064, + 0x00640064, + 0x00640064, + 0x00000064, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x000007ff, + 0x00000000, + 0x47ec00c8, + 0x00c8001f, + 0x00000000, + 0x0000cd98, + 0x00000000, + 0x03030100, + 0x03030303, + 0x03030303, + 0x03030303, + 0x00270000, + 0x00250027, + 0x00300000, + 0x008900b7, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_333_cl5_psync.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_333_cl5_psync.c new file mode 100644 index 000000000..105b3058f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_333_cl5_psync.c @@ -0,0 +1,119 @@ +/* + * (C) Copyright 2000-2009 + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#if (CONFIG_DDR_PLL2 || CONFIG_DDR_2HCLK) + +const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = { +#if (CONFIG_DDR_PLL2) + 0x00000001, + 0x00000000, +#elif (CONFIG_DDR_2HCLK) + 0x02020201, + 0x02020202, +#endif + 0x01000000, + 0x00000101, + 0x00000101, + 0x01000000, + 0x00010001, + 0x00000100, + 0x01010001, + 0x00000201, + 0x01000101, + 0x06000002, + 0x06060106, + 0x03050502, + 0x03040404, + 0x02020503, + 0x02010106, + 0x03000405, + 0x03040202, + 0x04000305, + 0x0707073f, + 0x07070707, + 0x06060607, + 0x06060606, + 0x05050506, + 0x05050505, + 0x04040405, + 0x04040404, + 0x03030304, + 0x03030303, + 0x02020203, + 0x02020202, + 0x01010102, + 0x01010101, + 0x0a0a0a01, + 0x0000023f, + 0x00050a00, + 0x11000000, + 0x00001302, + 0x00000A0A, + 0x72000000, + 0x00550000, + 0x2b050e86, + 0x00640064, + 0x00640064, + 0x00640064, + 0x00000064, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00000a24, + 0x43C20000, + 0x5b1c00c8, + 0x00c8002e, + 0x00000000, + 0x0001046b, + 0x00000000, + 0x03030100, + 0x03030303, + 0x03030303, + 0x03030303, + 0x00210000, + 0x00010021, + 0x00200000, + 0x006c0090, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_37e_166_cl4_sync.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_37e_166_cl4_sync.c new file mode 100644 index 000000000..00b6b2927 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_37e_166_cl4_sync.c @@ -0,0 +1,114 @@ +/* + * (C) Copyright 2000-2009 + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#if (CONFIG_DDR_HCLK) + +const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = { + 0x03030301, + 0x03030303, + 0x01000000, + 0x00000101, + 0x00000001, + 0x01000000, + 0x00010001, + 0x00000100, + 0x00010001, + 0x00000003, + 0x01000201, + 0x06000202, + 0x06060106, + 0x03050502, + 0x03040404, + 0x02020503, + 0x02010106, + 0x03000404, + 0x02020202, + 0x03000203, + 0x0707073f, + 0x07070707, + 0x06060607, + 0x06060606, + 0x05050506, + 0x05050505, + 0x04040405, + 0x04040404, + 0x03030304, + 0x03030303, + 0x02020203, + 0x02020202, + 0x01010102, + 0x01010101, + 0x08080a01, + 0x0000023f, + 0x00030600, + 0x00000000, + 0x00000a02, + 0x00001c1c, + 0x7f000000, + 0x005f0000, + 0x12030743, + 0x00640064, + 0x00640064, + 0x00640064, + 0x00000064, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x0000050e, + 0x00000000, + 0x2d8900c8, + 0x00c80014, + 0x00000000, + 0x00008236, + 0x00000000, + 0x03030100, + 0x03030303, + 0x03030303, + 0x03030303, + 0x00400000, + 0x003a0040, + 0x00680000, + 0x00d80120, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h64m16_3_333_cl5_psync.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h64m16_3_333_cl5_psync.c new file mode 100644 index 000000000..a406c3e8c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/spr600_mt47h64m16_3_333_cl5_psync.c @@ -0,0 +1,128 @@ +/* + * (C) Copyright 2000-2009 + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#if (CONFIG_DDR_PLL2 || CONFIG_DDR_2HCLK) + +const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = { +#if (CONFIG_DDR_PLL2) + 0x00000001, + 0x00000000, +#elif (CONFIG_DDR_2HCLK) + 0x02020201, + 0x02020202, +#endif + 0x01000000, + 0x00000101, + 0x00000101, + 0x01000000, + 0x00010001, + 0x00000100, + 0x01010001, + 0x00000201, + 0x01000101, + 0x06000002, + 0x06060106, + 0x03050502, + 0x03040404, + 0x02020503, +#ifdef CONFIG_X600 + 0x02030206, +#else + 0x02010106, +#endif + 0x03000405, + 0x03040202, + 0x04000305, + 0x0707073f, + 0x07070707, + 0x06060607, + 0x06060606, + 0x05050506, + 0x05050505, + 0x04040405, + 0x04040404, + 0x03030304, + 0x03030303, + 0x02020203, + 0x02020202, + 0x01010102, + 0x01010101, + 0x0a0a0a01, + 0x0000023f, + 0x00050a00, + 0x11000000, + 0x00001302, + 0x00000A0A, +#ifdef CONFIG_X600 + 0x7f000000, + 0x005c0000, +#else + 0x72000000, + 0x00550000, +#endif + 0x2b050e86, + 0x00640064, + 0x00640064, + 0x00640064, + 0x00000064, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00000a24, + 0x43C20000, + 0x5b1c00c8, + 0x00c8002e, + 0x00000000, + 0x0001046b, + 0x00000000, + 0x03030100, + 0x03030303, + 0x03030303, + 0x03030303, + 0x00210000, + 0x00010021, + 0x00200000, + 0x006c0090, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/start.S b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/start.S new file mode 100644 index 000000000..7dbd5dbf9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/start.S @@ -0,0 +1,106 @@ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + +#include <config.h> + +.globl _start +_start: + b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: +_software_interrupt: +_prefetch_abort: +_data_abort: +_not_used: +_irq: +_fiq: + .word infinite_loop + +infinite_loop: + b infinite_loop + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * Below are the critical initializations already taken place in BootROM. + * So, these are not taken care in Xloader + * 1. Relocation to RAM + * 2. Initializing stacks + * + ************************************************************************* + */ + +/* + * the actual reset code + */ + +reset: +/* + * Xloader has to return back to BootROM in a few cases. + * eg. Ethernet boot, UART boot, USB boot + * Saving registers for returning back + */ + stmdb sp!, {r0-r12,r14} + bl cpu_init_crit +/* + * Clearing bss area is not done in Xloader. + * BSS area lies in the DDR location which is not yet initialized + * bss is assumed to be uninitialized. + */ + bl spl_boot + ldmia sp!, {r0-r12,pc} + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + + /* + * enable instruction cache + */ + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ + mcr p15, 0, r0, c1, c0, 0 + + /* + * Go setup Memory and board specific bits prior to relocation. + */ + stmdb sp!, {lr} + bl lowlevel_init /* go setup pll,mux,memory */ + ldmia sp!, {pc} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/timer.c new file mode 100644 index 000000000..c88e962a3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/timer.c @@ -0,0 +1,123 @@ +/* + * (C) Copyright 2009 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_gpt.h> +#include <asm/arch/spr_misc.h> + +#define GPT_RESOLUTION (CONFIG_SPEAR_HZ_CLOCK / CONFIG_SPEAR_HZ) +#define READ_TIMER() (readl(&gpt_regs_p->count) & GPT_FREE_RUNNING) + +static struct gpt_regs *const gpt_regs_p = + (struct gpt_regs *)CONFIG_SPEAR_TIMERBASE; + +static struct misc_regs *const misc_regs_p = + (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp gd->arch.tbl +#define lastdec gd->arch.lastinc + +int timer_init(void) +{ + u32 synth; + + /* Prescaler setting */ +#if defined(CONFIG_SPEAR3XX) + writel(MISC_PRSC_CFG, &misc_regs_p->prsc2_clk_cfg); + synth = MISC_GPT4SYNTH; +#elif defined(CONFIG_SPEAR600) + writel(MISC_PRSC_CFG, &misc_regs_p->prsc1_clk_cfg); + synth = MISC_GPT3SYNTH; +#else +# error Incorrect config. Can only be spear{600|300|310|320} +#endif + + writel(readl(&misc_regs_p->periph_clk_cfg) | synth, + &misc_regs_p->periph_clk_cfg); + + /* disable timers */ + writel(GPT_PRESCALER_1 | GPT_MODE_AUTO_RELOAD, &gpt_regs_p->control); + + /* load value for free running */ + writel(GPT_FREE_RUNNING, &gpt_regs_p->compare); + + /* auto reload, start timer */ + writel(readl(&gpt_regs_p->control) | GPT_ENABLE, &gpt_regs_p->control); + + /* Reset the timer */ + lastdec = READ_TIMER(); + timestamp = 0; + + return 0; +} + +/* + * timer without interrupts + */ +ulong get_timer(ulong base) +{ + return (get_timer_masked() / GPT_RESOLUTION) - base; +} + +void __udelay(unsigned long usec) +{ + ulong tmo; + ulong start = get_timer_masked(); + ulong tenudelcnt = CONFIG_SPEAR_HZ_CLOCK / (1000 * 100); + ulong rndoff; + + rndoff = (usec % 10) ? 1 : 0; + + /* tenudelcnt timer tick gives 10 microsecconds delay */ + tmo = ((usec / 10) + rndoff) * tenudelcnt; + + while ((ulong) (get_timer_masked() - start) < tmo) + ; +} + +ulong get_timer_masked(void) +{ + ulong now = READ_TIMER(); + + if (now >= lastdec) { + /* normal mode */ + timestamp += now - lastdec; + } else { + /* we have an overflow ... */ + timestamp += now + GPT_FREE_RUNNING - lastdec; + } + lastdec = now; + + return timestamp; +} + +void udelay_masked(unsigned long usec) +{ + return udelay(usec); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_SPEAR_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds new file mode 100644 index 000000000..b6d0f65b6 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * January 2004 - Changed to support H4 device + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + arch/arm/cpu/arm926ejs/spear/start.o (.text*) + *(.text*) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + + .rel.dyn : { + __rel_dyn_start = .; + *(.rel*) + __rel_dyn_end = .; + } + + .bss : { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } + + .end : + { + *(.__end) + } + + _image_binary_end = .; + + .dynsym _image_binary_end : { *(.dynsym) } + .dynbss : { *(.dynbss) } + .dynstr : { *(.dynstr*) } + .dynamic : { *(.dynamic*) } + .hash : { *(.hash*) } + .plt : { *(.plt*) } + .interp : { *(.interp*) } + .gnu : { *(.gnu*) } + .ARM.exidx : { *(.ARM.exidx*) } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/start.S b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/start.S new file mode 100644 index 000000000..071732705 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/start.S @@ -0,0 +1,372 @@ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <common.h> +#include <version.h> + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + + +#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG +.globl _start +_start: +.globl _NOR_BOOT_CFG +_NOR_BOOT_CFG: + .word CONFIG_SYS_DV_NOR_BOOT_CFG + b reset +#else +.globl _start +_start: + b reset +#endif +#ifdef CONFIG_SPL_BUILD +/* No exception handlers in preloader */ + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + +_hang: + .word do_hang +/* pad to 64 byte boundary */ + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 +#else + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: + .word undefined_instruction +_software_interrupt: + .word software_interrupt +_prefetch_abort: + .word prefetch_abort +_data_abort: + .word data_abort +_not_used: + .word not_used +_irq: + .word irq +_fiq: + .word fiq + +#endif /* CONFIG_SPL_BUILD */ + .balignl 16,0xdeadbeef + + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + bx lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + /* + * flush D cache before disabling it + */ + mov r0, #0 +flush_dcache: + mrc p15, 0, r15, c7, c10, 3 + bne flush_dcache + + mcr p15, 0, r0, c8, c7, 0 /* invalidate TLB */ + mcr p15, 0, r0, c7, c5, 0 /* invalidate I Cache */ + + /* + * disable MMU and D cache + * enable I cache if CONFIG_SYS_ICACHE_OFF is not defined + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00000300 /* clear bits 9:8 (---- --RS) */ + bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ +#ifdef CONFIG_SYS_EXCEPTION_VECTORS_HIGH + orr r0, r0, #0x00002000 /* set bit 13 (--V- ----) */ +#else + bic r0, r0, #0x00002000 /* clear bit 13 (--V- ----) */ +#endif + orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ +#ifndef CONFIG_SYS_ICACHE_OFF + orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ +#endif + mcr p15, 0, r0, c1, c0, 0 + + /* + * Go setup Memory and board specific bits prior to relocation. + */ + mov ip, lr /* perserve link reg across call */ + bl lowlevel_init /* go setup pll,mux,memory */ + mov lr, ip /* restore link */ + mov pc, lr /* back to my caller */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + +#ifndef CONFIG_SPL_BUILD +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + @ carve out a frame on current user stack + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 + ldr r2, IRQ_STACK_START_IN + @ get values for "aborted" pc and cpsr (into parm regs) + ldmia r2, {r2 - r3} + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp @ save current stack into r0 (param register) + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + + str lr, [r13] @ save caller lr in position 0 of saved stack + mrs lr, spsr @ get the spsr + str lr, [r13, #4] @ save spsr in position 1 of saved stack + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 @ switch modes, make sure moves will execute + mov lr, pc @ capture return pc + movs pc, lr @ jump to next instruction & switch modes. + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm +#endif /* CONFIG_SPL_BUILD */ + +/* + * exception handlers + */ +#ifdef CONFIG_SPL_BUILD + .align 5 +do_hang: +1: + bl 1b /* hang and never return */ +#else /* !CONFIG_SPL_BUILD */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif +#endif /* CONFIG_SPL_BUILD */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/versatile/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/versatile/Makefile new file mode 100644 index 000000000..907f5161a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/versatile/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = timer.o +obj-y += reset.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/versatile/reset.S b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/versatile/reset.S new file mode 100644 index 000000000..1c557b0d9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/versatile/reset.S @@ -0,0 +1,29 @@ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + .align 5 +.globl reset_cpu +reset_cpu: + ldr r1, rstctl1 /* get clkm1 reset ctl */ + mov r3, #0x0 + strh r3, [r1] /* clear it */ + mov r3, #0x8 + strh r3, [r1] /* force dsp+arm reset */ +_loop_forever: + b _loop_forever + +rstctl1: + .word 0xfffece10 diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/versatile/timer.c b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/versatile/timer.c new file mode 100644 index 000000000..5d694d85e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm926ejs/versatile/timer.c @@ -0,0 +1,64 @@ +/* + * (C) Copyright 2003 + * Texas Instruments <www.ti.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#define TIMER_ENABLE (1 << 7) +#define TIMER_MODE_MSK (1 << 6) +#define TIMER_MODE_FR (0 << 6) +#define TIMER_MODE_PD (1 << 6) + +#define TIMER_INT_EN (1 << 5) +#define TIMER_PRS_MSK (3 << 2) +#define TIMER_PRS_8S (1 << 3) +#define TIMER_SIZE_MSK (1 << 2) +#define TIMER_ONE_SHT (1 << 0) + +int timer_init (void) +{ + ulong tmr_ctrl_val; + + /* 1st disable the Timer */ + tmr_ctrl_val = *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8); + tmr_ctrl_val &= ~TIMER_ENABLE; + *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8) = tmr_ctrl_val; + + /* + * The Timer Control Register has one Undefined/Shouldn't Use Bit + * So we should do read/modify/write Operation + */ + + /* + * Timer Mode : Free Running + * Interrupt : Disabled + * Prescale : 8 Stage, Clk/256 + * Tmr Siz : 16 Bit Counter + * Tmr in Wrapping Mode + */ + tmr_ctrl_val = *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8); + tmr_ctrl_val &= ~(TIMER_MODE_MSK | TIMER_INT_EN | TIMER_PRS_MSK | TIMER_SIZE_MSK | TIMER_ONE_SHT ); + tmr_ctrl_val |= (TIMER_ENABLE | TIMER_PRS_8S); + + *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8) = tmr_ctrl_val; + + return 0; +} + diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm946es/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm946es/Makefile new file mode 100644 index 000000000..a44bddc2f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm946es/Makefile @@ -0,0 +1,10 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y = start.o + +obj-y = cpu.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm946es/config.mk b/qemu/roms/u-boot/arch/arm/cpu/arm946es/config.mk new file mode 100644 index 000000000..438668d6f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm946es/config.mk @@ -0,0 +1,8 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +PLATFORM_CPPFLAGS += -march=armv4 diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm946es/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm946es/cpu.c new file mode 100644 index 000000000..0c8d92d73 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm946es/cpu.c @@ -0,0 +1,53 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +static void cache_flush(void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + disable_interrupts (); + + /* ARM926E-S needs the protection unit enabled for the icache to have + * been enabled - left for possible later use + * should turn off the protection unit as well.... + */ + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + /* flush I/D-cache */ + cache_flush(); + + return 0; +} + +/* flush I/D-cache */ +static void cache_flush (void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (i)); + asm ("mcr p15, 0, %0, c7, c6, 0": :"r" (i)); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm946es/start.S b/qemu/roms/u-boot/arch/arm/cpu/arm946es/start.S new file mode 100644 index 000000000..7d5014583 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm946es/start.S @@ -0,0 +1,345 @@ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + + +.globl _start +_start: + b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: + .word undefined_instruction +_software_interrupt: + .word software_interrupt +_prefetch_abort: + .word prefetch_abort +_data_abort: + .word data_abort +_not_used: + .word not_used +_irq: + .word irq +_fiq: + .word fiq + + .balignl 16,0xdeadbeef + +_vectors_end: + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 /* flush v4 I-cache */ + mcr p15, 0, r0, c7, c6, 0 /* flush v4 D-cache */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ + bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ + orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ + orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ + mcr p15, 0, r0, c1, c0, 0 + + /* + * Go setup Memory and board specific bits prior to relocation. + */ + mov ip, lr /* perserve link reg across call */ + bl lowlevel_init /* go setup memory */ + mov lr, ip /* restore link */ + mov pc, lr /* back to my caller */ +#endif +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + @ carve out a frame on current user stack + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 + + ldr r2, IRQ_STACK_START_IN + @ get values for "aborted" pc and cpsr (into parm regs) + ldmia r2, {r2 - r3} + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp @ save current stack into r0 (param register) + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + + str lr, [r13] @ save caller lr in position 0 of saved stack + mrs lr, spsr @ get the spsr + str lr, [r13, #4] @ save spsr in position 1 of saved stack + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 @ switch modes, make sure moves will execute + mov lr, pc @ capture return pc + movs pc, lr @ jump to next instruction & switch modes. + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif + +# ifdef CONFIG_INTEGRATOR + + /* Satisfied by general board level routine */ + +#else + + .align 5 +.globl reset_cpu +reset_cpu: + + ldr r1, rstctl1 /* get clkm1 reset ctl */ + mov r3, #0x0 + strh r3, [r1] /* clear it */ + mov r3, #0x8 + strh r3, [r1] /* force dsp+arm reset */ +_loop_forever: + b _loop_forever + +rstctl1: + .word 0xfffece10 + +#endif /* #ifdef CONFIG_INTEGRATOR */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/Makefile b/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/Makefile new file mode 100644 index 000000000..3279f125f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y = start.o +obj-y = cpu.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/config.mk b/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/config.mk new file mode 100644 index 000000000..438668d6f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/config.mk @@ -0,0 +1,8 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +PLATFORM_CPPFLAGS += -march=armv4 diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/cpu.c new file mode 100644 index 000000000..0d00e4b7a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/cpu.c @@ -0,0 +1,36 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * CPU specific code for an unknown cpu + * - hence fairly empty...... + */ + +#include <common.h> +#include <command.h> + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + disable_interrupts (); + + /* Since the CM has unknown processor we do not support + * cache operations + */ + + return (0); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/start.S b/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/start.S new file mode 100644 index 000000000..7404ea734 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/arm_intcm/start.S @@ -0,0 +1,305 @@ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> + +/* + ************************************************************************* + * + * Jump vector table + * + ************************************************************************* + */ + +.globl _start +_start: + b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: + .word undefined_instruction +_software_interrupt: + .word software_interrupt +_prefetch_abort: + .word prefetch_abort +_data_abort: + .word data_abort +_not_used: + .word not_used +_irq: + .word irq +_fiq: + .word fiq + + .balignl 16,0xdeadbeef + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + /* arm_int_generic assumes the ARM boot monitor, or user software, + * has initialized the platform + */ + mov pc, lr /* back to my caller */ +#endif +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + @ carve out a frame on current user stack + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 + + ldr r2, IRQ_STACK_START_IN + @ get values for "aborted" pc and cpsr (into parm regs) + ldmia r2, {r2 - r3} + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp @ save current stack into r0 (param register) + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + + str lr, [r13] @ save caller lr in position 0 of saved stack + mrs lr, spsr @ get the spsr + str lr, [r13, #4] @ save spsr in position 1 of saved stack + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 @ switch modes, make sure moves will execute + mov lr, pc @ capture return pc + movs pc, lr @ jump to next instruction & switch modes. + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + .align 5 +.globl undefined_instruction +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +.globl software_interrupt +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +.globl prefetch_abort +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +.globl data_abort +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +.globl not_used +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + .align 5 +.globl irq +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +.globl fiq +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +.globl irq +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +.globl fiq +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/Makefile new file mode 100644 index 000000000..ab869b1ee --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/Makefile @@ -0,0 +1,33 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y := start.o + +obj-y += cache_v7.o + +obj-y += cpu.o +obj-y += syslib.o + +ifneq ($(CONFIG_AM43XX)$(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA)$(CONFIG_MX6)$(CONFIG_TI81XX)$(CONFIG_AT91FAMILY),) +ifneq ($(CONFIG_SKIP_LOWLEVEL_INIT),y) +obj-y += lowlevel_init.o +endif +endif + +ifneq ($(CONFIG_ARMV7_NONSEC)$(CONFIG_ARMV7_VIRT),) +obj-y += nonsec_virt.o +obj-y += virt-v7.o +endif + +obj-$(CONFIG_KONA) += kona-common/ +obj-$(CONFIG_OMAP_COMMON) += omap-common/ +obj-$(CONFIG_SYS_ARCH_TIMER) += arch_timer.o +obj-$(CONFIG_TEGRA) += tegra-common/ + +ifneq (,$(filter s5pc1xx exynos,$(SOC))) +obj-y += s5p-common/ +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/Makefile new file mode 100644 index 000000000..5566310d9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/Makefile @@ -0,0 +1,21 @@ +# +# Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_AM33XX) += clock_am33xx.o +obj-$(CONFIG_TI814X) += clock_ti814x.o +obj-$(CONFIG_AM43XX) += clock_am43xx.o + +ifneq ($(CONFIG_AM43XX)$(CONFIG_AM33XX),) +obj-y += clock.o +endif + +obj-$(CONFIG_TI816X) += clock_ti816x.o +obj-y += sys_info.o +obj-y += mem.o +obj-y += ddr.o +obj-y += emif4.o +obj-y += board.o +obj-y += mux.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/board.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/board.c new file mode 100644 index 000000000..28c16f8d0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/board.c @@ -0,0 +1,251 @@ +/* + * board.c + * + * Common board functions for AM33XX based boards + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <spl.h> +#include <asm/arch/cpu.h> +#include <asm/arch/hardware.h> +#include <asm/arch/omap.h> +#include <asm/arch/ddr_defs.h> +#include <asm/arch/clock.h> +#include <asm/arch/gpio.h> +#include <asm/arch/mem.h> +#include <asm/arch/mmc_host_def.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> +#include <asm/emif.h> +#include <asm/gpio.h> +#include <i2c.h> +#include <miiphy.h> +#include <cpsw.h> +#include <asm/errno.h> +#include <linux/compiler.h> +#include <linux/usb/ch9.h> +#include <linux/usb/gadget.h> +#include <linux/usb/musb.h> +#include <asm/omap_musb.h> +#include <asm/davinci_rtc.h> + +DECLARE_GLOBAL_DATA_PTR; + +static const struct gpio_bank gpio_bank_am33xx[] = { + { (void *)AM33XX_GPIO0_BASE, METHOD_GPIO_24XX }, + { (void *)AM33XX_GPIO1_BASE, METHOD_GPIO_24XX }, + { (void *)AM33XX_GPIO2_BASE, METHOD_GPIO_24XX }, + { (void *)AM33XX_GPIO3_BASE, METHOD_GPIO_24XX }, +#ifdef CONFIG_AM43XX + { (void *)AM33XX_GPIO4_BASE, METHOD_GPIO_24XX }, + { (void *)AM33XX_GPIO5_BASE, METHOD_GPIO_24XX }, +#endif +}; + +const struct gpio_bank *const omap_gpio_bank = gpio_bank_am33xx; + +#if defined(CONFIG_OMAP_HSMMC) && !defined(CONFIG_SPL_BUILD) +int cpu_mmc_init(bd_t *bis) +{ + int ret; + + ret = omap_mmc_init(0, 0, 0, -1, -1); + if (ret) + return ret; + + return omap_mmc_init(1, 0, 0, -1, -1); +} +#endif + +/* AM33XX has two MUSB controllers which can be host or gadget */ +#if (defined(CONFIG_MUSB_GADGET) || defined(CONFIG_MUSB_HOST)) && \ + (defined(CONFIG_AM335X_USB0) || defined(CONFIG_AM335X_USB1)) +static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; + +/* USB 2.0 PHY Control */ +#define CM_PHY_PWRDN (1 << 0) +#define CM_PHY_OTG_PWRDN (1 << 1) +#define OTGVDET_EN (1 << 19) +#define OTGSESSENDEN (1 << 20) + +static void am33xx_usb_set_phy_power(u8 on, u32 *reg_addr) +{ + if (on) { + clrsetbits_le32(reg_addr, CM_PHY_PWRDN | CM_PHY_OTG_PWRDN, + OTGVDET_EN | OTGSESSENDEN); + } else { + clrsetbits_le32(reg_addr, 0, CM_PHY_PWRDN | CM_PHY_OTG_PWRDN); + } +} + +static struct musb_hdrc_config musb_config = { + .multipoint = 1, + .dyn_fifo = 1, + .num_eps = 16, + .ram_bits = 12, +}; + +#ifdef CONFIG_AM335X_USB0 +static void am33xx_otg0_set_phy_power(u8 on) +{ + am33xx_usb_set_phy_power(on, &cdev->usb_ctrl0); +} + +struct omap_musb_board_data otg0_board_data = { + .set_phy_power = am33xx_otg0_set_phy_power, +}; + +static struct musb_hdrc_platform_data otg0_plat = { + .mode = CONFIG_AM335X_USB0_MODE, + .config = &musb_config, + .power = 50, + .platform_ops = &musb_dsps_ops, + .board_data = &otg0_board_data, +}; +#endif + +#ifdef CONFIG_AM335X_USB1 +static void am33xx_otg1_set_phy_power(u8 on) +{ + am33xx_usb_set_phy_power(on, &cdev->usb_ctrl1); +} + +struct omap_musb_board_data otg1_board_data = { + .set_phy_power = am33xx_otg1_set_phy_power, +}; + +static struct musb_hdrc_platform_data otg1_plat = { + .mode = CONFIG_AM335X_USB1_MODE, + .config = &musb_config, + .power = 50, + .platform_ops = &musb_dsps_ops, + .board_data = &otg1_board_data, +}; +#endif +#endif + +int arch_misc_init(void) +{ +#ifdef CONFIG_AM335X_USB0 + musb_register(&otg0_plat, &otg0_board_data, + (void *)USB0_OTG_BASE); +#endif +#ifdef CONFIG_AM335X_USB1 + musb_register(&otg1_plat, &otg1_board_data, + (void *)USB1_OTG_BASE); +#endif + return 0; +} + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +/* + * This function is the place to do per-board things such as ramp up the + * MPU clock frequency. + */ +__weak void am33xx_spl_board_init(void) +{ + do_setup_dpll(&dpll_core_regs, &dpll_core_opp100); + do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100); +} + +#if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC) +static void rtc32k_enable(void) +{ + struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE; + + /* + * Unlock the RTC's registers. For more details please see the + * RTC_SS section of the TRM. In order to unlock we need to + * write these specific values (keys) in this order. + */ + writel(RTC_KICK0R_WE, &rtc->kick0r); + writel(RTC_KICK1R_WE, &rtc->kick1r); + + /* Enable the RTC 32K OSC by setting bits 3 and 6. */ + writel((1 << 3) | (1 << 6), &rtc->osc); +} +#endif + +static void uart_soft_reset(void) +{ + struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE; + u32 regval; + + regval = readl(&uart_base->uartsyscfg); + regval |= UART_RESET; + writel(regval, &uart_base->uartsyscfg); + while ((readl(&uart_base->uartsyssts) & + UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK) + ; + + /* Disable smart idle */ + regval = readl(&uart_base->uartsyscfg); + regval |= UART_SMART_IDLE_EN; + writel(regval, &uart_base->uartsyscfg); +} + +static void watchdog_disable(void) +{ + struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE; + + writel(0xAAAA, &wdtimer->wdtwspr); + while (readl(&wdtimer->wdtwwps) != 0x0) + ; + writel(0x5555, &wdtimer->wdtwspr); + while (readl(&wdtimer->wdtwwps) != 0x0) + ; +} + +void s_init(void) +{ + /* + * The ROM will only have set up sufficient pinmux to allow for the + * first 4KiB NOR to be read, we must finish doing what we know of + * the NOR mux in this space in order to continue. + */ +#ifdef CONFIG_NOR_BOOT + enable_norboot_pin_mux(); +#endif + /* + * Save the boot parameters passed from romcode. + * We cannot delay the saving further than this, + * to prevent overwrites. + */ +#ifdef CONFIG_SPL_BUILD + save_omap_boot_params(); +#endif + watchdog_disable(); + timer_init(); + set_uart_mux_conf(); + setup_clocks_for_console(); + uart_soft_reset(); +#ifdef CONFIG_NOR_BOOT + gd->baudrate = CONFIG_BAUDRATE; + serial_init(); + gd->have_console = 1; +#elif defined(CONFIG_SPL_BUILD) + gd = &gdata; + preloader_console_init(); +#endif + prcm_init(); + set_mux_conf_regs(); +#if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC) + /* Enable RTC32K clock */ + rtc32k_enable(); +#endif + sdram_init(); +} +#endif + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif /* !CONFIG_SYS_DCACHE_OFF */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock.c new file mode 100644 index 000000000..0672798fe --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock.c @@ -0,0 +1,177 @@ +/* + * clock.c + * + * Clock initialization for AM33XX boards. + * Derived from OMAP4 boards + * + * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clock.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> + +static void setup_post_dividers(const struct dpll_regs *dpll_regs, + const struct dpll_params *params) +{ + /* Setup post-dividers */ + if (params->m2 >= 0) + writel(params->m2, dpll_regs->cm_div_m2_dpll); + if (params->m3 >= 0) + writel(params->m3, dpll_regs->cm_div_m3_dpll); + if (params->m4 >= 0) + writel(params->m4, dpll_regs->cm_div_m4_dpll); + if (params->m5 >= 0) + writel(params->m5, dpll_regs->cm_div_m5_dpll); + if (params->m6 >= 0) + writel(params->m6, dpll_regs->cm_div_m6_dpll); +} + +static inline void do_lock_dpll(const struct dpll_regs *dpll_regs) +{ + clrsetbits_le32(dpll_regs->cm_clkmode_dpll, + CM_CLKMODE_DPLL_DPLL_EN_MASK, + DPLL_EN_LOCK << CM_CLKMODE_DPLL_EN_SHIFT); +} + +static inline void wait_for_lock(const struct dpll_regs *dpll_regs) +{ + if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK, + (void *)dpll_regs->cm_idlest_dpll, LDELAY)) { + printf("DPLL locking failed for 0x%x\n", + dpll_regs->cm_clkmode_dpll); + hang(); + } +} + +static inline void do_bypass_dpll(const struct dpll_regs *dpll_regs) +{ + clrsetbits_le32(dpll_regs->cm_clkmode_dpll, + CM_CLKMODE_DPLL_DPLL_EN_MASK, + DPLL_EN_MN_BYPASS << CM_CLKMODE_DPLL_EN_SHIFT); +} + +static inline void wait_for_bypass(const struct dpll_regs *dpll_regs) +{ + if (!wait_on_value(ST_DPLL_CLK_MASK, 0, + (void *)dpll_regs->cm_idlest_dpll, LDELAY)) { + printf("Bypassing DPLL failed 0x%x\n", + dpll_regs->cm_clkmode_dpll); + } +} + +static void bypass_dpll(const struct dpll_regs *dpll_regs) +{ + do_bypass_dpll(dpll_regs); + wait_for_bypass(dpll_regs); +} + +void do_setup_dpll(const struct dpll_regs *dpll_regs, + const struct dpll_params *params) +{ + u32 temp; + + if (!params) + return; + + temp = readl(dpll_regs->cm_clksel_dpll); + + bypass_dpll(dpll_regs); + + /* Set M & N */ + temp &= ~CM_CLKSEL_DPLL_M_MASK; + temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK; + + temp &= ~CM_CLKSEL_DPLL_N_MASK; + temp |= (params->n << CM_CLKSEL_DPLL_N_SHIFT) & CM_CLKSEL_DPLL_N_MASK; + + writel(temp, dpll_regs->cm_clksel_dpll); + + setup_post_dividers(dpll_regs, params); + + /* Wait till the DPLL locks */ + do_lock_dpll(dpll_regs); + wait_for_lock(dpll_regs); +} + +static void setup_dplls(void) +{ + const struct dpll_params *params; + + params = get_dpll_core_params(); + do_setup_dpll(&dpll_core_regs, params); + + params = get_dpll_mpu_params(); + do_setup_dpll(&dpll_mpu_regs, params); + + params = get_dpll_per_params(); + do_setup_dpll(&dpll_per_regs, params); + writel(0x300, &cmwkup->clkdcoldodpllper); + + params = get_dpll_ddr_params(); + do_setup_dpll(&dpll_ddr_regs, params); +} + +static inline void wait_for_clk_enable(u32 *clkctrl_addr) +{ + u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED; + u32 bound = LDELAY; + + while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) || + (idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) { + clkctrl = readl(clkctrl_addr); + idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >> + MODULE_CLKCTRL_IDLEST_SHIFT; + if (--bound == 0) { + printf("Clock enable failed for 0x%p idlest 0x%x\n", + clkctrl_addr, clkctrl); + return; + } + } +} + +static inline void enable_clock_module(u32 *const clkctrl_addr, u32 enable_mode, + u32 wait_for_enable) +{ + clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK, + enable_mode << MODULE_CLKCTRL_MODULEMODE_SHIFT); + debug("Enable clock module - %p\n", clkctrl_addr); + if (wait_for_enable) + wait_for_clk_enable(clkctrl_addr); +} + +static inline void enable_clock_domain(u32 *const clkctrl_reg, u32 enable_mode) +{ + clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK, + enable_mode << CD_CLKCTRL_CLKTRCTRL_SHIFT); + debug("Enable clock domain - %p\n", clkctrl_reg); +} + +void do_enable_clocks(u32 *const *clk_domains, + u32 *const *clk_modules_explicit_en, u8 wait_for_enable) +{ + u32 i, max = 100; + + /* Put the clock domains in SW_WKUP mode */ + for (i = 0; (i < max) && clk_domains[i]; i++) { + enable_clock_domain(clk_domains[i], + CD_CLKCTRL_CLKTRCTRL_SW_WKUP); + } + + /* Clock modules that need to be put in SW_EXPLICIT_EN mode */ + for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) { + enable_clock_module(clk_modules_explicit_en[i], + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN, + wait_for_enable); + }; +} + +void prcm_init() +{ + enable_basic_clocks(); + setup_dplls(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_am33xx.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_am33xx.c new file mode 100644 index 000000000..92142c893 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_am33xx.c @@ -0,0 +1,161 @@ +/* + * clock_am33xx.c + * + * clocks for AM33XX based boards + * + * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clock.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> + +#define OSC (V_OSCK/1000000) + +struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER; +struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP; +struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL; +struct cm_rtc *const cmrtc = (struct cm_rtc *)CM_RTC; + +const struct dpll_regs dpll_mpu_regs = { + .cm_clkmode_dpll = CM_WKUP + 0x88, + .cm_idlest_dpll = CM_WKUP + 0x20, + .cm_clksel_dpll = CM_WKUP + 0x2C, + .cm_div_m2_dpll = CM_WKUP + 0xA8, +}; + +const struct dpll_regs dpll_core_regs = { + .cm_clkmode_dpll = CM_WKUP + 0x90, + .cm_idlest_dpll = CM_WKUP + 0x5C, + .cm_clksel_dpll = CM_WKUP + 0x68, + .cm_div_m4_dpll = CM_WKUP + 0x80, + .cm_div_m5_dpll = CM_WKUP + 0x84, + .cm_div_m6_dpll = CM_WKUP + 0xD8, +}; + +const struct dpll_regs dpll_per_regs = { + .cm_clkmode_dpll = CM_WKUP + 0x8C, + .cm_idlest_dpll = CM_WKUP + 0x70, + .cm_clksel_dpll = CM_WKUP + 0x9C, + .cm_div_m2_dpll = CM_WKUP + 0xAC, +}; + +const struct dpll_regs dpll_ddr_regs = { + .cm_clkmode_dpll = CM_WKUP + 0x94, + .cm_idlest_dpll = CM_WKUP + 0x34, + .cm_clksel_dpll = CM_WKUP + 0x40, + .cm_div_m2_dpll = CM_WKUP + 0xA0, +}; + +struct dpll_params dpll_mpu_opp100 = { + CONFIG_SYS_MPUCLK, OSC-1, 1, -1, -1, -1, -1}; +const struct dpll_params dpll_core_opp100 = { + 1000, OSC-1, -1, -1, 10, 8, 4}; +const struct dpll_params dpll_mpu = { + MPUPLL_M_300, OSC-1, 1, -1, -1, -1, -1}; +const struct dpll_params dpll_core = { + 50, OSC-1, -1, -1, 1, 1, 1}; +const struct dpll_params dpll_per = { + 960, OSC-1, 5, -1, -1, -1, -1}; + +const struct dpll_params *get_dpll_mpu_params(void) +{ + return &dpll_mpu; +} + +const struct dpll_params *get_dpll_core_params(void) +{ + return &dpll_core; +} + +const struct dpll_params *get_dpll_per_params(void) +{ + return &dpll_per; +} + +void setup_clocks_for_console(void) +{ + clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, + CD_CLKCTRL_CLKTRCTRL_SW_WKUP << + CD_CLKCTRL_CLKTRCTRL_SHIFT); + + clrsetbits_le32(&cmper->l4hsclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, + CD_CLKCTRL_CLKTRCTRL_SW_WKUP << + CD_CLKCTRL_CLKTRCTRL_SHIFT); + + clrsetbits_le32(&cmwkup->wkup_uart0ctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); + clrsetbits_le32(&cmper->uart1clkctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); + clrsetbits_le32(&cmper->uart2clkctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); + clrsetbits_le32(&cmper->uart3clkctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); + clrsetbits_le32(&cmper->uart4clkctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); + clrsetbits_le32(&cmper->uart5clkctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); +} + +void enable_basic_clocks(void) +{ + u32 *const clk_domains[] = { + &cmper->l3clkstctrl, + &cmper->l4fwclkstctrl, + &cmper->l3sclkstctrl, + &cmper->l4lsclkstctrl, + &cmwkup->wkclkstctrl, + &cmper->emiffwclkctrl, + &cmrtc->clkstctrl, + 0 + }; + + u32 *const clk_modules_explicit_en[] = { + &cmper->l3clkctrl, + &cmper->l4lsclkctrl, + &cmper->l4fwclkctrl, + &cmwkup->wkl4wkclkctrl, + &cmper->l3instrclkctrl, + &cmper->l4hsclkctrl, + &cmwkup->wkgpio0clkctrl, + &cmwkup->wkctrlclkctrl, + &cmper->timer2clkctrl, + &cmper->gpmcclkctrl, + &cmper->elmclkctrl, + &cmper->mmc0clkctrl, + &cmper->mmc1clkctrl, + &cmwkup->wkup_i2c0ctrl, + &cmper->gpio1clkctrl, + &cmper->gpio2clkctrl, + &cmper->gpio3clkctrl, + &cmper->i2c1clkctrl, + &cmper->cpgmac0clkctrl, + &cmper->spi0clkctrl, + &cmrtc->rtcclkctrl, + &cmper->usb0clkctrl, + &cmper->emiffwclkctrl, + &cmper->emifclkctrl, + 0 + }; + + do_enable_clocks(clk_domains, clk_modules_explicit_en, 1); + + /* Select the Master osc 24 MHZ as Timer2 clock source */ + writel(0x1, &cmdpll->clktimer2clk); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_am43xx.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_am43xx.c new file mode 100644 index 000000000..d0bc2340c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_am43xx.c @@ -0,0 +1,112 @@ +/* + * clock_am43xx.c + * + * clocks for AM43XX based boards + * Derived from AM33XX based boards + * + * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clock.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> + +struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER; +struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP; +struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL; + +const struct dpll_regs dpll_mpu_regs = { + .cm_clkmode_dpll = CM_WKUP + 0x560, + .cm_idlest_dpll = CM_WKUP + 0x564, + .cm_clksel_dpll = CM_WKUP + 0x56c, + .cm_div_m2_dpll = CM_WKUP + 0x570, +}; + +const struct dpll_regs dpll_core_regs = { + .cm_clkmode_dpll = CM_WKUP + 0x520, + .cm_idlest_dpll = CM_WKUP + 0x524, + .cm_clksel_dpll = CM_WKUP + 0x52C, + .cm_div_m4_dpll = CM_WKUP + 0x538, + .cm_div_m5_dpll = CM_WKUP + 0x53C, + .cm_div_m6_dpll = CM_WKUP + 0x540, +}; + +const struct dpll_regs dpll_per_regs = { + .cm_clkmode_dpll = CM_WKUP + 0x5E0, + .cm_idlest_dpll = CM_WKUP + 0x5E4, + .cm_clksel_dpll = CM_WKUP + 0x5EC, + .cm_div_m2_dpll = CM_WKUP + 0x5F0, +}; + +const struct dpll_regs dpll_ddr_regs = { + .cm_clkmode_dpll = CM_WKUP + 0x5A0, + .cm_idlest_dpll = CM_WKUP + 0x5A4, + .cm_clksel_dpll = CM_WKUP + 0x5AC, + .cm_div_m2_dpll = CM_WKUP + 0x5B0, + .cm_div_m4_dpll = CM_WKUP + 0x5B8, +}; + +void setup_clocks_for_console(void) +{ + /* Do not add any spl_debug prints in this function */ + clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, + CD_CLKCTRL_CLKTRCTRL_SW_WKUP << + CD_CLKCTRL_CLKTRCTRL_SHIFT); + + /* Enable UART0 */ + clrsetbits_le32(&cmwkup->wkup_uart0ctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); +} + +void enable_basic_clocks(void) +{ + u32 *const clk_domains[] = { + &cmper->l3clkstctrl, + &cmper->l3sclkstctrl, + &cmper->l4lsclkstctrl, + &cmwkup->wkclkstctrl, + &cmper->emifclkstctrl, + 0 + }; + + u32 *const clk_modules_explicit_en[] = { + &cmper->l3clkctrl, + &cmper->l4lsclkctrl, + &cmper->l4fwclkctrl, + &cmwkup->wkl4wkclkctrl, + &cmper->l3instrclkctrl, + &cmper->l4hsclkctrl, + &cmwkup->wkgpio0clkctrl, + &cmwkup->wkctrlclkctrl, + &cmper->timer2clkctrl, + &cmper->gpmcclkctrl, + &cmper->elmclkctrl, + &cmper->mmc0clkctrl, + &cmper->mmc1clkctrl, + &cmwkup->wkup_i2c0ctrl, + &cmper->gpio1clkctrl, + &cmper->gpio2clkctrl, + &cmper->gpio3clkctrl, + &cmper->gpio4clkctrl, + &cmper->gpio5clkctrl, + &cmper->i2c1clkctrl, + &cmper->cpgmac0clkctrl, + &cmper->emiffwclkctrl, + &cmper->emifclkctrl, + &cmper->otfaemifclkctrl, + &cmper->qspiclkctrl, + 0 + }; + + do_enable_clocks(clk_domains, clk_modules_explicit_en, 1); + + /* Select the Master osc clk as Timer2 clock source */ + writel(0x1, &cmdpll->clktimer2clk); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_ti814x.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_ti814x.c new file mode 100644 index 000000000..9b5a47b01 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_ti814x.c @@ -0,0 +1,404 @@ +/* + * clock_ti814x.c + * + * Clocks for TI814X based boards + * + * Copyright (C) 2013, Texas Instruments, Incorporated + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clock.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> + +/* PRCM */ +#define PRCM_MOD_EN 0x2 + +/* CLK_SRC */ +#define OSC_SRC0 0 +#define OSC_SRC1 1 + +#define L3_OSC_SRC OSC_SRC0 + +#define OSC_0_FREQ 20 + +#define DCO_HS2_MIN 500 +#define DCO_HS2_MAX 1000 +#define DCO_HS1_MIN 1000 +#define DCO_HS1_MAX 2000 + +#define SELFREQDCO_HS2 0x00000801 +#define SELFREQDCO_HS1 0x00001001 + +#define MPU_N 0x1 +#define MPU_M 0x3C +#define MPU_M2 1 +#define MPU_CLKCTRL 0x1 + +#define L3_N 19 +#define L3_M 880 +#define L3_M2 4 +#define L3_CLKCTRL 0x801 + +#define DDR_N 19 +#define DDR_M 666 +#define DDR_M2 2 +#define DDR_CLKCTRL 0x801 + +/* ADPLLJ register values */ +#define ADPLLJ_CLKCTRL_HS2 0x00000801 /* HS2 mode, TINT2 = 1 */ +#define ADPLLJ_CLKCTRL_HS1 0x00001001 /* HS1 mode, TINT2 = 1 */ +#define ADPLLJ_CLKCTRL_CLKDCOLDOEN (1 << 29) +#define ADPLLJ_CLKCTRL_IDLE (1 << 23) +#define ADPLLJ_CLKCTRL_CLKOUTEN (1 << 20) +#define ADPLLJ_CLKCTRL_CLKOUTLDOEN (1 << 19) +#define ADPLLJ_CLKCTRL_CLKDCOLDOPWDNZ (1 << 17) +#define ADPLLJ_CLKCTRL_LPMODE (1 << 12) +#define ADPLLJ_CLKCTRL_DRIFTGUARDIAN (1 << 11) +#define ADPLLJ_CLKCTRL_REGM4XEN (1 << 10) +#define ADPLLJ_CLKCTRL_TINITZ (1 << 0) +#define ADPLLJ_CLKCTRL_CLKDCO (ADPLLJ_CLKCTRL_CLKDCOLDOEN | \ + ADPLLJ_CLKCTRL_CLKOUTEN | \ + ADPLLJ_CLKCTRL_CLKOUTLDOEN | \ + ADPLLJ_CLKCTRL_CLKDCOLDOPWDNZ) + +#define ADPLLJ_STATUS_PHASELOCK (1 << 10) +#define ADPLLJ_STATUS_FREQLOCK (1 << 9) +#define ADPLLJ_STATUS_PHSFRQLOCK (ADPLLJ_STATUS_PHASELOCK | \ + ADPLLJ_STATUS_FREQLOCK) +#define ADPLLJ_STATUS_BYPASSACK (1 << 8) +#define ADPLLJ_STATUS_BYPASS (1 << 0) +#define ADPLLJ_STATUS_BYPASSANDACK (ADPLLJ_STATUS_BYPASSACK | \ + ADPLLJ_STATUS_BYPASS) + +#define ADPLLJ_TENABLE_ENB (1 << 0) +#define ADPLLJ_TENABLEDIV_ENB (1 << 0) + +#define ADPLLJ_M2NDIV_M2SHIFT 16 + +#define MPU_PLL_BASE (PLL_SUBSYS_BASE + 0x048) +#define L3_PLL_BASE (PLL_SUBSYS_BASE + 0x110) +#define DDR_PLL_BASE (PLL_SUBSYS_BASE + 0x290) + +struct ad_pll { + unsigned int pwrctrl; + unsigned int clkctrl; + unsigned int tenable; + unsigned int tenablediv; + unsigned int m2ndiv; + unsigned int mn2div; + unsigned int fracdiv; + unsigned int bwctrl; + unsigned int fracctrl; + unsigned int status; + unsigned int m3div; + unsigned int rampctrl; +}; + +#define OSC_SRC_CTRL (PLL_SUBSYS_BASE + 0x2C0) + +#define ENET_CLKCTRL_CMPL 0x30000 + +#define SATA_PLL_BASE (CTRL_BASE + 0x0720) + +struct sata_pll { + unsigned int pllcfg0; + unsigned int pllcfg1; + unsigned int pllcfg2; + unsigned int pllcfg3; + unsigned int pllcfg4; + unsigned int pllstatus; + unsigned int rxstatus; + unsigned int txstatus; + unsigned int testcfg; +}; + +#define SEL_IN_FREQ (0x1 << 31) +#define DIGCLRZ (0x1 << 30) +#define ENDIGLDO (0x1 << 4) +#define APLL_CP_CURR (0x1 << 3) +#define ENBGSC_REF (0x1 << 2) +#define ENPLLLDO (0x1 << 1) +#define ENPLL (0x1 << 0) + +#define SATA_PLLCFG0_1 (SEL_IN_FREQ | ENBGSC_REF) +#define SATA_PLLCFG0_2 (SEL_IN_FREQ | ENDIGLDO | ENBGSC_REF) +#define SATA_PLLCFG0_3 (SEL_IN_FREQ | ENDIGLDO | ENBGSC_REF | ENPLLLDO) +#define SATA_PLLCFG0_4 (SEL_IN_FREQ | DIGCLRZ | ENDIGLDO | ENBGSC_REF | \ + ENPLLLDO | ENPLL) + +#define PLL_LOCK (0x1 << 0) + +#define ENSATAMODE (0x1 << 31) +#define PLLREFSEL (0x1 << 30) +#define MDIVINT (0x4b << 18) +#define EN_CLKAUX (0x1 << 5) +#define EN_CLK125M (0x1 << 4) +#define EN_CLK100M (0x1 << 3) +#define EN_CLK50M (0x1 << 2) + +#define SATA_PLLCFG1 (ENSATAMODE | \ + PLLREFSEL | \ + MDIVINT | \ + EN_CLKAUX | \ + EN_CLK125M | \ + EN_CLK100M | \ + EN_CLK50M) + +#define DIGLDO_EN_CAPLESSMODE (0x1 << 22) +#define PLLDO_EN_LDO_STABLE (0x1 << 11) +#define PLLDO_EN_BUF_CUR (0x1 << 7) +#define PLLDO_EN_LP (0x1 << 6) +#define PLLDO_CTRL_TRIM_1_4V (0x10 << 1) + +#define SATA_PLLCFG3 (DIGLDO_EN_CAPLESSMODE | \ + PLLDO_EN_LDO_STABLE | \ + PLLDO_EN_BUF_CUR | \ + PLLDO_EN_LP | \ + PLLDO_CTRL_TRIM_1_4V) + +const struct cm_alwon *cmalwon = (struct cm_alwon *)CM_ALWON_BASE; +const struct cm_def *cmdef = (struct cm_def *)CM_DEFAULT_BASE; +const struct sata_pll *spll = (struct sata_pll *)SATA_PLL_BASE; + +/* + * Enable the peripheral clock for required peripherals + */ +static void enable_per_clocks(void) +{ + /* HSMMC1 */ + writel(PRCM_MOD_EN, &cmalwon->mmchs1clkctrl); + while (readl(&cmalwon->mmchs1clkctrl) != PRCM_MOD_EN) + ; + + /* Ethernet */ + writel(PRCM_MOD_EN, &cmalwon->ethclkstctrl); + writel(PRCM_MOD_EN, &cmalwon->ethernet0clkctrl); + while ((readl(&cmalwon->ethernet0clkctrl) & ENET_CLKCTRL_CMPL) != 0) + ; + writel(PRCM_MOD_EN, &cmalwon->ethernet1clkctrl); + while ((readl(&cmalwon->ethernet1clkctrl) & ENET_CLKCTRL_CMPL) != 0) + ; + + /* RTC clocks */ + writel(PRCM_MOD_EN, &cmalwon->rtcclkstctrl); + writel(PRCM_MOD_EN, &cmalwon->rtcclkctrl); + while (readl(&cmalwon->rtcclkctrl) != PRCM_MOD_EN) + ; +} + +/* + * select the HS1 or HS2 for DCO Freq + * return : CLKCTRL + */ +static u32 pll_dco_freq_sel(u32 clkout_dco) +{ + if (clkout_dco >= DCO_HS2_MIN && clkout_dco < DCO_HS2_MAX) + return SELFREQDCO_HS2; + else if (clkout_dco >= DCO_HS1_MIN && clkout_dco < DCO_HS1_MAX) + return SELFREQDCO_HS1; + else + return -1; +} + +/* + * select the sigma delta config + * return: sigma delta val + */ +static u32 pll_sigma_delta_val(u32 clkout_dco) +{ + u32 sig_val = 0; + + sig_val = (clkout_dco + 225) / 250; + sig_val = sig_val << 24; + + return sig_val; +} + +/* + * configure individual ADPLLJ + */ +static void pll_config(u32 base, u32 n, u32 m, u32 m2, + u32 clkctrl_val, int adpllj) +{ + const struct ad_pll *adpll = (struct ad_pll *)base; + u32 m2nval, mn2val, read_clkctrl = 0, clkout_dco = 0; + u32 sig_val = 0, hs_mod = 0; + + m2nval = (m2 << ADPLLJ_M2NDIV_M2SHIFT) | n; + mn2val = m; + + /* calculate clkout_dco */ + clkout_dco = ((OSC_0_FREQ / (n+1)) * m); + + /* sigma delta & Hs mode selection skip for ADPLLS*/ + if (adpllj) { + sig_val = pll_sigma_delta_val(clkout_dco); + hs_mod = pll_dco_freq_sel(clkout_dco); + } + + /* by-pass pll */ + read_clkctrl = readl(&adpll->clkctrl); + writel((read_clkctrl | ADPLLJ_CLKCTRL_IDLE), &adpll->clkctrl); + while ((readl(&adpll->status) & ADPLLJ_STATUS_BYPASSANDACK) + != ADPLLJ_STATUS_BYPASSANDACK) + ; + + /* clear TINITZ */ + read_clkctrl = readl(&adpll->clkctrl); + writel((read_clkctrl & ~ADPLLJ_CLKCTRL_TINITZ), &adpll->clkctrl); + + /* + * ref_clk = 20/(n + 1); + * clkout_dco = ref_clk * m; + * clk_out = clkout_dco/m2; + */ + read_clkctrl = readl(&adpll->clkctrl) & + ~(ADPLLJ_CLKCTRL_LPMODE | + ADPLLJ_CLKCTRL_DRIFTGUARDIAN | + ADPLLJ_CLKCTRL_REGM4XEN); + writel(m2nval, &adpll->m2ndiv); + writel(mn2val, &adpll->mn2div); + + /* Skip for modena(ADPLLS) */ + if (adpllj) { + writel(sig_val, &adpll->fracdiv); + writel((read_clkctrl | hs_mod), &adpll->clkctrl); + } + + /* Load M2, N2 dividers of ADPLL */ + writel(ADPLLJ_TENABLEDIV_ENB, &adpll->tenablediv); + writel(~ADPLLJ_TENABLEDIV_ENB, &adpll->tenablediv); + + /* Load M, N dividers of ADPLL */ + writel(ADPLLJ_TENABLE_ENB, &adpll->tenable); + writel(~ADPLLJ_TENABLE_ENB, &adpll->tenable); + + /* Configure CLKDCOLDOEN,CLKOUTLDOEN,CLKOUT Enable BITS */ + read_clkctrl = readl(&adpll->clkctrl) & ~ADPLLJ_CLKCTRL_CLKDCO; + if (adpllj) + writel((read_clkctrl | ADPLLJ_CLKCTRL_CLKDCO), + &adpll->clkctrl); + + /* Enable TINTZ and disable IDLE(PLL in Active & Locked Mode */ + read_clkctrl = readl(&adpll->clkctrl) & ~ADPLLJ_CLKCTRL_IDLE; + writel((read_clkctrl | ADPLLJ_CLKCTRL_TINITZ), &adpll->clkctrl); + + /* Wait for phase and freq lock */ + while ((readl(&adpll->status) & ADPLLJ_STATUS_PHSFRQLOCK) != + ADPLLJ_STATUS_PHSFRQLOCK) + ; +} + +static void unlock_pll_control_mmr(void) +{ + /* TRM 2.10.1.4 and 3.2.7-3.2.11 */ + writel(0x1EDA4C3D, 0x481C5040); + writel(0x2FF1AC2B, 0x48140060); + writel(0xF757FDC0, 0x48140064); + writel(0xE2BC3A6D, 0x48140068); + writel(0x1EBF131D, 0x4814006c); + writel(0x6F361E05, 0x48140070); +} + +static void mpu_pll_config(void) +{ + pll_config(MPU_PLL_BASE, MPU_N, MPU_M, MPU_M2, MPU_CLKCTRL, 0); +} + +static void l3_pll_config(void) +{ + u32 l3_osc_src, rd_osc_src = 0; + + l3_osc_src = L3_OSC_SRC; + rd_osc_src = readl(OSC_SRC_CTRL); + + if (OSC_SRC0 == l3_osc_src) + writel((rd_osc_src & 0xfffffffe)|0x0, OSC_SRC_CTRL); + else + writel((rd_osc_src & 0xfffffffe)|0x1, OSC_SRC_CTRL); + + pll_config(L3_PLL_BASE, L3_N, L3_M, L3_M2, L3_CLKCTRL, 1); +} + +void ddr_pll_config(unsigned int ddrpll_m) +{ + pll_config(DDR_PLL_BASE, DDR_N, DDR_M, DDR_M2, DDR_CLKCTRL, 1); +} + +void sata_pll_config(void) +{ + /* + * This sequence for configuring the SATA PLL + * resident in the control module is documented + * in TI8148 TRM section 21.3.1 + */ + writel(SATA_PLLCFG1, &spll->pllcfg1); + udelay(50); + + writel(SATA_PLLCFG3, &spll->pllcfg3); + udelay(50); + + writel(SATA_PLLCFG0_1, &spll->pllcfg0); + udelay(50); + + writel(SATA_PLLCFG0_2, &spll->pllcfg0); + udelay(50); + + writel(SATA_PLLCFG0_3, &spll->pllcfg0); + udelay(50); + + writel(SATA_PLLCFG0_4, &spll->pllcfg0); + udelay(50); + + while (((readl(&spll->pllstatus) & PLL_LOCK) == 0)) + ; +} + +void enable_dmm_clocks(void) +{ + writel(PRCM_MOD_EN, &cmdef->fwclkctrl); + writel(PRCM_MOD_EN, &cmdef->l3fastclkstctrl); + writel(PRCM_MOD_EN, &cmdef->emif0clkctrl); + while ((readl(&cmdef->emif0clkctrl)) != PRCM_MOD_EN) + ; + writel(PRCM_MOD_EN, &cmdef->emif1clkctrl); + while ((readl(&cmdef->emif1clkctrl)) != PRCM_MOD_EN) + ; + while ((readl(&cmdef->l3fastclkstctrl) & 0x300) != 0x300) + ; + writel(PRCM_MOD_EN, &cmdef->dmmclkctrl); + while ((readl(&cmdef->dmmclkctrl)) != PRCM_MOD_EN) + ; + writel(PRCM_MOD_EN, &cmalwon->l3slowclkstctrl); + while ((readl(&cmalwon->l3slowclkstctrl) & 0x2100) != 0x2100) + ; +} + +void setup_clocks_for_console(void) +{ + unlock_pll_control_mmr(); + /* UART0 */ + writel(PRCM_MOD_EN, &cmalwon->uart0clkctrl); + while (readl(&cmalwon->uart0clkctrl) != PRCM_MOD_EN) + ; +} +/* + * Configure the PLL/PRCM for necessary peripherals + */ +void prcm_init(void) +{ + /* Enable the control module */ + writel(PRCM_MOD_EN, &cmalwon->controlclkctrl); + + /* Configure PLLs */ + mpu_pll_config(); + l3_pll_config(); + sata_pll_config(); + + /* Enable the required peripherals */ + enable_per_clocks(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_ti816x.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_ti816x.c new file mode 100644 index 000000000..ace4a5afe --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/clock_ti816x.c @@ -0,0 +1,445 @@ +/* + * clock_ti816x.c + * + * Clocks for TI816X based boards + * + * Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com> + * Antoine Tenart, <atenart@adeneo-embedded.com> + * + * Based on TI-PSP-04.00.02.14 : + * + * Copyright (C) 2009, Texas Instruments, Incorporated + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <asm/arch/ddr_defs.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clock.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> + +#include <asm/emif.h> + +#define CM_PLL_BASE (CTRL_BASE + 0x0400) + +/* Main PLL */ +#define MAIN_N 64 +#define MAIN_P 0x1 +#define MAIN_INTFREQ1 0x8 +#define MAIN_FRACFREQ1 0x800000 +#define MAIN_MDIV1 0x2 +#define MAIN_INTFREQ2 0xE +#define MAIN_FRACFREQ2 0x0 +#define MAIN_MDIV2 0x1 +#define MAIN_INTFREQ3 0x8 +#define MAIN_FRACFREQ3 0xAAAAB0 +#define MAIN_MDIV3 0x3 +#define MAIN_INTFREQ4 0x9 +#define MAIN_FRACFREQ4 0x55554F +#define MAIN_MDIV4 0x3 +#define MAIN_INTFREQ5 0x9 +#define MAIN_FRACFREQ5 0x374BC6 +#define MAIN_MDIV5 0xC +#define MAIN_MDIV6 0x48 +#define MAIN_MDIV7 0x4 + +/* DDR PLL */ +#if defined(CONFIG_TI816X_DDR_PLL_400) /* 400 MHz */ +#define DDR_N 59 +#define DDR_P 0x1 +#define DDR_MDIV1 0x4 +#define DDR_INTFREQ2 0x8 +#define DDR_FRACFREQ2 0xD99999 +#define DDR_MDIV2 0x1E +#define DDR_INTFREQ3 0x8 +#define DDR_FRACFREQ3 0x0 +#define DDR_MDIV3 0x4 +#define DDR_INTFREQ4 0xE /* Expansion DDR clk */ +#define DDR_FRACFREQ4 0x0 +#define DDR_MDIV4 0x4 +#define DDR_INTFREQ5 0xE /* Expansion DDR clk */ +#define DDR_FRACFREQ5 0x0 +#define DDR_MDIV5 0x4 +#elif defined(CONFIG_TI816X_DDR_PLL_531) /* 531 MHz */ +#define DDR_N 59 +#define DDR_P 0x1 +#define DDR_MDIV1 0x3 +#define DDR_INTFREQ2 0x8 +#define DDR_FRACFREQ2 0xD99999 +#define DDR_MDIV2 0x1E +#define DDR_INTFREQ3 0x8 +#define DDR_FRACFREQ3 0x0 +#define DDR_MDIV3 0x4 +#define DDR_INTFREQ4 0xE /* Expansion DDR clk */ +#define DDR_FRACFREQ4 0x0 +#define DDR_MDIV4 0x4 +#define DDR_INTFREQ5 0xE /* Expansion DDR clk */ +#define DDR_FRACFREQ5 0x0 +#define DDR_MDIV5 0x4 +#elif defined(CONFIG_TI816X_DDR_PLL_675) /* 675 MHz */ +#define DDR_N 50 +#define DDR_P 0x1 +#define DDR_MDIV1 0x2 +#define DDR_INTFREQ2 0x9 +#define DDR_FRACFREQ2 0x0 +#define DDR_MDIV2 0x19 +#define DDR_INTFREQ3 0x13 +#define DDR_FRACFREQ3 0x800000 +#define DDR_MDIV3 0x2 +#define DDR_INTFREQ4 0xE /* Expansion DDR clk */ +#define DDR_FRACFREQ4 0x0 +#define DDR_MDIV4 0x4 +#define DDR_INTFREQ5 0xE /* Expansion DDR clk */ +#define DDR_FRACFREQ5 0x0 +#define DDR_MDIV5 0x4 +#elif defined(CONFIG_TI816X_DDR_PLL_796) /* 796 MHz */ +#define DDR_N 59 +#define DDR_P 0x1 +#define DDR_MDIV1 0x2 +#define DDR_INTFREQ2 0x8 +#define DDR_FRACFREQ2 0xD99999 +#define DDR_MDIV2 0x1E +#define DDR_INTFREQ3 0x8 +#define DDR_FRACFREQ3 0x0 +#define DDR_MDIV3 0x4 +#define DDR_INTFREQ4 0xE /* Expansion DDR clk */ +#define DDR_FRACFREQ4 0x0 +#define DDR_MDIV4 0x4 +#define DDR_INTFREQ5 0xE /* Expansion DDR clk */ +#define DDR_FRACFREQ5 0x0 +#define DDR_MDIV5 0x4 +#endif + +#define CONTROL_STATUS (CTRL_BASE + 0x40) +#define DDR_RCD (CTRL_BASE + 0x070C) +#define CM_TIMER1_CLKSEL (PRCM_BASE + 0x390) +#define DMM_PAT_BASE_ADDR (DMM_BASE + 0x420) +#define CM_ALWON_CUST_EFUSE_CLKCTRL (PRCM_BASE + 0x1628) + +#define INTCPS_SYSCONFIG 0x48200010 +#define CM_SYSCLK10_CLKSEL 0x48180324 + +struct cm_pll { + unsigned int mainpll_ctrl; /* offset 0x400 */ + unsigned int mainpll_pwd; + unsigned int mainpll_freq1; + unsigned int mainpll_div1; + unsigned int mainpll_freq2; + unsigned int mainpll_div2; + unsigned int mainpll_freq3; + unsigned int mainpll_div3; + unsigned int mainpll_freq4; + unsigned int mainpll_div4; + unsigned int mainpll_freq5; + unsigned int mainpll_div5; + unsigned int resv0[1]; + unsigned int mainpll_div6; + unsigned int resv1[1]; + unsigned int mainpll_div7; + unsigned int ddrpll_ctrl; /* offset 0x440 */ + unsigned int ddrpll_pwd; + unsigned int resv2[1]; + unsigned int ddrpll_div1; + unsigned int ddrpll_freq2; + unsigned int ddrpll_div2; + unsigned int ddrpll_freq3; + unsigned int ddrpll_div3; + unsigned int ddrpll_freq4; + unsigned int ddrpll_div4; + unsigned int ddrpll_freq5; + unsigned int ddrpll_div5; + unsigned int videopll_ctrl; /* offset 0x470 */ + unsigned int videopll_pwd; + unsigned int videopll_freq1; + unsigned int videopll_div1; + unsigned int videopll_freq2; + unsigned int videopll_div2; + unsigned int videopll_freq3; + unsigned int videopll_div3; + unsigned int resv3[4]; + unsigned int audiopll_ctrl; /* offset 0x4A0 */ + unsigned int audiopll_pwd; + unsigned int resv4[2]; + unsigned int audiopll_freq2; + unsigned int audiopll_div2; + unsigned int audiopll_freq3; + unsigned int audiopll_div3; + unsigned int audiopll_freq4; + unsigned int audiopll_div4; + unsigned int audiopll_freq5; + unsigned int audiopll_div5; +}; + +const struct cm_alwon *cmalwon = (struct cm_alwon *)CM_ALWON_BASE; +const struct cm_def *cmdef = (struct cm_def *)CM_DEFAULT_BASE; +const struct cm_pll *cmpll = (struct cm_pll *)CM_PLL_BASE; +const struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE; + +void enable_dmm_clocks(void) +{ + writel(PRCM_MOD_EN, &cmdef->l3fastclkstctrl); + writel(PRCM_MOD_EN, &cmdef->emif0clkctrl); + writel(PRCM_MOD_EN, &cmdef->emif1clkctrl); + + /* Wait for clocks to be active */ + while ((readl(&cmdef->l3fastclkstctrl) & 0x300) != 0x300) + ; + /* Wait for emif0 to be fully functional, including OCP */ + while (((readl(&cmdef->emif0clkctrl) >> 17) & 0x3) != 0) + ; + /* Wait for emif1 to be fully functional, including OCP */ + while (((readl(&cmdef->emif1clkctrl) >> 17) & 0x3) != 0) + ; + + writel(PRCM_MOD_EN, &cmdef->dmmclkctrl); + /* Wait for dmm to be fully functional, including OCP */ + while (((readl(&cmdef->dmmclkctrl) >> 17) & 0x3) != 0) + ; + + /* Enable Tiled Access */ + writel(0x80000000, DMM_PAT_BASE_ADDR); +} + +/* assume delay is aprox at least 1us */ +static void ddr_delay(int d) +{ + int i; + + /* + * read a control register. + * this is a bit more delay and cannot be optimized by the compiler + * assuming one read takes 200 cycles and A8 is runing 1 GHz + * somewhat conservative setting + */ + for (i = 0; i < 50*d; i++) + readl(CONTROL_STATUS); +} + +static void main_pll_init_ti816x(void) +{ + u32 main_pll_ctrl = 0; + + /* Put the PLL in bypass mode by setting BIT2 in its ctrl reg */ + main_pll_ctrl = readl(&cmpll->mainpll_ctrl); + main_pll_ctrl &= 0xFFFFFFFB; + main_pll_ctrl |= BIT(2); + writel(main_pll_ctrl, &cmpll->mainpll_ctrl); + + /* Enable PLL by setting BIT3 in its ctrl reg */ + main_pll_ctrl = readl(&cmpll->mainpll_ctrl); + main_pll_ctrl &= 0xFFFFFFF7; + main_pll_ctrl |= BIT(3); + writel(main_pll_ctrl, &cmpll->mainpll_ctrl); + + /* Write the values of N,P in the CTRL reg */ + main_pll_ctrl = readl(&cmpll->mainpll_ctrl); + main_pll_ctrl &= 0xFF; + main_pll_ctrl |= (MAIN_N<<16 | MAIN_P<<8); + writel(main_pll_ctrl, &cmpll->mainpll_ctrl); + + /* Power up clock1-7 */ + writel(0x0, &cmpll->mainpll_pwd); + + /* Program the freq and divider values for clock1-7 */ + writel((1<<31 | 1<<28 | (MAIN_INTFREQ1<<24) | MAIN_FRACFREQ1), + &cmpll->mainpll_freq1); + writel(((1<<8) | MAIN_MDIV1), &cmpll->mainpll_div1); + + writel((1<<31 | 1<<28 | (MAIN_INTFREQ2<<24) | MAIN_FRACFREQ2), + &cmpll->mainpll_freq2); + writel(((1<<8) | MAIN_MDIV2), &cmpll->mainpll_div2); + + writel((1<<31 | 1<<28 | (MAIN_INTFREQ3<<24) | MAIN_FRACFREQ3), + &cmpll->mainpll_freq3); + writel(((1<<8) | MAIN_MDIV3), &cmpll->mainpll_div3); + + writel((1<<31 | 1<<28 | (MAIN_INTFREQ4<<24) | MAIN_FRACFREQ4), + &cmpll->mainpll_freq4); + writel(((1<<8) | MAIN_MDIV4), &cmpll->mainpll_div4); + + writel((1<<31 | 1<<28 | (MAIN_INTFREQ5<<24) | MAIN_FRACFREQ5), + &cmpll->mainpll_freq5); + writel(((1<<8) | MAIN_MDIV5), &cmpll->mainpll_div5); + + writel((1<<8 | MAIN_MDIV6), &cmpll->mainpll_div6); + + writel((1<<8 | MAIN_MDIV7), &cmpll->mainpll_div7); + + /* Wait for PLL to lock */ + while ((readl(&cmpll->mainpll_ctrl) & BIT(7)) != BIT(7)) + ; + + /* Put the PLL in normal mode, disable bypass */ + main_pll_ctrl = readl(&cmpll->mainpll_ctrl); + main_pll_ctrl &= 0xFFFFFFFB; + writel(main_pll_ctrl, &cmpll->mainpll_ctrl); +} + +static void ddr_pll_bypass_ti816x(void) +{ + u32 ddr_pll_ctrl = 0; + + /* Put the PLL in bypass mode by setting BIT2 in its ctrl reg */ + ddr_pll_ctrl = readl(&cmpll->ddrpll_ctrl); + ddr_pll_ctrl &= 0xFFFFFFFB; + ddr_pll_ctrl |= BIT(2); + writel(ddr_pll_ctrl, &cmpll->ddrpll_ctrl); +} + +static void ddr_pll_init_ti816x(void) +{ + u32 ddr_pll_ctrl = 0; + /* Enable PLL by setting BIT3 in its ctrl reg */ + ddr_pll_ctrl = readl(&cmpll->ddrpll_ctrl); + ddr_pll_ctrl &= 0xFFFFFFF7; + ddr_pll_ctrl |= BIT(3); + writel(ddr_pll_ctrl, &cmpll->ddrpll_ctrl); + + /* Write the values of N,P in the CTRL reg */ + ddr_pll_ctrl = readl(&cmpll->ddrpll_ctrl); + ddr_pll_ctrl &= 0xFF; + ddr_pll_ctrl |= (DDR_N<<16 | DDR_P<<8); + writel(ddr_pll_ctrl, &cmpll->ddrpll_ctrl); + + ddr_delay(10); + + /* Power up clock1-5 */ + writel(0x0, &cmpll->ddrpll_pwd); + + /* Program the freq and divider values for clock1-3 */ + writel(((0<<8) | DDR_MDIV1), &cmpll->ddrpll_div1); + ddr_delay(1); + writel(((1<<8) | DDR_MDIV1), &cmpll->ddrpll_div1); + writel((1<<31 | 1<<28 | (DDR_INTFREQ2<<24) | DDR_FRACFREQ2), + &cmpll->ddrpll_freq2); + writel(((1<<8) | DDR_MDIV2), &cmpll->ddrpll_div2); + writel(((0<<8) | DDR_MDIV3), &cmpll->ddrpll_div3); + ddr_delay(1); + writel(((1<<8) | DDR_MDIV3), &cmpll->ddrpll_div3); + ddr_delay(1); + writel((0<<31 | 1<<28 | (DDR_INTFREQ3<<24) | DDR_FRACFREQ3), + &cmpll->ddrpll_freq3); + ddr_delay(1); + writel((1<<31 | 1<<28 | (DDR_INTFREQ3<<24) | DDR_FRACFREQ3), + &cmpll->ddrpll_freq3); + + ddr_delay(5); + + /* Wait for PLL to lock */ + while ((readl(&cmpll->ddrpll_ctrl) & BIT(7)) != BIT(7)) + ; + + /* Power up RCD */ + writel(BIT(0), DDR_RCD); +} + +static void peripheral_enable(void) +{ + /* Wake-up the l3_slow clock */ + writel(PRCM_MOD_EN, &cmalwon->l3slowclkstctrl); + + /* + * Note on Timers: + * There are 8 timers(0-7) out of which timer 0 is a secure timer. + * Timer 0 mux should not be changed + * + * To access the timer registers we need the to be + * enabled which is what we do in the first step + */ + + /* Enable timer1 */ + writel(PRCM_MOD_EN, &cmalwon->timer1clkctrl); + /* Select timer1 clock to be CLKIN (27MHz) */ + writel(BIT(1), CM_TIMER1_CLKSEL); + + /* Wait for timer1 to be ON-ACTIVE */ + while (((readl(&cmalwon->l3slowclkstctrl) + & (0x80000<<1))>>20) != 1) + ; + /* Wait for timer1 to be enabled */ + while (((readl(&cmalwon->timer1clkctrl) & 0x30000)>>16) != 0) + ; + /* Active posted mode */ + writel(PRCM_MOD_EN, (DM_TIMER1_BASE + 0x54)); + while (readl(DM_TIMER1_BASE + 0x10) & BIT(0)) + ; + /* Start timer1 */ + writel(BIT(0), (DM_TIMER1_BASE + 0x38)); + + /* eFuse */ + writel(PRCM_MOD_EN, CM_ALWON_CUST_EFUSE_CLKCTRL); + while (readl(CM_ALWON_CUST_EFUSE_CLKCTRL) != PRCM_MOD_EN) + ; + + /* Enable gpio0 */ + writel(PRCM_MOD_EN, &cmalwon->gpio0clkctrl); + while (readl(&cmalwon->gpio0clkctrl) != PRCM_MOD_EN) + ; + writel((BIT(8)), &cmalwon->gpio0clkctrl); + + /* Enable spi */ + writel(PRCM_MOD_EN, &cmalwon->spiclkctrl); + while (readl(&cmalwon->spiclkctrl) != PRCM_MOD_EN) + ; + + /* Enable i2c0 */ + writel(PRCM_MOD_EN, &cmalwon->i2c0clkctrl); + while (readl(&cmalwon->i2c0clkctrl) != PRCM_MOD_EN) + ; + + /* Enable ethernet0 */ + writel(PRCM_MOD_EN, &cmalwon->ethclkstctrl); + writel(PRCM_MOD_EN, &cmalwon->ethernet0clkctrl); + writel(PRCM_MOD_EN, &cmalwon->ethernet1clkctrl); + + /* Enable hsmmc */ + writel(PRCM_MOD_EN, &cmalwon->sdioclkctrl); + while (readl(&cmalwon->sdioclkctrl) != PRCM_MOD_EN) + ; +} + +void setup_clocks_for_console(void) +{ + /* Fix ROM code bug - from TI-PSP-04.00.02.14 */ + writel(0x0, CM_SYSCLK10_CLKSEL); + + ddr_pll_bypass_ti816x(); + + /* Enable uart0-2 */ + writel(PRCM_MOD_EN, &cmalwon->uart0clkctrl); + while (readl(&cmalwon->uart0clkctrl) != PRCM_MOD_EN) + ; + writel(PRCM_MOD_EN, &cmalwon->uart1clkctrl); + while (readl(&cmalwon->uart1clkctrl) != PRCM_MOD_EN) + ; + writel(PRCM_MOD_EN, &cmalwon->uart2clkctrl); + while (readl(&cmalwon->uart2clkctrl) != PRCM_MOD_EN) + ; + while ((readl(&cmalwon->l3slowclkstctrl) & 0x2100) != 0x2100) + ; +} + +void prcm_init(void) +{ + /* Enable the control */ + writel(PRCM_MOD_EN, &cmalwon->controlclkctrl); + + main_pll_init_ti816x(); + ddr_pll_init_ti816x(); + + /* + * With clk freqs setup to desired values, + * enable the required peripherals + */ + peripheral_enable(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/config.mk b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/config.mk new file mode 100644 index 000000000..5294d1670 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/config.mk @@ -0,0 +1,11 @@ +# +# Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ +# +# SPDX-License-Identifier: GPL-2.0+ +# +ifdef CONFIG_SPL_BUILD +ALL-y += MLO +ALL-$(CONFIG_SPL_SPI_SUPPORT) += MLO.byteswap +else +ALL-y += u-boot.img +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/ddr.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/ddr.c new file mode 100644 index 000000000..9a625c466 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/ddr.c @@ -0,0 +1,266 @@ +/* + * DDR Configuration for AM33xx devices. + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/arch/cpu.h> +#include <asm/arch/ddr_defs.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> +#include <asm/emif.h> + +/** + * Base address for EMIF instances + */ +static struct emif_reg_struct *emif_reg[2] = { + (struct emif_reg_struct *)EMIF4_0_CFG_BASE, + (struct emif_reg_struct *)EMIF4_1_CFG_BASE}; + +/** + * Base addresses for DDR PHY cmd/data regs + */ +static struct ddr_cmd_regs *ddr_cmd_reg[2] = { + (struct ddr_cmd_regs *)DDR_PHY_CMD_ADDR, + (struct ddr_cmd_regs *)DDR_PHY_CMD_ADDR2}; + +static struct ddr_data_regs *ddr_data_reg[2] = { + (struct ddr_data_regs *)DDR_PHY_DATA_ADDR, + (struct ddr_data_regs *)DDR_PHY_DATA_ADDR2}; + +/** + * Base address for ddr io control instances + */ +static struct ddr_cmdtctrl *ioctrl_reg = { + (struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR}; + +static inline u32 get_mr(int nr, u32 cs, u32 mr_addr) +{ + u32 mr; + + mr_addr |= cs << EMIF_REG_CS_SHIFT; + writel(mr_addr, &emif_reg[nr]->emif_lpddr2_mode_reg_cfg); + + mr = readl(&emif_reg[nr]->emif_lpddr2_mode_reg_data); + debug("get_mr: EMIF1 cs %d mr %08x val 0x%x\n", cs, mr_addr, mr); + if (((mr & 0x0000ff00) >> 8) == (mr & 0xff) && + ((mr & 0x00ff0000) >> 16) == (mr & 0xff) && + ((mr & 0xff000000) >> 24) == (mr & 0xff)) + return mr & 0xff; + else + return mr; +} + +static inline void set_mr(int nr, u32 cs, u32 mr_addr, u32 mr_val) +{ + mr_addr |= cs << EMIF_REG_CS_SHIFT; + writel(mr_addr, &emif_reg[nr]->emif_lpddr2_mode_reg_cfg); + writel(mr_val, &emif_reg[nr]->emif_lpddr2_mode_reg_data); +} + +static void configure_mr(int nr, u32 cs) +{ + u32 mr_addr; + + while (get_mr(nr, cs, LPDDR2_MR0) & LPDDR2_MR0_DAI_MASK) + ; + set_mr(nr, cs, LPDDR2_MR10, 0x56); + + set_mr(nr, cs, LPDDR2_MR1, 0x43); + set_mr(nr, cs, LPDDR2_MR2, 0x2); + + mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK; + set_mr(nr, cs, mr_addr, 0x2); +} + +/* + * Configure EMIF4D5 registers and MR registers + */ +void config_sdram_emif4d5(const struct emif_regs *regs, int nr) +{ + writel(0xA0, &emif_reg[nr]->emif_pwr_mgmt_ctrl); + writel(0xA0, &emif_reg[nr]->emif_pwr_mgmt_ctrl_shdw); + writel(0x1, &emif_reg[nr]->emif_iodft_tlgc); + writel(regs->zq_config, &emif_reg[nr]->emif_zq_config); + + writel(regs->temp_alert_config, &emif_reg[nr]->emif_temp_alert_config); + writel(regs->emif_rd_wr_lvl_rmp_win, + &emif_reg[nr]->emif_rd_wr_lvl_rmp_win); + writel(regs->emif_rd_wr_lvl_rmp_ctl, + &emif_reg[nr]->emif_rd_wr_lvl_rmp_ctl); + writel(regs->emif_rd_wr_lvl_ctl, &emif_reg[nr]->emif_rd_wr_lvl_ctl); + writel(regs->emif_rd_wr_exec_thresh, + &emif_reg[nr]->emif_rd_wr_exec_thresh); + + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); + writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); + writel(regs->sdram_config, &cstat->secure_emif_sdram_config); + + if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2) { + configure_mr(nr, 0); + configure_mr(nr, 1); + } +} + +/** + * Configure SDRAM + */ +void config_sdram(const struct emif_regs *regs, int nr) +{ + if (regs->zq_config) { + /* + * A value of 0x2800 for the REF CTRL will give us + * about 570us for a delay, which will be long enough + * to configure things. + */ + writel(0x2800, &emif_reg[nr]->emif_sdram_ref_ctrl); + writel(regs->zq_config, &emif_reg[nr]->emif_zq_config); + writel(regs->sdram_config, &cstat->secure_emif_sdram_config); + writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw); + } + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw); + writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); +} + +/** + * Set SDRAM timings + */ +void set_sdram_timings(const struct emif_regs *regs, int nr) +{ + writel(regs->sdram_tim1, &emif_reg[nr]->emif_sdram_tim_1); + writel(regs->sdram_tim1, &emif_reg[nr]->emif_sdram_tim_1_shdw); + writel(regs->sdram_tim2, &emif_reg[nr]->emif_sdram_tim_2); + writel(regs->sdram_tim2, &emif_reg[nr]->emif_sdram_tim_2_shdw); + writel(regs->sdram_tim3, &emif_reg[nr]->emif_sdram_tim_3); + writel(regs->sdram_tim3, &emif_reg[nr]->emif_sdram_tim_3_shdw); +} + +void __weak emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size) +{ +} + +/* + * Configure EXT PHY registers + */ +static void ext_phy_settings(const struct emif_regs *regs, int nr) +{ + u32 *ext_phy_ctrl_base = 0; + u32 *emif_ext_phy_ctrl_base = 0; + const u32 *ext_phy_ctrl_const_regs; + u32 i = 0; + u32 size; + + ext_phy_ctrl_base = (u32 *)&(regs->emif_ddr_ext_phy_ctrl_1); + emif_ext_phy_ctrl_base = + (u32 *)&(emif_reg[nr]->emif_ddr_ext_phy_ctrl_1); + + /* Configure external phy control timing registers */ + for (i = 0; i < EMIF_EXT_PHY_CTRL_TIMING_REG; i++) { + writel(*ext_phy_ctrl_base, emif_ext_phy_ctrl_base++); + /* Update shadow registers */ + writel(*ext_phy_ctrl_base++, emif_ext_phy_ctrl_base++); + } + + /* + * external phy 6-24 registers do not change with + * ddr frequency + */ + emif_get_ext_phy_ctrl_const_regs(&ext_phy_ctrl_const_regs, &size); + + if (!size) + return; + + for (i = 0; i < size; i++) { + writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++); + /* Update shadow registers */ + writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++); + } +} + +/** + * Configure DDR PHY + */ +void config_ddr_phy(const struct emif_regs *regs, int nr) +{ + /* + * disable initialization and refreshes for now until we + * finish programming EMIF regs. + */ + setbits_le32(&emif_reg[nr]->emif_sdram_ref_ctrl, + EMIF_REG_INITREF_DIS_MASK); + + writel(regs->emif_ddr_phy_ctlr_1, + &emif_reg[nr]->emif_ddr_phy_ctrl_1); + writel(regs->emif_ddr_phy_ctlr_1, + &emif_reg[nr]->emif_ddr_phy_ctrl_1_shdw); + + if (get_emif_rev((u32)emif_reg[nr]) == EMIF_4D5) + ext_phy_settings(regs, nr); +} + +/** + * Configure DDR CMD control registers + */ +void config_cmd_ctrl(const struct cmd_control *cmd, int nr) +{ + if (!cmd) + return; + + writel(cmd->cmd0csratio, &ddr_cmd_reg[nr]->cm0csratio); + writel(cmd->cmd0iclkout, &ddr_cmd_reg[nr]->cm0iclkout); + + writel(cmd->cmd1csratio, &ddr_cmd_reg[nr]->cm1csratio); + writel(cmd->cmd1iclkout, &ddr_cmd_reg[nr]->cm1iclkout); + + writel(cmd->cmd2csratio, &ddr_cmd_reg[nr]->cm2csratio); + writel(cmd->cmd2iclkout, &ddr_cmd_reg[nr]->cm2iclkout); +} + +/** + * Configure DDR DATA registers + */ +void config_ddr_data(const struct ddr_data *data, int nr) +{ + int i; + + if (!data) + return; + + for (i = 0; i < DDR_DATA_REGS_NR; i++) { + writel(data->datardsratio0, + &(ddr_data_reg[nr]+i)->dt0rdsratio0); + writel(data->datawdsratio0, + &(ddr_data_reg[nr]+i)->dt0wdsratio0); + writel(data->datawiratio0, + &(ddr_data_reg[nr]+i)->dt0wiratio0); + writel(data->datagiratio0, + &(ddr_data_reg[nr]+i)->dt0giratio0); + writel(data->datafwsratio0, + &(ddr_data_reg[nr]+i)->dt0fwsratio0); + writel(data->datawrsratio0, + &(ddr_data_reg[nr]+i)->dt0wrsratio0); + } +} + +void config_io_ctrl(const struct ctrl_ioregs *ioregs) +{ + if (!ioregs) + return; + + writel(ioregs->cm0ioctl, &ioctrl_reg->cm0ioctl); + writel(ioregs->cm1ioctl, &ioctrl_reg->cm1ioctl); + writel(ioregs->cm2ioctl, &ioctrl_reg->cm2ioctl); + writel(ioregs->dt0ioctl, &ioctrl_reg->dt0ioctl); + writel(ioregs->dt1ioctl, &ioctrl_reg->dt1ioctl); +#ifdef CONFIG_AM43XX + writel(ioregs->dt2ioctrl, &ioctrl_reg->dt2ioctrl); + writel(ioregs->dt3ioctrl, &ioctrl_reg->dt3ioctrl); + writel(ioregs->emif_sdram_config_ext, + &ioctrl_reg->emif_sdram_config_ext); +#endif +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/emif4.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/emif4.c new file mode 100644 index 000000000..2c67c322c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/emif4.c @@ -0,0 +1,132 @@ +/* + * emif4.c + * + * AM33XX emif4 configuration file + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/ddr_defs.h> +#include <asm/arch/hardware.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> +#include <asm/emif.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + /* dram_init must store complete ramsize in gd->ram_size */ + gd->ram_size = get_ram_size( + (void *)CONFIG_SYS_SDRAM_BASE, + CONFIG_MAX_RAM_BANK_SIZE); + return 0; +} + +void dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_dram[0].size = gd->ram_size; +} + + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#ifdef CONFIG_TI81XX +static struct dmm_lisa_map_regs *hw_lisa_map_regs = + (struct dmm_lisa_map_regs *)DMM_BASE; +#endif +#ifndef CONFIG_TI816X +static struct vtp_reg *vtpreg[2] = { + (struct vtp_reg *)VTP0_CTRL_ADDR, + (struct vtp_reg *)VTP1_CTRL_ADDR}; +#endif +#ifdef CONFIG_AM33XX +static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR; +#endif +#ifdef CONFIG_AM43XX +static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR; +static struct cm_device_inst *cm_device = + (struct cm_device_inst *)CM_DEVICE_INST; +#endif + +#ifdef CONFIG_TI81XX +void config_dmm(const struct dmm_lisa_map_regs *regs) +{ + enable_dmm_clocks(); + + writel(0, &hw_lisa_map_regs->dmm_lisa_map_3); + writel(0, &hw_lisa_map_regs->dmm_lisa_map_2); + writel(0, &hw_lisa_map_regs->dmm_lisa_map_1); + writel(0, &hw_lisa_map_regs->dmm_lisa_map_0); + + writel(regs->dmm_lisa_map_3, &hw_lisa_map_regs->dmm_lisa_map_3); + writel(regs->dmm_lisa_map_2, &hw_lisa_map_regs->dmm_lisa_map_2); + writel(regs->dmm_lisa_map_1, &hw_lisa_map_regs->dmm_lisa_map_1); + writel(regs->dmm_lisa_map_0, &hw_lisa_map_regs->dmm_lisa_map_0); +} +#endif + +#ifndef CONFIG_TI816X +static void config_vtp(int nr) +{ + writel(readl(&vtpreg[nr]->vtp0ctrlreg) | VTP_CTRL_ENABLE, + &vtpreg[nr]->vtp0ctrlreg); + writel(readl(&vtpreg[nr]->vtp0ctrlreg) & (~VTP_CTRL_START_EN), + &vtpreg[nr]->vtp0ctrlreg); + writel(readl(&vtpreg[nr]->vtp0ctrlreg) | VTP_CTRL_START_EN, + &vtpreg[nr]->vtp0ctrlreg); + + /* Poll for READY */ + while ((readl(&vtpreg[nr]->vtp0ctrlreg) & VTP_CTRL_READY) != + VTP_CTRL_READY) + ; +} +#endif + +void __weak ddr_pll_config(unsigned int ddrpll_m) +{ +} + +void config_ddr(unsigned int pll, const struct ctrl_ioregs *ioregs, + const struct ddr_data *data, const struct cmd_control *ctrl, + const struct emif_regs *regs, int nr) +{ + ddr_pll_config(pll); +#ifndef CONFIG_TI816X + config_vtp(nr); +#endif + config_cmd_ctrl(ctrl, nr); + + config_ddr_data(data, nr); +#ifdef CONFIG_AM33XX + config_io_ctrl(ioregs); + + /* Set CKE to be controlled by EMIF/DDR PHY */ + writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl); +#endif +#ifdef CONFIG_AM43XX + writel(readl(&cm_device->cm_dll_ctrl) & ~0x1, &cm_device->cm_dll_ctrl); + while ((readl(&cm_device->cm_dll_ctrl) && CM_DLL_READYST) == 0) + ; + writel(0x80000000, &ddrctrl->ddrioctrl); + + config_io_ctrl(ioregs); + + /* Set CKE to be controlled by EMIF/DDR PHY */ + writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl); +#endif + + /* Program EMIF instance */ + config_ddr_phy(regs, nr); + set_sdram_timings(regs, nr); + if (get_emif_rev(EMIF1_BASE) == EMIF_4D5) + config_sdram_emif4d5(regs, nr); + else + config_sdram(regs, nr); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/mem.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/mem.c new file mode 100644 index 000000000..56c9e7dbc --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/mem.c @@ -0,0 +1,98 @@ +/* + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Author : + * Mansoor Ahamed <mansoor.ahamed@ti.com> + * + * Initial Code from: + * Manikandan Pillai <mani.pillai@ti.com> + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/mem.h> +#include <asm/arch/sys_proto.h> +#include <command.h> + +struct gpmc *gpmc_cfg; + + +void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base, + u32 size) +{ + writel(0, &cs->config7); + sdelay(1000); + /* Delay for settling */ + writel(gpmc_config[0], &cs->config1); + writel(gpmc_config[1], &cs->config2); + writel(gpmc_config[2], &cs->config3); + writel(gpmc_config[3], &cs->config4); + writel(gpmc_config[4], &cs->config5); + writel(gpmc_config[5], &cs->config6); + /* Enable the config */ + writel((((size & 0xF) << 8) | ((base >> 24) & 0x3F) | + (1 << 6)), &cs->config7); + sdelay(2000); +} + +/***************************************************** + * gpmc_init(): init gpmc bus + * Init GPMC for x16, MuxMode (SDRAM in x32). + * This code can only be executed from SRAM or SDRAM. + *****************************************************/ +void gpmc_init(void) +{ + /* putting a blanket check on GPMC based on ZeBu for now */ + gpmc_cfg = (struct gpmc *)GPMC_BASE; +#if defined(CONFIG_NOR) +/* configure GPMC for NOR */ + const u32 gpmc_regs[GPMC_MAX_REG] = { STNOR_GPMC_CONFIG1, + STNOR_GPMC_CONFIG2, + STNOR_GPMC_CONFIG3, + STNOR_GPMC_CONFIG4, + STNOR_GPMC_CONFIG5, + STNOR_GPMC_CONFIG6, + STNOR_GPMC_CONFIG7 + }; + u32 size = GPMC_SIZE_16M; + u32 base = CONFIG_SYS_FLASH_BASE; +#elif defined(CONFIG_NAND) +/* configure GPMC for NAND */ + const u32 gpmc_regs[GPMC_MAX_REG] = { M_NAND_GPMC_CONFIG1, + M_NAND_GPMC_CONFIG2, + M_NAND_GPMC_CONFIG3, + M_NAND_GPMC_CONFIG4, + M_NAND_GPMC_CONFIG5, + M_NAND_GPMC_CONFIG6, + 0 + }; + u32 size = GPMC_SIZE_256M; + u32 base = CONFIG_SYS_NAND_BASE; +#else + const u32 gpmc_regs[GPMC_MAX_REG] = { 0, 0, 0, 0, 0, 0, 0 }; + u32 size = 0; + u32 base = 0; +#endif + /* global settings */ + writel(0x00000008, &gpmc_cfg->sysconfig); + writel(0x00000000, &gpmc_cfg->irqstatus); + writel(0x00000000, &gpmc_cfg->irqenable); +#ifdef CONFIG_NOR + writel(0x00000200, &gpmc_cfg->config); +#else + writel(0x00000012, &gpmc_cfg->config); +#endif + /* + * Disable the GPMC0 config set by ROM code + */ + writel(0, &gpmc_cfg->cs[0].config7); + sdelay(1000); + /* enable chip-select specific configurations */ + enable_gpmc_cs_config(gpmc_regs, &gpmc_cfg->cs[0], base, size); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/mux.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/mux.c new file mode 100644 index 000000000..2ded47228 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/mux.c @@ -0,0 +1,33 @@ +/* + * mux.c + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <asm/arch/mux.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> + +/* + * Configure the pin mux for the module + */ +void configure_module_pin_mux(struct module_pin_mux *mod_pin_mux) +{ + int i; + + if (!mod_pin_mux) + return; + + for (i = 0; mod_pin_mux[i].reg_offset != -1; i++) + MUX_CFG(mod_pin_mux[i].val, mod_pin_mux[i].reg_offset); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/sys_info.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/sys_info.c new file mode 100644 index 000000000..50eb598ff --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/sys_info.c @@ -0,0 +1,178 @@ +/* + * sys_info.c + * + * System information functions + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * Derived from Beagle Board and 3430 SDP code by + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clock.h> +#include <power/tps65910.h> + +struct ctrl_stat *cstat = (struct ctrl_stat *)CTRL_BASE; + +/** + * get_cpu_rev(void) - extract rev info + */ +u32 get_cpu_rev(void) +{ + u32 id; + u32 rev; + + id = readl(DEVICE_ID); + rev = (id >> 28) & 0xff; + + return rev; +} + +/** + * get_cpu_type(void) - extract cpu info + */ +u32 get_cpu_type(void) +{ + u32 id = 0; + u32 partnum; + + id = readl(DEVICE_ID); + partnum = (id >> 12) & 0xffff; + + return partnum; +} + +/** + * get_board_rev() - setup to pass kernel board revision information + * returns:(bit[0-3] sub version, higher bit[7-4] is higher version) + */ +u32 get_board_rev(void) +{ + return BOARD_REV_ID; +} + +/** + * get_device_type(): tell if GP/HS/EMU/TST + */ +u32 get_device_type(void) +{ + int mode; + mode = readl(&cstat->statusreg) & (DEVICE_MASK); + return mode >>= 8; +} + +/** + * get_sysboot_value(void) - return SYS_BOOT[4:0] + */ +u32 get_sysboot_value(void) +{ + int mode; + mode = readl(&cstat->statusreg) & (SYSBOOT_MASK); + return mode; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +/** + * Print CPU information + */ +int print_cpuinfo(void) +{ + char *cpu_s, *sec_s; + + switch (get_cpu_type()) { + case AM335X: + cpu_s = "AM335X"; + break; + case TI81XX: + cpu_s = "TI81XX"; + break; + default: + cpu_s = "Unknown cpu type"; + break; + } + + switch (get_device_type()) { + case TST_DEVICE: + sec_s = "TST"; + break; + case EMU_DEVICE: + sec_s = "EMU"; + break; + case HS_DEVICE: + sec_s = "HS"; + break; + case GP_DEVICE: + sec_s = "GP"; + break; + default: + sec_s = "?"; + } + + printf("%s-%s rev %d\n", cpu_s, sec_s, get_cpu_rev()); + + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ + +#ifdef CONFIG_AM33XX +int am335x_get_efuse_mpu_max_freq(struct ctrl_dev *cdev) +{ + int sil_rev; + + sil_rev = readl(&cdev->deviceid) >> 28; + + if (sil_rev == 1) + /* PG 2.0, efuse may not be set. */ + return MPUPLL_M_800; + else if (sil_rev >= 2) { + /* Check what the efuse says our max speed is. */ + int efuse_arm_mpu_max_freq; + efuse_arm_mpu_max_freq = readl(&cdev->efuse_sma); + switch ((efuse_arm_mpu_max_freq & DEVICE_ID_MASK)) { + case AM335X_ZCZ_1000: + return MPUPLL_M_1000; + case AM335X_ZCZ_800: + return MPUPLL_M_800; + case AM335X_ZCZ_720: + return MPUPLL_M_720; + case AM335X_ZCZ_600: + case AM335X_ZCE_600: + return MPUPLL_M_600; + case AM335X_ZCZ_300: + case AM335X_ZCE_300: + return MPUPLL_M_300; + } + } + + /* PG 1.0 or otherwise unknown, use the PG1.0 max */ + return MPUPLL_M_720; +} + +int am335x_get_tps65910_mpu_vdd(int sil_rev, int frequency) +{ + /* For PG2.1 and later, we have one set of values. */ + if (sil_rev >= 2) { + switch (frequency) { + case MPUPLL_M_1000: + return TPS65910_OP_REG_SEL_1_3_2_5; + case MPUPLL_M_800: + return TPS65910_OP_REG_SEL_1_2_6; + case MPUPLL_M_720: + return TPS65910_OP_REG_SEL_1_2_0; + case MPUPLL_M_600: + case MPUPLL_M_300: + return TPS65910_OP_REG_SEL_1_1_3; + } + } + + /* Default to PG1.0/PG2.0 values. */ + return TPS65910_OP_REG_SEL_1_1_3; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/u-boot-spl.lds b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/u-boot-spl.lds new file mode 100644 index 000000000..b1c28c944 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/am33xx/u-boot-spl.lds @@ -0,0 +1,55 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : + { + __start = .; + arch/arm/cpu/armv7/start.o (.text) + *(.text*) + } >.sram + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram + + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } >.sram + + . = ALIGN(4); + __image_copy_end = .; + + .end : + { + *(.__end) + } >.sram + + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } >.sdram +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/arch_timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/arch_timer.c new file mode 100644 index 000000000..0588e2bae --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/arch_timer.c @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <div64.h> + +DECLARE_GLOBAL_DATA_PTR; + +int timer_init(void) +{ + gd->arch.tbl = 0; + gd->arch.tbu = 0; + + gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ; + + return 0; +} + +unsigned long long get_ticks(void) +{ + ulong nowl, nowu; + + asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (nowl), "=r" (nowu)); + + gd->arch.tbl = nowl; + gd->arch.tbu = nowu; + + return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl; +} + + +ulong get_timer(ulong base) +{ + return lldiv(get_ticks(), gd->arch.timer_rate_hz) - base; +} + +void __udelay(unsigned long usec) +{ + unsigned long long endtime; + + endtime = lldiv((unsigned long long)usec * gd->arch.timer_rate_hz, + 1000UL); + + endtime += get_ticks(); + + while (get_ticks() < endtime) + ; +} + +ulong get_tbclk(void) +{ + return gd->arch.timer_rate_hz; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/Makefile new file mode 100644 index 000000000..0a2e48d04 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/Makefile @@ -0,0 +1,15 @@ +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2013 +# Bo Shen <voice.shen@atmel.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_SAMA5D3) += sama5d3_devices.o +obj-y += clock.o +obj-y += cpu.o +obj-y += reset.o +obj-y += timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/clock.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/clock.c new file mode 100644 index 000000000..1588e0c8e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/clock.c @@ -0,0 +1,122 @@ +/* + * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c] + * + * Copyright (C) 2005 David Brownell + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * Copyright (C) 2013 Bo Shen <voice.shen@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/clk.h> + +#if !defined(CONFIG_AT91FAMILY) +# error You need to define CONFIG_AT91FAMILY in your board config! +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static unsigned long at91_css_to_rate(unsigned long css) +{ + switch (css) { + case AT91_PMC_MCKR_CSS_SLOW: + return CONFIG_SYS_AT91_SLOW_CLOCK; + case AT91_PMC_MCKR_CSS_MAIN: + return gd->arch.main_clk_rate_hz; + case AT91_PMC_MCKR_CSS_PLLA: + return gd->arch.plla_rate_hz; + } + + return 0; +} + +static u32 at91_pll_rate(u32 freq, u32 reg) +{ + unsigned mul, div; + + div = reg & 0xff; + mul = (reg >> 18) & 0x7f; + if (div && mul) { + freq /= div; + freq *= mul + 1; + } else { + freq = 0; + } + + return freq; +} + +int at91_clock_init(unsigned long main_clock) +{ + unsigned freq, mckr; + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; +#ifndef CONFIG_SYS_AT91_MAIN_CLOCK + unsigned tmp; + /* + * When the bootloader initialized the main oscillator correctly, + * there's no problem using the cycle counter. But if it didn't, + * or when using oscillator bypass mode, we must be told the speed + * of the main clock. + */ + if (!main_clock) { + do { + tmp = readl(&pmc->mcfr); + } while (!(tmp & AT91_PMC_MCFR_MAINRDY)); + tmp &= AT91_PMC_MCFR_MAINF_MASK; + main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16); + } +#endif + gd->arch.main_clk_rate_hz = main_clock; + + /* report if PLLA is more than mildly overclocked */ + gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar)); + + /* + * MCK and CPU derive from one of those primary clocks. + * For now, assume this parentage won't change. + */ + mckr = readl(&pmc->mckr); + + /* plla divisor by 2 */ + if (mckr & (1 << 12)) + gd->arch.plla_rate_hz >>= 1; + + gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); + freq = gd->arch.mck_rate_hz; + + /* prescale */ + freq >>= mckr & AT91_PMC_MCKR_PRES_MASK; + + switch (mckr & AT91_PMC_MCKR_MDIV_MASK) { + case AT91_PMC_MCKR_MDIV_2: + gd->arch.mck_rate_hz = freq / 2; + break; + case AT91_PMC_MCKR_MDIV_3: + gd->arch.mck_rate_hz = freq / 3; + break; + case AT91_PMC_MCKR_MDIV_4: + gd->arch.mck_rate_hz = freq / 4; + break; + default: + break; + } + + gd->arch.cpu_clk_rate_hz = freq; + + return 0; +} + +void at91_periph_clk_enable(int id) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + if (id > 31) + writel(1 << (id - 32), &pmc->pcer1); + else + writel(1 << id, &pmc->pcer); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/cpu.c new file mode 100644 index 000000000..2fbf60d54 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/cpu.c @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2010 + * Reinhard Meyer, reinhard.meyer@emk-elektronik.de + * (C) Copyright 2009 + * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * (C) Copyright 2013 + * Bo Shen <voice.shen@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_dbu.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_pit.h> +#include <asm/arch/at91_gpbr.h> +#include <asm/arch/clk.h> + +#ifndef CONFIG_SYS_AT91_MAIN_CLOCK +#define CONFIG_SYS_AT91_MAIN_CLOCK 0 +#endif + +int arch_cpu_init(void) +{ + return at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); +} + +void arch_preboot_os(void) +{ + ulong cpiv; + at91_pit_t *pit = (at91_pit_t *)ATMEL_BASE_PIT; + + cpiv = AT91_PIT_MR_PIV_MASK(readl(&pit->piir)); + + /* + * Disable PITC + * Add 0x1000 to current counter to stop it faster + * without waiting for wrapping back to 0 + */ + writel(cpiv + 0x1000, &pit->mr); +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + char buf[32]; + + printf("CPU: %s\n", get_cpu_name()); + printf("Crystal frequency: %8s MHz\n", + strmhz(buf, get_main_clk_rate())); + printf("CPU clock : %8s MHz\n", + strmhz(buf, get_cpu_clk_rate())); + printf("Master clock : %8s MHz\n", + strmhz(buf, get_mck_clk_rate())); + + return 0; +} +#endif + +void enable_caches(void) +{ +} + +unsigned int get_chip_id(void) +{ + return readl(ATMEL_BASE_DBGU + AT91_DBU_CIDR) & ~AT91_DBU_CIDR_MASK; +} + +unsigned int get_extension_chip_id(void) +{ + return readl(ATMEL_BASE_DBGU + AT91_DBU_EXID); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/reset.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/reset.c new file mode 100644 index 000000000..b30e79b60 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/reset.c @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * (C) Copyright 2013 + * Bo Shen <voice.shen@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_rstc.h> + +/* Reset the cpu by telling the reset controller to do so */ +void reset_cpu(ulong ignored) +{ + at91_rstc_t *rstc = (at91_rstc_t *)ATMEL_BASE_RSTC; + + writel(AT91_RSTC_KEY + | AT91_RSTC_CR_PROCRST /* Processor Reset */ + | AT91_RSTC_CR_PERRST /* Peripheral Reset */ +#ifdef CONFIG_AT91RESET_EXTRST + | AT91_RSTC_CR_EXTRST /* External Reset (assert nRST pin) */ +#endif + , &rstc->cr); + /* never reached */ + do { } while (1); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/sama5d3_devices.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/sama5d3_devices.c new file mode 100644 index 000000000..78ecfc882 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/sama5d3_devices.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2012-2013 Atmel Corporation + * Bo Shen <voice.shen@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/sama5d3.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/clk.h> +#include <asm/arch/gpio.h> +#include <asm/io.h> + +unsigned int has_emac() +{ + return cpu_is_sama5d31() || cpu_is_sama5d35() || cpu_is_sama5d36(); +} + +unsigned int has_gmac() +{ + return !cpu_is_sama5d31(); +} + +unsigned int has_lcdc() +{ + return !cpu_is_sama5d35(); +} + +char *get_cpu_name() +{ + unsigned int extension_id = get_extension_chip_id(); + + if (cpu_is_sama5d3()) + switch (extension_id) { + case ARCH_EXID_SAMA5D31: + return "SAMA5D31"; + case ARCH_EXID_SAMA5D33: + return "SAMA5D33"; + case ARCH_EXID_SAMA5D34: + return "SAMA5D34"; + case ARCH_EXID_SAMA5D35: + return "SAMA5D35"; + case ARCH_EXID_SAMA5D36: + return "SAMA5D36"; + default: + return "Unknown CPU type"; + } + else + return "Unknown CPU type"; +} + +void at91_serial0_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTD, 18, 1); /* TXD0 */ + at91_set_a_periph(AT91_PIO_PORTD, 17, 0); /* RXD0 */ + + /* Enable clock */ + at91_periph_clk_enable(ATMEL_ID_USART0); +} + +void at91_serial1_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTB, 29, 1); /* TXD1 */ + at91_set_a_periph(AT91_PIO_PORTB, 28, 0); /* RXD1 */ + + /* Enable clock */ + at91_periph_clk_enable(ATMEL_ID_USART1); +} + +void at91_serial2_hw_init(void) +{ + at91_set_b_periph(AT91_PIO_PORTE, 26, 1); /* TXD2 */ + at91_set_b_periph(AT91_PIO_PORTE, 25, 0); /* RXD2 */ + + /* Enable clock */ + at91_periph_clk_enable(ATMEL_ID_USART2); +} + +void at91_seriald_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTB, 31, 1); /* DTXD */ + at91_set_a_periph(AT91_PIO_PORTB, 30, 0); /* DRXD */ + + /* Enable clock */ + at91_periph_clk_enable(ATMEL_ID_DBGU); +} + +#if defined(CONFIG_ATMEL_SPI) +void at91_spi0_hw_init(unsigned long cs_mask) +{ + at91_set_a_periph(AT91_PIO_PORTD, 10, 0); /* SPI0_MISO */ + at91_set_a_periph(AT91_PIO_PORTD, 11, 0); /* SPI0_MOSI */ + at91_set_a_periph(AT91_PIO_PORTD, 12, 0); /* SPI0_SPCK */ + + if (cs_mask & (1 << 0)) + at91_set_pio_output(AT91_PIO_PORTD, 13, 1); + if (cs_mask & (1 << 1)) + at91_set_pio_output(AT91_PIO_PORTD, 14, 1); + if (cs_mask & (1 << 2)) + at91_set_pio_output(AT91_PIO_PORTD, 15, 1); + if (cs_mask & (1 << 3)) + at91_set_pio_output(AT91_PIO_PORTD, 16, 1); + + /* Enable clock */ + at91_periph_clk_enable(ATMEL_ID_SPI0); +} +#endif + +#ifdef CONFIG_GENERIC_ATMEL_MCI +void at91_mci_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTD, 0, 0); /* MCI0 CMD */ + at91_set_a_periph(AT91_PIO_PORTD, 1, 0); /* MCI0 DA0 */ + at91_set_a_periph(AT91_PIO_PORTD, 2, 0); /* MCI0 DA1 */ + at91_set_a_periph(AT91_PIO_PORTD, 3, 0); /* MCI0 DA2 */ + at91_set_a_periph(AT91_PIO_PORTD, 4, 0); /* MCI0 DA3 */ +#ifdef CONFIG_ATMEL_MCI_8BIT + at91_set_a_periph(AT91_PIO_PORTD, 5, 0); /* MCI0 DA4 */ + at91_set_a_periph(AT91_PIO_PORTD, 6, 0); /* MCI0 DA5 */ + at91_set_a_periph(AT91_PIO_PORTD, 7, 0); /* MCI0 DA6 */ + at91_set_a_periph(AT91_PIO_PORTD, 8, 0); /* MCI0 DA7 */ +#endif + at91_set_a_periph(AT91_PIO_PORTD, 9, 0); /* MCI0 CLK */ + + /* Enable clock */ + at91_periph_clk_enable(ATMEL_ID_MCI0); +} +#endif + +#ifdef CONFIG_MACB +void at91_macb_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTC, 7, 0); /* ETXCK_EREFCK */ + at91_set_a_periph(AT91_PIO_PORTC, 5, 0); /* ERXDV */ + at91_set_a_periph(AT91_PIO_PORTC, 2, 0); /* ERX0 */ + at91_set_a_periph(AT91_PIO_PORTC, 3, 0); /* ERX1 */ + at91_set_a_periph(AT91_PIO_PORTC, 6, 0); /* ERXER */ + at91_set_a_periph(AT91_PIO_PORTC, 4, 0); /* ETXEN */ + at91_set_a_periph(AT91_PIO_PORTC, 0, 0); /* ETX0 */ + at91_set_a_periph(AT91_PIO_PORTC, 1, 0); /* ETX1 */ + at91_set_a_periph(AT91_PIO_PORTC, 9, 0); /* EMDIO */ + at91_set_a_periph(AT91_PIO_PORTC, 8, 0); /* EMDC */ + + /* Enable clock */ + at91_periph_clk_enable(ATMEL_ID_EMAC); +} + +void at91_gmac_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTB, 0, 0); /* GTX0 */ + at91_set_a_periph(AT91_PIO_PORTB, 1, 0); /* GTX1 */ + at91_set_a_periph(AT91_PIO_PORTB, 2, 0); /* GTX2 */ + at91_set_a_periph(AT91_PIO_PORTB, 3, 0); /* GTX3 */ + at91_set_a_periph(AT91_PIO_PORTB, 4, 0); /* GRX0 */ + at91_set_a_periph(AT91_PIO_PORTB, 5, 0); /* GRX1 */ + at91_set_a_periph(AT91_PIO_PORTB, 6, 0); /* GRX2 */ + at91_set_a_periph(AT91_PIO_PORTB, 7, 0); /* GRX3 */ + at91_set_a_periph(AT91_PIO_PORTB, 8, 0); /* GTXCK */ + at91_set_a_periph(AT91_PIO_PORTB, 9, 0); /* GTXEN */ + + at91_set_a_periph(AT91_PIO_PORTB, 11, 0); /* GRXCK */ + at91_set_a_periph(AT91_PIO_PORTB, 13, 0); /* GRXER */ + + at91_set_a_periph(AT91_PIO_PORTB, 16, 0); /* GMDC */ + at91_set_a_periph(AT91_PIO_PORTB, 17, 0); /* GMDIO */ + at91_set_a_periph(AT91_PIO_PORTB, 18, 0); /* G125CK */ + + /* Enable clock */ + at91_periph_clk_enable(ATMEL_ID_GMAC); +} +#endif + +#ifdef CONFIG_LCD +void at91_lcd_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTA, 24, 0); /* LCDPWM */ + at91_set_a_periph(AT91_PIO_PORTA, 25, 0); /* LCDDISP */ + at91_set_a_periph(AT91_PIO_PORTA, 26, 0); /* LCDVSYNC */ + at91_set_a_periph(AT91_PIO_PORTA, 27, 0); /* LCDHSYNC */ + at91_set_a_periph(AT91_PIO_PORTA, 28, 0); /* LCDDOTCK */ + at91_set_a_periph(AT91_PIO_PORTA, 29, 0); /* LCDDEN */ + + /* The lower 16-bit of LCD only available on Port A */ + at91_set_a_periph(AT91_PIO_PORTA, 0, 0); /* LCDD0 */ + at91_set_a_periph(AT91_PIO_PORTA, 1, 0); /* LCDD1 */ + at91_set_a_periph(AT91_PIO_PORTA, 2, 0); /* LCDD2 */ + at91_set_a_periph(AT91_PIO_PORTA, 3, 0); /* LCDD3 */ + at91_set_a_periph(AT91_PIO_PORTA, 4, 0); /* LCDD4 */ + at91_set_a_periph(AT91_PIO_PORTA, 5, 0); /* LCDD5 */ + at91_set_a_periph(AT91_PIO_PORTA, 6, 0); /* LCDD6 */ + at91_set_a_periph(AT91_PIO_PORTA, 7, 0); /* LCDD7 */ + at91_set_a_periph(AT91_PIO_PORTA, 8, 0); /* LCDD8 */ + at91_set_a_periph(AT91_PIO_PORTA, 9, 0); /* LCDD9 */ + at91_set_a_periph(AT91_PIO_PORTA, 10, 0); /* LCDD10 */ + at91_set_a_periph(AT91_PIO_PORTA, 11, 0); /* LCDD11 */ + at91_set_a_periph(AT91_PIO_PORTA, 12, 0); /* LCDD12 */ + at91_set_a_periph(AT91_PIO_PORTA, 13, 0); /* LCDD13 */ + at91_set_a_periph(AT91_PIO_PORTA, 14, 0); /* LCDD14 */ + at91_set_a_periph(AT91_PIO_PORTA, 15, 0); /* LCDD15 */ + + /* Enable clock */ + at91_periph_clk_enable(ATMEL_ID_LCDC); +} +#endif + +#ifdef CONFIG_USB_GADGET_ATMEL_USBA +void at91_udp_hw_init(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + /* Enable UPLL clock */ + writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr); + /* Enable UDPHS clock */ + at91_periph_clk_enable(ATMEL_ID_UDPHS); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/timer.c new file mode 100644 index 000000000..e3ebfe0c5 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/at91/timer.c @@ -0,0 +1,123 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * (C) Copyright 2013 + * Bo Shen <voice.shen@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pit.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/clk.h> +#include <div64.h> + +#if !defined(CONFIG_AT91FAMILY) +# error You need to define CONFIG_AT91FAMILY in your board config! +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/* + * We're using the SAMA5D3x PITC in 32 bit mode, by + * setting the 20 bit counter period to its maximum (0xfffff). + * (See the relevant data sheets to understand that this really works) + * + * We do also mimic the typical powerpc way of incrementing + * two 32 bit registers called tbl and tbu. + * + * Those registers increment at 1/16 the main clock rate. + */ + +#define TIMER_LOAD_VAL 0xfffff + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, gd->arch.timer_rate_hz); + + return tick; +} + +static inline unsigned long long usec_to_tick(unsigned long long usec) +{ + usec *= gd->arch.timer_rate_hz; + do_div(usec, 1000000); + + return usec; +} + +/* + * Use the PITC in full 32 bit incrementing mode + */ +int timer_init(void) +{ + at91_pit_t *pit = (at91_pit_t *)ATMEL_BASE_PIT; + + /* Enable PITC Clock */ + at91_periph_clk_enable(ATMEL_ID_PIT); + + /* Enable PITC */ + writel(TIMER_LOAD_VAL | AT91_PIT_MR_EN , &pit->mr); + + gd->arch.timer_rate_hz = gd->arch.mck_rate_hz / 16; + gd->arch.tbu = 0; + gd->arch.tbl = 0; + + return 0; +} + +/* + * Get the current 64 bit timer tick count + */ +unsigned long long get_ticks(void) +{ + at91_pit_t *pit = (at91_pit_t *)ATMEL_BASE_PIT; + + ulong now = readl(&pit->piir); + + /* 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; +} + +void __udelay(unsigned long usec) +{ + unsigned long long start; + ulong tmo; + + start = get_ticks(); /* get current timestamp */ + tmo = usec_to_tick(usec); /* convert usecs to ticks */ + while ((get_ticks() - start) < tmo) + ; /* loop till time has passed */ +} + +/* + * get_timer(base) can be used to check for timeouts or + * to measure elasped time relative to an event: + * + * ulong start_time = get_timer(0) sets start_time to the current + * time value. + * get_timer(start_time) returns the time elapsed since then. + * + * The time is used in CONFIG_SYS_HZ units! + */ +ulong get_timer(ulong base) +{ + return tick_to_time(get_ticks()) - base; +} + +/* + * Return the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return gd->arch.timer_rate_hz; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/Makefile new file mode 100644 index 000000000..98f5aa59c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/Makefile @@ -0,0 +1,11 @@ +# +# Copyright 2013 Broadcom Corporation. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += reset.o +obj-y += clk-core.o +obj-y += clk-bcm281xx.o +obj-y += clk-sdio.o +obj-y += clk-bsc.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c new file mode 100644 index 000000000..bc8a170b4 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c @@ -0,0 +1,523 @@ +/* + * Copyright 2013 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * + * bcm281xx-specific clock tables + * + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +#define CLOCK_1K 1000 +#define CLOCK_1M (CLOCK_1K * 1000) + +/* declare a reference clock */ +#define DECLARE_REF_CLK(clk_name, clk_parent, clk_rate, clk_div) \ +static struct refclk clk_name = { \ + .clk = { \ + .name = #clk_name, \ + .parent = clk_parent, \ + .rate = clk_rate, \ + .div = clk_div, \ + .ops = &ref_clk_ops, \ + }, \ +} + +/* + * Reference clocks + */ + +/* Declare a list of reference clocks */ +DECLARE_REF_CLK(ref_crystal, 0, 26 * CLOCK_1M, 1); +DECLARE_REF_CLK(var_96m, 0, 96 * CLOCK_1M, 1); +DECLARE_REF_CLK(ref_96m, 0, 96 * CLOCK_1M, 1); +DECLARE_REF_CLK(ref_312m, 0, 312 * CLOCK_1M, 0); +DECLARE_REF_CLK(ref_104m, &ref_312m.clk, 104 * CLOCK_1M, 3); +DECLARE_REF_CLK(ref_52m, &ref_104m.clk, 52 * CLOCK_1M, 2); +DECLARE_REF_CLK(ref_13m, &ref_52m.clk, 13 * CLOCK_1M, 4); +DECLARE_REF_CLK(var_312m, 0, 312 * CLOCK_1M, 0); +DECLARE_REF_CLK(var_104m, &var_312m.clk, 104 * CLOCK_1M, 3); +DECLARE_REF_CLK(var_52m, &var_104m.clk, 52 * CLOCK_1M, 2); +DECLARE_REF_CLK(var_13m, &var_52m.clk, 13 * CLOCK_1M, 4); + +struct refclk_lkup { + struct refclk *procclk; + const char *name; +}; + +/* Lookup table for string to clk tranlation */ +#define MKSTR(x) {&x, #x} +static struct refclk_lkup refclk_str_tbl[] = { + MKSTR(ref_crystal), MKSTR(var_96m), MKSTR(ref_96m), + MKSTR(ref_312m), MKSTR(ref_104m), MKSTR(ref_52m), + MKSTR(ref_13m), MKSTR(var_312m), MKSTR(var_104m), + MKSTR(var_52m), MKSTR(var_13m), +}; + +int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]); + +/* convert ref clock string to clock structure pointer */ +struct refclk *refclk_str_to_clk(const char *name) +{ + int i; + struct refclk_lkup *tblp = refclk_str_tbl; + for (i = 0; i < refclk_entries; i++, tblp++) { + if (!(strcmp(name, tblp->name))) + return tblp->procclk; + } + return NULL; +} + +/* frequency tables indexed by freq_id */ +unsigned long master_axi_freq_tbl[8] = { + 26 * CLOCK_1M, + 52 * CLOCK_1M, + 104 * CLOCK_1M, + 156 * CLOCK_1M, + 156 * CLOCK_1M, + 208 * CLOCK_1M, + 312 * CLOCK_1M, + 312 * CLOCK_1M +}; + +unsigned long master_ahb_freq_tbl[8] = { + 26 * CLOCK_1M, + 52 * CLOCK_1M, + 52 * CLOCK_1M, + 52 * CLOCK_1M, + 78 * CLOCK_1M, + 104 * CLOCK_1M, + 104 * CLOCK_1M, + 156 * CLOCK_1M +}; + +unsigned long slave_axi_freq_tbl[8] = { + 26 * CLOCK_1M, + 52 * CLOCK_1M, + 78 * CLOCK_1M, + 104 * CLOCK_1M, + 156 * CLOCK_1M, + 156 * CLOCK_1M +}; + +unsigned long slave_apb_freq_tbl[8] = { + 26 * CLOCK_1M, + 26 * CLOCK_1M, + 39 * CLOCK_1M, + 52 * CLOCK_1M, + 52 * CLOCK_1M, + 78 * CLOCK_1M +}; + +static struct bus_clk_data bsc1_apb_data = { + .gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1), +}; + +static struct bus_clk_data bsc2_apb_data = { + .gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1), +}; + +static struct bus_clk_data bsc3_apb_data = { + .gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1), +}; + +/* * Master CCU clocks */ +static struct peri_clk_data sdio1_data = { + .gate = HW_SW_GATE(0x0358, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a28, 0, 3), + .div = DIVIDER(0x0a28, 4, 14), + .trig = TRIGGER(0x0afc, 9), +}; + +static struct peri_clk_data sdio2_data = { + .gate = HW_SW_GATE(0x035c, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a2c, 0, 3), + .div = DIVIDER(0x0a2c, 4, 14), + .trig = TRIGGER(0x0afc, 10), +}; + +static struct peri_clk_data sdio3_data = { + .gate = HW_SW_GATE(0x0364, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a34, 0, 3), + .div = DIVIDER(0x0a34, 4, 14), + .trig = TRIGGER(0x0afc, 12), +}; + +static struct peri_clk_data sdio4_data = { + .gate = HW_SW_GATE(0x0360, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a30, 0, 3), + .div = DIVIDER(0x0a30, 4, 14), + .trig = TRIGGER(0x0afc, 11), +}; + +static struct peri_clk_data sdio1_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x0358, 20, 4), +}; + +static struct peri_clk_data sdio2_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x035c, 20, 4), +}; + +static struct peri_clk_data sdio3_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x0364, 20, 4), +}; + +static struct peri_clk_data sdio4_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x0360, 20, 4), +}; + +static struct bus_clk_data sdio1_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0358, 16, 0, 1), +}; + +static struct bus_clk_data sdio2_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x035c, 16, 0, 1), +}; + +static struct bus_clk_data sdio3_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0364, 16, 0, 1), +}; + +static struct bus_clk_data sdio4_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0360, 16, 0, 1), +}; + +/* * Slave CCU clocks */ +static struct peri_clk_data bsc1_data = { + .gate = HW_SW_GATE(0x0458, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_104m", + "ref_104m", + "var_13m", + "ref_13m"), + .sel = SELECTOR(0x0a64, 0, 3), + .trig = TRIGGER(0x0afc, 23), +}; + +static struct peri_clk_data bsc2_data = { + .gate = HW_SW_GATE(0x045c, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_104m", + "ref_104m", + "var_13m", + "ref_13m"), + .sel = SELECTOR(0x0a68, 0, 3), + .trig = TRIGGER(0x0afc, 24), +}; + +static struct peri_clk_data bsc3_data = { + .gate = HW_SW_GATE(0x0484, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_104m", + "ref_104m", + "var_13m", + "ref_13m"), + .sel = SELECTOR(0x0a84, 0, 3), + .trig = TRIGGER(0x0b00, 2), +}; + +/* + * CCU clocks + */ + +static struct ccu_clock kpm_ccu_clk = { + .clk = { + .name = "kpm_ccu_clk", + .ops = &ccu_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .num_policy_masks = 1, + .policy_freq_offset = 0x00000008, + .freq_bit_shift = 8, + .policy_ctl_offset = 0x0000000c, + .policy0_mask_offset = 0x00000010, + .policy1_mask_offset = 0x00000014, + .policy2_mask_offset = 0x00000018, + .policy3_mask_offset = 0x0000001c, + .lvm_en_offset = 0x00000034, + .freq_id = 2, + .freq_tbl = master_axi_freq_tbl, +}; + +static struct ccu_clock kps_ccu_clk = { + .clk = { + .name = "kps_ccu_clk", + .ops = &ccu_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .num_policy_masks = 2, + .policy_freq_offset = 0x00000008, + .freq_bit_shift = 8, + .policy_ctl_offset = 0x0000000c, + .policy0_mask_offset = 0x00000010, + .policy1_mask_offset = 0x00000014, + .policy2_mask_offset = 0x00000018, + .policy3_mask_offset = 0x0000001c, + .policy0_mask2_offset = 0x00000048, + .policy1_mask2_offset = 0x0000004c, + .policy2_mask2_offset = 0x00000050, + .policy3_mask2_offset = 0x00000054, + .lvm_en_offset = 0x00000034, + .freq_id = 2, + .freq_tbl = slave_axi_freq_tbl, +}; + +/* + * Bus clocks + */ + +/* KPM bus clocks */ +static struct bus_clock sdio1_ahb_clk = { + .clk = { + .name = "sdio1_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio1_ahb_data, +}; + +static struct bus_clock sdio2_ahb_clk = { + .clk = { + .name = "sdio2_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio2_ahb_data, +}; + +static struct bus_clock sdio3_ahb_clk = { + .clk = { + .name = "sdio3_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio3_ahb_data, +}; + +static struct bus_clock sdio4_ahb_clk = { + .clk = { + .name = "sdio4_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio4_ahb_data, +}; + +static struct bus_clock bsc1_apb_clk = { + .clk = { + .name = "bsc1_apb_clk", + .parent = &kps_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .freq_tbl = slave_apb_freq_tbl, + .data = &bsc1_apb_data, +}; + +static struct bus_clock bsc2_apb_clk = { + .clk = { + .name = "bsc2_apb_clk", + .parent = &kps_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .freq_tbl = slave_apb_freq_tbl, + .data = &bsc2_apb_data, +}; + +static struct bus_clock bsc3_apb_clk = { + .clk = { + .name = "bsc3_apb_clk", + .parent = &kps_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .freq_tbl = slave_apb_freq_tbl, + .data = &bsc3_apb_data, +}; + +/* KPM peripheral */ +static struct peri_clock sdio1_clk = { + .clk = { + .name = "sdio1_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio1_data, +}; + +static struct peri_clock sdio2_clk = { + .clk = { + .name = "sdio2_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio2_data, +}; + +static struct peri_clock sdio3_clk = { + .clk = { + .name = "sdio3_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio3_data, +}; + +static struct peri_clock sdio4_clk = { + .clk = { + .name = "sdio4_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio4_data, +}; + +static struct peri_clock sdio1_sleep_clk = { + .clk = { + .name = "sdio1_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio1_sleep_data, +}; + +static struct peri_clock sdio2_sleep_clk = { + .clk = { + .name = "sdio2_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio2_sleep_data, +}; + +static struct peri_clock sdio3_sleep_clk = { + .clk = { + .name = "sdio3_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio3_sleep_data, +}; + +static struct peri_clock sdio4_sleep_clk = { + .clk = { + .name = "sdio4_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio4_sleep_data, +}; + +/* KPS peripheral clock */ +static struct peri_clock bsc1_clk = { + .clk = { + .name = "bsc1_clk", + .parent = &ref_13m.clk, + .rate = 13 * CLOCK_1M, + .div = 1, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .data = &bsc1_data, +}; + +static struct peri_clock bsc2_clk = { + .clk = { + .name = "bsc2_clk", + .parent = &ref_13m.clk, + .rate = 13 * CLOCK_1M, + .div = 1, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .data = &bsc2_data, +}; + +static struct peri_clock bsc3_clk = { + .clk = { + .name = "bsc3_clk", + .parent = &ref_13m.clk, + .rate = 13 * CLOCK_1M, + .div = 1, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .data = &bsc3_data, +}; + +/* public table for registering clocks */ +struct clk_lookup arch_clk_tbl[] = { + /* Peripheral clocks */ + CLK_LK(sdio1), + CLK_LK(sdio2), + CLK_LK(sdio3), + CLK_LK(sdio4), + CLK_LK(sdio1_sleep), + CLK_LK(sdio2_sleep), + CLK_LK(sdio3_sleep), + CLK_LK(sdio4_sleep), + CLK_LK(bsc1), + CLK_LK(bsc2), + CLK_LK(bsc3), + /* Bus clocks */ + CLK_LK(sdio1_ahb), + CLK_LK(sdio2_ahb), + CLK_LK(sdio3_ahb), + CLK_LK(sdio4_ahb), + CLK_LK(bsc1_apb), + CLK_LK(bsc2_apb), + CLK_LK(bsc3_apb), +}; + +/* public array size */ +unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl); diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c new file mode 100644 index 000000000..ba55d0aeb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c @@ -0,0 +1,52 @@ +/* + * Copyright 2013 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +/* Enable appropriate clocks for a BSC/I2C port */ +int clk_bsc_enable(void *base) +{ + int ret; + char *bscstr, *apbstr; + + switch ((u32) base) { + case PMU_BSC_BASE_ADDR: + /* PMU clock is always enabled */ + return 0; + case BSC1_BASE_ADDR: + bscstr = "bsc1_clk"; + apbstr = "bsc1_apb_clk"; + break; + case BSC2_BASE_ADDR: + bscstr = "bsc2_clk"; + apbstr = "bsc2_apb_clk"; + break; + case BSC3_BASE_ADDR: + bscstr = "bsc3_clk"; + apbstr = "bsc3_apb_clk"; + break; + default: + printf("%s: base 0x%p not found\n", __func__, base); + return -EINVAL; + } + + /* Note that the bus clock must be enabled first */ + + ret = clk_get_and_enable(apbstr); + if (ret) + return ret; + + ret = clk_get_and_enable(bscstr); + if (ret) + return ret; + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-core.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-core.c new file mode 100644 index 000000000..d4425835a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-core.c @@ -0,0 +1,513 @@ +/* + * Copyright 2013 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * + * bcm281xx architecture clock framework + * + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <bitfield.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +#define CLK_WR_ACCESS_PASSWORD 0x00a5a501 +#define WR_ACCESS_OFFSET 0 /* common to all clock blocks */ +#define POLICY_CTL_GO 1 /* Load and refresh policy masks */ +#define POLICY_CTL_GO_ATL 4 /* Active Load */ + +/* Helper function */ +int clk_get_and_enable(char *clkstr) +{ + int ret = 0; + struct clk *c; + + debug("%s: %s\n", __func__, clkstr); + + c = clk_get(clkstr); + if (c) { + ret = clk_enable(c); + if (ret) + return ret; + } else { + printf("%s: Couldn't find %s\n", __func__, clkstr); + return -EINVAL; + } + return ret; +} + +/* + * Poll a register in a CCU's address space, returning when the + * specified bit in that register's value is set (or clear). Delay + * a microsecond after each read of the register. Returns true if + * successful, or false if we gave up trying. + * + * Caller must ensure the CCU lock is held. + */ +#define CLK_GATE_DELAY_USEC 2000 +static inline int wait_bit(void *base, u32 offset, u32 bit, bool want) +{ + unsigned int tries; + u32 bit_mask = 1 << bit; + + for (tries = 0; tries < CLK_GATE_DELAY_USEC; tries++) { + u32 val; + bool bit_val; + + val = readl(base + offset); + bit_val = (val & bit_mask) ? 1 : 0; + if (bit_val == want) + return 0; /* success */ + udelay(1); + } + + debug("%s: timeout on addr 0x%p, waiting for bit %d to go to %d\n", + __func__, base + offset, bit, want); + + return -ETIMEDOUT; +} + +/* Enable a peripheral clock */ +static int peri_clk_enable(struct clk *c, int enable) +{ + int ret = 0; + u32 reg; + struct peri_clock *peri_clk = to_peri_clk(c); + struct peri_clk_data *cd = peri_clk->data; + struct bcm_clk_gate *gate = &cd->gate; + void *base = (void *)c->ccu_clk_mgr_base; + + + debug("%s: %s\n", __func__, c->name); + + clk_get_rate(c); /* Make sure rate and sel are filled in */ + + /* enable access */ + writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET); + + if (enable) { + debug("%s %s set rate %lu div %lu sel %d parent %lu\n", + __func__, c->name, c->rate, c->div, c->sel, + c->parent->rate); + + /* + * clkgate - only software controllable gates are + * supported by u-boot which includes all clocks + * that matter. This avoids bringing in a lot of extra + * complexity as done in the kernel framework. + */ + if (gate_exists(gate)) { + reg = readl(base + cd->gate.offset); + reg |= (1 << cd->gate.en_bit); + writel(reg, base + cd->gate.offset); + } + + /* div and pll select */ + if (divider_exists(&cd->div)) { + reg = readl(base + cd->div.offset); + bitfield_replace(reg, cd->div.shift, cd->div.width, + c->div - 1); + writel(reg, base + cd->div.offset); + } + + /* frequency selector */ + if (selector_exists(&cd->sel)) { + reg = readl(base + cd->sel.offset); + bitfield_replace(reg, cd->sel.shift, cd->sel.width, + c->sel); + writel(reg, base + cd->sel.offset); + } + + /* trigger */ + if (trigger_exists(&cd->trig)) { + writel((1 << cd->trig.bit), base + cd->trig.offset); + + /* wait for trigger status bit to go to 0 */ + ret = wait_bit(base, cd->trig.offset, cd->trig.bit, 0); + if (ret) + return ret; + } + + /* wait for running (status_bit = 1) */ + ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 1); + if (ret) + return ret; + } else { + debug("%s disable clock %s\n", __func__, c->name); + + /* clkgate */ + reg = readl(base + cd->gate.offset); + reg &= ~(1 << cd->gate.en_bit); + writel(reg, base + cd->gate.offset); + + /* wait for stop (status_bit = 0) */ + ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 0); + } + + /* disable access */ + writel(0, base + WR_ACCESS_OFFSET); + + return ret; +} + +/* Set the rate of a peripheral clock */ +static int peri_clk_set_rate(struct clk *c, unsigned long rate) +{ + int ret = 0; + int i; + unsigned long diff; + unsigned long new_rate = 0, div = 1; + struct peri_clock *peri_clk = to_peri_clk(c); + struct peri_clk_data *cd = peri_clk->data; + const char **clock; + + debug("%s: %s\n", __func__, c->name); + diff = rate; + + i = 0; + for (clock = cd->clocks; *clock; clock++, i++) { + struct refclk *ref = refclk_str_to_clk(*clock); + if (!ref) { + printf("%s: Lookup of %s failed\n", __func__, *clock); + return -EINVAL; + } + + /* round to the new rate */ + div = ref->clk.rate / rate; + if (div == 0) + div = 1; + + new_rate = ref->clk.rate / div; + + /* get the min diff */ + if (abs(new_rate - rate) < diff) { + diff = abs(new_rate - rate); + c->sel = i; + c->parent = &ref->clk; + c->rate = new_rate; + c->div = div; + } + } + + debug("%s %s set rate %lu div %lu sel %d parent %lu\n", __func__, + c->name, c->rate, c->div, c->sel, c->parent->rate); + return ret; +} + +/* Get the rate of a peripheral clock */ +static unsigned long peri_clk_get_rate(struct clk *c) +{ + struct peri_clock *peri_clk = to_peri_clk(c); + struct peri_clk_data *cd = peri_clk->data; + void *base = (void *)c->ccu_clk_mgr_base; + int div = 1; + const char **clock; + struct refclk *ref; + u32 reg; + + debug("%s: %s\n", __func__, c->name); + if (selector_exists(&cd->sel)) { + reg = readl(base + cd->sel.offset); + c->sel = bitfield_extract(reg, cd->sel.shift, cd->sel.width); + } else { + /* + * For peri clocks that don't have a selector, the single + * reference clock will always exist at index 0. + */ + c->sel = 0; + } + + if (divider_exists(&cd->div)) { + reg = readl(base + cd->div.offset); + div = bitfield_extract(reg, cd->div.shift, cd->div.width); + div += 1; + } + + clock = cd->clocks; + ref = refclk_str_to_clk(clock[c->sel]); + if (!ref) { + printf("%s: Can't lookup %s\n", __func__, clock[c->sel]); + return 0; + } + + c->parent = &ref->clk; + c->div = div; + c->rate = c->parent->rate / c->div; + debug("%s parent rate %lu div %d sel %d rate %lu\n", __func__, + c->parent->rate, div, c->sel, c->rate); + + return c->rate; +} + +/* Peripheral clock operations */ +struct clk_ops peri_clk_ops = { + .enable = peri_clk_enable, + .set_rate = peri_clk_set_rate, + .get_rate = peri_clk_get_rate, +}; + +/* Enable a CCU clock */ +static int ccu_clk_enable(struct clk *c, int enable) +{ + struct ccu_clock *ccu_clk = to_ccu_clk(c); + void *base = (void *)c->ccu_clk_mgr_base; + int ret = 0; + u32 reg; + + debug("%s: %s\n", __func__, c->name); + if (!enable) + return -EINVAL; /* CCU clock cannot shutdown */ + + /* enable access */ + writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET); + + /* config enable for policy engine */ + writel(1, base + ccu_clk->lvm_en_offset); + + /* wait for bit to go to 0 */ + ret = wait_bit(base, ccu_clk->lvm_en_offset, 0, 0); + if (ret) + return ret; + + /* freq ID */ + if (!ccu_clk->freq_bit_shift) + ccu_clk->freq_bit_shift = 8; + + /* Set frequency id for each of the 4 policies */ + reg = ccu_clk->freq_id | + (ccu_clk->freq_id << (ccu_clk->freq_bit_shift)) | + (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 2)) | + (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 3)); + writel(reg, base + ccu_clk->policy_freq_offset); + + /* enable all clock mask */ + writel(0x7fffffff, base + ccu_clk->policy0_mask_offset); + writel(0x7fffffff, base + ccu_clk->policy1_mask_offset); + writel(0x7fffffff, base + ccu_clk->policy2_mask_offset); + writel(0x7fffffff, base + ccu_clk->policy3_mask_offset); + + if (ccu_clk->num_policy_masks == 2) { + writel(0x7fffffff, base + ccu_clk->policy0_mask2_offset); + writel(0x7fffffff, base + ccu_clk->policy1_mask2_offset); + writel(0x7fffffff, base + ccu_clk->policy2_mask2_offset); + writel(0x7fffffff, base + ccu_clk->policy3_mask2_offset); + } + + /* start policy engine */ + reg = readl(base + ccu_clk->policy_ctl_offset); + reg |= (POLICY_CTL_GO + POLICY_CTL_GO_ATL); + writel(reg, base + ccu_clk->policy_ctl_offset); + + /* wait till started */ + ret = wait_bit(base, ccu_clk->policy_ctl_offset, 0, 0); + if (ret) + return ret; + + /* disable access */ + writel(0, base + WR_ACCESS_OFFSET); + + return ret; +} + +/* Get the CCU clock rate */ +static unsigned long ccu_clk_get_rate(struct clk *c) +{ + struct ccu_clock *ccu_clk = to_ccu_clk(c); + debug("%s: %s\n", __func__, c->name); + c->rate = ccu_clk->freq_tbl[ccu_clk->freq_id]; + return c->rate; +} + +/* CCU clock operations */ +struct clk_ops ccu_clk_ops = { + .enable = ccu_clk_enable, + .get_rate = ccu_clk_get_rate, +}; + +/* Enable a bus clock */ +static int bus_clk_enable(struct clk *c, int enable) +{ + struct bus_clock *bus_clk = to_bus_clk(c); + struct bus_clk_data *cd = bus_clk->data; + void *base = (void *)c->ccu_clk_mgr_base; + int ret = 0; + u32 reg; + + debug("%s: %s\n", __func__, c->name); + /* enable access */ + writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET); + + /* enable gating */ + reg = readl(base + cd->gate.offset); + if (!!(reg & (1 << cd->gate.status_bit)) == !!enable) + debug("%s already %s\n", c->name, + enable ? "enabled" : "disabled"); + else { + int want = (enable) ? 1 : 0; + reg |= (1 << cd->gate.hw_sw_sel_bit); + + if (enable) + reg |= (1 << cd->gate.en_bit); + else + reg &= ~(1 << cd->gate.en_bit); + + writel(reg, base + cd->gate.offset); + ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, + want); + if (ret) + return ret; + } + + /* disable access */ + writel(0, base + WR_ACCESS_OFFSET); + + return ret; +} + +/* Get the rate of a bus clock */ +static unsigned long bus_clk_get_rate(struct clk *c) +{ + struct bus_clock *bus_clk = to_bus_clk(c); + struct ccu_clock *ccu_clk; + + debug("%s: %s\n", __func__, c->name); + ccu_clk = to_ccu_clk(c->parent); + + c->rate = bus_clk->freq_tbl[ccu_clk->freq_id]; + c->div = ccu_clk->freq_tbl[ccu_clk->freq_id] / c->rate; + return c->rate; +} + +/* Bus clock operations */ +struct clk_ops bus_clk_ops = { + .enable = bus_clk_enable, + .get_rate = bus_clk_get_rate, +}; + +/* Enable a reference clock */ +static int ref_clk_enable(struct clk *c, int enable) +{ + debug("%s: %s\n", __func__, c->name); + return 0; +} + +/* Reference clock operations */ +struct clk_ops ref_clk_ops = { + .enable = ref_clk_enable, +}; + +/* + * clk.h implementation follows + */ + +/* Initialize the clock framework */ +int clk_init(void) +{ + debug("%s:\n", __func__); + return 0; +} + +/* Get a clock handle, give a name string */ +struct clk *clk_get(const char *con_id) +{ + int i; + struct clk_lookup *clk_tblp; + + debug("%s: %s\n", __func__, con_id); + + clk_tblp = arch_clk_tbl; + for (i = 0; i < arch_clk_tbl_array_size; i++, clk_tblp++) { + if (clk_tblp->con_id) { + if (!con_id || strcmp(clk_tblp->con_id, con_id)) + continue; + return clk_tblp->clk; + } + } + return NULL; +} + +/* Enable a clock */ +int clk_enable(struct clk *c) +{ + int ret = 0; + + debug("%s: %s\n", __func__, c->name); + if (!c->ops || !c->ops->enable) + return -1; + + /* enable parent clock first */ + if (c->parent) + ret = clk_enable(c->parent); + + if (ret) + return ret; + + if (!c->use_cnt) { + c->use_cnt++; + ret = c->ops->enable(c, 1); + } + + return ret; +} + +/* Disable a clock */ +void clk_disable(struct clk *c) +{ + debug("%s: %s\n", __func__, c->name); + if (!c->ops || !c->ops->enable) + return; + + if (c->use_cnt) { + c->use_cnt--; + c->ops->enable(c, 0); + } + + /* disable parent */ + if (c->parent) + clk_disable(c->parent); +} + +/* Get the clock rate */ +unsigned long clk_get_rate(struct clk *c) +{ + unsigned long rate; + + debug("%s: %s\n", __func__, c->name); + if (!c || !c->ops || !c->ops->get_rate) + return 0; + + rate = c->ops->get_rate(c); + debug("%s: rate = %ld\n", __func__, rate); + return rate; +} + +/* Set the clock rate */ +int clk_set_rate(struct clk *c, unsigned long rate) +{ + int ret; + + debug("%s: %s rate=%ld\n", __func__, c->name, rate); + if (!c || !c->ops || !c->ops->set_rate) + return -EINVAL; + + if (c->use_cnt) + return -EINVAL; + + ret = c->ops->set_rate(c, rate); + + return ret; +} + +/* Not required for this arch */ +/* +long clk_round_rate(struct clk *clk, unsigned long rate); +int clk_set_parent(struct clk *clk, struct clk *parent); +struct clk *clk_get_parent(struct clk *clk); +*/ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-core.h b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-core.h new file mode 100644 index 000000000..882a29779 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-core.h @@ -0,0 +1,495 @@ +/* + * Copyright 2013 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <linux/stddef.h> + +#ifdef CONFIG_CLK_DEBUG +#undef writel +#undef readl +static inline void writel(u32 val, void *addr) +{ + printf("Write [0x%p] = 0x%08x\n", addr, val); + *(u32 *)addr = val; +} + +static inline u32 readl(void *addr) +{ + u32 val = *(u32 *)addr; + printf("Read [0x%p] = 0x%08x\n", addr, val); + return val; +} +#endif + +struct clk; + +struct clk_lookup { + const char *dev_id; + const char *con_id; + struct clk *clk; +}; + +extern struct clk_lookup arch_clk_tbl[]; +extern unsigned int arch_clk_tbl_array_size; + +/** + * struct clk_ops - standard clock operations + * @enable: enable/disable clock, see clk_enable() and clk_disable() + * @set_rate: set the clock rate, see clk_set_rate(). + * @get_rate: get the clock rate, see clk_get_rate(). + * @round_rate: round a given clock rate, see clk_round_rate(). + * @set_parent: set the clock's parent, see clk_set_parent(). + * + * Group the common clock implementations together so that we + * don't have to keep setting the same fiels again. We leave + * enable in struct clk. + * + */ +struct clk_ops { + int (*enable) (struct clk *c, int enable); + int (*set_rate) (struct clk *c, unsigned long rate); + unsigned long (*get_rate) (struct clk *c); + unsigned long (*round_rate) (struct clk *c, unsigned long rate); + int (*set_parent) (struct clk *c, struct clk *parent); +}; + +struct clk { + struct clk *parent; + const char *name; + int use_cnt; + unsigned long rate; /* in HZ */ + + /* programmable divider. 0 means fixed ratio to parent clock */ + unsigned long div; + + struct clk_src *src; + struct clk_ops *ops; + + unsigned long ccu_clk_mgr_base; + int sel; +}; + +struct refclk *refclk_str_to_clk(const char *name); + +#define U8_MAX ((u8)~0U) +#define U32_MAX ((u32)~0U) +#define U64_MAX ((u64)~0U) + +/* The common clock framework uses u8 to represent a parent index */ +#define PARENT_COUNT_MAX ((u32)U8_MAX) + +#define BAD_CLK_INDEX U8_MAX /* Can't ever be valid */ +#define BAD_CLK_NAME ((const char *)-1) + +#define BAD_SCALED_DIV_VALUE U64_MAX + +/* + * Utility macros for object flag management. If possible, flags + * should be defined such that 0 is the desired default value. + */ +#define FLAG(type, flag) BCM_CLK_ ## type ## _FLAGS_ ## flag +#define FLAG_SET(obj, type, flag) ((obj)->flags |= FLAG(type, flag)) +#define FLAG_CLEAR(obj, type, flag) ((obj)->flags &= ~(FLAG(type, flag))) +#define FLAG_FLIP(obj, type, flag) ((obj)->flags ^= FLAG(type, flag)) +#define FLAG_TEST(obj, type, flag) (!!((obj)->flags & FLAG(type, flag))) + +/* Clock field state tests */ + +#define gate_exists(gate) FLAG_TEST(gate, GATE, EXISTS) +#define gate_is_enabled(gate) FLAG_TEST(gate, GATE, ENABLED) +#define gate_is_hw_controllable(gate) FLAG_TEST(gate, GATE, HW) +#define gate_is_sw_controllable(gate) FLAG_TEST(gate, GATE, SW) +#define gate_is_sw_managed(gate) FLAG_TEST(gate, GATE, SW_MANAGED) +#define gate_is_no_disable(gate) FLAG_TEST(gate, GATE, NO_DISABLE) + +#define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED) + +#define divider_exists(div) FLAG_TEST(div, DIV, EXISTS) +#define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED) +#define divider_has_fraction(div) (!divider_is_fixed(div) && \ + (div)->frac_width > 0) + +#define selector_exists(sel) ((sel)->width != 0) +#define trigger_exists(trig) FLAG_TEST(trig, TRIG, EXISTS) + +/* Clock type, used to tell common block what it's part of */ +enum bcm_clk_type { + bcm_clk_none, /* undefined clock type */ + bcm_clk_bus, + bcm_clk_core, + bcm_clk_peri +}; + +/* + * Gating control and status is managed by a 32-bit gate register. + * + * There are several types of gating available: + * - (no gate) + * A clock with no gate is assumed to be always enabled. + * - hardware-only gating (auto-gating) + * Enabling or disabling clocks with this type of gate is + * managed automatically by the hardware. Such clocks can be + * considered by the software to be enabled. The current status + * of auto-gated clocks can be read from the gate status bit. + * - software-only gating + * Auto-gating is not available for this type of clock. + * Instead, software manages whether it's enabled by setting or + * clearing the enable bit. The current gate status of a gate + * under software control can be read from the gate status bit. + * To ensure a change to the gating status is complete, the + * status bit can be polled to verify that the gate has entered + * the desired state. + * - selectable hardware or software gating + * Gating for this type of clock can be configured to be either + * under software or hardware control. Which type is in use is + * determined by the hw_sw_sel bit of the gate register. + */ +struct bcm_clk_gate { + u32 offset; /* gate register offset */ + u32 status_bit; /* 0: gate is disabled; 0: gatge is enabled */ + u32 en_bit; /* 0: disable; 1: enable */ + u32 hw_sw_sel_bit; /* 0: hardware gating; 1: software gating */ + u32 flags; /* BCM_CLK_GATE_FLAGS_* below */ +}; + +/* + * Gate flags: + * HW means this gate can be auto-gated + * SW means the state of this gate can be software controlled + * NO_DISABLE means this gate is (only) enabled if under software control + * SW_MANAGED means the status of this gate is under software control + * ENABLED means this software-managed gate is *supposed* to be enabled + */ +#define BCM_CLK_GATE_FLAGS_EXISTS ((u32)1 << 0) /* Gate is valid */ +#define BCM_CLK_GATE_FLAGS_HW ((u32)1 << 1) /* Can auto-gate */ +#define BCM_CLK_GATE_FLAGS_SW ((u32)1 << 2) /* Software control */ +#define BCM_CLK_GATE_FLAGS_NO_DISABLE ((u32)1 << 3) /* HW or enabled */ +#define BCM_CLK_GATE_FLAGS_SW_MANAGED ((u32)1 << 4) /* SW now in control */ +#define BCM_CLK_GATE_FLAGS_ENABLED ((u32)1 << 5) /* If SW_MANAGED */ + +/* + * Gate initialization macros. + * + * Any gate initially under software control will be enabled. + */ + +/* A hardware/software gate initially under software control */ +#define HW_SW_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .hw_sw_sel_bit = (_hw_sw_sel_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ + FLAG(GATE, SW_MANAGED)|FLAG(GATE, ENABLED)| \ + FLAG(GATE, EXISTS), \ + } + +/* A hardware/software gate initially under hardware control */ +#define HW_SW_GATE_AUTO(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .hw_sw_sel_bit = (_hw_sw_sel_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ + FLAG(GATE, EXISTS), \ + } + +/* A hardware-or-enabled gate (enabled if not under hardware control) */ +#define HW_ENABLE_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .hw_sw_sel_bit = (_hw_sw_sel_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ + FLAG(GATE, NO_DISABLE)|FLAG(GATE, EXISTS), \ + } + +/* A software-only gate */ +#define SW_ONLY_GATE(_offset, _status_bit, _en_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .flags = FLAG(GATE, SW)|FLAG(GATE, SW_MANAGED)| \ + FLAG(GATE, ENABLED)|FLAG(GATE, EXISTS), \ + } + +/* A hardware-only gate */ +#define HW_ONLY_GATE(_offset, _status_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \ + } + +/* + * Each clock can have zero, one, or two dividers which change the + * output rate of the clock. Each divider can be either fixed or + * variable. If there are two dividers, they are the "pre-divider" + * and the "regular" or "downstream" divider. If there is only one, + * there is no pre-divider. + * + * A fixed divider is any non-zero (positive) value, and it + * indicates how the input rate is affected by the divider. + * + * The value of a variable divider is maintained in a sub-field of a + * 32-bit divider register. The position of the field in the + * register is defined by its offset and width. The value recorded + * in this field is always 1 less than the value it represents. + * + * In addition, a variable divider can indicate that some subset + * of its bits represent a "fractional" part of the divider. Such + * bits comprise the low-order portion of the divider field, and can + * be viewed as representing the portion of the divider that lies to + * the right of the decimal point. Most variable dividers have zero + * fractional bits. Variable dividers with non-zero fraction width + * still record a value 1 less than the value they represent; the + * added 1 does *not* affect the low-order bit in this case, it + * affects the bits above the fractional part only. (Often in this + * code a divider field value is distinguished from the value it + * represents by referring to the latter as a "divisor".) + * + * In order to avoid dealing with fractions, divider arithmetic is + * performed using "scaled" values. A scaled value is one that's + * been left-shifted by the fractional width of a divider. Dividing + * a scaled value by a scaled divisor produces the desired quotient + * without loss of precision and without any other special handling + * for fractions. + * + * The recorded value of a variable divider can be modified. To + * modify either divider (or both), a clock must be enabled (i.e., + * using its gate). In addition, a trigger register (described + * below) must be used to commit the change, and polled to verify + * the change is complete. + */ +struct bcm_clk_div { + union { + struct { /* variable divider */ + u32 offset; /* divider register offset */ + u32 shift; /* field shift */ + u32 width; /* field width */ + u32 frac_width; /* field fraction width */ + + u64 scaled_div; /* scaled divider value */ + }; + u32 fixed; /* non-zero fixed divider value */ + }; + u32 flags; /* BCM_CLK_DIV_FLAGS_* below */ +}; + +/* + * Divider flags: + * EXISTS means this divider exists + * FIXED means it is a fixed-rate divider + */ +#define BCM_CLK_DIV_FLAGS_EXISTS ((u32)1 << 0) /* Divider is valid */ +#define BCM_CLK_DIV_FLAGS_FIXED ((u32)1 << 1) /* Fixed-value */ + +/* Divider initialization macros */ + +/* A fixed (non-zero) divider */ +#define FIXED_DIVIDER(_value) \ + { \ + .fixed = (_value), \ + .flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED), \ + } + +/* A divider with an integral divisor */ +#define DIVIDER(_offset, _shift, _width) \ + { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .scaled_div = BAD_SCALED_DIV_VALUE, \ + .flags = FLAG(DIV, EXISTS), \ + } + +/* A divider whose divisor has an integer and fractional part */ +#define FRAC_DIVIDER(_offset, _shift, _width, _frac_width) \ + { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .frac_width = (_frac_width), \ + .scaled_div = BAD_SCALED_DIV_VALUE, \ + .flags = FLAG(DIV, EXISTS), \ + } + +/* + * Clocks may have multiple "parent" clocks. If there is more than + * one, a selector must be specified to define which of the parent + * clocks is currently in use. The selected clock is indicated in a + * sub-field of a 32-bit selector register. The range of + * representable selector values typically exceeds the number of + * available parent clocks. Occasionally the reset value of a + * selector field is explicitly set to a (specific) value that does + * not correspond to a defined input clock. + * + * We register all known parent clocks with the common clock code + * using a packed array (i.e., no empty slots) of (parent) clock + * names, and refer to them later using indexes into that array. + * We maintain an array of selector values indexed by common clock + * index values in order to map between these common clock indexes + * and the selector values used by the hardware. + * + * Like dividers, a selector can be modified, but to do so a clock + * must be enabled, and a trigger must be used to commit the change. + */ +struct bcm_clk_sel { + u32 offset; /* selector register offset */ + u32 shift; /* field shift */ + u32 width; /* field width */ + + u32 parent_count; /* number of entries in parent_sel[] */ + u32 *parent_sel; /* array of parent selector values */ + u8 clk_index; /* current selected index in parent_sel[] */ +}; + +/* Selector initialization macro */ +#define SELECTOR(_offset, _shift, _width) \ + { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .clk_index = BAD_CLK_INDEX, \ + } + +/* + * Making changes to a variable divider or a selector for a clock + * requires the use of a trigger. A trigger is defined by a single + * bit within a register. To signal a change, a 1 is written into + * that bit. To determine when the change has been completed, that + * trigger bit is polled; the read value will be 1 while the change + * is in progress, and 0 when it is complete. + * + * Occasionally a clock will have more than one trigger. In this + * case, the "pre-trigger" will be used when changing a clock's + * selector and/or its pre-divider. + */ +struct bcm_clk_trig { + u32 offset; /* trigger register offset */ + u32 bit; /* trigger bit */ + u32 flags; /* BCM_CLK_TRIG_FLAGS_* below */ +}; + +/* + * Trigger flags: + * EXISTS means this trigger exists + */ +#define BCM_CLK_TRIG_FLAGS_EXISTS ((u32)1 << 0) /* Trigger is valid */ + +/* Trigger initialization macro */ +#define TRIGGER(_offset, _bit) \ + { \ + .offset = (_offset), \ + .bit = (_bit), \ + .flags = FLAG(TRIG, EXISTS), \ + } + +struct bus_clk_data { + struct bcm_clk_gate gate; +}; + +struct core_clk_data { + struct bcm_clk_gate gate; +}; + +struct peri_clk_data { + struct bcm_clk_gate gate; + struct bcm_clk_trig pre_trig; + struct bcm_clk_div pre_div; + struct bcm_clk_trig trig; + struct bcm_clk_div div; + struct bcm_clk_sel sel; + const char *clocks[]; /* must be last; use CLOCKS() to declare */ +}; +#define CLOCKS(...) { __VA_ARGS__, NULL, } +#define NO_CLOCKS { NULL, } /* Must use of no parent clocks */ + +struct refclk { + struct clk clk; +}; + +struct peri_clock { + struct clk clk; + struct peri_clk_data *data; +}; + +struct ccu_clock { + struct clk clk; + + int num_policy_masks; + unsigned long policy_freq_offset; + int freq_bit_shift; /* 8 for most CCUs */ + unsigned long policy_ctl_offset; + unsigned long policy0_mask_offset; + unsigned long policy1_mask_offset; + unsigned long policy2_mask_offset; + unsigned long policy3_mask_offset; + unsigned long policy0_mask2_offset; + unsigned long policy1_mask2_offset; + unsigned long policy2_mask2_offset; + unsigned long policy3_mask2_offset; + unsigned long lvm_en_offset; + + int freq_id; + unsigned long *freq_tbl; +}; + +struct bus_clock { + struct clk clk; + struct bus_clk_data *data; + unsigned long *freq_tbl; +}; + +struct ref_clock { + struct clk clk; +}; + +static inline int is_same_clock(struct clk *a, struct clk *b) +{ + return (a == b); +} + +#define to_clk(p) (&((p)->clk)) +#define name_to_clk(name) (&((name##_clk).clk)) +/* declare a struct clk_lookup */ +#define CLK_LK(name) \ +{.con_id = __stringify(name##_clk), .clk = name_to_clk(name),} + +static inline struct refclk *to_refclk(struct clk *clock) +{ + return container_of(clock, struct refclk, clk); +} + +static inline struct peri_clock *to_peri_clk(struct clk *clock) +{ + return container_of(clock, struct peri_clock, clk); +} + +static inline struct ccu_clock *to_ccu_clk(struct clk *clock) +{ + return container_of(clock, struct ccu_clock, clk); +} + +static inline struct bus_clock *to_bus_clk(struct clk *clock) +{ + return container_of(clock, struct bus_clock, clk); +} + +static inline struct ref_clock *to_ref_clk(struct clk *clock) +{ + return container_of(clock, struct ref_clock, clk); +} + +extern struct clk_ops peri_clk_ops; +extern struct clk_ops ccu_clk_ops; +extern struct clk_ops bus_clk_ops; +extern struct clk_ops ref_clk_ops; + +extern int clk_get_and_enable(char *clkstr); diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c new file mode 100644 index 000000000..49badcbaa --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c @@ -0,0 +1,73 @@ +/* + * Copyright 2013 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +/* Enable appropriate clocks for an SDIO port */ +int clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep) +{ + int ret; + struct clk *c; + + char *clkstr; + char *slpstr; + char *ahbstr; + + switch ((u32) base) { + case CONFIG_SYS_SDIO_BASE0: + clkstr = CONFIG_SYS_SDIO0 "_clk"; + ahbstr = CONFIG_SYS_SDIO0 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO0 "_sleep_clk"; + break; + case CONFIG_SYS_SDIO_BASE1: + clkstr = CONFIG_SYS_SDIO1 "_clk"; + ahbstr = CONFIG_SYS_SDIO1 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO1 "_sleep_clk"; + break; + case CONFIG_SYS_SDIO_BASE2: + clkstr = CONFIG_SYS_SDIO2 "_clk"; + ahbstr = CONFIG_SYS_SDIO2 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO2 "_sleep_clk"; + break; + case CONFIG_SYS_SDIO_BASE3: + clkstr = CONFIG_SYS_SDIO3 "_clk"; + ahbstr = CONFIG_SYS_SDIO3 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO3 "_sleep_clk"; + break; + default: + printf("%s: base 0x%p not found\n", __func__, base); + return -EINVAL; + } + + ret = clk_get_and_enable(ahbstr); + if (ret) + return ret; + + ret = clk_get_and_enable(slpstr); + if (ret) + return ret; + + c = clk_get(clkstr); + if (c) { + ret = clk_set_rate(c, rate); + if (ret) + return ret; + + ret = clk_enable(c); + if (ret) + return ret; + } else { + printf("%s: Couldn't find %s\n", __func__, clkstr); + return -EINVAL; + } + *actual_ratep = rate; + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/reset.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/reset.c new file mode 100644 index 000000000..3beb0ed9c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/bcm281xx/reset.c @@ -0,0 +1,27 @@ +/* + * Copyright 2013 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/sysmap.h> + +#define EN_MASK 0x08000000 /* Enable timer */ +#define SRSTEN_MASK 0x04000000 /* Enable soft reset */ +#define CLKS_SHIFT 20 /* Clock period shift */ +#define LD_SHIFT 0 /* Reload value shift */ + +void reset_cpu(ulong ignored) +{ + /* + * Set WD enable, RST enable, + * 3.9 msec clock period (8), reload value (8*3.9ms) + */ + u32 reg = EN_MASK + SRSTEN_MASK + (8 << CLKS_SHIFT) + (8 << LD_SHIFT); + writel(reg, SECWD2_BASE_ADDR); + + while (1) + ; /* loop forever till reset */ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/cache_v7.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/cache_v7.c new file mode 100644 index 000000000..bc5fc423d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/cache_v7.c @@ -0,0 +1,394 @@ +/* + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <linux/types.h> +#include <common.h> +#include <asm/armv7.h> +#include <asm/utils.h> + +#define ARMV7_DCACHE_INVAL_ALL 1 +#define ARMV7_DCACHE_CLEAN_INVAL_ALL 2 +#define ARMV7_DCACHE_INVAL_RANGE 3 +#define ARMV7_DCACHE_CLEAN_INVAL_RANGE 4 + +#ifndef CONFIG_SYS_DCACHE_OFF +/* + * Write the level and type you want to Cache Size Selection Register(CSSELR) + * to get size details from Current Cache Size ID Register(CCSIDR) + */ +static void set_csselr(u32 level, u32 type) +{ u32 csselr = level << 1 | type; + + /* Write to Cache Size Selection Register(CSSELR) */ + asm volatile ("mcr p15, 2, %0, c0, c0, 0" : : "r" (csselr)); +} + +static u32 get_ccsidr(void) +{ + u32 ccsidr; + + /* Read current CP15 Cache Size ID Register */ + asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr)); + return ccsidr; +} + +static u32 get_clidr(void) +{ + u32 clidr; + + /* Read current CP15 Cache Level ID Register */ + asm volatile ("mrc p15,1,%0,c0,c0,1" : "=r" (clidr)); + return clidr; +} + +static void v7_inval_dcache_level_setway(u32 level, u32 num_sets, + u32 num_ways, u32 way_shift, + u32 log2_line_len) +{ + int way, set, setway; + + /* + * For optimal assembly code: + * a. count down + * b. have bigger loop inside + */ + for (way = num_ways - 1; way >= 0 ; way--) { + for (set = num_sets - 1; set >= 0; set--) { + setway = (level << 1) | (set << log2_line_len) | + (way << way_shift); + /* Invalidate data/unified cache line by set/way */ + asm volatile (" mcr p15, 0, %0, c7, c6, 2" + : : "r" (setway)); + } + } + /* DSB to make sure the operation is complete */ + CP15DSB; +} + +static void v7_clean_inval_dcache_level_setway(u32 level, u32 num_sets, + u32 num_ways, u32 way_shift, + u32 log2_line_len) +{ + int way, set, setway; + + /* + * For optimal assembly code: + * a. count down + * b. have bigger loop inside + */ + for (way = num_ways - 1; way >= 0 ; way--) { + for (set = num_sets - 1; set >= 0; set--) { + setway = (level << 1) | (set << log2_line_len) | + (way << way_shift); + /* + * Clean & Invalidate data/unified + * cache line by set/way + */ + asm volatile (" mcr p15, 0, %0, c7, c14, 2" + : : "r" (setway)); + } + } + /* DSB to make sure the operation is complete */ + CP15DSB; +} + +static void v7_maint_dcache_level_setway(u32 level, u32 operation) +{ + u32 ccsidr; + u32 num_sets, num_ways, log2_line_len, log2_num_ways; + u32 way_shift; + + set_csselr(level, ARMV7_CSSELR_IND_DATA_UNIFIED); + + ccsidr = get_ccsidr(); + + log2_line_len = ((ccsidr & CCSIDR_LINE_SIZE_MASK) >> + CCSIDR_LINE_SIZE_OFFSET) + 2; + /* Converting from words to bytes */ + log2_line_len += 2; + + num_ways = ((ccsidr & CCSIDR_ASSOCIATIVITY_MASK) >> + CCSIDR_ASSOCIATIVITY_OFFSET) + 1; + num_sets = ((ccsidr & CCSIDR_NUM_SETS_MASK) >> + CCSIDR_NUM_SETS_OFFSET) + 1; + /* + * According to ARMv7 ARM number of sets and number of ways need + * not be a power of 2 + */ + log2_num_ways = log_2_n_round_up(num_ways); + + way_shift = (32 - log2_num_ways); + if (operation == ARMV7_DCACHE_INVAL_ALL) { + v7_inval_dcache_level_setway(level, num_sets, num_ways, + way_shift, log2_line_len); + } else if (operation == ARMV7_DCACHE_CLEAN_INVAL_ALL) { + v7_clean_inval_dcache_level_setway(level, num_sets, num_ways, + way_shift, log2_line_len); + } +} + +static void v7_maint_dcache_all(u32 operation) +{ + u32 level, cache_type, level_start_bit = 0; + + u32 clidr = get_clidr(); + + for (level = 0; level < 7; level++) { + cache_type = (clidr >> level_start_bit) & 0x7; + if ((cache_type == ARMV7_CLIDR_CTYPE_DATA_ONLY) || + (cache_type == ARMV7_CLIDR_CTYPE_INSTRUCTION_DATA) || + (cache_type == ARMV7_CLIDR_CTYPE_UNIFIED)) + v7_maint_dcache_level_setway(level, operation); + level_start_bit += 3; + } +} + +static void v7_dcache_clean_inval_range(u32 start, + u32 stop, u32 line_len) +{ + u32 mva; + + /* Align start to cache line boundary */ + start &= ~(line_len - 1); + for (mva = start; mva < stop; mva = mva + line_len) { + /* DCCIMVAC - Clean & Invalidate data cache by MVA to PoC */ + asm volatile ("mcr p15, 0, %0, c7, c14, 1" : : "r" (mva)); + } +} + +static void v7_dcache_inval_range(u32 start, u32 stop, u32 line_len) +{ + u32 mva; + + /* + * If start address is not aligned to cache-line do not + * invalidate the first cache-line + */ + if (start & (line_len - 1)) { + printf("ERROR: %s - start address is not aligned - 0x%08x\n", + __func__, start); + /* move to next cache line */ + start = (start + line_len - 1) & ~(line_len - 1); + } + + /* + * If stop address is not aligned to cache-line do not + * invalidate the last cache-line + */ + if (stop & (line_len - 1)) { + printf("ERROR: %s - stop address is not aligned - 0x%08x\n", + __func__, stop); + /* align to the beginning of this cache line */ + stop &= ~(line_len - 1); + } + + for (mva = start; mva < stop; mva = mva + line_len) { + /* DCIMVAC - Invalidate data cache by MVA to PoC */ + asm volatile ("mcr p15, 0, %0, c7, c6, 1" : : "r" (mva)); + } +} + +static void v7_dcache_maint_range(u32 start, u32 stop, u32 range_op) +{ + u32 line_len, ccsidr; + + ccsidr = get_ccsidr(); + line_len = ((ccsidr & CCSIDR_LINE_SIZE_MASK) >> + CCSIDR_LINE_SIZE_OFFSET) + 2; + /* Converting from words to bytes */ + line_len += 2; + /* converting from log2(linelen) to linelen */ + line_len = 1 << line_len; + + switch (range_op) { + case ARMV7_DCACHE_CLEAN_INVAL_RANGE: + v7_dcache_clean_inval_range(start, stop, line_len); + break; + case ARMV7_DCACHE_INVAL_RANGE: + v7_dcache_inval_range(start, stop, line_len); + break; + } + + /* DSB to make sure the operation is complete */ + CP15DSB; +} + +/* Invalidate TLB */ +static void v7_inval_tlb(void) +{ + /* Invalidate entire unified TLB */ + asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0)); + /* Invalidate entire data TLB */ + asm volatile ("mcr p15, 0, %0, c8, c6, 0" : : "r" (0)); + /* Invalidate entire instruction TLB */ + asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0)); + /* Full system DSB - make sure that the invalidation is complete */ + CP15DSB; + /* Full system ISB - make sure the instruction stream sees it */ + CP15ISB; +} + +void invalidate_dcache_all(void) +{ + v7_maint_dcache_all(ARMV7_DCACHE_INVAL_ALL); + + v7_outer_cache_inval_all(); +} + +/* + * Performs a clean & invalidation of the entire data cache + * at all levels + */ +void flush_dcache_all(void) +{ + v7_maint_dcache_all(ARMV7_DCACHE_CLEAN_INVAL_ALL); + + v7_outer_cache_flush_all(); +} + +/* + * Invalidates range in all levels of D-cache/unified cache used: + * Affects the range [start, stop - 1] + */ +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + + v7_dcache_maint_range(start, stop, ARMV7_DCACHE_INVAL_RANGE); + + v7_outer_cache_inval_range(start, stop); +} + +/* + * Flush range(clean & invalidate) from all levels of D-cache/unified + * cache used: + * Affects the range [start, stop - 1] + */ +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + v7_dcache_maint_range(start, stop, ARMV7_DCACHE_CLEAN_INVAL_RANGE); + + v7_outer_cache_flush_range(start, stop); +} + +void arm_init_before_mmu(void) +{ + v7_outer_cache_enable(); + invalidate_dcache_all(); + v7_inval_tlb(); +} + +void mmu_page_table_flush(unsigned long start, unsigned long stop) +{ + flush_dcache_range(start, stop); + v7_inval_tlb(); +} + +/* + * Flush range from all levels of d-cache/unified-cache used: + * Affects the range [start, start + size - 1] + */ +void flush_cache(unsigned long start, unsigned long size) +{ + flush_dcache_range(start, start + size); +} +#else /* #ifndef CONFIG_SYS_DCACHE_OFF */ +void invalidate_dcache_all(void) +{ +} + +void flush_dcache_all(void) +{ +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void arm_init_before_mmu(void) +{ +} + +void flush_cache(unsigned long start, unsigned long size) +{ +} + +void mmu_page_table_flush(unsigned long start, unsigned long stop) +{ +} + +void arm_init_domains(void) +{ +} +#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ + +#ifndef CONFIG_SYS_ICACHE_OFF +/* Invalidate entire I-cache and branch predictor array */ +void invalidate_icache_all(void) +{ + /* + * Invalidate all instruction caches to PoU. + * Also flushes branch target cache. + */ + asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); + + /* Invalidate entire branch predictor array */ + asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (0)); + + /* Full system DSB - make sure that the invalidation is complete */ + CP15DSB; + + /* ISB - make sure the instruction stream sees it */ + CP15ISB; +} +#else +void invalidate_icache_all(void) +{ +} +#endif + +/* + * Stub implementations for outer cache operations + */ +void __v7_outer_cache_enable(void) +{ +} +void v7_outer_cache_enable(void) + __attribute__((weak, alias("__v7_outer_cache_enable"))); + +void __v7_outer_cache_disable(void) +{ +} +void v7_outer_cache_disable(void) + __attribute__((weak, alias("__v7_outer_cache_disable"))); + +void __v7_outer_cache_flush_all(void) +{ +} +void v7_outer_cache_flush_all(void) + __attribute__((weak, alias("__v7_outer_cache_flush_all"))); + +void __v7_outer_cache_inval_all(void) +{ +} +void v7_outer_cache_inval_all(void) + __attribute__((weak, alias("__v7_outer_cache_inval_all"))); + +void __v7_outer_cache_flush_range(u32 start, u32 end) +{ +} +void v7_outer_cache_flush_range(u32 start, u32 end) + __attribute__((weak, alias("__v7_outer_cache_flush_range"))); + +void __v7_outer_cache_inval_range(u32 start, u32 end) +{ +} +void v7_outer_cache_inval_range(u32 start, u32 end) + __attribute__((weak, alias("__v7_outer_cache_inval_range"))); diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/config.mk b/qemu/roms/u-boot/arch/arm/cpu/armv7/config.mk new file mode 100644 index 000000000..6c82c3b53 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/config.mk @@ -0,0 +1,18 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# If armv7-a is not supported by GCC fall-back to armv5, which is +# supported by more tool-chains +PF_CPPFLAGS_ARMV7 := $(call cc-option, -march=armv7-a, -march=armv5) +PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV7) + +# On supported platforms we set the bit which causes us to trap on unaligned +# memory access. This is the opposite of what the compiler expects to be +# the default so we must pass in -mno-unaligned-access so that it is aware +# of our decision. +PF_NO_UNALIGNED := $(call cc-option, -mno-unaligned-access,) +PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/cpu.c new file mode 100644 index 000000000..01cdb7ee7 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/cpu.c @@ -0,0 +1,70 @@ +/* + * (C) Copyright 2008 Texas Insturments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> +#include <asm/cache.h> +#include <asm/armv7.h> +#include <linux/compiler.h> + +void __weak cpu_cache_initialization(void){} + +int cleanup_before_linux(void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ +#ifndef CONFIG_SPL_BUILD + disable_interrupts(); +#endif + + /* + * Turn off I-cache and invalidate it + */ + icache_disable(); + invalidate_icache_all(); + + /* + * turn off D-cache + * dcache_disable() in turn flushes the d-cache and disables MMU + */ + dcache_disable(); + v7_outer_cache_disable(); + + /* + * After D-cache is flushed and before it is disabled there may + * be some new valid entries brought into the cache. We are sure + * that these lines are not dirty and will not affect our execution. + * (because unwinding the call-stack and setting a bit in CP15 SCTRL + * is all we did during this. We have not pushed anything on to the + * stack. Neither have we affected any static data) + * So just invalidate the entire d-cache again to avoid coherency + * problems for kernel + */ + invalidate_dcache_all(); + + /* + * Some CPU need more cache attention before starting the kernel. + */ + cpu_cache_initialization(); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/Makefile new file mode 100644 index 000000000..e207bd6af --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2009 Samsung Electronics +# Minkyu Kang <mk7.kang@samsung.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += clock.o power.o soc.o system.o pinmux.o tzpc.o + +ifdef CONFIG_SPL_BUILD +obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o +obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o +obj-$(CONFIG_EXYNOS4210)+= dmc_init_exynos4.o clock_init_exynos4.o +obj-y += spl_boot.o +obj-y += lowlevel_init.o +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock.c new file mode 100644 index 000000000..1fea4d666 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock.c @@ -0,0 +1,1678 @@ +/* + * Copyright (C) 2010 Samsung Electronics + * Minkyu Kang <mk7.kang@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/clk.h> +#include <asm/arch/periph.h> + +#define PLL_DIV_1024 1024 +#define PLL_DIV_65535 65535 +#define PLL_DIV_65536 65536 + +/* * + * This structure is to store the src bit, div bit and prediv bit + * positions of the peripheral clocks of the src and div registers + */ +struct clk_bit_info { + int8_t src_bit; + int8_t div_bit; + int8_t prediv_bit; +}; + +/* src_bit div_bit prediv_bit */ +static struct clk_bit_info clk_bit_info[] = { + {0, 0, -1}, + {4, 4, -1}, + {8, 8, -1}, + {12, 12, -1}, + {0, 0, 8}, + {4, 16, 24}, + {8, 0, 8}, + {12, 16, 24}, + {-1, -1, -1}, + {16, 0, 8}, + {20, 16, 24}, + {24, 0, 8}, + {0, 0, 4}, + {4, 12, 16}, + {-1, -1, -1}, + {-1, -1, -1}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {24, 0, -1}, + {24, 0, -1}, + {24, 0, -1}, + {24, 0, -1}, + {24, 0, -1}, +}; + +/* Epll Clock division values to achive different frequency output */ +static struct set_epll_con_val exynos5_epll_div[] = { + { 192000000, 0, 48, 3, 1, 0 }, + { 180000000, 0, 45, 3, 1, 0 }, + { 73728000, 1, 73, 3, 3, 47710 }, + { 67737600, 1, 90, 4, 3, 20762 }, + { 49152000, 0, 49, 3, 3, 9961 }, + { 45158400, 0, 45, 3, 3, 10381 }, + { 180633600, 0, 45, 3, 1, 10381 } +}; + +/* exynos: return pll clock frequency */ +static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k) +{ + unsigned long m, p, s = 0, mask, fout; + unsigned int div; + unsigned int freq; + /* + * APLL_CON: MIDV [25:16] + * MPLL_CON: MIDV [25:16] + * EPLL_CON: MIDV [24:16] + * VPLL_CON: MIDV [24:16] + * BPLL_CON: MIDV [25:16]: Exynos5 + */ + if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL) + mask = 0x3ff; + else + mask = 0x1ff; + + m = (r >> 16) & mask; + + /* PDIV [13:8] */ + p = (r >> 8) & 0x3f; + /* SDIV [2:0] */ + s = r & 0x7; + + freq = CONFIG_SYS_CLK_FREQ; + + if (pllreg == EPLL || pllreg == RPLL) { + k = k & 0xffff; + /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */ + fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s))); + } else if (pllreg == VPLL) { + k = k & 0xfff; + + /* + * Exynos4210 + * FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) + * + * Exynos4412 + * FOUT = (MDIV + K / 65535) * FIN / (PDIV * 2^SDIV) + * + * Exynos5250 + * FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) + */ + if (proid_is_exynos4210()) + div = PLL_DIV_1024; + else if (proid_is_exynos4412()) + div = PLL_DIV_65535; + else if (proid_is_exynos5250() || proid_is_exynos5420()) + div = PLL_DIV_65536; + else + return 0; + + fout = (m + k / div) * (freq / (p * (1 << s))); + } else { + /* + * Exynos4412 / Exynos5250 + * FOUT = MDIV * FIN / (PDIV * 2^SDIV) + * + * Exynos4210 + * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1)) + */ + if (proid_is_exynos4210()) + fout = m * (freq / (p * (1 << (s - 1)))); + else + fout = m * (freq / (p * (1 << s))); + } + return fout; +} + +/* exynos4: return pll clock frequency */ +static unsigned long exynos4_get_pll_clk(int pllreg) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + unsigned long r, k = 0; + + switch (pllreg) { + case APLL: + r = readl(&clk->apll_con0); + break; + case MPLL: + r = readl(&clk->mpll_con0); + break; + case EPLL: + r = readl(&clk->epll_con0); + k = readl(&clk->epll_con1); + break; + case VPLL: + r = readl(&clk->vpll_con0); + k = readl(&clk->vpll_con1); + break; + default: + printf("Unsupported PLL (%d)\n", pllreg); + return 0; + } + + return exynos_get_pll_clk(pllreg, r, k); +} + +/* exynos4x12: return pll clock frequency */ +static unsigned long exynos4x12_get_pll_clk(int pllreg) +{ + struct exynos4x12_clock *clk = + (struct exynos4x12_clock *)samsung_get_base_clock(); + unsigned long r, k = 0; + + switch (pllreg) { + case APLL: + r = readl(&clk->apll_con0); + break; + case MPLL: + r = readl(&clk->mpll_con0); + break; + case EPLL: + r = readl(&clk->epll_con0); + k = readl(&clk->epll_con1); + break; + case VPLL: + r = readl(&clk->vpll_con0); + k = readl(&clk->vpll_con1); + break; + default: + printf("Unsupported PLL (%d)\n", pllreg); + return 0; + } + + return exynos_get_pll_clk(pllreg, r, k); +} + +/* exynos5: return pll clock frequency */ +static unsigned long exynos5_get_pll_clk(int pllreg) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned long r, k = 0, fout; + unsigned int pll_div2_sel, fout_sel; + + switch (pllreg) { + case APLL: + r = readl(&clk->apll_con0); + break; + case MPLL: + r = readl(&clk->mpll_con0); + break; + case EPLL: + r = readl(&clk->epll_con0); + k = readl(&clk->epll_con1); + break; + case VPLL: + r = readl(&clk->vpll_con0); + k = readl(&clk->vpll_con1); + break; + case BPLL: + r = readl(&clk->bpll_con0); + break; + default: + printf("Unsupported PLL (%d)\n", pllreg); + return 0; + } + + fout = exynos_get_pll_clk(pllreg, r, k); + + /* According to the user manual, in EVT1 MPLL and BPLL always gives + * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/ + if (pllreg == MPLL || pllreg == BPLL) { + pll_div2_sel = readl(&clk->pll_div2_sel); + + switch (pllreg) { + case MPLL: + fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT) + & MPLL_FOUT_SEL_MASK; + break; + case BPLL: + fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT) + & BPLL_FOUT_SEL_MASK; + break; + default: + fout_sel = -1; + break; + } + + if (fout_sel == 0) + fout /= 2; + } + + return fout; +} + +static unsigned long exynos5_get_periph_rate(int peripheral) +{ + struct clk_bit_info *bit_info = &clk_bit_info[peripheral]; + unsigned long sclk, sub_clk; + unsigned int src, div, sub_div; + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case PERIPH_ID_UART3: + src = readl(&clk->src_peric0); + div = readl(&clk->div_peric0); + break; + case PERIPH_ID_PWM0: + case PERIPH_ID_PWM1: + case PERIPH_ID_PWM2: + case PERIPH_ID_PWM3: + case PERIPH_ID_PWM4: + src = readl(&clk->src_peric0); + div = readl(&clk->div_peric3); + break; + case PERIPH_ID_I2S0: + src = readl(&clk->src_mau); + div = readl(&clk->div_mau); + case PERIPH_ID_SPI0: + case PERIPH_ID_SPI1: + src = readl(&clk->src_peric1); + div = readl(&clk->div_peric1); + break; + case PERIPH_ID_SPI2: + src = readl(&clk->src_peric1); + div = readl(&clk->div_peric2); + break; + case PERIPH_ID_SPI3: + case PERIPH_ID_SPI4: + src = readl(&clk->sclk_src_isp); + div = readl(&clk->sclk_div_isp); + break; + case PERIPH_ID_SDMMC0: + case PERIPH_ID_SDMMC1: + case PERIPH_ID_SDMMC2: + case PERIPH_ID_SDMMC3: + src = readl(&clk->src_fsys); + div = readl(&clk->div_fsys1); + break; + case PERIPH_ID_I2C0: + case PERIPH_ID_I2C1: + case PERIPH_ID_I2C2: + case PERIPH_ID_I2C3: + case PERIPH_ID_I2C4: + case PERIPH_ID_I2C5: + case PERIPH_ID_I2C6: + case PERIPH_ID_I2C7: + sclk = exynos5_get_pll_clk(MPLL); + sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit) + & 0x7) + 1; + div = ((readl(&clk->div_top0) >> bit_info->prediv_bit) + & 0x7) + 1; + return (sclk / sub_div) / div; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + }; + + src = (src >> bit_info->src_bit) & 0xf; + + switch (src) { + case EXYNOS_SRC_MPLL: + sclk = exynos5_get_pll_clk(MPLL); + break; + case EXYNOS_SRC_EPLL: + sclk = exynos5_get_pll_clk(EPLL); + break; + case EXYNOS_SRC_VPLL: + sclk = exynos5_get_pll_clk(VPLL); + break; + default: + return 0; + } + + /* Ratio clock division for this peripheral */ + sub_div = (div >> bit_info->div_bit) & 0xf; + sub_clk = sclk / (sub_div + 1); + + /* Pre-ratio clock division for SDMMC0 and 2 */ + if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) { + div = (div >> bit_info->prediv_bit) & 0xff; + return sub_clk / (div + 1); + } + + return sub_clk; +} + +unsigned long clock_get_periph_rate(int peripheral) +{ + if (cpu_is_exynos5()) + return exynos5_get_periph_rate(peripheral); + else + return 0; +} + +/* exynos5420: return pll clock frequency */ +static unsigned long exynos5420_get_pll_clk(int pllreg) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long r, k = 0; + + switch (pllreg) { + case APLL: + r = readl(&clk->apll_con0); + break; + case MPLL: + r = readl(&clk->mpll_con0); + break; + case EPLL: + r = readl(&clk->epll_con0); + k = readl(&clk->epll_con1); + break; + case VPLL: + r = readl(&clk->vpll_con0); + k = readl(&clk->vpll_con1); + break; + case BPLL: + r = readl(&clk->bpll_con0); + break; + case RPLL: + r = readl(&clk->rpll_con0); + k = readl(&clk->rpll_con1); + break; + default: + printf("Unsupported PLL (%d)\n", pllreg); + return 0; + } + + return exynos_get_pll_clk(pllreg, r, k); +} + +/* exynos4: return ARM clock frequency */ +static unsigned long exynos4_get_arm_clk(void) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + unsigned long div; + unsigned long armclk; + unsigned int core_ratio; + unsigned int core2_ratio; + + div = readl(&clk->div_cpu0); + + /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */ + core_ratio = (div >> 0) & 0x7; + core2_ratio = (div >> 28) & 0x7; + + armclk = get_pll_clk(APLL) / (core_ratio + 1); + armclk /= (core2_ratio + 1); + + return armclk; +} + +/* exynos4x12: return ARM clock frequency */ +static unsigned long exynos4x12_get_arm_clk(void) +{ + struct exynos4x12_clock *clk = + (struct exynos4x12_clock *)samsung_get_base_clock(); + unsigned long div; + unsigned long armclk; + unsigned int core_ratio; + unsigned int core2_ratio; + + div = readl(&clk->div_cpu0); + + /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */ + core_ratio = (div >> 0) & 0x7; + core2_ratio = (div >> 28) & 0x7; + + armclk = get_pll_clk(APLL) / (core_ratio + 1); + armclk /= (core2_ratio + 1); + + return armclk; +} + +/* exynos5: return ARM clock frequency */ +static unsigned long exynos5_get_arm_clk(void) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned long div; + unsigned long armclk; + unsigned int arm_ratio; + unsigned int arm2_ratio; + + div = readl(&clk->div_cpu0); + + /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */ + arm_ratio = (div >> 0) & 0x7; + arm2_ratio = (div >> 28) & 0x7; + + armclk = get_pll_clk(APLL) / (arm_ratio + 1); + armclk /= (arm2_ratio + 1); + + return armclk; +} + +/* exynos4: return pwm clock frequency */ +static unsigned long exynos4_get_pwm_clk(void) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + unsigned long pclk, sclk; + unsigned int sel; + unsigned int ratio; + + if (s5p_get_cpu_rev() == 0) { + /* + * CLK_SRC_PERIL0 + * PWM_SEL [27:24] + */ + sel = readl(&clk->src_peril0); + sel = (sel >> 24) & 0xf; + + if (sel == 0x6) + sclk = get_pll_clk(MPLL); + else if (sel == 0x7) + sclk = get_pll_clk(EPLL); + else if (sel == 0x8) + sclk = get_pll_clk(VPLL); + else + return 0; + + /* + * CLK_DIV_PERIL3 + * PWM_RATIO [3:0] + */ + ratio = readl(&clk->div_peril3); + ratio = ratio & 0xf; + } else if (s5p_get_cpu_rev() == 1) { + sclk = get_pll_clk(MPLL); + ratio = 8; + } else + return 0; + + pclk = sclk / (ratio + 1); + + return pclk; +} + +/* exynos4x12: return pwm clock frequency */ +static unsigned long exynos4x12_get_pwm_clk(void) +{ + unsigned long pclk, sclk; + unsigned int ratio; + + sclk = get_pll_clk(MPLL); + ratio = 8; + + pclk = sclk / (ratio + 1); + + return pclk; +} + +/* exynos5420: return pwm clock frequency */ +static unsigned long exynos5420_get_pwm_clk(void) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long pclk, sclk; + unsigned int ratio; + + /* + * CLK_DIV_PERIC0 + * PWM_RATIO [31:28] + */ + ratio = readl(&clk->div_peric0); + ratio = (ratio >> 28) & 0xf; + sclk = get_pll_clk(MPLL); + + pclk = sclk / (ratio + 1); + + return pclk; +} + +/* exynos4: return uart clock frequency */ +static unsigned long exynos4_get_uart_clk(int dev_index) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + unsigned long uclk, sclk; + unsigned int sel; + unsigned int ratio; + + /* + * CLK_SRC_PERIL0 + * UART0_SEL [3:0] + * UART1_SEL [7:4] + * UART2_SEL [8:11] + * UART3_SEL [12:15] + * UART4_SEL [16:19] + * UART5_SEL [23:20] + */ + sel = readl(&clk->src_peril0); + sel = (sel >> (dev_index << 2)) & 0xf; + + if (sel == 0x6) + sclk = get_pll_clk(MPLL); + else if (sel == 0x7) + sclk = get_pll_clk(EPLL); + else if (sel == 0x8) + sclk = get_pll_clk(VPLL); + else + return 0; + + /* + * CLK_DIV_PERIL0 + * UART0_RATIO [3:0] + * UART1_RATIO [7:4] + * UART2_RATIO [8:11] + * UART3_RATIO [12:15] + * UART4_RATIO [16:19] + * UART5_RATIO [23:20] + */ + ratio = readl(&clk->div_peril0); + ratio = (ratio >> (dev_index << 2)) & 0xf; + + uclk = sclk / (ratio + 1); + + return uclk; +} + +/* exynos4x12: return uart clock frequency */ +static unsigned long exynos4x12_get_uart_clk(int dev_index) +{ + struct exynos4x12_clock *clk = + (struct exynos4x12_clock *)samsung_get_base_clock(); + unsigned long uclk, sclk; + unsigned int sel; + unsigned int ratio; + + /* + * CLK_SRC_PERIL0 + * UART0_SEL [3:0] + * UART1_SEL [7:4] + * UART2_SEL [8:11] + * UART3_SEL [12:15] + * UART4_SEL [16:19] + */ + sel = readl(&clk->src_peril0); + sel = (sel >> (dev_index << 2)) & 0xf; + + if (sel == 0x6) + sclk = get_pll_clk(MPLL); + else if (sel == 0x7) + sclk = get_pll_clk(EPLL); + else if (sel == 0x8) + sclk = get_pll_clk(VPLL); + else + return 0; + + /* + * CLK_DIV_PERIL0 + * UART0_RATIO [3:0] + * UART1_RATIO [7:4] + * UART2_RATIO [8:11] + * UART3_RATIO [12:15] + * UART4_RATIO [16:19] + */ + ratio = readl(&clk->div_peril0); + ratio = (ratio >> (dev_index << 2)) & 0xf; + + uclk = sclk / (ratio + 1); + + return uclk; +} + +/* exynos5: return uart clock frequency */ +static unsigned long exynos5_get_uart_clk(int dev_index) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned long uclk, sclk; + unsigned int sel; + unsigned int ratio; + + /* + * CLK_SRC_PERIC0 + * UART0_SEL [3:0] + * UART1_SEL [7:4] + * UART2_SEL [8:11] + * UART3_SEL [12:15] + * UART4_SEL [16:19] + * UART5_SEL [23:20] + */ + sel = readl(&clk->src_peric0); + sel = (sel >> (dev_index << 2)) & 0xf; + + if (sel == 0x6) + sclk = get_pll_clk(MPLL); + else if (sel == 0x7) + sclk = get_pll_clk(EPLL); + else if (sel == 0x8) + sclk = get_pll_clk(VPLL); + else + return 0; + + /* + * CLK_DIV_PERIC0 + * UART0_RATIO [3:0] + * UART1_RATIO [7:4] + * UART2_RATIO [8:11] + * UART3_RATIO [12:15] + * UART4_RATIO [16:19] + * UART5_RATIO [23:20] + */ + ratio = readl(&clk->div_peric0); + ratio = (ratio >> (dev_index << 2)) & 0xf; + + uclk = sclk / (ratio + 1); + + return uclk; +} + +/* exynos5420: return uart clock frequency */ +static unsigned long exynos5420_get_uart_clk(int dev_index) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long uclk, sclk; + unsigned int sel; + unsigned int ratio; + + /* + * CLK_SRC_PERIC0 + * UART0_SEL [6:4] + * UART1_SEL [10:8] + * UART2_SEL [14:12] + * UART3_SEL [18:16] + * generalised calculation as follows + * sel = (sel >> ((dev_index * 4) + 4)) & mask; + */ + sel = readl(&clk->src_peric0); + sel = (sel >> ((dev_index * 4) + 4)) & 0x7; + + if (sel == 0x3) + sclk = get_pll_clk(MPLL); + else if (sel == 0x6) + sclk = get_pll_clk(EPLL); + else if (sel == 0x7) + sclk = get_pll_clk(RPLL); + else + return 0; + + /* + * CLK_DIV_PERIC0 + * UART0_RATIO [11:8] + * UART1_RATIO [15:12] + * UART2_RATIO [19:16] + * UART3_RATIO [23:20] + * generalised calculation as follows + * ratio = (ratio >> ((dev_index * 4) + 8)) & mask; + */ + ratio = readl(&clk->div_peric0); + ratio = (ratio >> ((dev_index * 4) + 8)) & 0xf; + + uclk = sclk / (ratio + 1); + + return uclk; +} + +static unsigned long exynos4_get_mmc_clk(int dev_index) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + unsigned long uclk, sclk; + unsigned int sel, ratio, pre_ratio; + int shift = 0; + + sel = readl(&clk->src_fsys); + sel = (sel >> (dev_index << 2)) & 0xf; + + if (sel == 0x6) + sclk = get_pll_clk(MPLL); + else if (sel == 0x7) + sclk = get_pll_clk(EPLL); + else if (sel == 0x8) + sclk = get_pll_clk(VPLL); + else + return 0; + + switch (dev_index) { + case 0: + case 1: + ratio = readl(&clk->div_fsys1); + pre_ratio = readl(&clk->div_fsys1); + break; + case 2: + case 3: + ratio = readl(&clk->div_fsys2); + pre_ratio = readl(&clk->div_fsys2); + break; + case 4: + ratio = readl(&clk->div_fsys3); + pre_ratio = readl(&clk->div_fsys3); + break; + default: + return 0; + } + + if (dev_index == 1 || dev_index == 3) + shift = 16; + + ratio = (ratio >> shift) & 0xf; + pre_ratio = (pre_ratio >> (shift + 8)) & 0xff; + uclk = (sclk / (ratio + 1)) / (pre_ratio + 1); + + return uclk; +} + +static unsigned long exynos5_get_mmc_clk(int dev_index) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned long uclk, sclk; + unsigned int sel, ratio, pre_ratio; + int shift = 0; + + sel = readl(&clk->src_fsys); + sel = (sel >> (dev_index << 2)) & 0xf; + + if (sel == 0x6) + sclk = get_pll_clk(MPLL); + else if (sel == 0x7) + sclk = get_pll_clk(EPLL); + else if (sel == 0x8) + sclk = get_pll_clk(VPLL); + else + return 0; + + switch (dev_index) { + case 0: + case 1: + ratio = readl(&clk->div_fsys1); + pre_ratio = readl(&clk->div_fsys1); + break; + case 2: + case 3: + ratio = readl(&clk->div_fsys2); + pre_ratio = readl(&clk->div_fsys2); + break; + default: + return 0; + } + + if (dev_index == 1 || dev_index == 3) + shift = 16; + + ratio = (ratio >> shift) & 0xf; + pre_ratio = (pre_ratio >> (shift + 8)) & 0xff; + uclk = (sclk / (ratio + 1)) / (pre_ratio + 1); + + return uclk; +} + +static unsigned long exynos5420_get_mmc_clk(int dev_index) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long uclk, sclk; + unsigned int sel, ratio; + + /* + * CLK_SRC_FSYS + * MMC0_SEL [10:8] + * MMC1_SEL [14:12] + * MMC2_SEL [18:16] + * generalised calculation as follows + * sel = (sel >> ((dev_index * 4) + 8)) & mask + */ + sel = readl(&clk->src_fsys); + sel = (sel >> ((dev_index * 4) + 8)) & 0x7; + + if (sel == 0x3) + sclk = get_pll_clk(MPLL); + else if (sel == 0x6) + sclk = get_pll_clk(EPLL); + else + return 0; + + /* + * CLK_DIV_FSYS1 + * MMC0_RATIO [9:0] + * MMC1_RATIO [19:10] + * MMC2_RATIO [29:20] + * generalised calculation as follows + * ratio = (ratio >> (dev_index * 10)) & mask + */ + ratio = readl(&clk->div_fsys1); + ratio = (ratio >> (dev_index * 10)) & 0x3ff; + + uclk = (sclk / (ratio + 1)); + + return uclk; +} + +/* exynos4: set the mmc clock */ +static void exynos4_set_mmc_clk(int dev_index, unsigned int div) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + unsigned int addr; + + /* + * CLK_DIV_FSYS1 + * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24] + * CLK_DIV_FSYS2 + * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24] + * CLK_DIV_FSYS3 + * MMC4_PRE_RATIO [15:8] + */ + if (dev_index < 2) { + addr = (unsigned int)&clk->div_fsys1; + } else if (dev_index == 4) { + addr = (unsigned int)&clk->div_fsys3; + dev_index -= 4; + } else { + addr = (unsigned int)&clk->div_fsys2; + dev_index -= 2; + } + + clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8), + (div & 0xff) << ((dev_index << 4) + 8)); +} + +/* exynos4x12: set the mmc clock */ +static void exynos4x12_set_mmc_clk(int dev_index, unsigned int div) +{ + struct exynos4x12_clock *clk = + (struct exynos4x12_clock *)samsung_get_base_clock(); + unsigned int addr; + + /* + * CLK_DIV_FSYS1 + * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24] + * CLK_DIV_FSYS2 + * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24] + */ + if (dev_index < 2) { + addr = (unsigned int)&clk->div_fsys1; + } else { + addr = (unsigned int)&clk->div_fsys2; + dev_index -= 2; + } + + clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8), + (div & 0xff) << ((dev_index << 4) + 8)); +} + +/* exynos5: set the mmc clock */ +static void exynos5_set_mmc_clk(int dev_index, unsigned int div) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned int addr; + + /* + * CLK_DIV_FSYS1 + * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24] + * CLK_DIV_FSYS2 + * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24] + */ + if (dev_index < 2) { + addr = (unsigned int)&clk->div_fsys1; + } else { + addr = (unsigned int)&clk->div_fsys2; + dev_index -= 2; + } + + clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8), + (div & 0xff) << ((dev_index << 4) + 8)); +} + +/* exynos5: set the mmc clock */ +static void exynos5420_set_mmc_clk(int dev_index, unsigned int div) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned int addr; + unsigned int shift; + + /* + * CLK_DIV_FSYS1 + * MMC0_RATIO [9:0] + * MMC1_RATIO [19:10] + * MMC2_RATIO [29:20] + */ + addr = (unsigned int)&clk->div_fsys1; + shift = dev_index * 10; + + clrsetbits_le32(addr, 0x3ff << shift, (div & 0x3ff) << shift); +} + +/* get_lcd_clk: return lcd clock frequency */ +static unsigned long exynos4_get_lcd_clk(void) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + unsigned long pclk, sclk; + unsigned int sel; + unsigned int ratio; + + /* + * CLK_SRC_LCD0 + * FIMD0_SEL [3:0] + */ + sel = readl(&clk->src_lcd0); + sel = sel & 0xf; + + /* + * 0x6: SCLK_MPLL + * 0x7: SCLK_EPLL + * 0x8: SCLK_VPLL + */ + if (sel == 0x6) + sclk = get_pll_clk(MPLL); + else if (sel == 0x7) + sclk = get_pll_clk(EPLL); + else if (sel == 0x8) + sclk = get_pll_clk(VPLL); + else + return 0; + + /* + * CLK_DIV_LCD0 + * FIMD0_RATIO [3:0] + */ + ratio = readl(&clk->div_lcd0); + ratio = ratio & 0xf; + + pclk = sclk / (ratio + 1); + + return pclk; +} + +/* get_lcd_clk: return lcd clock frequency */ +static unsigned long exynos5_get_lcd_clk(void) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned long pclk, sclk; + unsigned int sel; + unsigned int ratio; + + /* + * CLK_SRC_LCD0 + * FIMD0_SEL [3:0] + */ + sel = readl(&clk->src_disp1_0); + sel = sel & 0xf; + + /* + * 0x6: SCLK_MPLL + * 0x7: SCLK_EPLL + * 0x8: SCLK_VPLL + */ + if (sel == 0x6) + sclk = get_pll_clk(MPLL); + else if (sel == 0x7) + sclk = get_pll_clk(EPLL); + else if (sel == 0x8) + sclk = get_pll_clk(VPLL); + else + return 0; + + /* + * CLK_DIV_LCD0 + * FIMD0_RATIO [3:0] + */ + ratio = readl(&clk->div_disp1_0); + ratio = ratio & 0xf; + + pclk = sclk / (ratio + 1); + + return pclk; +} + +void exynos4_set_lcd_clk(void) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + + /* + * CLK_GATE_BLOCK + * CLK_CAM [0] + * CLK_TV [1] + * CLK_MFC [2] + * CLK_G3D [3] + * CLK_LCD0 [4] + * CLK_LCD1 [5] + * CLK_GPS [7] + */ + setbits_le32(&clk->gate_block, 1 << 4); + + /* + * CLK_SRC_LCD0 + * FIMD0_SEL [3:0] + * MDNIE0_SEL [7:4] + * MDNIE_PWM0_SEL [8:11] + * MIPI0_SEL [12:15] + * set lcd0 src clock 0x6: SCLK_MPLL + */ + clrsetbits_le32(&clk->src_lcd0, 0xf, 0x6); + + /* + * CLK_GATE_IP_LCD0 + * CLK_FIMD0 [0] + * CLK_MIE0 [1] + * CLK_MDNIE0 [2] + * CLK_DSIM0 [3] + * CLK_SMMUFIMD0 [4] + * CLK_PPMULCD0 [5] + * Gating all clocks for FIMD0 + */ + setbits_le32(&clk->gate_ip_lcd0, 1 << 0); + + /* + * CLK_DIV_LCD0 + * FIMD0_RATIO [3:0] + * MDNIE0_RATIO [7:4] + * MDNIE_PWM0_RATIO [11:8] + * MDNIE_PWM_PRE_RATIO [15:12] + * MIPI0_RATIO [19:16] + * MIPI0_PRE_RATIO [23:20] + * set fimd ratio + */ + clrsetbits_le32(&clk->div_lcd0, 0xf, 0x1); +} + +void exynos5_set_lcd_clk(void) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + + /* + * CLK_GATE_BLOCK + * CLK_CAM [0] + * CLK_TV [1] + * CLK_MFC [2] + * CLK_G3D [3] + * CLK_LCD0 [4] + * CLK_LCD1 [5] + * CLK_GPS [7] + */ + setbits_le32(&clk->gate_block, 1 << 4); + + /* + * CLK_SRC_LCD0 + * FIMD0_SEL [3:0] + * MDNIE0_SEL [7:4] + * MDNIE_PWM0_SEL [8:11] + * MIPI0_SEL [12:15] + * set lcd0 src clock 0x6: SCLK_MPLL + */ + clrsetbits_le32(&clk->src_disp1_0, 0xf, 0x6); + + /* + * CLK_GATE_IP_LCD0 + * CLK_FIMD0 [0] + * CLK_MIE0 [1] + * CLK_MDNIE0 [2] + * CLK_DSIM0 [3] + * CLK_SMMUFIMD0 [4] + * CLK_PPMULCD0 [5] + * Gating all clocks for FIMD0 + */ + setbits_le32(&clk->gate_ip_disp1, 1 << 0); + + /* + * CLK_DIV_LCD0 + * FIMD0_RATIO [3:0] + * MDNIE0_RATIO [7:4] + * MDNIE_PWM0_RATIO [11:8] + * MDNIE_PWM_PRE_RATIO [15:12] + * MIPI0_RATIO [19:16] + * MIPI0_PRE_RATIO [23:20] + * set fimd ratio + */ + clrsetbits_le32(&clk->div_disp1_0, 0xf, 0x0); +} + +void exynos4_set_mipi_clk(void) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + + /* + * CLK_SRC_LCD0 + * FIMD0_SEL [3:0] + * MDNIE0_SEL [7:4] + * MDNIE_PWM0_SEL [8:11] + * MIPI0_SEL [12:15] + * set mipi0 src clock 0x6: SCLK_MPLL + */ + clrsetbits_le32(&clk->src_lcd0, 0xf << 12, 0x6 << 12); + + /* + * CLK_SRC_MASK_LCD0 + * FIMD0_MASK [0] + * MDNIE0_MASK [4] + * MDNIE_PWM0_MASK [8] + * MIPI0_MASK [12] + * set src mask mipi0 0x1: Unmask + */ + setbits_le32(&clk->src_mask_lcd0, 0x1 << 12); + + /* + * CLK_GATE_IP_LCD0 + * CLK_FIMD0 [0] + * CLK_MIE0 [1] + * CLK_MDNIE0 [2] + * CLK_DSIM0 [3] + * CLK_SMMUFIMD0 [4] + * CLK_PPMULCD0 [5] + * Gating all clocks for MIPI0 + */ + setbits_le32(&clk->gate_ip_lcd0, 1 << 3); + + /* + * CLK_DIV_LCD0 + * FIMD0_RATIO [3:0] + * MDNIE0_RATIO [7:4] + * MDNIE_PWM0_RATIO [11:8] + * MDNIE_PWM_PRE_RATIO [15:12] + * MIPI0_RATIO [19:16] + * MIPI0_PRE_RATIO [23:20] + * set mipi ratio + */ + clrsetbits_le32(&clk->div_lcd0, 0xf << 16, 0x1 << 16); +} + +/* + * I2C + * + * exynos5: obtaining the I2C clock + */ +static unsigned long exynos5_get_i2c_clk(void) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned long aclk_66, aclk_66_pre, sclk; + unsigned int ratio; + + sclk = get_pll_clk(MPLL); + + ratio = (readl(&clk->div_top1)) >> 24; + ratio &= 0x7; + aclk_66_pre = sclk / (ratio + 1); + ratio = readl(&clk->div_top0); + ratio &= 0x7; + aclk_66 = aclk_66_pre / (ratio + 1); + return aclk_66; +} + +int exynos5_set_epll_clk(unsigned long rate) +{ + unsigned int epll_con, epll_con_k; + unsigned int i; + unsigned int lockcnt; + unsigned int start; + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + + epll_con = readl(&clk->epll_con0); + epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK << + EPLL_CON0_LOCK_DET_EN_SHIFT) | + EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT | + EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT | + EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT); + + for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) { + if (exynos5_epll_div[i].freq_out == rate) + break; + } + + if (i == ARRAY_SIZE(exynos5_epll_div)) + return -1; + + epll_con_k = exynos5_epll_div[i].k_dsm << 0; + epll_con |= exynos5_epll_div[i].en_lock_det << + EPLL_CON0_LOCK_DET_EN_SHIFT; + epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT; + epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT; + epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT; + + /* + * Required period ( in cycles) to genarate a stable clock output. + * The maximum clock time can be up to 3000 * PDIV cycles of PLLs + * frequency input (as per spec) + */ + lockcnt = 3000 * exynos5_epll_div[i].p_div; + + writel(lockcnt, &clk->epll_lock); + writel(epll_con, &clk->epll_con0); + writel(epll_con_k, &clk->epll_con1); + + start = get_timer(0); + + while (!(readl(&clk->epll_con0) & + (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) { + if (get_timer(start) > TIMEOUT_EPLL_LOCK) { + debug("%s: Timeout waiting for EPLL lock\n", __func__); + return -1; + } + } + return 0; +} + +int exynos5_set_i2s_clk_source(unsigned int i2s_id) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass(); + + if (i2s_id == 0) { + setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL); + clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK, + (CLK_SRC_SCLK_EPLL)); + setbits_le32(audio_ass, AUDIO_CLKMUX_ASS); + } else if (i2s_id == 1) { + clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK, + (CLK_SRC_SCLK_EPLL)); + } else { + return -1; + } + return 0; +} + +int exynos5_set_i2s_clk_prescaler(unsigned int src_frq, + unsigned int dst_frq, + unsigned int i2s_id) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned int div; + + if ((dst_frq == 0) || (src_frq == 0)) { + debug("%s: Invalid requency input for prescaler\n", __func__); + debug("src frq = %d des frq = %d ", src_frq, dst_frq); + return -1; + } + + div = (src_frq / dst_frq); + if (i2s_id == 0) { + if (div > AUDIO_0_RATIO_MASK) { + debug("%s: Frequency ratio is out of range\n", + __func__); + debug("src frq = %d des frq = %d ", src_frq, dst_frq); + return -1; + } + clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK, + (div & AUDIO_0_RATIO_MASK)); + } else if(i2s_id == 1) { + if (div > AUDIO_1_RATIO_MASK) { + debug("%s: Frequency ratio is out of range\n", + __func__); + debug("src frq = %d des frq = %d ", src_frq, dst_frq); + return -1; + } + clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK, + (div & AUDIO_1_RATIO_MASK)); + } else { + return -1; + } + return 0; +} + +/** + * Linearly searches for the most accurate main and fine stage clock scalars + * (divisors) for a specified target frequency and scalar bit sizes by checking + * all multiples of main_scalar_bits values. Will always return scalars up to or + * slower than target. + * + * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32 + * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32 + * @param input_freq Clock frequency to be scaled in Hz + * @param target_freq Desired clock frequency in Hz + * @param best_fine_scalar Pointer to store the fine stage divisor + * + * @return best_main_scalar Main scalar for desired frequency or -1 if none + * found + */ +static int clock_calc_best_scalar(unsigned int main_scaler_bits, + unsigned int fine_scalar_bits, unsigned int input_rate, + unsigned int target_rate, unsigned int *best_fine_scalar) +{ + int i; + int best_main_scalar = -1; + unsigned int best_error = target_rate; + const unsigned int cap = (1 << fine_scalar_bits) - 1; + const unsigned int loops = 1 << main_scaler_bits; + + debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate, + target_rate, cap); + + assert(best_fine_scalar != NULL); + assert(main_scaler_bits <= fine_scalar_bits); + + *best_fine_scalar = 1; + + if (input_rate == 0 || target_rate == 0) + return -1; + + if (target_rate >= input_rate) + return 1; + + for (i = 1; i <= loops; i++) { + const unsigned int effective_div = max(min(input_rate / i / + target_rate, cap), 1); + const unsigned int effective_rate = input_rate / i / + effective_div; + const int error = target_rate - effective_rate; + + debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div, + effective_rate, error); + + if (error >= 0 && error <= best_error) { + best_error = error; + best_main_scalar = i; + *best_fine_scalar = effective_div; + } + } + + return best_main_scalar; +} + +static int exynos5_set_spi_clk(enum periph_id periph_id, + unsigned int rate) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + int main; + unsigned int fine; + unsigned shift, pre_shift; + unsigned mask = 0xff; + u32 *reg; + + main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine); + if (main < 0) { + debug("%s: Cannot set clock rate for periph %d", + __func__, periph_id); + return -1; + } + main = main - 1; + fine = fine - 1; + + switch (periph_id) { + case PERIPH_ID_SPI0: + reg = &clk->div_peric1; + shift = 0; + pre_shift = 8; + break; + case PERIPH_ID_SPI1: + reg = &clk->div_peric1; + shift = 16; + pre_shift = 24; + break; + case PERIPH_ID_SPI2: + reg = &clk->div_peric2; + shift = 0; + pre_shift = 8; + break; + case PERIPH_ID_SPI3: + reg = &clk->sclk_div_isp; + shift = 0; + pre_shift = 4; + break; + case PERIPH_ID_SPI4: + reg = &clk->sclk_div_isp; + shift = 12; + pre_shift = 16; + break; + default: + debug("%s: Unsupported peripheral ID %d\n", __func__, + periph_id); + return -1; + } + clrsetbits_le32(reg, mask << shift, (main & mask) << shift); + clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift); + + return 0; +} + +static int exynos5420_set_spi_clk(enum periph_id periph_id, + unsigned int rate) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + int main; + unsigned int fine; + unsigned shift, pre_shift; + unsigned div_mask = 0xf, pre_div_mask = 0xff; + u32 *reg; + u32 *pre_reg; + + main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine); + if (main < 0) { + debug("%s: Cannot set clock rate for periph %d", + __func__, periph_id); + return -1; + } + main = main - 1; + fine = fine - 1; + + switch (periph_id) { + case PERIPH_ID_SPI0: + reg = &clk->div_peric1; + shift = 20; + pre_reg = &clk->div_peric4; + pre_shift = 8; + break; + case PERIPH_ID_SPI1: + reg = &clk->div_peric1; + shift = 24; + pre_reg = &clk->div_peric4; + pre_shift = 16; + break; + case PERIPH_ID_SPI2: + reg = &clk->div_peric1; + shift = 28; + pre_reg = &clk->div_peric4; + pre_shift = 24; + break; + case PERIPH_ID_SPI3: + reg = &clk->div_isp1; + shift = 16; + pre_reg = &clk->div_isp1; + pre_shift = 0; + break; + case PERIPH_ID_SPI4: + reg = &clk->div_isp1; + shift = 20; + pre_reg = &clk->div_isp1; + pre_shift = 8; + break; + default: + debug("%s: Unsupported peripheral ID %d\n", __func__, + periph_id); + return -1; + } + + clrsetbits_le32(reg, div_mask << shift, (main & div_mask) << shift); + clrsetbits_le32(pre_reg, pre_div_mask << pre_shift, + (fine & pre_div_mask) << pre_shift); + + return 0; +} + +static unsigned long exynos4_get_i2c_clk(void) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + unsigned long sclk, aclk_100; + unsigned int ratio; + + sclk = get_pll_clk(APLL); + + ratio = (readl(&clk->div_top)) >> 4; + ratio &= 0xf; + aclk_100 = sclk / (ratio + 1); + return aclk_100; +} + +unsigned long get_pll_clk(int pllreg) +{ + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_get_pll_clk(pllreg); + return exynos5_get_pll_clk(pllreg); + } else { + if (proid_is_exynos4412()) + return exynos4x12_get_pll_clk(pllreg); + return exynos4_get_pll_clk(pllreg); + } +} + +unsigned long get_arm_clk(void) +{ + if (cpu_is_exynos5()) + return exynos5_get_arm_clk(); + else { + if (proid_is_exynos4412()) + return exynos4x12_get_arm_clk(); + return exynos4_get_arm_clk(); + } +} + +unsigned long get_i2c_clk(void) +{ + if (cpu_is_exynos5()) { + return exynos5_get_i2c_clk(); + } else if (cpu_is_exynos4()) { + return exynos4_get_i2c_clk(); + } else { + debug("I2C clock is not set for this CPU\n"); + return 0; + } +} + +unsigned long get_pwm_clk(void) +{ + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_get_pwm_clk(); + return clock_get_periph_rate(PERIPH_ID_PWM0); + } else { + if (proid_is_exynos4412()) + return exynos4x12_get_pwm_clk(); + return exynos4_get_pwm_clk(); + } +} + +unsigned long get_uart_clk(int dev_index) +{ + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_get_uart_clk(dev_index); + return exynos5_get_uart_clk(dev_index); + } else { + if (proid_is_exynos4412()) + return exynos4x12_get_uart_clk(dev_index); + return exynos4_get_uart_clk(dev_index); + } +} + +unsigned long get_mmc_clk(int dev_index) +{ + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_get_mmc_clk(dev_index); + return exynos5_get_mmc_clk(dev_index); + } else { + return exynos4_get_mmc_clk(dev_index); + } +} + +void set_mmc_clk(int dev_index, unsigned int div) +{ + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + exynos5420_set_mmc_clk(dev_index, div); + else + exynos5_set_mmc_clk(dev_index, div); + } else { + if (proid_is_exynos4412()) + exynos4x12_set_mmc_clk(dev_index, div); + else + exynos4_set_mmc_clk(dev_index, div); + } +} + +unsigned long get_lcd_clk(void) +{ + if (cpu_is_exynos4()) + return exynos4_get_lcd_clk(); + else + return exynos5_get_lcd_clk(); +} + +void set_lcd_clk(void) +{ + if (cpu_is_exynos4()) + exynos4_set_lcd_clk(); + else + exynos5_set_lcd_clk(); +} + +void set_mipi_clk(void) +{ + if (cpu_is_exynos4()) + exynos4_set_mipi_clk(); +} + +int set_spi_clk(int periph_id, unsigned int rate) +{ + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_set_spi_clk(periph_id, rate); + return exynos5_set_spi_clk(periph_id, rate); + } else { + return 0; + } +} + +int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq, + unsigned int i2s_id) +{ + if (cpu_is_exynos5()) + return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id); + else + return 0; +} + +int set_i2s_clk_source(unsigned int i2s_id) +{ + if (cpu_is_exynos5()) + return exynos5_set_i2s_clk_source(i2s_id); + else + return 0; +} + +int set_epll_clk(unsigned long rate) +{ + if (cpu_is_exynos5()) + return exynos5_set_epll_clk(rate); + else + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock_init.h b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock_init.h new file mode 100644 index 000000000..a875d0b48 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock_init.h @@ -0,0 +1,155 @@ +/* + * Clock initialization routines + * + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __EXYNOS_CLOCK_INIT_H +#define __EXYNOS_CLOCK_INIT_H + +enum { +#ifdef CONFIG_EXYNOS5420 + MEM_TIMINGS_MSR_COUNT = 5, +#else + MEM_TIMINGS_MSR_COUNT = 4, +#endif +}; + +/* These are the ratio's for configuring ARM clock */ +struct arm_clk_ratios { + unsigned arm_freq_mhz; /* Frequency of ARM core in MHz */ + + unsigned apll_mdiv; + unsigned apll_pdiv; + unsigned apll_sdiv; + + unsigned arm2_ratio; + unsigned apll_ratio; + unsigned pclk_dbg_ratio; + unsigned atb_ratio; + unsigned periph_ratio; + unsigned acp_ratio; + unsigned cpud_ratio; + unsigned arm_ratio; +}; + +/* These are the memory timings for a particular memory type and speed */ +struct mem_timings { + enum mem_manuf mem_manuf; /* Memory manufacturer */ + enum ddr_mode mem_type; /* Memory type */ + unsigned frequency_mhz; /* Frequency of memory in MHz */ + + /* Here follow the timing parameters for the selected memory */ + unsigned apll_mdiv; + unsigned apll_pdiv; + unsigned apll_sdiv; + unsigned mpll_mdiv; + unsigned mpll_pdiv; + unsigned mpll_sdiv; + unsigned cpll_mdiv; + unsigned cpll_pdiv; + unsigned cpll_sdiv; + unsigned gpll_mdiv; + unsigned gpll_pdiv; + unsigned gpll_sdiv; + unsigned epll_mdiv; + unsigned epll_pdiv; + unsigned epll_sdiv; + unsigned vpll_mdiv; + unsigned vpll_pdiv; + unsigned vpll_sdiv; + unsigned bpll_mdiv; + unsigned bpll_pdiv; + unsigned bpll_sdiv; + unsigned kpll_mdiv; + unsigned kpll_pdiv; + unsigned kpll_sdiv; + unsigned dpll_mdiv; + unsigned dpll_pdiv; + unsigned dpll_sdiv; + unsigned ipll_mdiv; + unsigned ipll_pdiv; + unsigned ipll_sdiv; + unsigned spll_mdiv; + unsigned spll_pdiv; + unsigned spll_sdiv; + unsigned pclk_cdrex_ratio; + unsigned direct_cmd_msr[MEM_TIMINGS_MSR_COUNT]; + + unsigned timing_ref; + unsigned timing_row; + unsigned timing_data; + unsigned timing_power; + + /* DQS, DQ, DEBUG offsets */ + unsigned phy0_dqs; + unsigned phy1_dqs; + unsigned phy0_dq; + unsigned phy1_dq; + unsigned phy0_tFS; + unsigned phy1_tFS; + unsigned phy0_pulld_dqs; + unsigned phy1_pulld_dqs; + + unsigned lpddr3_ctrl_phy_reset; + unsigned ctrl_start_point; + unsigned ctrl_inc; + unsigned ctrl_start; + unsigned ctrl_dll_on; + unsigned ctrl_ref; + + unsigned ctrl_force; + unsigned ctrl_rdlat; + unsigned ctrl_bstlen; + + unsigned fp_resync; + unsigned iv_size; + unsigned dfi_init_start; + unsigned aref_en; + + unsigned rd_fetch; + + unsigned zq_mode_dds; + unsigned zq_mode_term; + unsigned zq_mode_noterm; /* 1 to allow termination disable */ + + unsigned memcontrol; + unsigned memconfig; + + unsigned membaseconfig0; + unsigned membaseconfig1; + unsigned prechconfig_tp_cnt; + unsigned dpwrdn_cyc; + unsigned dsref_cyc; + unsigned concontrol; + /* Channel and Chip Selection */ + uint8_t dmc_channels; /* number of memory channels */ + uint8_t chips_per_channel; /* number of chips per channel */ + uint8_t chips_to_configure; /* number of chips to configure */ + uint8_t send_zq_init; /* 1 to send this command */ + unsigned impedance; /* drive strength impedeance */ + uint8_t gate_leveling_enable; /* check gate leveling is enabled */ + uint8_t read_leveling_enable; /* check h/w read leveling is enabled */ +}; + +/** + * Get the correct memory timings for our selected memory type and speed. + * + * This function can be called from SPL or the main U-Boot. + * + * @return pointer to the memory timings that we should use + */ +struct mem_timings *clock_get_mem_timings(void); + +/* + * Initialize clock for the device + */ +void system_clock_init(void); + +/* + * Set clock divisor value for booting from EMMC. + */ +void emmc_boot_clk_div_set(void); +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock_init_exynos4.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock_init_exynos4.c new file mode 100644 index 000000000..31610909f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock_init_exynos4.c @@ -0,0 +1,95 @@ +/* + * Clock Initialization for board based on EXYNOS4210 + * + * Copyright (C) 2013 Samsung Electronics + * Rajeshwari Shinde <rajeshwari.s@samsung.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <version.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clk.h> +#include <asm/arch/clock.h> +#include "common_setup.h" +#include "exynos4_setup.h" + +/* + * system_clock_init: Initialize core clock and bus clock. + * void system_clock_init(void) + */ +void system_clock_init(void) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + + writel(CLK_SRC_CPU_VAL, &clk->src_cpu); + + sdelay(0x10000); + + writel(CLK_SRC_TOP0_VAL, &clk->src_top0); + writel(CLK_SRC_TOP1_VAL, &clk->src_top1); + writel(CLK_SRC_DMC_VAL, &clk->src_dmc); + writel(CLK_SRC_LEFTBUS_VAL, &clk->src_leftbus); + writel(CLK_SRC_RIGHTBUS_VAL, &clk->src_rightbus); + writel(CLK_SRC_FSYS_VAL, &clk->src_fsys); + writel(CLK_SRC_PERIL0_VAL, &clk->src_peril0); + writel(CLK_SRC_CAM_VAL, &clk->src_cam); + writel(CLK_SRC_MFC_VAL, &clk->src_mfc); + writel(CLK_SRC_G3D_VAL, &clk->src_g3d); + writel(CLK_SRC_LCD0_VAL, &clk->src_lcd0); + + sdelay(0x10000); + + writel(CLK_DIV_CPU0_VAL, &clk->div_cpu0); + writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1); + writel(CLK_DIV_DMC0_VAL, &clk->div_dmc0); + writel(CLK_DIV_DMC1_VAL, &clk->div_dmc1); + writel(CLK_DIV_LEFTBUS_VAL, &clk->div_leftbus); + writel(CLK_DIV_RIGHTBUS_VAL, &clk->div_rightbus); + writel(CLK_DIV_TOP_VAL, &clk->div_top); + writel(CLK_DIV_FSYS1_VAL, &clk->div_fsys1); + writel(CLK_DIV_FSYS2_VAL, &clk->div_fsys2); + writel(CLK_DIV_FSYS3_VAL, &clk->div_fsys3); + writel(CLK_DIV_PERIL0_VAL, &clk->div_peril0); + writel(CLK_DIV_CAM_VAL, &clk->div_cam); + writel(CLK_DIV_MFC_VAL, &clk->div_mfc); + writel(CLK_DIV_G3D_VAL, &clk->div_g3d); + writel(CLK_DIV_LCD0_VAL, &clk->div_lcd0); + + /* Set PLL locktime */ + writel(PLL_LOCKTIME, &clk->apll_lock); + writel(PLL_LOCKTIME, &clk->mpll_lock); + writel(PLL_LOCKTIME, &clk->epll_lock); + writel(PLL_LOCKTIME, &clk->vpll_lock); + + writel(APLL_CON1_VAL, &clk->apll_con1); + writel(APLL_CON0_VAL, &clk->apll_con0); + writel(MPLL_CON1_VAL, &clk->mpll_con1); + writel(MPLL_CON0_VAL, &clk->mpll_con0); + writel(EPLL_CON1_VAL, &clk->epll_con1); + writel(EPLL_CON0_VAL, &clk->epll_con0); + writel(VPLL_CON1_VAL, &clk->vpll_con1); + writel(VPLL_CON0_VAL, &clk->vpll_con0); + + sdelay(0x30000); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock_init_exynos5.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock_init_exynos5.c new file mode 100644 index 000000000..1d6977fa4 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/clock_init_exynos5.c @@ -0,0 +1,992 @@ +/* + * Clock setup for SMDK5250 board based on EXYNOS5 + * + * Copyright (C) 2012 Samsung Electronics + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/clk.h> +#include <asm/arch/clock.h> +#include <asm/arch/spl.h> +#include <asm/arch/dwmmc.h> + +#include "clock_init.h" +#include "common_setup.h" +#include "exynos5_setup.h" + +#define FSYS1_MMC0_DIV_MASK 0xff0f +#define FSYS1_MMC0_DIV_VAL 0x0701 + +DECLARE_GLOBAL_DATA_PTR; + +struct arm_clk_ratios arm_clk_ratios[] = { +#ifdef CONFIG_EXYNOS5420 + { + .arm_freq_mhz = 900, + + .apll_mdiv = 0x96, + .apll_pdiv = 0x2, + .apll_sdiv = 0x1, + + .arm2_ratio = 0x0, + .apll_ratio = 0x3, + .pclk_dbg_ratio = 0x6, + .atb_ratio = 0x6, + .periph_ratio = 0x7, + .acp_ratio = 0x0, + .cpud_ratio = 0x2, + .arm_ratio = 0x0, + } +#else + { + .arm_freq_mhz = 600, + + .apll_mdiv = 0xc8, + .apll_pdiv = 0x4, + .apll_sdiv = 0x1, + + .arm2_ratio = 0x0, + .apll_ratio = 0x1, + .pclk_dbg_ratio = 0x1, + .atb_ratio = 0x2, + .periph_ratio = 0x7, + .acp_ratio = 0x7, + .cpud_ratio = 0x1, + .arm_ratio = 0x0, + }, { + .arm_freq_mhz = 800, + + .apll_mdiv = 0x64, + .apll_pdiv = 0x3, + .apll_sdiv = 0x0, + + .arm2_ratio = 0x0, + .apll_ratio = 0x1, + .pclk_dbg_ratio = 0x1, + .atb_ratio = 0x3, + .periph_ratio = 0x7, + .acp_ratio = 0x7, + .cpud_ratio = 0x2, + .arm_ratio = 0x0, + }, { + .arm_freq_mhz = 1000, + + .apll_mdiv = 0x7d, + .apll_pdiv = 0x3, + .apll_sdiv = 0x0, + + .arm2_ratio = 0x0, + .apll_ratio = 0x1, + .pclk_dbg_ratio = 0x1, + .atb_ratio = 0x4, + .periph_ratio = 0x7, + .acp_ratio = 0x7, + .cpud_ratio = 0x2, + .arm_ratio = 0x0, + }, { + .arm_freq_mhz = 1200, + + .apll_mdiv = 0x96, + .apll_pdiv = 0x3, + .apll_sdiv = 0x0, + + .arm2_ratio = 0x0, + .apll_ratio = 0x3, + .pclk_dbg_ratio = 0x1, + .atb_ratio = 0x5, + .periph_ratio = 0x7, + .acp_ratio = 0x7, + .cpud_ratio = 0x3, + .arm_ratio = 0x0, + }, { + .arm_freq_mhz = 1400, + + .apll_mdiv = 0xaf, + .apll_pdiv = 0x3, + .apll_sdiv = 0x0, + + .arm2_ratio = 0x0, + .apll_ratio = 0x3, + .pclk_dbg_ratio = 0x1, + .atb_ratio = 0x6, + .periph_ratio = 0x7, + .acp_ratio = 0x7, + .cpud_ratio = 0x3, + .arm_ratio = 0x0, + }, { + .arm_freq_mhz = 1700, + + .apll_mdiv = 0x1a9, + .apll_pdiv = 0x6, + .apll_sdiv = 0x0, + + .arm2_ratio = 0x0, + .apll_ratio = 0x3, + .pclk_dbg_ratio = 0x1, + .atb_ratio = 0x6, + .periph_ratio = 0x7, + .acp_ratio = 0x7, + .cpud_ratio = 0x3, + .arm_ratio = 0x0, + } +#endif +}; + +struct mem_timings mem_timings[] = { +#ifdef CONFIG_EXYNOS5420 + { + .mem_manuf = MEM_MANUF_SAMSUNG, + .mem_type = DDR_MODE_DDR3, + .frequency_mhz = 800, + + /* MPLL @800MHz*/ + .mpll_mdiv = 0xc8, + .mpll_pdiv = 0x3, + .mpll_sdiv = 0x1, + /* CPLL @666MHz */ + .cpll_mdiv = 0xde, + .cpll_pdiv = 0x4, + .cpll_sdiv = 0x1, + /* EPLL @600MHz */ + .epll_mdiv = 0x64, + .epll_pdiv = 0x2, + .epll_sdiv = 0x1, + /* VPLL @430MHz */ + .vpll_mdiv = 0xd7, + .vpll_pdiv = 0x3, + .vpll_sdiv = 0x2, + /* BPLL @800MHz */ + .bpll_mdiv = 0xc8, + .bpll_pdiv = 0x3, + .bpll_sdiv = 0x1, + /* KPLL @600MHz */ + .kpll_mdiv = 0x190, + .kpll_pdiv = 0x4, + .kpll_sdiv = 0x2, + /* DPLL @600MHz */ + .dpll_mdiv = 0x190, + .dpll_pdiv = 0x4, + .dpll_sdiv = 0x2, + /* IPLL @370MHz */ + .ipll_mdiv = 0xb9, + .ipll_pdiv = 0x3, + .ipll_sdiv = 0x2, + /* SPLL @400MHz */ + .spll_mdiv = 0xc8, + .spll_pdiv = 0x3, + .spll_sdiv = 0x2, + + .direct_cmd_msr = { + 0x00020018, 0x00030000, 0x00010046, 0x00000d70, + 0x00000c70 + }, + .timing_ref = 0x000000bb, + .timing_row = 0x6836650f, + .timing_data = 0x3630580b, + .timing_power = 0x41000a26, + .phy0_dqs = 0x08080808, + .phy1_dqs = 0x08080808, + .phy0_dq = 0x08080808, + .phy1_dq = 0x08080808, + .phy0_tFS = 0x8, + .phy1_tFS = 0x8, + .phy0_pulld_dqs = 0xf, + .phy1_pulld_dqs = 0xf, + + .lpddr3_ctrl_phy_reset = 0x1, + .ctrl_start_point = 0x10, + .ctrl_inc = 0x10, + .ctrl_start = 0x1, + .ctrl_dll_on = 0x1, + .ctrl_ref = 0x8, + + .ctrl_force = 0x1a, + .ctrl_rdlat = 0x0b, + .ctrl_bstlen = 0x08, + + .fp_resync = 0x8, + .iv_size = 0x7, + .dfi_init_start = 1, + .aref_en = 1, + + .rd_fetch = 0x3, + + .zq_mode_dds = 0x7, + .zq_mode_term = 0x1, + .zq_mode_noterm = 1, + + /* + * Dynamic Clock: Always Running + * Memory Burst length: 8 + * Number of chips: 1 + * Memory Bus width: 32 bit + * Memory Type: DDR3 + * Additional Latancy for PLL: 0 Cycle + */ + .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE | + DMC_MEMCONTROL_DPWRDN_DISABLE | + DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE | + DMC_MEMCONTROL_TP_DISABLE | + DMC_MEMCONTROL_DSREF_DISABLE | + DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) | + DMC_MEMCONTROL_MEM_TYPE_DDR3 | + DMC_MEMCONTROL_MEM_WIDTH_32BIT | + DMC_MEMCONTROL_NUM_CHIP_1 | + DMC_MEMCONTROL_BL_8 | + DMC_MEMCONTROL_PZQ_DISABLE | + DMC_MEMCONTROL_MRR_BYTE_7_0, + .memconfig = DMC_MEMCONFIG_CHIP_MAP_SPLIT | + DMC_MEMCONFIGX_CHIP_COL_10 | + DMC_MEMCONFIGX_CHIP_ROW_15 | + DMC_MEMCONFIGX_CHIP_BANK_8, + .prechconfig_tp_cnt = 0xff, + .dpwrdn_cyc = 0xff, + .dsref_cyc = 0xffff, + .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE | + DMC_CONCONTROL_TIMEOUT_LEVEL0 | + DMC_CONCONTROL_RD_FETCH_DISABLE | + DMC_CONCONTROL_EMPTY_DISABLE | + DMC_CONCONTROL_AREF_EN_DISABLE | + DMC_CONCONTROL_IO_PD_CON_DISABLE, + .dmc_channels = 1, + .chips_per_channel = 1, + .chips_to_configure = 1, + .send_zq_init = 1, + .gate_leveling_enable = 1, + .read_leveling_enable = 0, + } +#else + { + .mem_manuf = MEM_MANUF_ELPIDA, + .mem_type = DDR_MODE_DDR3, + .frequency_mhz = 800, + .mpll_mdiv = 0xc8, + .mpll_pdiv = 0x3, + .mpll_sdiv = 0x0, + .cpll_mdiv = 0xde, + .cpll_pdiv = 0x4, + .cpll_sdiv = 0x2, + .gpll_mdiv = 0x215, + .gpll_pdiv = 0xc, + .gpll_sdiv = 0x1, + .epll_mdiv = 0x60, + .epll_pdiv = 0x3, + .epll_sdiv = 0x3, + .vpll_mdiv = 0x96, + .vpll_pdiv = 0x3, + .vpll_sdiv = 0x2, + + .bpll_mdiv = 0x64, + .bpll_pdiv = 0x3, + .bpll_sdiv = 0x0, + .pclk_cdrex_ratio = 0x5, + .direct_cmd_msr = { + 0x00020018, 0x00030000, 0x00010042, 0x00000d70 + }, + .timing_ref = 0x000000bb, + .timing_row = 0x8c36650e, + .timing_data = 0x3630580b, + .timing_power = 0x41000a44, + .phy0_dqs = 0x08080808, + .phy1_dqs = 0x08080808, + .phy0_dq = 0x08080808, + .phy1_dq = 0x08080808, + .phy0_tFS = 0x4, + .phy1_tFS = 0x4, + .phy0_pulld_dqs = 0xf, + .phy1_pulld_dqs = 0xf, + + .lpddr3_ctrl_phy_reset = 0x1, + .ctrl_start_point = 0x10, + .ctrl_inc = 0x10, + .ctrl_start = 0x1, + .ctrl_dll_on = 0x1, + .ctrl_ref = 0x8, + + .ctrl_force = 0x1a, + .ctrl_rdlat = 0x0b, + .ctrl_bstlen = 0x08, + + .fp_resync = 0x8, + .iv_size = 0x7, + .dfi_init_start = 1, + .aref_en = 1, + + .rd_fetch = 0x3, + + .zq_mode_dds = 0x7, + .zq_mode_term = 0x1, + .zq_mode_noterm = 0, + + /* + * Dynamic Clock: Always Running + * Memory Burst length: 8 + * Number of chips: 1 + * Memory Bus width: 32 bit + * Memory Type: DDR3 + * Additional Latancy for PLL: 0 Cycle + */ + .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE | + DMC_MEMCONTROL_DPWRDN_DISABLE | + DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE | + DMC_MEMCONTROL_TP_DISABLE | + DMC_MEMCONTROL_DSREF_ENABLE | + DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) | + DMC_MEMCONTROL_MEM_TYPE_DDR3 | + DMC_MEMCONTROL_MEM_WIDTH_32BIT | + DMC_MEMCONTROL_NUM_CHIP_1 | + DMC_MEMCONTROL_BL_8 | + DMC_MEMCONTROL_PZQ_DISABLE | + DMC_MEMCONTROL_MRR_BYTE_7_0, + .memconfig = DMC_MEMCONFIGX_CHIP_MAP_INTERLEAVED | + DMC_MEMCONFIGX_CHIP_COL_10 | + DMC_MEMCONFIGX_CHIP_ROW_15 | + DMC_MEMCONFIGX_CHIP_BANK_8, + .membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40), + .membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80), + .prechconfig_tp_cnt = 0xff, + .dpwrdn_cyc = 0xff, + .dsref_cyc = 0xffff, + .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE | + DMC_CONCONTROL_TIMEOUT_LEVEL0 | + DMC_CONCONTROL_RD_FETCH_DISABLE | + DMC_CONCONTROL_EMPTY_DISABLE | + DMC_CONCONTROL_AREF_EN_DISABLE | + DMC_CONCONTROL_IO_PD_CON_DISABLE, + .dmc_channels = 2, + .chips_per_channel = 2, + .chips_to_configure = 1, + .send_zq_init = 1, + .impedance = IMP_OUTPUT_DRV_30_OHM, + .gate_leveling_enable = 0, + }, { + .mem_manuf = MEM_MANUF_SAMSUNG, + .mem_type = DDR_MODE_DDR3, + .frequency_mhz = 800, + .mpll_mdiv = 0xc8, + .mpll_pdiv = 0x3, + .mpll_sdiv = 0x0, + .cpll_mdiv = 0xde, + .cpll_pdiv = 0x4, + .cpll_sdiv = 0x2, + .gpll_mdiv = 0x215, + .gpll_pdiv = 0xc, + .gpll_sdiv = 0x1, + .epll_mdiv = 0x60, + .epll_pdiv = 0x3, + .epll_sdiv = 0x3, + .vpll_mdiv = 0x96, + .vpll_pdiv = 0x3, + .vpll_sdiv = 0x2, + + .bpll_mdiv = 0x64, + .bpll_pdiv = 0x3, + .bpll_sdiv = 0x0, + .pclk_cdrex_ratio = 0x5, + .direct_cmd_msr = { + 0x00020018, 0x00030000, 0x00010000, 0x00000d70 + }, + .timing_ref = 0x000000bb, + .timing_row = 0x8c36650e, + .timing_data = 0x3630580b, + .timing_power = 0x41000a44, + .phy0_dqs = 0x08080808, + .phy1_dqs = 0x08080808, + .phy0_dq = 0x08080808, + .phy1_dq = 0x08080808, + .phy0_tFS = 0x8, + .phy1_tFS = 0x8, + .phy0_pulld_dqs = 0xf, + .phy1_pulld_dqs = 0xf, + + .lpddr3_ctrl_phy_reset = 0x1, + .ctrl_start_point = 0x10, + .ctrl_inc = 0x10, + .ctrl_start = 0x1, + .ctrl_dll_on = 0x1, + .ctrl_ref = 0x8, + + .ctrl_force = 0x1a, + .ctrl_rdlat = 0x0b, + .ctrl_bstlen = 0x08, + + .fp_resync = 0x8, + .iv_size = 0x7, + .dfi_init_start = 1, + .aref_en = 1, + + .rd_fetch = 0x3, + + .zq_mode_dds = 0x5, + .zq_mode_term = 0x1, + .zq_mode_noterm = 1, + + /* + * Dynamic Clock: Always Running + * Memory Burst length: 8 + * Number of chips: 1 + * Memory Bus width: 32 bit + * Memory Type: DDR3 + * Additional Latancy for PLL: 0 Cycle + */ + .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE | + DMC_MEMCONTROL_DPWRDN_DISABLE | + DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE | + DMC_MEMCONTROL_TP_DISABLE | + DMC_MEMCONTROL_DSREF_ENABLE | + DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) | + DMC_MEMCONTROL_MEM_TYPE_DDR3 | + DMC_MEMCONTROL_MEM_WIDTH_32BIT | + DMC_MEMCONTROL_NUM_CHIP_1 | + DMC_MEMCONTROL_BL_8 | + DMC_MEMCONTROL_PZQ_DISABLE | + DMC_MEMCONTROL_MRR_BYTE_7_0, + .memconfig = DMC_MEMCONFIGX_CHIP_MAP_INTERLEAVED | + DMC_MEMCONFIGX_CHIP_COL_10 | + DMC_MEMCONFIGX_CHIP_ROW_15 | + DMC_MEMCONFIGX_CHIP_BANK_8, + .membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40), + .membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80), + .prechconfig_tp_cnt = 0xff, + .dpwrdn_cyc = 0xff, + .dsref_cyc = 0xffff, + .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE | + DMC_CONCONTROL_TIMEOUT_LEVEL0 | + DMC_CONCONTROL_RD_FETCH_DISABLE | + DMC_CONCONTROL_EMPTY_DISABLE | + DMC_CONCONTROL_AREF_EN_DISABLE | + DMC_CONCONTROL_IO_PD_CON_DISABLE, + .dmc_channels = 2, + .chips_per_channel = 2, + .chips_to_configure = 1, + .send_zq_init = 1, + .impedance = IMP_OUTPUT_DRV_40_OHM, + .gate_leveling_enable = 1, + } +#endif +}; + +/** + * Get the required memory type and speed (SPL version). + * + * In SPL we have no device tree, so we use the machine parameters + * + * @param mem_type Returns memory type + * @param frequency_mhz Returns memory speed in MHz + * @param arm_freq Returns ARM clock speed in MHz + * @param mem_manuf Return Memory Manufacturer name + */ +static void clock_get_mem_selection(enum ddr_mode *mem_type, + unsigned *frequency_mhz, unsigned *arm_freq, + enum mem_manuf *mem_manuf) +{ + struct spl_machine_param *params; + + params = spl_get_machine_params(); + *mem_type = params->mem_type; + *frequency_mhz = params->frequency_mhz; + *arm_freq = params->arm_freq_mhz; + *mem_manuf = params->mem_manuf; +} + +/* Get the ratios for setting ARM clock */ +struct arm_clk_ratios *get_arm_ratios(void) +{ + struct arm_clk_ratios *arm_ratio; + enum ddr_mode mem_type; + enum mem_manuf mem_manuf; + unsigned frequency_mhz, arm_freq; + int i; + + clock_get_mem_selection(&mem_type, &frequency_mhz, + &arm_freq, &mem_manuf); + + for (i = 0, arm_ratio = arm_clk_ratios; i < ARRAY_SIZE(arm_clk_ratios); + i++, arm_ratio++) { + if (arm_ratio->arm_freq_mhz == arm_freq) + return arm_ratio; + } + + /* will hang if failed to find clock ratio */ + while (1) + ; + + return NULL; +} + +struct mem_timings *clock_get_mem_timings(void) +{ + struct mem_timings *mem; + enum ddr_mode mem_type; + enum mem_manuf mem_manuf; + unsigned frequency_mhz, arm_freq; + int i; + + clock_get_mem_selection(&mem_type, &frequency_mhz, + &arm_freq, &mem_manuf); + for (i = 0, mem = mem_timings; i < ARRAY_SIZE(mem_timings); + i++, mem++) { + if (mem->mem_type == mem_type && + mem->frequency_mhz == frequency_mhz && + mem->mem_manuf == mem_manuf) + return mem; + } + + /* will hang if failed to find memory timings */ + while (1) + ; + + return NULL; +} + +static void exynos5250_system_clock_init(void) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + struct mem_timings *mem; + struct arm_clk_ratios *arm_clk_ratio; + u32 val, tmp; + + mem = clock_get_mem_timings(); + arm_clk_ratio = get_arm_ratios(); + + clrbits_le32(&clk->src_cpu, MUX_APLL_SEL_MASK); + do { + val = readl(&clk->mux_stat_cpu); + } while ((val | MUX_APLL_SEL_MASK) != val); + + clrbits_le32(&clk->src_core1, MUX_MPLL_SEL_MASK); + do { + val = readl(&clk->mux_stat_core1); + } while ((val | MUX_MPLL_SEL_MASK) != val); + + clrbits_le32(&clk->src_top2, MUX_CPLL_SEL_MASK); + clrbits_le32(&clk->src_top2, MUX_EPLL_SEL_MASK); + clrbits_le32(&clk->src_top2, MUX_VPLL_SEL_MASK); + clrbits_le32(&clk->src_top2, MUX_GPLL_SEL_MASK); + tmp = MUX_CPLL_SEL_MASK | MUX_EPLL_SEL_MASK | MUX_VPLL_SEL_MASK + | MUX_GPLL_SEL_MASK; + do { + val = readl(&clk->mux_stat_top2); + } while ((val | tmp) != val); + + clrbits_le32(&clk->src_cdrex, MUX_BPLL_SEL_MASK); + do { + val = readl(&clk->mux_stat_cdrex); + } while ((val | MUX_BPLL_SEL_MASK) != val); + + /* PLL locktime */ + writel(mem->apll_pdiv * PLL_LOCK_FACTOR, &clk->apll_lock); + writel(mem->mpll_pdiv * PLL_LOCK_FACTOR, &clk->mpll_lock); + writel(mem->bpll_pdiv * PLL_LOCK_FACTOR, &clk->bpll_lock); + writel(mem->cpll_pdiv * PLL_LOCK_FACTOR, &clk->cpll_lock); + writel(mem->gpll_pdiv * PLL_X_LOCK_FACTOR, &clk->gpll_lock); + writel(mem->epll_pdiv * PLL_X_LOCK_FACTOR, &clk->epll_lock); + writel(mem->vpll_pdiv * PLL_X_LOCK_FACTOR, &clk->vpll_lock); + + writel(CLK_REG_DISABLE, &clk->pll_div2_sel); + + writel(MUX_HPM_SEL_MASK, &clk->src_cpu); + do { + val = readl(&clk->mux_stat_cpu); + } while ((val | HPM_SEL_SCLK_MPLL) != val); + + val = arm_clk_ratio->arm2_ratio << 28 + | arm_clk_ratio->apll_ratio << 24 + | arm_clk_ratio->pclk_dbg_ratio << 20 + | arm_clk_ratio->atb_ratio << 16 + | arm_clk_ratio->periph_ratio << 12 + | arm_clk_ratio->acp_ratio << 8 + | arm_clk_ratio->cpud_ratio << 4 + | arm_clk_ratio->arm_ratio; + writel(val, &clk->div_cpu0); + do { + val = readl(&clk->div_stat_cpu0); + } while (0 != val); + + writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1); + do { + val = readl(&clk->div_stat_cpu1); + } while (0 != val); + + /* Set APLL */ + writel(APLL_CON1_VAL, &clk->apll_con1); + val = set_pll(arm_clk_ratio->apll_mdiv, arm_clk_ratio->apll_pdiv, + arm_clk_ratio->apll_sdiv); + writel(val, &clk->apll_con0); + while ((readl(&clk->apll_con0) & APLL_CON0_LOCKED) == 0) + ; + + /* Set MPLL */ + writel(MPLL_CON1_VAL, &clk->mpll_con1); + val = set_pll(mem->mpll_mdiv, mem->mpll_pdiv, mem->mpll_sdiv); + writel(val, &clk->mpll_con0); + while ((readl(&clk->mpll_con0) & MPLL_CON0_LOCKED) == 0) + ; + + /* Set BPLL */ + writel(BPLL_CON1_VAL, &clk->bpll_con1); + val = set_pll(mem->bpll_mdiv, mem->bpll_pdiv, mem->bpll_sdiv); + writel(val, &clk->bpll_con0); + while ((readl(&clk->bpll_con0) & BPLL_CON0_LOCKED) == 0) + ; + + /* Set CPLL */ + writel(CPLL_CON1_VAL, &clk->cpll_con1); + val = set_pll(mem->cpll_mdiv, mem->cpll_pdiv, mem->cpll_sdiv); + writel(val, &clk->cpll_con0); + while ((readl(&clk->cpll_con0) & CPLL_CON0_LOCKED) == 0) + ; + + /* Set GPLL */ + writel(GPLL_CON1_VAL, &clk->gpll_con1); + val = set_pll(mem->gpll_mdiv, mem->gpll_pdiv, mem->gpll_sdiv); + writel(val, &clk->gpll_con0); + while ((readl(&clk->gpll_con0) & GPLL_CON0_LOCKED) == 0) + ; + + /* Set EPLL */ + writel(EPLL_CON2_VAL, &clk->epll_con2); + writel(EPLL_CON1_VAL, &clk->epll_con1); + val = set_pll(mem->epll_mdiv, mem->epll_pdiv, mem->epll_sdiv); + writel(val, &clk->epll_con0); + while ((readl(&clk->epll_con0) & EPLL_CON0_LOCKED) == 0) + ; + + /* Set VPLL */ + writel(VPLL_CON2_VAL, &clk->vpll_con2); + writel(VPLL_CON1_VAL, &clk->vpll_con1); + val = set_pll(mem->vpll_mdiv, mem->vpll_pdiv, mem->vpll_sdiv); + writel(val, &clk->vpll_con0); + while ((readl(&clk->vpll_con0) & VPLL_CON0_LOCKED) == 0) + ; + + writel(CLK_SRC_CORE0_VAL, &clk->src_core0); + writel(CLK_DIV_CORE0_VAL, &clk->div_core0); + while (readl(&clk->div_stat_core0) != 0) + ; + + writel(CLK_DIV_CORE1_VAL, &clk->div_core1); + while (readl(&clk->div_stat_core1) != 0) + ; + + writel(CLK_DIV_SYSRGT_VAL, &clk->div_sysrgt); + while (readl(&clk->div_stat_sysrgt) != 0) + ; + + writel(CLK_DIV_ACP_VAL, &clk->div_acp); + while (readl(&clk->div_stat_acp) != 0) + ; + + writel(CLK_DIV_SYSLFT_VAL, &clk->div_syslft); + while (readl(&clk->div_stat_syslft) != 0) + ; + + writel(CLK_SRC_TOP0_VAL, &clk->src_top0); + writel(CLK_SRC_TOP1_VAL, &clk->src_top1); + writel(TOP2_VAL, &clk->src_top2); + writel(CLK_SRC_TOP3_VAL, &clk->src_top3); + + writel(CLK_DIV_TOP0_VAL, &clk->div_top0); + while (readl(&clk->div_stat_top0)) + ; + + writel(CLK_DIV_TOP1_VAL, &clk->div_top1); + while (readl(&clk->div_stat_top1)) + ; + + writel(CLK_SRC_LEX_VAL, &clk->src_lex); + while (1) { + val = readl(&clk->mux_stat_lex); + if (val == (val | 1)) + break; + } + + writel(CLK_DIV_LEX_VAL, &clk->div_lex); + while (readl(&clk->div_stat_lex)) + ; + + writel(CLK_DIV_R0X_VAL, &clk->div_r0x); + while (readl(&clk->div_stat_r0x)) + ; + + writel(CLK_DIV_R0X_VAL, &clk->div_r0x); + while (readl(&clk->div_stat_r0x)) + ; + + writel(CLK_DIV_R1X_VAL, &clk->div_r1x); + while (readl(&clk->div_stat_r1x)) + ; + + writel(CLK_REG_DISABLE, &clk->src_cdrex); + + writel(CLK_DIV_CDREX_VAL, &clk->div_cdrex); + while (readl(&clk->div_stat_cdrex)) + ; + + val = readl(&clk->src_cpu); + val |= CLK_SRC_CPU_VAL; + writel(val, &clk->src_cpu); + + val = readl(&clk->src_top2); + val |= CLK_SRC_TOP2_VAL; + writel(val, &clk->src_top2); + + val = readl(&clk->src_core1); + val |= CLK_SRC_CORE1_VAL; + writel(val, &clk->src_core1); + + writel(CLK_SRC_FSYS0_VAL, &clk->src_fsys); + writel(CLK_DIV_FSYS0_VAL, &clk->div_fsys0); + while (readl(&clk->div_stat_fsys0)) + ; + + writel(CLK_REG_DISABLE, &clk->clkout_cmu_cpu); + writel(CLK_REG_DISABLE, &clk->clkout_cmu_core); + writel(CLK_REG_DISABLE, &clk->clkout_cmu_acp); + writel(CLK_REG_DISABLE, &clk->clkout_cmu_top); + writel(CLK_REG_DISABLE, &clk->clkout_cmu_lex); + writel(CLK_REG_DISABLE, &clk->clkout_cmu_r0x); + writel(CLK_REG_DISABLE, &clk->clkout_cmu_r1x); + writel(CLK_REG_DISABLE, &clk->clkout_cmu_cdrex); + + writel(CLK_SRC_PERIC0_VAL, &clk->src_peric0); + writel(CLK_DIV_PERIC0_VAL, &clk->div_peric0); + + writel(CLK_SRC_PERIC1_VAL, &clk->src_peric1); + writel(CLK_DIV_PERIC1_VAL, &clk->div_peric1); + writel(CLK_DIV_PERIC2_VAL, &clk->div_peric2); + writel(CLK_DIV_PERIC3_VAL, &clk->div_peric3); + + writel(SCLK_SRC_ISP_VAL, &clk->sclk_src_isp); + writel(SCLK_DIV_ISP_VAL, &clk->sclk_div_isp); + writel(CLK_DIV_ISP0_VAL, &clk->div_isp0); + writel(CLK_DIV_ISP1_VAL, &clk->div_isp1); + writel(CLK_DIV_ISP2_VAL, &clk->div_isp2); + + /* FIMD1 SRC CLK SELECTION */ + writel(CLK_SRC_DISP1_0_VAL, &clk->src_disp1_0); + + val = MMC2_PRE_RATIO_VAL << MMC2_PRE_RATIO_OFFSET + | MMC2_RATIO_VAL << MMC2_RATIO_OFFSET + | MMC3_PRE_RATIO_VAL << MMC3_PRE_RATIO_OFFSET + | MMC3_RATIO_VAL << MMC3_RATIO_OFFSET; + writel(val, &clk->div_fsys2); +} + +static void exynos5420_system_clock_init(void) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + struct mem_timings *mem; + struct arm_clk_ratios *arm_clk_ratio; + u32 val; + + mem = clock_get_mem_timings(); + arm_clk_ratio = get_arm_ratios(); + + /* PLL locktime */ + writel(arm_clk_ratio->apll_pdiv * PLL_LOCK_FACTOR, &clk->apll_lock); + writel(mem->mpll_pdiv * PLL_LOCK_FACTOR, &clk->mpll_lock); + writel(mem->bpll_pdiv * PLL_LOCK_FACTOR, &clk->bpll_lock); + writel(mem->cpll_pdiv * PLL_LOCK_FACTOR, &clk->cpll_lock); + writel(mem->dpll_pdiv * PLL_LOCK_FACTOR, &clk->dpll_lock); + writel(mem->epll_pdiv * PLL_X_LOCK_FACTOR, &clk->epll_lock); + writel(mem->vpll_pdiv * PLL_LOCK_FACTOR, &clk->vpll_lock); + writel(mem->ipll_pdiv * PLL_LOCK_FACTOR, &clk->ipll_lock); + writel(mem->spll_pdiv * PLL_LOCK_FACTOR, &clk->spll_lock); + writel(mem->kpll_pdiv * PLL_LOCK_FACTOR, &clk->kpll_lock); + + setbits_le32(&clk->src_cpu, MUX_HPM_SEL_MASK); + + writel(0, &clk->src_top6); + + writel(0, &clk->src_cdrex); + writel(SRC_KFC_HPM_SEL, &clk->src_kfc); + writel(HPM_RATIO, &clk->div_cpu1); + writel(CLK_DIV_CPU0_VAL, &clk->div_cpu0); + + /* switch A15 clock source to OSC clock before changing APLL */ + clrbits_le32(&clk->src_cpu, APLL_FOUT); + + /* Set APLL */ + writel(APLL_CON1_VAL, &clk->apll_con1); + val = set_pll(arm_clk_ratio->apll_mdiv, + arm_clk_ratio->apll_pdiv, + arm_clk_ratio->apll_sdiv); + writel(val, &clk->apll_con0); + while ((readl(&clk->apll_con0) & PLL_LOCKED) == 0) + ; + + /* now it is safe to switch to APLL */ + setbits_le32(&clk->src_cpu, APLL_FOUT); + + writel(SRC_KFC_HPM_SEL, &clk->src_kfc); + writel(CLK_DIV_KFC_VAL, &clk->div_kfc0); + + /* switch A7 clock source to OSC clock before changing KPLL */ + clrbits_le32(&clk->src_kfc, KPLL_FOUT); + + /* Set KPLL*/ + writel(KPLL_CON1_VAL, &clk->kpll_con1); + val = set_pll(mem->kpll_mdiv, mem->kpll_pdiv, mem->kpll_sdiv); + writel(val, &clk->kpll_con0); + while ((readl(&clk->kpll_con0) & PLL_LOCKED) == 0) + ; + + /* now it is safe to switch to KPLL */ + setbits_le32(&clk->src_kfc, KPLL_FOUT); + + /* Set MPLL */ + writel(MPLL_CON1_VAL, &clk->mpll_con1); + val = set_pll(mem->mpll_mdiv, mem->mpll_pdiv, mem->mpll_sdiv); + writel(val, &clk->mpll_con0); + while ((readl(&clk->mpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set DPLL */ + writel(DPLL_CON1_VAL, &clk->dpll_con1); + val = set_pll(mem->dpll_mdiv, mem->dpll_pdiv, mem->dpll_sdiv); + writel(val, &clk->dpll_con0); + while ((readl(&clk->dpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set EPLL */ + writel(EPLL_CON2_VAL, &clk->epll_con2); + writel(EPLL_CON1_VAL, &clk->epll_con1); + val = set_pll(mem->epll_mdiv, mem->epll_pdiv, mem->epll_sdiv); + writel(val, &clk->epll_con0); + while ((readl(&clk->epll_con0) & PLL_LOCKED) == 0) + ; + + /* Set CPLL */ + writel(CPLL_CON1_VAL, &clk->cpll_con1); + val = set_pll(mem->cpll_mdiv, mem->cpll_pdiv, mem->cpll_sdiv); + writel(val, &clk->cpll_con0); + while ((readl(&clk->cpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set IPLL */ + writel(IPLL_CON1_VAL, &clk->ipll_con1); + val = set_pll(mem->ipll_mdiv, mem->ipll_pdiv, mem->ipll_sdiv); + writel(val, &clk->ipll_con0); + while ((readl(&clk->ipll_con0) & PLL_LOCKED) == 0) + ; + + /* Set VPLL */ + writel(VPLL_CON1_VAL, &clk->vpll_con1); + val = set_pll(mem->vpll_mdiv, mem->vpll_pdiv, mem->vpll_sdiv); + writel(val, &clk->vpll_con0); + while ((readl(&clk->vpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set BPLL */ + writel(BPLL_CON1_VAL, &clk->bpll_con1); + val = set_pll(mem->bpll_mdiv, mem->bpll_pdiv, mem->bpll_sdiv); + writel(val, &clk->bpll_con0); + while ((readl(&clk->bpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set SPLL */ + writel(SPLL_CON1_VAL, &clk->spll_con1); + val = set_pll(mem->spll_mdiv, mem->spll_pdiv, mem->spll_sdiv); + writel(val, &clk->spll_con0); + while ((readl(&clk->spll_con0) & PLL_LOCKED) == 0) + ; + + writel(CLK_DIV_CDREX0_VAL, &clk->div_cdrex0); + writel(CLK_DIV_CDREX1_VAL, &clk->div_cdrex1); + + writel(CLK_SRC_TOP0_VAL, &clk->src_top0); + writel(CLK_SRC_TOP1_VAL, &clk->src_top1); + writel(CLK_SRC_TOP2_VAL, &clk->src_top2); + writel(CLK_SRC_TOP7_VAL, &clk->src_top7); + + writel(CLK_DIV_TOP0_VAL, &clk->div_top0); + writel(CLK_DIV_TOP1_VAL, &clk->div_top1); + writel(CLK_DIV_TOP2_VAL, &clk->div_top2); + + writel(0, &clk->src_top10); + writel(0, &clk->src_top11); + writel(0, &clk->src_top12); + + writel(CLK_SRC_TOP3_VAL, &clk->src_top3); + writel(CLK_SRC_TOP4_VAL, &clk->src_top4); + writel(CLK_SRC_TOP5_VAL, &clk->src_top5); + + /* DISP1 BLK CLK SELECTION */ + writel(CLK_SRC_DISP1_0_VAL, &clk->src_disp10); + writel(CLK_DIV_DISP1_0_VAL, &clk->div_disp10); + + /* AUDIO BLK */ + writel(AUDIO0_SEL_EPLL, &clk->src_mau); + writel(DIV_MAU_VAL, &clk->div_mau); + + /* FSYS */ + writel(CLK_SRC_FSYS0_VAL, &clk->src_fsys); + writel(CLK_DIV_FSYS0_VAL, &clk->div_fsys0); + writel(CLK_DIV_FSYS1_VAL, &clk->div_fsys1); + writel(CLK_DIV_FSYS2_VAL, &clk->div_fsys2); + + writel(CLK_SRC_ISP_VAL, &clk->src_isp); + writel(CLK_DIV_ISP0_VAL, &clk->div_isp0); + writel(CLK_DIV_ISP1_VAL, &clk->div_isp1); + + writel(CLK_SRC_PERIC0_VAL, &clk->src_peric0); + writel(CLK_SRC_PERIC1_VAL, &clk->src_peric1); + + writel(CLK_DIV_PERIC0_VAL, &clk->div_peric0); + writel(CLK_DIV_PERIC1_VAL, &clk->div_peric1); + writel(CLK_DIV_PERIC2_VAL, &clk->div_peric2); + writel(CLK_DIV_PERIC3_VAL, &clk->div_peric3); + writel(CLK_DIV_PERIC4_VAL, &clk->div_peric4); + + writel(CLK_DIV_CPERI1_VAL, &clk->div_cperi1); + + writel(CLK_DIV2_RATIO, &clk->clkdiv2_ratio); + writel(CLK_DIV4_RATIO, &clk->clkdiv4_ratio); + writel(CLK_DIV_G2D, &clk->div_g2d); + + writel(CLK_SRC_TOP6_VAL, &clk->src_top6); + writel(CLK_SRC_CDREX_VAL, &clk->src_cdrex); + writel(CLK_SRC_KFC_VAL, &clk->src_kfc); +} + +void system_clock_init(void) +{ + if (proid_is_exynos5420()) + exynos5420_system_clock_init(); + else + exynos5250_system_clock_init(); +} + +void clock_init_dp_clock(void) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + + /* DP clock enable */ + setbits_le32(&clk->gate_ip_disp1, CLK_GATE_DP1_ALLOW); + + /* We run DP at 267 Mhz */ + setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1); +} + +/* + * Set clock divisor value for booting from EMMC. + * Set DWMMC channel-0 clk div to operate mmc0 device at 50MHz. + */ +void emmc_boot_clk_div_set(void) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned int div_mmc; + + div_mmc = readl((unsigned int) &clk->div_fsys1) & ~FSYS1_MMC0_DIV_MASK; + div_mmc |= FSYS1_MMC0_DIV_VAL; + writel(div_mmc, (unsigned int) &clk->div_fsys1); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/common_setup.h b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/common_setup.h new file mode 100644 index 000000000..e6318c036 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/common_setup.h @@ -0,0 +1,45 @@ +/* + * Common APIs for EXYNOS based board + * + * Copyright (C) 2013 Samsung Electronics + * Rajeshwari Shinde <rajeshwari.s@samsung.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#define DMC_OFFSET 0x10000 + +/* + * Memory initialization + * + * @param reset Reset PHY during initialization. + */ +void mem_ctrl_init(int reset); + + /* System Clock initialization */ +void system_clock_init(void); + +/* + * Init subsystems according to the reset status + * + * @return 0 for a normal boot, non-zero for a resume + */ +int do_lowlevel_init(void); + +void sdelay(unsigned long); diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/config.mk b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/config.mk new file mode 100644 index 000000000..ee0d2dab7 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/config.mk @@ -0,0 +1,7 @@ +# +# Copyright (C) Albert ARIBAUD <albert.u.boot@aribaud.net> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +SPL_OBJCFLAGS += -j .machine_param diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/dmc_common.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/dmc_common.c new file mode 100644 index 000000000..cca925e42 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/dmc_common.c @@ -0,0 +1,176 @@ +/* + * Mem setup common file for different types of DDR present on Exynos boards. + * + * Copyright (C) 2012 Samsung Electronics + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/spl.h> + +#include "clock_init.h" +#include "common_setup.h" +#include "exynos5_setup.h" + +#define ZQ_INIT_TIMEOUT 10000 + +int dmc_config_zq(struct mem_timings *mem, uint32_t *phy0_con16, + uint32_t *phy1_con16, uint32_t *phy0_con17, + uint32_t *phy1_con17) +{ + unsigned long val = 0; + int i; + + /* + * ZQ Calibration: + * Select Driver Strength, + * long calibration for manual calibration + */ + val = PHY_CON16_RESET_VAL; + val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT; + val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT; + val |= ZQ_CLK_DIV_EN; + writel(val, phy0_con16); + writel(val, phy1_con16); + + /* Disable termination */ + if (mem->zq_mode_noterm) + val |= PHY_CON16_ZQ_MODE_NOTERM_MASK; + writel(val, phy0_con16); + writel(val, phy1_con16); + + /* ZQ_MANUAL_START: Enable */ + val |= ZQ_MANUAL_STR; + writel(val, phy0_con16); + writel(val, phy1_con16); + + /* ZQ_MANUAL_START: Disable */ + val &= ~ZQ_MANUAL_STR; + + /* + * Since we are manaully calibrating the ZQ values, + * we are looping for the ZQ_init to complete. + */ + i = ZQ_INIT_TIMEOUT; + while ((readl(phy0_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { + sdelay(100); + i--; + } + if (!i) + return -1; + writel(val, phy0_con16); + + i = ZQ_INIT_TIMEOUT; + while ((readl(phy1_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { + sdelay(100); + i--; + } + if (!i) + return -1; + writel(val, phy1_con16); + + return 0; +} + +void update_reset_dll(uint32_t *phycontrol0, enum ddr_mode mode) +{ + unsigned long val; + + if (mode == DDR_MODE_DDR3) { + val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE; + writel(val, phycontrol0); + } + + /* Update DLL Information: Force DLL Resyncronization */ + val = readl(phycontrol0); + val |= FP_RSYNC; + writel(val, phycontrol0); + + /* Reset Force DLL Resyncronization */ + val = readl(phycontrol0); + val &= ~FP_RSYNC; + writel(val, phycontrol0); +} + +void dmc_config_mrs(struct mem_timings *mem, uint32_t *directcmd) +{ + int channel, chip; + + for (channel = 0; channel < mem->dmc_channels; channel++) { + unsigned long mask; + + mask = channel << DIRECT_CMD_CHANNEL_SHIFT; + for (chip = 0; chip < mem->chips_to_configure; chip++) { + int i; + + mask |= chip << DIRECT_CMD_CHIP_SHIFT; + + /* Sending NOP command */ + writel(DIRECT_CMD_NOP | mask, directcmd); + + /* + * TODO(alim.akhtar@samsung.com): Do we need these + * delays? This one and the next were not there for + * DDR3. + */ + sdelay(0x10000); + + /* Sending EMRS/MRS commands */ + for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) { + writel(mem->direct_cmd_msr[i] | mask, + directcmd); + sdelay(0x10000); + } + + if (mem->send_zq_init) { + /* Sending ZQINIT command */ + writel(DIRECT_CMD_ZQINIT | mask, + directcmd); + + sdelay(10000); + } + } + } +} + +void dmc_config_prech(struct mem_timings *mem, uint32_t *directcmd) +{ + int channel, chip; + + for (channel = 0; channel < mem->dmc_channels; channel++) { + unsigned long mask; + + mask = channel << DIRECT_CMD_CHANNEL_SHIFT; + for (chip = 0; chip < mem->chips_per_channel; chip++) { + mask |= chip << DIRECT_CMD_CHIP_SHIFT; + + /* PALL (all banks precharge) CMD */ + writel(DIRECT_CMD_PALL | mask, directcmd); + sdelay(0x10000); + } + } +} + +void mem_ctrl_init(int reset) +{ + struct spl_machine_param *param = spl_get_machine_params(); + struct mem_timings *mem; + int ret; + + mem = clock_get_mem_timings(); + + /* If there are any other memory variant, add their init call below */ + if (param->mem_type == DDR_MODE_DDR3) { + ret = ddr3_mem_ctrl_init(mem, param->mem_iv_size, reset); + if (ret) { + /* will hang if failed to init memory control */ + while (1) + ; + } + } else { + /* will hang if unknow memory type */ + while (1) + ; + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c new file mode 100644 index 000000000..487e6f423 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c @@ -0,0 +1,636 @@ +/* + * DDR3 mem setup file for board based on EXYNOS5 + * + * Copyright (C) 2012 Samsung Electronics + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/cpu.h> +#include <asm/arch/dmc.h> +#include <asm/arch/power.h> +#include "common_setup.h" +#include "exynos5_setup.h" +#include "clock_init.h" + +#define TIMEOUT 10000 + +#ifdef CONFIG_EXYNOS5250 +static void reset_phy_ctrl(void) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + + writel(DDR3PHY_CTRL_PHY_RESET_OFF, &clk->lpddr3phy_ctrl); + writel(DDR3PHY_CTRL_PHY_RESET, &clk->lpddr3phy_ctrl); +} + +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, + int reset) +{ + unsigned int val; + struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl; + struct exynos5_dmc *dmc; + int i; + + phy0_ctrl = (struct exynos5_phy_control *)samsung_get_base_dmc_phy(); + phy1_ctrl = (struct exynos5_phy_control *)(samsung_get_base_dmc_phy() + + DMC_OFFSET); + dmc = (struct exynos5_dmc *)samsung_get_base_dmc_ctrl(); + + if (reset) + reset_phy_ctrl(); + + /* Set Impedance Output Driver */ + val = (mem->impedance << CA_CK_DRVR_DS_OFFSET) | + (mem->impedance << CA_CKE_DRVR_DS_OFFSET) | + (mem->impedance << CA_CS_DRVR_DS_OFFSET) | + (mem->impedance << CA_ADR_DRVR_DS_OFFSET); + writel(val, &phy0_ctrl->phy_con39); + writel(val, &phy1_ctrl->phy_con39); + + /* Set Read Latency and Burst Length for PHY0 and PHY1 */ + val = (mem->ctrl_bstlen << PHY_CON42_CTRL_BSTLEN_SHIFT) | + (mem->ctrl_rdlat << PHY_CON42_CTRL_RDLAT_SHIFT); + writel(val, &phy0_ctrl->phy_con42); + writel(val, &phy1_ctrl->phy_con42); + + /* ZQ Calibration */ + if (dmc_config_zq(mem, &phy0_ctrl->phy_con16, &phy1_ctrl->phy_con16, + &phy0_ctrl->phy_con17, &phy1_ctrl->phy_con17)) + return SETUP_ERR_ZQ_CALIBRATION_FAILURE; + + /* DQ Signal */ + writel(mem->phy0_pulld_dqs, &phy0_ctrl->phy_con14); + writel(mem->phy1_pulld_dqs, &phy1_ctrl->phy_con14); + + writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT) + | (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT), + &dmc->concontrol); + + update_reset_dll(&dmc->phycontrol0, DDR_MODE_DDR3); + + /* DQS Signal */ + writel(mem->phy0_dqs, &phy0_ctrl->phy_con4); + writel(mem->phy1_dqs, &phy1_ctrl->phy_con4); + + writel(mem->phy0_dq, &phy0_ctrl->phy_con6); + writel(mem->phy1_dq, &phy1_ctrl->phy_con6); + + writel(mem->phy0_tFS, &phy0_ctrl->phy_con10); + writel(mem->phy1_tFS, &phy1_ctrl->phy_con10); + + val = (mem->ctrl_start_point << PHY_CON12_CTRL_START_POINT_SHIFT) | + (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | + (mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) | + (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); + writel(val, &phy0_ctrl->phy_con12); + writel(val, &phy1_ctrl->phy_con12); + + /* Start DLL locking */ + writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT), + &phy0_ctrl->phy_con12); + writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT), + &phy1_ctrl->phy_con12); + + update_reset_dll(&dmc->phycontrol0, DDR_MODE_DDR3); + + writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), + &dmc->concontrol); + + /* Memory Channel Inteleaving Size */ + writel(mem->iv_size, &dmc->ivcontrol); + + writel(mem->memconfig, &dmc->memconfig0); + writel(mem->memconfig, &dmc->memconfig1); + writel(mem->membaseconfig0, &dmc->membaseconfig0); + writel(mem->membaseconfig1, &dmc->membaseconfig1); + + /* Precharge Configuration */ + writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, + &dmc->prechconfig); + + /* Power Down mode Configuration */ + writel(mem->dpwrdn_cyc << PWRDNCONFIG_DPWRDN_CYC_SHIFT | + mem->dsref_cyc << PWRDNCONFIG_DSREF_CYC_SHIFT, + &dmc->pwrdnconfig); + + /* TimingRow, TimingData, TimingPower and Timingaref + * values as per Memory AC parameters + */ + writel(mem->timing_ref, &dmc->timingref); + writel(mem->timing_row, &dmc->timingrow); + writel(mem->timing_data, &dmc->timingdata); + writel(mem->timing_power, &dmc->timingpower); + + /* Send PALL command */ + dmc_config_prech(mem, &dmc->directcmd); + + /* Send NOP, MRS and ZQINIT commands */ + dmc_config_mrs(mem, &dmc->directcmd); + + if (mem->gate_leveling_enable) { + val = PHY_CON0_RESET_VAL; + val |= P0_CMD_EN; + writel(val, &phy0_ctrl->phy_con0); + writel(val, &phy1_ctrl->phy_con0); + + val = PHY_CON2_RESET_VAL; + val |= INIT_DESKEW_EN; + writel(val, &phy0_ctrl->phy_con2); + writel(val, &phy1_ctrl->phy_con2); + + val = PHY_CON0_RESET_VAL; + val |= P0_CMD_EN; + val |= BYTE_RDLVL_EN; + writel(val, &phy0_ctrl->phy_con0); + writel(val, &phy1_ctrl->phy_con0); + + val = (mem->ctrl_start_point << + PHY_CON12_CTRL_START_POINT_SHIFT) | + (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | + (mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) | + (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) | + (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); + writel(val, &phy0_ctrl->phy_con12); + writel(val, &phy1_ctrl->phy_con12); + + val = PHY_CON2_RESET_VAL; + val |= INIT_DESKEW_EN; + val |= RDLVL_GATE_EN; + writel(val, &phy0_ctrl->phy_con2); + writel(val, &phy1_ctrl->phy_con2); + + val = PHY_CON0_RESET_VAL; + val |= P0_CMD_EN; + val |= BYTE_RDLVL_EN; + val |= CTRL_SHGATE; + writel(val, &phy0_ctrl->phy_con0); + writel(val, &phy1_ctrl->phy_con0); + + val = PHY_CON1_RESET_VAL; + val &= ~(CTRL_GATEDURADJ_MASK); + writel(val, &phy0_ctrl->phy_con1); + writel(val, &phy1_ctrl->phy_con1); + + writel(CTRL_RDLVL_GATE_ENABLE, &dmc->rdlvl_config); + i = TIMEOUT; + while ((readl(&dmc->phystatus) & + (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1)) != + (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1) && i > 0) { + /* + * TODO(waihong): Comment on how long this take to + * timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + writel(CTRL_RDLVL_GATE_DISABLE, &dmc->rdlvl_config); + + writel(0, &phy0_ctrl->phy_con14); + writel(0, &phy1_ctrl->phy_con14); + + val = (mem->ctrl_start_point << + PHY_CON12_CTRL_START_POINT_SHIFT) | + (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | + (mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) | + (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) | + (mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) | + (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); + writel(val, &phy0_ctrl->phy_con12); + writel(val, &phy1_ctrl->phy_con12); + + update_reset_dll(&dmc->phycontrol0, DDR_MODE_DDR3); + } + + /* Send PALL command */ + dmc_config_prech(mem, &dmc->directcmd); + + writel(mem->memcontrol, &dmc->memcontrol); + + /* Set DMC Concontrol and enable auto-refresh counter */ + writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT) + | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT), &dmc->concontrol); + return 0; +} +#endif + +#ifdef CONFIG_EXYNOS5420 +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, + int reset) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + struct exynos5420_power *power = + (struct exynos5420_power *)samsung_get_base_power(); + struct exynos5420_phy_control *phy0_ctrl, *phy1_ctrl; + struct exynos5420_dmc *drex0, *drex1; + struct exynos5420_tzasc *tzasc0, *tzasc1; + uint32_t val, n_lock_r, n_lock_w_phy0, n_lock_w_phy1; + int chip; + int i; + + phy0_ctrl = (struct exynos5420_phy_control *)samsung_get_base_dmc_phy(); + phy1_ctrl = (struct exynos5420_phy_control *)(samsung_get_base_dmc_phy() + + DMC_OFFSET); + drex0 = (struct exynos5420_dmc *)samsung_get_base_dmc_ctrl(); + drex1 = (struct exynos5420_dmc *)(samsung_get_base_dmc_ctrl() + + DMC_OFFSET); + tzasc0 = (struct exynos5420_tzasc *)samsung_get_base_dmc_tzasc(); + tzasc1 = (struct exynos5420_tzasc *)(samsung_get_base_dmc_tzasc() + + DMC_OFFSET); + + /* Enable PAUSE for DREX */ + setbits_le32(&clk->pause, ENABLE_BIT); + + /* Enable BYPASS mode */ + setbits_le32(&clk->bpll_con1, BYPASS_EN); + + writel(MUX_BPLL_SEL_FOUTBPLL, &clk->src_cdrex); + do { + val = readl(&clk->mux_stat_cdrex); + val &= BPLL_SEL_MASK; + } while (val != FOUTBPLL); + + clrbits_le32(&clk->bpll_con1, BYPASS_EN); + + /* Specify the DDR memory type as DDR3 */ + val = readl(&phy0_ctrl->phy_con0); + val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK << PHY_CON0_CTRL_DDR_MODE_SHIFT); + val |= (DDR_MODE_DDR3 << PHY_CON0_CTRL_DDR_MODE_SHIFT); + writel(val, &phy0_ctrl->phy_con0); + + val = readl(&phy1_ctrl->phy_con0); + val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK << PHY_CON0_CTRL_DDR_MODE_SHIFT); + val |= (DDR_MODE_DDR3 << PHY_CON0_CTRL_DDR_MODE_SHIFT); + writel(val, &phy1_ctrl->phy_con0); + + /* Set Read Latency and Burst Length for PHY0 and PHY1 */ + val = (mem->ctrl_bstlen << PHY_CON42_CTRL_BSTLEN_SHIFT) | + (mem->ctrl_rdlat << PHY_CON42_CTRL_RDLAT_SHIFT); + writel(val, &phy0_ctrl->phy_con42); + writel(val, &phy1_ctrl->phy_con42); + + val = readl(&phy0_ctrl->phy_con26); + val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET); + val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET); + writel(val, &phy0_ctrl->phy_con26); + + val = readl(&phy1_ctrl->phy_con26); + val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET); + val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET); + writel(val, &phy1_ctrl->phy_con26); + + /* + * Set Driver strength for CK, CKE, CS & CA to 0x7 + * Set Driver strength for Data Slice 0~3 to 0x7 + */ + val = (0x7 << CA_CK_DRVR_DS_OFFSET) | (0x7 << CA_CKE_DRVR_DS_OFFSET) | + (0x7 << CA_CS_DRVR_DS_OFFSET) | (0x7 << CA_ADR_DRVR_DS_OFFSET); + val |= (0x7 << DA_3_DS_OFFSET) | (0x7 << DA_2_DS_OFFSET) | + (0x7 << DA_1_DS_OFFSET) | (0x7 << DA_0_DS_OFFSET); + writel(val, &phy0_ctrl->phy_con39); + writel(val, &phy1_ctrl->phy_con39); + + /* ZQ Calibration */ + if (dmc_config_zq(mem, &phy0_ctrl->phy_con16, &phy1_ctrl->phy_con16, + &phy0_ctrl->phy_con17, &phy1_ctrl->phy_con17)) + return SETUP_ERR_ZQ_CALIBRATION_FAILURE; + + clrbits_le32(&phy0_ctrl->phy_con16, ZQ_CLK_DIV_EN); + clrbits_le32(&phy1_ctrl->phy_con16, ZQ_CLK_DIV_EN); + + /* DQ Signal */ + val = readl(&phy0_ctrl->phy_con14); + val |= mem->phy0_pulld_dqs; + writel(val, &phy0_ctrl->phy_con14); + val = readl(&phy1_ctrl->phy_con14); + val |= mem->phy1_pulld_dqs; + writel(val, &phy1_ctrl->phy_con14); + + val = MEM_TERM_EN | PHY_TERM_EN; + writel(val, &drex0->phycontrol0); + writel(val, &drex1->phycontrol0); + + writel(mem->concontrol | + (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), + &drex0->concontrol); + writel(mem->concontrol | + (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), + &drex1->concontrol); + + do { + val = readl(&drex0->phystatus); + } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE); + do { + val = readl(&drex1->phystatus); + } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE); + + clrbits_le32(&drex0->concontrol, DFI_INIT_START); + clrbits_le32(&drex1->concontrol, DFI_INIT_START); + + update_reset_dll(&drex0->phycontrol0, DDR_MODE_DDR3); + update_reset_dll(&drex1->phycontrol0, DDR_MODE_DDR3); + + /* + * Set Base Address: + * 0x2000_0000 ~ 0x5FFF_FFFF + * 0x6000_0000 ~ 0x9FFF_FFFF + */ + /* MEMBASECONFIG0 */ + val = DMC_MEMBASECONFIGX_CHIP_BASE(DMC_CHIP_BASE_0) | + DMC_MEMBASECONFIGX_CHIP_MASK(DMC_CHIP_MASK); + writel(val, &tzasc0->membaseconfig0); + writel(val, &tzasc1->membaseconfig0); + + /* MEMBASECONFIG1 */ + val = DMC_MEMBASECONFIGX_CHIP_BASE(DMC_CHIP_BASE_1) | + DMC_MEMBASECONFIGX_CHIP_MASK(DMC_CHIP_MASK); + writel(val, &tzasc0->membaseconfig1); + writel(val, &tzasc1->membaseconfig1); + + /* + * Memory Channel Inteleaving Size + * Ares Channel interleaving = 128 bytes + */ + /* MEMCONFIG0/1 */ + writel(mem->memconfig, &tzasc0->memconfig0); + writel(mem->memconfig, &tzasc1->memconfig0); + writel(mem->memconfig, &tzasc0->memconfig1); + writel(mem->memconfig, &tzasc1->memconfig1); + + /* Precharge Configuration */ + writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, + &drex0->prechconfig0); + writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, + &drex1->prechconfig0); + + /* + * TimingRow, TimingData, TimingPower and Timingaref + * values as per Memory AC parameters + */ + writel(mem->timing_ref, &drex0->timingref); + writel(mem->timing_ref, &drex1->timingref); + writel(mem->timing_row, &drex0->timingrow0); + writel(mem->timing_row, &drex1->timingrow0); + writel(mem->timing_data, &drex0->timingdata0); + writel(mem->timing_data, &drex1->timingdata0); + writel(mem->timing_power, &drex0->timingpower0); + writel(mem->timing_power, &drex1->timingpower0); + + if (reset) { + /* + * Send NOP, MRS and ZQINIT commands + * Sending MRS command will reset the DRAM. We should not be + * reseting the DRAM after resume, this will lead to memory + * corruption as DRAM content is lost after DRAM reset + */ + dmc_config_mrs(mem, &drex0->directcmd); + dmc_config_mrs(mem, &drex1->directcmd); + } else { + /* + * During Suspend-Resume & S/W-Reset, as soon as PMU releases + * pad retention, CKE goes high. This causes memory contents + * not to be retained during DRAM initialization. Therfore, + * there is a new control register(0x100431e8[28]) which lets us + * release pad retention and retain the memory content until the + * initialization is complete. + */ + writel(PAD_RETENTION_DRAM_COREBLK_VAL, + &power->pad_retention_dram_coreblk_option); + do { + val = readl(&power->pad_retention_dram_status); + } while (val != 0x1); + + /* + * CKE PAD retention disables DRAM self-refresh mode. + * Send auto refresh command for DRAM refresh. + */ + for (i = 0; i < 128; i++) { + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(DIRECT_CMD_REFA | + (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(DIRECT_CMD_REFA | + (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + } + } + + if (mem->gate_leveling_enable) { + writel(PHY_CON0_RESET_VAL, &phy0_ctrl->phy_con0); + writel(PHY_CON0_RESET_VAL, &phy1_ctrl->phy_con0); + + setbits_le32(&phy0_ctrl->phy_con0, P0_CMD_EN); + setbits_le32(&phy1_ctrl->phy_con0, P0_CMD_EN); + + val = PHY_CON2_RESET_VAL; + val |= INIT_DESKEW_EN; + writel(val, &phy0_ctrl->phy_con2); + writel(val, &phy1_ctrl->phy_con2); + + val = readl(&phy0_ctrl->phy_con1); + val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET); + writel(val, &phy0_ctrl->phy_con1); + + val = readl(&phy1_ctrl->phy_con1); + val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET); + writel(val, &phy1_ctrl->phy_con1); + + n_lock_r = readl(&phy0_ctrl->phy_con13); + n_lock_w_phy0 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2; + n_lock_r = readl(&phy0_ctrl->phy_con12); + n_lock_r &= ~CTRL_DLL_ON; + n_lock_r |= n_lock_w_phy0; + writel(n_lock_r, &phy0_ctrl->phy_con12); + + n_lock_r = readl(&phy1_ctrl->phy_con13); + n_lock_w_phy1 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2; + n_lock_r = readl(&phy1_ctrl->phy_con12); + n_lock_r &= ~CTRL_DLL_ON; + n_lock_r |= n_lock_w_phy1; + writel(n_lock_r, &phy1_ctrl->phy_con12); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT) | 0x4; + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + setbits_le32(&phy0_ctrl->phy_con2, RDLVL_GATE_EN); + setbits_le32(&phy1_ctrl->phy_con2, RDLVL_GATE_EN); + + setbits_le32(&phy0_ctrl->phy_con0, CTRL_SHGATE); + setbits_le32(&phy1_ctrl->phy_con0, CTRL_SHGATE); + + val = readl(&phy0_ctrl->phy_con1); + val &= ~(CTRL_GATEDURADJ_MASK); + writel(val, &phy0_ctrl->phy_con1); + + val = readl(&phy1_ctrl->phy_con1); + val &= ~(CTRL_GATEDURADJ_MASK); + writel(val, &phy1_ctrl->phy_con1); + + writel(CTRL_RDLVL_GATE_ENABLE, &drex0->rdlvl_config); + i = TIMEOUT; + while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) != + RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take to + * timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + writel(CTRL_RDLVL_GATE_DISABLE, &drex0->rdlvl_config); + + writel(CTRL_RDLVL_GATE_ENABLE, &drex1->rdlvl_config); + i = TIMEOUT; + while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) != + RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take to + * timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + writel(CTRL_RDLVL_GATE_DISABLE, &drex1->rdlvl_config); + + writel(0, &phy0_ctrl->phy_con14); + writel(0, &phy1_ctrl->phy_con14); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT); + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + if (mem->read_leveling_enable) { + /* Set Read DQ Calibration */ + val = (0x3 << DIRECT_CMD_BANK_SHIFT) | 0x4; + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + val = readl(&phy0_ctrl->phy_con1); + val |= READ_LEVELLING_DDR3; + writel(val, &phy0_ctrl->phy_con1); + val = readl(&phy1_ctrl->phy_con1); + val |= READ_LEVELLING_DDR3; + writel(val, &phy1_ctrl->phy_con1); + + val = readl(&phy0_ctrl->phy_con2); + val |= (RDLVL_EN | RDLVL_INCR_ADJ); + writel(val, &phy0_ctrl->phy_con2); + val = readl(&phy1_ctrl->phy_con2); + val |= (RDLVL_EN | RDLVL_INCR_ADJ); + writel(val, &phy1_ctrl->phy_con2); + + setbits_le32(&drex0->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + i = TIMEOUT; + while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) + != RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take + * to timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + + clrbits_le32(&drex0->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + setbits_le32(&drex1->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + i = TIMEOUT; + while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) + != RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take + * to timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + + clrbits_le32(&drex1->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT); + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + update_reset_dll(&drex0->phycontrol0, DDR_MODE_DDR3); + update_reset_dll(&drex1->phycontrol0, DDR_MODE_DDR3); + } + + /* Common Settings for Leveling */ + val = PHY_CON12_RESET_VAL; + writel((val + n_lock_w_phy0), &phy0_ctrl->phy_con12); + writel((val + n_lock_w_phy1), &phy1_ctrl->phy_con12); + + setbits_le32(&phy0_ctrl->phy_con2, DLL_DESKEW_EN); + setbits_le32(&phy1_ctrl->phy_con2, DLL_DESKEW_EN); + } + + /* Send PALL command */ + dmc_config_prech(mem, &drex0->directcmd); + dmc_config_prech(mem, &drex1->directcmd); + + writel(mem->memcontrol, &drex0->memcontrol); + writel(mem->memcontrol, &drex1->memcontrol); + + /* + * Set DMC Concontrol: Enable auto-refresh counter, provide + * read data fetch cycles and enable DREX auto set powerdown + * for input buffer of I/O in none read memory state. + */ + writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)| + DMC_CONCONTROL_IO_PD_CON(0x2), + &drex0->concontrol); + writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)| + DMC_CONCONTROL_IO_PD_CON(0x2), + &drex1->concontrol); + + /* + * Enable Clock Gating Control for DMC + * this saves around 25 mw dmc power as compared to the power + * consumption without these bits enabled + */ + setbits_le32(&drex0->cgcontrol, DMC_INTERNAL_CG); + setbits_le32(&drex1->cgcontrol, DMC_INTERNAL_CG); + + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/dmc_init_exynos4.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/dmc_init_exynos4.c new file mode 100644 index 000000000..ecddc7268 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/dmc_init_exynos4.c @@ -0,0 +1,213 @@ +/* + * Memory setup for board based on EXYNOS4210 + * + * Copyright (C) 2013 Samsung Electronics + * Rajeshwari Shinde <rajeshwari.s@samsung.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <asm/arch/dmc.h> +#include "common_setup.h" +#include "exynos4_setup.h" + +struct mem_timings mem = { + .direct_cmd_msr = { + DIRECT_CMD1, DIRECT_CMD2, DIRECT_CMD3, DIRECT_CMD4 + }, + .timingref = TIMINGREF_VAL, + .timingrow = TIMINGROW_VAL, + .timingdata = TIMINGDATA_VAL, + .timingpower = TIMINGPOWER_VAL, + .zqcontrol = ZQ_CONTROL_VAL, + .control0 = CONTROL0_VAL, + .control1 = CONTROL1_VAL, + .control2 = CONTROL2_VAL, + .concontrol = CONCONTROL_VAL, + .prechconfig = PRECHCONFIG, + .memcontrol = MEMCONTROL_VAL, + .memconfig0 = MEMCONFIG0_VAL, + .memconfig1 = MEMCONFIG1_VAL, + .dll_resync = FORCE_DLL_RESYNC, + .dll_on = DLL_CONTROL_ON, +}; +static void phy_control_reset(int ctrl_no, struct exynos4_dmc *dmc) +{ + if (ctrl_no) { + writel((mem.control1 | (1 << mem.dll_resync)), + &dmc->phycontrol1); + writel((mem.control1 | (0 << mem.dll_resync)), + &dmc->phycontrol1); + } else { + writel((mem.control0 | (0 << mem.dll_on)), + &dmc->phycontrol0); + writel((mem.control0 | (1 << mem.dll_on)), + &dmc->phycontrol0); + } +} + +static void dmc_config_mrs(struct exynos4_dmc *dmc, int chip) +{ + int i; + unsigned long mask = 0; + + if (chip) + mask = DIRECT_CMD_CHIP1_SHIFT; + + for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) { + writel(mem.direct_cmd_msr[i] | mask, + &dmc->directcmd); + } +} + +static void dmc_init(struct exynos4_dmc *dmc) +{ + /* + * DLL Parameter Setting: + * Termination: Enable R/W + * Phase Delay for DQS Cleaning: 180' Shift + */ + writel(mem.control1, &dmc->phycontrol1); + + /* + * ZQ Calibration + * Termination: Disable + * Auto Calibration Start: Enable + */ + writel(mem.zqcontrol, &dmc->phyzqcontrol); + sdelay(0x100000); + + /* + * Update DLL Information: + * Force DLL Resyncronization + */ + phy_control_reset(1, dmc); + phy_control_reset(0, dmc); + + /* Set DLL Parameters */ + writel(mem.control1, &dmc->phycontrol1); + + /* DLL Start */ + writel((mem.control0 | CTRL_START | CTRL_DLL_ON), &dmc->phycontrol0); + + writel(mem.control2, &dmc->phycontrol2); + + /* Set Clock Ratio of Bus clock to Memory Clock */ + writel(mem.concontrol, &dmc->concontrol); + + /* + * Memor Burst length: 8 + * Number of chips: 2 + * Memory Bus width: 32 bit + * Memory Type: DDR3 + * Additional Latancy for PLL: 1 Cycle + */ + writel(mem.memcontrol, &dmc->memcontrol); + + writel(mem.memconfig0, &dmc->memconfig0); + writel(mem.memconfig1, &dmc->memconfig1); + + /* Config Precharge Policy */ + writel(mem.prechconfig, &dmc->prechconfig); + /* + * TimingAref, TimingRow, TimingData, TimingPower Setting: + * Values as per Memory AC Parameters + */ + writel(mem.timingref, &dmc->timingref); + writel(mem.timingrow, &dmc->timingrow); + writel(mem.timingdata, &dmc->timingdata); + writel(mem.timingpower, &dmc->timingpower); + + /* Chip0: NOP Command: Assert and Hold CKE to high level */ + writel(DIRECT_CMD_NOP, &dmc->directcmd); + sdelay(0x100000); + + /* Chip0: EMRS2, EMRS3, EMRS, MRS Commands Using Direct Command */ + dmc_config_mrs(dmc, 0); + sdelay(0x100000); + + /* Chip0: ZQINIT */ + writel(DIRECT_CMD_ZQ, &dmc->directcmd); + sdelay(0x100000); + + writel((DIRECT_CMD_NOP | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd); + sdelay(0x100000); + + /* Chip1: EMRS2, EMRS3, EMRS, MRS Commands Using Direct Command */ + dmc_config_mrs(dmc, 1); + sdelay(0x100000); + + /* Chip1: ZQINIT */ + writel((DIRECT_CMD_ZQ | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd); + sdelay(0x100000); + + phy_control_reset(1, dmc); + sdelay(0x100000); + + /* turn on DREX0, DREX1 */ + writel((mem.concontrol | AREF_EN), &dmc->concontrol); +} + +void mem_ctrl_init(int reset) +{ + struct exynos4_dmc *dmc; + + /* + * Async bridge configuration at CPU_core: + * 1: half_sync + * 0: full_sync + */ + writel(1, ASYNC_CONFIG); +#ifdef CONFIG_ORIGEN + /* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */ + writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE + + APB_SFR_INTERLEAVE_CONF_OFFSET); + /* Update MIU Configuration */ + writel(APB_SFR_ARBRITATION_CONF_VAL, EXYNOS4_MIU_BASE + + APB_SFR_ARBRITATION_CONF_OFFSET); +#else + writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE + + APB_SFR_INTERLEAVE_CONF_OFFSET); + writel(INTERLEAVE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE + + ABP_SFR_INTERLEAVE_ADDRMAP_START_OFFSET); + writel(INTERLEAVE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE + + ABP_SFR_INTERLEAVE_ADDRMAP_END_OFFSET); + writel(INTERLEAVE_ADDR_MAP_EN, EXYNOS4_MIU_BASE + + ABP_SFR_SLV_ADDRMAP_CONF_OFFSET); +#ifdef CONFIG_MIU_LINEAR + writel(SLAVE0_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE + + ABP_SFR_SLV0_SINGLE_ADDRMAP_START_OFFSET); + writel(SLAVE0_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE + + ABP_SFR_SLV0_SINGLE_ADDRMAP_END_OFFSET); + writel(SLAVE1_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE + + ABP_SFR_SLV1_SINGLE_ADDRMAP_START_OFFSET); + writel(SLAVE1_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE + + ABP_SFR_SLV1_SINGLE_ADDRMAP_END_OFFSET); + writel(APB_SFR_SLV_ADDR_MAP_CONF_VAL, EXYNOS4_MIU_BASE + + ABP_SFR_SLV_ADDRMAP_CONF_OFFSET); +#endif +#endif + /* DREX0 */ + dmc = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl(); + dmc_init(dmc); + dmc = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl() + + DMC_OFFSET); + dmc_init(dmc); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/exynos4_setup.h b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/exynos4_setup.h new file mode 100644 index 000000000..b633e5660 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/exynos4_setup.h @@ -0,0 +1,578 @@ +/* + * Machine Specific Values for EXYNOS4012 based board + * + * Copyright (C) 2011 Samsung Electronics + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ORIGEN_SETUP_H +#define _ORIGEN_SETUP_H + +#include <config.h> +#include <version.h> +#include <asm/arch/cpu.h> + +#ifdef CONFIG_CLK_800_330_165 +#define DRAM_CLK_330 +#endif +#ifdef CONFIG_CLK_1000_200_200 +#define DRAM_CLK_200 +#endif +#ifdef CONFIG_CLK_1000_330_165 +#define DRAM_CLK_330 +#endif +#ifdef CONFIG_CLK_1000_400_200 +#define DRAM_CLK_400 +#endif + +/* Bus Configuration Register Address */ +#define ASYNC_CONFIG 0x10010350 + +/* CLK_SRC_CPU */ +#define MUX_HPM_SEL_MOUTAPLL 0x0 +#define MUX_HPM_SEL_SCLKMPLL 0x1 +#define MUX_CORE_SEL_MOUTAPLL 0x0 +#define MUX_CORE_SEL_SCLKMPLL 0x1 +#define MUX_MPLL_SEL_FILPLL 0x0 +#define MUX_MPLL_SEL_MOUTMPLLFOUT 0x1 +#define MUX_APLL_SEL_FILPLL 0x0 +#define MUX_APLL_SEL_MOUTMPLLFOUT 0x1 +#define CLK_SRC_CPU_VAL ((MUX_HPM_SEL_MOUTAPLL << 20) \ + | (MUX_CORE_SEL_MOUTAPLL << 16) \ + | (MUX_MPLL_SEL_MOUTMPLLFOUT << 8)\ + | (MUX_APLL_SEL_MOUTMPLLFOUT << 0)) + +/* CLK_DIV_CPU0 */ +#define APLL_RATIO 0x0 +#define PCLK_DBG_RATIO 0x1 +#define ATB_RATIO 0x3 +#define PERIPH_RATIO 0x3 +#define COREM1_RATIO 0x7 +#define COREM0_RATIO 0x3 +#define CORE_RATIO 0x0 +#define CLK_DIV_CPU0_VAL ((APLL_RATIO << 24) \ + | (PCLK_DBG_RATIO << 20) \ + | (ATB_RATIO << 16) \ + | (PERIPH_RATIO << 12) \ + | (COREM1_RATIO << 8) \ + | (COREM0_RATIO << 4) \ + | (CORE_RATIO << 0)) + +/* CLK_DIV_CPU1 */ +#define HPM_RATIO 0x0 +#define COPY_RATIO 0x3 +#define CLK_DIV_CPU1_VAL ((HPM_RATIO << 4) | (COPY_RATIO)) + +/* CLK_SRC_DMC */ +#define MUX_PWI_SEL_XXTI 0x0 +#define MUX_PWI_SEL_XUSBXTI 0x1 +#define MUX_PWI_SEL_SCLK_HDMI24M 0x2 +#define MUX_PWI_SEL_SCLK_USBPHY0 0x3 +#define MUX_PWI_SEL_SCLK_USBPHY1 0x4 +#define MUX_PWI_SEL_SCLK_HDMIPHY 0x5 +#define MUX_PWI_SEL_SCLKMPLL 0x6 +#define MUX_PWI_SEL_SCLKEPLL 0x7 +#define MUX_PWI_SEL_SCLKVPLL 0x8 +#define MUX_DPHY_SEL_SCLKMPLL 0x0 +#define MUX_DPHY_SEL_SCLKAPLL 0x1 +#define MUX_DMC_BUS_SEL_SCLKMPLL 0x0 +#define MUX_DMC_BUS_SEL_SCLKAPLL 0x1 +#define CLK_SRC_DMC_VAL ((MUX_PWI_SEL_XUSBXTI << 16) \ + | (MUX_DPHY_SEL_SCLKMPLL << 8) \ + | (MUX_DMC_BUS_SEL_SCLKMPLL << 4)) + +/* CLK_DIV_DMC0 */ +#define CORE_TIMERS_RATIO 0x1 +#define COPY2_RATIO 0x3 +#define DMCP_RATIO 0x1 +#define DMCD_RATIO 0x1 +#define DMC_RATIO 0x1 +#define DPHY_RATIO 0x1 +#define ACP_PCLK_RATIO 0x1 +#define ACP_RATIO 0x3 +#define CLK_DIV_DMC0_VAL ((CORE_TIMERS_RATIO << 28) \ + | (COPY2_RATIO << 24) \ + | (DMCP_RATIO << 20) \ + | (DMCD_RATIO << 16) \ + | (DMC_RATIO << 12) \ + | (DPHY_RATIO << 8) \ + | (ACP_PCLK_RATIO << 4) \ + | (ACP_RATIO << 0)) + +/* CLK_DIV_DMC1 */ +#define DPM_RATIO 0x1 +#define DVSEM_RATIO 0x1 +#define PWI_RATIO 0x1 +#define CLK_DIV_DMC1_VAL ((DPM_RATIO << 24) \ + | (DVSEM_RATIO << 16) \ + | (PWI_RATIO << 8)) + +/* CLK_SRC_TOP0 */ +#define MUX_ONENAND_SEL_ACLK_133 0x0 +#define MUX_ONENAND_SEL_ACLK_160 0x1 +#define MUX_ACLK_133_SEL_SCLKMPLL 0x0 +#define MUX_ACLK_133_SEL_SCLKAPLL 0x1 +#define MUX_ACLK_160_SEL_SCLKMPLL 0x0 +#define MUX_ACLK_160_SEL_SCLKAPLL 0x1 +#define MUX_ACLK_100_SEL_SCLKMPLL 0x0 +#define MUX_ACLK_100_SEL_SCLKAPLL 0x1 +#define MUX_ACLK_200_SEL_SCLKMPLL 0x0 +#define MUX_ACLK_200_SEL_SCLKAPLL 0x1 +#define MUX_VPLL_SEL_FINPLL 0x0 +#define MUX_VPLL_SEL_FOUTVPLL 0x1 +#define MUX_EPLL_SEL_FINPLL 0x0 +#define MUX_EPLL_SEL_FOUTEPLL 0x1 +#define MUX_ONENAND_1_SEL_MOUTONENAND 0x0 +#define MUX_ONENAND_1_SEL_SCLKVPLL 0x1 +#define CLK_SRC_TOP0_VAL ((MUX_ONENAND_SEL_ACLK_133 << 28) \ + | (MUX_ACLK_133_SEL_SCLKMPLL << 24) \ + | (MUX_ACLK_160_SEL_SCLKMPLL << 20) \ + | (MUX_ACLK_100_SEL_SCLKMPLL << 16) \ + | (MUX_ACLK_200_SEL_SCLKMPLL << 12) \ + | (MUX_VPLL_SEL_FINPLL << 8) \ + | (MUX_EPLL_SEL_FINPLL << 4)\ + | (MUX_ONENAND_1_SEL_MOUTONENAND << 0)) + +/* CLK_SRC_TOP1 */ +#define VPLLSRC_SEL_FINPLL 0x0 +#define VPLLSRC_SEL_SCLKHDMI24M 0x1 +#define CLK_SRC_TOP1_VAL (VPLLSRC_SEL_FINPLL) + +/* CLK_DIV_TOP */ +#define ONENAND_RATIO 0x0 +#define ACLK_133_RATIO 0x5 +#define ACLK_160_RATIO 0x4 +#define ACLK_100_RATIO 0x7 +#define ACLK_200_RATIO 0x3 +#define CLK_DIV_TOP_VAL ((ONENAND_RATIO << 16) \ + | (ACLK_133_RATIO << 12)\ + | (ACLK_160_RATIO << 8) \ + | (ACLK_100_RATIO << 4) \ + | (ACLK_200_RATIO << 0)) + +/* CLK_SRC_LEFTBUS */ +#define MUX_GDL_SEL_SCLKMPLL 0x0 +#define MUX_GDL_SEL_SCLKAPLL 0x1 +#define CLK_SRC_LEFTBUS_VAL (MUX_GDL_SEL_SCLKMPLL) + +/* CLK_DIV_LEFTBUS */ +#define GPL_RATIO 0x1 +#define GDL_RATIO 0x3 +#define CLK_DIV_LEFTBUS_VAL ((GPL_RATIO << 4) | (GDL_RATIO)) + +/* CLK_SRC_RIGHTBUS */ +#define MUX_GDR_SEL_SCLKMPLL 0x0 +#define MUX_GDR_SEL_SCLKAPLL 0x1 +#define CLK_SRC_RIGHTBUS_VAL (MUX_GDR_SEL_SCLKMPLL) + +/* CLK_DIV_RIGHTBUS */ +#define GPR_RATIO 0x1 +#define GDR_RATIO 0x3 +#define CLK_DIV_RIGHTBUS_VAL ((GPR_RATIO << 4) | (GDR_RATIO)) + +/* CLK_SRS_FSYS: 6 = SCLKMPLL */ +#define SATA_SEL_SCLKMPLL 0 +#define SATA_SEL_SCLKAPLL 1 + +#define MMC_SEL_XXTI 0 +#define MMC_SEL_XUSBXTI 1 +#define MMC_SEL_SCLK_HDMI24M 2 +#define MMC_SEL_SCLK_USBPHY0 3 +#define MMC_SEL_SCLK_USBPHY1 4 +#define MMC_SEL_SCLK_HDMIPHY 5 +#define MMC_SEL_SCLKMPLL 6 +#define MMC_SEL_SCLKEPLL 7 +#define MMC_SEL_SCLKVPLL 8 + +#define MMCC0_SEL MMC_SEL_SCLKMPLL +#define MMCC1_SEL MMC_SEL_SCLKMPLL +#define MMCC2_SEL MMC_SEL_SCLKMPLL +#define MMCC3_SEL MMC_SEL_SCLKMPLL +#define MMCC4_SEL MMC_SEL_SCLKMPLL +#define CLK_SRC_FSYS_VAL ((SATA_SEL_SCLKMPLL << 24) \ + | (MMCC4_SEL << 16) \ + | (MMCC3_SEL << 12) \ + | (MMCC2_SEL << 8) \ + | (MMCC1_SEL << 4) \ + | (MMCC0_SEL << 0)) + +/* SCLK_MMC[0-4] = MOUTMMC[0-4]/(MMC[0-4]_RATIO + 1)/(MMC[0-4]_PRE_RATIO +1) */ +/* CLK_DIV_FSYS1 */ +#define MMC0_RATIO 0xF +#define MMC0_PRE_RATIO 0x0 +#define MMC1_RATIO 0xF +#define MMC1_PRE_RATIO 0x0 +#define CLK_DIV_FSYS1_VAL ((MMC1_PRE_RATIO << 24) \ + | (MMC1_RATIO << 16) \ + | (MMC0_PRE_RATIO << 8) \ + | (MMC0_RATIO << 0)) + +/* CLK_DIV_FSYS2 */ +#define MMC2_RATIO 0xF +#define MMC2_PRE_RATIO 0x0 +#define MMC3_RATIO 0xF +#define MMC3_PRE_RATIO 0x0 +#define CLK_DIV_FSYS2_VAL ((MMC3_PRE_RATIO << 24) \ + | (MMC3_RATIO << 16) \ + | (MMC2_PRE_RATIO << 8) \ + | (MMC2_RATIO << 0)) + +/* CLK_DIV_FSYS3 */ +#define MMC4_RATIO 0xF +#define MMC4_PRE_RATIO 0x0 +#define CLK_DIV_FSYS3_VAL ((MMC4_PRE_RATIO << 8) \ + | (MMC4_RATIO << 0)) + +/* CLK_SRC_PERIL0 */ +#define UART_SEL_XXTI 0 +#define UART_SEL_XUSBXTI 1 +#define UART_SEL_SCLK_HDMI24M 2 +#define UART_SEL_SCLK_USBPHY0 3 +#define UART_SEL_SCLK_USBPHY1 4 +#define UART_SEL_SCLK_HDMIPHY 5 +#define UART_SEL_SCLKMPLL 6 +#define UART_SEL_SCLKEPLL 7 +#define UART_SEL_SCLKVPLL 8 + +#define UART0_SEL UART_SEL_SCLKMPLL +#define UART1_SEL UART_SEL_SCLKMPLL +#define UART2_SEL UART_SEL_SCLKMPLL +#define UART3_SEL UART_SEL_SCLKMPLL +#define UART4_SEL UART_SEL_SCLKMPLL +#define CLK_SRC_PERIL0_VAL ((UART4_SEL << 16) \ + | (UART3_SEL << 12) \ + | (UART2_SEL << 8) \ + | (UART1_SEL << 4) \ + | (UART0_SEL << 0)) + +/* SCLK_UART[0-4] = MOUTUART[0-4]/(UART[0-4]_RATIO + 1) */ +/* CLK_DIV_PERIL0 */ +#define UART0_RATIO 7 +#define UART1_RATIO 7 +#define UART2_RATIO 7 +#define UART3_RATIO 7 +#define UART4_RATIO 7 +#define CLK_DIV_PERIL0_VAL ((UART4_RATIO << 16) \ + | (UART3_RATIO << 12) \ + | (UART2_RATIO << 8) \ + | (UART1_RATIO << 4) \ + | (UART0_RATIO << 0)) + +/* Clock Source CAM/FIMC */ +/* CLK_SRC_CAM */ +#define CAM0_SEL_XUSBXTI 1 +#define CAM1_SEL_XUSBXTI 1 +#define CSIS0_SEL_XUSBXTI 1 +#define CSIS1_SEL_XUSBXTI 1 + +#define FIMC_SEL_SCLKMPLL 6 +#define FIMC0_LCLK_SEL FIMC_SEL_SCLKMPLL +#define FIMC1_LCLK_SEL FIMC_SEL_SCLKMPLL +#define FIMC2_LCLK_SEL FIMC_SEL_SCLKMPLL +#define FIMC3_LCLK_SEL FIMC_SEL_SCLKMPLL + +#define CLK_SRC_CAM_VAL ((CSIS1_SEL_XUSBXTI << 28) \ + | (CSIS0_SEL_XUSBXTI << 24) \ + | (CAM1_SEL_XUSBXTI << 20) \ + | (CAM0_SEL_XUSBXTI << 16) \ + | (FIMC3_LCLK_SEL << 12) \ + | (FIMC2_LCLK_SEL << 8) \ + | (FIMC1_LCLK_SEL << 4) \ + | (FIMC0_LCLK_SEL << 0)) + +/* SCLK CAM */ +/* CLK_DIV_CAM */ +#define FIMC0_LCLK_RATIO 4 +#define FIMC1_LCLK_RATIO 4 +#define FIMC2_LCLK_RATIO 4 +#define FIMC3_LCLK_RATIO 4 +#define CLK_DIV_CAM_VAL ((FIMC3_LCLK_RATIO << 12) \ + | (FIMC2_LCLK_RATIO << 8) \ + | (FIMC1_LCLK_RATIO << 4) \ + | (FIMC0_LCLK_RATIO << 0)) + +/* SCLK MFC */ +/* CLK_SRC_MFC */ +#define MFC_SEL_MPLL 0 +#define MOUTMFC_0 0 +#define MFC_SEL MOUTMFC_0 +#define MFC_0_SEL MFC_SEL_MPLL +#define CLK_SRC_MFC_VAL ((MFC_SEL << 8) | (MFC_0_SEL)) + + +/* CLK_DIV_MFC */ +#define MFC_RATIO 3 +#define CLK_DIV_MFC_VAL (MFC_RATIO) + +/* SCLK G3D */ +/* CLK_SRC_G3D */ +#define G3D_SEL_MPLL 0 +#define MOUTG3D_0 0 +#define G3D_SEL MOUTG3D_0 +#define G3D_0_SEL G3D_SEL_MPLL +#define CLK_SRC_G3D_VAL ((G3D_SEL << 8) | (G3D_0_SEL)) + +/* CLK_DIV_G3D */ +#define G3D_RATIO 1 +#define CLK_DIV_G3D_VAL (G3D_RATIO) + +/* SCLK LCD0 */ +/* CLK_SRC_LCD0 */ +#define FIMD_SEL_SCLKMPLL 6 +#define MDNIE0_SEL_XUSBXTI 1 +#define MDNIE_PWM0_SEL_XUSBXTI 1 +#define MIPI0_SEL_XUSBXTI 1 +#define CLK_SRC_LCD0_VAL ((MIPI0_SEL_XUSBXTI << 12) \ + | (MDNIE_PWM0_SEL_XUSBXTI << 8) \ + | (MDNIE0_SEL_XUSBXTI << 4) \ + | (FIMD_SEL_SCLKMPLL << 0)) + +/* CLK_DIV_LCD0 */ +#define FIMD0_RATIO 4 +#define CLK_DIV_LCD0_VAL (FIMD0_RATIO) + +/* Required period to generate a stable clock output */ +/* PLL_LOCK_TIME */ +#define PLL_LOCKTIME 0x1C20 + +/* PLL Values */ +#define DISABLE 0 +#define ENABLE 1 +#define SET_PLL(mdiv, pdiv, sdiv) ((ENABLE << 31)\ + | (mdiv << 16) \ + | (pdiv << 8) \ + | (sdiv << 0)) + +/* APLL_CON0 */ +#define APLL_MDIV 0xFA +#define APLL_PDIV 0x6 +#define APLL_SDIV 0x1 +#define APLL_CON0_VAL SET_PLL(APLL_MDIV, APLL_PDIV, APLL_SDIV) + +/* APLL_CON1 */ +#define APLL_AFC_ENB 0x1 +#define APLL_AFC 0xC +#define APLL_CON1_VAL ((APLL_AFC_ENB << 31) | (APLL_AFC << 0)) + +/* MPLL_CON0 */ +#define MPLL_MDIV 0xC8 +#define MPLL_PDIV 0x6 +#define MPLL_SDIV 0x1 +#define MPLL_CON0_VAL SET_PLL(MPLL_MDIV, MPLL_PDIV, MPLL_SDIV) + +/* MPLL_CON1 */ +#define MPLL_AFC_ENB 0x0 +#define MPLL_AFC 0x1C +#define MPLL_CON1_VAL ((MPLL_AFC_ENB << 31) | (MPLL_AFC << 0)) + +/* EPLL_CON0 */ +#define EPLL_MDIV 0x30 +#define EPLL_PDIV 0x3 +#define EPLL_SDIV 0x2 +#define EPLL_CON0_VAL SET_PLL(EPLL_MDIV, EPLL_PDIV, EPLL_SDIV) + +/* EPLL_CON1 */ +#define EPLL_K 0x0 +#define EPLL_CON1_VAL (EPLL_K >> 0) + +/* VPLL_CON0 */ +#define VPLL_MDIV 0x35 +#define VPLL_PDIV 0x3 +#define VPLL_SDIV 0x2 +#define VPLL_CON0_VAL SET_PLL(VPLL_MDIV, VPLL_PDIV, VPLL_SDIV) + +/* VPLL_CON1 */ +#define VPLL_SSCG_EN DISABLE +#define VPLL_SEL_PF_DN_SPREAD 0x0 +#define VPLL_MRR 0x11 +#define VPLL_MFR 0x0 +#define VPLL_K 0x400 +#define VPLL_CON1_VAL ((VPLL_SSCG_EN << 31)\ + | (VPLL_SEL_PF_DN_SPREAD << 29) \ + | (VPLL_MRR << 24) \ + | (VPLL_MFR << 16) \ + | (VPLL_K << 0)) + +/* DMC */ +#define DIRECT_CMD_NOP 0x07000000 +#define DIRECT_CMD_ZQ 0x0a000000 +#define DIRECT_CMD_CHIP1_SHIFT (1 << 20) +#define MEM_TIMINGS_MSR_COUNT 4 +#define CTRL_START (1 << 0) +#define CTRL_DLL_ON (1 << 1) +#define AREF_EN (1 << 5) +#define DRV_TYPE (1 << 6) + +struct mem_timings { + unsigned direct_cmd_msr[MEM_TIMINGS_MSR_COUNT]; + unsigned timingref; + unsigned timingrow; + unsigned timingdata; + unsigned timingpower; + unsigned zqcontrol; + unsigned control0; + unsigned control1; + unsigned control2; + unsigned concontrol; + unsigned prechconfig; + unsigned memcontrol; + unsigned memconfig0; + unsigned memconfig1; + unsigned dll_resync; + unsigned dll_on; +}; + +/* MIU */ +/* MIU Config Register Offsets*/ +#define APB_SFR_INTERLEAVE_CONF_OFFSET 0x400 +#define APB_SFR_ARBRITATION_CONF_OFFSET 0xC00 +#define ABP_SFR_SLV_ADDRMAP_CONF_OFFSET 0x800 +#define ABP_SFR_INTERLEAVE_ADDRMAP_START_OFFSET 0x808 +#define ABP_SFR_INTERLEAVE_ADDRMAP_END_OFFSET 0x810 +#define ABP_SFR_SLV0_SINGLE_ADDRMAP_START_OFFSET 0x818 +#define ABP_SFR_SLV0_SINGLE_ADDRMAP_END_OFFSET 0x820 +#define ABP_SFR_SLV1_SINGLE_ADDRMAP_START_OFFSET 0x828 +#define ABP_SFR_SLV1_SINGLE_ADDRMAP_END_OFFSET 0x830 + +#ifdef CONFIG_ORIGEN +/* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */ +#define APB_SFR_INTERLEAVE_CONF_VAL 0x20001507 +#define APB_SFR_ARBRITATION_CONF_VAL 0x00000001 +#endif + +#define INTERLEAVE_ADDR_MAP_START_ADDR 0x40000000 +#define INTERLEAVE_ADDR_MAP_END_ADDR 0xbfffffff +#define INTERLEAVE_ADDR_MAP_EN 0x00000001 + +#ifdef CONFIG_MIU_1BIT_INTERLEAVED +/* Interleave_bit0: 0xC*/ +#define APB_SFR_INTERLEAVE_CONF_VAL 0x0000000c +#endif +#ifdef CONFIG_MIU_2BIT_INTERLEAVED +/* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0xc */ +#define APB_SFR_INTERLEAVE_CONF_VAL 0x2000150c +#endif +#define SLAVE0_SINGLE_ADDR_MAP_START_ADDR 0x40000000 +#define SLAVE0_SINGLE_ADDR_MAP_END_ADDR 0x7fffffff +#define SLAVE1_SINGLE_ADDR_MAP_START_ADDR 0x80000000 +#define SLAVE1_SINGLE_ADDR_MAP_END_ADDR 0xbfffffff +/* Enable SME0 and SME1*/ +#define APB_SFR_SLV_ADDR_MAP_CONF_VAL 0x00000006 + +#define FORCE_DLL_RESYNC 3 +#define DLL_CONTROL_ON 1 + +#define DIRECT_CMD1 0x00020000 +#define DIRECT_CMD2 0x00030000 +#define DIRECT_CMD3 0x00010002 +#define DIRECT_CMD4 0x00000328 + +#define CTRL_ZQ_MODE_NOTERM (0x1 << 0) +#define CTRL_ZQ_START (0x1 << 1) +#define CTRL_ZQ_DIV (0 << 4) +#define CTRL_ZQ_MODE_DDS (0x7 << 8) +#define CTRL_ZQ_MODE_TERM (0x2 << 11) +#define CTRL_ZQ_FORCE_IMPN (0x5 << 14) +#define CTRL_ZQ_FORCE_IMPP (0x6 << 17) +#define CTRL_DCC (0xE38 << 20) +#define ZQ_CONTROL_VAL (CTRL_ZQ_MODE_NOTERM | CTRL_ZQ_START\ + | CTRL_ZQ_DIV | CTRL_ZQ_MODE_DDS\ + | CTRL_ZQ_MODE_TERM | CTRL_ZQ_FORCE_IMPN\ + | CTRL_ZQ_FORCE_IMPP | CTRL_DCC) + +#define ASYNC (0 << 0) +#define CLK_RATIO (1 << 1) +#define DIV_PIPE (1 << 3) +#define AWR_ON (1 << 4) +#define AREF_DISABLE (0 << 5) +#define DRV_TYPE_DISABLE (0 << 6) +#define CHIP0_NOT_EMPTY (0 << 8) +#define CHIP1_NOT_EMPTY (0 << 9) +#define DQ_SWAP_DISABLE (0 << 10) +#define QOS_FAST_DISABLE (0 << 11) +#define RD_FETCH (0x3 << 12) +#define TIMEOUT_LEVEL0 (0xFFF << 16) +#define CONCONTROL_VAL (ASYNC | CLK_RATIO | DIV_PIPE | AWR_ON\ + | AREF_DISABLE | DRV_TYPE_DISABLE\ + | CHIP0_NOT_EMPTY | CHIP1_NOT_EMPTY\ + | DQ_SWAP_DISABLE | QOS_FAST_DISABLE\ + | RD_FETCH | TIMEOUT_LEVEL0) + +#define CLK_STOP_DISABLE (0 << 1) +#define DPWRDN_DISABLE (0 << 2) +#define DPWRDN_TYPE (0 << 3) +#define TP_DISABLE (0 << 4) +#define DSREF_DIABLE (0 << 5) +#define ADD_LAT_PALL (1 << 6) +#define MEM_TYPE_DDR3 (0x6 << 8) +#define MEM_WIDTH_32 (0x2 << 12) +#define NUM_CHIP_2 (1 << 16) +#define BL_8 (0x3 << 20) +#define MEMCONTROL_VAL (CLK_STOP_DISABLE | DPWRDN_DISABLE\ + | DPWRDN_TYPE | TP_DISABLE | DSREF_DIABLE\ + | ADD_LAT_PALL | MEM_TYPE_DDR3 | MEM_WIDTH_32\ + | NUM_CHIP_2 | BL_8) + + +#define CHIP_BANK_8 (0x3 << 0) +#define CHIP_ROW_14 (0x2 << 4) +#define CHIP_COL_10 (0x3 << 8) +#define CHIP_MAP_INTERLEAVED (1 << 12) +#define CHIP_MASK (0xe0 << 16) +#ifdef CONFIG_MIU_LINEAR +#define CHIP0_BASE (0x40 << 24) +#define CHIP1_BASE (0x60 << 24) +#else +#define CHIP0_BASE (0x20 << 24) +#define CHIP1_BASE (0x40 << 24) +#endif +#define MEMCONFIG0_VAL (CHIP_BANK_8 | CHIP_ROW_14 | CHIP_COL_10\ + | CHIP_MAP_INTERLEAVED | CHIP_MASK | CHIP0_BASE) +#define MEMCONFIG1_VAL (CHIP_BANK_8 | CHIP_ROW_14 | CHIP_COL_10\ + | CHIP_MAP_INTERLEAVED | CHIP_MASK | CHIP1_BASE) + +#define TP_CNT (0xff << 24) +#define PRECHCONFIG TP_CNT + +#define CTRL_OFF (0 << 0) +#define CTRL_DLL_OFF (0 << 1) +#define CTRL_HALF (0 << 2) +#define CTRL_DFDQS (1 << 3) +#define DQS_DELAY (0 << 4) +#define CTRL_START_POINT (0x10 << 8) +#define CTRL_INC (0x10 << 16) +#define CTRL_FORCE (0x71 << 24) +#define CONTROL0_VAL (CTRL_OFF | CTRL_DLL_OFF | CTRL_HALF\ + | CTRL_DFDQS | DQS_DELAY | CTRL_START_POINT\ + | CTRL_INC | CTRL_FORCE) + +#define CTRL_SHIFTC (0x6 << 0) +#define CTRL_REF (8 << 4) +#define CTRL_SHGATE (1 << 29) +#define TERM_READ_EN (1 << 30) +#define TERM_WRITE_EN (1 << 31) +#define CONTROL1_VAL (CTRL_SHIFTC | CTRL_REF | CTRL_SHGATE\ + | TERM_READ_EN | TERM_WRITE_EN) + +#define CONTROL2_VAL 0x00000000 + +#ifdef CONFIG_ORIGEN +#define TIMINGREF_VAL 0x000000BB +#define TIMINGROW_VAL 0x4046654f +#define TIMINGDATA_VAL 0x46400506 +#define TIMINGPOWER_VAL 0x52000A3C +#else +#define TIMINGREF_VAL 0x000000BC +#ifdef DRAM_CLK_330 +#define TIMINGROW_VAL 0x3545548d +#define TIMINGDATA_VAL 0x45430506 +#define TIMINGPOWER_VAL 0x4439033c +#endif +#ifdef DRAM_CLK_400 +#define TIMINGROW_VAL 0x45430506 +#define TIMINGDATA_VAL 0x56500506 +#define TIMINGPOWER_VAL 0x5444033d +#endif +#endif +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/exynos5_setup.h new file mode 100644 index 000000000..53b0ace6e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -0,0 +1,945 @@ +/* + * Machine Specific Values for SMDK5250 board based on EXYNOS5 + * + * Copyright (C) 2012 Samsung Electronics + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SMDK5250_SETUP_H +#define _SMDK5250_SETUP_H + +#include <config.h> +#include <asm/arch/dmc.h> + +#define NOT_AVAILABLE 0 +#define DATA_MASK 0xFFFFF + +#define ENABLE_BIT 0x1 +#define DISABLE_BIT 0x0 +#define CA_SWAP_EN (1 << 0) + +/* Set PLL */ +#define set_pll(mdiv, pdiv, sdiv) (1<<31 | mdiv<<16 | pdiv<<8 | sdiv) + +/* MEMCONTROL register bit fields */ +#define DMC_MEMCONTROL_CLK_STOP_DISABLE (0 << 0) +#define DMC_MEMCONTROL_DPWRDN_DISABLE (0 << 1) +#define DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE (0 << 2) +#define DMC_MEMCONTROL_TP_DISABLE (0 << 4) +#define DMC_MEMCONTROL_DSREF_DISABLE (0 << 5) +#define DMC_MEMCONTROL_DSREF_ENABLE (1 << 5) +#define DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(x) (x << 6) + +#define DMC_MEMCONTROL_MEM_TYPE_LPDDR3 (7 << 8) +#define DMC_MEMCONTROL_MEM_TYPE_DDR3 (6 << 8) +#define DMC_MEMCONTROL_MEM_TYPE_LPDDR2 (5 << 8) + +#define DMC_MEMCONTROL_MEM_WIDTH_32BIT (2 << 12) + +#define DMC_MEMCONTROL_NUM_CHIP_1 (0 << 16) +#define DMC_MEMCONTROL_NUM_CHIP_2 (1 << 16) + +#define DMC_MEMCONTROL_BL_8 (3 << 20) +#define DMC_MEMCONTROL_BL_4 (2 << 20) + +#define DMC_MEMCONTROL_PZQ_DISABLE (0 << 24) + +#define DMC_MEMCONTROL_MRR_BYTE_7_0 (0 << 25) +#define DMC_MEMCONTROL_MRR_BYTE_15_8 (1 << 25) +#define DMC_MEMCONTROL_MRR_BYTE_23_16 (2 << 25) +#define DMC_MEMCONTROL_MRR_BYTE_31_24 (3 << 25) + +/* MEMCONFIG0 register bit fields */ +#define DMC_MEMCONFIGX_CHIP_MAP_INTERLEAVED (1 << 12) +#define DMC_MEMCONFIG_CHIP_MAP_SPLIT (2 << 12) +#define DMC_MEMCONFIGX_CHIP_COL_10 (3 << 8) +#define DMC_MEMCONFIGX_CHIP_ROW_14 (2 << 4) +#define DMC_MEMCONFIGX_CHIP_ROW_15 (3 << 4) +#define DMC_MEMCONFIGX_CHIP_BANK_8 (3 << 0) + +#define DMC_MEMBASECONFIGX_CHIP_BASE(x) (x << 16) +#define DMC_MEMBASECONFIGX_CHIP_MASK(x) (x << 0) +#define DMC_MEMBASECONFIG_VAL(x) ( \ + DMC_MEMBASECONFIGX_CHIP_BASE(x) | \ + DMC_MEMBASECONFIGX_CHIP_MASK(0x780) \ +) + +/* + * As we use channel interleaving, therefore value of the base address + * register must be set as half of the bus base address + * RAM start addess is 0x2000_0000 which means chip_base is 0x20, so + * we need to set half 0x10 to the membaseconfigx registers + * see exynos5420 UM section 17.17.3.21 for more. + */ +#define DMC_CHIP_BASE_0 0x10 +#define DMC_CHIP_BASE_1 0x50 +#define DMC_CHIP_MASK 0x7C0 + +#define DMC_MEMBASECONFIG0_VAL DMC_MEMBASECONFIG_VAL(0x40) +#define DMC_MEMBASECONFIG1_VAL DMC_MEMBASECONFIG_VAL(0x80) + +#define DMC_PRECHCONFIG_VAL 0xFF000000 +#define DMC_PWRDNCONFIG_VAL 0xFFFF00FF + +#define DMC_CONCONTROL_RESET_VAL 0x0FFF0000 +#define DFI_INIT_START (1 << 28) +#define EMPTY (1 << 8) +#define AREF_EN (1 << 5) + +#define DFI_INIT_COMPLETE_CHO (1 << 2) +#define DFI_INIT_COMPLETE_CH1 (1 << 3) + +#define RDLVL_COMPLETE_CHO (1 << 14) +#define RDLVL_COMPLETE_CH1 (1 << 15) + +#define CLK_STOP_EN (1 << 0) +#define DPWRDN_EN (1 << 1) +#define DSREF_EN (1 << 5) + +/* COJCONTROL register bit fields */ +#define DMC_CONCONTROL_IO_PD_CON_DISABLE (0 << 3) +#define DMC_CONCONTROL_IO_PD_CON_ENABLE (1 << 3) +#define DMC_CONCONTROL_AREF_EN_DISABLE (0 << 5) +#define DMC_CONCONTROL_AREF_EN_ENABLE (1 << 5) +#define DMC_CONCONTROL_EMPTY_DISABLE (0 << 8) +#define DMC_CONCONTROL_EMPTY_ENABLE (1 << 8) +#define DMC_CONCONTROL_RD_FETCH_DISABLE (0x0 << 12) +#define DMC_CONCONTROL_TIMEOUT_LEVEL0 (0xFFF << 16) +#define DMC_CONCONTROL_DFI_INIT_START_DISABLE (0 << 28) + +#define DMC_CONCONTROL_VAL 0x1FFF2101 + +#define DREX_CONCONTROL_VAL DMC_CONCONTROL_VAL \ + | DMC_CONCONTROL_AREF_EN_ENABLE \ + | DMC_CONCONTROL_IO_PD_CON_ENABLE + +#define DMC_CONCONTROL_IO_PD_CON(x) (x << 6) + +/* CLK_DIV_CPU1 */ +#define HPM_RATIO 0x2 +#define COPY_RATIO 0x0 + +/* CLK_DIV_CPU1 = 0x00000003 */ +#define CLK_DIV_CPU1_VAL ((HPM_RATIO << 4) \ + | (COPY_RATIO)) + +/* CLK_SRC_CORE0 */ +#define CLK_SRC_CORE0_VAL 0x00000000 + +/* CLK_SRC_CORE1 */ +#define CLK_SRC_CORE1_VAL 0x100 + +/* CLK_DIV_CORE0 */ +#define CLK_DIV_CORE0_VAL 0x00120000 + +/* CLK_DIV_CORE1 */ +#define CLK_DIV_CORE1_VAL 0x07070700 + +/* CLK_DIV_SYSRGT */ +#define CLK_DIV_SYSRGT_VAL 0x00000111 + +/* CLK_DIV_ACP */ +#define CLK_DIV_ACP_VAL 0x12 + +/* CLK_DIV_SYSLFT */ +#define CLK_DIV_SYSLFT_VAL 0x00000311 + +#define MUX_APLL_SEL_MASK (1 << 0) +#define MUX_MPLL_SEL_MASK (1 << 8) +#define MPLL_SEL_MOUT_MPLLFOUT (2 << 8) +#define MUX_CPLL_SEL_MASK (1 << 8) +#define MUX_EPLL_SEL_MASK (1 << 12) +#define MUX_VPLL_SEL_MASK (1 << 16) +#define MUX_GPLL_SEL_MASK (1 << 28) +#define MUX_BPLL_SEL_MASK (1 << 0) +#define MUX_HPM_SEL_MASK (1 << 20) +#define HPM_SEL_SCLK_MPLL (1 << 21) +#define PLL_LOCKED (1 << 29) +#define APLL_CON0_LOCKED (1 << 29) +#define MPLL_CON0_LOCKED (1 << 29) +#define BPLL_CON0_LOCKED (1 << 29) +#define CPLL_CON0_LOCKED (1 << 29) +#define EPLL_CON0_LOCKED (1 << 29) +#define GPLL_CON0_LOCKED (1 << 29) +#define VPLL_CON0_LOCKED (1 << 29) +#define CLK_REG_DISABLE 0x0 +#define TOP2_VAL 0x0110000 + +/* SCLK_SRC_ISP - set SPI0/1 to 6 = SCLK_MPLL_USER */ +#define SPI0_ISP_SEL 6 +#define SPI1_ISP_SEL 6 +#define SCLK_SRC_ISP_VAL (SPI1_ISP_SEL << 4) \ + | (SPI0_ISP_SEL << 0) + +/* SCLK_DIV_ISP - set SPI0/1 to 0xf = divide by 16 */ +#define SPI0_ISP_RATIO 0xf +#define SPI1_ISP_RATIO 0xf +#define SCLK_DIV_ISP_VAL (SPI1_ISP_RATIO << 12) \ + | (SPI0_ISP_RATIO << 0) + +/* CLK_DIV_FSYS2 */ +#define MMC2_RATIO_MASK 0xf +#define MMC2_RATIO_VAL 0x3 +#define MMC2_RATIO_OFFSET 0 + +#define MMC2_PRE_RATIO_MASK 0xff +#define MMC2_PRE_RATIO_VAL 0x9 +#define MMC2_PRE_RATIO_OFFSET 8 + +#define MMC3_RATIO_MASK 0xf +#define MMC3_RATIO_VAL 0x1 +#define MMC3_RATIO_OFFSET 16 + +#define MMC3_PRE_RATIO_MASK 0xff +#define MMC3_PRE_RATIO_VAL 0x0 +#define MMC3_PRE_RATIO_OFFSET 24 + +/* CLK_SRC_LEX */ +#define CLK_SRC_LEX_VAL 0x0 + +/* CLK_DIV_LEX */ +#define CLK_DIV_LEX_VAL 0x10 + +/* CLK_DIV_R0X */ +#define CLK_DIV_R0X_VAL 0x10 + +/* CLK_DIV_L0X */ +#define CLK_DIV_R1X_VAL 0x10 + +/* CLK_DIV_ISP2 */ +#define CLK_DIV_ISP2_VAL 0x1 + +/* CLK_SRC_KFC */ +#define SRC_KFC_HPM_SEL (1 << 15) + +/* CLK_SRC_KFC */ +#define CLK_SRC_KFC_VAL 0x00008001 + +/* CLK_DIV_KFC */ +#define CLK_DIV_KFC_VAL 0x03300110 + +/* CLK_DIV2_RATIO */ +#define CLK_DIV2_RATIO 0x10111150 + +/* CLK_DIV4_RATIO */ +#define CLK_DIV4_RATIO 0x00000003 + +/* CLK_DIV_G2D */ +#define CLK_DIV_G2D 0x00000010 + +/* + * DIV_DISP1_0 + * For DP, divisor should be 2 + */ +#define CLK_DIV_DISP1_0_FIMD1 (2 << 0) + +/* CLK_GATE_IP_DISP1 */ +#define CLK_GATE_DP1_ALLOW (1 << 4) + +/* AUDIO CLK SEL */ +#define AUDIO0_SEL_EPLL (0x6 << 28) +#define AUDIO0_RATIO 0x5 +#define PCM0_RATIO 0x3 +#define DIV_MAU_VAL (PCM0_RATIO << 24 | AUDIO0_RATIO << 20) + +/* CLK_SRC_CDREX */ +#define MUX_MCLK_CDR_MSPLL (1 << 4) +#define MUX_BPLL_SEL_FOUTBPLL (1 << 0) +#define BPLL_SEL_MASK 0x7 +#define FOUTBPLL 2 + +#define DDR3PHY_CTRL_PHY_RESET (1 << 0) +#define DDR3PHY_CTRL_PHY_RESET_OFF (0 << 0) + +#define PHY_CON0_RESET_VAL 0x17020a40 +#define P0_CMD_EN (1 << 14) +#define BYTE_RDLVL_EN (1 << 13) +#define CTRL_SHGATE (1 << 8) + +#define PHY_CON1_RESET_VAL 0x09210100 +#define RDLVL_PASS_ADJ_VAL 0x6 +#define RDLVL_PASS_ADJ_OFFSET 16 +#define CTRL_GATEDURADJ_MASK (0xf << 20) +#define READ_LEVELLING_DDR3 0x0100 + +#define PHY_CON2_RESET_VAL 0x00010004 +#define INIT_DESKEW_EN (1 << 6) +#define DLL_DESKEW_EN (1 << 12) +#define RDLVL_GATE_EN (1 << 24) +#define RDLVL_EN (1 << 25) +#define RDLVL_INCR_ADJ (0x1 << 16) + +/* DREX_PAUSE */ +#define DREX_PAUSE_EN (1 << 0) + +#define BYPASS_EN (1 << 22) + +/* MEMMORY VAL */ +#define PHY_CON0_VAL 0x17021A00 + +#define PHY_CON12_RESET_VAL 0x10100070 +#define PHY_CON12_VAL 0x10107F50 +#define CTRL_START (1 << 6) +#define CTRL_DLL_ON (1 << 5) +#define CTRL_FORCE_MASK (0x7F << 8) +#define CTRL_LOCK_COARSE_MASK (0x7F << 10) + +#define CTRL_OFFSETD_RESET_VAL 0x8 +#define CTRL_OFFSETD_VAL 0x7F + +#define CTRL_OFFSETR0 0x7F +#define CTRL_OFFSETR1 0x7F +#define CTRL_OFFSETR2 0x7F +#define CTRL_OFFSETR3 0x7F +#define PHY_CON4_VAL (CTRL_OFFSETR0 << 0 | \ + CTRL_OFFSETR1 << 8 | \ + CTRL_OFFSETR2 << 16 | \ + CTRL_OFFSETR3 << 24) +#define PHY_CON4_RESET_VAL 0x08080808 + +#define CTRL_OFFSETW0 0x7F +#define CTRL_OFFSETW1 0x7F +#define CTRL_OFFSETW2 0x7F +#define CTRL_OFFSETW3 0x7F +#define PHY_CON6_VAL (CTRL_OFFSETW0 << 0 | \ + CTRL_OFFSETW1 << 8 | \ + CTRL_OFFSETW2 << 16 | \ + CTRL_OFFSETW3 << 24) +#define PHY_CON6_RESET_VAL 0x08080808 + +#define PHY_CON14_RESET_VAL 0x001F0000 +#define CTRL_PULLD_DQS 0xF +#define CTRL_PULLD_DQS_OFFSET 0 + +/* ZQ Configurations */ +#define PHY_CON16_RESET_VAL 0x08000304 + +#define ZQ_CLK_EN (1 << 27) +#define ZQ_CLK_DIV_EN (1 << 18) +#define ZQ_MANUAL_STR (1 << 1) +#define ZQ_DONE (1 << 0) +#define ZQ_MODE_DDS_OFFSET 24 + +#define CTRL_RDLVL_GATE_ENABLE 1 +#define CTRL_RDLVL_GATE_DISABLE 0 +#define CTRL_RDLVL_DATA_ENABLE 2 + +/* Direct Command */ +#define DIRECT_CMD_NOP 0x07000000 +#define DIRECT_CMD_PALL 0x01000000 +#define DIRECT_CMD_ZQINIT 0x0a000000 +#define DIRECT_CMD_CHANNEL_SHIFT 28 +#define DIRECT_CMD_CHIP_SHIFT 20 +#define DIRECT_CMD_BANK_SHIFT 16 +#define DIRECT_CMD_REFA (5 << 24) +#define DIRECT_CMD_MRS1 0x71C00 +#define DIRECT_CMD_MRS2 0x10BFC +#define DIRECT_CMD_MRS3 0x0050C +#define DIRECT_CMD_MRS4 0x00868 +#define DIRECT_CMD_MRS5 0x00C04 + +/* Drive Strength */ +#define IMPEDANCE_48_OHM 4 +#define IMPEDANCE_40_OHM 5 +#define IMPEDANCE_34_OHM 6 +#define IMPEDANCE_30_OHM 7 +#define PHY_CON39_VAL_48_OHM 0x09240924 +#define PHY_CON39_VAL_40_OHM 0x0B6D0B6D +#define PHY_CON39_VAL_34_OHM 0x0DB60DB6 +#define PHY_CON39_VAL_30_OHM 0x0FFF0FFF + +#define CTRL_BSTLEN_OFFSET 8 +#define CTRL_RDLAT_OFFSET 0 + +#define CMD_DEFAULT_LPDDR3 0xF +#define CMD_DEFUALT_OFFSET 0 +#define T_WRDATA_EN 0x7 +#define T_WRDATA_EN_DDR3 0x8 +#define T_WRDATA_EN_OFFSET 16 +#define T_WRDATA_EN_MASK 0x1f + +#define PHY_CON31_VAL 0x0C183060 +#define PHY_CON32_VAL 0x60C18306 +#define PHY_CON33_VAL 0x00000030 + +#define PHY_CON31_RESET_VAL 0x0 +#define PHY_CON32_RESET_VAL 0x0 +#define PHY_CON33_RESET_VAL 0x0 + +#define SL_DLL_DYN_CON_EN (1 << 1) +#define FP_RESYNC (1 << 3) +#define CTRL_START (1 << 6) + +#define DMC_AREF_EN (1 << 5) +#define DMC_CONCONTROL_EMPTY (1 << 8) +#define DFI_INIT_START (1 << 28) + +#define DMC_MEMCONTROL_VAL 0x00312700 +#define CLK_STOP_EN (1 << 0) +#define DPWRDN_EN (1 << 1) +#define DSREF_EN (1 << 5) + +#define MEMBASECONFIG_CHIP_MASK_VAL 0x7E0 +#define MEMBASECONFIG_CHIP_MASK_OFFSET 0 +#define MEMBASECONFIG0_CHIP_BASE_VAL 0x20 +#define MEMBASECONFIG1_CHIP_BASE_VAL 0x40 +#define CHIP_BASE_OFFSET 16 + +#define MEMCONFIG_VAL 0x1323 +#define PRECHCONFIG_DEFAULT_VAL 0xFF000000 +#define PWRDNCONFIG_DEFAULT_VAL 0xFFFF00FF + +#define TIMINGAREF_VAL 0x5d +#define TIMINGROW_VAL 0x345A8692 +#define TIMINGDATA_VAL 0x3630065C +#define TIMINGPOWER_VAL 0x50380336 +#define DFI_INIT_COMPLETE (1 << 3) + +#define BRBRSVCONTROL_VAL 0x00000033 +#define BRBRSVCONFIG_VAL 0x88778877 + +/* Clock Gating Control (CGCONTROL) register */ +#define MEMIF_CG_EN (1 << 3) /* Memory interface clock gating */ +#define SCG_CG_EN (1 << 2) /* Scheduler clock gating */ +#define BUSIF_WR_CG_EN (1 << 1) /* Bus interface write channel clock gating */ +#define BUSIF_RD_CG_EN (1 << 0) /* Bus interface read channel clock gating */ +#define DMC_INTERNAL_CG (MEMIF_CG_EN | SCG_CG_EN | \ + BUSIF_WR_CG_EN | BUSIF_RD_CG_EN) + +/* DMC PHY Control0 register */ +#define PHY_CONTROL0_RESET_VAL 0x0 +#define MEM_TERM_EN (1 << 31) /* Termination enable for memory */ +#define PHY_TERM_EN (1 << 30) /* Termination enable for PHY */ +#define DMC_CTRL_SHGATE (1 << 29) /* Duration of DQS gating signal */ +#define FP_RSYNC (1 << 3) /* Force DLL resyncronization */ + +/* Driver strength for CK, CKE, CS & CA */ +#define IMP_OUTPUT_DRV_40_OHM 0x5 +#define IMP_OUTPUT_DRV_30_OHM 0x7 +#define DA_3_DS_OFFSET 25 +#define DA_2_DS_OFFSET 22 +#define DA_1_DS_OFFSET 19 +#define DA_0_DS_OFFSET 16 +#define CA_CK_DRVR_DS_OFFSET 9 +#define CA_CKE_DRVR_DS_OFFSET 6 +#define CA_CS_DRVR_DS_OFFSET 3 +#define CA_ADR_DRVR_DS_OFFSET 0 + +#define PHY_CON42_CTRL_BSTLEN_SHIFT 8 +#define PHY_CON42_CTRL_RDLAT_SHIFT 0 + +/* + * Definitions that differ with SoC's. + * Below is the part defining macros for smdk5250. + * Else part introduces macros for smdk5420. + */ +#ifndef CONFIG_SMDK5420 + +/* APLL_CON1 */ +#define APLL_CON1_VAL (0x00203800) + +/* MPLL_CON1 */ +#define MPLL_CON1_VAL (0x00203800) + +/* CPLL_CON1 */ +#define CPLL_CON1_VAL (0x00203800) + +/* DPLL_CON1 */ +#define DPLL_CON1_VAL (NOT_AVAILABLE) + +/* GPLL_CON1 */ +#define GPLL_CON1_VAL (0x00203800) + +/* EPLL_CON1, CON2 */ +#define EPLL_CON1_VAL 0x00000000 +#define EPLL_CON2_VAL 0x00000080 + +/* VPLL_CON1, CON2 */ +#define VPLL_CON1_VAL 0x00000000 +#define VPLL_CON2_VAL 0x00000080 + +/* RPLL_CON1, CON2 */ +#define RPLL_CON1_VAL NOT_AVAILABLE +#define RPLL_CON2_VAL NOT_AVAILABLE + +/* BPLL_CON1 */ +#define BPLL_CON1_VAL 0x00203800 + +/* SPLL_CON1 */ +#define SPLL_CON1_VAL NOT_AVAILABLE + +/* IPLL_CON1 */ +#define IPLL_CON1_VAL NOT_AVAILABLE + +/* KPLL_CON1 */ +#define KPLL_CON1_VAL NOT_AVAILABLE + +/* CLK_SRC_ISP */ +#define CLK_SRC_ISP_VAL NOT_AVAILABLE +#define CLK_DIV_ISP0_VAL 0x31 +#define CLK_DIV_ISP1_VAL 0x0 + +/* CLK_FSYS */ +#define CLK_SRC_FSYS0_VAL 0x66666 +#define CLK_DIV_FSYS0_VAL 0x0BB00000 +#define CLK_DIV_FSYS1_VAL NOT_AVAILABLE +#define CLK_DIV_FSYS2_VAL NOT_AVAILABLE + +/* CLK_SRC_CPU */ +/* 0 = MOUTAPLL, 1 = SCLKMPLL */ +#define MUX_HPM_SEL 0 +#define MUX_CPU_SEL 0 +#define MUX_APLL_SEL 1 + +#define CLK_SRC_CPU_VAL ((MUX_HPM_SEL << 20) \ + | (MUX_CPU_SEL << 16) \ + | (MUX_APLL_SEL)) + +/* CLK_SRC_CDREX */ +#define CLK_SRC_CDREX_VAL 0x1 + +/* CLK_DIV_CDREX */ +#define CLK_DIV_CDREX0_VAL NOT_AVAILABLE +#define CLK_DIV_CDREX1_VAL NOT_AVAILABLE + +/* CLK_DIV_CPU0_VAL */ +#define CLK_DIV_CPU0_VAL NOT_AVAILABLE + +#define MCLK_CDREX2_RATIO 0x0 +#define ACLK_EFCON_RATIO 0x1 +#define MCLK_DPHY_RATIO 0x1 +#define MCLK_CDREX_RATIO 0x1 +#define ACLK_C2C_200_RATIO 0x1 +#define C2C_CLK_400_RATIO 0x1 +#define PCLK_CDREX_RATIO 0x1 +#define ACLK_CDREX_RATIO 0x1 + +#define CLK_DIV_CDREX_VAL ((MCLK_DPHY_RATIO << 24) \ + | (C2C_CLK_400_RATIO << 6) \ + | (PCLK_CDREX_RATIO << 4) \ + | (ACLK_CDREX_RATIO)) + +/* CLK_SRC_TOP0 */ +#define MUX_ACLK_300_GSCL_SEL 0x0 +#define MUX_ACLK_300_GSCL_MID_SEL 0x0 +#define MUX_ACLK_400_G3D_MID_SEL 0x0 +#define MUX_ACLK_333_SEL 0x0 +#define MUX_ACLK_300_DISP1_SEL 0x0 +#define MUX_ACLK_300_DISP1_MID_SEL 0x0 +#define MUX_ACLK_200_SEL 0x0 +#define MUX_ACLK_166_SEL 0x0 +#define CLK_SRC_TOP0_VAL ((MUX_ACLK_300_GSCL_SEL << 25) \ + | (MUX_ACLK_300_GSCL_MID_SEL << 24) \ + | (MUX_ACLK_400_G3D_MID_SEL << 20) \ + | (MUX_ACLK_333_SEL << 16) \ + | (MUX_ACLK_300_DISP1_SEL << 15) \ + | (MUX_ACLK_300_DISP1_MID_SEL << 14) \ + | (MUX_ACLK_200_SEL << 12) \ + | (MUX_ACLK_166_SEL << 8)) + +/* CLK_SRC_TOP1 */ +#define MUX_ACLK_400_G3D_SEL 0x1 +#define MUX_ACLK_400_ISP_SEL 0x0 +#define MUX_ACLK_400_IOP_SEL 0x0 +#define MUX_ACLK_MIPI_HSI_TXBASE_SEL 0x0 +#define MUX_ACLK_300_GSCL_MID1_SEL 0x0 +#define MUX_ACLK_300_DISP1_MID1_SEL 0x0 +#define CLK_SRC_TOP1_VAL ((MUX_ACLK_400_G3D_SEL << 28) \ + |(MUX_ACLK_400_ISP_SEL << 24) \ + |(MUX_ACLK_400_IOP_SEL << 20) \ + |(MUX_ACLK_MIPI_HSI_TXBASE_SEL << 16) \ + |(MUX_ACLK_300_GSCL_MID1_SEL << 12) \ + |(MUX_ACLK_300_DISP1_MID1_SEL << 8)) + +/* CLK_SRC_TOP2 */ +#define MUX_GPLL_SEL 0x1 +#define MUX_BPLL_USER_SEL 0x0 +#define MUX_MPLL_USER_SEL 0x0 +#define MUX_VPLL_SEL 0x1 +#define MUX_EPLL_SEL 0x1 +#define MUX_CPLL_SEL 0x1 +#define VPLLSRC_SEL 0x0 +#define CLK_SRC_TOP2_VAL ((MUX_GPLL_SEL << 28) \ + | (MUX_BPLL_USER_SEL << 24) \ + | (MUX_MPLL_USER_SEL << 20) \ + | (MUX_VPLL_SEL << 16) \ + | (MUX_EPLL_SEL << 12) \ + | (MUX_CPLL_SEL << 8) \ + | (VPLLSRC_SEL)) +/* CLK_SRC_TOP3 */ +#define MUX_ACLK_333_SUB_SEL 0x1 +#define MUX_ACLK_400_SUB_SEL 0x1 +#define MUX_ACLK_266_ISP_SUB_SEL 0x1 +#define MUX_ACLK_266_GPS_SUB_SEL 0x0 +#define MUX_ACLK_300_GSCL_SUB_SEL 0x1 +#define MUX_ACLK_266_GSCL_SUB_SEL 0x1 +#define MUX_ACLK_300_DISP1_SUB_SEL 0x1 +#define MUX_ACLK_200_DISP1_SUB_SEL 0x1 +#define CLK_SRC_TOP3_VAL ((MUX_ACLK_333_SUB_SEL << 24) \ + | (MUX_ACLK_400_SUB_SEL << 20) \ + | (MUX_ACLK_266_ISP_SUB_SEL << 16) \ + | (MUX_ACLK_266_GPS_SUB_SEL << 12) \ + | (MUX_ACLK_300_GSCL_SUB_SEL << 10) \ + | (MUX_ACLK_266_GSCL_SUB_SEL << 8) \ + | (MUX_ACLK_300_DISP1_SUB_SEL << 6) \ + | (MUX_ACLK_200_DISP1_SUB_SEL << 4)) + +#define CLK_SRC_TOP4_VAL NOT_AVAILABLE +#define CLK_SRC_TOP5_VAL NOT_AVAILABLE +#define CLK_SRC_TOP6_VAL NOT_AVAILABLE +#define CLK_SRC_TOP7_VAL NOT_AVAILABLE + +/* CLK_DIV_TOP0 */ +#define ACLK_300_DISP1_RATIO 0x2 +#define ACLK_400_G3D_RATIO 0x0 +#define ACLK_333_RATIO 0x0 +#define ACLK_266_RATIO 0x2 +#define ACLK_200_RATIO 0x3 +#define ACLK_166_RATIO 0x1 +#define ACLK_133_RATIO 0x1 +#define ACLK_66_RATIO 0x5 + +#define CLK_DIV_TOP0_VAL ((ACLK_300_DISP1_RATIO << 28) \ + | (ACLK_400_G3D_RATIO << 24) \ + | (ACLK_333_RATIO << 20) \ + | (ACLK_266_RATIO << 16) \ + | (ACLK_200_RATIO << 12) \ + | (ACLK_166_RATIO << 8) \ + | (ACLK_133_RATIO << 4) \ + | (ACLK_66_RATIO)) + +/* CLK_DIV_TOP1 */ +#define ACLK_MIPI_HSI_TX_BASE_RATIO 0x3 +#define ACLK_66_PRE_RATIO 0x1 +#define ACLK_400_ISP_RATIO 0x1 +#define ACLK_400_IOP_RATIO 0x1 +#define ACLK_300_GSCL_RATIO 0x2 + +#define CLK_DIV_TOP1_VAL ((ACLK_MIPI_HSI_TX_BASE_RATIO << 28) \ + | (ACLK_66_PRE_RATIO << 24) \ + | (ACLK_400_ISP_RATIO << 20) \ + | (ACLK_400_IOP_RATIO << 16) \ + | (ACLK_300_GSCL_RATIO << 12)) + +#define CLK_DIV_TOP2_VAL NOT_AVAILABLE + +/* PLL Lock Value Factor */ +#define PLL_LOCK_FACTOR 250 +#define PLL_X_LOCK_FACTOR 3000 + +/* CLK_SRC_PERIC0 */ +#define PWM_SEL 6 +#define UART3_SEL 6 +#define UART2_SEL 6 +#define UART1_SEL 6 +#define UART0_SEL 6 +/* SRC_CLOCK = SCLK_MPLL */ +#define CLK_SRC_PERIC0_VAL ((PWM_SEL << 24) \ + | (UART3_SEL << 12) \ + | (UART2_SEL << 8) \ + | (UART1_SEL << 4) \ + | (UART0_SEL)) + +/* CLK_SRC_PERIC1 */ +/* SRC_CLOCK = SCLK_MPLL */ +#define SPI0_SEL 6 +#define SPI1_SEL 6 +#define SPI2_SEL 6 +#define CLK_SRC_PERIC1_VAL ((SPI2_SEL << 24) \ + | (SPI1_SEL << 20) \ + | (SPI0_SEL << 16)) + +/* CLK_DIV_PERIL0 */ +#define UART5_RATIO 7 +#define UART4_RATIO 7 +#define UART3_RATIO 7 +#define UART2_RATIO 7 +#define UART1_RATIO 7 +#define UART0_RATIO 7 + +#define CLK_DIV_PERIC0_VAL ((UART3_RATIO << 12) \ + | (UART2_RATIO << 8) \ + | (UART1_RATIO << 4) \ + | (UART0_RATIO)) +/* CLK_DIV_PERIC1 */ +#define SPI1_RATIO 0x7 +#define SPI0_RATIO 0xf +#define SPI1_SUB_RATIO 0x0 +#define SPI0_SUB_RATIO 0x0 +#define CLK_DIV_PERIC1_VAL ((SPI1_SUB_RATIO << 24) \ + | ((SPI1_RATIO << 16) \ + | (SPI0_SUB_RATIO << 8) \ + | (SPI0_RATIO << 0))) + +/* CLK_DIV_PERIC2 */ +#define SPI2_RATIO 0xf +#define SPI2_SUB_RATIO 0x0 +#define CLK_DIV_PERIC2_VAL ((SPI2_SUB_RATIO << 8) \ + | (SPI2_RATIO << 0)) + +/* CLK_DIV_PERIC3 */ +#define PWM_RATIO 8 +#define CLK_DIV_PERIC3_VAL (PWM_RATIO << 0) + + +/* CLK_DIV_PERIC4 */ +#define CLK_DIV_PERIC4_VAL NOT_AVAILABLE + +/* CLK_SRC_DISP1_0 */ +#define CLK_SRC_DISP1_0_VAL 0x6 +#define CLK_DIV_DISP1_0_VAL NOT_AVAILABLE + +#define APLL_FOUT (1 << 0) +#define KPLL_FOUT NOT_AVAILABLE + +#define CLK_DIV_CPERI1_VAL NOT_AVAILABLE + +#else +#define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000 + +/* APLL_CON1 */ +#define APLL_CON1_VAL (0x0020F300) + +/* MPLL_CON1 */ +#define MPLL_CON1_VAL (0x0020F300) + + +/* CPLL_CON1 */ +#define CPLL_CON1_VAL 0x0020f300 + +/* DPLL_CON1 */ +#define DPLL_CON1_VAL (0x0020F300) + +/* GPLL_CON1 */ +#define GPLL_CON1_VAL (NOT_AVAILABLE) + + +/* EPLL_CON1, CON2 */ +#define EPLL_CON1_VAL 0x00000000 +#define EPLL_CON2_VAL 0x00000080 + +/* VPLL_CON1, CON2 */ +#define VPLL_CON1_VAL 0x0020f300 +#define VPLL_CON2_VAL NOT_AVAILABLE + +/* RPLL_CON1, CON2 */ +#define RPLL_CON1_VAL 0x00000000 +#define RPLL_CON2_VAL 0x00000080 + +/* BPLL_CON1 */ +#define BPLL_CON1_VAL 0x0020f300 + +/* SPLL_CON1 */ +#define SPLL_CON1_VAL 0x0020f300 + +/* IPLL_CON1 */ +#define IPLL_CON1_VAL 0x00000080 + +/* KPLL_CON1 */ +#define KPLL_CON1_VAL 0x200000 + +/* CLK_SRC_ISP */ +#define CLK_SRC_ISP_VAL 0x33366000 +#define CLK_DIV_ISP0_VAL 0x13131300 +#define CLK_DIV_ISP1_VAL 0xbb110202 + + +/* CLK_FSYS */ +#define CLK_SRC_FSYS0_VAL 0x33033300 +#define CLK_DIV_FSYS0_VAL 0x0 +#define CLK_DIV_FSYS1_VAL 0x04f13c4f +#define CLK_DIV_FSYS2_VAL 0x041d0000 + +/* CLK_SRC_CPU */ +/* 0 = MOUTAPLL, 1 = SCLKMPLL */ +#define MUX_HPM_SEL 1 +#define MUX_CPU_SEL 0 +#define MUX_APLL_SEL 1 + +#define CLK_SRC_CPU_VAL ((MUX_HPM_SEL << 20) \ + | (MUX_CPU_SEL << 16) \ + | (MUX_APLL_SEL)) + +/* CLK_SRC_CDREX */ +#define CLK_SRC_CDREX_VAL 0x00000011 + +/* CLK_DIV_CDREX */ +#define CLK_DIV_CDREX0_VAL 0x30010100 +#define CLK_DIV_CDREX1_VAL 0x300 + +#define CLK_DIV_CDREX_VAL 0x17010100 + +/* CLK_DIV_CPU0_VAL */ +#define CLK_DIV_CPU0_VAL 0x01440020 + +/* CLK_SRC_TOP */ +#define CLK_SRC_TOP0_VAL 0x12221222 +#define CLK_SRC_TOP1_VAL 0x00100200 +#define CLK_SRC_TOP2_VAL 0x11101000 +#define CLK_SRC_TOP3_VAL 0x11111111 +#define CLK_SRC_TOP4_VAL 0x11110111 +#define CLK_SRC_TOP5_VAL 0x11111100 +#define CLK_SRC_TOP6_VAL 0x11110111 +#define CLK_SRC_TOP7_VAL 0x00022200 + +/* CLK_DIV_TOP */ +#define CLK_DIV_TOP0_VAL 0x23712311 +#define CLK_DIV_TOP1_VAL 0x13100B00 +#define CLK_DIV_TOP2_VAL 0x11101100 + +/* PLL Lock Value Factor */ +#define PLL_LOCK_FACTOR 200 +#define PLL_X_LOCK_FACTOR 3000 + +/* CLK_SRC_PERIC0 */ +#define SPDIF_SEL 1 +#define PWM_SEL 3 +#define UART4_SEL 3 +#define UART3_SEL 3 +#define UART2_SEL 3 +#define UART1_SEL 3 +#define UART0_SEL 3 +/* SRC_CLOCK = SCLK_RPLL */ +#define CLK_SRC_PERIC0_VAL ((SPDIF_SEL << 28) \ + | (PWM_SEL << 24) \ + | (UART4_SEL << 20) \ + | (UART3_SEL << 16) \ + | (UART2_SEL << 12) \ + | (UART1_SEL << 8) \ + | (UART0_SEL << 4)) + +/* CLK_SRC_PERIC1 */ +/* SRC_CLOCK = SCLK_EPLL */ +#define SPI0_SEL 6 +#define SPI1_SEL 6 +#define SPI2_SEL 6 +#define AUDIO0_SEL 6 +#define AUDIO1_SEL 6 +#define AUDIO2_SEL 6 +#define CLK_SRC_PERIC1_VAL ((SPI2_SEL << 28) \ + | (SPI1_SEL << 24) \ + | (SPI0_SEL << 20) \ + | (AUDIO2_SEL << 16) \ + | (AUDIO2_SEL << 12) \ + | (AUDIO2_SEL << 8)) + +/* CLK_DIV_PERIC0 */ +#define PWM_RATIO 8 +#define UART4_RATIO 9 +#define UART3_RATIO 9 +#define UART2_RATIO 9 +#define UART1_RATIO 9 +#define UART0_RATIO 9 + +#define CLK_DIV_PERIC0_VAL ((PWM_RATIO << 28) \ + | (UART4_RATIO << 24) \ + | (UART3_RATIO << 20) \ + | (UART2_RATIO << 16) \ + | (UART1_RATIO << 12) \ + | (UART0_RATIO << 8)) +/* CLK_DIV_PERIC1 */ +#define SPI2_RATIO 0x1 +#define SPI1_RATIO 0x1 +#define SPI0_RATIO 0x1 +#define CLK_DIV_PERIC1_VAL ((SPI2_RATIO << 28) \ + | (SPI1_RATIO << 24) \ + | (SPI0_RATIO << 20)) + +/* CLK_DIV_PERIC2 */ +#define PCM2_RATIO 0x3 +#define PCM1_RATIO 0x3 +#define CLK_DIV_PERIC2_VAL ((PCM2_RATIO << 24) \ + | (PCM1_RATIO << 16)) + +/* CLK_DIV_PERIC3 */ +#define AUDIO2_RATIO 0x5 +#define AUDIO1_RATIO 0x5 +#define AUDIO0_RATIO 0x5 +#define CLK_DIV_PERIC3_VAL ((AUDIO2_RATIO << 28) \ + | (AUDIO1_RATIO << 24) \ + | (AUDIO0_RATIO << 20)) + +/* CLK_DIV_PERIC4 */ +#define SPI2_PRE_RATIO 0x2 +#define SPI1_PRE_RATIO 0x2 +#define SPI0_PRE_RATIO 0x2 +#define CLK_DIV_PERIC4_VAL ((SPI2_PRE_RATIO << 24) \ + | (SPI1_PRE_RATIO << 16) \ + | (SPI0_PRE_RATIO << 8)) + +/* CLK_SRC_DISP1_0 */ +#define CLK_SRC_DISP1_0_VAL 0x10666600 +#define CLK_DIV_DISP1_0_VAL 0x01050211 + +#define APLL_FOUT (1 << 0) +#define KPLL_FOUT (1 << 0) + +#define CLK_DIV_CPERI1_VAL 0x3f3f0000 +#endif + +struct mem_timings; + +/* Errors that we can encourter in low-level setup */ +enum { + SETUP_ERR_OK, + SETUP_ERR_RDLV_COMPLETE_TIMEOUT = -1, + SETUP_ERR_ZQ_CALIBRATION_FAILURE = -2, +}; + +/* + * Memory variant specific initialization code for DDR3 + * + * @param mem Memory timings for this memory type. + * @param mem_iv_size Memory interleaving size is a configurable parameter + * which the DMC uses to decide how to split a memory + * chunk into smaller chunks to support concurrent + * accesses; may vary across boards. + * @param reset Reset DDR PHY during initialization. + * @return 0 if ok, SETUP_ERR_... if there is a problem + */ +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, + int reset); + +/* Memory variant specific initialization code for LPDDR3 */ +void lpddr3_mem_ctrl_init(void); + +/* + * Configure ZQ I/O interface + * + * @param mem Memory timings for this memory type. + * @param phy0_con16 Register address for dmc_phy0->phy_con16 + * @param phy1_con16 Register address for dmc_phy1->phy_con16 + * @param phy0_con17 Register address for dmc_phy0->phy_con17 + * @param phy1_con17 Register address for dmc_phy1->phy_con17 + * @return 0 if ok, -1 on error + */ +int dmc_config_zq(struct mem_timings *mem, uint32_t *phy0_con16, + uint32_t *phy1_con16, uint32_t *phy0_con17, + uint32_t *phy1_con17); +/* + * Send NOP and MRS/EMRS Direct commands + * + * @param mem Memory timings for this memory type. + * @param directcmd Register address for dmc_phy->directcmd + */ +void dmc_config_mrs(struct mem_timings *mem, uint32_t *directcmd); + +/* + * Send PALL Direct commands + * + * @param mem Memory timings for this memory type. + * @param directcmd Register address for dmc_phy->directcmd + */ +void dmc_config_prech(struct mem_timings *mem, uint32_t *directcmd); + +/* + * Reset the DLL. This function is common between DDR3 and LPDDR2. + * However, the reset value is different. So we are passing a flag + * ddr_mode to distinguish between LPDDR2 and DDR3. + * + * @param phycontrol0 Register address for dmc_phy->phycontrol0 + * @param ddr_mode Type of DDR memory + */ +void update_reset_dll(uint32_t *phycontrol0, enum ddr_mode); +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/lowlevel_init.c new file mode 100644 index 000000000..11fe5b8d0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -0,0 +1,73 @@ +/* + * Lowlevel setup for EXYNOS5 based board + * + * Copyright (C) 2013 Samsung Electronics + * Rajeshwari Shinde <rajeshwari.s@samsung.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <asm/arch/cpu.h> +#include <asm/arch/dmc.h> +#include <asm/arch/power.h> +#include <asm/arch/tzpc.h> +#include <asm/arch/periph.h> +#include <asm/arch/pinmux.h> +#include "common_setup.h" + +/* These are the things we can do during low-level init */ +enum { + DO_WAKEUP = 1 << 0, + DO_CLOCKS = 1 << 1, + DO_MEM_RESET = 1 << 2, + DO_UART = 1 << 3, +}; + +int do_lowlevel_init(void) +{ + uint32_t reset_status; + int actions = 0; + + arch_cpu_init(); + + reset_status = get_reset_status(); + + switch (reset_status) { + case S5P_CHECK_SLEEP: + actions = DO_CLOCKS | DO_WAKEUP; + break; + case S5P_CHECK_DIDLE: + case S5P_CHECK_LPA: + actions = DO_WAKEUP; + break; + default: + /* This is a normal boot (not a wake from sleep) */ + actions = DO_CLOCKS | DO_MEM_RESET; + } + + if (actions & DO_CLOCKS) { + system_clock_init(); + mem_ctrl_init(actions & DO_MEM_RESET); + tzpc_init(); + } + + return actions & DO_WAKEUP; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/pinmux.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/pinmux.c new file mode 100644 index 000000000..9edb47502 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/pinmux.c @@ -0,0 +1,793 @@ +/* + * Copyright (c) 2012 Samsung Electronics. + * Abhilash Kesavan <a.kesavan@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fdtdec.h> +#include <asm/arch/gpio.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/sromc.h> + +static void exynos5_uart_config(int peripheral) +{ + struct exynos5_gpio_part1 *gpio1 = + (struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1(); + struct s5p_gpio_bank *bank; + int i, start, count; + + switch (peripheral) { + case PERIPH_ID_UART0: + bank = &gpio1->a0; + start = 0; + count = 4; + break; + case PERIPH_ID_UART1: + bank = &gpio1->d0; + start = 0; + count = 4; + break; + case PERIPH_ID_UART2: + bank = &gpio1->a1; + start = 0; + count = 4; + break; + case PERIPH_ID_UART3: + bank = &gpio1->a1; + start = 4; + count = 2; + break; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return; + } + for (i = start; i < start + count; i++) { + s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + } +} + +static void exynos5420_uart_config(int peripheral) +{ + struct exynos5420_gpio_part1 *gpio1 = + (struct exynos5420_gpio_part1 *)samsung_get_base_gpio_part1(); + struct s5p_gpio_bank *bank; + int i, start, count; + + switch (peripheral) { + case PERIPH_ID_UART0: + bank = &gpio1->a0; + start = 0; + count = 4; + break; + case PERIPH_ID_UART1: + bank = &gpio1->a0; + start = 4; + count = 4; + break; + case PERIPH_ID_UART2: + bank = &gpio1->a1; + start = 0; + count = 4; + break; + case PERIPH_ID_UART3: + bank = &gpio1->a1; + start = 4; + count = 2; + break; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return; + } + + for (i = start; i < start + count; i++) { + s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + } +} + +static int exynos5_mmc_config(int peripheral, int flags) +{ + struct exynos5_gpio_part1 *gpio1 = + (struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1(); + struct s5p_gpio_bank *bank, *bank_ext; + int i, start = 0, gpio_func = 0; + + switch (peripheral) { + case PERIPH_ID_SDMMC0: + bank = &gpio1->c0; + bank_ext = &gpio1->c1; + start = 0; + gpio_func = GPIO_FUNC(0x2); + break; + case PERIPH_ID_SDMMC1: + bank = &gpio1->c2; + bank_ext = NULL; + break; + case PERIPH_ID_SDMMC2: + bank = &gpio1->c3; + bank_ext = &gpio1->c4; + start = 3; + gpio_func = GPIO_FUNC(0x3); + break; + case PERIPH_ID_SDMMC3: + bank = &gpio1->c4; + bank_ext = NULL; + break; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + if ((flags & PINMUX_FLAG_8BIT_MODE) && !bank_ext) { + debug("SDMMC device %d does not support 8bit mode", + peripheral); + return -1; + } + if (flags & PINMUX_FLAG_8BIT_MODE) { + for (i = start; i <= (start + 3); i++) { + s5p_gpio_cfg_pin(bank_ext, i, gpio_func); + s5p_gpio_set_pull(bank_ext, i, GPIO_PULL_UP); + s5p_gpio_set_drv(bank_ext, i, GPIO_DRV_4X); + } + } + for (i = 0; i < 2; i++) { + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); + s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); + } + for (i = 3; i <= 6; i++) { + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + s5p_gpio_set_pull(bank, i, GPIO_PULL_UP); + s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); + } + + return 0; +} + +static int exynos5420_mmc_config(int peripheral, int flags) +{ + struct exynos5420_gpio_part3 *gpio3 = + (struct exynos5420_gpio_part3 *)samsung_get_base_gpio_part3(); + struct s5p_gpio_bank *bank = NULL, *bank_ext = NULL; + int i, start; + + switch (peripheral) { + case PERIPH_ID_SDMMC0: + bank = &gpio3->c0; + bank_ext = &gpio3->c3; + start = 0; + break; + case PERIPH_ID_SDMMC1: + bank = &gpio3->c1; + bank_ext = &gpio3->d1; + start = 4; + break; + case PERIPH_ID_SDMMC2: + bank = &gpio3->c2; + bank_ext = NULL; + start = 0; + break; + default: + start = 0; + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + + if ((flags & PINMUX_FLAG_8BIT_MODE) && !bank_ext) { + debug("SDMMC device %d does not support 8bit mode", + peripheral); + return -1; + } + + if (flags & PINMUX_FLAG_8BIT_MODE) { + for (i = start; i <= (start + 3); i++) { + s5p_gpio_cfg_pin(bank_ext, i, GPIO_FUNC(0x2)); + s5p_gpio_set_pull(bank_ext, i, GPIO_PULL_UP); + s5p_gpio_set_drv(bank_ext, i, GPIO_DRV_4X); + } + } + + for (i = 0; i < 3; i++) { + /* + * MMC0 is intended to be used for eMMC. The + * card detect pin is used as a VDDEN signal to + * power on the eMMC. The 5420 iROM makes + * this same assumption. + */ + if ((peripheral == PERIPH_ID_SDMMC0) && (i == 2)) { + s5p_gpio_set_value(bank, i, 1); + s5p_gpio_cfg_pin(bank, i, GPIO_OUTPUT); + } else { + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + } + s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); + s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); + } + + for (i = 3; i <= 6; i++) { + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + s5p_gpio_set_pull(bank, i, GPIO_PULL_UP); + s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); + } + + return 0; +} + +static void exynos5_sromc_config(int flags) +{ + struct exynos5_gpio_part1 *gpio1 = + (struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1(); + int i; + + /* + * SROM:CS1 and EBI + * + * GPY0[0] SROM_CSn[0] + * GPY0[1] SROM_CSn[1](2) + * GPY0[2] SROM_CSn[2] + * GPY0[3] SROM_CSn[3] + * GPY0[4] EBI_OEn(2) + * GPY0[5] EBI_EEn(2) + * + * GPY1[0] EBI_BEn[0](2) + * GPY1[1] EBI_BEn[1](2) + * GPY1[2] SROM_WAIT(2) + * GPY1[3] EBI_DATA_RDn(2) + */ + s5p_gpio_cfg_pin(&gpio1->y0, (flags & PINMUX_FLAG_BANK), + GPIO_FUNC(2)); + s5p_gpio_cfg_pin(&gpio1->y0, 4, GPIO_FUNC(2)); + s5p_gpio_cfg_pin(&gpio1->y0, 5, GPIO_FUNC(2)); + + for (i = 0; i < 4; i++) + s5p_gpio_cfg_pin(&gpio1->y1, i, GPIO_FUNC(2)); + + /* + * EBI: 8 Addrss Lines + * + * GPY3[0] EBI_ADDR[0](2) + * GPY3[1] EBI_ADDR[1](2) + * GPY3[2] EBI_ADDR[2](2) + * GPY3[3] EBI_ADDR[3](2) + * GPY3[4] EBI_ADDR[4](2) + * GPY3[5] EBI_ADDR[5](2) + * GPY3[6] EBI_ADDR[6](2) + * GPY3[7] EBI_ADDR[7](2) + * + * EBI: 16 Data Lines + * + * GPY5[0] EBI_DATA[0](2) + * GPY5[1] EBI_DATA[1](2) + * GPY5[2] EBI_DATA[2](2) + * GPY5[3] EBI_DATA[3](2) + * GPY5[4] EBI_DATA[4](2) + * GPY5[5] EBI_DATA[5](2) + * GPY5[6] EBI_DATA[6](2) + * GPY5[7] EBI_DATA[7](2) + * + * GPY6[0] EBI_DATA[8](2) + * GPY6[1] EBI_DATA[9](2) + * GPY6[2] EBI_DATA[10](2) + * GPY6[3] EBI_DATA[11](2) + * GPY6[4] EBI_DATA[12](2) + * GPY6[5] EBI_DATA[13](2) + * GPY6[6] EBI_DATA[14](2) + * GPY6[7] EBI_DATA[15](2) + */ + for (i = 0; i < 8; i++) { + s5p_gpio_cfg_pin(&gpio1->y3, i, GPIO_FUNC(2)); + s5p_gpio_set_pull(&gpio1->y3, i, GPIO_PULL_UP); + + s5p_gpio_cfg_pin(&gpio1->y5, i, GPIO_FUNC(2)); + s5p_gpio_set_pull(&gpio1->y5, i, GPIO_PULL_UP); + + s5p_gpio_cfg_pin(&gpio1->y6, i, GPIO_FUNC(2)); + s5p_gpio_set_pull(&gpio1->y6, i, GPIO_PULL_UP); + } +} + +static void exynos5_i2c_config(int peripheral, int flags) +{ + + struct exynos5_gpio_part1 *gpio1 = + (struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1(); + + switch (peripheral) { + case PERIPH_ID_I2C0: + s5p_gpio_cfg_pin(&gpio1->b3, 0, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b3, 1, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C1: + s5p_gpio_cfg_pin(&gpio1->b3, 2, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b3, 3, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C2: + s5p_gpio_cfg_pin(&gpio1->a0, 6, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a0, 7, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C3: + s5p_gpio_cfg_pin(&gpio1->a1, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a1, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C4: + s5p_gpio_cfg_pin(&gpio1->a2, 0, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a2, 1, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C5: + s5p_gpio_cfg_pin(&gpio1->a2, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a2, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C6: + s5p_gpio_cfg_pin(&gpio1->b1, 3, GPIO_FUNC(0x4)); + s5p_gpio_cfg_pin(&gpio1->b1, 4, GPIO_FUNC(0x4)); + break; + case PERIPH_ID_I2C7: + s5p_gpio_cfg_pin(&gpio1->b2, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->b2, 3, GPIO_FUNC(0x3)); + break; + } +} + +static void exynos5420_i2c_config(int peripheral) +{ + struct exynos5420_gpio_part1 *gpio1 = + (struct exynos5420_gpio_part1 *)samsung_get_base_gpio_part1(); + + switch (peripheral) { + case PERIPH_ID_I2C0: + s5p_gpio_cfg_pin(&gpio1->b3, 0, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b3, 1, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C1: + s5p_gpio_cfg_pin(&gpio1->b3, 2, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b3, 3, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C2: + s5p_gpio_cfg_pin(&gpio1->a0, 6, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a0, 7, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C3: + s5p_gpio_cfg_pin(&gpio1->a1, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a1, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C4: + s5p_gpio_cfg_pin(&gpio1->a2, 0, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a2, 1, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C5: + s5p_gpio_cfg_pin(&gpio1->a2, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a2, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C6: + s5p_gpio_cfg_pin(&gpio1->b1, 3, GPIO_FUNC(0x4)); + s5p_gpio_cfg_pin(&gpio1->b1, 4, GPIO_FUNC(0x4)); + break; + case PERIPH_ID_I2C7: + s5p_gpio_cfg_pin(&gpio1->b2, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->b2, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C8: + s5p_gpio_cfg_pin(&gpio1->b3, 4, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b3, 5, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C9: + s5p_gpio_cfg_pin(&gpio1->b3, 6, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b3, 7, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C10: + s5p_gpio_cfg_pin(&gpio1->b4, 0, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b4, 1, GPIO_FUNC(0x2)); + break; + } +} + +static void exynos5_i2s_config(int peripheral) +{ + int i; + struct exynos5_gpio_part1 *gpio1 = + (struct exynos5_gpio_part1 *)samsung_get_base_gpio_part1(); + struct exynos5_gpio_part4 *gpio4 = + (struct exynos5_gpio_part4 *)samsung_get_base_gpio_part4(); + + switch (peripheral) { + case PERIPH_ID_I2S0: + for (i = 0; i < 5; i++) + s5p_gpio_cfg_pin(&gpio4->z, i, GPIO_FUNC(0x02)); + break; + case PERIPH_ID_I2S1: + for (i = 0; i < 5; i++) + s5p_gpio_cfg_pin(&gpio1->b0, i, GPIO_FUNC(0x02)); + break; + } +} + +void exynos5_spi_config(int peripheral) +{ + int cfg = 0, pin = 0, i; + struct s5p_gpio_bank *bank = NULL; + struct exynos5_gpio_part1 *gpio1 = + (struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1(); + struct exynos5_gpio_part2 *gpio2 = + (struct exynos5_gpio_part2 *) samsung_get_base_gpio_part2(); + + switch (peripheral) { + case PERIPH_ID_SPI0: + bank = &gpio1->a2; + cfg = GPIO_FUNC(0x2); + pin = 0; + break; + case PERIPH_ID_SPI1: + bank = &gpio1->a2; + cfg = GPIO_FUNC(0x2); + pin = 4; + break; + case PERIPH_ID_SPI2: + bank = &gpio1->b1; + cfg = GPIO_FUNC(0x5); + pin = 1; + break; + case PERIPH_ID_SPI3: + bank = &gpio2->f1; + cfg = GPIO_FUNC(0x2); + pin = 0; + break; + case PERIPH_ID_SPI4: + for (i = 0; i < 2; i++) { + s5p_gpio_cfg_pin(&gpio2->f0, i + 2, GPIO_FUNC(0x4)); + s5p_gpio_cfg_pin(&gpio2->e0, i + 4, GPIO_FUNC(0x4)); + } + break; + } + if (peripheral != PERIPH_ID_SPI4) { + for (i = pin; i < pin + 4; i++) + s5p_gpio_cfg_pin(bank, i, cfg); + } +} + +void exynos5420_spi_config(int peripheral) +{ + int cfg, pin, i; + struct s5p_gpio_bank *bank = NULL; + struct exynos5420_gpio_part1 *gpio1 = + (struct exynos5420_gpio_part1 *)samsung_get_base_gpio_part1(); + struct exynos5420_gpio_part4 *gpio4 = + (struct exynos5420_gpio_part4 *)samsung_get_base_gpio_part4(); + + switch (peripheral) { + case PERIPH_ID_SPI0: + bank = &gpio1->a2; + cfg = GPIO_FUNC(0x2); + pin = 0; + break; + case PERIPH_ID_SPI1: + bank = &gpio1->a2; + cfg = GPIO_FUNC(0x2); + pin = 4; + break; + case PERIPH_ID_SPI2: + bank = &gpio1->b1; + cfg = GPIO_FUNC(0x5); + pin = 1; + break; + case PERIPH_ID_SPI3: + bank = &gpio4->f1; + cfg = GPIO_FUNC(0x2); + pin = 0; + break; + case PERIPH_ID_SPI4: + cfg = 0; + pin = 0; + break; + default: + cfg = 0; + pin = 0; + debug("%s: invalid peripheral %d", __func__, peripheral); + return; + } + + if (peripheral != PERIPH_ID_SPI4) { + for (i = pin; i < pin + 4; i++) + s5p_gpio_cfg_pin(bank, i, cfg); + } else { + for (i = 0; i < 2; i++) { + s5p_gpio_cfg_pin(&gpio4->f0, i + 2, GPIO_FUNC(0x4)); + s5p_gpio_cfg_pin(&gpio4->e0, i + 4, GPIO_FUNC(0x4)); + } + } +} + +static int exynos5_pinmux_config(int peripheral, int flags) +{ + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case PERIPH_ID_UART3: + exynos5_uart_config(peripheral); + break; + case PERIPH_ID_SDMMC0: + case PERIPH_ID_SDMMC1: + case PERIPH_ID_SDMMC2: + case PERIPH_ID_SDMMC3: + return exynos5_mmc_config(peripheral, flags); + case PERIPH_ID_SROMC: + exynos5_sromc_config(flags); + break; + case PERIPH_ID_I2C0: + case PERIPH_ID_I2C1: + case PERIPH_ID_I2C2: + case PERIPH_ID_I2C3: + case PERIPH_ID_I2C4: + case PERIPH_ID_I2C5: + case PERIPH_ID_I2C6: + case PERIPH_ID_I2C7: + exynos5_i2c_config(peripheral, flags); + break; + case PERIPH_ID_I2S0: + case PERIPH_ID_I2S1: + exynos5_i2s_config(peripheral); + break; + case PERIPH_ID_SPI0: + case PERIPH_ID_SPI1: + case PERIPH_ID_SPI2: + case PERIPH_ID_SPI3: + case PERIPH_ID_SPI4: + exynos5_spi_config(peripheral); + break; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + + return 0; +} + +static int exynos5420_pinmux_config(int peripheral, int flags) +{ + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case PERIPH_ID_UART3: + exynos5420_uart_config(peripheral); + break; + case PERIPH_ID_SDMMC0: + case PERIPH_ID_SDMMC1: + case PERIPH_ID_SDMMC2: + case PERIPH_ID_SDMMC3: + return exynos5420_mmc_config(peripheral, flags); + case PERIPH_ID_SPI0: + case PERIPH_ID_SPI1: + case PERIPH_ID_SPI2: + case PERIPH_ID_SPI3: + case PERIPH_ID_SPI4: + exynos5420_spi_config(peripheral); + break; + case PERIPH_ID_I2C0: + case PERIPH_ID_I2C1: + case PERIPH_ID_I2C2: + case PERIPH_ID_I2C3: + case PERIPH_ID_I2C4: + case PERIPH_ID_I2C5: + case PERIPH_ID_I2C6: + case PERIPH_ID_I2C7: + case PERIPH_ID_I2C8: + case PERIPH_ID_I2C9: + case PERIPH_ID_I2C10: + exynos5420_i2c_config(peripheral); + break; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + + return 0; +} + +static void exynos4_i2c_config(int peripheral, int flags) +{ + struct exynos4_gpio_part1 *gpio1 = + (struct exynos4_gpio_part1 *) samsung_get_base_gpio_part1(); + + switch (peripheral) { + case PERIPH_ID_I2C0: + s5p_gpio_cfg_pin(&gpio1->d1, 0, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->d1, 1, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C1: + s5p_gpio_cfg_pin(&gpio1->d1, 2, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->d1, 3, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C2: + s5p_gpio_cfg_pin(&gpio1->a0, 6, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a0, 7, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C3: + s5p_gpio_cfg_pin(&gpio1->a1, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a1, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C4: + s5p_gpio_cfg_pin(&gpio1->b, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->b, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C5: + s5p_gpio_cfg_pin(&gpio1->b, 6, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->b, 7, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C6: + s5p_gpio_cfg_pin(&gpio1->c1, 3, GPIO_FUNC(0x4)); + s5p_gpio_cfg_pin(&gpio1->c1, 4, GPIO_FUNC(0x4)); + break; + case PERIPH_ID_I2C7: + s5p_gpio_cfg_pin(&gpio1->d0, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->d0, 3, GPIO_FUNC(0x3)); + break; + } +} + +static int exynos4_mmc_config(int peripheral, int flags) +{ + struct exynos4_gpio_part2 *gpio2 = + (struct exynos4_gpio_part2 *)samsung_get_base_gpio_part2(); + struct s5p_gpio_bank *bank, *bank_ext; + int i; + + switch (peripheral) { + case PERIPH_ID_SDMMC0: + bank = &gpio2->k0; + bank_ext = &gpio2->k1; + break; + case PERIPH_ID_SDMMC2: + bank = &gpio2->k2; + bank_ext = &gpio2->k3; + break; + default: + return -1; + } + for (i = 0; i < 7; i++) { + if (i == 2) + continue; + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); + s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); + } + if (flags & PINMUX_FLAG_8BIT_MODE) { + for (i = 3; i < 7; i++) { + s5p_gpio_cfg_pin(bank_ext, i, GPIO_FUNC(0x3)); + s5p_gpio_set_pull(bank_ext, i, GPIO_PULL_NONE); + s5p_gpio_set_drv(bank_ext, i, GPIO_DRV_4X); + } + } + + return 0; +} + +static void exynos4_uart_config(int peripheral) +{ + struct exynos4_gpio_part1 *gpio1 = + (struct exynos4_gpio_part1 *)samsung_get_base_gpio_part1(); + struct s5p_gpio_bank *bank; + int i, start, count; + + switch (peripheral) { + case PERIPH_ID_UART0: + bank = &gpio1->a0; + start = 0; + count = 4; + break; + case PERIPH_ID_UART1: + bank = &gpio1->a0; + start = 4; + count = 4; + break; + case PERIPH_ID_UART2: + bank = &gpio1->a1; + start = 0; + count = 4; + break; + case PERIPH_ID_UART3: + bank = &gpio1->a1; + start = 4; + count = 2; + break; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return; + } + for (i = start; i < start + count; i++) { + s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + } +} +static int exynos4_pinmux_config(int peripheral, int flags) +{ + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case PERIPH_ID_UART3: + exynos4_uart_config(peripheral); + break; + case PERIPH_ID_I2C0: + case PERIPH_ID_I2C1: + case PERIPH_ID_I2C2: + case PERIPH_ID_I2C3: + case PERIPH_ID_I2C4: + case PERIPH_ID_I2C5: + case PERIPH_ID_I2C6: + case PERIPH_ID_I2C7: + exynos4_i2c_config(peripheral, flags); + break; + case PERIPH_ID_SDMMC0: + case PERIPH_ID_SDMMC2: + return exynos4_mmc_config(peripheral, flags); + case PERIPH_ID_SDMMC1: + case PERIPH_ID_SDMMC3: + case PERIPH_ID_SDMMC4: + debug("SDMMC device %d not implemented\n", peripheral); + return -1; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + + return 0; +} + +int exynos_pinmux_config(int peripheral, int flags) +{ + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_pinmux_config(peripheral, flags); + else if (proid_is_exynos5250()) + return exynos5_pinmux_config(peripheral, flags); + } else if (cpu_is_exynos4()) { + return exynos4_pinmux_config(peripheral, flags); + } else { + debug("pinmux functionality not supported\n"); + } + + return -1; +} + +#ifdef CONFIG_OF_CONTROL +static int exynos4_pinmux_decode_periph_id(const void *blob, int node) +{ + int err; + u32 cell[3]; + + err = fdtdec_get_int_array(blob, node, "interrupts", cell, + ARRAY_SIZE(cell)); + if (err) { + debug(" invalid peripheral id\n"); + return PERIPH_ID_NONE; + } + + return cell[1]; +} + +static int exynos5_pinmux_decode_periph_id(const void *blob, int node) +{ + int err; + u32 cell[3]; + + err = fdtdec_get_int_array(blob, node, "interrupts", cell, + ARRAY_SIZE(cell)); + if (err) + return PERIPH_ID_NONE; + + return cell[1]; +} + +int pinmux_decode_periph_id(const void *blob, int node) +{ + if (cpu_is_exynos5()) + return exynos5_pinmux_decode_periph_id(blob, node); + else if (cpu_is_exynos4()) + return exynos4_pinmux_decode_periph_id(blob, node); + else + return PERIPH_ID_NONE; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/power.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/power.c new file mode 100644 index 000000000..563abd750 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/power.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * Donghwa Lee <dh09.lee@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/power.h> + +static void exynos4_mipi_phy_control(unsigned int dev_index, + unsigned int enable) +{ + struct exynos4_power *pmu = + (struct exynos4_power *)samsung_get_base_power(); + unsigned int addr, cfg = 0; + + if (dev_index == 0) + addr = (unsigned int)&pmu->mipi_phy0_control; + else + addr = (unsigned int)&pmu->mipi_phy1_control; + + + cfg = readl(addr); + if (enable) + cfg |= (EXYNOS_MIPI_PHY_MRESETN | EXYNOS_MIPI_PHY_ENABLE); + else + cfg &= ~(EXYNOS_MIPI_PHY_MRESETN | EXYNOS_MIPI_PHY_ENABLE); + + writel(cfg, addr); +} + +void set_mipi_phy_ctrl(unsigned int dev_index, unsigned int enable) +{ + if (cpu_is_exynos4()) + exynos4_mipi_phy_control(dev_index, enable); +} + +void exynos5_set_usbhost_phy_ctrl(unsigned int enable) +{ + struct exynos5_power *power = + (struct exynos5_power *)samsung_get_base_power(); + + if (enable) { + /* Enabling USBHOST_PHY */ + setbits_le32(&power->usbhost_phy_control, + POWER_USB_HOST_PHY_CTRL_EN); + } else { + /* Disabling USBHOST_PHY */ + clrbits_le32(&power->usbhost_phy_control, + POWER_USB_HOST_PHY_CTRL_EN); + } +} + +void set_usbhost_phy_ctrl(unsigned int enable) +{ + if (cpu_is_exynos5()) + exynos5_set_usbhost_phy_ctrl(enable); +} + +static void exynos5_set_usbdrd_phy_ctrl(unsigned int enable) +{ + struct exynos5_power *power = + (struct exynos5_power *)samsung_get_base_power(); + + if (enable) { + /* Enabling USBDRD_PHY */ + setbits_le32(&power->usbdrd_phy_control, + POWER_USB_DRD_PHY_CTRL_EN); + } else { + /* Disabling USBDRD_PHY */ + clrbits_le32(&power->usbdrd_phy_control, + POWER_USB_DRD_PHY_CTRL_EN); + } +} + +void set_usbdrd_phy_ctrl(unsigned int enable) +{ + if (cpu_is_exynos5()) + exynos5_set_usbdrd_phy_ctrl(enable); +} + +static void exynos5_dp_phy_control(unsigned int enable) +{ + unsigned int cfg; + struct exynos5_power *power = + (struct exynos5_power *)samsung_get_base_power(); + + cfg = readl(&power->dptx_phy_control); + if (enable) + cfg |= EXYNOS_DP_PHY_ENABLE; + else + cfg &= ~EXYNOS_DP_PHY_ENABLE; + + writel(cfg, &power->dptx_phy_control); +} + +void set_dp_phy_ctrl(unsigned int enable) +{ + if (cpu_is_exynos5()) + exynos5_dp_phy_control(enable); +} + +static void exynos5_set_ps_hold_ctrl(void) +{ + struct exynos5_power *power = + (struct exynos5_power *)samsung_get_base_power(); + + /* Set PS-Hold high */ + setbits_le32(&power->ps_hold_control, + EXYNOS_PS_HOLD_CONTROL_DATA_HIGH); +} + +void set_ps_hold_ctrl(void) +{ + if (cpu_is_exynos5()) + exynos5_set_ps_hold_ctrl(); +} + + +static void exynos5_set_xclkout(void) +{ + struct exynos5_power *power = + (struct exynos5_power *)samsung_get_base_power(); + + /* use xxti for xclk out */ + clrsetbits_le32(&power->pmu_debug, PMU_DEBUG_CLKOUT_SEL_MASK, + PMU_DEBUG_XXTI); +} + +void set_xclkout(void) +{ + if (cpu_is_exynos5()) + exynos5_set_xclkout(); +} + +/* Enables hardware tripping to power off the system when TMU fails */ +void set_hw_thermal_trip(void) +{ + if (cpu_is_exynos5()) { + struct exynos5_power *power = + (struct exynos5_power *)samsung_get_base_power(); + + /* PS_HOLD_CONTROL register ENABLE_HW_TRIP bit*/ + setbits_le32(&power->ps_hold_control, POWER_ENABLE_HW_TRIP); + } +} + +static uint32_t exynos5_get_reset_status(void) +{ + struct exynos5_power *power = + (struct exynos5_power *)samsung_get_base_power(); + + return power->inform1; +} + +static uint32_t exynos4_get_reset_status(void) +{ + struct exynos4_power *power = + (struct exynos4_power *)samsung_get_base_power(); + + return power->inform1; +} + +uint32_t get_reset_status(void) +{ + if (cpu_is_exynos5()) + return exynos5_get_reset_status(); + else + return exynos4_get_reset_status(); +} + +static void exynos5_power_exit_wakeup(void) +{ + struct exynos5_power *power = + (struct exynos5_power *)samsung_get_base_power(); + typedef void (*resume_func)(void); + + ((resume_func)power->inform0)(); +} + +static void exynos4_power_exit_wakeup(void) +{ + struct exynos4_power *power = + (struct exynos4_power *)samsung_get_base_power(); + typedef void (*resume_func)(void); + + ((resume_func)power->inform0)(); +} + +void power_exit_wakeup(void) +{ + if (cpu_is_exynos5()) + exynos5_power_exit_wakeup(); + else + exynos4_power_exit_wakeup(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/soc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/soc.c new file mode 100644 index 000000000..8c7d7d893 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/soc.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010 Samsung Electronics. + * Minkyu Kang <mk7.kang@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/system.h> + +enum l2_cache_params { + CACHE_TAG_RAM_SETUP = (1 << 9), + CACHE_DATA_RAM_SETUP = (1 << 5), + CACHE_TAG_RAM_LATENCY = (2 << 6), + CACHE_DATA_RAM_LATENCY = (2 << 0) +}; + +void reset_cpu(ulong addr) +{ + writel(0x1, samsung_get_base_swreset()); +} + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif + +#ifndef CONFIG_SYS_L2CACHE_OFF +/* + * Set L2 cache parameters + */ +static void exynos5_set_l2cache_params(void) +{ + unsigned int val = 0; + + asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r"(val)); + + val |= CACHE_TAG_RAM_SETUP | + CACHE_DATA_RAM_SETUP | + CACHE_TAG_RAM_LATENCY | + CACHE_DATA_RAM_LATENCY; + + asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val)); +} + +/* + * Sets L2 cache related parameters before enabling data cache + */ +void v7_outer_cache_enable(void) +{ + if (cpu_is_exynos5()) + exynos5_set_l2cache_params(); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/spl_boot.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/spl_boot.c new file mode 100644 index 000000000..ade45fd5d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/spl_boot.c @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include<common.h> +#include<config.h> + +#include <asm/arch/clock.h> +#include <asm/arch/clk.h> +#include <asm/arch/dmc.h> +#include <asm/arch/periph.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/power.h> +#include <asm/arch/spl.h> +#include <asm/arch/spi.h> + +#include "common_setup.h" +#include "clock_init.h" + +DECLARE_GLOBAL_DATA_PTR; +#define OM_STAT (0x1f << 1) + +/* Index into irom ptr table */ +enum index { + MMC_INDEX, + EMMC44_INDEX, + EMMC44_END_INDEX, + SPI_INDEX, + USB_INDEX, +}; + +/* IROM Function Pointers Table */ +u32 irom_ptr_table[] = { + [MMC_INDEX] = 0x02020030, /* iROM Function Pointer-SDMMC boot */ + [EMMC44_INDEX] = 0x02020044, /* iROM Function Pointer-EMMC4.4 boot*/ + [EMMC44_END_INDEX] = 0x02020048,/* iROM Function Pointer + -EMMC4.4 end boot operation */ + [SPI_INDEX] = 0x02020058, /* iROM Function Pointer-SPI boot */ + [USB_INDEX] = 0x02020070, /* iROM Function Pointer-USB boot*/ + }; + +void *get_irom_func(int index) +{ + return (void *)*(u32 *)irom_ptr_table[index]; +} + +#ifdef CONFIG_USB_BOOTING +/* + * Set/clear program flow prediction and return the previous state. + */ +static int config_branch_prediction(int set_cr_z) +{ + unsigned int cr; + + /* System Control Register: 11th bit Z Branch prediction enable */ + cr = get_cr(); + set_cr(set_cr_z ? cr | CR_Z : cr & ~CR_Z); + + return cr & CR_Z; +} +#endif + +#ifdef CONFIG_SPI_BOOTING +static void spi_rx_tx(struct exynos_spi *regs, int todo, + void *dinp, void const *doutp, int i) +{ + uint *rxp = (uint *)(dinp + (i * (32 * 1024))); + int rx_lvl, tx_lvl; + uint out_bytes, in_bytes; + + out_bytes = todo; + in_bytes = todo; + setbits_le32(®s->ch_cfg, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_CH_RST); + writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, ®s->pkt_cnt); + + while (in_bytes) { + uint32_t spi_sts; + int temp; + + spi_sts = readl(®s->spi_sts); + rx_lvl = ((spi_sts >> 15) & 0x7f); + tx_lvl = ((spi_sts >> 6) & 0x7f); + while (tx_lvl < 32 && out_bytes) { + temp = 0xffffffff; + writel(temp, ®s->tx_data); + out_bytes -= 4; + tx_lvl += 4; + } + while (rx_lvl >= 4 && in_bytes) { + temp = readl(®s->rx_data); + if (rxp) + *rxp++ = temp; + in_bytes -= 4; + rx_lvl -= 4; + } + } +} + +/* + * Copy uboot from spi flash to RAM + * + * @parma uboot_size size of u-boot to copy + * @param uboot_addr address in u-boot to copy + */ +static void exynos_spi_copy(unsigned int uboot_size, unsigned int uboot_addr) +{ + int upto, todo; + int i, timeout = 100; + struct exynos_spi *regs = (struct exynos_spi *)CONFIG_ENV_SPI_BASE; + + set_spi_clk(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ + /* set the spi1 GPIO */ + exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); + + /* set pktcnt and enable it */ + writel(4 | SPI_PACKET_CNT_EN, ®s->pkt_cnt); + /* set FB_CLK_SEL */ + writel(SPI_FB_DELAY_180, ®s->fb_clk); + /* set CH_WIDTH and BUS_WIDTH as word */ + setbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | + SPI_MODE_BUS_WIDTH_WORD); + clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */ + + /* clear rx and tx channel if set priveously */ + clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); + + setbits_le32(®s->swap_cfg, SPI_RX_SWAP_EN | + SPI_RX_BYTE_SWAP | + SPI_RX_HWORD_SWAP); + + /* do a soft reset */ + setbits_le32(®s->ch_cfg, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_CH_RST); + + /* now set rx and tx channel ON */ + setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); + clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ + + /* Send read instruction (0x3h) followed by a 24 bit addr */ + writel((SF_READ_DATA_CMD << 24) | SPI_FLASH_UBOOT_POS, ®s->tx_data); + + /* waiting for TX done */ + while (!(readl(®s->spi_sts) & SPI_ST_TX_DONE)) { + if (!timeout) { + debug("SPI TIMEOUT\n"); + break; + } + timeout--; + } + + for (upto = 0, i = 0; upto < uboot_size; upto += todo, i++) { + todo = min(uboot_size - upto, (1 << 15)); + spi_rx_tx(regs, todo, (void *)(uboot_addr), + (void *)(SPI_FLASH_UBOOT_POS), i); + } + + setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ + + /* + * Let put controller mode to BYTE as + * SPI driver does not support WORD mode yet + */ + clrbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | + SPI_MODE_BUS_WIDTH_WORD); + writel(0, ®s->swap_cfg); + + /* + * Flush spi tx, rx fifos and reset the SPI controller + * and clear rx/tx channel + */ + clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); +} +#endif + +/* +* Copy U-boot from mmc to RAM: +* COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains +* Pointer to API (Data transfer from mmc to ram) +*/ +void copy_uboot_to_ram(void) +{ + enum boot_mode bootmode = BOOT_MODE_OM; + + u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL; + u32 offset = 0, size = 0; +#ifdef CONFIG_SPI_BOOTING + struct spl_machine_param *param = spl_get_machine_params(); +#endif +#ifdef CONFIG_SUPPORT_EMMC_BOOT + u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst); + void (*end_bootop_from_emmc)(void); +#endif +#ifdef CONFIG_USB_BOOTING + u32 (*usb_copy)(void); + int is_cr_z_set; + unsigned int sec_boot_check; + + /* Read iRAM location to check for secondary USB boot mode */ + sec_boot_check = readl(EXYNOS_IRAM_SECONDARY_BASE); + if (sec_boot_check == EXYNOS_USB_SECONDARY_BOOT) + bootmode = BOOT_MODE_USB; +#endif + + if (bootmode == BOOT_MODE_OM) + bootmode = readl(samsung_get_base_power()) & OM_STAT; + + switch (bootmode) { +#ifdef CONFIG_SPI_BOOTING + case BOOT_MODE_SERIAL: + /* Customised function to copy u-boot from SF */ + exynos_spi_copy(param->uboot_size, CONFIG_SYS_TEXT_BASE); + break; +#endif + case BOOT_MODE_MMC: + offset = BL2_START_OFFSET; + size = BL2_SIZE_BLOC_COUNT; + copy_bl2 = get_irom_func(MMC_INDEX); + break; +#ifdef CONFIG_SUPPORT_EMMC_BOOT + case BOOT_MODE_EMMC: + /* Set the FSYS1 clock divisor value for EMMC boot */ + emmc_boot_clk_div_set(); + + copy_bl2_from_emmc = get_irom_func(EMMC44_INDEX); + end_bootop_from_emmc = get_irom_func(EMMC44_END_INDEX); + + copy_bl2_from_emmc(BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE); + end_bootop_from_emmc(); + break; +#endif +#ifdef CONFIG_USB_BOOTING + case BOOT_MODE_USB: + /* + * iROM needs program flow prediction to be disabled + * before copy from USB device to RAM + */ + is_cr_z_set = config_branch_prediction(0); + usb_copy = get_irom_func(USB_INDEX); + usb_copy(); + config_branch_prediction(is_cr_z_set); + break; +#endif + default: + break; + } + + if (copy_bl2) + copy_bl2(offset, size, CONFIG_SYS_TEXT_BASE); +} + +void memzero(void *s, size_t n) +{ + char *ptr = s; + size_t i; + + for (i = 0; i < n; i++) + *ptr++ = '\0'; +} + +/** + * Set up the U-Boot global_data pointer + * + * This sets the address of the global data, and sets up basic values. + * + * @param gdp Value to give to gd + */ +static void setup_global_data(gd_t *gdp) +{ + gd = gdp; + memzero((void *)gd, sizeof(gd_t)); + gd->flags |= GD_FLG_RELOC; + gd->baudrate = CONFIG_BAUDRATE; + gd->have_console = 1; +} + +void board_init_f(unsigned long bootflag) +{ + __aligned(8) gd_t local_gd; + __attribute__((noreturn)) void (*uboot)(void); + + setup_global_data(&local_gd); + + if (do_lowlevel_init()) + power_exit_wakeup(); + + copy_uboot_to_ram(); + + /* Jump to U-Boot image */ + uboot = (void *)CONFIG_SYS_TEXT_BASE; + (*uboot)(); + /* Never returns Here */ +} + +/* Place Holders */ +void board_init_r(gd_t *id, ulong dest_addr) +{ + /* Function attribute is no-return */ + /* This Function never executes */ + while (1) + ; +} +void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/system.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/system.c new file mode 100644 index 000000000..ad1244583 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/system.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * Donghwa Lee <dh09.lee@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/system.h> + +static void exynos5_set_usbhost_mode(unsigned int mode) +{ + struct exynos5_sysreg *sysreg = + (struct exynos5_sysreg *)samsung_get_base_sysreg(); + + /* Setting USB20PHY_CONFIG register to USB 2.0 HOST link */ + if (mode == USB20_PHY_CFG_HOST_LINK_EN) { + setbits_le32(&sysreg->usb20phy_cfg, + USB20_PHY_CFG_HOST_LINK_EN); + } else { + clrbits_le32(&sysreg->usb20phy_cfg, + USB20_PHY_CFG_HOST_LINK_EN); + } +} + +void set_usbhost_mode(unsigned int mode) +{ + if (cpu_is_exynos5()) + exynos5_set_usbhost_mode(mode); +} + +static void exynos4_set_system_display(void) +{ + struct exynos4_sysreg *sysreg = + (struct exynos4_sysreg *)samsung_get_base_sysreg(); + unsigned int cfg = 0; + + /* + * system register path set + * 0: MIE/MDNIE + * 1: FIMD Bypass + */ + cfg = readl(&sysreg->display_ctrl); + cfg |= (1 << 1); + writel(cfg, &sysreg->display_ctrl); +} + +static void exynos5_set_system_display(void) +{ + struct exynos5_sysreg *sysreg = + (struct exynos5_sysreg *)samsung_get_base_sysreg(); + unsigned int cfg = 0; + + /* + * system register path set + * 0: MIE/MDNIE + * 1: FIMD Bypass + */ + cfg = readl(&sysreg->disp1blk_cfg); + cfg |= (1 << 15); + writel(cfg, &sysreg->disp1blk_cfg); +} + +void set_system_display_ctrl(void) +{ + if (cpu_is_exynos4()) + exynos4_set_system_display(); + else + exynos5_set_system_display(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/tzpc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/tzpc.c new file mode 100644 index 000000000..395077cf2 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/exynos/tzpc.c @@ -0,0 +1,41 @@ +/* + * Lowlevel setup for SMDK5250 board based on S5PC520 + * + * Copyright (C) 2012 Samsung Electronics + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/tzpc.h> +#include <asm/io.h> + +/* Setting TZPC[TrustZone Protection Controller] */ +void tzpc_init(void) +{ + struct exynos_tzpc *tzpc; + unsigned int addr, start = 0, end = 0; + + start = samsung_get_base_tzpc(); + + if (cpu_is_exynos5()) + end = start + ((EXYNOS5_NR_TZPC_BANKS - 1) * TZPC_BASE_OFFSET); + else if (cpu_is_exynos4()) + end = start + ((EXYNOS4_NR_TZPC_BANKS - 1) * TZPC_BASE_OFFSET); + + for (addr = start; addr <= end; addr += TZPC_BASE_OFFSET) { + tzpc = (struct exynos_tzpc *)addr; + + if (addr == start) + writel(R0SIZE, &tzpc->r0size); + + writel(DECPROTXSET, &tzpc->decprot0set); + writel(DECPROTXSET, &tzpc->decprot1set); + + if (cpu_is_exynos5() && (addr == end)) + break; + + writel(DECPROTXSET, &tzpc->decprot2set); + writel(DECPROTXSET, &tzpc->decprot3set); + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/highbank/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/highbank/Makefile new file mode 100644 index 000000000..876099d9a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/highbank/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/highbank/timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/highbank/timer.c new file mode 100644 index 000000000..d56bf2113 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/highbank/timer.c @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2011 Calxeda, Inc. + * + * Based on arm926ejs/mx27/timer.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch-armv7/systimer.h> + +#undef SYSTIMER_BASE +#define SYSTIMER_BASE 0xFFF34000 /* Timer 0 and 1 base */ + +static struct systimer *systimer_base = (struct systimer *)SYSTIMER_BASE; + +/* + * Start the timer + */ +int timer_init(void) +{ + /* + * Setup timer0 + */ + writel(0, &systimer_base->timer0control); + writel(SYSTIMER_RELOAD, &systimer_base->timer0load); + writel(SYSTIMER_RELOAD, &systimer_base->timer0value); + writel(SYSTIMER_EN | SYSTIMER_32BIT | SYSTIMER_PRESC_256, + &systimer_base->timer0control); + + return 0; + +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/Makefile new file mode 100644 index 000000000..b1bd0224e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/Makefile @@ -0,0 +1,17 @@ +# +# (C) Copyright 2012-2014 +# Texas Instruments Incorporated, <www.ti.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += aemif.o +obj-y += init.o +obj-y += psc.o +obj-y += clock.o +obj-y += cmd_clock.o +obj-y += cmd_mon.o +obj-y += keystone_nav.o +obj-y += msmc.o +obj-$(CONFIG_SPL_BUILD) += spl.o +obj-y += ddr3.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/aemif.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/aemif.c new file mode 100644 index 000000000..9b26886db --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/aemif.c @@ -0,0 +1,71 @@ +/* + * Keystone2: Asynchronous EMIF Configuration + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/emif_defs.h> + +#define AEMIF_CFG_SELECT_STROBE(v) ((v) ? 1 << 31 : 0) +#define AEMIF_CFG_EXTEND_WAIT(v) ((v) ? 1 << 30 : 0) +#define AEMIF_CFG_WR_SETUP(v) (((v) & 0x0f) << 26) +#define AEMIF_CFG_WR_STROBE(v) (((v) & 0x3f) << 20) +#define AEMIF_CFG_WR_HOLD(v) (((v) & 0x07) << 17) +#define AEMIF_CFG_RD_SETUP(v) (((v) & 0x0f) << 13) +#define AEMIF_CFG_RD_STROBE(v) (((v) & 0x3f) << 7) +#define AEMIF_CFG_RD_HOLD(v) (((v) & 0x07) << 4) +#define AEMIF_CFG_TURN_AROUND(v) (((v) & 0x03) << 2) +#define AEMIF_CFG_WIDTH(v) (((v) & 0x03) << 0) + +#define set_config_field(reg, field, val) \ + do { \ + if (val != -1) { \ + reg &= ~AEMIF_CFG_##field(0xffffffff); \ + reg |= AEMIF_CFG_##field(val); \ + } \ + } while (0) + +void configure_async_emif(int cs, struct async_emif_config *cfg) +{ + unsigned long tmp; + + if (cfg->mode == ASYNC_EMIF_MODE_NAND) { + tmp = __raw_readl(&davinci_emif_regs->nandfcr); + tmp |= (1 << cs); + __raw_writel(tmp, &davinci_emif_regs->nandfcr); + + } else if (cfg->mode == ASYNC_EMIF_MODE_ONENAND) { + tmp = __raw_readl(&davinci_emif_regs->one_nand_cr); + tmp |= (1 << cs); + __raw_writel(tmp, &davinci_emif_regs->one_nand_cr); + } + + tmp = __raw_readl(&davinci_emif_regs->abncr[cs]); + + set_config_field(tmp, SELECT_STROBE, cfg->select_strobe); + set_config_field(tmp, EXTEND_WAIT, cfg->extend_wait); + set_config_field(tmp, WR_SETUP, cfg->wr_setup); + set_config_field(tmp, WR_STROBE, cfg->wr_strobe); + set_config_field(tmp, WR_HOLD, cfg->wr_hold); + set_config_field(tmp, RD_SETUP, cfg->rd_setup); + set_config_field(tmp, RD_STROBE, cfg->rd_strobe); + set_config_field(tmp, RD_HOLD, cfg->rd_hold); + set_config_field(tmp, TURN_AROUND, cfg->turn_around); + set_config_field(tmp, WIDTH, cfg->width); + + __raw_writel(tmp, &davinci_emif_regs->abncr[cs]); +} + +void init_async_emif(int num_cs, struct async_emif_config *config) +{ + int cs; + + for (cs = 0; cs < num_cs; cs++) + configure_async_emif(cs, config + cs); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/clock.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/clock.c new file mode 100644 index 000000000..bfa4c9d8f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/clock.c @@ -0,0 +1,318 @@ +/* + * Keystone2: pll initialization + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm-generic/errno.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/arch/clock.h> +#include <asm/arch/clock_defs.h> + +static void wait_for_completion(const struct pll_init_data *data) +{ + int i; + for (i = 0; i < 100; i++) { + sdelay(450); + if ((pllctl_reg_read(data->pll, stat) & PLLSTAT_GO) == 0) + break; + } +} + +struct pll_regs { + u32 reg0, reg1; +}; + +static const struct pll_regs pll_regs[] = { + [CORE_PLL] = { K2HK_MAINPLLCTL0, K2HK_MAINPLLCTL1}, + [PASS_PLL] = { K2HK_PASSPLLCTL0, K2HK_PASSPLLCTL1}, + [TETRIS_PLL] = { K2HK_ARMPLLCTL0, K2HK_ARMPLLCTL1}, + [DDR3A_PLL] = { K2HK_DDR3APLLCTL0, K2HK_DDR3APLLCTL1}, + [DDR3B_PLL] = { K2HK_DDR3BPLLCTL0, K2HK_DDR3BPLLCTL1}, +}; + +/* Fout = Fref * NF(mult) / NR(prediv) / OD */ +static unsigned long pll_freq_get(int pll) +{ + unsigned long mult = 1, prediv = 1, output_div = 2; + unsigned long ret; + u32 tmp, reg; + + if (pll == CORE_PLL) { + ret = external_clk[sys_clk]; + if (pllctl_reg_read(pll, ctl) & PLLCTL_PLLEN) { + /* PLL mode */ + tmp = __raw_readl(K2HK_MAINPLLCTL0); + prediv = (tmp & PLL_DIV_MASK) + 1; + mult = (((tmp & PLLM_MULT_HI_SMASK) >> 6) | + (pllctl_reg_read(pll, mult) & + PLLM_MULT_LO_MASK)) + 1; + output_div = ((pllctl_reg_read(pll, secctl) >> + PLL_CLKOD_SHIFT) & PLL_CLKOD_MASK) + 1; + + ret = ret / prediv / output_div * mult; + } + } else { + switch (pll) { + case PASS_PLL: + ret = external_clk[pa_clk]; + reg = K2HK_PASSPLLCTL0; + break; + case TETRIS_PLL: + ret = external_clk[tetris_clk]; + reg = K2HK_ARMPLLCTL0; + break; + case DDR3A_PLL: + ret = external_clk[ddr3a_clk]; + reg = K2HK_DDR3APLLCTL0; + break; + case DDR3B_PLL: + ret = external_clk[ddr3b_clk]; + reg = K2HK_DDR3BPLLCTL0; + break; + default: + return 0; + } + + tmp = __raw_readl(reg); + + if (!(tmp & PLLCTL_BYPASS)) { + /* Bypass disabled */ + prediv = (tmp & PLL_DIV_MASK) + 1; + mult = ((tmp >> PLL_MULT_SHIFT) & PLL_MULT_MASK) + 1; + output_div = ((tmp >> PLL_CLKOD_SHIFT) & + PLL_CLKOD_MASK) + 1; + ret = ((ret / prediv) * mult) / output_div; + } + } + + return ret; +} + +unsigned long clk_get_rate(unsigned int clk) +{ + switch (clk) { + case core_pll_clk: return pll_freq_get(CORE_PLL); + case pass_pll_clk: return pll_freq_get(PASS_PLL); + case tetris_pll_clk: return pll_freq_get(TETRIS_PLL); + case ddr3a_pll_clk: return pll_freq_get(DDR3A_PLL); + case ddr3b_pll_clk: return pll_freq_get(DDR3B_PLL); + case sys_clk0_1_clk: + case sys_clk0_clk: return pll_freq_get(CORE_PLL) / pll0div_read(1); + case sys_clk1_clk: return pll_freq_get(CORE_PLL) / pll0div_read(2); + case sys_clk2_clk: return pll_freq_get(CORE_PLL) / pll0div_read(3); + case sys_clk3_clk: return pll_freq_get(CORE_PLL) / pll0div_read(4); + case sys_clk0_2_clk: return clk_get_rate(sys_clk0_clk) / 2; + case sys_clk0_3_clk: return clk_get_rate(sys_clk0_clk) / 3; + case sys_clk0_4_clk: return clk_get_rate(sys_clk0_clk) / 4; + case sys_clk0_6_clk: return clk_get_rate(sys_clk0_clk) / 6; + case sys_clk0_8_clk: return clk_get_rate(sys_clk0_clk) / 8; + case sys_clk0_12_clk: return clk_get_rate(sys_clk0_clk) / 12; + case sys_clk0_24_clk: return clk_get_rate(sys_clk0_clk) / 24; + case sys_clk1_3_clk: return clk_get_rate(sys_clk1_clk) / 3; + case sys_clk1_4_clk: return clk_get_rate(sys_clk1_clk) / 4; + case sys_clk1_6_clk: return clk_get_rate(sys_clk1_clk) / 6; + case sys_clk1_12_clk: return clk_get_rate(sys_clk1_clk) / 12; + default: + break; + } + return 0; +} + +void init_pll(const struct pll_init_data *data) +{ + u32 tmp, tmp_ctl, pllm, plld, pllod, bwadj; + + pllm = data->pll_m - 1; + plld = (data->pll_d - 1) & PLL_DIV_MASK; + pllod = (data->pll_od - 1) & PLL_CLKOD_MASK; + + if (data->pll == MAIN_PLL) { + /* The requered delay before main PLL configuration */ + sdelay(210000); + + tmp = pllctl_reg_read(data->pll, secctl); + + if (tmp & (PLLCTL_BYPASS)) { + setbits_le32(pll_regs[data->pll].reg1, + BIT(MAIN_ENSAT_OFFSET)); + + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLEN | + PLLCTL_PLLENSRC); + sdelay(340); + + pllctl_reg_setbits(data->pll, secctl, PLLCTL_BYPASS); + pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLPWRDN); + sdelay(21000); + + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLPWRDN); + } else { + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLEN | + PLLCTL_PLLENSRC); + sdelay(340); + } + + pllctl_reg_write(data->pll, mult, pllm & PLLM_MULT_LO_MASK); + + clrsetbits_le32(pll_regs[data->pll].reg0, PLLM_MULT_HI_SMASK, + (pllm << 6)); + + /* Set the BWADJ (12 bit field) */ + tmp_ctl = pllm >> 1; /* Divide the pllm by 2 */ + clrsetbits_le32(pll_regs[data->pll].reg0, PLL_BWADJ_LO_SMASK, + (tmp_ctl << PLL_BWADJ_LO_SHIFT)); + clrsetbits_le32(pll_regs[data->pll].reg1, PLL_BWADJ_HI_MASK, + (tmp_ctl >> 8)); + + /* + * Set the pll divider (6 bit field) * + * PLLD[5:0] is located in MAINPLLCTL0 + */ + clrsetbits_le32(pll_regs[data->pll].reg0, PLL_DIV_MASK, plld); + + /* Set the OUTPUT DIVIDE (4 bit field) in SECCTL */ + pllctl_reg_rmw(data->pll, secctl, PLL_CLKOD_SMASK, + (pllod << PLL_CLKOD_SHIFT)); + wait_for_completion(data); + + pllctl_reg_write(data->pll, div1, PLLM_RATIO_DIV1); + pllctl_reg_write(data->pll, div2, PLLM_RATIO_DIV2); + pllctl_reg_write(data->pll, div3, PLLM_RATIO_DIV3); + pllctl_reg_write(data->pll, div4, PLLM_RATIO_DIV4); + pllctl_reg_write(data->pll, div5, PLLM_RATIO_DIV5); + + pllctl_reg_setbits(data->pll, alnctl, 0x1f); + + /* + * Set GOSET bit in PLLCMD to initiate the GO operation + * to change the divide + */ + pllctl_reg_setbits(data->pll, cmd, PLLSTAT_GO); + sdelay(1500); /* wait for the phase adj */ + wait_for_completion(data); + + /* Reset PLL */ + pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLRST); + sdelay(21000); /* Wait for a minimum of 7 us*/ + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLRST); + sdelay(105000); /* Wait for PLL Lock time (min 50 us) */ + + pllctl_reg_clrbits(data->pll, secctl, PLLCTL_BYPASS); + + tmp = pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLEN); + + } else if (data->pll == TETRIS_PLL) { + bwadj = pllm >> 1; + /* 1.5 Set PLLCTL0[BYPASS] =1 (enable bypass), */ + setbits_le32(pll_regs[data->pll].reg0, PLLCTL_BYPASS); + /* + * Set CHIPMISCCTL1[13] = 0 (enable glitchfree bypass) + * only applicable for Kepler + */ + clrbits_le32(K2HK_MISC_CTRL, ARM_PLL_EN); + /* 2 In PLLCTL1, write PLLRST = 1 (PLL is reset) */ + setbits_le32(pll_regs[data->pll].reg1 , + PLL_PLLRST | PLLCTL_ENSAT); + + /* + * 3 Program PLLM and PLLD in PLLCTL0 register + * 4 Program BWADJ[7:0] in PLLCTL0 and BWADJ[11:8] in + * PLLCTL1 register. BWADJ value must be set + * to ((PLLM + 1) >> 1) – 1) + */ + tmp = ((bwadj & PLL_BWADJ_LO_MASK) << PLL_BWADJ_LO_SHIFT) | + (pllm << 6) | + (plld & PLL_DIV_MASK) | + (pllod << PLL_CLKOD_SHIFT) | PLLCTL_BYPASS; + __raw_writel(tmp, pll_regs[data->pll].reg0); + + /* Set BWADJ[11:8] bits */ + tmp = __raw_readl(pll_regs[data->pll].reg1); + tmp &= ~(PLL_BWADJ_HI_MASK); + tmp |= ((bwadj>>8) & PLL_BWADJ_HI_MASK); + __raw_writel(tmp, pll_regs[data->pll].reg1); + /* + * 5 Wait for at least 5 us based on the reference + * clock (PLL reset time) + */ + sdelay(21000); /* Wait for a minimum of 7 us*/ + + /* 6 In PLLCTL1, write PLLRST = 0 (PLL reset is released) */ + clrbits_le32(pll_regs[data->pll].reg1, PLL_PLLRST); + /* + * 7 Wait for at least 500 * REFCLK cycles * (PLLD + 1) + * (PLL lock time) + */ + sdelay(105000); + /* 8 disable bypass */ + clrbits_le32(pll_regs[data->pll].reg0, PLLCTL_BYPASS); + /* + * 9 Set CHIPMISCCTL1[13] = 1 (disable glitchfree bypass) + * only applicable for Kepler + */ + setbits_le32(K2HK_MISC_CTRL, ARM_PLL_EN); + } else { + setbits_le32(pll_regs[data->pll].reg1, PLLCTL_ENSAT); + /* + * process keeps state of Bypass bit while programming + * all other DDR PLL settings + */ + tmp = __raw_readl(pll_regs[data->pll].reg0); + tmp &= PLLCTL_BYPASS; /* clear everything except Bypass */ + + /* + * Set the BWADJ[7:0], PLLD[5:0] and PLLM to PLLCTL0, + * bypass disabled + */ + bwadj = pllm >> 1; + tmp |= ((bwadj & PLL_BWADJ_LO_SHIFT) << PLL_BWADJ_LO_SHIFT) | + (pllm << PLL_MULT_SHIFT) | + (plld & PLL_DIV_MASK) | + (pllod << PLL_CLKOD_SHIFT); + __raw_writel(tmp, pll_regs[data->pll].reg0); + + /* Set BWADJ[11:8] bits */ + tmp = __raw_readl(pll_regs[data->pll].reg1); + tmp &= ~(PLL_BWADJ_HI_MASK); + tmp |= ((bwadj >> 8) & PLL_BWADJ_HI_MASK); + + /* set PLL Select (bit 13) for PASS PLL */ + if (data->pll == PASS_PLL) + tmp |= PLLCTL_PAPLL; + + __raw_writel(tmp, pll_regs[data->pll].reg1); + + /* Reset bit: bit 14 for both DDR3 & PASS PLL */ + tmp = PLL_PLLRST; + /* Set RESET bit = 1 */ + setbits_le32(pll_regs[data->pll].reg1, tmp); + /* Wait for a minimum of 7 us*/ + sdelay(21000); + /* Clear RESET bit */ + clrbits_le32(pll_regs[data->pll].reg1, tmp); + sdelay(105000); + + /* clear BYPASS (Enable PLL Mode) */ + clrbits_le32(pll_regs[data->pll].reg0, PLLCTL_BYPASS); + sdelay(21000); /* Wait for a minimum of 7 us*/ + } + + /* + * This is required to provide a delay between multiple + * consequent PPL configurations + */ + sdelay(210000); +} + +void init_plls(int num_pll, struct pll_init_data *config) +{ + int i; + + for (i = 0; i < num_pll; i++) + init_pll(&config[i]); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_clock.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_clock.c new file mode 100644 index 000000000..afd30f385 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_clock.c @@ -0,0 +1,124 @@ +/* + * keystone2: commands for clocks + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <asm/arch/hardware.h> +#include <asm/arch/clock.h> +#include <asm/arch/psc_defs.h> + +struct pll_init_data cmd_pll_data = { + .pll = MAIN_PLL, + .pll_m = 16, + .pll_d = 1, + .pll_od = 2, +}; + +int do_pll_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc != 5) + goto pll_cmd_usage; + + if (strncmp(argv[1], "pa", 2) == 0) + cmd_pll_data.pll = PASS_PLL; + else if (strncmp(argv[1], "arm", 3) == 0) + cmd_pll_data.pll = TETRIS_PLL; + else if (strncmp(argv[1], "ddr3a", 5) == 0) + cmd_pll_data.pll = DDR3A_PLL; + else if (strncmp(argv[1], "ddr3b", 5) == 0) + cmd_pll_data.pll = DDR3B_PLL; + else + goto pll_cmd_usage; + + cmd_pll_data.pll_m = simple_strtoul(argv[2], NULL, 10); + cmd_pll_data.pll_d = simple_strtoul(argv[3], NULL, 10); + cmd_pll_data.pll_od = simple_strtoul(argv[4], NULL, 10); + + printf("Trying to set pll %d; mult %d; div %d; OD %d\n", + cmd_pll_data.pll, cmd_pll_data.pll_m, + cmd_pll_data.pll_d, cmd_pll_data.pll_od); + init_pll(&cmd_pll_data); + + return 0; + +pll_cmd_usage: + return cmd_usage(cmdtp); +} + +U_BOOT_CMD( + pllset, 5, 0, do_pll_cmd, + "set pll multiplier and pre divider", + "<pa|arm|ddr3a|ddr3b> <mult> <div> <OD>\n" +); + +int do_getclk_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned int clk; + unsigned int freq; + + if (argc != 2) + goto getclk_cmd_usage; + + clk = simple_strtoul(argv[1], NULL, 10); + + freq = clk_get_rate(clk); + printf("clock index [%d] - frequency %u\n", clk, freq); + return 0; + +getclk_cmd_usage: + return cmd_usage(cmdtp); +} + +U_BOOT_CMD( + getclk, 2, 0, do_getclk_cmd, + "get clock rate", + "<clk index>\n" + "See the 'enum clk_e' in the k2hk clock.h for clk indexes\n" +); + +int do_psc_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int psc_module; + int res; + + if (argc != 3) + goto psc_cmd_usage; + + psc_module = simple_strtoul(argv[1], NULL, 10); + if (strcmp(argv[2], "en") == 0) { + res = psc_enable_module(psc_module); + printf("psc_enable_module(%d) - %s\n", psc_module, + (res) ? "ERROR" : "OK"); + return 0; + } + + if (strcmp(argv[2], "di") == 0) { + res = psc_disable_module(psc_module); + printf("psc_disable_module(%d) - %s\n", psc_module, + (res) ? "ERROR" : "OK"); + return 0; + } + + if (strcmp(argv[2], "domain") == 0) { + res = psc_disable_domain(psc_module); + printf("psc_disable_domain(%d) - %s\n", psc_module, + (res) ? "ERROR" : "OK"); + return 0; + } + +psc_cmd_usage: + return cmd_usage(cmdtp); +} + +U_BOOT_CMD( + psc, 3, 0, do_psc_cmd, + "<enable/disable psc module os disable domain>", + "<mod/domain index> <en|di|domain>\n" + "See the hardware.h for Power and Sleep Controller (PSC) Domains\n" +); diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_mon.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_mon.c new file mode 100644 index 000000000..f9f58a37d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_mon.c @@ -0,0 +1,131 @@ +/* + * K2HK: secure kernel command file + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +asm(".arch_extension sec\n\t"); + +static int mon_install(u32 addr, u32 dpsc, u32 freq) +{ + int result; + + __asm__ __volatile__ ( + "stmfd r13!, {lr}\n" + "mov r0, %1\n" + "mov r1, %2\n" + "mov r2, %3\n" + "blx r0\n" + "ldmfd r13!, {lr}\n" + : "=&r" (result) + : "r" (addr), "r" (dpsc), "r" (freq) + : "cc", "r0", "r1", "r2", "memory"); + return result; +} + +static int do_mon_install(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + u32 addr, dpsc_base = 0x1E80000, freq; + int rcode = 0; + + if (argc < 2) + return CMD_RET_USAGE; + + freq = clk_get_rate(sys_clk0_6_clk); + + addr = simple_strtoul(argv[1], NULL, 16); + + rcode = mon_install(addr, dpsc_base, freq); + printf("## installed monitor, freq [%d], status %d\n", + freq, rcode); + + return 0; +} + +U_BOOT_CMD(mon_install, 2, 0, do_mon_install, + "Install boot kernel at 'addr'", + "" +); + +static void core_spin(void) +{ + while (1) + ; /* forever */; +} + +int mon_power_on(int core_id, void *ep) +{ + int result; + + asm volatile ( + "stmfd r13!, {lr}\n" + "mov r1, %1\n" + "mov r2, %2\n" + "mov r0, #0\n" + "smc #0\n" + "ldmfd r13!, {lr}\n" + : "=&r" (result) + : "r" (core_id), "r" (ep) + : "cc", "r0", "r1", "r2", "memory"); + return result; +} + +int mon_power_off(int core_id) +{ + int result; + + asm volatile ( + "stmfd r13!, {lr}\n" + "mov r1, %1\n" + "mov r0, #1\n" + "smc #1\n" + "ldmfd r13!, {lr}\n" + : "=&r" (result) + : "r" (core_id) + : "cc", "r0", "r1", "memory"); + return result; +} + +int do_mon_power(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int rcode = 0, core_id, on; + void (*fn)(void); + + fn = core_spin; + + if (argc < 3) + return CMD_RET_USAGE; + + core_id = simple_strtoul(argv[1], NULL, 16); + on = simple_strtoul(argv[2], NULL, 16); + + if (on) + rcode = mon_power_on(core_id, fn); + else + rcode = mon_power_off(core_id); + + if (on) { + if (!rcode) + printf("core %d powered on successfully\n", core_id); + else + printf("core %d power on failure\n", core_id); + } else { + printf("core %d powered off successfully\n", core_id); + } + + return 0; +} + +U_BOOT_CMD(mon_power, 3, 0, do_mon_power, + "Power On/Off secondary core", + "mon_power <coreid> <oper>\n" + "- coreid (1-3) and oper (1 - ON, 0 - OFF)\n" + "" +); diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/ddr3.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/ddr3.c new file mode 100644 index 000000000..4875db76a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/ddr3.c @@ -0,0 +1,69 @@ +/* + * Keystone2: DDR3 initialization + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/arch/hardware.h> +#include <asm/io.h> + +void init_ddrphy(u32 base, struct ddr3_phy_config *phy_cfg) +{ + unsigned int tmp; + + while ((__raw_readl(base + KS2_DDRPHY_PGSR0_OFFSET) + & 0x00000001) != 0x00000001) + ; + + __raw_writel(phy_cfg->pllcr, base + KS2_DDRPHY_PLLCR_OFFSET); + + tmp = __raw_readl(base + KS2_DDRPHY_PGCR1_OFFSET); + tmp &= ~(phy_cfg->pgcr1_mask); + tmp |= phy_cfg->pgcr1_val; + __raw_writel(tmp, base + KS2_DDRPHY_PGCR1_OFFSET); + + __raw_writel(phy_cfg->ptr0, base + KS2_DDRPHY_PTR0_OFFSET); + __raw_writel(phy_cfg->ptr1, base + KS2_DDRPHY_PTR1_OFFSET); + __raw_writel(phy_cfg->ptr3, base + KS2_DDRPHY_PTR3_OFFSET); + __raw_writel(phy_cfg->ptr4, base + KS2_DDRPHY_PTR4_OFFSET); + + tmp = __raw_readl(base + KS2_DDRPHY_DCR_OFFSET); + tmp &= ~(phy_cfg->dcr_mask); + tmp |= phy_cfg->dcr_val; + __raw_writel(tmp, base + KS2_DDRPHY_DCR_OFFSET); + + __raw_writel(phy_cfg->dtpr0, base + KS2_DDRPHY_DTPR0_OFFSET); + __raw_writel(phy_cfg->dtpr1, base + KS2_DDRPHY_DTPR1_OFFSET); + __raw_writel(phy_cfg->dtpr2, base + KS2_DDRPHY_DTPR2_OFFSET); + __raw_writel(phy_cfg->mr0, base + KS2_DDRPHY_MR0_OFFSET); + __raw_writel(phy_cfg->mr1, base + KS2_DDRPHY_MR1_OFFSET); + __raw_writel(phy_cfg->mr2, base + KS2_DDRPHY_MR2_OFFSET); + __raw_writel(phy_cfg->dtcr, base + KS2_DDRPHY_DTCR_OFFSET); + __raw_writel(phy_cfg->pgcr2, base + KS2_DDRPHY_PGCR2_OFFSET); + + __raw_writel(phy_cfg->zq0cr1, base + KS2_DDRPHY_ZQ0CR1_OFFSET); + __raw_writel(phy_cfg->zq1cr1, base + KS2_DDRPHY_ZQ1CR1_OFFSET); + __raw_writel(phy_cfg->zq2cr1, base + KS2_DDRPHY_ZQ2CR1_OFFSET); + + __raw_writel(phy_cfg->pir_v1, base + KS2_DDRPHY_PIR_OFFSET); + while ((__raw_readl(base + KS2_DDRPHY_PGSR0_OFFSET) & 0x1) != 0x1) + ; + + __raw_writel(phy_cfg->pir_v2, base + KS2_DDRPHY_PIR_OFFSET); + while ((__raw_readl(base + KS2_DDRPHY_PGSR0_OFFSET) & 0x1) != 0x1) + ; +} + +void init_ddremif(u32 base, struct ddr3_emif_config *emif_cfg) +{ + __raw_writel(emif_cfg->sdcfg, base + KS2_DDR3_SDCFG_OFFSET); + __raw_writel(emif_cfg->sdtim1, base + KS2_DDR3_SDTIM1_OFFSET); + __raw_writel(emif_cfg->sdtim2, base + KS2_DDR3_SDTIM2_OFFSET); + __raw_writel(emif_cfg->sdtim3, base + KS2_DDR3_SDTIM3_OFFSET); + __raw_writel(emif_cfg->sdtim4, base + KS2_DDR3_SDTIM4_OFFSET); + __raw_writel(emif_cfg->zqcfg, base + KS2_DDR3_ZQCFG_OFFSET); + __raw_writel(emif_cfg->sdrfc, base + KS2_DDR3_SDRFC_OFFSET); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/init.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/init.c new file mode 100644 index 000000000..044015aed --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/init.c @@ -0,0 +1,56 @@ +/* + * Keystone2: Architecture initialization + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/hardware.h> + +void chip_configuration_unlock(void) +{ + __raw_writel(KEYSTONE_KICK0_MAGIC, KEYSTONE_KICK0); + __raw_writel(KEYSTONE_KICK1_MAGIC, KEYSTONE_KICK1); +} + +int arch_cpu_init(void) +{ + chip_configuration_unlock(); + icache_enable(); + +#ifdef CONFIG_SOC_K2HK + share_all_segments(8); + share_all_segments(9); + share_all_segments(10); /* QM PDSP */ + share_all_segments(11); /* PCIE */ +#endif + + return 0; +} + +void reset_cpu(ulong addr) +{ + volatile u32 *rstctrl = (volatile u32 *)(KS2_RSTCTRL); + u32 tmp; + + tmp = *rstctrl & KS2_RSTCTRL_MASK; + *rstctrl = tmp | KS2_RSTCTRL_KEY; + + *rstctrl &= KS2_RSTCTRL_SWRST; + + for (;;) + ; +} + +void enable_caches(void) +{ +#ifndef CONFIG_SYS_DCACHE_OFF + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +#endif +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/keystone_nav.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/keystone_nav.c new file mode 100644 index 000000000..39d6f995f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/keystone_nav.c @@ -0,0 +1,376 @@ +/* + * Multicore Navigator driver for TI Keystone 2 devices. + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/keystone_nav.h> + +static int soc_type = +#ifdef CONFIG_SOC_K2HK + k2hk; +#endif + +struct qm_config k2hk_qm_memmap = { + .stat_cfg = 0x02a40000, + .queue = (struct qm_reg_queue *)0x02a80000, + .mngr_vbusm = 0x23a80000, + .i_lram = 0x00100000, + .proxy = (struct qm_reg_queue *)0x02ac0000, + .status_ram = 0x02a06000, + .mngr_cfg = (struct qm_cfg_reg *)0x02a02000, + .intd_cfg = 0x02a0c000, + .desc_mem = (struct descr_mem_setup_reg *)0x02a03000, + .region_num = 64, + .pdsp_cmd = 0x02a20000, + .pdsp_ctl = 0x02a0f000, + .pdsp_iram = 0x02a10000, + .qpool_num = 4000, +}; + +/* + * We are going to use only one type of descriptors - host packet + * descriptors. We staticaly allocate memory for them here + */ +struct qm_host_desc desc_pool[HDESC_NUM] __aligned(sizeof(struct qm_host_desc)); + +static struct qm_config *qm_cfg; + +inline int num_of_desc_to_reg(int num_descr) +{ + int j, num; + + for (j = 0, num = 32; j < 15; j++, num *= 2) { + if (num_descr <= num) + return j; + } + + return 15; +} + +static int _qm_init(struct qm_config *cfg) +{ + u32 j; + + if (cfg == NULL) + return QM_ERR; + + qm_cfg = cfg; + + qm_cfg->mngr_cfg->link_ram_base0 = qm_cfg->i_lram; + qm_cfg->mngr_cfg->link_ram_size0 = HDESC_NUM * 8; + qm_cfg->mngr_cfg->link_ram_base1 = 0; + qm_cfg->mngr_cfg->link_ram_size1 = 0; + qm_cfg->mngr_cfg->link_ram_base2 = 0; + + qm_cfg->desc_mem[0].base_addr = (u32)desc_pool; + qm_cfg->desc_mem[0].start_idx = 0; + qm_cfg->desc_mem[0].desc_reg_size = + (((sizeof(struct qm_host_desc) >> 4) - 1) << 16) | + num_of_desc_to_reg(HDESC_NUM); + + memset(desc_pool, 0, sizeof(desc_pool)); + for (j = 0; j < HDESC_NUM; j++) + qm_push(&desc_pool[j], qm_cfg->qpool_num); + + return QM_OK; +} + +int qm_init(void) +{ + switch (soc_type) { + case k2hk: + return _qm_init(&k2hk_qm_memmap); + } + + return QM_ERR; +} + +void qm_close(void) +{ + u32 j; + + if (qm_cfg == NULL) + return; + + queue_close(qm_cfg->qpool_num); + + qm_cfg->mngr_cfg->link_ram_base0 = 0; + qm_cfg->mngr_cfg->link_ram_size0 = 0; + qm_cfg->mngr_cfg->link_ram_base1 = 0; + qm_cfg->mngr_cfg->link_ram_size1 = 0; + qm_cfg->mngr_cfg->link_ram_base2 = 0; + + for (j = 0; j < qm_cfg->region_num; j++) { + qm_cfg->desc_mem[j].base_addr = 0; + qm_cfg->desc_mem[j].start_idx = 0; + qm_cfg->desc_mem[j].desc_reg_size = 0; + } + + qm_cfg = NULL; +} + +void qm_push(struct qm_host_desc *hd, u32 qnum) +{ + u32 regd; + + if (!qm_cfg) + return; + + cpu_to_bus((u32 *)hd, sizeof(struct qm_host_desc)/4); + regd = (u32)hd | ((sizeof(struct qm_host_desc) >> 4) - 1); + writel(regd, &qm_cfg->queue[qnum].ptr_size_thresh); +} + +void qm_buff_push(struct qm_host_desc *hd, u32 qnum, + void *buff_ptr, u32 buff_len) +{ + hd->orig_buff_len = buff_len; + hd->buff_len = buff_len; + hd->orig_buff_ptr = (u32)buff_ptr; + hd->buff_ptr = (u32)buff_ptr; + qm_push(hd, qnum); +} + +struct qm_host_desc *qm_pop(u32 qnum) +{ + u32 uhd; + + if (!qm_cfg) + return NULL; + + uhd = readl(&qm_cfg->queue[qnum].ptr_size_thresh) & ~0xf; + if (uhd) + cpu_to_bus((u32 *)uhd, sizeof(struct qm_host_desc)/4); + + return (struct qm_host_desc *)uhd; +} + +struct qm_host_desc *qm_pop_from_free_pool(void) +{ + if (!qm_cfg) + return NULL; + + return qm_pop(qm_cfg->qpool_num); +} + +void queue_close(u32 qnum) +{ + struct qm_host_desc *hd; + + while ((hd = qm_pop(qnum))) + ; +} + +/* + * DMA API + */ + +struct pktdma_cfg k2hk_netcp_pktdma = { + .global = (struct global_ctl_regs *)0x02004000, + .tx_ch = (struct tx_chan_regs *)0x02004400, + .tx_ch_num = 9, + .rx_ch = (struct rx_chan_regs *)0x02004800, + .rx_ch_num = 26, + .tx_sched = (u32 *)0x02004c00, + .rx_flows = (struct rx_flow_regs *)0x02005000, + .rx_flow_num = 32, + .rx_free_q = 4001, + .rx_rcv_q = 4002, + .tx_snd_q = 648, +}; + +struct pktdma_cfg *netcp; + +static int netcp_rx_disable(void) +{ + u32 j, v, k; + + for (j = 0; j < netcp->rx_ch_num; j++) { + v = readl(&netcp->rx_ch[j].cfg_a); + if (!(v & CPDMA_CHAN_A_ENABLE)) + continue; + + writel(v | CPDMA_CHAN_A_TDOWN, &netcp->rx_ch[j].cfg_a); + for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) { + udelay(100); + v = readl(&netcp->rx_ch[j].cfg_a); + if (!(v & CPDMA_CHAN_A_ENABLE)) + continue; + } + /* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */ + } + + /* Clear all of the flow registers */ + for (j = 0; j < netcp->rx_flow_num; j++) { + writel(0, &netcp->rx_flows[j].control); + writel(0, &netcp->rx_flows[j].tags); + writel(0, &netcp->rx_flows[j].tag_sel); + writel(0, &netcp->rx_flows[j].fdq_sel[0]); + writel(0, &netcp->rx_flows[j].fdq_sel[1]); + writel(0, &netcp->rx_flows[j].thresh[0]); + writel(0, &netcp->rx_flows[j].thresh[1]); + writel(0, &netcp->rx_flows[j].thresh[2]); + } + + return QM_OK; +} + +static int netcp_tx_disable(void) +{ + u32 j, v, k; + + for (j = 0; j < netcp->tx_ch_num; j++) { + v = readl(&netcp->tx_ch[j].cfg_a); + if (!(v & CPDMA_CHAN_A_ENABLE)) + continue; + + writel(v | CPDMA_CHAN_A_TDOWN, &netcp->tx_ch[j].cfg_a); + for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) { + udelay(100); + v = readl(&netcp->tx_ch[j].cfg_a); + if (!(v & CPDMA_CHAN_A_ENABLE)) + continue; + } + /* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */ + } + + return QM_OK; +} + +static int _netcp_init(struct pktdma_cfg *netcp_cfg, + struct rx_buff_desc *rx_buffers) +{ + u32 j, v; + struct qm_host_desc *hd; + u8 *rx_ptr; + + if (netcp_cfg == NULL || rx_buffers == NULL || + rx_buffers->buff_ptr == NULL || qm_cfg == NULL) + return QM_ERR; + + netcp = netcp_cfg; + netcp->rx_flow = rx_buffers->rx_flow; + + /* init rx queue */ + rx_ptr = rx_buffers->buff_ptr; + + for (j = 0; j < rx_buffers->num_buffs; j++) { + hd = qm_pop(qm_cfg->qpool_num); + if (hd == NULL) + return QM_ERR; + + qm_buff_push(hd, netcp->rx_free_q, + rx_ptr, rx_buffers->buff_len); + + rx_ptr += rx_buffers->buff_len; + } + + netcp_rx_disable(); + + /* configure rx channels */ + v = CPDMA_REG_VAL_MAKE_RX_FLOW_A(1, 1, 0, 0, 0, 0, 0, netcp->rx_rcv_q); + writel(v, &netcp->rx_flows[netcp->rx_flow].control); + writel(0, &netcp->rx_flows[netcp->rx_flow].tags); + writel(0, &netcp->rx_flows[netcp->rx_flow].tag_sel); + + v = CPDMA_REG_VAL_MAKE_RX_FLOW_D(0, netcp->rx_free_q, 0, + netcp->rx_free_q); + + writel(v, &netcp->rx_flows[netcp->rx_flow].fdq_sel[0]); + writel(v, &netcp->rx_flows[netcp->rx_flow].fdq_sel[1]); + writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[0]); + writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[1]); + writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[2]); + + for (j = 0; j < netcp->rx_ch_num; j++) + writel(CPDMA_CHAN_A_ENABLE, &netcp->rx_ch[j].cfg_a); + + /* configure tx channels */ + /* Disable loopback in the tx direction */ + writel(0, &netcp->global->emulation_control); + +/* TODO: make it dependend on a soc type variable */ +#ifdef CONFIG_SOC_K2HK + /* Set QM base address, only for K2x devices */ + writel(0x23a80000, &netcp->global->qm_base_addr[0]); +#endif + + /* Enable all channels. The current state isn't important */ + for (j = 0; j < netcp->tx_ch_num; j++) { + writel(0, &netcp->tx_ch[j].cfg_b); + writel(CPDMA_CHAN_A_ENABLE, &netcp->tx_ch[j].cfg_a); + } + + return QM_OK; +} + +int netcp_init(struct rx_buff_desc *rx_buffers) +{ + switch (soc_type) { + case k2hk: + _netcp_init(&k2hk_netcp_pktdma, rx_buffers); + return QM_OK; + } + return QM_ERR; +} + +int netcp_close(void) +{ + if (!netcp) + return QM_ERR; + + netcp_tx_disable(); + netcp_rx_disable(); + + queue_close(netcp->rx_free_q); + queue_close(netcp->rx_rcv_q); + queue_close(netcp->tx_snd_q); + + return QM_OK; +} + +int netcp_send(u32 *pkt, int num_bytes, u32 swinfo2) +{ + struct qm_host_desc *hd; + + hd = qm_pop(qm_cfg->qpool_num); + if (hd == NULL) + return QM_ERR; + + hd->desc_info = num_bytes; + hd->swinfo[2] = swinfo2; + hd->packet_info = qm_cfg->qpool_num; + + qm_buff_push(hd, netcp->tx_snd_q, pkt, num_bytes); + + return QM_OK; +} + +void *netcp_recv(u32 **pkt, int *num_bytes) +{ + struct qm_host_desc *hd; + + hd = qm_pop(netcp->rx_rcv_q); + if (!hd) + return NULL; + + *pkt = (u32 *)hd->buff_ptr; + *num_bytes = hd->desc_info & 0x3fffff; + + return hd; +} + +void netcp_release_rxhd(void *hd) +{ + struct qm_host_desc *_hd = (struct qm_host_desc *)hd; + + _hd->buff_len = _hd->orig_buff_len; + _hd->buff_ptr = _hd->orig_buff_ptr; + + qm_push(_hd, netcp->rx_free_q); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/msmc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/msmc.c new file mode 100644 index 000000000..f3f1621d2 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/msmc.c @@ -0,0 +1,68 @@ +/* + * MSMC controller utilities + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/hardware.h> + +struct mpax { + u32 mpaxl; + u32 mpaxh; +}; + +struct msms_regs { + u32 pid; + u32 _res_04; + u32 smcerrar; + u32 smcerrxr; + u32 smedcc; + u32 smcea; + u32 smsecc; + u32 smpfar; + u32 smpfxr; + u32 smpfr; + u32 smpfcr; + u32 _res_2c; + u32 sbndc[8]; + u32 sbndm; + u32 sbnde; + u32 _res_58; + u32 cfglck; + u32 cfgulck; + u32 cfglckstat; + u32 sms_mpax_lck; + u32 sms_mpax_ulck; + u32 sms_mpax_lckstat; + u32 ses_mpax_lck; + u32 ses_mpax_ulck; + u32 ses_mpax_lckstat; + u32 smestat; + u32 smirstat; + u32 smirc; + u32 smiestat; + u32 smiec; + u32 _res_94_c0[12]; + u32 smncerrar; + u32 smncerrxr; + u32 smncea; + u32 _res_d0_1fc[76]; + struct mpax sms[16][8]; + struct mpax ses[16][8]; +}; + + +void share_all_segments(int priv_id) +{ + struct msms_regs *msmc = (struct msms_regs *)K2HK_MSMC_CTRL_BASE; + int j; + + for (j = 0; j < 8; j++) { + msmc->sms[priv_id][j].mpaxh &= 0xffffff7ful; + msmc->ses[priv_id][j].mpaxh &= 0xffffff7ful; + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/psc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/psc.c new file mode 100644 index 000000000..c844dc84d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/psc.c @@ -0,0 +1,237 @@ +/* + * Keystone: PSC configuration module + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm-generic/errno.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/arch/psc_defs.h> + +#define DEVICE_REG32_R(addr) __raw_readl((u32 *)(addr)) +#define DEVICE_REG32_W(addr, val) __raw_writel(val, (u32 *)(addr)) + +#ifdef CONFIG_SOC_K2HK +#define DEVICE_PSC_BASE K2HK_PSC_BASE +#endif + +int psc_delay(void) +{ + udelay(10); + return 10; +} + +/* + * FUNCTION PURPOSE: Wait for end of transitional state + * + * DESCRIPTION: Polls pstat for the selected domain and waits for transitions + * to be complete. + * + * Since this is boot loader code it is *ASSUMED* that interrupts + * are disabled and no other core is mucking around with the psc + * at the same time. + * + * Returns 0 when the domain is free. Returns -1 if a timeout + * occurred waiting for the completion. + */ +int psc_wait(u32 domain_num) +{ + u32 retry; + u32 ptstat; + + /* + * Do nothing if the power domain is in transition. This should never + * happen since the boot code is the only software accesses psc. + * It's still remotely possible that the hardware state machines + * initiate transitions. + * Don't trap if the domain (or a module in this domain) is + * stuck in transition. + */ + retry = 0; + + do { + ptstat = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_PSTAT); + ptstat = ptstat & (1 << domain_num); + } while ((ptstat != 0) && ((retry += psc_delay()) < + PSC_PTSTAT_TIMEOUT_LIMIT)); + + if (retry >= PSC_PTSTAT_TIMEOUT_LIMIT) + return -1; + + return 0; +} + +u32 psc_get_domain_num(u32 mod_num) +{ + u32 domain_num; + + /* Get the power domain associated with the module number */ + domain_num = DEVICE_REG32_R(DEVICE_PSC_BASE + + PSC_REG_MDCFG(mod_num)); + domain_num = PSC_REG_MDCFG_GET_PD(domain_num); + + return domain_num; +} + +/* + * FUNCTION PURPOSE: Power up/down a module + * + * DESCRIPTION: Powers up/down the requested module and the associated power + * domain if required. No action is taken it the module is + * already powered up/down. + * + * This only controls modules. The domain in which the module + * resides will be left in the power on state. Multiple modules + * can exist in a power domain, so powering down the domain based + * on a single module is not done. + * + * Returns 0 on success, -1 if the module can't be powered up, or + * if there is a timeout waiting for the transition. + */ +int psc_set_state(u32 mod_num, u32 state) +{ + u32 domain_num; + u32 pdctl; + u32 mdctl; + u32 ptcmd; + u32 reset_iso; + u32 v; + + /* + * Get the power domain associated with the module number, and reset + * isolation functionality + */ + v = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCFG(mod_num)); + domain_num = PSC_REG_MDCFG_GET_PD(v); + reset_iso = PSC_REG_MDCFG_GET_RESET_ISO(v); + + /* Wait for the status of the domain/module to be non-transitional */ + if (psc_wait(domain_num) != 0) + return -1; + + /* + * Perform configuration even if the current status matches the + * existing state + * + * Set the next state of the power domain to on. It's OK if the domain + * is always on. This code will not ever power down a domain, so no + * change is made if the new state is power down. + */ + if (state == PSC_REG_VAL_MDCTL_NEXT_ON) { + pdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + + PSC_REG_PDCTL(domain_num)); + pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, + PSC_REG_VAL_PDCTL_NEXT_ON); + DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_PDCTL(domain_num), + pdctl); + } + + /* Set the next state for the module to enabled/disabled */ + mdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num)); + mdctl = PSC_REG_MDCTL_SET_NEXT(mdctl, state); + mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, reset_iso); + DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num), mdctl); + + /* Trigger the enable */ + ptcmd = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_PTCMD); + ptcmd |= (u32)(1<<domain_num); + DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_PTCMD, ptcmd); + + /* Wait on the complete */ + return psc_wait(domain_num); +} + +/* + * FUNCTION PURPOSE: Power up a module + * + * DESCRIPTION: Powers up the requested module and the associated power domain + * if required. No action is taken it the module is already + * powered up. + * + * Returns 0 on success, -1 if the module can't be powered up, or + * if there is a timeout waiting for the transition. + */ +int psc_enable_module(u32 mod_num) +{ + u32 mdctl; + + /* Set the bit to apply reset */ + mdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num)); + if ((mdctl & 0x3f) == PSC_REG_VAL_MDSTAT_STATE_ON) + return 0; + + return psc_set_state(mod_num, PSC_REG_VAL_MDCTL_NEXT_ON); +} + +/* + * FUNCTION PURPOSE: Power down a module + * + * DESCRIPTION: Powers down the requested module. + * + * Returns 0 on success, -1 on failure or timeout. + */ +int psc_disable_module(u32 mod_num) +{ + u32 mdctl; + + /* Set the bit to apply reset */ + mdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num)); + if ((mdctl & 0x3f) == 0) + return 0; + mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl, 0); + DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num), mdctl); + + return psc_set_state(mod_num, PSC_REG_VAL_MDCTL_NEXT_SWRSTDISABLE); +} + +/* + * FUNCTION PURPOSE: Set the reset isolation bit in mdctl + * + * DESCRIPTION: The reset isolation enable bit is set. The state of the module + * is not changed. Returns 0 if the module config showed that + * reset isolation is supported. Returns 1 otherwise. This is not + * an error, but setting the bit in mdctl has no effect. + */ +int psc_set_reset_iso(u32 mod_num) +{ + u32 v; + u32 mdctl; + + /* Set the reset isolation bit */ + mdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num)); + mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, 1); + DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num), mdctl); + + v = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCFG(mod_num)); + if (PSC_REG_MDCFG_GET_RESET_ISO(v) == 1) + return 0; + + return 1; +} + +/* + * FUNCTION PURPOSE: Disable a power domain + * + * DESCRIPTION: The power domain is disabled + */ +int psc_disable_domain(u32 domain_num) +{ + u32 pdctl; + u32 ptcmd; + + pdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_PDCTL(domain_num)); + pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, PSC_REG_VAL_PDCTL_NEXT_OFF); + pdctl = PSC_REG_PDCTL_SET_PDMODE(pdctl, PSC_REG_VAL_PDCTL_PDMODE_SLEEP); + DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_PDCTL(domain_num), pdctl); + + ptcmd = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_PTCMD); + ptcmd |= (u32)(1 << domain_num); + DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_PTCMD, ptcmd); + + return psc_wait(domain_num); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/spl.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/spl.c new file mode 100644 index 000000000..e07b64db9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/keystone/spl.c @@ -0,0 +1,45 @@ +/* + * common spl init code + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <config.h> +#include <ns16550.h> +#include <malloc.h> +#include <spl.h> +#include <spi_flash.h> + +#include <asm/u-boot.h> +#include <asm/utils.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct pll_init_data spl_pll_config[] = { + CORE_PLL_799, + TETRIS_PLL_500, +}; + +void spl_init_keystone_plls(void) +{ + init_plls(ARRAY_SIZE(spl_pll_config), spl_pll_config); +} + +void spl_board_init(void) +{ + spl_init_keystone_plls(); + preloader_console_init(); +} + +u32 spl_boot_device(void) +{ +#if defined(CONFIG_SPL_SPI_LOAD) + return BOOT_DEVICE_SPI; +#else + puts("Unknown boot device\n"); + hang(); +#endif +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/Makefile new file mode 100644 index 000000000..da225cb4f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/Makefile @@ -0,0 +1,9 @@ +# +# Copyright 2013 Broadcom Corporation. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += s_init.o +obj-y += hwinit-common.o +obj-y += clk-stubs.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/clk-stubs.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/clk-stubs.c new file mode 100644 index 000000000..338e0e496 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/clk-stubs.c @@ -0,0 +1,21 @@ +/* + * Copyright 2013 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +/* + * These weak functions are available to kona architectures that don't + * require clock enables from the driver code. + */ +int __weak clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep) +{ + return 0; +} + +int __weak clk_bsc_enable(void *base, u32 rate, u32 *actual_ratep) +{ + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/hwinit-common.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/hwinit-common.c new file mode 100644 index 000000000..2b3a84051 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/hwinit-common.c @@ -0,0 +1,16 @@ +/* + * Copyright 2013 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <linux/sizes.h> + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/s_init.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/s_init.c new file mode 100644 index 000000000..6066a73c5 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/kona-common/s_init.c @@ -0,0 +1,12 @@ +/* + * Copyright 2014 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Early system init. Currently empty. + */ +void s_init(void) +{ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/lowlevel_init.S new file mode 100644 index 000000000..f1aea05c9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/lowlevel_init.S @@ -0,0 +1,41 @@ +/* + * A lowlevel_init function that sets up the stack to call a C function to + * perform further init. + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Author : + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> + +ENTRY(lowlevel_init) + /* + * Setup a temporary stack + */ + ldr sp, =CONFIG_SYS_INIT_SP_ADDR + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ +#ifdef CONFIG_SPL_BUILD + ldr r9, =gdata +#else + sub sp, sp, #GD_SIZE + bic sp, sp, #7 + mov r9, sp +#endif + /* + * Save the old lr(passed in ip) and the current lr to stack + */ + push {ip, lr} + + /* + * go setup pll, mux, memory + */ + bl s_init + pop {ip, pc} +ENDPROC(lowlevel_init) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/Makefile new file mode 100644 index 000000000..d021842f6 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/Makefile @@ -0,0 +1,11 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2009 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := soc.o clock.o +obj-y += lowlevel_init.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/clock.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/clock.c new file mode 100644 index 000000000..bf52f0d19 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/clock.c @@ -0,0 +1,949 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (C) Copyright 2009 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/crm_regs.h> +#include <asm/arch/clock.h> +#include <div64.h> +#include <asm/arch/sys_proto.h> + +enum pll_clocks { + PLL1_CLOCK = 0, + PLL2_CLOCK, + PLL3_CLOCK, +#ifdef CONFIG_MX53 + PLL4_CLOCK, +#endif + PLL_CLOCKS, +}; + +struct mxc_pll_reg *mxc_plls[PLL_CLOCKS] = { + [PLL1_CLOCK] = (struct mxc_pll_reg *)PLL1_BASE_ADDR, + [PLL2_CLOCK] = (struct mxc_pll_reg *)PLL2_BASE_ADDR, + [PLL3_CLOCK] = (struct mxc_pll_reg *)PLL3_BASE_ADDR, +#ifdef CONFIG_MX53 + [PLL4_CLOCK] = (struct mxc_pll_reg *)PLL4_BASE_ADDR, +#endif +}; + +#define AHB_CLK_ROOT 133333333 +#define SZ_DEC_1M 1000000 +#define PLL_PD_MAX 16 /* Actual pd+1 */ +#define PLL_MFI_MAX 15 +#define PLL_MFI_MIN 5 +#define ARM_DIV_MAX 8 +#define IPG_DIV_MAX 4 +#define AHB_DIV_MAX 8 +#define EMI_DIV_MAX 8 +#define NFC_DIV_MAX 8 + +#define MX5_CBCMR 0x00015154 +#define MX5_CBCDR 0x02888945 + +struct fixed_pll_mfd { + u32 ref_clk_hz; + u32 mfd; +}; + +const struct fixed_pll_mfd fixed_mfd[] = { + {MXC_HCLK, 24 * 16}, +}; + +struct pll_param { + u32 pd; + u32 mfi; + u32 mfn; + u32 mfd; +}; + +#define PLL_FREQ_MAX(ref_clk) (4 * (ref_clk) * PLL_MFI_MAX) +#define PLL_FREQ_MIN(ref_clk) \ + ((2 * (ref_clk) * (PLL_MFI_MIN - 1)) / PLL_PD_MAX) +#define MAX_DDR_CLK 420000000 +#define NFC_CLK_MAX 34000000 + +struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE; + +void set_usboh3_clk(void) +{ + clrsetbits_le32(&mxc_ccm->cscmr1, + MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK, + MXC_CCM_CSCMR1_USBOH3_CLK_SEL(1)); + clrsetbits_le32(&mxc_ccm->cscdr1, + MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK | + MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK, + MXC_CCM_CSCDR1_USBOH3_CLK_PRED(4) | + MXC_CCM_CSCDR1_USBOH3_CLK_PODF(1)); +} + +void enable_usboh3_clk(bool enable) +{ + unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF; + + clrsetbits_le32(&mxc_ccm->CCGR2, + MXC_CCM_CCGR2_USBOH3_60M(MXC_CCM_CCGR_CG_MASK), + MXC_CCM_CCGR2_USBOH3_60M(cg)); +} + +#ifdef CONFIG_SYS_I2C_MXC +/* i2c_num can be from 0, to 1 for i.MX51 and 2 for i.MX53 */ +int enable_i2c_clk(unsigned char enable, unsigned i2c_num) +{ + u32 mask; + +#if defined(CONFIG_MX51) + if (i2c_num > 1) +#elif defined(CONFIG_MX53) + if (i2c_num > 2) +#endif + return -EINVAL; + mask = MXC_CCM_CCGR_CG_MASK << + (MXC_CCM_CCGR1_I2C1_OFFSET + (i2c_num << 1)); + if (enable) + setbits_le32(&mxc_ccm->CCGR1, mask); + else + clrbits_le32(&mxc_ccm->CCGR1, mask); + return 0; +} +#endif + +void set_usb_phy_clk(void) +{ + clrbits_le32(&mxc_ccm->cscmr1, MXC_CCM_CSCMR1_USB_PHY_CLK_SEL); +} + +#if defined(CONFIG_MX51) +void enable_usb_phy1_clk(bool enable) +{ + unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF; + + clrsetbits_le32(&mxc_ccm->CCGR2, + MXC_CCM_CCGR2_USB_PHY(MXC_CCM_CCGR_CG_MASK), + MXC_CCM_CCGR2_USB_PHY(cg)); +} + +void enable_usb_phy2_clk(bool enable) +{ + /* i.MX51 has a single USB PHY clock, so do nothing here. */ +} +#elif defined(CONFIG_MX53) +void enable_usb_phy1_clk(bool enable) +{ + unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF; + + clrsetbits_le32(&mxc_ccm->CCGR4, + MXC_CCM_CCGR4_USB_PHY1(MXC_CCM_CCGR_CG_MASK), + MXC_CCM_CCGR4_USB_PHY1(cg)); +} + +void enable_usb_phy2_clk(bool enable) +{ + unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF; + + clrsetbits_le32(&mxc_ccm->CCGR4, + MXC_CCM_CCGR4_USB_PHY2(MXC_CCM_CCGR_CG_MASK), + MXC_CCM_CCGR4_USB_PHY2(cg)); +} +#endif + +/* + * Calculate the frequency of PLLn. + */ +static uint32_t decode_pll(struct mxc_pll_reg *pll, uint32_t infreq) +{ + uint32_t ctrl, op, mfd, mfn, mfi, pdf, ret; + uint64_t refclk, temp; + int32_t mfn_abs; + + ctrl = readl(&pll->ctrl); + + if (ctrl & MXC_DPLLC_CTL_HFSM) { + mfn = readl(&pll->hfs_mfn); + mfd = readl(&pll->hfs_mfd); + op = readl(&pll->hfs_op); + } else { + mfn = readl(&pll->mfn); + mfd = readl(&pll->mfd); + op = readl(&pll->op); + } + + mfd &= MXC_DPLLC_MFD_MFD_MASK; + mfn &= MXC_DPLLC_MFN_MFN_MASK; + pdf = op & MXC_DPLLC_OP_PDF_MASK; + mfi = MXC_DPLLC_OP_MFI_RD(op); + + /* 21.2.3 */ + if (mfi < 5) + mfi = 5; + + /* Sign extend */ + if (mfn >= 0x04000000) { + mfn |= 0xfc000000; + mfn_abs = -mfn; + } else + mfn_abs = mfn; + + refclk = infreq * 2; + if (ctrl & MXC_DPLLC_CTL_DPDCK0_2_EN) + refclk *= 2; + + do_div(refclk, pdf + 1); + temp = refclk * mfn_abs; + do_div(temp, mfd + 1); + ret = refclk * mfi; + + if ((int)mfn < 0) + ret -= temp; + else + ret += temp; + + return ret; +} + +#ifdef CONFIG_MX51 +/* + * This function returns the Frequency Pre-Multiplier clock. + */ +static u32 get_fpm(void) +{ + u32 mult; + u32 ccr = readl(&mxc_ccm->ccr); + + if (ccr & MXC_CCM_CCR_FPM_MULT) + mult = 1024; + else + mult = 512; + + return MXC_CLK32 * mult; +} +#endif + +/* + * This function returns the low power audio clock. + */ +static u32 get_lp_apm(void) +{ + u32 ret_val = 0; + u32 ccsr = readl(&mxc_ccm->ccsr); + + if (ccsr & MXC_CCM_CCSR_LP_APM) +#if defined(CONFIG_MX51) + ret_val = get_fpm(); +#elif defined(CONFIG_MX53) + ret_val = decode_pll(mxc_plls[PLL4_CLOCK], MXC_HCLK); +#endif + else + ret_val = MXC_HCLK; + + return ret_val; +} + +/* + * Get mcu main rate + */ +u32 get_mcu_main_clk(void) +{ + u32 reg, freq; + + reg = MXC_CCM_CACRR_ARM_PODF_RD(readl(&mxc_ccm->cacrr)); + freq = decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK); + return freq / (reg + 1); +} + +/* + * Get the rate of peripheral's root clock. + */ +u32 get_periph_clk(void) +{ + u32 reg; + + reg = readl(&mxc_ccm->cbcdr); + if (!(reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL)) + return decode_pll(mxc_plls[PLL2_CLOCK], MXC_HCLK); + reg = readl(&mxc_ccm->cbcmr); + switch (MXC_CCM_CBCMR_PERIPH_CLK_SEL_RD(reg)) { + case 0: + return decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK); + case 1: + return decode_pll(mxc_plls[PLL3_CLOCK], MXC_HCLK); + case 2: + return get_lp_apm(); + default: + return 0; + } + /* NOTREACHED */ +} + +/* + * Get the rate of ipg clock. + */ +static u32 get_ipg_clk(void) +{ + uint32_t freq, reg, div; + + freq = get_ahb_clk(); + + reg = readl(&mxc_ccm->cbcdr); + div = MXC_CCM_CBCDR_IPG_PODF_RD(reg) + 1; + + return freq / div; +} + +/* + * Get the rate of ipg_per clock. + */ +static u32 get_ipg_per_clk(void) +{ + u32 freq, pred1, pred2, podf; + + if (readl(&mxc_ccm->cbcmr) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL) + return get_ipg_clk(); + + if (readl(&mxc_ccm->cbcmr) & MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL) + freq = get_lp_apm(); + else + freq = get_periph_clk(); + podf = readl(&mxc_ccm->cbcdr); + pred1 = MXC_CCM_CBCDR_PERCLK_PRED1_RD(podf); + pred2 = MXC_CCM_CBCDR_PERCLK_PRED2_RD(podf); + podf = MXC_CCM_CBCDR_PERCLK_PODF_RD(podf); + return freq / ((pred1 + 1) * (pred2 + 1) * (podf + 1)); +} + +/* Get the output clock rate of a standard PLL MUX for peripherals. */ +static u32 get_standard_pll_sel_clk(u32 clk_sel) +{ + u32 freq = 0; + + switch (clk_sel & 0x3) { + case 0: + freq = decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK); + break; + case 1: + freq = decode_pll(mxc_plls[PLL2_CLOCK], MXC_HCLK); + break; + case 2: + freq = decode_pll(mxc_plls[PLL3_CLOCK], MXC_HCLK); + break; + case 3: + freq = get_lp_apm(); + break; + } + + return freq; +} + +/* + * Get the rate of uart clk. + */ +static u32 get_uart_clk(void) +{ + unsigned int clk_sel, freq, reg, pred, podf; + + reg = readl(&mxc_ccm->cscmr1); + clk_sel = MXC_CCM_CSCMR1_UART_CLK_SEL_RD(reg); + freq = get_standard_pll_sel_clk(clk_sel); + + reg = readl(&mxc_ccm->cscdr1); + pred = MXC_CCM_CSCDR1_UART_CLK_PRED_RD(reg); + podf = MXC_CCM_CSCDR1_UART_CLK_PODF_RD(reg); + freq /= (pred + 1) * (podf + 1); + + return freq; +} + +/* + * get cspi clock rate. + */ +static u32 imx_get_cspiclk(void) +{ + u32 ret_val = 0, pdf, pre_pdf, clk_sel, freq; + u32 cscmr1 = readl(&mxc_ccm->cscmr1); + u32 cscdr2 = readl(&mxc_ccm->cscdr2); + + pre_pdf = MXC_CCM_CSCDR2_CSPI_CLK_PRED_RD(cscdr2); + pdf = MXC_CCM_CSCDR2_CSPI_CLK_PODF_RD(cscdr2); + clk_sel = MXC_CCM_CSCMR1_CSPI_CLK_SEL_RD(cscmr1); + freq = get_standard_pll_sel_clk(clk_sel); + ret_val = freq / ((pre_pdf + 1) * (pdf + 1)); + return ret_val; +} + +/* + * get esdhc clock rate. + */ +static u32 get_esdhc_clk(u32 port) +{ + u32 clk_sel = 0, pred = 0, podf = 0, freq = 0; + u32 cscmr1 = readl(&mxc_ccm->cscmr1); + u32 cscdr1 = readl(&mxc_ccm->cscdr1); + + switch (port) { + case 0: + clk_sel = MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_RD(cscmr1); + pred = MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_RD(cscdr1); + podf = MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_RD(cscdr1); + break; + case 1: + clk_sel = MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_RD(cscmr1); + pred = MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_RD(cscdr1); + podf = MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_RD(cscdr1); + break; + case 2: + if (cscmr1 & MXC_CCM_CSCMR1_ESDHC3_CLK_SEL) + return get_esdhc_clk(1); + else + return get_esdhc_clk(0); + case 3: + if (cscmr1 & MXC_CCM_CSCMR1_ESDHC4_CLK_SEL) + return get_esdhc_clk(1); + else + return get_esdhc_clk(0); + default: + break; + } + + freq = get_standard_pll_sel_clk(clk_sel) / ((pred + 1) * (podf + 1)); + return freq; +} + +static u32 get_axi_a_clk(void) +{ + u32 cbcdr = readl(&mxc_ccm->cbcdr); + u32 pdf = MXC_CCM_CBCDR_AXI_A_PODF_RD(cbcdr); + + return get_periph_clk() / (pdf + 1); +} + +static u32 get_axi_b_clk(void) +{ + u32 cbcdr = readl(&mxc_ccm->cbcdr); + u32 pdf = MXC_CCM_CBCDR_AXI_B_PODF_RD(cbcdr); + + return get_periph_clk() / (pdf + 1); +} + +static u32 get_emi_slow_clk(void) +{ + u32 cbcdr = readl(&mxc_ccm->cbcdr); + u32 emi_clk_sel = cbcdr & MXC_CCM_CBCDR_EMI_CLK_SEL; + u32 pdf = MXC_CCM_CBCDR_EMI_PODF_RD(cbcdr); + + if (emi_clk_sel) + return get_ahb_clk() / (pdf + 1); + + return get_periph_clk() / (pdf + 1); +} + +static u32 get_ddr_clk(void) +{ + u32 ret_val = 0; + u32 cbcmr = readl(&mxc_ccm->cbcmr); + u32 ddr_clk_sel = MXC_CCM_CBCMR_DDR_CLK_SEL_RD(cbcmr); +#ifdef CONFIG_MX51 + u32 cbcdr = readl(&mxc_ccm->cbcdr); + if (cbcdr & MXC_CCM_CBCDR_DDR_HIFREQ_SEL) { + u32 ddr_clk_podf = MXC_CCM_CBCDR_DDR_PODF_RD(cbcdr); + + ret_val = decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK); + ret_val /= ddr_clk_podf + 1; + + return ret_val; + } +#endif + switch (ddr_clk_sel) { + case 0: + ret_val = get_axi_a_clk(); + break; + case 1: + ret_val = get_axi_b_clk(); + break; + case 2: + ret_val = get_emi_slow_clk(); + break; + case 3: + ret_val = get_ahb_clk(); + break; + default: + break; + } + + return ret_val; +} + +/* + * The API of get mxc clocks. + */ +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return get_mcu_main_clk(); + case MXC_AHB_CLK: + return get_ahb_clk(); + case MXC_IPG_CLK: + return get_ipg_clk(); + case MXC_IPG_PERCLK: + case MXC_I2C_CLK: + return get_ipg_per_clk(); + case MXC_UART_CLK: + return get_uart_clk(); + case MXC_CSPI_CLK: + return imx_get_cspiclk(); + case MXC_ESDHC_CLK: + return get_esdhc_clk(0); + case MXC_ESDHC2_CLK: + return get_esdhc_clk(1); + case MXC_ESDHC3_CLK: + return get_esdhc_clk(2); + case MXC_ESDHC4_CLK: + return get_esdhc_clk(3); + case MXC_FEC_CLK: + return get_ipg_clk(); + case MXC_SATA_CLK: + return get_ahb_clk(); + case MXC_DDR_CLK: + return get_ddr_clk(); + default: + break; + } + return -EINVAL; +} + +u32 imx_get_uartclk(void) +{ + return get_uart_clk(); +} + +u32 imx_get_fecclk(void) +{ + return get_ipg_clk(); +} + +static int gcd(int m, int n) +{ + int t; + while (m > 0) { + if (n > m) { + t = m; + m = n; + n = t; + } /* swap */ + m -= n; + } + return n; +} + +/* + * This is to calculate various parameters based on reference clock and + * targeted clock based on the equation: + * t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1) + * This calculation is based on a fixed MFD value for simplicity. + */ +static int calc_pll_params(u32 ref, u32 target, struct pll_param *pll) +{ + u64 pd, mfi = 1, mfn, mfd, t1; + u32 n_target = target; + u32 n_ref = ref, i; + + /* + * Make sure targeted freq is in the valid range. + * Otherwise the following calculation might be wrong!!! + */ + if (n_target < PLL_FREQ_MIN(ref) || + n_target > PLL_FREQ_MAX(ref)) { + printf("Targeted peripheral clock should be" + "within [%d - %d]\n", + PLL_FREQ_MIN(ref) / SZ_DEC_1M, + PLL_FREQ_MAX(ref) / SZ_DEC_1M); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(fixed_mfd); i++) { + if (fixed_mfd[i].ref_clk_hz == ref) { + mfd = fixed_mfd[i].mfd; + break; + } + } + + if (i == ARRAY_SIZE(fixed_mfd)) + return -EINVAL; + + /* Use n_target and n_ref to avoid overflow */ + for (pd = 1; pd <= PLL_PD_MAX; pd++) { + t1 = n_target * pd; + do_div(t1, (4 * n_ref)); + mfi = t1; + if (mfi > PLL_MFI_MAX) + return -EINVAL; + else if (mfi < 5) + continue; + break; + } + /* + * Now got pd and mfi already + * + * mfn = (((n_target * pd) / 4 - n_ref * mfi) * mfd) / n_ref; + */ + t1 = n_target * pd; + do_div(t1, 4); + t1 -= n_ref * mfi; + t1 *= mfd; + do_div(t1, n_ref); + mfn = t1; + debug("ref=%d, target=%d, pd=%d," "mfi=%d,mfn=%d, mfd=%d\n", + ref, n_target, (u32)pd, (u32)mfi, (u32)mfn, (u32)mfd); + i = 1; + if (mfn != 0) + i = gcd(mfd, mfn); + pll->pd = (u32)pd; + pll->mfi = (u32)mfi; + do_div(mfn, i); + pll->mfn = (u32)mfn; + do_div(mfd, i); + pll->mfd = (u32)mfd; + + return 0; +} + +#define calc_div(tgt_clk, src_clk, limit) ({ \ + u32 v = 0; \ + if (((src_clk) % (tgt_clk)) <= 100) \ + v = (src_clk) / (tgt_clk); \ + else \ + v = ((src_clk) / (tgt_clk)) + 1;\ + if (v > limit) \ + v = limit; \ + (v - 1); \ + }) + +#define CHANGE_PLL_SETTINGS(pll, pd, fi, fn, fd) \ + { \ + writel(0x1232, &pll->ctrl); \ + writel(0x2, &pll->config); \ + writel((((pd) - 1) << 0) | ((fi) << 4), \ + &pll->op); \ + writel(fn, &(pll->mfn)); \ + writel((fd) - 1, &pll->mfd); \ + writel((((pd) - 1) << 0) | ((fi) << 4), \ + &pll->hfs_op); \ + writel(fn, &pll->hfs_mfn); \ + writel((fd) - 1, &pll->hfs_mfd); \ + writel(0x1232, &pll->ctrl); \ + while (!readl(&pll->ctrl) & 0x1) \ + ;\ + } + +static int config_pll_clk(enum pll_clocks index, struct pll_param *pll_param) +{ + u32 ccsr = readl(&mxc_ccm->ccsr); + struct mxc_pll_reg *pll = mxc_plls[index]; + + switch (index) { + case PLL1_CLOCK: + /* Switch ARM to PLL2 clock */ + writel(ccsr | MXC_CCM_CCSR_PLL1_SW_CLK_SEL, + &mxc_ccm->ccsr); + CHANGE_PLL_SETTINGS(pll, pll_param->pd, + pll_param->mfi, pll_param->mfn, + pll_param->mfd); + /* Switch back */ + writel(ccsr & ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL, + &mxc_ccm->ccsr); + break; + case PLL2_CLOCK: + /* Switch to pll2 bypass clock */ + writel(ccsr | MXC_CCM_CCSR_PLL2_SW_CLK_SEL, + &mxc_ccm->ccsr); + CHANGE_PLL_SETTINGS(pll, pll_param->pd, + pll_param->mfi, pll_param->mfn, + pll_param->mfd); + /* Switch back */ + writel(ccsr & ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL, + &mxc_ccm->ccsr); + break; + case PLL3_CLOCK: + /* Switch to pll3 bypass clock */ + writel(ccsr | MXC_CCM_CCSR_PLL3_SW_CLK_SEL, + &mxc_ccm->ccsr); + CHANGE_PLL_SETTINGS(pll, pll_param->pd, + pll_param->mfi, pll_param->mfn, + pll_param->mfd); + /* Switch back */ + writel(ccsr & ~MXC_CCM_CCSR_PLL3_SW_CLK_SEL, + &mxc_ccm->ccsr); + break; +#ifdef CONFIG_MX53 + case PLL4_CLOCK: + /* Switch to pll4 bypass clock */ + writel(ccsr | MXC_CCM_CCSR_PLL4_SW_CLK_SEL, + &mxc_ccm->ccsr); + CHANGE_PLL_SETTINGS(pll, pll_param->pd, + pll_param->mfi, pll_param->mfn, + pll_param->mfd); + /* Switch back */ + writel(ccsr & ~MXC_CCM_CCSR_PLL4_SW_CLK_SEL, + &mxc_ccm->ccsr); + break; +#endif + default: + return -EINVAL; + } + + return 0; +} + +/* Config CPU clock */ +static int config_core_clk(u32 ref, u32 freq) +{ + int ret = 0; + struct pll_param pll_param; + + memset(&pll_param, 0, sizeof(struct pll_param)); + + /* The case that periph uses PLL1 is not considered here */ + ret = calc_pll_params(ref, freq, &pll_param); + if (ret != 0) { + printf("Error:Can't find pll parameters: %d\n", ret); + return ret; + } + + return config_pll_clk(PLL1_CLOCK, &pll_param); +} + +static int config_nfc_clk(u32 nfc_clk) +{ + u32 parent_rate = get_emi_slow_clk(); + u32 div; + + if (nfc_clk == 0) + return -EINVAL; + div = parent_rate / nfc_clk; + if (div == 0) + div++; + if (parent_rate / div > NFC_CLK_MAX) + div++; + clrsetbits_le32(&mxc_ccm->cbcdr, + MXC_CCM_CBCDR_NFC_PODF_MASK, + MXC_CCM_CBCDR_NFC_PODF(div - 1)); + while (readl(&mxc_ccm->cdhipr) != 0) + ; + return 0; +} + +void enable_nfc_clk(unsigned char enable) +{ + unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF; + + clrsetbits_le32(&mxc_ccm->CCGR5, + MXC_CCM_CCGR5_EMI_ENFC(MXC_CCM_CCGR_CG_MASK), + MXC_CCM_CCGR5_EMI_ENFC(cg)); +} + +#ifdef CONFIG_FSL_IIM +void enable_efuse_prog_supply(bool enable) +{ + if (enable) + setbits_le32(&mxc_ccm->cgpr, + MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE); + else + clrbits_le32(&mxc_ccm->cgpr, + MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE); +} +#endif + +/* Config main_bus_clock for periphs */ +static int config_periph_clk(u32 ref, u32 freq) +{ + int ret = 0; + struct pll_param pll_param; + + memset(&pll_param, 0, sizeof(struct pll_param)); + + if (readl(&mxc_ccm->cbcdr) & MXC_CCM_CBCDR_PERIPH_CLK_SEL) { + ret = calc_pll_params(ref, freq, &pll_param); + if (ret != 0) { + printf("Error:Can't find pll parameters: %d\n", + ret); + return ret; + } + switch (MXC_CCM_CBCMR_PERIPH_CLK_SEL_RD( + readl(&mxc_ccm->cbcmr))) { + case 0: + return config_pll_clk(PLL1_CLOCK, &pll_param); + break; + case 1: + return config_pll_clk(PLL3_CLOCK, &pll_param); + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static int config_ddr_clk(u32 emi_clk) +{ + u32 clk_src; + s32 shift = 0, clk_sel, div = 1; + u32 cbcmr = readl(&mxc_ccm->cbcmr); + + if (emi_clk > MAX_DDR_CLK) { + printf("Warning:DDR clock should not exceed %d MHz\n", + MAX_DDR_CLK / SZ_DEC_1M); + emi_clk = MAX_DDR_CLK; + } + + clk_src = get_periph_clk(); + /* Find DDR clock input */ + clk_sel = MXC_CCM_CBCMR_DDR_CLK_SEL_RD(cbcmr); + switch (clk_sel) { + case 0: + shift = 16; + break; + case 1: + shift = 19; + break; + case 2: + shift = 22; + break; + case 3: + shift = 10; + break; + default: + return -EINVAL; + } + + if ((clk_src % emi_clk) < 10000000) + div = clk_src / emi_clk; + else + div = (clk_src / emi_clk) + 1; + if (div > 8) + div = 8; + + clrsetbits_le32(&mxc_ccm->cbcdr, 0x7 << shift, (div - 1) << shift); + while (readl(&mxc_ccm->cdhipr) != 0) + ; + writel(0x0, &mxc_ccm->ccdr); + + return 0; +} + +/* + * This function assumes the expected core clock has to be changed by + * modifying the PLL. This is NOT true always but for most of the times, + * it is. So it assumes the PLL output freq is the same as the expected + * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN. + * In the latter case, it will try to increase the presc value until + * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to + * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based + * on the targeted PLL and reference input clock to the PLL. Lastly, + * it sets the register based on these values along with the dividers. + * Note 1) There is no value checking for the passed-in divider values + * so the caller has to make sure those values are sensible. + * 2) Also adjust the NFC divider such that the NFC clock doesn't + * exceed NFC_CLK_MAX. + * 3) IPU HSP clock is independent of AHB clock. Even it can go up to + * 177MHz for higher voltage, this function fixes the max to 133MHz. + * 4) This function should not have allowed diag_printf() calls since + * the serial driver has been stoped. But leave then here to allow + * easy debugging by NOT calling the cyg_hal_plf_serial_stop(). + */ +int mxc_set_clock(u32 ref, u32 freq, enum mxc_clock clk) +{ + freq *= SZ_DEC_1M; + + switch (clk) { + case MXC_ARM_CLK: + if (config_core_clk(ref, freq)) + return -EINVAL; + break; + case MXC_PERIPH_CLK: + if (config_periph_clk(ref, freq)) + return -EINVAL; + break; + case MXC_DDR_CLK: + if (config_ddr_clk(freq)) + return -EINVAL; + break; + case MXC_NFC_CLK: + if (config_nfc_clk(freq)) + return -EINVAL; + break; + default: + printf("Warning:Unsupported or invalid clock type\n"); + } + + return 0; +} + +#ifdef CONFIG_MX53 +/* + * The clock for the external interface can be set to use internal clock + * if fuse bank 4, row 3, bit 2 is set. + * This is an undocumented feature and it was confirmed by Freescale's support: + * Fuses (but not pins) may be used to configure SATA clocks. + * Particularly the i.MX53 Fuse_Map contains the next information + * about configuring SATA clocks : SATA_ALT_REF_CLK[1:0] (offset 0x180C) + * '00' - 100MHz (External) + * '01' - 50MHz (External) + * '10' - 120MHz, internal (USB PHY) + * '11' - Reserved +*/ +void mxc_set_sata_internal_clock(void) +{ + u32 *tmp_base = + (u32 *)(IIM_BASE_ADDR + 0x180c); + + set_usb_phy_clk(); + + clrsetbits_le32(tmp_base, 0x6, 0x4); +} +#endif + +/* + * Dump some core clockes. + */ +int do_mx5_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + u32 freq; + + freq = decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK); + printf("PLL1 %8d MHz\n", freq / 1000000); + freq = decode_pll(mxc_plls[PLL2_CLOCK], MXC_HCLK); + printf("PLL2 %8d MHz\n", freq / 1000000); + freq = decode_pll(mxc_plls[PLL3_CLOCK], MXC_HCLK); + printf("PLL3 %8d MHz\n", freq / 1000000); +#ifdef CONFIG_MX53 + freq = decode_pll(mxc_plls[PLL4_CLOCK], MXC_HCLK); + printf("PLL4 %8d MHz\n", freq / 1000000); +#endif + + printf("\n"); + printf("AHB %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000); + printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000); + printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000); + printf("DDR %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000); +#ifdef CONFIG_MXC_SPI + printf("CSPI %8d kHz\n", mxc_get_clock(MXC_CSPI_CLK) / 1000); +#endif + return 0; +} + +/***************************************************/ + +U_BOOT_CMD( + clocks, CONFIG_SYS_MAXARGS, 1, do_mx5_showclocks, + "display clocks", + "" +); diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/lowlevel_init.S new file mode 100644 index 000000000..f5bc6728b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/lowlevel_init.S @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de> + * + * (C) Copyright 2009 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <asm/arch/imx-regs.h> +#include <generated/asm-offsets.h> +#include <linux/linkage.h> + +.section ".text.init", "x" + +.macro init_arm_erratum + /* ARM erratum ID #468414 */ + mrc 15, 0, r1, c1, c0, 1 + orr r1, r1, #(1 << 5) /* enable L1NEON bit */ + mcr 15, 0, r1, c1, c0, 1 +.endm + +/* + * L2CC Cache setup/invalidation/disable + */ +.macro init_l2cc + /* explicitly disable L2 cache */ + mrc 15, 0, r0, c1, c0, 1 + bic r0, r0, #0x2 + mcr 15, 0, r0, c1, c0, 1 + + /* reconfigure L2 cache aux control reg */ + ldr r0, =0xC0 | /* tag RAM */ \ + 0x4 | /* data RAM */ \ + 1 << 24 | /* disable write allocate delay */ \ + 1 << 23 | /* disable write allocate combine */ \ + 1 << 22 /* disable write allocate */ + +#if defined(CONFIG_MX51) + ldr r3, [r4, #ROM_SI_REV] + cmp r3, #0x10 + + /* disable write combine for TO 2 and lower revs */ + orrls r0, r0, #1 << 25 +#endif + + mcr 15, 1, r0, c9, c0, 2 + + /* enable L2 cache */ + mrc 15, 0, r0, c1, c0, 1 + orr r0, r0, #2 + mcr 15, 0, r0, c1, c0, 1 + +.endm /* init_l2cc */ + +/* AIPS setup - Only setup MPROTx registers. + * The PACR default values are good.*/ +.macro init_aips + /* + * Set all MPROTx to be non-bufferable, trusted for R/W, + * not forced to user-mode. + */ + ldr r0, =AIPS1_BASE_ADDR + ldr r1, =0x77777777 + str r1, [r0, #0x0] + str r1, [r0, #0x4] + ldr r0, =AIPS2_BASE_ADDR + str r1, [r0, #0x0] + str r1, [r0, #0x4] + /* + * Clear the on and off peripheral modules Supervisor Protect bit + * for SDMA to access them. Did not change the AIPS control registers + * (offset 0x20) access type + */ +.endm /* init_aips */ + +/* M4IF setup */ +.macro init_m4if +#ifdef CONFIG_MX51 + /* VPU and IPU given higher priority (0x4) + * IPU accesses with ID=0x1 given highest priority (=0xA) + */ + ldr r0, =M4IF_BASE_ADDR + + ldr r1, =0x00000203 + str r1, [r0, #0x40] + + str r4, [r0, #0x44] + + ldr r1, =0x00120125 + str r1, [r0, #0x9C] + + ldr r1, =0x001901A3 + str r1, [r0, #0x48] + +#endif +.endm /* init_m4if */ + +.macro setup_pll pll, freq + ldr r0, =\pll + adr r2, W_DP_\freq + bl setup_pll_func +.endm + +#define W_DP_OP 0 +#define W_DP_MFD 4 +#define W_DP_MFN 8 + +setup_pll_func: + ldr r1, =0x00001232 + str r1, [r0, #PLL_DP_CTL] /* Set DPLL ON (set UPEN bit): BRMO=1 */ + mov r1, #0x2 + str r1, [r0, #PLL_DP_CONFIG] /* Enable auto-restart AREN bit */ + + ldr r1, [r2, #W_DP_OP] + str r1, [r0, #PLL_DP_OP] + str r1, [r0, #PLL_DP_HFS_OP] + + ldr r1, [r2, #W_DP_MFD] + str r1, [r0, #PLL_DP_MFD] + str r1, [r0, #PLL_DP_HFS_MFD] + + ldr r1, [r2, #W_DP_MFN] + str r1, [r0, #PLL_DP_MFN] + str r1, [r0, #PLL_DP_HFS_MFN] + + ldr r1, =0x00001232 + str r1, [r0, #PLL_DP_CTL] +1: ldr r1, [r0, #PLL_DP_CTL] + ands r1, r1, #0x1 + beq 1b + + /* r10 saved upper lr */ + mov pc, lr + +.macro setup_pll_errata pll, freq + ldr r2, =\pll + str r4, [r2, #PLL_DP_CONFIG] /* Disable auto-restart AREN bit */ + ldr r1, =0x00001236 + str r1, [r2, #PLL_DP_CTL] /* Restart PLL with PLM=1 */ +1: ldr r1, [r2, #PLL_DP_CTL] /* Wait for lock */ + ands r1, r1, #0x1 + beq 1b + + ldr r5, \freq + str r5, [r2, #PLL_DP_MFN] /* Modify MFN value */ + str r5, [r2, #PLL_DP_HFS_MFN] + + mov r1, #0x1 + str r1, [r2, #PLL_DP_CONFIG] /* Reload MFN value */ + +2: ldr r1, [r2, #PLL_DP_CONFIG] + tst r1, #1 + bne 2b + + ldr r1, =100 /* Wait at least 4 us */ +3: subs r1, r1, #1 + bge 3b + + mov r1, #0x2 + str r1, [r2, #PLL_DP_CONFIG] /* Enable auto-restart AREN bit */ +.endm + +.macro init_clock +#if defined (CONFIG_MX51) + ldr r0, =CCM_BASE_ADDR + + /* Gate of clocks to the peripherals first */ + ldr r1, =0x3FFFFFFF + str r1, [r0, #CLKCTL_CCGR0] + str r4, [r0, #CLKCTL_CCGR1] + str r4, [r0, #CLKCTL_CCGR2] + str r4, [r0, #CLKCTL_CCGR3] + + ldr r1, =0x00030000 + str r1, [r0, #CLKCTL_CCGR4] + ldr r1, =0x00FFF030 + str r1, [r0, #CLKCTL_CCGR5] + ldr r1, =0x00000300 + str r1, [r0, #CLKCTL_CCGR6] + + /* Disable IPU and HSC dividers */ + mov r1, #0x60000 + str r1, [r0, #CLKCTL_CCDR] + + /* Make sure to switch the DDR away from PLL 1 */ + ldr r1, =0x19239145 + str r1, [r0, #CLKCTL_CBCDR] + /* make sure divider effective */ +1: ldr r1, [r0, #CLKCTL_CDHIPR] + cmp r1, #0x0 + bne 1b + + /* Switch ARM to step clock */ + mov r1, #0x4 + str r1, [r0, #CLKCTL_CCSR] + +#if defined(CONFIG_MX51_PLL_ERRATA) + setup_pll PLL1_BASE_ADDR, 864 + setup_pll_errata PLL1_BASE_ADDR, W_DP_MFN_800_DIT +#else + setup_pll PLL1_BASE_ADDR, 800 +#endif + + setup_pll PLL3_BASE_ADDR, 665 + + /* Switch peripheral to PLL 3 */ + ldr r0, =CCM_BASE_ADDR + ldr r1, =0x000010C0 | CONFIG_SYS_DDR_CLKSEL + str r1, [r0, #CLKCTL_CBCMR] + ldr r1, =0x13239145 + str r1, [r0, #CLKCTL_CBCDR] + setup_pll PLL2_BASE_ADDR, 665 + + /* Switch peripheral to PLL2 */ + ldr r0, =CCM_BASE_ADDR + ldr r1, =0x19239145 + str r1, [r0, #CLKCTL_CBCDR] + ldr r1, =0x000020C0 | CONFIG_SYS_DDR_CLKSEL + str r1, [r0, #CLKCTL_CBCMR] + + setup_pll PLL3_BASE_ADDR, 216 + + /* Set the platform clock dividers */ + ldr r0, =ARM_BASE_ADDR + ldr r1, =0x00000725 + str r1, [r0, #0x14] + + ldr r0, =CCM_BASE_ADDR + + /* Run 3.0 at Full speed, for other TO's wait till we increase VDDGP */ + ldr r3, [r4, #ROM_SI_REV] + cmp r3, #0x10 + movls r1, #0x1 + movhi r1, #0 + + str r1, [r0, #CLKCTL_CACRR] + + /* Switch ARM back to PLL 1 */ + str r4, [r0, #CLKCTL_CCSR] + + /* setup the rest */ + /* Use lp_apm (24MHz) source for perclk */ + ldr r1, =0x000020C2 | CONFIG_SYS_DDR_CLKSEL + str r1, [r0, #CLKCTL_CBCMR] + /* ddr clock from PLL 1, all perclk dividers are 1 since using 24MHz */ + ldr r1, =CONFIG_SYS_CLKTL_CBCDR + str r1, [r0, #CLKCTL_CBCDR] + + /* Restore the default values in the Gate registers */ + ldr r1, =0xFFFFFFFF + str r1, [r0, #CLKCTL_CCGR0] + str r1, [r0, #CLKCTL_CCGR1] + str r1, [r0, #CLKCTL_CCGR2] + str r1, [r0, #CLKCTL_CCGR3] + str r1, [r0, #CLKCTL_CCGR4] + str r1, [r0, #CLKCTL_CCGR5] + str r1, [r0, #CLKCTL_CCGR6] + + /* Use PLL 2 for UART's, get 66.5MHz from it */ + ldr r1, =0xA5A2A020 + str r1, [r0, #CLKCTL_CSCMR1] + ldr r1, =0x00C30321 + str r1, [r0, #CLKCTL_CSCDR1] + /* make sure divider effective */ +1: ldr r1, [r0, #CLKCTL_CDHIPR] + cmp r1, #0x0 + bne 1b + + str r4, [r0, #CLKCTL_CCDR] + + /* for cko - for ARM div by 8 */ + mov r1, #0x000A0000 + add r1, r1, #0x00000F0 + str r1, [r0, #CLKCTL_CCOSR] +#else /* CONFIG_MX53 */ + ldr r0, =CCM_BASE_ADDR + + /* Gate of clocks to the peripherals first */ + ldr r1, =0x3FFFFFFF + str r1, [r0, #CLKCTL_CCGR0] + str r4, [r0, #CLKCTL_CCGR1] + str r4, [r0, #CLKCTL_CCGR2] + str r4, [r0, #CLKCTL_CCGR3] + str r4, [r0, #CLKCTL_CCGR7] + ldr r1, =0x00030000 + str r1, [r0, #CLKCTL_CCGR4] + ldr r1, =0x00FFF030 + str r1, [r0, #CLKCTL_CCGR5] + ldr r1, =0x0F00030F + str r1, [r0, #CLKCTL_CCGR6] + + /* Switch ARM to step clock */ + mov r1, #0x4 + str r1, [r0, #CLKCTL_CCSR] + + setup_pll PLL1_BASE_ADDR, 800 + + setup_pll PLL3_BASE_ADDR, 400 + + /* Switch peripheral to PLL3 */ + ldr r0, =CCM_BASE_ADDR + ldr r1, =0x00015154 + str r1, [r0, #CLKCTL_CBCMR] + ldr r1, =0x02898945 + str r1, [r0, #CLKCTL_CBCDR] + /* make sure change is effective */ +1: ldr r1, [r0, #CLKCTL_CDHIPR] + cmp r1, #0x0 + bne 1b + + setup_pll PLL2_BASE_ADDR, 400 + + /* Switch peripheral to PLL2 */ + ldr r0, =CCM_BASE_ADDR + ldr r1, =0x00888945 + str r1, [r0, #CLKCTL_CBCDR] + + ldr r1, =0x00016154 + str r1, [r0, #CLKCTL_CBCMR] + + /*change uart clk parent to pll2*/ + ldr r1, [r0, #CLKCTL_CSCMR1] + and r1, r1, #0xfcffffff + orr r1, r1, #0x01000000 + str r1, [r0, #CLKCTL_CSCMR1] + + /* make sure change is effective */ +1: ldr r1, [r0, #CLKCTL_CDHIPR] + cmp r1, #0x0 + bne 1b + + setup_pll PLL3_BASE_ADDR, 216 + + setup_pll PLL4_BASE_ADDR, 455 + + /* Set the platform clock dividers */ + ldr r0, =ARM_BASE_ADDR + ldr r1, =0x00000124 + str r1, [r0, #0x14] + + ldr r0, =CCM_BASE_ADDR + mov r1, #0 + str r1, [r0, #CLKCTL_CACRR] + + /* Switch ARM back to PLL 1. */ + mov r1, #0x0 + str r1, [r0, #CLKCTL_CCSR] + + /* make uart div=6 */ + ldr r1, [r0, #CLKCTL_CSCDR1] + and r1, r1, #0xffffffc0 + orr r1, r1, #0x0a + str r1, [r0, #CLKCTL_CSCDR1] + + /* Restore the default values in the Gate registers */ + ldr r1, =0xFFFFFFFF + str r1, [r0, #CLKCTL_CCGR0] + str r1, [r0, #CLKCTL_CCGR1] + str r1, [r0, #CLKCTL_CCGR2] + str r1, [r0, #CLKCTL_CCGR3] + str r1, [r0, #CLKCTL_CCGR4] + str r1, [r0, #CLKCTL_CCGR5] + str r1, [r0, #CLKCTL_CCGR6] + str r1, [r0, #CLKCTL_CCGR7] + + mov r1, #0x00000 + str r1, [r0, #CLKCTL_CCDR] + + /* for cko - for ARM div by 8 */ + mov r1, #0x000A0000 + add r1, r1, #0x00000F0 + str r1, [r0, #CLKCTL_CCOSR] + +#endif /* CONFIG_MX53 */ +.endm + +ENTRY(lowlevel_init) + mov r10, lr + mov r4, #0 /* Fix R4 to 0 */ + +#if defined(CONFIG_SYS_MAIN_PWR_ON) + ldr r0, =GPIO1_BASE_ADDR + ldr r1, [r0, #0x0] + orr r1, r1, #1 << 23 + str r1, [r0, #0x0] + ldr r1, [r0, #0x4] + orr r1, r1, #1 << 23 + str r1, [r0, #0x4] +#endif + + init_arm_erratum + + init_l2cc + + init_aips + + init_m4if + + init_clock + + mov pc, r10 +ENDPROC(lowlevel_init) + +/* Board level setting value */ +#if defined(CONFIG_MX51_PLL_ERRATA) +W_DP_864: .word DP_OP_864 + .word DP_MFD_864 + .word DP_MFN_864 +W_DP_MFN_800_DIT: .word DP_MFN_800_DIT +#else +W_DP_800: .word DP_OP_800 + .word DP_MFD_800 + .word DP_MFN_800 +#endif +#if defined(CONFIG_MX51) +W_DP_665: .word DP_OP_665 + .word DP_MFD_665 + .word DP_MFN_665 +#endif +W_DP_216: .word DP_OP_216 + .word DP_MFD_216 + .word DP_MFN_216 +W_DP_400: .word DP_OP_400 + .word DP_MFD_400 + .word DP_MFN_400 +W_DP_455: .word DP_OP_455 + .word DP_MFD_455 + .word DP_MFN_455 diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/soc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/soc.c new file mode 100644 index 000000000..2d53669c8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx5/soc.c @@ -0,0 +1,147 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (C) Copyright 2009 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> + +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/imx-common/boot_mode.h> + +#if !(defined(CONFIG_MX51) || defined(CONFIG_MX53)) +#error "CPU_TYPE not defined" +#endif + +u32 get_cpu_rev(void) +{ +#ifdef CONFIG_MX51 + int system_rev = 0x51000; +#else + int system_rev = 0x53000; +#endif + int reg = __raw_readl(ROM_SI_REV); + +#if defined(CONFIG_MX51) + switch (reg) { + case 0x02: + system_rev |= CHIP_REV_1_1; + break; + case 0x10: + if ((__raw_readl(GPIO1_BASE_ADDR + 0x0) & (0x1 << 22)) == 0) + system_rev |= CHIP_REV_2_5; + else + system_rev |= CHIP_REV_2_0; + break; + case 0x20: + system_rev |= CHIP_REV_3_0; + break; + default: + system_rev |= CHIP_REV_1_0; + break; + } +#else + if (reg < 0x20) + system_rev |= CHIP_REV_1_0; + else + system_rev |= reg; +#endif + return system_rev; +} + +#ifdef CONFIG_REVISION_TAG +u32 __weak get_board_rev(void) +{ + return get_cpu_rev(); +} +#endif + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif + +#if defined(CONFIG_FEC_MXC) +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + int i; + struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; + struct fuse_bank *bank = &iim->bank[1]; + struct fuse_bank1_regs *fuse = + (struct fuse_bank1_regs *)bank->fuse_regs; + + for (i = 0; i < 6; i++) + mac[i] = readl(&fuse->mac_addr[i]) & 0xff; +} +#endif + +void set_chipselect_size(int const cs_size) +{ + unsigned int reg; + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; + reg = readl(&iomuxc_regs->gpr1); + + switch (cs_size) { + case CS0_128: + reg &= ~0x7; /* CS0=128MB, CS1=0, CS2=0, CS3=0 */ + reg |= 0x5; + break; + case CS0_64M_CS1_64M: + reg &= ~0x3F; /* CS0=64MB, CS1=64MB, CS2=0, CS3=0 */ + reg |= 0x1B; + break; + case CS0_64M_CS1_32M_CS2_32M: + reg &= ~0x1FF; /* CS0=64MB, CS1=32MB, CS2=32MB, CS3=0 */ + reg |= 0x4B; + break; + case CS0_32M_CS1_32M_CS2_32M_CS3_32M: + reg &= ~0xFFF; /* CS0=32MB, CS1=32MB, CS2=32MB, CS3=32MB */ + reg |= 0x249; + break; + default: + printf("Unknown chip select size: %d\n", cs_size); + break; + } + + writel(reg, &iomuxc_regs->gpr1); +} + +#ifdef CONFIG_MX53 +void boot_mode_apply(unsigned cfg_val) +{ + writel(cfg_val, &((struct srtc_regs *)SRTC_BASE_ADDR)->lpgr); +} +/* + * cfg_val will be used for + * Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0] + * + * If bit 28 of LPGR is set upon watchdog reset, + * bits[25:0] of LPGR will move to SBMR. + */ +const struct boot_mode soc_boot_modes[] = { + {"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)}, + /* usb or serial download */ + {"usb", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x13)}, + {"sata", MAKE_CFGVAL(0x28, 0x00, 0x00, 0x12)}, + {"escpi1:0", MAKE_CFGVAL(0x38, 0x20, 0x00, 0x12)}, + {"escpi1:1", MAKE_CFGVAL(0x38, 0x20, 0x04, 0x12)}, + {"escpi1:2", MAKE_CFGVAL(0x38, 0x20, 0x08, 0x12)}, + {"escpi1:3", MAKE_CFGVAL(0x38, 0x20, 0x0c, 0x12)}, + /* 4 bit bus width */ + {"esdhc1", MAKE_CFGVAL(0x40, 0x20, 0x00, 0x12)}, + {"esdhc2", MAKE_CFGVAL(0x40, 0x20, 0x08, 0x12)}, + {"esdhc3", MAKE_CFGVAL(0x40, 0x20, 0x10, 0x12)}, + {"esdhc4", MAKE_CFGVAL(0x40, 0x20, 0x18, 0x12)}, + {NULL, 0}, +}; +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/Makefile new file mode 100644 index 000000000..d7285fc2c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/Makefile @@ -0,0 +1,11 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2011 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := soc.o clock.o +obj-$(CONFIG_SECURE_BOOT) += hab.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/clock.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/clock.c new file mode 100644 index 000000000..bd65a08ba --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/clock.c @@ -0,0 +1,590 @@ +/* + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/crm_regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> + +enum pll_clocks { + PLL_SYS, /* System PLL */ + PLL_BUS, /* System Bus PLL*/ + PLL_USBOTG, /* OTG USB PLL */ + PLL_ENET, /* ENET PLL */ +}; + +struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + +#ifdef CONFIG_MXC_OCOTP +void enable_ocotp_clk(unsigned char enable) +{ + u32 reg; + + reg = __raw_readl(&imx_ccm->CCGR2); + if (enable) + reg |= MXC_CCM_CCGR2_OCOTP_CTRL_MASK; + else + reg &= ~MXC_CCM_CCGR2_OCOTP_CTRL_MASK; + __raw_writel(reg, &imx_ccm->CCGR2); +} +#endif + +void enable_usboh3_clk(unsigned char enable) +{ + u32 reg; + + reg = __raw_readl(&imx_ccm->CCGR6); + if (enable) + reg |= MXC_CCM_CCGR6_USBOH3_MASK; + else + reg &= ~(MXC_CCM_CCGR6_USBOH3_MASK); + __raw_writel(reg, &imx_ccm->CCGR6); + +} + +#ifdef CONFIG_SYS_I2C_MXC +/* i2c_num can be from 0 - 2 */ +int enable_i2c_clk(unsigned char enable, unsigned i2c_num) +{ + u32 reg; + u32 mask; + + if (i2c_num > 2) + return -EINVAL; + + mask = MXC_CCM_CCGR_CG_MASK + << (MXC_CCM_CCGR2_I2C1_SERIAL_OFFSET + (i2c_num << 1)); + reg = __raw_readl(&imx_ccm->CCGR2); + if (enable) + reg |= mask; + else + reg &= ~mask; + __raw_writel(reg, &imx_ccm->CCGR2); + return 0; +} +#endif + +static u32 decode_pll(enum pll_clocks pll, u32 infreq) +{ + u32 div; + + switch (pll) { + case PLL_SYS: + div = __raw_readl(&imx_ccm->analog_pll_sys); + div &= BM_ANADIG_PLL_SYS_DIV_SELECT; + + return infreq * (div >> 1); + case PLL_BUS: + div = __raw_readl(&imx_ccm->analog_pll_528); + div &= BM_ANADIG_PLL_528_DIV_SELECT; + + return infreq * (20 + (div << 1)); + case PLL_USBOTG: + div = __raw_readl(&imx_ccm->analog_usb1_pll_480_ctrl); + div &= BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT; + + return infreq * (20 + (div << 1)); + case PLL_ENET: + div = __raw_readl(&imx_ccm->analog_pll_enet); + div &= BM_ANADIG_PLL_ENET_DIV_SELECT; + + return 25000000 * (div + (div >> 1) + 1); + default: + return 0; + } + /* NOTREACHED */ +} +static u32 mxc_get_pll_pfd(enum pll_clocks pll, int pfd_num) +{ + u32 div; + u64 freq; + + switch (pll) { + case PLL_BUS: + if (pfd_num == 3) { + /* No PFD3 on PPL2 */ + return 0; + } + div = __raw_readl(&imx_ccm->analog_pfd_528); + freq = (u64)decode_pll(PLL_BUS, MXC_HCLK); + break; + case PLL_USBOTG: + div = __raw_readl(&imx_ccm->analog_pfd_480); + freq = (u64)decode_pll(PLL_USBOTG, MXC_HCLK); + break; + default: + /* No PFD on other PLL */ + return 0; + } + + return lldiv(freq * 18, (div & ANATOP_PFD_FRAC_MASK(pfd_num)) >> + ANATOP_PFD_FRAC_SHIFT(pfd_num)); +} + +static u32 get_mcu_main_clk(void) +{ + u32 reg, freq; + + reg = __raw_readl(&imx_ccm->cacrr); + reg &= MXC_CCM_CACRR_ARM_PODF_MASK; + reg >>= MXC_CCM_CACRR_ARM_PODF_OFFSET; + freq = decode_pll(PLL_SYS, MXC_HCLK); + + return freq / (reg + 1); +} + +u32 get_periph_clk(void) +{ + u32 reg, freq = 0; + + reg = __raw_readl(&imx_ccm->cbcdr); + if (reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL) { + reg = __raw_readl(&imx_ccm->cbcmr); + reg &= MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK; + reg >>= MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET; + + switch (reg) { + case 0: + freq = decode_pll(PLL_USBOTG, MXC_HCLK); + break; + case 1: + case 2: + freq = MXC_HCLK; + break; + default: + break; + } + } else { + reg = __raw_readl(&imx_ccm->cbcmr); + reg &= MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK; + reg >>= MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET; + + switch (reg) { + case 0: + freq = decode_pll(PLL_BUS, MXC_HCLK); + break; + case 1: + freq = mxc_get_pll_pfd(PLL_BUS, 2); + break; + case 2: + freq = mxc_get_pll_pfd(PLL_BUS, 0); + break; + case 3: + /* static / 2 divider */ + freq = mxc_get_pll_pfd(PLL_BUS, 2) / 2; + break; + default: + break; + } + } + + return freq; +} + +static u32 get_ipg_clk(void) +{ + u32 reg, ipg_podf; + + reg = __raw_readl(&imx_ccm->cbcdr); + reg &= MXC_CCM_CBCDR_IPG_PODF_MASK; + ipg_podf = reg >> MXC_CCM_CBCDR_IPG_PODF_OFFSET; + + return get_ahb_clk() / (ipg_podf + 1); +} + +static u32 get_ipg_per_clk(void) +{ + u32 reg, perclk_podf; + + reg = __raw_readl(&imx_ccm->cscmr1); + perclk_podf = reg & MXC_CCM_CSCMR1_PERCLK_PODF_MASK; + + return get_ipg_clk() / (perclk_podf + 1); +} + +static u32 get_uart_clk(void) +{ + u32 reg, uart_podf; + u32 freq = decode_pll(PLL_USBOTG, MXC_HCLK) / 6; /* static divider */ + reg = __raw_readl(&imx_ccm->cscdr1); +#ifdef CONFIG_MX6SL + if (reg & MXC_CCM_CSCDR1_UART_CLK_SEL) + freq = MXC_HCLK; +#endif + reg &= MXC_CCM_CSCDR1_UART_CLK_PODF_MASK; + uart_podf = reg >> MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET; + + return freq / (uart_podf + 1); +} + +static u32 get_cspi_clk(void) +{ + u32 reg, cspi_podf; + + reg = __raw_readl(&imx_ccm->cscdr2); + reg &= MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK; + cspi_podf = reg >> MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET; + + return decode_pll(PLL_USBOTG, MXC_HCLK) / (8 * (cspi_podf + 1)); +} + +static u32 get_axi_clk(void) +{ + u32 root_freq, axi_podf; + u32 cbcdr = __raw_readl(&imx_ccm->cbcdr); + + axi_podf = cbcdr & MXC_CCM_CBCDR_AXI_PODF_MASK; + axi_podf >>= MXC_CCM_CBCDR_AXI_PODF_OFFSET; + + if (cbcdr & MXC_CCM_CBCDR_AXI_SEL) { + if (cbcdr & MXC_CCM_CBCDR_AXI_ALT_SEL) + root_freq = mxc_get_pll_pfd(PLL_BUS, 2); + else + root_freq = mxc_get_pll_pfd(PLL_USBOTG, 1); + } else + root_freq = get_periph_clk(); + + return root_freq / (axi_podf + 1); +} + +static u32 get_emi_slow_clk(void) +{ + u32 emi_clk_sel, emi_slow_podf, cscmr1, root_freq = 0; + + cscmr1 = __raw_readl(&imx_ccm->cscmr1); + emi_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK; + emi_clk_sel >>= MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET; + emi_slow_podf = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK; + emi_slow_podf >>= MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET; + + switch (emi_clk_sel) { + case 0: + root_freq = get_axi_clk(); + break; + case 1: + root_freq = decode_pll(PLL_USBOTG, MXC_HCLK); + break; + case 2: + root_freq = mxc_get_pll_pfd(PLL_BUS, 2); + break; + case 3: + root_freq = mxc_get_pll_pfd(PLL_BUS, 0); + break; + } + + return root_freq / (emi_slow_podf + 1); +} + +#ifdef CONFIG_MX6SL +static u32 get_mmdc_ch0_clk(void) +{ + u32 cbcmr = __raw_readl(&imx_ccm->cbcmr); + u32 cbcdr = __raw_readl(&imx_ccm->cbcdr); + u32 freq, podf; + + podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK) \ + >> MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET; + + switch ((cbcmr & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK) >> + MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET) { + case 0: + freq = decode_pll(PLL_BUS, MXC_HCLK); + break; + case 1: + freq = mxc_get_pll_pfd(PLL_BUS, 2); + break; + case 2: + freq = mxc_get_pll_pfd(PLL_BUS, 0); + break; + case 3: + /* static / 2 divider */ + freq = mxc_get_pll_pfd(PLL_BUS, 2) / 2; + } + + return freq / (podf + 1); + +} +#else +static u32 get_mmdc_ch0_clk(void) +{ + u32 cbcdr = __raw_readl(&imx_ccm->cbcdr); + u32 mmdc_ch0_podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK) >> + MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET; + + return get_periph_clk() / (mmdc_ch0_podf + 1); +} +#endif + +#ifdef CONFIG_FEC_MXC +int enable_fec_anatop_clock(enum enet_freq freq) +{ + u32 reg = 0; + s32 timeout = 100000; + + struct anatop_regs __iomem *anatop = + (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; + + if (freq < ENET_25MHz || freq > ENET_125MHz) + return -EINVAL; + + reg = readl(&anatop->pll_enet); + reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT; + reg |= freq; + + if ((reg & BM_ANADIG_PLL_ENET_POWERDOWN) || + (!(reg & BM_ANADIG_PLL_ENET_LOCK))) { + reg &= ~BM_ANADIG_PLL_ENET_POWERDOWN; + writel(reg, &anatop->pll_enet); + while (timeout--) { + if (readl(&anatop->pll_enet) & BM_ANADIG_PLL_ENET_LOCK) + break; + } + if (timeout < 0) + return -ETIMEDOUT; + } + + /* Enable FEC clock */ + reg |= BM_ANADIG_PLL_ENET_ENABLE; + reg &= ~BM_ANADIG_PLL_ENET_BYPASS; + writel(reg, &anatop->pll_enet); + + return 0; +} +#endif + +static u32 get_usdhc_clk(u32 port) +{ + u32 root_freq = 0, usdhc_podf = 0, clk_sel = 0; + u32 cscmr1 = __raw_readl(&imx_ccm->cscmr1); + u32 cscdr1 = __raw_readl(&imx_ccm->cscdr1); + + switch (port) { + case 0: + usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC1_PODF_MASK) >> + MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET; + clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC1_CLK_SEL; + + break; + case 1: + usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC2_PODF_MASK) >> + MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET; + clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC2_CLK_SEL; + + break; + case 2: + usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC3_PODF_MASK) >> + MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET; + clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC3_CLK_SEL; + + break; + case 3: + usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC4_PODF_MASK) >> + MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET; + clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC4_CLK_SEL; + + break; + default: + break; + } + + if (clk_sel) + root_freq = mxc_get_pll_pfd(PLL_BUS, 0); + else + root_freq = mxc_get_pll_pfd(PLL_BUS, 2); + + return root_freq / (usdhc_podf + 1); +} + +u32 imx_get_uartclk(void) +{ + return get_uart_clk(); +} + +u32 imx_get_fecclk(void) +{ + return mxc_get_clock(MXC_IPG_CLK); +} + +static int enable_enet_pll(uint32_t en) +{ + struct mxc_ccm_reg *const imx_ccm + = (struct mxc_ccm_reg *) CCM_BASE_ADDR; + s32 timeout = 100000; + u32 reg = 0; + + /* Enable PLLs */ + reg = readl(&imx_ccm->analog_pll_enet); + reg &= ~BM_ANADIG_PLL_SYS_POWERDOWN; + writel(reg, &imx_ccm->analog_pll_enet); + reg |= BM_ANADIG_PLL_SYS_ENABLE; + while (timeout--) { + if (readl(&imx_ccm->analog_pll_enet) & BM_ANADIG_PLL_SYS_LOCK) + break; + } + if (timeout <= 0) + return -EIO; + reg &= ~BM_ANADIG_PLL_SYS_BYPASS; + writel(reg, &imx_ccm->analog_pll_enet); + reg |= en; + writel(reg, &imx_ccm->analog_pll_enet); + return 0; +} + +static void ungate_sata_clock(void) +{ + struct mxc_ccm_reg *const imx_ccm = + (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + /* Enable SATA clock. */ + setbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK); +} + +static void ungate_pcie_clock(void) +{ + struct mxc_ccm_reg *const imx_ccm = + (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + /* Enable PCIe clock. */ + setbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_PCIE_MASK); +} + +int enable_sata_clock(void) +{ + ungate_sata_clock(); + return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA); +} + +int enable_pcie_clock(void) +{ + struct anatop_regs *anatop_regs = + (struct anatop_regs *)ANATOP_BASE_ADDR; + struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + /* + * Here be dragons! + * + * The register ANATOP_MISC1 is not documented in the Freescale + * MX6RM. The register that is mapped in the ANATOP space and + * marked as ANATOP_MISC1 is actually documented in the PMU section + * of the datasheet as PMU_MISC1. + * + * Switch LVDS clock source to SATA (0xb), disable clock INPUT and + * enable clock OUTPUT. This is important for PCI express link that + * is clocked from the i.MX6. + */ +#define ANADIG_ANA_MISC1_LVDSCLK1_IBEN (1 << 12) +#define ANADIG_ANA_MISC1_LVDSCLK1_OBEN (1 << 10) +#define ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK 0x0000001F + clrsetbits_le32(&anatop_regs->ana_misc1, + ANADIG_ANA_MISC1_LVDSCLK1_IBEN | + ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK, + ANADIG_ANA_MISC1_LVDSCLK1_OBEN | 0xb); + + /* PCIe reference clock sourced from AXI. */ + clrbits_le32(&ccm_regs->cbcmr, MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL); + + /* Party time! Ungate the clock to the PCIe. */ + ungate_sata_clock(); + ungate_pcie_clock(); + + return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA | + BM_ANADIG_PLL_ENET_ENABLE_PCIE); +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return get_mcu_main_clk(); + case MXC_PER_CLK: + return get_periph_clk(); + case MXC_AHB_CLK: + return get_ahb_clk(); + case MXC_IPG_CLK: + return get_ipg_clk(); + case MXC_IPG_PERCLK: + case MXC_I2C_CLK: + return get_ipg_per_clk(); + case MXC_UART_CLK: + return get_uart_clk(); + case MXC_CSPI_CLK: + return get_cspi_clk(); + case MXC_AXI_CLK: + return get_axi_clk(); + case MXC_EMI_SLOW_CLK: + return get_emi_slow_clk(); + case MXC_DDR_CLK: + return get_mmdc_ch0_clk(); + case MXC_ESDHC_CLK: + return get_usdhc_clk(0); + case MXC_ESDHC2_CLK: + return get_usdhc_clk(1); + case MXC_ESDHC3_CLK: + return get_usdhc_clk(2); + case MXC_ESDHC4_CLK: + return get_usdhc_clk(3); + case MXC_SATA_CLK: + return get_ahb_clk(); + default: + break; + } + + return -1; +} + +/* + * Dump some core clockes. + */ +int do_mx6_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + u32 freq; + freq = decode_pll(PLL_SYS, MXC_HCLK); + printf("PLL_SYS %8d MHz\n", freq / 1000000); + freq = decode_pll(PLL_BUS, MXC_HCLK); + printf("PLL_BUS %8d MHz\n", freq / 1000000); + freq = decode_pll(PLL_USBOTG, MXC_HCLK); + printf("PLL_OTG %8d MHz\n", freq / 1000000); + freq = decode_pll(PLL_ENET, MXC_HCLK); + printf("PLL_NET %8d MHz\n", freq / 1000000); + + printf("\n"); + printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000); + printf("UART %8d kHz\n", mxc_get_clock(MXC_UART_CLK) / 1000); +#ifdef CONFIG_MXC_SPI + printf("CSPI %8d kHz\n", mxc_get_clock(MXC_CSPI_CLK) / 1000); +#endif + printf("AHB %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000); + printf("AXI %8d kHz\n", mxc_get_clock(MXC_AXI_CLK) / 1000); + printf("DDR %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000); + printf("USDHC1 %8d kHz\n", mxc_get_clock(MXC_ESDHC_CLK) / 1000); + printf("USDHC2 %8d kHz\n", mxc_get_clock(MXC_ESDHC2_CLK) / 1000); + printf("USDHC3 %8d kHz\n", mxc_get_clock(MXC_ESDHC3_CLK) / 1000); + printf("USDHC4 %8d kHz\n", mxc_get_clock(MXC_ESDHC4_CLK) / 1000); + printf("EMI SLOW %8d kHz\n", mxc_get_clock(MXC_EMI_SLOW_CLK) / 1000); + printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000); + + return 0; +} + +void enable_ipu_clock(void) +{ + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + int reg; + reg = readl(&mxc_ccm->CCGR3); + reg |= MXC_CCM_CCGR3_IPU1_IPU_MASK; + writel(reg, &mxc_ccm->CCGR3); +} +/***************************************************/ + +U_BOOT_CMD( + clocks, CONFIG_SYS_MAXARGS, 1, do_mx6_showclocks, + "display clocks", + "" +); diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/hab.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/hab.c new file mode 100644 index 000000000..518777536 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/hab.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hab.h> + +/* -------- start of HAB API updates ------------*/ +#define hab_rvt_report_event ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT) +#define hab_rvt_report_status ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS) +#define hab_rvt_authenticate_image \ + ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE) +#define hab_rvt_entry ((hab_rvt_entry_t *)HAB_RVT_ENTRY) +#define hab_rvt_exit ((hab_rvt_exit_t *)HAB_RVT_EXIT) +#define hab_rvt_clock_init HAB_RVT_CLOCK_INIT + +bool is_hab_enabled(void) +{ + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[0]; + struct fuse_bank0_regs *fuse = + (struct fuse_bank0_regs *)bank->fuse_regs; + uint32_t reg = readl(&fuse->cfg5); + + return (reg & 0x2) == 0x2; +} + +void display_event(uint8_t *event_data, size_t bytes) +{ + uint32_t i; + + if (!(event_data && bytes > 0)) + return; + + for (i = 0; i < bytes; i++) { + if (i == 0) + printf("\t0x%02x", event_data[i]); + else if ((i % 8) == 0) + printf("\n\t0x%02x", event_data[i]); + else + printf(" 0x%02x", event_data[i]); + } +} + +int get_hab_status(void) +{ + uint32_t index = 0; /* Loop index */ + uint8_t event_data[128]; /* Event data buffer */ + size_t bytes = sizeof(event_data); /* Event size in bytes */ + enum hab_config config = 0; + enum hab_state state = 0; + + if (is_hab_enabled()) + puts("\nSecure boot enabled\n"); + else + puts("\nSecure boot disabled\n"); + + /* Check HAB status */ + if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) { + printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", + config, state); + + /* Display HAB Error events */ + while (hab_rvt_report_event(HAB_FAILURE, index, event_data, + &bytes) == HAB_SUCCESS) { + puts("\n"); + printf("--------- HAB Event %d -----------------\n", + index + 1); + puts("event data:\n"); + display_event(event_data, bytes); + puts("\n"); + bytes = sizeof(event_data); + index++; + } + } + /* Display message if no HAB events are found */ + else { + printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", + config, state); + puts("No HAB Events Found!\n\n"); + } + return 0; +} + +int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if ((argc != 1)) { + cmd_usage(cmdtp); + return 1; + } + + get_hab_status(); + + return 0; +} + +U_BOOT_CMD( + hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status, + "display HAB status", + "" + ); diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/soc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/soc.c new file mode 100644 index 000000000..172527987 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/mx6/soc.c @@ -0,0 +1,435 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (C) Copyright 2009 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/armv7.h> +#include <asm/pl310.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <asm/imx-common/boot_mode.h> +#include <asm/imx-common/dma.h> +#include <stdbool.h> +#include <asm/arch/mxc_hdmi.h> +#include <asm/arch/crm_regs.h> + +enum ldo_reg { + LDO_ARM, + LDO_SOC, + LDO_PU, +}; + +struct scu_regs { + u32 ctrl; + u32 config; + u32 status; + u32 invalidate; + u32 fpga_rev; +}; + +u32 get_cpu_rev(void) +{ + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; + u32 reg = readl(&anatop->digprog_sololite); + u32 type = ((reg >> 16) & 0xff); + + if (type != MXC_CPU_MX6SL) { + reg = readl(&anatop->digprog); + struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR; + u32 cfg = readl(&scu->config) & 3; + type = ((reg >> 16) & 0xff); + if (type == MXC_CPU_MX6DL) { + if (!cfg) + type = MXC_CPU_MX6SOLO; + } + + if (type == MXC_CPU_MX6Q) { + if (cfg == 1) + type = MXC_CPU_MX6D; + } + + } + reg &= 0xff; /* mx6 silicon revision */ + return (type << 12) | (reg + 0x10); +} + +#ifdef CONFIG_REVISION_TAG +u32 __weak get_board_rev(void) +{ + u32 cpurev = get_cpu_rev(); + u32 type = ((cpurev >> 12) & 0xff); + if (type == MXC_CPU_MX6SOLO) + cpurev = (MXC_CPU_MX6DL) << 12 | (cpurev & 0xFFF); + + if (type == MXC_CPU_MX6D) + cpurev = (MXC_CPU_MX6Q) << 12 | (cpurev & 0xFFF); + + return cpurev; +} +#endif + +void init_aips(void) +{ + struct aipstz_regs *aips1, *aips2; + + aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR; + aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR; + + /* + * Set all MPROTx to be non-bufferable, trusted for R/W, + * not forced to user-mode. + */ + writel(0x77777777, &aips1->mprot0); + writel(0x77777777, &aips1->mprot1); + writel(0x77777777, &aips2->mprot0); + writel(0x77777777, &aips2->mprot1); + + /* + * Set all OPACRx to be non-bufferable, not require + * supervisor privilege level for access,allow for + * write access and untrusted master access. + */ + writel(0x00000000, &aips1->opacr0); + writel(0x00000000, &aips1->opacr1); + writel(0x00000000, &aips1->opacr2); + writel(0x00000000, &aips1->opacr3); + writel(0x00000000, &aips1->opacr4); + writel(0x00000000, &aips2->opacr0); + writel(0x00000000, &aips2->opacr1); + writel(0x00000000, &aips2->opacr2); + writel(0x00000000, &aips2->opacr3); + writel(0x00000000, &aips2->opacr4); +} + +static void clear_ldo_ramp(void) +{ + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; + int reg; + + /* ROM may modify LDO ramp up time according to fuse setting, so in + * order to be in the safe side we neeed to reset these settings to + * match the reset value: 0'b00 + */ + reg = readl(&anatop->ana_misc2); + reg &= ~(0x3f << 24); + writel(reg, &anatop->ana_misc2); +} + +/* + * Set the VDDSOC + * + * Mask out the REG_CORE[22:18] bits (REG2_TRIG) and set + * them to the specified millivolt level. + * Possible values are from 0.725V to 1.450V in steps of + * 0.025V (25mV). + */ +static int set_ldo_voltage(enum ldo_reg ldo, u32 mv) +{ + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; + u32 val, step, old, reg = readl(&anatop->reg_core); + u8 shift; + + if (mv < 725) + val = 0x00; /* Power gated off */ + else if (mv > 1450) + val = 0x1F; /* Power FET switched full on. No regulation */ + else + val = (mv - 700) / 25; + + clear_ldo_ramp(); + + switch (ldo) { + case LDO_SOC: + shift = 18; + break; + case LDO_PU: + shift = 9; + break; + case LDO_ARM: + shift = 0; + break; + default: + return -EINVAL; + } + + old = (reg & (0x1F << shift)) >> shift; + step = abs(val - old); + if (step == 0) + return 0; + + reg = (reg & ~(0x1F << shift)) | (val << shift); + writel(reg, &anatop->reg_core); + + /* + * The LDO ramp-up is based on 64 clock cycles of 24 MHz = 2.6 us per + * step + */ + udelay(3 * step); + + return 0; +} + +static void imx_set_wdog_powerdown(bool enable) +{ + struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR; + struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR; + + /* Write to the PDE (Power Down Enable) bit */ + writew(enable, &wdog1->wmcr); + writew(enable, &wdog2->wmcr); +} + +static void set_ahb_rate(u32 val) +{ + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + u32 reg, div; + + div = get_periph_clk() / val - 1; + reg = readl(&mxc_ccm->cbcdr); + + writel((reg & (~MXC_CCM_CBCDR_AHB_PODF_MASK)) | + (div << MXC_CCM_CBCDR_AHB_PODF_OFFSET), &mxc_ccm->cbcdr); +} + +static void clear_mmdc_ch_mask(void) +{ + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + /* Clear MMDC channel mask */ + writel(0, &mxc_ccm->ccdr); +} + +int arch_cpu_init(void) +{ + init_aips(); + + /* Need to clear MMDC_CHx_MASK to make warm reset work. */ + clear_mmdc_ch_mask(); + + /* + * When low freq boot is enabled, ROM will not set AHB + * freq, so we need to ensure AHB freq is 132MHz in such + * scenario. + */ + if (mxc_get_clock(MXC_ARM_CLK) == 396000000) + set_ahb_rate(132000000); + + imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */ + +#ifdef CONFIG_APBH_DMA + /* Start APBH DMA */ + mxs_dma_init(); +#endif + + return 0; +} + +int board_postclk_init(void) +{ + set_ldo_voltage(LDO_SOC, 1175); /* Set VDDSOC to 1.175V */ + + return 0; +} + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Avoid random hang when download by usb */ + invalidate_dcache_all(); + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif + +#if defined(CONFIG_FEC_MXC) +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[4]; + struct fuse_bank4_regs *fuse = + (struct fuse_bank4_regs *)bank->fuse_regs; + + u32 value = readl(&fuse->mac_addr_high); + mac[0] = (value >> 8); + mac[1] = value ; + + value = readl(&fuse->mac_addr_low); + mac[2] = value >> 24 ; + mac[3] = value >> 16 ; + mac[4] = value >> 8 ; + mac[5] = value ; + +} +#endif + +void boot_mode_apply(unsigned cfg_val) +{ + unsigned reg; + struct src *psrc = (struct src *)SRC_BASE_ADDR; + writel(cfg_val, &psrc->gpr9); + reg = readl(&psrc->gpr10); + if (cfg_val) + reg |= 1 << 28; + else + reg &= ~(1 << 28); + writel(reg, &psrc->gpr10); +} +/* + * cfg_val will be used for + * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0] + * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0] + * to SBMR1, which will determine the boot device. + */ +const struct boot_mode soc_boot_modes[] = { + {"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)}, + /* reserved value should start rom usb */ + {"usb", MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)}, + {"sata", MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)}, + {"escpi1:0", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)}, + {"escpi1:1", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)}, + {"escpi1:2", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)}, + {"escpi1:3", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)}, + /* 4 bit bus width */ + {"esdhc1", MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)}, + {"esdhc2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, + {"esdhc3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, + {"esdhc4", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)}, + {NULL, 0}, +}; + +void s_init(void) +{ + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; + int is_6q = is_cpu_type(MXC_CPU_MX6Q); + u32 mask480; + u32 mask528; + + /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs + * to make sure PFD is working right, otherwise, PFDs may + * not output clock after reset, MX6DL and MX6SL have added 396M pfd + * workaround in ROM code, as bus clock need it + */ + + mask480 = ANATOP_PFD_CLKGATE_MASK(0) | + ANATOP_PFD_CLKGATE_MASK(1) | + ANATOP_PFD_CLKGATE_MASK(2) | + ANATOP_PFD_CLKGATE_MASK(3); + mask528 = ANATOP_PFD_CLKGATE_MASK(0) | + ANATOP_PFD_CLKGATE_MASK(1) | + ANATOP_PFD_CLKGATE_MASK(3); + + /* + * Don't reset PFD2 on DL/S + */ + if (is_6q) + mask528 |= ANATOP_PFD_CLKGATE_MASK(2); + writel(mask480, &anatop->pfd_480_set); + writel(mask528, &anatop->pfd_528_set); + writel(mask480, &anatop->pfd_480_clr); + writel(mask528, &anatop->pfd_528_clr); +} + +#ifdef CONFIG_IMX_HDMI +void imx_enable_hdmi_phy(void) +{ + struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR; + u8 reg; + reg = readb(&hdmi->phy_conf0); + reg |= HDMI_PHY_CONF0_PDZ_MASK; + writeb(reg, &hdmi->phy_conf0); + udelay(3000); + reg |= HDMI_PHY_CONF0_ENTMDS_MASK; + writeb(reg, &hdmi->phy_conf0); + udelay(3000); + reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK; + writeb(reg, &hdmi->phy_conf0); + writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz); +} + +void imx_setup_hdmi(void) +{ + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR; + int reg; + + /* Turn on HDMI PHY clock */ + reg = readl(&mxc_ccm->CCGR2); + reg |= MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK| + MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK; + writel(reg, &mxc_ccm->CCGR2); + writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz); + reg = readl(&mxc_ccm->chsccdr); + reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK| + MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK| + MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK); + reg |= (CHSCCDR_PODF_DIVIDE_BY_3 + << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) + |(CHSCCDR_IPU_PRE_CLK_540M_PFD + << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET); + writel(reg, &mxc_ccm->chsccdr); +} +#endif + +#ifndef CONFIG_SYS_L2CACHE_OFF +#define IOMUXC_GPR11_L2CACHE_AS_OCRAM 0x00000002 +void v7_outer_cache_enable(void) +{ + struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE; + unsigned int val; + +#if defined CONFIG_MX6SL + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; + val = readl(&iomux->gpr[11]); + if (val & IOMUXC_GPR11_L2CACHE_AS_OCRAM) { + /* L2 cache configured as OCRAM, reset it */ + val &= ~IOMUXC_GPR11_L2CACHE_AS_OCRAM; + writel(val, &iomux->gpr[11]); + } +#endif + + writel(0x132, &pl310->pl310_tag_latency_ctrl); + writel(0x132, &pl310->pl310_data_latency_ctrl); + + val = readl(&pl310->pl310_prefetch_ctrl); + + /* Turn on the L2 I/D prefetch */ + val |= 0x30000000; + + /* + * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0 + * The L2 cache controller(PL310) version on the i.MX6DL/SOLO/SL is r3p2 + * But according to ARM PL310 errata: 752271 + * ID: 752271: Double linefill feature can cause data corruption + * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2 + * Workaround: The only workaround to this erratum is to disable the + * double linefill feature. This is the default behavior. + */ + +#ifndef CONFIG_MX6Q + val |= 0x40800000; +#endif + writel(val, &pl310->pl310_prefetch_ctrl); + + val = readl(&pl310->pl310_power_ctrl); + val |= L2X0_DYNAMIC_CLK_GATING_EN; + val |= L2X0_STNDBY_MODE_EN; + writel(val, &pl310->pl310_power_ctrl); + + setbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); +} + +void v7_outer_cache_disable(void) +{ + struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE; + + clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); +} +#endif /* !CONFIG_SYS_L2CACHE_OFF */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/nonsec_virt.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/nonsec_virt.S new file mode 100644 index 000000000..6367e0961 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/nonsec_virt.S @@ -0,0 +1,192 @@ +/* + * code for switching cores into non-secure state and into HYP mode + * + * Copyright (c) 2013 Andre Przywara <andre.przywara@linaro.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <linux/linkage.h> +#include <asm/gic.h> +#include <asm/armv7.h> + +.arch_extension sec +.arch_extension virt + + .align 5 +/* the vector table for secure state and HYP mode */ +_monitor_vectors: + .word 0 /* reset */ + .word 0 /* undef */ + adr pc, _secure_monitor + .word 0 + .word 0 + adr pc, _hyp_trap + .word 0 + .word 0 + +/* + * secure monitor handler + * U-boot calls this "software interrupt" in start.S + * This is executed on a "smc" instruction, we use a "smc #0" to switch + * to non-secure state. + * We use only r0 and r1 here, due to constraints in the caller. + */ +_secure_monitor: + mrc p15, 0, r1, c1, c1, 0 @ read SCR + bic r1, r1, #0x4e @ clear IRQ, FIQ, EA, nET bits + orr r1, r1, #0x31 @ enable NS, AW, FW bits + +#ifdef CONFIG_ARMV7_VIRT + mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1 + and r0, r0, #CPUID_ARM_VIRT_MASK @ mask virtualization bits + cmp r0, #(1 << CPUID_ARM_VIRT_SHIFT) + orreq r1, r1, #0x100 @ allow HVC instruction +#endif + + mcr p15, 0, r1, c1, c1, 0 @ write SCR (with NS bit set) + +#ifdef CONFIG_ARMV7_VIRT + mrceq p15, 0, r0, c12, c0, 1 @ get MVBAR value + mcreq p15, 4, r0, c12, c0, 0 @ write HVBAR +#endif + + movs pc, lr @ return to non-secure SVC + +_hyp_trap: + mrs lr, elr_hyp @ for older asm: .byte 0x00, 0xe3, 0x0e, 0xe1 + mov pc, lr @ do no switch modes, but + @ return to caller + +/* + * Secondary CPUs start here and call the code for the core specific parts + * of the non-secure and HYP mode transition. The GIC distributor specific + * code has already been executed by a C function before. + * Then they go back to wfi and wait to be woken up by the kernel again. + */ +ENTRY(_smp_pen) + mrs r0, cpsr + orr r0, r0, #0xc0 + msr cpsr, r0 @ disable interrupts + ldr r1, =_start + mcr p15, 0, r1, c12, c0, 0 @ set VBAR + + bl _nonsec_init + mov r12, r0 @ save GICC address +#ifdef CONFIG_ARMV7_VIRT + bl _switch_to_hyp +#endif + + ldr r1, [r12, #GICC_IAR] @ acknowledge IPI + str r1, [r12, #GICC_EOIR] @ signal end of interrupt + + adr r0, _smp_pen @ do not use this address again + b smp_waitloop @ wait for IPIs, board specific +ENDPROC(_smp_pen) + +/* + * Switch a core to non-secure state. + * + * 1. initialize the GIC per-core interface + * 2. allow coprocessor access in non-secure modes + * 3. switch the cpu mode (by calling "smc #0") + * + * Called from smp_pen by secondary cores and directly by the BSP. + * Do not assume that the stack is available and only use registers + * r0-r3 and r12. + * + * PERIPHBASE is used to get the GIC address. This could be 40 bits long, + * though, but we check this in C before calling this function. + */ +ENTRY(_nonsec_init) +#ifdef CONFIG_ARM_GIC_BASE_ADDRESS + ldr r2, =CONFIG_ARM_GIC_BASE_ADDRESS +#else + mrc p15, 4, r2, c15, c0, 0 @ read CBAR + bfc r2, #0, #15 @ clear reserved bits +#endif + add r3, r2, #GIC_DIST_OFFSET @ GIC dist i/f offset + mvn r1, #0 @ all bits to 1 + str r1, [r3, #GICD_IGROUPRn] @ allow private interrupts + + mrc p15, 0, r0, c0, c0, 0 @ read MIDR + ldr r1, =MIDR_PRIMARY_PART_MASK + and r0, r0, r1 @ mask out variant and revision + + ldr r1, =MIDR_CORTEX_A7_R0P0 & MIDR_PRIMARY_PART_MASK + cmp r0, r1 @ check for Cortex-A7 + + ldr r1, =MIDR_CORTEX_A15_R0P0 & MIDR_PRIMARY_PART_MASK + cmpne r0, r1 @ check for Cortex-A15 + + movne r1, #GIC_CPU_OFFSET_A9 @ GIC CPU offset for A9 + moveq r1, #GIC_CPU_OFFSET_A15 @ GIC CPU offset for A15/A7 + add r3, r2, r1 @ r3 = GIC CPU i/f addr + + mov r1, #1 @ set GICC_CTLR[enable] + str r1, [r3, #GICC_CTLR] @ and clear all other bits + mov r1, #0xff + str r1, [r3, #GICC_PMR] @ set priority mask register + + movw r1, #0x3fff + movt r1, #0x0006 + mcr p15, 0, r1, c1, c1, 2 @ NSACR = all copros to non-sec + +/* The CNTFRQ register of the generic timer needs to be + * programmed in secure state. Some primary bootloaders / firmware + * omit this, so if the frequency is provided in the configuration, + * we do this here instead. + * But first check if we have the generic timer. + */ +#ifdef CONFIG_SYS_CLK_FREQ + mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1 + and r0, r0, #CPUID_ARM_GENTIMER_MASK @ mask arch timer bits + cmp r0, #(1 << CPUID_ARM_GENTIMER_SHIFT) + ldreq r1, =CONFIG_SYS_CLK_FREQ + mcreq p15, 0, r1, c14, c0, 0 @ write CNTFRQ +#endif + + adr r1, _monitor_vectors + mcr p15, 0, r1, c12, c0, 1 @ set MVBAR to secure vectors + + mrc p15, 0, ip, c12, c0, 0 @ save secure copy of VBAR + + isb + smc #0 @ call into MONITOR mode + + mcr p15, 0, ip, c12, c0, 0 @ write non-secure copy of VBAR + + mov r1, #1 + str r1, [r3, #GICC_CTLR] @ enable non-secure CPU i/f + add r2, r2, #GIC_DIST_OFFSET + str r1, [r2, #GICD_CTLR] @ allow private interrupts + + mov r0, r3 @ return GICC address + + bx lr +ENDPROC(_nonsec_init) + +#ifdef CONFIG_SMP_PEN_ADDR +/* void __weak smp_waitloop(unsigned previous_address); */ +ENTRY(smp_waitloop) + wfi + ldr r1, =CONFIG_SMP_PEN_ADDR @ load start address + ldr r1, [r1] + cmp r0, r1 @ make sure we dont execute this code + beq smp_waitloop @ again (due to a spurious wakeup) + mov pc, r1 +ENDPROC(smp_waitloop) +.weak smp_waitloop +#endif + +ENTRY(_switch_to_hyp) + mov r0, lr + mov r1, sp @ save SVC copy of LR and SP + isb + hvc #0 @ for older asm: .byte 0x70, 0x00, 0x40, 0xe1 + mov sp, r1 + mov lr, r0 @ restore SVC copy of LR and SP + + bx lr +ENDPROC(_switch_to_hyp) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/Makefile new file mode 100644 index 000000000..59f5352b2 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/Makefile @@ -0,0 +1,34 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := reset.o +obj-y += timer.o +obj-y += utils.o + +ifneq ($(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),) +obj-y += hwinit-common.o +obj-y += clocks-common.o +obj-y += emif-common.o +obj-y += vc.o +obj-y += abb.o +endif + +ifneq ($(CONFIG_OMAP54XX),) +obj-y += pipe3-phy.o +obj-$(CONFIG_SCSI_AHCI_PLAT) += sata.o +endif + +ifeq ($(CONFIG_OMAP34XX),) +obj-y += boot-common.o +obj-y += lowlevel_init.o +endif + +ifndef CONFIG_SPL_BUILD +ifneq ($(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),) +obj-y += mem-common.o +endif +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/abb.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/abb.c new file mode 100644 index 000000000..423aeb980 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/abb.c @@ -0,0 +1,121 @@ +/* + * Adaptive Body Bias programming sequence for OMAP family + * + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * Andrii Tseglytskyi <andrii.tseglytskyi@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/omap_common.h> +#include <asm/arch/clock.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> + +__weak s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb) +{ + return -1; +} + +static void abb_setup_timings(u32 setup) +{ + u32 sys_rate, sr2_cnt, clk_cycles; + + /* + * SR2_WTCNT_VALUE is the settling time for the ABB ldo after a + * transition and must be programmed with the correct time at boot. + * The value programmed into the register is the number of SYS_CLK + * clock cycles that match a given wall time profiled for the ldo. + * This value depends on: + * settling time of ldo in micro-seconds (varies per OMAP family), + * of clock cycles per SYS_CLK period (varies per OMAP family), + * the SYS_CLK frequency in MHz (varies per board) + * The formula is: + * + * ldo settling time (in micro-seconds) + * SR2_WTCNT_VALUE = ------------------------------------------ + * (# system clock cycles) * (sys_clk period) + * + * Put another way: + * + * SR2_WTCNT_VALUE = settling time / (# SYS_CLK cycles / SYS_CLK rate)) + * + * To avoid dividing by zero multiply both "# clock cycles" and + * "settling time" by 10 such that the final result is the one we want. + */ + + /* calculate SR2_WTCNT_VALUE */ + sys_rate = DIV_ROUND(V_OSCK, 1000000); + clk_cycles = DIV_ROUND(OMAP_ABB_CLOCK_CYCLES * 10, sys_rate); + sr2_cnt = DIV_ROUND(OMAP_ABB_SETTLING_TIME * 10, clk_cycles); + + setbits_le32(setup, + sr2_cnt << (ffs(OMAP_ABB_SETUP_SR2_WTCNT_VALUE_MASK) - 1)); +} + +void abb_setup(u32 fuse, u32 ldovbb, u32 setup, u32 control, + u32 txdone, u32 txdone_mask, u32 opp) +{ + u32 abb_type_mask, opp_sel_mask; + + /* sanity check */ + if (!setup || !control || !txdone) + return; + + /* setup ABB only in case of Fast or Slow OPP */ + switch (opp) { + case OMAP_ABB_FAST_OPP: + abb_type_mask = OMAP_ABB_SETUP_ACTIVE_FBB_SEL_MASK; + opp_sel_mask = OMAP_ABB_CONTROL_FAST_OPP_SEL_MASK; + break; + case OMAP_ABB_SLOW_OPP: + abb_type_mask = OMAP_ABB_SETUP_ACTIVE_RBB_SEL_MASK; + opp_sel_mask = OMAP_ABB_CONTROL_SLOW_OPP_SEL_MASK; + break; + default: + return; + } + + /* + * For some OMAP silicons additional setup for LDOVBB register is + * required. This is determined by data retrieved from corresponding + * OPP EFUSE register. Data, which is retrieved from EFUSE - is + * ABB enable/disable flag and VSET value, which must be copied + * to LDOVBB register. If function call fails - return quietly, + * it means no ABB is required for such silicon. + * + * For silicons, which don't require LDOVBB setup "fuse" and + * "ldovbb" offsets are not defined. ABB will be initialized in + * the common way for them. + */ + if (fuse && ldovbb) { + if (abb_setup_ldovbb(fuse, ldovbb)) + return; + } + + /* clear ABB registers */ + writel(0, setup); + writel(0, control); + + /* configure timings, based on oscillator value */ + abb_setup_timings(setup); + + /* clear pending interrupts before setup */ + setbits_le32(txdone, txdone_mask); + + /* select ABB type */ + setbits_le32(setup, abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK); + + /* initiate ABB ldo change */ + setbits_le32(control, opp_sel_mask | OMAP_ABB_CONTROL_OPP_CHANGE_MASK); + + /* wait until transition complete */ + if (!wait_on_value(txdone_mask, txdone_mask, (void *)txdone, LDELAY)) + puts("Error: ABB txdone is not set\n"); + + /* clear ABB tranxdone */ + setbits_le32(txdone, txdone_mask); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/boot-common.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/boot-common.c new file mode 100644 index 000000000..303356476 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/boot-common.c @@ -0,0 +1,134 @@ +/* + * boot-common.c + * + * Common bootmode functions for omap based boards + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <spl.h> +#include <asm/omap_common.h> +#include <asm/arch/omap.h> +#include <asm/arch/mmc_host_def.h> +#include <asm/arch/sys_proto.h> +#include <watchdog.h> + +DECLARE_GLOBAL_DATA_PTR; + +void save_omap_boot_params(void) +{ + u32 rom_params = *((u32 *)OMAP_SRAM_SCRATCH_BOOT_PARAMS); + u8 boot_device; + u32 dev_desc, dev_data; + + if ((rom_params < NON_SECURE_SRAM_START) || + (rom_params > NON_SECURE_SRAM_END)) + return; + + /* + * rom_params can be type casted to omap_boot_parameters and + * used. But it not correct to assume that romcode structure + * encoding would be same as u-boot. So use the defined offsets. + */ + gd->arch.omap_boot_params.omap_bootdevice = boot_device = + *((u8 *)(rom_params + BOOT_DEVICE_OFFSET)); + + gd->arch.omap_boot_params.ch_flags = + *((u8 *)(rom_params + CH_FLAGS_OFFSET)); + + if ((boot_device >= MMC_BOOT_DEVICES_START) && + (boot_device <= MMC_BOOT_DEVICES_END)) { +#if !defined(CONFIG_AM33XX) && !defined(CONFIG_TI81XX) && \ + !defined(CONFIG_AM43XX) + if ((omap_hw_init_context() == + OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL)) { + gd->arch.omap_boot_params.omap_bootmode = + *((u8 *)(rom_params + BOOT_MODE_OFFSET)); + } else +#endif + { + dev_desc = *((u32 *)(rom_params + DEV_DESC_PTR_OFFSET)); + dev_data = *((u32 *)(dev_desc + DEV_DATA_PTR_OFFSET)); + gd->arch.omap_boot_params.omap_bootmode = + *((u32 *)(dev_data + BOOT_MODE_OFFSET)); + } + } + +#ifdef CONFIG_DRA7XX + /* + * We get different values for QSPI_1 and QSPI_4 being used, but + * don't actually care about this difference. Rather than + * mangle the later code, if we're coming in as QSPI_4 just + * change to the QSPI_1 value. + */ + if (gd->arch.omap_boot_params.omap_bootdevice == 11) + gd->arch.omap_boot_params.omap_bootdevice = BOOT_DEVICE_SPI; +#endif +} + +#ifdef CONFIG_SPL_BUILD +u32 spl_boot_device(void) +{ + return (u32) (gd->arch.omap_boot_params.omap_bootdevice); +} + +u32 spl_boot_mode(void) +{ + u32 val = gd->arch.omap_boot_params.omap_bootmode; + + if (val == MMCSD_MODE_RAW) + return MMCSD_MODE_RAW; + else if (val == MMCSD_MODE_FAT) + return MMCSD_MODE_FAT; + else +#ifdef CONFIG_SUPPORT_EMMC_BOOT + return MMCSD_MODE_EMMCBOOT; +#else + return MMCSD_MODE_UNDEFINED; +#endif +} + +void spl_board_init(void) +{ +#ifdef CONFIG_SPL_NAND_SUPPORT + gpmc_init(); +#endif +#if defined(CONFIG_AM33XX) && defined(CONFIG_SPL_MUSB_NEW_SUPPORT) + arch_misc_init(); +#endif +#if defined(CONFIG_HW_WATCHDOG) + hw_watchdog_init(); +#endif +#ifdef CONFIG_AM33XX + am33xx_spl_board_init(); +#endif +} + +int board_mmc_init(bd_t *bis) +{ + switch (spl_boot_device()) { + case BOOT_DEVICE_MMC1: + omap_mmc_init(0, 0, 0, -1, -1); + break; + case BOOT_DEVICE_MMC2: + case BOOT_DEVICE_MMC2_2: + omap_mmc_init(1, 0, 0, -1, -1); + break; + } + return 0; +} + +void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) +{ + typedef void __noreturn (*image_entry_noargs_t)(u32 *); + image_entry_noargs_t image_entry = + (image_entry_noargs_t) spl_image->entry_point; + + debug("image entry point: 0x%X\n", spl_image->entry_point); + /* Pass the saved boot_params from rom code */ + image_entry((u32 *)&gd->arch.omap_boot_params); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/clocks-common.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/clocks-common.c new file mode 100644 index 000000000..8e7411d43 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/clocks-common.c @@ -0,0 +1,733 @@ +/* + * + * Clock initialization for OMAP4 + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Aneesh V <aneesh@ti.com> + * + * Based on previous work by: + * Santosh Shilimkar <santosh.shilimkar@ti.com> + * Rajendra Nayak <rnayak@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <i2c.h> +#include <asm/omap_common.h> +#include <asm/gpio.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <asm/utils.h> +#include <asm/omap_gpio.h> +#include <asm/emif.h> + +#ifndef CONFIG_SPL_BUILD +/* + * printing to console doesn't work unless + * this code is executed from SPL + */ +#define printf(fmt, args...) +#define puts(s) +#endif + +const u32 sys_clk_array[8] = { + 12000000, /* 12 MHz */ + 20000000, /* 20 MHz */ + 16800000, /* 16.8 MHz */ + 19200000, /* 19.2 MHz */ + 26000000, /* 26 MHz */ + 27000000, /* 27 MHz */ + 38400000, /* 38.4 MHz */ +}; + +static inline u32 __get_sys_clk_index(void) +{ + s8 ind; + /* + * For ES1 the ROM code calibration of sys clock is not reliable + * due to hw issue. So, use hard-coded value. If this value is not + * correct for any board over-ride this function in board file + * From ES2.0 onwards you will get this information from + * CM_SYS_CLKSEL + */ + if (omap_revision() == OMAP4430_ES1_0) + ind = OMAP_SYS_CLK_IND_38_4_MHZ; + else { + /* SYS_CLKSEL - 1 to match the dpll param array indices */ + ind = (readl((*prcm)->cm_sys_clksel) & + CM_SYS_CLKSEL_SYS_CLKSEL_MASK) - 1; + } + return ind; +} + +u32 get_sys_clk_index(void) + __attribute__ ((weak, alias("__get_sys_clk_index"))); + +u32 get_sys_clk_freq(void) +{ + u8 index = get_sys_clk_index(); + return sys_clk_array[index]; +} + +void setup_post_dividers(u32 const base, const struct dpll_params *params) +{ + struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; + + /* Setup post-dividers */ + if (params->m2 >= 0) + writel(params->m2, &dpll_regs->cm_div_m2_dpll); + if (params->m3 >= 0) + writel(params->m3, &dpll_regs->cm_div_m3_dpll); + if (params->m4_h11 >= 0) + writel(params->m4_h11, &dpll_regs->cm_div_m4_h11_dpll); + if (params->m5_h12 >= 0) + writel(params->m5_h12, &dpll_regs->cm_div_m5_h12_dpll); + if (params->m6_h13 >= 0) + writel(params->m6_h13, &dpll_regs->cm_div_m6_h13_dpll); + if (params->m7_h14 >= 0) + writel(params->m7_h14, &dpll_regs->cm_div_m7_h14_dpll); + if (params->h21 >= 0) + writel(params->h21, &dpll_regs->cm_div_h21_dpll); + if (params->h22 >= 0) + writel(params->h22, &dpll_regs->cm_div_h22_dpll); + if (params->h23 >= 0) + writel(params->h23, &dpll_regs->cm_div_h23_dpll); + if (params->h24 >= 0) + writel(params->h24, &dpll_regs->cm_div_h24_dpll); +} + +static inline void do_bypass_dpll(u32 const base) +{ + struct dpll_regs *dpll_regs = (struct dpll_regs *)base; + + clrsetbits_le32(&dpll_regs->cm_clkmode_dpll, + CM_CLKMODE_DPLL_DPLL_EN_MASK, + DPLL_EN_FAST_RELOCK_BYPASS << + CM_CLKMODE_DPLL_EN_SHIFT); +} + +static inline void wait_for_bypass(u32 const base) +{ + struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; + + if (!wait_on_value(ST_DPLL_CLK_MASK, 0, &dpll_regs->cm_idlest_dpll, + LDELAY)) { + printf("Bypassing DPLL failed %x\n", base); + } +} + +static inline void do_lock_dpll(u32 const base) +{ + struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; + + clrsetbits_le32(&dpll_regs->cm_clkmode_dpll, + CM_CLKMODE_DPLL_DPLL_EN_MASK, + DPLL_EN_LOCK << CM_CLKMODE_DPLL_EN_SHIFT); +} + +static inline void wait_for_lock(u32 const base) +{ + struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; + + if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK, + &dpll_regs->cm_idlest_dpll, LDELAY)) { + printf("DPLL locking failed for %x\n", base); + hang(); + } +} + +inline u32 check_for_lock(u32 const base) +{ + struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; + u32 lock = readl(&dpll_regs->cm_idlest_dpll) & ST_DPLL_CLK_MASK; + + return lock; +} + +const struct dpll_params *get_mpu_dpll_params(struct dplls const *dpll_data) +{ + u32 sysclk_ind = get_sys_clk_index(); + return &dpll_data->mpu[sysclk_ind]; +} + +const struct dpll_params *get_core_dpll_params(struct dplls const *dpll_data) +{ + u32 sysclk_ind = get_sys_clk_index(); + return &dpll_data->core[sysclk_ind]; +} + +const struct dpll_params *get_per_dpll_params(struct dplls const *dpll_data) +{ + u32 sysclk_ind = get_sys_clk_index(); + return &dpll_data->per[sysclk_ind]; +} + +const struct dpll_params *get_iva_dpll_params(struct dplls const *dpll_data) +{ + u32 sysclk_ind = get_sys_clk_index(); + return &dpll_data->iva[sysclk_ind]; +} + +const struct dpll_params *get_usb_dpll_params(struct dplls const *dpll_data) +{ + u32 sysclk_ind = get_sys_clk_index(); + return &dpll_data->usb[sysclk_ind]; +} + +const struct dpll_params *get_abe_dpll_params(struct dplls const *dpll_data) +{ +#ifdef CONFIG_SYS_OMAP_ABE_SYSCK + u32 sysclk_ind = get_sys_clk_index(); + return &dpll_data->abe[sysclk_ind]; +#else + return dpll_data->abe; +#endif +} + +static const struct dpll_params *get_ddr_dpll_params + (struct dplls const *dpll_data) +{ + u32 sysclk_ind = get_sys_clk_index(); + + if (!dpll_data->ddr) + return NULL; + return &dpll_data->ddr[sysclk_ind]; +} + +#ifdef CONFIG_DRIVER_TI_CPSW +static const struct dpll_params *get_gmac_dpll_params + (struct dplls const *dpll_data) +{ + u32 sysclk_ind = get_sys_clk_index(); + + if (!dpll_data->gmac) + return NULL; + return &dpll_data->gmac[sysclk_ind]; +} +#endif + +static void do_setup_dpll(u32 const base, const struct dpll_params *params, + u8 lock, char *dpll) +{ + u32 temp, M, N; + struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; + + if (!params) + return; + + temp = readl(&dpll_regs->cm_clksel_dpll); + + if (check_for_lock(base)) { + /* + * The Dpll has already been locked by rom code using CH. + * Check if M,N are matching with Ideal nominal opp values. + * If matches, skip the rest otherwise relock. + */ + M = (temp & CM_CLKSEL_DPLL_M_MASK) >> CM_CLKSEL_DPLL_M_SHIFT; + N = (temp & CM_CLKSEL_DPLL_N_MASK) >> CM_CLKSEL_DPLL_N_SHIFT; + if ((M != (params->m)) || (N != (params->n))) { + debug("\n %s Dpll locked, but not for ideal M = %d," + "N = %d values, current values are M = %d," + "N= %d" , dpll, params->m, params->n, + M, N); + } else { + /* Dpll locked with ideal values for nominal opps. */ + debug("\n %s Dpll already locked with ideal" + "nominal opp values", dpll); + goto setup_post_dividers; + } + } + + bypass_dpll(base); + + /* Set M & N */ + temp &= ~CM_CLKSEL_DPLL_M_MASK; + temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK; + + temp &= ~CM_CLKSEL_DPLL_N_MASK; + temp |= (params->n << CM_CLKSEL_DPLL_N_SHIFT) & CM_CLKSEL_DPLL_N_MASK; + + writel(temp, &dpll_regs->cm_clksel_dpll); + + /* Lock */ + if (lock) + do_lock_dpll(base); + +setup_post_dividers: + setup_post_dividers(base, params); + + /* Wait till the DPLL locks */ + if (lock) + wait_for_lock(base); +} + +u32 omap_ddr_clk(void) +{ + u32 ddr_clk, sys_clk_khz, omap_rev, divider; + const struct dpll_params *core_dpll_params; + + omap_rev = omap_revision(); + sys_clk_khz = get_sys_clk_freq() / 1000; + + core_dpll_params = get_core_dpll_params(*dplls_data); + + debug("sys_clk %d\n ", sys_clk_khz * 1000); + + /* Find Core DPLL locked frequency first */ + ddr_clk = sys_clk_khz * 2 * core_dpll_params->m / + (core_dpll_params->n + 1); + + if (omap_rev < OMAP5430_ES1_0) { + /* + * DDR frequency is PHY_ROOT_CLK/2 + * PHY_ROOT_CLK = Fdpll/2/M2 + */ + divider = 4; + } else { + /* + * DDR frequency is PHY_ROOT_CLK + * PHY_ROOT_CLK = Fdpll/2/M2 + */ + divider = 2; + } + + ddr_clk = ddr_clk / divider / core_dpll_params->m2; + ddr_clk *= 1000; /* convert to Hz */ + debug("ddr_clk %d\n ", ddr_clk); + + return ddr_clk; +} + +/* + * Lock MPU dpll + * + * Resulting MPU frequencies: + * 4430 ES1.0 : 600 MHz + * 4430 ES2.x : 792 MHz (OPP Turbo) + * 4460 : 920 MHz (OPP Turbo) - DCC disabled + */ +void configure_mpu_dpll(void) +{ + const struct dpll_params *params; + struct dpll_regs *mpu_dpll_regs; + u32 omap_rev; + omap_rev = omap_revision(); + + /* + * DCC and clock divider settings for 4460. + * DCC is required, if more than a certain frequency is required. + * For, 4460 > 1GHZ. + * 5430 > 1.4GHZ. + */ + if ((omap_rev >= OMAP4460_ES1_0) && (omap_rev < OMAP5430_ES1_0)) { + mpu_dpll_regs = + (struct dpll_regs *)((*prcm)->cm_clkmode_dpll_mpu); + bypass_dpll((*prcm)->cm_clkmode_dpll_mpu); + clrbits_le32((*prcm)->cm_mpu_mpu_clkctrl, + MPU_CLKCTRL_CLKSEL_EMIF_DIV_MODE_MASK); + setbits_le32((*prcm)->cm_mpu_mpu_clkctrl, + MPU_CLKCTRL_CLKSEL_ABE_DIV_MODE_MASK); + clrbits_le32(&mpu_dpll_regs->cm_clksel_dpll, + CM_CLKSEL_DCC_EN_MASK); + } + + params = get_mpu_dpll_params(*dplls_data); + + do_setup_dpll((*prcm)->cm_clkmode_dpll_mpu, params, DPLL_LOCK, "mpu"); + debug("MPU DPLL locked\n"); +} + +#if defined(CONFIG_USB_EHCI_OMAP) || defined(CONFIG_USB_XHCI_OMAP) +static void setup_usb_dpll(void) +{ + const struct dpll_params *params; + u32 sys_clk_khz, sd_div, num, den; + + sys_clk_khz = get_sys_clk_freq() / 1000; + /* + * USB: + * USB dpll is J-type. Need to set DPLL_SD_DIV for jitter correction + * DPLL_SD_DIV = CEILING ([DPLL_MULT/(DPLL_DIV+1)]* CLKINP / 250) + * - where CLKINP is sys_clk in MHz + * Use CLKINP in KHz and adjust the denominator accordingly so + * that we have enough accuracy and at the same time no overflow + */ + params = get_usb_dpll_params(*dplls_data); + num = params->m * sys_clk_khz; + den = (params->n + 1) * 250 * 1000; + num += den - 1; + sd_div = num / den; + clrsetbits_le32((*prcm)->cm_clksel_dpll_usb, + CM_CLKSEL_DPLL_DPLL_SD_DIV_MASK, + sd_div << CM_CLKSEL_DPLL_DPLL_SD_DIV_SHIFT); + + /* Now setup the dpll with the regular function */ + do_setup_dpll((*prcm)->cm_clkmode_dpll_usb, params, DPLL_LOCK, "usb"); +} +#endif + +static void setup_dplls(void) +{ + u32 temp; + const struct dpll_params *params; + + debug("setup_dplls\n"); + + /* CORE dpll */ + params = get_core_dpll_params(*dplls_data); /* default - safest */ + /* + * Do not lock the core DPLL now. Just set it up. + * Core DPLL will be locked after setting up EMIF + * using the FREQ_UPDATE method(freq_update_core()) + */ + if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2) + do_setup_dpll((*prcm)->cm_clkmode_dpll_core, params, + DPLL_NO_LOCK, "core"); + else + do_setup_dpll((*prcm)->cm_clkmode_dpll_core, params, + DPLL_LOCK, "core"); + /* Set the ratios for CORE_CLK, L3_CLK, L4_CLK */ + temp = (CLKSEL_CORE_X2_DIV_1 << CLKSEL_CORE_SHIFT) | + (CLKSEL_L3_CORE_DIV_2 << CLKSEL_L3_SHIFT) | + (CLKSEL_L4_L3_DIV_2 << CLKSEL_L4_SHIFT); + writel(temp, (*prcm)->cm_clksel_core); + debug("Core DPLL configured\n"); + + /* lock PER dpll */ + params = get_per_dpll_params(*dplls_data); + do_setup_dpll((*prcm)->cm_clkmode_dpll_per, + params, DPLL_LOCK, "per"); + debug("PER DPLL locked\n"); + + /* MPU dpll */ + configure_mpu_dpll(); + +#if defined(CONFIG_USB_EHCI_OMAP) || defined(CONFIG_USB_XHCI_OMAP) + setup_usb_dpll(); +#endif + params = get_ddr_dpll_params(*dplls_data); + do_setup_dpll((*prcm)->cm_clkmode_dpll_ddrphy, + params, DPLL_LOCK, "ddr"); + +#ifdef CONFIG_DRIVER_TI_CPSW + params = get_gmac_dpll_params(*dplls_data); + do_setup_dpll((*prcm)->cm_clkmode_dpll_gmac, params, + DPLL_LOCK, "gmac"); +#endif +} + +u32 get_offset_code(u32 volt_offset, struct pmic_data *pmic) +{ + u32 offset_code; + + volt_offset -= pmic->base_offset; + + offset_code = (volt_offset + pmic->step - 1) / pmic->step; + + /* + * Offset codes 1-6 all give the base voltage in Palmas + * Offset code 0 switches OFF the SMPS + */ + return offset_code + pmic->start_code; +} + +void do_scale_vcore(u32 vcore_reg, u32 volt_mv, struct pmic_data *pmic) +{ + u32 offset_code; + u32 offset = volt_mv; + int ret = 0; + + if (!volt_mv) + return; + + pmic->pmic_bus_init(); + /* See if we can first get the GPIO if needed */ + if (pmic->gpio_en) + ret = gpio_request(pmic->gpio, "PMIC_GPIO"); + + if (ret < 0) { + printf("%s: gpio %d request failed %d\n", __func__, + pmic->gpio, ret); + return; + } + + /* Pull the GPIO low to select SET0 register, while we program SET1 */ + if (pmic->gpio_en) + gpio_direction_output(pmic->gpio, 0); + + /* convert to uV for better accuracy in the calculations */ + offset *= 1000; + + offset_code = get_offset_code(offset, pmic); + + debug("do_scale_vcore: volt - %d offset_code - 0x%x\n", volt_mv, + offset_code); + + if (pmic->pmic_write(pmic->i2c_slave_addr, vcore_reg, offset_code)) + printf("Scaling voltage failed for 0x%x\n", vcore_reg); + + if (pmic->gpio_en) + gpio_direction_output(pmic->gpio, 1); +} + +static u32 optimize_vcore_voltage(struct volts const *v) +{ + u32 val; + if (!v->value) + return 0; + if (!v->efuse.reg) + return v->value; + + switch (v->efuse.reg_bits) { + case 16: + val = readw(v->efuse.reg); + break; + case 32: + val = readl(v->efuse.reg); + break; + default: + printf("Error: efuse 0x%08x bits=%d unknown\n", + v->efuse.reg, v->efuse.reg_bits); + return v->value; + } + + if (!val) { + printf("Error: efuse 0x%08x bits=%d val=0, using %d\n", + v->efuse.reg, v->efuse.reg_bits, v->value); + return v->value; + } + + debug("%s:efuse 0x%08x bits=%d Vnom=%d, using efuse value %d\n", + __func__, v->efuse.reg, v->efuse.reg_bits, v->value, val); + return val; +} + +/* + * Setup the voltages for vdd_mpu, vdd_core, and vdd_iva + * We set the maximum voltages allowed here because Smart-Reflex is not + * enabled in bootloader. Voltage initialization in the kernel will set + * these to the nominal values after enabling Smart-Reflex + */ +void scale_vcores(struct vcores_data const *vcores) +{ + u32 val; + + val = optimize_vcore_voltage(&vcores->core); + do_scale_vcore(vcores->core.addr, val, vcores->core.pmic); + + val = optimize_vcore_voltage(&vcores->mpu); + do_scale_vcore(vcores->mpu.addr, val, vcores->mpu.pmic); + + /* Configure MPU ABB LDO after scale */ + abb_setup((*ctrl)->control_std_fuse_opp_vdd_mpu_2, + (*ctrl)->control_wkup_ldovbb_mpu_voltage_ctrl, + (*prcm)->prm_abbldo_mpu_setup, + (*prcm)->prm_abbldo_mpu_ctrl, + (*prcm)->prm_irqstatus_mpu_2, + OMAP_ABB_MPU_TXDONE_MASK, + OMAP_ABB_FAST_OPP); + + val = optimize_vcore_voltage(&vcores->mm); + do_scale_vcore(vcores->mm.addr, val, vcores->mm.pmic); + + val = optimize_vcore_voltage(&vcores->gpu); + do_scale_vcore(vcores->gpu.addr, val, vcores->gpu.pmic); + + val = optimize_vcore_voltage(&vcores->eve); + do_scale_vcore(vcores->eve.addr, val, vcores->eve.pmic); + + val = optimize_vcore_voltage(&vcores->iva); + do_scale_vcore(vcores->iva.addr, val, vcores->iva.pmic); +} + +static inline void enable_clock_domain(u32 const clkctrl_reg, u32 enable_mode) +{ + clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK, + enable_mode << CD_CLKCTRL_CLKTRCTRL_SHIFT); + debug("Enable clock domain - %x\n", clkctrl_reg); +} + +static inline void wait_for_clk_enable(u32 clkctrl_addr) +{ + u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED; + u32 bound = LDELAY; + + while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) || + (idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) { + + clkctrl = readl(clkctrl_addr); + idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >> + MODULE_CLKCTRL_IDLEST_SHIFT; + if (--bound == 0) { + printf("Clock enable failed for 0x%x idlest 0x%x\n", + clkctrl_addr, clkctrl); + return; + } + } +} + +static inline void enable_clock_module(u32 const clkctrl_addr, u32 enable_mode, + u32 wait_for_enable) +{ + clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK, + enable_mode << MODULE_CLKCTRL_MODULEMODE_SHIFT); + debug("Enable clock module - %x\n", clkctrl_addr); + if (wait_for_enable) + wait_for_clk_enable(clkctrl_addr); +} + +void freq_update_core(void) +{ + u32 freq_config1 = 0; + const struct dpll_params *core_dpll_params; + u32 omap_rev = omap_revision(); + + core_dpll_params = get_core_dpll_params(*dplls_data); + /* Put EMIF clock domain in sw wakeup mode */ + enable_clock_domain((*prcm)->cm_memif_clkstctrl, + CD_CLKCTRL_CLKTRCTRL_SW_WKUP); + wait_for_clk_enable((*prcm)->cm_memif_emif_1_clkctrl); + wait_for_clk_enable((*prcm)->cm_memif_emif_2_clkctrl); + + freq_config1 = SHADOW_FREQ_CONFIG1_FREQ_UPDATE_MASK | + SHADOW_FREQ_CONFIG1_DLL_RESET_MASK; + + freq_config1 |= (DPLL_EN_LOCK << SHADOW_FREQ_CONFIG1_DPLL_EN_SHIFT) & + SHADOW_FREQ_CONFIG1_DPLL_EN_MASK; + + freq_config1 |= (core_dpll_params->m2 << + SHADOW_FREQ_CONFIG1_M2_DIV_SHIFT) & + SHADOW_FREQ_CONFIG1_M2_DIV_MASK; + + writel(freq_config1, (*prcm)->cm_shadow_freq_config1); + if (!wait_on_value(SHADOW_FREQ_CONFIG1_FREQ_UPDATE_MASK, 0, + (u32 *) (*prcm)->cm_shadow_freq_config1, LDELAY)) { + puts("FREQ UPDATE procedure failed!!"); + hang(); + } + + /* + * Putting EMIF in HW_AUTO is seen to be causing issues with + * EMIF clocks and the master DLL. Keep EMIF in SW_WKUP + * in OMAP5430 ES1.0 silicon + */ + if (omap_rev != OMAP5430_ES1_0) { + /* Put EMIF clock domain back in hw auto mode */ + enable_clock_domain((*prcm)->cm_memif_clkstctrl, + CD_CLKCTRL_CLKTRCTRL_HW_AUTO); + wait_for_clk_enable((*prcm)->cm_memif_emif_1_clkctrl); + wait_for_clk_enable((*prcm)->cm_memif_emif_2_clkctrl); + } +} + +void bypass_dpll(u32 const base) +{ + do_bypass_dpll(base); + wait_for_bypass(base); +} + +void lock_dpll(u32 const base) +{ + do_lock_dpll(base); + wait_for_lock(base); +} + +void setup_clocks_for_console(void) +{ + /* Do not add any spl_debug prints in this function */ + clrsetbits_le32((*prcm)->cm_l4per_clkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, + CD_CLKCTRL_CLKTRCTRL_SW_WKUP << + CD_CLKCTRL_CLKTRCTRL_SHIFT); + + /* Enable all UARTs - console will be on one of them */ + clrsetbits_le32((*prcm)->cm_l4per_uart1_clkctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); + + clrsetbits_le32((*prcm)->cm_l4per_uart2_clkctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); + + clrsetbits_le32((*prcm)->cm_l4per_uart3_clkctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); + + clrsetbits_le32((*prcm)->cm_l4per_uart4_clkctrl, + MODULE_CLKCTRL_MODULEMODE_MASK, + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << + MODULE_CLKCTRL_MODULEMODE_SHIFT); + + clrsetbits_le32((*prcm)->cm_l4per_clkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, + CD_CLKCTRL_CLKTRCTRL_HW_AUTO << + CD_CLKCTRL_CLKTRCTRL_SHIFT); +} + +void do_enable_clocks(u32 const *clk_domains, + u32 const *clk_modules_hw_auto, + u32 const *clk_modules_explicit_en, + u8 wait_for_enable) +{ + u32 i, max = 100; + + /* Put the clock domains in SW_WKUP mode */ + for (i = 0; (i < max) && clk_domains[i]; i++) { + enable_clock_domain(clk_domains[i], + CD_CLKCTRL_CLKTRCTRL_SW_WKUP); + } + + /* Clock modules that need to be put in HW_AUTO */ + for (i = 0; (i < max) && clk_modules_hw_auto[i]; i++) { + enable_clock_module(clk_modules_hw_auto[i], + MODULE_CLKCTRL_MODULEMODE_HW_AUTO, + wait_for_enable); + }; + + /* Clock modules that need to be put in SW_EXPLICIT_EN mode */ + for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) { + enable_clock_module(clk_modules_explicit_en[i], + MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN, + wait_for_enable); + }; + + /* Put the clock domains in HW_AUTO mode now */ + for (i = 0; (i < max) && clk_domains[i]; i++) { + enable_clock_domain(clk_domains[i], + CD_CLKCTRL_CLKTRCTRL_HW_AUTO); + } +} + +void prcm_init(void) +{ + switch (omap_hw_init_context()) { + case OMAP_INIT_CONTEXT_SPL: + case OMAP_INIT_CONTEXT_UBOOT_FROM_NOR: + case OMAP_INIT_CONTEXT_UBOOT_AFTER_CH: + enable_basic_clocks(); + timer_init(); + scale_vcores(*omap_vcores); + setup_dplls(); + setup_warmreset_time(); + break; + default: + break; + } + + if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) + enable_basic_uboot_clocks(); +} + +void gpi2c_init(void) +{ + static int gpi2c = 1; + + if (gpi2c) { + i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, + CONFIG_SYS_OMAP24_I2C_SLAVE); + gpi2c = 0; + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/emif-common.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/emif-common.c new file mode 100644 index 000000000..429c4becf --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/emif-common.c @@ -0,0 +1,1392 @@ +/* + * EMIF programming + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/emif.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <asm/omap_common.h> +#include <asm/utils.h> +#include <linux/compiler.h> + +static int emif1_enabled = -1, emif2_enabled = -1; + +void set_lpmode_selfrefresh(u32 base) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + u32 reg; + + reg = readl(&emif->emif_pwr_mgmt_ctrl); + reg &= ~EMIF_REG_LP_MODE_MASK; + reg |= LP_MODE_SELF_REFRESH << EMIF_REG_LP_MODE_SHIFT; + reg &= ~EMIF_REG_SR_TIM_MASK; + writel(reg, &emif->emif_pwr_mgmt_ctrl); + + /* dummy read for the new SR_TIM to be loaded */ + readl(&emif->emif_pwr_mgmt_ctrl); +} + +void force_emif_self_refresh() +{ + set_lpmode_selfrefresh(EMIF1_BASE); + set_lpmode_selfrefresh(EMIF2_BASE); +} + +inline u32 emif_num(u32 base) +{ + if (base == EMIF1_BASE) + return 1; + else if (base == EMIF2_BASE) + return 2; + else + return 0; +} + +static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr) +{ + u32 mr; + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + mr_addr |= cs << EMIF_REG_CS_SHIFT; + writel(mr_addr, &emif->emif_lpddr2_mode_reg_cfg); + if (omap_revision() == OMAP4430_ES2_0) + mr = readl(&emif->emif_lpddr2_mode_reg_data_es2); + else + mr = readl(&emif->emif_lpddr2_mode_reg_data); + debug("get_mr: EMIF%d cs %d mr %08x val 0x%x\n", emif_num(base), + cs, mr_addr, mr); + if (((mr & 0x0000ff00) >> 8) == (mr & 0xff) && + ((mr & 0x00ff0000) >> 16) == (mr & 0xff) && + ((mr & 0xff000000) >> 24) == (mr & 0xff)) + return mr & 0xff; + else + return mr; +} + +static inline void set_mr(u32 base, u32 cs, u32 mr_addr, u32 mr_val) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + mr_addr |= cs << EMIF_REG_CS_SHIFT; + writel(mr_addr, &emif->emif_lpddr2_mode_reg_cfg); + writel(mr_val, &emif->emif_lpddr2_mode_reg_data); +} + +void emif_reset_phy(u32 base) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + u32 iodft; + + iodft = readl(&emif->emif_iodft_tlgc); + iodft |= EMIF_REG_RESET_PHY_MASK; + writel(iodft, &emif->emif_iodft_tlgc); +} + +static void do_lpddr2_init(u32 base, u32 cs) +{ + u32 mr_addr; + const struct lpddr2_mr_regs *mr_regs; + + get_lpddr2_mr_regs(&mr_regs); + /* Wait till device auto initialization is complete */ + while (get_mr(base, cs, LPDDR2_MR0) & LPDDR2_MR0_DAI_MASK) + ; + set_mr(base, cs, LPDDR2_MR10, mr_regs->mr10); + /* + * tZQINIT = 1 us + * Enough loops assuming a maximum of 2GHz + */ + + sdelay(2000); + + set_mr(base, cs, LPDDR2_MR1, mr_regs->mr1); + set_mr(base, cs, LPDDR2_MR16, mr_regs->mr16); + + /* + * Enable refresh along with writing MR2 + * Encoding of RL in MR2 is (RL - 2) + */ + mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK; + set_mr(base, cs, mr_addr, mr_regs->mr2); + + if (mr_regs->mr3 > 0) + set_mr(base, cs, LPDDR2_MR3, mr_regs->mr3); +} + +static void lpddr2_init(u32 base, const struct emif_regs *regs) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + /* Not NVM */ + clrbits_le32(&emif->emif_lpddr2_nvm_config, EMIF_REG_CS1NVMEN_MASK); + + /* + * Keep REG_INITREF_DIS = 1 to prevent re-initialization of SDRAM + * when EMIF_SDRAM_CONFIG register is written + */ + setbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_MASK); + + /* + * Set the SDRAM_CONFIG and PHY_CTRL for the + * un-locked frequency & default RL + */ + writel(regs->sdram_config_init, &emif->emif_sdram_config); + writel(regs->emif_ddr_phy_ctlr_1_init, &emif->emif_ddr_phy_ctrl_1); + + do_ext_phy_settings(base, regs); + + do_lpddr2_init(base, CS0); + if (regs->sdram_config & EMIF_REG_EBANK_MASK) + do_lpddr2_init(base, CS1); + + writel(regs->sdram_config, &emif->emif_sdram_config); + writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1); + + /* Enable refresh now */ + clrbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_MASK); + + } + +__weak void do_ext_phy_settings(u32 base, const struct emif_regs *regs) +{ +} + +void emif_update_timings(u32 base, const struct emif_regs *regs) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl_shdw); + writel(regs->sdram_tim1, &emif->emif_sdram_tim_1_shdw); + writel(regs->sdram_tim2, &emif->emif_sdram_tim_2_shdw); + writel(regs->sdram_tim3, &emif->emif_sdram_tim_3_shdw); + if (omap_revision() == OMAP4430_ES1_0) { + /* ES1 bug EMIF should be in force idle during freq_update */ + writel(0, &emif->emif_pwr_mgmt_ctrl); + } else { + writel(EMIF_PWR_MGMT_CTRL, &emif->emif_pwr_mgmt_ctrl); + writel(EMIF_PWR_MGMT_CTRL_SHDW, &emif->emif_pwr_mgmt_ctrl_shdw); + } + writel(regs->read_idle_ctrl, &emif->emif_read_idlectrl_shdw); + writel(regs->zq_config, &emif->emif_zq_config); + writel(regs->temp_alert_config, &emif->emif_temp_alert_config); + writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1_shdw); + + if ((omap_revision() >= OMAP5430_ES1_0) || is_dra7xx()) { + writel(EMIF_L3_CONFIG_VAL_SYS_10_MPU_5_LL_0, + &emif->emif_l3_config); + } else if (omap_revision() >= OMAP4460_ES1_0) { + writel(EMIF_L3_CONFIG_VAL_SYS_10_MPU_3_LL_0, + &emif->emif_l3_config); + } else { + writel(EMIF_L3_CONFIG_VAL_SYS_10_LL_0, + &emif->emif_l3_config); + } +} + +static void omap5_ddr3_leveling(u32 base, const struct emif_regs *regs) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + /* keep sdram in self-refresh */ + writel(((LP_MODE_SELF_REFRESH << EMIF_REG_LP_MODE_SHIFT) + & EMIF_REG_LP_MODE_MASK), &emif->emif_pwr_mgmt_ctrl); + __udelay(130); + + /* + * Set invert_clkout (if activated)--DDR_PHYCTRL_1 + * Invert clock adds an additional half cycle delay on the + * command interface. The additional half cycle, is usually + * meant to enable leveling in the situation that DQS is later + * than CK on the board.It also helps provide some additional + * margin for leveling. + */ + writel(regs->emif_ddr_phy_ctlr_1, + &emif->emif_ddr_phy_ctrl_1); + + writel(regs->emif_ddr_phy_ctlr_1, + &emif->emif_ddr_phy_ctrl_1_shdw); + __udelay(130); + + writel(((LP_MODE_DISABLE << EMIF_REG_LP_MODE_SHIFT) + & EMIF_REG_LP_MODE_MASK), &emif->emif_pwr_mgmt_ctrl); + + /* Launch Full leveling */ + writel(DDR3_FULL_LVL, &emif->emif_rd_wr_lvl_ctl); + + /* Wait till full leveling is complete */ + readl(&emif->emif_rd_wr_lvl_ctl); + __udelay(130); + + /* Read data eye leveling no of samples */ + config_data_eye_leveling_samples(base); + + /* + * Launch 8 incremental WR_LVL- to compensate for + * PHY limitation. + */ + writel(0x2 << EMIF_REG_WRLVLINC_INT_SHIFT, + &emif->emif_rd_wr_lvl_ctl); + + __udelay(130); + + /* Launch Incremental leveling */ + writel(DDR3_INC_LVL, &emif->emif_rd_wr_lvl_ctl); + __udelay(130); +} + +static void dra7_ddr3_leveling(u32 base, const struct emif_regs *regs) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + u32 fifo_reg; + + fifo_reg = readl(&emif->emif_ddr_fifo_misaligned_clear_1); + writel(fifo_reg | 0x00000100, + &emif->emif_ddr_fifo_misaligned_clear_1); + + fifo_reg = readl(&emif->emif_ddr_fifo_misaligned_clear_2); + writel(fifo_reg | 0x00000100, + &emif->emif_ddr_fifo_misaligned_clear_2); + + /* Launch Full leveling */ + writel(DDR3_FULL_LVL, &emif->emif_rd_wr_lvl_ctl); + + /* Wait till full leveling is complete */ + readl(&emif->emif_rd_wr_lvl_ctl); + __udelay(130); + + /* Read data eye leveling no of samples */ + config_data_eye_leveling_samples(base); + + /* + * Disable leveling. This is because if leveling is kept + * enabled, then PHY triggers a false leveling during + * EMIF-idle scenario which results in wrong delay + * values getting updated. After this the EMIF becomes + * unaccessible. So disable it after the first time + */ + writel(0x0, &emif->emif_rd_wr_lvl_rmp_ctl); +} + +static void ddr3_leveling(u32 base, const struct emif_regs *regs) +{ + if (is_omap54xx()) + omap5_ddr3_leveling(base, regs); + else + dra7_ddr3_leveling(base, regs); +} + +static void ddr3_init(u32 base, const struct emif_regs *regs) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + /* + * Set SDRAM_CONFIG and PHY control registers to locked frequency + * and RL =7. As the default values of the Mode Registers are not + * defined, contents of mode Registers must be fully initialized. + * H/W takes care of this initialization + */ + writel(regs->emif_ddr_phy_ctlr_1_init, &emif->emif_ddr_phy_ctrl_1); + + /* Update timing registers */ + writel(regs->sdram_tim1, &emif->emif_sdram_tim_1); + writel(regs->sdram_tim2, &emif->emif_sdram_tim_2); + writel(regs->sdram_tim3, &emif->emif_sdram_tim_3); + + writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl); + writel(regs->read_idle_ctrl, &emif->emif_read_idlectrl); + + /* + * The same sequence should work on OMAP5432 as well. But strange that + * it is not working + */ + if (is_dra7xx()) { + do_ext_phy_settings(base, regs); + writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config); + writel(regs->sdram_config_init, &emif->emif_sdram_config); + } else { + writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config); + writel(regs->sdram_config_init, &emif->emif_sdram_config); + do_ext_phy_settings(base, regs); + } + + /* enable leveling */ + writel(regs->emif_rd_wr_lvl_rmp_ctl, &emif->emif_rd_wr_lvl_rmp_ctl); + + ddr3_leveling(base, regs); +} + +#ifndef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS +#define print_timing_reg(reg) debug(#reg" - 0x%08x\n", (reg)) + +/* + * Organization and refresh requirements for LPDDR2 devices of different + * types and densities. Derived from JESD209-2 section 2.4 + */ +const struct lpddr2_addressing addressing_table[] = { + /* Banks tREFIx10 rowx32,rowx16 colx32,colx16 density */ + {BANKS4, T_REFI_15_6, {ROW_12, ROW_12}, {COL_7, COL_8} },/*64M */ + {BANKS4, T_REFI_15_6, {ROW_12, ROW_12}, {COL_8, COL_9} },/*128M */ + {BANKS4, T_REFI_7_8, {ROW_13, ROW_13}, {COL_8, COL_9} },/*256M */ + {BANKS4, T_REFI_7_8, {ROW_13, ROW_13}, {COL_9, COL_10} },/*512M */ + {BANKS8, T_REFI_7_8, {ROW_13, ROW_13}, {COL_9, COL_10} },/*1GS4 */ + {BANKS8, T_REFI_3_9, {ROW_14, ROW_14}, {COL_9, COL_10} },/*2GS4 */ + {BANKS8, T_REFI_3_9, {ROW_14, ROW_14}, {COL_10, COL_11} },/*4G */ + {BANKS8, T_REFI_3_9, {ROW_15, ROW_15}, {COL_10, COL_11} },/*8G */ + {BANKS4, T_REFI_7_8, {ROW_14, ROW_14}, {COL_9, COL_10} },/*1GS2 */ + {BANKS4, T_REFI_3_9, {ROW_15, ROW_15}, {COL_9, COL_10} },/*2GS2 */ +}; + +static const u32 lpddr2_density_2_size_in_mbytes[] = { + 8, /* 64Mb */ + 16, /* 128Mb */ + 32, /* 256Mb */ + 64, /* 512Mb */ + 128, /* 1Gb */ + 256, /* 2Gb */ + 512, /* 4Gb */ + 1024, /* 8Gb */ + 2048, /* 16Gb */ + 4096 /* 32Gb */ +}; + +/* + * Calculate the period of DDR clock from frequency value and set the + * denominator and numerator in global variables for easy access later + */ +static void set_ddr_clk_period(u32 freq) +{ + /* + * period = 1/freq + * period_in_ns = 10^9/freq + */ + *T_num = 1000000000; + *T_den = freq; + cancel_out(T_num, T_den, 200); + +} + +/* + * Convert time in nano seconds to number of cycles of DDR clock + */ +static inline u32 ns_2_cycles(u32 ns) +{ + return ((ns * (*T_den)) + (*T_num) - 1) / (*T_num); +} + +/* + * ns_2_cycles with the difference that the time passed is 2 times the actual + * value(to avoid fractions). The cycles returned is for the original value of + * the timing parameter + */ +static inline u32 ns_x2_2_cycles(u32 ns) +{ + return ((ns * (*T_den)) + (*T_num) * 2 - 1) / ((*T_num) * 2); +} + +/* + * Find addressing table index based on the device's type(S2 or S4) and + * density + */ +s8 addressing_table_index(u8 type, u8 density, u8 width) +{ + u8 index; + if ((density > LPDDR2_DENSITY_8Gb) || (width == LPDDR2_IO_WIDTH_8)) + return -1; + + /* + * Look at the way ADDR_TABLE_INDEX* values have been defined + * in emif.h compared to LPDDR2_DENSITY_* values + * The table is layed out in the increasing order of density + * (ignoring type). The exceptions 1GS2 and 2GS2 have been placed + * at the end + */ + if ((type == LPDDR2_TYPE_S2) && (density == LPDDR2_DENSITY_1Gb)) + index = ADDR_TABLE_INDEX1GS2; + else if ((type == LPDDR2_TYPE_S2) && (density == LPDDR2_DENSITY_2Gb)) + index = ADDR_TABLE_INDEX2GS2; + else + index = density; + + debug("emif: addressing table index %d\n", index); + + return index; +} + +/* + * Find the the right timing table from the array of timing + * tables of the device using DDR clock frequency + */ +static const struct lpddr2_ac_timings *get_timings_table(const struct + lpddr2_ac_timings const *const *device_timings, + u32 freq) +{ + u32 i, temp, freq_nearest; + const struct lpddr2_ac_timings *timings = 0; + + emif_assert(freq <= MAX_LPDDR2_FREQ); + emif_assert(device_timings); + + /* + * Start with the maximum allowed frequency - that is always safe + */ + freq_nearest = MAX_LPDDR2_FREQ; + /* + * Find the timings table that has the max frequency value: + * i. Above or equal to the DDR frequency - safe + * ii. The lowest that satisfies condition (i) - optimal + */ + for (i = 0; (i < MAX_NUM_SPEEDBINS) && device_timings[i]; i++) { + temp = device_timings[i]->max_freq; + if ((temp >= freq) && (temp <= freq_nearest)) { + freq_nearest = temp; + timings = device_timings[i]; + } + } + debug("emif: timings table: %d\n", freq_nearest); + return timings; +} + +/* + * Finds the value of emif_sdram_config_reg + * All parameters are programmed based on the device on CS0. + * If there is a device on CS1, it will be same as that on CS0 or + * it will be NVM. We don't support NVM yet. + * If cs1_device pointer is NULL it is assumed that there is no device + * on CS1 + */ +static u32 get_sdram_config_reg(const struct lpddr2_device_details *cs0_device, + const struct lpddr2_device_details *cs1_device, + const struct lpddr2_addressing *addressing, + u8 RL) +{ + u32 config_reg = 0; + + config_reg |= (cs0_device->type + 4) << EMIF_REG_SDRAM_TYPE_SHIFT; + config_reg |= EMIF_INTERLEAVING_POLICY_MAX_INTERLEAVING << + EMIF_REG_IBANK_POS_SHIFT; + + config_reg |= cs0_device->io_width << EMIF_REG_NARROW_MODE_SHIFT; + + config_reg |= RL << EMIF_REG_CL_SHIFT; + + config_reg |= addressing->row_sz[cs0_device->io_width] << + EMIF_REG_ROWSIZE_SHIFT; + + config_reg |= addressing->num_banks << EMIF_REG_IBANK_SHIFT; + + config_reg |= (cs1_device ? EBANK_CS1_EN : EBANK_CS1_DIS) << + EMIF_REG_EBANK_SHIFT; + + config_reg |= addressing->col_sz[cs0_device->io_width] << + EMIF_REG_PAGESIZE_SHIFT; + + return config_reg; +} + +static u32 get_sdram_ref_ctrl(u32 freq, + const struct lpddr2_addressing *addressing) +{ + u32 ref_ctrl = 0, val = 0, freq_khz; + freq_khz = freq / 1000; + /* + * refresh rate to be set is 'tREFI * freq in MHz + * division by 10000 to account for khz and x10 in t_REFI_us_x10 + */ + val = addressing->t_REFI_us_x10 * freq_khz / 10000; + ref_ctrl |= val << EMIF_REG_REFRESH_RATE_SHIFT; + + return ref_ctrl; +} + +static u32 get_sdram_tim_1_reg(const struct lpddr2_ac_timings *timings, + const struct lpddr2_min_tck *min_tck, + const struct lpddr2_addressing *addressing) +{ + u32 tim1 = 0, val = 0; + val = max(min_tck->tWTR, ns_x2_2_cycles(timings->tWTRx2)) - 1; + tim1 |= val << EMIF_REG_T_WTR_SHIFT; + + if (addressing->num_banks == BANKS8) + val = (timings->tFAW * (*T_den) + 4 * (*T_num) - 1) / + (4 * (*T_num)) - 1; + else + val = max(min_tck->tRRD, ns_2_cycles(timings->tRRD)) - 1; + + tim1 |= val << EMIF_REG_T_RRD_SHIFT; + + val = ns_2_cycles(timings->tRASmin + timings->tRPab) - 1; + tim1 |= val << EMIF_REG_T_RC_SHIFT; + + val = max(min_tck->tRAS_MIN, ns_2_cycles(timings->tRASmin)) - 1; + tim1 |= val << EMIF_REG_T_RAS_SHIFT; + + val = max(min_tck->tWR, ns_2_cycles(timings->tWR)) - 1; + tim1 |= val << EMIF_REG_T_WR_SHIFT; + + val = max(min_tck->tRCD, ns_2_cycles(timings->tRCD)) - 1; + tim1 |= val << EMIF_REG_T_RCD_SHIFT; + + val = max(min_tck->tRP_AB, ns_2_cycles(timings->tRPab)) - 1; + tim1 |= val << EMIF_REG_T_RP_SHIFT; + + return tim1; +} + +static u32 get_sdram_tim_2_reg(const struct lpddr2_ac_timings *timings, + const struct lpddr2_min_tck *min_tck) +{ + u32 tim2 = 0, val = 0; + val = max(min_tck->tCKE, timings->tCKE) - 1; + tim2 |= val << EMIF_REG_T_CKE_SHIFT; + + val = max(min_tck->tRTP, ns_x2_2_cycles(timings->tRTPx2)) - 1; + tim2 |= val << EMIF_REG_T_RTP_SHIFT; + + /* + * tXSRD = tRFCab + 10 ns. XSRD and XSNR should have the + * same value + */ + val = ns_2_cycles(timings->tXSR) - 1; + tim2 |= val << EMIF_REG_T_XSRD_SHIFT; + tim2 |= val << EMIF_REG_T_XSNR_SHIFT; + + val = max(min_tck->tXP, ns_x2_2_cycles(timings->tXPx2)) - 1; + tim2 |= val << EMIF_REG_T_XP_SHIFT; + + return tim2; +} + +static u32 get_sdram_tim_3_reg(const struct lpddr2_ac_timings *timings, + const struct lpddr2_min_tck *min_tck, + const struct lpddr2_addressing *addressing) +{ + u32 tim3 = 0, val = 0; + val = min(timings->tRASmax * 10 / addressing->t_REFI_us_x10 - 1, 0xF); + tim3 |= val << EMIF_REG_T_RAS_MAX_SHIFT; + + val = ns_2_cycles(timings->tRFCab) - 1; + tim3 |= val << EMIF_REG_T_RFC_SHIFT; + + val = ns_x2_2_cycles(timings->tDQSCKMAXx2) - 1; + tim3 |= val << EMIF_REG_T_TDQSCKMAX_SHIFT; + + val = ns_2_cycles(timings->tZQCS) - 1; + tim3 |= val << EMIF_REG_ZQ_ZQCS_SHIFT; + + val = max(min_tck->tCKESR, ns_2_cycles(timings->tCKESR)) - 1; + tim3 |= val << EMIF_REG_T_CKESR_SHIFT; + + return tim3; +} + +static u32 get_zq_config_reg(const struct lpddr2_device_details *cs1_device, + const struct lpddr2_addressing *addressing, + u8 volt_ramp) +{ + u32 zq = 0, val = 0; + if (volt_ramp) + val = + EMIF_ZQCS_INTERVAL_DVFS_IN_US * 10 / + addressing->t_REFI_us_x10; + else + val = + EMIF_ZQCS_INTERVAL_NORMAL_IN_US * 10 / + addressing->t_REFI_us_x10; + zq |= val << EMIF_REG_ZQ_REFINTERVAL_SHIFT; + + zq |= (REG_ZQ_ZQCL_MULT - 1) << EMIF_REG_ZQ_ZQCL_MULT_SHIFT; + + zq |= (REG_ZQ_ZQINIT_MULT - 1) << EMIF_REG_ZQ_ZQINIT_MULT_SHIFT; + + zq |= REG_ZQ_SFEXITEN_ENABLE << EMIF_REG_ZQ_SFEXITEN_SHIFT; + + /* + * Assuming that two chipselects have a single calibration resistor + * If there are indeed two calibration resistors, then this flag should + * be enabled to take advantage of dual calibration feature. + * This data should ideally come from board files. But considering + * that none of the boards today have calibration resistors per CS, + * it would be an unnecessary overhead. + */ + zq |= REG_ZQ_DUALCALEN_DISABLE << EMIF_REG_ZQ_DUALCALEN_SHIFT; + + zq |= REG_ZQ_CS0EN_ENABLE << EMIF_REG_ZQ_CS0EN_SHIFT; + + zq |= (cs1_device ? 1 : 0) << EMIF_REG_ZQ_CS1EN_SHIFT; + + return zq; +} + +static u32 get_temp_alert_config(const struct lpddr2_device_details *cs1_device, + const struct lpddr2_addressing *addressing, + u8 is_derated) +{ + u32 alert = 0, interval; + interval = + TEMP_ALERT_POLL_INTERVAL_MS * 10000 / addressing->t_REFI_us_x10; + if (is_derated) + interval *= 4; + alert |= interval << EMIF_REG_TA_REFINTERVAL_SHIFT; + + alert |= TEMP_ALERT_CONFIG_DEVCT_1 << EMIF_REG_TA_DEVCNT_SHIFT; + + alert |= TEMP_ALERT_CONFIG_DEVWDT_32 << EMIF_REG_TA_DEVWDT_SHIFT; + + alert |= 1 << EMIF_REG_TA_SFEXITEN_SHIFT; + + alert |= 1 << EMIF_REG_TA_CS0EN_SHIFT; + + alert |= (cs1_device ? 1 : 0) << EMIF_REG_TA_CS1EN_SHIFT; + + return alert; +} + +static u32 get_read_idle_ctrl_reg(u8 volt_ramp) +{ + u32 idle = 0, val = 0; + if (volt_ramp) + val = ns_2_cycles(READ_IDLE_INTERVAL_DVFS) / 64 - 1; + else + /*Maximum value in normal conditions - suggested by hw team */ + val = 0x1FF; + idle |= val << EMIF_REG_READ_IDLE_INTERVAL_SHIFT; + + idle |= EMIF_REG_READ_IDLE_LEN_VAL << EMIF_REG_READ_IDLE_LEN_SHIFT; + + return idle; +} + +static u32 get_ddr_phy_ctrl_1(u32 freq, u8 RL) +{ + u32 phy = 0, val = 0; + + phy |= (RL + 2) << EMIF_REG_READ_LATENCY_SHIFT; + + if (freq <= 100000000) + val = EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS; + else if (freq <= 200000000) + val = EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ; + else + val = EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ; + phy |= val << EMIF_REG_DLL_SLAVE_DLY_CTRL_SHIFT; + + /* Other fields are constant magic values. Hardcode them together */ + phy |= EMIF_DDR_PHY_CTRL_1_BASE_VAL << + EMIF_EMIF_DDR_PHY_CTRL_1_BASE_VAL_SHIFT; + + return phy; +} + +static u32 get_emif_mem_size(u32 base) +{ + u32 size_mbytes = 0, temp; + struct emif_device_details dev_details; + struct lpddr2_device_details cs0_dev_details, cs1_dev_details; + u32 emif_nr = emif_num(base); + + emif_reset_phy(base); + dev_details.cs0_device_details = emif_get_device_details(emif_nr, CS0, + &cs0_dev_details); + dev_details.cs1_device_details = emif_get_device_details(emif_nr, CS1, + &cs1_dev_details); + emif_reset_phy(base); + + if (dev_details.cs0_device_details) { + temp = dev_details.cs0_device_details->density; + size_mbytes += lpddr2_density_2_size_in_mbytes[temp]; + } + + if (dev_details.cs1_device_details) { + temp = dev_details.cs1_device_details->density; + size_mbytes += lpddr2_density_2_size_in_mbytes[temp]; + } + /* convert to bytes */ + return size_mbytes << 20; +} + +/* Gets the encoding corresponding to a given DMM section size */ +u32 get_dmm_section_size_map(u32 section_size) +{ + /* + * Section size mapping: + * 0x0: 16-MiB section + * 0x1: 32-MiB section + * 0x2: 64-MiB section + * 0x3: 128-MiB section + * 0x4: 256-MiB section + * 0x5: 512-MiB section + * 0x6: 1-GiB section + * 0x7: 2-GiB section + */ + section_size >>= 24; /* divide by 16 MB */ + return log_2_n_round_down(section_size); +} + +static void emif_calculate_regs( + const struct emif_device_details *emif_dev_details, + u32 freq, struct emif_regs *regs) +{ + u32 temp, sys_freq; + const struct lpddr2_addressing *addressing; + const struct lpddr2_ac_timings *timings; + const struct lpddr2_min_tck *min_tck; + const struct lpddr2_device_details *cs0_dev_details = + emif_dev_details->cs0_device_details; + const struct lpddr2_device_details *cs1_dev_details = + emif_dev_details->cs1_device_details; + const struct lpddr2_device_timings *cs0_dev_timings = + emif_dev_details->cs0_device_timings; + + emif_assert(emif_dev_details); + emif_assert(regs); + /* + * You can not have a device on CS1 without one on CS0 + * So configuring EMIF without a device on CS0 doesn't + * make sense + */ + emif_assert(cs0_dev_details); + emif_assert(cs0_dev_details->type != LPDDR2_TYPE_NVM); + /* + * If there is a device on CS1 it should be same type as CS0 + * (or NVM. But NVM is not supported in this driver yet) + */ + emif_assert((cs1_dev_details == NULL) || + (cs1_dev_details->type == LPDDR2_TYPE_NVM) || + (cs0_dev_details->type == cs1_dev_details->type)); + emif_assert(freq <= MAX_LPDDR2_FREQ); + + set_ddr_clk_period(freq); + + /* + * The device on CS0 is used for all timing calculations + * There is only one set of registers for timings per EMIF. So, if the + * second CS(CS1) has a device, it should have the same timings as the + * device on CS0 + */ + timings = get_timings_table(cs0_dev_timings->ac_timings, freq); + emif_assert(timings); + min_tck = cs0_dev_timings->min_tck; + + temp = addressing_table_index(cs0_dev_details->type, + cs0_dev_details->density, + cs0_dev_details->io_width); + + emif_assert((temp >= 0)); + addressing = &(addressing_table[temp]); + emif_assert(addressing); + + sys_freq = get_sys_clk_freq(); + + regs->sdram_config_init = get_sdram_config_reg(cs0_dev_details, + cs1_dev_details, + addressing, RL_BOOT); + + regs->sdram_config = get_sdram_config_reg(cs0_dev_details, + cs1_dev_details, + addressing, RL_FINAL); + + regs->ref_ctrl = get_sdram_ref_ctrl(freq, addressing); + + regs->sdram_tim1 = get_sdram_tim_1_reg(timings, min_tck, addressing); + + regs->sdram_tim2 = get_sdram_tim_2_reg(timings, min_tck); + + regs->sdram_tim3 = get_sdram_tim_3_reg(timings, min_tck, addressing); + + regs->read_idle_ctrl = get_read_idle_ctrl_reg(LPDDR2_VOLTAGE_STABLE); + + regs->temp_alert_config = + get_temp_alert_config(cs1_dev_details, addressing, 0); + + regs->zq_config = get_zq_config_reg(cs1_dev_details, addressing, + LPDDR2_VOLTAGE_STABLE); + + regs->emif_ddr_phy_ctlr_1_init = + get_ddr_phy_ctrl_1(sys_freq / 2, RL_BOOT); + + regs->emif_ddr_phy_ctlr_1 = + get_ddr_phy_ctrl_1(freq, RL_FINAL); + + regs->freq = freq; + + print_timing_reg(regs->sdram_config_init); + print_timing_reg(regs->sdram_config); + print_timing_reg(regs->ref_ctrl); + print_timing_reg(regs->sdram_tim1); + print_timing_reg(regs->sdram_tim2); + print_timing_reg(regs->sdram_tim3); + print_timing_reg(regs->read_idle_ctrl); + print_timing_reg(regs->temp_alert_config); + print_timing_reg(regs->zq_config); + print_timing_reg(regs->emif_ddr_phy_ctlr_1); + print_timing_reg(regs->emif_ddr_phy_ctlr_1_init); +} +#endif /* CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS */ + +#ifdef CONFIG_SYS_AUTOMATIC_SDRAM_DETECTION +const char *get_lpddr2_type(u8 type_id) +{ + switch (type_id) { + case LPDDR2_TYPE_S4: + return "LPDDR2-S4"; + case LPDDR2_TYPE_S2: + return "LPDDR2-S2"; + default: + return NULL; + } +} + +const char *get_lpddr2_io_width(u8 width_id) +{ + switch (width_id) { + case LPDDR2_IO_WIDTH_8: + return "x8"; + case LPDDR2_IO_WIDTH_16: + return "x16"; + case LPDDR2_IO_WIDTH_32: + return "x32"; + default: + return NULL; + } +} + +const char *get_lpddr2_manufacturer(u32 manufacturer) +{ + switch (manufacturer) { + case LPDDR2_MANUFACTURER_SAMSUNG: + return "Samsung"; + case LPDDR2_MANUFACTURER_QIMONDA: + return "Qimonda"; + case LPDDR2_MANUFACTURER_ELPIDA: + return "Elpida"; + case LPDDR2_MANUFACTURER_ETRON: + return "Etron"; + case LPDDR2_MANUFACTURER_NANYA: + return "Nanya"; + case LPDDR2_MANUFACTURER_HYNIX: + return "Hynix"; + case LPDDR2_MANUFACTURER_MOSEL: + return "Mosel"; + case LPDDR2_MANUFACTURER_WINBOND: + return "Winbond"; + case LPDDR2_MANUFACTURER_ESMT: + return "ESMT"; + case LPDDR2_MANUFACTURER_SPANSION: + return "Spansion"; + case LPDDR2_MANUFACTURER_SST: + return "SST"; + case LPDDR2_MANUFACTURER_ZMOS: + return "ZMOS"; + case LPDDR2_MANUFACTURER_INTEL: + return "Intel"; + case LPDDR2_MANUFACTURER_NUMONYX: + return "Numonyx"; + case LPDDR2_MANUFACTURER_MICRON: + return "Micron"; + default: + return NULL; + } +} + +static void display_sdram_details(u32 emif_nr, u32 cs, + struct lpddr2_device_details *device) +{ + const char *mfg_str; + const char *type_str; + char density_str[10]; + u32 density; + + debug("EMIF%d CS%d\t", emif_nr, cs); + + if (!device) { + debug("None\n"); + return; + } + + mfg_str = get_lpddr2_manufacturer(device->manufacturer); + type_str = get_lpddr2_type(device->type); + + density = lpddr2_density_2_size_in_mbytes[device->density]; + if ((density / 1024 * 1024) == density) { + density /= 1024; + sprintf(density_str, "%d GB", density); + } else + sprintf(density_str, "%d MB", density); + if (mfg_str && type_str) + debug("%s\t\t%s\t%s\n", mfg_str, type_str, density_str); +} + +static u8 is_lpddr2_sdram_present(u32 base, u32 cs, + struct lpddr2_device_details *lpddr2_device) +{ + u32 mr = 0, temp; + + mr = get_mr(base, cs, LPDDR2_MR0); + if (mr > 0xFF) { + /* Mode register value bigger than 8 bit */ + return 0; + } + + temp = (mr & LPDDR2_MR0_DI_MASK) >> LPDDR2_MR0_DI_SHIFT; + if (temp) { + /* Not SDRAM */ + return 0; + } + temp = (mr & LPDDR2_MR0_DNVI_MASK) >> LPDDR2_MR0_DNVI_SHIFT; + + if (temp) { + /* DNV supported - But DNV is only supported for NVM */ + return 0; + } + + mr = get_mr(base, cs, LPDDR2_MR4); + if (mr > 0xFF) { + /* Mode register value bigger than 8 bit */ + return 0; + } + + mr = get_mr(base, cs, LPDDR2_MR5); + if (mr > 0xFF) { + /* Mode register value bigger than 8 bit */ + return 0; + } + + if (!get_lpddr2_manufacturer(mr)) { + /* Manufacturer not identified */ + return 0; + } + lpddr2_device->manufacturer = mr; + + mr = get_mr(base, cs, LPDDR2_MR6); + if (mr >= 0xFF) { + /* Mode register value bigger than 8 bit */ + return 0; + } + + mr = get_mr(base, cs, LPDDR2_MR7); + if (mr >= 0xFF) { + /* Mode register value bigger than 8 bit */ + return 0; + } + + mr = get_mr(base, cs, LPDDR2_MR8); + if (mr >= 0xFF) { + /* Mode register value bigger than 8 bit */ + return 0; + } + + temp = (mr & MR8_TYPE_MASK) >> MR8_TYPE_SHIFT; + if (!get_lpddr2_type(temp)) { + /* Not SDRAM */ + return 0; + } + lpddr2_device->type = temp; + + temp = (mr & MR8_DENSITY_MASK) >> MR8_DENSITY_SHIFT; + if (temp > LPDDR2_DENSITY_32Gb) { + /* Density not supported */ + return 0; + } + lpddr2_device->density = temp; + + temp = (mr & MR8_IO_WIDTH_MASK) >> MR8_IO_WIDTH_SHIFT; + if (!get_lpddr2_io_width(temp)) { + /* IO width unsupported value */ + return 0; + } + lpddr2_device->io_width = temp; + + /* + * If all the above tests pass we should + * have a device on this chip-select + */ + return 1; +} + +struct lpddr2_device_details *emif_get_device_details(u32 emif_nr, u8 cs, + struct lpddr2_device_details *lpddr2_dev_details) +{ + u32 phy; + u32 base = (emif_nr == 1) ? EMIF1_BASE : EMIF2_BASE; + + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + if (!lpddr2_dev_details) + return NULL; + + /* Do the minimum init for mode register accesses */ + if (!(running_from_sdram() || warm_reset())) { + phy = get_ddr_phy_ctrl_1(get_sys_clk_freq() / 2, RL_BOOT); + writel(phy, &emif->emif_ddr_phy_ctrl_1); + } + + if (!(is_lpddr2_sdram_present(base, cs, lpddr2_dev_details))) + return NULL; + + display_sdram_details(emif_num(base), cs, lpddr2_dev_details); + + return lpddr2_dev_details; +} +#endif /* CONFIG_SYS_AUTOMATIC_SDRAM_DETECTION */ + +static void do_sdram_init(u32 base) +{ + const struct emif_regs *regs; + u32 in_sdram, emif_nr; + + debug(">>do_sdram_init() %x\n", base); + + in_sdram = running_from_sdram(); + emif_nr = (base == EMIF1_BASE) ? 1 : 2; + +#ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS + emif_get_reg_dump(emif_nr, ®s); + if (!regs) { + debug("EMIF: reg dump not provided\n"); + return; + } +#else + /* + * The user has not provided the register values. We need to + * calculate it based on the timings and the DDR frequency + */ + struct emif_device_details dev_details; + struct emif_regs calculated_regs; + + /* + * Get device details: + * - Discovered if CONFIG_SYS_AUTOMATIC_SDRAM_DETECTION is set + * - Obtained from user otherwise + */ + struct lpddr2_device_details cs0_dev_details, cs1_dev_details; + emif_reset_phy(base); + dev_details.cs0_device_details = emif_get_device_details(emif_nr, CS0, + &cs0_dev_details); + dev_details.cs1_device_details = emif_get_device_details(emif_nr, CS1, + &cs1_dev_details); + emif_reset_phy(base); + + /* Return if no devices on this EMIF */ + if (!dev_details.cs0_device_details && + !dev_details.cs1_device_details) { + return; + } + + /* + * Get device timings: + * - Default timings specified by JESD209-2 if + * CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS is set + * - Obtained from user otherwise + */ + emif_get_device_timings(emif_nr, &dev_details.cs0_device_timings, + &dev_details.cs1_device_timings); + + /* Calculate the register values */ + emif_calculate_regs(&dev_details, omap_ddr_clk(), &calculated_regs); + regs = &calculated_regs; +#endif /* CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS */ + + /* + * Initializing the LPDDR2 device can not happen from SDRAM. + * Changing the timing registers in EMIF can happen(going from one + * OPP to another) + */ + if (!(in_sdram || warm_reset())) { + if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2) + lpddr2_init(base, regs); + else + ddr3_init(base, regs); + } + if (warm_reset() && (emif_sdram_type() == EMIF_SDRAM_TYPE_DDR3)) { + set_lpmode_selfrefresh(base); + emif_reset_phy(base); + ddr3_leveling(base, regs); + } + + /* Write to the shadow registers */ + emif_update_timings(base, regs); + + debug("<<do_sdram_init() %x\n", base); +} + +void emif_post_init_config(u32 base) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + u32 omap_rev = omap_revision(); + + /* reset phy on ES2.0 */ + if (omap_rev == OMAP4430_ES2_0) + emif_reset_phy(base); + + /* Put EMIF back in smart idle on ES1.0 */ + if (omap_rev == OMAP4430_ES1_0) + writel(0x80000000, &emif->emif_pwr_mgmt_ctrl); +} + +void dmm_init(u32 base) +{ + const struct dmm_lisa_map_regs *lisa_map_regs; + u32 i, section, valid; + +#ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS + emif_get_dmm_regs(&lisa_map_regs); +#else + u32 emif1_size, emif2_size, mapped_size, section_map = 0; + u32 section_cnt, sys_addr; + struct dmm_lisa_map_regs lis_map_regs_calculated = {0}; + + mapped_size = 0; + section_cnt = 3; + sys_addr = CONFIG_SYS_SDRAM_BASE; + emif1_size = get_emif_mem_size(EMIF1_BASE); + emif2_size = get_emif_mem_size(EMIF2_BASE); + debug("emif1_size 0x%x emif2_size 0x%x\n", emif1_size, emif2_size); + + if (!emif1_size && !emif2_size) + return; + + /* symmetric interleaved section */ + if (emif1_size && emif2_size) { + mapped_size = min(emif1_size, emif2_size); + section_map = DMM_LISA_MAP_INTERLEAVED_BASE_VAL; + section_map |= 0 << EMIF_SDRC_ADDR_SHIFT; + /* only MSB */ + section_map |= (sys_addr >> 24) << + EMIF_SYS_ADDR_SHIFT; + section_map |= get_dmm_section_size_map(mapped_size * 2) + << EMIF_SYS_SIZE_SHIFT; + lis_map_regs_calculated.dmm_lisa_map_3 = section_map; + emif1_size -= mapped_size; + emif2_size -= mapped_size; + sys_addr += (mapped_size * 2); + section_cnt--; + } + + /* + * Single EMIF section(we can have a maximum of 1 single EMIF + * section- either EMIF1 or EMIF2 or none, but not both) + */ + if (emif1_size) { + section_map = DMM_LISA_MAP_EMIF1_ONLY_BASE_VAL; + section_map |= get_dmm_section_size_map(emif1_size) + << EMIF_SYS_SIZE_SHIFT; + /* only MSB */ + section_map |= (mapped_size >> 24) << + EMIF_SDRC_ADDR_SHIFT; + /* only MSB */ + section_map |= (sys_addr >> 24) << EMIF_SYS_ADDR_SHIFT; + section_cnt--; + } + if (emif2_size) { + section_map = DMM_LISA_MAP_EMIF2_ONLY_BASE_VAL; + section_map |= get_dmm_section_size_map(emif2_size) << + EMIF_SYS_SIZE_SHIFT; + /* only MSB */ + section_map |= mapped_size >> 24 << EMIF_SDRC_ADDR_SHIFT; + /* only MSB */ + section_map |= sys_addr >> 24 << EMIF_SYS_ADDR_SHIFT; + section_cnt--; + } + + if (section_cnt == 2) { + /* Only 1 section - either symmetric or single EMIF */ + lis_map_regs_calculated.dmm_lisa_map_3 = section_map; + lis_map_regs_calculated.dmm_lisa_map_2 = 0; + lis_map_regs_calculated.dmm_lisa_map_1 = 0; + } else { + /* 2 sections - 1 symmetric, 1 single EMIF */ + lis_map_regs_calculated.dmm_lisa_map_2 = section_map; + lis_map_regs_calculated.dmm_lisa_map_1 = 0; + } + + /* TRAP for invalid TILER mappings in section 0 */ + lis_map_regs_calculated.dmm_lisa_map_0 = DMM_LISA_MAP_0_INVAL_ADDR_TRAP; + + if (omap_revision() >= OMAP4460_ES1_0) + lis_map_regs_calculated.is_ma_present = 1; + + lisa_map_regs = &lis_map_regs_calculated; +#endif + struct dmm_lisa_map_regs *hw_lisa_map_regs = + (struct dmm_lisa_map_regs *)base; + + writel(0, &hw_lisa_map_regs->dmm_lisa_map_3); + writel(0, &hw_lisa_map_regs->dmm_lisa_map_2); + writel(0, &hw_lisa_map_regs->dmm_lisa_map_1); + writel(0, &hw_lisa_map_regs->dmm_lisa_map_0); + + writel(lisa_map_regs->dmm_lisa_map_3, + &hw_lisa_map_regs->dmm_lisa_map_3); + writel(lisa_map_regs->dmm_lisa_map_2, + &hw_lisa_map_regs->dmm_lisa_map_2); + writel(lisa_map_regs->dmm_lisa_map_1, + &hw_lisa_map_regs->dmm_lisa_map_1); + writel(lisa_map_regs->dmm_lisa_map_0, + &hw_lisa_map_regs->dmm_lisa_map_0); + + if (lisa_map_regs->is_ma_present) { + hw_lisa_map_regs = + (struct dmm_lisa_map_regs *)MA_BASE; + + writel(lisa_map_regs->dmm_lisa_map_3, + &hw_lisa_map_regs->dmm_lisa_map_3); + writel(lisa_map_regs->dmm_lisa_map_2, + &hw_lisa_map_regs->dmm_lisa_map_2); + writel(lisa_map_regs->dmm_lisa_map_1, + &hw_lisa_map_regs->dmm_lisa_map_1); + writel(lisa_map_regs->dmm_lisa_map_0, + &hw_lisa_map_regs->dmm_lisa_map_0); + } + + /* + * EMIF should be configured only when + * memory is mapped on it. Using emif1_enabled + * and emif2_enabled variables for this. + */ + emif1_enabled = 0; + emif2_enabled = 0; + for (i = 0; i < 4; i++) { + section = __raw_readl(DMM_BASE + i*4); + valid = (section & EMIF_SDRC_MAP_MASK) >> + (EMIF_SDRC_MAP_SHIFT); + if (valid == 3) { + emif1_enabled = 1; + emif2_enabled = 1; + break; + } else if (valid == 1) { + emif1_enabled = 1; + } else if (valid == 2) { + emif2_enabled = 1; + } + } + +} + +static void do_bug0039_workaround(u32 base) +{ + u32 val, i, clkctrl; + struct emif_reg_struct *emif_base = (struct emif_reg_struct *)base; + const struct read_write_regs *bug_00339_regs; + u32 iterations; + u32 *phy_status_base = &emif_base->emif_ddr_phy_status[0]; + u32 *phy_ctrl_base = &emif_base->emif_ddr_ext_phy_ctrl_1; + + if (is_dra7xx()) + phy_status_base++; + + bug_00339_regs = get_bug_regs(&iterations); + + /* Put EMIF in to idle */ + clkctrl = __raw_readl((*prcm)->cm_memif_clkstctrl); + __raw_writel(0x0, (*prcm)->cm_memif_clkstctrl); + + /* Copy the phy status registers in to phy ctrl shadow registers */ + for (i = 0; i < iterations; i++) { + val = __raw_readl(phy_status_base + + bug_00339_regs[i].read_reg - 1); + + __raw_writel(val, phy_ctrl_base + + ((bug_00339_regs[i].write_reg - 1) << 1)); + + __raw_writel(val, phy_ctrl_base + + (bug_00339_regs[i].write_reg << 1) - 1); + } + + /* Disable leveling */ + writel(0x0, &emif_base->emif_rd_wr_lvl_rmp_ctl); + + __raw_writel(clkctrl, (*prcm)->cm_memif_clkstctrl); +} + +/* + * SDRAM initialization: + * SDRAM initialization has two parts: + * 1. Configuring the SDRAM device + * 2. Update the AC timings related parameters in the EMIF module + * (1) should be done only once and should not be done while we are + * running from SDRAM. + * (2) can and should be done more than once if OPP changes. + * Particularly, this may be needed when we boot without SPL and + * and using Configuration Header(CH). ROM code supports only at 50% OPP + * at boot (low power boot). So u-boot has to switch to OPP100 and update + * the frequency. So, + * Doing (1) and (2) makes sense - first time initialization + * Doing (2) and not (1) makes sense - OPP change (when using CH) + * Doing (1) and not (2) doen't make sense + * See do_sdram_init() for the details + */ +void sdram_init(void) +{ + u32 in_sdram, size_prog, size_detect; + u32 sdram_type = emif_sdram_type(); + + debug(">>sdram_init()\n"); + + if (omap_hw_init_context() == OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL) + return; + + in_sdram = running_from_sdram(); + debug("in_sdram = %d\n", in_sdram); + + if (!in_sdram) { + if ((sdram_type == EMIF_SDRAM_TYPE_LPDDR2) && !warm_reset()) + bypass_dpll((*prcm)->cm_clkmode_dpll_core); + else if (sdram_type == EMIF_SDRAM_TYPE_DDR3) + writel(CM_DLL_CTRL_NO_OVERRIDE, (*prcm)->cm_dll_ctrl); + } + + if (!in_sdram) + dmm_init(DMM_BASE); + + if (emif1_enabled) + do_sdram_init(EMIF1_BASE); + + if (emif2_enabled) + do_sdram_init(EMIF2_BASE); + + if (!(in_sdram || warm_reset())) { + if (emif1_enabled) + emif_post_init_config(EMIF1_BASE); + if (emif2_enabled) + emif_post_init_config(EMIF2_BASE); + } + + /* for the shadow registers to take effect */ + if (sdram_type == EMIF_SDRAM_TYPE_LPDDR2) + freq_update_core(); + + /* Do some testing after the init */ + if (!in_sdram) { + size_prog = omap_sdram_size(); + size_prog = log_2_n_round_down(size_prog); + size_prog = (1 << size_prog); + + size_detect = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, + size_prog); + /* Compare with the size programmed */ + if (size_detect != size_prog) { + printf("SDRAM: identified size not same as expected" + " size identified: %x expected: %x\n", + size_detect, + size_prog); + } else + debug("get_ram_size() successful"); + } + + if (sdram_type == EMIF_SDRAM_TYPE_DDR3 && + (!in_sdram && !warm_reset())) { + do_bug0039_workaround(EMIF1_BASE); + do_bug0039_workaround(EMIF2_BASE); + } + + debug("<<sdram_init()\n"); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/hwinit-common.c new file mode 100644 index 000000000..8ebc0ce25 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/hwinit-common.c @@ -0,0 +1,299 @@ +/* + * + * Common functions for OMAP4/5 based boards + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Author : + * Aneesh V <aneesh@ti.com> + * Steve Sakoman <steve@sakoman.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <spl.h> +#include <asm/arch/sys_proto.h> +#include <linux/sizes.h> +#include <asm/emif.h> +#include <asm/omap_common.h> +#include <linux/compiler.h> +#include <asm/cache.h> +#include <asm/system.h> + +#define ARMV7_DCACHE_WRITEBACK 0xe +#define ARMV7_DOMAIN_CLIENT 1 +#define ARMV7_DOMAIN_MASK (0x3 << 0) + +DECLARE_GLOBAL_DATA_PTR; + +void do_set_mux(u32 base, struct pad_conf_entry const *array, int size) +{ + int i; + struct pad_conf_entry *pad = (struct pad_conf_entry *) array; + + for (i = 0; i < size; i++, pad++) + writew(pad->val, base + pad->offset); +} + +static void set_mux_conf_regs(void) +{ + switch (omap_hw_init_context()) { + case OMAP_INIT_CONTEXT_SPL: + set_muxconf_regs_essential(); + break; + case OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL: + break; + case OMAP_INIT_CONTEXT_UBOOT_FROM_NOR: + case OMAP_INIT_CONTEXT_UBOOT_AFTER_CH: + set_muxconf_regs_essential(); + break; + } +} + +u32 cortex_rev(void) +{ + + unsigned int rev; + + /* Read Main ID Register (MIDR) */ + asm ("mrc p15, 0, %0, c0, c0, 0" : "=r" (rev)); + + return rev; +} + +static void omap_rev_string(void) +{ + u32 omap_rev = omap_revision(); + u32 soc_variant = (omap_rev & 0xF0000000) >> 28; + u32 omap_variant = (omap_rev & 0xFFFF0000) >> 16; + u32 major_rev = (omap_rev & 0x00000F00) >> 8; + u32 minor_rev = (omap_rev & 0x000000F0) >> 4; + + if (soc_variant) + printf("OMAP"); + else + printf("DRA"); + printf("%x ES%x.%x\n", omap_variant, major_rev, + minor_rev); +} + +#ifdef CONFIG_SPL_BUILD +void spl_display_print(void) +{ + omap_rev_string(); +} +#endif + +void __weak srcomp_enable(void) +{ +} + +#ifdef CONFIG_ARCH_CPU_INIT +/* + * SOC specific cpu init + */ +int arch_cpu_init(void) +{ + save_omap_boot_params(); + return 0; +} +#endif /* CONFIG_ARCH_CPU_INIT */ + +/* + * Routine: s_init + * Description: Does early system init of watchdog, muxing, andclocks + * Watchdog disable is done always. For the rest what gets done + * depends on the boot mode in which this function is executed + * 1. s_init of SPL running from SRAM + * 2. s_init of U-Boot running from FLASH + * 3. s_init of U-Boot loaded to SDRAM by SPL + * 4. s_init of U-Boot loaded to SDRAM by ROM code using the + * Configuration Header feature + * Please have a look at the respective functions to see what gets + * done in each of these cases + * This function is called with SRAM stack. + */ +void s_init(void) +{ + /* + * Save the boot parameters passed from romcode. + * We cannot delay the saving further than this, + * to prevent overwrites. + */ +#ifdef CONFIG_SPL_BUILD + save_omap_boot_params(); +#endif + init_omap_revision(); + hw_data_init(); + +#ifdef CONFIG_SPL_BUILD + if (warm_reset() && (omap_revision() <= OMAP5430_ES1_0)) + force_emif_self_refresh(); +#endif + watchdog_init(); + set_mux_conf_regs(); +#ifdef CONFIG_SPL_BUILD + srcomp_enable(); + setup_clocks_for_console(); + + gd = &gdata; + + preloader_console_init(); + do_io_settings(); +#endif + prcm_init(); +#ifdef CONFIG_SPL_BUILD + /* For regular u-boot sdram_init() is called from dram_init() */ + sdram_init(); +#endif +} + +/* + * Routine: wait_for_command_complete + * Description: Wait for posting to finish on watchdog + */ +void wait_for_command_complete(struct watchdog *wd_base) +{ + int pending = 1; + do { + pending = readl(&wd_base->wwps); + } while (pending); +} + +/* + * Routine: watchdog_init + * Description: Shut down watch dogs + */ +void watchdog_init(void) +{ + struct watchdog *wd2_base = (struct watchdog *)WDT2_BASE; + + writel(WD_UNLOCK1, &wd2_base->wspr); + wait_for_command_complete(wd2_base); + writel(WD_UNLOCK2, &wd2_base->wspr); +} + + +/* + * This function finds the SDRAM size available in the system + * based on DMM section configurations + * This is needed because the size of memory installed may be + * different on different versions of the board + */ +u32 omap_sdram_size(void) +{ + u32 section, i, valid; + u64 sdram_start = 0, sdram_end = 0, addr, + size, total_size = 0, trap_size = 0; + + for (i = 0; i < 4; i++) { + section = __raw_readl(DMM_BASE + i*4); + valid = (section & EMIF_SDRC_ADDRSPC_MASK) >> + (EMIF_SDRC_ADDRSPC_SHIFT); + addr = section & EMIF_SYS_ADDR_MASK; + + /* See if the address is valid */ + if ((addr >= DRAM_ADDR_SPACE_START) && + (addr < DRAM_ADDR_SPACE_END)) { + size = ((section & EMIF_SYS_SIZE_MASK) >> + EMIF_SYS_SIZE_SHIFT); + size = 1 << size; + size *= SZ_16M; + + if (valid != DMM_SDRC_ADDR_SPC_INVALID) { + if (!sdram_start || (addr < sdram_start)) + sdram_start = addr; + if (!sdram_end || ((addr + size) > sdram_end)) + sdram_end = addr + size; + } else { + trap_size = size; + } + + } + + } + total_size = (sdram_end - sdram_start) - (trap_size); + + return total_size; +} + + +/* + * Routine: dram_init + * Description: sets uboots idea of sdram size + */ +int dram_init(void) +{ + sdram_init(); + gd->ram_size = omap_sdram_size(); + return 0; +} + +/* + * Print board information + */ +int checkboard(void) +{ + puts(sysinfo.board_string); + return 0; +} + +/* + * get_device_type(): tell if GP/HS/EMU/TST + */ +u32 get_device_type(void) +{ + return (readl((*ctrl)->control_status) & + (DEVICE_TYPE_MASK)) >> DEVICE_TYPE_SHIFT; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +/* + * Print CPU information + */ +int print_cpuinfo(void) +{ + puts("CPU : "); + omap_rev_string(); + + return 0; +} +#endif + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} + +void dram_bank_mmu_setup(int bank) +{ + bd_t *bd = gd->bd; + int i; + + u32 start = bd->bi_dram[bank].start >> 20; + u32 size = bd->bi_dram[bank].size >> 20; + u32 end = start + size; + + debug("%s: bank: %d\n", __func__, bank); + for (i = start; i < end; i++) + set_section_dcache(i, ARMV7_DCACHE_WRITEBACK); + +} + +void arm_init_domains(void) +{ + u32 reg; + + reg = get_dacr(); + /* + * Set DOMAIN to client access so that all permissions + * set in pagetables are validated by the mmu. + */ + reg &= ~ARMV7_DOMAIN_MASK; + reg |= ARMV7_DOMAIN_CLIENT; + set_dacr(reg); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/lowlevel_init.S new file mode 100644 index 000000000..86c0e4217 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/lowlevel_init.S @@ -0,0 +1,32 @@ +/* + * Board specific setup info + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Author : + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <asm/arch/omap.h> +#include <asm/omap_common.h> +#include <asm/arch/spl.h> +#include <linux/linkage.h> + +ENTRY(save_boot_params) + ldr r1, =OMAP_SRAM_SCRATCH_BOOT_PARAMS + str r0, [r1] + bx lr +ENDPROC(save_boot_params) + +ENTRY(set_pl310_ctrl_reg) + PUSH {r4-r11, lr} @ save registers - ROM code may pollute + @ our registers + LDR r12, =0x102 @ Set PL310 control register - value in R0 + .word 0xe1600070 @ SMC #0 - hand assembled because -march=armv5 + @ call ROM Code API to set control register + POP {r4-r11, pc} +ENDPROC(set_pl310_ctrl_reg) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/mem-common.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/mem-common.c new file mode 100644 index 000000000..afc1bc185 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/mem-common.c @@ -0,0 +1,32 @@ +/* + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Steve Sakoman <steve@sakoman.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/arch/cpu.h> +#include <asm/arch/sys_proto.h> + +struct gpmc *gpmc_cfg; + +/***************************************************** + * gpmc_init(): init gpmc bus + * This code can only be executed from SRAM or SDRAM. + *****************************************************/ +void gpmc_init(void) +{ + gpmc_cfg = (struct gpmc *)GPMC_BASE; + + /* global settings */ + writel(0, &gpmc_cfg->irqenable); /* isr's sources masked */ + writel(0, &gpmc_cfg->timeout_control);/* timeout disable */ + + /* + * Disable the GPMC0 config set by ROM code + * It conflicts with our MPDB (both at 0x08000000) + */ + writel(0, &gpmc_cfg->cs[0].config7); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/pipe3-phy.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/pipe3-phy.c new file mode 100644 index 000000000..b71d76941 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/pipe3-phy.c @@ -0,0 +1,231 @@ +/* + * TI PIPE3 PHY + * + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <sata.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> +#include <asm/errno.h> +#include "pipe3-phy.h" + +/* PLLCTRL Registers */ +#define PLL_STATUS 0x00000004 +#define PLL_GO 0x00000008 +#define PLL_CONFIGURATION1 0x0000000C +#define PLL_CONFIGURATION2 0x00000010 +#define PLL_CONFIGURATION3 0x00000014 +#define PLL_CONFIGURATION4 0x00000020 + +#define PLL_REGM_MASK 0x001FFE00 +#define PLL_REGM_SHIFT 9 +#define PLL_REGM_F_MASK 0x0003FFFF +#define PLL_REGM_F_SHIFT 0 +#define PLL_REGN_MASK 0x000001FE +#define PLL_REGN_SHIFT 1 +#define PLL_SELFREQDCO_MASK 0x0000000E +#define PLL_SELFREQDCO_SHIFT 1 +#define PLL_SD_MASK 0x0003FC00 +#define PLL_SD_SHIFT 10 +#define SET_PLL_GO 0x1 +#define PLL_TICOPWDN BIT(16) +#define PLL_LDOPWDN BIT(15) +#define PLL_LOCK 0x2 +#define PLL_IDLE 0x1 + +/* PHY POWER CONTROL Register */ +#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK 0x003FC000 +#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT 0xE + +#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK 0xFFC00000 +#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT 0x16 + +#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON 0x3 +#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF 0x0 + + +#define PLL_IDLE_TIME 100 /* in milliseconds */ +#define PLL_LOCK_TIME 100 /* in milliseconds */ + +static inline u32 omap_pipe3_readl(void __iomem *addr, unsigned offset) +{ + return __raw_readl(addr + offset); +} + +static inline void omap_pipe3_writel(void __iomem *addr, unsigned offset, + u32 data) +{ + __raw_writel(data, addr + offset); +} + +static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(struct omap_pipe3 + *pipe3) +{ + u32 rate; + struct pipe3_dpll_map *dpll_map = pipe3->dpll_map; + + rate = get_sys_clk_freq(); + + for (; dpll_map->rate; dpll_map++) { + if (rate == dpll_map->rate) + return &dpll_map->params; + } + + printf("%s: No DPLL configuration for %u Hz SYS CLK\n", + __func__, rate); + return NULL; +} + + +static int omap_pipe3_wait_lock(struct omap_pipe3 *phy) +{ + u32 val; + int timeout = PLL_LOCK_TIME; + + do { + mdelay(1); + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); + if (val & PLL_LOCK) + break; + } while (--timeout); + + if (!(val & PLL_LOCK)) { + printf("%s: DPLL failed to lock\n", __func__); + return -EBUSY; + } + + return 0; +} + +static int omap_pipe3_dpll_program(struct omap_pipe3 *phy) +{ + u32 val; + struct pipe3_dpll_params *dpll_params; + + dpll_params = omap_pipe3_get_dpll_params(phy); + if (!dpll_params) { + printf("%s: Invalid DPLL parameters\n", __func__); + return -EINVAL; + } + + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); + val &= ~PLL_REGN_MASK; + val |= dpll_params->n << PLL_REGN_SHIFT; + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); + + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); + val &= ~PLL_SELFREQDCO_MASK; + val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); + + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); + val &= ~PLL_REGM_MASK; + val |= dpll_params->m << PLL_REGM_SHIFT; + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); + + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); + val &= ~PLL_REGM_F_MASK; + val |= dpll_params->mf << PLL_REGM_F_SHIFT; + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); + + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); + val &= ~PLL_SD_MASK; + val |= dpll_params->sd << PLL_SD_SHIFT; + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); + + omap_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO); + + return omap_pipe3_wait_lock(phy); +} + +static void omap_control_phy_power(struct omap_pipe3 *phy, int on) +{ + u32 val, rate; + + val = readl(phy->power_reg); + + rate = get_sys_clk_freq(); + rate = rate/1000000; + + if (on) { + val &= ~(OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK | + OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK); + val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON << + OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT; + val |= rate << + OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT; + } else { + val &= ~OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK; + val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF << + OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT; + } + + writel(val, phy->power_reg); +} + +int phy_pipe3_power_on(struct omap_pipe3 *phy) +{ + int ret; + u32 val; + + /* Program the DPLL only if not locked */ + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); + if (!(val & PLL_LOCK)) { + ret = omap_pipe3_dpll_program(phy); + if (ret) + return ret; + } else { + /* else just bring it out of IDLE mode */ + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); + if (val & PLL_IDLE) { + val &= ~PLL_IDLE; + omap_pipe3_writel(phy->pll_ctrl_base, + PLL_CONFIGURATION2, val); + ret = omap_pipe3_wait_lock(phy); + if (ret) + return ret; + } + } + + /* Power up the PHY */ + omap_control_phy_power(phy, 1); + + return 0; +} + +int phy_pipe3_power_off(struct omap_pipe3 *phy) +{ + u32 val; + int timeout = PLL_IDLE_TIME; + + /* Power down the PHY */ + omap_control_phy_power(phy, 0); + + /* Put DPLL in IDLE mode */ + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); + val |= PLL_IDLE; + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); + + /* wait for LDO and Oscillator to power down */ + do { + mdelay(1); + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); + if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN)) + break; + } while (--timeout); + + if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) { + printf("%s: Failed to power down DPLL: PLL_STATUS 0x%x\n", + __func__, val); + return -EBUSY; + } + + return 0; +} + diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/pipe3-phy.h b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/pipe3-phy.h new file mode 100644 index 000000000..441f49a3f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/pipe3-phy.h @@ -0,0 +1,36 @@ +/* + * TI PIPE3 PHY + * + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __OMAP_PIPE3_PHY_H +#define __OMAP_PIPE3_PHY_H + +struct pipe3_dpll_params { + u16 m; + u8 n; + u8 freq:3; + u8 sd; + u32 mf; +}; + +struct pipe3_dpll_map { + unsigned long rate; + struct pipe3_dpll_params params; +}; + +struct omap_pipe3 { + void __iomem *pll_ctrl_base; + void __iomem *power_reg; + struct pipe3_dpll_map *dpll_map; +}; + + +int phy_pipe3_power_on(struct omap_pipe3 *phy); +int phy_pipe3_power_off(struct omap_pipe3 *pipe3); + +#endif /* __OMAP_PIPE3_PHY_H */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/reset.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/reset.c new file mode 100644 index 000000000..91ad031dd --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/reset.c @@ -0,0 +1,29 @@ +/* + * + * Common layer for reset related functionality of OMAP based socs. + * + * (C) Copyright 2012 + * Texas Instruments, <www.ti.com> + * + * Sricharan R <r.sricharan@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <config.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <linux/compiler.h> + +void __weak reset_cpu(unsigned long ignored) +{ + writel(PRM_RSTCTRL_RESET, PRM_RSTCTRL); +} + +u32 __weak warm_reset(void) +{ + return (readl(PRM_RSTST) & PRM_RSTST_WARM_RESET_MASK); +} + +void __weak setup_warmreset_time(void) +{ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/sata.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/sata.c new file mode 100644 index 000000000..cad4feed0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/sata.c @@ -0,0 +1,76 @@ +/* + * TI SATA platform driver + * + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <ahci.h> +#include <scsi.h> +#include <asm/arch/clock.h> +#include <asm/arch/sata.h> +#include <sata.h> +#include <asm/io.h> +#include "pipe3-phy.h" + +static struct pipe3_dpll_map dpll_map_sata[] = { + {12000000, {1000, 7, 4, 6, 0} }, /* 12 MHz */ + {16800000, {714, 7, 4, 6, 0} }, /* 16.8 MHz */ + {19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */ + {20000000, {600, 7, 4, 6, 0} }, /* 20 MHz */ + {26000000, {461, 7, 4, 6, 0} }, /* 26 MHz */ + {38400000, {312, 7, 4, 6, 0} }, /* 38.4 MHz */ + { }, /* Terminator */ +}; + +struct omap_pipe3 sata_phy = { + .pll_ctrl_base = (void __iomem *)TI_SATA_PLLCTRL_BASE, + /* .power_reg is updated at runtime */ + .dpll_map = dpll_map_sata, +}; + +int init_sata(int dev) +{ + int ret; + u32 val; + + u32 const clk_domains_sata[] = { + 0 + }; + + u32 const clk_modules_hw_auto_sata[] = { + (*prcm)->cm_l3init_ocp2scp3_clkctrl, + 0 + }; + + u32 const clk_modules_explicit_en_sata[] = { + (*prcm)->cm_l3init_sata_clkctrl, + 0 + }; + + do_enable_clocks(clk_domains_sata, + clk_modules_hw_auto_sata, + clk_modules_explicit_en_sata, + 0); + + /* Enable optional functional clock for SATA */ + setbits_le32((*prcm)->cm_l3init_sata_clkctrl, + SATA_CLKCTRL_OPTFCLKEN_MASK); + + sata_phy.power_reg = (void __iomem *)(*ctrl)->control_phy_power_sata; + + /* Power up the PHY */ + phy_pipe3_power_on(&sata_phy); + + /* Enable SATA module, No Idle, No Standby */ + val = TI_SATA_IDLE_NO | TI_SATA_STANDBY_NO; + writel(val, TI_SATA_WRAPPER_BASE + TI_SATA_SYSCONFIG); + + ret = ahci_init(DWC_AHSATA_BASE); + scsi_scan(1); + + return ret; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/timer.c new file mode 100644 index 000000000..7c9924dc3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/timer.c @@ -0,0 +1,108 @@ +/* + * (C) Copyright 2008 + * Texas Instruments + * + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Moahmmed Khasim <khasim@ti.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clock.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct gptimer *timer_base = (struct gptimer *)CONFIG_SYS_TIMERBASE; + +/* + * Nothing really to do with interrupts, just starts up a counter. + */ + +#define TIMER_CLOCK (V_SCLK / (2 << CONFIG_SYS_PTV)) +#define TIMER_OVERFLOW_VAL 0xffffffff +#define TIMER_LOAD_VAL 0 + +int timer_init(void) +{ + /* start the counter ticking up, reload value on overflow */ + writel(TIMER_LOAD_VAL, &timer_base->tldr); + /* enable timer */ + writel((CONFIG_SYS_PTV << 2) | TCLR_PRE | TCLR_AR | TCLR_ST, + &timer_base->tclr); + + /* reset time, capture current incrementer value time */ + gd->arch.lastinc = readl(&timer_base->tcrr) / + (TIMER_CLOCK / CONFIG_SYS_HZ); + gd->arch.tbl = 0; /* start "advancing" time stamp from 0 */ + + return 0; +} + +/* + * timer without interrupts + */ +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* delay x useconds */ +void __udelay(unsigned long usec) +{ + long tmo = usec * (TIMER_CLOCK / 1000) / 1000; + unsigned long now, last = readl(&timer_base->tcrr); + + while (tmo > 0) { + now = readl(&timer_base->tcrr); + if (last > now) /* count up timer overflow */ + tmo -= TIMER_OVERFLOW_VAL - last + now + 1; + else + tmo -= now - last; + last = now; + } +} + +ulong get_timer_masked(void) +{ + /* current tick value */ + ulong now = readl(&timer_base->tcrr) / (TIMER_CLOCK / CONFIG_SYS_HZ); + + if (now >= gd->arch.lastinc) { /* normal mode (non roll) */ + /* move stamp fordward with absoulte diff ticks */ + gd->arch.tbl += (now - gd->arch.lastinc); + } else { /* we have rollover of incrementer */ + gd->arch.tbl += ((TIMER_LOAD_VAL / (TIMER_CLOCK / + CONFIG_SYS_HZ)) - gd->arch.lastinc) + now; + } + gd->arch.lastinc = now; + return gd->arch.tbl; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/u-boot-spl.lds b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/u-boot-spl.lds new file mode 100644 index 000000000..745603d0f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/u-boot-spl.lds @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : + { + __start = .; + arch/arm/cpu/armv7/start.o (.text*) + *(.text*) + } >.sram + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*_i2c_*))); + } >.sram + + . = ALIGN(4); + __image_copy_end = .; + + .end : + { + *(.__end) + } + + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } >.sdram +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/utils.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/utils.c new file mode 100644 index 000000000..1696c2dbd --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/utils.c @@ -0,0 +1,62 @@ +/* + * Copyright 2011 Linaro Limited + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/arch/sys_proto.h> +static void do_cancel_out(u32 *num, u32 *den, u32 factor) +{ + while (1) { + if (((*num)/factor*factor == (*num)) && + ((*den)/factor*factor == (*den))) { + (*num) /= factor; + (*den) /= factor; + } else + break; + } +} + +/* + * Cancel out the denominator and numerator of a fraction + * to get smaller numerator and denominator. + */ +void cancel_out(u32 *num, u32 *den, u32 den_limit) +{ + do_cancel_out(num, den, 2); + do_cancel_out(num, den, 3); + do_cancel_out(num, den, 5); + do_cancel_out(num, den, 7); + do_cancel_out(num, den, 11); + do_cancel_out(num, den, 13); + do_cancel_out(num, den, 17); + while ((*den) > den_limit) { + *num /= 2; + /* + * Round up the denominator so that the final fraction + * (num/den) is always <= the desired value + */ + *den = (*den + 1) / 2; + } +} + +void __weak usb_fake_mac_from_die_id(u32 *id) +{ + uint8_t device_mac[6]; + + if (!getenv("usbethaddr")) { + /* + * create a fake MAC address from the processor ID code. + * first byte is 0x02 to signify locally administered. + */ + device_mac[0] = 0x02; + device_mac[1] = id[3] & 0xff; + device_mac[2] = id[2] & 0xff; + device_mac[3] = id[1] & 0xff; + device_mac[4] = id[0] & 0xff; + device_mac[5] = (id[0] >> 8) & 0xff; + + eth_setenv_enetaddr("usbethaddr", device_mac); + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/vc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/vc.c new file mode 100644 index 000000000..a68f1d145 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap-common/vc.c @@ -0,0 +1,151 @@ +/* + * Voltage Controller implementation for OMAP + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <asm/omap_common.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/clock.h> + +/* + * Define Master code if there are multiple masters on the I2C_SR bus. + * Normally not required + */ +#ifndef CONFIG_OMAP_VC_I2C_HS_MCODE +#define CONFIG_OMAP_VC_I2C_HS_MCODE 0x0 +#endif + +/* Register defines and masks for VC IP Block */ +/* PRM_VC_CFG_I2C_MODE */ +#define PRM_VC_CFG_I2C_MODE_DFILTEREN_BIT (0x1 << 6) +#define PRM_VC_CFG_I2C_MODE_SRMODEEN_BIT (0x1 << 4) +#define PRM_VC_CFG_I2C_MODE_HSMODEEN_BIT (0x1 << 3) +#define PRM_VC_CFG_I2C_MODE_HSMCODE_SHIFT 0x0 +#define PRM_VC_CFG_I2C_MODE_HSMCODE_MASK 0x3 + +/* PRM_VC_CFG_I2C_CLK */ +#define PRM_VC_CFG_I2C_CLK_HSCLL_SHIFT 24 +#define PRM_VC_CFG_I2C_CLK_HSCLL_MASK 0xFF +#define PRM_VC_CFG_I2C_CLK_HSCLH_SHIFT 16 +#define PRM_VC_CFG_I2C_CLK_HSCLH_MASK 0xFF +#define PRM_VC_CFG_I2C_CLK_SCLH_SHIFT 0 +#define PRM_VC_CFG_I2C_CLK_SCLH_MASK 0xFF +#define PRM_VC_CFG_I2C_CLK_SCLL_SHIFT 8 +#define PRM_VC_CFG_I2C_CLK_SCLL_MASK (0xFF << 8) + +/* PRM_VC_VAL_BYPASS */ +#define PRM_VC_VAL_BYPASS_VALID_BIT (0x1 << 24) +#define PRM_VC_VAL_BYPASS_SLAVEADDR_SHIFT 0 +#define PRM_VC_VAL_BYPASS_SLAVEADDR_MASK 0x7F +#define PRM_VC_VAL_BYPASS_REGADDR_SHIFT 8 +#define PRM_VC_VAL_BYPASS_REGADDR_MASK 0xFF +#define PRM_VC_VAL_BYPASS_DATA_SHIFT 16 +#define PRM_VC_VAL_BYPASS_DATA_MASK 0xFF + +/** + * omap_vc_init() - Initialization for Voltage controller + * @speed_khz: I2C buspeed in KHz + */ +static void omap_vc_init(u16 speed_khz) +{ + u32 val; + u32 sys_clk_khz, cycles_hi, cycles_low; + + sys_clk_khz = get_sys_clk_freq() / 1000; + + if (speed_khz > 400) { + puts("higher speed requested - throttle to 400Khz\n"); + speed_khz = 400; + } + + /* + * Setup the dedicated I2C controller for Voltage Control + * I2C clk - high period 40% low period 60% + */ + speed_khz /= 10; + cycles_hi = sys_clk_khz * 4 / speed_khz; + cycles_low = sys_clk_khz * 6 / speed_khz; + /* values to be set in register - less by 5 & 7 respectively */ + cycles_hi -= 5; + cycles_low -= 7; + val = (cycles_hi << PRM_VC_CFG_I2C_CLK_SCLH_SHIFT) | + (cycles_low << PRM_VC_CFG_I2C_CLK_SCLL_SHIFT); + writel(val, (*prcm)->prm_vc_cfg_i2c_clk); + + val = CONFIG_OMAP_VC_I2C_HS_MCODE << + PRM_VC_CFG_I2C_MODE_HSMCODE_SHIFT; + /* No HS mode for now */ + val &= ~PRM_VC_CFG_I2C_MODE_HSMODEEN_BIT; + writel(val, (*prcm)->prm_vc_cfg_i2c_mode); +} + +/** + * omap_vc_bypass_send_value() - Send a data using VC Bypass command + * @sa: 7 bit I2C slave address of the PMIC + * @reg_addr: I2C register address(8 bit) address in PMIC + * @reg_data: what 8 bit data to write + */ +int omap_vc_bypass_send_value(u8 sa, u8 reg_addr, u8 reg_data) +{ + /* + * Unfortunately we need to loop here instead of a defined time + * use arbitary large value + */ + u32 timeout = 0xFFFF; + u32 reg_val; + + sa &= PRM_VC_VAL_BYPASS_SLAVEADDR_MASK; + reg_addr &= PRM_VC_VAL_BYPASS_REGADDR_MASK; + reg_data &= PRM_VC_VAL_BYPASS_DATA_MASK; + + /* program VC to send data */ + reg_val = sa << PRM_VC_VAL_BYPASS_SLAVEADDR_SHIFT | + reg_addr << PRM_VC_VAL_BYPASS_REGADDR_SHIFT | + reg_data << PRM_VC_VAL_BYPASS_DATA_SHIFT; + writel(reg_val, (*prcm)->prm_vc_val_bypass); + + /* Signal VC to send data */ + writel(reg_val | PRM_VC_VAL_BYPASS_VALID_BIT, + (*prcm)->prm_vc_val_bypass); + + /* Wait on VC to complete transmission */ + do { + reg_val = readl((*prcm)->prm_vc_val_bypass) & + PRM_VC_VAL_BYPASS_VALID_BIT; + if (!reg_val) + break; + + sdelay(100); + } while (--timeout); + + /* Optional: cleanup PRM_IRQSTATUS_Ax */ + /* In case we can do something about it in future.. */ + if (!timeout) + return -1; + + /* All good.. */ + return 0; +} + +void sri2c_init(void) +{ + static int sri2c = 1; + + if (sri2c) { + omap_vc_init(PRM_VC_I2C_CHANNEL_FREQ_KHZ); + sri2c = 0; + } + return; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/Makefile new file mode 100644 index 000000000..39ff2575b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/Makefile @@ -0,0 +1,21 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := lowlevel_init.o + +obj-y += board.o +obj-y += clock.o +obj-y += mem.o +obj-y += sys_info.o +ifdef CONFIG_SPL_BUILD +obj-$(CONFIG_SPL_OMAP3_ID_NAND) += spl_id_nand.o +endif + +obj-$(CONFIG_DRIVER_TI_EMAC) += emac.o +obj-$(CONFIG_EMIF4) += emif4.o +obj-$(CONFIG_SDRC) += sdrc.o +obj-$(CONFIG_USB_MUSB_AM35X) += am35x_musb.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/am35x_musb.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/am35x_musb.c new file mode 100644 index 000000000..74dd105eb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/am35x_musb.c @@ -0,0 +1,61 @@ +/* + * This file configures the internal USB PHY in AM35X. + * + * Copyright (C) 2012 Ilya Yanok <ilya.yanok@gmail.com> + * + * Based on omap_phy_internal.c code from Linux by + * Hema HK <hemahk@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/am35x_def.h> + +void am35x_musb_reset(void) +{ + /* Reset the musb interface */ + clrsetbits_le32(&am35x_scm_general_regs->ip_sw_reset, + 0, USBOTGSS_SW_RST); + clrsetbits_le32(&am35x_scm_general_regs->ip_sw_reset, + USBOTGSS_SW_RST, 0); +} + +void am35x_musb_phy_power(u8 on) +{ + unsigned long start = get_timer(0); + + if (on) { + /* + * Start the on-chip PHY and its PLL. + */ + clrsetbits_le32(&am35x_scm_general_regs->devconf2, + CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN, + CONF2_PHY_PLLON); + + debug("Waiting for PHY clock good...\n"); + while (!(readl(&am35x_scm_general_regs->devconf2) + & CONF2_PHYCLKGD)) { + + if (get_timer(start) > CONFIG_SYS_HZ / 10) { + printf("musb PHY clock good timed out\n"); + break; + } + } + } else { + /* + * Power down the on-chip PHY. + */ + clrsetbits_le32(&am35x_scm_general_regs->devconf2, + CONF2_PHY_PLLON, + CONF2_PHYPWRDN | CONF2_OTGPWRDN); + } +} + +void am35x_musb_clear_irq(void) +{ + clrsetbits_le32(&am35x_scm_general_regs->lvl_intr_clr, + 0, USBOTGSS_INT_CLR); + readl(&am35x_scm_general_regs->lvl_intr_clr); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/board.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/board.c new file mode 100644 index 000000000..9bb1a1c8f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/board.c @@ -0,0 +1,488 @@ +/* + * + * Common board functions for OMAP3 based boards. + * + * (C) Copyright 2004-2008 + * Texas Instruments, <www.ti.com> + * + * Author : + * Sunil Kumar <sunilsaini05@gmail.com> + * Shashi Ranjan <shashiranjanmca05@gmail.com> + * + * Derived from Beagle Board and 3430 SDP code by + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <spl.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/mem.h> +#include <asm/cache.h> +#include <asm/armv7.h> +#include <asm/arch/gpio.h> +#include <asm/omap_common.h> +#include <asm/arch/mmc_host_def.h> +#include <i2c.h> +#include <linux/compiler.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Declarations */ +extern omap3_sysinfo sysinfo; +static void omap3_setup_aux_cr(void); +#ifndef CONFIG_SYS_L2CACHE_OFF +static void omap3_invalidate_l2_cache_secure(void); +#endif + +static const struct gpio_bank gpio_bank_34xx[6] = { + { (void *)OMAP34XX_GPIO1_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP34XX_GPIO2_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP34XX_GPIO3_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP34XX_GPIO4_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP34XX_GPIO5_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP34XX_GPIO6_BASE, METHOD_GPIO_24XX }, +}; + +const struct gpio_bank *const omap_gpio_bank = gpio_bank_34xx; + +#ifdef CONFIG_SPL_BUILD +/* +* We use static variables because global data is not ready yet. +* Initialized data is available in SPL right from the beginning. +* We would not typically need to save these parameters in regular +* U-Boot. This is needed only in SPL at the moment. +*/ +u32 omap3_boot_device = BOOT_DEVICE_NAND; + +/* auto boot mode detection is not possible for OMAP3 - hard code */ +u32 spl_boot_mode(void) +{ + switch (spl_boot_device()) { + case BOOT_DEVICE_MMC2: + return MMCSD_MODE_RAW; + case BOOT_DEVICE_MMC1: + return MMCSD_MODE_FAT; + break; + default: + puts("spl: ERROR: unknown device - can't select boot mode\n"); + hang(); + } +} + +u32 spl_boot_device(void) +{ + return omap3_boot_device; +} + +int board_mmc_init(bd_t *bis) +{ + switch (spl_boot_device()) { + case BOOT_DEVICE_MMC1: + omap_mmc_init(0, 0, 0, -1, -1); + break; + case BOOT_DEVICE_MMC2: + case BOOT_DEVICE_MMC2_2: + omap_mmc_init(1, 0, 0, -1, -1); + break; + } + return 0; +} + +void spl_board_init(void) +{ +#if defined(CONFIG_SPL_NAND_SUPPORT) || defined(CONFIG_SPL_ONENAND_SUPPORT) + gpmc_init(); +#endif +#ifdef CONFIG_SPL_I2C_SUPPORT + i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE); +#endif +} +#endif /* CONFIG_SPL_BUILD */ + + +/****************************************************************************** + * Routine: secure_unlock + * Description: Setup security registers for access + * (GP Device only) + *****************************************************************************/ +void secure_unlock_mem(void) +{ + struct pm *pm_rt_ape_base = (struct pm *)PM_RT_APE_BASE_ADDR_ARM; + struct pm *pm_gpmc_base = (struct pm *)PM_GPMC_BASE_ADDR_ARM; + struct pm *pm_ocm_ram_base = (struct pm *)PM_OCM_RAM_BASE_ADDR_ARM; + struct pm *pm_iva2_base = (struct pm *)PM_IVA2_BASE_ADDR_ARM; + struct sms *sms_base = (struct sms *)OMAP34XX_SMS_BASE; + + /* Protection Module Register Target APE (PM_RT) */ + writel(UNLOCK_1, &pm_rt_ape_base->req_info_permission_1); + writel(UNLOCK_1, &pm_rt_ape_base->read_permission_0); + writel(UNLOCK_1, &pm_rt_ape_base->wirte_permission_0); + writel(UNLOCK_2, &pm_rt_ape_base->addr_match_1); + + writel(UNLOCK_3, &pm_gpmc_base->req_info_permission_0); + writel(UNLOCK_3, &pm_gpmc_base->read_permission_0); + writel(UNLOCK_3, &pm_gpmc_base->wirte_permission_0); + + writel(UNLOCK_3, &pm_ocm_ram_base->req_info_permission_0); + writel(UNLOCK_3, &pm_ocm_ram_base->read_permission_0); + writel(UNLOCK_3, &pm_ocm_ram_base->wirte_permission_0); + writel(UNLOCK_2, &pm_ocm_ram_base->addr_match_2); + + /* IVA Changes */ + writel(UNLOCK_3, &pm_iva2_base->req_info_permission_0); + writel(UNLOCK_3, &pm_iva2_base->read_permission_0); + writel(UNLOCK_3, &pm_iva2_base->wirte_permission_0); + + /* SDRC region 0 public */ + writel(UNLOCK_1, &sms_base->rg_att0); +} + +/****************************************************************************** + * Routine: secureworld_exit() + * Description: If chip is EMU and boot type is external + * configure secure registers and exit secure world + * general use. + *****************************************************************************/ +void secureworld_exit() +{ + unsigned long i; + + /* configure non-secure access control register */ + __asm__ __volatile__("mrc p15, 0, %0, c1, c1, 2":"=r"(i)); + /* enabling co-processor CP10 and CP11 accesses in NS world */ + __asm__ __volatile__("orr %0, %0, #0xC00":"=r"(i)); + /* + * allow allocation of locked TLBs and L2 lines in NS world + * allow use of PLE registers in NS world also + */ + __asm__ __volatile__("orr %0, %0, #0x70000":"=r"(i)); + __asm__ __volatile__("mcr p15, 0, %0, c1, c1, 2":"=r"(i)); + + /* Enable ASA in ACR register */ + __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i)); + __asm__ __volatile__("orr %0, %0, #0x10":"=r"(i)); + __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i)); + + /* Exiting secure world */ + __asm__ __volatile__("mrc p15, 0, %0, c1, c1, 0":"=r"(i)); + __asm__ __volatile__("orr %0, %0, #0x31":"=r"(i)); + __asm__ __volatile__("mcr p15, 0, %0, c1, c1, 0":"=r"(i)); +} + +/****************************************************************************** + * Routine: try_unlock_sram() + * Description: If chip is GP/EMU(special) type, unlock the SRAM for + * general use. + *****************************************************************************/ +void try_unlock_memory() +{ + int mode; + int in_sdram = is_running_in_sdram(); + + /* + * if GP device unlock device SRAM for general use + * secure code breaks for Secure/Emulation device - HS/E/T + */ + mode = get_device_type(); + if (mode == GP_DEVICE) + secure_unlock_mem(); + + /* + * If device is EMU and boot is XIP external booting + * Unlock firewalls and disable L2 and put chip + * out of secure world + * + * Assuming memories are unlocked by the demon who put us in SDRAM + */ + if ((mode <= EMU_DEVICE) && (get_boot_type() == 0x1F) + && (!in_sdram)) { + secure_unlock_mem(); + secureworld_exit(); + } + + return; +} + +/****************************************************************************** + * Routine: s_init + * Description: Does early system init of muxing and clocks. + * - Called path is with SRAM stack. + *****************************************************************************/ +void s_init(void) +{ + int in_sdram = is_running_in_sdram(); + + watchdog_init(); + + try_unlock_memory(); + + /* Errata workarounds */ + omap3_setup_aux_cr(); + +#ifndef CONFIG_SYS_L2CACHE_OFF + /* Invalidate L2-cache from secure mode */ + omap3_invalidate_l2_cache_secure(); +#endif + + set_muxconf_regs(); + sdelay(100); + + prcm_init(); + + per_clocks_enable(); + +#ifdef CONFIG_USB_EHCI_OMAP + ehci_clocks_enable(); +#endif + +#ifdef CONFIG_SPL_BUILD + gd = &gdata; + + preloader_console_init(); + + timer_init(); +#endif + + if (!in_sdram) + mem_init(); +} + +/* + * Routine: misc_init_r + * Description: A basic misc_init_r that just displays the die ID + */ +int __weak misc_init_r(void) +{ + dieid_num_r(); + + return 0; +} + +/****************************************************************************** + * Routine: wait_for_command_complete + * Description: Wait for posting to finish on watchdog + *****************************************************************************/ +void wait_for_command_complete(struct watchdog *wd_base) +{ + int pending = 1; + do { + pending = readl(&wd_base->wwps); + } while (pending); +} + +/****************************************************************************** + * Routine: watchdog_init + * Description: Shut down watch dogs + *****************************************************************************/ +void watchdog_init(void) +{ + struct watchdog *wd2_base = (struct watchdog *)WD2_BASE; + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + + /* + * There are 3 watch dogs WD1=Secure, WD2=MPU, WD3=IVA. WD1 is + * either taken care of by ROM (HS/EMU) or not accessible (GP). + * We need to take care of WD2-MPU or take a PRCM reset. WD3 + * should not be running and does not generate a PRCM reset. + */ + + setbits_le32(&prcm_base->fclken_wkup, 0x20); + setbits_le32(&prcm_base->iclken_wkup, 0x20); + wait_on_value(ST_WDT2, 0x20, &prcm_base->idlest_wkup, 5); + + writel(WD_UNLOCK1, &wd2_base->wspr); + wait_for_command_complete(wd2_base); + writel(WD_UNLOCK2, &wd2_base->wspr); +} + +/****************************************************************************** + * Dummy function to handle errors for EABI incompatibility + *****************************************************************************/ +void abort(void) +{ +} + +#if defined(CONFIG_NAND_OMAP_GPMC) & !defined(CONFIG_SPL_BUILD) +/****************************************************************************** + * OMAP3 specific command to switch between NAND HW and SW ecc + *****************************************************************************/ +static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc < 2 || argc > 3) + goto usage; + + if (strncmp(argv[1], "hw", 2) == 0) { + if (argc == 2) { + omap_nand_switch_ecc(1, 1); + } else { + if (strncmp(argv[2], "hamming", 7) == 0) + omap_nand_switch_ecc(1, 1); + else if (strncmp(argv[2], "bch8", 4) == 0) + omap_nand_switch_ecc(1, 8); + else + goto usage; + } + } else if (strncmp(argv[1], "sw", 2) == 0) { + omap_nand_switch_ecc(0, 0); + } else { + goto usage; + } + + return 0; + +usage: + printf ("Usage: nandecc %s\n", cmdtp->usage); + return 1; +} + +U_BOOT_CMD( + nandecc, 3, 1, do_switch_ecc, + "switch OMAP3 NAND ECC calculation algorithm", + "hw [hamming|bch8] - Switch between NAND hardware 1-bit hamming and" + " 8-bit BCH\n" + " ecc calculation (second parameter may" + " be omitted).\n" + "nandecc sw - Switch to NAND software ecc algorithm." +); + +#endif /* CONFIG_NAND_OMAP_GPMC & !CONFIG_SPL_BUILD */ + +#ifdef CONFIG_DISPLAY_BOARDINFO +/** + * Print board information + */ +int checkboard (void) +{ + char *mem_s ; + + if (is_mem_sdr()) + mem_s = "mSDR"; + else + mem_s = "LPDDR"; + + printf("%s + %s/%s\n", sysinfo.board_string, mem_s, + sysinfo.nand_string); + + return 0; +} +#endif /* CONFIG_DISPLAY_BOARDINFO */ + +static void omap3_emu_romcode_call(u32 service_id, u32 *parameters) +{ + u32 i, num_params = *parameters; + u32 *sram_scratch_space = (u32 *)OMAP3_PUBLIC_SRAM_SCRATCH_AREA; + + /* + * copy the parameters to an un-cached area to avoid coherency + * issues + */ + for (i = 0; i < num_params; i++) { + __raw_writel(*parameters, sram_scratch_space); + parameters++; + sram_scratch_space++; + } + + /* Now make the PPA call */ + do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA); +} + +static void omap3_update_aux_cr_secure(u32 set_bits, u32 clear_bits) +{ + u32 acr; + + /* Read ACR */ + asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr)); + acr &= ~clear_bits; + acr |= set_bits; + + if (get_device_type() == GP_DEVICE) { + omap3_gp_romcode_call(OMAP3_GP_ROMCODE_API_WRITE_ACR, + acr); + } else { + struct emu_hal_params emu_romcode_params; + emu_romcode_params.num_params = 1; + emu_romcode_params.param1 = acr; + omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR, + (u32 *)&emu_romcode_params); + } +} + +static void omap3_setup_aux_cr(void) +{ + /* Workaround for Cortex-A8 errata: #454179 #430973 + * Set "IBE" bit + * Set "Disable Branch Size Mispredicts" bit + * Workaround for erratum #621766 + * Enable L1NEON bit + * ACR |= (IBE | DBSM | L1NEON) => ACR |= 0xE0 + */ + omap3_update_aux_cr_secure(0xE0, 0); +} + +#ifndef CONFIG_SYS_L2CACHE_OFF +static void omap3_update_aux_cr(u32 set_bits, u32 clear_bits) +{ + u32 acr; + + /* Read ACR */ + asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr)); + acr &= ~clear_bits; + acr |= set_bits; + + /* Write ACR - affects non-secure banked bits */ + asm volatile ("mcr p15, 0, %0, c1, c0, 1" : : "r" (acr)); +} + +/* Invalidate the entire L2 cache from secure mode */ +static void omap3_invalidate_l2_cache_secure(void) +{ + if (get_device_type() == GP_DEVICE) { + omap3_gp_romcode_call(OMAP3_GP_ROMCODE_API_L2_INVAL, + 0); + } else { + struct emu_hal_params emu_romcode_params; + emu_romcode_params.num_params = 1; + emu_romcode_params.param1 = 0; + omap3_emu_romcode_call(OMAP3_EMU_HAL_API_L2_INVAL, + (u32 *)&emu_romcode_params); + } +} + +void v7_outer_cache_enable(void) +{ + /* Set L2EN */ + omap3_update_aux_cr_secure(0x2, 0); + + /* + * On some revisions L2EN bit is banked on some revisions it's not + * No harm in setting both banked bits(in fact this is required + * by an erratum) + */ + omap3_update_aux_cr(0x2, 0); +} + +void omap3_outer_cache_disable(void) +{ + /* Clear L2EN */ + omap3_update_aux_cr_secure(0, 0x2); + + /* + * On some revisions L2EN bit is banked on some revisions it's not + * No harm in clearing both banked bits(in fact this is required + * by an erratum) + */ + omap3_update_aux_cr(0, 0x2); +} +#endif /* !CONFIG_SYS_L2CACHE_OFF */ + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif /* !CONFIG_SYS_DCACHE_OFF */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/clock.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/clock.c new file mode 100644 index 000000000..529ad9a94 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/clock.c @@ -0,0 +1,790 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Author : + * Manikandan Pillai <mani.pillai@ti.com> + * + * Derived from Beagle Board and OMAP3 SDP code by + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/clocks_omap3.h> +#include <asm/arch/mem.h> +#include <asm/arch/sys_proto.h> +#include <environment.h> +#include <command.h> + +/****************************************************************************** + * get_sys_clk_speed() - determine reference oscillator speed + * based on known 32kHz clock and gptimer. + *****************************************************************************/ +u32 get_osc_clk_speed(void) +{ + u32 start, cstart, cend, cdiff, cdiv, val; + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + struct prm *prm_base = (struct prm *)PRM_BASE; + struct gptimer *gpt1_base = (struct gptimer *)OMAP34XX_GPT1; + struct s32ktimer *s32k_base = (struct s32ktimer *)SYNC_32KTIMER_BASE; + + val = readl(&prm_base->clksrc_ctrl); + + if (val & SYSCLKDIV_2) + cdiv = 2; + else + cdiv = 1; + + /* enable timer2 */ + val = readl(&prcm_base->clksel_wkup) | CLKSEL_GPT1; + + /* select sys_clk for GPT1 */ + writel(val, &prcm_base->clksel_wkup); + + /* Enable I and F Clocks for GPT1 */ + val = readl(&prcm_base->iclken_wkup) | EN_GPT1 | EN_32KSYNC; + writel(val, &prcm_base->iclken_wkup); + + val = readl(&prcm_base->fclken_wkup) | EN_GPT1; + writel(val, &prcm_base->fclken_wkup); + + writel(0, &gpt1_base->tldr); /* start counting at 0 */ + writel(GPT_EN, &gpt1_base->tclr); /* enable clock */ + + /* enable 32kHz source, determine sys_clk via gauging */ + + /* start time in 20 cycles */ + start = 20 + readl(&s32k_base->s32k_cr); + + /* dead loop till start time */ + while (readl(&s32k_base->s32k_cr) < start); + + /* get start sys_clk count */ + cstart = readl(&gpt1_base->tcrr); + + /* wait for 40 cycles */ + while (readl(&s32k_base->s32k_cr) < (start + 20)) ; + cend = readl(&gpt1_base->tcrr); /* get end sys_clk count */ + cdiff = cend - cstart; /* get elapsed ticks */ + cdiff *= cdiv; + + /* based on number of ticks assign speed */ + if (cdiff > 19000) + return S38_4M; + else if (cdiff > 15200) + return S26M; + else if (cdiff > 13000) + return S24M; + else if (cdiff > 9000) + return S19_2M; + else if (cdiff > 7600) + return S13M; + else + return S12M; +} + +/****************************************************************************** + * get_sys_clkin_sel() - returns the sys_clkin_sel field value based on + * input oscillator clock frequency. + *****************************************************************************/ +void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel) +{ + switch(osc_clk) { + case S38_4M: + *sys_clkin_sel = 4; + break; + case S26M: + *sys_clkin_sel = 3; + break; + case S19_2M: + *sys_clkin_sel = 2; + break; + case S13M: + *sys_clkin_sel = 1; + break; + case S12M: + default: + *sys_clkin_sel = 0; + } +} + +/* + * OMAP34XX/35XX specific functions + */ + +static void dpll3_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_core_dpll_param(); + void (*f_lock_pll) (u32, u32, u32, u32); + int xip_safe, p0, p1, p2, p3; + + xip_safe = is_running_in_sram(); + + /* Moving to the right sysclk and ES rev base */ + ptr = ptr + (3 * clk_index) + sil_index; + + if (xip_safe) { + /* + * CORE DPLL + */ + clrsetbits_le32(&prcm_base->clken_pll, + 0x00000007, PLL_FAST_RELOCK_BYPASS); + wait_on_value(ST_CORE_CLK, 0, &prcm_base->idlest_ckgen, + LDELAY); + + /* + * For OMAP3 ES1.0 Errata 1.50, default value directly doesn't + * work. write another value and then default value. + */ + + /* CM_CLKSEL1_EMU[DIV_DPLL3] */ + clrsetbits_le32(&prcm_base->clksel1_emu, + 0x001F0000, (CORE_M3X2 + 1) << 16) ; + clrsetbits_le32(&prcm_base->clksel1_emu, + 0x001F0000, CORE_M3X2 << 16); + + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + clrsetbits_le32(&prcm_base->clksel1_pll, + 0xF8000000, ptr->m2 << 27); + + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + clrsetbits_le32(&prcm_base->clksel1_pll, + 0x07FF0000, ptr->m << 16); + + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + clrsetbits_le32(&prcm_base->clksel1_pll, + 0x00007F00, ptr->n << 8); + + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + clrbits_le32(&prcm_base->clksel1_pll, 0x00000040); + + /* SSI */ + clrsetbits_le32(&prcm_base->clksel_core, + 0x00000F00, CORE_SSI_DIV << 8); + /* FSUSB */ + clrsetbits_le32(&prcm_base->clksel_core, + 0x00000030, CORE_FUSB_DIV << 4); + /* L4 */ + clrsetbits_le32(&prcm_base->clksel_core, + 0x0000000C, CORE_L4_DIV << 2); + /* L3 */ + clrsetbits_le32(&prcm_base->clksel_core, + 0x00000003, CORE_L3_DIV); + /* GFX */ + clrsetbits_le32(&prcm_base->clksel_gfx, + 0x00000007, GFX_DIV); + /* RESET MGR */ + clrsetbits_le32(&prcm_base->clksel_wkup, + 0x00000006, WKUP_RSM << 1); + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + clrsetbits_le32(&prcm_base->clken_pll, + 0x000000F0, ptr->fsel << 4); + /* LOCK MODE */ + clrsetbits_le32(&prcm_base->clken_pll, + 0x00000007, PLL_LOCK); + + wait_on_value(ST_CORE_CLK, 1, &prcm_base->idlest_ckgen, + LDELAY); + } else if (is_running_in_flash()) { + /* + * if running from flash, jump to small relocated code + * area in SRAM. + */ + f_lock_pll = (void *) (SRAM_CLK_CODE); + + p0 = readl(&prcm_base->clken_pll); + clrsetbits_le32(&p0, 0x00000007, PLL_FAST_RELOCK_BYPASS); + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + clrsetbits_le32(&p0, 0x000000F0, ptr->fsel << 4); + + p1 = readl(&prcm_base->clksel1_pll); + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + clrsetbits_le32(&p1, 0xF8000000, ptr->m2 << 27); + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + clrsetbits_le32(&p1, 0x07FF0000, ptr->m << 16); + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + clrsetbits_le32(&p1, 0x00007F00, ptr->n << 8); + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + clrbits_le32(&p1, 0x00000040); + + p2 = readl(&prcm_base->clksel_core); + /* SSI */ + clrsetbits_le32(&p2, 0x00000F00, CORE_SSI_DIV << 8); + /* FSUSB */ + clrsetbits_le32(&p2, 0x00000030, CORE_FUSB_DIV << 4); + /* L4 */ + clrsetbits_le32(&p2, 0x0000000C, CORE_L4_DIV << 2); + /* L3 */ + clrsetbits_le32(&p2, 0x00000003, CORE_L3_DIV); + + p3 = (u32)&prcm_base->idlest_ckgen; + + (*f_lock_pll) (p0, p1, p2, p3); + } +} + +static void dpll4_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_per_dpll_param(); + + /* Moving it to the right sysclk base */ + ptr = ptr + clk_index; + + /* EN_PERIPH_DPLL: CM_CLKEN_PLL[16:18] */ + clrsetbits_le32(&prcm_base->clken_pll, 0x00070000, PLL_STOP << 16); + wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY); + + /* + * Errata 1.50 Workaround for OMAP3 ES1.0 only + * If using default divisors, write default divisor + 1 + * and then the actual divisor value + */ + /* M6 */ + clrsetbits_le32(&prcm_base->clksel1_emu, + 0x1F000000, (PER_M6X2 + 1) << 24); + clrsetbits_le32(&prcm_base->clksel1_emu, + 0x1F000000, PER_M6X2 << 24); + /* M5 */ + clrsetbits_le32(&prcm_base->clksel_cam, 0x0000001F, (PER_M5X2 + 1)); + clrsetbits_le32(&prcm_base->clksel_cam, 0x0000001F, PER_M5X2); + /* M4 */ + clrsetbits_le32(&prcm_base->clksel_dss, 0x0000001F, (PER_M4X2 + 1)); + clrsetbits_le32(&prcm_base->clksel_dss, 0x0000001F, PER_M4X2); + /* M3 */ + clrsetbits_le32(&prcm_base->clksel_dss, + 0x00001F00, (PER_M3X2 + 1) << 8); + clrsetbits_le32(&prcm_base->clksel_dss, + 0x00001F00, PER_M3X2 << 8); + /* M2 (DIV_96M): CM_CLKSEL3_PLL[0:4] */ + clrsetbits_le32(&prcm_base->clksel3_pll, 0x0000001F, (ptr->m2 + 1)); + clrsetbits_le32(&prcm_base->clksel3_pll, 0x0000001F, ptr->m2); + /* Workaround end */ + + /* M (PERIPH_DPLL_MULT): CM_CLKSEL2_PLL[8:18] */ + clrsetbits_le32(&prcm_base->clksel2_pll, + 0x0007FF00, ptr->m << 8); + + /* N (PERIPH_DPLL_DIV): CM_CLKSEL2_PLL[0:6] */ + clrsetbits_le32(&prcm_base->clksel2_pll, 0x0000007F, ptr->n); + + /* FREQSEL (PERIPH_DPLL_FREQSEL): CM_CLKEN_PLL[20:23] */ + clrsetbits_le32(&prcm_base->clken_pll, 0x00F00000, ptr->fsel << 20); + + /* LOCK MODE (EN_PERIPH_DPLL): CM_CLKEN_PLL[16:18] */ + clrsetbits_le32(&prcm_base->clken_pll, 0x00070000, PLL_LOCK << 16); + wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY); +} + +static void dpll5_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_per2_dpll_param(); + + /* Moving it to the right sysclk base */ + ptr = ptr + clk_index; + + /* PER2 DPLL (DPLL5) */ + clrsetbits_le32(&prcm_base->clken2_pll, 0x00000007, PLL_STOP); + wait_on_value(1, 0, &prcm_base->idlest2_ckgen, LDELAY); + /* set M2 (usbtll_fck) */ + clrsetbits_le32(&prcm_base->clksel5_pll, 0x0000001F, ptr->m2); + /* set m (11-bit multiplier) */ + clrsetbits_le32(&prcm_base->clksel4_pll, 0x0007FF00, ptr->m << 8); + /* set n (7-bit divider)*/ + clrsetbits_le32(&prcm_base->clksel4_pll, 0x0000007F, ptr->n); + /* FREQSEL */ + clrsetbits_le32(&prcm_base->clken_pll, 0x000000F0, ptr->fsel << 4); + /* lock mode */ + clrsetbits_le32(&prcm_base->clken2_pll, 0x00000007, PLL_LOCK); + wait_on_value(1, 1, &prcm_base->idlest2_ckgen, LDELAY); +} + +static void mpu_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_mpu_dpll_param(); + + /* Moving to the right sysclk and ES rev base */ + ptr = ptr + (3 * clk_index) + sil_index; + + /* MPU DPLL (unlocked already) */ + + /* M2 (MPU_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_MPU[0:4] */ + clrsetbits_le32(&prcm_base->clksel2_pll_mpu, + 0x0000001F, ptr->m2); + + /* M (MPU_DPLL_MULT) : CM_CLKSEL2_PLL_MPU[8:18] */ + clrsetbits_le32(&prcm_base->clksel1_pll_mpu, + 0x0007FF00, ptr->m << 8); + + /* N (MPU_DPLL_DIV) : CM_CLKSEL2_PLL_MPU[0:6] */ + clrsetbits_le32(&prcm_base->clksel1_pll_mpu, + 0x0000007F, ptr->n); + + /* FREQSEL (MPU_DPLL_FREQSEL) : CM_CLKEN_PLL_MPU[4:7] */ + clrsetbits_le32(&prcm_base->clken_pll_mpu, + 0x000000F0, ptr->fsel << 4); +} + +static void iva_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_iva_dpll_param(); + + /* Moving to the right sysclk and ES rev base */ + ptr = ptr + (3 * clk_index) + sil_index; + + /* IVA DPLL */ + /* EN_IVA2_DPLL : CM_CLKEN_PLL_IVA2[0:2] */ + clrsetbits_le32(&prcm_base->clken_pll_iva2, + 0x00000007, PLL_STOP); + wait_on_value(ST_IVA2_CLK, 0, &prcm_base->idlest_pll_iva2, LDELAY); + + /* M2 (IVA2_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_IVA2[0:4] */ + clrsetbits_le32(&prcm_base->clksel2_pll_iva2, + 0x0000001F, ptr->m2); + + /* M (IVA2_DPLL_MULT) : CM_CLKSEL1_PLL_IVA2[8:18] */ + clrsetbits_le32(&prcm_base->clksel1_pll_iva2, + 0x0007FF00, ptr->m << 8); + + /* N (IVA2_DPLL_DIV) : CM_CLKSEL1_PLL_IVA2[0:6] */ + clrsetbits_le32(&prcm_base->clksel1_pll_iva2, + 0x0000007F, ptr->n); + + /* FREQSEL (IVA2_DPLL_FREQSEL) : CM_CLKEN_PLL_IVA2[4:7] */ + clrsetbits_le32(&prcm_base->clken_pll_iva2, + 0x000000F0, ptr->fsel << 4); + + /* LOCK MODE (EN_IVA2_DPLL) : CM_CLKEN_PLL_IVA2[0:2] */ + clrsetbits_le32(&prcm_base->clken_pll_iva2, + 0x00000007, PLL_LOCK); + + wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY); +} + +/* + * OMAP3630 specific functions + */ + +static void dpll3_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_36x_core_dpll_param(); + void (*f_lock_pll) (u32, u32, u32, u32); + int xip_safe, p0, p1, p2, p3; + + xip_safe = is_running_in_sram(); + + /* Moving it to the right sysclk base */ + ptr += clk_index; + + if (xip_safe) { + /* CORE DPLL */ + + /* Select relock bypass: CM_CLKEN_PLL[0:2] */ + clrsetbits_le32(&prcm_base->clken_pll, + 0x00000007, PLL_FAST_RELOCK_BYPASS); + wait_on_value(ST_CORE_CLK, 0, &prcm_base->idlest_ckgen, + LDELAY); + + /* CM_CLKSEL1_EMU[DIV_DPLL3] */ + clrsetbits_le32(&prcm_base->clksel1_emu, + 0x001F0000, CORE_M3X2 << 16); + + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + clrsetbits_le32(&prcm_base->clksel1_pll, + 0xF8000000, ptr->m2 << 27); + + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + clrsetbits_le32(&prcm_base->clksel1_pll, + 0x07FF0000, ptr->m << 16); + + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + clrsetbits_le32(&prcm_base->clksel1_pll, + 0x00007F00, ptr->n << 8); + + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + clrbits_le32(&prcm_base->clksel1_pll, 0x00000040); + + /* SSI */ + clrsetbits_le32(&prcm_base->clksel_core, + 0x00000F00, CORE_SSI_DIV << 8); + /* FSUSB */ + clrsetbits_le32(&prcm_base->clksel_core, + 0x00000030, CORE_FUSB_DIV << 4); + /* L4 */ + clrsetbits_le32(&prcm_base->clksel_core, + 0x0000000C, CORE_L4_DIV << 2); + /* L3 */ + clrsetbits_le32(&prcm_base->clksel_core, + 0x00000003, CORE_L3_DIV); + /* GFX */ + clrsetbits_le32(&prcm_base->clksel_gfx, + 0x00000007, GFX_DIV_36X); + /* RESET MGR */ + clrsetbits_le32(&prcm_base->clksel_wkup, + 0x00000006, WKUP_RSM << 1); + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + clrsetbits_le32(&prcm_base->clken_pll, + 0x000000F0, ptr->fsel << 4); + /* LOCK MODE */ + clrsetbits_le32(&prcm_base->clken_pll, + 0x00000007, PLL_LOCK); + + wait_on_value(ST_CORE_CLK, 1, &prcm_base->idlest_ckgen, + LDELAY); + } else if (is_running_in_flash()) { + /* + * if running from flash, jump to small relocated code + * area in SRAM. + */ + f_lock_pll = (void *) (SRAM_CLK_CODE); + + p0 = readl(&prcm_base->clken_pll); + clrsetbits_le32(&p0, 0x00000007, PLL_FAST_RELOCK_BYPASS); + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + clrsetbits_le32(&p0, 0x000000F0, ptr->fsel << 4); + + p1 = readl(&prcm_base->clksel1_pll); + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + clrsetbits_le32(&p1, 0xF8000000, ptr->m2 << 27); + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + clrsetbits_le32(&p1, 0x07FF0000, ptr->m << 16); + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + clrsetbits_le32(&p1, 0x00007F00, ptr->n << 8); + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + clrbits_le32(&p1, 0x00000040); + + p2 = readl(&prcm_base->clksel_core); + /* SSI */ + clrsetbits_le32(&p2, 0x00000F00, CORE_SSI_DIV << 8); + /* FSUSB */ + clrsetbits_le32(&p2, 0x00000030, CORE_FUSB_DIV << 4); + /* L4 */ + clrsetbits_le32(&p2, 0x0000000C, CORE_L4_DIV << 2); + /* L3 */ + clrsetbits_le32(&p2, 0x00000003, CORE_L3_DIV); + + p3 = (u32)&prcm_base->idlest_ckgen; + + (*f_lock_pll) (p0, p1, p2, p3); + } +} + +static void dpll4_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + struct dpll_per_36x_param *ptr; + + ptr = (struct dpll_per_36x_param *)get_36x_per_dpll_param(); + + /* Moving it to the right sysclk base */ + ptr += clk_index; + + /* EN_PERIPH_DPLL: CM_CLKEN_PLL[16:18] */ + clrsetbits_le32(&prcm_base->clken_pll, 0x00070000, PLL_STOP << 16); + wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY); + + /* M6 (DIV_DPLL4): CM_CLKSEL1_EMU[24:29] */ + clrsetbits_le32(&prcm_base->clksel1_emu, 0x3F000000, ptr->m6 << 24); + + /* M5 (CLKSEL_CAM): CM_CLKSEL1_EMU[0:5] */ + clrsetbits_le32(&prcm_base->clksel_cam, 0x0000003F, ptr->m5); + + /* M4 (CLKSEL_DSS1): CM_CLKSEL_DSS[0:5] */ + clrsetbits_le32(&prcm_base->clksel_dss, 0x0000003F, ptr->m4); + + /* M3 (CLKSEL_DSS1): CM_CLKSEL_DSS[8:13] */ + clrsetbits_le32(&prcm_base->clksel_dss, 0x00003F00, ptr->m3 << 8); + + /* M2 (DIV_96M): CM_CLKSEL3_PLL[0:4] */ + clrsetbits_le32(&prcm_base->clksel3_pll, 0x0000001F, ptr->m2); + + /* M (PERIPH_DPLL_MULT): CM_CLKSEL2_PLL[8:19] */ + clrsetbits_le32(&prcm_base->clksel2_pll, 0x000FFF00, ptr->m << 8); + + /* N (PERIPH_DPLL_DIV): CM_CLKSEL2_PLL[0:6] */ + clrsetbits_le32(&prcm_base->clksel2_pll, 0x0000007F, ptr->n); + + /* M2DIV (CLKSEL_96M): CM_CLKSEL_CORE[12:13] */ + clrsetbits_le32(&prcm_base->clksel_core, 0x00003000, ptr->m2div << 12); + + /* LOCK MODE (EN_PERIPH_DPLL): CM_CLKEN_PLL[16:18] */ + clrsetbits_le32(&prcm_base->clken_pll, 0x00070000, PLL_LOCK << 16); + wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY); +} + +static void dpll5_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_36x_per2_dpll_param(); + + /* Moving it to the right sysclk base */ + ptr = ptr + clk_index; + + /* PER2 DPLL (DPLL5) */ + clrsetbits_le32(&prcm_base->clken2_pll, 0x00000007, PLL_STOP); + wait_on_value(1, 0, &prcm_base->idlest2_ckgen, LDELAY); + /* set M2 (usbtll_fck) */ + clrsetbits_le32(&prcm_base->clksel5_pll, 0x0000001F, ptr->m2); + /* set m (11-bit multiplier) */ + clrsetbits_le32(&prcm_base->clksel4_pll, 0x0007FF00, ptr->m << 8); + /* set n (7-bit divider)*/ + clrsetbits_le32(&prcm_base->clksel4_pll, 0x0000007F, ptr->n); + /* lock mode */ + clrsetbits_le32(&prcm_base->clken2_pll, 0x00000007, PLL_LOCK); + wait_on_value(1, 1, &prcm_base->idlest2_ckgen, LDELAY); +} + +static void mpu_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_36x_mpu_dpll_param(); + + /* Moving to the right sysclk */ + ptr += clk_index; + + /* MPU DPLL (unlocked already */ + + /* M2 (MPU_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_MPU[0:4] */ + clrsetbits_le32(&prcm_base->clksel2_pll_mpu, 0x0000001F, ptr->m2); + + /* M (MPU_DPLL_MULT) : CM_CLKSEL2_PLL_MPU[8:18] */ + clrsetbits_le32(&prcm_base->clksel1_pll_mpu, 0x0007FF00, ptr->m << 8); + + /* N (MPU_DPLL_DIV) : CM_CLKSEL2_PLL_MPU[0:6] */ + clrsetbits_le32(&prcm_base->clksel1_pll_mpu, 0x0000007F, ptr->n); +} + +static void iva_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *)get_36x_iva_dpll_param(); + + /* Moving to the right sysclk */ + ptr += clk_index; + + /* IVA DPLL */ + /* EN_IVA2_DPLL : CM_CLKEN_PLL_IVA2[0:2] */ + clrsetbits_le32(&prcm_base->clken_pll_iva2, 0x00000007, PLL_STOP); + wait_on_value(ST_IVA2_CLK, 0, &prcm_base->idlest_pll_iva2, LDELAY); + + /* M2 (IVA2_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_IVA2[0:4] */ + clrsetbits_le32(&prcm_base->clksel2_pll_iva2, 0x0000001F, ptr->m2); + + /* M (IVA2_DPLL_MULT) : CM_CLKSEL1_PLL_IVA2[8:18] */ + clrsetbits_le32(&prcm_base->clksel1_pll_iva2, 0x0007FF00, ptr->m << 8); + + /* N (IVA2_DPLL_DIV) : CM_CLKSEL1_PLL_IVA2[0:6] */ + clrsetbits_le32(&prcm_base->clksel1_pll_iva2, 0x0000007F, ptr->n); + + /* LOCK (MODE (EN_IVA2_DPLL) : CM_CLKEN_PLL_IVA2[0:2] */ + clrsetbits_le32(&prcm_base->clken_pll_iva2, 0x00000007, PLL_LOCK); + + wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY); +} + +/****************************************************************************** + * prcm_init() - inits clocks for PRCM as defined in clocks.h + * called from SRAM, or Flash (using temp SRAM stack). + *****************************************************************************/ +void prcm_init(void) +{ + u32 osc_clk = 0, sys_clkin_sel; + u32 clk_index, sil_index = 0; + struct prm *prm_base = (struct prm *)PRM_BASE; + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + + /* + * Gauge the input clock speed and find out the sys_clkin_sel + * value corresponding to the input clock. + */ + osc_clk = get_osc_clk_speed(); + get_sys_clkin_sel(osc_clk, &sys_clkin_sel); + + /* set input crystal speed */ + clrsetbits_le32(&prm_base->clksel, 0x00000007, sys_clkin_sel); + + /* If the input clock is greater than 19.2M always divide/2 */ + if (sys_clkin_sel > 2) { + /* input clock divider */ + clrsetbits_le32(&prm_base->clksrc_ctrl, 0x000000C0, 2 << 6); + clk_index = sys_clkin_sel / 2; + } else { + /* input clock divider */ + clrsetbits_le32(&prm_base->clksrc_ctrl, 0x000000C0, 1 << 6); + clk_index = sys_clkin_sel; + } + + if (get_cpu_family() == CPU_OMAP36XX) { + /* + * In warm reset conditions on OMAP36xx/AM/DM37xx + * the rom code incorrectly sets the DPLL4 clock + * input divider to /6.5. Section 3.5.3.3.3.2.1 of + * the AM/DM37x TRM explains that the /6.5 divider + * is used only when the input clock is 13MHz. + * + * If the part is in this cpu family *and* the input + * clock *is not* 13 MHz, then reset the DPLL4 clock + * input divider to /1 as it should never set to /6.5 + * in this case. + */ + if (sys_clkin_sel != 1) { /* 13 MHz */ + /* Bit 8: DPLL4_CLKINP_DIV */ + clrbits_le32(&prm_base->clksrc_ctrl, 0x00000100); + } + + /* Unlock MPU DPLL (slows things down, and needed later) */ + clrsetbits_le32(&prcm_base->clken_pll_mpu, + 0x00000007, PLL_LOW_POWER_BYPASS); + wait_on_value(ST_MPU_CLK, 0, &prcm_base->idlest_pll_mpu, + LDELAY); + + dpll3_init_36xx(0, clk_index); + dpll4_init_36xx(0, clk_index); + dpll5_init_36xx(0, clk_index); + iva_init_36xx(0, clk_index); + mpu_init_36xx(0, clk_index); + + /* Lock MPU DPLL to set frequency */ + clrsetbits_le32(&prcm_base->clken_pll_mpu, + 0x00000007, PLL_LOCK); + wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, + LDELAY); + } else { + /* + * The DPLL tables are defined according to sysclk value and + * silicon revision. The clk_index value will be used to get + * the values for that input sysclk from the DPLL param table + * and sil_index will get the values for that SysClk for the + * appropriate silicon rev. + */ + if (((get_cpu_family() == CPU_OMAP34XX) + && (get_cpu_rev() >= CPU_3XX_ES20)) || + (get_cpu_family() == CPU_AM35XX)) + sil_index = 1; + + /* Unlock MPU DPLL (slows things down, and needed later) */ + clrsetbits_le32(&prcm_base->clken_pll_mpu, + 0x00000007, PLL_LOW_POWER_BYPASS); + wait_on_value(ST_MPU_CLK, 0, &prcm_base->idlest_pll_mpu, + LDELAY); + + dpll3_init_34xx(sil_index, clk_index); + dpll4_init_34xx(sil_index, clk_index); + dpll5_init_34xx(sil_index, clk_index); + if (get_cpu_family() != CPU_AM35XX) + iva_init_34xx(sil_index, clk_index); + + mpu_init_34xx(sil_index, clk_index); + + /* Lock MPU DPLL to set frequency */ + clrsetbits_le32(&prcm_base->clken_pll_mpu, + 0x00000007, PLL_LOCK); + wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, + LDELAY); + } + + /* Set up GPTimers to sys_clk source only */ + setbits_le32(&prcm_base->clksel_per, 0x000000FF); + setbits_le32(&prcm_base->clksel_wkup, 1); + + sdelay(5000); +} + +/* + * Enable usb ehci uhh, tll clocks + */ +void ehci_clocks_enable(void) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + + /* Enable USBHOST_L3_ICLK (USBHOST_MICLK) */ + setbits_le32(&prcm_base->iclken_usbhost, 1); + /* + * Enable USBHOST_48M_FCLK (USBHOST_FCLK1) + * and USBHOST_120M_FCLK (USBHOST_FCLK2) + */ + setbits_le32(&prcm_base->fclken_usbhost, 0x00000003); + /* Enable USBTTL_ICLK */ + setbits_le32(&prcm_base->iclken3_core, 0x00000004); + /* Enable USBTTL_FCLK */ + setbits_le32(&prcm_base->fclken3_core, 0x00000004); +} + +/****************************************************************************** + * peripheral_enable() - Enable the clks & power for perifs (GPT2, UART1,...) + *****************************************************************************/ +void per_clocks_enable(void) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + + /* Enable GP2 timer. */ + setbits_le32(&prcm_base->clksel_per, 0x01); /* GPT2 = sys clk */ + setbits_le32(&prcm_base->iclken_per, 0x08); /* ICKen GPT2 */ + setbits_le32(&prcm_base->fclken_per, 0x08); /* FCKen GPT2 */ + +#ifdef CONFIG_SYS_NS16550 + /* Enable UART1 clocks */ + setbits_le32(&prcm_base->fclken1_core, 0x00002000); + setbits_le32(&prcm_base->iclken1_core, 0x00002000); + + /* UART 3 Clocks */ + setbits_le32(&prcm_base->fclken_per, 0x00000800); + setbits_le32(&prcm_base->iclken_per, 0x00000800); +#endif + +#ifdef CONFIG_OMAP3_GPIO_2 + setbits_le32(&prcm_base->fclken_per, 0x00002000); + setbits_le32(&prcm_base->iclken_per, 0x00002000); +#endif +#ifdef CONFIG_OMAP3_GPIO_3 + setbits_le32(&prcm_base->fclken_per, 0x00004000); + setbits_le32(&prcm_base->iclken_per, 0x00004000); +#endif +#ifdef CONFIG_OMAP3_GPIO_4 + setbits_le32(&prcm_base->fclken_per, 0x00008000); + setbits_le32(&prcm_base->iclken_per, 0x00008000); +#endif +#ifdef CONFIG_OMAP3_GPIO_5 + setbits_le32(&prcm_base->fclken_per, 0x00010000); + setbits_le32(&prcm_base->iclken_per, 0x00010000); +#endif +#ifdef CONFIG_OMAP3_GPIO_6 + setbits_le32(&prcm_base->fclken_per, 0x00020000); + setbits_le32(&prcm_base->iclken_per, 0x00020000); +#endif + +#ifdef CONFIG_SYS_I2C_OMAP34XX + /* Turn on all 3 I2C clocks */ + setbits_le32(&prcm_base->fclken1_core, 0x00038000); + setbits_le32(&prcm_base->iclken1_core, 0x00038000); /* I2C1,2,3 = on */ +#endif + /* Enable the ICLK for 32K Sync Timer as its used in udelay */ + setbits_le32(&prcm_base->iclken_wkup, 0x00000004); + + if (get_cpu_family() != CPU_AM35XX) + out_le32(&prcm_base->fclken_iva2, FCK_IVA2_ON); + + out_le32(&prcm_base->fclken1_core, FCK_CORE1_ON); + out_le32(&prcm_base->iclken1_core, ICK_CORE1_ON); + out_le32(&prcm_base->iclken2_core, ICK_CORE2_ON); + out_le32(&prcm_base->fclken_wkup, FCK_WKUP_ON); + out_le32(&prcm_base->iclken_wkup, ICK_WKUP_ON); + out_le32(&prcm_base->fclken_dss, FCK_DSS_ON); + out_le32(&prcm_base->iclken_dss, ICK_DSS_ON); + if (get_cpu_family() != CPU_AM35XX) { + out_le32(&prcm_base->fclken_cam, FCK_CAM_ON); + out_le32(&prcm_base->iclken_cam, ICK_CAM_ON); + } + + sdelay(1000); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/config.mk b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/config.mk new file mode 100644 index 000000000..ad44d6384 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/config.mk @@ -0,0 +1,15 @@ +# +# Copyright 2011 Linaro Limited +# +# (C) Copyright 2010 +# Texas Instruments, <www.ti.com> +# +# Aneesh V <aneesh@ti.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# +ifdef CONFIG_SPL_BUILD +ALL-y += MLO +else +ALL-y += u-boot.img +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/emac.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/emac.c new file mode 100644 index 000000000..37f4b8b49 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/emac.c @@ -0,0 +1,29 @@ +/* + * + * DaVinci EMAC initialization. + * + * (C) Copyright 2011, Ilya Yanok, Emcraft Systems + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/am35x_def.h> + +/* + * Initializes on-chip ethernet controllers. + * to override, implement board_eth_init() + */ +int cpu_eth_init(bd_t *bis) +{ + u32 reset; + + /* ensure that the module is out of reset */ + reset = readl(&am35x_scm_general_regs->ip_sw_reset); + reset &= ~CPGMACSS_SW_RST; + writel(reset, &am35x_scm_general_regs->ip_sw_reset); + + return davinci_emac_initialize(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/emif4.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/emif4.c new file mode 100644 index 000000000..6c7330a0c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/emif4.c @@ -0,0 +1,165 @@ +/* + * Author : + * Vaibhav Hiremath <hvaibhav@ti.com> + * + * Based on mem.c and sdrc.c + * + * Copyright (C) 2010 + * Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/mem.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/emif4.h> + +DECLARE_GLOBAL_DATA_PTR; +extern omap3_sysinfo sysinfo; + +static emif4_t *emif4_base = (emif4_t *)OMAP34XX_SDRC_BASE; + +/* + * is_mem_sdr - + * - Return 1 if mem type in use is SDR + */ +u32 is_mem_sdr(void) +{ + return 0; +} + +/* + * get_sdr_cs_size - + * - Get size of chip select 0/1 + */ +u32 get_sdr_cs_size(u32 cs) +{ + u32 size = 0; + + /* TODO: Calculate the size based on EMIF4 configuration */ + if (cs == CS0) + size = CONFIG_SYS_CS0_SIZE; + + return size; +} + +/* + * get_sdr_cs_offset - + * - Get offset of cs from cs0 start + */ +u32 get_sdr_cs_offset(u32 cs) +{ + u32 offset = 0; + + return offset; +} + +/* + * do_emif4_init - + * - Init the emif4 module for DDR access + * - Early init routines, called from flash or SRAM. + */ +void do_emif4_init(void) +{ + unsigned int regval; + /* Set the DDR PHY parameters in PHY ctrl registers */ + regval = (EMIF4_DDR1_READ_LAT | EMIF4_DDR1_PWRDN_DIS | + EMIF4_DDR1_EXT_STRB_DIS); + writel(regval, &emif4_base->ddr_phyctrl1); + writel(regval, &emif4_base->ddr_phyctrl1_shdw); + writel(0, &emif4_base->ddr_phyctrl2); + + /* Reset the DDR PHY and wait till completed */ + regval = readl(&emif4_base->sdram_iodft_tlgc); + regval |= (1<<10); + writel(regval, &emif4_base->sdram_iodft_tlgc); + /*Wait till that bit clears*/ + while ((readl(&emif4_base->sdram_iodft_tlgc) & (1<<10)) == 0x1); + /*Re-verify the DDR PHY status*/ + while ((readl(&emif4_base->sdram_sts) & (1<<2)) == 0x0); + + regval |= (1<<0); + writel(regval, &emif4_base->sdram_iodft_tlgc); + /* Set SDR timing registers */ + regval = (EMIF4_TIM1_T_WTR | EMIF4_TIM1_T_RRD | + EMIF4_TIM1_T_RC | EMIF4_TIM1_T_RAS | + EMIF4_TIM1_T_WR | EMIF4_TIM1_T_RCD | + EMIF4_TIM1_T_RP); + writel(regval, &emif4_base->sdram_time1); + writel(regval, &emif4_base->sdram_time1_shdw); + + regval = (EMIF4_TIM2_T_CKE | EMIF4_TIM2_T_RTP | + EMIF4_TIM2_T_XSRD | EMIF4_TIM2_T_XSNR | + EMIF4_TIM2_T_ODT | EMIF4_TIM2_T_XP); + writel(regval, &emif4_base->sdram_time2); + writel(regval, &emif4_base->sdram_time2_shdw); + + regval = (EMIF4_TIM3_T_RAS_MAX | EMIF4_TIM3_T_RFC); + writel(regval, &emif4_base->sdram_time3); + writel(regval, &emif4_base->sdram_time3_shdw); + + /* Set the PWR control register */ + regval = (EMIF4_PWR_PM_TIM | EMIF4_PWR_LP_MODE | + EMIF4_PWR_DPD_DIS | EMIF4_PWR_IDLE_MODE); + writel(regval, &emif4_base->sdram_pwr_mgmt); + writel(regval, &emif4_base->sdram_pwr_mgmt_shdw); + + /* Set the DDR refresh rate control register */ + regval = (EMIF4_REFRESH_RATE | EMIF4_INITREF_DIS); + writel(regval, &emif4_base->sdram_refresh_ctrl); + writel(regval, &emif4_base->sdram_refresh_ctrl_shdw); + + /* set the SDRAM configuration register */ + regval = (EMIF4_CFG_PGSIZE | EMIF4_CFG_EBANK | + EMIF4_CFG_IBANK | EMIF4_CFG_ROWSIZE | + EMIF4_CFG_CL | EMIF4_CFG_NARROW_MD | + EMIF4_CFG_SDR_DRV | EMIF4_CFG_DDR_DIS_DLL | + EMIF4_CFG_DDR2_DDQS | EMIF4_CFG_DDR_TERM | + EMIF4_CFG_IBANK_POS | EMIF4_CFG_SDRAM_TYP); + writel(regval, &emif4_base->sdram_config); +} + +/* + * dram_init - + * - Sets uboots idea of sdram size + */ +int dram_init(void) +{ + unsigned int size0 = 0, size1 = 0; + + size0 = get_sdr_cs_size(CS0); + /* + * If a second bank of DDR is attached to CS1 this is + * where it can be started. Early init code will init + * memory on CS0. + */ + if ((sysinfo.mtype == DDR_COMBO) || (sysinfo.mtype == DDR_STACKED)) + size1 = get_sdr_cs_size(CS1); + + gd->ram_size = size0 + size1; + return 0; +} + +void dram_init_banksize (void) +{ + unsigned int size0 = 0, size1 = 0; + + size0 = get_sdr_cs_size(CS0); + size1 = get_sdr_cs_size(CS1); + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = size0; + gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + get_sdr_cs_offset(CS1); + gd->bd->bi_dram[1].size = size1; +} + +/* + * mem_init() - + * - Initialize memory subsystem + */ +void mem_init(void) +{ + do_emif4_init(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/lowlevel_init.S new file mode 100644 index 000000000..78577b1d1 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/lowlevel_init.S @@ -0,0 +1,498 @@ +/* + * Board specific setup info + * + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Initial Code by: + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <version.h> +#include <asm/arch/mem.h> +#include <asm/arch/clocks_omap3.h> +#include <linux/linkage.h> + +#ifdef CONFIG_SPL_BUILD +ENTRY(save_boot_params) + ldr r4, =omap3_boot_device + ldr r5, [r0, #0x4] + and r5, r5, #0xff + str r5, [r4] + bx lr +ENDPROC(save_boot_params) +#endif + +ENTRY(omap3_gp_romcode_call) + PUSH {r4-r12, lr} @ Save all registers from ROM code! + MOV r12, r0 @ Copy the Service ID in R12 + MOV r0, r1 @ Copy parameter to R0 + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c10, 5 @ DMB + .word 0xe1600070 @ SMC #0 to enter monitor - hand assembled + @ because we use -march=armv5 + POP {r4-r12, pc} +ENDPROC(omap3_gp_romcode_call) + +/* + * Funtion for making PPA HAL API calls in secure devices + * Input: + * R0 - Service ID + * R1 - paramer list + */ +ENTRY(do_omap3_emu_romcode_call) + PUSH {r4-r12, lr} @ Save all registers from ROM code! + MOV r12, r0 @ Copy the Secure Service ID in R12 + MOV r3, r1 @ Copy the pointer to va_list in R3 + MOV r1, #0 @ Process ID - 0 + MOV r2, #OMAP3_EMU_HAL_START_HAL_CRITICAL @ Copy the pointer + @ to va_list in R3 + MOV r6, #0xFF @ Indicate new Task call + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c10, 5 @ DMB + .word 0xe1600071 @ SMC #1 to call PPA service - hand assembled + @ because we use -march=armv5 + POP {r4-r12, pc} +ENDPROC(do_omap3_emu_romcode_call) + +#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_NAND_BOOT) +/************************************************************************** + * cpy_clk_code: relocates clock code into SRAM where its safer to execute + * R1 = SRAM destination address. + *************************************************************************/ +ENTRY(cpy_clk_code) + /* Copy DPLL code into SRAM */ + adr r0, go_to_speed /* copy from start of go_to_speed... */ + adr r2, lowlevel_init /* ... up to start of low_level_init */ +next2: + ldmia r0!, {r3 - r10} /* copy from source address [r0] */ + stmia r1!, {r3 - r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end address [r2] */ + blo next2 + mov pc, lr /* back to caller */ +ENDPROC(cpy_clk_code) + +/* *************************************************************************** + * go_to_speed: -Moves to bypass, -Commits clock dividers, -puts dpll at speed + * -executed from SRAM. + * R0 = CM_CLKEN_PLL-bypass value + * R1 = CM_CLKSEL1_PLL-m, n, and divider values + * R2 = CM_CLKSEL_CORE-divider values + * R3 = CM_IDLEST_CKGEN - addr dpll lock wait + * + * Note: If core unlocks/relocks and SDRAM is running fast already it gets + * confused. A reset of the controller gets it back. Taking away its + * L3 when its not in self refresh seems bad for it. Normally, this + * code runs from flash before SDR is init so that should be ok. + ****************************************************************************/ +ENTRY(go_to_speed) + stmfd sp!, {r4 - r6} + + /* move into fast relock bypass */ + ldr r4, pll_ctl_add + str r0, [r4] +wait1: + ldr r5, [r3] /* get status */ + and r5, r5, #0x1 /* isolate core status */ + cmp r5, #0x1 /* still locked? */ + beq wait1 /* if lock, loop */ + + /* set new dpll dividers _after_ in bypass */ + ldr r5, pll_div_add1 + str r1, [r5] /* set m, n, m2 */ + ldr r5, pll_div_add2 + str r2, [r5] /* set l3/l4/.. dividers*/ + ldr r5, pll_div_add3 /* wkup */ + ldr r2, pll_div_val3 /* rsm val */ + str r2, [r5] + ldr r5, pll_div_add4 /* gfx */ + ldr r2, pll_div_val4 + str r2, [r5] + ldr r5, pll_div_add5 /* emu */ + ldr r2, pll_div_val5 + str r2, [r5] + + /* now prepare GPMC (flash) for new dpll speed */ + /* flash needs to be stable when we jump back to it */ + ldr r5, flash_cfg3_addr + ldr r2, flash_cfg3_val + str r2, [r5] + ldr r5, flash_cfg4_addr + ldr r2, flash_cfg4_val + str r2, [r5] + ldr r5, flash_cfg5_addr + ldr r2, flash_cfg5_val + str r2, [r5] + ldr r5, flash_cfg1_addr + ldr r2, [r5] + orr r2, r2, #0x3 /* up gpmc divider */ + str r2, [r5] + + /* lock DPLL3 and wait a bit */ + orr r0, r0, #0x7 /* set up for lock mode */ + str r0, [r4] /* lock */ + nop /* ARM slow at this point working at sys_clk */ + nop + nop + nop +wait2: + ldr r5, [r3] /* get status */ + and r5, r5, #0x1 /* isolate core status */ + cmp r5, #0x1 /* still locked? */ + bne wait2 /* if lock, loop */ + nop + nop + nop + nop + ldmfd sp!, {r4 - r6} + mov pc, lr /* back to caller, locked */ +ENDPROC(go_to_speed) + +_go_to_speed: .word go_to_speed + +/* these constants need to be close for PIC code */ +/* The Nor has to be in the Flash Base CS0 for this condition to happen */ +flash_cfg1_addr: + .word (GPMC_CONFIG_CS0_BASE + GPMC_CONFIG1) +flash_cfg3_addr: + .word (GPMC_CONFIG_CS0_BASE + GPMC_CONFIG3) +flash_cfg3_val: + .word STNOR_GPMC_CONFIG3 +flash_cfg4_addr: + .word (GPMC_CONFIG_CS0_BASE + GPMC_CONFIG4) +flash_cfg4_val: + .word STNOR_GPMC_CONFIG4 +flash_cfg5_val: + .word STNOR_GPMC_CONFIG5 +flash_cfg5_addr: + .word (GPMC_CONFIG_CS0_BASE + GPMC_CONFIG5) +pll_ctl_add: + .word CM_CLKEN_PLL +pll_div_add1: + .word CM_CLKSEL1_PLL +pll_div_add2: + .word CM_CLKSEL_CORE +pll_div_add3: + .word CM_CLKSEL_WKUP +pll_div_val3: + .word (WKUP_RSM << 1) +pll_div_add4: + .word CM_CLKSEL_GFX +pll_div_val4: + .word (GFX_DIV << 0) +pll_div_add5: + .word CM_CLKSEL1_EMU +pll_div_val5: + .word CLSEL1_EMU_VAL + +#endif + +ENTRY(lowlevel_init) + ldr sp, SRAM_STACK + str ip, [sp] /* stash ip register */ + mov ip, lr /* save link reg across call */ +#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT) +/* + * No need to copy/exec the clock code - DPLL adjust already done + * in NAND/oneNAND Boot. + */ + ldr r1, =SRAM_CLK_CODE + bl cpy_clk_code +#endif /* NAND Boot */ + mov lr, ip /* restore link reg */ + ldr ip, [sp] /* restore save ip */ + /* tail-call s_init to setup pll, mux, memory */ + b s_init + +ENDPROC(lowlevel_init) + + /* the literal pools origin */ + .ltorg + +REG_CONTROL_STATUS: + .word CONTROL_STATUS +SRAM_STACK: + .word LOW_LEVEL_SRAM_STACK + +/* DPLL(1-4) PARAM TABLES */ + +/* + * Each of the tables has M, N, FREQSEL, M2 values defined for nominal + * OPP (1.2V). The fields are defined according to dpll_param struct (clock.c). + * The values are defined for all possible sysclk and for ES1 and ES2. + */ + +mpu_dpll_param: +/* 12MHz */ +/* ES1 */ +.word MPU_M_12_ES1, MPU_N_12_ES1, MPU_FSEL_12_ES1, MPU_M2_12_ES1 +/* ES2 */ +.word MPU_M_12_ES2, MPU_N_12_ES2, MPU_FSEL_12_ES2, MPU_M2_ES2 +/* 3410 */ +.word MPU_M_12, MPU_N_12, MPU_FSEL_12, MPU_M2_12 + +/* 13MHz */ +/* ES1 */ +.word MPU_M_13_ES1, MPU_N_13_ES1, MPU_FSEL_13_ES1, MPU_M2_13_ES1 +/* ES2 */ +.word MPU_M_13_ES2, MPU_N_13_ES2, MPU_FSEL_13_ES2, MPU_M2_13_ES2 +/* 3410 */ +.word MPU_M_13, MPU_N_13, MPU_FSEL_13, MPU_M2_13 + +/* 19.2MHz */ +/* ES1 */ +.word MPU_M_19P2_ES1, MPU_N_19P2_ES1, MPU_FSEL_19P2_ES1, MPU_M2_19P2_ES1 +/* ES2 */ +.word MPU_M_19P2_ES2, MPU_N_19P2_ES2, MPU_FSEL_19P2_ES2, MPU_M2_19P2_ES2 +/* 3410 */ +.word MPU_M_19P2, MPU_N_19P2, MPU_FSEL_19P2, MPU_M2_19P2 + +/* 26MHz */ +/* ES1 */ +.word MPU_M_26_ES1, MPU_N_26_ES1, MPU_FSEL_26_ES1, MPU_M2_26_ES1 +/* ES2 */ +.word MPU_M_26_ES2, MPU_N_26_ES2, MPU_FSEL_26_ES2, MPU_M2_26_ES2 +/* 3410 */ +.word MPU_M_26, MPU_N_26, MPU_FSEL_26, MPU_M2_26 + +/* 38.4MHz */ +/* ES1 */ +.word MPU_M_38P4_ES1, MPU_N_38P4_ES1, MPU_FSEL_38P4_ES1, MPU_M2_38P4_ES1 +/* ES2 */ +.word MPU_M_38P4_ES2, MPU_N_38P4_ES2, MPU_FSEL_38P4_ES2, MPU_M2_38P4_ES2 +/* 3410 */ +.word MPU_M_38P4, MPU_N_38P4, MPU_FSEL_38P4, MPU_M2_38P4 + + +.globl get_mpu_dpll_param +get_mpu_dpll_param: + adr r0, mpu_dpll_param + mov pc, lr + +iva_dpll_param: +/* 12MHz */ +/* ES1 */ +.word IVA_M_12_ES1, IVA_N_12_ES1, IVA_FSEL_12_ES1, IVA_M2_12_ES1 +/* ES2 */ +.word IVA_M_12_ES2, IVA_N_12_ES2, IVA_FSEL_12_ES2, IVA_M2_12_ES2 +/* 3410 */ +.word IVA_M_12, IVA_N_12, IVA_FSEL_12, IVA_M2_12 + +/* 13MHz */ +/* ES1 */ +.word IVA_M_13_ES1, IVA_N_13_ES1, IVA_FSEL_13_ES1, IVA_M2_13_ES1 +/* ES2 */ +.word IVA_M_13_ES2, IVA_N_13_ES2, IVA_FSEL_13_ES2, IVA_M2_13_ES2 +/* 3410 */ +.word IVA_M_13, IVA_N_13, IVA_FSEL_13, IVA_M2_13 + +/* 19.2MHz */ +/* ES1 */ +.word IVA_M_19P2_ES1, IVA_N_19P2_ES1, IVA_FSEL_19P2_ES1, IVA_M2_19P2_ES1 +/* ES2 */ +.word IVA_M_19P2_ES2, IVA_N_19P2_ES2, IVA_FSEL_19P2_ES2, IVA_M2_19P2_ES2 +/* 3410 */ +.word IVA_M_19P2, IVA_N_19P2, IVA_FSEL_19P2, IVA_M2_19P2 + +/* 26MHz */ +/* ES1 */ +.word IVA_M_26_ES1, IVA_N_26_ES1, IVA_FSEL_26_ES1, IVA_M2_26_ES1 +/* ES2 */ +.word IVA_M_26_ES2, IVA_N_26_ES2, IVA_FSEL_26_ES2, IVA_M2_26_ES2 +/* 3410 */ +.word IVA_M_26, IVA_N_26, IVA_FSEL_26, IVA_M2_26 + +/* 38.4MHz */ +/* ES1 */ +.word IVA_M_38P4_ES1, IVA_N_38P4_ES1, IVA_FSEL_38P4_ES1, IVA_M2_38P4_ES1 +/* ES2 */ +.word IVA_M_38P4_ES2, IVA_N_38P4_ES2, IVA_FSEL_38P4_ES2, IVA_M2_38P4_ES2 +/* 3410 */ +.word IVA_M_38P4, IVA_N_38P4, IVA_FSEL_38P4, IVA_M2_38P4 + + +.globl get_iva_dpll_param +get_iva_dpll_param: + adr r0, iva_dpll_param + mov pc, lr + +/* Core DPLL targets for L3 at 166 & L133 */ +core_dpll_param: +/* 12MHz */ +/* ES1 */ +.word CORE_M_12_ES1, CORE_N_12_ES1, CORE_FSL_12_ES1, CORE_M2_12_ES1 +/* ES2 */ +.word CORE_M_12, CORE_N_12, CORE_FSEL_12, CORE_M2_12 +/* 3410 */ +.word CORE_M_12, CORE_N_12, CORE_FSEL_12, CORE_M2_12 + +/* 13MHz */ +/* ES1 */ +.word CORE_M_13_ES1, CORE_N_13_ES1, CORE_FSL_13_ES1, CORE_M2_13_ES1 +/* ES2 */ +.word CORE_M_13, CORE_N_13, CORE_FSEL_13, CORE_M2_13 +/* 3410 */ +.word CORE_M_13, CORE_N_13, CORE_FSEL_13, CORE_M2_13 + +/* 19.2MHz */ +/* ES1 */ +.word CORE_M_19P2_ES1, CORE_N_19P2_ES1, CORE_FSL_19P2_ES1, CORE_M2_19P2_ES1 +/* ES2 */ +.word CORE_M_19P2, CORE_N_19P2, CORE_FSEL_19P2, CORE_M2_19P2 +/* 3410 */ +.word CORE_M_19P2, CORE_N_19P2, CORE_FSEL_19P2, CORE_M2_19P2 + +/* 26MHz */ +/* ES1 */ +.word CORE_M_26_ES1, CORE_N_26_ES1, CORE_FSL_26_ES1, CORE_M2_26_ES1 +/* ES2 */ +.word CORE_M_26, CORE_N_26, CORE_FSEL_26, CORE_M2_26 +/* 3410 */ +.word CORE_M_26, CORE_N_26, CORE_FSEL_26, CORE_M2_26 + +/* 38.4MHz */ +/* ES1 */ +.word CORE_M_38P4_ES1, CORE_N_38P4_ES1, CORE_FSL_38P4_ES1, CORE_M2_38P4_ES1 +/* ES2 */ +.word CORE_M_38P4, CORE_N_38P4, CORE_FSEL_38P4, CORE_M2_38P4 +/* 3410 */ +.word CORE_M_38P4, CORE_N_38P4, CORE_FSEL_38P4, CORE_M2_38P4 + +.globl get_core_dpll_param +get_core_dpll_param: + adr r0, core_dpll_param + mov pc, lr + +/* PER DPLL values are same for both ES1 and ES2 */ +per_dpll_param: +/* 12MHz */ +.word PER_M_12, PER_N_12, PER_FSEL_12, PER_M2_12 + +/* 13MHz */ +.word PER_M_13, PER_N_13, PER_FSEL_13, PER_M2_13 + +/* 19.2MHz */ +.word PER_M_19P2, PER_N_19P2, PER_FSEL_19P2, PER_M2_19P2 + +/* 26MHz */ +.word PER_M_26, PER_N_26, PER_FSEL_26, PER_M2_26 + +/* 38.4MHz */ +.word PER_M_38P4, PER_N_38P4, PER_FSEL_38P4, PER_M2_38P4 + +.globl get_per_dpll_param +get_per_dpll_param: + adr r0, per_dpll_param + mov pc, lr + +/* PER2 DPLL values */ +per2_dpll_param: +/* 12MHz */ +.word PER2_M_12, PER2_N_12, PER2_FSEL_12, PER2_M2_12 + +/* 13MHz */ +.word PER2_M_13, PER2_N_13, PER2_FSEL_13, PER2_M2_13 + +/* 19.2MHz */ +.word PER2_M_19P2, PER2_N_19P2, PER2_FSEL_19P2, PER2_M2_19P2 + +/* 26MHz */ +.word PER2_M_26, PER2_N_26, PER2_FSEL_26, PER2_M2_26 + +/* 38.4MHz */ +.word PER2_M_38P4, PER2_N_38P4, PER2_FSEL_38P4, PER2_M2_38P4 + +.globl get_per2_dpll_param +get_per2_dpll_param: + adr r0, per2_dpll_param + mov pc, lr + +/* + * Tables for 36XX/37XX devices + * + */ +mpu_36x_dpll_param: +/* 12MHz */ +.word 50, 0, 0, 1 +/* 13MHz */ +.word 600, 12, 0, 1 +/* 19.2MHz */ +.word 125, 3, 0, 1 +/* 26MHz */ +.word 300, 12, 0, 1 +/* 38.4MHz */ +.word 125, 7, 0, 1 + +iva_36x_dpll_param: +/* 12MHz */ +.word 130, 2, 0, 1 +/* 13MHz */ +.word 20, 0, 0, 1 +/* 19.2MHz */ +.word 325, 11, 0, 1 +/* 26MHz */ +.word 10, 0, 0, 1 +/* 38.4MHz */ +.word 325, 23, 0, 1 + +core_36x_dpll_param: +/* 12MHz */ +.word 100, 2, 0, 1 +/* 13MHz */ +.word 400, 12, 0, 1 +/* 19.2MHz */ +.word 375, 17, 0, 1 +/* 26MHz */ +.word 200, 12, 0, 1 +/* 38.4MHz */ +.word 375, 35, 0, 1 + +per_36x_dpll_param: +/* SYSCLK M N M2 M3 M4 M5 M6 m2DIV */ +.word 12000, 360, 4, 9, 16, 5, 4, 3, 1 +.word 13000, 864, 12, 9, 16, 9, 4, 3, 1 +.word 19200, 360, 7, 9, 16, 5, 4, 3, 1 +.word 26000, 432, 12, 9, 16, 9, 4, 3, 1 +.word 38400, 360, 15, 9, 16, 5, 4, 3, 1 + +per2_36x_dpll_param: +/* 12MHz */ +.word PER2_36XX_M_12, PER2_36XX_N_12, 0, PER2_36XX_M2_12 +/* 13MHz */ +.word PER2_36XX_M_13, PER2_36XX_N_13, 0, PER2_36XX_M2_13 +/* 19.2MHz */ +.word PER2_36XX_M_19P2, PER2_36XX_N_19P2, 0, PER2_36XX_M2_19P2 +/* 26MHz */ +.word PER2_36XX_M_26, PER2_36XX_N_26, 0, PER2_36XX_M2_26 +/* 38.4MHz */ +.word PER2_36XX_M_38P4, PER2_36XX_N_38P4, 0, PER2_36XX_M2_38P4 + + +ENTRY(get_36x_mpu_dpll_param) + adr r0, mpu_36x_dpll_param + mov pc, lr +ENDPROC(get_36x_mpu_dpll_param) + +ENTRY(get_36x_iva_dpll_param) + adr r0, iva_36x_dpll_param + mov pc, lr +ENDPROC(get_36x_iva_dpll_param) + +ENTRY(get_36x_core_dpll_param) + adr r0, core_36x_dpll_param + mov pc, lr +ENDPROC(get_36x_core_dpll_param) + +ENTRY(get_36x_per_dpll_param) + adr r0, per_36x_dpll_param + mov pc, lr +ENDPROC(get_36x_per_dpll_param) + +ENTRY(get_36x_per2_dpll_param) + adr r0, per2_36x_dpll_param + mov pc, lr +ENDPROC(get_36x_per2_dpll_param) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/mem.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/mem.c new file mode 100644 index 000000000..e64940965 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/mem.c @@ -0,0 +1,151 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Author : + * Manikandan Pillai <mani.pillai@ti.com> + * + * Initial Code from: + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/mem.h> +#include <asm/arch/sys_proto.h> +#include <command.h> + +struct gpmc *gpmc_cfg; + +#if defined(CONFIG_CMD_NAND) +#if defined(GPMC_NAND_ECC_SP_x8_LAYOUT) || defined(GPMC_NAND_ECC_LP_x8_LAYOUT) +static const u32 gpmc_m_nand[GPMC_MAX_REG] = { + SMNAND_GPMC_CONFIG1, + SMNAND_GPMC_CONFIG2, + SMNAND_GPMC_CONFIG3, + SMNAND_GPMC_CONFIG4, + SMNAND_GPMC_CONFIG5, + SMNAND_GPMC_CONFIG6, + 0, +}; +#else +static const u32 gpmc_m_nand[GPMC_MAX_REG] = { + M_NAND_GPMC_CONFIG1, + M_NAND_GPMC_CONFIG2, + M_NAND_GPMC_CONFIG3, + M_NAND_GPMC_CONFIG4, + M_NAND_GPMC_CONFIG5, + M_NAND_GPMC_CONFIG6, 0 +}; +#endif +#endif /* CONFIG_CMD_NAND */ + +#if defined(CONFIG_CMD_ONENAND) +static const u32 gpmc_onenand[GPMC_MAX_REG] = { + ONENAND_GPMC_CONFIG1, + ONENAND_GPMC_CONFIG2, + ONENAND_GPMC_CONFIG3, + ONENAND_GPMC_CONFIG4, + ONENAND_GPMC_CONFIG5, + ONENAND_GPMC_CONFIG6, 0 +}; +#endif /* CONFIG_CMD_ONENAND */ + +/******************************************************** + * mem_ok() - test used to see if timings are correct + * for a part. Helps in guessing which part + * we are currently using. + *******************************************************/ +u32 mem_ok(u32 cs) +{ + u32 val1, val2, addr; + u32 pattern = 0x12345678; + + addr = OMAP34XX_SDRC_CS0 + get_sdr_cs_offset(cs); + + writel(0x0, addr + 0x400); /* clear pos A */ + writel(pattern, addr); /* pattern to pos B */ + writel(0x0, addr + 4); /* remove pattern off the bus */ + val1 = readl(addr + 0x400); /* get pos A value */ + val2 = readl(addr); /* get val2 */ + writel(0x0, addr + 0x400); /* clear pos A */ + + if ((val1 != 0) || (val2 != pattern)) /* see if pos A val changed */ + return 0; + else + return 1; +} + +void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base, + u32 size) +{ + writel(0, &cs->config7); + sdelay(1000); + /* Delay for settling */ + writel(gpmc_config[0], &cs->config1); + writel(gpmc_config[1], &cs->config2); + writel(gpmc_config[2], &cs->config3); + writel(gpmc_config[3], &cs->config4); + writel(gpmc_config[4], &cs->config5); + writel(gpmc_config[5], &cs->config6); + + /* + * Enable the config. size is the CS size and goes in + * bits 11:8. We set bit 6 to enable this CS and the base + * address goes into bits 5:0. + */ + writel((size << 8) | (GPMC_CS_ENABLE << 6) | + ((base >> 24) & GPMC_BASEADDR_MASK), + &cs->config7); + sdelay(2000); +} + +/***************************************************** + * gpmc_init(): init gpmc bus + * Init GPMC for x16, MuxMode (SDRAM in x32). + * This code can only be executed from SRAM or SDRAM. + *****************************************************/ +void gpmc_init(void) +{ + /* putting a blanket check on GPMC based on ZeBu for now */ + gpmc_cfg = (struct gpmc *)GPMC_BASE; +#if defined(CONFIG_CMD_NAND) || defined(CONFIG_CMD_ONENAND) + const u32 *gpmc_config = NULL; + u32 base = 0; + u32 size = 0; +#endif + u32 config = 0; + + /* global settings */ + writel(0, &gpmc_cfg->irqenable); /* isr's sources masked */ + writel(0, &gpmc_cfg->timeout_control);/* timeout disable */ + + config = readl(&gpmc_cfg->config); + config &= (~0xf00); + writel(config, &gpmc_cfg->config); + + /* + * Disable the GPMC0 config set by ROM code + * It conflicts with our MPDB (both at 0x08000000) + */ + writel(0, &gpmc_cfg->cs[0].config7); + sdelay(1000); + +#if defined(CONFIG_CMD_NAND) /* CS 0 */ + gpmc_config = gpmc_m_nand; + + base = PISMO1_NAND_BASE; + size = PISMO1_NAND_SIZE; + enable_gpmc_cs_config(gpmc_config, &gpmc_cfg->cs[0], base, size); +#endif + +#if defined(CONFIG_CMD_ONENAND) + gpmc_config = gpmc_onenand; + base = PISMO1_ONEN_BASE; + size = PISMO1_ONEN_SIZE; + enable_gpmc_cs_config(gpmc_config, &gpmc_cfg->cs[0], base, size); +#endif +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/sdrc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/sdrc.c new file mode 100644 index 000000000..7a291318a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/sdrc.c @@ -0,0 +1,237 @@ +/* + * Functions related to OMAP3 SDRC. + * + * This file has been created after exctracting and consolidating + * the SDRC related content from mem.c and board.c, also created + * generic init function (mem_init). + * + * Copyright (C) 2004-2010 + * Texas Instruments Incorporated - http://www.ti.com/ + * + * Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de> + * + * Author : + * Vaibhav Hiremath <hvaibhav@ti.com> + * + * Original implementation by (mem.c, board.c) : + * Sunil Kumar <sunilsaini05@gmail.com> + * Shashi Ranjan <shashiranjanmca05@gmail.com> + * Manikandan Pillai <mani.pillai@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/mem.h> +#include <asm/arch/sys_proto.h> + +DECLARE_GLOBAL_DATA_PTR; +extern omap3_sysinfo sysinfo; + +static struct sdrc *sdrc_base = (struct sdrc *)OMAP34XX_SDRC_BASE; + +/* + * is_mem_sdr - + * - Return 1 if mem type in use is SDR + */ +u32 is_mem_sdr(void) +{ + if (readl(&sdrc_base->cs[CS0].mr) == SDRC_MR_0_SDR) + return 1; + return 0; +} + +/* + * make_cs1_contiguous - + * - When we have CS1 populated we want to have it mapped after cs0 to allow + * command line mem=xyz use all memory with out discontinuous support + * compiled in. We could do it in the ATAG, but there really is two banks... + */ +void make_cs1_contiguous(void) +{ + u32 size, a_add_low, a_add_high; + + size = get_sdr_cs_size(CS0); + size >>= 25; /* divide by 32 MiB to find size to offset CS1 */ + a_add_high = (size & 3) << 8; /* set up low field */ + a_add_low = (size & 0x3C) >> 2; /* set up high field */ + writel((a_add_high | a_add_low), &sdrc_base->cs_cfg); + +} + + +/* + * get_sdr_cs_size - + * - Get size of chip select 0/1 + */ +u32 get_sdr_cs_size(u32 cs) +{ + u32 size; + + /* get ram size field */ + size = readl(&sdrc_base->cs[cs].mcfg) >> 8; + size &= 0x3FF; /* remove unwanted bits */ + size <<= 21; /* multiply by 2 MiB to find size in MB */ + return size; +} + +/* + * get_sdr_cs_offset - + * - Get offset of cs from cs0 start + */ +u32 get_sdr_cs_offset(u32 cs) +{ + u32 offset; + + if (!cs) + return 0; + + offset = readl(&sdrc_base->cs_cfg); + offset = (offset & 15) << 27 | (offset & 0x300) << 17; + + return offset; +} + +/* + * write_sdrc_timings - + * - Takes CS and associated timings and initalize SDRAM + * - Test CS to make sure it's OK for use + */ +static void write_sdrc_timings(u32 cs, struct sdrc_actim *sdrc_actim_base, + struct board_sdrc_timings *timings) +{ + /* Setup timings we got from the board. */ + writel(timings->mcfg, &sdrc_base->cs[cs].mcfg); + writel(timings->ctrla, &sdrc_actim_base->ctrla); + writel(timings->ctrlb, &sdrc_actim_base->ctrlb); + writel(timings->rfr_ctrl, &sdrc_base->cs[cs].rfr_ctrl); + writel(CMD_NOP, &sdrc_base->cs[cs].manual); + writel(CMD_PRECHARGE, &sdrc_base->cs[cs].manual); + writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual); + writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual); + writel(timings->mr, &sdrc_base->cs[cs].mr); + + /* + * Test ram in this bank + * Disable if bad or not present + */ + if (!mem_ok(cs)) + writel(0, &sdrc_base->cs[cs].mcfg); +} + +/* + * do_sdrc_init - + * - Code called once in C-Stack only context for CS0 and with early being + * true and a possible 2nd time depending on memory configuration from + * stack+global context. + */ +void do_sdrc_init(u32 cs, u32 early) +{ + struct sdrc_actim *sdrc_actim_base0, *sdrc_actim_base1; + struct board_sdrc_timings timings; + + sdrc_actim_base0 = (struct sdrc_actim *)SDRC_ACTIM_CTRL0_BASE; + sdrc_actim_base1 = (struct sdrc_actim *)SDRC_ACTIM_CTRL1_BASE; + + /* + * When called in the early context this may be SPL and we will + * need to set all of the timings. This ends up being board + * specific so we call a helper function to take care of this + * for us. Otherwise, to be safe, we need to copy the settings + * from the first bank to the second. We will setup CS0, + * then set cs_cfg to the appropriate value then try and + * setup CS1. + */ +#ifdef CONFIG_SPL_BUILD + get_board_mem_timings(&timings); +#endif + if (early) { + /* reset sdrc controller */ + writel(SOFTRESET, &sdrc_base->sysconfig); + wait_on_value(RESETDONE, RESETDONE, &sdrc_base->status, + 12000000); + writel(0, &sdrc_base->sysconfig); + + /* setup sdrc to ball mux */ + writel(SDRC_SHARING, &sdrc_base->sharing); + + /* Disable Power Down of CKE because of 1 CKE on combo part */ + writel(WAKEUPPROC | SRFRONRESET | PAGEPOLICY_HIGH, + &sdrc_base->power); + + writel(ENADLL | DLLPHASE_90, &sdrc_base->dlla_ctrl); + sdelay(0x20000); +#ifdef CONFIG_SPL_BUILD + write_sdrc_timings(CS0, sdrc_actim_base0, &timings); + make_cs1_contiguous(); + write_sdrc_timings(CS1, sdrc_actim_base1, &timings); +#endif + + } + + /* + * If we aren't using SPL we have been loaded by some + * other means which may not have correctly initialized + * both CS0 and CS1 (such as some older versions of x-loader) + * so we may be asked now to setup CS1. + */ + if (cs == CS1) { + timings.mcfg = readl(&sdrc_base->cs[CS0].mcfg), + timings.rfr_ctrl = readl(&sdrc_base->cs[CS0].rfr_ctrl); + timings.ctrla = readl(&sdrc_actim_base0->ctrla); + timings.ctrlb = readl(&sdrc_actim_base0->ctrlb); + timings.mr = readl(&sdrc_base->cs[CS0].mr); + write_sdrc_timings(cs, sdrc_actim_base1, &timings); + } +} + +/* + * dram_init - + * - Sets uboots idea of sdram size + */ +int dram_init(void) +{ + unsigned int size0 = 0, size1 = 0; + + size0 = get_sdr_cs_size(CS0); + /* + * We always need to have cs_cfg point at where the second + * bank would be, if present. Failure to do so can lead to + * strange situations where memory isn't detected and + * configured correctly. CS0 will already have been setup + * at this point. + */ + make_cs1_contiguous(); + do_sdrc_init(CS1, NOT_EARLY); + size1 = get_sdr_cs_size(CS1); + + gd->ram_size = size0 + size1; + + return 0; +} + +void dram_init_banksize (void) +{ + unsigned int size0 = 0, size1 = 0; + + size0 = get_sdr_cs_size(CS0); + size1 = get_sdr_cs_size(CS1); + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = size0; + gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + get_sdr_cs_offset(CS1); + gd->bd->bi_dram[1].size = size1; +} + +/* + * mem_init - + * - Init the sdrc chip, + * - Selects CS0 and CS1, + */ +void mem_init(void) +{ + /* only init up first bank here */ + do_sdrc_init(CS0, EARLY_INIT); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/spl_id_nand.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/spl_id_nand.c new file mode 100644 index 000000000..db6de0911 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/spl_id_nand.c @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2011 + * Texas Instruments, <www.ti.com> + * + * Author : + * Tom Rini <trini@ti.com> + * + * Initial Code from: + * Richard Woodruff <r-woodruff2@ti.com> + * Jian Zhang <jzhang@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <linux/mtd/nand.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/mem.h> + +static struct gpmc *gpmc_config = (struct gpmc *)GPMC_BASE; + +/* nand_command: Send a flash command to the flash chip */ +static void nand_command(u8 command) +{ + writeb(command, &gpmc_config->cs[0].nand_cmd); + + if (command == NAND_CMD_RESET) { + unsigned char ret_val; + writeb(NAND_CMD_STATUS, &gpmc_config->cs[0].nand_cmd); + do { + /* Wait until ready */ + ret_val = readl(&gpmc_config->cs[0].nand_dat); + } while ((ret_val & NAND_STATUS_READY) != NAND_STATUS_READY); + } +} + +/* + * Many boards will want to know the results of the NAND_CMD_READID command + * in order to decide what to do about DDR initialization. This function + * allows us to do that very early and to pass those results back to the + * board so it can make whatever decisions need to be made. + */ +void identify_nand_chip(int *mfr, int *id) +{ + /* Make sure that we have setup GPMC for NAND correctly. */ + writel(M_NAND_GPMC_CONFIG1, &gpmc_config->cs[0].config1); + writel(M_NAND_GPMC_CONFIG2, &gpmc_config->cs[0].config2); + writel(M_NAND_GPMC_CONFIG3, &gpmc_config->cs[0].config3); + writel(M_NAND_GPMC_CONFIG4, &gpmc_config->cs[0].config4); + writel(M_NAND_GPMC_CONFIG5, &gpmc_config->cs[0].config5); + writel(M_NAND_GPMC_CONFIG6, &gpmc_config->cs[0].config6); + + /* + * Enable the config. The CS size goes in bits 11:8. We set + * bit 6 to enable the CS and the base address goes into bits 5:0. + */ + writel((GPMC_SIZE_128M << 8) | (GPMC_CS_ENABLE << 6) | + ((NAND_BASE >> 24) & GPMC_BASEADDR_MASK), + &gpmc_config->cs[0].config7); + + sdelay(2000); + + /* Issue a RESET and then READID */ + nand_command(NAND_CMD_RESET); + nand_command(NAND_CMD_READID); + + /* Set the address to read to 0x0 */ + writeb(0x0, &gpmc_config->cs[0].nand_adr); + + /* Read off the manufacturer and device id. */ + *mfr = readb(&gpmc_config->cs[0].nand_dat); + *id = readb(&gpmc_config->cs[0].nand_dat); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/sys_info.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/sys_info.c new file mode 100644 index 000000000..bef5f05ea --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap3/sys_info.c @@ -0,0 +1,364 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Author : + * Manikandan Pillai <mani.pillai@ti.com> + * + * Derived from Beagle Board and 3430 SDP code by + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/mem.h> /* get mem tables */ +#include <asm/arch/sys_proto.h> +#include <i2c.h> +#include <linux/compiler.h> + +extern omap3_sysinfo sysinfo; +static struct ctrl *ctrl_base = (struct ctrl *)OMAP34XX_CTRL_BASE; + +#ifdef CONFIG_DISPLAY_CPUINFO +static char *rev_s[CPU_3XX_MAX_REV] = { + "1.0", + "2.0", + "2.1", + "3.0", + "3.1", + "UNKNOWN", + "UNKNOWN", + "3.1.2"}; + +/* this is the revision table for 37xx CPUs */ +static char *rev_s_37xx[CPU_37XX_MAX_REV] = { + "1.0", + "1.1", + "1.2"}; +#endif /* CONFIG_DISPLAY_CPUINFO */ + +/***************************************************************** + * get_dieid(u32 *id) - read die ID + *****************************************************************/ +void get_dieid(u32 *id) +{ + struct ctrl_id *id_base = (struct ctrl_id *)OMAP34XX_ID_L4_IO_BASE; + + id[3] = readl(&id_base->die_id_0); + id[2] = readl(&id_base->die_id_1); + id[1] = readl(&id_base->die_id_2); + id[0] = readl(&id_base->die_id_3); +} + +/***************************************************************** + * dieid_num_r(void) - read and set die ID + *****************************************************************/ +void dieid_num_r(void) +{ + char *uid_s, die_id[34]; + u32 id[4]; + + memset(die_id, 0, sizeof(die_id)); + + uid_s = getenv("dieid#"); + + if (uid_s == NULL) { + get_dieid(id); + sprintf(die_id, "%08x%08x%08x%08x", id[0], id[1], id[2], id[3]); + setenv("dieid#", die_id); + uid_s = die_id; + } + + printf("Die ID #%s\n", uid_s); +} + +/****************************************** + * get_cpu_type(void) - extract cpu info + ******************************************/ +u32 get_cpu_type(void) +{ + return readl(&ctrl_base->ctrl_omap_stat); +} + +/****************************************** + * get_cpu_id(void) - extract cpu id + * returns 0 for ES1.0, cpuid otherwise + ******************************************/ +u32 get_cpu_id(void) +{ + struct ctrl_id *id_base; + u32 cpuid = 0; + + /* + * On ES1.0 the IDCODE register is not exposed on L4 + * so using CPU ID to differentiate between ES1.0 and > ES1.0. + */ + __asm__ __volatile__("mrc p15, 0, %0, c0, c0, 0":"=r"(cpuid)); + if ((cpuid & 0xf) == 0x0) { + return 0; + } else { + /* Decode the IDs on > ES1.0 */ + id_base = (struct ctrl_id *) OMAP34XX_ID_L4_IO_BASE; + + cpuid = readl(&id_base->idcode); + } + + return cpuid; +} + +/****************************************** + * get_cpu_family(void) - extract cpu info + ******************************************/ +u32 get_cpu_family(void) +{ + u16 hawkeye; + u32 cpu_family; + u32 cpuid = get_cpu_id(); + + if (cpuid == 0) + return CPU_OMAP34XX; + + hawkeye = (cpuid >> HAWKEYE_SHIFT) & 0xffff; + switch (hawkeye) { + case HAWKEYE_OMAP34XX: + cpu_family = CPU_OMAP34XX; + break; + case HAWKEYE_AM35XX: + cpu_family = CPU_AM35XX; + break; + case HAWKEYE_OMAP36XX: + cpu_family = CPU_OMAP36XX; + break; + default: + cpu_family = CPU_OMAP34XX; + } + + return cpu_family; +} + +/****************************************** + * get_cpu_rev(void) - extract version info + ******************************************/ +u32 get_cpu_rev(void) +{ + u32 cpuid = get_cpu_id(); + + if (cpuid == 0) + return CPU_3XX_ES10; + else + return (cpuid >> CPU_3XX_ID_SHIFT) & 0xf; +} + +/***************************************************************** + * get_sku_id(void) - read sku_id to get info on max clock rate + *****************************************************************/ +u32 get_sku_id(void) +{ + struct ctrl_id *id_base = (struct ctrl_id *)OMAP34XX_ID_L4_IO_BASE; + return readl(&id_base->sku_id) & SKUID_CLK_MASK; +} + +/*************************************************************************** + * get_gpmc0_base() - Return current address hardware will be + * fetching from. The below effectively gives what is correct, its a bit + * mis-leading compared to the TRM. For the most general case the mask + * needs to be also taken into account this does work in practice. + * - for u-boot we currently map: + * -- 0 to nothing, + * -- 4 to flash + * -- 8 to enent + * -- c to wifi + ****************************************************************************/ +u32 get_gpmc0_base(void) +{ + u32 b; + + b = readl(&gpmc_cfg->cs[0].config7); + b &= 0x1F; /* keep base [5:0] */ + b = b << 24; /* ret 0x0b000000 */ + return b; +} + +/******************************************************************* + * get_gpmc0_width() - See if bus is in x8 or x16 (mainly for nand) + *******************************************************************/ +u32 get_gpmc0_width(void) +{ + return WIDTH_16BIT; +} + +/************************************************************************* + * get_board_rev() - setup to pass kernel board revision information + * returns:(bit[0-3] sub version, higher bit[7-4] is higher version) + *************************************************************************/ +u32 __weak get_board_rev(void) +{ + return 0x20; +} + +/******************************************************** + * get_base(); get upper addr of current execution + *******************************************************/ +u32 get_base(void) +{ + u32 val; + + __asm__ __volatile__("mov %0, pc \n":"=r"(val)::"memory"); + val &= 0xF0000000; + val >>= 28; + return val; +} + +/******************************************************** + * is_running_in_flash() - tell if currently running in + * FLASH. + *******************************************************/ +u32 is_running_in_flash(void) +{ + if (get_base() < 4) + return 1; /* in FLASH */ + + return 0; /* running in SRAM or SDRAM */ +} + +/******************************************************** + * is_running_in_sram() - tell if currently running in + * SRAM. + *******************************************************/ +u32 is_running_in_sram(void) +{ + if (get_base() == 4) + return 1; /* in SRAM */ + + return 0; /* running in FLASH or SDRAM */ +} + +/******************************************************** + * is_running_in_sdram() - tell if currently running in + * SDRAM. + *******************************************************/ +u32 is_running_in_sdram(void) +{ + if (get_base() > 4) + return 1; /* in SDRAM */ + + return 0; /* running in SRAM or FLASH */ +} + +/*************************************************************** + * get_boot_type() - Is this an XIP type device or a stream one + * bits 4-0 specify type. Bit 5 says mem/perif + ***************************************************************/ +u32 get_boot_type(void) +{ + return (readl(&ctrl_base->status) & SYSBOOT_MASK); +} + +/************************************************************* + * get_device_type(): tell if GP/HS/EMU/TST + *************************************************************/ +u32 get_device_type(void) +{ + return ((readl(&ctrl_base->status) & (DEVICE_MASK)) >> 8); +} + +#ifdef CONFIG_DISPLAY_CPUINFO +/** + * Print CPU information + */ +int print_cpuinfo (void) +{ + char *cpu_family_s, *cpu_s, *sec_s, *max_clk; + + switch (get_cpu_family()) { + case CPU_OMAP34XX: + cpu_family_s = "OMAP"; + switch (get_cpu_type()) { + case OMAP3503: + cpu_s = "3503"; + break; + case OMAP3515: + cpu_s = "3515"; + break; + case OMAP3525: + cpu_s = "3525"; + break; + case OMAP3530: + cpu_s = "3530"; + break; + default: + cpu_s = "35XX"; + break; + } + if ((get_cpu_rev() >= CPU_3XX_ES31) && + (get_sku_id() == SKUID_CLK_720MHZ)) + max_clk = "720 MHz"; + else + max_clk = "600 MHz"; + + break; + case CPU_AM35XX: + cpu_family_s = "AM"; + switch (get_cpu_type()) { + case AM3505: + cpu_s = "3505"; + break; + case AM3517: + cpu_s = "3517"; + break; + default: + cpu_s = "35XX"; + break; + } + max_clk = "600 Mhz"; + break; + case CPU_OMAP36XX: + cpu_family_s = "OMAP"; + switch (get_cpu_type()) { + case OMAP3730: + cpu_s = "3630/3730"; + break; + default: + cpu_s = "36XX/37XX"; + break; + } + max_clk = "1 Ghz"; + break; + default: + cpu_family_s = "OMAP"; + cpu_s = "35XX"; + max_clk = "600 Mhz"; + } + + switch (get_device_type()) { + case TST_DEVICE: + sec_s = "TST"; + break; + case EMU_DEVICE: + sec_s = "EMU"; + break; + case HS_DEVICE: + sec_s = "HS"; + break; + case GP_DEVICE: + sec_s = "GP"; + break; + default: + sec_s = "?"; + } + + if (CPU_OMAP36XX == get_cpu_family()) + printf("%s%s-%s ES%s, CPU-OPP2, L3-200MHz, Max CPU Clock %s\n", + cpu_family_s, cpu_s, sec_s, + rev_s_37xx[get_cpu_rev()], max_clk); + else + printf("%s%s-%s ES%s, CPU-OPP2, L3-165MHz, Max CPU Clock %s\n", + cpu_family_s, cpu_s, sec_s, + rev_s[get_cpu_rev()], max_clk); + + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/Makefile new file mode 100644 index 000000000..76a032a2d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/Makefile @@ -0,0 +1,12 @@ +# +# (C) Copyright 2000-2010 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += sdram_elpida.o +obj-y += hwinit.o +obj-y += emif.o +obj-y += prcm-regs.o +obj-y += hw_data.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/config.mk b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/config.mk new file mode 100644 index 000000000..ad44d6384 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/config.mk @@ -0,0 +1,15 @@ +# +# Copyright 2011 Linaro Limited +# +# (C) Copyright 2010 +# Texas Instruments, <www.ti.com> +# +# Aneesh V <aneesh@ti.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# +ifdef CONFIG_SPL_BUILD +ALL-y += MLO +else +ALL-y += u-boot.img +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/emif.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/emif.c new file mode 100644 index 000000000..e89032be7 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/emif.c @@ -0,0 +1,112 @@ +/* + * EMIF programming + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/emif.h> +#include <asm/arch/sys_proto.h> +#include <asm/utils.h> + +#ifndef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS +u32 *const T_num = (u32 *)OMAP_SRAM_SCRATCH_EMIF_T_NUM; +u32 *const T_den = (u32 *)OMAP_SRAM_SCRATCH_EMIF_T_DEN; +#endif + +#ifdef CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS +/* Base AC Timing values specified by JESD209-2 for 400MHz operation */ +static const struct lpddr2_ac_timings timings_jedec_400_mhz = { + .max_freq = 400000000, + .RL = 6, + .tRPab = 21, + .tRCD = 18, + .tWR = 15, + .tRASmin = 42, + .tRRD = 10, + .tWTRx2 = 15, + .tXSR = 140, + .tXPx2 = 15, + .tRFCab = 130, + .tRTPx2 = 15, + .tCKE = 3, + .tCKESR = 15, + .tZQCS = 90, + .tZQCL = 360, + .tZQINIT = 1000, + .tDQSCKMAXx2 = 11, + .tRASmax = 70, + .tFAW = 50 +}; + +/* Base AC Timing values specified by JESD209-2 for 200 MHz operation */ +static const struct lpddr2_ac_timings timings_jedec_200_mhz = { + .max_freq = 200000000, + .RL = 3, + .tRPab = 21, + .tRCD = 18, + .tWR = 15, + .tRASmin = 42, + .tRRD = 10, + .tWTRx2 = 20, + .tXSR = 140, + .tXPx2 = 15, + .tRFCab = 130, + .tRTPx2 = 15, + .tCKE = 3, + .tCKESR = 15, + .tZQCS = 90, + .tZQCL = 360, + .tZQINIT = 1000, + .tDQSCKMAXx2 = 11, + .tRASmax = 70, + .tFAW = 50 +}; + +/* + * Min tCK values specified by JESD209-2 + * Min tCK specifies the minimum duration of some AC timing parameters in terms + * of the number of cycles. If the calculated number of cycles based on the + * absolute time value is less than the min tCK value, min tCK value should + * be used instead. This typically happens at low frequencies. + */ +static const struct lpddr2_min_tck min_tck_jedec = { + .tRL = 3, + .tRP_AB = 3, + .tRCD = 3, + .tWR = 3, + .tRAS_MIN = 3, + .tRRD = 2, + .tWTR = 2, + .tXP = 2, + .tRTP = 2, + .tCKE = 3, + .tCKESR = 3, + .tFAW = 8 +}; + +static const struct lpddr2_ac_timings const* + jedec_ac_timings[MAX_NUM_SPEEDBINS] = { + &timings_jedec_200_mhz, + &timings_jedec_400_mhz +}; + +static const struct lpddr2_device_timings jedec_default_timings = { + .ac_timings = jedec_ac_timings, + .min_tck = &min_tck_jedec +}; + +void emif_get_device_timings(u32 emif_nr, + const struct lpddr2_device_timings **cs0_device_timings, + const struct lpddr2_device_timings **cs1_device_timings) +{ + /* Assume Identical devices on EMIF1 & EMIF2 */ + *cs0_device_timings = &jedec_default_timings; + *cs1_device_timings = &jedec_default_timings; +} +#endif /* CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/hw_data.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/hw_data.c new file mode 100644 index 000000000..029533c85 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/hw_data.c @@ -0,0 +1,457 @@ +/* + * + * HW data initialization for OMAP4 + * + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * Sricharan R <r.sricharan@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/arch/omap.h> +#include <asm/arch/sys_proto.h> +#include <asm/omap_common.h> +#include <asm/arch/clock.h> +#include <asm/omap_gpio.h> +#include <asm/io.h> + +struct prcm_regs const **prcm = + (struct prcm_regs const **) OMAP_SRAM_SCRATCH_PRCM_PTR; +struct dplls const **dplls_data = + (struct dplls const **) OMAP_SRAM_SCRATCH_DPLLS_PTR; +struct vcores_data const **omap_vcores = + (struct vcores_data const **) OMAP_SRAM_SCRATCH_VCORES_PTR; +struct omap_sys_ctrl_regs const **ctrl = + (struct omap_sys_ctrl_regs const **)OMAP_SRAM_SCRATCH_SYS_CTRL; + +/* + * The M & N values in the following tables are created using the + * following tool: + * tools/omap/clocks_get_m_n.c + * Please use this tool for creating the table for any new frequency. + */ + +/* + * dpll locked at 1400 MHz MPU clk at 700 MHz(OPP100) - DCC OFF + * OMAP4460 OPP_NOM frequency + */ +static const struct dpll_params mpu_dpll_params_1400mhz[NUM_SYS_CLKS] = { + {175, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {700, 12, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {125, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {401, 10, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {350, 12, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {700, 26, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {638, 34, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* + * dpll locked at 1600 MHz - MPU clk at 800 MHz(OPP Turbo 4430) + * OMAP4430 OPP_TURBO frequency + * OMAP4470 OPP_NOM frequency + */ +static const struct dpll_params mpu_dpll_params_1600mhz[NUM_SYS_CLKS] = { + {200, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {800, 12, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {619, 12, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {125, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {400, 12, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {800, 26, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {125, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* + * dpll locked at 1200 MHz - MPU clk at 600 MHz + * OMAP4430 OPP_NOM frequency + */ +static const struct dpll_params mpu_dpll_params_1200mhz[NUM_SYS_CLKS] = { + {50, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {600, 12, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {250, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {125, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {300, 12, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {200, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {125, 7, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* OMAP4460 OPP_NOM frequency */ +/* OMAP4470 OPP_NOM (Low Power) frequency */ +static const struct dpll_params core_dpll_params_1600mhz[NUM_SYS_CLKS] = { + {200, 2, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 12 MHz */ + {800, 12, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 13 MHz */ + {619, 12, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 16.8 MHz */ + {125, 2, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 19.2 MHz */ + {400, 12, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 26 MHz */ + {800, 26, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 27 MHz */ + {125, 5, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* OMAP4430 ES1 OPP_NOM frequency */ +static const struct dpll_params core_dpll_params_es1_1524mhz[NUM_SYS_CLKS] = { + {127, 1, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 12 MHz */ + {762, 12, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 13 MHz */ + {635, 13, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 16.8 MHz */ + {635, 15, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 19.2 MHz */ + {381, 12, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 26 MHz */ + {254, 8, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 27 MHz */ + {496, 24, 1, 5, 8, 4, 6, 5, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* OMAP4430 ES2.X OPP_NOM frequency */ +static const struct dpll_params + core_dpll_params_es2_1600mhz_ddr200mhz[NUM_SYS_CLKS] = { + {200, 2, 2, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 12 MHz */ + {800, 12, 2, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 13 MHz */ + {619, 12, 2, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 16.8 MHz */ + {125, 2, 2, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 19.2 MHz */ + {400, 12, 2, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 26 MHz */ + {800, 26, 2, 5, 8, 4, 6, 5, -1, -1, -1, -1}, /* 27 MHz */ + {125, 5, 2, 5, 8, 4, 6, 5, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +static const struct dpll_params per_dpll_params_1536mhz[NUM_SYS_CLKS] = { + {64, 0, 8, 6, 12, 9, 4, 5, -1, -1, -1, -1}, /* 12 MHz */ + {768, 12, 8, 6, 12, 9, 4, 5, -1, -1, -1, -1}, /* 13 MHz */ + {320, 6, 8, 6, 12, 9, 4, 5, -1, -1, -1, -1}, /* 16.8 MHz */ + {40, 0, 8, 6, 12, 9, 4, 5, -1, -1, -1, -1}, /* 19.2 MHz */ + {384, 12, 8, 6, 12, 9, 4, 5, -1, -1, -1, -1}, /* 26 MHz */ + {256, 8, 8, 6, 12, 9, 4, 5, -1, -1, -1, -1}, /* 27 MHz */ + {20, 0, 8, 6, 12, 9, 4, 5, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +static const struct dpll_params iva_dpll_params_1862mhz[NUM_SYS_CLKS] = { + {931, 11, -1, -1, 4, 7, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {931, 12, -1, -1, 4, 7, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {665, 11, -1, -1, 4, 7, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {727, 14, -1, -1, 4, 7, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {931, 25, -1, -1, 4, 7, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {931, 26, -1, -1, 4, 7, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {291, 11, -1, -1, 4, 7, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* ABE M & N values with sys_clk as source */ +static const struct dpll_params + abe_dpll_params_sysclk_196608khz[NUM_SYS_CLKS] = { + {49, 5, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {68, 8, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {35, 5, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {46, 8, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {34, 8, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {29, 7, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {64, 24, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* ABE M & N values with 32K clock as source */ +static const struct dpll_params abe_dpll_params_32k_196608khz = { + 750, 0, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +static const struct dpll_params usb_dpll_params_1920mhz[NUM_SYS_CLKS] = { + {80, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {960, 12, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {400, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {50, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {480, 12, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {320, 8, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {25, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +struct dplls omap4430_dplls_es1 = { + .mpu = mpu_dpll_params_1200mhz, + .core = core_dpll_params_es1_1524mhz, + .per = per_dpll_params_1536mhz, + .iva = iva_dpll_params_1862mhz, +#ifdef CONFIG_SYS_OMAP_ABE_SYSCK + .abe = abe_dpll_params_sysclk_196608khz, +#else + .abe = &abe_dpll_params_32k_196608khz, +#endif + .usb = usb_dpll_params_1920mhz, + .ddr = NULL +}; + +struct dplls omap4430_dplls_es20 = { + .mpu = mpu_dpll_params_1200mhz, + .core = core_dpll_params_es2_1600mhz_ddr200mhz, + .per = per_dpll_params_1536mhz, + .iva = iva_dpll_params_1862mhz, +#ifdef CONFIG_SYS_OMAP_ABE_SYSCK + .abe = abe_dpll_params_sysclk_196608khz, +#else + .abe = &abe_dpll_params_32k_196608khz, +#endif + .usb = usb_dpll_params_1920mhz, + .ddr = NULL +}; + +struct dplls omap4430_dplls = { + .mpu = mpu_dpll_params_1200mhz, + .core = core_dpll_params_1600mhz, + .per = per_dpll_params_1536mhz, + .iva = iva_dpll_params_1862mhz, +#ifdef CONFIG_SYS_OMAP_ABE_SYSCK + .abe = abe_dpll_params_sysclk_196608khz, +#else + .abe = &abe_dpll_params_32k_196608khz, +#endif + .usb = usb_dpll_params_1920mhz, + .ddr = NULL +}; + +struct dplls omap4460_dplls = { + .mpu = mpu_dpll_params_1400mhz, + .core = core_dpll_params_1600mhz, + .per = per_dpll_params_1536mhz, + .iva = iva_dpll_params_1862mhz, +#ifdef CONFIG_SYS_OMAP_ABE_SYSCK + .abe = abe_dpll_params_sysclk_196608khz, +#else + .abe = &abe_dpll_params_32k_196608khz, +#endif + .usb = usb_dpll_params_1920mhz, + .ddr = NULL +}; + +struct dplls omap4470_dplls = { + .mpu = mpu_dpll_params_1600mhz, + .core = core_dpll_params_1600mhz, + .per = per_dpll_params_1536mhz, + .iva = iva_dpll_params_1862mhz, +#ifdef CONFIG_SYS_OMAP_ABE_SYSCK + .abe = abe_dpll_params_sysclk_196608khz, +#else + .abe = &abe_dpll_params_32k_196608khz, +#endif + .usb = usb_dpll_params_1920mhz, + .ddr = NULL +}; + +struct pmic_data twl6030_4430es1 = { + .base_offset = PHOENIX_SMPS_BASE_VOLT_STD_MODE_UV, + .step = 12660, /* 12.66 mV represented in uV */ + /* The code starts at 1 not 0 */ + .start_code = 1, + .i2c_slave_addr = SMPS_I2C_SLAVE_ADDR, + .pmic_bus_init = sri2c_init, + .pmic_write = omap_vc_bypass_send_value, +}; + +/* twl6030 struct is used for TWL6030 and TWL6032 PMIC */ +struct pmic_data twl6030 = { + .base_offset = PHOENIX_SMPS_BASE_VOLT_STD_MODE_WITH_OFFSET_UV, + .step = 12660, /* 12.66 mV represented in uV */ + /* The code starts at 1 not 0 */ + .start_code = 1, + .i2c_slave_addr = SMPS_I2C_SLAVE_ADDR, + .pmic_bus_init = sri2c_init, + .pmic_write = omap_vc_bypass_send_value, +}; + +struct pmic_data tps62361 = { + .base_offset = TPS62361_BASE_VOLT_MV, + .step = 10000, /* 10 mV represented in uV */ + .start_code = 0, + .gpio = TPS62361_VSEL0_GPIO, + .gpio_en = 1, + .i2c_slave_addr = SMPS_I2C_SLAVE_ADDR, + .pmic_bus_init = sri2c_init, + .pmic_write = omap_vc_bypass_send_value, +}; + +struct vcores_data omap4430_volts_es1 = { + .mpu.value = 1325, + .mpu.addr = SMPS_REG_ADDR_VCORE1, + .mpu.pmic = &twl6030_4430es1, + + .core.value = 1200, + .core.addr = SMPS_REG_ADDR_VCORE3, + .core.pmic = &twl6030_4430es1, + + .mm.value = 1200, + .mm.addr = SMPS_REG_ADDR_VCORE2, + .mm.pmic = &twl6030_4430es1, +}; + +struct vcores_data omap4430_volts = { + .mpu.value = 1325, + .mpu.addr = SMPS_REG_ADDR_VCORE1, + .mpu.pmic = &twl6030, + + .core.value = 1200, + .core.addr = SMPS_REG_ADDR_VCORE3, + .core.pmic = &twl6030, + + .mm.value = 1200, + .mm.addr = SMPS_REG_ADDR_VCORE2, + .mm.pmic = &twl6030, +}; + +struct vcores_data omap4460_volts = { + .mpu.value = 1203, + .mpu.addr = TPS62361_REG_ADDR_SET1, + .mpu.pmic = &tps62361, + + .core.value = 1200, + .core.addr = SMPS_REG_ADDR_VCORE1, + .core.pmic = &twl6030, + + .mm.value = 1200, + .mm.addr = SMPS_REG_ADDR_VCORE2, + .mm.pmic = &twl6030, +}; + +/* + * Take closest integer part of the mV value corresponding to a TWL6032 SMPS + * voltage selection code. Aligned with OMAP4470 ES1.0 OCA V.0.7. + */ +struct vcores_data omap4470_volts = { + .mpu.value = 1202, + .mpu.addr = SMPS_REG_ADDR_SMPS1, + .mpu.pmic = &twl6030, + + .core.value = 1126, + .core.addr = SMPS_REG_ADDR_SMPS2, + .core.pmic = &twl6030, + + .mm.value = 1139, + .mm.addr = SMPS_REG_ADDR_SMPS5, + .mm.pmic = &twl6030, +}; + +/* + * Enable essential clock domains, modules and + * do some additional special settings needed + */ +void enable_basic_clocks(void) +{ + u32 const clk_domains_essential[] = { + (*prcm)->cm_l4per_clkstctrl, + (*prcm)->cm_l3init_clkstctrl, + (*prcm)->cm_memif_clkstctrl, + (*prcm)->cm_l4cfg_clkstctrl, + 0 + }; + + u32 const clk_modules_hw_auto_essential[] = { + (*prcm)->cm_l3_gpmc_clkctrl, + (*prcm)->cm_memif_emif_1_clkctrl, + (*prcm)->cm_memif_emif_2_clkctrl, + (*prcm)->cm_l4cfg_l4_cfg_clkctrl, + (*prcm)->cm_wkup_gpio1_clkctrl, + (*prcm)->cm_l4per_gpio2_clkctrl, + (*prcm)->cm_l4per_gpio3_clkctrl, + (*prcm)->cm_l4per_gpio4_clkctrl, + (*prcm)->cm_l4per_gpio5_clkctrl, + (*prcm)->cm_l4per_gpio6_clkctrl, + 0 + }; + + u32 const clk_modules_explicit_en_essential[] = { + (*prcm)->cm_wkup_gptimer1_clkctrl, + (*prcm)->cm_l3init_hsmmc1_clkctrl, + (*prcm)->cm_l3init_hsmmc2_clkctrl, + (*prcm)->cm_l4per_gptimer2_clkctrl, + (*prcm)->cm_wkup_wdtimer2_clkctrl, + (*prcm)->cm_l4per_uart3_clkctrl, + 0 + }; + + /* Enable optional additional functional clock for GPIO4 */ + setbits_le32((*prcm)->cm_l4per_gpio4_clkctrl, + GPIO4_CLKCTRL_OPTFCLKEN_MASK); + + /* Enable 96 MHz clock for MMC1 & MMC2 */ + setbits_le32((*prcm)->cm_l3init_hsmmc1_clkctrl, + HSMMC_CLKCTRL_CLKSEL_MASK); + setbits_le32((*prcm)->cm_l3init_hsmmc2_clkctrl, + HSMMC_CLKCTRL_CLKSEL_MASK); + + /* Select 32KHz clock as the source of GPTIMER1 */ + setbits_le32((*prcm)->cm_wkup_gptimer1_clkctrl, + GPTIMER1_CLKCTRL_CLKSEL_MASK); + + /* Enable optional 48M functional clock for USB PHY */ + setbits_le32((*prcm)->cm_l3init_usbphy_clkctrl, + USBPHY_CLKCTRL_OPTFCLKEN_PHY_48M_MASK); + + do_enable_clocks(clk_domains_essential, + clk_modules_hw_auto_essential, + clk_modules_explicit_en_essential, + 1); +} + +void enable_basic_uboot_clocks(void) +{ + u32 const clk_domains_essential[] = { + 0 + }; + + u32 const clk_modules_hw_auto_essential[] = { + (*prcm)->cm_l3init_hsusbotg_clkctrl, + (*prcm)->cm_l3init_usbphy_clkctrl, + (*prcm)->cm_l3init_usbphy_clkctrl, + (*prcm)->cm_clksel_usb_60mhz, + (*prcm)->cm_l3init_hsusbtll_clkctrl, + 0 + }; + + u32 const clk_modules_explicit_en_essential[] = { + (*prcm)->cm_l4per_mcspi1_clkctrl, + (*prcm)->cm_l4per_i2c1_clkctrl, + (*prcm)->cm_l4per_i2c2_clkctrl, + (*prcm)->cm_l4per_i2c3_clkctrl, + (*prcm)->cm_l4per_i2c4_clkctrl, + (*prcm)->cm_l3init_hsusbhost_clkctrl, + 0 + }; + + do_enable_clocks(clk_domains_essential, + clk_modules_hw_auto_essential, + clk_modules_explicit_en_essential, + 1); +} + +void hw_data_init(void) +{ + u32 omap_rev = omap_revision(); + + (*prcm) = &omap4_prcm; + + switch (omap_rev) { + + case OMAP4430_ES1_0: + *dplls_data = &omap4430_dplls_es1; + *omap_vcores = &omap4430_volts_es1; + break; + + case OMAP4430_ES2_0: + *dplls_data = &omap4430_dplls_es20; + *omap_vcores = &omap4430_volts; + break; + + case OMAP4430_ES2_1: + case OMAP4430_ES2_2: + case OMAP4430_ES2_3: + *dplls_data = &omap4430_dplls; + *omap_vcores = &omap4430_volts; + break; + + case OMAP4460_ES1_0: + case OMAP4460_ES1_1: + *dplls_data = &omap4460_dplls; + *omap_vcores = &omap4460_volts; + break; + + case OMAP4470_ES1_0: + *dplls_data = &omap4470_dplls; + *omap_vcores = &omap4470_volts; + break; + + default: + printf("\n INVALID OMAP REVISION "); + } + + *ctrl = &omap4_ctrl; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/hwinit.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/hwinit.c new file mode 100644 index 000000000..db16548fa --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/hwinit.c @@ -0,0 +1,169 @@ +/* + * + * Common functions for OMAP4 based boards + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Author : + * Aneesh V <aneesh@ti.com> + * Steve Sakoman <steve@sakoman.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/armv7.h> +#include <asm/arch/cpu.h> +#include <asm/arch/sys_proto.h> +#include <linux/sizes.h> +#include <asm/emif.h> +#include <asm/arch/gpio.h> +#include <asm/omap_common.h> + +DECLARE_GLOBAL_DATA_PTR; + +u32 *const omap_si_rev = (u32 *)OMAP_SRAM_SCRATCH_OMAP_REV; + +static const struct gpio_bank gpio_bank_44xx[6] = { + { (void *)OMAP44XX_GPIO1_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP44XX_GPIO2_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP44XX_GPIO3_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP44XX_GPIO4_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP44XX_GPIO5_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP44XX_GPIO6_BASE, METHOD_GPIO_24XX }, +}; + +const struct gpio_bank *const omap_gpio_bank = gpio_bank_44xx; + +#ifdef CONFIG_SPL_BUILD +/* + * Some tuning of IOs for optimal power and performance + */ +void do_io_settings(void) +{ + u32 lpddr2io; + + u32 omap4_rev = omap_revision(); + + if (omap4_rev == OMAP4430_ES1_0) + lpddr2io = CONTROL_LPDDR2IO_SLEW_125PS_DRV8_PULL_DOWN; + else if (omap4_rev == OMAP4430_ES2_0) + lpddr2io = CONTROL_LPDDR2IO_SLEW_325PS_DRV8_GATE_KEEPER; + else + lpddr2io = CONTROL_LPDDR2IO_SLEW_315PS_DRV12_PULL_DOWN; + + /* EMIF1 */ + writel(lpddr2io, (*ctrl)->control_lpddr2io1_0); + writel(lpddr2io, (*ctrl)->control_lpddr2io1_1); + /* No pull for GR10 as per hw team's recommendation */ + writel(lpddr2io & ~LPDDR2IO_GR10_WD_MASK, + (*ctrl)->control_lpddr2io1_2); + writel(CONTROL_LPDDR2IO_3_VAL, (*ctrl)->control_lpddr2io1_3); + + /* EMIF2 */ + writel(lpddr2io, (*ctrl)->control_lpddr2io2_0); + writel(lpddr2io, (*ctrl)->control_lpddr2io2_1); + /* No pull for GR10 as per hw team's recommendation */ + writel(lpddr2io & ~LPDDR2IO_GR10_WD_MASK, + (*ctrl)->control_lpddr2io2_2); + writel(CONTROL_LPDDR2IO_3_VAL, (*ctrl)->control_lpddr2io2_3); + + /* + * Some of these settings (TRIM values) come from eFuse and are + * in turn programmed in the eFuse at manufacturing time after + * calibration of the device. Do the software over-ride only if + * the device is not correctly trimmed + */ + if (!(readl((*ctrl)->control_std_fuse_opp_bgap) & 0xFFFF)) { + + writel(LDOSRAM_VOLT_CTRL_OVERRIDE, + (*ctrl)->control_ldosram_iva_voltage_ctrl); + + writel(LDOSRAM_VOLT_CTRL_OVERRIDE, + (*ctrl)->control_ldosram_mpu_voltage_ctrl); + + writel(LDOSRAM_VOLT_CTRL_OVERRIDE, + (*ctrl)->control_ldosram_core_voltage_ctrl); + } + + /* + * Over-ride the register + * i. unconditionally for all 4430 + * ii. only if un-trimmed for 4460 + */ + if (!readl((*ctrl)->control_efuse_1)) + writel(CONTROL_EFUSE_1_OVERRIDE, (*ctrl)->control_efuse_1); + + if ((omap4_rev < OMAP4460_ES1_0) || !readl((*ctrl)->control_efuse_2)) + writel(CONTROL_EFUSE_2_OVERRIDE, (*ctrl)->control_efuse_2); +} +#endif /* CONFIG_SPL_BUILD */ + +/* dummy fuction for omap4 */ +void config_data_eye_leveling_samples(u32 emif_base) +{ +} + +void init_omap_revision(void) +{ + /* + * For some of the ES2/ES1 boards ID_CODE is not reliable: + * Also, ES1 and ES2 have different ARM revisions + * So use ARM revision for identification + */ + unsigned int arm_rev = cortex_rev(); + + switch (arm_rev) { + case MIDR_CORTEX_A9_R0P1: + *omap_si_rev = OMAP4430_ES1_0; + break; + case MIDR_CORTEX_A9_R1P2: + switch (readl(CONTROL_ID_CODE)) { + case OMAP4_CONTROL_ID_CODE_ES2_0: + *omap_si_rev = OMAP4430_ES2_0; + break; + case OMAP4_CONTROL_ID_CODE_ES2_1: + *omap_si_rev = OMAP4430_ES2_1; + break; + case OMAP4_CONTROL_ID_CODE_ES2_2: + *omap_si_rev = OMAP4430_ES2_2; + break; + default: + *omap_si_rev = OMAP4430_ES2_0; + break; + } + break; + case MIDR_CORTEX_A9_R1P3: + *omap_si_rev = OMAP4430_ES2_3; + break; + case MIDR_CORTEX_A9_R2P10: + switch (readl(CONTROL_ID_CODE)) { + case OMAP4470_CONTROL_ID_CODE_ES1_0: + *omap_si_rev = OMAP4470_ES1_0; + break; + case OMAP4460_CONTROL_ID_CODE_ES1_1: + *omap_si_rev = OMAP4460_ES1_1; + break; + case OMAP4460_CONTROL_ID_CODE_ES1_0: + default: + *omap_si_rev = OMAP4460_ES1_0; + break; + } + break; + default: + *omap_si_rev = OMAP4430_SILICON_ID_INVALID; + break; + } +} + +#ifndef CONFIG_SYS_L2CACHE_OFF +void v7_outer_cache_enable(void) +{ + set_pl310_ctrl_reg(1); +} + +void v7_outer_cache_disable(void) +{ + set_pl310_ctrl_reg(0); +} +#endif /* !CONFIG_SYS_L2CACHE_OFF */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/prcm-regs.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/prcm-regs.c new file mode 100644 index 000000000..1ed146b44 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/prcm-regs.c @@ -0,0 +1,302 @@ +/* + * + * HW regs data for OMAP4 + * + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * Sricharan R <r.sricharan@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/omap_common.h> + +struct prcm_regs const omap4_prcm = { + /* cm1.ckgen */ + .cm_clksel_core = 0x4a004100, + .cm_clksel_abe = 0x4a004108, + .cm_dll_ctrl = 0x4a004110, + .cm_clkmode_dpll_core = 0x4a004120, + .cm_idlest_dpll_core = 0x4a004124, + .cm_autoidle_dpll_core = 0x4a004128, + .cm_clksel_dpll_core = 0x4a00412c, + .cm_div_m2_dpll_core = 0x4a004130, + .cm_div_m3_dpll_core = 0x4a004134, + .cm_div_m4_dpll_core = 0x4a004138, + .cm_div_m5_dpll_core = 0x4a00413c, + .cm_div_m6_dpll_core = 0x4a004140, + .cm_div_m7_dpll_core = 0x4a004144, + .cm_ssc_deltamstep_dpll_core = 0x4a004148, + .cm_ssc_modfreqdiv_dpll_core = 0x4a00414c, + .cm_emu_override_dpll_core = 0x4a004150, + .cm_clkmode_dpll_mpu = 0x4a004160, + .cm_idlest_dpll_mpu = 0x4a004164, + .cm_autoidle_dpll_mpu = 0x4a004168, + .cm_clksel_dpll_mpu = 0x4a00416c, + .cm_div_m2_dpll_mpu = 0x4a004170, + .cm_ssc_deltamstep_dpll_mpu = 0x4a004188, + .cm_ssc_modfreqdiv_dpll_mpu = 0x4a00418c, + .cm_bypclk_dpll_mpu = 0x4a00419c, + .cm_clkmode_dpll_iva = 0x4a0041a0, + .cm_idlest_dpll_iva = 0x4a0041a4, + .cm_autoidle_dpll_iva = 0x4a0041a8, + .cm_clksel_dpll_iva = 0x4a0041ac, + .cm_div_m4_dpll_iva = 0x4a0041b8, + .cm_div_m5_dpll_iva = 0x4a0041bc, + .cm_ssc_deltamstep_dpll_iva = 0x4a0041c8, + .cm_ssc_modfreqdiv_dpll_iva = 0x4a0041cc, + .cm_bypclk_dpll_iva = 0x4a0041dc, + .cm_clkmode_dpll_abe = 0x4a0041e0, + .cm_idlest_dpll_abe = 0x4a0041e4, + .cm_autoidle_dpll_abe = 0x4a0041e8, + .cm_clksel_dpll_abe = 0x4a0041ec, + .cm_div_m2_dpll_abe = 0x4a0041f0, + .cm_div_m3_dpll_abe = 0x4a0041f4, + .cm_ssc_deltamstep_dpll_abe = 0x4a004208, + .cm_ssc_modfreqdiv_dpll_abe = 0x4a00420c, + .cm_clkmode_dpll_ddrphy = 0x4a004220, + .cm_idlest_dpll_ddrphy = 0x4a004224, + .cm_autoidle_dpll_ddrphy = 0x4a004228, + .cm_clksel_dpll_ddrphy = 0x4a00422c, + .cm_div_m2_dpll_ddrphy = 0x4a004230, + .cm_div_m4_dpll_ddrphy = 0x4a004238, + .cm_div_m5_dpll_ddrphy = 0x4a00423c, + .cm_div_m6_dpll_ddrphy = 0x4a004240, + .cm_ssc_deltamstep_dpll_ddrphy = 0x4a004248, + .cm_shadow_freq_config1 = 0x4a004260, + .cm_mpu_mpu_clkctrl = 0x4a004320, + + /* cm1.dsp */ + .cm_dsp_clkstctrl = 0x4a004400, + .cm_dsp_dsp_clkctrl = 0x4a004420, + + /* cm1.abe */ + .cm1_abe_clkstctrl = 0x4a004500, + .cm1_abe_l4abe_clkctrl = 0x4a004520, + .cm1_abe_aess_clkctrl = 0x4a004528, + .cm1_abe_pdm_clkctrl = 0x4a004530, + .cm1_abe_dmic_clkctrl = 0x4a004538, + .cm1_abe_mcasp_clkctrl = 0x4a004540, + .cm1_abe_mcbsp1_clkctrl = 0x4a004548, + .cm1_abe_mcbsp2_clkctrl = 0x4a004550, + .cm1_abe_mcbsp3_clkctrl = 0x4a004558, + .cm1_abe_slimbus_clkctrl = 0x4a004560, + .cm1_abe_timer5_clkctrl = 0x4a004568, + .cm1_abe_timer6_clkctrl = 0x4a004570, + .cm1_abe_timer7_clkctrl = 0x4a004578, + .cm1_abe_timer8_clkctrl = 0x4a004580, + .cm1_abe_wdt3_clkctrl = 0x4a004588, + + /* cm2.ckgen */ + .cm_clksel_mpu_m3_iss_root = 0x4a008100, + .cm_clksel_usb_60mhz = 0x4a008104, + .cm_scale_fclk = 0x4a008108, + .cm_core_dvfs_perf1 = 0x4a008110, + .cm_core_dvfs_perf2 = 0x4a008114, + .cm_core_dvfs_perf3 = 0x4a008118, + .cm_core_dvfs_perf4 = 0x4a00811c, + .cm_core_dvfs_current = 0x4a008124, + .cm_iva_dvfs_perf_tesla = 0x4a008128, + .cm_iva_dvfs_perf_ivahd = 0x4a00812c, + .cm_iva_dvfs_perf_abe = 0x4a008130, + .cm_iva_dvfs_current = 0x4a008138, + .cm_clkmode_dpll_per = 0x4a008140, + .cm_idlest_dpll_per = 0x4a008144, + .cm_autoidle_dpll_per = 0x4a008148, + .cm_clksel_dpll_per = 0x4a00814c, + .cm_div_m2_dpll_per = 0x4a008150, + .cm_div_m3_dpll_per = 0x4a008154, + .cm_div_m4_dpll_per = 0x4a008158, + .cm_div_m5_dpll_per = 0x4a00815c, + .cm_div_m6_dpll_per = 0x4a008160, + .cm_div_m7_dpll_per = 0x4a008164, + .cm_ssc_deltamstep_dpll_per = 0x4a008168, + .cm_ssc_modfreqdiv_dpll_per = 0x4a00816c, + .cm_emu_override_dpll_per = 0x4a008170, + .cm_clkmode_dpll_usb = 0x4a008180, + .cm_idlest_dpll_usb = 0x4a008184, + .cm_autoidle_dpll_usb = 0x4a008188, + .cm_clksel_dpll_usb = 0x4a00818c, + .cm_div_m2_dpll_usb = 0x4a008190, + .cm_ssc_deltamstep_dpll_usb = 0x4a0081a8, + .cm_ssc_modfreqdiv_dpll_usb = 0x4a0081ac, + .cm_clkdcoldo_dpll_usb = 0x4a0081b4, + .cm_clkmode_dpll_unipro = 0x4a0081c0, + .cm_idlest_dpll_unipro = 0x4a0081c4, + .cm_autoidle_dpll_unipro = 0x4a0081c8, + .cm_clksel_dpll_unipro = 0x4a0081cc, + .cm_div_m2_dpll_unipro = 0x4a0081d0, + .cm_ssc_deltamstep_dpll_unipro = 0x4a0081e8, + .cm_ssc_modfreqdiv_dpll_unipro = 0x4a0081ec, + + /* cm2.core */ + .cm_l3_1_clkstctrl = 0x4a008700, + .cm_l3_1_dynamicdep = 0x4a008708, + .cm_l3_1_l3_1_clkctrl = 0x4a008720, + .cm_l3_2_clkstctrl = 0x4a008800, + .cm_l3_2_dynamicdep = 0x4a008808, + .cm_l3_2_l3_2_clkctrl = 0x4a008820, + .cm_l3_gpmc_clkctrl = 0x4a008828, + .cm_l3_2_ocmc_ram_clkctrl = 0x4a008830, + .cm_mpu_m3_clkstctrl = 0x4a008900, + .cm_mpu_m3_staticdep = 0x4a008904, + .cm_mpu_m3_dynamicdep = 0x4a008908, + .cm_mpu_m3_mpu_m3_clkctrl = 0x4a008920, + .cm_sdma_clkstctrl = 0x4a008a00, + .cm_sdma_staticdep = 0x4a008a04, + .cm_sdma_dynamicdep = 0x4a008a08, + .cm_sdma_sdma_clkctrl = 0x4a008a20, + .cm_memif_clkstctrl = 0x4a008b00, + .cm_memif_dmm_clkctrl = 0x4a008b20, + .cm_memif_emif_fw_clkctrl = 0x4a008b28, + .cm_memif_emif_1_clkctrl = 0x4a008b30, + .cm_memif_emif_2_clkctrl = 0x4a008b38, + .cm_memif_dll_clkctrl = 0x4a008b40, + .cm_memif_emif_h1_clkctrl = 0x4a008b50, + .cm_memif_emif_h2_clkctrl = 0x4a008b58, + .cm_memif_dll_h_clkctrl = 0x4a008b60, + .cm_c2c_clkstctrl = 0x4a008c00, + .cm_c2c_staticdep = 0x4a008c04, + .cm_c2c_dynamicdep = 0x4a008c08, + .cm_c2c_sad2d_clkctrl = 0x4a008c20, + .cm_c2c_modem_icr_clkctrl = 0x4a008c28, + .cm_c2c_sad2d_fw_clkctrl = 0x4a008c30, + .cm_l4cfg_clkstctrl = 0x4a008d00, + .cm_l4cfg_dynamicdep = 0x4a008d08, + .cm_l4cfg_l4_cfg_clkctrl = 0x4a008d20, + .cm_l4cfg_hw_sem_clkctrl = 0x4a008d28, + .cm_l4cfg_mailbox_clkctrl = 0x4a008d30, + .cm_l4cfg_sar_rom_clkctrl = 0x4a008d38, + .cm_l3instr_clkstctrl = 0x4a008e00, + .cm_l3instr_l3_3_clkctrl = 0x4a008e20, + .cm_l3instr_l3_instr_clkctrl = 0x4a008e28, + .cm_l3instr_intrconn_wp1_clkct = 0x4a008e40, + .cm_ivahd_clkstctrl = 0x4a008f00, + + /* cm2.ivahd */ + .cm_ivahd_ivahd_clkctrl = 0x4a008f20, + .cm_ivahd_sl2_clkctrl = 0x4a008f28, + + /* cm2.cam */ + .cm_cam_clkstctrl = 0x4a009000, + .cm_cam_iss_clkctrl = 0x4a009020, + .cm_cam_fdif_clkctrl = 0x4a009028, + + /* cm2.dss */ + .cm_dss_clkstctrl = 0x4a009100, + .cm_dss_dss_clkctrl = 0x4a009120, + + /* cm2.sgx */ + .cm_sgx_clkstctrl = 0x4a009200, + .cm_sgx_sgx_clkctrl = 0x4a009220, + + /* cm2.l3init */ + .cm_l3init_clkstctrl = 0x4a009300, + .cm_l3init_hsmmc1_clkctrl = 0x4a009328, + .cm_l3init_hsmmc2_clkctrl = 0x4a009330, + .cm_l3init_hsi_clkctrl = 0x4a009338, + .cm_l3init_hsusbhost_clkctrl = 0x4a009358, + .cm_l3init_hsusbotg_clkctrl = 0x4a009360, + .cm_l3init_hsusbtll_clkctrl = 0x4a009368, + .cm_l3init_p1500_clkctrl = 0x4a009378, + .cm_l3init_fsusb_clkctrl = 0x4a0093d0, + .cm_l3init_usbphy_clkctrl = 0x4a0093e0, + + /* cm2.l4per */ + .cm_l4per_clkstctrl = 0x4a009400, + .cm_l4per_dynamicdep = 0x4a009408, + .cm_l4per_adc_clkctrl = 0x4a009420, + .cm_l4per_gptimer10_clkctrl = 0x4a009428, + .cm_l4per_gptimer11_clkctrl = 0x4a009430, + .cm_l4per_gptimer2_clkctrl = 0x4a009438, + .cm_l4per_gptimer3_clkctrl = 0x4a009440, + .cm_l4per_gptimer4_clkctrl = 0x4a009448, + .cm_l4per_gptimer9_clkctrl = 0x4a009450, + .cm_l4per_elm_clkctrl = 0x4a009458, + .cm_l4per_gpio2_clkctrl = 0x4a009460, + .cm_l4per_gpio3_clkctrl = 0x4a009468, + .cm_l4per_gpio4_clkctrl = 0x4a009470, + .cm_l4per_gpio5_clkctrl = 0x4a009478, + .cm_l4per_gpio6_clkctrl = 0x4a009480, + .cm_l4per_hdq1w_clkctrl = 0x4a009488, + .cm_l4per_hecc1_clkctrl = 0x4a009490, + .cm_l4per_hecc2_clkctrl = 0x4a009498, + .cm_l4per_i2c1_clkctrl = 0x4a0094a0, + .cm_l4per_i2c2_clkctrl = 0x4a0094a8, + .cm_l4per_i2c3_clkctrl = 0x4a0094b0, + .cm_l4per_i2c4_clkctrl = 0x4a0094b8, + .cm_l4per_l4per_clkctrl = 0x4a0094c0, + .cm_l4per_mcasp2_clkctrl = 0x4a0094d0, + .cm_l4per_mcasp3_clkctrl = 0x4a0094d8, + .cm_l4per_mcbsp4_clkctrl = 0x4a0094e0, + .cm_l4per_mgate_clkctrl = 0x4a0094e8, + .cm_l4per_mcspi1_clkctrl = 0x4a0094f0, + .cm_l4per_mcspi2_clkctrl = 0x4a0094f8, + .cm_l4per_mcspi3_clkctrl = 0x4a009500, + .cm_l4per_mcspi4_clkctrl = 0x4a009508, + .cm_l4per_mmcsd3_clkctrl = 0x4a009520, + .cm_l4per_mmcsd4_clkctrl = 0x4a009528, + .cm_l4per_msprohg_clkctrl = 0x4a009530, + .cm_l4per_slimbus2_clkctrl = 0x4a009538, + .cm_l4per_uart1_clkctrl = 0x4a009540, + .cm_l4per_uart2_clkctrl = 0x4a009548, + .cm_l4per_uart3_clkctrl = 0x4a009550, + .cm_l4per_uart4_clkctrl = 0x4a009558, + .cm_l4per_mmcsd5_clkctrl = 0x4a009560, + .cm_l4per_i2c5_clkctrl = 0x4a009568, + .cm_l4sec_clkstctrl = 0x4a009580, + .cm_l4sec_staticdep = 0x4a009584, + .cm_l4sec_dynamicdep = 0x4a009588, + .cm_l4sec_aes1_clkctrl = 0x4a0095a0, + .cm_l4sec_aes2_clkctrl = 0x4a0095a8, + .cm_l4sec_des3des_clkctrl = 0x4a0095b0, + .cm_l4sec_pkaeip29_clkctrl = 0x4a0095b8, + .cm_l4sec_rng_clkctrl = 0x4a0095c0, + .cm_l4sec_sha2md51_clkctrl = 0x4a0095c8, + .cm_l4sec_cryptodma_clkctrl = 0x4a0095d8, + + /* l4 wkup regs */ + .cm_abe_pll_ref_clksel = 0x4a30610c, + .cm_sys_clksel = 0x4a306110, + .cm_wkup_clkstctrl = 0x4a307800, + .cm_wkup_l4wkup_clkctrl = 0x4a307820, + .cm_wkup_wdtimer1_clkctrl = 0x4a307828, + .cm_wkup_wdtimer2_clkctrl = 0x4a307830, + .cm_wkup_gpio1_clkctrl = 0x4a307838, + .cm_wkup_gptimer1_clkctrl = 0x4a307840, + .cm_wkup_gptimer12_clkctrl = 0x4a307848, + .cm_wkup_synctimer_clkctrl = 0x4a307850, + .cm_wkup_usim_clkctrl = 0x4a307858, + .cm_wkup_sarram_clkctrl = 0x4a307860, + .cm_wkup_keyboard_clkctrl = 0x4a307878, + .cm_wkup_rtc_clkctrl = 0x4a307880, + .cm_wkup_bandgap_clkctrl = 0x4a307888, + .prm_vc_val_bypass = 0x4a307ba0, + .prm_vc_cfg_channel = 0x4a307ba4, + .prm_vc_cfg_i2c_mode = 0x4a307ba8, + .prm_vc_cfg_i2c_clk = 0x4a307bac, +}; + +struct omap_sys_ctrl_regs const omap4_ctrl = { + .control_id_code = 0x4A002204, + .control_std_fuse_opp_bgap = 0x4a002260, + .control_status = 0x4a0022c4, + .control_ldosram_iva_voltage_ctrl = 0x4A002320, + .control_ldosram_mpu_voltage_ctrl = 0x4A002324, + .control_ldosram_core_voltage_ctrl = 0x4A002328, + .control_usbotghs_ctrl = 0x4A00233C, + .control_padconf_core_base = 0x4A100000, + .control_pbiaslite = 0x4A100600, + .control_lpddr2io1_0 = 0x4A100638, + .control_lpddr2io1_1 = 0x4A10063C, + .control_lpddr2io1_2 = 0x4A100640, + .control_lpddr2io1_3 = 0x4A100644, + .control_lpddr2io2_0 = 0x4A100648, + .control_lpddr2io2_1 = 0x4A10064C, + .control_lpddr2io2_2 = 0x4A100650, + .control_lpddr2io2_3 = 0x4A100654, + .control_efuse_1 = 0x4A100700, + .control_efuse_2 = 0x4A100704, + .control_padconf_wkup_base = 0x4A31E000, +}; diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/sdram_elpida.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/sdram_elpida.c new file mode 100644 index 000000000..6903696e1 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap4/sdram_elpida.c @@ -0,0 +1,328 @@ +/* + * Timing and Organization details of the Elpida parts used in OMAP4 + * SDPs and Panda + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/emif.h> +#include <asm/arch/sys_proto.h> + +/* + * This file provides details of the LPDDR2 SDRAM parts used on OMAP4430 + * SDP and Panda. Since the parts used and geometry are identical for + * SDP and Panda for a given OMAP4 revision, this information is kept + * here instead of being in board directory. However the key functions + * exported are weakly linked so that they can be over-ridden in the board + * directory if there is a OMAP4 board in the future that uses a different + * memory device or geometry. + * + * For any new board with different memory devices over-ride one or more + * of the following functions as per the CONFIG flags you intend to enable: + * - emif_get_reg_dump() + * - emif_get_dmm_regs() + * - emif_get_device_details() + * - emif_get_device_timings() + */ + +#ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS + +const struct emif_regs emif_regs_elpida_200_mhz_2cs = { + .sdram_config_init = 0x80000eb9, + .sdram_config = 0x80001ab9, + .ref_ctrl = 0x0000030c, + .sdram_tim1 = 0x08648311, + .sdram_tim2 = 0x101b06ca, + .sdram_tim3 = 0x0048a19f, + .read_idle_ctrl = 0x000501ff, + .zq_config = 0x500b3214, + .temp_alert_config = 0xd8016893, + .emif_ddr_phy_ctlr_1_init = 0x049ffff5, + .emif_ddr_phy_ctlr_1 = 0x049ff808 +}; + +const struct emif_regs emif_regs_elpida_380_mhz_1cs = { + .sdram_config_init = 0x80000eb1, + .sdram_config = 0x80001ab1, + .ref_ctrl = 0x000005cd, + .sdram_tim1 = 0x10cb0622, + .sdram_tim2 = 0x20350d52, + .sdram_tim3 = 0x00b1431f, + .read_idle_ctrl = 0x000501ff, + .zq_config = 0x500b3214, + .temp_alert_config = 0x58016893, + .emif_ddr_phy_ctlr_1_init = 0x049ffff5, + .emif_ddr_phy_ctlr_1 = 0x049ff418 +}; + +const struct emif_regs emif_regs_elpida_400_mhz_1cs = { + .sdram_config_init = 0x80800eb2, + .sdram_config = 0x80801ab2, + .ref_ctrl = 0x00000618, + .sdram_tim1 = 0x10eb0662, + .sdram_tim2 = 0x20370dd2, + .sdram_tim3 = 0x00b1c33f, + .read_idle_ctrl = 0x000501ff, + .zq_config = 0x500b3215, + .temp_alert_config = 0x58016893, + .emif_ddr_phy_ctlr_1_init = 0x049ffff5, + .emif_ddr_phy_ctlr_1 = 0x049ff418 +}; + +const struct emif_regs emif_regs_elpida_400_mhz_2cs = { + .sdram_config_init = 0x80000eb9, + .sdram_config = 0x80001ab9, + .ref_ctrl = 0x00000618, + .sdram_tim1 = 0x10eb0662, + .sdram_tim2 = 0x20370dd2, + .sdram_tim3 = 0x00b1c33f, + .read_idle_ctrl = 0x000501ff, + .zq_config = 0xd00b3214, + .temp_alert_config = 0xd8016893, + .emif_ddr_phy_ctlr_1_init = 0x049ffff5, + .emif_ddr_phy_ctlr_1 = 0x049ff418 +}; + +const struct dmm_lisa_map_regs lisa_map_2G_x_1_x_2 = { + .dmm_lisa_map_0 = 0xFF020100, + .dmm_lisa_map_1 = 0, + .dmm_lisa_map_2 = 0, + .dmm_lisa_map_3 = 0x80540300, + .is_ma_present = 0x0 +}; + +const struct dmm_lisa_map_regs lisa_map_2G_x_2_x_2 = { + .dmm_lisa_map_0 = 0xFF020100, + .dmm_lisa_map_1 = 0, + .dmm_lisa_map_2 = 0, + .dmm_lisa_map_3 = 0x80640300, + .is_ma_present = 0x0 +}; + +const struct dmm_lisa_map_regs ma_lisa_map_2G_x_2_x_2 = { + .dmm_lisa_map_0 = 0xFF020100, + .dmm_lisa_map_1 = 0, + .dmm_lisa_map_2 = 0, + .dmm_lisa_map_3 = 0x80640300, + .is_ma_present = 0x1 +}; + +static void emif_get_reg_dump_sdp(u32 emif_nr, const struct emif_regs **regs) +{ + u32 omap4_rev = omap_revision(); + + /* Same devices and geometry on both EMIFs */ + if (omap4_rev == OMAP4430_ES1_0) + *regs = &emif_regs_elpida_380_mhz_1cs; + else if (omap4_rev == OMAP4430_ES2_0) + *regs = &emif_regs_elpida_200_mhz_2cs; + else if (omap4_rev == OMAP4430_ES2_3) + *regs = &emif_regs_elpida_400_mhz_1cs; + else if (omap4_rev < OMAP4470_ES1_0) + *regs = &emif_regs_elpida_400_mhz_2cs; + else + *regs = &emif_regs_elpida_400_mhz_1cs; +} +void emif_get_reg_dump(u32 emif_nr, const struct emif_regs **regs) + __attribute__((weak, alias("emif_get_reg_dump_sdp"))); + +static void emif_get_dmm_regs_sdp(const struct dmm_lisa_map_regs + **dmm_lisa_regs) +{ + u32 omap_rev = omap_revision(); + + if (omap_rev == OMAP4430_ES1_0) + *dmm_lisa_regs = &lisa_map_2G_x_1_x_2; + else if (omap_rev == OMAP4430_ES2_3) + *dmm_lisa_regs = &lisa_map_2G_x_2_x_2; + else if (omap_rev < OMAP4460_ES1_0) + *dmm_lisa_regs = &lisa_map_2G_x_2_x_2; + else + *dmm_lisa_regs = &ma_lisa_map_2G_x_2_x_2; +} + +void emif_get_dmm_regs(const struct dmm_lisa_map_regs **dmm_lisa_regs) + __attribute__((weak, alias("emif_get_dmm_regs_sdp"))); + +#else + +static const struct lpddr2_device_details elpida_2G_S4_details = { + .type = LPDDR2_TYPE_S4, + .density = LPDDR2_DENSITY_2Gb, + .io_width = LPDDR2_IO_WIDTH_32, + .manufacturer = LPDDR2_MANUFACTURER_ELPIDA +}; + +static const struct lpddr2_device_details elpida_4G_S4_details = { + .type = LPDDR2_TYPE_S4, + .density = LPDDR2_DENSITY_4Gb, + .io_width = LPDDR2_IO_WIDTH_32, + .manufacturer = LPDDR2_MANUFACTURER_ELPIDA +}; + +struct lpddr2_device_details *emif_get_device_details_sdp(u32 emif_nr, u8 cs, + struct lpddr2_device_details *lpddr2_dev_details) +{ + u32 omap_rev = omap_revision(); + + /* EMIF1 & EMIF2 have identical configuration */ + if (((omap_rev == OMAP4430_ES1_0) || (omap_rev == OMAP4470_ES1_0)) + && (cs == CS1)) { + /* Nothing connected on CS1 for 4430/4470 ES1.0 */ + return NULL; + } else if (omap_rev < OMAP4470_ES1_0) { + /* In all other 4430/4460 cases Elpida 2G device */ + *lpddr2_dev_details = elpida_2G_S4_details; + } else { + /* 4470: 4G device */ + *lpddr2_dev_details = elpida_4G_S4_details; + } + return lpddr2_dev_details; +} + +struct lpddr2_device_details *emif_get_device_details(u32 emif_nr, u8 cs, + struct lpddr2_device_details *lpddr2_dev_details) + __attribute__((weak, alias("emif_get_device_details_sdp"))); + +#endif /* CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS */ + +#ifndef CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS +static const struct lpddr2_ac_timings timings_elpida_400_mhz = { + .max_freq = 400000000, + .RL = 6, + .tRPab = 21, + .tRCD = 18, + .tWR = 15, + .tRASmin = 42, + .tRRD = 10, + .tWTRx2 = 15, + .tXSR = 140, + .tXPx2 = 15, + .tRFCab = 130, + .tRTPx2 = 15, + .tCKE = 3, + .tCKESR = 15, + .tZQCS = 90, + .tZQCL = 360, + .tZQINIT = 1000, + .tDQSCKMAXx2 = 11, + .tRASmax = 70, + .tFAW = 50 +}; + +static const struct lpddr2_ac_timings timings_elpida_333_mhz = { + .max_freq = 333000000, + .RL = 5, + .tRPab = 21, + .tRCD = 18, + .tWR = 15, + .tRASmin = 42, + .tRRD = 10, + .tWTRx2 = 15, + .tXSR = 140, + .tXPx2 = 15, + .tRFCab = 130, + .tRTPx2 = 15, + .tCKE = 3, + .tCKESR = 15, + .tZQCS = 90, + .tZQCL = 360, + .tZQINIT = 1000, + .tDQSCKMAXx2 = 11, + .tRASmax = 70, + .tFAW = 50 +}; + +static const struct lpddr2_ac_timings timings_elpida_200_mhz = { + .max_freq = 200000000, + .RL = 3, + .tRPab = 21, + .tRCD = 18, + .tWR = 15, + .tRASmin = 42, + .tRRD = 10, + .tWTRx2 = 20, + .tXSR = 140, + .tXPx2 = 15, + .tRFCab = 130, + .tRTPx2 = 15, + .tCKE = 3, + .tCKESR = 15, + .tZQCS = 90, + .tZQCL = 360, + .tZQINIT = 1000, + .tDQSCKMAXx2 = 11, + .tRASmax = 70, + .tFAW = 50 +}; + +static const struct lpddr2_min_tck min_tck_elpida = { + .tRL = 3, + .tRP_AB = 3, + .tRCD = 3, + .tWR = 3, + .tRAS_MIN = 3, + .tRRD = 2, + .tWTR = 2, + .tXP = 2, + .tRTP = 2, + .tCKE = 3, + .tCKESR = 3, + .tFAW = 8 +}; + +static const struct lpddr2_ac_timings *elpida_ac_timings[MAX_NUM_SPEEDBINS] = { + &timings_elpida_200_mhz, + &timings_elpida_333_mhz, + &timings_elpida_400_mhz +}; + +static const struct lpddr2_device_timings elpida_2G_S4_timings = { + .ac_timings = elpida_ac_timings, + .min_tck = &min_tck_elpida, +}; + +void emif_get_device_timings_sdp(u32 emif_nr, + const struct lpddr2_device_timings **cs0_device_timings, + const struct lpddr2_device_timings **cs1_device_timings) +{ + u32 omap_rev = omap_revision(); + + /* Identical devices on EMIF1 & EMIF2 */ + *cs0_device_timings = &elpida_2G_S4_timings; + + if ((omap_rev == OMAP4430_ES1_0) || (omap_rev == OMAP4470_ES1_0)) + *cs1_device_timings = NULL; + else + *cs1_device_timings = &elpida_2G_S4_timings; +} + +void emif_get_device_timings(u32 emif_nr, + const struct lpddr2_device_timings **cs0_device_timings, + const struct lpddr2_device_timings **cs1_device_timings) + __attribute__((weak, alias("emif_get_device_timings_sdp"))); + +#endif /* CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS */ + +const struct lpddr2_mr_regs mr_regs = { + .mr1 = MR1_BL_8_BT_SEQ_WRAP_EN_NWR_3, + .mr2 = 0x4, + .mr3 = -1, + .mr10 = MR10_ZQ_ZQINIT, + .mr16 = MR16_REF_FULL_ARRAY +}; + +void get_lpddr2_mr_regs(const struct lpddr2_mr_regs **regs) +{ + *regs = &mr_regs; +} + +__weak const struct read_write_regs *get_bug_regs(u32 *iterations) +{ + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/Makefile new file mode 100644 index 000000000..64c68791f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/Makefile @@ -0,0 +1,13 @@ +# +# (C) Copyright 2000-2010 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += hwinit.o +obj-y += emif.o +obj-y += sdram.o +obj-y += prcm-regs.o +obj-y += hw_data.o +obj-y += abb.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/abb.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/abb.c new file mode 100644 index 000000000..3bf88979e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/abb.c @@ -0,0 +1,57 @@ +/* + * Adaptive Body Bias programming sequence for OMAP5 family + * + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * Andrii Tseglytskyi <andrii.tseglytskyi@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/omap_common.h> +#include <asm/io.h> + +/* + * Setup LDOVBB for OMAP5. + * On OMAP5+ some ABB settings are fused. They are handled + * in the following way: + * + * 1. corresponding EFUSE register contains ABB enable bit + * and VSET value + * 2. If ABB enable bit is set to 1, than ABB should be + * enabled, otherwise ABB should be disabled + * 3. If ABB is enabled, than VSET value should be copied + * to corresponding MUX control register + */ +s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb) +{ + u32 vset; + u32 fuse_enable_mask = OMAP5_ABB_FUSE_ENABLE_MASK; + u32 fuse_vset_mask = OMAP5_ABB_FUSE_VSET_MASK; + + if (!is_omap54xx()) { + /* DRA7 */ + fuse_enable_mask = DRA7_ABB_FUSE_ENABLE_MASK; + fuse_vset_mask = DRA7_ABB_FUSE_VSET_MASK; + } + /* + * ABB parameters must be properly fused + * otherwise ABB should be disabled + */ + vset = readl(fuse); + if (!(vset & fuse_enable_mask)) + return -1; + + /* prepare VSET value for LDOVBB mux register */ + vset &= fuse_vset_mask; + vset >>= ffs(fuse_vset_mask) - 1; + vset <<= ffs(OMAP5_ABB_LDOVBBMPU_VSET_OUT_MASK) - 1; + vset |= OMAP5_ABB_LDOVBBMPU_MUX_CTRL_MASK; + + /* setup LDOVBB using fused value */ + clrsetbits_le32(ldovbb, OMAP5_ABB_LDOVBBMPU_VSET_OUT_MASK, vset); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/config.mk b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/config.mk new file mode 100644 index 000000000..ef2725aff --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/config.mk @@ -0,0 +1,13 @@ +# +# Copyright 2011 Linaro Limited +# +# Aneesh V <annesh@ti.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +ifdef CONFIG_SPL_BUILD +ALL-y += MLO +else +ALL-y += u-boot.img +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/emif.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/emif.c new file mode 100644 index 000000000..b1203a37a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/emif.c @@ -0,0 +1,88 @@ +/* + * EMIF programming + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Aneesh V <aneesh@ti.com> for OMAP4 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/emif.h> +#include <asm/arch/sys_proto.h> +#include <asm/utils.h> + +#ifndef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS +#define print_timing_reg(reg) debug(#reg" - 0x%08x\n", (reg)) +static u32 *const T_num = (u32 *)OMAP_SRAM_SCRATCH_EMIF_T_NUM; +static u32 *const T_den = (u32 *)OMAP_SRAM_SCRATCH_EMIF_T_DEN; +#endif + +#ifdef CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS +/* Base AC Timing values specified by JESD209-2 for 532MHz operation */ +static const struct lpddr2_ac_timings timings_jedec_532_mhz = { + .max_freq = 532000000, + .RL = 8, + .tRPab = 21, + .tRCD = 18, + .tWR = 15, + .tRASmin = 42, + .tRRD = 10, + .tWTRx2 = 15, + .tXSR = 140, + .tXPx2 = 15, + .tRFCab = 130, + .tRTPx2 = 15, + .tCKE = 3, + .tCKESR = 15, + .tZQCS = 90, + .tZQCL = 360, + .tZQINIT = 1000, + .tDQSCKMAXx2 = 11, + .tRASmax = 70, + .tFAW = 50 +}; + +/* + * Min tCK values specified by JESD209-2 + * Min tCK specifies the minimum duration of some AC timing parameters in terms + * of the number of cycles. If the calculated number of cycles based on the + * absolute time value is less than the min tCK value, min tCK value should + * be used instead. This typically happens at low frequencies. + */ +static const struct lpddr2_min_tck min_tck_jedec = { + .tRL = 3, + .tRP_AB = 3, + .tRCD = 3, + .tWR = 3, + .tRAS_MIN = 3, + .tRRD = 2, + .tWTR = 2, + .tXP = 2, + .tRTP = 2, + .tCKE = 3, + .tCKESR = 3, + .tFAW = 8 +}; + +static const struct lpddr2_ac_timings const* + jedec_ac_timings[MAX_NUM_SPEEDBINS] = { + &timings_jedec_532_mhz +}; + +static const struct lpddr2_device_timings jedec_default_timings = { + .ac_timings = jedec_ac_timings, + .min_tck = &min_tck_jedec +}; + +void emif_get_device_timings(u32 emif_nr, + const struct lpddr2_device_timings **cs0_device_timings, + const struct lpddr2_device_timings **cs1_device_timings) +{ + /* Assume Identical devices on EMIF1 & EMIF2 */ + *cs0_device_timings = &jedec_default_timings; + *cs1_device_timings = NULL; +} +#endif /* CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/hw_data.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/hw_data.c new file mode 100644 index 000000000..ad971327b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/hw_data.c @@ -0,0 +1,589 @@ +/* + * + * HW data initialization for OMAP5 + * + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * Sricharan R <r.sricharan@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <palmas.h> +#include <asm/arch/omap.h> +#include <asm/arch/sys_proto.h> +#include <asm/omap_common.h> +#include <asm/arch/clock.h> +#include <asm/omap_gpio.h> +#include <asm/io.h> +#include <asm/emif.h> + +struct prcm_regs const **prcm = + (struct prcm_regs const **) OMAP_SRAM_SCRATCH_PRCM_PTR; +struct dplls const **dplls_data = + (struct dplls const **) OMAP_SRAM_SCRATCH_DPLLS_PTR; +struct vcores_data const **omap_vcores = + (struct vcores_data const **) OMAP_SRAM_SCRATCH_VCORES_PTR; +struct omap_sys_ctrl_regs const **ctrl = + (struct omap_sys_ctrl_regs const **)OMAP_SRAM_SCRATCH_SYS_CTRL; + +/* OPP HIGH FREQUENCY for ES2.0 */ +static const struct dpll_params mpu_dpll_params_1_5ghz[NUM_SYS_CLKS] = { + {125, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {625, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {625, 7, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {750, 12, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {625, 15, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* OPP NOM FREQUENCY for ES1.0 */ +static const struct dpll_params mpu_dpll_params_800mhz[NUM_SYS_CLKS] = { + {200, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {1000, 20, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {375, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {400, 12, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {375, 17, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* OPP LOW FREQUENCY for ES1.0 */ +static const struct dpll_params mpu_dpll_params_400mhz[NUM_SYS_CLKS] = { + {200, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {1000, 20, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {375, 8, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {400, 12, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {375, 17, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* OPP LOW FREQUENCY for ES2.0 */ +static const struct dpll_params mpu_dpll_params_499mhz[NUM_SYS_CLKS] = { + {499, 11, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {297, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {493, 18, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {499, 25, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {493, 37, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* OPP NOM FREQUENCY for OMAP5 ES2.0, and DRA7 ES1.0 */ +static const struct dpll_params mpu_dpll_params_1ghz[NUM_SYS_CLKS] = { + {250, 2, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {500, 9, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 20 MHz */ + {119, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {625, 11, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {500, 12, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {625, 23, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 38.4 MHz */ +}; + +static const struct dpll_params + core_dpll_params_2128mhz_ddr532[NUM_SYS_CLKS] = { + {266, 2, 2, 5, 8, 4, 62, 5, -1, 5, 7, -1}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {443, 6, 2, 5, 8, 4, 62, 5, -1, 5, 7, -1}, /* 16.8 MHz */ + {277, 4, 2, 5, 8, 4, 62, 5, -1, 5, 7, -1}, /* 19.2 MHz */ + {368, 8, 2, 5, 8, 4, 62, 5, -1, 5, 7, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {277, 9, 2, 5, 8, 4, 62, 5, -1, 5, 7, -1} /* 38.4 MHz */ +}; + +static const struct dpll_params + core_dpll_params_2128mhz_ddr532_es2[NUM_SYS_CLKS] = { + {266, 2, 2, 5, 8, 4, 62, 63, 6, 5, 7, 6}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {443, 6, 2, 5, 8, 4, 62, 63, 6, 5, 7, 6}, /* 16.8 MHz */ + {277, 4, 2, 5, 8, 4, 62, 63, 6, 5, 7, 6}, /* 19.2 MHz */ + {368, 8, 2, 5, 8, 4, 62, 63, 6, 5, 7, 6}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {277, 9, 2, 5, 8, 4, 62, 63, 6, 5, 7, 6} /* 38.4 MHz */ +}; + +static const struct dpll_params + core_dpll_params_2128mhz_dra7xx[NUM_SYS_CLKS] = { + {266, 2, 2, 1, -1, 4, 62, 5, -1, 5, 4, 6}, /* 12 MHz */ + {266, 4, 2, 1, -1, 4, 62, 5, -1, 5, 4, 6}, /* 20 MHz */ + {443, 6, 2, 1, -1, 4, 62, 5, -1, 5, 4, 6}, /* 16.8 MHz */ + {277, 4, 2, 1, -1, 4, 62, 5, -1, 5, 4, 6}, /* 19.2 MHz */ + {368, 8, 2, 1, -1, 4, 62, 5, -1, 5, 4, 6}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {277, 9, 2, 1, -1, 4, 62, 5, -1, 5, 4, 6}, /* 38.4 MHz */ +}; + +static const struct dpll_params + core_dpll_params_2128mhz_ddr266[NUM_SYS_CLKS] = { + {266, 2, 4, 8, 8, 8, 62, 10, -1, 10, 14, -1}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {443, 6, 4, 8, 8, 8, 62, 10, -1, 10, 14, -1}, /* 16.8 MHz */ + {277, 4, 4, 8, 8, 8, 62, 10, -1, 10, 14, -1}, /* 19.2 MHz */ + {368, 8, 4, 8, 8, 8, 62, 10, -1, 10, 14, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {277, 9, 4, 8, 8, 8, 62, 10, -1, 10, 14, -1} /* 38.4 MHz */ +}; + +static const struct dpll_params + core_dpll_params_2128mhz_ddr266_es2[NUM_SYS_CLKS] = { + {266, 2, 4, 8, 8, 8, 62, 5, 12, 10, 14, 12}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {443, 6, 4, 8, 8, 8, 62, 5, 12, 10, 14, 12}, /* 16.8 MHz */ + {277, 4, 4, 8, 8, 8, 62, 5, 12, 10, 14, 12}, /* 19.2 MHz */ + {368, 8, 4, 8, 8, 8, 62, 5, 12, 10, 14, 12}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {277, 9, 4, 8, 8, 8, 62, 5, 12, 10, 14, 12} /* 38.4 MHz */ +}; + +static const struct dpll_params per_dpll_params_768mhz[NUM_SYS_CLKS] = { + {32, 0, 4, 3, 6, 4, -1, 2, -1, -1, -1, -1}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {160, 6, 4, 3, 6, 4, -1, 2, -1, -1, -1, -1}, /* 16.8 MHz */ + {20, 0, 4, 3, 6, 4, -1, 2, -1, -1, -1, -1}, /* 19.2 MHz */ + {192, 12, 4, 3, 6, 4, -1, 2, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {10, 0, 4, 3, 6, 4, -1, 2, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +static const struct dpll_params per_dpll_params_768mhz_es2[NUM_SYS_CLKS] = { + {32, 0, 4, 3, 3, 4, -1, 2, -1, -1, -1, -1}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {160, 6, 4, 3, 3, 4, -1, 2, -1, -1, -1, -1}, /* 16.8 MHz */ + {20, 0, 4, 3, 3, 4, -1, 2, -1, -1, -1, -1}, /* 19.2 MHz */ + {192, 12, 4, 3, 3, 4, -1, 2, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {10, 0, 4, 3, 3, 4, -1, 2, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +static const struct dpll_params per_dpll_params_768mhz_dra7xx[NUM_SYS_CLKS] = { + {32, 0, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1}, /* 12 MHz */ + {96, 4, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1}, /* 20 MHz */ + {160, 6, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1}, /* 16.8 MHz */ + {20, 0, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1}, /* 19.2 MHz */ + {192, 12, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {10, 0, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1}, /* 38.4 MHz */ +}; + +static const struct dpll_params iva_dpll_params_2330mhz[NUM_SYS_CLKS] = { + {1165, 11, -1, -1, 5, 6, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {208, 2, -1, -1, 5, 6, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {182, 2, -1, -1, 5, 6, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {224, 4, -1, -1, 5, 6, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {91, 2, -1, -1, 5, 6, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +static const struct dpll_params iva_dpll_params_2330mhz_dra7xx[NUM_SYS_CLKS] = { + {1165, 11, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {233, 3, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 20 MHz */ + {208, 2, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {182, 2, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {224, 4, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {91, 2, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 38.4 MHz */ +}; + +/* ABE M & N values with sys_clk as source */ +static const struct dpll_params + abe_dpll_params_sysclk_196608khz[NUM_SYS_CLKS] = { + {49, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */ + {35, 5, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {46, 8, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {34, 8, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {64, 24, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */ +}; + +/* ABE M & N values with 32K clock as source */ +static const struct dpll_params abe_dpll_params_32k_196608khz = { + 750, 0, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +/* ABE M & N values with sysclk2(22.5792 MHz) as input */ +static const struct dpll_params + abe_dpll_params_sysclk2_361267khz[NUM_SYS_CLKS] = { + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {16, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 20 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 38.4 MHz */ +}; + +static const struct dpll_params usb_dpll_params_1920mhz[NUM_SYS_CLKS] = { + {400, 4, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {480, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 20 MHz */ + {400, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {400, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {480, 12, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {400, 15, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 38.4 MHz */ +}; + +static const struct dpll_params ddr_dpll_params_2128mhz[NUM_SYS_CLKS] = { + {266, 2, 2, 1, 8, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */ + {266, 4, 2, 1, 8, -1, -1, -1, -1, -1, -1, -1}, /* 20 MHz */ + {190, 2, 2, 1, 8, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {665, 11, 2, 1, 8, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {532, 12, 2, 1, 8, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {665, 23, 2, 1, 8, -1, -1, -1, -1, -1, -1, -1}, /* 38.4 MHz */ +}; + +static const struct dpll_params gmac_dpll_params_2000mhz[NUM_SYS_CLKS] = { + {250, 2, 4, 10, 40, 8, 10, -1, -1, -1, -1, -1}, /* 12 MHz */ + {250, 4, 4, 10, 40, 8, 10, -1, -1, -1, -1, -1}, /* 20 MHz */ + {119, 1, 4, 10, 40, 8, 10, -1, -1, -1, -1, -1}, /* 16.8 MHz */ + {625, 11, 4, 10, 40, 8, 10, -1, -1, -1, -1, -1}, /* 19.2 MHz */ + {500, 12, 4, 10, 40, 8, 10, -1, -1, -1, -1, -1}, /* 26 MHz */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */ + {625, 23, 4, 10, 40, 8, 10, -1, -1, -1, -1, -1}, /* 38.4 MHz */ +}; + +struct dplls omap5_dplls_es1 = { + .mpu = mpu_dpll_params_800mhz, + .core = core_dpll_params_2128mhz_ddr532, + .per = per_dpll_params_768mhz, + .iva = iva_dpll_params_2330mhz, +#ifdef CONFIG_SYS_OMAP_ABE_SYSCK + .abe = abe_dpll_params_sysclk_196608khz, +#else + .abe = &abe_dpll_params_32k_196608khz, +#endif + .usb = usb_dpll_params_1920mhz, + .ddr = NULL +}; + +struct dplls omap5_dplls_es2 = { + .mpu = mpu_dpll_params_1ghz, + .core = core_dpll_params_2128mhz_ddr532_es2, + .per = per_dpll_params_768mhz_es2, + .iva = iva_dpll_params_2330mhz, +#ifdef CONFIG_SYS_OMAP_ABE_SYSCK + .abe = abe_dpll_params_sysclk_196608khz, +#else + .abe = &abe_dpll_params_32k_196608khz, +#endif + .usb = usb_dpll_params_1920mhz, + .ddr = NULL +}; + +struct dplls dra7xx_dplls = { + .mpu = mpu_dpll_params_1ghz, + .core = core_dpll_params_2128mhz_dra7xx, + .per = per_dpll_params_768mhz_dra7xx, + .abe = abe_dpll_params_sysclk2_361267khz, + .iva = iva_dpll_params_2330mhz_dra7xx, + .usb = usb_dpll_params_1920mhz, + .ddr = ddr_dpll_params_2128mhz, + .gmac = gmac_dpll_params_2000mhz, +}; + +struct pmic_data palmas = { + .base_offset = PALMAS_SMPS_BASE_VOLT_UV, + .step = 10000, /* 10 mV represented in uV */ + /* + * Offset codes 1-6 all give the base voltage in Palmas + * Offset code 0 switches OFF the SMPS + */ + .start_code = 6, + .i2c_slave_addr = SMPS_I2C_SLAVE_ADDR, + .pmic_bus_init = sri2c_init, + .pmic_write = omap_vc_bypass_send_value, +}; + +struct pmic_data tps659038 = { + .base_offset = PALMAS_SMPS_BASE_VOLT_UV, + .step = 10000, /* 10 mV represented in uV */ + /* + * Offset codes 1-6 all give the base voltage in Palmas + * Offset code 0 switches OFF the SMPS + */ + .start_code = 6, + .i2c_slave_addr = TPS659038_I2C_SLAVE_ADDR, + .pmic_bus_init = gpi2c_init, + .pmic_write = palmas_i2c_write_u8, +}; + +struct vcores_data omap5430_volts = { + .mpu.value = VDD_MPU, + .mpu.addr = SMPS_REG_ADDR_12_MPU, + .mpu.pmic = &palmas, + + .core.value = VDD_CORE, + .core.addr = SMPS_REG_ADDR_8_CORE, + .core.pmic = &palmas, + + .mm.value = VDD_MM, + .mm.addr = SMPS_REG_ADDR_45_IVA, + .mm.pmic = &palmas, +}; + +struct vcores_data omap5430_volts_es2 = { + .mpu.value = VDD_MPU_ES2, + .mpu.addr = SMPS_REG_ADDR_12_MPU, + .mpu.pmic = &palmas, + + .core.value = VDD_CORE_ES2, + .core.addr = SMPS_REG_ADDR_8_CORE, + .core.pmic = &palmas, + + .mm.value = VDD_MM_ES2, + .mm.addr = SMPS_REG_ADDR_45_IVA, + .mm.pmic = &palmas, +}; + +struct vcores_data dra752_volts = { + .mpu.value = VDD_MPU_DRA752, + .mpu.efuse.reg = STD_FUSE_OPP_VMIN_MPU_NOM, + .mpu.efuse.reg_bits = DRA752_EFUSE_REGBITS, + .mpu.addr = TPS659038_REG_ADDR_SMPS12_MPU, + .mpu.pmic = &tps659038, + + .eve.value = VDD_EVE_DRA752, + .eve.efuse.reg = STD_FUSE_OPP_VMIN_DSPEVE_NOM, + .eve.efuse.reg_bits = DRA752_EFUSE_REGBITS, + .eve.addr = TPS659038_REG_ADDR_SMPS45_EVE, + .eve.pmic = &tps659038, + + .gpu.value = VDD_GPU_DRA752, + .gpu.efuse.reg = STD_FUSE_OPP_VMIN_GPU_NOM, + .gpu.efuse.reg_bits = DRA752_EFUSE_REGBITS, + .gpu.addr = TPS659038_REG_ADDR_SMPS6_GPU, + .gpu.pmic = &tps659038, + + .core.value = VDD_CORE_DRA752, + .core.efuse.reg = STD_FUSE_OPP_VMIN_CORE_NOM, + .core.efuse.reg_bits = DRA752_EFUSE_REGBITS, + .core.addr = TPS659038_REG_ADDR_SMPS7_CORE, + .core.pmic = &tps659038, + + .iva.value = VDD_IVA_DRA752, + .iva.efuse.reg = STD_FUSE_OPP_VMIN_IVA_NOM, + .iva.efuse.reg_bits = DRA752_EFUSE_REGBITS, + .iva.addr = TPS659038_REG_ADDR_SMPS8_IVA, + .iva.pmic = &tps659038, +}; + +/* + * Enable essential clock domains, modules and + * do some additional special settings needed + */ +void enable_basic_clocks(void) +{ + u32 const clk_domains_essential[] = { + (*prcm)->cm_l4per_clkstctrl, + (*prcm)->cm_l3init_clkstctrl, + (*prcm)->cm_memif_clkstctrl, + (*prcm)->cm_l4cfg_clkstctrl, +#ifdef CONFIG_DRIVER_TI_CPSW + (*prcm)->cm_gmac_clkstctrl, +#endif + 0 + }; + + u32 const clk_modules_hw_auto_essential[] = { + (*prcm)->cm_l3_gpmc_clkctrl, + (*prcm)->cm_memif_emif_1_clkctrl, + (*prcm)->cm_memif_emif_2_clkctrl, + (*prcm)->cm_l4cfg_l4_cfg_clkctrl, + (*prcm)->cm_wkup_gpio1_clkctrl, + (*prcm)->cm_l4per_gpio2_clkctrl, + (*prcm)->cm_l4per_gpio3_clkctrl, + (*prcm)->cm_l4per_gpio4_clkctrl, + (*prcm)->cm_l4per_gpio5_clkctrl, + (*prcm)->cm_l4per_gpio6_clkctrl, + (*prcm)->cm_l4per_gpio7_clkctrl, + (*prcm)->cm_l4per_gpio8_clkctrl, + 0 + }; + + u32 const clk_modules_explicit_en_essential[] = { + (*prcm)->cm_wkup_gptimer1_clkctrl, + (*prcm)->cm_l3init_hsmmc1_clkctrl, + (*prcm)->cm_l3init_hsmmc2_clkctrl, + (*prcm)->cm_l4per_gptimer2_clkctrl, + (*prcm)->cm_wkup_wdtimer2_clkctrl, + (*prcm)->cm_l4per_uart3_clkctrl, + (*prcm)->cm_l4per_i2c1_clkctrl, +#ifdef CONFIG_DRIVER_TI_CPSW + (*prcm)->cm_gmac_gmac_clkctrl, +#endif + +#ifdef CONFIG_TI_QSPI + (*prcm)->cm_l4per_qspi_clkctrl, +#endif + 0 + }; + + /* Enable optional additional functional clock for GPIO4 */ + setbits_le32((*prcm)->cm_l4per_gpio4_clkctrl, + GPIO4_CLKCTRL_OPTFCLKEN_MASK); + + /* Enable 96 MHz clock for MMC1 & MMC2 */ + setbits_le32((*prcm)->cm_l3init_hsmmc1_clkctrl, + HSMMC_CLKCTRL_CLKSEL_MASK); + setbits_le32((*prcm)->cm_l3init_hsmmc2_clkctrl, + HSMMC_CLKCTRL_CLKSEL_MASK); + + /* Set the correct clock dividers for mmc */ + setbits_le32((*prcm)->cm_l3init_hsmmc1_clkctrl, + HSMMC_CLKCTRL_CLKSEL_DIV_MASK); + setbits_le32((*prcm)->cm_l3init_hsmmc2_clkctrl, + HSMMC_CLKCTRL_CLKSEL_DIV_MASK); + + /* Select 32KHz clock as the source of GPTIMER1 */ + setbits_le32((*prcm)->cm_wkup_gptimer1_clkctrl, + GPTIMER1_CLKCTRL_CLKSEL_MASK); + + do_enable_clocks(clk_domains_essential, + clk_modules_hw_auto_essential, + clk_modules_explicit_en_essential, + 1); + +#ifdef CONFIG_TI_QSPI + setbits_le32((*prcm)->cm_l4per_qspi_clkctrl, (1<<24)); +#endif + + /* Enable SCRM OPT clocks for PER and CORE dpll */ + setbits_le32((*prcm)->cm_wkupaon_scrm_clkctrl, + OPTFCLKEN_SCRM_PER_MASK); + setbits_le32((*prcm)->cm_wkupaon_scrm_clkctrl, + OPTFCLKEN_SCRM_CORE_MASK); +} + +void enable_basic_uboot_clocks(void) +{ + u32 const clk_domains_essential[] = { + 0 + }; + + u32 const clk_modules_hw_auto_essential[] = { + (*prcm)->cm_l3init_hsusbtll_clkctrl, + 0 + }; + + u32 const clk_modules_explicit_en_essential[] = { + (*prcm)->cm_l4per_mcspi1_clkctrl, + (*prcm)->cm_l4per_i2c2_clkctrl, + (*prcm)->cm_l4per_i2c3_clkctrl, + (*prcm)->cm_l4per_i2c4_clkctrl, + (*prcm)->cm_l4per_i2c5_clkctrl, + (*prcm)->cm_l3init_hsusbhost_clkctrl, + (*prcm)->cm_l3init_fsusb_clkctrl, + 0 + }; + do_enable_clocks(clk_domains_essential, + clk_modules_hw_auto_essential, + clk_modules_explicit_en_essential, + 1); +} + +const struct ctrl_ioregs ioregs_omap5430 = { + .ctrl_ddrch = DDR_IO_I_34OHM_SR_FASTEST_WD_DQ_NO_PULL_DQS_PULL_DOWN, + .ctrl_lpddr2ch = DDR_IO_I_34OHM_SR_FASTEST_WD_CK_CKE_NCS_CA_PULL_DOWN, + .ctrl_ddrio_0 = DDR_IO_0_DDR2_DQ_INT_EN_ALL_DDR3_CA_DIS_ALL, + .ctrl_ddrio_1 = DDR_IO_1_DQ_OUT_EN_ALL_DQ_INT_EN_ALL, + .ctrl_ddrio_2 = DDR_IO_2_CA_OUT_EN_ALL_CA_INT_EN_ALL, +}; + +const struct ctrl_ioregs ioregs_omap5432_es1 = { + .ctrl_ddrch = DDR_IO_I_40OHM_SR_FAST_WD_DQ_NO_PULL_DQS_NO_PULL, + .ctrl_lpddr2ch = 0x0, + .ctrl_ddr3ch = DDR_IO_I_40OHM_SR_SLOWEST_WD_DQ_NO_PULL_DQS_NO_PULL, + .ctrl_ddrio_0 = DDR_IO_0_VREF_CELLS_DDR3_VALUE, + .ctrl_ddrio_1 = DDR_IO_1_VREF_CELLS_DDR3_VALUE, + .ctrl_ddrio_2 = DDR_IO_2_VREF_CELLS_DDR3_VALUE, + .ctrl_emif_sdram_config_ext = SDRAM_CONFIG_EXT_RD_LVL_11_SAMPLES, + .ctrl_emif_sdram_config_ext_final = SDRAM_CONFIG_EXT_RD_LVL_4_SAMPLES, +}; + +const struct ctrl_ioregs ioregs_omap5432_es2 = { + .ctrl_ddrch = DDR_IO_I_40OHM_SR_FAST_WD_DQ_NO_PULL_DQS_NO_PULL_ES2, + .ctrl_lpddr2ch = 0x0, + .ctrl_ddr3ch = DDR_IO_I_40OHM_SR_SLOWEST_WD_DQ_NO_PULL_DQS_NO_PULL_ES2, + .ctrl_ddrio_0 = DDR_IO_0_VREF_CELLS_DDR3_VALUE_ES2, + .ctrl_ddrio_1 = DDR_IO_1_VREF_CELLS_DDR3_VALUE_ES2, + .ctrl_ddrio_2 = DDR_IO_2_VREF_CELLS_DDR3_VALUE_ES2, + .ctrl_emif_sdram_config_ext = SDRAM_CONFIG_EXT_RD_LVL_11_SAMPLES, + .ctrl_emif_sdram_config_ext_final = SDRAM_CONFIG_EXT_RD_LVL_4_SAMPLES, +}; + +const struct ctrl_ioregs ioregs_dra7xx_es1 = { + .ctrl_ddrch = 0x40404040, + .ctrl_lpddr2ch = 0x40404040, + .ctrl_ddr3ch = 0x80808080, + .ctrl_ddrio_0 = 0xA2084210, + .ctrl_ddrio_1 = 0x84210840, + .ctrl_ddrio_2 = 0x84210000, + .ctrl_emif_sdram_config_ext = 0x0001C1A7, + .ctrl_emif_sdram_config_ext_final = 0x000101A7, + .ctrl_ddr_ctrl_ext_0 = 0xA2000000, +}; + +void hw_data_init(void) +{ + u32 omap_rev = omap_revision(); + + switch (omap_rev) { + + case OMAP5430_ES1_0: + case OMAP5432_ES1_0: + *prcm = &omap5_es1_prcm; + *dplls_data = &omap5_dplls_es1; + *omap_vcores = &omap5430_volts; + *ctrl = &omap5_ctrl; + break; + + case OMAP5430_ES2_0: + case OMAP5432_ES2_0: + *prcm = &omap5_es2_prcm; + *dplls_data = &omap5_dplls_es2; + *omap_vcores = &omap5430_volts_es2; + *ctrl = &omap5_ctrl; + break; + + case DRA752_ES1_0: + case DRA752_ES1_1: + *prcm = &dra7xx_prcm; + *dplls_data = &dra7xx_dplls; + *omap_vcores = &dra752_volts; + *ctrl = &dra7xx_ctrl; + break; + + default: + printf("\n INVALID OMAP REVISION "); + } +} + +void get_ioregs(const struct ctrl_ioregs **regs) +{ + u32 omap_rev = omap_revision(); + + switch (omap_rev) { + case OMAP5430_ES1_0: + case OMAP5430_ES2_0: + *regs = &ioregs_omap5430; + break; + case OMAP5432_ES1_0: + *regs = &ioregs_omap5432_es1; + break; + case OMAP5432_ES2_0: + *regs = &ioregs_omap5432_es2; + break; + case DRA752_ES1_0: + case DRA752_ES1_1: + *regs = &ioregs_dra7xx_es1; + break; + + default: + printf("\n INVALID OMAP REVISION "); + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/hwinit.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/hwinit.c new file mode 100644 index 000000000..93feb1623 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/hwinit.c @@ -0,0 +1,380 @@ +/* + * + * Functions for omap5 based boards. + * + * (C) Copyright 2011 + * Texas Instruments, <www.ti.com> + * + * Author : + * Aneesh V <aneesh@ti.com> + * Steve Sakoman <steve@sakoman.com> + * Sricharan <r.sricharan@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/armv7.h> +#include <asm/arch/cpu.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/clock.h> +#include <linux/sizes.h> +#include <asm/utils.h> +#include <asm/arch/gpio.h> +#include <asm/emif.h> +#include <asm/omap_common.h> + +DECLARE_GLOBAL_DATA_PTR; + +u32 *const omap_si_rev = (u32 *)OMAP_SRAM_SCRATCH_OMAP_REV; + +static struct gpio_bank gpio_bank_54xx[8] = { + { (void *)OMAP54XX_GPIO1_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP54XX_GPIO2_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP54XX_GPIO3_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP54XX_GPIO4_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP54XX_GPIO5_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP54XX_GPIO6_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP54XX_GPIO7_BASE, METHOD_GPIO_24XX }, + { (void *)OMAP54XX_GPIO8_BASE, METHOD_GPIO_24XX }, +}; + +const struct gpio_bank *const omap_gpio_bank = gpio_bank_54xx; + +#ifdef CONFIG_SPL_BUILD +/* LPDDR2 specific IO settings */ +static void io_settings_lpddr2(void) +{ + const struct ctrl_ioregs *ioregs; + + get_ioregs(&ioregs); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch1_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch1_1); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch2_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch2_1); + writel(ioregs->ctrl_lpddr2ch, (*ctrl)->control_lpddr2ch1_0); + writel(ioregs->ctrl_lpddr2ch, (*ctrl)->control_lpddr2ch1_1); + writel(ioregs->ctrl_ddrio_0, (*ctrl)->control_ddrio_0); + writel(ioregs->ctrl_ddrio_1, (*ctrl)->control_ddrio_1); + writel(ioregs->ctrl_ddrio_2, (*ctrl)->control_ddrio_2); +} + +/* DDR3 specific IO settings */ +static void io_settings_ddr3(void) +{ + u32 io_settings = 0; + const struct ctrl_ioregs *ioregs; + + get_ioregs(&ioregs); + writel(ioregs->ctrl_ddr3ch, (*ctrl)->control_ddr3ch1_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch1_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch1_1); + + writel(ioregs->ctrl_ddr3ch, (*ctrl)->control_ddr3ch2_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch2_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch2_1); + + writel(ioregs->ctrl_ddrio_0, (*ctrl)->control_ddrio_0); + writel(ioregs->ctrl_ddrio_1, (*ctrl)->control_ddrio_1); + writel(ioregs->ctrl_ddrio_2, (*ctrl)->control_ddrio_2); + + /* omap5432 does not use lpddr2 */ + writel(ioregs->ctrl_lpddr2ch, (*ctrl)->control_lpddr2ch1_0); + writel(ioregs->ctrl_lpddr2ch, (*ctrl)->control_lpddr2ch1_1); + + writel(ioregs->ctrl_emif_sdram_config_ext, + (*ctrl)->control_emif1_sdram_config_ext); + writel(ioregs->ctrl_emif_sdram_config_ext, + (*ctrl)->control_emif2_sdram_config_ext); + + if (is_omap54xx()) { + /* Disable DLL select */ + io_settings = (readl((*ctrl)->control_port_emif1_sdram_config) + & 0xFFEFFFFF); + writel(io_settings, + (*ctrl)->control_port_emif1_sdram_config); + + io_settings = (readl((*ctrl)->control_port_emif2_sdram_config) + & 0xFFEFFFFF); + writel(io_settings, + (*ctrl)->control_port_emif2_sdram_config); + } else { + writel(ioregs->ctrl_ddr_ctrl_ext_0, + (*ctrl)->control_ddr_control_ext_0); + } +} + +/* + * Some tuning of IOs for optimal power and performance + */ +void do_io_settings(void) +{ + u32 io_settings = 0, mask = 0; + + /* Impedance settings EMMC, C2C 1,2, hsi2 */ + mask = (ds_mask << 2) | (ds_mask << 8) | + (ds_mask << 16) | (ds_mask << 18); + io_settings = readl((*ctrl)->control_smart1io_padconf_0) & + (~mask); + io_settings |= (ds_60_ohm << 8) | (ds_45_ohm << 16) | + (ds_45_ohm << 18) | (ds_60_ohm << 2); + writel(io_settings, (*ctrl)->control_smart1io_padconf_0); + + /* Impedance settings Mcspi2 */ + mask = (ds_mask << 30); + io_settings = readl((*ctrl)->control_smart1io_padconf_1) & + (~mask); + io_settings |= (ds_60_ohm << 30); + writel(io_settings, (*ctrl)->control_smart1io_padconf_1); + + /* Impedance settings C2C 3,4 */ + mask = (ds_mask << 14) | (ds_mask << 16); + io_settings = readl((*ctrl)->control_smart1io_padconf_2) & + (~mask); + io_settings |= (ds_45_ohm << 14) | (ds_45_ohm << 16); + writel(io_settings, (*ctrl)->control_smart1io_padconf_2); + + /* Slew rate settings EMMC, C2C 1,2 */ + mask = (sc_mask << 8) | (sc_mask << 16) | (sc_mask << 18); + io_settings = readl((*ctrl)->control_smart2io_padconf_0) & + (~mask); + io_settings |= (sc_fast << 8) | (sc_na << 16) | (sc_na << 18); + writel(io_settings, (*ctrl)->control_smart2io_padconf_0); + + /* Slew rate settings hsi2, Mcspi2 */ + mask = (sc_mask << 24) | (sc_mask << 28); + io_settings = readl((*ctrl)->control_smart2io_padconf_1) & + (~mask); + io_settings |= (sc_fast << 28) | (sc_fast << 24); + writel(io_settings, (*ctrl)->control_smart2io_padconf_1); + + /* Slew rate settings C2C 3,4 */ + mask = (sc_mask << 16) | (sc_mask << 18); + io_settings = readl((*ctrl)->control_smart2io_padconf_2) & + (~mask); + io_settings |= (sc_na << 16) | (sc_na << 18); + writel(io_settings, (*ctrl)->control_smart2io_padconf_2); + + /* impedance and slew rate settings for usb */ + mask = (usb_i_mask << 29) | (usb_i_mask << 26) | (usb_i_mask << 23) | + (usb_i_mask << 20) | (usb_i_mask << 17) | (usb_i_mask << 14); + io_settings = readl((*ctrl)->control_smart3io_padconf_1) & + (~mask); + io_settings |= (ds_60_ohm << 29) | (ds_60_ohm << 26) | + (ds_60_ohm << 23) | (sc_fast << 20) | + (sc_fast << 17) | (sc_fast << 14); + writel(io_settings, (*ctrl)->control_smart3io_padconf_1); + + if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2) + io_settings_lpddr2(); + else + io_settings_ddr3(); +} + +static const struct srcomp_params srcomp_parameters[NUM_SYS_CLKS] = { + {0x45, 0x1}, /* 12 MHz */ + {-1, -1}, /* 13 MHz */ + {0x63, 0x2}, /* 16.8 MHz */ + {0x57, 0x2}, /* 19.2 MHz */ + {0x20, 0x1}, /* 26 MHz */ + {-1, -1}, /* 27 MHz */ + {0x41, 0x3} /* 38.4 MHz */ +}; + +void srcomp_enable(void) +{ + u32 srcomp_value, mul_factor, div_factor, clk_val, i; + u32 sysclk_ind = get_sys_clk_index(); + u32 omap_rev = omap_revision(); + + if (!is_omap54xx()) + return; + + mul_factor = srcomp_parameters[sysclk_ind].multiply_factor; + div_factor = srcomp_parameters[sysclk_ind].divide_factor; + + for (i = 0; i < 4; i++) { + srcomp_value = readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value &= + ~(MULTIPLY_FACTOR_XS_MASK | DIVIDE_FACTOR_XS_MASK); + srcomp_value |= (mul_factor << MULTIPLY_FACTOR_XS_SHIFT) | + (div_factor << DIVIDE_FACTOR_XS_SHIFT); + writel(srcomp_value, (*ctrl)->control_srcomp_north_side + i*4); + } + + if ((omap_rev == OMAP5430_ES1_0) || (omap_rev == OMAP5432_ES1_0)) { + clk_val = readl((*prcm)->cm_coreaon_io_srcomp_clkctrl); + clk_val |= OPTFCLKEN_SRCOMP_FCLK_MASK; + writel(clk_val, (*prcm)->cm_coreaon_io_srcomp_clkctrl); + + for (i = 0; i < 4; i++) { + srcomp_value = + readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value &= ~PWRDWN_XS_MASK; + writel(srcomp_value, + (*ctrl)->control_srcomp_north_side + i*4); + + while (((readl((*ctrl)->control_srcomp_north_side + i*4) + & SRCODE_READ_XS_MASK) >> + SRCODE_READ_XS_SHIFT) == 0) + ; + + srcomp_value = + readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value &= ~OVERRIDE_XS_MASK; + writel(srcomp_value, + (*ctrl)->control_srcomp_north_side + i*4); + } + } else { + srcomp_value = readl((*ctrl)->control_srcomp_east_side_wkup); + srcomp_value &= ~(MULTIPLY_FACTOR_XS_MASK | + DIVIDE_FACTOR_XS_MASK); + srcomp_value |= (mul_factor << MULTIPLY_FACTOR_XS_SHIFT) | + (div_factor << DIVIDE_FACTOR_XS_SHIFT); + writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup); + + for (i = 0; i < 4; i++) { + srcomp_value = + readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value |= SRCODE_OVERRIDE_SEL_XS_MASK; + writel(srcomp_value, + (*ctrl)->control_srcomp_north_side + i*4); + + srcomp_value = + readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value &= ~OVERRIDE_XS_MASK; + writel(srcomp_value, + (*ctrl)->control_srcomp_north_side + i*4); + } + + srcomp_value = + readl((*ctrl)->control_srcomp_east_side_wkup); + srcomp_value |= SRCODE_OVERRIDE_SEL_XS_MASK; + writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup); + + srcomp_value = + readl((*ctrl)->control_srcomp_east_side_wkup); + srcomp_value &= ~OVERRIDE_XS_MASK; + writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup); + + clk_val = readl((*prcm)->cm_coreaon_io_srcomp_clkctrl); + clk_val |= OPTFCLKEN_SRCOMP_FCLK_MASK; + writel(clk_val, (*prcm)->cm_coreaon_io_srcomp_clkctrl); + + clk_val = readl((*prcm)->cm_wkupaon_io_srcomp_clkctrl); + clk_val |= OPTFCLKEN_SRCOMP_FCLK_MASK; + writel(clk_val, (*prcm)->cm_wkupaon_io_srcomp_clkctrl); + + for (i = 0; i < 4; i++) { + while (((readl((*ctrl)->control_srcomp_north_side + i*4) + & SRCODE_READ_XS_MASK) >> + SRCODE_READ_XS_SHIFT) == 0) + ; + + srcomp_value = + readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value &= ~SRCODE_OVERRIDE_SEL_XS_MASK; + writel(srcomp_value, + (*ctrl)->control_srcomp_north_side + i*4); + } + + while (((readl((*ctrl)->control_srcomp_east_side_wkup) & + SRCODE_READ_XS_MASK) >> SRCODE_READ_XS_SHIFT) == 0) + ; + + srcomp_value = + readl((*ctrl)->control_srcomp_east_side_wkup); + srcomp_value &= ~SRCODE_OVERRIDE_SEL_XS_MASK; + writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup); + } +} +#endif + +void config_data_eye_leveling_samples(u32 emif_base) +{ + const struct ctrl_ioregs *ioregs; + + get_ioregs(&ioregs); + + /*EMIF_SDRAM_CONFIG_EXT-Read data eye leveling no of samples =4*/ + if (emif_base == EMIF1_BASE) + writel(ioregs->ctrl_emif_sdram_config_ext_final, + (*ctrl)->control_emif1_sdram_config_ext); + else if (emif_base == EMIF2_BASE) + writel(ioregs->ctrl_emif_sdram_config_ext_final, + (*ctrl)->control_emif2_sdram_config_ext); +} + +void init_omap_revision(void) +{ + /* + * For some of the ES2/ES1 boards ID_CODE is not reliable: + * Also, ES1 and ES2 have different ARM revisions + * So use ARM revision for identification + */ + unsigned int rev = cortex_rev(); + + switch (readl(CONTROL_ID_CODE)) { + case OMAP5430_CONTROL_ID_CODE_ES1_0: + *omap_si_rev = OMAP5430_ES1_0; + if (rev == MIDR_CORTEX_A15_R2P2) + *omap_si_rev = OMAP5430_ES2_0; + break; + case OMAP5432_CONTROL_ID_CODE_ES1_0: + *omap_si_rev = OMAP5432_ES1_0; + if (rev == MIDR_CORTEX_A15_R2P2) + *omap_si_rev = OMAP5432_ES2_0; + break; + case OMAP5430_CONTROL_ID_CODE_ES2_0: + *omap_si_rev = OMAP5430_ES2_0; + break; + case OMAP5432_CONTROL_ID_CODE_ES2_0: + *omap_si_rev = OMAP5432_ES2_0; + break; + case DRA752_CONTROL_ID_CODE_ES1_0: + *omap_si_rev = DRA752_ES1_0; + break; + case DRA752_CONTROL_ID_CODE_ES1_1: + *omap_si_rev = DRA752_ES1_1; + break; + default: + *omap_si_rev = OMAP5430_SILICON_ID_INVALID; + } +} + +void reset_cpu(ulong ignored) +{ + u32 omap_rev = omap_revision(); + + /* + * WARM reset is not functional in case of OMAP5430 ES1.0 soc. + * So use cold reset in case instead. + */ + if (omap_rev == OMAP5430_ES1_0) + writel(PRM_RSTCTRL_RESET << 0x1, (*prcm)->prm_rstctrl); + else + writel(PRM_RSTCTRL_RESET, (*prcm)->prm_rstctrl); +} + +u32 warm_reset(void) +{ + return readl((*prcm)->prm_rstst) & PRM_RSTST_WARM_RESET_MASK; +} + +void setup_warmreset_time(void) +{ + u32 rst_time, rst_val; + +#ifndef CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC + rst_time = CONFIG_DEFAULT_OMAP_RESET_TIME_MAX_USEC; +#else + rst_time = CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC; +#endif + rst_time = usec_to_32k(rst_time) << RSTTIME1_SHIFT; + + if (rst_time > RSTTIME1_MASK) + rst_time = RSTTIME1_MASK; + + rst_val = readl((*prcm)->prm_rsttime) & ~RSTTIME1_MASK; + rst_val |= rst_time; + writel(rst_val, (*prcm)->prm_rsttime); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/prcm-regs.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/prcm-regs.c new file mode 100644 index 000000000..7292161f3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/prcm-regs.c @@ -0,0 +1,978 @@ +/* + * + * HW regs data for OMAP5 Soc + * + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * Sricharan R <r.sricharan@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/omap_common.h> + +struct prcm_regs const omap5_es1_prcm = { + /* cm1.ckgen */ + .cm_clksel_core = 0x4a004100, + .cm_clksel_abe = 0x4a004108, + .cm_dll_ctrl = 0x4a004110, + .cm_clkmode_dpll_core = 0x4a004120, + .cm_idlest_dpll_core = 0x4a004124, + .cm_autoidle_dpll_core = 0x4a004128, + .cm_clksel_dpll_core = 0x4a00412c, + .cm_div_m2_dpll_core = 0x4a004130, + .cm_div_m3_dpll_core = 0x4a004134, + .cm_div_h11_dpll_core = 0x4a004138, + .cm_div_h12_dpll_core = 0x4a00413c, + .cm_div_h13_dpll_core = 0x4a004140, + .cm_div_h14_dpll_core = 0x4a004144, + .cm_ssc_deltamstep_dpll_core = 0x4a004148, + .cm_ssc_modfreqdiv_dpll_core = 0x4a00414c, + .cm_emu_override_dpll_core = 0x4a004150, + .cm_div_h22_dpllcore = 0x4a004154, + .cm_div_h23_dpll_core = 0x4a004158, + .cm_clkmode_dpll_mpu = 0x4a004160, + .cm_idlest_dpll_mpu = 0x4a004164, + .cm_autoidle_dpll_mpu = 0x4a004168, + .cm_clksel_dpll_mpu = 0x4a00416c, + .cm_div_m2_dpll_mpu = 0x4a004170, + .cm_ssc_deltamstep_dpll_mpu = 0x4a004188, + .cm_ssc_modfreqdiv_dpll_mpu = 0x4a00418c, + .cm_bypclk_dpll_mpu = 0x4a00419c, + .cm_clkmode_dpll_iva = 0x4a0041a0, + .cm_idlest_dpll_iva = 0x4a0041a4, + .cm_autoidle_dpll_iva = 0x4a0041a8, + .cm_clksel_dpll_iva = 0x4a0041ac, + .cm_div_h11_dpll_iva = 0x4a0041b8, + .cm_div_h12_dpll_iva = 0x4a0041bc, + .cm_ssc_deltamstep_dpll_iva = 0x4a0041c8, + .cm_ssc_modfreqdiv_dpll_iva = 0x4a0041cc, + .cm_bypclk_dpll_iva = 0x4a0041dc, + .cm_clkmode_dpll_abe = 0x4a0041e0, + .cm_idlest_dpll_abe = 0x4a0041e4, + .cm_autoidle_dpll_abe = 0x4a0041e8, + .cm_clksel_dpll_abe = 0x4a0041ec, + .cm_div_m2_dpll_abe = 0x4a0041f0, + .cm_div_m3_dpll_abe = 0x4a0041f4, + .cm_ssc_deltamstep_dpll_abe = 0x4a004208, + .cm_ssc_modfreqdiv_dpll_abe = 0x4a00420c, + .cm_clkmode_dpll_ddrphy = 0x4a004220, + .cm_idlest_dpll_ddrphy = 0x4a004224, + .cm_autoidle_dpll_ddrphy = 0x4a004228, + .cm_clksel_dpll_ddrphy = 0x4a00422c, + .cm_div_m2_dpll_ddrphy = 0x4a004230, + .cm_div_h11_dpll_ddrphy = 0x4a004238, + .cm_div_h12_dpll_ddrphy = 0x4a00423c, + .cm_div_h13_dpll_ddrphy = 0x4a004240, + .cm_ssc_deltamstep_dpll_ddrphy = 0x4a004248, + .cm_shadow_freq_config1 = 0x4a004260, + .cm_mpu_mpu_clkctrl = 0x4a004320, + + /* cm1.dsp */ + .cm_dsp_clkstctrl = 0x4a004400, + .cm_dsp_dsp_clkctrl = 0x4a004420, + + /* cm1.abe */ + .cm1_abe_clkstctrl = 0x4a004500, + .cm1_abe_l4abe_clkctrl = 0x4a004520, + .cm1_abe_aess_clkctrl = 0x4a004528, + .cm1_abe_pdm_clkctrl = 0x4a004530, + .cm1_abe_dmic_clkctrl = 0x4a004538, + .cm1_abe_mcasp_clkctrl = 0x4a004540, + .cm1_abe_mcbsp1_clkctrl = 0x4a004548, + .cm1_abe_mcbsp2_clkctrl = 0x4a004550, + .cm1_abe_mcbsp3_clkctrl = 0x4a004558, + .cm1_abe_slimbus_clkctrl = 0x4a004560, + .cm1_abe_timer5_clkctrl = 0x4a004568, + .cm1_abe_timer6_clkctrl = 0x4a004570, + .cm1_abe_timer7_clkctrl = 0x4a004578, + .cm1_abe_timer8_clkctrl = 0x4a004580, + .cm1_abe_wdt3_clkctrl = 0x4a004588, + + /* cm2.ckgen */ + .cm_clksel_mpu_m3_iss_root = 0x4a008100, + .cm_clksel_usb_60mhz = 0x4a008104, + .cm_scale_fclk = 0x4a008108, + .cm_core_dvfs_perf1 = 0x4a008110, + .cm_core_dvfs_perf2 = 0x4a008114, + .cm_core_dvfs_perf3 = 0x4a008118, + .cm_core_dvfs_perf4 = 0x4a00811c, + .cm_core_dvfs_current = 0x4a008124, + .cm_iva_dvfs_perf_tesla = 0x4a008128, + .cm_iva_dvfs_perf_ivahd = 0x4a00812c, + .cm_iva_dvfs_perf_abe = 0x4a008130, + .cm_iva_dvfs_current = 0x4a008138, + .cm_clkmode_dpll_per = 0x4a008140, + .cm_idlest_dpll_per = 0x4a008144, + .cm_autoidle_dpll_per = 0x4a008148, + .cm_clksel_dpll_per = 0x4a00814c, + .cm_div_m2_dpll_per = 0x4a008150, + .cm_div_m3_dpll_per = 0x4a008154, + .cm_div_h11_dpll_per = 0x4a008158, + .cm_div_h12_dpll_per = 0x4a00815c, + .cm_div_h14_dpll_per = 0x4a008164, + .cm_ssc_deltamstep_dpll_per = 0x4a008168, + .cm_ssc_modfreqdiv_dpll_per = 0x4a00816c, + .cm_emu_override_dpll_per = 0x4a008170, + .cm_clkmode_dpll_usb = 0x4a008180, + .cm_idlest_dpll_usb = 0x4a008184, + .cm_autoidle_dpll_usb = 0x4a008188, + .cm_clksel_dpll_usb = 0x4a00818c, + .cm_div_m2_dpll_usb = 0x4a008190, + .cm_ssc_deltamstep_dpll_usb = 0x4a0081a8, + .cm_ssc_modfreqdiv_dpll_usb = 0x4a0081ac, + .cm_clkdcoldo_dpll_usb = 0x4a0081b4, + .cm_clkmode_dpll_unipro = 0x4a0081c0, + .cm_idlest_dpll_unipro = 0x4a0081c4, + .cm_autoidle_dpll_unipro = 0x4a0081c8, + .cm_clksel_dpll_unipro = 0x4a0081cc, + .cm_div_m2_dpll_unipro = 0x4a0081d0, + .cm_ssc_deltamstep_dpll_unipro = 0x4a0081e8, + .cm_ssc_modfreqdiv_dpll_unipro = 0x4a0081ec, + + /* cm2.core */ + .cm_coreaon_bandgap_clkctrl = 0x4a008648, + .cm_coreaon_io_srcomp_clkctrl = 0x4a008650, + .cm_l3_1_clkstctrl = 0x4a008700, + .cm_l3_1_dynamicdep = 0x4a008708, + .cm_l3_1_l3_1_clkctrl = 0x4a008720, + .cm_l3_2_clkstctrl = 0x4a008800, + .cm_l3_2_dynamicdep = 0x4a008808, + .cm_l3_2_l3_2_clkctrl = 0x4a008820, + .cm_l3_gpmc_clkctrl = 0x4a008828, + .cm_l3_2_ocmc_ram_clkctrl = 0x4a008830, + .cm_mpu_m3_clkstctrl = 0x4a008900, + .cm_mpu_m3_staticdep = 0x4a008904, + .cm_mpu_m3_dynamicdep = 0x4a008908, + .cm_mpu_m3_mpu_m3_clkctrl = 0x4a008920, + .cm_sdma_clkstctrl = 0x4a008a00, + .cm_sdma_staticdep = 0x4a008a04, + .cm_sdma_dynamicdep = 0x4a008a08, + .cm_sdma_sdma_clkctrl = 0x4a008a20, + .cm_memif_clkstctrl = 0x4a008b00, + .cm_memif_dmm_clkctrl = 0x4a008b20, + .cm_memif_emif_fw_clkctrl = 0x4a008b28, + .cm_memif_emif_1_clkctrl = 0x4a008b30, + .cm_memif_emif_2_clkctrl = 0x4a008b38, + .cm_memif_dll_clkctrl = 0x4a008b40, + .cm_memif_emif_h1_clkctrl = 0x4a008b50, + .cm_memif_emif_h2_clkctrl = 0x4a008b58, + .cm_memif_dll_h_clkctrl = 0x4a008b60, + .cm_c2c_clkstctrl = 0x4a008c00, + .cm_c2c_staticdep = 0x4a008c04, + .cm_c2c_dynamicdep = 0x4a008c08, + .cm_c2c_sad2d_clkctrl = 0x4a008c20, + .cm_c2c_modem_icr_clkctrl = 0x4a008c28, + .cm_c2c_sad2d_fw_clkctrl = 0x4a008c30, + .cm_l4cfg_clkstctrl = 0x4a008d00, + .cm_l4cfg_dynamicdep = 0x4a008d08, + .cm_l4cfg_l4_cfg_clkctrl = 0x4a008d20, + .cm_l4cfg_hw_sem_clkctrl = 0x4a008d28, + .cm_l4cfg_mailbox_clkctrl = 0x4a008d30, + .cm_l4cfg_sar_rom_clkctrl = 0x4a008d38, + .cm_l3instr_clkstctrl = 0x4a008e00, + .cm_l3instr_l3_3_clkctrl = 0x4a008e20, + .cm_l3instr_l3_instr_clkctrl = 0x4a008e28, + .cm_l3instr_intrconn_wp1_clkctrl = 0x4a008e40, + + /* cm2.ivahd */ + .cm_ivahd_clkstctrl = 0x4a008f00, + .cm_ivahd_ivahd_clkctrl = 0x4a008f20, + .cm_ivahd_sl2_clkctrl = 0x4a008f28, + + /* cm2.cam */ + .cm_cam_clkstctrl = 0x4a009000, + .cm_cam_iss_clkctrl = 0x4a009020, + .cm_cam_fdif_clkctrl = 0x4a009028, + + /* cm2.dss */ + .cm_dss_clkstctrl = 0x4a009100, + .cm_dss_dss_clkctrl = 0x4a009120, + + /* cm2.sgx */ + .cm_sgx_clkstctrl = 0x4a009200, + .cm_sgx_sgx_clkctrl = 0x4a009220, + + /* cm2.l3init */ + .cm_l3init_clkstctrl = 0x4a009300, + .cm_l3init_hsmmc1_clkctrl = 0x4a009328, + .cm_l3init_hsmmc2_clkctrl = 0x4a009330, + .cm_l3init_hsi_clkctrl = 0x4a009338, + .cm_l3init_hsusbhost_clkctrl = 0x4a009358, + .cm_l3init_hsusbotg_clkctrl = 0x4a009360, + .cm_l3init_hsusbtll_clkctrl = 0x4a009368, + .cm_l3init_p1500_clkctrl = 0x4a009378, + .cm_l3init_sata_clkctrl = 0x4a009388, + .cm_l3init_fsusb_clkctrl = 0x4a0093d0, + .cm_l3init_ocp2scp1_clkctrl = 0x4a0093e0, + .cm_l3init_ocp2scp3_clkctrl = 0x4a0093e8, + + /* cm2.l4per */ + .cm_l4per_clkstctrl = 0x4a009400, + .cm_l4per_dynamicdep = 0x4a009408, + .cm_l4per_adc_clkctrl = 0x4a009420, + .cm_l4per_gptimer10_clkctrl = 0x4a009428, + .cm_l4per_gptimer11_clkctrl = 0x4a009430, + .cm_l4per_gptimer2_clkctrl = 0x4a009438, + .cm_l4per_gptimer3_clkctrl = 0x4a009440, + .cm_l4per_gptimer4_clkctrl = 0x4a009448, + .cm_l4per_gptimer9_clkctrl = 0x4a009450, + .cm_l4per_elm_clkctrl = 0x4a009458, + .cm_l4per_gpio2_clkctrl = 0x4a009460, + .cm_l4per_gpio3_clkctrl = 0x4a009468, + .cm_l4per_gpio4_clkctrl = 0x4a009470, + .cm_l4per_gpio5_clkctrl = 0x4a009478, + .cm_l4per_gpio6_clkctrl = 0x4a009480, + .cm_l4per_hdq1w_clkctrl = 0x4a009488, + .cm_l4per_hecc1_clkctrl = 0x4a009490, + .cm_l4per_hecc2_clkctrl = 0x4a009498, + .cm_l4per_i2c1_clkctrl = 0x4a0094a0, + .cm_l4per_i2c2_clkctrl = 0x4a0094a8, + .cm_l4per_i2c3_clkctrl = 0x4a0094b0, + .cm_l4per_i2c4_clkctrl = 0x4a0094b8, + .cm_l4per_l4per_clkctrl = 0x4a0094c0, + .cm_l4per_mcasp2_clkctrl = 0x4a0094d0, + .cm_l4per_mcasp3_clkctrl = 0x4a0094d8, + .cm_l4per_mgate_clkctrl = 0x4a0094e8, + .cm_l4per_mcspi1_clkctrl = 0x4a0094f0, + .cm_l4per_mcspi2_clkctrl = 0x4a0094f8, + .cm_l4per_mcspi3_clkctrl = 0x4a009500, + .cm_l4per_mcspi4_clkctrl = 0x4a009508, + .cm_l4per_gpio7_clkctrl = 0x4a009510, + .cm_l4per_gpio8_clkctrl = 0x4a009518, + .cm_l4per_mmcsd3_clkctrl = 0x4a009520, + .cm_l4per_mmcsd4_clkctrl = 0x4a009528, + .cm_l4per_msprohg_clkctrl = 0x4a009530, + .cm_l4per_slimbus2_clkctrl = 0x4a009538, + .cm_l4per_uart1_clkctrl = 0x4a009540, + .cm_l4per_uart2_clkctrl = 0x4a009548, + .cm_l4per_uart3_clkctrl = 0x4a009550, + .cm_l4per_uart4_clkctrl = 0x4a009558, + .cm_l4per_mmcsd5_clkctrl = 0x4a009560, + .cm_l4per_i2c5_clkctrl = 0x4a009568, + .cm_l4per_uart5_clkctrl = 0x4a009570, + .cm_l4per_uart6_clkctrl = 0x4a009578, + .cm_l4sec_clkstctrl = 0x4a009580, + .cm_l4sec_staticdep = 0x4a009584, + .cm_l4sec_dynamicdep = 0x4a009588, + .cm_l4sec_aes1_clkctrl = 0x4a0095a0, + .cm_l4sec_aes2_clkctrl = 0x4a0095a8, + .cm_l4sec_des3des_clkctrl = 0x4a0095b0, + .cm_l4sec_pkaeip29_clkctrl = 0x4a0095b8, + .cm_l4sec_rng_clkctrl = 0x4a0095c0, + .cm_l4sec_sha2md51_clkctrl = 0x4a0095c8, + .cm_l4sec_cryptodma_clkctrl = 0x4a0095d8, + + /* l4 wkup regs */ + .cm_abe_pll_ref_clksel = 0x4ae0610c, + .cm_sys_clksel = 0x4ae06110, + .cm_wkup_clkstctrl = 0x4ae07800, + .cm_wkup_l4wkup_clkctrl = 0x4ae07820, + .cm_wkup_wdtimer1_clkctrl = 0x4ae07828, + .cm_wkup_wdtimer2_clkctrl = 0x4ae07830, + .cm_wkup_gpio1_clkctrl = 0x4ae07838, + .cm_wkup_gptimer1_clkctrl = 0x4ae07840, + .cm_wkup_gptimer12_clkctrl = 0x4ae07848, + .cm_wkup_synctimer_clkctrl = 0x4ae07850, + .cm_wkup_usim_clkctrl = 0x4ae07858, + .cm_wkup_sarram_clkctrl = 0x4ae07860, + .cm_wkup_keyboard_clkctrl = 0x4ae07878, + .cm_wkup_rtc_clkctrl = 0x4ae07880, + .cm_wkup_bandgap_clkctrl = 0x4ae07888, + .cm_wkupaon_scrm_clkctrl = 0x4ae07890, + .cm_wkupaon_io_srcomp_clkctrl = 0x4ae07898, + .prm_rstctrl = 0x4ae07b00, + .prm_rstst = 0x4ae07b04, + .prm_rsttime = 0x4ae07b08, + .prm_vc_val_bypass = 0x4ae07ba0, + .prm_vc_cfg_i2c_mode = 0x4ae07bb4, + .prm_vc_cfg_i2c_clk = 0x4ae07bb8, + + /* SCRM stuff, used by some boards */ + .scrm_auxclk0 = 0x4ae0a310, + .scrm_auxclk1 = 0x4ae0a314, +}; + +struct omap_sys_ctrl_regs const omap5_ctrl = { + .control_status = 0x4A002134, + .control_std_fuse_opp_vdd_mpu_2 = 0x4A0021B4, + .control_phy_power_usb = 0x4A002370, + .control_phy_power_sata = 0x4A002374, + .control_padconf_core_base = 0x4A002800, + .control_paconf_global = 0x4A002DA0, + .control_paconf_mode = 0x4A002DA4, + .control_smart1io_padconf_0 = 0x4A002DA8, + .control_smart1io_padconf_1 = 0x4A002DAC, + .control_smart1io_padconf_2 = 0x4A002DB0, + .control_smart2io_padconf_0 = 0x4A002DB4, + .control_smart2io_padconf_1 = 0x4A002DB8, + .control_smart2io_padconf_2 = 0x4A002DBC, + .control_smart3io_padconf_0 = 0x4A002DC0, + .control_smart3io_padconf_1 = 0x4A002DC4, + .control_pbias = 0x4A002E00, + .control_i2c_0 = 0x4A002E04, + .control_camera_rx = 0x4A002E08, + .control_hdmi_tx_phy = 0x4A002E0C, + .control_uniportm = 0x4A002E10, + .control_dsiphy = 0x4A002E14, + .control_mcbsplp = 0x4A002E18, + .control_usb2phycore = 0x4A002E1C, + .control_hdmi_1 = 0x4A002E20, + .control_hsi = 0x4A002E24, + .control_ddr3ch1_0 = 0x4A002E30, + .control_ddr3ch2_0 = 0x4A002E34, + .control_ddrch1_0 = 0x4A002E38, + .control_ddrch1_1 = 0x4A002E3C, + .control_ddrch2_0 = 0x4A002E40, + .control_ddrch2_1 = 0x4A002E44, + .control_lpddr2ch1_0 = 0x4A002E48, + .control_lpddr2ch1_1 = 0x4A002E4C, + .control_ddrio_0 = 0x4A002E50, + .control_ddrio_1 = 0x4A002E54, + .control_ddrio_2 = 0x4A002E58, + .control_hyst_1 = 0x4A002E5C, + .control_usbb_hsic_control = 0x4A002E60, + .control_c2c = 0x4A002E64, + .control_core_control_spare_rw = 0x4A002E68, + .control_core_control_spare_r = 0x4A002E6C, + .control_core_control_spare_r_c0 = 0x4A002E70, + .control_srcomp_north_side = 0x4A002E74, + .control_srcomp_south_side = 0x4A002E78, + .control_srcomp_east_side = 0x4A002E7C, + .control_srcomp_west_side = 0x4A002E80, + .control_srcomp_code_latch = 0x4A002E84, + .control_port_emif1_sdram_config = 0x4AE0C110, + .control_port_emif1_lpddr2_nvm_config = 0x4AE0C114, + .control_port_emif2_sdram_config = 0x4AE0C118, + .control_emif1_sdram_config_ext = 0x4AE0C144, + .control_emif2_sdram_config_ext = 0x4AE0C148, + .control_wkup_ldovbb_mpu_voltage_ctrl = 0x4AE0C318, + .control_padconf_wkup_base = 0x4AE0C800, + .control_smart1nopmio_padconf_0 = 0x4AE0CDA0, + .control_smart1nopmio_padconf_1 = 0x4AE0CDA4, + .control_padconf_mode = 0x4AE0CDA8, + .control_xtal_oscillator = 0x4AE0CDAC, + .control_i2c_2 = 0x4AE0CDB0, + .control_ckobuffer = 0x4AE0CDB4, + .control_wkup_control_spare_rw = 0x4AE0CDB8, + .control_wkup_control_spare_r = 0x4AE0CDBC, + .control_wkup_control_spare_r_c0 = 0x4AE0CDC0, + .control_srcomp_east_side_wkup = 0x4AE0CDC4, + .control_efuse_1 = 0x4AE0CDC8, + .control_efuse_2 = 0x4AE0CDCC, + .control_efuse_3 = 0x4AE0CDD0, + .control_efuse_4 = 0x4AE0CDD4, + .control_efuse_5 = 0x4AE0CDD8, + .control_efuse_6 = 0x4AE0CDDC, + .control_efuse_7 = 0x4AE0CDE0, + .control_efuse_8 = 0x4AE0CDE4, + .control_efuse_9 = 0x4AE0CDE8, + .control_efuse_10 = 0x4AE0CDEC, + .control_efuse_11 = 0x4AE0CDF0, + .control_efuse_12 = 0x4AE0CDF4, + .control_efuse_13 = 0x4AE0CDF8, +}; + +struct omap_sys_ctrl_regs const dra7xx_ctrl = { + .control_status = 0x4A002134, + .control_phy_power_sata = 0x4A002374, + .control_core_mac_id_0_lo = 0x4A002514, + .control_core_mac_id_0_hi = 0x4A002518, + .control_core_mac_id_1_lo = 0x4A00251C, + .control_core_mac_id_1_hi = 0x4A002520, + .control_core_mmr_lock1 = 0x4A002540, + .control_core_mmr_lock2 = 0x4A002544, + .control_core_mmr_lock3 = 0x4A002548, + .control_core_mmr_lock4 = 0x4A00254C, + .control_core_mmr_lock5 = 0x4A002550, + .control_core_control_io1 = 0x4A002554, + .control_core_control_io2 = 0x4A002558, + .control_paconf_global = 0x4A002DA0, + .control_paconf_mode = 0x4A002DA4, + .control_smart1io_padconf_0 = 0x4A002DA8, + .control_smart1io_padconf_1 = 0x4A002DAC, + .control_smart1io_padconf_2 = 0x4A002DB0, + .control_smart2io_padconf_0 = 0x4A002DB4, + .control_smart2io_padconf_1 = 0x4A002DB8, + .control_smart2io_padconf_2 = 0x4A002DBC, + .control_smart3io_padconf_0 = 0x4A002DC0, + .control_smart3io_padconf_1 = 0x4A002DC4, + .control_pbias = 0x4A002E00, + .control_i2c_0 = 0x4A002E04, + .control_camera_rx = 0x4A002E08, + .control_hdmi_tx_phy = 0x4A002E0C, + .control_uniportm = 0x4A002E10, + .control_dsiphy = 0x4A002E14, + .control_mcbsplp = 0x4A002E18, + .control_usb2phycore = 0x4A002E1C, + .control_hdmi_1 = 0x4A002E20, + .control_hsi = 0x4A002E24, + .control_ddr3ch1_0 = 0x4A002E30, + .control_ddr3ch2_0 = 0x4A002E34, + .control_ddrch1_0 = 0x4A002E38, + .control_ddrch1_1 = 0x4A002E3C, + .control_ddrch2_0 = 0x4A002E40, + .control_ddrch2_1 = 0x4A002E44, + .control_lpddr2ch1_0 = 0x4A002E48, + .control_lpddr2ch1_1 = 0x4A002E4C, + .control_ddrio_0 = 0x4A002E50, + .control_ddrio_1 = 0x4A002E54, + .control_ddrio_2 = 0x4A002E58, + .control_hyst_1 = 0x4A002E5C, + .control_usbb_hsic_control = 0x4A002E60, + .control_c2c = 0x4A002E64, + .control_core_control_spare_rw = 0x4A002E68, + .control_core_control_spare_r = 0x4A002E6C, + .control_core_control_spare_r_c0 = 0x4A002E70, + .control_srcomp_north_side = 0x4A002E74, + .control_srcomp_south_side = 0x4A002E78, + .control_srcomp_east_side = 0x4A002E7C, + .control_srcomp_west_side = 0x4A002E80, + .control_srcomp_code_latch = 0x4A002E84, + .control_ddr_control_ext_0 = 0x4A002E88, + .control_padconf_core_base = 0x4A003400, + .control_std_fuse_opp_vdd_mpu_2 = 0x4A003B20, + .control_port_emif1_sdram_config = 0x4AE0C110, + .control_port_emif1_lpddr2_nvm_config = 0x4AE0C114, + .control_port_emif2_sdram_config = 0x4AE0C118, + .control_emif1_sdram_config_ext = 0x4AE0C144, + .control_emif2_sdram_config_ext = 0x4AE0C148, + .control_wkup_ldovbb_mpu_voltage_ctrl = 0x4AE0C158, + .control_padconf_mode = 0x4AE0C5A0, + .control_xtal_oscillator = 0x4AE0C5A4, + .control_i2c_2 = 0x4AE0C5A8, + .control_ckobuffer = 0x4AE0C5AC, + .control_wkup_control_spare_rw = 0x4AE0C5B0, + .control_wkup_control_spare_r = 0x4AE0C5B4, + .control_wkup_control_spare_r_c0 = 0x4AE0C5B8, + .control_srcomp_east_side_wkup = 0x4AE0C5BC, + .control_efuse_1 = 0x4AE0C5C0, + .control_efuse_2 = 0x4AE0C5C4, + .control_efuse_3 = 0x4AE0C5C8, + .control_efuse_4 = 0x4AE0C5CC, + .control_efuse_13 = 0x4AE0C5F0, +}; + +struct prcm_regs const omap5_es2_prcm = { + /* cm1.ckgen */ + .cm_clksel_core = 0x4a004100, + .cm_clksel_abe = 0x4a004108, + .cm_dll_ctrl = 0x4a004110, + .cm_clkmode_dpll_core = 0x4a004120, + .cm_idlest_dpll_core = 0x4a004124, + .cm_autoidle_dpll_core = 0x4a004128, + .cm_clksel_dpll_core = 0x4a00412c, + .cm_div_m2_dpll_core = 0x4a004130, + .cm_div_m3_dpll_core = 0x4a004134, + .cm_div_h11_dpll_core = 0x4a004138, + .cm_div_h12_dpll_core = 0x4a00413c, + .cm_div_h13_dpll_core = 0x4a004140, + .cm_div_h14_dpll_core = 0x4a004144, + .cm_ssc_deltamstep_dpll_core = 0x4a004148, + .cm_ssc_modfreqdiv_dpll_core = 0x4a00414c, + .cm_div_h21_dpll_core = 0x4a004150, + .cm_div_h22_dpllcore = 0x4a004154, + .cm_div_h23_dpll_core = 0x4a004158, + .cm_div_h24_dpll_core = 0x4a00415c, + .cm_clkmode_dpll_mpu = 0x4a004160, + .cm_idlest_dpll_mpu = 0x4a004164, + .cm_autoidle_dpll_mpu = 0x4a004168, + .cm_clksel_dpll_mpu = 0x4a00416c, + .cm_div_m2_dpll_mpu = 0x4a004170, + .cm_ssc_deltamstep_dpll_mpu = 0x4a004188, + .cm_ssc_modfreqdiv_dpll_mpu = 0x4a00418c, + .cm_bypclk_dpll_mpu = 0x4a00419c, + .cm_clkmode_dpll_iva = 0x4a0041a0, + .cm_idlest_dpll_iva = 0x4a0041a4, + .cm_autoidle_dpll_iva = 0x4a0041a8, + .cm_clksel_dpll_iva = 0x4a0041ac, + .cm_div_h11_dpll_iva = 0x4a0041b8, + .cm_div_h12_dpll_iva = 0x4a0041bc, + .cm_ssc_deltamstep_dpll_iva = 0x4a0041c8, + .cm_ssc_modfreqdiv_dpll_iva = 0x4a0041cc, + .cm_bypclk_dpll_iva = 0x4a0041dc, + .cm_clkmode_dpll_abe = 0x4a0041e0, + .cm_idlest_dpll_abe = 0x4a0041e4, + .cm_autoidle_dpll_abe = 0x4a0041e8, + .cm_clksel_dpll_abe = 0x4a0041ec, + .cm_div_m2_dpll_abe = 0x4a0041f0, + .cm_div_m3_dpll_abe = 0x4a0041f4, + .cm_ssc_deltamstep_dpll_abe = 0x4a004208, + .cm_ssc_modfreqdiv_dpll_abe = 0x4a00420c, + .cm_clkmode_dpll_ddrphy = 0x4a004220, + .cm_idlest_dpll_ddrphy = 0x4a004224, + .cm_autoidle_dpll_ddrphy = 0x4a004228, + .cm_clksel_dpll_ddrphy = 0x4a00422c, + .cm_div_m2_dpll_ddrphy = 0x4a004230, + .cm_div_h11_dpll_ddrphy = 0x4a004238, + .cm_div_h12_dpll_ddrphy = 0x4a00423c, + .cm_div_h13_dpll_ddrphy = 0x4a004240, + .cm_ssc_deltamstep_dpll_ddrphy = 0x4a004248, + .cm_shadow_freq_config1 = 0x4a004260, + .cm_mpu_mpu_clkctrl = 0x4a004320, + + /* cm1.dsp */ + .cm_dsp_clkstctrl = 0x4a004400, + .cm_dsp_dsp_clkctrl = 0x4a004420, + + /* cm1.abe */ + .cm1_abe_clkstctrl = 0x4a004500, + .cm1_abe_l4abe_clkctrl = 0x4a004520, + .cm1_abe_aess_clkctrl = 0x4a004528, + .cm1_abe_pdm_clkctrl = 0x4a004530, + .cm1_abe_dmic_clkctrl = 0x4a004538, + .cm1_abe_mcasp_clkctrl = 0x4a004540, + .cm1_abe_mcbsp1_clkctrl = 0x4a004548, + .cm1_abe_mcbsp2_clkctrl = 0x4a004550, + .cm1_abe_mcbsp3_clkctrl = 0x4a004558, + .cm1_abe_slimbus_clkctrl = 0x4a004560, + .cm1_abe_timer5_clkctrl = 0x4a004568, + .cm1_abe_timer6_clkctrl = 0x4a004570, + .cm1_abe_timer7_clkctrl = 0x4a004578, + .cm1_abe_timer8_clkctrl = 0x4a004580, + .cm1_abe_wdt3_clkctrl = 0x4a004588, + + /* cm2.ckgen */ + .cm_clksel_mpu_m3_iss_root = 0x4a008100, + .cm_clksel_usb_60mhz = 0x4a008104, + .cm_scale_fclk = 0x4a008108, + .cm_core_dvfs_perf1 = 0x4a008110, + .cm_core_dvfs_perf2 = 0x4a008114, + .cm_core_dvfs_perf3 = 0x4a008118, + .cm_core_dvfs_perf4 = 0x4a00811c, + .cm_core_dvfs_current = 0x4a008124, + .cm_iva_dvfs_perf_tesla = 0x4a008128, + .cm_iva_dvfs_perf_ivahd = 0x4a00812c, + .cm_iva_dvfs_perf_abe = 0x4a008130, + .cm_iva_dvfs_current = 0x4a008138, + .cm_clkmode_dpll_per = 0x4a008140, + .cm_idlest_dpll_per = 0x4a008144, + .cm_autoidle_dpll_per = 0x4a008148, + .cm_clksel_dpll_per = 0x4a00814c, + .cm_div_m2_dpll_per = 0x4a008150, + .cm_div_m3_dpll_per = 0x4a008154, + .cm_div_h11_dpll_per = 0x4a008158, + .cm_div_h12_dpll_per = 0x4a00815c, + .cm_div_h13_dpll_per = 0x4a008160, + .cm_div_h14_dpll_per = 0x4a008164, + .cm_ssc_deltamstep_dpll_per = 0x4a008168, + .cm_ssc_modfreqdiv_dpll_per = 0x4a00816c, + .cm_emu_override_dpll_per = 0x4a008170, + .cm_clkmode_dpll_usb = 0x4a008180, + .cm_idlest_dpll_usb = 0x4a008184, + .cm_autoidle_dpll_usb = 0x4a008188, + .cm_clksel_dpll_usb = 0x4a00818c, + .cm_div_m2_dpll_usb = 0x4a008190, + .cm_ssc_deltamstep_dpll_usb = 0x4a0081a8, + .cm_ssc_modfreqdiv_dpll_usb = 0x4a0081ac, + .cm_clkdcoldo_dpll_usb = 0x4a0081b4, + .cm_clkmode_dpll_unipro = 0x4a0081c0, + .cm_idlest_dpll_unipro = 0x4a0081c4, + .cm_autoidle_dpll_unipro = 0x4a0081c8, + .cm_clksel_dpll_unipro = 0x4a0081cc, + .cm_div_m2_dpll_unipro = 0x4a0081d0, + .cm_ssc_deltamstep_dpll_unipro = 0x4a0081e8, + .cm_ssc_modfreqdiv_dpll_unipro = 0x4a0081ec, + .cm_coreaon_usb_phy_core_clkctrl = 0x4A008640, + .cm_coreaon_bandgap_clkctrl = 0x4a008648, + .cm_coreaon_io_srcomp_clkctrl = 0x4a008650, + + /* cm2.core */ + .cm_l3_1_clkstctrl = 0x4a008700, + .cm_l3_1_dynamicdep = 0x4a008708, + .cm_l3_1_l3_1_clkctrl = 0x4a008720, + .cm_l3_2_clkstctrl = 0x4a008800, + .cm_l3_2_dynamicdep = 0x4a008808, + .cm_l3_2_l3_2_clkctrl = 0x4a008820, + .cm_l3_gpmc_clkctrl = 0x4a008828, + .cm_l3_2_ocmc_ram_clkctrl = 0x4a008830, + .cm_mpu_m3_clkstctrl = 0x4a008900, + .cm_mpu_m3_staticdep = 0x4a008904, + .cm_mpu_m3_dynamicdep = 0x4a008908, + .cm_mpu_m3_mpu_m3_clkctrl = 0x4a008920, + .cm_sdma_clkstctrl = 0x4a008a00, + .cm_sdma_staticdep = 0x4a008a04, + .cm_sdma_dynamicdep = 0x4a008a08, + .cm_sdma_sdma_clkctrl = 0x4a008a20, + .cm_memif_clkstctrl = 0x4a008b00, + .cm_memif_dmm_clkctrl = 0x4a008b20, + .cm_memif_emif_fw_clkctrl = 0x4a008b28, + .cm_memif_emif_1_clkctrl = 0x4a008b30, + .cm_memif_emif_2_clkctrl = 0x4a008b38, + .cm_memif_dll_clkctrl = 0x4a008b40, + .cm_memif_emif_h1_clkctrl = 0x4a008b50, + .cm_memif_emif_h2_clkctrl = 0x4a008b58, + .cm_memif_dll_h_clkctrl = 0x4a008b60, + .cm_c2c_clkstctrl = 0x4a008c00, + .cm_c2c_staticdep = 0x4a008c04, + .cm_c2c_dynamicdep = 0x4a008c08, + .cm_c2c_sad2d_clkctrl = 0x4a008c20, + .cm_c2c_modem_icr_clkctrl = 0x4a008c28, + .cm_c2c_sad2d_fw_clkctrl = 0x4a008c30, + .cm_l4cfg_clkstctrl = 0x4a008d00, + .cm_l4cfg_dynamicdep = 0x4a008d08, + .cm_l4cfg_l4_cfg_clkctrl = 0x4a008d20, + .cm_l4cfg_hw_sem_clkctrl = 0x4a008d28, + .cm_l4cfg_mailbox_clkctrl = 0x4a008d30, + .cm_l4cfg_sar_rom_clkctrl = 0x4a008d38, + .cm_l3instr_clkstctrl = 0x4a008e00, + .cm_l3instr_l3_3_clkctrl = 0x4a008e20, + .cm_l3instr_l3_instr_clkctrl = 0x4a008e28, + .cm_l3instr_intrconn_wp1_clkctrl = 0x4a008e40, + .cm_l4per_clkstctrl = 0x4a009000, + .cm_l4per_dynamicdep = 0x4a009008, + .cm_l4per_adc_clkctrl = 0x4a009020, + .cm_l4per_gptimer10_clkctrl = 0x4a009028, + .cm_l4per_gptimer11_clkctrl = 0x4a009030, + .cm_l4per_gptimer2_clkctrl = 0x4a009038, + .cm_l4per_gptimer3_clkctrl = 0x4a009040, + .cm_l4per_gptimer4_clkctrl = 0x4a009048, + .cm_l4per_gptimer9_clkctrl = 0x4a009050, + .cm_l4per_elm_clkctrl = 0x4a009058, + .cm_l4per_gpio2_clkctrl = 0x4a009060, + .cm_l4per_gpio3_clkctrl = 0x4a009068, + .cm_l4per_gpio4_clkctrl = 0x4a009070, + .cm_l4per_gpio5_clkctrl = 0x4a009078, + .cm_l4per_gpio6_clkctrl = 0x4a009080, + .cm_l4per_hdq1w_clkctrl = 0x4a009088, + .cm_l4per_hecc1_clkctrl = 0x4a009090, + .cm_l4per_hecc2_clkctrl = 0x4a009098, + .cm_l4per_i2c1_clkctrl = 0x4a0090a0, + .cm_l4per_i2c2_clkctrl = 0x4a0090a8, + .cm_l4per_i2c3_clkctrl = 0x4a0090b0, + .cm_l4per_i2c4_clkctrl = 0x4a0090b8, + .cm_l4per_l4per_clkctrl = 0x4a0090c0, + .cm_l4per_mcasp2_clkctrl = 0x4a0090d0, + .cm_l4per_mcasp3_clkctrl = 0x4a0090d8, + .cm_l4per_mgate_clkctrl = 0x4a0090e8, + .cm_l4per_mcspi1_clkctrl = 0x4a0090f0, + .cm_l4per_mcspi2_clkctrl = 0x4a0090f8, + .cm_l4per_mcspi3_clkctrl = 0x4a009100, + .cm_l4per_mcspi4_clkctrl = 0x4a009108, + .cm_l4per_gpio7_clkctrl = 0x4a009110, + .cm_l4per_gpio8_clkctrl = 0x4a009118, + .cm_l4per_mmcsd3_clkctrl = 0x4a009120, + .cm_l4per_mmcsd4_clkctrl = 0x4a009128, + .cm_l4per_msprohg_clkctrl = 0x4a009130, + .cm_l4per_slimbus2_clkctrl = 0x4a009138, + .cm_l4per_uart1_clkctrl = 0x4a009140, + .cm_l4per_uart2_clkctrl = 0x4a009148, + .cm_l4per_uart3_clkctrl = 0x4a009150, + .cm_l4per_uart4_clkctrl = 0x4a009158, + .cm_l4per_mmcsd5_clkctrl = 0x4a009160, + .cm_l4per_i2c5_clkctrl = 0x4a009168, + .cm_l4per_uart5_clkctrl = 0x4a009170, + .cm_l4per_uart6_clkctrl = 0x4a009178, + .cm_l4sec_clkstctrl = 0x4a009180, + .cm_l4sec_staticdep = 0x4a009184, + .cm_l4sec_dynamicdep = 0x4a009188, + .cm_l4sec_aes1_clkctrl = 0x4a0091a0, + .cm_l4sec_aes2_clkctrl = 0x4a0091a8, + .cm_l4sec_des3des_clkctrl = 0x4a0091b0, + .cm_l4sec_pkaeip29_clkctrl = 0x4a0091b8, + .cm_l4sec_rng_clkctrl = 0x4a0091c0, + .cm_l4sec_sha2md51_clkctrl = 0x4a0091c8, + .cm_l4sec_cryptodma_clkctrl = 0x4a0091d8, + + /* cm2.ivahd */ + .cm_ivahd_clkstctrl = 0x4a009200, + .cm_ivahd_ivahd_clkctrl = 0x4a009220, + .cm_ivahd_sl2_clkctrl = 0x4a009228, + + /* cm2.cam */ + .cm_cam_clkstctrl = 0x4a009300, + .cm_cam_iss_clkctrl = 0x4a009320, + .cm_cam_fdif_clkctrl = 0x4a009328, + + /* cm2.dss */ + .cm_dss_clkstctrl = 0x4a009400, + .cm_dss_dss_clkctrl = 0x4a009420, + + /* cm2.sgx */ + .cm_sgx_clkstctrl = 0x4a009500, + .cm_sgx_sgx_clkctrl = 0x4a009520, + + /* cm2.l3init */ + .cm_l3init_clkstctrl = 0x4a009600, + + /* cm2.l3init */ + .cm_l3init_hsmmc1_clkctrl = 0x4a009628, + .cm_l3init_hsmmc2_clkctrl = 0x4a009630, + .cm_l3init_hsi_clkctrl = 0x4a009638, + .cm_l3init_hsusbhost_clkctrl = 0x4a009658, + .cm_l3init_hsusbotg_clkctrl = 0x4a009660, + .cm_l3init_hsusbtll_clkctrl = 0x4a009668, + .cm_l3init_p1500_clkctrl = 0x4a009678, + .cm_l3init_sata_clkctrl = 0x4a009688, + .cm_l3init_fsusb_clkctrl = 0x4a0096d0, + .cm_l3init_ocp2scp1_clkctrl = 0x4a0096e0, + .cm_l3init_ocp2scp3_clkctrl = 0x4a0096e8, + .cm_l3init_usb_otg_ss_clkctrl = 0x4a0096f0, + + /* prm irqstatus regs */ + .prm_irqstatus_mpu_2 = 0x4ae06014, + + /* l4 wkup regs */ + .cm_abe_pll_ref_clksel = 0x4ae0610c, + .cm_sys_clksel = 0x4ae06110, + .cm_wkup_clkstctrl = 0x4ae07900, + .cm_wkup_l4wkup_clkctrl = 0x4ae07920, + .cm_wkup_wdtimer1_clkctrl = 0x4ae07928, + .cm_wkup_wdtimer2_clkctrl = 0x4ae07930, + .cm_wkup_gpio1_clkctrl = 0x4ae07938, + .cm_wkup_gptimer1_clkctrl = 0x4ae07940, + .cm_wkup_gptimer12_clkctrl = 0x4ae07948, + .cm_wkup_synctimer_clkctrl = 0x4ae07950, + .cm_wkup_usim_clkctrl = 0x4ae07958, + .cm_wkup_sarram_clkctrl = 0x4ae07960, + .cm_wkup_keyboard_clkctrl = 0x4ae07978, + .cm_wkup_rtc_clkctrl = 0x4ae07980, + .cm_wkup_bandgap_clkctrl = 0x4ae07988, + .cm_wkupaon_scrm_clkctrl = 0x4ae07990, + .cm_wkupaon_io_srcomp_clkctrl = 0x4ae07998, + .prm_rstctrl = 0x4ae07c00, + .prm_rstst = 0x4ae07c04, + .prm_rsttime = 0x4ae07c08, + .prm_vc_val_bypass = 0x4ae07ca0, + .prm_vc_cfg_i2c_mode = 0x4ae07cb4, + .prm_vc_cfg_i2c_clk = 0x4ae07cb8, + + .prm_abbldo_mpu_setup = 0x4ae07cdc, + .prm_abbldo_mpu_ctrl = 0x4ae07ce0, + + /* SCRM stuff, used by some boards */ + .scrm_auxclk0 = 0x4ae0a310, + .scrm_auxclk1 = 0x4ae0a314, +}; + +struct prcm_regs const dra7xx_prcm = { + /* cm1.ckgen */ + .cm_clksel_core = 0x4a005100, + .cm_clksel_abe = 0x4a005108, + .cm_dll_ctrl = 0x4a005110, + .cm_clkmode_dpll_core = 0x4a005120, + .cm_idlest_dpll_core = 0x4a005124, + .cm_autoidle_dpll_core = 0x4a005128, + .cm_clksel_dpll_core = 0x4a00512c, + .cm_div_m2_dpll_core = 0x4a005130, + .cm_div_m3_dpll_core = 0x4a005134, + .cm_div_h11_dpll_core = 0x4a005138, + .cm_div_h12_dpll_core = 0x4a00513c, + .cm_div_h13_dpll_core = 0x4a005140, + .cm_div_h14_dpll_core = 0x4a005144, + .cm_ssc_deltamstep_dpll_core = 0x4a005148, + .cm_ssc_modfreqdiv_dpll_core = 0x4a00514c, + .cm_div_h21_dpll_core = 0x4a005150, + .cm_div_h22_dpllcore = 0x4a005154, + .cm_div_h23_dpll_core = 0x4a005158, + .cm_div_h24_dpll_core = 0x4a00515c, + .cm_clkmode_dpll_mpu = 0x4a005160, + .cm_idlest_dpll_mpu = 0x4a005164, + .cm_autoidle_dpll_mpu = 0x4a005168, + .cm_clksel_dpll_mpu = 0x4a00516c, + .cm_div_m2_dpll_mpu = 0x4a005170, + .cm_ssc_deltamstep_dpll_mpu = 0x4a005188, + .cm_ssc_modfreqdiv_dpll_mpu = 0x4a00518c, + .cm_bypclk_dpll_mpu = 0x4a00519c, + .cm_clkmode_dpll_iva = 0x4a0051a0, + .cm_idlest_dpll_iva = 0x4a0051a4, + .cm_autoidle_dpll_iva = 0x4a0051a8, + .cm_clksel_dpll_iva = 0x4a0051ac, + .cm_ssc_deltamstep_dpll_iva = 0x4a0051c8, + .cm_ssc_modfreqdiv_dpll_iva = 0x4a0051cc, + .cm_bypclk_dpll_iva = 0x4a0051dc, + .cm_clkmode_dpll_abe = 0x4a0051e0, + .cm_idlest_dpll_abe = 0x4a0051e4, + .cm_autoidle_dpll_abe = 0x4a0051e8, + .cm_clksel_dpll_abe = 0x4a0051ec, + .cm_div_m2_dpll_abe = 0x4a0051f0, + .cm_div_m3_dpll_abe = 0x4a0051f4, + .cm_ssc_deltamstep_dpll_abe = 0x4a005208, + .cm_ssc_modfreqdiv_dpll_abe = 0x4a00520c, + .cm_clkmode_dpll_ddrphy = 0x4a005210, + .cm_idlest_dpll_ddrphy = 0x4a005214, + .cm_autoidle_dpll_ddrphy = 0x4a005218, + .cm_clksel_dpll_ddrphy = 0x4a00521c, + .cm_div_m2_dpll_ddrphy = 0x4a005220, + .cm_div_h11_dpll_ddrphy = 0x4a005228, + .cm_ssc_deltamstep_dpll_ddrphy = 0x4a00522c, + .cm_clkmode_dpll_dsp = 0x4a005234, + .cm_shadow_freq_config1 = 0x4a005260, + .cm_clkmode_dpll_gmac = 0x4a0052a8, + .cm_coreaon_usb_phy2_core_clkctrl = 0x4a008688, + + /* cm1.mpu */ + .cm_mpu_mpu_clkctrl = 0x4a005320, + + /* cm1.dsp */ + .cm_dsp_clkstctrl = 0x4a005400, + .cm_dsp_dsp_clkctrl = 0x4a005420, + + /* prm irqstatus regs */ + .prm_irqstatus_mpu_2 = 0x4ae06014, + + /* cm2.ckgen */ + .cm_clksel_usb_60mhz = 0x4a008104, + .cm_clkmode_dpll_per = 0x4a008140, + .cm_idlest_dpll_per = 0x4a008144, + .cm_autoidle_dpll_per = 0x4a008148, + .cm_clksel_dpll_per = 0x4a00814c, + .cm_div_m2_dpll_per = 0x4a008150, + .cm_div_m3_dpll_per = 0x4a008154, + .cm_div_h11_dpll_per = 0x4a008158, + .cm_div_h12_dpll_per = 0x4a00815c, + .cm_div_h13_dpll_per = 0x4a008160, + .cm_div_h14_dpll_per = 0x4a008164, + .cm_ssc_deltamstep_dpll_per = 0x4a008168, + .cm_ssc_modfreqdiv_dpll_per = 0x4a00816c, + .cm_clkmode_dpll_usb = 0x4a008180, + .cm_idlest_dpll_usb = 0x4a008184, + .cm_autoidle_dpll_usb = 0x4a008188, + .cm_clksel_dpll_usb = 0x4a00818c, + .cm_div_m2_dpll_usb = 0x4a008190, + .cm_ssc_deltamstep_dpll_usb = 0x4a0081a8, + .cm_ssc_modfreqdiv_dpll_usb = 0x4a0081ac, + .cm_clkdcoldo_dpll_usb = 0x4a0081b4, + .cm_clkmode_dpll_pcie_ref = 0x4a008200, + .cm_clkmode_apll_pcie = 0x4a00821c, + .cm_idlest_apll_pcie = 0x4a008220, + .cm_div_m2_apll_pcie = 0x4a008224, + .cm_clkvcoldo_apll_pcie = 0x4a008228, + + /* cm2.core */ + .cm_l3_1_clkstctrl = 0x4a008700, + .cm_l3_1_dynamicdep = 0x4a008708, + .cm_l3_1_l3_1_clkctrl = 0x4a008720, + .cm_l3_gpmc_clkctrl = 0x4a008728, + .cm_mpu_m3_clkstctrl = 0x4a008900, + .cm_mpu_m3_staticdep = 0x4a008904, + .cm_mpu_m3_dynamicdep = 0x4a008908, + .cm_mpu_m3_mpu_m3_clkctrl = 0x4a008920, + .cm_sdma_clkstctrl = 0x4a008a00, + .cm_sdma_staticdep = 0x4a008a04, + .cm_sdma_dynamicdep = 0x4a008a08, + .cm_sdma_sdma_clkctrl = 0x4a008a20, + .cm_memif_clkstctrl = 0x4a008b00, + .cm_memif_dmm_clkctrl = 0x4a008b20, + .cm_memif_emif_fw_clkctrl = 0x4a008b28, + .cm_memif_emif_1_clkctrl = 0x4a008b30, + .cm_memif_emif_2_clkctrl = 0x4a008b38, + .cm_memif_dll_clkctrl = 0x4a008b40, + .cm_l4cfg_clkstctrl = 0x4a008d00, + .cm_l4cfg_dynamicdep = 0x4a008d08, + .cm_l4cfg_l4_cfg_clkctrl = 0x4a008d20, + .cm_l4cfg_hw_sem_clkctrl = 0x4a008d28, + .cm_l4cfg_mailbox_clkctrl = 0x4a008d30, + .cm_l4cfg_sar_rom_clkctrl = 0x4a008d38, + .cm_l3instr_clkstctrl = 0x4a008e00, + .cm_l3instr_l3_3_clkctrl = 0x4a008e20, + .cm_l3instr_l3_instr_clkctrl = 0x4a008e28, + .cm_l3instr_intrconn_wp1_clkctrl = 0x4a008e40, + + /* cm2.ivahd */ + .cm_ivahd_clkstctrl = 0x4a008f00, + .cm_ivahd_ivahd_clkctrl = 0x4a008f20, + .cm_ivahd_sl2_clkctrl = 0x4a008f28, + + /* cm2.cam */ + .cm_cam_clkstctrl = 0x4a009000, + .cm_cam_vip1_clkctrl = 0x4a009020, + .cm_cam_vip2_clkctrl = 0x4a009028, + .cm_cam_vip3_clkctrl = 0x4a009030, + .cm_cam_lvdsrx_clkctrl = 0x4a009038, + .cm_cam_csi1_clkctrl = 0x4a009040, + .cm_cam_csi2_clkctrl = 0x4a009048, + + /* cm2.dss */ + .cm_dss_clkstctrl = 0x4a009100, + .cm_dss_dss_clkctrl = 0x4a009120, + + /* cm2.sgx */ + .cm_sgx_clkstctrl = 0x4a009200, + .cm_sgx_sgx_clkctrl = 0x4a009220, + + /* cm2.l3init */ + .cm_l3init_clkstctrl = 0x4a009300, + + /* cm2.l3init */ + .cm_l3init_hsmmc1_clkctrl = 0x4a009328, + .cm_l3init_hsmmc2_clkctrl = 0x4a009330, + .cm_l3init_hsusbhost_clkctrl = 0x4a009340, + .cm_l3init_hsusbotg_clkctrl = 0x4a009348, + .cm_l3init_hsusbtll_clkctrl = 0x4a009350, + .cm_l3init_sata_clkctrl = 0x4a009388, + .cm_gmac_clkstctrl = 0x4a0093c0, + .cm_gmac_gmac_clkctrl = 0x4a0093d0, + .cm_l3init_ocp2scp1_clkctrl = 0x4a0093e0, + .cm_l3init_ocp2scp3_clkctrl = 0x4a0093e8, + + /* cm2.l4per */ + .cm_l4per_clkstctrl = 0x4a009700, + .cm_l4per_dynamicdep = 0x4a009708, + .cm_l4per_gptimer10_clkctrl = 0x4a009728, + .cm_l4per_gptimer11_clkctrl = 0x4a009730, + .cm_l4per_gptimer2_clkctrl = 0x4a009738, + .cm_l4per_gptimer3_clkctrl = 0x4a009740, + .cm_l4per_gptimer4_clkctrl = 0x4a009748, + .cm_l4per_gptimer9_clkctrl = 0x4a009750, + .cm_l4per_elm_clkctrl = 0x4a009758, + .cm_l4per_gpio2_clkctrl = 0x4a009760, + .cm_l4per_gpio3_clkctrl = 0x4a009768, + .cm_l4per_gpio4_clkctrl = 0x4a009770, + .cm_l4per_gpio5_clkctrl = 0x4a009778, + .cm_l4per_gpio6_clkctrl = 0x4a009780, + .cm_l4per_hdq1w_clkctrl = 0x4a009788, + .cm_l4per_i2c1_clkctrl = 0x4a0097a0, + .cm_l4per_i2c2_clkctrl = 0x4a0097a8, + .cm_l4per_i2c3_clkctrl = 0x4a0097b0, + .cm_l4per_i2c4_clkctrl = 0x4a0097b8, + .cm_l4per_l4per_clkctrl = 0x4a0097c0, + .cm_l4per_mcspi1_clkctrl = 0x4a0097f0, + .cm_l4per_mcspi2_clkctrl = 0x4a0097f8, + .cm_l4per_mcspi3_clkctrl = 0x4a009800, + .cm_l4per_mcspi4_clkctrl = 0x4a009808, + .cm_l4per_gpio7_clkctrl = 0x4a009810, + .cm_l4per_gpio8_clkctrl = 0x4a009818, + .cm_l4per_mmcsd3_clkctrl = 0x4a009820, + .cm_l4per_mmcsd4_clkctrl = 0x4a009828, + .cm_l4per_qspi_clkctrl = 0x4a009838, + .cm_l4per_uart1_clkctrl = 0x4a009840, + .cm_l4per_uart2_clkctrl = 0x4a009848, + .cm_l4per_uart3_clkctrl = 0x4a009850, + .cm_l4per_uart4_clkctrl = 0x4a009858, + .cm_l4per_uart5_clkctrl = 0x4a009870, + .cm_l4sec_clkstctrl = 0x4a009880, + .cm_l4sec_staticdep = 0x4a009884, + .cm_l4sec_dynamicdep = 0x4a009888, + .cm_l4sec_aes1_clkctrl = 0x4a0098a0, + .cm_l4sec_aes2_clkctrl = 0x4a0098a8, + .cm_l4sec_des3des_clkctrl = 0x4a0098b0, + .cm_l4sec_rng_clkctrl = 0x4a0098c0, + .cm_l4sec_sha2md51_clkctrl = 0x4a0098c8, + .cm_l4sec_cryptodma_clkctrl = 0x4a0098d8, + + /* l4 wkup regs */ + .cm_abe_pll_ref_clksel = 0x4ae0610c, + .cm_sys_clksel = 0x4ae06110, + .cm_abe_pll_sys_clksel = 0x4ae06118, + .cm_wkup_clkstctrl = 0x4ae07800, + .cm_wkup_l4wkup_clkctrl = 0x4ae07820, + .cm_wkup_wdtimer1_clkctrl = 0x4ae07828, + .cm_wkup_wdtimer2_clkctrl = 0x4ae07830, + .cm_wkup_gpio1_clkctrl = 0x4ae07838, + .cm_wkup_gptimer1_clkctrl = 0x4ae07840, + .cm_wkup_gptimer12_clkctrl = 0x4ae07848, + .cm_wkup_sarram_clkctrl = 0x4ae07860, + .cm_wkup_keyboard_clkctrl = 0x4ae07878, + .cm_wkupaon_scrm_clkctrl = 0x4ae07890, + .prm_rstctrl = 0x4ae07d00, + .prm_rstst = 0x4ae07d04, + .prm_rsttime = 0x4ae07d08, + .prm_vc_val_bypass = 0x4ae07da0, + .prm_vc_cfg_i2c_mode = 0x4ae07db4, + .prm_vc_cfg_i2c_clk = 0x4ae07db8, + + .prm_abbldo_mpu_setup = 0x4AE07DDC, + .prm_abbldo_mpu_ctrl = 0x4AE07DE0, +}; diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/sdram.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/sdram.c new file mode 100644 index 000000000..16a91f911 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/omap5/sdram.c @@ -0,0 +1,658 @@ +/* + * Timing and Organization details of the ddr device parts used in OMAP5 + * EVM + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Aneesh V <aneesh@ti.com> + * Sricharan R <r.sricharan@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/emif.h> +#include <asm/arch/sys_proto.h> + +/* + * This file provides details of the LPDDR2 SDRAM parts used on OMAP5 + * EVM. Since the parts used and geometry are identical for + * evm for a given OMAP5 revision, this information is kept + * here instead of being in board directory. However the key functions + * exported are weakly linked so that they can be over-ridden in the board + * directory if there is a OMAP5 board in the future that uses a different + * memory device or geometry. + * + * For any new board with different memory devices over-ride one or more + * of the following functions as per the CONFIG flags you intend to enable: + * - emif_get_reg_dump() + * - emif_get_dmm_regs() + * - emif_get_device_details() + * - emif_get_device_timings() + */ + +#ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS +const struct emif_regs emif_regs_532_mhz_2cs = { + .sdram_config_init = 0x80800EBA, + .sdram_config = 0x808022BA, + .ref_ctrl = 0x0000081A, + .sdram_tim1 = 0x772F6873, + .sdram_tim2 = 0x304a129a, + .sdram_tim3 = 0x02f7e45f, + .read_idle_ctrl = 0x00050000, + .zq_config = 0x000b3215, + .temp_alert_config = 0x08000a05, + .emif_ddr_phy_ctlr_1_init = 0x0E28420d, + .emif_ddr_phy_ctlr_1 = 0x0E28420d, + .emif_ddr_ext_phy_ctrl_1 = 0x04020080, + .emif_ddr_ext_phy_ctrl_2 = 0x28C518A3, + .emif_ddr_ext_phy_ctrl_3 = 0x518A3146, + .emif_ddr_ext_phy_ctrl_4 = 0x0014628C, + .emif_ddr_ext_phy_ctrl_5 = 0x04010040 +}; + +const struct emif_regs emif_regs_532_mhz_2cs_es2 = { + .sdram_config_init = 0x80800EBA, + .sdram_config = 0x808022BA, + .ref_ctrl = 0x0000081A, + .sdram_tim1 = 0x772F6873, + .sdram_tim2 = 0x304a129a, + .sdram_tim3 = 0x02f7e45f, + .read_idle_ctrl = 0x00050000, + .zq_config = 0x100b3215, + .temp_alert_config = 0x08000a05, + .emif_ddr_phy_ctlr_1_init = 0x0E30400d, + .emif_ddr_phy_ctlr_1 = 0x0E30400d, + .emif_ddr_ext_phy_ctrl_1 = 0x04020080, + .emif_ddr_ext_phy_ctrl_2 = 0x28C518A3, + .emif_ddr_ext_phy_ctrl_3 = 0x518A3146, + .emif_ddr_ext_phy_ctrl_4 = 0x0014628C, + .emif_ddr_ext_phy_ctrl_5 = 0xC330CC33, +}; + +const struct emif_regs emif_regs_266_mhz_2cs = { + .sdram_config_init = 0x80800EBA, + .sdram_config = 0x808022BA, + .ref_ctrl = 0x0000040D, + .sdram_tim1 = 0x2A86B419, + .sdram_tim2 = 0x1025094A, + .sdram_tim3 = 0x026BA22F, + .read_idle_ctrl = 0x00050000, + .zq_config = 0x000b3215, + .temp_alert_config = 0x08000a05, + .emif_ddr_phy_ctlr_1_init = 0x0E28420d, + .emif_ddr_phy_ctlr_1 = 0x0E28420d, + .emif_ddr_ext_phy_ctrl_1 = 0x04020080, + .emif_ddr_ext_phy_ctrl_2 = 0x0A414829, + .emif_ddr_ext_phy_ctrl_3 = 0x14829052, + .emif_ddr_ext_phy_ctrl_4 = 0x000520A4, + .emif_ddr_ext_phy_ctrl_5 = 0x04010040 +}; + +const struct emif_regs emif_regs_ddr3_532_mhz_1cs = { + .sdram_config_init = 0x61851B32, + .sdram_config = 0x61851B32, + .sdram_config2 = 0x0, + .ref_ctrl = 0x00001035, + .sdram_tim1 = 0xCCCF36B3, + .sdram_tim2 = 0x308F7FDA, + .sdram_tim3 = 0x027F88A8, + .read_idle_ctrl = 0x00050000, + .zq_config = 0x0007190B, + .temp_alert_config = 0x00000000, + .emif_ddr_phy_ctlr_1_init = 0x0020420A, + .emif_ddr_phy_ctlr_1 = 0x0024420A, + .emif_ddr_ext_phy_ctrl_1 = 0x04040100, + .emif_ddr_ext_phy_ctrl_2 = 0x00000000, + .emif_ddr_ext_phy_ctrl_3 = 0x00000000, + .emif_ddr_ext_phy_ctrl_4 = 0x00000000, + .emif_ddr_ext_phy_ctrl_5 = 0x04010040, + .emif_rd_wr_lvl_rmp_win = 0x00000000, + .emif_rd_wr_lvl_rmp_ctl = 0x80000000, + .emif_rd_wr_lvl_ctl = 0x00000000, + .emif_rd_wr_exec_thresh = 0x00000305 +}; + +const struct emif_regs emif_regs_ddr3_532_mhz_1cs_es2 = { + .sdram_config_init = 0x61851B32, + .sdram_config = 0x61851B32, + .sdram_config2 = 0x0, + .ref_ctrl = 0x00001035, + .sdram_tim1 = 0xCCCF36B3, + .sdram_tim2 = 0x308F7FDA, + .sdram_tim3 = 0x027F88A8, + .read_idle_ctrl = 0x00050000, + .zq_config = 0x1007190B, + .temp_alert_config = 0x00000000, + .emif_ddr_phy_ctlr_1_init = 0x0030400A, + .emif_ddr_phy_ctlr_1 = 0x0034400A, + .emif_ddr_ext_phy_ctrl_1 = 0x04040100, + .emif_ddr_ext_phy_ctrl_2 = 0x00000000, + .emif_ddr_ext_phy_ctrl_3 = 0x00000000, + .emif_ddr_ext_phy_ctrl_4 = 0x00000000, + .emif_ddr_ext_phy_ctrl_5 = 0x4350D435, + .emif_rd_wr_lvl_rmp_win = 0x00000000, + .emif_rd_wr_lvl_rmp_ctl = 0x80000000, + .emif_rd_wr_lvl_ctl = 0x00000000, + .emif_rd_wr_exec_thresh = 0x40000305 +}; + +const struct emif_regs emif_1_regs_ddr3_532_mhz_1cs_dra_es1 = { + .sdram_config_init = 0x61851ab2, + .sdram_config = 0x61851ab2, + .sdram_config2 = 0x08000000, + .ref_ctrl = 0x00001035, + .sdram_tim1 = 0xCCCF36B3, + .sdram_tim2 = 0x308F7FDA, + .sdram_tim3 = 0x027F88A8, + .read_idle_ctrl = 0x00050000, + .zq_config = 0x0007190B, + .temp_alert_config = 0x00000000, + .emif_ddr_phy_ctlr_1_init = 0x0024400A, + .emif_ddr_phy_ctlr_1 = 0x0024400A, + .emif_ddr_ext_phy_ctrl_1 = 0x10040100, + .emif_ddr_ext_phy_ctrl_2 = 0x00B000B0, + .emif_ddr_ext_phy_ctrl_3 = 0x00B000B0, + .emif_ddr_ext_phy_ctrl_4 = 0x00B000B0, + .emif_ddr_ext_phy_ctrl_5 = 0x00B000B0, + .emif_rd_wr_lvl_rmp_win = 0x00000000, + .emif_rd_wr_lvl_rmp_ctl = 0x80000000, + .emif_rd_wr_lvl_ctl = 0x00000000, + .emif_rd_wr_exec_thresh = 0x00000305 +}; + +const struct emif_regs emif_2_regs_ddr3_532_mhz_1cs_dra_es1 = { + .sdram_config_init = 0x61851B32, + .sdram_config = 0x61851B32, + .sdram_config2 = 0x08000000, + .ref_ctrl = 0x00001035, + .sdram_tim1 = 0xCCCF36B3, + .sdram_tim2 = 0x308F7FDA, + .sdram_tim3 = 0x027F88A8, + .read_idle_ctrl = 0x00050000, + .zq_config = 0x0007190B, + .temp_alert_config = 0x00000000, + .emif_ddr_phy_ctlr_1_init = 0x0024400A, + .emif_ddr_phy_ctlr_1 = 0x0024400A, + .emif_ddr_ext_phy_ctrl_1 = 0x10040100, + .emif_ddr_ext_phy_ctrl_2 = 0x00B000B0, + .emif_ddr_ext_phy_ctrl_3 = 0x00B000B0, + .emif_ddr_ext_phy_ctrl_4 = 0x00B000B0, + .emif_ddr_ext_phy_ctrl_5 = 0x00B000B0, + .emif_rd_wr_lvl_rmp_win = 0x00000000, + .emif_rd_wr_lvl_rmp_ctl = 0x80000000, + .emif_rd_wr_lvl_ctl = 0x00000000, + .emif_rd_wr_exec_thresh = 0x00000305 +}; + +const struct dmm_lisa_map_regs lisa_map_4G_x_2_x_2 = { + .dmm_lisa_map_0 = 0x0, + .dmm_lisa_map_1 = 0x0, + .dmm_lisa_map_2 = 0x80740300, + .dmm_lisa_map_3 = 0xFF020100, + .is_ma_present = 0x1 +}; + +/* + * DRA752 EVM board has 1.5 GB of memory + * EMIF1 --> 2Gb * 2 = 512MB + * EMIF2 --> 2Gb * 4 = 1GB + * so mapping 1GB interleaved and 512MB non-interleaved + */ +const struct dmm_lisa_map_regs lisa_map_2G_x_2_x_2_2G_x_1_x_2 = { + .dmm_lisa_map_0 = 0x0, + .dmm_lisa_map_1 = 0x80640300, + .dmm_lisa_map_2 = 0xC0500220, + .dmm_lisa_map_3 = 0xFF020100, + .is_ma_present = 0x1 +}; + +/* + * DRA752 EVM EMIF1 ONLY CONFIGURATION + */ +const struct dmm_lisa_map_regs lisa_map_2G_x_1_x_2 = { + .dmm_lisa_map_0 = 0x0, + .dmm_lisa_map_1 = 0x0, + .dmm_lisa_map_2 = 0x80500100, + .dmm_lisa_map_3 = 0xFF020100, + .is_ma_present = 0x1 +}; + +/* + * DRA752 EVM EMIF2 ONLY CONFIGURATION + */ +const struct dmm_lisa_map_regs lisa_map_2G_x_2_x_2 = { + .dmm_lisa_map_0 = 0x0, + .dmm_lisa_map_1 = 0x0, + .dmm_lisa_map_2 = 0x80600200, + .dmm_lisa_map_3 = 0xFF020100, + .is_ma_present = 0x1 +}; + +static void emif_get_reg_dump_sdp(u32 emif_nr, const struct emif_regs **regs) +{ + switch (omap_revision()) { + case OMAP5430_ES1_0: + *regs = &emif_regs_532_mhz_2cs; + break; + case OMAP5432_ES1_0: + *regs = &emif_regs_ddr3_532_mhz_1cs; + break; + case OMAP5430_ES2_0: + *regs = &emif_regs_532_mhz_2cs_es2; + break; + case OMAP5432_ES2_0: + *regs = &emif_regs_ddr3_532_mhz_1cs_es2; + break; + case DRA752_ES1_0: + case DRA752_ES1_1: + switch (emif_nr) { + case 1: + *regs = &emif_1_regs_ddr3_532_mhz_1cs_dra_es1; + break; + case 2: + *regs = &emif_2_regs_ddr3_532_mhz_1cs_dra_es1; + break; + } + break; + default: + *regs = &emif_1_regs_ddr3_532_mhz_1cs_dra_es1; + } +} + +void emif_get_reg_dump(u32 emif_nr, const struct emif_regs **regs) + __attribute__((weak, alias("emif_get_reg_dump_sdp"))); + +static void emif_get_dmm_regs_sdp(const struct dmm_lisa_map_regs + **dmm_lisa_regs) +{ + switch (omap_revision()) { + case OMAP5430_ES1_0: + case OMAP5430_ES2_0: + case OMAP5432_ES1_0: + case OMAP5432_ES2_0: + *dmm_lisa_regs = &lisa_map_4G_x_2_x_2; + break; + case DRA752_ES1_0: + case DRA752_ES1_1: + default: + *dmm_lisa_regs = &lisa_map_2G_x_2_x_2_2G_x_1_x_2; + } + +} + +void emif_get_dmm_regs(const struct dmm_lisa_map_regs **dmm_lisa_regs) + __attribute__((weak, alias("emif_get_dmm_regs_sdp"))); +#else + +static const struct lpddr2_device_details dev_4G_S4_details = { + .type = LPDDR2_TYPE_S4, + .density = LPDDR2_DENSITY_4Gb, + .io_width = LPDDR2_IO_WIDTH_32, + .manufacturer = LPDDR2_MANUFACTURER_SAMSUNG +}; + +static void emif_get_device_details_sdp(u32 emif_nr, + struct lpddr2_device_details *cs0_device_details, + struct lpddr2_device_details *cs1_device_details) +{ + /* EMIF1 & EMIF2 have identical configuration */ + *cs0_device_details = dev_4G_S4_details; + *cs1_device_details = dev_4G_S4_details; +} + +void emif_get_device_details(u32 emif_nr, + struct lpddr2_device_details *cs0_device_details, + struct lpddr2_device_details *cs1_device_details) + __attribute__((weak, alias("emif_get_device_details_sdp"))); + +#endif /* CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS */ + +const u32 ext_phy_ctrl_const_base[] = { + 0x01004010, + 0x00001004, + 0x04010040, + 0x01004010, + 0x00001004, + 0x00000000, + 0x00000000, + 0x00000000, + 0x80080080, + 0x00800800, + 0x08102040, + 0x00000001, + 0x540A8150, + 0xA81502a0, + 0x002A0540, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000077, + 0x0 +}; + +const u32 ddr3_ext_phy_ctrl_const_base_es1[] = { + 0x01004010, + 0x00001004, + 0x04010040, + 0x01004010, + 0x00001004, + 0x00000000, + 0x00000000, + 0x00000000, + 0x80080080, + 0x00800800, + 0x08102040, + 0x00000002, + 0x0, + 0x0, + 0x0, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000057, + 0x0 +}; + +const u32 ddr3_ext_phy_ctrl_const_base_es2[] = { + 0x50D4350D, + 0x00000D43, + 0x04010040, + 0x01004010, + 0x00001004, + 0x00000000, + 0x00000000, + 0x00000000, + 0x80080080, + 0x00800800, + 0x08102040, + 0x00000002, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000057, + 0x0 +}; + +const u32 +dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[] = { + 0x00B000B0, + 0x00400040, + 0x00400040, + 0x00400040, + 0x00400040, + 0x00400040, + 0x00800080, + 0x00800080, + 0x00800080, + 0x00800080, + 0x00800080, + 0x00600060, + 0x00600060, + 0x00600060, + 0x00600060, + 0x00600060, + 0x00800080, + 0x00800080, + 0x40010080, + 0x08102040, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0 +}; + +const u32 +dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[] = { + 0x00BB00BB, + 0x00440044, + 0x00440044, + 0x00440044, + 0x00440044, + 0x00440044, + 0x007F007F, + 0x007F007F, + 0x007F007F, + 0x007F007F, + 0x007F007F, + 0x00600060, + 0x00600060, + 0x00600060, + 0x00600060, + 0x00600060, + 0x0, + 0x00600020, + 0x40010080, + 0x08102040, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0 +}; + +const struct lpddr2_mr_regs mr_regs = { + .mr1 = MR1_BL_8_BT_SEQ_WRAP_EN_NWR_8, + .mr2 = 0x6, + .mr3 = 0x1, + .mr10 = MR10_ZQ_ZQINIT, + .mr16 = MR16_REF_FULL_ARRAY +}; + +static void emif_get_ext_phy_ctrl_const_regs(u32 emif_nr, + const u32 **regs, + u32 *size) +{ + switch (omap_revision()) { + case OMAP5430_ES1_0: + case OMAP5430_ES2_0: + *regs = ext_phy_ctrl_const_base; + *size = ARRAY_SIZE(ext_phy_ctrl_const_base); + break; + case OMAP5432_ES1_0: + *regs = ddr3_ext_phy_ctrl_const_base_es1; + *size = ARRAY_SIZE(ddr3_ext_phy_ctrl_const_base_es1); + break; + case OMAP5432_ES2_0: + *regs = ddr3_ext_phy_ctrl_const_base_es2; + *size = ARRAY_SIZE(ddr3_ext_phy_ctrl_const_base_es2); + break; + case DRA752_ES1_0: + case DRA752_ES1_1: + if (emif_nr == 1) { + *regs = dra_ddr3_ext_phy_ctrl_const_base_es1_emif1; + *size = + ARRAY_SIZE(dra_ddr3_ext_phy_ctrl_const_base_es1_emif1); + } else { + *regs = dra_ddr3_ext_phy_ctrl_const_base_es1_emif2; + *size = + ARRAY_SIZE(dra_ddr3_ext_phy_ctrl_const_base_es1_emif2); + } + break; + default: + *regs = ddr3_ext_phy_ctrl_const_base_es2; + *size = ARRAY_SIZE(ddr3_ext_phy_ctrl_const_base_es2); + + } +} + +void get_lpddr2_mr_regs(const struct lpddr2_mr_regs **regs) +{ + *regs = &mr_regs; +} + +void do_ext_phy_settings(u32 base, const struct emif_regs *regs) +{ + u32 *ext_phy_ctrl_base = 0; + u32 *emif_ext_phy_ctrl_base = 0; + u32 emif_nr; + const u32 *ext_phy_ctrl_const_regs; + u32 i = 0; + u32 size; + + emif_nr = (base == EMIF1_BASE) ? 1 : 2; + + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + ext_phy_ctrl_base = (u32 *) &(regs->emif_ddr_ext_phy_ctrl_1); + emif_ext_phy_ctrl_base = (u32 *) &(emif->emif_ddr_ext_phy_ctrl_1); + + /* Configure external phy control timing registers */ + for (i = 0; i < EMIF_EXT_PHY_CTRL_TIMING_REG; i++) { + writel(*ext_phy_ctrl_base, emif_ext_phy_ctrl_base++); + /* Update shadow registers */ + writel(*ext_phy_ctrl_base++, emif_ext_phy_ctrl_base++); + } + + /* + * external phy 6-24 registers do not change with + * ddr frequency + */ + emif_get_ext_phy_ctrl_const_regs(emif_nr, + &ext_phy_ctrl_const_regs, &size); + + for (i = 0; i < size; i++) { + writel(ext_phy_ctrl_const_regs[i], + emif_ext_phy_ctrl_base++); + /* Update shadow registers */ + writel(ext_phy_ctrl_const_regs[i], + emif_ext_phy_ctrl_base++); + } +} + +#ifndef CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS +static const struct lpddr2_ac_timings timings_jedec_532_mhz = { + .max_freq = 532000000, + .RL = 8, + .tRPab = 21, + .tRCD = 18, + .tWR = 15, + .tRASmin = 42, + .tRRD = 10, + .tWTRx2 = 15, + .tXSR = 140, + .tXPx2 = 15, + .tRFCab = 130, + .tRTPx2 = 15, + .tCKE = 3, + .tCKESR = 15, + .tZQCS = 90, + .tZQCL = 360, + .tZQINIT = 1000, + .tDQSCKMAXx2 = 11, + .tRASmax = 70, + .tFAW = 50 +}; + +static const struct lpddr2_min_tck min_tck = { + .tRL = 3, + .tRP_AB = 3, + .tRCD = 3, + .tWR = 3, + .tRAS_MIN = 3, + .tRRD = 2, + .tWTR = 2, + .tXP = 2, + .tRTP = 2, + .tCKE = 3, + .tCKESR = 3, + .tFAW = 8 +}; + +static const struct lpddr2_ac_timings *ac_timings[MAX_NUM_SPEEDBINS] = { + &timings_jedec_532_mhz +}; + +static const struct lpddr2_device_timings dev_4G_S4_timings = { + .ac_timings = ac_timings, + .min_tck = &min_tck, +}; + +/* + * List of status registers to be controlled back to control registers + * after initial leveling + * readreg, writereg + */ +const struct read_write_regs omap5_bug_00339_regs[] = { + { 8, 5 }, + { 9, 6 }, + { 10, 7 }, + { 14, 8 }, + { 15, 9 }, + { 16, 10 }, + { 11, 2 }, + { 12, 3 }, + { 13, 4 }, + { 17, 11 }, + { 18, 12 }, + { 19, 13 }, +}; + +const struct read_write_regs dra_bug_00339_regs[] = { + { 7, 7 }, + { 8, 8 }, + { 9, 9 }, + { 10, 10 }, + { 11, 11 }, + { 12, 2 }, + { 13, 3 }, + { 14, 4 }, + { 15, 5 }, + { 16, 6 }, + { 17, 12 }, + { 18, 13 }, + { 19, 14 }, + { 20, 15 }, + { 21, 16 }, + { 22, 17 }, + { 23, 18 }, + { 24, 19 }, + { 25, 20 }, + { 26, 21} +}; + +const struct read_write_regs *get_bug_regs(u32 *iterations) +{ + const struct read_write_regs *bug_00339_regs_ptr = NULL; + + switch (omap_revision()) { + case OMAP5430_ES1_0: + case OMAP5430_ES2_0: + case OMAP5432_ES1_0: + case OMAP5432_ES2_0: + bug_00339_regs_ptr = omap5_bug_00339_regs; + *iterations = sizeof(omap5_bug_00339_regs)/ + sizeof(omap5_bug_00339_regs[0]); + break; + case DRA752_ES1_0: + case DRA752_ES1_1: + bug_00339_regs_ptr = dra_bug_00339_regs; + *iterations = sizeof(dra_bug_00339_regs)/ + sizeof(dra_bug_00339_regs[0]); + break; + default: + printf("\n Error: UnKnown SOC"); + } + + return bug_00339_regs_ptr; +} + +void emif_get_device_timings_sdp(u32 emif_nr, + const struct lpddr2_device_timings **cs0_device_timings, + const struct lpddr2_device_timings **cs1_device_timings) +{ + /* Identical devices on EMIF1 & EMIF2 */ + *cs0_device_timings = &dev_4G_S4_timings; + *cs1_device_timings = &dev_4G_S4_timings; +} + +void emif_get_device_timings(u32 emif_nr, + const struct lpddr2_device_timings **cs0_device_timings, + const struct lpddr2_device_timings **cs1_device_timings) + __attribute__((weak, alias("emif_get_device_timings_sdp"))); + +#endif /* CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/Makefile new file mode 100644 index 000000000..22219990d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/Makefile @@ -0,0 +1,17 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu_info.o +obj-y += emac.o + +obj-$(CONFIG_DISPLAY_BOARDINFO) += board.o +obj-$(CONFIG_GLOBAL_TIMER) += timer.o +obj-$(CONFIG_R8A7740) += lowlevel_init.o cpu_info-r8a7740.o pfc-r8a7740.o +obj-$(CONFIG_R8A7790) += lowlevel_init_ca15.o cpu_info-r8a7790.o pfc-r8a7790.o +obj-$(CONFIG_R8A7791) += lowlevel_init_ca15.o cpu_info-r8a7791.o pfc-r8a7791.o +obj-$(CONFIG_SH73A0) += lowlevel_init.o cpu_info-sh73a0.o pfc-sh73a0.o +obj-$(CONFIG_TMU_TIMER) += ../../../../sh/lib/time.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/board.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/board.c new file mode 100644 index 000000000..d91bc2670 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/board.c @@ -0,0 +1,15 @@ +/* + * (C) Copyright 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> + * (C) Copyright 2012 Renesas Solutions Corp. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> + +int checkboard(void) +{ + printf("Board: %s\n", sysinfo.board_string); + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-r8a7740.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-r8a7740.c new file mode 100644 index 000000000..dfe8950ae --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-r8a7740.c @@ -0,0 +1,32 @@ +/* + * (C) Copyright 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> + * (C) Copyright 2012 Renesas Solutions Corp. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/io.h> + +u32 rmobile_get_cpu_type(void) +{ + u32 id; + u32 type; + struct r8a7740_hpb *hpb = (struct r8a7740_hpb *)HPB_BASE; + + id = readl(hpb->cccr); + type = (id >> 8) & 0xFF; + + return type; +} + +u32 rmobile_get_cpu_rev(void) +{ + u32 id; + u32 rev; + struct r8a7740_hpb *hpb = (struct r8a7740_hpb *)HPB_BASE; + + id = readl(hpb->cccr); + rev = (id >> 4) & 0xF; + + return rev; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-r8a7790.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-r8a7790.c new file mode 100644 index 000000000..7232e2377 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-r8a7790.c @@ -0,0 +1,22 @@ +/* + * arch/arm/cpu/armv7/rmobile/cpu_info-r8a7790.c + * This file is r8a7790 processor support. + * + * Copyright (C) 2013 Renesas Electronics Corporation + * + * SPDX-License-Identifier: GPL-2.0 + */ +#include <common.h> +#include <asm/io.h> + +#define PRR 0xFF000044 + +u32 rmobile_get_cpu_type(void) +{ + return (readl(PRR) & 0x00007F00) >> 8; +} + +u32 rmobile_get_cpu_rev_integer(void) +{ + return (readl(PRR) & 0x000000F0) >> 4; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-r8a7791.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-r8a7791.c new file mode 100644 index 000000000..2de58ed27 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-r8a7791.c @@ -0,0 +1,29 @@ +/* + * arch/arm/cpu/armv7/rmobile/cpu_info-r8a7791.c + * + * Copyright (C) 2013 Renesas Electronics Corporation + * + * SPDX-License-Identifier: GPL-2.0 + */ +#include <common.h> +#include <asm/io.h> + +#define PRR 0xFF000044 + +u32 rmobile_get_cpu_type(void) +{ + u32 product; + + product = readl(PRR); + + return (u32)((product & 0x00007F00) >> 8); +} + +u32 rmobile_get_cpu_rev_integer(void) +{ + u32 product; + + product = readl(PRR); + + return (u32)((product & 0x000000F0) >> 4); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-sh73a0.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-sh73a0.c new file mode 100644 index 000000000..186b4b5cb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info-sh73a0.c @@ -0,0 +1,44 @@ +/* + * (C) Copyright 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> + * (C) Copyright 2012 Renesas Solutions Corp. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/io.h> + +u32 rmobile_get_cpu_type(void) +{ + u32 id; + u32 type; + struct sh73a0_hpb *hpb = (struct sh73a0_hpb *)HPB_BASE; + + id = readl(&hpb->cccr); + type = (id >> 8) & 0xFF; + + return type; +} + +u32 rmobile_get_cpu_rev_integer(void) +{ + u32 id; + u32 rev; + struct sh73a0_hpb *hpb = (struct sh73a0_hpb *)HPB_BASE; + + id = readl(&hpb->cccr); + rev = ((id >> 4) & 0xF) + 1; + + return rev; +} + +u32 rmobile_get_cpu_rev_fraction(void) +{ + u32 id; + u32 rev; + struct sh73a0_hpb *hpb = (struct sh73a0_hpb *)HPB_BASE; + + id = readl(&hpb->cccr); + rev = id & 0xF; + + return rev; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info.c new file mode 100644 index 000000000..83d5282e3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/cpu_info.c @@ -0,0 +1,79 @@ +/* + * (C) Copyright 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> + * (C) Copyright 2012 Renesas Solutions Corp. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/io.h> + +#ifdef CONFIG_ARCH_CPU_INIT +int arch_cpu_init(void) +{ + icache_enable(); + return 0; +} +#endif + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + dcache_enable(); +} +#endif + +#ifdef CONFIG_DISPLAY_CPUINFO +static u32 __rmobile_get_cpu_type(void) +{ + return 0x0; +} +u32 rmobile_get_cpu_type(void) + __attribute__((weak, alias("__rmobile_get_cpu_type"))); + +static u32 __rmobile_get_cpu_rev_integer(void) +{ + return 0; +} +u32 rmobile_get_cpu_rev_integer(void) + __attribute__((weak, alias("__rmobile_get_cpu_rev_integer"))); + +static u32 __rmobile_get_cpu_rev_fraction(void) +{ + return 0; +} +u32 rmobile_get_cpu_rev_fraction(void) + __attribute__((weak, alias("__rmobile_get_cpu_rev_fraction"))); + +int print_cpuinfo(void) +{ + switch (rmobile_get_cpu_type()) { + case 0x37: + printf("CPU: Renesas Electronics SH73A0 rev %d.%d\n", + rmobile_get_cpu_rev_integer(), + rmobile_get_cpu_rev_fraction()); + break; + case 0x40: + printf("CPU: Renesas Electronics R8A7740 rev %d.%d\n", + rmobile_get_cpu_rev_integer(), + rmobile_get_cpu_rev_fraction()); + break; + + case 0x45: + printf("CPU: Renesas Electronics R8A7790 rev %d\n", + rmobile_get_cpu_rev_integer()); + break; + + case 0x47: + printf("CPU: Renesas Electronics R8A7791 rev %d\n", + rmobile_get_cpu_rev_integer()); + break; + + default: + printf("CPU: Renesas Electronics CPU rev %d.%d\n", + rmobile_get_cpu_rev_integer(), + rmobile_get_cpu_rev_fraction()); + break; + } + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/emac.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/emac.c new file mode 100644 index 000000000..0710cfd3c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/emac.c @@ -0,0 +1,21 @@ +/* + * RMOBILE EtherMAC initialization. + * + * Copyright (C) 2012 Renesas Solutions Corp. + * Copyright (C) 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/errno.h> +#include <netdev.h> + +int cpu_eth_init(bd_t *bis) +{ + int ret = -ENODEV; +#ifdef CONFIG_SH_ETHER + ret = sh_eth_initialize(bis); +#endif + return ret; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/lowlevel_init.S new file mode 100644 index 000000000..0d654403e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/lowlevel_init.S @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2012 Nobuhiro Iwamatsu <nobuhiro.Iwamatsu.yj@renesas.com> + * Copyright (C) 2012 Renesas Solutions Corp. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <linux/linkage.h> + +ENTRY(lowlevel_init) + ldr r0, =MERAM_BASE + mov r1, #0x0 + str r1, [r0] + + mrc p15, 0, r0, c0, c0, 5 + ands r0, r0, #0xF + beq lowlevel_init__ + b wait_interrupt + + .pool + .align 4 + +wait_interrupt: +#ifdef ICCICR + ldr r1, =ICCICR + mov r2, #0x0 + str r2, [r1] + mov r2, #0xF0 + adds r1, r1, #4 /* ICCPMR */ + str r2, [r1] + ldr r1, =ICCICR + mov r2, #0x1 + str r2, [r1] +#endif + +wait_loop: + .long 0xE320F003 /* wfi */ + + ldr r2, [r1, #0xC] + str r2, [r1, #0x10] + + ldr r0, =MERAM_BASE + ldr r2, [r0] + cmp r2, #0 + movne pc, r2 + + b wait_loop + +wait_loop_end: + .pool + .align 4 + +lowlevel_init__: + + mov r0, #0x200000 + +loop0: + subs r0, r0, #1 + bne loop0 + + ldr sp, MERAM_STACK + b s_init + + .pool + .align 4 + +ENDPROC(lowlevel_init) + .ltorg + +MERAM_STACK: + .word LOW_LEVEL_MERAM_STACK diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/lowlevel_init_ca15.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/lowlevel_init_ca15.S new file mode 100644 index 000000000..e07cc8093 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/lowlevel_init_ca15.S @@ -0,0 +1,60 @@ +/* + * arch/arm/cpu/armv7/rmobile/lowlevel_init_ca15.S + * This file is lager low level initialize. + * + * Copyright (C) 2013 Renesas Electronics Corporation + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <config.h> +#include <linux/linkage.h> + +ENTRY(lowlevel_init) + mrc p15, 0, r4, c0, c0, 5 /* mpidr */ + orr r4, r4, r4, lsr #6 + and r4, r4, #7 /* id 0-3 = ca15.0,1,2,3 */ + + b do_lowlevel_init + + .pool + +/* + * CPU ID #1-#3 come here + */ + .align 4 +do_cpu_waiting: + ldr r1, =0xe6180000 /* sysc */ +1: ldr r0, [r1, #0x20] /* sbar */ + tst r0, r0 + beq 1b + bx r0 + +/* + * Only CPU ID #0 comes here + */ + .align 4 +do_lowlevel_init: + /* surpress wfe if ca15 */ + tst r4, #4 + mrceq p15, 0, r0, c1, c0, 1 /* actlr */ + orreq r0, r0, #(1<<7) + mcreq p15, 0, r0, c1, c0, 1 + /* and set l2 latency */ + mrceq p15, 1, r0, c9, c0, 2 /* l2ctlr */ + orreq r0, r0, #0x00000800 + orreq r0, r0, #0x00000003 + mcreq p15, 1, r0, c9, c0, 2 + + ldr r3, =(CONFIG_SYS_INIT_SP_ADDR) + sub sp, r3, #4 + str lr, [sp] + + /* initialize system */ + bl s_init + + ldr lr, [sp] + mov pc, lr + nop +ENDPROC(lowlevel_init) + .ltorg diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7740.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7740.c new file mode 100644 index 000000000..5d42a6826 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7740.c @@ -0,0 +1,2612 @@ +/* + * R8A7740 processor support + * + * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2011 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <common.h> +#include <sh_pfc.h> +#include <asm/gpio.h> +#include <asm/arch/irqs.h> + +#define CPU_ALL_PORT(fn, pfx, sfx) \ + PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx), \ + PORT_10(fn, pfx##10, sfx), PORT_90(fn, pfx##1, sfx), \ + PORT_10(fn, pfx##20, sfx), \ + PORT_1(fn, pfx##210, sfx), PORT_1(fn, pfx##211, sfx) + +enum { + PINMUX_RESERVED = 0, + + /* PORT0_DATA -> PORT211_DATA */ + PINMUX_DATA_BEGIN, + PORT_ALL(DATA), + PINMUX_DATA_END, + + /* PORT0_IN -> PORT211_IN */ + PINMUX_INPUT_BEGIN, + PORT_ALL(IN), + PINMUX_INPUT_END, + + /* PORT0_IN_PU -> PORT211_IN_PU */ + PINMUX_INPUT_PULLUP_BEGIN, + PORT_ALL(IN_PU), + PINMUX_INPUT_PULLUP_END, + + /* PORT0_IN_PD -> PORT211_IN_PD */ + PINMUX_INPUT_PULLDOWN_BEGIN, + PORT_ALL(IN_PD), + PINMUX_INPUT_PULLDOWN_END, + + /* PORT0_OUT -> PORT211_OUT */ + PINMUX_OUTPUT_BEGIN, + PORT_ALL(OUT), + PINMUX_OUTPUT_END, + + PINMUX_FUNCTION_BEGIN, + PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT211_FN_IN */ + PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT211_FN_OUT */ + PORT_ALL(FN0), /* PORT0_FN0 -> PORT211_FN0 */ + PORT_ALL(FN1), /* PORT0_FN1 -> PORT211_FN1 */ + PORT_ALL(FN2), /* PORT0_FN2 -> PORT211_FN2 */ + PORT_ALL(FN3), /* PORT0_FN3 -> PORT211_FN3 */ + PORT_ALL(FN4), /* PORT0_FN4 -> PORT211_FN4 */ + PORT_ALL(FN5), /* PORT0_FN5 -> PORT211_FN5 */ + PORT_ALL(FN6), /* PORT0_FN6 -> PORT211_FN6 */ + PORT_ALL(FN7), /* PORT0_FN7 -> PORT211_FN7 */ + + MSEL1CR_31_0, MSEL1CR_31_1, + MSEL1CR_30_0, MSEL1CR_30_1, + MSEL1CR_29_0, MSEL1CR_29_1, + MSEL1CR_28_0, MSEL1CR_28_1, + MSEL1CR_27_0, MSEL1CR_27_1, + MSEL1CR_26_0, MSEL1CR_26_1, + MSEL1CR_16_0, MSEL1CR_16_1, + MSEL1CR_15_0, MSEL1CR_15_1, + MSEL1CR_14_0, MSEL1CR_14_1, + MSEL1CR_13_0, MSEL1CR_13_1, + MSEL1CR_12_0, MSEL1CR_12_1, + MSEL1CR_9_0, MSEL1CR_9_1, + MSEL1CR_7_0, MSEL1CR_7_1, + MSEL1CR_6_0, MSEL1CR_6_1, + MSEL1CR_5_0, MSEL1CR_5_1, + MSEL1CR_4_0, MSEL1CR_4_1, + MSEL1CR_3_0, MSEL1CR_3_1, + MSEL1CR_2_0, MSEL1CR_2_1, + MSEL1CR_0_0, MSEL1CR_0_1, + + MSEL3CR_15_0, MSEL3CR_15_1, /* Trace / Debug ? */ + MSEL3CR_6_0, MSEL3CR_6_1, + + MSEL4CR_19_0, MSEL4CR_19_1, + MSEL4CR_18_0, MSEL4CR_18_1, + MSEL4CR_15_0, MSEL4CR_15_1, + MSEL4CR_10_0, MSEL4CR_10_1, + MSEL4CR_6_0, MSEL4CR_6_1, + MSEL4CR_4_0, MSEL4CR_4_1, + MSEL4CR_1_0, MSEL4CR_1_1, + + MSEL5CR_31_0, MSEL5CR_31_1, /* irq/fiq output */ + MSEL5CR_30_0, MSEL5CR_30_1, + MSEL5CR_29_0, MSEL5CR_29_1, + MSEL5CR_27_0, MSEL5CR_27_1, + MSEL5CR_25_0, MSEL5CR_25_1, + MSEL5CR_23_0, MSEL5CR_23_1, + MSEL5CR_21_0, MSEL5CR_21_1, + MSEL5CR_19_0, MSEL5CR_19_1, + MSEL5CR_17_0, MSEL5CR_17_1, + MSEL5CR_15_0, MSEL5CR_15_1, + MSEL5CR_14_0, MSEL5CR_14_1, + MSEL5CR_13_0, MSEL5CR_13_1, + MSEL5CR_12_0, MSEL5CR_12_1, + MSEL5CR_11_0, MSEL5CR_11_1, + MSEL5CR_10_0, MSEL5CR_10_1, + MSEL5CR_8_0, MSEL5CR_8_1, + MSEL5CR_7_0, MSEL5CR_7_1, + MSEL5CR_6_0, MSEL5CR_6_1, + MSEL5CR_5_0, MSEL5CR_5_1, + MSEL5CR_4_0, MSEL5CR_4_1, + MSEL5CR_3_0, MSEL5CR_3_1, + MSEL5CR_2_0, MSEL5CR_2_1, + MSEL5CR_0_0, MSEL5CR_0_1, + PINMUX_FUNCTION_END, + + PINMUX_MARK_BEGIN, + + /* IRQ */ + IRQ0_PORT2_MARK, IRQ0_PORT13_MARK, + IRQ1_MARK, + IRQ2_PORT11_MARK, IRQ2_PORT12_MARK, + IRQ3_PORT10_MARK, IRQ3_PORT14_MARK, + IRQ4_PORT15_MARK, IRQ4_PORT172_MARK, + IRQ5_PORT0_MARK, IRQ5_PORT1_MARK, + IRQ6_PORT121_MARK, IRQ6_PORT173_MARK, + IRQ7_PORT120_MARK, IRQ7_PORT209_MARK, + IRQ8_MARK, + IRQ9_PORT118_MARK, IRQ9_PORT210_MARK, + IRQ10_MARK, + IRQ11_MARK, + IRQ12_PORT42_MARK, IRQ12_PORT97_MARK, + IRQ13_PORT64_MARK, IRQ13_PORT98_MARK, + IRQ14_PORT63_MARK, IRQ14_PORT99_MARK, + IRQ15_PORT62_MARK, IRQ15_PORT100_MARK, + IRQ16_PORT68_MARK, IRQ16_PORT211_MARK, + IRQ17_MARK, + IRQ18_MARK, + IRQ19_MARK, + IRQ20_MARK, + IRQ21_MARK, + IRQ22_MARK, + IRQ23_MARK, + IRQ24_MARK, + IRQ25_MARK, + IRQ26_PORT58_MARK, IRQ26_PORT81_MARK, + IRQ27_PORT57_MARK, IRQ27_PORT168_MARK, + IRQ28_PORT56_MARK, IRQ28_PORT169_MARK, + IRQ29_PORT50_MARK, IRQ29_PORT170_MARK, + IRQ30_PORT49_MARK, IRQ30_PORT171_MARK, + IRQ31_PORT41_MARK, IRQ31_PORT167_MARK, + + /* Function */ + + /* DBGT */ + DBGMDT2_MARK, DBGMDT1_MARK, DBGMDT0_MARK, + DBGMD10_MARK, DBGMD11_MARK, DBGMD20_MARK, + DBGMD21_MARK, + + /* FSI */ + FSIAISLD_PORT0_MARK, /* FSIAISLD Port 0/5 */ + FSIAISLD_PORT5_MARK, + FSIASPDIF_PORT9_MARK, /* FSIASPDIF Port 9/18 */ + FSIASPDIF_PORT18_MARK, + FSIAOSLD1_MARK, FSIAOSLD2_MARK, FSIAOLR_MARK, + FSIAOBT_MARK, FSIAOSLD_MARK, FSIAOMC_MARK, + FSIACK_MARK, FSIAILR_MARK, FSIAIBT_MARK, + + /* FMSI */ + FMSISLD_PORT1_MARK, /* FMSISLD Port 1/6 */ + FMSISLD_PORT6_MARK, + FMSIILR_MARK, FMSIIBT_MARK, FMSIOLR_MARK, FMSIOBT_MARK, + FMSICK_MARK, FMSOILR_MARK, FMSOIBT_MARK, FMSOOLR_MARK, + FMSOOBT_MARK, FMSOSLD_MARK, FMSOCK_MARK, + + /* SCIFA0 */ + SCIFA0_SCK_MARK, SCIFA0_CTS_MARK, SCIFA0_RTS_MARK, + SCIFA0_RXD_MARK, SCIFA0_TXD_MARK, + + /* SCIFA1 */ + SCIFA1_CTS_MARK, SCIFA1_SCK_MARK, SCIFA1_RXD_MARK, + SCIFA1_TXD_MARK, SCIFA1_RTS_MARK, + + /* SCIFA2 */ + SCIFA2_SCK_PORT22_MARK, /* SCIFA2_SCK Port 22/199 */ + SCIFA2_SCK_PORT199_MARK, + SCIFA2_RXD_MARK, SCIFA2_TXD_MARK, + SCIFA2_CTS_MARK, SCIFA2_RTS_MARK, + + /* SCIFA3 */ + SCIFA3_RTS_PORT105_MARK, /* MSEL5CR_8_0 */ + SCIFA3_SCK_PORT116_MARK, + SCIFA3_CTS_PORT117_MARK, + SCIFA3_RXD_PORT174_MARK, + SCIFA3_TXD_PORT175_MARK, + + SCIFA3_RTS_PORT161_MARK, /* MSEL5CR_8_1 */ + SCIFA3_SCK_PORT158_MARK, + SCIFA3_CTS_PORT162_MARK, + SCIFA3_RXD_PORT159_MARK, + SCIFA3_TXD_PORT160_MARK, + + /* SCIFA4 */ + SCIFA4_RXD_PORT12_MARK, /* MSEL5CR[12:11] = 00 */ + SCIFA4_TXD_PORT13_MARK, + + SCIFA4_RXD_PORT204_MARK, /* MSEL5CR[12:11] = 01 */ + SCIFA4_TXD_PORT203_MARK, + + SCIFA4_RXD_PORT94_MARK, /* MSEL5CR[12:11] = 10 */ + SCIFA4_TXD_PORT93_MARK, + + SCIFA4_SCK_PORT21_MARK, /* SCIFA4_SCK Port 21/205 */ + SCIFA4_SCK_PORT205_MARK, + + /* SCIFA5 */ + SCIFA5_TXD_PORT20_MARK, /* MSEL5CR[15:14] = 00 */ + SCIFA5_RXD_PORT10_MARK, + + SCIFA5_RXD_PORT207_MARK, /* MSEL5CR[15:14] = 01 */ + SCIFA5_TXD_PORT208_MARK, + + SCIFA5_TXD_PORT91_MARK, /* MSEL5CR[15:14] = 10 */ + SCIFA5_RXD_PORT92_MARK, + + SCIFA5_SCK_PORT23_MARK, /* SCIFA5_SCK Port 23/206 */ + SCIFA5_SCK_PORT206_MARK, + + /* SCIFA6 */ + SCIFA6_SCK_MARK, SCIFA6_RXD_MARK, SCIFA6_TXD_MARK, + + /* SCIFA7 */ + SCIFA7_TXD_MARK, SCIFA7_RXD_MARK, + + /* SCIFAB */ + SCIFB_SCK_PORT190_MARK, /* MSEL5CR_17_0 */ + SCIFB_RXD_PORT191_MARK, + SCIFB_TXD_PORT192_MARK, + SCIFB_RTS_PORT186_MARK, + SCIFB_CTS_PORT187_MARK, + + SCIFB_SCK_PORT2_MARK, /* MSEL5CR_17_1 */ + SCIFB_RXD_PORT3_MARK, + SCIFB_TXD_PORT4_MARK, + SCIFB_RTS_PORT172_MARK, + SCIFB_CTS_PORT173_MARK, + + /* LCD0 */ + LCDC0_SELECT_MARK, + + LCD0_D0_MARK, LCD0_D1_MARK, LCD0_D2_MARK, LCD0_D3_MARK, + LCD0_D4_MARK, LCD0_D5_MARK, LCD0_D6_MARK, LCD0_D7_MARK, + LCD0_D8_MARK, LCD0_D9_MARK, LCD0_D10_MARK, LCD0_D11_MARK, + LCD0_D12_MARK, LCD0_D13_MARK, LCD0_D14_MARK, LCD0_D15_MARK, + LCD0_D16_MARK, LCD0_D17_MARK, + LCD0_DON_MARK, LCD0_VCPWC_MARK, LCD0_VEPWC_MARK, + LCD0_DCK_MARK, LCD0_VSYN_MARK, /* for RGB */ + LCD0_HSYN_MARK, LCD0_DISP_MARK, /* for RGB */ + LCD0_WR_MARK, LCD0_RD_MARK, /* for SYS */ + LCD0_CS_MARK, LCD0_RS_MARK, /* for SYS */ + + LCD0_D21_PORT158_MARK, LCD0_D23_PORT159_MARK, /* MSEL5CR_6_1 */ + LCD0_D22_PORT160_MARK, LCD0_D20_PORT161_MARK, + LCD0_D19_PORT162_MARK, LCD0_D18_PORT163_MARK, + LCD0_LCLK_PORT165_MARK, + + LCD0_D18_PORT40_MARK, LCD0_D22_PORT0_MARK, /* MSEL5CR_6_0 */ + LCD0_D23_PORT1_MARK, LCD0_D21_PORT2_MARK, + LCD0_D20_PORT3_MARK, LCD0_D19_PORT4_MARK, + LCD0_LCLK_PORT102_MARK, + + /* LCD1 */ + LCDC1_SELECT_MARK, + + LCD1_D0_MARK, LCD1_D1_MARK, LCD1_D2_MARK, LCD1_D3_MARK, + LCD1_D4_MARK, LCD1_D5_MARK, LCD1_D6_MARK, LCD1_D7_MARK, + LCD1_D8_MARK, LCD1_D9_MARK, LCD1_D10_MARK, LCD1_D11_MARK, + LCD1_D12_MARK, LCD1_D13_MARK, LCD1_D14_MARK, LCD1_D15_MARK, + LCD1_D16_MARK, LCD1_D17_MARK, LCD1_D18_MARK, LCD1_D19_MARK, + LCD1_D20_MARK, LCD1_D21_MARK, LCD1_D22_MARK, LCD1_D23_MARK, + LCD1_DON_MARK, LCD1_VCPWC_MARK, + LCD1_LCLK_MARK, LCD1_VEPWC_MARK, + + LCD1_DCK_MARK, LCD1_VSYN_MARK, /* for RGB */ + LCD1_HSYN_MARK, LCD1_DISP_MARK, /* for RGB */ + LCD1_RS_MARK, LCD1_CS_MARK, /* for SYS */ + LCD1_RD_MARK, LCD1_WR_MARK, /* for SYS */ + + /* RSPI */ + RSPI_SSL0_A_MARK, RSPI_SSL1_A_MARK, RSPI_SSL2_A_MARK, + RSPI_SSL3_A_MARK, RSPI_CK_A_MARK, RSPI_MOSI_A_MARK, + RSPI_MISO_A_MARK, + + /* VIO CKO */ + VIO_CKO1_MARK, /* needs fixup */ + VIO_CKO2_MARK, + VIO_CKO_1_MARK, + VIO_CKO_MARK, + + /* VIO0 */ + VIO0_D0_MARK, VIO0_D1_MARK, VIO0_D2_MARK, VIO0_D3_MARK, + VIO0_D4_MARK, VIO0_D5_MARK, VIO0_D6_MARK, VIO0_D7_MARK, + VIO0_D8_MARK, VIO0_D9_MARK, VIO0_D10_MARK, VIO0_D11_MARK, + VIO0_D12_MARK, VIO0_VD_MARK, VIO0_HD_MARK, VIO0_CLK_MARK, + VIO0_FIELD_MARK, + + VIO0_D13_PORT26_MARK, /* MSEL5CR_27_0 */ + VIO0_D14_PORT25_MARK, + VIO0_D15_PORT24_MARK, + + VIO0_D13_PORT22_MARK, /* MSEL5CR_27_1 */ + VIO0_D14_PORT95_MARK, + VIO0_D15_PORT96_MARK, + + /* VIO1 */ + VIO1_D0_MARK, VIO1_D1_MARK, VIO1_D2_MARK, VIO1_D3_MARK, + VIO1_D4_MARK, VIO1_D5_MARK, VIO1_D6_MARK, VIO1_D7_MARK, + VIO1_VD_MARK, VIO1_HD_MARK, VIO1_CLK_MARK, VIO1_FIELD_MARK, + + /* TPU0 */ + TPU0TO0_MARK, TPU0TO1_MARK, TPU0TO3_MARK, + TPU0TO2_PORT66_MARK, /* TPU0TO2 Port 66/202 */ + TPU0TO2_PORT202_MARK, + + /* SSP1 0 */ + STP0_IPD0_MARK, STP0_IPD1_MARK, STP0_IPD2_MARK, STP0_IPD3_MARK, + STP0_IPD4_MARK, STP0_IPD5_MARK, STP0_IPD6_MARK, STP0_IPD7_MARK, + STP0_IPEN_MARK, STP0_IPCLK_MARK, STP0_IPSYNC_MARK, + + /* SSP1 1 */ + STP1_IPD1_MARK, STP1_IPD2_MARK, STP1_IPD3_MARK, STP1_IPD4_MARK, + STP1_IPD5_MARK, STP1_IPD6_MARK, STP1_IPD7_MARK, STP1_IPCLK_MARK, + STP1_IPSYNC_MARK, + + STP1_IPD0_PORT186_MARK, /* MSEL5CR_23_0 */ + STP1_IPEN_PORT187_MARK, + + STP1_IPD0_PORT194_MARK, /* MSEL5CR_23_1 */ + STP1_IPEN_PORT193_MARK, + + /* SIM */ + SIM_RST_MARK, SIM_CLK_MARK, + SIM_D_PORT22_MARK, /* SIM_D Port 22/199 */ + SIM_D_PORT199_MARK, + + /* SDHI0 */ + SDHI0_D0_MARK, SDHI0_D1_MARK, SDHI0_D2_MARK, SDHI0_D3_MARK, + SDHI0_CD_MARK, SDHI0_WP_MARK, SDHI0_CMD_MARK, SDHI0_CLK_MARK, + + /* SDHI1 */ + SDHI1_D0_MARK, SDHI1_D1_MARK, SDHI1_D2_MARK, SDHI1_D3_MARK, + SDHI1_CD_MARK, SDHI1_WP_MARK, SDHI1_CMD_MARK, SDHI1_CLK_MARK, + + /* SDHI2 */ + SDHI2_D0_MARK, SDHI2_D1_MARK, SDHI2_D2_MARK, SDHI2_D3_MARK, + SDHI2_CLK_MARK, SDHI2_CMD_MARK, + + SDHI2_CD_PORT24_MARK, /* MSEL5CR_19_0 */ + SDHI2_WP_PORT25_MARK, + + SDHI2_WP_PORT177_MARK, /* MSEL5CR_19_1 */ + SDHI2_CD_PORT202_MARK, + + /* MSIOF2 */ + MSIOF2_TXD_MARK, MSIOF2_RXD_MARK, MSIOF2_TSCK_MARK, + MSIOF2_SS2_MARK, MSIOF2_TSYNC_MARK, MSIOF2_SS1_MARK, + MSIOF2_MCK1_MARK, MSIOF2_MCK0_MARK, MSIOF2_RSYNC_MARK, + MSIOF2_RSCK_MARK, + + /* KEYSC */ + KEYIN4_MARK, KEYIN5_MARK, KEYIN6_MARK, KEYIN7_MARK, + KEYOUT0_MARK, KEYOUT1_MARK, KEYOUT2_MARK, KEYOUT3_MARK, + KEYOUT4_MARK, KEYOUT5_MARK, KEYOUT6_MARK, KEYOUT7_MARK, + + KEYIN0_PORT43_MARK, /* MSEL4CR_18_0 */ + KEYIN1_PORT44_MARK, + KEYIN2_PORT45_MARK, + KEYIN3_PORT46_MARK, + + KEYIN0_PORT58_MARK, /* MSEL4CR_18_1 */ + KEYIN1_PORT57_MARK, + KEYIN2_PORT56_MARK, + KEYIN3_PORT55_MARK, + + /* VOU */ + DV_D0_MARK, DV_D1_MARK, DV_D2_MARK, DV_D3_MARK, + DV_D4_MARK, DV_D5_MARK, DV_D6_MARK, DV_D7_MARK, + DV_D8_MARK, DV_D9_MARK, DV_D10_MARK, DV_D11_MARK, + DV_D12_MARK, DV_D13_MARK, DV_D14_MARK, DV_D15_MARK, + DV_CLK_MARK, DV_VSYNC_MARK, DV_HSYNC_MARK, + + /* MEMC */ + MEMC_AD0_MARK, MEMC_AD1_MARK, MEMC_AD2_MARK, MEMC_AD3_MARK, + MEMC_AD4_MARK, MEMC_AD5_MARK, MEMC_AD6_MARK, MEMC_AD7_MARK, + MEMC_AD8_MARK, MEMC_AD9_MARK, MEMC_AD10_MARK, MEMC_AD11_MARK, + MEMC_AD12_MARK, MEMC_AD13_MARK, MEMC_AD14_MARK, MEMC_AD15_MARK, + MEMC_CS0_MARK, MEMC_INT_MARK, MEMC_NWE_MARK, MEMC_NOE_MARK, + + MEMC_CS1_MARK, /* MSEL4CR_6_0 */ + MEMC_ADV_MARK, + MEMC_WAIT_MARK, + MEMC_BUSCLK_MARK, + + MEMC_A1_MARK, /* MSEL4CR_6_1 */ + MEMC_DREQ0_MARK, + MEMC_DREQ1_MARK, + MEMC_A0_MARK, + + /* MMC */ + MMC0_D0_PORT68_MARK, MMC0_D1_PORT69_MARK, MMC0_D2_PORT70_MARK, + MMC0_D3_PORT71_MARK, MMC0_D4_PORT72_MARK, MMC0_D5_PORT73_MARK, + MMC0_D6_PORT74_MARK, MMC0_D7_PORT75_MARK, MMC0_CLK_PORT66_MARK, + MMC0_CMD_PORT67_MARK, /* MSEL4CR_15_0 */ + + MMC1_D0_PORT149_MARK, MMC1_D1_PORT148_MARK, MMC1_D2_PORT147_MARK, + MMC1_D3_PORT146_MARK, MMC1_D4_PORT145_MARK, MMC1_D5_PORT144_MARK, + MMC1_D6_PORT143_MARK, MMC1_D7_PORT142_MARK, MMC1_CLK_PORT103_MARK, + MMC1_CMD_PORT104_MARK, /* MSEL4CR_15_1 */ + + /* MSIOF0 */ + MSIOF0_SS1_MARK, MSIOF0_SS2_MARK, MSIOF0_RXD_MARK, + MSIOF0_TXD_MARK, MSIOF0_MCK0_MARK, MSIOF0_MCK1_MARK, + MSIOF0_RSYNC_MARK, MSIOF0_RSCK_MARK, MSIOF0_TSCK_MARK, + MSIOF0_TSYNC_MARK, + + /* MSIOF1 */ + MSIOF1_RSCK_MARK, MSIOF1_RSYNC_MARK, + MSIOF1_MCK0_MARK, MSIOF1_MCK1_MARK, + + MSIOF1_SS2_PORT116_MARK, MSIOF1_SS1_PORT117_MARK, + MSIOF1_RXD_PORT118_MARK, MSIOF1_TXD_PORT119_MARK, + MSIOF1_TSYNC_PORT120_MARK, + MSIOF1_TSCK_PORT121_MARK, /* MSEL4CR_10_0 */ + + MSIOF1_SS1_PORT67_MARK, MSIOF1_TSCK_PORT72_MARK, + MSIOF1_TSYNC_PORT73_MARK, MSIOF1_TXD_PORT74_MARK, + MSIOF1_RXD_PORT75_MARK, + MSIOF1_SS2_PORT202_MARK, /* MSEL4CR_10_1 */ + + /* GPIO */ + GPO0_MARK, GPI0_MARK, GPO1_MARK, GPI1_MARK, + + /* USB0 */ + USB0_OCI_MARK, USB0_PPON_MARK, VBUS_MARK, + + /* USB1 */ + USB1_OCI_MARK, USB1_PPON_MARK, + + /* BBIF1 */ + BBIF1_RXD_MARK, BBIF1_TXD_MARK, BBIF1_TSYNC_MARK, + BBIF1_TSCK_MARK, BBIF1_RSCK_MARK, BBIF1_RSYNC_MARK, + BBIF1_FLOW_MARK, BBIF1_RX_FLOW_N_MARK, + + /* BBIF2 */ + BBIF2_TXD2_PORT5_MARK, /* MSEL5CR_0_0 */ + BBIF2_RXD2_PORT60_MARK, + BBIF2_TSYNC2_PORT6_MARK, + BBIF2_TSCK2_PORT59_MARK, + + BBIF2_RXD2_PORT90_MARK, /* MSEL5CR_0_1 */ + BBIF2_TXD2_PORT183_MARK, + BBIF2_TSCK2_PORT89_MARK, + BBIF2_TSYNC2_PORT184_MARK, + + /* BSC / FLCTL / PCMCIA */ + CS0_MARK, CS2_MARK, CS4_MARK, + CS5B_MARK, CS6A_MARK, + CS5A_PORT105_MARK, /* CS5A PORT 19/105 */ + CS5A_PORT19_MARK, + IOIS16_MARK, /* ? */ + + A0_MARK, A1_MARK, A2_MARK, A3_MARK, + A4_FOE_MARK, /* share with FLCTL */ + A5_FCDE_MARK, /* share with FLCTL */ + A6_MARK, A7_MARK, A8_MARK, A9_MARK, + A10_MARK, A11_MARK, A12_MARK, A13_MARK, + A14_MARK, A15_MARK, A16_MARK, A17_MARK, + A18_MARK, A19_MARK, A20_MARK, A21_MARK, + A22_MARK, A23_MARK, A24_MARK, A25_MARK, + A26_MARK, + + D0_NAF0_MARK, D1_NAF1_MARK, D2_NAF2_MARK, /* share with FLCTL */ + D3_NAF3_MARK, D4_NAF4_MARK, D5_NAF5_MARK, /* share with FLCTL */ + D6_NAF6_MARK, D7_NAF7_MARK, D8_NAF8_MARK, /* share with FLCTL */ + D9_NAF9_MARK, D10_NAF10_MARK, D11_NAF11_MARK, /* share with FLCTL */ + D12_NAF12_MARK, D13_NAF13_MARK, D14_NAF14_MARK, /* share with FLCTL */ + D15_NAF15_MARK, /* share with FLCTL */ + D16_MARK, D17_MARK, D18_MARK, D19_MARK, + D20_MARK, D21_MARK, D22_MARK, D23_MARK, + D24_MARK, D25_MARK, D26_MARK, D27_MARK, + D28_MARK, D29_MARK, D30_MARK, D31_MARK, + + WE0_FWE_MARK, /* share with FLCTL */ + WE1_MARK, + WE2_ICIORD_MARK, /* share with PCMCIA */ + WE3_ICIOWR_MARK, /* share with PCMCIA */ + CKO_MARK, BS_MARK, RDWR_MARK, + RD_FSC_MARK, /* share with FLCTL */ + WAIT_PORT177_MARK, /* WAIT Port 90/177 */ + WAIT_PORT90_MARK, + + FCE0_MARK, FCE1_MARK, FRB_MARK, /* FLCTL */ + + /* IRDA */ + IRDA_FIRSEL_MARK, IRDA_IN_MARK, IRDA_OUT_MARK, + + /* ATAPI */ + IDE_D0_MARK, IDE_D1_MARK, IDE_D2_MARK, IDE_D3_MARK, + IDE_D4_MARK, IDE_D5_MARK, IDE_D6_MARK, IDE_D7_MARK, + IDE_D8_MARK, IDE_D9_MARK, IDE_D10_MARK, IDE_D11_MARK, + IDE_D12_MARK, IDE_D13_MARK, IDE_D14_MARK, IDE_D15_MARK, + IDE_A0_MARK, IDE_A1_MARK, IDE_A2_MARK, IDE_CS0_MARK, + IDE_CS1_MARK, IDE_IOWR_MARK, IDE_IORD_MARK, IDE_IORDY_MARK, + IDE_INT_MARK, IDE_RST_MARK, IDE_DIRECTION_MARK, + IDE_EXBUF_ENB_MARK, IDE_IODACK_MARK, IDE_IODREQ_MARK, + + /* RMII */ + RMII_CRS_DV_MARK, RMII_RX_ER_MARK, RMII_RXD0_MARK, + RMII_RXD1_MARK, RMII_TX_EN_MARK, RMII_TXD0_MARK, + RMII_MDC_MARK, RMII_TXD1_MARK, RMII_MDIO_MARK, + RMII_REF50CK_MARK, /* for RMII */ + RMII_REF125CK_MARK, /* for GMII */ + + /* GEther */ + ET_TX_CLK_MARK, ET_TX_EN_MARK, ET_ETXD0_MARK, ET_ETXD1_MARK, + ET_ETXD2_MARK, ET_ETXD3_MARK, + ET_ETXD4_MARK, ET_ETXD5_MARK, /* for GEther */ + ET_ETXD6_MARK, ET_ETXD7_MARK, /* for GEther */ + ET_COL_MARK, ET_TX_ER_MARK, ET_RX_CLK_MARK, ET_RX_DV_MARK, + ET_ERXD0_MARK, ET_ERXD1_MARK, ET_ERXD2_MARK, ET_ERXD3_MARK, + ET_ERXD4_MARK, ET_ERXD5_MARK, /* for GEther */ + ET_ERXD6_MARK, ET_ERXD7_MARK, /* for GEther */ + ET_RX_ER_MARK, ET_CRS_MARK, ET_MDC_MARK, ET_MDIO_MARK, + ET_LINK_MARK, ET_PHY_INT_MARK, ET_WOL_MARK, ET_GTX_CLK_MARK, + + /* DMA0 */ + DREQ0_MARK, DACK0_MARK, + + /* DMA1 */ + DREQ1_MARK, DACK1_MARK, + + /* SYSC */ + RESETOUTS_MARK, RESETP_PULLUP_MARK, RESETP_PLAIN_MARK, + + /* IRREM */ + IROUT_MARK, + + /* SDENC */ + SDENC_CPG_MARK, SDENC_DV_CLKI_MARK, + + /* DEBUG */ + EDEBGREQ_PULLUP_MARK, /* for JTAG */ + EDEBGREQ_PULLDOWN_MARK, + + TRACEAUD_FROM_VIO_MARK, /* for TRACE/AUD */ + TRACEAUD_FROM_LCDC0_MARK, + TRACEAUD_FROM_MEMC_MARK, + + PINMUX_MARK_END, +}; + +static unsigned short pinmux_data[] = { + /* specify valid pin states for each pin in GPIO mode */ + + /* I/O and Pull U/D */ + PORT_DATA_IO_PD(0), PORT_DATA_IO_PD(1), + PORT_DATA_IO_PD(2), PORT_DATA_IO_PD(3), + PORT_DATA_IO_PD(4), PORT_DATA_IO_PD(5), + PORT_DATA_IO_PD(6), PORT_DATA_IO(7), + PORT_DATA_IO(8), PORT_DATA_IO(9), + + PORT_DATA_IO_PD(10), PORT_DATA_IO_PD(11), + PORT_DATA_IO_PD(12), PORT_DATA_IO_PU_PD(13), + PORT_DATA_IO_PD(14), PORT_DATA_IO_PD(15), + PORT_DATA_IO_PD(16), PORT_DATA_IO_PD(17), + PORT_DATA_IO(18), PORT_DATA_IO_PU(19), + + PORT_DATA_IO_PU_PD(20), PORT_DATA_IO_PD(21), + PORT_DATA_IO_PU_PD(22), PORT_DATA_IO(23), + PORT_DATA_IO_PU(24), PORT_DATA_IO_PU(25), + PORT_DATA_IO_PU(26), PORT_DATA_IO_PU(27), + PORT_DATA_IO_PU(28), PORT_DATA_IO_PU(29), + + PORT_DATA_IO_PU(30), PORT_DATA_IO_PD(31), + PORT_DATA_IO_PD(32), PORT_DATA_IO_PD(33), + PORT_DATA_IO_PD(34), PORT_DATA_IO_PU(35), + PORT_DATA_IO_PU(36), PORT_DATA_IO_PD(37), + PORT_DATA_IO_PU(38), PORT_DATA_IO_PD(39), + + PORT_DATA_IO_PU_PD(40), PORT_DATA_IO_PD(41), + PORT_DATA_IO_PD(42), PORT_DATA_IO_PU_PD(43), + PORT_DATA_IO_PU_PD(44), PORT_DATA_IO_PU_PD(45), + PORT_DATA_IO_PU_PD(46), PORT_DATA_IO_PU_PD(47), + PORT_DATA_IO_PU_PD(48), PORT_DATA_IO_PU_PD(49), + + PORT_DATA_IO_PU_PD(50), PORT_DATA_IO_PD(51), + PORT_DATA_IO_PD(52), PORT_DATA_IO_PD(53), + PORT_DATA_IO_PD(54), PORT_DATA_IO_PU_PD(55), + PORT_DATA_IO_PU_PD(56), PORT_DATA_IO_PU_PD(57), + PORT_DATA_IO_PU_PD(58), PORT_DATA_IO_PU_PD(59), + + PORT_DATA_IO_PU_PD(60), PORT_DATA_IO_PD(61), + PORT_DATA_IO_PD(62), PORT_DATA_IO_PD(63), + PORT_DATA_IO_PD(64), PORT_DATA_IO_PD(65), + PORT_DATA_IO_PU_PD(66), PORT_DATA_IO_PU_PD(67), + PORT_DATA_IO_PU_PD(68), PORT_DATA_IO_PU_PD(69), + + PORT_DATA_IO_PU_PD(70), PORT_DATA_IO_PU_PD(71), + PORT_DATA_IO_PU_PD(72), PORT_DATA_IO_PU_PD(73), + PORT_DATA_IO_PU_PD(74), PORT_DATA_IO_PU_PD(75), + PORT_DATA_IO_PU_PD(76), PORT_DATA_IO_PU_PD(77), + PORT_DATA_IO_PU_PD(78), PORT_DATA_IO_PU_PD(79), + + PORT_DATA_IO_PU_PD(80), PORT_DATA_IO_PU_PD(81), + PORT_DATA_IO(82), PORT_DATA_IO_PU_PD(83), + PORT_DATA_IO(84), PORT_DATA_IO_PD(85), + PORT_DATA_IO_PD(86), PORT_DATA_IO_PD(87), + PORT_DATA_IO_PD(88), PORT_DATA_IO_PD(89), + + PORT_DATA_IO_PD(90), PORT_DATA_IO_PU_PD(91), + PORT_DATA_IO_PU_PD(92), PORT_DATA_IO_PU_PD(93), + PORT_DATA_IO_PU_PD(94), PORT_DATA_IO_PU_PD(95), + PORT_DATA_IO_PU_PD(96), PORT_DATA_IO_PU_PD(97), + PORT_DATA_IO_PU_PD(98), PORT_DATA_IO_PU_PD(99), + + PORT_DATA_IO_PU_PD(100), PORT_DATA_IO(101), + PORT_DATA_IO_PU(102), PORT_DATA_IO_PU_PD(103), + PORT_DATA_IO_PU(104), PORT_DATA_IO_PU(105), + PORT_DATA_IO_PU_PD(106), PORT_DATA_IO(107), + PORT_DATA_IO(108), PORT_DATA_IO(109), + + PORT_DATA_IO(110), PORT_DATA_IO(111), + PORT_DATA_IO(112), PORT_DATA_IO(113), + PORT_DATA_IO_PU_PD(114), PORT_DATA_IO(115), + PORT_DATA_IO_PD(116), PORT_DATA_IO_PD(117), + PORT_DATA_IO_PD(118), PORT_DATA_IO_PD(119), + + PORT_DATA_IO_PD(120), PORT_DATA_IO_PD(121), + PORT_DATA_IO_PD(122), PORT_DATA_IO_PD(123), + PORT_DATA_IO_PD(124), PORT_DATA_IO(125), + PORT_DATA_IO(126), PORT_DATA_IO(127), + PORT_DATA_IO(128), PORT_DATA_IO(129), + + PORT_DATA_IO(130), PORT_DATA_IO(131), + PORT_DATA_IO(132), PORT_DATA_IO(133), + PORT_DATA_IO(134), PORT_DATA_IO(135), + PORT_DATA_IO(136), PORT_DATA_IO(137), + PORT_DATA_IO(138), PORT_DATA_IO(139), + + PORT_DATA_IO(140), PORT_DATA_IO(141), + PORT_DATA_IO_PU(142), PORT_DATA_IO_PU(143), + PORT_DATA_IO_PU(144), PORT_DATA_IO_PU(145), + PORT_DATA_IO_PU(146), PORT_DATA_IO_PU(147), + PORT_DATA_IO_PU(148), PORT_DATA_IO_PU(149), + + PORT_DATA_IO_PU(150), PORT_DATA_IO_PU(151), + PORT_DATA_IO_PU(152), PORT_DATA_IO_PU(153), + PORT_DATA_IO_PU(154), PORT_DATA_IO_PU(155), + PORT_DATA_IO_PU(156), PORT_DATA_IO_PU(157), + PORT_DATA_IO_PD(158), PORT_DATA_IO_PD(159), + + PORT_DATA_IO_PU_PD(160), PORT_DATA_IO_PD(161), + PORT_DATA_IO_PD(162), PORT_DATA_IO_PD(163), + PORT_DATA_IO_PD(164), PORT_DATA_IO_PD(165), + PORT_DATA_IO_PU(166), PORT_DATA_IO_PU(167), + PORT_DATA_IO_PU(168), PORT_DATA_IO_PU(169), + + PORT_DATA_IO_PU(170), PORT_DATA_IO_PU(171), + PORT_DATA_IO_PD(172), PORT_DATA_IO_PD(173), + PORT_DATA_IO_PD(174), PORT_DATA_IO_PD(175), + PORT_DATA_IO_PU(176), PORT_DATA_IO_PU_PD(177), + PORT_DATA_IO_PU(178), PORT_DATA_IO_PD(179), + + PORT_DATA_IO_PD(180), PORT_DATA_IO_PU(181), + PORT_DATA_IO_PU(182), PORT_DATA_IO(183), + PORT_DATA_IO_PD(184), PORT_DATA_IO_PD(185), + PORT_DATA_IO_PD(186), PORT_DATA_IO_PD(187), + PORT_DATA_IO_PD(188), PORT_DATA_IO_PD(189), + + PORT_DATA_IO_PD(190), PORT_DATA_IO_PD(191), + PORT_DATA_IO_PD(192), PORT_DATA_IO_PU_PD(193), + PORT_DATA_IO_PU_PD(194), PORT_DATA_IO_PD(195), + PORT_DATA_IO_PU_PD(196), PORT_DATA_IO_PD(197), + PORT_DATA_IO_PU_PD(198), PORT_DATA_IO_PU_PD(199), + + PORT_DATA_IO_PU_PD(200), PORT_DATA_IO_PU(201), + PORT_DATA_IO_PU_PD(202), PORT_DATA_IO(203), + PORT_DATA_IO_PU_PD(204), PORT_DATA_IO_PU_PD(205), + PORT_DATA_IO_PU_PD(206), PORT_DATA_IO_PU_PD(207), + PORT_DATA_IO_PU_PD(208), PORT_DATA_IO_PD(209), + + PORT_DATA_IO_PD(210), PORT_DATA_IO_PD(211), + + /* Port0 */ + PINMUX_DATA(DBGMDT2_MARK, PORT0_FN1), + PINMUX_DATA(FSIAISLD_PORT0_MARK, PORT0_FN2, MSEL5CR_3_0), + PINMUX_DATA(FSIAOSLD1_MARK, PORT0_FN3), + PINMUX_DATA(LCD0_D22_PORT0_MARK, PORT0_FN4, MSEL5CR_6_0), + PINMUX_DATA(SCIFA7_RXD_MARK, PORT0_FN6), + PINMUX_DATA(LCD1_D4_MARK, PORT0_FN7), + PINMUX_DATA(IRQ5_PORT0_MARK, PORT0_FN0, MSEL1CR_5_0), + + /* Port1 */ + PINMUX_DATA(DBGMDT1_MARK, PORT1_FN1), + PINMUX_DATA(FMSISLD_PORT1_MARK, PORT1_FN2, MSEL5CR_5_0), + PINMUX_DATA(FSIAOSLD2_MARK, PORT1_FN3), + PINMUX_DATA(LCD0_D23_PORT1_MARK, PORT1_FN4, MSEL5CR_6_0), + PINMUX_DATA(SCIFA7_TXD_MARK, PORT1_FN6), + PINMUX_DATA(LCD1_D3_MARK, PORT1_FN7), + PINMUX_DATA(IRQ5_PORT1_MARK, PORT1_FN0, MSEL1CR_5_1), + + /* Port2 */ + PINMUX_DATA(DBGMDT0_MARK, PORT2_FN1), + PINMUX_DATA(SCIFB_SCK_PORT2_MARK, PORT2_FN2, MSEL5CR_17_1), + PINMUX_DATA(LCD0_D21_PORT2_MARK, PORT2_FN4, MSEL5CR_6_0), + PINMUX_DATA(LCD1_D2_MARK, PORT2_FN7), + PINMUX_DATA(IRQ0_PORT2_MARK, PORT2_FN0, MSEL1CR_0_1), + + /* Port3 */ + PINMUX_DATA(DBGMD21_MARK, PORT3_FN1), + PINMUX_DATA(SCIFB_RXD_PORT3_MARK, PORT3_FN2, MSEL5CR_17_1), + PINMUX_DATA(LCD0_D20_PORT3_MARK, PORT3_FN4, MSEL5CR_6_0), + PINMUX_DATA(LCD1_D1_MARK, PORT3_FN7), + + /* Port4 */ + PINMUX_DATA(DBGMD20_MARK, PORT4_FN1), + PINMUX_DATA(SCIFB_TXD_PORT4_MARK, PORT4_FN2, MSEL5CR_17_1), + PINMUX_DATA(LCD0_D19_PORT4_MARK, PORT4_FN4, MSEL5CR_6_0), + PINMUX_DATA(LCD1_D0_MARK, PORT4_FN7), + + /* Port5 */ + PINMUX_DATA(DBGMD11_MARK, PORT5_FN1), + PINMUX_DATA(BBIF2_TXD2_PORT5_MARK, PORT5_FN2, MSEL5CR_0_0), + PINMUX_DATA(FSIAISLD_PORT5_MARK, PORT5_FN4, MSEL5CR_3_1), + PINMUX_DATA(RSPI_SSL0_A_MARK, PORT5_FN6), + PINMUX_DATA(LCD1_VCPWC_MARK, PORT5_FN7), + + /* Port6 */ + PINMUX_DATA(DBGMD10_MARK, PORT6_FN1), + PINMUX_DATA(BBIF2_TSYNC2_PORT6_MARK, PORT6_FN2, MSEL5CR_0_0), + PINMUX_DATA(FMSISLD_PORT6_MARK, PORT6_FN4, MSEL5CR_5_1), + PINMUX_DATA(RSPI_SSL1_A_MARK, PORT6_FN6), + PINMUX_DATA(LCD1_VEPWC_MARK, PORT6_FN7), + + /* Port7 */ + PINMUX_DATA(FSIAOLR_MARK, PORT7_FN1), + + /* Port8 */ + PINMUX_DATA(FSIAOBT_MARK, PORT8_FN1), + + /* Port9 */ + PINMUX_DATA(FSIAOSLD_MARK, PORT9_FN1), + PINMUX_DATA(FSIASPDIF_PORT9_MARK, PORT9_FN2, MSEL5CR_4_0), + + /* Port10 */ + PINMUX_DATA(FSIAOMC_MARK, PORT10_FN1), + PINMUX_DATA(SCIFA5_RXD_PORT10_MARK, PORT10_FN3, MSEL5CR_14_0, + MSEL5CR_15_0), + PINMUX_DATA(IRQ3_PORT10_MARK, PORT10_FN0, MSEL1CR_3_0), + + /* Port11 */ + PINMUX_DATA(FSIACK_MARK, PORT11_FN1), + PINMUX_DATA(IRQ2_PORT11_MARK, PORT11_FN0, MSEL1CR_2_0), + + /* Port12 */ + PINMUX_DATA(FSIAILR_MARK, PORT12_FN1), + PINMUX_DATA(SCIFA4_RXD_PORT12_MARK, PORT12_FN2, MSEL5CR_12_0, + MSEL5CR_11_0), + PINMUX_DATA(LCD1_RS_MARK, PORT12_FN6), + PINMUX_DATA(LCD1_DISP_MARK, PORT12_FN7), + PINMUX_DATA(IRQ2_PORT12_MARK, PORT12_FN0, MSEL1CR_2_1), + + /* Port13 */ + PINMUX_DATA(FSIAIBT_MARK, PORT13_FN1), + PINMUX_DATA(SCIFA4_TXD_PORT13_MARK, PORT13_FN2, MSEL5CR_12_0, + MSEL5CR_11_0), + PINMUX_DATA(LCD1_RD_MARK, PORT13_FN7), + PINMUX_DATA(IRQ0_PORT13_MARK, PORT13_FN0, MSEL1CR_0_0), + + /* Port14 */ + PINMUX_DATA(FMSOILR_MARK, PORT14_FN1), + PINMUX_DATA(FMSIILR_MARK, PORT14_FN2), + PINMUX_DATA(VIO_CKO1_MARK, PORT14_FN3), + PINMUX_DATA(LCD1_D23_MARK, PORT14_FN7), + PINMUX_DATA(IRQ3_PORT14_MARK, PORT14_FN0, MSEL1CR_3_1), + + /* Port15 */ + PINMUX_DATA(FMSOIBT_MARK, PORT15_FN1), + PINMUX_DATA(FMSIIBT_MARK, PORT15_FN2), + PINMUX_DATA(VIO_CKO2_MARK, PORT15_FN3), + PINMUX_DATA(LCD1_D22_MARK, PORT15_FN7), + PINMUX_DATA(IRQ4_PORT15_MARK, PORT15_FN0, MSEL1CR_4_0), + + /* Port16 */ + PINMUX_DATA(FMSOOLR_MARK, PORT16_FN1), + PINMUX_DATA(FMSIOLR_MARK, PORT16_FN2), + + /* Port17 */ + PINMUX_DATA(FMSOOBT_MARK, PORT17_FN1), + PINMUX_DATA(FMSIOBT_MARK, PORT17_FN2), + + /* Port18 */ + PINMUX_DATA(FMSOSLD_MARK, PORT18_FN1), + PINMUX_DATA(FSIASPDIF_PORT18_MARK, PORT18_FN2, MSEL5CR_4_1), + + /* Port19 */ + PINMUX_DATA(FMSICK_MARK, PORT19_FN1), + PINMUX_DATA(CS5A_PORT19_MARK, PORT19_FN7, MSEL5CR_2_1), + PINMUX_DATA(IRQ10_MARK, PORT19_FN0), + + /* Port20 */ + PINMUX_DATA(FMSOCK_MARK, PORT20_FN1), + PINMUX_DATA(SCIFA5_TXD_PORT20_MARK, PORT20_FN3, MSEL5CR_15_0, + MSEL5CR_14_0), + PINMUX_DATA(IRQ1_MARK, PORT20_FN0), + + /* Port21 */ + PINMUX_DATA(SCIFA1_CTS_MARK, PORT21_FN1), + PINMUX_DATA(SCIFA4_SCK_PORT21_MARK, PORT21_FN2, MSEL5CR_10_0), + PINMUX_DATA(TPU0TO1_MARK, PORT21_FN4), + PINMUX_DATA(VIO1_FIELD_MARK, PORT21_FN5), + PINMUX_DATA(STP0_IPD5_MARK, PORT21_FN6), + PINMUX_DATA(LCD1_D10_MARK, PORT21_FN7), + + /* Port22 */ + PINMUX_DATA(SCIFA2_SCK_PORT22_MARK, PORT22_FN1, MSEL5CR_7_0), + PINMUX_DATA(SIM_D_PORT22_MARK, PORT22_FN4, MSEL5CR_21_0), + PINMUX_DATA(VIO0_D13_PORT22_MARK, PORT22_FN7, MSEL5CR_27_1), + + /* Port23 */ + PINMUX_DATA(SCIFA1_RTS_MARK, PORT23_FN1), + PINMUX_DATA(SCIFA5_SCK_PORT23_MARK, PORT23_FN3, MSEL5CR_13_0), + PINMUX_DATA(TPU0TO0_MARK, PORT23_FN4), + PINMUX_DATA(VIO_CKO_1_MARK, PORT23_FN5), + PINMUX_DATA(STP0_IPD2_MARK, PORT23_FN6), + PINMUX_DATA(LCD1_D7_MARK, PORT23_FN7), + + /* Port24 */ + PINMUX_DATA(VIO0_D15_PORT24_MARK, PORT24_FN1, MSEL5CR_27_0), + PINMUX_DATA(VIO1_D7_MARK, PORT24_FN5), + PINMUX_DATA(SCIFA6_SCK_MARK, PORT24_FN6), + PINMUX_DATA(SDHI2_CD_PORT24_MARK, PORT24_FN7, MSEL5CR_19_0), + + /* Port25 */ + PINMUX_DATA(VIO0_D14_PORT25_MARK, PORT25_FN1, MSEL5CR_27_0), + PINMUX_DATA(VIO1_D6_MARK, PORT25_FN5), + PINMUX_DATA(SCIFA6_RXD_MARK, PORT25_FN6), + PINMUX_DATA(SDHI2_WP_PORT25_MARK, PORT25_FN7, MSEL5CR_19_0), + + /* Port26 */ + PINMUX_DATA(VIO0_D13_PORT26_MARK, PORT26_FN1, MSEL5CR_27_0), + PINMUX_DATA(VIO1_D5_MARK, PORT26_FN5), + PINMUX_DATA(SCIFA6_TXD_MARK, PORT26_FN6), + + /* Port27 - Port39 Function */ + PINMUX_DATA(VIO0_D7_MARK, PORT27_FN1), + PINMUX_DATA(VIO0_D6_MARK, PORT28_FN1), + PINMUX_DATA(VIO0_D5_MARK, PORT29_FN1), + PINMUX_DATA(VIO0_D4_MARK, PORT30_FN1), + PINMUX_DATA(VIO0_D3_MARK, PORT31_FN1), + PINMUX_DATA(VIO0_D2_MARK, PORT32_FN1), + PINMUX_DATA(VIO0_D1_MARK, PORT33_FN1), + PINMUX_DATA(VIO0_D0_MARK, PORT34_FN1), + PINMUX_DATA(VIO0_CLK_MARK, PORT35_FN1), + PINMUX_DATA(VIO_CKO_MARK, PORT36_FN1), + PINMUX_DATA(VIO0_HD_MARK, PORT37_FN1), + PINMUX_DATA(VIO0_FIELD_MARK, PORT38_FN1), + PINMUX_DATA(VIO0_VD_MARK, PORT39_FN1), + + /* Port38 IRQ */ + PINMUX_DATA(IRQ25_MARK, PORT38_FN0), + + /* Port40 */ + PINMUX_DATA(LCD0_D18_PORT40_MARK, PORT40_FN4, MSEL5CR_6_0), + PINMUX_DATA(RSPI_CK_A_MARK, PORT40_FN6), + PINMUX_DATA(LCD1_LCLK_MARK, PORT40_FN7), + + /* Port41 */ + PINMUX_DATA(LCD0_D17_MARK, PORT41_FN1), + PINMUX_DATA(MSIOF2_SS1_MARK, PORT41_FN2), + PINMUX_DATA(IRQ31_PORT41_MARK, PORT41_FN0, MSEL1CR_31_1), + + /* Port42 */ + PINMUX_DATA(LCD0_D16_MARK, PORT42_FN1), + PINMUX_DATA(MSIOF2_MCK1_MARK, PORT42_FN2), + PINMUX_DATA(IRQ12_PORT42_MARK, PORT42_FN0, MSEL1CR_12_1), + + /* Port43 */ + PINMUX_DATA(LCD0_D15_MARK, PORT43_FN1), + PINMUX_DATA(MSIOF2_MCK0_MARK, PORT43_FN2), + PINMUX_DATA(KEYIN0_PORT43_MARK, PORT43_FN3, MSEL4CR_18_0), + PINMUX_DATA(DV_D15_MARK, PORT43_FN6), + + /* Port44 */ + PINMUX_DATA(LCD0_D14_MARK, PORT44_FN1), + PINMUX_DATA(MSIOF2_RSYNC_MARK, PORT44_FN2), + PINMUX_DATA(KEYIN1_PORT44_MARK, PORT44_FN3, MSEL4CR_18_0), + PINMUX_DATA(DV_D14_MARK, PORT44_FN6), + + /* Port45 */ + PINMUX_DATA(LCD0_D13_MARK, PORT45_FN1), + PINMUX_DATA(MSIOF2_RSCK_MARK, PORT45_FN2), + PINMUX_DATA(KEYIN2_PORT45_MARK, PORT45_FN3, MSEL4CR_18_0), + PINMUX_DATA(DV_D13_MARK, PORT45_FN6), + + /* Port46 */ + PINMUX_DATA(LCD0_D12_MARK, PORT46_FN1), + PINMUX_DATA(KEYIN3_PORT46_MARK, PORT46_FN3, MSEL4CR_18_0), + PINMUX_DATA(DV_D12_MARK, PORT46_FN6), + + /* Port47 */ + PINMUX_DATA(LCD0_D11_MARK, PORT47_FN1), + PINMUX_DATA(KEYIN4_MARK, PORT47_FN3), + PINMUX_DATA(DV_D11_MARK, PORT47_FN6), + + /* Port48 */ + PINMUX_DATA(LCD0_D10_MARK, PORT48_FN1), + PINMUX_DATA(KEYIN5_MARK, PORT48_FN3), + PINMUX_DATA(DV_D10_MARK, PORT48_FN6), + + /* Port49 */ + PINMUX_DATA(LCD0_D9_MARK, PORT49_FN1), + PINMUX_DATA(KEYIN6_MARK, PORT49_FN3), + PINMUX_DATA(DV_D9_MARK, PORT49_FN6), + PINMUX_DATA(IRQ30_PORT49_MARK, PORT49_FN0, MSEL1CR_30_1), + + /* Port50 */ + PINMUX_DATA(LCD0_D8_MARK, PORT50_FN1), + PINMUX_DATA(KEYIN7_MARK, PORT50_FN3), + PINMUX_DATA(DV_D8_MARK, PORT50_FN6), + PINMUX_DATA(IRQ29_PORT50_MARK, PORT50_FN0, MSEL1CR_29_1), + + /* Port51 */ + PINMUX_DATA(LCD0_D7_MARK, PORT51_FN1), + PINMUX_DATA(KEYOUT0_MARK, PORT51_FN3), + PINMUX_DATA(DV_D7_MARK, PORT51_FN6), + + /* Port52 */ + PINMUX_DATA(LCD0_D6_MARK, PORT52_FN1), + PINMUX_DATA(KEYOUT1_MARK, PORT52_FN3), + PINMUX_DATA(DV_D6_MARK, PORT52_FN6), + + /* Port53 */ + PINMUX_DATA(LCD0_D5_MARK, PORT53_FN1), + PINMUX_DATA(KEYOUT2_MARK, PORT53_FN3), + PINMUX_DATA(DV_D5_MARK, PORT53_FN6), + + /* Port54 */ + PINMUX_DATA(LCD0_D4_MARK, PORT54_FN1), + PINMUX_DATA(KEYOUT3_MARK, PORT54_FN3), + PINMUX_DATA(DV_D4_MARK, PORT54_FN6), + + /* Port55 */ + PINMUX_DATA(LCD0_D3_MARK, PORT55_FN1), + PINMUX_DATA(KEYOUT4_MARK, PORT55_FN3), + PINMUX_DATA(KEYIN3_PORT55_MARK, PORT55_FN4, MSEL4CR_18_1), + PINMUX_DATA(DV_D3_MARK, PORT55_FN6), + + /* Port56 */ + PINMUX_DATA(LCD0_D2_MARK, PORT56_FN1), + PINMUX_DATA(KEYOUT5_MARK, PORT56_FN3), + PINMUX_DATA(KEYIN2_PORT56_MARK, PORT56_FN4, MSEL4CR_18_1), + PINMUX_DATA(DV_D2_MARK, PORT56_FN6), + PINMUX_DATA(IRQ28_PORT56_MARK, PORT56_FN0, MSEL1CR_28_1), + + /* Port57 */ + PINMUX_DATA(LCD0_D1_MARK, PORT57_FN1), + PINMUX_DATA(KEYOUT6_MARK, PORT57_FN3), + PINMUX_DATA(KEYIN1_PORT57_MARK, PORT57_FN4, MSEL4CR_18_1), + PINMUX_DATA(DV_D1_MARK, PORT57_FN6), + PINMUX_DATA(IRQ27_PORT57_MARK, PORT57_FN0, MSEL1CR_27_1), + + /* Port58 */ + PINMUX_DATA(LCD0_D0_MARK, PORT58_FN1), + PINMUX_DATA(KEYOUT7_MARK, PORT58_FN3), + PINMUX_DATA(KEYIN0_PORT58_MARK, PORT58_FN4, MSEL4CR_18_1), + PINMUX_DATA(DV_D0_MARK, PORT58_FN6), + PINMUX_DATA(IRQ26_PORT58_MARK, PORT58_FN0, MSEL1CR_26_1), + + /* Port59 */ + PINMUX_DATA(LCD0_VCPWC_MARK, PORT59_FN1), + PINMUX_DATA(BBIF2_TSCK2_PORT59_MARK, PORT59_FN2, MSEL5CR_0_0), + PINMUX_DATA(RSPI_MOSI_A_MARK, PORT59_FN6), + + /* Port60 */ + PINMUX_DATA(LCD0_VEPWC_MARK, PORT60_FN1), + PINMUX_DATA(BBIF2_RXD2_PORT60_MARK, PORT60_FN2, MSEL5CR_0_0), + PINMUX_DATA(RSPI_MISO_A_MARK, PORT60_FN6), + + /* Port61 */ + PINMUX_DATA(LCD0_DON_MARK, PORT61_FN1), + PINMUX_DATA(MSIOF2_TXD_MARK, PORT61_FN2), + + /* Port62 */ + PINMUX_DATA(LCD0_DCK_MARK, PORT62_FN1), + PINMUX_DATA(LCD0_WR_MARK, PORT62_FN4), + PINMUX_DATA(DV_CLK_MARK, PORT62_FN6), + PINMUX_DATA(IRQ15_PORT62_MARK, PORT62_FN0, MSEL1CR_15_1), + + /* Port63 */ + PINMUX_DATA(LCD0_VSYN_MARK, PORT63_FN1), + PINMUX_DATA(DV_VSYNC_MARK, PORT63_FN6), + PINMUX_DATA(IRQ14_PORT63_MARK, PORT63_FN0, MSEL1CR_14_1), + + /* Port64 */ + PINMUX_DATA(LCD0_HSYN_MARK, PORT64_FN1), + PINMUX_DATA(LCD0_CS_MARK, PORT64_FN4), + PINMUX_DATA(DV_HSYNC_MARK, PORT64_FN6), + PINMUX_DATA(IRQ13_PORT64_MARK, PORT64_FN0, MSEL1CR_13_1), + + /* Port65 */ + PINMUX_DATA(LCD0_DISP_MARK, PORT65_FN1), + PINMUX_DATA(MSIOF2_TSCK_MARK, PORT65_FN2), + PINMUX_DATA(LCD0_RS_MARK, PORT65_FN4), + + /* Port66 */ + PINMUX_DATA(MEMC_INT_MARK, PORT66_FN1), + PINMUX_DATA(TPU0TO2_PORT66_MARK, PORT66_FN3, MSEL5CR_25_0), + PINMUX_DATA(MMC0_CLK_PORT66_MARK, PORT66_FN4, MSEL4CR_15_0), + PINMUX_DATA(SDHI1_CLK_MARK, PORT66_FN6), + + /* Port67 - Port73 Function1 */ + PINMUX_DATA(MEMC_CS0_MARK, PORT67_FN1), + PINMUX_DATA(MEMC_AD8_MARK, PORT68_FN1), + PINMUX_DATA(MEMC_AD9_MARK, PORT69_FN1), + PINMUX_DATA(MEMC_AD10_MARK, PORT70_FN1), + PINMUX_DATA(MEMC_AD11_MARK, PORT71_FN1), + PINMUX_DATA(MEMC_AD12_MARK, PORT72_FN1), + PINMUX_DATA(MEMC_AD13_MARK, PORT73_FN1), + + /* Port67 - Port73 Function2 */ + PINMUX_DATA(MSIOF1_SS1_PORT67_MARK, PORT67_FN2, MSEL4CR_10_1), + PINMUX_DATA(MSIOF1_RSCK_MARK, PORT68_FN2), + PINMUX_DATA(MSIOF1_RSYNC_MARK, PORT69_FN2), + PINMUX_DATA(MSIOF1_MCK0_MARK, PORT70_FN2), + PINMUX_DATA(MSIOF1_MCK1_MARK, PORT71_FN2), + PINMUX_DATA(MSIOF1_TSCK_PORT72_MARK, PORT72_FN2, MSEL4CR_10_1), + PINMUX_DATA(MSIOF1_TSYNC_PORT73_MARK, PORT73_FN2, MSEL4CR_10_1), + + /* Port67 - Port73 Function4 */ + PINMUX_DATA(MMC0_CMD_PORT67_MARK, PORT67_FN4, MSEL4CR_15_0), + PINMUX_DATA(MMC0_D0_PORT68_MARK, PORT68_FN4, MSEL4CR_15_0), + PINMUX_DATA(MMC0_D1_PORT69_MARK, PORT69_FN4, MSEL4CR_15_0), + PINMUX_DATA(MMC0_D2_PORT70_MARK, PORT70_FN4, MSEL4CR_15_0), + PINMUX_DATA(MMC0_D3_PORT71_MARK, PORT71_FN4, MSEL4CR_15_0), + PINMUX_DATA(MMC0_D4_PORT72_MARK, PORT72_FN4, MSEL4CR_15_0), + PINMUX_DATA(MMC0_D5_PORT73_MARK, PORT73_FN4, MSEL4CR_15_0), + + /* Port67 - Port73 Function6 */ + PINMUX_DATA(SDHI1_CMD_MARK, PORT67_FN6), + PINMUX_DATA(SDHI1_D0_MARK, PORT68_FN6), + PINMUX_DATA(SDHI1_D1_MARK, PORT69_FN6), + PINMUX_DATA(SDHI1_D2_MARK, PORT70_FN6), + PINMUX_DATA(SDHI1_D3_MARK, PORT71_FN6), + PINMUX_DATA(SDHI1_CD_MARK, PORT72_FN6), + PINMUX_DATA(SDHI1_WP_MARK, PORT73_FN6), + + /* Port67 - Port71 IRQ */ + PINMUX_DATA(IRQ20_MARK, PORT67_FN0), + PINMUX_DATA(IRQ16_PORT68_MARK, PORT68_FN0, MSEL1CR_16_0), + PINMUX_DATA(IRQ17_MARK, PORT69_FN0), + PINMUX_DATA(IRQ18_MARK, PORT70_FN0), + PINMUX_DATA(IRQ19_MARK, PORT71_FN0), + + /* Port74 */ + PINMUX_DATA(MEMC_AD14_MARK, PORT74_FN1), + PINMUX_DATA(MSIOF1_TXD_PORT74_MARK, PORT74_FN2, MSEL4CR_10_1), + PINMUX_DATA(MMC0_D6_PORT74_MARK, PORT74_FN4, MSEL4CR_15_0), + PINMUX_DATA(STP1_IPD7_MARK, PORT74_FN6), + PINMUX_DATA(LCD1_D21_MARK, PORT74_FN7), + + /* Port75 */ + PINMUX_DATA(MEMC_AD15_MARK, PORT75_FN1), + PINMUX_DATA(MSIOF1_RXD_PORT75_MARK, PORT75_FN2, MSEL4CR_10_1), + PINMUX_DATA(MMC0_D7_PORT75_MARK, PORT75_FN4, MSEL4CR_15_0), + PINMUX_DATA(STP1_IPD6_MARK, PORT75_FN6), + PINMUX_DATA(LCD1_D20_MARK, PORT75_FN7), + + /* Port76 - Port80 Function */ + PINMUX_DATA(SDHI0_CMD_MARK, PORT76_FN1), + PINMUX_DATA(SDHI0_D0_MARK, PORT77_FN1), + PINMUX_DATA(SDHI0_D1_MARK, PORT78_FN1), + PINMUX_DATA(SDHI0_D2_MARK, PORT79_FN1), + PINMUX_DATA(SDHI0_D3_MARK, PORT80_FN1), + + /* Port81 */ + PINMUX_DATA(SDHI0_CD_MARK, PORT81_FN1), + PINMUX_DATA(IRQ26_PORT81_MARK, PORT81_FN0, MSEL1CR_26_0), + + /* Port82 - Port88 Function */ + PINMUX_DATA(SDHI0_CLK_MARK, PORT82_FN1), + PINMUX_DATA(SDHI0_WP_MARK, PORT83_FN1), + PINMUX_DATA(RESETOUTS_MARK, PORT84_FN1), + PINMUX_DATA(USB0_PPON_MARK, PORT85_FN1), + PINMUX_DATA(USB0_OCI_MARK, PORT86_FN1), + PINMUX_DATA(USB1_PPON_MARK, PORT87_FN1), + PINMUX_DATA(USB1_OCI_MARK, PORT88_FN1), + + /* Port89 */ + PINMUX_DATA(DREQ0_MARK, PORT89_FN1), + PINMUX_DATA(BBIF2_TSCK2_PORT89_MARK, PORT89_FN2, MSEL5CR_0_1), + PINMUX_DATA(RSPI_SSL3_A_MARK, PORT89_FN6), + + /* Port90 */ + PINMUX_DATA(DACK0_MARK, PORT90_FN1), + PINMUX_DATA(BBIF2_RXD2_PORT90_MARK, PORT90_FN2, MSEL5CR_0_1), + PINMUX_DATA(RSPI_SSL2_A_MARK, PORT90_FN6), + PINMUX_DATA(WAIT_PORT90_MARK, PORT90_FN7, MSEL5CR_2_1), + + /* Port91 */ + PINMUX_DATA(MEMC_AD0_MARK, PORT91_FN1), + PINMUX_DATA(BBIF1_RXD_MARK, PORT91_FN2), + PINMUX_DATA(SCIFA5_TXD_PORT91_MARK, PORT91_FN3, MSEL5CR_15_1, + MSEL5CR_14_0), + PINMUX_DATA(LCD1_D5_MARK, PORT91_FN7), + + /* Port92 */ + PINMUX_DATA(MEMC_AD1_MARK, PORT92_FN1), + PINMUX_DATA(BBIF1_TSYNC_MARK, PORT92_FN2), + PINMUX_DATA(SCIFA5_RXD_PORT92_MARK, PORT92_FN3, MSEL5CR_15_1, + MSEL5CR_14_0), + PINMUX_DATA(STP0_IPD1_MARK, PORT92_FN6), + PINMUX_DATA(LCD1_D6_MARK, PORT92_FN7), + + /* Port93 */ + PINMUX_DATA(MEMC_AD2_MARK, PORT93_FN1), + PINMUX_DATA(BBIF1_TSCK_MARK, PORT93_FN2), + PINMUX_DATA(SCIFA4_TXD_PORT93_MARK, PORT93_FN3, MSEL5CR_12_1, + MSEL5CR_11_0), + PINMUX_DATA(STP0_IPD3_MARK, PORT93_FN6), + PINMUX_DATA(LCD1_D8_MARK, PORT93_FN7), + + /* Port94 */ + PINMUX_DATA(MEMC_AD3_MARK, PORT94_FN1), + PINMUX_DATA(BBIF1_TXD_MARK, PORT94_FN2), + PINMUX_DATA(SCIFA4_RXD_PORT94_MARK, PORT94_FN3, MSEL5CR_12_1, + MSEL5CR_11_0), + PINMUX_DATA(STP0_IPD4_MARK, PORT94_FN6), + PINMUX_DATA(LCD1_D9_MARK, PORT94_FN7), + + /* Port95 */ + PINMUX_DATA(MEMC_CS1_MARK, PORT95_FN1, MSEL4CR_6_0), + PINMUX_DATA(MEMC_A1_MARK, PORT95_FN1, MSEL4CR_6_1), + + PINMUX_DATA(SCIFA2_CTS_MARK, PORT95_FN2), + PINMUX_DATA(SIM_RST_MARK, PORT95_FN4), + PINMUX_DATA(VIO0_D14_PORT95_MARK, PORT95_FN7, MSEL5CR_27_1), + PINMUX_DATA(IRQ22_MARK, PORT95_FN0), + + /* Port96 */ + PINMUX_DATA(MEMC_ADV_MARK, PORT96_FN1, MSEL4CR_6_0), + PINMUX_DATA(MEMC_DREQ0_MARK, PORT96_FN1, MSEL4CR_6_1), + + PINMUX_DATA(SCIFA2_RTS_MARK, PORT96_FN2), + PINMUX_DATA(SIM_CLK_MARK, PORT96_FN4), + PINMUX_DATA(VIO0_D15_PORT96_MARK, PORT96_FN7, MSEL5CR_27_1), + PINMUX_DATA(IRQ23_MARK, PORT96_FN0), + + /* Port97 */ + PINMUX_DATA(MEMC_AD4_MARK, PORT97_FN1), + PINMUX_DATA(BBIF1_RSCK_MARK, PORT97_FN2), + PINMUX_DATA(LCD1_CS_MARK, PORT97_FN6), + PINMUX_DATA(LCD1_HSYN_MARK, PORT97_FN7), + PINMUX_DATA(IRQ12_PORT97_MARK, PORT97_FN0, MSEL1CR_12_0), + + /* Port98 */ + PINMUX_DATA(MEMC_AD5_MARK, PORT98_FN1), + PINMUX_DATA(BBIF1_RSYNC_MARK, PORT98_FN2), + PINMUX_DATA(LCD1_VSYN_MARK, PORT98_FN7), + PINMUX_DATA(IRQ13_PORT98_MARK, PORT98_FN0, MSEL1CR_13_0), + + /* Port99 */ + PINMUX_DATA(MEMC_AD6_MARK, PORT99_FN1), + PINMUX_DATA(BBIF1_FLOW_MARK, PORT99_FN2), + PINMUX_DATA(LCD1_WR_MARK, PORT99_FN6), + PINMUX_DATA(LCD1_DCK_MARK, PORT99_FN7), + PINMUX_DATA(IRQ14_PORT99_MARK, PORT99_FN0, MSEL1CR_14_0), + + /* Port100 */ + PINMUX_DATA(MEMC_AD7_MARK, PORT100_FN1), + PINMUX_DATA(BBIF1_RX_FLOW_N_MARK, PORT100_FN2), + PINMUX_DATA(LCD1_DON_MARK, PORT100_FN7), + PINMUX_DATA(IRQ15_PORT100_MARK, PORT100_FN0, MSEL1CR_15_0), + + /* Port101 */ + PINMUX_DATA(FCE0_MARK, PORT101_FN1), + + /* Port102 */ + PINMUX_DATA(FRB_MARK, PORT102_FN1), + PINMUX_DATA(LCD0_LCLK_PORT102_MARK, PORT102_FN4, MSEL5CR_6_0), + + /* Port103 */ + PINMUX_DATA(CS5B_MARK, PORT103_FN1), + PINMUX_DATA(FCE1_MARK, PORT103_FN2), + PINMUX_DATA(MMC1_CLK_PORT103_MARK, PORT103_FN3, MSEL4CR_15_1), + + /* Port104 */ + PINMUX_DATA(CS6A_MARK, PORT104_FN1), + PINMUX_DATA(MMC1_CMD_PORT104_MARK, PORT104_FN3, MSEL4CR_15_1), + PINMUX_DATA(IRQ11_MARK, PORT104_FN0), + + /* Port105 */ + PINMUX_DATA(CS5A_PORT105_MARK, PORT105_FN1, MSEL5CR_2_0), + PINMUX_DATA(SCIFA3_RTS_PORT105_MARK, PORT105_FN4, MSEL5CR_8_0), + + /* Port106 */ + PINMUX_DATA(IOIS16_MARK, PORT106_FN1), + PINMUX_DATA(IDE_EXBUF_ENB_MARK, PORT106_FN6), + + /* Port107 - Port115 Function */ + PINMUX_DATA(WE3_ICIOWR_MARK, PORT107_FN1), + PINMUX_DATA(WE2_ICIORD_MARK, PORT108_FN1), + PINMUX_DATA(CS0_MARK, PORT109_FN1), + PINMUX_DATA(CS2_MARK, PORT110_FN1), + PINMUX_DATA(CS4_MARK, PORT111_FN1), + PINMUX_DATA(WE1_MARK, PORT112_FN1), + PINMUX_DATA(WE0_FWE_MARK, PORT113_FN1), + PINMUX_DATA(RDWR_MARK, PORT114_FN1), + PINMUX_DATA(RD_FSC_MARK, PORT115_FN1), + + /* Port116 */ + PINMUX_DATA(A25_MARK, PORT116_FN1), + PINMUX_DATA(MSIOF0_SS2_MARK, PORT116_FN2), + PINMUX_DATA(MSIOF1_SS2_PORT116_MARK, PORT116_FN3, MSEL4CR_10_0), + PINMUX_DATA(SCIFA3_SCK_PORT116_MARK, PORT116_FN4, MSEL5CR_8_0), + PINMUX_DATA(GPO1_MARK, PORT116_FN5), + + /* Port117 */ + PINMUX_DATA(A24_MARK, PORT117_FN1), + PINMUX_DATA(MSIOF0_SS1_MARK, PORT117_FN2), + PINMUX_DATA(MSIOF1_SS1_PORT117_MARK, PORT117_FN3, MSEL4CR_10_0), + PINMUX_DATA(SCIFA3_CTS_PORT117_MARK, PORT117_FN4, MSEL5CR_8_0), + PINMUX_DATA(GPO0_MARK, PORT117_FN5), + + /* Port118 */ + PINMUX_DATA(A23_MARK, PORT118_FN1), + PINMUX_DATA(MSIOF0_MCK1_MARK, PORT118_FN2), + PINMUX_DATA(MSIOF1_RXD_PORT118_MARK, PORT118_FN3, MSEL4CR_10_0), + PINMUX_DATA(GPI1_MARK, PORT118_FN5), + PINMUX_DATA(IRQ9_PORT118_MARK, PORT118_FN0, MSEL1CR_9_0), + + /* Port119 */ + PINMUX_DATA(A22_MARK, PORT119_FN1), + PINMUX_DATA(MSIOF0_MCK0_MARK, PORT119_FN2), + PINMUX_DATA(MSIOF1_TXD_PORT119_MARK, PORT119_FN3, MSEL4CR_10_0), + PINMUX_DATA(GPI0_MARK, PORT119_FN5), + PINMUX_DATA(IRQ8_MARK, PORT119_FN0), + + /* Port120 */ + PINMUX_DATA(A21_MARK, PORT120_FN1), + PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT120_FN2), + PINMUX_DATA(MSIOF1_TSYNC_PORT120_MARK, PORT120_FN3, MSEL4CR_10_0), + PINMUX_DATA(IRQ7_PORT120_MARK, PORT120_FN0, MSEL1CR_7_0), + + /* Port121 */ + PINMUX_DATA(A20_MARK, PORT121_FN1), + PINMUX_DATA(MSIOF0_RSCK_MARK, PORT121_FN2), + PINMUX_DATA(MSIOF1_TSCK_PORT121_MARK, PORT121_FN3, MSEL4CR_10_0), + PINMUX_DATA(IRQ6_PORT121_MARK, PORT121_FN0, MSEL1CR_6_0), + + /* Port122 */ + PINMUX_DATA(A19_MARK, PORT122_FN1), + PINMUX_DATA(MSIOF0_RXD_MARK, PORT122_FN2), + + /* Port123 */ + PINMUX_DATA(A18_MARK, PORT123_FN1), + PINMUX_DATA(MSIOF0_TSCK_MARK, PORT123_FN2), + + /* Port124 */ + PINMUX_DATA(A17_MARK, PORT124_FN1), + PINMUX_DATA(MSIOF0_TSYNC_MARK, PORT124_FN2), + + /* Port125 - Port141 Function */ + PINMUX_DATA(A16_MARK, PORT125_FN1), + PINMUX_DATA(A15_MARK, PORT126_FN1), + PINMUX_DATA(A14_MARK, PORT127_FN1), + PINMUX_DATA(A13_MARK, PORT128_FN1), + PINMUX_DATA(A12_MARK, PORT129_FN1), + PINMUX_DATA(A11_MARK, PORT130_FN1), + PINMUX_DATA(A10_MARK, PORT131_FN1), + PINMUX_DATA(A9_MARK, PORT132_FN1), + PINMUX_DATA(A8_MARK, PORT133_FN1), + PINMUX_DATA(A7_MARK, PORT134_FN1), + PINMUX_DATA(A6_MARK, PORT135_FN1), + PINMUX_DATA(A5_FCDE_MARK, PORT136_FN1), + PINMUX_DATA(A4_FOE_MARK, PORT137_FN1), + PINMUX_DATA(A3_MARK, PORT138_FN1), + PINMUX_DATA(A2_MARK, PORT139_FN1), + PINMUX_DATA(A1_MARK, PORT140_FN1), + PINMUX_DATA(CKO_MARK, PORT141_FN1), + + /* Port142 - Port157 Function1 */ + PINMUX_DATA(D15_NAF15_MARK, PORT142_FN1), + PINMUX_DATA(D14_NAF14_MARK, PORT143_FN1), + PINMUX_DATA(D13_NAF13_MARK, PORT144_FN1), + PINMUX_DATA(D12_NAF12_MARK, PORT145_FN1), + PINMUX_DATA(D11_NAF11_MARK, PORT146_FN1), + PINMUX_DATA(D10_NAF10_MARK, PORT147_FN1), + PINMUX_DATA(D9_NAF9_MARK, PORT148_FN1), + PINMUX_DATA(D8_NAF8_MARK, PORT149_FN1), + PINMUX_DATA(D7_NAF7_MARK, PORT150_FN1), + PINMUX_DATA(D6_NAF6_MARK, PORT151_FN1), + PINMUX_DATA(D5_NAF5_MARK, PORT152_FN1), + PINMUX_DATA(D4_NAF4_MARK, PORT153_FN1), + PINMUX_DATA(D3_NAF3_MARK, PORT154_FN1), + PINMUX_DATA(D2_NAF2_MARK, PORT155_FN1), + PINMUX_DATA(D1_NAF1_MARK, PORT156_FN1), + PINMUX_DATA(D0_NAF0_MARK, PORT157_FN1), + + /* Port142 - Port149 Function3 */ + PINMUX_DATA(MMC1_D7_PORT142_MARK, PORT142_FN3, MSEL4CR_15_1), + PINMUX_DATA(MMC1_D6_PORT143_MARK, PORT143_FN3, MSEL4CR_15_1), + PINMUX_DATA(MMC1_D5_PORT144_MARK, PORT144_FN3, MSEL4CR_15_1), + PINMUX_DATA(MMC1_D4_PORT145_MARK, PORT145_FN3, MSEL4CR_15_1), + PINMUX_DATA(MMC1_D3_PORT146_MARK, PORT146_FN3, MSEL4CR_15_1), + PINMUX_DATA(MMC1_D2_PORT147_MARK, PORT147_FN3, MSEL4CR_15_1), + PINMUX_DATA(MMC1_D1_PORT148_MARK, PORT148_FN3, MSEL4CR_15_1), + PINMUX_DATA(MMC1_D0_PORT149_MARK, PORT149_FN3, MSEL4CR_15_1), + + /* Port158 */ + PINMUX_DATA(D31_MARK, PORT158_FN1), + PINMUX_DATA(SCIFA3_SCK_PORT158_MARK, PORT158_FN2, MSEL5CR_8_1), + PINMUX_DATA(RMII_REF125CK_MARK, PORT158_FN3), + PINMUX_DATA(LCD0_D21_PORT158_MARK, PORT158_FN4, MSEL5CR_6_1), + PINMUX_DATA(IRDA_FIRSEL_MARK, PORT158_FN5), + PINMUX_DATA(IDE_D15_MARK, PORT158_FN6), + + /* Port159 */ + PINMUX_DATA(D30_MARK, PORT159_FN1), + PINMUX_DATA(SCIFA3_RXD_PORT159_MARK, PORT159_FN2, MSEL5CR_8_1), + PINMUX_DATA(RMII_REF50CK_MARK, PORT159_FN3), + PINMUX_DATA(LCD0_D23_PORT159_MARK, PORT159_FN4, MSEL5CR_6_1), + PINMUX_DATA(IDE_D14_MARK, PORT159_FN6), + + /* Port160 */ + PINMUX_DATA(D29_MARK, PORT160_FN1), + PINMUX_DATA(SCIFA3_TXD_PORT160_MARK, PORT160_FN2, MSEL5CR_8_1), + PINMUX_DATA(LCD0_D22_PORT160_MARK, PORT160_FN4, MSEL5CR_6_1), + PINMUX_DATA(VIO1_HD_MARK, PORT160_FN5), + PINMUX_DATA(IDE_D13_MARK, PORT160_FN6), + + /* Port161 */ + PINMUX_DATA(D28_MARK, PORT161_FN1), + PINMUX_DATA(SCIFA3_RTS_PORT161_MARK, PORT161_FN2, MSEL5CR_8_1), + PINMUX_DATA(ET_RX_DV_MARK, PORT161_FN3), + PINMUX_DATA(LCD0_D20_PORT161_MARK, PORT161_FN4, MSEL5CR_6_1), + PINMUX_DATA(IRDA_IN_MARK, PORT161_FN5), + PINMUX_DATA(IDE_D12_MARK, PORT161_FN6), + + /* Port162 */ + PINMUX_DATA(D27_MARK, PORT162_FN1), + PINMUX_DATA(SCIFA3_CTS_PORT162_MARK, PORT162_FN2, MSEL5CR_8_1), + PINMUX_DATA(LCD0_D19_PORT162_MARK, PORT162_FN4, MSEL5CR_6_1), + PINMUX_DATA(IRDA_OUT_MARK, PORT162_FN5), + PINMUX_DATA(IDE_D11_MARK, PORT162_FN6), + + /* Port163 */ + PINMUX_DATA(D26_MARK, PORT163_FN1), + PINMUX_DATA(MSIOF2_SS2_MARK, PORT163_FN2), + PINMUX_DATA(ET_COL_MARK, PORT163_FN3), + PINMUX_DATA(LCD0_D18_PORT163_MARK, PORT163_FN4, MSEL5CR_6_1), + PINMUX_DATA(IROUT_MARK, PORT163_FN5), + PINMUX_DATA(IDE_D10_MARK, PORT163_FN6), + + /* Port164 */ + PINMUX_DATA(D25_MARK, PORT164_FN1), + PINMUX_DATA(MSIOF2_TSYNC_MARK, PORT164_FN2), + PINMUX_DATA(ET_PHY_INT_MARK, PORT164_FN3), + PINMUX_DATA(LCD0_RD_MARK, PORT164_FN4), + PINMUX_DATA(IDE_D9_MARK, PORT164_FN6), + + /* Port165 */ + PINMUX_DATA(D24_MARK, PORT165_FN1), + PINMUX_DATA(MSIOF2_RXD_MARK, PORT165_FN2), + PINMUX_DATA(LCD0_LCLK_PORT165_MARK, PORT165_FN4, MSEL5CR_6_1), + PINMUX_DATA(IDE_D8_MARK, PORT165_FN6), + + /* Port166 - Port171 Function1 */ + PINMUX_DATA(D21_MARK, PORT166_FN1), + PINMUX_DATA(D20_MARK, PORT167_FN1), + PINMUX_DATA(D19_MARK, PORT168_FN1), + PINMUX_DATA(D18_MARK, PORT169_FN1), + PINMUX_DATA(D17_MARK, PORT170_FN1), + PINMUX_DATA(D16_MARK, PORT171_FN1), + + /* Port166 - Port171 Function3 */ + PINMUX_DATA(ET_ETXD5_MARK, PORT166_FN3), + PINMUX_DATA(ET_ETXD4_MARK, PORT167_FN3), + PINMUX_DATA(ET_ETXD3_MARK, PORT168_FN3), + PINMUX_DATA(ET_ETXD2_MARK, PORT169_FN3), + PINMUX_DATA(ET_ETXD1_MARK, PORT170_FN3), + PINMUX_DATA(ET_ETXD0_MARK, PORT171_FN3), + + /* Port166 - Port171 Function6 */ + PINMUX_DATA(IDE_D5_MARK, PORT166_FN6), + PINMUX_DATA(IDE_D4_MARK, PORT167_FN6), + PINMUX_DATA(IDE_D3_MARK, PORT168_FN6), + PINMUX_DATA(IDE_D2_MARK, PORT169_FN6), + PINMUX_DATA(IDE_D1_MARK, PORT170_FN6), + PINMUX_DATA(IDE_D0_MARK, PORT171_FN6), + + /* Port167 - Port171 IRQ */ + PINMUX_DATA(IRQ31_PORT167_MARK, PORT167_FN0, MSEL1CR_31_0), + PINMUX_DATA(IRQ27_PORT168_MARK, PORT168_FN0, MSEL1CR_27_0), + PINMUX_DATA(IRQ28_PORT169_MARK, PORT169_FN0, MSEL1CR_28_0), + PINMUX_DATA(IRQ29_PORT170_MARK, PORT170_FN0, MSEL1CR_29_0), + PINMUX_DATA(IRQ30_PORT171_MARK, PORT171_FN0, MSEL1CR_30_0), + + /* Port172 */ + PINMUX_DATA(D23_MARK, PORT172_FN1), + PINMUX_DATA(SCIFB_RTS_PORT172_MARK, PORT172_FN2, MSEL5CR_17_1), + PINMUX_DATA(ET_ETXD7_MARK, PORT172_FN3), + PINMUX_DATA(IDE_D7_MARK, PORT172_FN6), + PINMUX_DATA(IRQ4_PORT172_MARK, PORT172_FN0, MSEL1CR_4_1), + + /* Port173 */ + PINMUX_DATA(D22_MARK, PORT173_FN1), + PINMUX_DATA(SCIFB_CTS_PORT173_MARK, PORT173_FN2, MSEL5CR_17_1), + PINMUX_DATA(ET_ETXD6_MARK, PORT173_FN3), + PINMUX_DATA(IDE_D6_MARK, PORT173_FN6), + PINMUX_DATA(IRQ6_PORT173_MARK, PORT173_FN0, MSEL1CR_6_1), + + /* Port174 */ + PINMUX_DATA(A26_MARK, PORT174_FN1), + PINMUX_DATA(MSIOF0_TXD_MARK, PORT174_FN2), + PINMUX_DATA(ET_RX_CLK_MARK, PORT174_FN3), + PINMUX_DATA(SCIFA3_RXD_PORT174_MARK, PORT174_FN4, MSEL5CR_8_0), + + /* Port175 */ + PINMUX_DATA(A0_MARK, PORT175_FN1), + PINMUX_DATA(BS_MARK, PORT175_FN2), + PINMUX_DATA(ET_WOL_MARK, PORT175_FN3), + PINMUX_DATA(SCIFA3_TXD_PORT175_MARK, PORT175_FN4, MSEL5CR_8_0), + + /* Port176 */ + PINMUX_DATA(ET_GTX_CLK_MARK, PORT176_FN3), + + /* Port177 */ + PINMUX_DATA(WAIT_PORT177_MARK, PORT177_FN1, MSEL5CR_2_0), + PINMUX_DATA(ET_LINK_MARK, PORT177_FN3), + PINMUX_DATA(IDE_IOWR_MARK, PORT177_FN6), + PINMUX_DATA(SDHI2_WP_PORT177_MARK, PORT177_FN7, MSEL5CR_19_1), + + /* Port178 */ + PINMUX_DATA(VIO0_D12_MARK, PORT178_FN1), + PINMUX_DATA(VIO1_D4_MARK, PORT178_FN5), + PINMUX_DATA(IDE_IORD_MARK, PORT178_FN6), + + /* Port179 */ + PINMUX_DATA(VIO0_D11_MARK, PORT179_FN1), + PINMUX_DATA(VIO1_D3_MARK, PORT179_FN5), + PINMUX_DATA(IDE_IORDY_MARK, PORT179_FN6), + + /* Port180 */ + PINMUX_DATA(VIO0_D10_MARK, PORT180_FN1), + PINMUX_DATA(TPU0TO3_MARK, PORT180_FN4), + PINMUX_DATA(VIO1_D2_MARK, PORT180_FN5), + PINMUX_DATA(IDE_INT_MARK, PORT180_FN6), + PINMUX_DATA(IRQ24_MARK, PORT180_FN0), + + /* Port181 */ + PINMUX_DATA(VIO0_D9_MARK, PORT181_FN1), + PINMUX_DATA(VIO1_D1_MARK, PORT181_FN5), + PINMUX_DATA(IDE_RST_MARK, PORT181_FN6), + + /* Port182 */ + PINMUX_DATA(VIO0_D8_MARK, PORT182_FN1), + PINMUX_DATA(VIO1_D0_MARK, PORT182_FN5), + PINMUX_DATA(IDE_DIRECTION_MARK, PORT182_FN6), + + /* Port183 */ + PINMUX_DATA(DREQ1_MARK, PORT183_FN1), + PINMUX_DATA(BBIF2_TXD2_PORT183_MARK, PORT183_FN2, MSEL5CR_0_1), + PINMUX_DATA(ET_TX_EN_MARK, PORT183_FN3), + + /* Port184 */ + PINMUX_DATA(DACK1_MARK, PORT184_FN1), + PINMUX_DATA(BBIF2_TSYNC2_PORT184_MARK, PORT184_FN2, MSEL5CR_0_1), + PINMUX_DATA(ET_TX_CLK_MARK, PORT184_FN3), + + /* Port185 - Port192 Function1 */ + PINMUX_DATA(SCIFA1_SCK_MARK, PORT185_FN1), + PINMUX_DATA(SCIFB_RTS_PORT186_MARK, PORT186_FN1, MSEL5CR_17_0), + PINMUX_DATA(SCIFB_CTS_PORT187_MARK, PORT187_FN1, MSEL5CR_17_0), + PINMUX_DATA(SCIFA0_SCK_MARK, PORT188_FN1), + PINMUX_DATA(SCIFB_SCK_PORT190_MARK, PORT190_FN1, MSEL5CR_17_0), + PINMUX_DATA(SCIFB_RXD_PORT191_MARK, PORT191_FN1, MSEL5CR_17_0), + PINMUX_DATA(SCIFB_TXD_PORT192_MARK, PORT192_FN1, MSEL5CR_17_0), + + /* Port185 - Port192 Function3 */ + PINMUX_DATA(ET_ERXD0_MARK, PORT185_FN3), + PINMUX_DATA(ET_ERXD1_MARK, PORT186_FN3), + PINMUX_DATA(ET_ERXD2_MARK, PORT187_FN3), + PINMUX_DATA(ET_ERXD3_MARK, PORT188_FN3), + PINMUX_DATA(ET_ERXD4_MARK, PORT189_FN3), + PINMUX_DATA(ET_ERXD5_MARK, PORT190_FN3), + PINMUX_DATA(ET_ERXD6_MARK, PORT191_FN3), + PINMUX_DATA(ET_ERXD7_MARK, PORT192_FN3), + + /* Port185 - Port192 Function6 */ + PINMUX_DATA(STP1_IPCLK_MARK, PORT185_FN6), + PINMUX_DATA(STP1_IPD0_PORT186_MARK, PORT186_FN6, MSEL5CR_23_0), + PINMUX_DATA(STP1_IPEN_PORT187_MARK, PORT187_FN6, MSEL5CR_23_0), + PINMUX_DATA(STP1_IPSYNC_MARK, PORT188_FN6), + PINMUX_DATA(STP0_IPCLK_MARK, PORT189_FN6), + PINMUX_DATA(STP0_IPD0_MARK, PORT190_FN6), + PINMUX_DATA(STP0_IPEN_MARK, PORT191_FN6), + PINMUX_DATA(STP0_IPSYNC_MARK, PORT192_FN6), + + /* Port193 */ + PINMUX_DATA(SCIFA0_CTS_MARK, PORT193_FN1), + PINMUX_DATA(RMII_CRS_DV_MARK, PORT193_FN3), + PINMUX_DATA(STP1_IPEN_PORT193_MARK, PORT193_FN6, MSEL5CR_23_1), + PINMUX_DATA(LCD1_D17_MARK, PORT193_FN7), + + /* Port194 */ + PINMUX_DATA(SCIFA0_RTS_MARK, PORT194_FN1), + PINMUX_DATA(RMII_RX_ER_MARK, PORT194_FN3), + PINMUX_DATA(STP1_IPD0_PORT194_MARK, PORT194_FN6, MSEL5CR_23_1), + PINMUX_DATA(LCD1_D16_MARK, PORT194_FN7), + + /* Port195 */ + PINMUX_DATA(SCIFA1_RXD_MARK, PORT195_FN1), + PINMUX_DATA(RMII_RXD0_MARK, PORT195_FN3), + PINMUX_DATA(STP1_IPD3_MARK, PORT195_FN6), + PINMUX_DATA(LCD1_D15_MARK, PORT195_FN7), + + /* Port196 */ + PINMUX_DATA(SCIFA1_TXD_MARK, PORT196_FN1), + PINMUX_DATA(RMII_RXD1_MARK, PORT196_FN3), + PINMUX_DATA(STP1_IPD2_MARK, PORT196_FN6), + PINMUX_DATA(LCD1_D14_MARK, PORT196_FN7), + + /* Port197 */ + PINMUX_DATA(SCIFA0_RXD_MARK, PORT197_FN1), + PINMUX_DATA(VIO1_CLK_MARK, PORT197_FN5), + PINMUX_DATA(STP1_IPD5_MARK, PORT197_FN6), + PINMUX_DATA(LCD1_D19_MARK, PORT197_FN7), + + /* Port198 */ + PINMUX_DATA(SCIFA0_TXD_MARK, PORT198_FN1), + PINMUX_DATA(VIO1_VD_MARK, PORT198_FN5), + PINMUX_DATA(STP1_IPD4_MARK, PORT198_FN6), + PINMUX_DATA(LCD1_D18_MARK, PORT198_FN7), + + /* Port199 */ + PINMUX_DATA(MEMC_NWE_MARK, PORT199_FN1), + PINMUX_DATA(SCIFA2_SCK_PORT199_MARK, PORT199_FN2, MSEL5CR_7_1), + PINMUX_DATA(RMII_TX_EN_MARK, PORT199_FN3), + PINMUX_DATA(SIM_D_PORT199_MARK, PORT199_FN4, MSEL5CR_21_1), + PINMUX_DATA(STP1_IPD1_MARK, PORT199_FN6), + PINMUX_DATA(LCD1_D13_MARK, PORT199_FN7), + + /* Port200 */ + PINMUX_DATA(MEMC_NOE_MARK, PORT200_FN1), + PINMUX_DATA(SCIFA2_RXD_MARK, PORT200_FN2), + PINMUX_DATA(RMII_TXD0_MARK, PORT200_FN3), + PINMUX_DATA(STP0_IPD7_MARK, PORT200_FN6), + PINMUX_DATA(LCD1_D12_MARK, PORT200_FN7), + + /* Port201 */ + PINMUX_DATA(MEMC_WAIT_MARK, PORT201_FN1, MSEL4CR_6_0), + PINMUX_DATA(MEMC_DREQ1_MARK, PORT201_FN1, MSEL4CR_6_1), + + PINMUX_DATA(SCIFA2_TXD_MARK, PORT201_FN2), + PINMUX_DATA(RMII_TXD1_MARK, PORT201_FN3), + PINMUX_DATA(STP0_IPD6_MARK, PORT201_FN6), + PINMUX_DATA(LCD1_D11_MARK, PORT201_FN7), + + /* Port202 */ + PINMUX_DATA(MEMC_BUSCLK_MARK, PORT202_FN1, MSEL4CR_6_0), + PINMUX_DATA(MEMC_A0_MARK, PORT202_FN1, MSEL4CR_6_1), + + PINMUX_DATA(MSIOF1_SS2_PORT202_MARK, PORT202_FN2, MSEL4CR_10_1), + PINMUX_DATA(RMII_MDC_MARK, PORT202_FN3), + PINMUX_DATA(TPU0TO2_PORT202_MARK, PORT202_FN4, MSEL5CR_25_1), + PINMUX_DATA(IDE_CS0_MARK, PORT202_FN6), + PINMUX_DATA(SDHI2_CD_PORT202_MARK, PORT202_FN7, MSEL5CR_19_1), + PINMUX_DATA(IRQ21_MARK, PORT202_FN0), + + /* Port203 - Port208 Function1 */ + PINMUX_DATA(SDHI2_CLK_MARK, PORT203_FN1), + PINMUX_DATA(SDHI2_CMD_MARK, PORT204_FN1), + PINMUX_DATA(SDHI2_D0_MARK, PORT205_FN1), + PINMUX_DATA(SDHI2_D1_MARK, PORT206_FN1), + PINMUX_DATA(SDHI2_D2_MARK, PORT207_FN1), + PINMUX_DATA(SDHI2_D3_MARK, PORT208_FN1), + + /* Port203 - Port208 Function3 */ + PINMUX_DATA(ET_TX_ER_MARK, PORT203_FN3), + PINMUX_DATA(ET_RX_ER_MARK, PORT204_FN3), + PINMUX_DATA(ET_CRS_MARK, PORT205_FN3), + PINMUX_DATA(ET_MDC_MARK, PORT206_FN3), + PINMUX_DATA(ET_MDIO_MARK, PORT207_FN3), + PINMUX_DATA(RMII_MDIO_MARK, PORT208_FN3), + + /* Port203 - Port208 Function6 */ + PINMUX_DATA(IDE_A2_MARK, PORT203_FN6), + PINMUX_DATA(IDE_A1_MARK, PORT204_FN6), + PINMUX_DATA(IDE_A0_MARK, PORT205_FN6), + PINMUX_DATA(IDE_IODACK_MARK, PORT206_FN6), + PINMUX_DATA(IDE_IODREQ_MARK, PORT207_FN6), + PINMUX_DATA(IDE_CS1_MARK, PORT208_FN6), + + /* Port203 - Port208 Function7 */ + PINMUX_DATA(SCIFA4_TXD_PORT203_MARK, PORT203_FN7, MSEL5CR_12_0, + MSEL5CR_11_1), + PINMUX_DATA(SCIFA4_RXD_PORT204_MARK, PORT204_FN7, MSEL5CR_12_0, + MSEL5CR_11_1), + PINMUX_DATA(SCIFA4_SCK_PORT205_MARK, PORT205_FN7, MSEL5CR_10_1), + PINMUX_DATA(SCIFA5_SCK_PORT206_MARK, PORT206_FN7, MSEL5CR_13_1), + PINMUX_DATA(SCIFA5_RXD_PORT207_MARK, PORT207_FN7, MSEL5CR_15_0, + MSEL5CR_14_1), + PINMUX_DATA(SCIFA5_TXD_PORT208_MARK, PORT208_FN7, MSEL5CR_15_0, + MSEL5CR_14_1), + + /* Port209 */ + PINMUX_DATA(VBUS_MARK, PORT209_FN1), + PINMUX_DATA(IRQ7_PORT209_MARK, PORT209_FN0, MSEL1CR_7_1), + + /* Port210 */ + PINMUX_DATA(IRQ9_PORT210_MARK, PORT210_FN0, MSEL1CR_9_1), + + /* Port211 */ + PINMUX_DATA(IRQ16_PORT211_MARK, PORT211_FN0, MSEL1CR_16_1), + + /* LCDC select */ + PINMUX_DATA(LCDC0_SELECT_MARK, MSEL3CR_6_0), + PINMUX_DATA(LCDC1_SELECT_MARK, MSEL3CR_6_1), + + /* SDENC */ + PINMUX_DATA(SDENC_CPG_MARK, MSEL4CR_19_0), + PINMUX_DATA(SDENC_DV_CLKI_MARK, MSEL4CR_19_1), + + /* SYSC */ + PINMUX_DATA(RESETP_PULLUP_MARK, MSEL4CR_4_0), + PINMUX_DATA(RESETP_PLAIN_MARK, MSEL4CR_4_1), + + /* DEBUG */ + PINMUX_DATA(EDEBGREQ_PULLDOWN_MARK, MSEL4CR_1_0), + PINMUX_DATA(EDEBGREQ_PULLUP_MARK, MSEL4CR_1_1), + + PINMUX_DATA(TRACEAUD_FROM_VIO_MARK, MSEL5CR_30_0, MSEL5CR_29_0), + PINMUX_DATA(TRACEAUD_FROM_LCDC0_MARK, MSEL5CR_30_0, MSEL5CR_29_1), + PINMUX_DATA(TRACEAUD_FROM_MEMC_MARK, MSEL5CR_30_1, MSEL5CR_29_0), +}; + +static struct pinmux_gpio pinmux_gpios[] = { + + /* PORT */ + GPIO_PORT_ALL(), + + /* IRQ */ + GPIO_FN(IRQ0_PORT2), GPIO_FN(IRQ0_PORT13), + GPIO_FN(IRQ1), + GPIO_FN(IRQ2_PORT11), GPIO_FN(IRQ2_PORT12), + GPIO_FN(IRQ3_PORT10), GPIO_FN(IRQ3_PORT14), + GPIO_FN(IRQ4_PORT15), GPIO_FN(IRQ4_PORT172), + GPIO_FN(IRQ5_PORT0), GPIO_FN(IRQ5_PORT1), + GPIO_FN(IRQ6_PORT121), GPIO_FN(IRQ6_PORT173), + GPIO_FN(IRQ7_PORT120), GPIO_FN(IRQ7_PORT209), + GPIO_FN(IRQ8), + GPIO_FN(IRQ9_PORT118), GPIO_FN(IRQ9_PORT210), + GPIO_FN(IRQ10), + GPIO_FN(IRQ11), + GPIO_FN(IRQ12_PORT42), GPIO_FN(IRQ12_PORT97), + GPIO_FN(IRQ13_PORT64), GPIO_FN(IRQ13_PORT98), + GPIO_FN(IRQ14_PORT63), GPIO_FN(IRQ14_PORT99), + GPIO_FN(IRQ15_PORT62), GPIO_FN(IRQ15_PORT100), + GPIO_FN(IRQ16_PORT68), GPIO_FN(IRQ16_PORT211), + GPIO_FN(IRQ17), + GPIO_FN(IRQ18), + GPIO_FN(IRQ19), + GPIO_FN(IRQ20), + GPIO_FN(IRQ21), + GPIO_FN(IRQ22), + GPIO_FN(IRQ23), + GPIO_FN(IRQ24), + GPIO_FN(IRQ25), + GPIO_FN(IRQ26_PORT58), GPIO_FN(IRQ26_PORT81), + GPIO_FN(IRQ27_PORT57), GPIO_FN(IRQ27_PORT168), + GPIO_FN(IRQ28_PORT56), GPIO_FN(IRQ28_PORT169), + GPIO_FN(IRQ29_PORT50), GPIO_FN(IRQ29_PORT170), + GPIO_FN(IRQ30_PORT49), GPIO_FN(IRQ30_PORT171), + GPIO_FN(IRQ31_PORT41), GPIO_FN(IRQ31_PORT167), + + /* Function */ + + /* DBGT */ + GPIO_FN(DBGMDT2), GPIO_FN(DBGMDT1), GPIO_FN(DBGMDT0), + GPIO_FN(DBGMD10), GPIO_FN(DBGMD11), GPIO_FN(DBGMD20), + GPIO_FN(DBGMD21), + + /* FSI */ + GPIO_FN(FSIAISLD_PORT0), /* FSIAISLD Port 0/5 */ + GPIO_FN(FSIAISLD_PORT5), + GPIO_FN(FSIASPDIF_PORT9), /* FSIASPDIF Port 9/18 */ + GPIO_FN(FSIASPDIF_PORT18), + GPIO_FN(FSIAOSLD1), GPIO_FN(FSIAOSLD2), GPIO_FN(FSIAOLR), + GPIO_FN(FSIAOBT), GPIO_FN(FSIAOSLD), GPIO_FN(FSIAOMC), + GPIO_FN(FSIACK), GPIO_FN(FSIAILR), GPIO_FN(FSIAIBT), + + /* FMSI */ + GPIO_FN(FMSISLD_PORT1), /* FMSISLD Port 1/6 */ + GPIO_FN(FMSISLD_PORT6), + GPIO_FN(FMSIILR), GPIO_FN(FMSIIBT), GPIO_FN(FMSIOLR), + GPIO_FN(FMSIOBT), GPIO_FN(FMSICK), GPIO_FN(FMSOILR), + GPIO_FN(FMSOIBT), GPIO_FN(FMSOOLR), GPIO_FN(FMSOOBT), + GPIO_FN(FMSOSLD), GPIO_FN(FMSOCK), + + /* SCIFA0 */ + GPIO_FN(SCIFA0_SCK), GPIO_FN(SCIFA0_CTS), GPIO_FN(SCIFA0_RTS), + GPIO_FN(SCIFA0_RXD), GPIO_FN(SCIFA0_TXD), + + /* SCIFA1 */ + GPIO_FN(SCIFA1_CTS), GPIO_FN(SCIFA1_SCK), + GPIO_FN(SCIFA1_RXD), GPIO_FN(SCIFA1_TXD), GPIO_FN(SCIFA1_RTS), + + /* SCIFA2 */ + GPIO_FN(SCIFA2_SCK_PORT22), /* SCIFA2_SCK Port 22/199 */ + GPIO_FN(SCIFA2_SCK_PORT199), + GPIO_FN(SCIFA2_RXD), GPIO_FN(SCIFA2_TXD), + GPIO_FN(SCIFA2_CTS), GPIO_FN(SCIFA2_RTS), + + /* SCIFA3 */ + GPIO_FN(SCIFA3_RTS_PORT105), /* MSEL5CR_8_0 */ + GPIO_FN(SCIFA3_SCK_PORT116), + GPIO_FN(SCIFA3_CTS_PORT117), + GPIO_FN(SCIFA3_RXD_PORT174), + GPIO_FN(SCIFA3_TXD_PORT175), + + GPIO_FN(SCIFA3_RTS_PORT161), /* MSEL5CR_8_1 */ + GPIO_FN(SCIFA3_SCK_PORT158), + GPIO_FN(SCIFA3_CTS_PORT162), + GPIO_FN(SCIFA3_RXD_PORT159), + GPIO_FN(SCIFA3_TXD_PORT160), + + /* SCIFA4 */ + GPIO_FN(SCIFA4_RXD_PORT12), /* MSEL5CR[12:11] = 00 */ + GPIO_FN(SCIFA4_TXD_PORT13), + + GPIO_FN(SCIFA4_RXD_PORT204), /* MSEL5CR[12:11] = 01 */ + GPIO_FN(SCIFA4_TXD_PORT203), + + GPIO_FN(SCIFA4_RXD_PORT94), /* MSEL5CR[12:11] = 10 */ + GPIO_FN(SCIFA4_TXD_PORT93), + + GPIO_FN(SCIFA4_SCK_PORT21), /* SCIFA4_SCK Port 21/205 */ + GPIO_FN(SCIFA4_SCK_PORT205), + + /* SCIFA5 */ + GPIO_FN(SCIFA5_TXD_PORT20), /* MSEL5CR[15:14] = 00 */ + GPIO_FN(SCIFA5_RXD_PORT10), + + GPIO_FN(SCIFA5_RXD_PORT207), /* MSEL5CR[15:14] = 01 */ + GPIO_FN(SCIFA5_TXD_PORT208), + + GPIO_FN(SCIFA5_TXD_PORT91), /* MSEL5CR[15:14] = 10 */ + GPIO_FN(SCIFA5_RXD_PORT92), + + GPIO_FN(SCIFA5_SCK_PORT23), /* SCIFA5_SCK Port 23/206 */ + GPIO_FN(SCIFA5_SCK_PORT206), + + /* SCIFA6 */ + GPIO_FN(SCIFA6_SCK), GPIO_FN(SCIFA6_RXD), GPIO_FN(SCIFA6_TXD), + + /* SCIFA7 */ + GPIO_FN(SCIFA7_TXD), GPIO_FN(SCIFA7_RXD), + + /* SCIFAB */ + GPIO_FN(SCIFB_SCK_PORT190), /* MSEL5CR_17_0 */ + GPIO_FN(SCIFB_RXD_PORT191), + GPIO_FN(SCIFB_TXD_PORT192), + GPIO_FN(SCIFB_RTS_PORT186), + GPIO_FN(SCIFB_CTS_PORT187), + + GPIO_FN(SCIFB_SCK_PORT2), /* MSEL5CR_17_1 */ + GPIO_FN(SCIFB_RXD_PORT3), + GPIO_FN(SCIFB_TXD_PORT4), + GPIO_FN(SCIFB_RTS_PORT172), + GPIO_FN(SCIFB_CTS_PORT173), + + /* LCD0 */ + GPIO_FN(LCD0_D0), GPIO_FN(LCD0_D1), GPIO_FN(LCD0_D2), + GPIO_FN(LCD0_D3), GPIO_FN(LCD0_D4), GPIO_FN(LCD0_D5), + GPIO_FN(LCD0_D6), GPIO_FN(LCD0_D7), GPIO_FN(LCD0_D8), + GPIO_FN(LCD0_D9), GPIO_FN(LCD0_D10), GPIO_FN(LCD0_D11), + GPIO_FN(LCD0_D12), GPIO_FN(LCD0_D13), GPIO_FN(LCD0_D14), + GPIO_FN(LCD0_D15), GPIO_FN(LCD0_D16), GPIO_FN(LCD0_D17), + GPIO_FN(LCD0_DON), GPIO_FN(LCD0_VCPWC), GPIO_FN(LCD0_VEPWC), + GPIO_FN(LCD0_DCK), GPIO_FN(LCD0_VSYN), + GPIO_FN(LCD0_HSYN), GPIO_FN(LCD0_DISP), + GPIO_FN(LCD0_WR), GPIO_FN(LCD0_RD), + GPIO_FN(LCD0_CS), GPIO_FN(LCD0_RS), + + GPIO_FN(LCD0_D18_PORT163), GPIO_FN(LCD0_D19_PORT162), + GPIO_FN(LCD0_D20_PORT161), GPIO_FN(LCD0_D21_PORT158), + GPIO_FN(LCD0_D22_PORT160), GPIO_FN(LCD0_D23_PORT159), + GPIO_FN(LCD0_LCLK_PORT165), /* MSEL5CR_6_1 */ + + GPIO_FN(LCD0_D18_PORT40), GPIO_FN(LCD0_D19_PORT4), + GPIO_FN(LCD0_D20_PORT3), GPIO_FN(LCD0_D21_PORT2), + GPIO_FN(LCD0_D22_PORT0), GPIO_FN(LCD0_D23_PORT1), + GPIO_FN(LCD0_LCLK_PORT102), /* MSEL5CR_6_0 */ + + /* LCD1 */ + GPIO_FN(LCD1_D0), GPIO_FN(LCD1_D1), GPIO_FN(LCD1_D2), + GPIO_FN(LCD1_D3), GPIO_FN(LCD1_D4), GPIO_FN(LCD1_D5), + GPIO_FN(LCD1_D6), GPIO_FN(LCD1_D7), GPIO_FN(LCD1_D8), + GPIO_FN(LCD1_D9), GPIO_FN(LCD1_D10), GPIO_FN(LCD1_D11), + GPIO_FN(LCD1_D12), GPIO_FN(LCD1_D13), GPIO_FN(LCD1_D14), + GPIO_FN(LCD1_D15), GPIO_FN(LCD1_D16), GPIO_FN(LCD1_D17), + GPIO_FN(LCD1_D18), GPIO_FN(LCD1_D19), GPIO_FN(LCD1_D20), + GPIO_FN(LCD1_D21), GPIO_FN(LCD1_D22), GPIO_FN(LCD1_D23), + GPIO_FN(LCD1_RS), GPIO_FN(LCD1_RD), GPIO_FN(LCD1_CS), + GPIO_FN(LCD1_WR), GPIO_FN(LCD1_DCK), GPIO_FN(LCD1_DON), + GPIO_FN(LCD1_VCPWC), GPIO_FN(LCD1_LCLK), GPIO_FN(LCD1_HSYN), + GPIO_FN(LCD1_VSYN), GPIO_FN(LCD1_VEPWC), GPIO_FN(LCD1_DISP), + + /* RSPI */ + GPIO_FN(RSPI_SSL0_A), GPIO_FN(RSPI_SSL1_A), GPIO_FN(RSPI_SSL2_A), + GPIO_FN(RSPI_SSL3_A), GPIO_FN(RSPI_CK_A), GPIO_FN(RSPI_MOSI_A), + GPIO_FN(RSPI_MISO_A), + + /* VIO CKO */ + GPIO_FN(VIO_CKO1), + GPIO_FN(VIO_CKO2), + GPIO_FN(VIO_CKO_1), + GPIO_FN(VIO_CKO), + + /* VIO0 */ + GPIO_FN(VIO0_D0), GPIO_FN(VIO0_D1), GPIO_FN(VIO0_D2), + GPIO_FN(VIO0_D3), GPIO_FN(VIO0_D4), GPIO_FN(VIO0_D5), + GPIO_FN(VIO0_D6), GPIO_FN(VIO0_D7), GPIO_FN(VIO0_D8), + GPIO_FN(VIO0_D9), GPIO_FN(VIO0_D10), GPIO_FN(VIO0_D11), + GPIO_FN(VIO0_D12), GPIO_FN(VIO0_VD), GPIO_FN(VIO0_HD), + GPIO_FN(VIO0_CLK), GPIO_FN(VIO0_FIELD), + + GPIO_FN(VIO0_D13_PORT26), /* MSEL5CR_27_0 */ + GPIO_FN(VIO0_D14_PORT25), + GPIO_FN(VIO0_D15_PORT24), + + GPIO_FN(VIO0_D13_PORT22), /* MSEL5CR_27_1 */ + GPIO_FN(VIO0_D14_PORT95), + GPIO_FN(VIO0_D15_PORT96), + + /* VIO1 */ + GPIO_FN(VIO1_D0), GPIO_FN(VIO1_D1), GPIO_FN(VIO1_D2), + GPIO_FN(VIO1_D3), GPIO_FN(VIO1_D4), GPIO_FN(VIO1_D5), + GPIO_FN(VIO1_D6), GPIO_FN(VIO1_D7), GPIO_FN(VIO1_VD), + GPIO_FN(VIO1_HD), GPIO_FN(VIO1_CLK), GPIO_FN(VIO1_FIELD), + + /* TPU0 */ + GPIO_FN(TPU0TO0), GPIO_FN(TPU0TO1), GPIO_FN(TPU0TO3), + GPIO_FN(TPU0TO2_PORT66), /* TPU0TO2 Port 66/202 */ + GPIO_FN(TPU0TO2_PORT202), + + /* SSP1 0 */ + GPIO_FN(STP0_IPD0), GPIO_FN(STP0_IPD1), GPIO_FN(STP0_IPD2), + GPIO_FN(STP0_IPD3), GPIO_FN(STP0_IPD4), GPIO_FN(STP0_IPD5), + GPIO_FN(STP0_IPD6), GPIO_FN(STP0_IPD7), GPIO_FN(STP0_IPEN), + GPIO_FN(STP0_IPCLK), GPIO_FN(STP0_IPSYNC), + + /* SSP1 1 */ + GPIO_FN(STP1_IPD1), GPIO_FN(STP1_IPD2), GPIO_FN(STP1_IPD3), + GPIO_FN(STP1_IPD4), GPIO_FN(STP1_IPD5), GPIO_FN(STP1_IPD6), + GPIO_FN(STP1_IPD7), GPIO_FN(STP1_IPCLK), GPIO_FN(STP1_IPSYNC), + + GPIO_FN(STP1_IPD0_PORT186), /* MSEL5CR_23_0 */ + GPIO_FN(STP1_IPEN_PORT187), + + GPIO_FN(STP1_IPD0_PORT194), /* MSEL5CR_23_1 */ + GPIO_FN(STP1_IPEN_PORT193), + + /* SIM */ + GPIO_FN(SIM_RST), GPIO_FN(SIM_CLK), + GPIO_FN(SIM_D_PORT22), /* SIM_D Port 22/199 */ + GPIO_FN(SIM_D_PORT199), + + /* SDHI0 */ + GPIO_FN(SDHI0_D0), GPIO_FN(SDHI0_D1), GPIO_FN(SDHI0_D2), + GPIO_FN(SDHI0_D3), GPIO_FN(SDHI0_CD), GPIO_FN(SDHI0_WP), + GPIO_FN(SDHI0_CMD), GPIO_FN(SDHI0_CLK), + + /* SDHI1 */ + GPIO_FN(SDHI1_D0), GPIO_FN(SDHI1_D1), GPIO_FN(SDHI1_D2), + GPIO_FN(SDHI1_D3), GPIO_FN(SDHI1_CD), GPIO_FN(SDHI1_WP), + GPIO_FN(SDHI1_CMD), GPIO_FN(SDHI1_CLK), + + /* SDHI2 */ + GPIO_FN(SDHI2_D0), GPIO_FN(SDHI2_D1), GPIO_FN(SDHI2_D2), + GPIO_FN(SDHI2_D3), GPIO_FN(SDHI2_CLK), GPIO_FN(SDHI2_CMD), + + GPIO_FN(SDHI2_CD_PORT24), /* MSEL5CR_19_0 */ + GPIO_FN(SDHI2_WP_PORT25), + + GPIO_FN(SDHI2_WP_PORT177), /* MSEL5CR_19_1 */ + GPIO_FN(SDHI2_CD_PORT202), + + /* MSIOF2 */ + GPIO_FN(MSIOF2_TXD), GPIO_FN(MSIOF2_RXD), GPIO_FN(MSIOF2_TSCK), + GPIO_FN(MSIOF2_SS2), GPIO_FN(MSIOF2_TSYNC), GPIO_FN(MSIOF2_SS1), + GPIO_FN(MSIOF2_MCK1), GPIO_FN(MSIOF2_MCK0), GPIO_FN(MSIOF2_RSYNC), + GPIO_FN(MSIOF2_RSCK), + + /* KEYSC */ + GPIO_FN(KEYIN4), GPIO_FN(KEYIN5), + GPIO_FN(KEYIN6), GPIO_FN(KEYIN7), + GPIO_FN(KEYOUT0), GPIO_FN(KEYOUT1), GPIO_FN(KEYOUT2), + GPIO_FN(KEYOUT3), GPIO_FN(KEYOUT4), GPIO_FN(KEYOUT5), + GPIO_FN(KEYOUT6), GPIO_FN(KEYOUT7), + + GPIO_FN(KEYIN0_PORT43), /* MSEL4CR_18_0 */ + GPIO_FN(KEYIN1_PORT44), + GPIO_FN(KEYIN2_PORT45), + GPIO_FN(KEYIN3_PORT46), + + GPIO_FN(KEYIN0_PORT58), /* MSEL4CR_18_1 */ + GPIO_FN(KEYIN1_PORT57), + GPIO_FN(KEYIN2_PORT56), + GPIO_FN(KEYIN3_PORT55), + + /* VOU */ + GPIO_FN(DV_D0), GPIO_FN(DV_D1), GPIO_FN(DV_D2), + GPIO_FN(DV_D3), GPIO_FN(DV_D4), GPIO_FN(DV_D5), + GPIO_FN(DV_D6), GPIO_FN(DV_D7), GPIO_FN(DV_D8), + GPIO_FN(DV_D9), GPIO_FN(DV_D10), GPIO_FN(DV_D11), + GPIO_FN(DV_D12), GPIO_FN(DV_D13), GPIO_FN(DV_D14), + GPIO_FN(DV_D15), GPIO_FN(DV_CLK), + GPIO_FN(DV_VSYNC), GPIO_FN(DV_HSYNC), + + /* MEMC */ + GPIO_FN(MEMC_AD0), GPIO_FN(MEMC_AD1), GPIO_FN(MEMC_AD2), + GPIO_FN(MEMC_AD3), GPIO_FN(MEMC_AD4), GPIO_FN(MEMC_AD5), + GPIO_FN(MEMC_AD6), GPIO_FN(MEMC_AD7), GPIO_FN(MEMC_AD8), + GPIO_FN(MEMC_AD9), GPIO_FN(MEMC_AD10), GPIO_FN(MEMC_AD11), + GPIO_FN(MEMC_AD12), GPIO_FN(MEMC_AD13), GPIO_FN(MEMC_AD14), + GPIO_FN(MEMC_AD15), GPIO_FN(MEMC_CS0), GPIO_FN(MEMC_INT), + GPIO_FN(MEMC_NWE), GPIO_FN(MEMC_NOE), GPIO_FN(MEMC_CS1), + GPIO_FN(MEMC_A1), GPIO_FN(MEMC_ADV), GPIO_FN(MEMC_DREQ0), + GPIO_FN(MEMC_WAIT), GPIO_FN(MEMC_DREQ1), GPIO_FN(MEMC_BUSCLK), + GPIO_FN(MEMC_A0), + + /* MMC */ + GPIO_FN(MMC0_D0_PORT68), GPIO_FN(MMC0_D1_PORT69), + GPIO_FN(MMC0_D2_PORT70), GPIO_FN(MMC0_D3_PORT71), + GPIO_FN(MMC0_D4_PORT72), GPIO_FN(MMC0_D5_PORT73), + GPIO_FN(MMC0_D6_PORT74), GPIO_FN(MMC0_D7_PORT75), + GPIO_FN(MMC0_CLK_PORT66), + GPIO_FN(MMC0_CMD_PORT67), /* MSEL4CR_15_0 */ + + GPIO_FN(MMC1_D0_PORT149), GPIO_FN(MMC1_D1_PORT148), + GPIO_FN(MMC1_D2_PORT147), GPIO_FN(MMC1_D3_PORT146), + GPIO_FN(MMC1_D4_PORT145), GPIO_FN(MMC1_D5_PORT144), + GPIO_FN(MMC1_D6_PORT143), GPIO_FN(MMC1_D7_PORT142), + GPIO_FN(MMC1_CLK_PORT103), + GPIO_FN(MMC1_CMD_PORT104), /* MSEL4CR_15_1 */ + + /* MSIOF0 */ + GPIO_FN(MSIOF0_SS1), GPIO_FN(MSIOF0_SS2), GPIO_FN(MSIOF0_RXD), + GPIO_FN(MSIOF0_TXD), GPIO_FN(MSIOF0_MCK0), GPIO_FN(MSIOF0_MCK1), + GPIO_FN(MSIOF0_RSYNC), GPIO_FN(MSIOF0_RSCK), GPIO_FN(MSIOF0_TSCK), + GPIO_FN(MSIOF0_TSYNC), + + /* MSIOF1 */ + GPIO_FN(MSIOF1_RSCK), GPIO_FN(MSIOF1_RSYNC), + GPIO_FN(MSIOF1_MCK0), GPIO_FN(MSIOF1_MCK1), + + GPIO_FN(MSIOF1_SS2_PORT116), GPIO_FN(MSIOF1_SS1_PORT117), + GPIO_FN(MSIOF1_RXD_PORT118), GPIO_FN(MSIOF1_TXD_PORT119), + GPIO_FN(MSIOF1_TSYNC_PORT120), + GPIO_FN(MSIOF1_TSCK_PORT121), /* MSEL4CR_10_0 */ + + GPIO_FN(MSIOF1_SS1_PORT67), GPIO_FN(MSIOF1_TSCK_PORT72), + GPIO_FN(MSIOF1_TSYNC_PORT73), GPIO_FN(MSIOF1_TXD_PORT74), + GPIO_FN(MSIOF1_RXD_PORT75), + GPIO_FN(MSIOF1_SS2_PORT202), /* MSEL4CR_10_1 */ + + /* GPIO */ + GPIO_FN(GPO0), GPIO_FN(GPI0), + GPIO_FN(GPO1), GPIO_FN(GPI1), + + /* USB0 */ + GPIO_FN(USB0_OCI), GPIO_FN(USB0_PPON), GPIO_FN(VBUS), + + /* USB1 */ + GPIO_FN(USB1_OCI), GPIO_FN(USB1_PPON), + + /* BBIF1 */ + GPIO_FN(BBIF1_RXD), GPIO_FN(BBIF1_TXD), GPIO_FN(BBIF1_TSYNC), + GPIO_FN(BBIF1_TSCK), GPIO_FN(BBIF1_RSCK), GPIO_FN(BBIF1_RSYNC), + GPIO_FN(BBIF1_FLOW), GPIO_FN(BBIF1_RX_FLOW_N), + + /* BBIF2 */ + GPIO_FN(BBIF2_TXD2_PORT5), /* MSEL5CR_0_0 */ + GPIO_FN(BBIF2_RXD2_PORT60), + GPIO_FN(BBIF2_TSYNC2_PORT6), + GPIO_FN(BBIF2_TSCK2_PORT59), + + GPIO_FN(BBIF2_RXD2_PORT90), /* MSEL5CR_0_1 */ + GPIO_FN(BBIF2_TXD2_PORT183), + GPIO_FN(BBIF2_TSCK2_PORT89), + GPIO_FN(BBIF2_TSYNC2_PORT184), + + /* BSC / FLCTL / PCMCIA */ + GPIO_FN(CS0), GPIO_FN(CS2), GPIO_FN(CS4), + GPIO_FN(CS5B), GPIO_FN(CS6A), + GPIO_FN(CS5A_PORT105), /* CS5A PORT 19/105 */ + GPIO_FN(CS5A_PORT19), + GPIO_FN(IOIS16), /* ? */ + + GPIO_FN(A0), GPIO_FN(A1), GPIO_FN(A2), GPIO_FN(A3), + GPIO_FN(A4_FOE), GPIO_FN(A5_FCDE), /* share with FLCTL */ + GPIO_FN(A6), GPIO_FN(A7), GPIO_FN(A8), GPIO_FN(A9), + GPIO_FN(A10), GPIO_FN(A11), GPIO_FN(A12), GPIO_FN(A13), + GPIO_FN(A14), GPIO_FN(A15), GPIO_FN(A16), GPIO_FN(A17), + GPIO_FN(A18), GPIO_FN(A19), GPIO_FN(A20), GPIO_FN(A21), + GPIO_FN(A22), GPIO_FN(A23), GPIO_FN(A24), GPIO_FN(A25), + GPIO_FN(A26), + + GPIO_FN(D0_NAF0), GPIO_FN(D1_NAF1), /* share with FLCTL */ + GPIO_FN(D2_NAF2), GPIO_FN(D3_NAF3), /* share with FLCTL */ + GPIO_FN(D4_NAF4), GPIO_FN(D5_NAF5), /* share with FLCTL */ + GPIO_FN(D6_NAF6), GPIO_FN(D7_NAF7), /* share with FLCTL */ + GPIO_FN(D8_NAF8), GPIO_FN(D9_NAF9), /* share with FLCTL */ + GPIO_FN(D10_NAF10), GPIO_FN(D11_NAF11), /* share with FLCTL */ + GPIO_FN(D12_NAF12), GPIO_FN(D13_NAF13), /* share with FLCTL */ + GPIO_FN(D14_NAF14), GPIO_FN(D15_NAF15), /* share with FLCTL */ + GPIO_FN(D16), GPIO_FN(D17), GPIO_FN(D18), GPIO_FN(D19), + GPIO_FN(D20), GPIO_FN(D21), GPIO_FN(D22), GPIO_FN(D23), + GPIO_FN(D24), GPIO_FN(D25), GPIO_FN(D26), GPIO_FN(D27), + GPIO_FN(D28), GPIO_FN(D29), GPIO_FN(D30), GPIO_FN(D31), + + GPIO_FN(WE0_FWE), /* share with FLCTL */ + GPIO_FN(WE1), + GPIO_FN(WE2_ICIORD), /* share with PCMCIA */ + GPIO_FN(WE3_ICIOWR), /* share with PCMCIA */ + GPIO_FN(CKO), GPIO_FN(BS), GPIO_FN(RDWR), + GPIO_FN(RD_FSC), /* share with FLCTL */ + GPIO_FN(WAIT_PORT177), /* WAIT Port 90/177 */ + GPIO_FN(WAIT_PORT90), + + GPIO_FN(FCE0), GPIO_FN(FCE1), GPIO_FN(FRB), /* FLCTL */ + + /* IRDA */ + GPIO_FN(IRDA_FIRSEL), GPIO_FN(IRDA_IN), GPIO_FN(IRDA_OUT), + + /* ATAPI */ + GPIO_FN(IDE_D0), GPIO_FN(IDE_D1), GPIO_FN(IDE_D2), + GPIO_FN(IDE_D3), GPIO_FN(IDE_D4), GPIO_FN(IDE_D5), + GPIO_FN(IDE_D6), GPIO_FN(IDE_D7), GPIO_FN(IDE_D8), + GPIO_FN(IDE_D9), GPIO_FN(IDE_D10), GPIO_FN(IDE_D11), + GPIO_FN(IDE_D12), GPIO_FN(IDE_D13), GPIO_FN(IDE_D14), + GPIO_FN(IDE_D15), GPIO_FN(IDE_A0), GPIO_FN(IDE_A1), + GPIO_FN(IDE_A2), GPIO_FN(IDE_CS0), GPIO_FN(IDE_CS1), + GPIO_FN(IDE_IOWR), GPIO_FN(IDE_IORD), GPIO_FN(IDE_IORDY), + GPIO_FN(IDE_INT), GPIO_FN(IDE_RST), GPIO_FN(IDE_DIRECTION), + GPIO_FN(IDE_EXBUF_ENB), GPIO_FN(IDE_IODACK), GPIO_FN(IDE_IODREQ), + + /* RMII */ + GPIO_FN(RMII_CRS_DV), GPIO_FN(RMII_RX_ER), GPIO_FN(RMII_RXD0), + GPIO_FN(RMII_RXD1), GPIO_FN(RMII_TX_EN), GPIO_FN(RMII_TXD0), + GPIO_FN(RMII_MDC), GPIO_FN(RMII_TXD1), GPIO_FN(RMII_MDIO), + GPIO_FN(RMII_REF50CK), GPIO_FN(RMII_REF125CK), /* for GMII */ + + /* GEther */ + GPIO_FN(ET_TX_CLK), GPIO_FN(ET_TX_EN), GPIO_FN(ET_ETXD0), + GPIO_FN(ET_ETXD1), GPIO_FN(ET_ETXD2), GPIO_FN(ET_ETXD3), + GPIO_FN(ET_ETXD4), GPIO_FN(ET_ETXD5), /* for GEther */ + GPIO_FN(ET_ETXD6), GPIO_FN(ET_ETXD7), /* for GEther */ + GPIO_FN(ET_COL), GPIO_FN(ET_TX_ER), GPIO_FN(ET_RX_CLK), + GPIO_FN(ET_RX_DV), GPIO_FN(ET_ERXD0), GPIO_FN(ET_ERXD1), + GPIO_FN(ET_ERXD2), GPIO_FN(ET_ERXD3), + GPIO_FN(ET_ERXD4), GPIO_FN(ET_ERXD5), /* for GEther */ + GPIO_FN(ET_ERXD6), GPIO_FN(ET_ERXD7), /* for GEther */ + GPIO_FN(ET_RX_ER), GPIO_FN(ET_CRS), GPIO_FN(ET_MDC), + GPIO_FN(ET_MDIO), GPIO_FN(ET_LINK), GPIO_FN(ET_PHY_INT), + GPIO_FN(ET_WOL), GPIO_FN(ET_GTX_CLK), + + /* DMA0 */ + GPIO_FN(DREQ0), GPIO_FN(DACK0), + + /* DMA1 */ + GPIO_FN(DREQ1), GPIO_FN(DACK1), + + /* SYSC */ + GPIO_FN(RESETOUTS), + + /* IRREM */ + GPIO_FN(IROUT), + + /* LCDC */ + GPIO_FN(LCDC0_SELECT), + GPIO_FN(LCDC1_SELECT), + + /* SDENC */ + GPIO_FN(SDENC_CPG), + GPIO_FN(SDENC_DV_CLKI), + + /* SYSC */ + GPIO_FN(RESETP_PULLUP), + GPIO_FN(RESETP_PLAIN), + + /* DEBUG */ + GPIO_FN(EDEBGREQ_PULLDOWN), + GPIO_FN(EDEBGREQ_PULLUP), + + GPIO_FN(TRACEAUD_FROM_VIO), + GPIO_FN(TRACEAUD_FROM_LCDC0), + GPIO_FN(TRACEAUD_FROM_MEMC), +}; + +static struct pinmux_cfg_reg pinmux_config_regs[] = { + PORTCR(0, 0xe6050000), /* PORT0CR */ + PORTCR(1, 0xe6050001), /* PORT1CR */ + PORTCR(2, 0xe6050002), /* PORT2CR */ + PORTCR(3, 0xe6050003), /* PORT3CR */ + PORTCR(4, 0xe6050004), /* PORT4CR */ + PORTCR(5, 0xe6050005), /* PORT5CR */ + PORTCR(6, 0xe6050006), /* PORT6CR */ + PORTCR(7, 0xe6050007), /* PORT7CR */ + PORTCR(8, 0xe6050008), /* PORT8CR */ + PORTCR(9, 0xe6050009), /* PORT9CR */ + PORTCR(10, 0xe605000a), /* PORT10CR */ + PORTCR(11, 0xe605000b), /* PORT11CR */ + PORTCR(12, 0xe605000c), /* PORT12CR */ + PORTCR(13, 0xe605000d), /* PORT13CR */ + PORTCR(14, 0xe605000e), /* PORT14CR */ + PORTCR(15, 0xe605000f), /* PORT15CR */ + PORTCR(16, 0xe6050010), /* PORT16CR */ + PORTCR(17, 0xe6050011), /* PORT17CR */ + PORTCR(18, 0xe6050012), /* PORT18CR */ + PORTCR(19, 0xe6050013), /* PORT19CR */ + PORTCR(20, 0xe6050014), /* PORT20CR */ + PORTCR(21, 0xe6050015), /* PORT21CR */ + PORTCR(22, 0xe6050016), /* PORT22CR */ + PORTCR(23, 0xe6050017), /* PORT23CR */ + PORTCR(24, 0xe6050018), /* PORT24CR */ + PORTCR(25, 0xe6050019), /* PORT25CR */ + PORTCR(26, 0xe605001a), /* PORT26CR */ + PORTCR(27, 0xe605001b), /* PORT27CR */ + PORTCR(28, 0xe605001c), /* PORT28CR */ + PORTCR(29, 0xe605001d), /* PORT29CR */ + PORTCR(30, 0xe605001e), /* PORT30CR */ + PORTCR(31, 0xe605001f), /* PORT31CR */ + PORTCR(32, 0xe6050020), /* PORT32CR */ + PORTCR(33, 0xe6050021), /* PORT33CR */ + PORTCR(34, 0xe6050022), /* PORT34CR */ + PORTCR(35, 0xe6050023), /* PORT35CR */ + PORTCR(36, 0xe6050024), /* PORT36CR */ + PORTCR(37, 0xe6050025), /* PORT37CR */ + PORTCR(38, 0xe6050026), /* PORT38CR */ + PORTCR(39, 0xe6050027), /* PORT39CR */ + PORTCR(40, 0xe6050028), /* PORT40CR */ + PORTCR(41, 0xe6050029), /* PORT41CR */ + PORTCR(42, 0xe605002a), /* PORT42CR */ + PORTCR(43, 0xe605002b), /* PORT43CR */ + PORTCR(44, 0xe605002c), /* PORT44CR */ + PORTCR(45, 0xe605002d), /* PORT45CR */ + PORTCR(46, 0xe605002e), /* PORT46CR */ + PORTCR(47, 0xe605002f), /* PORT47CR */ + PORTCR(48, 0xe6050030), /* PORT48CR */ + PORTCR(49, 0xe6050031), /* PORT49CR */ + PORTCR(50, 0xe6050032), /* PORT50CR */ + PORTCR(51, 0xe6050033), /* PORT51CR */ + PORTCR(52, 0xe6050034), /* PORT52CR */ + PORTCR(53, 0xe6050035), /* PORT53CR */ + PORTCR(54, 0xe6050036), /* PORT54CR */ + PORTCR(55, 0xe6050037), /* PORT55CR */ + PORTCR(56, 0xe6050038), /* PORT56CR */ + PORTCR(57, 0xe6050039), /* PORT57CR */ + PORTCR(58, 0xe605003a), /* PORT58CR */ + PORTCR(59, 0xe605003b), /* PORT59CR */ + PORTCR(60, 0xe605003c), /* PORT60CR */ + PORTCR(61, 0xe605003d), /* PORT61CR */ + PORTCR(62, 0xe605003e), /* PORT62CR */ + PORTCR(63, 0xe605003f), /* PORT63CR */ + PORTCR(64, 0xe6050040), /* PORT64CR */ + PORTCR(65, 0xe6050041), /* PORT65CR */ + PORTCR(66, 0xe6050042), /* PORT66CR */ + PORTCR(67, 0xe6050043), /* PORT67CR */ + PORTCR(68, 0xe6050044), /* PORT68CR */ + PORTCR(69, 0xe6050045), /* PORT69CR */ + PORTCR(70, 0xe6050046), /* PORT70CR */ + PORTCR(71, 0xe6050047), /* PORT71CR */ + PORTCR(72, 0xe6050048), /* PORT72CR */ + PORTCR(73, 0xe6050049), /* PORT73CR */ + PORTCR(74, 0xe605004a), /* PORT74CR */ + PORTCR(75, 0xe605004b), /* PORT75CR */ + PORTCR(76, 0xe605004c), /* PORT76CR */ + PORTCR(77, 0xe605004d), /* PORT77CR */ + PORTCR(78, 0xe605004e), /* PORT78CR */ + PORTCR(79, 0xe605004f), /* PORT79CR */ + PORTCR(80, 0xe6050050), /* PORT80CR */ + PORTCR(81, 0xe6050051), /* PORT81CR */ + PORTCR(82, 0xe6050052), /* PORT82CR */ + PORTCR(83, 0xe6050053), /* PORT83CR */ + + PORTCR(84, 0xe6051054), /* PORT84CR */ + PORTCR(85, 0xe6051055), /* PORT85CR */ + PORTCR(86, 0xe6051056), /* PORT86CR */ + PORTCR(87, 0xe6051057), /* PORT87CR */ + PORTCR(88, 0xe6051058), /* PORT88CR */ + PORTCR(89, 0xe6051059), /* PORT89CR */ + PORTCR(90, 0xe605105a), /* PORT90CR */ + PORTCR(91, 0xe605105b), /* PORT91CR */ + PORTCR(92, 0xe605105c), /* PORT92CR */ + PORTCR(93, 0xe605105d), /* PORT93CR */ + PORTCR(94, 0xe605105e), /* PORT94CR */ + PORTCR(95, 0xe605105f), /* PORT95CR */ + PORTCR(96, 0xe6051060), /* PORT96CR */ + PORTCR(97, 0xe6051061), /* PORT97CR */ + PORTCR(98, 0xe6051062), /* PORT98CR */ + PORTCR(99, 0xe6051063), /* PORT99CR */ + PORTCR(100, 0xe6051064), /* PORT100CR */ + PORTCR(101, 0xe6051065), /* PORT101CR */ + PORTCR(102, 0xe6051066), /* PORT102CR */ + PORTCR(103, 0xe6051067), /* PORT103CR */ + PORTCR(104, 0xe6051068), /* PORT104CR */ + PORTCR(105, 0xe6051069), /* PORT105CR */ + PORTCR(106, 0xe605106a), /* PORT106CR */ + PORTCR(107, 0xe605106b), /* PORT107CR */ + PORTCR(108, 0xe605106c), /* PORT108CR */ + PORTCR(109, 0xe605106d), /* PORT109CR */ + PORTCR(110, 0xe605106e), /* PORT110CR */ + PORTCR(111, 0xe605106f), /* PORT111CR */ + PORTCR(112, 0xe6051070), /* PORT112CR */ + PORTCR(113, 0xe6051071), /* PORT113CR */ + PORTCR(114, 0xe6051072), /* PORT114CR */ + + PORTCR(115, 0xe6052073), /* PORT115CR */ + PORTCR(116, 0xe6052074), /* PORT116CR */ + PORTCR(117, 0xe6052075), /* PORT117CR */ + PORTCR(118, 0xe6052076), /* PORT118CR */ + PORTCR(119, 0xe6052077), /* PORT119CR */ + PORTCR(120, 0xe6052078), /* PORT120CR */ + PORTCR(121, 0xe6052079), /* PORT121CR */ + PORTCR(122, 0xe605207a), /* PORT122CR */ + PORTCR(123, 0xe605207b), /* PORT123CR */ + PORTCR(124, 0xe605207c), /* PORT124CR */ + PORTCR(125, 0xe605207d), /* PORT125CR */ + PORTCR(126, 0xe605207e), /* PORT126CR */ + PORTCR(127, 0xe605207f), /* PORT127CR */ + PORTCR(128, 0xe6052080), /* PORT128CR */ + PORTCR(129, 0xe6052081), /* PORT129CR */ + PORTCR(130, 0xe6052082), /* PORT130CR */ + PORTCR(131, 0xe6052083), /* PORT131CR */ + PORTCR(132, 0xe6052084), /* PORT132CR */ + PORTCR(133, 0xe6052085), /* PORT133CR */ + PORTCR(134, 0xe6052086), /* PORT134CR */ + PORTCR(135, 0xe6052087), /* PORT135CR */ + PORTCR(136, 0xe6052088), /* PORT136CR */ + PORTCR(137, 0xe6052089), /* PORT137CR */ + PORTCR(138, 0xe605208a), /* PORT138CR */ + PORTCR(139, 0xe605208b), /* PORT139CR */ + PORTCR(140, 0xe605208c), /* PORT140CR */ + PORTCR(141, 0xe605208d), /* PORT141CR */ + PORTCR(142, 0xe605208e), /* PORT142CR */ + PORTCR(143, 0xe605208f), /* PORT143CR */ + PORTCR(144, 0xe6052090), /* PORT144CR */ + PORTCR(145, 0xe6052091), /* PORT145CR */ + PORTCR(146, 0xe6052092), /* PORT146CR */ + PORTCR(147, 0xe6052093), /* PORT147CR */ + PORTCR(148, 0xe6052094), /* PORT148CR */ + PORTCR(149, 0xe6052095), /* PORT149CR */ + PORTCR(150, 0xe6052096), /* PORT150CR */ + PORTCR(151, 0xe6052097), /* PORT151CR */ + PORTCR(152, 0xe6052098), /* PORT152CR */ + PORTCR(153, 0xe6052099), /* PORT153CR */ + PORTCR(154, 0xe605209a), /* PORT154CR */ + PORTCR(155, 0xe605209b), /* PORT155CR */ + PORTCR(156, 0xe605209c), /* PORT156CR */ + PORTCR(157, 0xe605209d), /* PORT157CR */ + PORTCR(158, 0xe605209e), /* PORT158CR */ + PORTCR(159, 0xe605209f), /* PORT159CR */ + PORTCR(160, 0xe60520a0), /* PORT160CR */ + PORTCR(161, 0xe60520a1), /* PORT161CR */ + PORTCR(162, 0xe60520a2), /* PORT162CR */ + PORTCR(163, 0xe60520a3), /* PORT163CR */ + PORTCR(164, 0xe60520a4), /* PORT164CR */ + PORTCR(165, 0xe60520a5), /* PORT165CR */ + PORTCR(166, 0xe60520a6), /* PORT166CR */ + PORTCR(167, 0xe60520a7), /* PORT167CR */ + PORTCR(168, 0xe60520a8), /* PORT168CR */ + PORTCR(169, 0xe60520a9), /* PORT169CR */ + PORTCR(170, 0xe60520aa), /* PORT170CR */ + PORTCR(171, 0xe60520ab), /* PORT171CR */ + PORTCR(172, 0xe60520ac), /* PORT172CR */ + PORTCR(173, 0xe60520ad), /* PORT173CR */ + PORTCR(174, 0xe60520ae), /* PORT174CR */ + PORTCR(175, 0xe60520af), /* PORT175CR */ + PORTCR(176, 0xe60520b0), /* PORT176CR */ + PORTCR(177, 0xe60520b1), /* PORT177CR */ + PORTCR(178, 0xe60520b2), /* PORT178CR */ + PORTCR(179, 0xe60520b3), /* PORT179CR */ + PORTCR(180, 0xe60520b4), /* PORT180CR */ + PORTCR(181, 0xe60520b5), /* PORT181CR */ + PORTCR(182, 0xe60520b6), /* PORT182CR */ + PORTCR(183, 0xe60520b7), /* PORT183CR */ + PORTCR(184, 0xe60520b8), /* PORT184CR */ + PORTCR(185, 0xe60520b9), /* PORT185CR */ + PORTCR(186, 0xe60520ba), /* PORT186CR */ + PORTCR(187, 0xe60520bb), /* PORT187CR */ + PORTCR(188, 0xe60520bc), /* PORT188CR */ + PORTCR(189, 0xe60520bd), /* PORT189CR */ + PORTCR(190, 0xe60520be), /* PORT190CR */ + PORTCR(191, 0xe60520bf), /* PORT191CR */ + PORTCR(192, 0xe60520c0), /* PORT192CR */ + PORTCR(193, 0xe60520c1), /* PORT193CR */ + PORTCR(194, 0xe60520c2), /* PORT194CR */ + PORTCR(195, 0xe60520c3), /* PORT195CR */ + PORTCR(196, 0xe60520c4), /* PORT196CR */ + PORTCR(197, 0xe60520c5), /* PORT197CR */ + PORTCR(198, 0xe60520c6), /* PORT198CR */ + PORTCR(199, 0xe60520c7), /* PORT199CR */ + PORTCR(200, 0xe60520c8), /* PORT200CR */ + PORTCR(201, 0xe60520c9), /* PORT201CR */ + PORTCR(202, 0xe60520ca), /* PORT202CR */ + PORTCR(203, 0xe60520cb), /* PORT203CR */ + PORTCR(204, 0xe60520cc), /* PORT204CR */ + PORTCR(205, 0xe60520cd), /* PORT205CR */ + PORTCR(206, 0xe60520ce), /* PORT206CR */ + PORTCR(207, 0xe60520cf), /* PORT207CR */ + PORTCR(208, 0xe60520d0), /* PORT208CR */ + PORTCR(209, 0xe60520d1), /* PORT209CR */ + + PORTCR(210, 0xe60530d2), /* PORT210CR */ + PORTCR(211, 0xe60530d3), /* PORT211CR */ + + { PINMUX_CFG_REG("MSEL1CR", 0xe605800c, 32, 1) { + MSEL1CR_31_0, MSEL1CR_31_1, + MSEL1CR_30_0, MSEL1CR_30_1, + MSEL1CR_29_0, MSEL1CR_29_1, + MSEL1CR_28_0, MSEL1CR_28_1, + MSEL1CR_27_0, MSEL1CR_27_1, + MSEL1CR_26_0, MSEL1CR_26_1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + MSEL1CR_16_0, MSEL1CR_16_1, + MSEL1CR_15_0, MSEL1CR_15_1, + MSEL1CR_14_0, MSEL1CR_14_1, + MSEL1CR_13_0, MSEL1CR_13_1, + MSEL1CR_12_0, MSEL1CR_12_1, + 0, 0, 0, 0, + MSEL1CR_9_0, MSEL1CR_9_1, + 0, 0, + MSEL1CR_7_0, MSEL1CR_7_1, + MSEL1CR_6_0, MSEL1CR_6_1, + MSEL1CR_5_0, MSEL1CR_5_1, + MSEL1CR_4_0, MSEL1CR_4_1, + MSEL1CR_3_0, MSEL1CR_3_1, + MSEL1CR_2_0, MSEL1CR_2_1, + 0, 0, + MSEL1CR_0_0, MSEL1CR_0_1, + } + }, + { PINMUX_CFG_REG("MSEL3CR", 0xE6058020, 32, 1) { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + MSEL3CR_15_0, MSEL3CR_15_1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + MSEL3CR_6_0, MSEL3CR_6_1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + } + }, + { PINMUX_CFG_REG("MSEL4CR", 0xE6058024, 32, 1) { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + MSEL4CR_19_0, MSEL4CR_19_1, + MSEL4CR_18_0, MSEL4CR_18_1, + 0, 0, 0, 0, + MSEL4CR_15_0, MSEL4CR_15_1, + 0, 0, 0, 0, 0, 0, 0, 0, + MSEL4CR_10_0, MSEL4CR_10_1, + 0, 0, 0, 0, 0, 0, + MSEL4CR_6_0, MSEL4CR_6_1, + 0, 0, + MSEL4CR_4_0, MSEL4CR_4_1, + 0, 0, 0, 0, + MSEL4CR_1_0, MSEL4CR_1_1, + 0, 0, + } + }, + { PINMUX_CFG_REG("MSEL5CR", 0xE6058028, 32, 1) { + MSEL5CR_31_0, MSEL5CR_31_1, + MSEL5CR_30_0, MSEL5CR_30_1, + MSEL5CR_29_0, MSEL5CR_29_1, + 0, 0, + MSEL5CR_27_0, MSEL5CR_27_1, + 0, 0, + MSEL5CR_25_0, MSEL5CR_25_1, + 0, 0, + MSEL5CR_23_0, MSEL5CR_23_1, + 0, 0, + MSEL5CR_21_0, MSEL5CR_21_1, + 0, 0, + MSEL5CR_19_0, MSEL5CR_19_1, + 0, 0, + MSEL5CR_17_0, MSEL5CR_17_1, + 0, 0, + MSEL5CR_15_0, MSEL5CR_15_1, + MSEL5CR_14_0, MSEL5CR_14_1, + MSEL5CR_13_0, MSEL5CR_13_1, + MSEL5CR_12_0, MSEL5CR_12_1, + MSEL5CR_11_0, MSEL5CR_11_1, + MSEL5CR_10_0, MSEL5CR_10_1, + 0, 0, + MSEL5CR_8_0, MSEL5CR_8_1, + MSEL5CR_7_0, MSEL5CR_7_1, + MSEL5CR_6_0, MSEL5CR_6_1, + MSEL5CR_5_0, MSEL5CR_5_1, + MSEL5CR_4_0, MSEL5CR_4_1, + MSEL5CR_3_0, MSEL5CR_3_1, + MSEL5CR_2_0, MSEL5CR_2_1, + 0, 0, + MSEL5CR_0_0, MSEL5CR_0_1, + } + }, + { }, +}; + +static struct pinmux_data_reg pinmux_data_regs[] = { + { PINMUX_DATA_REG("PORTL031_000DR", 0xe6054800, 32) { + PORT31_DATA, PORT30_DATA, PORT29_DATA, PORT28_DATA, + PORT27_DATA, PORT26_DATA, PORT25_DATA, PORT24_DATA, + PORT23_DATA, PORT22_DATA, PORT21_DATA, PORT20_DATA, + PORT19_DATA, PORT18_DATA, PORT17_DATA, PORT16_DATA, + PORT15_DATA, PORT14_DATA, PORT13_DATA, PORT12_DATA, + PORT11_DATA, PORT10_DATA, PORT9_DATA, PORT8_DATA, + PORT7_DATA, PORT6_DATA, PORT5_DATA, PORT4_DATA, + PORT3_DATA, PORT2_DATA, PORT1_DATA, PORT0_DATA } + }, + { PINMUX_DATA_REG("PORTL063_032DR", 0xe6054804, 32) { + PORT63_DATA, PORT62_DATA, PORT61_DATA, PORT60_DATA, + PORT59_DATA, PORT58_DATA, PORT57_DATA, PORT56_DATA, + PORT55_DATA, PORT54_DATA, PORT53_DATA, PORT52_DATA, + PORT51_DATA, PORT50_DATA, PORT49_DATA, PORT48_DATA, + PORT47_DATA, PORT46_DATA, PORT45_DATA, PORT44_DATA, + PORT43_DATA, PORT42_DATA, PORT41_DATA, PORT40_DATA, + PORT39_DATA, PORT38_DATA, PORT37_DATA, PORT36_DATA, + PORT35_DATA, PORT34_DATA, PORT33_DATA, PORT32_DATA } + }, + { PINMUX_DATA_REG("PORTL095_064DR", 0xe6054808, 32) { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + PORT83_DATA, PORT82_DATA, PORT81_DATA, PORT80_DATA, + PORT79_DATA, PORT78_DATA, PORT77_DATA, PORT76_DATA, + PORT75_DATA, PORT74_DATA, PORT73_DATA, PORT72_DATA, + PORT71_DATA, PORT70_DATA, PORT69_DATA, PORT68_DATA, + PORT67_DATA, PORT66_DATA, PORT65_DATA, PORT64_DATA } + }, + { PINMUX_DATA_REG("PORTD095_064DR", 0xe6055808, 32) { + PORT95_DATA, PORT94_DATA, PORT93_DATA, PORT92_DATA, + PORT91_DATA, PORT90_DATA, PORT89_DATA, PORT88_DATA, + PORT87_DATA, PORT86_DATA, PORT85_DATA, PORT84_DATA, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 } + }, + { PINMUX_DATA_REG("PORTD127_096DR", 0xe605580c, 32) { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, PORT114_DATA, PORT113_DATA, PORT112_DATA, + PORT111_DATA, PORT110_DATA, PORT109_DATA, PORT108_DATA, + PORT107_DATA, PORT106_DATA, PORT105_DATA, PORT104_DATA, + PORT103_DATA, PORT102_DATA, PORT101_DATA, PORT100_DATA, + PORT99_DATA, PORT98_DATA, PORT97_DATA, PORT96_DATA } + }, + { PINMUX_DATA_REG("PORTR127_096DR", 0xe605680C, 32) { + PORT127_DATA, PORT126_DATA, PORT125_DATA, PORT124_DATA, + PORT123_DATA, PORT122_DATA, PORT121_DATA, PORT120_DATA, + PORT119_DATA, PORT118_DATA, PORT117_DATA, PORT116_DATA, + PORT115_DATA, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 } + }, + { PINMUX_DATA_REG("PORTR159_128DR", 0xe6056810, 32) { + PORT159_DATA, PORT158_DATA, PORT157_DATA, PORT156_DATA, + PORT155_DATA, PORT154_DATA, PORT153_DATA, PORT152_DATA, + PORT151_DATA, PORT150_DATA, PORT149_DATA, PORT148_DATA, + PORT147_DATA, PORT146_DATA, PORT145_DATA, PORT144_DATA, + PORT143_DATA, PORT142_DATA, PORT141_DATA, PORT140_DATA, + PORT139_DATA, PORT138_DATA, PORT137_DATA, PORT136_DATA, + PORT135_DATA, PORT134_DATA, PORT133_DATA, PORT132_DATA, + PORT131_DATA, PORT130_DATA, PORT129_DATA, PORT128_DATA } + }, + { PINMUX_DATA_REG("PORTR191_160DR", 0xe6056814, 32) { + PORT191_DATA, PORT190_DATA, PORT189_DATA, PORT188_DATA, + PORT187_DATA, PORT186_DATA, PORT185_DATA, PORT184_DATA, + PORT183_DATA, PORT182_DATA, PORT181_DATA, PORT180_DATA, + PORT179_DATA, PORT178_DATA, PORT177_DATA, PORT176_DATA, + PORT175_DATA, PORT174_DATA, PORT173_DATA, PORT172_DATA, + PORT171_DATA, PORT170_DATA, PORT169_DATA, PORT168_DATA, + PORT167_DATA, PORT166_DATA, PORT165_DATA, PORT164_DATA, + PORT163_DATA, PORT162_DATA, PORT161_DATA, PORT160_DATA } + }, + { PINMUX_DATA_REG("PORTR223_192DR", 0xe6056818, 32) { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, PORT209_DATA, PORT208_DATA, + PORT207_DATA, PORT206_DATA, PORT205_DATA, PORT204_DATA, + PORT203_DATA, PORT202_DATA, PORT201_DATA, PORT200_DATA, + PORT199_DATA, PORT198_DATA, PORT197_DATA, PORT196_DATA, + PORT195_DATA, PORT194_DATA, PORT193_DATA, PORT192_DATA } + }, + { PINMUX_DATA_REG("PORTU223_192DR", 0xe6057818, 32) { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + PORT211_DATA, PORT210_DATA, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 } + }, + { }, +}; + +static struct pinmux_irq pinmux_irqs[] = { + PINMUX_IRQ(evt2irq(0x0200), PORT2_FN0, PORT13_FN0), /* IRQ0A */ + PINMUX_IRQ(evt2irq(0x0220), PORT20_FN0), /* IRQ1A */ + PINMUX_IRQ(evt2irq(0x0240), PORT11_FN0, PORT12_FN0), /* IRQ2A */ + PINMUX_IRQ(evt2irq(0x0260), PORT10_FN0, PORT14_FN0), /* IRQ3A */ + PINMUX_IRQ(evt2irq(0x0280), PORT15_FN0, PORT172_FN0), /* IRQ4A */ + PINMUX_IRQ(evt2irq(0x02A0), PORT0_FN0, PORT1_FN0), /* IRQ5A */ + PINMUX_IRQ(evt2irq(0x02C0), PORT121_FN0, PORT173_FN0), /* IRQ6A */ + PINMUX_IRQ(evt2irq(0x02E0), PORT120_FN0, PORT209_FN0), /* IRQ7A */ + PINMUX_IRQ(evt2irq(0x0300), PORT119_FN0), /* IRQ8A */ + PINMUX_IRQ(evt2irq(0x0320), PORT118_FN0, PORT210_FN0), /* IRQ9A */ + PINMUX_IRQ(evt2irq(0x0340), PORT19_FN0), /* IRQ10A */ + PINMUX_IRQ(evt2irq(0x0360), PORT104_FN0), /* IRQ11A */ + PINMUX_IRQ(evt2irq(0x0380), PORT42_FN0, PORT97_FN0), /* IRQ12A */ + PINMUX_IRQ(evt2irq(0x03A0), PORT64_FN0, PORT98_FN0), /* IRQ13A */ + PINMUX_IRQ(evt2irq(0x03C0), PORT63_FN0, PORT99_FN0), /* IRQ14A */ + PINMUX_IRQ(evt2irq(0x03E0), PORT62_FN0, PORT100_FN0), /* IRQ15A */ + PINMUX_IRQ(evt2irq(0x3200), PORT68_FN0, PORT211_FN0), /* IRQ16A */ + PINMUX_IRQ(evt2irq(0x3220), PORT69_FN0), /* IRQ17A */ + PINMUX_IRQ(evt2irq(0x3240), PORT70_FN0), /* IRQ18A */ + PINMUX_IRQ(evt2irq(0x3260), PORT71_FN0), /* IRQ19A */ + PINMUX_IRQ(evt2irq(0x3280), PORT67_FN0), /* IRQ20A */ + PINMUX_IRQ(evt2irq(0x32A0), PORT202_FN0), /* IRQ21A */ + PINMUX_IRQ(evt2irq(0x32C0), PORT95_FN0), /* IRQ22A */ + PINMUX_IRQ(evt2irq(0x32E0), PORT96_FN0), /* IRQ23A */ + PINMUX_IRQ(evt2irq(0x3300), PORT180_FN0), /* IRQ24A */ + PINMUX_IRQ(evt2irq(0x3320), PORT38_FN0), /* IRQ25A */ + PINMUX_IRQ(evt2irq(0x3340), PORT58_FN0, PORT81_FN0), /* IRQ26A */ + PINMUX_IRQ(evt2irq(0x3360), PORT57_FN0, PORT168_FN0), /* IRQ27A */ + PINMUX_IRQ(evt2irq(0x3380), PORT56_FN0, PORT169_FN0), /* IRQ28A */ + PINMUX_IRQ(evt2irq(0x33A0), PORT50_FN0, PORT170_FN0), /* IRQ29A */ + PINMUX_IRQ(evt2irq(0x33C0), PORT49_FN0, PORT171_FN0), /* IRQ30A */ + PINMUX_IRQ(evt2irq(0x33E0), PORT41_FN0, PORT167_FN0), /* IRQ31A */ +}; + +static struct pinmux_info r8a7740_pinmux_info = { + .name = "r8a7740_pfc", + .reserved_id = PINMUX_RESERVED, + .data = { PINMUX_DATA_BEGIN, + PINMUX_DATA_END }, + .input = { PINMUX_INPUT_BEGIN, + PINMUX_INPUT_END }, + .input_pu = { PINMUX_INPUT_PULLUP_BEGIN, + PINMUX_INPUT_PULLUP_END }, + .input_pd = { PINMUX_INPUT_PULLDOWN_BEGIN, + PINMUX_INPUT_PULLDOWN_END }, + .output = { PINMUX_OUTPUT_BEGIN, + PINMUX_OUTPUT_END }, + .mark = { PINMUX_MARK_BEGIN, + PINMUX_MARK_END }, + .function = { PINMUX_FUNCTION_BEGIN, + PINMUX_FUNCTION_END }, + + .first_gpio = GPIO_PORT0, + .last_gpio = GPIO_FN_TRACEAUD_FROM_MEMC, + + .gpios = pinmux_gpios, + .cfg_regs = pinmux_config_regs, + .data_regs = pinmux_data_regs, + + .gpio_data = pinmux_data, + .gpio_data_size = ARRAY_SIZE(pinmux_data), + + .gpio_irq = pinmux_irqs, + .gpio_irq_size = ARRAY_SIZE(pinmux_irqs), +}; + +void r8a7740_pinmux_init(void) +{ + register_pinmux(&r8a7740_pinmux_info); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7790.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7790.c new file mode 100644 index 000000000..1259062a6 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7790.c @@ -0,0 +1,829 @@ +/* + * arch/arm/cpu/armv7/rmobile/pfc-r8a7790.c + * This file is r8a7790 processor support - PFC hardware block. + * + * Copy from linux-kernel:drivers/pinctrl/sh-pfc/pfc-r8a7790.c + * + * Copyright (C) 2013 Renesas Electronics Corporation + * Copyright (C) 2013 Magnus Damm + * Copyright (C) 2012 Renesas Solutions Corp. + * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <sh_pfc.h> +#include <asm/gpio.h> +#include "pfc-r8a7790.h" + +enum { + PINMUX_RESERVED = 0, + + PINMUX_DATA_BEGIN, + GP_ALL(DATA), + PINMUX_DATA_END, + + PINMUX_INPUT_BEGIN, + GP_ALL(IN), + PINMUX_INPUT_END, + + PINMUX_OUTPUT_BEGIN, + GP_ALL(OUT), + PINMUX_OUTPUT_END, + + PINMUX_FUNCTION_BEGIN, + GP_ALL(FN), + + /* GPSR0 */ + FN_IP0_2_0, FN_IP0_5_3, FN_IP0_8_6, FN_IP0_11_9, FN_IP0_15_12, + FN_IP0_19_16, FN_IP0_22_20, FN_IP0_26_23, FN_IP0_30_27, + FN_IP1_3_0, FN_IP1_7_4, FN_IP1_11_8, FN_IP1_14_12, + FN_IP1_17_15, FN_IP1_21_18, FN_IP1_25_22, FN_IP1_27_26, + FN_IP1_29_28, FN_IP2_2_0, FN_IP2_5_3, FN_IP2_8_6, FN_IP2_11_9, + FN_IP2_14_12, FN_IP2_17_15, FN_IP2_21_18, FN_IP2_25_22, + FN_IP2_28_26, FN_IP3_3_0, FN_IP3_7_4, FN_IP3_11_8, + FN_IP3_14_12, FN_IP3_17_15, + + /* GPSR1 */ + FN_IP3_19_18, FN_IP3_22_20, FN_IP3_25_23, FN_IP3_28_26, + FN_IP3_31_29, FN_IP4_2_0, FN_IP4_5_3, FN_IP4_8_6, FN_IP4_11_9, + FN_IP4_14_12, FN_IP4_17_15, FN_IP4_20_18, FN_IP4_23_21, + FN_IP4_26_24, FN_IP4_29_27, FN_IP5_2_0, FN_IP5_5_3, FN_IP5_9_6, + FN_IP5_12_10, FN_IP5_14_13, FN_IP5_17_15, FN_IP5_20_18, + FN_IP5_23_21, FN_IP5_26_24, FN_IP5_29_27, FN_IP6_2_0, + FN_IP6_5_3, FN_IP6_8_6, FN_IP6_10_9, FN_IP6_13_11, + + /* GPSR2 */ + FN_IP7_28_27, FN_IP7_30_29, FN_IP8_1_0, FN_IP8_3_2, FN_IP8_5_4, + FN_IP8_7_6, FN_IP8_9_8, FN_IP8_11_10, FN_IP8_13_12, FN_IP8_15_14, + FN_IP8_17_16, FN_IP8_19_18, FN_IP8_21_20, FN_IP8_23_22, + FN_IP8_25_24, FN_IP8_26, FN_IP8_27, FN_VI1_DATA7_VI1_B7, + FN_IP6_16_14, FN_IP6_19_17, FN_IP6_22_20, FN_IP6_25_23, + FN_IP6_28_26, FN_IP6_31_29, FN_IP7_2_0, FN_IP7_5_3, FN_IP7_7_6, + FN_IP7_9_8, FN_IP7_12_10, FN_IP7_15_13, + + /* GPSR3 */ + FN_IP8_28, FN_IP8_30_29, FN_IP9_1_0, FN_IP9_3_2, FN_IP9_5_4, + FN_IP9_7_6, FN_IP9_11_8, FN_IP9_15_12, FN_IP9_17_16, FN_IP9_19_18, + FN_IP9_21_20, FN_IP9_23_22, FN_IP9_25_24, FN_IP9_27_26, + FN_IP9_31_28, FN_IP10_3_0, FN_IP10_6_4, FN_IP10_10_7, FN_IP10_14_11, + FN_IP10_18_15, FN_IP10_22_19, FN_IP10_25_23, FN_IP10_29_26, + FN_IP11_3_0, FN_IP11_4, FN_IP11_6_5, FN_IP11_8_7, FN_IP11_10_9, + FN_IP11_12_11, FN_IP11_14_13, FN_IP11_17_15, FN_IP11_21_18, + + /* GPSR4 */ + FN_IP11_23_22, FN_IP11_26_24, FN_IP11_29_27, FN_IP11_31_30, + FN_IP12_1_0, FN_IP12_3_2, FN_IP12_5_4, FN_IP12_7_6, FN_IP12_10_8, + FN_IP12_13_11, FN_IP12_16_14, FN_IP12_19_17, FN_IP12_22_20, + FN_IP12_24_23, FN_IP12_27_25, FN_IP12_30_28, FN_IP13_2_0, + FN_IP13_6_3, FN_IP13_9_7, FN_IP13_12_10, FN_IP13_15_13, + FN_IP13_18_16, FN_IP13_22_19, FN_IP13_25_23, FN_IP13_28_26, + FN_IP13_30_29, FN_IP14_2_0, FN_IP14_5_3, FN_IP14_8_6, FN_IP14_11_9, + FN_IP14_15_12, FN_IP14_18_16, + + /* GPSR5 */ + FN_IP14_21_19, FN_IP14_24_22, FN_IP14_27_25, FN_IP14_30_28, + FN_IP15_2_0, FN_IP15_5_3, FN_IP15_8_6, FN_IP15_11_9, FN_IP15_13_12, + FN_IP15_15_14, FN_IP15_17_16, FN_IP15_19_18, FN_IP15_22_20, + FN_IP15_25_23, FN_IP15_27_26, FN_IP15_29_28, FN_IP16_2_0, + FN_IP16_5_3, FN_USB0_PWEN, FN_USB0_OVC_VBUS, FN_IP16_6, FN_IP16_7, + FN_USB2_PWEN, FN_USB2_OVC, FN_AVS1, FN_AVS2, FN_DU_DOTCLKIN0, + FN_IP7_26_25, FN_DU_DOTCLKIN2, FN_IP7_18_16, FN_IP7_21_19, FN_IP7_24_22, + + /* IPSR0 - IPSR5 */ + /* IPSR6 */ + FN_DACK0, FN_IRQ0, FN_INTC_IRQ0_N, FN_SSI_SCK6_B, + FN_VI1_VSYNC_N, FN_VI1_VSYNC_N_B, FN_SSI_WS78_C, + FN_DREQ1_N, FN_VI1_CLKENB, FN_VI1_CLKENB_B, + FN_SSI_SDATA7_C, FN_SSI_SCK78_B, FN_DACK1, FN_IRQ1, + FN_INTC_IRQ1_N, FN_SSI_WS6_B, FN_SSI_SDATA8_C, + FN_DREQ2_N, FN_HSCK1_B, FN_HCTS0_N_B, + FN_MSIOF0_TXD_B, FN_DACK2, FN_IRQ2, FN_INTC_IRQ2_N, + FN_SSI_SDATA6_B, FN_HRTS0_N_B, FN_MSIOF0_RXD_B, + FN_ETH_CRS_DV, FN_RMII_CRS_DV, FN_STP_ISCLK_0_B, + FN_TS_SDEN0_D, FN_GLO_Q0_C, FN_SCL2_E, + FN_SCL2_CIS_E, FN_ETH_RX_ER, FN_RMII_RX_ER, + FN_STP_ISD_0_B, FN_TS_SPSYNC0_D, FN_GLO_Q1_C, + FN_SDA2_E, FN_SDA2_CIS_E, FN_ETH_RXD0, FN_RMII_RXD0, + FN_STP_ISEN_0_B, FN_TS_SDAT0_D, FN_GLO_I0_C, + FN_SCIFB1_SCK_G, FN_SCK1_E, FN_ETH_RXD1, + FN_RMII_RXD1, FN_HRX0_E, FN_STP_ISSYNC_0_B, + FN_TS_SCK0_D, FN_GLO_I1_C, FN_SCIFB1_RXD_G, + FN_RX1_E, FN_ETH_LINK, FN_RMII_LINK, FN_HTX0_E, + FN_STP_IVCXO27_0_B, FN_SCIFB1_TXD_G, FN_TX1_E, + FN_ETH_REF_CLK, FN_RMII_REF_CLK, FN_HCTS0_N_E, + FN_STP_IVCXO27_1_B, FN_HRX0_F, + + /* IPSR7 */ + FN_ETH_MDIO, FN_RMII_MDIO, FN_HRTS0_N_E, + FN_SIM0_D_C, FN_HCTS0_N_F, FN_ETH_TXD1, + FN_RMII_TXD1, FN_HTX0_F, FN_BPFCLK_G, FN_RDS_CLK_F, + FN_ETH_TX_EN, FN_RMII_TX_EN, FN_SIM0_CLK_C, + FN_HRTS0_N_F, FN_ETH_MAGIC, FN_RMII_MAGIC, + FN_SIM0_RST_C, FN_ETH_TXD0, FN_RMII_TXD0, + FN_STP_ISCLK_1_B, FN_TS_SDEN1_C, FN_GLO_SCLK_C, + FN_ETH_MDC, FN_RMII_MDC, FN_STP_ISD_1_B, + FN_TS_SPSYNC1_C, FN_GLO_SDATA_C, FN_PWM0, + FN_SCIFA2_SCK_C, FN_STP_ISEN_1_B, FN_TS_SDAT1_C, + FN_GLO_SS_C, FN_PWM1, FN_SCIFA2_TXD_C, + FN_STP_ISSYNC_1_B, FN_TS_SCK1_C, FN_GLO_RFON_C, + FN_PCMOE_N, FN_PWM2, FN_PWMFSW0, FN_SCIFA2_RXD_C, + FN_PCMWE_N, FN_IECLK_C, FN_DU1_DOTCLKIN, + FN_AUDIO_CLKC, FN_AUDIO_CLKOUT_C, FN_VI0_CLK, + FN_ATACS00_N, FN_AVB_RXD1, FN_MII_RXD1, + FN_VI0_DATA0_VI0_B0, FN_ATACS10_N, FN_AVB_RXD2, + FN_MII_RXD2, + + /* IPSR8 - IPSR16 */ + + FN_SEL_SCIF1_0, FN_SEL_SCIF1_1, FN_SEL_SCIF1_2, FN_SEL_SCIF1_3, + FN_SEL_SCIF1_4, + FN_SEL_SCIFB_0, FN_SEL_SCIFB_1, FN_SEL_SCIFB_2, + FN_SEL_SCIFB2_0, FN_SEL_SCIFB2_1, FN_SEL_SCIFB2_2, + FN_SEL_SCIFB1_0, FN_SEL_SCIFB1_1, FN_SEL_SCIFB1_2, FN_SEL_SCIFB1_3, + FN_SEL_SCIFB1_4, + FN_SEL_SCIFB1_5, FN_SEL_SCIFB1_6, + FN_SEL_SCIFA1_0, FN_SEL_SCIFA1_1, FN_SEL_SCIFA1_2, FN_SEL_SCIFA1_3, + FN_SEL_SCIF0_0, FN_SEL_SCIF0_1, + FN_SEL_SCFA_0, FN_SEL_SCFA_1, + FN_SEL_SOF1_0, FN_SEL_SOF1_1, + FN_SEL_SSI7_0, FN_SEL_SSI7_1, FN_SEL_SSI7_2, + FN_SEL_SSI6_0, FN_SEL_SSI6_1, + FN_SEL_SSI5_0, FN_SEL_SSI5_1, FN_SEL_SSI5_2, + FN_SEL_VI3_0, FN_SEL_VI3_1, + FN_SEL_VI2_0, FN_SEL_VI2_1, + FN_SEL_VI1_0, FN_SEL_VI1_1, + FN_SEL_VI0_0, FN_SEL_VI0_1, + FN_SEL_TSIF1_0, FN_SEL_TSIF1_1, FN_SEL_TSIF1_2, + FN_SEL_LBS_0, FN_SEL_LBS_1, + FN_SEL_TSIF0_0, FN_SEL_TSIF0_1, FN_SEL_TSIF0_2, FN_SEL_TSIF0_3, + FN_SEL_SOF3_0, FN_SEL_SOF3_1, + FN_SEL_SOF0_0, FN_SEL_SOF0_1, + + FN_SEL_TMU1_0, FN_SEL_TMU1_1, + FN_SEL_HSCIF1_0, FN_SEL_HSCIF1_1, + FN_SEL_SCIFCLK_0, FN_SEL_SCIFCLK_1, + FN_SEL_CAN0_0, FN_SEL_CAN0_1, FN_SEL_CAN0_2, FN_SEL_CAN0_3, + FN_SEL_CANCLK_0, FN_SEL_CANCLK_1, + FN_SEL_SCIFA2_0, FN_SEL_SCIFA2_1, FN_SEL_SCIFA2_2, + FN_SEL_CAN1_0, FN_SEL_CAN1_1, + FN_SEL_ADI_0, FN_SEL_ADI_1, + FN_SEL_SSP_0, FN_SEL_SSP_1, + FN_SEL_FM_0, FN_SEL_FM_1, FN_SEL_FM_2, FN_SEL_FM_3, + FN_SEL_FM_4, FN_SEL_FM_5, FN_SEL_FM_6, + FN_SEL_HSCIF0_0, FN_SEL_HSCIF0_1, FN_SEL_HSCIF0_2, FN_SEL_HSCIF0_3, + FN_SEL_HSCIF0_4, FN_SEL_HSCIF0_5, + FN_SEL_GPS_0, FN_SEL_GPS_1, FN_SEL_GPS_2, + FN_SEL_RDS_0, FN_SEL_RDS_1, FN_SEL_RDS_2, + FN_SEL_RDS_3, FN_SEL_RDS_4, FN_SEL_RDS_5, + FN_SEL_SIM_0, FN_SEL_SIM_1, FN_SEL_SIM_2, + FN_SEL_SSI8_0, FN_SEL_SSI8_1, FN_SEL_SSI8_2, + + FN_SEL_IICDVFS_0, FN_SEL_IICDVFS_1, + FN_SEL_IIC0_0, FN_SEL_IIC0_1, + FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2, + FN_SEL_IIC2_0, FN_SEL_IIC2_1, FN_SEL_IIC2_2, FN_SEL_IIC2_3, + FN_SEL_IIC2_4, + FN_SEL_IIC1_0, FN_SEL_IIC1_1, FN_SEL_IIC1_2, + FN_SEL_I2C2_0, FN_SEL_I2C2_1, FN_SEL_I2C2_2, FN_SEL_I2C2_3, + FN_SEL_I2C2_4, + FN_SEL_I2C1_0, FN_SEL_I2C1_1, FN_SEL_I2C1_2, + + PINMUX_FUNCTION_END, + + PINMUX_MARK_BEGIN, + + DACK0_MARK, IRQ0_MARK, INTC_IRQ0_N_MARK, SSI_SCK6_B_MARK, + VI1_VSYNC_N_MARK, VI1_VSYNC_N_B_MARK, SSI_WS78_C_MARK, + DREQ1_N_MARK, VI1_CLKENB_MARK, VI1_CLKENB_B_MARK, + SSI_SDATA7_C_MARK, SSI_SCK78_B_MARK, DACK1_MARK, IRQ1_MARK, + INTC_IRQ1_N_MARK, SSI_WS6_B_MARK, SSI_SDATA8_C_MARK, + DREQ2_N_MARK, HSCK1_B_MARK, HCTS0_N_B_MARK, + MSIOF0_TXD_B_MARK, DACK2_MARK, IRQ2_MARK, INTC_IRQ2_N_MARK, + SSI_SDATA6_B_MARK, HRTS0_N_B_MARK, MSIOF0_RXD_B_MARK, + ETH_CRS_DV_MARK, RMII_CRS_DV_MARK, STP_ISCLK_0_B_MARK, + TS_SDEN0_D_MARK, GLO_Q0_C_MARK, SCL2_E_MARK, + SCL2_CIS_E_MARK, ETH_RX_ER_MARK, RMII_RX_ER_MARK, + STP_ISD_0_B_MARK, TS_SPSYNC0_D_MARK, GLO_Q1_C_MARK, + SDA2_E_MARK, SDA2_CIS_E_MARK, ETH_RXD0_MARK, RMII_RXD0_MARK, + STP_ISEN_0_B_MARK, TS_SDAT0_D_MARK, GLO_I0_C_MARK, + SCIFB1_SCK_G_MARK, SCK1_E_MARK, ETH_RXD1_MARK, + RMII_RXD1_MARK, HRX0_E_MARK, STP_ISSYNC_0_B_MARK, + TS_SCK0_D_MARK, GLO_I1_C_MARK, SCIFB1_RXD_G_MARK, + RX1_E_MARK, ETH_LINK_MARK, RMII_LINK_MARK, HTX0_E_MARK, + STP_IVCXO27_0_B_MARK, SCIFB1_TXD_G_MARK, TX1_E_MARK, + ETH_REF_CLK_MARK, RMII_REF_CLK_MARK, HCTS0_N_E_MARK, + STP_IVCXO27_1_B_MARK, HRX0_F_MARK, + + ETH_MDIO_MARK, RMII_MDIO_MARK, HRTS0_N_E_MARK, + SIM0_D_C_MARK, HCTS0_N_F_MARK, ETH_TXD1_MARK, + RMII_TXD1_MARK, HTX0_F_MARK, BPFCLK_G_MARK, RDS_CLK_F_MARK, + ETH_TX_EN_MARK, RMII_TX_EN_MARK, SIM0_CLK_C_MARK, + HRTS0_N_F_MARK, ETH_MAGIC_MARK, RMII_MAGIC_MARK, + SIM0_RST_C_MARK, ETH_TXD0_MARK, RMII_TXD0_MARK, + STP_ISCLK_1_B_MARK, TS_SDEN1_C_MARK, GLO_SCLK_C_MARK, + ETH_MDC_MARK, RMII_MDC_MARK, STP_ISD_1_B_MARK, + TS_SPSYNC1_C_MARK, GLO_SDATA_C_MARK, PWM0_MARK, + SCIFA2_SCK_C_MARK, STP_ISEN_1_B_MARK, TS_SDAT1_C_MARK, + GLO_SS_C_MARK, PWM1_MARK, SCIFA2_TXD_C_MARK, + STP_ISSYNC_1_B_MARK, TS_SCK1_C_MARK, GLO_RFON_C_MARK, + PCMOE_N_MARK, PWM2_MARK, PWMFSW0_MARK, SCIFA2_RXD_C_MARK, + PCMWE_N_MARK, IECLK_C_MARK, DU1_DOTCLKIN_MARK, + AUDIO_CLKC_MARK, AUDIO_CLKOUT_C_MARK, VI0_CLK_MARK, + ATACS00_N_MARK, AVB_RXD1_MARK, MII_RXD1_MARK, + VI0_DATA0_VI0_B0_MARK, ATACS10_N_MARK, AVB_RXD2_MARK, + MII_RXD2_MARK, + + PINMUX_MARK_END, +}; + +static pinmux_enum_t pinmux_data[] = { + PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */ + + PINMUX_IPSR_DATA(IP6_2_0, DACK0), + PINMUX_IPSR_DATA(IP6_2_0, IRQ0), + PINMUX_IPSR_DATA(IP6_2_0, INTC_IRQ0_N), + PINMUX_IPSR_MODSEL_DATA(IP6_2_0, SSI_SCK6_B, SEL_SSI6_1), + PINMUX_IPSR_MODSEL_DATA(IP6_2_0, VI1_VSYNC_N, SEL_VI1_0), + PINMUX_IPSR_MODSEL_DATA(IP6_2_0, VI1_VSYNC_N_B, SEL_VI1_1), + PINMUX_IPSR_MODSEL_DATA(IP6_2_0, SSI_WS78_C, SEL_SSI7_2), + PINMUX_IPSR_DATA(IP6_5_3, DREQ1_N), + PINMUX_IPSR_MODSEL_DATA(IP6_5_3, VI1_CLKENB, SEL_VI1_0), + PINMUX_IPSR_MODSEL_DATA(IP6_5_3, VI1_CLKENB_B, SEL_VI1_1), + PINMUX_IPSR_MODSEL_DATA(IP6_5_3, SSI_SDATA7_C, SEL_SSI7_2), + PINMUX_IPSR_MODSEL_DATA(IP6_5_3, SSI_SCK78_B, SEL_SSI7_1), + PINMUX_IPSR_DATA(IP6_8_6, DACK1), + PINMUX_IPSR_DATA(IP6_8_6, IRQ1), + PINMUX_IPSR_DATA(IP6_8_6, INTC_IRQ1_N), + PINMUX_IPSR_MODSEL_DATA(IP6_8_6, SSI_WS6_B, SEL_SSI6_1), + PINMUX_IPSR_MODSEL_DATA(IP6_8_6, SSI_SDATA8_C, SEL_SSI8_2), + PINMUX_IPSR_DATA(IP6_10_9, DREQ2_N), + PINMUX_IPSR_MODSEL_DATA(IP6_10_9, HSCK1_B, SEL_HSCIF1_1), + PINMUX_IPSR_MODSEL_DATA(IP6_10_9, HCTS0_N_B, SEL_HSCIF0_1), + PINMUX_IPSR_MODSEL_DATA(IP6_10_9, MSIOF0_TXD_B, SEL_SOF0_1), + PINMUX_IPSR_DATA(IP6_13_11, DACK2), + PINMUX_IPSR_DATA(IP6_13_11, IRQ2), + PINMUX_IPSR_DATA(IP6_13_11, INTC_IRQ2_N), + PINMUX_IPSR_MODSEL_DATA(IP6_13_11, SSI_SDATA6_B, SEL_SSI6_1), + PINMUX_IPSR_MODSEL_DATA(IP6_13_11, HRTS0_N_B, SEL_HSCIF0_1), + PINMUX_IPSR_MODSEL_DATA(IP6_13_11, MSIOF0_RXD_B, SEL_SOF0_1), + PINMUX_IPSR_DATA(IP6_16_14, ETH_CRS_DV), + PINMUX_IPSR_DATA(IP6_16_14, RMII_CRS_DV), + PINMUX_IPSR_MODSEL_DATA(IP6_16_14, STP_ISCLK_0_B, SEL_SSP_1), + PINMUX_IPSR_MODSEL_DATA(IP6_16_14, TS_SDEN0_D, SEL_TSIF0_3), + PINMUX_IPSR_MODSEL_DATA(IP6_16_14, GLO_Q0_C, SEL_GPS_2), + PINMUX_IPSR_MODSEL_DATA(IP6_16_14, SCL2_E, SEL_IIC2_4), + PINMUX_IPSR_MODSEL_DATA(IP6_16_14, SCL2_CIS_E, SEL_I2C2_4), + PINMUX_IPSR_DATA(IP6_19_17, ETH_RX_ER), + PINMUX_IPSR_DATA(IP6_19_17, RMII_RX_ER), + PINMUX_IPSR_MODSEL_DATA(IP6_19_17, STP_ISD_0_B, SEL_SSP_1), + PINMUX_IPSR_MODSEL_DATA(IP6_19_17, TS_SPSYNC0_D, SEL_TSIF0_3), + PINMUX_IPSR_MODSEL_DATA(IP6_19_17, GLO_Q1_C, SEL_GPS_2), + PINMUX_IPSR_MODSEL_DATA(IP6_19_17, SDA2_E, SEL_IIC2_4), + PINMUX_IPSR_MODSEL_DATA(IP6_19_17, SDA2_CIS_E, SEL_I2C2_4), + PINMUX_IPSR_DATA(IP6_22_20, ETH_RXD0), + PINMUX_IPSR_DATA(IP6_22_20, RMII_RXD0), + PINMUX_IPSR_MODSEL_DATA(IP6_22_20, STP_ISEN_0_B, SEL_SSP_1), + PINMUX_IPSR_MODSEL_DATA(IP6_22_20, TS_SDAT0_D, SEL_TSIF0_3), + PINMUX_IPSR_MODSEL_DATA(IP6_22_20, GLO_I0_C, SEL_GPS_2), + PINMUX_IPSR_MODSEL_DATA(IP6_22_20, SCIFB1_SCK_G, SEL_SCIFB1_6), + PINMUX_IPSR_MODSEL_DATA(IP6_22_20, SCK1_E, SEL_SCIF1_4), + PINMUX_IPSR_DATA(IP6_25_23, ETH_RXD1), + PINMUX_IPSR_DATA(IP6_25_23, RMII_RXD1), + PINMUX_IPSR_MODSEL_DATA(IP6_25_23, HRX0_E, SEL_HSCIF0_4), + PINMUX_IPSR_MODSEL_DATA(IP6_25_23, STP_ISSYNC_0_B, SEL_SSP_1), + PINMUX_IPSR_MODSEL_DATA(IP6_25_23, TS_SCK0_D, SEL_TSIF0_3), + PINMUX_IPSR_MODSEL_DATA(IP6_25_23, GLO_I1_C, SEL_GPS_2), + PINMUX_IPSR_MODSEL_DATA(IP6_25_23, SCIFB1_RXD_G, SEL_SCIFB1_6), + PINMUX_IPSR_MODSEL_DATA(IP6_25_23, RX1_E, SEL_SCIF1_4), + PINMUX_IPSR_DATA(IP6_28_26, ETH_LINK), + PINMUX_IPSR_DATA(IP6_28_26, RMII_LINK), + PINMUX_IPSR_MODSEL_DATA(IP6_28_26, HTX0_E, SEL_HSCIF0_4), + PINMUX_IPSR_MODSEL_DATA(IP6_28_26, STP_IVCXO27_0_B, SEL_SSP_1), + PINMUX_IPSR_MODSEL_DATA(IP6_28_26, SCIFB1_TXD_G, SEL_SCIFB1_6), + PINMUX_IPSR_MODSEL_DATA(IP6_28_26, TX1_E, SEL_SCIF1_4), + PINMUX_IPSR_DATA(IP6_31_29, ETH_REF_CLK), + PINMUX_IPSR_DATA(IP6_31_29, RMII_REF_CLK), + PINMUX_IPSR_MODSEL_DATA(IP6_31_29, HCTS0_N_E, SEL_HSCIF0_4), + PINMUX_IPSR_MODSEL_DATA(IP6_31_29, STP_IVCXO27_1_B, SEL_SSP_1), + PINMUX_IPSR_MODSEL_DATA(IP6_31_29, HRX0_F, SEL_HSCIF0_5), + + PINMUX_IPSR_DATA(IP7_2_0, ETH_MDIO), + PINMUX_IPSR_DATA(IP7_2_0, RMII_MDIO), + PINMUX_IPSR_MODSEL_DATA(IP7_2_0, HRTS0_N_E, SEL_HSCIF0_4), + PINMUX_IPSR_MODSEL_DATA(IP7_2_0, SIM0_D_C, SEL_SIM_2), + PINMUX_IPSR_MODSEL_DATA(IP7_2_0, HCTS0_N_F, SEL_HSCIF0_5), + PINMUX_IPSR_DATA(IP7_5_3, ETH_TXD1), + PINMUX_IPSR_DATA(IP7_5_3, RMII_TXD1), + PINMUX_IPSR_MODSEL_DATA(IP7_5_3, HTX0_F, SEL_HSCIF0_4), + PINMUX_IPSR_MODSEL_DATA(IP7_5_3, BPFCLK_G, SEL_SIM_2), + PINMUX_IPSR_MODSEL_DATA(IP7_5_3, RDS_CLK_F, SEL_HSCIF0_5), + PINMUX_IPSR_DATA(IP7_7_6, ETH_TX_EN), + PINMUX_IPSR_DATA(IP7_7_6, RMII_TX_EN), + PINMUX_IPSR_MODSEL_DATA(IP7_7_6, SIM0_CLK_C, SEL_SIM_2), + PINMUX_IPSR_MODSEL_DATA(IP7_7_6, HRTS0_N_F, SEL_HSCIF0_5), + PINMUX_IPSR_DATA(IP7_9_8, ETH_MAGIC), + PINMUX_IPSR_DATA(IP7_9_8, RMII_MAGIC), + PINMUX_IPSR_MODSEL_DATA(IP7_9_8, SIM0_RST_C, SEL_SIM_2), + PINMUX_IPSR_DATA(IP7_12_10, ETH_TXD0), + PINMUX_IPSR_DATA(IP7_12_10, RMII_TXD0), + PINMUX_IPSR_MODSEL_DATA(IP7_12_10, STP_ISCLK_1_B, SEL_SSP_1), + PINMUX_IPSR_MODSEL_DATA(IP7_12_10, TS_SDEN1_C, SEL_TSIF1_2), + PINMUX_IPSR_MODSEL_DATA(IP7_12_10, GLO_SCLK_C, SEL_GPS_2), + PINMUX_IPSR_DATA(IP7_15_13, ETH_MDC), + PINMUX_IPSR_DATA(IP7_15_13, RMII_MDC), + PINMUX_IPSR_MODSEL_DATA(IP7_15_13, STP_ISD_1_B, SEL_SSP_1), + PINMUX_IPSR_MODSEL_DATA(IP7_15_13, TS_SPSYNC1_C, SEL_TSIF1_2), + PINMUX_IPSR_MODSEL_DATA(IP7_15_13, GLO_SDATA_C, SEL_GPS_2), + PINMUX_IPSR_DATA(IP7_18_16, PWM0), + PINMUX_IPSR_MODSEL_DATA(IP7_18_16, SCIFA2_SCK_C, SEL_SCIFA2_2), + PINMUX_IPSR_MODSEL_DATA(IP7_18_16, STP_ISEN_1_B, SEL_SSP_1), + PINMUX_IPSR_MODSEL_DATA(IP7_18_16, TS_SDAT1_C, SEL_TSIF1_2), + PINMUX_IPSR_MODSEL_DATA(IP7_18_16, GLO_SS_C, SEL_GPS_2), + PINMUX_IPSR_DATA(IP7_21_19, PWM1), + PINMUX_IPSR_MODSEL_DATA(IP7_21_19, SCIFA2_TXD_C, SEL_SCIFA2_2), + PINMUX_IPSR_MODSEL_DATA(IP7_21_19, STP_ISSYNC_1_B, SEL_SSP_1), + PINMUX_IPSR_MODSEL_DATA(IP7_21_19, TS_SCK1_C, SEL_TSIF1_2), + PINMUX_IPSR_MODSEL_DATA(IP7_21_19, GLO_RFON_C, SEL_GPS_2), + PINMUX_IPSR_DATA(IP7_21_19, PCMOE_N), + PINMUX_IPSR_DATA(IP7_24_22, PWM2), + PINMUX_IPSR_DATA(IP7_24_22, PWMFSW0), + PINMUX_IPSR_MODSEL_DATA(IP7_24_22, SCIFA2_RXD_C, SEL_SCIFA2_2), + PINMUX_IPSR_DATA(IP7_24_22, PCMWE_N), + PINMUX_IPSR_MODSEL_DATA(IP7_24_22, IECLK_C, SEL_IEB_2), + PINMUX_IPSR_DATA(IP7_26_25, DU1_DOTCLKIN), + PINMUX_IPSR_DATA(IP7_26_25, AUDIO_CLKC), + PINMUX_IPSR_DATA(IP7_26_25, AUDIO_CLKOUT_C), + PINMUX_IPSR_MODSEL_DATA(IP7_28_27, VI0_CLK, SEL_VI0_0), + PINMUX_IPSR_DATA(IP7_28_27, ATACS00_N), + PINMUX_IPSR_DATA(IP7_28_27, AVB_RXD1), + PINMUX_IPSR_DATA(IP7_28_27, MII_RXD1), + PINMUX_IPSR_MODSEL_DATA(IP7_30_29, VI0_DATA0_VI0_B0, SEL_VI0_0), + PINMUX_IPSR_DATA(IP7_30_29, ATACS10_N), + PINMUX_IPSR_DATA(IP7_30_29, AVB_RXD2), + PINMUX_IPSR_DATA(IP7_30_29, MII_RXD2), + +}; + +static struct pinmux_gpio pinmux_gpios[] = { + PINMUX_GPIO_GP_ALL(), + + /*IPSR0 - IPSR5*/ + /*IPSR6*/ + GPIO_FN(DACK0), GPIO_FN(IRQ0), GPIO_FN(INTC_IRQ0_N), + GPIO_FN(SSI_SCK6_B), GPIO_FN(VI1_VSYNC_N), GPIO_FN(VI1_VSYNC_N_B), + GPIO_FN(SSI_WS78_C), GPIO_FN(DREQ1_N), GPIO_FN(VI1_CLKENB), + GPIO_FN(VI1_CLKENB_B), GPIO_FN(SSI_SDATA7_C), GPIO_FN(SSI_SCK78_B), + GPIO_FN(DACK1), GPIO_FN(IRQ1), GPIO_FN(INTC_IRQ1_N), GPIO_FN(SSI_WS6_B), + GPIO_FN(SSI_SDATA8_C), GPIO_FN(DREQ2_N), GPIO_FN(HSCK1_B), + GPIO_FN(HCTS0_N_B), GPIO_FN(MSIOF0_TXD_B), GPIO_FN(DACK2), + GPIO_FN(IRQ2), GPIO_FN(INTC_IRQ2_N), GPIO_FN(SSI_SDATA6_B), + GPIO_FN(HRTS0_N_B), GPIO_FN(MSIOF0_RXD_B), GPIO_FN(ETH_CRS_DV), + GPIO_FN(RMII_CRS_DV), GPIO_FN(STP_ISCLK_0_B), GPIO_FN(TS_SDEN0_D), + GPIO_FN(GLO_Q0_C), GPIO_FN(SCL2_E), GPIO_FN(SCL2_CIS_E), + GPIO_FN(ETH_RX_ER), GPIO_FN(RMII_RX_ER), GPIO_FN(STP_ISD_0_B), + GPIO_FN(TS_SPSYNC0_D), GPIO_FN(GLO_Q1_C), GPIO_FN(SDA2_E), + GPIO_FN(SDA2_CIS_E), GPIO_FN(ETH_RXD0), GPIO_FN(RMII_RXD0), + GPIO_FN(STP_ISEN_0_B), GPIO_FN(TS_SDAT0_D), GPIO_FN(GLO_I0_C), + GPIO_FN(SCIFB1_SCK_G), GPIO_FN(SCK1_E), GPIO_FN(ETH_RXD1), + GPIO_FN(RMII_RXD1), GPIO_FN(HRX0_E), GPIO_FN(STP_ISSYNC_0_B), + GPIO_FN(TS_SCK0_D), GPIO_FN(GLO_I1_C), GPIO_FN(SCIFB1_RXD_G), + GPIO_FN(RX1_E), GPIO_FN(ETH_LINK), GPIO_FN(RMII_LINK), GPIO_FN(HTX0_E), + GPIO_FN(STP_IVCXO27_0_B), GPIO_FN(SCIFB1_TXD_G), GPIO_FN(TX1_E), + GPIO_FN(ETH_REF_CLK), GPIO_FN(RMII_REF_CLK), GPIO_FN(HCTS0_N_E), + GPIO_FN(STP_IVCXO27_1_B), GPIO_FN(HRX0_F), + + /*IPSR7*/ + GPIO_FN(ETH_MDIO), GPIO_FN(RMII_MDIO), GPIO_FN(HRTS0_N_E), + GPIO_FN(SIM0_D_C), GPIO_FN(HCTS0_N_F), GPIO_FN(ETH_TXD1), + GPIO_FN(RMII_TXD1), GPIO_FN(HTX0_F), GPIO_FN(BPFCLK_G), + GPIO_FN(RDS_CLK_F), GPIO_FN(ETH_TX_EN), GPIO_FN(RMII_TX_EN), + GPIO_FN(SIM0_CLK_C), GPIO_FN(HRTS0_N_F), GPIO_FN(ETH_MAGIC), + GPIO_FN(RMII_MAGIC), GPIO_FN(SIM0_RST_C), GPIO_FN(ETH_TXD0), + GPIO_FN(RMII_TXD0), GPIO_FN(STP_ISCLK_1_B), GPIO_FN(TS_SDEN1_C), + GPIO_FN(GLO_SCLK_C), GPIO_FN(ETH_MDC), GPIO_FN(RMII_MDC), + GPIO_FN(STP_ISD_1_B), GPIO_FN(TS_SPSYNC1_C), GPIO_FN(GLO_SDATA_C), + GPIO_FN(PWM0), GPIO_FN(SCIFA2_SCK_C), GPIO_FN(STP_ISEN_1_B), + GPIO_FN(TS_SDAT1_C), GPIO_FN(GLO_SS_C), GPIO_FN(PWM1), + GPIO_FN(SCIFA2_TXD_C), GPIO_FN(STP_ISSYNC_1_B), GPIO_FN(TS_SCK1_C), + GPIO_FN(GLO_RFON_C), GPIO_FN(PCMOE_N), GPIO_FN(PWM2), GPIO_FN(PWMFSW0), + GPIO_FN(SCIFA2_RXD_C), GPIO_FN(PCMWE_N), GPIO_FN(IECLK_C), + GPIO_FN(DU1_DOTCLKIN), GPIO_FN(AUDIO_CLKC), GPIO_FN(AUDIO_CLKOUT_C), + GPIO_FN(VI0_CLK), GPIO_FN(ATACS00_N), GPIO_FN(AVB_RXD1), + GPIO_FN(MII_RXD1), GPIO_FN(VI0_DATA0_VI0_B0), GPIO_FN(ATACS10_N), + GPIO_FN(AVB_RXD2), GPIO_FN(MII_RXD2), + /*IPSR8 - IPSR16*/ +}; + +static struct pinmux_cfg_reg pinmux_config_regs[] = { + { PINMUX_CFG_REG("GPSR0", 0xE6060004, 32, 1) { + GP_0_31_FN, FN_IP3_17_15, + GP_0_30_FN, FN_IP3_14_12, + GP_0_29_FN, FN_IP3_11_8, + GP_0_28_FN, FN_IP3_7_4, + GP_0_27_FN, FN_IP3_3_0, + GP_0_26_FN, FN_IP2_28_26, + GP_0_25_FN, FN_IP2_25_22, + GP_0_24_FN, FN_IP2_21_18, + GP_0_23_FN, FN_IP2_17_15, + GP_0_22_FN, FN_IP2_14_12, + GP_0_21_FN, FN_IP2_11_9, + GP_0_20_FN, FN_IP2_8_6, + GP_0_19_FN, FN_IP2_5_3, + GP_0_18_FN, FN_IP2_2_0, + GP_0_17_FN, FN_IP1_29_28, + GP_0_16_FN, FN_IP1_27_26, + GP_0_15_FN, FN_IP1_25_22, + GP_0_14_FN, FN_IP1_21_18, + GP_0_13_FN, FN_IP1_17_15, + GP_0_12_FN, FN_IP1_14_12, + GP_0_11_FN, FN_IP1_11_8, + GP_0_10_FN, FN_IP1_7_4, + GP_0_9_FN, FN_IP1_3_0, + GP_0_8_FN, FN_IP0_30_27, + GP_0_7_FN, FN_IP0_26_23, + GP_0_6_FN, FN_IP0_22_20, + GP_0_5_FN, FN_IP0_19_16, + GP_0_4_FN, FN_IP0_15_12, + GP_0_3_FN, FN_IP0_11_9, + GP_0_2_FN, FN_IP0_8_6, + GP_0_1_FN, FN_IP0_5_3, + GP_0_0_FN, FN_IP0_2_0 } + }, + { PINMUX_CFG_REG("GPSR1", 0xE6060008, 32, 1) { + 0, 0, + 0, 0, + GP_1_29_FN, FN_IP6_13_11, + GP_1_28_FN, FN_IP6_10_9, + GP_1_27_FN, FN_IP6_8_6, + GP_1_26_FN, FN_IP6_5_3, + GP_1_25_FN, FN_IP6_2_0, + GP_1_24_FN, FN_IP5_29_27, + GP_1_23_FN, FN_IP5_26_24, + GP_1_22_FN, FN_IP5_23_21, + GP_1_21_FN, FN_IP5_20_18, + GP_1_20_FN, FN_IP5_17_15, + GP_1_19_FN, FN_IP5_14_13, + GP_1_18_FN, FN_IP5_12_10, + GP_1_17_FN, FN_IP5_9_6, + GP_1_16_FN, FN_IP5_5_3, + GP_1_15_FN, FN_IP5_2_0, + GP_1_14_FN, FN_IP4_29_27, + GP_1_13_FN, FN_IP4_26_24, + GP_1_12_FN, FN_IP4_23_21, + GP_1_11_FN, FN_IP4_20_18, + GP_1_10_FN, FN_IP4_17_15, + GP_1_9_FN, FN_IP4_14_12, + GP_1_8_FN, FN_IP4_11_9, + GP_1_7_FN, FN_IP4_8_6, + GP_1_6_FN, FN_IP4_5_3, + GP_1_5_FN, FN_IP4_2_0, + GP_1_4_FN, FN_IP3_31_29, + GP_1_3_FN, FN_IP3_28_26, + GP_1_2_FN, FN_IP3_25_23, + GP_1_1_FN, FN_IP3_22_20, + GP_1_0_FN, FN_IP3_19_18, } + }, + { PINMUX_CFG_REG("GPSR2", 0xE606000C, 32, 1) { + 0, 0, + 0, 0, + GP_2_29_FN, FN_IP7_15_13, + GP_2_28_FN, FN_IP7_12_10, + GP_2_27_FN, FN_IP7_9_8, + GP_2_26_FN, FN_IP7_7_6, + GP_2_25_FN, FN_IP7_5_3, + GP_2_24_FN, FN_IP7_2_0, + GP_2_23_FN, FN_IP6_31_29, + GP_2_22_FN, FN_IP6_28_26, + GP_2_21_FN, FN_IP6_25_23, + GP_2_20_FN, FN_IP6_22_20, + GP_2_19_FN, FN_IP6_19_17, + GP_2_18_FN, FN_IP6_16_14, + GP_2_17_FN, FN_VI1_DATA7_VI1_B7, + GP_2_16_FN, FN_IP8_27, + GP_2_15_FN, FN_IP8_26, + GP_2_14_FN, FN_IP8_25_24, + GP_2_13_FN, FN_IP8_23_22, + GP_2_12_FN, FN_IP8_21_20, + GP_2_11_FN, FN_IP8_19_18, + GP_2_10_FN, FN_IP8_17_16, + GP_2_9_FN, FN_IP8_15_14, + GP_2_8_FN, FN_IP8_13_12, + GP_2_7_FN, FN_IP8_11_10, + GP_2_6_FN, FN_IP8_9_8, + GP_2_5_FN, FN_IP8_7_6, + GP_2_4_FN, FN_IP8_5_4, + GP_2_3_FN, FN_IP8_3_2, + GP_2_2_FN, FN_IP8_1_0, + GP_2_1_FN, FN_IP7_30_29, + GP_2_0_FN, FN_IP7_28_27 } + }, + { PINMUX_CFG_REG("GPSR3", 0xE6060010, 32, 1) { + GP_3_31_FN, FN_IP11_21_18, + GP_3_30_FN, FN_IP11_17_15, + GP_3_29_FN, FN_IP11_14_13, + GP_3_28_FN, FN_IP11_12_11, + GP_3_27_FN, FN_IP11_10_9, + GP_3_26_FN, FN_IP11_8_7, + GP_3_25_FN, FN_IP11_6_5, + GP_3_24_FN, FN_IP11_4, + GP_3_23_FN, FN_IP11_3_0, + GP_3_22_FN, FN_IP10_29_26, + GP_3_21_FN, FN_IP10_25_23, + GP_3_20_FN, FN_IP10_22_19, + GP_3_19_FN, FN_IP10_18_15, + GP_3_18_FN, FN_IP10_14_11, + GP_3_17_FN, FN_IP10_10_7, + GP_3_16_FN, FN_IP10_6_4, + GP_3_15_FN, FN_IP10_3_0, + GP_3_14_FN, FN_IP9_31_28, + GP_3_13_FN, FN_IP9_27_26, + GP_3_12_FN, FN_IP9_25_24, + GP_3_11_FN, FN_IP9_23_22, + GP_3_10_FN, FN_IP9_21_20, + GP_3_9_FN, FN_IP9_19_18, + GP_3_8_FN, FN_IP9_17_16, + GP_3_7_FN, FN_IP9_15_12, + GP_3_6_FN, FN_IP9_11_8, + GP_3_5_FN, FN_IP9_7_6, + GP_3_4_FN, FN_IP9_5_4, + GP_3_3_FN, FN_IP9_3_2, + GP_3_2_FN, FN_IP9_1_0, + GP_3_1_FN, FN_IP8_30_29, + GP_3_0_FN, FN_IP8_28 } + }, + { PINMUX_CFG_REG("GPSR4", 0xE6060014, 32, 1) { + GP_4_31_FN, FN_IP14_18_16, + GP_4_30_FN, FN_IP14_15_12, + GP_4_29_FN, FN_IP14_11_9, + GP_4_28_FN, FN_IP14_8_6, + GP_4_27_FN, FN_IP14_5_3, + GP_4_26_FN, FN_IP14_2_0, + GP_4_25_FN, FN_IP13_30_29, + GP_4_24_FN, FN_IP13_28_26, + GP_4_23_FN, FN_IP13_25_23, + GP_4_22_FN, FN_IP13_22_19, + GP_4_21_FN, FN_IP13_18_16, + GP_4_20_FN, FN_IP13_15_13, + GP_4_19_FN, FN_IP13_12_10, + GP_4_18_FN, FN_IP13_9_7, + GP_4_17_FN, FN_IP13_6_3, + GP_4_16_FN, FN_IP13_2_0, + GP_4_15_FN, FN_IP12_30_28, + GP_4_14_FN, FN_IP12_27_25, + GP_4_13_FN, FN_IP12_24_23, + GP_4_12_FN, FN_IP12_22_20, + GP_4_11_FN, FN_IP12_19_17, + GP_4_10_FN, FN_IP12_16_14, + GP_4_9_FN, FN_IP12_13_11, + GP_4_8_FN, FN_IP12_10_8, + GP_4_7_FN, FN_IP12_7_6, + GP_4_6_FN, FN_IP12_5_4, + GP_4_5_FN, FN_IP12_3_2, + GP_4_4_FN, FN_IP12_1_0, + GP_4_3_FN, FN_IP11_31_30, + GP_4_2_FN, FN_IP11_29_27, + GP_4_1_FN, FN_IP11_26_24, + GP_4_0_FN, FN_IP11_23_22 } + }, + { PINMUX_CFG_REG("GPSR5", 0xE6060018, 32, 1) { + GP_5_31_FN, FN_IP7_24_22, + GP_5_30_FN, FN_IP7_21_19, + GP_5_29_FN, FN_IP7_18_16, + GP_5_28_FN, FN_DU_DOTCLKIN2, + GP_5_27_FN, FN_IP7_26_25, + GP_5_26_FN, FN_DU_DOTCLKIN0, + GP_5_25_FN, FN_AVS2, + GP_5_24_FN, FN_AVS1, + GP_5_23_FN, FN_USB2_OVC, + GP_5_22_FN, FN_USB2_PWEN, + GP_5_21_FN, FN_IP16_7, + GP_5_20_FN, FN_IP16_6, + GP_5_19_FN, FN_USB0_OVC_VBUS, + GP_5_18_FN, FN_USB0_PWEN, + GP_5_17_FN, FN_IP16_5_3, + GP_5_16_FN, FN_IP16_2_0, + GP_5_15_FN, FN_IP15_29_28, + GP_5_14_FN, FN_IP15_27_26, + GP_5_13_FN, FN_IP15_25_23, + GP_5_12_FN, FN_IP15_22_20, + GP_5_11_FN, FN_IP15_19_18, + GP_5_10_FN, FN_IP15_17_16, + GP_5_9_FN, FN_IP15_15_14, + GP_5_8_FN, FN_IP15_13_12, + GP_5_7_FN, FN_IP15_11_9, + GP_5_6_FN, FN_IP15_8_6, + GP_5_5_FN, FN_IP15_5_3, + GP_5_4_FN, FN_IP15_2_0, + GP_5_3_FN, FN_IP14_30_28, + GP_5_2_FN, FN_IP14_27_25, + GP_5_1_FN, FN_IP14_24_22, + GP_5_0_FN, FN_IP14_21_19 } + }, + + /*IPSR0 - IPSR5*/ + { PINMUX_CFG_REG_VAR("IPSR6", 0xE6060038, 32, + 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3) { + /* IP6_31_29 [3] */ + FN_ETH_REF_CLK, FN_RMII_REF_CLK, FN_HCTS0_N_E, + FN_STP_IVCXO27_1_B, FN_HRX0_F, 0, 0, 0, + /* IP6_28_26 [3] */ + FN_ETH_LINK, FN_RMII_LINK, FN_HTX0_E, + FN_STP_IVCXO27_0_B, FN_SCIFB1_TXD_G, FN_TX1_E, 0, 0, + /* IP6_25_23 [3] */ + FN_ETH_RXD1, FN_RMII_RXD1, FN_HRX0_E, FN_STP_ISSYNC_0_B, + FN_TS_SCK0_D, FN_GLO_I1_C, FN_SCIFB1_RXD_G, FN_RX1_E, + /* IP6_22_20 [3] */ + FN_ETH_RXD0, FN_RMII_RXD0, FN_STP_ISEN_0_B, FN_TS_SDAT0_D, + FN_GLO_I0_C, FN_SCIFB1_SCK_G, FN_SCK1_E, 0, + /* IP6_19_17 [3] */ + FN_ETH_RX_ER, FN_RMII_RX_ER, FN_STP_ISD_0_B, + FN_TS_SPSYNC0_D, FN_GLO_Q1_C, FN_SDA2_E, FN_SDA2_CIS_E, 0, + /* IP6_16_14 [3] */ + FN_ETH_CRS_DV, FN_RMII_CRS_DV, FN_STP_ISCLK_0_B, + FN_TS_SDEN0_D, FN_GLO_Q0_C, FN_SCL2_E, + FN_SCL2_CIS_E, 0, + /* IP6_13_11 [3] */ + FN_DACK2, FN_IRQ2, FN_INTC_IRQ2_N, + FN_SSI_SDATA6_B, FN_HRTS0_N_B, FN_MSIOF0_RXD_B, 0, 0, + /* IP6_10_9 [2] */ + FN_DREQ2_N, FN_HSCK1_B, FN_HCTS0_N_B, FN_MSIOF0_TXD_B, + /* IP6_8_6 [3] */ + FN_DACK1, FN_IRQ1, FN_INTC_IRQ1_N, FN_SSI_WS6_B, + FN_SSI_SDATA8_C, 0, 0, 0, + /* IP6_5_3 [3] */ + FN_DREQ1_N, FN_VI1_CLKENB, FN_VI1_CLKENB_B, + FN_SSI_SDATA7_C, FN_SSI_SCK78_B, 0, 0, 0, + /* IP6_2_0 [3] */ + FN_DACK0, FN_IRQ0, FN_INTC_IRQ0_N, FN_SSI_SCK6_B, + FN_VI1_VSYNC_N, FN_VI1_VSYNC_N_B, FN_SSI_WS78_C, 0, } + }, + { PINMUX_CFG_REG_VAR("IPSR7", 0xE606003C, 32, + 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 3, 3) { + /* IP7_31 [1] */ + 0, 0, + /* IP7_30_29 [2] */ + FN_VI0_DATA0_VI0_B0, FN_ATACS10_N, FN_AVB_RXD2, + FN_MII_RXD2, + /* IP7_28_27 [2] */ + FN_VI0_CLK, FN_ATACS00_N, FN_AVB_RXD1, FN_MII_RXD1, + /* IP7_26_25 [2] */ + FN_DU1_DOTCLKIN, FN_AUDIO_CLKC, FN_AUDIO_CLKOUT_C, 0, + /* IP7_24_22 [3] */ + FN_PWM2, FN_PWMFSW0, FN_SCIFA2_RXD_C, FN_PCMWE_N, FN_IECLK_C, + 0, 0, 0, + /* IP7_21_19 [3] */ + FN_PWM1, FN_SCIFA2_TXD_C, FN_STP_ISSYNC_1_B, FN_TS_SCK1_C, + FN_GLO_RFON_C, FN_PCMOE_N, 0, 0, + /* IP7_18_16 [3] */ + FN_PWM0, FN_SCIFA2_SCK_C, FN_STP_ISEN_1_B, FN_TS_SDAT1_C, + FN_GLO_SS_C, 0, 0, 0, + /* IP7_15_13 [3] */ + FN_ETH_MDC, FN_RMII_MDC, FN_STP_ISD_1_B, + FN_TS_SPSYNC1_C, FN_GLO_SDATA_C, 0, 0, 0, + /* IP7_12_10 [3] */ + FN_ETH_TXD0, FN_RMII_TXD0, FN_STP_ISCLK_1_B, FN_TS_SDEN1_C, + FN_GLO_SCLK_C, 0, 0, 0, + /* IP7_9_8 [2] */ + FN_ETH_MAGIC, FN_RMII_MAGIC, FN_SIM0_RST_C, 0, + /* IP7_7_6 [2] */ + FN_ETH_TX_EN, FN_RMII_TX_EN, FN_SIM0_CLK_C, FN_HRTS0_N_F, + /* IP7_5_3 [3] */ + FN_ETH_TXD1, FN_RMII_TXD1, FN_HTX0_F, FN_BPFCLK_G, FN_RDS_CLK_F, + 0, 0, 0, + /* IP7_2_0 [3] */ + FN_ETH_MDIO, FN_RMII_MDIO, FN_HRTS0_N_E, + FN_SIM0_D_C, FN_HCTS0_N_F, 0, 0, 0, } + }, + /*IPSR8 - IPSR16*/ + { PINMUX_CFG_REG("INOUTSEL0", 0xE6050004, 32, 1) { GP_INOUTSEL(0) } }, + { PINMUX_CFG_REG("INOUTSEL1", 0xE6051004, 32, 1) { + 0, 0, + 0, 0, + GP_1_29_IN, GP_1_29_OUT, + GP_1_28_IN, GP_1_28_OUT, + GP_1_27_IN, GP_1_27_OUT, + GP_1_26_IN, GP_1_26_OUT, + GP_1_25_IN, GP_1_25_OUT, + GP_1_24_IN, GP_1_24_OUT, + GP_1_23_IN, GP_1_23_OUT, + GP_1_22_IN, GP_1_22_OUT, + GP_1_21_IN, GP_1_21_OUT, + GP_1_20_IN, GP_1_20_OUT, + GP_1_19_IN, GP_1_19_OUT, + GP_1_18_IN, GP_1_18_OUT, + GP_1_17_IN, GP_1_17_OUT, + GP_1_16_IN, GP_1_16_OUT, + GP_1_15_IN, GP_1_15_OUT, + GP_1_14_IN, GP_1_14_OUT, + GP_1_13_IN, GP_1_13_OUT, + GP_1_12_IN, GP_1_12_OUT, + GP_1_11_IN, GP_1_11_OUT, + GP_1_10_IN, GP_1_10_OUT, + GP_1_9_IN, GP_1_9_OUT, + GP_1_8_IN, GP_1_8_OUT, + GP_1_7_IN, GP_1_7_OUT, + GP_1_6_IN, GP_1_6_OUT, + GP_1_5_IN, GP_1_5_OUT, + GP_1_4_IN, GP_1_4_OUT, + GP_1_3_IN, GP_1_3_OUT, + GP_1_2_IN, GP_1_2_OUT, + GP_1_1_IN, GP_1_1_OUT, + GP_1_0_IN, GP_1_0_OUT, } + }, + { PINMUX_CFG_REG("INOUTSEL2", 0xE6052004, 32, 1) { + 0, 0, + 0, 0, + GP_2_29_IN, GP_2_29_OUT, + GP_2_28_IN, GP_2_28_OUT, + GP_2_27_IN, GP_2_27_OUT, + GP_2_26_IN, GP_2_26_OUT, + GP_2_25_IN, GP_2_25_OUT, + GP_2_24_IN, GP_2_24_OUT, + GP_2_23_IN, GP_2_23_OUT, + GP_2_22_IN, GP_2_22_OUT, + GP_2_21_IN, GP_2_21_OUT, + GP_2_20_IN, GP_2_20_OUT, + GP_2_19_IN, GP_2_19_OUT, + GP_2_18_IN, GP_2_18_OUT, + GP_2_17_IN, GP_2_17_OUT, + GP_2_16_IN, GP_2_16_OUT, + GP_2_15_IN, GP_2_15_OUT, + GP_2_14_IN, GP_2_14_OUT, + GP_2_13_IN, GP_2_13_OUT, + GP_2_12_IN, GP_2_12_OUT, + GP_2_11_IN, GP_2_11_OUT, + GP_2_10_IN, GP_2_10_OUT, + GP_2_9_IN, GP_2_9_OUT, + GP_2_8_IN, GP_2_8_OUT, + GP_2_7_IN, GP_2_7_OUT, + GP_2_6_IN, GP_2_6_OUT, + GP_2_5_IN, GP_2_5_OUT, + GP_2_4_IN, GP_2_4_OUT, + GP_2_3_IN, GP_2_3_OUT, + GP_2_2_IN, GP_2_2_OUT, + GP_2_1_IN, GP_2_1_OUT, + GP_2_0_IN, GP_2_0_OUT, } + }, + { PINMUX_CFG_REG("INOUTSEL3", 0xE6053004, 32, 1) { GP_INOUTSEL(3) } }, + { PINMUX_CFG_REG("INOUTSEL4", 0xE6054004, 32, 1) { GP_INOUTSEL(4) } }, + { PINMUX_CFG_REG("INOUTSEL5", 0xE6055004, 32, 1) { GP_INOUTSEL(5) } }, + { }, +}; + +static struct pinmux_data_reg pinmux_data_regs[] = { + { PINMUX_DATA_REG("INDT0", 0xE6050008, 32) { GP_INDT(0) } }, + { PINMUX_DATA_REG("INDT1", 0xE6051008, 32) { + 0, 0, GP_1_29_DATA, GP_1_28_DATA, + GP_1_27_DATA, GP_1_26_DATA, GP_1_25_DATA, GP_1_24_DATA, + GP_1_23_DATA, GP_1_22_DATA, GP_1_21_DATA, GP_1_20_DATA, + GP_1_19_DATA, GP_1_18_DATA, GP_1_17_DATA, GP_1_16_DATA, + GP_1_15_DATA, GP_1_14_DATA, GP_1_13_DATA, GP_1_12_DATA, + GP_1_11_DATA, GP_1_10_DATA, GP_1_9_DATA, GP_1_8_DATA, + GP_1_7_DATA, GP_1_6_DATA, GP_1_5_DATA, GP_1_4_DATA, + GP_1_3_DATA, GP_1_2_DATA, GP_1_1_DATA, GP_1_0_DATA } + }, + { PINMUX_DATA_REG("INDT2", 0xE6052008, 32) { + 0, 0, GP_2_29_DATA, GP_2_28_DATA, + GP_2_27_DATA, GP_2_26_DATA, GP_2_25_DATA, GP_2_24_DATA, + GP_2_23_DATA, GP_2_22_DATA, GP_2_21_DATA, GP_2_20_DATA, + GP_2_19_DATA, GP_2_18_DATA, GP_2_17_DATA, GP_2_16_DATA, + GP_2_15_DATA, GP_2_14_DATA, GP_2_13_DATA, GP_2_12_DATA, + GP_2_11_DATA, GP_2_10_DATA, GP_2_9_DATA, GP_2_8_DATA, + GP_2_7_DATA, GP_2_6_DATA, GP_2_5_DATA, GP_2_4_DATA, + GP_2_3_DATA, GP_2_2_DATA, GP_2_1_DATA, GP_2_0_DATA } + }, + { PINMUX_DATA_REG("INDT3", 0xE6053008, 32) { GP_INDT(3) } }, + { PINMUX_DATA_REG("INDT4", 0xE6054008, 32) { GP_INDT(4) } }, + { PINMUX_DATA_REG("INDT5", 0xE6055008, 32) { GP_INDT(5) } }, + { }, +}; + +static struct pinmux_info r8a7790_pinmux_info = { + .name = "r8a7790_pfc", + + .unlock_reg = 0xe6060000, /* PMMR */ + + .reserved_id = PINMUX_RESERVED, + .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END }, + .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END }, + .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END }, + .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END }, + .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, + + .first_gpio = GPIO_GP_0_0, + .last_gpio = GPIO_FN_MII_RXD2 /* GPIO_FN_TCLK1_B */, + + .gpios = pinmux_gpios, + .cfg_regs = pinmux_config_regs, + .data_regs = pinmux_data_regs, + + .gpio_data = pinmux_data, + .gpio_data_size = ARRAY_SIZE(pinmux_data), +}; + +void r8a7790_pinmux_init(void) +{ + register_pinmux(&r8a7790_pinmux_info); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7790.h b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7790.h new file mode 100644 index 000000000..a13317be0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7790.h @@ -0,0 +1,92 @@ +/* + * arch/arm/cpu/armv7/rmobile/pfc-r8a7790.h + * + * Copyright (C) 2013 Renesas Electronics Corporation + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef __PFC_R8A7790_H__ +#define __PFC_R8A7790_H__ + +#include <sh_pfc.h> +#include <asm/gpio.h> + +#define CPU_32_PORT(fn, pfx, sfx) \ + PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \ + PORT_10(fn, pfx##2, sfx), PORT_1(fn, pfx##30, sfx), \ + PORT_1(fn, pfx##31, sfx) + +#define CPU_32_PORT2(fn, pfx, sfx) \ + PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \ + PORT_10(fn, pfx##2, sfx) + +#if defined(CONFIG_R8A7790) +#define CPU_32_PORT1(fn, pfx, sfx) \ + PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \ + PORT_10(fn, pfx##2, sfx) \ +/* GP_0_0_DATA -> GP_5_31_DATA (except for GP1[30],GP1[31],GP2[30],GP2[31]) */ +#define CPU_ALL_PORT(fn, pfx, sfx) \ + CPU_32_PORT(fn, pfx##_0_, sfx), \ + CPU_32_PORT1(fn, pfx##_1_, sfx), \ + CPU_32_PORT2(fn, pfx##_2_, sfx), \ + CPU_32_PORT(fn, pfx##_3_, sfx), \ + CPU_32_PORT(fn, pfx##_4_, sfx), \ + CPU_32_PORT(fn, pfx##_5_, sfx) + +#elif defined(CONFIG_R8A7791) +#define CPU_32_PORT1(fn, pfx, sfx) \ + PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \ + PORT_1(fn, pfx##20, sfx), PORT_1(fn, pfx##21, sfx), \ + PORT_1(fn, pfx##22, sfx), PORT_1(fn, pfx##23, sfx), \ + PORT_1(fn, pfx##24, sfx), PORT_1(fn, pfx##25, sfx) + +/* + * GP_0_0_DATA -> GP_7_25_DATA + * (except for GP1[26],GP1[27],GP1[28],GP1[29]),GP1[30]),GP1[31] + * GP7[26],GP7[27],GP7[28],GP7[29]),GP7[30]),GP7[31]) + */ +#define CPU_ALL_PORT(fn, pfx, sfx) \ + CPU_32_PORT(fn, pfx##_0_, sfx), \ + CPU_32_PORT1(fn, pfx##_1_, sfx), \ + CPU_32_PORT(fn, pfx##_2_, sfx), \ + CPU_32_PORT(fn, pfx##_3_, sfx), \ + CPU_32_PORT(fn, pfx##_4_, sfx), \ + CPU_32_PORT(fn, pfx##_5_, sfx), \ + CPU_32_PORT(fn, pfx##_6_, sfx), \ + CPU_32_PORT1(fn, pfx##_7_, sfx) +#else +#error "NO support" +#endif + +#define _GP_GPIO(pfx, sfx) PINMUX_GPIO(GPIO_GP##pfx, GP##pfx##_DATA) +#define _GP_DATA(pfx, sfx) PINMUX_DATA(GP##pfx##_DATA, GP##pfx##_FN, \ + GP##pfx##_IN, GP##pfx##_OUT) + +#define _GP_INOUTSEL(pfx, sfx) GP##pfx##_IN, GP##pfx##_OUT +#define _GP_INDT(pfx, sfx) GP##pfx##_DATA + +#define GP_ALL(str) CPU_ALL_PORT(_PORT_ALL, GP, str) +#define PINMUX_GPIO_GP_ALL() CPU_ALL_PORT(_GP_GPIO, , unused) +#define PINMUX_DATA_GP_ALL() CPU_ALL_PORT(_GP_DATA, , unused) + +#define PORT_10_REV(fn, pfx, sfx) \ + PORT_1(fn, pfx##9, sfx), PORT_1(fn, pfx##8, sfx), \ + PORT_1(fn, pfx##7, sfx), PORT_1(fn, pfx##6, sfx), \ + PORT_1(fn, pfx##5, sfx), PORT_1(fn, pfx##4, sfx), \ + PORT_1(fn, pfx##3, sfx), PORT_1(fn, pfx##2, sfx), \ + PORT_1(fn, pfx##1, sfx), PORT_1(fn, pfx##0, sfx) + +#define CPU_32_PORT_REV(fn, pfx, sfx) \ + PORT_1(fn, pfx##31, sfx), PORT_1(fn, pfx##30, sfx), \ + PORT_10_REV(fn, pfx##2, sfx), PORT_10_REV(fn, pfx##1, sfx), \ + PORT_10_REV(fn, pfx, sfx) + +#define GP_INOUTSEL(bank) CPU_32_PORT_REV(_GP_INOUTSEL, _##bank##_, unused) +#define GP_INDT(bank) CPU_32_PORT_REV(_GP_INDT, _##bank##_, unused) + +#define PINMUX_IPSR_DATA(ipsr, fn) PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##fn) +#define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) PINMUX_DATA(fn##_MARK, FN_##ms, \ + FN_##ipsr, FN_##fn) + +#endif /* __PFC_R8A7790_H__ */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7791.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7791.c new file mode 100644 index 000000000..f49f990a0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-r8a7791.c @@ -0,0 +1,1117 @@ +/* + * arch/arm/cpu/armv7/rmobile/pfc-r8a7791.c + * + * Copyright (C) 2013 Renesas Electronics Corporation + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <sh_pfc.h> +#include <asm/gpio.h> +#include "pfc-r8a7790.h" + +enum { + PINMUX_RESERVED = 0, + + PINMUX_DATA_BEGIN, + GP_ALL(DATA), + PINMUX_DATA_END, + + PINMUX_INPUT_BEGIN, + GP_ALL(IN), + PINMUX_INPUT_END, + + PINMUX_OUTPUT_BEGIN, + GP_ALL(OUT), + PINMUX_OUTPUT_END, + + PINMUX_FUNCTION_BEGIN, + GP_ALL(FN), + + /* GPSR0 */ + FN_IP0_0, FN_IP0_1, FN_IP0_2, FN_IP0_3, FN_IP0_4, FN_IP0_5, + FN_IP0_6, FN_IP0_7, FN_IP0_8, FN_IP0_9, FN_IP0_10, FN_IP0_11, + FN_IP0_12, FN_IP0_13, FN_IP0_14, FN_IP0_15, FN_IP0_18_16, FN_IP0_20_19, + FN_IP0_22_21, FN_IP0_24_23, FN_IP0_26_25, FN_IP0_28_27, FN_IP0_30_29, + FN_IP1_1_0, FN_IP1_3_2, FN_IP1_5_4, FN_IP1_7_6, FN_IP1_10_8, + FN_IP1_13_11, FN_IP1_16_14, FN_IP1_19_17, FN_IP1_22_20, + + /* GPSR1 */ + FN_IP1_25_23, FN_IP1_28_26, FN_IP1_31_29, FN_IP2_2_0, FN_IP2_4_3, + FN_IP2_6_5, FN_IP2_9_7, FN_IP2_12_10, FN_IP2_15_13, FN_IP2_18_16, + FN_IP2_20_19, FN_IP2_22_21, FN_EX_CS0_N, FN_IP2_24_23, FN_IP2_26_25, + FN_IP2_29_27, FN_IP3_2_0, FN_IP3_5_3, FN_IP3_8_6, FN_RD_N, + FN_IP3_11_9, FN_IP3_13_12, FN_IP3_15_14 , FN_IP3_17_16 , FN_IP3_19_18, + FN_IP3_21_20, + + /* GPSR2 */ + FN_IP3_27_25, FN_IP3_30_28, FN_IP4_1_0, FN_IP4_4_2, FN_IP4_7_5, + FN_IP4_9_8, FN_IP4_12_10, FN_IP4_15_13, FN_IP4_18_16, FN_IP4_19, + FN_IP4_20, FN_IP4_21, FN_IP4_23_22, FN_IP4_25_24, FN_IP4_27_26, + FN_IP4_30_28, FN_IP5_2_0, FN_IP5_5_3, FN_IP5_8_6, FN_IP5_11_9, + FN_IP5_14_12, FN_IP5_16_15, FN_IP5_19_17, FN_IP5_21_20, FN_IP5_23_22, + FN_IP5_25_24, FN_IP5_28_26, FN_IP5_31_29, FN_AUDIO_CLKA, FN_IP6_2_0, + FN_IP6_5_3, FN_IP6_7_6, + + /* GPSR3 */ + FN_IP7_5_3, FN_IP7_8_6, FN_IP7_10_9, FN_IP7_12_11, FN_IP7_14_13, + FN_IP7_16_15, FN_IP7_18_17, FN_IP7_20_19, FN_IP7_23_21, FN_IP7_26_24, + FN_IP7_29_27, FN_IP8_2_0, FN_IP8_5_3, FN_IP8_8_6, FN_IP8_11_9, + FN_IP8_14_12, FN_IP8_17_15, FN_IP8_20_18, FN_IP8_23_21, FN_IP8_25_24, + FN_IP8_27_26, FN_IP8_30_28, FN_IP9_2_0, FN_IP9_5_3, FN_IP9_6, FN_IP9_7, + FN_IP9_10_8, FN_IP9_11, FN_IP9_12, FN_IP9_15_13, FN_IP9_16, + FN_IP9_18_17, + + /* GPSR4 */ + FN_VI0_CLK, FN_IP9_20_19, FN_IP9_22_21, FN_IP9_24_23, FN_IP9_26_25, + FN_VI0_DATA0_VI0_B0, FN_VI0_DATA0_VI0_B1, FN_VI0_DATA0_VI0_B2, + FN_IP9_28_27, FN_VI0_DATA0_VI0_B4, FN_VI0_DATA0_VI0_B5, + FN_VI0_DATA0_VI0_B6, FN_VI0_DATA0_VI0_B7, FN_IP9_31_29, FN_IP10_2_0, + FN_IP10_5_3, FN_IP10_8_6, FN_IP10_11_9, FN_IP10_14_12, FN_IP10_16_15, + FN_IP10_18_17, FN_IP10_21_19, FN_IP10_24_22, FN_IP10_26_25, + FN_IP10_28_27, FN_IP10_31_29, FN_IP11_2_0, FN_IP11_5_3, FN_IP11_8_6, + FN_IP15_1_0, FN_IP15_3_2, FN_IP15_5_4, + + /* GPSR5 */ + FN_IP11_11_9, FN_IP11_14_12, FN_IP11_16_15, FN_IP11_18_17, FN_IP11_19, + FN_IP11_20, FN_IP11_21, FN_IP11_22, FN_IP11_23, FN_IP11_24, + FN_IP11_25, FN_IP11_26, FN_IP11_27, FN_IP11_29_28, FN_IP11_31_30, + FN_IP12_1_0, FN_IP12_3_2, FN_IP12_6_4, FN_IP12_9_7, FN_IP12_12_10, + FN_IP12_15_13, FN_IP12_17_16, FN_IP12_19_18, FN_IP12_21_20, + FN_IP12_23_22, FN_IP12_26_24, FN_IP12_29_27, FN_IP13_2_0, FN_IP13_4_3, + FN_IP13_6_5, FN_IP13_9_7, FN_IP3_24_22, + + /* GPSR6 */ + FN_IP13_10, FN_IP13_11, FN_IP13_12, FN_IP13_13, FN_IP13_14, + FN_IP13_15, FN_IP13_18_16, FN_IP13_21_19, FN_IP13_22, FN_IP13_24_23, + FN_IP13_25, FN_IP13_26, FN_IP13_27, FN_IP13_30_28, FN_IP14_1_0, + FN_IP14_2, FN_IP14_3, FN_IP14_4, FN_IP14_5, FN_IP14_6, FN_IP14_7, + FN_IP14_10_8, FN_IP14_13_11, FN_IP14_16_14, FN_IP14_19_17, + FN_IP14_22_20, FN_IP14_25_23, FN_IP14_28_26, FN_IP14_31_29, + + /* GPSR7 */ + FN_IP15_17_15, FN_IP15_20_18, FN_IP15_23_21, FN_IP15_26_24, + FN_IP15_29_27, FN_IP16_2_0, FN_IP16_5_3, FN_IP16_7_6, FN_IP16_9_8, + FN_IP16_11_10, FN_IP6_9_8, FN_IP6_11_10, FN_IP6_13_12, FN_IP6_15_14, + FN_IP6_18_16, FN_IP6_20_19, FN_IP6_23_21, FN_IP6_26_24, FN_IP6_29_27, + FN_IP7_2_0, FN_IP15_8_6, FN_IP15_11_9, FN_IP15_14_12, + FN_USB0_PWEN, FN_USB0_OVC, FN_USB1_PWEN, + + /* IPSR0 - IPSR10 */ + + /* IPSR11 */ + FN_VI0_R5, FN_VI2_DATA6, FN_GLO_SDATA_B, FN_RX0_C, FN_SDA1_D, + FN_VI0_R6, FN_VI2_DATA7, FN_GLO_SS_B, FN_TX1_C, FN_SCL4_B, + FN_VI0_R7, FN_GLO_RFON_B, FN_RX1_C, FN_CAN0_RX_E, + FN_SDA4_B, FN_HRX1_D, FN_SCIFB0_RXD_D, + FN_VI1_HSYNC_N, FN_AVB_RXD0, FN_TS_SDATA0_B, FN_TX4_B, FN_SCIFA4_TXD_B, + FN_VI1_VSYNC_N, FN_AVB_RXD1, FN_TS_SCK0_B, FN_RX4_B, FN_SCIFA4_RXD_B, + FN_VI1_CLKENB, FN_AVB_RXD2, FN_TS_SDEN0_B, + FN_VI1_FIELD, FN_AVB_RXD3, FN_TS_SPSYNC0_B, + FN_VI1_CLK, FN_AVB_RXD4, FN_VI1_DATA0, FN_AVB_RXD5, + FN_VI1_DATA1, FN_AVB_RXD6, FN_VI1_DATA2, FN_AVB_RXD7, + FN_VI1_DATA3, FN_AVB_RX_ER, FN_VI1_DATA4, FN_AVB_MDIO, + FN_VI1_DATA5, FN_AVB_RX_DV, FN_VI1_DATA6, FN_AVB_MAGIC, + FN_VI1_DATA7, FN_AVB_MDC, + FN_ETH_MDIO, FN_AVB_RX_CLK, FN_SCL2_C, + FN_ETH_CRS_DV, FN_AVB_LINK, FN_SDA2_C, + + /* IPSR12 */ + FN_ETH_RX_ER, FN_AVB_CRS, FN_SCL3, FN_SCL7, + FN_ETH_RXD0, FN_AVB_PHY_INT, FN_SDA3, FN_SDA7, + FN_ETH_RXD1, FN_AVB_GTXREFCLK, FN_CAN0_TX_C, + FN_SCL2_D, FN_MSIOF1_RXD_E, + FN_ETH_LINK, FN_AVB_TXD0, FN_CAN0_RX_C, FN_SDA2_D, FN_MSIOF1_SCK_E, + FN_ETH_REFCLK, FN_AVB_TXD1, FN_SCIFA3_RXD_B, + FN_CAN1_RX_C, FN_MSIOF1_SYNC_E, + FN_ETH_TXD1, FN_AVB_TXD2, FN_SCIFA3_TXD_B, + FN_CAN1_TX_C, FN_MSIOF1_TXD_E, + FN_ETH_TX_EN, FN_AVB_TXD3, FN_TCLK1_B, FN_CAN_CLK_B, + FN_ETH_MAGIC, FN_AVB_TXD4, FN_IETX_C, + FN_ETH_TXD0, FN_AVB_TXD5, FN_IECLK_C, + FN_ETH_MDC, FN_AVB_TXD6, FN_IERX_C, + FN_STP_IVCXO27_0, FN_AVB_TXD7, FN_SCIFB2_TXD_D, + FN_ADIDATA_B, FN_MSIOF0_SYNC_C, + FN_STP_ISCLK_0, FN_AVB_TX_EN, FN_SCIFB2_RXD_D, + FN_ADICS_SAMP_B, FN_MSIOF0_SCK_C, + + /* IPSR13 */ + /* MOD_SEL */ + FN_SEL_SCIF1_0, FN_SEL_SCIF1_1, FN_SEL_SCIF1_2, FN_SEL_SCIF1_3, + FN_SEL_SCIFB_0, FN_SEL_SCIFB_1, FN_SEL_SCIFB_2, FN_SEL_SCIFB_3, + FN_SEL_SCIFB2_0, FN_SEL_SCIFB2_1, FN_SEL_SCIFB2_2, FN_SEL_SCIFB2_3, + FN_SEL_SCIFB1_0, FN_SEL_SCIFB1_1, FN_SEL_SCIFB1_2, FN_SEL_SCIFB1_3, + FN_SEL_SCIFA1_0, FN_SEL_SCIFA1_1, FN_SEL_SCIFA1_2, + FN_SEL_SSI9_0, FN_SEL_SSI9_1, + FN_SEL_SCFA_0, FN_SEL_SCFA_1, + FN_SEL_QSP_0, FN_SEL_QSP_1, + FN_SEL_SSI7_0, FN_SEL_SSI7_1, + FN_SEL_HSCIF1_0, FN_SEL_HSCIF1_1, FN_SEL_HSCIF1_2, FN_SEL_HSCIF1_3, + FN_SEL_HSCIF1_4, + FN_SEL_VI1_0, FN_SEL_VI1_1, FN_SEL_VI1_2, + FN_SEL_TMU1_0, FN_SEL_TMU1_1, + FN_SEL_LBS_0, FN_SEL_LBS_1, FN_SEL_LBS_2, FN_SEL_LBS_3, + FN_SEL_TSIF0_0, FN_SEL_TSIF0_1, FN_SEL_TSIF0_2, FN_SEL_TSIF0_3, + FN_SEL_SOF0_0, FN_SEL_SOF0_1, FN_SEL_SOF0_2, + + /* MOD_SEL2 */ + FN_SEL_SCIF0_0, FN_SEL_SCIF0_1, FN_SEL_SCIF0_2, FN_SEL_SCIF0_3, + FN_SEL_SCIF0_4, + FN_SEL_SCIF_0, FN_SEL_SCIF_1, + FN_SEL_CAN0_0, FN_SEL_CAN0_1, FN_SEL_CAN0_2, FN_SEL_CAN0_3, + FN_SEL_CAN0_4, FN_SEL_CAN0_5, + FN_SEL_CAN1_0, FN_SEL_CAN1_1, FN_SEL_CAN1_2, FN_SEL_CAN1_3, + FN_SEL_SCIFA2_0, FN_SEL_SCIFA2_1, + FN_SEL_SCIF4_0, FN_SEL_SCIF4_1, FN_SEL_SCIF4_2, + FN_SEL_ADG_0, FN_SEL_ADG_1, + FN_SEL_FM_0, FN_SEL_FM_1, FN_SEL_FM_2, FN_SEL_FM_3, FN_SEL_FM_4, + FN_SEL_SCIFA5_0, FN_SEL_SCIFA5_1, FN_SEL_SCIFA5_2, + FN_SEL_GPS_0, FN_SEL_GPS_1, FN_SEL_GPS_2, FN_SEL_GPS_3, + FN_SEL_SCIFA4_0, FN_SEL_SCIFA4_1, FN_SEL_SCIFA4_2, + FN_SEL_SCIFA3_0, FN_SEL_SCIFA3_1, FN_SEL_SCIFA3_2, + FN_SEL_SIM_0, FN_SEL_SIM_1, + FN_SEL_SSI8_0, FN_SEL_SSI8_1, + + /* MOD_SEL3 */ + FN_SEL_HSCIF2_0, FN_SEL_HSCIF2_1, FN_SEL_HSCIF2_2, FN_SEL_HSCIF2_3, + FN_SEL_CANCLK_0, FN_SEL_CANCLK_1, FN_SEL_CANCLK_2, FN_SEL_CANCLK_3, + FN_SEL_IIC8_0, FN_SEL_IIC8_1, FN_SEL_IIC8_2, + FN_SEL_IIC7_0, FN_SEL_IIC7_1, FN_SEL_IIC7_2, + FN_SEL_IIC4_0, FN_SEL_IIC4_1, FN_SEL_IIC4_2, + FN_SEL_IIC3_0, FN_SEL_IIC3_1, FN_SEL_IIC3_2, FN_SEL_IIC3_3, + FN_SEL_SCIF3_0, FN_SEL_SCIF3_1, FN_SEL_SCIF3_2, FN_SEL_SCIF3_3, + FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2, + FN_SEL_MMC_0, FN_SEL_MMC_1, + FN_SEL_SCIF5_0, FN_SEL_SCIF5_1, + FN_SEL_IIC2_0, FN_SEL_IIC2_1, FN_SEL_IIC2_2, FN_SEL_IIC2_3, + FN_SEL_IIC1_0, FN_SEL_IIC1_1, FN_SEL_IIC1_2, FN_SEL_IIC1_3, + FN_SEL_IIC1_4, + FN_SEL_IIC0_0, FN_SEL_IIC0_1, FN_SEL_IIC0_2, + + /* MOD_SEL4 */ + FN_SEL_SOF1_0, FN_SEL_SOF1_1, FN_SEL_SOF1_2, FN_SEL_SOF1_3, + FN_SEL_SOF1_4, + FN_SEL_HSCIF0_0, FN_SEL_HSCIF0_1, FN_SEL_HSCIF0_2, + FN_SEL_DIS_0, FN_SEL_DIS_1, FN_SEL_DIS_2, + FN_SEL_RAD_0, FN_SEL_RAD_1, + FN_SEL_RCN_0, FN_SEL_RCN_1, + FN_SEL_RSP_0, FN_SEL_RSP_1, + FN_SEL_SCIF2_0, FN_SEL_SCIF2_1, FN_SEL_SCIF2_2, FN_SEL_SCIF2_3, + FN_SEL_SCIF2_4, + FN_SEL_SOF2_0, FN_SEL_SOF2_1, FN_SEL_SOF2_2, FN_SEL_SOF2_3, + FN_SEL_SOF2_4, + FN_SEL_SSI1_0, FN_SEL_SSI1_1, + FN_SEL_SSI0_0, FN_SEL_SSI0_1, + FN_SEL_SSP_0, FN_SEL_SSP_1, FN_SEL_SSP_2, + PINMUX_FUNCTION_END, + + PINMUX_MARK_BEGIN, + + EX_CS0_N_MARK, RD_N_MARK, + + AUDIO_CLKA_MARK, + + VI0_CLK_MARK, VI0_DATA0_VI0_B0_MARK, VI0_DATA0_VI0_B1_MARK, + VI0_DATA0_VI0_B2_MARK, VI0_DATA0_VI0_B4_MARK, VI0_DATA0_VI0_B5_MARK, + VI0_DATA0_VI0_B6_MARK, VI0_DATA0_VI0_B7_MARK, + + USB0_PWEN_MARK, USB0_OVC_MARK, USB1_PWEN_MARK, + + /* IPSR0 IPSR10 */ + /* IPSR11 */ + VI0_R5_MARK, VI2_DATA6_MARK, GLO_SDATA_B_MARK, RX0_C_MARK, SDA1_D_MARK, + VI0_R6_MARK, VI2_DATA7_MARK, GLO_SS_B_MARK, TX1_C_MARK, SCL4_B_MARK, + VI0_R7_MARK, GLO_RFON_B_MARK, RX1_C_MARK, CAN0_RX_E_MARK, + SDA4_B_MARK, _MARK, HRX1_D_MARK, SCIFB0_RXD_D_MARK, + VI1_HSYNC_N_MARK, AVB_RXD0_MARK, TS_SDATA0_B_MARK, + TX4_B_MARK, SCIFA4_TXD_B_MARK, + VI1_VSYNC_N_MARK, AVB_RXD1_MARK, TS_SCK0_B_MARK, + RX4_B_MARK, SCIFA4_RXD_B_MARK, + VI1_CLKENB_MARK, AVB_RXD2_MARK, TS_SDEN0_B_MARK, + VI1_FIELD_MARK, AVB_RXD3_MARK, TS_SPSYNC0_B_MARK, + VI1_CLK_MARK, AVB_RXD4_MARK, VI1_DATA0_MARK, AVB_RXD5_MARK, + VI1_DATA1_MARK, AVB_RXD6_MARK, VI1_DATA2_MARK, AVB_RXD7_MARK, + VI1_DATA3_MARK, AVB_RX_ER_MARK, VI1_DATA4_MARK, AVB_MDIO_MARK, + VI1_DATA5_MARK, AVB_RX_DV_MARK, VI1_DATA6_MARK, AVB_MAGIC_MARK, + VI1_DATA7_MARK, AVB_MDC_MARK, + ETH_MDIO_MARK, AVB_RX_CLK_MARK, SCL2_C_MARK, + ETH_CRS_DV_MARK, AVB_LINK_MARK, SDA2_C_MARK, + + /* IPSR12 */ + ETH_RX_ER_MARK, AVB_CRS_MARK, SCL3_MARK, SCL7_MARK, + ETH_RXD0_MARK, AVB_PHY_INT_MARK, SDA3_MARK, SDA7_MARK, + ETH_RXD1_MARK, AVB_GTXREFCLK_MARK, CAN0_TX_C_MARK, + SCL2_D_MARK, MSIOF1_RXD_E_MARK, + ETH_LINK_MARK, AVB_TXD0_MARK, CAN0_RX_C_MARK, + SDA2_D_MARK, MSIOF1_SCK_E_MARK, + ETH_REFCLK_MARK, AVB_TXD1_MARK, SCIFA3_RXD_B_MARK, + CAN1_RX_C_MARK, MSIOF1_SYNC_E_MARK, + ETH_TXD1_MARK, AVB_TXD2_MARK, SCIFA3_TXD_B_MARK, + CAN1_TX_C_MARK, MSIOF1_TXD_E_MARK, + ETH_TX_EN_MARK, AVB_TXD3_MARK, TCLK1_B_MARK, CAN_CLK_B_MARK, + ETH_MAGIC_MARK, AVB_TXD4_MARK, IETX_C_MARK, + ETH_TXD0_MARK, AVB_TXD5_MARK, IECLK_C_MARK, + ETH_MDC_MARK, AVB_TXD6_MARK, IERX_C_MARK, + STP_IVCXO27_0_MARK, AVB_TXD7_MARK, SCIFB2_TXD_D_MARK, + ADIDATA_B_MARK, MSIOF0_SYNC_C_MARK, + STP_ISCLK_0_MARK, AVB_TX_EN_MARK, SCIFB2_RXD_D_MARK, + ADICS_SAMP_B_MARK, MSIOF0_SCK_C_MARK, + + /* IPSR13 */ + PINMUX_MARK_END, +}; + +static pinmux_enum_t pinmux_data[] = { + PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */ + + /* OTHER IPSR0 - IPSR10 */ + /* IPSR11 */ + PINMUX_IPSR_DATA(IP11_2_0, VI0_R5), + PINMUX_IPSR_DATA(IP11_2_0, VI2_DATA6), + PINMUX_IPSR_MODSEL_DATA(IP11_2_0, GLO_SDATA_B, SEL_GPS_1), + PINMUX_IPSR_MODSEL_DATA(IP11_2_0, RX0_C, SEL_SCIF0_2), + PINMUX_IPSR_MODSEL_DATA(IP11_2_0, SDA1_D, SEL_IIC1_3), + PINMUX_IPSR_DATA(IP11_5_3, VI0_R6), + PINMUX_IPSR_DATA(IP11_5_3, VI2_DATA7), + PINMUX_IPSR_MODSEL_DATA(IP11_5_3, GLO_SS_B, SEL_GPS_1), + PINMUX_IPSR_MODSEL_DATA(IP11_5_3, TX1_C, SEL_SCIF1_2), + PINMUX_IPSR_MODSEL_DATA(IP11_5_3, SCL4_B, SEL_IIC4_1), + PINMUX_IPSR_DATA(IP11_8_6, VI0_R7), + PINMUX_IPSR_MODSEL_DATA(IP11_8_6, GLO_RFON_B, SEL_GPS_1), + PINMUX_IPSR_MODSEL_DATA(IP11_8_6, RX1_C, SEL_SCIF1_2), + PINMUX_IPSR_MODSEL_DATA(IP11_8_6, CAN0_RX_E, SEL_CAN0_4), + PINMUX_IPSR_MODSEL_DATA(IP11_8_6, SDA4_B, SEL_IIC4_1), + PINMUX_IPSR_MODSEL_DATA(IP11_8_6, HRX1_D, SEL_HSCIF1_3), + PINMUX_IPSR_MODSEL_DATA(IP11_8_6, SCIFB0_RXD_D, SEL_SCIFB_3), + PINMUX_IPSR_MODSEL_DATA(IP11_11_9, VI1_HSYNC_N, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_11_9, AVB_RXD0), + PINMUX_IPSR_MODSEL_DATA(IP11_11_9, TS_SDATA0_B, SEL_TSIF0_1), + PINMUX_IPSR_MODSEL_DATA(IP11_11_9, TX4_B, SEL_SCIF4_1), + PINMUX_IPSR_MODSEL_DATA(IP11_11_9, SCIFA4_TXD_B, SEL_SCIFA4_1), + PINMUX_IPSR_MODSEL_DATA(IP11_14_12, VI1_VSYNC_N, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_14_12, AVB_RXD1), + PINMUX_IPSR_MODSEL_DATA(IP11_14_12, TS_SCK0_B, SEL_TSIF0_1), + PINMUX_IPSR_MODSEL_DATA(IP11_14_12, RX4_B, SEL_SCIF4_1), + PINMUX_IPSR_MODSEL_DATA(IP11_14_12, SCIFA4_RXD_B, SEL_SCIFA4_1), + PINMUX_IPSR_MODSEL_DATA(IP11_16_15, VI1_CLKENB, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_16_15, AVB_RXD2), + PINMUX_IPSR_MODSEL_DATA(IP11_16_15, TS_SDEN0_B, SEL_TSIF0_1), + PINMUX_IPSR_MODSEL_DATA(IP11_18_17, VI1_FIELD, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_18_17, AVB_RXD3), + PINMUX_IPSR_MODSEL_DATA(IP11_18_17, TS_SPSYNC0_B, SEL_TSIF0_1), + PINMUX_IPSR_MODSEL_DATA(IP11_19, VI1_CLK, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_19, AVB_RXD4), + PINMUX_IPSR_MODSEL_DATA(IP11_20, VI1_DATA0, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_20, AVB_RXD5), + PINMUX_IPSR_MODSEL_DATA(IP11_21, VI1_DATA1, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_21, AVB_RXD6), + PINMUX_IPSR_MODSEL_DATA(IP11_22, VI1_DATA2, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_22, AVB_RXD7), + PINMUX_IPSR_MODSEL_DATA(IP11_23, VI1_DATA3, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_23, AVB_RX_ER), + PINMUX_IPSR_MODSEL_DATA(IP11_24, VI1_DATA4, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_24, AVB_MDIO), + PINMUX_IPSR_MODSEL_DATA(IP11_25, VI1_DATA5, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_25, AVB_RX_DV), + PINMUX_IPSR_MODSEL_DATA(IP11_26, VI1_DATA6, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_26, AVB_MAGIC), + PINMUX_IPSR_MODSEL_DATA(IP11_27, VI1_DATA7, SEL_VI1_0), + PINMUX_IPSR_DATA(IP11_27, AVB_MDC), + PINMUX_IPSR_DATA(IP11_29_28, ETH_MDIO), + PINMUX_IPSR_DATA(IP11_29_28, AVB_RX_CLK), + PINMUX_IPSR_MODSEL_DATA(IP11_29_28, SCL2_C, SEL_IIC2_2), + PINMUX_IPSR_DATA(IP11_31_30, ETH_CRS_DV), + PINMUX_IPSR_DATA(IP11_31_30, AVB_LINK), + PINMUX_IPSR_MODSEL_DATA(IP11_31_30, SDA2_C, SEL_IIC2_2), + + /* IPSR12 */ + PINMUX_IPSR_DATA(IP12_1_0, ETH_RX_ER), + PINMUX_IPSR_DATA(IP12_1_0, AVB_CRS), + PINMUX_IPSR_MODSEL_DATA(IP12_1_0, SCL3, SEL_IIC3_0), + PINMUX_IPSR_MODSEL_DATA(IP12_1_0, SCL7, SEL_IIC7_0), + PINMUX_IPSR_DATA(IP12_3_2, ETH_RXD0), + PINMUX_IPSR_DATA(IP12_3_2, AVB_PHY_INT), + PINMUX_IPSR_MODSEL_DATA(IP12_3_2, SDA3, SEL_IIC3_0), + PINMUX_IPSR_MODSEL_DATA(IP12_3_2, SDA7, SEL_IIC7_0), + PINMUX_IPSR_DATA(IP12_6_4, ETH_RXD1), + PINMUX_IPSR_DATA(IP12_6_4, AVB_GTXREFCLK), + PINMUX_IPSR_MODSEL_DATA(IP12_6_4, CAN0_TX_C, SEL_CAN0_2), + PINMUX_IPSR_MODSEL_DATA(IP12_6_4, SCL2_D, SEL_IIC2_3), + PINMUX_IPSR_MODSEL_DATA(IP12_6_4, MSIOF1_RXD_E, SEL_SOF1_4), + PINMUX_IPSR_DATA(IP12_9_7, ETH_LINK), + PINMUX_IPSR_DATA(IP12_9_7, AVB_TXD0), + PINMUX_IPSR_MODSEL_DATA(IP12_9_7, CAN0_RX_C, SEL_CAN0_2), + PINMUX_IPSR_MODSEL_DATA(IP12_9_7, SDA2_D, SEL_IIC2_3), + PINMUX_IPSR_MODSEL_DATA(IP12_9_7, MSIOF1_SCK_E, SEL_SOF1_4), + PINMUX_IPSR_DATA(IP12_12_10, ETH_REFCLK), + PINMUX_IPSR_DATA(IP12_12_10, AVB_TXD1), + PINMUX_IPSR_MODSEL_DATA(IP12_12_10, SCIFA3_RXD_B, SEL_SCIFA3_1), + PINMUX_IPSR_MODSEL_DATA(IP12_12_10, CAN1_RX_C, SEL_CAN1_2), + PINMUX_IPSR_MODSEL_DATA(IP12_12_10, MSIOF1_SYNC_E, SEL_SOF1_4), + PINMUX_IPSR_DATA(IP12_15_13, ETH_TXD1), + PINMUX_IPSR_DATA(IP12_15_13, AVB_TXD2), + PINMUX_IPSR_MODSEL_DATA(IP12_15_13, SCIFA3_TXD_B, SEL_SCIFA3_1), + PINMUX_IPSR_MODSEL_DATA(IP12_15_13, CAN1_TX_C, SEL_CAN1_2), + PINMUX_IPSR_MODSEL_DATA(IP12_15_13, MSIOF1_TXD_E, SEL_SOF1_4), + PINMUX_IPSR_DATA(IP12_17_16, ETH_TX_EN), + PINMUX_IPSR_DATA(IP12_17_16, AVB_TXD3), + PINMUX_IPSR_MODSEL_DATA(IP12_17_16, TCLK1_B, SEL_TMU1_0), + PINMUX_IPSR_MODSEL_DATA(IP12_17_16, CAN_CLK_B, SEL_CANCLK_1), + PINMUX_IPSR_DATA(IP12_19_18, ETH_MAGIC), + PINMUX_IPSR_DATA(IP12_19_18, AVB_TXD4), + PINMUX_IPSR_MODSEL_DATA(IP12_19_18, IETX_C, SEL_IEB_2), + PINMUX_IPSR_DATA(IP12_21_20, ETH_TXD0), + PINMUX_IPSR_DATA(IP12_21_20, AVB_TXD5), + PINMUX_IPSR_MODSEL_DATA(IP12_21_20, IECLK_C, SEL_IEB_2), + PINMUX_IPSR_DATA(IP12_23_22, ETH_MDC), + PINMUX_IPSR_DATA(IP12_23_22, AVB_TXD6), + PINMUX_IPSR_MODSEL_DATA(IP12_23_22, IERX_C, SEL_IEB_2), + PINMUX_IPSR_MODSEL_DATA(IP12_26_24, STP_IVCXO27_0, SEL_SSP_0), + PINMUX_IPSR_DATA(IP12_26_24, AVB_TXD7), + PINMUX_IPSR_MODSEL_DATA(IP12_26_24, SCIFB2_TXD_D, SEL_SCIFB2_3), + PINMUX_IPSR_MODSEL_DATA(IP12_26_24, ADIDATA_B, SEL_RAD_1), + PINMUX_IPSR_MODSEL_DATA(IP12_26_24, MSIOF0_SYNC_C, SEL_SOF0_2), + PINMUX_IPSR_MODSEL_DATA(IP12_29_27, STP_ISCLK_0, SEL_SSP_0), + PINMUX_IPSR_DATA(IP12_29_27, AVB_TX_EN), + PINMUX_IPSR_MODSEL_DATA(IP12_29_27, SCIFB2_RXD_D, SEL_SCIFB2_3), + PINMUX_IPSR_MODSEL_DATA(IP12_29_27, ADICS_SAMP_B, SEL_RAD_1), + PINMUX_IPSR_MODSEL_DATA(IP12_29_27, MSIOF0_SCK_C, SEL_SOF0_2), + + /* IPSR13 - IPSR16 */ +}; + +static struct pinmux_gpio pinmux_gpios[] = { + PINMUX_GPIO_GP_ALL(), + + /* OTHER, IPSR0 - IPSR10 */ + /* IPSR11 */ + GPIO_FN(VI0_R5), GPIO_FN(VI2_DATA6), GPIO_FN(GLO_SDATA_B), + GPIO_FN(RX0_C), GPIO_FN(SDA1_D), + GPIO_FN(VI0_R6), GPIO_FN(VI2_DATA7), + GPIO_FN(GLO_SS_B), GPIO_FN(TX1_C), GPIO_FN(SCL4_B), + GPIO_FN(VI0_R7), GPIO_FN(GLO_RFON_B), + GPIO_FN(RX1_C), GPIO_FN(CAN0_RX_E), + GPIO_FN(SDA4_B), GPIO_FN(HRX1_D), GPIO_FN(SCIFB0_RXD_D), + GPIO_FN(VI1_HSYNC_N), GPIO_FN(AVB_RXD0), GPIO_FN(TS_SDATA0_B), + GPIO_FN(TX4_B), GPIO_FN(SCIFA4_TXD_B), + GPIO_FN(VI1_VSYNC_N), GPIO_FN(AVB_RXD1), GPIO_FN(TS_SCK0_B), + GPIO_FN(RX4_B), GPIO_FN(SCIFA4_RXD_B), + GPIO_FN(VI1_CLKENB), GPIO_FN(AVB_RXD2), GPIO_FN(TS_SDEN0_B), + GPIO_FN(VI1_FIELD), GPIO_FN(AVB_RXD3), GPIO_FN(TS_SPSYNC0_B), + GPIO_FN(VI1_CLK), GPIO_FN(AVB_RXD4), + GPIO_FN(VI1_DATA0), GPIO_FN(AVB_RXD5), + GPIO_FN(VI1_DATA1), GPIO_FN(AVB_RXD6), + GPIO_FN(VI1_DATA2), GPIO_FN(AVB_RXD7), + GPIO_FN(VI1_DATA3), GPIO_FN(AVB_RX_ER), + GPIO_FN(VI1_DATA4), GPIO_FN(AVB_MDIO), + GPIO_FN(VI1_DATA5), GPIO_FN(AVB_RX_DV), + GPIO_FN(VI1_DATA6), GPIO_FN(AVB_MAGIC), + GPIO_FN(VI1_DATA7), GPIO_FN(AVB_MDC), + GPIO_FN(ETH_MDIO), GPIO_FN(AVB_RX_CLK), GPIO_FN(SCL2_C), + GPIO_FN(ETH_CRS_DV), GPIO_FN(AVB_LINK), GPIO_FN(SDA2_C), + + /* IPSR12 */ + GPIO_FN(ETH_RX_ER), GPIO_FN(AVB_CRS), GPIO_FN(SCL3), GPIO_FN(SCL7), + GPIO_FN(ETH_RXD0), GPIO_FN(AVB_PHY_INT), GPIO_FN(SDA3), GPIO_FN(SDA7), + GPIO_FN(ETH_RXD1), GPIO_FN(AVB_GTXREFCLK), GPIO_FN(CAN0_TX_C), + GPIO_FN(SCL2_D), GPIO_FN(MSIOF1_RXD_E), + GPIO_FN(ETH_LINK), GPIO_FN(AVB_TXD0), GPIO_FN(CAN0_RX_C), + GPIO_FN(SDA2_D), GPIO_FN(MSIOF1_SCK_E), + GPIO_FN(ETH_REFCLK), GPIO_FN(AVB_TXD1), GPIO_FN(SCIFA3_RXD_B), + GPIO_FN(CAN1_RX_C), GPIO_FN(MSIOF1_SYNC_E), + GPIO_FN(ETH_TXD1), GPIO_FN(AVB_TXD2), GPIO_FN(SCIFA3_TXD_B), + GPIO_FN(CAN1_TX_C), GPIO_FN(MSIOF1_TXD_E), + GPIO_FN(ETH_TX_EN), GPIO_FN(AVB_TXD3), + GPIO_FN(TCLK1_B), GPIO_FN(CAN_CLK_B), + GPIO_FN(ETH_MAGIC), GPIO_FN(AVB_TXD4), GPIO_FN(IETX_C), + GPIO_FN(ETH_TXD0), GPIO_FN(AVB_TXD5), GPIO_FN(IECLK_C), + GPIO_FN(ETH_MDC), GPIO_FN(AVB_TXD6), GPIO_FN(IERX_C), + GPIO_FN(STP_IVCXO27_0), GPIO_FN(AVB_TXD7), GPIO_FN(SCIFB2_TXD_D), + GPIO_FN(ADIDATA_B), GPIO_FN(MSIOF0_SYNC_C), + GPIO_FN(STP_ISCLK_0), GPIO_FN(AVB_TX_EN), GPIO_FN(SCIFB2_RXD_D), + GPIO_FN(ADICS_SAMP_B), GPIO_FN(MSIOF0_SCK_C), + + /* IPSR13 - IPSR16 */ +}; + +static struct pinmux_cfg_reg pinmux_config_regs[] = { + { PINMUX_CFG_REG("GPSR0", 0xE6060004, 32, 1) { + GP_0_31_FN, FN_IP1_22_20, + GP_0_30_FN, FN_IP1_19_17, + GP_0_29_FN, FN_IP1_16_14, + GP_0_28_FN, FN_IP1_13_11, + GP_0_27_FN, FN_IP1_10_8, + GP_0_26_FN, FN_IP1_7_6, + GP_0_25_FN, FN_IP1_5_4, + GP_0_24_FN, FN_IP1_3_2, + GP_0_23_FN, FN_IP1_1_0, + GP_0_22_FN, FN_IP0_30_29, + GP_0_21_FN, FN_IP0_28_27, + GP_0_20_FN, FN_IP0_26_25, + GP_0_19_FN, FN_IP0_24_23, + GP_0_18_FN, FN_IP0_22_21, + GP_0_17_FN, FN_IP0_20_19, + GP_0_16_FN, FN_IP0_18_16, + GP_0_15_FN, FN_IP0_15, + GP_0_14_FN, FN_IP0_14, + GP_0_13_FN, FN_IP0_13, + GP_0_12_FN, FN_IP0_12, + GP_0_11_FN, FN_IP0_11, + GP_0_10_FN, FN_IP0_10, + GP_0_9_FN, FN_IP0_9, + GP_0_8_FN, FN_IP0_8, + GP_0_7_FN, FN_IP0_7, + GP_0_6_FN, FN_IP0_6, + GP_0_5_FN, FN_IP0_5, + GP_0_4_FN, FN_IP0_4, + GP_0_3_FN, FN_IP0_3, + GP_0_2_FN, FN_IP0_2, + GP_0_1_FN, FN_IP0_1, + GP_0_0_FN, FN_IP0_0, } + }, + { PINMUX_CFG_REG("GPSR1", 0xE6060008, 32, 1) { + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + GP_1_25_FN, FN_IP3_21_20, + GP_1_24_FN, FN_IP3_19_18, + GP_1_23_FN, FN_IP3_17_16, + GP_1_22_FN, FN_IP3_15_14, + GP_1_21_FN, FN_IP3_13_12, + GP_1_20_FN, FN_IP3_11_9, + GP_1_19_FN, FN_RD_N, + GP_1_18_FN, FN_IP3_8_6, + GP_1_17_FN, FN_IP3_5_3, + GP_1_16_FN, FN_IP3_2_0, + GP_1_15_FN, FN_IP2_29_27, + GP_1_14_FN, FN_IP2_26_25, + GP_1_13_FN, FN_IP2_24_23, + GP_1_12_FN, FN_EX_CS0_N, + GP_1_11_FN, FN_IP2_22_21, + GP_1_10_FN, FN_IP2_20_19, + GP_1_9_FN, FN_IP2_18_16, + GP_1_8_FN, FN_IP2_15_13, + GP_1_7_FN, FN_IP2_12_10, + GP_1_6_FN, FN_IP2_9_7, + GP_1_5_FN, FN_IP2_6_5, + GP_1_4_FN, FN_IP2_4_3, + GP_1_3_FN, FN_IP2_2_0, + GP_1_2_FN, FN_IP1_31_29, + GP_1_1_FN, FN_IP1_28_26, + GP_1_0_FN, FN_IP1_25_23, } + }, + { PINMUX_CFG_REG("GPSR2", 0xE606000C, 32, 1) { + GP_2_31_FN, FN_IP6_7_6, + GP_2_30_FN, FN_IP6_5_3, + GP_2_29_FN, FN_IP6_2_0, + GP_2_28_FN, FN_AUDIO_CLKA, + GP_2_27_FN, FN_IP5_31_29, + GP_2_26_FN, FN_IP5_28_26, + GP_2_25_FN, FN_IP5_25_24, + GP_2_24_FN, FN_IP5_23_22, + GP_2_23_FN, FN_IP5_21_20, + GP_2_22_FN, FN_IP5_19_17, + GP_2_21_FN, FN_IP5_16_15, + GP_2_20_FN, FN_IP5_14_12, + GP_2_19_FN, FN_IP5_11_9, + GP_2_18_FN, FN_IP5_8_6, + GP_2_17_FN, FN_IP5_5_3, + GP_2_16_FN, FN_IP5_2_0, + GP_2_15_FN, FN_IP4_30_28, + GP_2_14_FN, FN_IP4_27_26, + GP_2_13_FN, FN_IP4_25_24, + GP_2_12_FN, FN_IP4_23_22, + GP_2_11_FN, FN_IP4_21, + GP_2_10_FN, FN_IP4_20, + GP_2_9_FN, FN_IP4_19, + GP_2_8_FN, FN_IP4_18_16, + GP_2_7_FN, FN_IP4_15_13, + GP_2_6_FN, FN_IP4_12_10, + GP_2_5_FN, FN_IP4_9_8, + GP_2_4_FN, FN_IP4_7_5, + GP_2_3_FN, FN_IP4_4_2, + GP_2_2_FN, FN_IP4_1_0, + GP_2_1_FN, FN_IP3_30_28, + GP_2_0_FN, FN_IP3_27_25 } + }, + { PINMUX_CFG_REG("GPSR3", 0xE6060010, 32, 1) { + GP_3_31_FN, FN_IP9_18_17, + GP_3_30_FN, FN_IP9_16, + GP_3_29_FN, FN_IP9_15_13, + GP_3_28_FN, FN_IP9_12, + GP_3_27_FN, FN_IP9_11, + GP_3_26_FN, FN_IP9_10_8, + GP_3_25_FN, FN_IP9_7, + GP_3_24_FN, FN_IP9_6, + GP_3_23_FN, FN_IP9_5_3, + GP_3_22_FN, FN_IP9_2_0, + GP_3_21_FN, FN_IP8_30_28, + GP_3_20_FN, FN_IP8_27_26, + GP_3_19_FN, FN_IP8_25_24, + GP_3_18_FN, FN_IP8_23_21, + GP_3_17_FN, FN_IP8_20_18, + GP_3_16_FN, FN_IP8_17_15, + GP_3_15_FN, FN_IP8_14_12, + GP_3_14_FN, FN_IP8_11_9, + GP_3_13_FN, FN_IP8_8_6, + GP_3_12_FN, FN_IP8_5_3, + GP_3_11_FN, FN_IP8_2_0, + GP_3_10_FN, FN_IP7_29_27, + GP_3_9_FN, FN_IP7_26_24, + GP_3_8_FN, FN_IP7_23_21, + GP_3_7_FN, FN_IP7_20_19, + GP_3_6_FN, FN_IP7_18_17, + GP_3_5_FN, FN_IP7_16_15, + GP_3_4_FN, FN_IP7_14_13, + GP_3_3_FN, FN_IP7_12_11, + GP_3_2_FN, FN_IP7_10_9, + GP_3_1_FN, FN_IP7_8_6, + GP_3_0_FN, FN_IP7_5_3 } + }, + { PINMUX_CFG_REG("GPSR4", 0xE6060014, 32, 1) { + GP_4_31_FN, FN_IP15_5_4, + GP_4_30_FN, FN_IP15_3_2, + GP_4_29_FN, FN_IP15_1_0, + GP_4_28_FN, FN_IP11_8_6, + GP_4_27_FN, FN_IP11_5_3, + GP_4_26_FN, FN_IP11_2_0, + GP_4_25_FN, FN_IP10_31_29, + GP_4_24_FN, FN_IP10_28_27, + GP_4_23_FN, FN_IP10_26_25, + GP_4_22_FN, FN_IP10_24_22, + GP_4_21_FN, FN_IP10_21_19, + GP_4_20_FN, FN_IP10_18_17, + GP_4_19_FN, FN_IP10_16_15, + GP_4_18_FN, FN_IP10_14_12, + GP_4_17_FN, FN_IP10_11_9, + GP_4_16_FN, FN_IP10_8_6, + GP_4_15_FN, FN_IP10_5_3, + GP_4_14_FN, FN_IP10_2_0, + GP_4_13_FN, FN_IP9_31_29, + GP_4_12_FN, FN_VI0_DATA0_VI0_B7, + GP_4_11_FN, FN_VI0_DATA0_VI0_B6, + GP_4_10_FN, FN_VI0_DATA0_VI0_B5, + GP_4_9_FN, FN_VI0_DATA0_VI0_B4, + GP_4_8_FN, FN_IP9_28_27, + GP_4_7_FN, FN_VI0_DATA0_VI0_B2, + GP_4_6_FN, FN_VI0_DATA0_VI0_B1, + GP_4_5_FN, FN_VI0_DATA0_VI0_B0, + GP_4_4_FN, FN_IP9_26_25, + GP_4_3_FN, FN_IP9_24_23, + GP_4_2_FN, FN_IP9_22_21, + GP_4_1_FN, FN_IP9_20_19, + GP_4_0_FN, FN_VI0_CLK } + }, + { PINMUX_CFG_REG("GPSR5", 0xE6060018, 32, 1) { + GP_5_31_FN, FN_IP3_24_22, + GP_5_30_FN, FN_IP13_9_7, + GP_5_29_FN, FN_IP13_6_5, + GP_5_28_FN, FN_IP13_4_3, + GP_5_27_FN, FN_IP13_2_0, + GP_5_26_FN, FN_IP12_29_27, + GP_5_25_FN, FN_IP12_26_24, + GP_5_24_FN, FN_IP12_23_22, + GP_5_23_FN, FN_IP12_21_20, + GP_5_22_FN, FN_IP12_19_18, + GP_5_21_FN, FN_IP12_17_16, + GP_5_20_FN, FN_IP12_15_13, + GP_5_19_FN, FN_IP12_12_10, + GP_5_18_FN, FN_IP12_9_7, + GP_5_17_FN, FN_IP12_6_4, + GP_5_16_FN, FN_IP12_3_2, + GP_5_15_FN, FN_IP12_1_0, + GP_5_14_FN, FN_IP11_31_30, + GP_5_13_FN, FN_IP11_29_28, + GP_5_12_FN, FN_IP11_27, + GP_5_11_FN, FN_IP11_26, + GP_5_10_FN, FN_IP11_25, + GP_5_9_FN, FN_IP11_24, + GP_5_8_FN, FN_IP11_23, + GP_5_7_FN, FN_IP11_22, + GP_5_6_FN, FN_IP11_21, + GP_5_5_FN, FN_IP11_20, + GP_5_4_FN, FN_IP11_19, + GP_5_3_FN, FN_IP11_18_17, + GP_5_2_FN, FN_IP11_16_15, + GP_5_1_FN, FN_IP11_14_12, + GP_5_0_FN, FN_IP11_11_9 } + }, + { PINMUX_CFG_REG("GPSR6", 0xE606001C, 32, 1) { + 0, 0, + 0, 0, + GP_6_29_FN, FN_IP14_31_29, + GP_6_28_FN, FN_IP14_28_26, + GP_6_27_FN, FN_IP14_25_23, + GP_6_26_FN, FN_IP14_22_20, + GP_6_25_FN, FN_IP14_19_17, + GP_6_24_FN, FN_IP14_16_14, + GP_6_23_FN, FN_IP14_13_11, + GP_6_22_FN, FN_IP14_10_8, + GP_6_21_FN, FN_IP14_7, + GP_6_20_FN, FN_IP14_6, + GP_6_19_FN, FN_IP14_5, + GP_6_18_FN, FN_IP14_4, + GP_6_17_FN, FN_IP14_3, + GP_6_16_FN, FN_IP14_2, + GP_6_15_FN, FN_IP14_1_0, + GP_6_14_FN, FN_IP13_30_28, + GP_6_13_FN, FN_IP13_27, + GP_6_12_FN, FN_IP13_26, + GP_6_11_FN, FN_IP13_25, + GP_6_10_FN, FN_IP13_24_23, + GP_6_9_FN, FN_IP13_22, + 0, 0, + GP_6_7_FN, FN_IP13_21_19, + GP_6_6_FN, FN_IP13_18_16, + GP_6_5_FN, FN_IP13_15, + GP_6_4_FN, FN_IP13_14, + GP_6_3_FN, FN_IP13_13, + GP_6_2_FN, FN_IP13_12, + GP_6_1_FN, FN_IP13_11, + GP_6_0_FN, FN_IP13_10 } + }, + { PINMUX_CFG_REG("GPSR7", 0xE6060074, 32, 1) { + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + GP_7_25_FN, FN_USB1_PWEN, + GP_7_24_FN, FN_USB0_OVC, + GP_7_23_FN, FN_USB0_PWEN, + GP_7_22_FN, FN_IP15_14_12, + GP_7_21_FN, FN_IP15_11_9, + GP_7_20_FN, FN_IP15_8_6, + GP_7_19_FN, FN_IP7_2_0, + GP_7_18_FN, FN_IP6_29_27, + GP_7_17_FN, FN_IP6_26_24, + GP_7_16_FN, FN_IP6_23_21, + GP_7_15_FN, FN_IP6_20_19, + GP_7_14_FN, FN_IP6_18_16, + GP_7_13_FN, FN_IP6_15_14, + GP_7_12_FN, FN_IP6_13_12, + GP_7_11_FN, FN_IP6_11_10, + GP_7_10_FN, FN_IP6_9_8, + GP_7_9_FN, FN_IP16_11_10, + GP_7_8_FN, FN_IP16_9_8, + GP_7_7_FN, FN_IP16_7_6, + GP_7_6_FN, FN_IP16_5_3, + GP_7_5_FN, FN_IP16_2_0, + GP_7_4_FN, FN_IP15_29_27, + GP_7_3_FN, FN_IP15_26_24, + GP_7_2_FN, FN_IP15_23_21, + GP_7_1_FN, FN_IP15_20_18, + GP_7_0_FN, FN_IP15_17_15 } + }, + /* IPSR0 - IPSR10 */ + { PINMUX_CFG_REG_VAR("IPSR11", 0xE606004C, 32, + 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 3, 3, 3, 3, 3) { + /* IP11_31_30 [2] */ + FN_ETH_CRS_DV, FN_AVB_LINK, FN_SDA2_C, 0, + /* IP11_29_28 [2] */ + FN_ETH_MDIO, FN_AVB_RX_CLK, FN_SCL2_C, 0, + /* IP11_27 [1] */ + FN_VI1_DATA7, FN_AVB_MDC, + /* IP11_26 [1] */ + FN_VI1_DATA6, FN_AVB_MAGIC, + /* IP11_25 [1] */ + FN_VI1_DATA5, FN_AVB_RX_DV, + /* IP11_24 [1] */ + FN_VI1_DATA4, FN_AVB_MDIO, + /* IP11_23 [1] */ + FN_VI1_DATA3, FN_AVB_RX_ER, + /* IP11_22 [1] */ + FN_VI1_DATA2, FN_AVB_RXD7, + /* IP11_21 [1] */ + FN_VI1_DATA1, FN_AVB_RXD6, + /* IP11_20 [1] */ + FN_VI1_DATA0, FN_AVB_RXD5, + /* IP11_19 [1] */ + FN_VI1_CLK, FN_AVB_RXD4, + /* IP11_18_17 [2] */ + FN_VI1_FIELD, FN_AVB_RXD3, FN_TS_SPSYNC0_B, 0, + /* IP11_16_15 [2] */ + FN_VI1_CLKENB, FN_AVB_RXD2, FN_TS_SDEN0_B, 0, + /* IP11_14_12 [3] */ + FN_VI1_VSYNC_N, FN_AVB_RXD1, FN_TS_SCK0_B, + FN_RX4_B, FN_SCIFA4_RXD_B, + 0, 0, 0, + /* IP11_11_9 [3] */ + FN_VI1_HSYNC_N, FN_AVB_RXD0, FN_TS_SDATA0_B, + FN_TX4_B, FN_SCIFA4_TXD_B, + 0, 0, 0, + /* IP11_8_6 [3] */ + FN_VI0_R7, FN_GLO_RFON_B, FN_RX1_C, FN_CAN0_RX_E, + FN_SDA4_B, FN_HRX1_D, FN_SCIFB0_RXD_D, 0, + /* IP11_5_3 [3] */ + FN_VI0_R6, FN_VI2_DATA7, FN_GLO_SS_B, FN_TX1_C, FN_SCL4_B, + 0, 0, 0, + /* IP11_2_0 [3] */ + FN_VI0_R5, FN_VI2_DATA6, FN_GLO_SDATA_B, FN_RX0_C, FN_SDA1_D, + 0, 0, 0, } + }, + { PINMUX_CFG_REG_VAR("IPSR12", 0xE6060050, 32, + 2, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2) { + /* IP12_31_30 [2] */ + 0, 0, 0, 0, + /* IP12_29_27 [3] */ + FN_STP_ISCLK_0, FN_AVB_TX_EN, FN_SCIFB2_RXD_D, + FN_ADICS_SAMP_B, FN_MSIOF0_SCK_C, + 0, 0, 0, + /* IP12_26_24 [3] */ + FN_STP_IVCXO27_0, FN_AVB_TXD7, FN_SCIFB2_TXD_D, + FN_ADIDATA_B, FN_MSIOF0_SYNC_C, + 0, 0, 0, + /* IP12_23_22 [2] */ + FN_ETH_MDC, FN_AVB_TXD6, FN_IERX_C, 0, + /* IP12_21_20 [2] */ + FN_ETH_TXD0, FN_AVB_TXD5, FN_IECLK_C, 0, + /* IP12_19_18 [2] */ + FN_ETH_MAGIC, FN_AVB_TXD4, FN_IETX_C, 0, + /* IP12_17_16 [2] */ + FN_ETH_TX_EN, FN_AVB_TXD3, FN_TCLK1_B, FN_CAN_CLK_B, + /* IP12_15_13 [3] */ + FN_ETH_TXD1, FN_AVB_TXD2, FN_SCIFA3_TXD_B, + FN_CAN1_TX_C, FN_MSIOF1_TXD_E, + 0, 0, 0, + /* IP12_12_10 [3] */ + FN_ETH_REFCLK, FN_AVB_TXD1, FN_SCIFA3_RXD_B, + FN_CAN1_RX_C, FN_MSIOF1_SYNC_E, + 0, 0, 0, + /* IP12_9_7 [3] */ + FN_ETH_LINK, FN_AVB_TXD0, FN_CAN0_RX_C, + FN_SDA2_D, FN_MSIOF1_SCK_E, + 0, 0, 0, + /* IP12_6_4 [3] */ + FN_ETH_RXD1, FN_AVB_GTXREFCLK, FN_CAN0_TX_C, + FN_SCL2_D, FN_MSIOF1_RXD_E, + 0, 0, 0, + /* IP12_3_2 [2] */ + FN_ETH_RXD0, FN_AVB_PHY_INT, FN_SDA3, FN_SDA7, + /* IP12_1_0 [2] */ + FN_ETH_RX_ER, FN_AVB_CRS, FN_SCL3, FN_SCL7, } + }, + + /* IPSR13 - IPSR16 */ + + { PINMUX_CFG_REG_VAR("MOD_SEL", 0xE6060090, 32, + 1, 2, 2, 2, 3, 2, 1, 1, 1, 1, + 3, 2, 2, 2, 1, 2, 2, 2) { + /* RESEVED [1] */ + 0, 0, + /* SEL_SCIF1 [2] */ + FN_SEL_SCIF1_0, FN_SEL_SCIF1_1, FN_SEL_SCIF1_2, FN_SEL_SCIF1_3, + /* SEL_SCIFB [2] */ + FN_SEL_SCIFB_0, FN_SEL_SCIFB_1, FN_SEL_SCIFB_2, FN_SEL_SCIFB_3, + /* SEL_SCIFB2 [2] */ + FN_SEL_SCIFB2_0, FN_SEL_SCIFB2_1, + FN_SEL_SCIFB2_2, FN_SEL_SCIFB2_3, + /* SEL_SCIFB1 [3] */ + FN_SEL_SCIFB1_0, FN_SEL_SCIFB1_1, + FN_SEL_SCIFB1_2, FN_SEL_SCIFB1_3, + 0, 0, 0, 0, + /* SEL_SCIFA1 [2] */ + FN_SEL_SCIFA1_0, FN_SEL_SCIFA1_1, FN_SEL_SCIFA1_2, 0, + /* SEL_SSI9 [1] */ + FN_SEL_SSI9_0, FN_SEL_SSI9_1, + /* SEL_SCFA [1] */ + FN_SEL_SCFA_0, FN_SEL_SCFA_1, + /* SEL_QSP [1] */ + FN_SEL_QSP_0, FN_SEL_QSP_1, + /* SEL_SSI7 [1] */ + FN_SEL_SSI7_0, FN_SEL_SSI7_1, + /* SEL_HSCIF1 [3] */ + FN_SEL_HSCIF1_0, FN_SEL_HSCIF1_1, FN_SEL_HSCIF1_2, + FN_SEL_HSCIF1_3, FN_SEL_HSCIF1_4, + 0, 0, 0, + /* RESEVED [2] */ + 0, 0, 0, 0, + /* SEL_VI1 [2] */ + FN_SEL_VI1_0, FN_SEL_VI1_1, FN_SEL_VI1_2, 0, + /* RESEVED [2] */ + 0, 0, 0, 0, + /* SEL_TMU [1] */ + FN_SEL_TMU1_0, FN_SEL_TMU1_1, + /* SEL_LBS [2] */ + FN_SEL_LBS_0, FN_SEL_LBS_1, FN_SEL_LBS_2, FN_SEL_LBS_3, + /* SEL_TSIF0 [2] */ + FN_SEL_TSIF0_0, FN_SEL_TSIF0_1, FN_SEL_TSIF0_2, FN_SEL_TSIF0_3, + /* SEL_SOF0 [2] */ + FN_SEL_SOF0_0, FN_SEL_SOF0_1, FN_SEL_SOF0_2, 0, } + }, + { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xE6060094, 32, + 3, 1, 1, 3, 2, 1, 1, 2, 2, + 1, 3, 2, 1, 2, 2, 2, 1, 1, 1) { + /* SEL_SCIF0 [3] */ + FN_SEL_SCIF0_0, FN_SEL_SCIF0_1, FN_SEL_SCIF0_2, + FN_SEL_SCIF0_3, FN_SEL_SCIF0_4, + 0, 0, 0, + /* RESEVED [1] */ + 0, 0, + /* SEL_SCIF [1] */ + FN_SEL_SCIF_0, FN_SEL_SCIF_1, + /* SEL_CAN0 [3] */ + FN_SEL_CAN0_0, FN_SEL_CAN0_1, FN_SEL_CAN0_2, FN_SEL_CAN0_3, + FN_SEL_CAN0_4, FN_SEL_CAN0_5, + 0, 0, + /* SEL_CAN1 [2] */ + FN_SEL_CAN1_0, FN_SEL_CAN1_1, FN_SEL_CAN1_2, FN_SEL_CAN1_3, + /* RESEVED [1] */ + 0, 0, + /* SEL_SCIFA2 [1] */ + FN_SEL_SCIFA2_0, FN_SEL_SCIFA2_1, + /* SEL_SCIF4 [2] */ + FN_SEL_SCIF4_0, FN_SEL_SCIF4_1, FN_SEL_SCIF4_2, 0, + /* RESEVED [2] */ + 0, 0, 0, 0, + /* SEL_ADG [1] */ + FN_SEL_ADG_0, FN_SEL_ADG_1, + /* SEL_FM [3] */ + FN_SEL_FM_0, FN_SEL_FM_1, FN_SEL_FM_2, + FN_SEL_FM_3, FN_SEL_FM_4, + 0, 0, 0, + /* SEL_SCIFA5 [2] */ + FN_SEL_SCIFA5_0, FN_SEL_SCIFA5_1, FN_SEL_SCIFA5_2, 0, + /* RESEVED [1] */ + 0, 0, + /* SEL_GPS [2] */ + FN_SEL_GPS_0, FN_SEL_GPS_1, FN_SEL_GPS_2, FN_SEL_GPS_3, + /* SEL_SCIFA4 [2] */ + FN_SEL_SCIFA4_0, FN_SEL_SCIFA4_1, FN_SEL_SCIFA4_2, 0, + /* SEL_SCIFA3 [2] */ + FN_SEL_SCIFA3_0, FN_SEL_SCIFA3_1, FN_SEL_SCIFA3_2, 0, + /* SEL_SIM [1] */ + FN_SEL_SIM_0, FN_SEL_SIM_1, + /* RESEVED [1] */ + 0, 0, + /* SEL_SSI8 [1] */ + FN_SEL_SSI8_0, FN_SEL_SSI8_1, } + }, + { PINMUX_CFG_REG_VAR("MOD_SEL3", 0xE6060098, 32, + 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 2, 2, 3, 2, 2, 2, 1) { + /* SEL_HSCIF2 [2] */ + FN_SEL_HSCIF2_0, FN_SEL_HSCIF2_1, + FN_SEL_HSCIF2_2, FN_SEL_HSCIF2_3, + /* SEL_CANCLK [2] */ + FN_SEL_CANCLK_0, FN_SEL_CANCLK_1, + FN_SEL_CANCLK_2, FN_SEL_CANCLK_3, + /* SEL_IIC8 [2] */ + FN_SEL_IIC8_0, FN_SEL_IIC8_1, FN_SEL_IIC8_2, 0, + /* SEL_IIC7 [2] */ + FN_SEL_IIC7_0, FN_SEL_IIC7_1, FN_SEL_IIC7_2, 0, + /* SEL_IIC4 [2] */ + FN_SEL_IIC4_0, FN_SEL_IIC4_1, FN_SEL_IIC4_2, 0, + /* SEL_IIC3 [2] */ + FN_SEL_IIC3_0, FN_SEL_IIC3_1, FN_SEL_IIC3_2, FN_SEL_IIC3_3, + /* SEL_SCIF3 [2] */ + FN_SEL_SCIF3_0, FN_SEL_SCIF3_1, FN_SEL_SCIF3_2, FN_SEL_SCIF3_3, + /* SEL_IEB [2] */ + FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2, + /* SEL_MMC [1] */ + FN_SEL_MMC_0, FN_SEL_MMC_1, + /* SEL_SCIF5 [1] */ + FN_SEL_SCIF5_0, FN_SEL_SCIF5_1, + /* RESEVED [2] */ + 0, 0, 0, 0, + /* SEL_IIC2 [2] */ + FN_SEL_IIC2_0, FN_SEL_IIC2_1, FN_SEL_IIC2_2, FN_SEL_IIC2_3, + /* SEL_IIC1 [3] */ + FN_SEL_IIC1_0, FN_SEL_IIC1_1, FN_SEL_IIC1_2, FN_SEL_IIC1_3, + FN_SEL_IIC1_4, + 0, 0, 0, + /* SEL_IIC0 [2] */ + FN_SEL_IIC0_0, FN_SEL_IIC0_1, FN_SEL_IIC0_2, 0, + /* RESEVED [2] */ + 0, 0, 0, 0, + /* RESEVED [2] */ + 0, 0, 0, 0, + /* RESEVED [1] */ + 0, 0, } + }, + { PINMUX_CFG_REG_VAR("MOD_SEL4", 0xE606009C, 32, + 3, 2, 2, 1, 1, 1, 1, 3, 2, + 2, 3, 1, 1, 1, 2, 2, 2, 2) { + /* SEL_SOF1 [3] */ + FN_SEL_SOF1_0, FN_SEL_SOF1_1, FN_SEL_SOF1_2, FN_SEL_SOF1_3, + FN_SEL_SOF1_4, + 0, 0, 0, + /* SEL_HSCIF0 [2] */ + FN_SEL_HSCIF0_0, FN_SEL_HSCIF0_1, FN_SEL_HSCIF0_2, 0, + /* SEL_DIS [2] */ + FN_SEL_DIS_0, FN_SEL_DIS_1, FN_SEL_DIS_2, 0, + /* RESEVED [1] */ + 0, 0, + /* SEL_RAD [1] */ + FN_SEL_RAD_0, FN_SEL_RAD_1, + /* SEL_RCN [1] */ + FN_SEL_RCN_0, FN_SEL_RCN_1, + /* SEL_RSP [1] */ + FN_SEL_RSP_0, FN_SEL_RSP_1, + /* SEL_SCIF2 [3] */ + FN_SEL_SCIF2_0, FN_SEL_SCIF2_1, FN_SEL_SCIF2_2, + FN_SEL_SCIF2_3, FN_SEL_SCIF2_4, + 0, 0, 0, + /* RESEVED [2] */ + 0, 0, 0, 0, + /* RESEVED [2] */ + 0, 0, 0, 0, + /* SEL_SOF2 [3] */ + FN_SEL_SOF2_0, FN_SEL_SOF2_1, FN_SEL_SOF2_2, + FN_SEL_SOF2_3, FN_SEL_SOF2_4, + 0, 0, 0, + /* RESEVED [1] */ + 0, 0, + /* SEL_SSI1 [1] */ + FN_SEL_SSI1_0, FN_SEL_SSI1_1, + /* SEL_SSI0 [1] */ + FN_SEL_SSI0_0, FN_SEL_SSI0_1, + /* SEL_SSP [2] */ + FN_SEL_SSP_0, FN_SEL_SSP_1, FN_SEL_SSP_2, 0, + /* RESEVED [2] */ + 0, 0, 0, 0, + /* RESEVED [2] */ + 0, 0, 0, 0, + /* RESEVED [2] */ + 0, 0, 0, 0, } + }, + { PINMUX_CFG_REG("INOUTSEL0", 0xE6050004, 32, 1) { GP_INOUTSEL(0) } }, + { PINMUX_CFG_REG("INOUTSEL1", 0xE6051004, 32, 1) { + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + GP_1_25_IN, GP_1_25_OUT, + GP_1_24_IN, GP_1_24_OUT, + GP_1_23_IN, GP_1_23_OUT, + GP_1_22_IN, GP_1_22_OUT, + GP_1_21_IN, GP_1_21_OUT, + GP_1_20_IN, GP_1_20_OUT, + GP_1_19_IN, GP_1_19_OUT, + GP_1_18_IN, GP_1_18_OUT, + GP_1_17_IN, GP_1_17_OUT, + GP_1_16_IN, GP_1_16_OUT, + GP_1_15_IN, GP_1_15_OUT, + GP_1_14_IN, GP_1_14_OUT, + GP_1_13_IN, GP_1_13_OUT, + GP_1_12_IN, GP_1_12_OUT, + GP_1_11_IN, GP_1_11_OUT, + GP_1_10_IN, GP_1_10_OUT, + GP_1_9_IN, GP_1_9_OUT, + GP_1_8_IN, GP_1_8_OUT, + GP_1_7_IN, GP_1_7_OUT, + GP_1_6_IN, GP_1_6_OUT, + GP_1_5_IN, GP_1_5_OUT, + GP_1_4_IN, GP_1_4_OUT, + GP_1_3_IN, GP_1_3_OUT, + GP_1_2_IN, GP_1_2_OUT, + GP_1_1_IN, GP_1_1_OUT, + GP_1_0_IN, GP_1_0_OUT, } + }, + { PINMUX_CFG_REG("INOUTSEL2", 0xE6052004, 32, 1) { GP_INOUTSEL(2) } }, + { PINMUX_CFG_REG("INOUTSEL3", 0xE6053004, 32, 1) { GP_INOUTSEL(3) } }, + { PINMUX_CFG_REG("INOUTSEL4", 0xE6054004, 32, 1) { GP_INOUTSEL(4) } }, + { PINMUX_CFG_REG("INOUTSEL5", 0xE6055004, 32, 1) { GP_INOUTSEL(5) } }, + { PINMUX_CFG_REG("INOUTSEL6", 0xE6055404, 32, 1) { GP_INOUTSEL(6) } }, + { PINMUX_CFG_REG("INOUTSEL7", 0xE6055804, 32, 1) { + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + GP_7_25_IN, GP_7_25_OUT, + GP_7_24_IN, GP_7_24_OUT, + GP_7_23_IN, GP_7_23_OUT, + GP_7_22_IN, GP_7_22_OUT, + GP_7_21_IN, GP_7_21_OUT, + GP_7_20_IN, GP_7_20_OUT, + GP_7_19_IN, GP_7_19_OUT, + GP_7_18_IN, GP_7_18_OUT, + GP_7_17_IN, GP_7_17_OUT, + GP_7_16_IN, GP_7_16_OUT, + GP_7_15_IN, GP_7_15_OUT, + GP_7_14_IN, GP_7_14_OUT, + GP_7_13_IN, GP_7_13_OUT, + GP_7_12_IN, GP_7_12_OUT, + GP_7_11_IN, GP_7_11_OUT, + GP_7_10_IN, GP_7_10_OUT, + GP_7_9_IN, GP_7_9_OUT, + GP_7_8_IN, GP_7_8_OUT, + GP_7_7_IN, GP_7_7_OUT, + GP_7_6_IN, GP_7_6_OUT, + GP_7_5_IN, GP_7_5_OUT, + GP_7_4_IN, GP_7_4_OUT, + GP_7_3_IN, GP_7_3_OUT, + GP_7_2_IN, GP_7_2_OUT, + GP_7_1_IN, GP_7_1_OUT, + GP_7_0_IN, GP_7_0_OUT, } + }, + { }, +}; + +static struct pinmux_data_reg pinmux_data_regs[] = { + { PINMUX_DATA_REG("INDT0", 0xE6050008, 32) { GP_INDT(0) } }, + { PINMUX_DATA_REG("INDT1", 0xE6051008, 32) { + 0, 0, 0, 0, + 0, 0, GP_1_25_DATA, GP_1_24_DATA, + GP_1_23_DATA, GP_1_22_DATA, GP_1_21_DATA, GP_1_20_DATA, + GP_1_19_DATA, GP_1_18_DATA, GP_1_17_DATA, GP_1_16_DATA, + GP_1_15_DATA, GP_1_14_DATA, GP_1_13_DATA, GP_1_12_DATA, + GP_1_11_DATA, GP_1_10_DATA, GP_1_9_DATA, GP_1_8_DATA, + GP_1_7_DATA, GP_1_6_DATA, GP_1_5_DATA, GP_1_4_DATA, + GP_1_3_DATA, GP_1_2_DATA, GP_1_1_DATA, GP_1_0_DATA } + }, + { PINMUX_DATA_REG("INDT2", 0xE6052008, 32) { GP_INDT(2) } }, + { PINMUX_DATA_REG("INDT3", 0xE6053008, 32) { GP_INDT(3) } }, + { PINMUX_DATA_REG("INDT4", 0xE6054008, 32) { GP_INDT(4) } }, + { PINMUX_DATA_REG("INDT5", 0xE6055008, 32) { GP_INDT(5) } }, + { PINMUX_DATA_REG("INDT6", 0xE6055408, 32) { GP_INDT(6) } }, + { PINMUX_DATA_REG("INDT7", 0xE6055808, 32) { + 0, 0, 0, 0, + 0, 0, GP_7_25_DATA, GP_7_24_DATA, + GP_7_23_DATA, GP_7_22_DATA, GP_7_21_DATA, GP_7_20_DATA, + GP_7_19_DATA, GP_7_18_DATA, GP_7_17_DATA, GP_7_16_DATA, + GP_7_15_DATA, GP_7_14_DATA, GP_7_13_DATA, GP_7_12_DATA, + GP_7_11_DATA, GP_7_10_DATA, GP_7_9_DATA, GP_7_8_DATA, + GP_7_7_DATA, GP_7_6_DATA, GP_7_5_DATA, GP_7_4_DATA, + GP_7_3_DATA, GP_7_2_DATA, GP_7_1_DATA, GP_7_0_DATA } + }, + { }, +}; + +static struct pinmux_info r8a7791_pinmux_info = { + .name = "r8a7791_pfc", + + .unlock_reg = 0xe6060000, /* PMMR */ + + .reserved_id = PINMUX_RESERVED, + .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END }, + .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END }, + .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END }, + .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END }, + .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, + + .first_gpio = GPIO_GP_0_0, + .last_gpio = GPIO_FN_MSIOF0_SCK_C /* GPIO_FN_CAN1_RX_B */, + + .gpios = pinmux_gpios, + .cfg_regs = pinmux_config_regs, + .data_regs = pinmux_data_regs, + + .gpio_data = pinmux_data, + .gpio_data_size = ARRAY_SIZE(pinmux_data), +}; + +void r8a7791_pinmux_init(void) +{ + register_pinmux(&r8a7791_pinmux_info); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-sh73a0.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-sh73a0.c new file mode 100644 index 000000000..55dab7c13 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/pfc-sh73a0.c @@ -0,0 +1,2807 @@ +/* + * sh73a0 processor support - PFC hardware block + * + * Copyright (C) 2010 Renesas Solutions Corp. + * Copyright (C) 2010 NISHIMOTO Hiroki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <common.h> +#include <sh_pfc.h> +#include <asm/arch/sh73a0-gpio.h> + +#define CPU_ALL_PORT(fn, pfx, sfx) \ + PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \ + PORT_10(fn, pfx##2, sfx), PORT_10(fn, pfx##3, sfx), \ + PORT_10(fn, pfx##4, sfx), PORT_10(fn, pfx##5, sfx), \ + PORT_10(fn, pfx##6, sfx), PORT_10(fn, pfx##7, sfx), \ + PORT_10(fn, pfx##8, sfx), PORT_10(fn, pfx##9, sfx), \ + PORT_10(fn, pfx##10, sfx), \ + PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx), \ + PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx), \ + PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx), \ + PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx), \ + PORT_1(fn, pfx##118, sfx), \ + PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx), \ + PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx), \ + PORT_10(fn, pfx##15, sfx), \ + PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx), \ + PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx), \ + PORT_1(fn, pfx##164, sfx), \ + PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx), \ + PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx), \ + PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx), \ + PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx), \ + PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx), \ + PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx), \ + PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx), \ + PORT_10(fn, pfx##26, sfx), PORT_10(fn, pfx##27, sfx), \ + PORT_1(fn, pfx##280, sfx), PORT_1(fn, pfx##281, sfx), \ + PORT_1(fn, pfx##282, sfx), \ + PORT_1(fn, pfx##288, sfx), PORT_1(fn, pfx##289, sfx), \ + PORT_10(fn, pfx##29, sfx), PORT_10(fn, pfx##30, sfx) + +enum { + PINMUX_RESERVED = 0, + + PINMUX_DATA_BEGIN, + PORT_ALL(DATA), /* PORT0_DATA -> PORT309_DATA */ + PINMUX_DATA_END, + + PINMUX_INPUT_BEGIN, + PORT_ALL(IN), /* PORT0_IN -> PORT309_IN */ + PINMUX_INPUT_END, + + PINMUX_INPUT_PULLUP_BEGIN, + PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT309_IN_PU */ + PINMUX_INPUT_PULLUP_END, + + PINMUX_INPUT_PULLDOWN_BEGIN, + PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT309_IN_PD */ + PINMUX_INPUT_PULLDOWN_END, + + PINMUX_OUTPUT_BEGIN, + PORT_ALL(OUT), /* PORT0_OUT -> PORT309_OUT */ + PINMUX_OUTPUT_END, + + PINMUX_FUNCTION_BEGIN, + PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT309_FN_IN */ + PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT309_FN_OUT */ + PORT_ALL(FN0), /* PORT0_FN0 -> PORT309_FN0 */ + PORT_ALL(FN1), /* PORT0_FN1 -> PORT309_FN1 */ + PORT_ALL(FN2), /* PORT0_FN2 -> PORT309_FN2 */ + PORT_ALL(FN3), /* PORT0_FN3 -> PORT309_FN3 */ + PORT_ALL(FN4), /* PORT0_FN4 -> PORT309_FN4 */ + PORT_ALL(FN5), /* PORT0_FN5 -> PORT309_FN5 */ + PORT_ALL(FN6), /* PORT0_FN6 -> PORT309_FN6 */ + PORT_ALL(FN7), /* PORT0_FN7 -> PORT309_FN7 */ + + MSEL2CR_MSEL19_0, MSEL2CR_MSEL19_1, + MSEL2CR_MSEL18_0, MSEL2CR_MSEL18_1, + MSEL2CR_MSEL17_0, MSEL2CR_MSEL17_1, + MSEL2CR_MSEL16_0, MSEL2CR_MSEL16_1, + MSEL2CR_MSEL14_0, MSEL2CR_MSEL14_1, + MSEL2CR_MSEL13_0, MSEL2CR_MSEL13_1, + MSEL2CR_MSEL12_0, MSEL2CR_MSEL12_1, + MSEL2CR_MSEL11_0, MSEL2CR_MSEL11_1, + MSEL2CR_MSEL10_0, MSEL2CR_MSEL10_1, + MSEL2CR_MSEL9_0, MSEL2CR_MSEL9_1, + MSEL2CR_MSEL8_0, MSEL2CR_MSEL8_1, + MSEL2CR_MSEL7_0, MSEL2CR_MSEL7_1, + MSEL2CR_MSEL6_0, MSEL2CR_MSEL6_1, + MSEL2CR_MSEL4_0, MSEL2CR_MSEL4_1, + MSEL2CR_MSEL5_0, MSEL2CR_MSEL5_1, + MSEL2CR_MSEL3_0, MSEL2CR_MSEL3_1, + MSEL2CR_MSEL2_0, MSEL2CR_MSEL2_1, + MSEL2CR_MSEL1_0, MSEL2CR_MSEL1_1, + MSEL2CR_MSEL0_0, MSEL2CR_MSEL0_1, + MSEL3CR_MSEL28_0, MSEL3CR_MSEL28_1, + MSEL3CR_MSEL15_0, MSEL3CR_MSEL15_1, + MSEL3CR_MSEL11_0, MSEL3CR_MSEL11_1, + MSEL3CR_MSEL9_0, MSEL3CR_MSEL9_1, + MSEL3CR_MSEL6_0, MSEL3CR_MSEL6_1, + MSEL3CR_MSEL2_0, MSEL3CR_MSEL2_1, + MSEL4CR_MSEL29_0, MSEL4CR_MSEL29_1, + MSEL4CR_MSEL27_0, MSEL4CR_MSEL27_1, + MSEL4CR_MSEL26_0, MSEL4CR_MSEL26_1, + MSEL4CR_MSEL22_0, MSEL4CR_MSEL22_1, + MSEL4CR_MSEL21_0, MSEL4CR_MSEL21_1, + MSEL4CR_MSEL20_0, MSEL4CR_MSEL20_1, + MSEL4CR_MSEL19_0, MSEL4CR_MSEL19_1, + MSEL4CR_MSEL15_0, MSEL4CR_MSEL15_1, + MSEL4CR_MSEL13_0, MSEL4CR_MSEL13_1, + MSEL4CR_MSEL12_0, MSEL4CR_MSEL12_1, + MSEL4CR_MSEL11_0, MSEL4CR_MSEL11_1, + MSEL4CR_MSEL10_0, MSEL4CR_MSEL10_1, + MSEL4CR_MSEL9_0, MSEL4CR_MSEL9_1, + MSEL4CR_MSEL8_0, MSEL4CR_MSEL8_1, + MSEL4CR_MSEL7_0, MSEL4CR_MSEL7_1, + MSEL4CR_MSEL4_0, MSEL4CR_MSEL4_1, + MSEL4CR_MSEL1_0, MSEL4CR_MSEL1_1, + PINMUX_FUNCTION_END, + + PINMUX_MARK_BEGIN, + /* Hardware manual Table 25-1 (Function 0-7) */ + VBUS_0_MARK, + GPI0_MARK, + GPI1_MARK, + GPI2_MARK, + GPI3_MARK, + GPI4_MARK, + GPI5_MARK, + GPI6_MARK, + GPI7_MARK, + SCIFA7_RXD_MARK, + SCIFA7_CTS__MARK, + GPO7_MARK, MFG0_OUT2_MARK, + GPO6_MARK, MFG1_OUT2_MARK, + GPO5_MARK, SCIFA0_SCK_MARK, FSICOSLDT3_MARK, PORT16_VIO_CKOR_MARK, + SCIFA0_TXD_MARK, + SCIFA7_TXD_MARK, + SCIFA7_RTS__MARK, PORT19_VIO_CKO2_MARK, + GPO0_MARK, + GPO1_MARK, + GPO2_MARK, STATUS0_MARK, + GPO3_MARK, STATUS1_MARK, + GPO4_MARK, STATUS2_MARK, + VINT_MARK, + TCKON_MARK, + XDVFS1_MARK, PORT27_I2C_SCL2_MARK, PORT27_I2C_SCL3_MARK, \ + MFG0_OUT1_MARK, PORT27_IROUT_MARK, + XDVFS2_MARK, PORT28_I2C_SDA2_MARK, PORT28_I2C_SDA3_MARK, \ + PORT28_TPU1TO1_MARK, + SIM_RST_MARK, PORT29_TPU1TO1_MARK, + SIM_CLK_MARK, PORT30_VIO_CKOR_MARK, + SIM_D_MARK, PORT31_IROUT_MARK, + SCIFA4_TXD_MARK, + SCIFA4_RXD_MARK, XWUP_MARK, + SCIFA4_RTS__MARK, + SCIFA4_CTS__MARK, + FSIBOBT_MARK, FSIBIBT_MARK, + FSIBOLR_MARK, FSIBILR_MARK, + FSIBOSLD_MARK, + FSIBISLD_MARK, + VACK_MARK, + XTAL1L_MARK, + SCIFA0_RTS__MARK, FSICOSLDT2_MARK, + SCIFA0_RXD_MARK, + SCIFA0_CTS__MARK, FSICOSLDT1_MARK, + FSICOBT_MARK, FSICIBT_MARK, FSIDOBT_MARK, FSIDIBT_MARK, + FSICOLR_MARK, FSICILR_MARK, FSIDOLR_MARK, FSIDILR_MARK, + FSICOSLD_MARK, PORT47_FSICSPDIF_MARK, + FSICISLD_MARK, FSIDISLD_MARK, + FSIACK_MARK, PORT49_IRDA_OUT_MARK, PORT49_IROUT_MARK, FSIAOMC_MARK, + FSIAOLR_MARK, BBIF2_TSYNC2_MARK, TPU2TO2_MARK, FSIAILR_MARK, + + FSIAOBT_MARK, BBIF2_TSCK2_MARK, TPU2TO3_MARK, FSIAIBT_MARK, + FSIAOSLD_MARK, BBIF2_TXD2_MARK, + FSIASPDIF_MARK, PORT53_IRDA_IN_MARK, TPU3TO3_MARK, FSIBSPDIF_MARK, \ + PORT53_FSICSPDIF_MARK, + FSIBCK_MARK, PORT54_IRDA_FIRSEL_MARK, TPU3TO2_MARK, FSIBOMC_MARK, \ + FSICCK_MARK, FSICOMC_MARK, + FSIAISLD_MARK, TPU0TO0_MARK, + A0_MARK, BS__MARK, + A12_MARK, PORT58_KEYOUT7_MARK, TPU4TO2_MARK, + A13_MARK, PORT59_KEYOUT6_MARK, TPU0TO1_MARK, + A14_MARK, KEYOUT5_MARK, + A15_MARK, KEYOUT4_MARK, + A16_MARK, KEYOUT3_MARK, MSIOF0_SS1_MARK, + A17_MARK, KEYOUT2_MARK, MSIOF0_TSYNC_MARK, + A18_MARK, KEYOUT1_MARK, MSIOF0_TSCK_MARK, + A19_MARK, KEYOUT0_MARK, MSIOF0_TXD_MARK, + A20_MARK, KEYIN0_MARK, MSIOF0_RSCK_MARK, + A21_MARK, KEYIN1_MARK, MSIOF0_RSYNC_MARK, + A22_MARK, KEYIN2_MARK, MSIOF0_MCK0_MARK, + A23_MARK, KEYIN3_MARK, MSIOF0_MCK1_MARK, + A24_MARK, KEYIN4_MARK, MSIOF0_RXD_MARK, + A25_MARK, KEYIN5_MARK, MSIOF0_SS2_MARK, + A26_MARK, KEYIN6_MARK, + KEYIN7_MARK, + D0_NAF0_MARK, + D1_NAF1_MARK, + D2_NAF2_MARK, + D3_NAF3_MARK, + D4_NAF4_MARK, + D5_NAF5_MARK, + D6_NAF6_MARK, + D7_NAF7_MARK, + D8_NAF8_MARK, + D9_NAF9_MARK, + D10_NAF10_MARK, + D11_NAF11_MARK, + D12_NAF12_MARK, + D13_NAF13_MARK, + D14_NAF14_MARK, + D15_NAF15_MARK, + CS4__MARK, + CS5A__MARK, PORT91_RDWR_MARK, + CS5B__MARK, FCE1__MARK, + CS6B__MARK, DACK0_MARK, + FCE0__MARK, CS6A__MARK, + WAIT__MARK, DREQ0_MARK, + RD__FSC_MARK, + WE0__FWE_MARK, RDWR_FWE_MARK, + WE1__MARK, + FRB_MARK, + CKO_MARK, + NBRSTOUT__MARK, + NBRST__MARK, + BBIF2_TXD_MARK, + BBIF2_RXD_MARK, + BBIF2_SYNC_MARK, + BBIF2_SCK_MARK, + SCIFA3_CTS__MARK, MFG3_IN2_MARK, + SCIFA3_RXD_MARK, MFG3_IN1_MARK, + BBIF1_SS2_MARK, SCIFA3_RTS__MARK, MFG3_OUT1_MARK, + SCIFA3_TXD_MARK, + HSI_RX_DATA_MARK, BBIF1_RXD_MARK, + HSI_TX_WAKE_MARK, BBIF1_TSCK_MARK, + HSI_TX_DATA_MARK, BBIF1_TSYNC_MARK, + HSI_TX_READY_MARK, BBIF1_TXD_MARK, + HSI_RX_READY_MARK, BBIF1_RSCK_MARK, PORT115_I2C_SCL2_MARK, \ + PORT115_I2C_SCL3_MARK, + HSI_RX_WAKE_MARK, BBIF1_RSYNC_MARK, PORT116_I2C_SDA2_MARK, \ + PORT116_I2C_SDA3_MARK, + HSI_RX_FLAG_MARK, BBIF1_SS1_MARK, BBIF1_FLOW_MARK, + HSI_TX_FLAG_MARK, + VIO_VD_MARK, PORT128_LCD2VSYN_MARK, VIO2_VD_MARK, LCD2D0_MARK, + + VIO_HD_MARK, PORT129_LCD2HSYN_MARK, PORT129_LCD2CS__MARK, \ + VIO2_HD_MARK, LCD2D1_MARK, + VIO_D0_MARK, PORT130_MSIOF2_RXD_MARK, LCD2D10_MARK, + VIO_D1_MARK, PORT131_KEYOUT6_MARK, PORT131_MSIOF2_SS1_MARK, \ + PORT131_KEYOUT11_MARK, LCD2D11_MARK, + VIO_D2_MARK, PORT132_KEYOUT7_MARK, PORT132_MSIOF2_SS2_MARK, \ + PORT132_KEYOUT10_MARK, LCD2D12_MARK, + VIO_D3_MARK, MSIOF2_TSYNC_MARK, LCD2D13_MARK, + VIO_D4_MARK, MSIOF2_TXD_MARK, LCD2D14_MARK, + VIO_D5_MARK, MSIOF2_TSCK_MARK, LCD2D15_MARK, + VIO_D6_MARK, PORT136_KEYOUT8_MARK, LCD2D16_MARK, + VIO_D7_MARK, PORT137_KEYOUT9_MARK, LCD2D17_MARK, + VIO_D8_MARK, PORT138_KEYOUT8_MARK, VIO2_D0_MARK, LCD2D6_MARK, + VIO_D9_MARK, PORT139_KEYOUT9_MARK, VIO2_D1_MARK, LCD2D7_MARK, + VIO_D10_MARK, TPU0TO2_MARK, VIO2_D2_MARK, LCD2D8_MARK, + VIO_D11_MARK, TPU0TO3_MARK, VIO2_D3_MARK, LCD2D9_MARK, + VIO_D12_MARK, PORT142_KEYOUT10_MARK, VIO2_D4_MARK, LCD2D2_MARK, + VIO_D13_MARK, PORT143_KEYOUT11_MARK, PORT143_KEYOUT6_MARK, \ + VIO2_D5_MARK, LCD2D3_MARK, + VIO_D14_MARK, PORT144_KEYOUT7_MARK, VIO2_D6_MARK, LCD2D4_MARK, + VIO_D15_MARK, TPU1TO3_MARK, PORT145_LCD2DISP_MARK, \ + PORT145_LCD2RS_MARK, VIO2_D7_MARK, LCD2D5_MARK, + VIO_CLK_MARK, LCD2DCK_MARK, PORT146_LCD2WR__MARK, VIO2_CLK_MARK, \ + LCD2D18_MARK, + VIO_FIELD_MARK, LCD2RD__MARK, VIO2_FIELD_MARK, LCD2D19_MARK, + VIO_CKO_MARK, + A27_MARK, PORT149_RDWR_MARK, MFG0_IN1_MARK, PORT149_KEYOUT9_MARK, + MFG0_IN2_MARK, + TS_SPSYNC3_MARK, MSIOF2_RSCK_MARK, + TS_SDAT3_MARK, MSIOF2_RSYNC_MARK, + TPU1TO2_MARK, TS_SDEN3_MARK, PORT153_MSIOF2_SS1_MARK, + SCIFA2_TXD1_MARK, MSIOF2_MCK0_MARK, + SCIFA2_RXD1_MARK, MSIOF2_MCK1_MARK, + SCIFA2_RTS1__MARK, PORT156_MSIOF2_SS2_MARK, + SCIFA2_CTS1__MARK, PORT157_MSIOF2_RXD_MARK, + DINT__MARK, SCIFA2_SCK1_MARK, TS_SCK3_MARK, + PORT159_SCIFB_SCK_MARK, PORT159_SCIFA5_SCK_MARK, NMI_MARK, + PORT160_SCIFB_TXD_MARK, PORT160_SCIFA5_TXD_MARK, + PORT161_SCIFB_CTS__MARK, PORT161_SCIFA5_CTS__MARK, + PORT162_SCIFB_RXD_MARK, PORT162_SCIFA5_RXD_MARK, + PORT163_SCIFB_RTS__MARK, PORT163_SCIFA5_RTS__MARK, TPU3TO0_MARK, + LCDD0_MARK, + LCDD1_MARK, PORT193_SCIFA5_CTS__MARK, BBIF2_TSYNC1_MARK, + LCDD2_MARK, PORT194_SCIFA5_RTS__MARK, BBIF2_TSCK1_MARK, + LCDD3_MARK, PORT195_SCIFA5_RXD_MARK, BBIF2_TXD1_MARK, + LCDD4_MARK, PORT196_SCIFA5_TXD_MARK, + LCDD5_MARK, PORT197_SCIFA5_SCK_MARK, MFG2_OUT2_MARK, TPU2TO1_MARK, + LCDD6_MARK, + LCDD7_MARK, TPU4TO1_MARK, MFG4_OUT2_MARK, + LCDD8_MARK, D16_MARK, + LCDD9_MARK, D17_MARK, + LCDD10_MARK, D18_MARK, + LCDD11_MARK, D19_MARK, + LCDD12_MARK, D20_MARK, + LCDD13_MARK, D21_MARK, + LCDD14_MARK, D22_MARK, + LCDD15_MARK, PORT207_MSIOF0L_SS1_MARK, D23_MARK, + LCDD16_MARK, PORT208_MSIOF0L_SS2_MARK, D24_MARK, + LCDD17_MARK, D25_MARK, + LCDD18_MARK, DREQ2_MARK, PORT210_MSIOF0L_SS1_MARK, D26_MARK, + LCDD19_MARK, PORT211_MSIOF0L_SS2_MARK, D27_MARK, + LCDD20_MARK, TS_SPSYNC1_MARK, MSIOF0L_MCK0_MARK, D28_MARK, + LCDD21_MARK, TS_SDAT1_MARK, MSIOF0L_MCK1_MARK, D29_MARK, + LCDD22_MARK, TS_SDEN1_MARK, MSIOF0L_RSCK_MARK, D30_MARK, + LCDD23_MARK, TS_SCK1_MARK, MSIOF0L_RSYNC_MARK, D31_MARK, + LCDDCK_MARK, LCDWR__MARK, + LCDRD__MARK, DACK2_MARK, PORT217_LCD2RS_MARK, MSIOF0L_TSYNC_MARK, \ + VIO2_FIELD3_MARK, PORT217_LCD2DISP_MARK, + LCDHSYN_MARK, LCDCS__MARK, LCDCS2__MARK, DACK3_MARK, \ + PORT218_VIO_CKOR_MARK, + LCDDISP_MARK, LCDRS_MARK, PORT219_LCD2WR__MARK, DREQ3_MARK, \ + MSIOF0L_TSCK_MARK, VIO2_CLK3_MARK, LCD2DCK_2_MARK, + LCDVSYN_MARK, LCDVSYN2_MARK, + LCDLCLK_MARK, DREQ1_MARK, PORT221_LCD2CS__MARK, PWEN_MARK, \ + MSIOF0L_RXD_MARK, VIO2_HD3_MARK, PORT221_LCD2HSYN_MARK, + LCDDON_MARK, LCDDON2_MARK, DACK1_MARK, OVCN_MARK, MSIOF0L_TXD_MARK, \ + VIO2_VD3_MARK, PORT222_LCD2VSYN_MARK, + + SCIFA1_TXD_MARK, OVCN2_MARK, + EXTLP_MARK, SCIFA1_SCK_MARK, PORT226_VIO_CKO2_MARK, + SCIFA1_RTS__MARK, IDIN_MARK, + SCIFA1_RXD_MARK, + SCIFA1_CTS__MARK, MFG1_IN1_MARK, + MSIOF1_TXD_MARK, SCIFA2_TXD2_MARK, + MSIOF1_TSYNC_MARK, SCIFA2_CTS2__MARK, + MSIOF1_TSCK_MARK, SCIFA2_SCK2_MARK, + MSIOF1_RXD_MARK, SCIFA2_RXD2_MARK, + MSIOF1_RSCK_MARK, SCIFA2_RTS2__MARK, VIO2_CLK2_MARK, LCD2D20_MARK, + MSIOF1_RSYNC_MARK, MFG1_IN2_MARK, VIO2_VD2_MARK, LCD2D21_MARK, + MSIOF1_MCK0_MARK, PORT236_I2C_SDA2_MARK, + MSIOF1_MCK1_MARK, PORT237_I2C_SCL2_MARK, + MSIOF1_SS1_MARK, VIO2_FIELD2_MARK, LCD2D22_MARK, + MSIOF1_SS2_MARK, VIO2_HD2_MARK, LCD2D23_MARK, + SCIFA6_TXD_MARK, + PORT241_IRDA_OUT_MARK, PORT241_IROUT_MARK, MFG4_OUT1_MARK, TPU4TO0_MARK, + PORT242_IRDA_IN_MARK, MFG4_IN2_MARK, + PORT243_IRDA_FIRSEL_MARK, PORT243_VIO_CKO2_MARK, + PORT244_SCIFA5_CTS__MARK, MFG2_IN1_MARK, PORT244_SCIFB_CTS__MARK, \ + MSIOF2R_RXD_MARK, + PORT245_SCIFA5_RTS__MARK, MFG2_IN2_MARK, PORT245_SCIFB_RTS__MARK, \ + MSIOF2R_TXD_MARK, + PORT246_SCIFA5_RXD_MARK, MFG1_OUT1_MARK, PORT246_SCIFB_RXD_MARK, \ + TPU1TO0_MARK, + PORT247_SCIFA5_TXD_MARK, MFG3_OUT2_MARK, PORT247_SCIFB_TXD_MARK, \ + TPU3TO1_MARK, + PORT248_SCIFA5_SCK_MARK, MFG2_OUT1_MARK, PORT248_SCIFB_SCK_MARK, \ + TPU2TO0_MARK, PORT248_I2C_SCL3_MARK, MSIOF2R_TSCK_MARK, + PORT249_IROUT_MARK, MFG4_IN1_MARK, PORT249_I2C_SDA3_MARK, \ + MSIOF2R_TSYNC_MARK, + SDHICLK0_MARK, + SDHICD0_MARK, + SDHID0_0_MARK, + SDHID0_1_MARK, + SDHID0_2_MARK, + SDHID0_3_MARK, + SDHICMD0_MARK, + SDHIWP0_MARK, + SDHICLK1_MARK, + SDHID1_0_MARK, TS_SPSYNC2_MARK, + SDHID1_1_MARK, TS_SDAT2_MARK, + SDHID1_2_MARK, TS_SDEN2_MARK, + SDHID1_3_MARK, TS_SCK2_MARK, + SDHICMD1_MARK, + SDHICLK2_MARK, + SDHID2_0_MARK, TS_SPSYNC4_MARK, + SDHID2_1_MARK, TS_SDAT4_MARK, + SDHID2_2_MARK, TS_SDEN4_MARK, + SDHID2_3_MARK, TS_SCK4_MARK, + SDHICMD2_MARK, + MMCCLK0_MARK, + MMCD0_0_MARK, + MMCD0_1_MARK, + MMCD0_2_MARK, + MMCD0_3_MARK, + MMCD0_4_MARK, TS_SPSYNC5_MARK, + MMCD0_5_MARK, TS_SDAT5_MARK, + MMCD0_6_MARK, TS_SDEN5_MARK, + MMCD0_7_MARK, TS_SCK5_MARK, + MMCCMD0_MARK, + RESETOUTS__MARK, EXTAL2OUT_MARK, + MCP_WAIT__MCP_FRB_MARK, + MCP_CKO_MARK, MMCCLK1_MARK, + MCP_D15_MCP_NAF15_MARK, + MCP_D14_MCP_NAF14_MARK, + MCP_D13_MCP_NAF13_MARK, + MCP_D12_MCP_NAF12_MARK, + MCP_D11_MCP_NAF11_MARK, + MCP_D10_MCP_NAF10_MARK, + MCP_D9_MCP_NAF9_MARK, + MCP_D8_MCP_NAF8_MARK, MMCCMD1_MARK, + MCP_D7_MCP_NAF7_MARK, MMCD1_7_MARK, + + MCP_D6_MCP_NAF6_MARK, MMCD1_6_MARK, + MCP_D5_MCP_NAF5_MARK, MMCD1_5_MARK, + MCP_D4_MCP_NAF4_MARK, MMCD1_4_MARK, + MCP_D3_MCP_NAF3_MARK, MMCD1_3_MARK, + MCP_D2_MCP_NAF2_MARK, MMCD1_2_MARK, + MCP_D1_MCP_NAF1_MARK, MMCD1_1_MARK, + MCP_D0_MCP_NAF0_MARK, MMCD1_0_MARK, + MCP_NBRSTOUT__MARK, + MCP_WE0__MCP_FWE_MARK, MCP_RDWR_MCP_FWE_MARK, + + /* MSEL2 special cases */ + TSIF2_TS_XX1_MARK, + TSIF2_TS_XX2_MARK, + TSIF2_TS_XX3_MARK, + TSIF2_TS_XX4_MARK, + TSIF2_TS_XX5_MARK, + TSIF1_TS_XX1_MARK, + TSIF1_TS_XX2_MARK, + TSIF1_TS_XX3_MARK, + TSIF1_TS_XX4_MARK, + TSIF1_TS_XX5_MARK, + TSIF0_TS_XX1_MARK, + TSIF0_TS_XX2_MARK, + TSIF0_TS_XX3_MARK, + TSIF0_TS_XX4_MARK, + TSIF0_TS_XX5_MARK, + MST1_TS_XX1_MARK, + MST1_TS_XX2_MARK, + MST1_TS_XX3_MARK, + MST1_TS_XX4_MARK, + MST1_TS_XX5_MARK, + MST0_TS_XX1_MARK, + MST0_TS_XX2_MARK, + MST0_TS_XX3_MARK, + MST0_TS_XX4_MARK, + MST0_TS_XX5_MARK, + + /* MSEL3 special cases */ + SDHI0_VCCQ_MC0_ON_MARK, + SDHI0_VCCQ_MC0_OFF_MARK, + DEBUG_MON_VIO_MARK, + DEBUG_MON_LCDD_MARK, + LCDC_LCDC0_MARK, + LCDC_LCDC1_MARK, + + /* MSEL4 special cases */ + IRQ9_MEM_INT_MARK, + IRQ9_MCP_INT_MARK, + A11_MARK, + KEYOUT8_MARK, + TPU4TO3_MARK, + RESETA_N_PU_ON_MARK, + RESETA_N_PU_OFF_MARK, + EDBGREQ_PD_MARK, + EDBGREQ_PU_MARK, + + /* Functions with pull-ups */ + KEYIN0_PU_MARK, + KEYIN1_PU_MARK, + KEYIN2_PU_MARK, + KEYIN3_PU_MARK, + KEYIN4_PU_MARK, + KEYIN5_PU_MARK, + KEYIN6_PU_MARK, + KEYIN7_PU_MARK, + SDHICD0_PU_MARK, + SDHID0_0_PU_MARK, + SDHID0_1_PU_MARK, + SDHID0_2_PU_MARK, + SDHID0_3_PU_MARK, + SDHICMD0_PU_MARK, + SDHIWP0_PU_MARK, + SDHID1_0_PU_MARK, + SDHID1_1_PU_MARK, + SDHID1_2_PU_MARK, + SDHID1_3_PU_MARK, + SDHICMD1_PU_MARK, + SDHID2_0_PU_MARK, + SDHID2_1_PU_MARK, + SDHID2_2_PU_MARK, + SDHID2_3_PU_MARK, + SDHICMD2_PU_MARK, + MMCCMD0_PU_MARK, + MMCCMD1_PU_MARK, + MMCD0_0_PU_MARK, + MMCD0_1_PU_MARK, + MMCD0_2_PU_MARK, + MMCD0_3_PU_MARK, + MMCD0_4_PU_MARK, + MMCD0_5_PU_MARK, + MMCD0_6_PU_MARK, + MMCD0_7_PU_MARK, + FSIBISLD_PU_MARK, + FSIACK_PU_MARK, + FSIAILR_PU_MARK, + FSIAIBT_PU_MARK, + FSIAISLD_PU_MARK, + + PINMUX_MARK_END, +}; + +static unsigned short pinmux_data[] = { + /* specify valid pin states for each pin in GPIO mode */ + + /* Table 25-1 (I/O and Pull U/D) */ + PORT_DATA_I_PD(0), + PORT_DATA_I_PU(1), + PORT_DATA_I_PU(2), + PORT_DATA_I_PU(3), + PORT_DATA_I_PU(4), + PORT_DATA_I_PU(5), + PORT_DATA_I_PU(6), + PORT_DATA_I_PU(7), + PORT_DATA_I_PU(8), + PORT_DATA_I_PD(9), + PORT_DATA_I_PD(10), + PORT_DATA_I_PU_PD(11), + PORT_DATA_IO_PU_PD(12), + PORT_DATA_IO_PU_PD(13), + PORT_DATA_IO_PU_PD(14), + PORT_DATA_IO_PU_PD(15), + PORT_DATA_IO_PD(16), + PORT_DATA_IO_PD(17), + PORT_DATA_IO_PU(18), + PORT_DATA_IO_PU(19), + PORT_DATA_O(20), + PORT_DATA_O(21), + PORT_DATA_O(22), + PORT_DATA_O(23), + PORT_DATA_O(24), + PORT_DATA_I_PD(25), + PORT_DATA_I_PD(26), + PORT_DATA_IO_PU(27), + PORT_DATA_IO_PU(28), + PORT_DATA_IO_PD(29), + PORT_DATA_IO_PD(30), + PORT_DATA_IO_PU(31), + PORT_DATA_IO_PD(32), + PORT_DATA_I_PU_PD(33), + PORT_DATA_IO_PD(34), + PORT_DATA_I_PU_PD(35), + PORT_DATA_IO_PD(36), + PORT_DATA_IO(37), + PORT_DATA_O(38), + PORT_DATA_I_PU(39), + PORT_DATA_I_PU_PD(40), + PORT_DATA_O(41), + PORT_DATA_IO_PD(42), + PORT_DATA_IO_PU_PD(43), + PORT_DATA_IO_PU_PD(44), + PORT_DATA_IO_PD(45), + PORT_DATA_IO_PD(46), + PORT_DATA_IO_PD(47), + PORT_DATA_I_PD(48), + PORT_DATA_IO_PU_PD(49), + PORT_DATA_IO_PD(50), + + PORT_DATA_IO_PD(51), + PORT_DATA_O(52), + PORT_DATA_IO_PU_PD(53), + PORT_DATA_IO_PU_PD(54), + PORT_DATA_IO_PD(55), + PORT_DATA_I_PU_PD(56), + PORT_DATA_IO(57), + PORT_DATA_IO(58), + PORT_DATA_IO(59), + PORT_DATA_IO(60), + PORT_DATA_IO(61), + PORT_DATA_IO_PD(62), + PORT_DATA_IO_PD(63), + PORT_DATA_IO_PU_PD(64), + PORT_DATA_IO_PD(65), + PORT_DATA_IO_PU_PD(66), + PORT_DATA_IO_PU_PD(67), + PORT_DATA_IO_PU_PD(68), + PORT_DATA_IO_PU_PD(69), + PORT_DATA_IO_PU_PD(70), + PORT_DATA_IO_PU_PD(71), + PORT_DATA_IO_PU_PD(72), + PORT_DATA_I_PU_PD(73), + PORT_DATA_IO_PU(74), + PORT_DATA_IO_PU(75), + PORT_DATA_IO_PU(76), + PORT_DATA_IO_PU(77), + PORT_DATA_IO_PU(78), + PORT_DATA_IO_PU(79), + PORT_DATA_IO_PU(80), + PORT_DATA_IO_PU(81), + PORT_DATA_IO_PU(82), + PORT_DATA_IO_PU(83), + PORT_DATA_IO_PU(84), + PORT_DATA_IO_PU(85), + PORT_DATA_IO_PU(86), + PORT_DATA_IO_PU(87), + PORT_DATA_IO_PU(88), + PORT_DATA_IO_PU(89), + PORT_DATA_O(90), + PORT_DATA_IO_PU(91), + PORT_DATA_O(92), + PORT_DATA_IO_PU(93), + PORT_DATA_O(94), + PORT_DATA_I_PU_PD(95), + PORT_DATA_IO(96), + PORT_DATA_IO(97), + PORT_DATA_IO(98), + PORT_DATA_I_PU(99), + PORT_DATA_O(100), + PORT_DATA_O(101), + PORT_DATA_I_PU(102), + PORT_DATA_IO_PD(103), + PORT_DATA_I_PU_PD(104), + PORT_DATA_I_PD(105), + PORT_DATA_I_PD(106), + PORT_DATA_I_PU_PD(107), + PORT_DATA_I_PU_PD(108), + PORT_DATA_IO_PD(109), + PORT_DATA_IO_PD(110), + PORT_DATA_IO_PU_PD(111), + PORT_DATA_IO_PU_PD(112), + PORT_DATA_IO_PU_PD(113), + PORT_DATA_IO_PD(114), + PORT_DATA_IO_PU(115), + PORT_DATA_IO_PU(116), + PORT_DATA_IO_PU_PD(117), + PORT_DATA_IO_PU_PD(118), + PORT_DATA_IO_PD(128), + + PORT_DATA_IO_PD(129), + PORT_DATA_IO_PU_PD(130), + PORT_DATA_IO_PD(131), + PORT_DATA_IO_PD(132), + PORT_DATA_IO_PD(133), + PORT_DATA_IO_PU_PD(134), + PORT_DATA_IO_PU_PD(135), + PORT_DATA_IO_PU_PD(136), + PORT_DATA_IO_PU_PD(137), + PORT_DATA_IO_PD(138), + PORT_DATA_IO_PD(139), + PORT_DATA_IO_PD(140), + PORT_DATA_IO_PD(141), + PORT_DATA_IO_PD(142), + PORT_DATA_IO_PD(143), + PORT_DATA_IO_PU_PD(144), + PORT_DATA_IO_PD(145), + PORT_DATA_IO_PU_PD(146), + PORT_DATA_IO_PU_PD(147), + PORT_DATA_IO_PU_PD(148), + PORT_DATA_IO_PU_PD(149), + PORT_DATA_I_PU_PD(150), + PORT_DATA_IO_PU_PD(151), + PORT_DATA_IO_PU_PD(152), + PORT_DATA_IO_PD(153), + PORT_DATA_IO_PD(154), + PORT_DATA_I_PU_PD(155), + PORT_DATA_IO_PU_PD(156), + PORT_DATA_I_PD(157), + PORT_DATA_IO_PD(158), + PORT_DATA_IO_PU_PD(159), + PORT_DATA_IO_PU_PD(160), + PORT_DATA_I_PU_PD(161), + PORT_DATA_I_PU_PD(162), + PORT_DATA_IO_PU_PD(163), + PORT_DATA_I_PU_PD(164), + PORT_DATA_IO_PD(192), + PORT_DATA_IO_PU_PD(193), + PORT_DATA_IO_PD(194), + PORT_DATA_IO_PU_PD(195), + PORT_DATA_IO_PD(196), + PORT_DATA_IO_PD(197), + PORT_DATA_IO_PD(198), + PORT_DATA_IO_PD(199), + PORT_DATA_IO_PU_PD(200), + PORT_DATA_IO_PU_PD(201), + PORT_DATA_IO_PU_PD(202), + PORT_DATA_IO_PU_PD(203), + PORT_DATA_IO_PU_PD(204), + PORT_DATA_IO_PU_PD(205), + PORT_DATA_IO_PU_PD(206), + PORT_DATA_IO_PD(207), + PORT_DATA_IO_PD(208), + PORT_DATA_IO_PD(209), + PORT_DATA_IO_PD(210), + PORT_DATA_IO_PD(211), + PORT_DATA_IO_PD(212), + PORT_DATA_IO_PD(213), + PORT_DATA_IO_PU_PD(214), + PORT_DATA_IO_PU_PD(215), + PORT_DATA_IO_PD(216), + PORT_DATA_IO_PD(217), + PORT_DATA_O(218), + PORT_DATA_IO_PD(219), + PORT_DATA_IO_PD(220), + PORT_DATA_IO_PU_PD(221), + PORT_DATA_IO_PU_PD(222), + PORT_DATA_I_PU_PD(223), + PORT_DATA_I_PU_PD(224), + + PORT_DATA_IO_PU_PD(225), + PORT_DATA_O(226), + PORT_DATA_IO_PU_PD(227), + PORT_DATA_I_PU_PD(228), + PORT_DATA_I_PD(229), + PORT_DATA_IO(230), + PORT_DATA_IO_PU_PD(231), + PORT_DATA_IO_PU_PD(232), + PORT_DATA_I_PU_PD(233), + PORT_DATA_IO_PU_PD(234), + PORT_DATA_IO_PU_PD(235), + PORT_DATA_IO_PU_PD(236), + PORT_DATA_IO_PD(237), + PORT_DATA_IO_PU_PD(238), + PORT_DATA_IO_PU_PD(239), + PORT_DATA_IO_PU_PD(240), + PORT_DATA_O(241), + PORT_DATA_I_PD(242), + PORT_DATA_IO_PU_PD(243), + PORT_DATA_IO_PU_PD(244), + PORT_DATA_IO_PU_PD(245), + PORT_DATA_IO_PU_PD(246), + PORT_DATA_IO_PU_PD(247), + PORT_DATA_IO_PU_PD(248), + PORT_DATA_IO_PU_PD(249), + PORT_DATA_IO_PU_PD(250), + PORT_DATA_IO_PU_PD(251), + PORT_DATA_IO_PU_PD(252), + PORT_DATA_IO_PU_PD(253), + PORT_DATA_IO_PU_PD(254), + PORT_DATA_IO_PU_PD(255), + PORT_DATA_IO_PU_PD(256), + PORT_DATA_IO_PU_PD(257), + PORT_DATA_IO_PU_PD(258), + PORT_DATA_IO_PU_PD(259), + PORT_DATA_IO_PU_PD(260), + PORT_DATA_IO_PU_PD(261), + PORT_DATA_IO_PU_PD(262), + PORT_DATA_IO_PU_PD(263), + PORT_DATA_IO_PU_PD(264), + PORT_DATA_IO_PU_PD(265), + PORT_DATA_IO_PU_PD(266), + PORT_DATA_IO_PU_PD(267), + PORT_DATA_IO_PU_PD(268), + PORT_DATA_IO_PU_PD(269), + PORT_DATA_IO_PU_PD(270), + PORT_DATA_IO_PU_PD(271), + PORT_DATA_IO_PU_PD(272), + PORT_DATA_IO_PU_PD(273), + PORT_DATA_IO_PU_PD(274), + PORT_DATA_IO_PU_PD(275), + PORT_DATA_IO_PU_PD(276), + PORT_DATA_IO_PU_PD(277), + PORT_DATA_IO_PU_PD(278), + PORT_DATA_IO_PU_PD(279), + PORT_DATA_IO_PU_PD(280), + PORT_DATA_O(281), + PORT_DATA_O(282), + PORT_DATA_I_PU(288), + PORT_DATA_IO_PU_PD(289), + PORT_DATA_IO_PU_PD(290), + PORT_DATA_IO_PU_PD(291), + PORT_DATA_IO_PU_PD(292), + PORT_DATA_IO_PU_PD(293), + PORT_DATA_IO_PU_PD(294), + PORT_DATA_IO_PU_PD(295), + PORT_DATA_IO_PU_PD(296), + PORT_DATA_IO_PU_PD(297), + PORT_DATA_IO_PU_PD(298), + + PORT_DATA_IO_PU_PD(299), + PORT_DATA_IO_PU_PD(300), + PORT_DATA_IO_PU_PD(301), + PORT_DATA_IO_PU_PD(302), + PORT_DATA_IO_PU_PD(303), + PORT_DATA_IO_PU_PD(304), + PORT_DATA_IO_PU_PD(305), + PORT_DATA_O(306), + PORT_DATA_O(307), + PORT_DATA_I_PU(308), + PORT_DATA_O(309), + + /* Table 25-1 (Function 0-7) */ + PINMUX_DATA(VBUS_0_MARK, PORT0_FN1), + PINMUX_DATA(GPI0_MARK, PORT1_FN1), + PINMUX_DATA(GPI1_MARK, PORT2_FN1), + PINMUX_DATA(GPI2_MARK, PORT3_FN1), + PINMUX_DATA(GPI3_MARK, PORT4_FN1), + PINMUX_DATA(GPI4_MARK, PORT5_FN1), + PINMUX_DATA(GPI5_MARK, PORT6_FN1), + PINMUX_DATA(GPI6_MARK, PORT7_FN1), + PINMUX_DATA(GPI7_MARK, PORT8_FN1), + PINMUX_DATA(SCIFA7_RXD_MARK, PORT12_FN2), + PINMUX_DATA(SCIFA7_CTS__MARK, PORT13_FN2), + PINMUX_DATA(GPO7_MARK, PORT14_FN1), \ + PINMUX_DATA(MFG0_OUT2_MARK, PORT14_FN4), + PINMUX_DATA(GPO6_MARK, PORT15_FN1), \ + PINMUX_DATA(MFG1_OUT2_MARK, PORT15_FN4), + PINMUX_DATA(GPO5_MARK, PORT16_FN1), \ + PINMUX_DATA(SCIFA0_SCK_MARK, PORT16_FN2), \ + PINMUX_DATA(FSICOSLDT3_MARK, PORT16_FN3), \ + PINMUX_DATA(PORT16_VIO_CKOR_MARK, PORT16_FN4), + PINMUX_DATA(SCIFA0_TXD_MARK, PORT17_FN2), + PINMUX_DATA(SCIFA7_TXD_MARK, PORT18_FN2), + PINMUX_DATA(SCIFA7_RTS__MARK, PORT19_FN2), \ + PINMUX_DATA(PORT19_VIO_CKO2_MARK, PORT19_FN3), + PINMUX_DATA(GPO0_MARK, PORT20_FN1), + PINMUX_DATA(GPO1_MARK, PORT21_FN1), + PINMUX_DATA(GPO2_MARK, PORT22_FN1), \ + PINMUX_DATA(STATUS0_MARK, PORT22_FN2), + PINMUX_DATA(GPO3_MARK, PORT23_FN1), \ + PINMUX_DATA(STATUS1_MARK, PORT23_FN2), + PINMUX_DATA(GPO4_MARK, PORT24_FN1), \ + PINMUX_DATA(STATUS2_MARK, PORT24_FN2), + PINMUX_DATA(VINT_MARK, PORT25_FN1), + PINMUX_DATA(TCKON_MARK, PORT26_FN1), + PINMUX_DATA(XDVFS1_MARK, PORT27_FN1), \ + PINMUX_DATA(PORT27_I2C_SCL2_MARK, PORT27_FN2, MSEL2CR_MSEL17_0, + MSEL2CR_MSEL16_1), \ + PINMUX_DATA(PORT27_I2C_SCL3_MARK, PORT27_FN3, MSEL2CR_MSEL19_0, + MSEL2CR_MSEL18_1), \ + PINMUX_DATA(MFG0_OUT1_MARK, PORT27_FN4), \ + PINMUX_DATA(PORT27_IROUT_MARK, PORT27_FN7), + PINMUX_DATA(XDVFS2_MARK, PORT28_FN1), \ + PINMUX_DATA(PORT28_I2C_SDA2_MARK, PORT28_FN2, MSEL2CR_MSEL17_0, + MSEL2CR_MSEL16_1), \ + PINMUX_DATA(PORT28_I2C_SDA3_MARK, PORT28_FN3, MSEL2CR_MSEL19_0, + MSEL2CR_MSEL18_1), \ + PINMUX_DATA(PORT28_TPU1TO1_MARK, PORT28_FN7), + PINMUX_DATA(SIM_RST_MARK, PORT29_FN1), \ + PINMUX_DATA(PORT29_TPU1TO1_MARK, PORT29_FN4), + PINMUX_DATA(SIM_CLK_MARK, PORT30_FN1), \ + PINMUX_DATA(PORT30_VIO_CKOR_MARK, PORT30_FN4), + PINMUX_DATA(SIM_D_MARK, PORT31_FN1), \ + PINMUX_DATA(PORT31_IROUT_MARK, PORT31_FN4), + PINMUX_DATA(SCIFA4_TXD_MARK, PORT32_FN2), + PINMUX_DATA(SCIFA4_RXD_MARK, PORT33_FN2), \ + PINMUX_DATA(XWUP_MARK, PORT33_FN3), + PINMUX_DATA(SCIFA4_RTS__MARK, PORT34_FN2), + PINMUX_DATA(SCIFA4_CTS__MARK, PORT35_FN2), + PINMUX_DATA(FSIBOBT_MARK, PORT36_FN1), \ + PINMUX_DATA(FSIBIBT_MARK, PORT36_FN2), + PINMUX_DATA(FSIBOLR_MARK, PORT37_FN1), \ + PINMUX_DATA(FSIBILR_MARK, PORT37_FN2), + PINMUX_DATA(FSIBOSLD_MARK, PORT38_FN1), + PINMUX_DATA(FSIBISLD_MARK, PORT39_FN1), + PINMUX_DATA(VACK_MARK, PORT40_FN1), + PINMUX_DATA(XTAL1L_MARK, PORT41_FN1), + PINMUX_DATA(SCIFA0_RTS__MARK, PORT42_FN2), \ + PINMUX_DATA(FSICOSLDT2_MARK, PORT42_FN3), + PINMUX_DATA(SCIFA0_RXD_MARK, PORT43_FN2), + PINMUX_DATA(SCIFA0_CTS__MARK, PORT44_FN2), \ + PINMUX_DATA(FSICOSLDT1_MARK, PORT44_FN3), + PINMUX_DATA(FSICOBT_MARK, PORT45_FN1), \ + PINMUX_DATA(FSICIBT_MARK, PORT45_FN2), \ + PINMUX_DATA(FSIDOBT_MARK, PORT45_FN3), \ + PINMUX_DATA(FSIDIBT_MARK, PORT45_FN4), + PINMUX_DATA(FSICOLR_MARK, PORT46_FN1), \ + PINMUX_DATA(FSICILR_MARK, PORT46_FN2), \ + PINMUX_DATA(FSIDOLR_MARK, PORT46_FN3), \ + PINMUX_DATA(FSIDILR_MARK, PORT46_FN4), + PINMUX_DATA(FSICOSLD_MARK, PORT47_FN1), \ + PINMUX_DATA(PORT47_FSICSPDIF_MARK, PORT47_FN2), + PINMUX_DATA(FSICISLD_MARK, PORT48_FN1), \ + PINMUX_DATA(FSIDISLD_MARK, PORT48_FN3), + PINMUX_DATA(FSIACK_MARK, PORT49_FN1), \ + PINMUX_DATA(PORT49_IRDA_OUT_MARK, PORT49_FN2, MSEL4CR_MSEL19_1), \ + PINMUX_DATA(PORT49_IROUT_MARK, PORT49_FN4), \ + PINMUX_DATA(FSIAOMC_MARK, PORT49_FN5), + PINMUX_DATA(FSIAOLR_MARK, PORT50_FN1), \ + PINMUX_DATA(BBIF2_TSYNC2_MARK, PORT50_FN2), \ + PINMUX_DATA(TPU2TO2_MARK, PORT50_FN3), \ + PINMUX_DATA(FSIAILR_MARK, PORT50_FN5), + + PINMUX_DATA(FSIAOBT_MARK, PORT51_FN1), \ + PINMUX_DATA(BBIF2_TSCK2_MARK, PORT51_FN2), \ + PINMUX_DATA(TPU2TO3_MARK, PORT51_FN3), \ + PINMUX_DATA(FSIAIBT_MARK, PORT51_FN5), + PINMUX_DATA(FSIAOSLD_MARK, PORT52_FN1), \ + PINMUX_DATA(BBIF2_TXD2_MARK, PORT52_FN2), + PINMUX_DATA(FSIASPDIF_MARK, PORT53_FN1), \ + PINMUX_DATA(PORT53_IRDA_IN_MARK, PORT53_FN2, MSEL4CR_MSEL19_1), \ + PINMUX_DATA(TPU3TO3_MARK, PORT53_FN3), \ + PINMUX_DATA(FSIBSPDIF_MARK, PORT53_FN5), \ + PINMUX_DATA(PORT53_FSICSPDIF_MARK, PORT53_FN6), + PINMUX_DATA(FSIBCK_MARK, PORT54_FN1), \ + PINMUX_DATA(PORT54_IRDA_FIRSEL_MARK, PORT54_FN2, MSEL4CR_MSEL19_1), \ + PINMUX_DATA(TPU3TO2_MARK, PORT54_FN3), \ + PINMUX_DATA(FSIBOMC_MARK, PORT54_FN5), \ + PINMUX_DATA(FSICCK_MARK, PORT54_FN6), \ + PINMUX_DATA(FSICOMC_MARK, PORT54_FN7), + PINMUX_DATA(FSIAISLD_MARK, PORT55_FN1), \ + PINMUX_DATA(TPU0TO0_MARK, PORT55_FN3), + PINMUX_DATA(A0_MARK, PORT57_FN1), \ + PINMUX_DATA(BS__MARK, PORT57_FN2), + PINMUX_DATA(A12_MARK, PORT58_FN1), \ + PINMUX_DATA(PORT58_KEYOUT7_MARK, PORT58_FN2), \ + PINMUX_DATA(TPU4TO2_MARK, PORT58_FN4), + PINMUX_DATA(A13_MARK, PORT59_FN1), \ + PINMUX_DATA(PORT59_KEYOUT6_MARK, PORT59_FN2), \ + PINMUX_DATA(TPU0TO1_MARK, PORT59_FN4), + PINMUX_DATA(A14_MARK, PORT60_FN1), \ + PINMUX_DATA(KEYOUT5_MARK, PORT60_FN2), + PINMUX_DATA(A15_MARK, PORT61_FN1), \ + PINMUX_DATA(KEYOUT4_MARK, PORT61_FN2), + PINMUX_DATA(A16_MARK, PORT62_FN1), \ + PINMUX_DATA(KEYOUT3_MARK, PORT62_FN2), \ + PINMUX_DATA(MSIOF0_SS1_MARK, PORT62_FN4, MSEL3CR_MSEL11_0), + PINMUX_DATA(A17_MARK, PORT63_FN1), \ + PINMUX_DATA(KEYOUT2_MARK, PORT63_FN2), \ + PINMUX_DATA(MSIOF0_TSYNC_MARK, PORT63_FN4, MSEL3CR_MSEL11_0), + PINMUX_DATA(A18_MARK, PORT64_FN1), \ + PINMUX_DATA(KEYOUT1_MARK, PORT64_FN2), \ + PINMUX_DATA(MSIOF0_TSCK_MARK, PORT64_FN4, MSEL3CR_MSEL11_0), + PINMUX_DATA(A19_MARK, PORT65_FN1), \ + PINMUX_DATA(KEYOUT0_MARK, PORT65_FN2), \ + PINMUX_DATA(MSIOF0_TXD_MARK, PORT65_FN4, MSEL3CR_MSEL11_0), + PINMUX_DATA(A20_MARK, PORT66_FN1), \ + PINMUX_DATA(KEYIN0_MARK, PORT66_FN2), \ + PINMUX_DATA(MSIOF0_RSCK_MARK, PORT66_FN4, MSEL3CR_MSEL11_0), + PINMUX_DATA(A21_MARK, PORT67_FN1), \ + PINMUX_DATA(KEYIN1_MARK, PORT67_FN2), \ + PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT67_FN4, MSEL3CR_MSEL11_0), + PINMUX_DATA(A22_MARK, PORT68_FN1), \ + PINMUX_DATA(KEYIN2_MARK, PORT68_FN2), \ + PINMUX_DATA(MSIOF0_MCK0_MARK, PORT68_FN4, MSEL3CR_MSEL11_0), + PINMUX_DATA(A23_MARK, PORT69_FN1), \ + PINMUX_DATA(KEYIN3_MARK, PORT69_FN2), \ + PINMUX_DATA(MSIOF0_MCK1_MARK, PORT69_FN4, MSEL3CR_MSEL11_0), + PINMUX_DATA(A24_MARK, PORT70_FN1), \ + PINMUX_DATA(KEYIN4_MARK, PORT70_FN2), \ + PINMUX_DATA(MSIOF0_RXD_MARK, PORT70_FN4, MSEL3CR_MSEL11_0), + PINMUX_DATA(A25_MARK, PORT71_FN1), \ + PINMUX_DATA(KEYIN5_MARK, PORT71_FN2), \ + PINMUX_DATA(MSIOF0_SS2_MARK, PORT71_FN4, MSEL3CR_MSEL11_0), + PINMUX_DATA(A26_MARK, PORT72_FN1), \ + PINMUX_DATA(KEYIN6_MARK, PORT72_FN2), + PINMUX_DATA(KEYIN7_MARK, PORT73_FN2), + PINMUX_DATA(D0_NAF0_MARK, PORT74_FN1), + PINMUX_DATA(D1_NAF1_MARK, PORT75_FN1), + PINMUX_DATA(D2_NAF2_MARK, PORT76_FN1), + PINMUX_DATA(D3_NAF3_MARK, PORT77_FN1), + PINMUX_DATA(D4_NAF4_MARK, PORT78_FN1), + PINMUX_DATA(D5_NAF5_MARK, PORT79_FN1), + PINMUX_DATA(D6_NAF6_MARK, PORT80_FN1), + PINMUX_DATA(D7_NAF7_MARK, PORT81_FN1), + PINMUX_DATA(D8_NAF8_MARK, PORT82_FN1), + PINMUX_DATA(D9_NAF9_MARK, PORT83_FN1), + PINMUX_DATA(D10_NAF10_MARK, PORT84_FN1), + PINMUX_DATA(D11_NAF11_MARK, PORT85_FN1), + PINMUX_DATA(D12_NAF12_MARK, PORT86_FN1), + PINMUX_DATA(D13_NAF13_MARK, PORT87_FN1), + PINMUX_DATA(D14_NAF14_MARK, PORT88_FN1), + PINMUX_DATA(D15_NAF15_MARK, PORT89_FN1), + PINMUX_DATA(CS4__MARK, PORT90_FN1), + PINMUX_DATA(CS5A__MARK, PORT91_FN1), \ + PINMUX_DATA(PORT91_RDWR_MARK, PORT91_FN2), + PINMUX_DATA(CS5B__MARK, PORT92_FN1), \ + PINMUX_DATA(FCE1__MARK, PORT92_FN2), + PINMUX_DATA(CS6B__MARK, PORT93_FN1), \ + PINMUX_DATA(DACK0_MARK, PORT93_FN4), + PINMUX_DATA(FCE0__MARK, PORT94_FN1), \ + PINMUX_DATA(CS6A__MARK, PORT94_FN2), + PINMUX_DATA(WAIT__MARK, PORT95_FN1), \ + PINMUX_DATA(DREQ0_MARK, PORT95_FN2), + PINMUX_DATA(RD__FSC_MARK, PORT96_FN1), + PINMUX_DATA(WE0__FWE_MARK, PORT97_FN1), \ + PINMUX_DATA(RDWR_FWE_MARK, PORT97_FN2), + PINMUX_DATA(WE1__MARK, PORT98_FN1), + PINMUX_DATA(FRB_MARK, PORT99_FN1), + PINMUX_DATA(CKO_MARK, PORT100_FN1), + PINMUX_DATA(NBRSTOUT__MARK, PORT101_FN1), + PINMUX_DATA(NBRST__MARK, PORT102_FN1), + PINMUX_DATA(BBIF2_TXD_MARK, PORT103_FN3), + PINMUX_DATA(BBIF2_RXD_MARK, PORT104_FN3), + PINMUX_DATA(BBIF2_SYNC_MARK, PORT105_FN3), + PINMUX_DATA(BBIF2_SCK_MARK, PORT106_FN3), + PINMUX_DATA(SCIFA3_CTS__MARK, PORT107_FN3), \ + PINMUX_DATA(MFG3_IN2_MARK, PORT107_FN4), + PINMUX_DATA(SCIFA3_RXD_MARK, PORT108_FN3), \ + PINMUX_DATA(MFG3_IN1_MARK, PORT108_FN4), + PINMUX_DATA(BBIF1_SS2_MARK, PORT109_FN2), \ + PINMUX_DATA(SCIFA3_RTS__MARK, PORT109_FN3), \ + PINMUX_DATA(MFG3_OUT1_MARK, PORT109_FN4), + PINMUX_DATA(SCIFA3_TXD_MARK, PORT110_FN3), + PINMUX_DATA(HSI_RX_DATA_MARK, PORT111_FN1), \ + PINMUX_DATA(BBIF1_RXD_MARK, PORT111_FN3), + PINMUX_DATA(HSI_TX_WAKE_MARK, PORT112_FN1), \ + PINMUX_DATA(BBIF1_TSCK_MARK, PORT112_FN3), + PINMUX_DATA(HSI_TX_DATA_MARK, PORT113_FN1), \ + PINMUX_DATA(BBIF1_TSYNC_MARK, PORT113_FN3), + PINMUX_DATA(HSI_TX_READY_MARK, PORT114_FN1), \ + PINMUX_DATA(BBIF1_TXD_MARK, PORT114_FN3), + PINMUX_DATA(HSI_RX_READY_MARK, PORT115_FN1), \ + PINMUX_DATA(BBIF1_RSCK_MARK, PORT115_FN3), \ + PINMUX_DATA(PORT115_I2C_SCL2_MARK, PORT115_FN5, MSEL2CR_MSEL17_1), \ + PINMUX_DATA(PORT115_I2C_SCL3_MARK, PORT115_FN6, MSEL2CR_MSEL19_1), + PINMUX_DATA(HSI_RX_WAKE_MARK, PORT116_FN1), \ + PINMUX_DATA(BBIF1_RSYNC_MARK, PORT116_FN3), \ + PINMUX_DATA(PORT116_I2C_SDA2_MARK, PORT116_FN5, MSEL2CR_MSEL17_1), \ + PINMUX_DATA(PORT116_I2C_SDA3_MARK, PORT116_FN6, MSEL2CR_MSEL19_1), + PINMUX_DATA(HSI_RX_FLAG_MARK, PORT117_FN1), \ + PINMUX_DATA(BBIF1_SS1_MARK, PORT117_FN2), \ + PINMUX_DATA(BBIF1_FLOW_MARK, PORT117_FN3), + PINMUX_DATA(HSI_TX_FLAG_MARK, PORT118_FN1), + PINMUX_DATA(VIO_VD_MARK, PORT128_FN1), \ + PINMUX_DATA(PORT128_LCD2VSYN_MARK, PORT128_FN4, MSEL3CR_MSEL2_0), \ + PINMUX_DATA(VIO2_VD_MARK, PORT128_FN6, MSEL4CR_MSEL27_0), \ + PINMUX_DATA(LCD2D0_MARK, PORT128_FN7), + + PINMUX_DATA(VIO_HD_MARK, PORT129_FN1), \ + PINMUX_DATA(PORT129_LCD2HSYN_MARK, PORT129_FN4), \ + PINMUX_DATA(PORT129_LCD2CS__MARK, PORT129_FN5), \ + PINMUX_DATA(VIO2_HD_MARK, PORT129_FN6, MSEL4CR_MSEL27_0), \ + PINMUX_DATA(LCD2D1_MARK, PORT129_FN7), + PINMUX_DATA(VIO_D0_MARK, PORT130_FN1), \ + PINMUX_DATA(PORT130_MSIOF2_RXD_MARK, PORT130_FN3, MSEL4CR_MSEL11_0, + MSEL4CR_MSEL10_1), \ + PINMUX_DATA(LCD2D10_MARK, PORT130_FN7), + PINMUX_DATA(VIO_D1_MARK, PORT131_FN1), \ + PINMUX_DATA(PORT131_KEYOUT6_MARK, PORT131_FN2), \ + PINMUX_DATA(PORT131_MSIOF2_SS1_MARK, PORT131_FN3), \ + PINMUX_DATA(PORT131_KEYOUT11_MARK, PORT131_FN4), \ + PINMUX_DATA(LCD2D11_MARK, PORT131_FN7), + PINMUX_DATA(VIO_D2_MARK, PORT132_FN1), \ + PINMUX_DATA(PORT132_KEYOUT7_MARK, PORT132_FN2), \ + PINMUX_DATA(PORT132_MSIOF2_SS2_MARK, PORT132_FN3), \ + PINMUX_DATA(PORT132_KEYOUT10_MARK, PORT132_FN4), \ + PINMUX_DATA(LCD2D12_MARK, PORT132_FN7), + PINMUX_DATA(VIO_D3_MARK, PORT133_FN1), \ + PINMUX_DATA(MSIOF2_TSYNC_MARK, PORT133_FN3, MSEL4CR_MSEL11_0), \ + PINMUX_DATA(LCD2D13_MARK, PORT133_FN7), + PINMUX_DATA(VIO_D4_MARK, PORT134_FN1), \ + PINMUX_DATA(MSIOF2_TXD_MARK, PORT134_FN3, MSEL4CR_MSEL11_0), \ + PINMUX_DATA(LCD2D14_MARK, PORT134_FN7), + PINMUX_DATA(VIO_D5_MARK, PORT135_FN1), \ + PINMUX_DATA(MSIOF2_TSCK_MARK, PORT135_FN3, MSEL4CR_MSEL11_0), \ + PINMUX_DATA(LCD2D15_MARK, PORT135_FN7), + PINMUX_DATA(VIO_D6_MARK, PORT136_FN1), \ + PINMUX_DATA(PORT136_KEYOUT8_MARK, PORT136_FN2), \ + PINMUX_DATA(LCD2D16_MARK, PORT136_FN7), + PINMUX_DATA(VIO_D7_MARK, PORT137_FN1), \ + PINMUX_DATA(PORT137_KEYOUT9_MARK, PORT137_FN2), \ + PINMUX_DATA(LCD2D17_MARK, PORT137_FN7), + PINMUX_DATA(VIO_D8_MARK, PORT138_FN1), \ + PINMUX_DATA(PORT138_KEYOUT8_MARK, PORT138_FN2), \ + PINMUX_DATA(VIO2_D0_MARK, PORT138_FN6), \ + PINMUX_DATA(LCD2D6_MARK, PORT138_FN7), + PINMUX_DATA(VIO_D9_MARK, PORT139_FN1), \ + PINMUX_DATA(PORT139_KEYOUT9_MARK, PORT139_FN2), \ + PINMUX_DATA(VIO2_D1_MARK, PORT139_FN6), \ + PINMUX_DATA(LCD2D7_MARK, PORT139_FN7), + PINMUX_DATA(VIO_D10_MARK, PORT140_FN1), \ + PINMUX_DATA(TPU0TO2_MARK, PORT140_FN4), \ + PINMUX_DATA(VIO2_D2_MARK, PORT140_FN6), \ + PINMUX_DATA(LCD2D8_MARK, PORT140_FN7), + PINMUX_DATA(VIO_D11_MARK, PORT141_FN1), \ + PINMUX_DATA(TPU0TO3_MARK, PORT141_FN4), \ + PINMUX_DATA(VIO2_D3_MARK, PORT141_FN6), \ + PINMUX_DATA(LCD2D9_MARK, PORT141_FN7), + PINMUX_DATA(VIO_D12_MARK, PORT142_FN1), \ + PINMUX_DATA(PORT142_KEYOUT10_MARK, PORT142_FN2), \ + PINMUX_DATA(VIO2_D4_MARK, PORT142_FN6), \ + PINMUX_DATA(LCD2D2_MARK, PORT142_FN7), + PINMUX_DATA(VIO_D13_MARK, PORT143_FN1), \ + PINMUX_DATA(PORT143_KEYOUT11_MARK, PORT143_FN2), \ + PINMUX_DATA(PORT143_KEYOUT6_MARK, PORT143_FN3), \ + PINMUX_DATA(VIO2_D5_MARK, PORT143_FN6), \ + PINMUX_DATA(LCD2D3_MARK, PORT143_FN7), + PINMUX_DATA(VIO_D14_MARK, PORT144_FN1), \ + PINMUX_DATA(PORT144_KEYOUT7_MARK, PORT144_FN2), \ + PINMUX_DATA(VIO2_D6_MARK, PORT144_FN6), \ + PINMUX_DATA(LCD2D4_MARK, PORT144_FN7), + PINMUX_DATA(VIO_D15_MARK, PORT145_FN1), \ + PINMUX_DATA(TPU1TO3_MARK, PORT145_FN3), \ + PINMUX_DATA(PORT145_LCD2DISP_MARK, PORT145_FN4), \ + PINMUX_DATA(PORT145_LCD2RS_MARK, PORT145_FN5), \ + PINMUX_DATA(VIO2_D7_MARK, PORT145_FN6), \ + PINMUX_DATA(LCD2D5_MARK, PORT145_FN7), + PINMUX_DATA(VIO_CLK_MARK, PORT146_FN1), \ + PINMUX_DATA(LCD2DCK_MARK, PORT146_FN4), \ + PINMUX_DATA(PORT146_LCD2WR__MARK, PORT146_FN5), \ + PINMUX_DATA(VIO2_CLK_MARK, PORT146_FN6, MSEL4CR_MSEL27_0), \ + PINMUX_DATA(LCD2D18_MARK, PORT146_FN7), + PINMUX_DATA(VIO_FIELD_MARK, PORT147_FN1), \ + PINMUX_DATA(LCD2RD__MARK, PORT147_FN4), \ + PINMUX_DATA(VIO2_FIELD_MARK, PORT147_FN6, MSEL4CR_MSEL27_0), \ + PINMUX_DATA(LCD2D19_MARK, PORT147_FN7), + PINMUX_DATA(VIO_CKO_MARK, PORT148_FN1), + PINMUX_DATA(A27_MARK, PORT149_FN1), \ + PINMUX_DATA(PORT149_RDWR_MARK, PORT149_FN2), \ + PINMUX_DATA(MFG0_IN1_MARK, PORT149_FN3), \ + PINMUX_DATA(PORT149_KEYOUT9_MARK, PORT149_FN4), + PINMUX_DATA(MFG0_IN2_MARK, PORT150_FN3), + PINMUX_DATA(TS_SPSYNC3_MARK, PORT151_FN4), \ + PINMUX_DATA(MSIOF2_RSCK_MARK, PORT151_FN5), + PINMUX_DATA(TS_SDAT3_MARK, PORT152_FN4), \ + PINMUX_DATA(MSIOF2_RSYNC_MARK, PORT152_FN5), + PINMUX_DATA(TPU1TO2_MARK, PORT153_FN3), \ + PINMUX_DATA(TS_SDEN3_MARK, PORT153_FN4), \ + PINMUX_DATA(PORT153_MSIOF2_SS1_MARK, PORT153_FN5), + PINMUX_DATA(SCIFA2_TXD1_MARK, PORT154_FN2, MSEL3CR_MSEL9_0), \ + PINMUX_DATA(MSIOF2_MCK0_MARK, PORT154_FN5), + PINMUX_DATA(SCIFA2_RXD1_MARK, PORT155_FN2, MSEL3CR_MSEL9_0), \ + PINMUX_DATA(MSIOF2_MCK1_MARK, PORT155_FN5), + PINMUX_DATA(SCIFA2_RTS1__MARK, PORT156_FN2, MSEL3CR_MSEL9_0), \ + PINMUX_DATA(PORT156_MSIOF2_SS2_MARK, PORT156_FN5), + PINMUX_DATA(SCIFA2_CTS1__MARK, PORT157_FN2, MSEL3CR_MSEL9_0), \ + PINMUX_DATA(PORT157_MSIOF2_RXD_MARK, PORT157_FN5, MSEL4CR_MSEL11_0, + MSEL4CR_MSEL10_0), + PINMUX_DATA(DINT__MARK, PORT158_FN1), \ + PINMUX_DATA(SCIFA2_SCK1_MARK, PORT158_FN2, MSEL3CR_MSEL9_0), \ + PINMUX_DATA(TS_SCK3_MARK, PORT158_FN4), + PINMUX_DATA(PORT159_SCIFB_SCK_MARK, PORT159_FN1, MSEL4CR_MSEL22_0), \ + PINMUX_DATA(PORT159_SCIFA5_SCK_MARK, PORT159_FN2, MSEL4CR_MSEL21_1), \ + PINMUX_DATA(NMI_MARK, PORT159_FN3), + PINMUX_DATA(PORT160_SCIFB_TXD_MARK, PORT160_FN1, MSEL4CR_MSEL22_0), \ + PINMUX_DATA(PORT160_SCIFA5_TXD_MARK, PORT160_FN2, MSEL4CR_MSEL21_1), + PINMUX_DATA(PORT161_SCIFB_CTS__MARK, PORT161_FN1, MSEL4CR_MSEL22_0), \ + PINMUX_DATA(PORT161_SCIFA5_CTS__MARK, PORT161_FN2, MSEL4CR_MSEL21_1), + PINMUX_DATA(PORT162_SCIFB_RXD_MARK, PORT162_FN1, MSEL4CR_MSEL22_0), \ + PINMUX_DATA(PORT162_SCIFA5_RXD_MARK, PORT162_FN2, MSEL4CR_MSEL21_1), + PINMUX_DATA(PORT163_SCIFB_RTS__MARK, PORT163_FN1, MSEL4CR_MSEL22_0), \ + PINMUX_DATA(PORT163_SCIFA5_RTS__MARK, PORT163_FN2, MSEL4CR_MSEL21_1), \ + PINMUX_DATA(TPU3TO0_MARK, PORT163_FN5), + PINMUX_DATA(LCDD0_MARK, PORT192_FN1), + PINMUX_DATA(LCDD1_MARK, PORT193_FN1), \ + PINMUX_DATA(PORT193_SCIFA5_CTS__MARK, PORT193_FN3, MSEL4CR_MSEL21_0, + MSEL4CR_MSEL20_1), \ + PINMUX_DATA(BBIF2_TSYNC1_MARK, PORT193_FN5), + PINMUX_DATA(LCDD2_MARK, PORT194_FN1), \ + PINMUX_DATA(PORT194_SCIFA5_RTS__MARK, PORT194_FN3, MSEL4CR_MSEL21_0, + MSEL4CR_MSEL20_1), \ + PINMUX_DATA(BBIF2_TSCK1_MARK, PORT194_FN5), + PINMUX_DATA(LCDD3_MARK, PORT195_FN1), \ + PINMUX_DATA(PORT195_SCIFA5_RXD_MARK, PORT195_FN3, MSEL4CR_MSEL21_0, + MSEL4CR_MSEL20_1), \ + PINMUX_DATA(BBIF2_TXD1_MARK, PORT195_FN5), + PINMUX_DATA(LCDD4_MARK, PORT196_FN1), \ + PINMUX_DATA(PORT196_SCIFA5_TXD_MARK, PORT196_FN3, MSEL4CR_MSEL21_0, + MSEL4CR_MSEL20_1), + PINMUX_DATA(LCDD5_MARK, PORT197_FN1), \ + PINMUX_DATA(PORT197_SCIFA5_SCK_MARK, PORT197_FN3, MSEL4CR_MSEL21_0, + MSEL4CR_MSEL20_1), \ + PINMUX_DATA(MFG2_OUT2_MARK, PORT197_FN5), \ + PINMUX_DATA(TPU2TO1_MARK, PORT197_FN7), + PINMUX_DATA(LCDD6_MARK, PORT198_FN1), + PINMUX_DATA(LCDD7_MARK, PORT199_FN1), \ + PINMUX_DATA(TPU4TO1_MARK, PORT199_FN2), \ + PINMUX_DATA(MFG4_OUT2_MARK, PORT199_FN5), + PINMUX_DATA(LCDD8_MARK, PORT200_FN1), \ + PINMUX_DATA(D16_MARK, PORT200_FN6), + PINMUX_DATA(LCDD9_MARK, PORT201_FN1), \ + PINMUX_DATA(D17_MARK, PORT201_FN6), + PINMUX_DATA(LCDD10_MARK, PORT202_FN1), \ + PINMUX_DATA(D18_MARK, PORT202_FN6), + PINMUX_DATA(LCDD11_MARK, PORT203_FN1), \ + PINMUX_DATA(D19_MARK, PORT203_FN6), + PINMUX_DATA(LCDD12_MARK, PORT204_FN1), \ + PINMUX_DATA(D20_MARK, PORT204_FN6), + PINMUX_DATA(LCDD13_MARK, PORT205_FN1), \ + PINMUX_DATA(D21_MARK, PORT205_FN6), + PINMUX_DATA(LCDD14_MARK, PORT206_FN1), \ + PINMUX_DATA(D22_MARK, PORT206_FN6), + PINMUX_DATA(LCDD15_MARK, PORT207_FN1), \ + PINMUX_DATA(PORT207_MSIOF0L_SS1_MARK, PORT207_FN2, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(D23_MARK, PORT207_FN6), + PINMUX_DATA(LCDD16_MARK, PORT208_FN1), \ + PINMUX_DATA(PORT208_MSIOF0L_SS2_MARK, PORT208_FN2, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(D24_MARK, PORT208_FN6), + PINMUX_DATA(LCDD17_MARK, PORT209_FN1), \ + PINMUX_DATA(D25_MARK, PORT209_FN6), + PINMUX_DATA(LCDD18_MARK, PORT210_FN1), \ + PINMUX_DATA(DREQ2_MARK, PORT210_FN2), \ + PINMUX_DATA(PORT210_MSIOF0L_SS1_MARK, PORT210_FN5, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(D26_MARK, PORT210_FN6), + PINMUX_DATA(LCDD19_MARK, PORT211_FN1), \ + PINMUX_DATA(PORT211_MSIOF0L_SS2_MARK, PORT211_FN5, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(D27_MARK, PORT211_FN6), + PINMUX_DATA(LCDD20_MARK, PORT212_FN1), \ + PINMUX_DATA(TS_SPSYNC1_MARK, PORT212_FN2), \ + PINMUX_DATA(MSIOF0L_MCK0_MARK, PORT212_FN5, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(D28_MARK, PORT212_FN6), + PINMUX_DATA(LCDD21_MARK, PORT213_FN1), \ + PINMUX_DATA(TS_SDAT1_MARK, PORT213_FN2), \ + PINMUX_DATA(MSIOF0L_MCK1_MARK, PORT213_FN5, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(D29_MARK, PORT213_FN6), + PINMUX_DATA(LCDD22_MARK, PORT214_FN1), \ + PINMUX_DATA(TS_SDEN1_MARK, PORT214_FN2), \ + PINMUX_DATA(MSIOF0L_RSCK_MARK, PORT214_FN5, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(D30_MARK, PORT214_FN6), + PINMUX_DATA(LCDD23_MARK, PORT215_FN1), \ + PINMUX_DATA(TS_SCK1_MARK, PORT215_FN2), \ + PINMUX_DATA(MSIOF0L_RSYNC_MARK, PORT215_FN5, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(D31_MARK, PORT215_FN6), + PINMUX_DATA(LCDDCK_MARK, PORT216_FN1), \ + PINMUX_DATA(LCDWR__MARK, PORT216_FN2), + PINMUX_DATA(LCDRD__MARK, PORT217_FN1), \ + PINMUX_DATA(DACK2_MARK, PORT217_FN2), \ + PINMUX_DATA(PORT217_LCD2RS_MARK, PORT217_FN3), \ + PINMUX_DATA(MSIOF0L_TSYNC_MARK, PORT217_FN5, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(VIO2_FIELD3_MARK, PORT217_FN6, MSEL4CR_MSEL27_1, + MSEL4CR_MSEL26_1), \ + PINMUX_DATA(PORT217_LCD2DISP_MARK, PORT217_FN7), + PINMUX_DATA(LCDHSYN_MARK, PORT218_FN1), \ + PINMUX_DATA(LCDCS__MARK, PORT218_FN2), \ + PINMUX_DATA(LCDCS2__MARK, PORT218_FN3), \ + PINMUX_DATA(DACK3_MARK, PORT218_FN4), \ + PINMUX_DATA(PORT218_VIO_CKOR_MARK, PORT218_FN5), + PINMUX_DATA(LCDDISP_MARK, PORT219_FN1), \ + PINMUX_DATA(LCDRS_MARK, PORT219_FN2), \ + PINMUX_DATA(PORT219_LCD2WR__MARK, PORT219_FN3), \ + PINMUX_DATA(DREQ3_MARK, PORT219_FN4), \ + PINMUX_DATA(MSIOF0L_TSCK_MARK, PORT219_FN5, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(VIO2_CLK3_MARK, PORT219_FN6, MSEL4CR_MSEL27_1, + MSEL4CR_MSEL26_1), \ + PINMUX_DATA(LCD2DCK_2_MARK, PORT219_FN7), + PINMUX_DATA(LCDVSYN_MARK, PORT220_FN1), \ + PINMUX_DATA(LCDVSYN2_MARK, PORT220_FN2), + PINMUX_DATA(LCDLCLK_MARK, PORT221_FN1), \ + PINMUX_DATA(DREQ1_MARK, PORT221_FN2), \ + PINMUX_DATA(PORT221_LCD2CS__MARK, PORT221_FN3), \ + PINMUX_DATA(PWEN_MARK, PORT221_FN4), \ + PINMUX_DATA(MSIOF0L_RXD_MARK, PORT221_FN5, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(VIO2_HD3_MARK, PORT221_FN6, MSEL4CR_MSEL27_1, + MSEL4CR_MSEL26_1), \ + PINMUX_DATA(PORT221_LCD2HSYN_MARK, PORT221_FN7), + PINMUX_DATA(LCDDON_MARK, PORT222_FN1), \ + PINMUX_DATA(LCDDON2_MARK, PORT222_FN2), \ + PINMUX_DATA(DACK1_MARK, PORT222_FN3), \ + PINMUX_DATA(OVCN_MARK, PORT222_FN4), \ + PINMUX_DATA(MSIOF0L_TXD_MARK, PORT222_FN5, MSEL3CR_MSEL11_1), \ + PINMUX_DATA(VIO2_VD3_MARK, PORT222_FN6, MSEL4CR_MSEL27_1, + MSEL4CR_MSEL26_1), \ + PINMUX_DATA(PORT222_LCD2VSYN_MARK, PORT222_FN7, MSEL3CR_MSEL2_1), + + PINMUX_DATA(SCIFA1_TXD_MARK, PORT225_FN2), \ + PINMUX_DATA(OVCN2_MARK, PORT225_FN4), + PINMUX_DATA(EXTLP_MARK, PORT226_FN1), \ + PINMUX_DATA(SCIFA1_SCK_MARK, PORT226_FN2), \ + PINMUX_DATA(PORT226_VIO_CKO2_MARK, PORT226_FN5), + PINMUX_DATA(SCIFA1_RTS__MARK, PORT227_FN2), \ + PINMUX_DATA(IDIN_MARK, PORT227_FN4), + PINMUX_DATA(SCIFA1_RXD_MARK, PORT228_FN2), + PINMUX_DATA(SCIFA1_CTS__MARK, PORT229_FN2), \ + PINMUX_DATA(MFG1_IN1_MARK, PORT229_FN3), + PINMUX_DATA(MSIOF1_TXD_MARK, PORT230_FN1), \ + PINMUX_DATA(SCIFA2_TXD2_MARK, PORT230_FN2, MSEL3CR_MSEL9_1), + PINMUX_DATA(MSIOF1_TSYNC_MARK, PORT231_FN1), \ + PINMUX_DATA(SCIFA2_CTS2__MARK, PORT231_FN2, MSEL3CR_MSEL9_1), + PINMUX_DATA(MSIOF1_TSCK_MARK, PORT232_FN1), \ + PINMUX_DATA(SCIFA2_SCK2_MARK, PORT232_FN2, MSEL3CR_MSEL9_1), + PINMUX_DATA(MSIOF1_RXD_MARK, PORT233_FN1), \ + PINMUX_DATA(SCIFA2_RXD2_MARK, PORT233_FN2, MSEL3CR_MSEL9_1), + PINMUX_DATA(MSIOF1_RSCK_MARK, PORT234_FN1), \ + PINMUX_DATA(SCIFA2_RTS2__MARK, PORT234_FN2, MSEL3CR_MSEL9_1), \ + PINMUX_DATA(VIO2_CLK2_MARK, PORT234_FN6, MSEL4CR_MSEL27_1, + MSEL4CR_MSEL26_0), \ + PINMUX_DATA(LCD2D20_MARK, PORT234_FN7), + PINMUX_DATA(MSIOF1_RSYNC_MARK, PORT235_FN1), \ + PINMUX_DATA(MFG1_IN2_MARK, PORT235_FN3), \ + PINMUX_DATA(VIO2_VD2_MARK, PORT235_FN6, MSEL4CR_MSEL27_1, + MSEL4CR_MSEL26_0), \ + PINMUX_DATA(LCD2D21_MARK, PORT235_FN7), + PINMUX_DATA(MSIOF1_MCK0_MARK, PORT236_FN1), \ + PINMUX_DATA(PORT236_I2C_SDA2_MARK, PORT236_FN2, MSEL2CR_MSEL17_0, + MSEL2CR_MSEL16_0), + PINMUX_DATA(MSIOF1_MCK1_MARK, PORT237_FN1), \ + PINMUX_DATA(PORT237_I2C_SCL2_MARK, PORT237_FN2, MSEL2CR_MSEL17_0, + MSEL2CR_MSEL16_0), + PINMUX_DATA(MSIOF1_SS1_MARK, PORT238_FN1), \ + PINMUX_DATA(VIO2_FIELD2_MARK, PORT238_FN6, MSEL4CR_MSEL27_1, + MSEL4CR_MSEL26_0), \ + PINMUX_DATA(LCD2D22_MARK, PORT238_FN7), + PINMUX_DATA(MSIOF1_SS2_MARK, PORT239_FN1), \ + PINMUX_DATA(VIO2_HD2_MARK, PORT239_FN6, MSEL4CR_MSEL27_1, + MSEL4CR_MSEL26_0), \ + PINMUX_DATA(LCD2D23_MARK, PORT239_FN7), + PINMUX_DATA(SCIFA6_TXD_MARK, PORT240_FN1), + PINMUX_DATA(PORT241_IRDA_OUT_MARK, PORT241_FN1, MSEL4CR_MSEL19_0), \ + PINMUX_DATA(PORT241_IROUT_MARK, PORT241_FN2), \ + PINMUX_DATA(MFG4_OUT1_MARK, PORT241_FN3), \ + PINMUX_DATA(TPU4TO0_MARK, PORT241_FN4), + PINMUX_DATA(PORT242_IRDA_IN_MARK, PORT242_FN1, MSEL4CR_MSEL19_0), \ + PINMUX_DATA(MFG4_IN2_MARK, PORT242_FN3), + PINMUX_DATA(PORT243_IRDA_FIRSEL_MARK, PORT243_FN1, MSEL4CR_MSEL19_0), \ + PINMUX_DATA(PORT243_VIO_CKO2_MARK, PORT243_FN2), + PINMUX_DATA(PORT244_SCIFA5_CTS__MARK, PORT244_FN1, MSEL4CR_MSEL21_0, + MSEL4CR_MSEL20_0), \ + PINMUX_DATA(MFG2_IN1_MARK, PORT244_FN2), \ + PINMUX_DATA(PORT244_SCIFB_CTS__MARK, PORT244_FN3, MSEL4CR_MSEL22_1), \ + PINMUX_DATA(MSIOF2R_RXD_MARK, PORT244_FN7, MSEL4CR_MSEL11_1), + PINMUX_DATA(PORT245_SCIFA5_RTS__MARK, PORT245_FN1, MSEL4CR_MSEL21_0, + MSEL4CR_MSEL20_0), \ + PINMUX_DATA(MFG2_IN2_MARK, PORT245_FN2), \ + PINMUX_DATA(PORT245_SCIFB_RTS__MARK, PORT245_FN3, MSEL4CR_MSEL22_1), \ + PINMUX_DATA(MSIOF2R_TXD_MARK, PORT245_FN7, MSEL4CR_MSEL11_1), + PINMUX_DATA(PORT246_SCIFA5_RXD_MARK, PORT246_FN1, MSEL4CR_MSEL21_0, + MSEL4CR_MSEL20_0), \ + PINMUX_DATA(MFG1_OUT1_MARK, PORT246_FN2), \ + PINMUX_DATA(PORT246_SCIFB_RXD_MARK, PORT246_FN3, MSEL4CR_MSEL22_1), \ + PINMUX_DATA(TPU1TO0_MARK, PORT246_FN4), + PINMUX_DATA(PORT247_SCIFA5_TXD_MARK, PORT247_FN1, MSEL4CR_MSEL21_0, + MSEL4CR_MSEL20_0), \ + PINMUX_DATA(MFG3_OUT2_MARK, PORT247_FN2), \ + PINMUX_DATA(PORT247_SCIFB_TXD_MARK, PORT247_FN3, MSEL4CR_MSEL22_1), \ + PINMUX_DATA(TPU3TO1_MARK, PORT247_FN4), + PINMUX_DATA(PORT248_SCIFA5_SCK_MARK, PORT248_FN1, MSEL4CR_MSEL21_0, + MSEL4CR_MSEL20_0), \ + PINMUX_DATA(MFG2_OUT1_MARK, PORT248_FN2), \ + PINMUX_DATA(PORT248_SCIFB_SCK_MARK, PORT248_FN3, MSEL4CR_MSEL22_1), \ + PINMUX_DATA(TPU2TO0_MARK, PORT248_FN4), \ + PINMUX_DATA(PORT248_I2C_SCL3_MARK, PORT248_FN5, MSEL2CR_MSEL19_0, + MSEL2CR_MSEL18_0), \ + PINMUX_DATA(MSIOF2R_TSCK_MARK, PORT248_FN7, MSEL4CR_MSEL11_1), + PINMUX_DATA(PORT249_IROUT_MARK, PORT249_FN1), \ + PINMUX_DATA(MFG4_IN1_MARK, PORT249_FN2), \ + PINMUX_DATA(PORT249_I2C_SDA3_MARK, PORT249_FN5, MSEL2CR_MSEL19_0, + MSEL2CR_MSEL18_0), \ + PINMUX_DATA(MSIOF2R_TSYNC_MARK, PORT249_FN7, MSEL4CR_MSEL11_1), + PINMUX_DATA(SDHICLK0_MARK, PORT250_FN1), + PINMUX_DATA(SDHICD0_MARK, PORT251_FN1), + PINMUX_DATA(SDHID0_0_MARK, PORT252_FN1), + PINMUX_DATA(SDHID0_1_MARK, PORT253_FN1), + PINMUX_DATA(SDHID0_2_MARK, PORT254_FN1), + PINMUX_DATA(SDHID0_3_MARK, PORT255_FN1), + PINMUX_DATA(SDHICMD0_MARK, PORT256_FN1), + PINMUX_DATA(SDHIWP0_MARK, PORT257_FN1), + PINMUX_DATA(SDHICLK1_MARK, PORT258_FN1), + PINMUX_DATA(SDHID1_0_MARK, PORT259_FN1), \ + PINMUX_DATA(TS_SPSYNC2_MARK, PORT259_FN3), + PINMUX_DATA(SDHID1_1_MARK, PORT260_FN1), \ + PINMUX_DATA(TS_SDAT2_MARK, PORT260_FN3), + PINMUX_DATA(SDHID1_2_MARK, PORT261_FN1), \ + PINMUX_DATA(TS_SDEN2_MARK, PORT261_FN3), + PINMUX_DATA(SDHID1_3_MARK, PORT262_FN1), \ + PINMUX_DATA(TS_SCK2_MARK, PORT262_FN3), + PINMUX_DATA(SDHICMD1_MARK, PORT263_FN1), + PINMUX_DATA(SDHICLK2_MARK, PORT264_FN1), + PINMUX_DATA(SDHID2_0_MARK, PORT265_FN1), \ + PINMUX_DATA(TS_SPSYNC4_MARK, PORT265_FN3), + PINMUX_DATA(SDHID2_1_MARK, PORT266_FN1), \ + PINMUX_DATA(TS_SDAT4_MARK, PORT266_FN3), + PINMUX_DATA(SDHID2_2_MARK, PORT267_FN1), \ + PINMUX_DATA(TS_SDEN4_MARK, PORT267_FN3), + PINMUX_DATA(SDHID2_3_MARK, PORT268_FN1), \ + PINMUX_DATA(TS_SCK4_MARK, PORT268_FN3), + PINMUX_DATA(SDHICMD2_MARK, PORT269_FN1), + PINMUX_DATA(MMCCLK0_MARK, PORT270_FN1, MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_0_MARK, PORT271_FN1, PORT271_IN_PU, + MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_1_MARK, PORT272_FN1, PORT272_IN_PU, + MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_2_MARK, PORT273_FN1, PORT273_IN_PU, + MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_3_MARK, PORT274_FN1, PORT274_IN_PU, + MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_4_MARK, PORT275_FN1, PORT275_IN_PU, + MSEL4CR_MSEL15_0), \ + PINMUX_DATA(TS_SPSYNC5_MARK, PORT275_FN3), + PINMUX_DATA(MMCD0_5_MARK, PORT276_FN1, PORT276_IN_PU, + MSEL4CR_MSEL15_0), \ + PINMUX_DATA(TS_SDAT5_MARK, PORT276_FN3), + PINMUX_DATA(MMCD0_6_MARK, PORT277_FN1, PORT277_IN_PU, + MSEL4CR_MSEL15_0), \ + PINMUX_DATA(TS_SDEN5_MARK, PORT277_FN3), + PINMUX_DATA(MMCD0_7_MARK, PORT278_FN1, PORT278_IN_PU, + MSEL4CR_MSEL15_0), \ + PINMUX_DATA(TS_SCK5_MARK, PORT278_FN3), + PINMUX_DATA(MMCCMD0_MARK, PORT279_FN1, PORT279_IN_PU, + MSEL4CR_MSEL15_0), + PINMUX_DATA(RESETOUTS__MARK, PORT281_FN1), \ + PINMUX_DATA(EXTAL2OUT_MARK, PORT281_FN2), + PINMUX_DATA(MCP_WAIT__MCP_FRB_MARK, PORT288_FN1), + PINMUX_DATA(MCP_CKO_MARK, PORT289_FN1), \ + PINMUX_DATA(MMCCLK1_MARK, PORT289_FN2, MSEL4CR_MSEL15_1), + PINMUX_DATA(MCP_D15_MCP_NAF15_MARK, PORT290_FN1), + PINMUX_DATA(MCP_D14_MCP_NAF14_MARK, PORT291_FN1), + PINMUX_DATA(MCP_D13_MCP_NAF13_MARK, PORT292_FN1), + PINMUX_DATA(MCP_D12_MCP_NAF12_MARK, PORT293_FN1), + PINMUX_DATA(MCP_D11_MCP_NAF11_MARK, PORT294_FN1), + PINMUX_DATA(MCP_D10_MCP_NAF10_MARK, PORT295_FN1), + PINMUX_DATA(MCP_D9_MCP_NAF9_MARK, PORT296_FN1), + PINMUX_DATA(MCP_D8_MCP_NAF8_MARK, PORT297_FN1), \ + PINMUX_DATA(MMCCMD1_MARK, PORT297_FN2, MSEL4CR_MSEL15_1), + PINMUX_DATA(MCP_D7_MCP_NAF7_MARK, PORT298_FN1), \ + PINMUX_DATA(MMCD1_7_MARK, PORT298_FN2, MSEL4CR_MSEL15_1), + + PINMUX_DATA(MCP_D6_MCP_NAF6_MARK, PORT299_FN1), \ + PINMUX_DATA(MMCD1_6_MARK, PORT299_FN2, MSEL4CR_MSEL15_1), + PINMUX_DATA(MCP_D5_MCP_NAF5_MARK, PORT300_FN1), \ + PINMUX_DATA(MMCD1_5_MARK, PORT300_FN2, MSEL4CR_MSEL15_1), + PINMUX_DATA(MCP_D4_MCP_NAF4_MARK, PORT301_FN1), \ + PINMUX_DATA(MMCD1_4_MARK, PORT301_FN2, MSEL4CR_MSEL15_1), + PINMUX_DATA(MCP_D3_MCP_NAF3_MARK, PORT302_FN1), \ + PINMUX_DATA(MMCD1_3_MARK, PORT302_FN2, MSEL4CR_MSEL15_1), + PINMUX_DATA(MCP_D2_MCP_NAF2_MARK, PORT303_FN1), \ + PINMUX_DATA(MMCD1_2_MARK, PORT303_FN2, MSEL4CR_MSEL15_1), + PINMUX_DATA(MCP_D1_MCP_NAF1_MARK, PORT304_FN1), \ + PINMUX_DATA(MMCD1_1_MARK, PORT304_FN2, MSEL4CR_MSEL15_1), + PINMUX_DATA(MCP_D0_MCP_NAF0_MARK, PORT305_FN1), \ + PINMUX_DATA(MMCD1_0_MARK, PORT305_FN2, MSEL4CR_MSEL15_1), + PINMUX_DATA(MCP_NBRSTOUT__MARK, PORT306_FN1), + PINMUX_DATA(MCP_WE0__MCP_FWE_MARK, PORT309_FN1), \ + PINMUX_DATA(MCP_RDWR_MCP_FWE_MARK, PORT309_FN2), + + /* MSEL2 special cases */ + PINMUX_DATA(TSIF2_TS_XX1_MARK, MSEL2CR_MSEL14_0, MSEL2CR_MSEL13_0, + MSEL2CR_MSEL12_0), + PINMUX_DATA(TSIF2_TS_XX2_MARK, MSEL2CR_MSEL14_0, MSEL2CR_MSEL13_0, + MSEL2CR_MSEL12_1), + PINMUX_DATA(TSIF2_TS_XX3_MARK, MSEL2CR_MSEL14_0, MSEL2CR_MSEL13_1, + MSEL2CR_MSEL12_0), + PINMUX_DATA(TSIF2_TS_XX4_MARK, MSEL2CR_MSEL14_0, MSEL2CR_MSEL13_1, + MSEL2CR_MSEL12_1), + PINMUX_DATA(TSIF2_TS_XX5_MARK, MSEL2CR_MSEL14_1, MSEL2CR_MSEL13_0, + MSEL2CR_MSEL12_0), + PINMUX_DATA(TSIF1_TS_XX1_MARK, MSEL2CR_MSEL11_0, MSEL2CR_MSEL10_0, + MSEL2CR_MSEL9_0), + PINMUX_DATA(TSIF1_TS_XX2_MARK, MSEL2CR_MSEL11_0, MSEL2CR_MSEL10_0, + MSEL2CR_MSEL9_1), + PINMUX_DATA(TSIF1_TS_XX3_MARK, MSEL2CR_MSEL11_0, MSEL2CR_MSEL10_1, + MSEL2CR_MSEL9_0), + PINMUX_DATA(TSIF1_TS_XX4_MARK, MSEL2CR_MSEL11_0, MSEL2CR_MSEL10_1, + MSEL2CR_MSEL9_1), + PINMUX_DATA(TSIF1_TS_XX5_MARK, MSEL2CR_MSEL11_1, MSEL2CR_MSEL10_0, + MSEL2CR_MSEL9_0), + PINMUX_DATA(TSIF0_TS_XX1_MARK, MSEL2CR_MSEL8_0, MSEL2CR_MSEL7_0, + MSEL2CR_MSEL6_0), + PINMUX_DATA(TSIF0_TS_XX2_MARK, MSEL2CR_MSEL8_0, MSEL2CR_MSEL7_0, + MSEL2CR_MSEL6_1), + PINMUX_DATA(TSIF0_TS_XX3_MARK, MSEL2CR_MSEL8_0, MSEL2CR_MSEL7_1, + MSEL2CR_MSEL6_0), + PINMUX_DATA(TSIF0_TS_XX4_MARK, MSEL2CR_MSEL8_0, MSEL2CR_MSEL7_1, + MSEL2CR_MSEL6_1), + PINMUX_DATA(TSIF0_TS_XX5_MARK, MSEL2CR_MSEL8_1, MSEL2CR_MSEL7_0, + MSEL2CR_MSEL6_0), + PINMUX_DATA(MST1_TS_XX1_MARK, MSEL2CR_MSEL5_0, MSEL2CR_MSEL4_0, + MSEL2CR_MSEL3_0), + PINMUX_DATA(MST1_TS_XX2_MARK, MSEL2CR_MSEL5_0, MSEL2CR_MSEL4_0, + MSEL2CR_MSEL3_1), + PINMUX_DATA(MST1_TS_XX3_MARK, MSEL2CR_MSEL5_0, MSEL2CR_MSEL4_1, + MSEL2CR_MSEL3_0), + PINMUX_DATA(MST1_TS_XX4_MARK, MSEL2CR_MSEL5_0, MSEL2CR_MSEL4_1, + MSEL2CR_MSEL3_1), + PINMUX_DATA(MST1_TS_XX5_MARK, MSEL2CR_MSEL5_1, MSEL2CR_MSEL4_0, + MSEL2CR_MSEL3_0), + PINMUX_DATA(MST0_TS_XX1_MARK, MSEL2CR_MSEL2_0, MSEL2CR_MSEL1_0, + MSEL2CR_MSEL0_0), + PINMUX_DATA(MST0_TS_XX2_MARK, MSEL2CR_MSEL2_0, MSEL2CR_MSEL1_0, + MSEL2CR_MSEL0_1), + PINMUX_DATA(MST0_TS_XX3_MARK, MSEL2CR_MSEL2_0, MSEL2CR_MSEL1_1, + MSEL2CR_MSEL0_0), + PINMUX_DATA(MST0_TS_XX4_MARK, MSEL2CR_MSEL2_0, MSEL2CR_MSEL1_1, + MSEL2CR_MSEL0_1), + PINMUX_DATA(MST0_TS_XX5_MARK, MSEL2CR_MSEL2_1, MSEL2CR_MSEL1_0, + MSEL2CR_MSEL0_0), + + /* MSEL3 special cases */ + PINMUX_DATA(SDHI0_VCCQ_MC0_ON_MARK, MSEL3CR_MSEL28_1), + PINMUX_DATA(SDHI0_VCCQ_MC0_OFF_MARK, MSEL3CR_MSEL28_0), + PINMUX_DATA(DEBUG_MON_VIO_MARK, MSEL3CR_MSEL15_0), + PINMUX_DATA(DEBUG_MON_LCDD_MARK, MSEL3CR_MSEL15_1), + PINMUX_DATA(LCDC_LCDC0_MARK, MSEL3CR_MSEL6_0), + PINMUX_DATA(LCDC_LCDC1_MARK, MSEL3CR_MSEL6_1), + + /* MSEL4 special cases */ + PINMUX_DATA(IRQ9_MEM_INT_MARK, MSEL4CR_MSEL29_0), + PINMUX_DATA(IRQ9_MCP_INT_MARK, MSEL4CR_MSEL29_1), + PINMUX_DATA(A11_MARK, MSEL4CR_MSEL13_0, MSEL4CR_MSEL12_0), + PINMUX_DATA(KEYOUT8_MARK, MSEL4CR_MSEL13_0, MSEL4CR_MSEL12_1), + PINMUX_DATA(TPU4TO3_MARK, MSEL4CR_MSEL13_1, MSEL4CR_MSEL12_0), + PINMUX_DATA(RESETA_N_PU_ON_MARK, MSEL4CR_MSEL4_0), + PINMUX_DATA(RESETA_N_PU_OFF_MARK, MSEL4CR_MSEL4_1), + PINMUX_DATA(EDBGREQ_PD_MARK, MSEL4CR_MSEL1_0), + PINMUX_DATA(EDBGREQ_PU_MARK, MSEL4CR_MSEL1_1), + + /* Functions with pull-ups */ + PINMUX_DATA(KEYIN0_PU_MARK, PORT66_FN2, PORT66_IN_PU), + PINMUX_DATA(KEYIN1_PU_MARK, PORT67_FN2, PORT67_IN_PU), + PINMUX_DATA(KEYIN2_PU_MARK, PORT68_FN2, PORT68_IN_PU), + PINMUX_DATA(KEYIN3_PU_MARK, PORT69_FN2, PORT69_IN_PU), + PINMUX_DATA(KEYIN4_PU_MARK, PORT70_FN2, PORT70_IN_PU), + PINMUX_DATA(KEYIN5_PU_MARK, PORT71_FN2, PORT71_IN_PU), + PINMUX_DATA(KEYIN6_PU_MARK, PORT72_FN2, PORT72_IN_PU), + PINMUX_DATA(KEYIN7_PU_MARK, PORT73_FN2, PORT73_IN_PU), + + PINMUX_DATA(SDHICD0_PU_MARK, PORT251_FN1, PORT251_IN_PU), + PINMUX_DATA(SDHID0_0_PU_MARK, PORT252_FN1, PORT252_IN_PU), + PINMUX_DATA(SDHID0_1_PU_MARK, PORT253_FN1, PORT253_IN_PU), + PINMUX_DATA(SDHID0_2_PU_MARK, PORT254_FN1, PORT254_IN_PU), + PINMUX_DATA(SDHID0_3_PU_MARK, PORT255_FN1, PORT255_IN_PU), + PINMUX_DATA(SDHICMD0_PU_MARK, PORT256_FN1, PORT256_IN_PU), + PINMUX_DATA(SDHIWP0_PU_MARK, PORT257_FN1, PORT256_IN_PU), + PINMUX_DATA(SDHID1_0_PU_MARK, PORT259_FN1, PORT259_IN_PU), + PINMUX_DATA(SDHID1_1_PU_MARK, PORT260_FN1, PORT260_IN_PU), + PINMUX_DATA(SDHID1_2_PU_MARK, PORT261_FN1, PORT261_IN_PU), + PINMUX_DATA(SDHID1_3_PU_MARK, PORT262_FN1, PORT262_IN_PU), + PINMUX_DATA(SDHICMD1_PU_MARK, PORT263_FN1, PORT263_IN_PU), + PINMUX_DATA(SDHID2_0_PU_MARK, PORT265_FN1, PORT265_IN_PU), + PINMUX_DATA(SDHID2_1_PU_MARK, PORT266_FN1, PORT266_IN_PU), + PINMUX_DATA(SDHID2_2_PU_MARK, PORT267_FN1, PORT267_IN_PU), + PINMUX_DATA(SDHID2_3_PU_MARK, PORT268_FN1, PORT268_IN_PU), + PINMUX_DATA(SDHICMD2_PU_MARK, PORT269_FN1, PORT269_IN_PU), + + PINMUX_DATA(MMCCMD0_PU_MARK, PORT279_FN1, PORT279_IN_PU, + MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT297_IN_PU, + MSEL4CR_MSEL15_1), + + PINMUX_DATA(MMCD0_0_PU_MARK, + PORT271_FN1, PORT271_IN_PU, MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_1_PU_MARK, + PORT272_FN1, PORT272_IN_PU, MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_2_PU_MARK, + PORT273_FN1, PORT273_IN_PU, MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_3_PU_MARK, + PORT274_FN1, PORT274_IN_PU, MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_4_PU_MARK, + PORT275_FN1, PORT275_IN_PU, MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_5_PU_MARK, + PORT276_FN1, PORT276_IN_PU, MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_6_PU_MARK, + PORT277_FN1, PORT277_IN_PU, MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCD0_7_PU_MARK, + PORT278_FN1, PORT278_IN_PU, MSEL4CR_MSEL15_0), + + PINMUX_DATA(FSIBISLD_PU_MARK, PORT39_FN1, PORT39_IN_PU), + PINMUX_DATA(FSIACK_PU_MARK, PORT49_FN1, PORT49_IN_PU), + PINMUX_DATA(FSIAILR_PU_MARK, PORT50_FN5, PORT50_IN_PU), + PINMUX_DATA(FSIAIBT_PU_MARK, PORT51_FN5, PORT51_IN_PU), + PINMUX_DATA(FSIAISLD_PU_MARK, PORT55_FN1, PORT55_IN_PU), +}; + +static struct pinmux_gpio pinmux_gpios[] = { + GPIO_PORT_ALL(), + + /* Table 25-1 (Functions 0-7) */ + GPIO_FN(VBUS_0), + GPIO_FN(GPI0), + GPIO_FN(GPI1), + GPIO_FN(GPI2), + GPIO_FN(GPI3), + GPIO_FN(GPI4), + GPIO_FN(GPI5), + GPIO_FN(GPI6), + GPIO_FN(GPI7), + GPIO_FN(SCIFA7_RXD), + GPIO_FN(SCIFA7_CTS_), + GPIO_FN(GPO7), \ + GPIO_FN(MFG0_OUT2), + GPIO_FN(GPO6), \ + GPIO_FN(MFG1_OUT2), + GPIO_FN(GPO5), \ + GPIO_FN(SCIFA0_SCK), \ + GPIO_FN(FSICOSLDT3), \ + GPIO_FN(PORT16_VIO_CKOR), + GPIO_FN(SCIFA0_TXD), + GPIO_FN(SCIFA7_TXD), + GPIO_FN(SCIFA7_RTS_), \ + GPIO_FN(PORT19_VIO_CKO2), + GPIO_FN(GPO0), + GPIO_FN(GPO1), + GPIO_FN(GPO2), \ + GPIO_FN(STATUS0), + GPIO_FN(GPO3), \ + GPIO_FN(STATUS1), + GPIO_FN(GPO4), \ + GPIO_FN(STATUS2), + GPIO_FN(VINT), + GPIO_FN(TCKON), + GPIO_FN(XDVFS1), \ + GPIO_FN(PORT27_I2C_SCL2), \ + GPIO_FN(PORT27_I2C_SCL3), \ + GPIO_FN(MFG0_OUT1), \ + GPIO_FN(PORT27_IROUT), + GPIO_FN(XDVFS2), \ + GPIO_FN(PORT28_I2C_SDA2), \ + GPIO_FN(PORT28_I2C_SDA3), \ + GPIO_FN(PORT28_TPU1TO1), + GPIO_FN(SIM_RST), \ + GPIO_FN(PORT29_TPU1TO1), + GPIO_FN(SIM_CLK), \ + GPIO_FN(PORT30_VIO_CKOR), + GPIO_FN(SIM_D), \ + GPIO_FN(PORT31_IROUT), + GPIO_FN(SCIFA4_TXD), + GPIO_FN(SCIFA4_RXD), \ + GPIO_FN(XWUP), + GPIO_FN(SCIFA4_RTS_), + GPIO_FN(SCIFA4_CTS_), + GPIO_FN(FSIBOBT), \ + GPIO_FN(FSIBIBT), + GPIO_FN(FSIBOLR), \ + GPIO_FN(FSIBILR), + GPIO_FN(FSIBOSLD), + GPIO_FN(FSIBISLD), + GPIO_FN(VACK), + GPIO_FN(XTAL1L), + GPIO_FN(SCIFA0_RTS_), \ + GPIO_FN(FSICOSLDT2), + GPIO_FN(SCIFA0_RXD), + GPIO_FN(SCIFA0_CTS_), \ + GPIO_FN(FSICOSLDT1), + GPIO_FN(FSICOBT), \ + GPIO_FN(FSICIBT), \ + GPIO_FN(FSIDOBT), \ + GPIO_FN(FSIDIBT), + GPIO_FN(FSICOLR), \ + GPIO_FN(FSICILR), \ + GPIO_FN(FSIDOLR), \ + GPIO_FN(FSIDILR), + GPIO_FN(FSICOSLD), \ + GPIO_FN(PORT47_FSICSPDIF), + GPIO_FN(FSICISLD), \ + GPIO_FN(FSIDISLD), + GPIO_FN(FSIACK), \ + GPIO_FN(PORT49_IRDA_OUT), \ + GPIO_FN(PORT49_IROUT), \ + GPIO_FN(FSIAOMC), + GPIO_FN(FSIAOLR), \ + GPIO_FN(BBIF2_TSYNC2), \ + GPIO_FN(TPU2TO2), \ + GPIO_FN(FSIAILR), + + GPIO_FN(FSIAOBT), \ + GPIO_FN(BBIF2_TSCK2), \ + GPIO_FN(TPU2TO3), \ + GPIO_FN(FSIAIBT), + GPIO_FN(FSIAOSLD), \ + GPIO_FN(BBIF2_TXD2), + GPIO_FN(FSIASPDIF), \ + GPIO_FN(PORT53_IRDA_IN), \ + GPIO_FN(TPU3TO3), \ + GPIO_FN(FSIBSPDIF), \ + GPIO_FN(PORT53_FSICSPDIF), + GPIO_FN(FSIBCK), \ + GPIO_FN(PORT54_IRDA_FIRSEL), \ + GPIO_FN(TPU3TO2), \ + GPIO_FN(FSIBOMC), \ + GPIO_FN(FSICCK), \ + GPIO_FN(FSICOMC), + GPIO_FN(FSIAISLD), \ + GPIO_FN(TPU0TO0), + GPIO_FN(A0), \ + GPIO_FN(BS_), + GPIO_FN(A12), \ + GPIO_FN(PORT58_KEYOUT7), \ + GPIO_FN(TPU4TO2), + GPIO_FN(A13), \ + GPIO_FN(PORT59_KEYOUT6), \ + GPIO_FN(TPU0TO1), + GPIO_FN(A14), \ + GPIO_FN(KEYOUT5), + GPIO_FN(A15), \ + GPIO_FN(KEYOUT4), + GPIO_FN(A16), \ + GPIO_FN(KEYOUT3), \ + GPIO_FN(MSIOF0_SS1), + GPIO_FN(A17), \ + GPIO_FN(KEYOUT2), \ + GPIO_FN(MSIOF0_TSYNC), + GPIO_FN(A18), \ + GPIO_FN(KEYOUT1), \ + GPIO_FN(MSIOF0_TSCK), + GPIO_FN(A19), \ + GPIO_FN(KEYOUT0), \ + GPIO_FN(MSIOF0_TXD), + GPIO_FN(A20), \ + GPIO_FN(KEYIN0), \ + GPIO_FN(MSIOF0_RSCK), + GPIO_FN(A21), \ + GPIO_FN(KEYIN1), \ + GPIO_FN(MSIOF0_RSYNC), + GPIO_FN(A22), \ + GPIO_FN(KEYIN2), \ + GPIO_FN(MSIOF0_MCK0), + GPIO_FN(A23), \ + GPIO_FN(KEYIN3), \ + GPIO_FN(MSIOF0_MCK1), + GPIO_FN(A24), \ + GPIO_FN(KEYIN4), \ + GPIO_FN(MSIOF0_RXD), + GPIO_FN(A25), \ + GPIO_FN(KEYIN5), \ + GPIO_FN(MSIOF0_SS2), + GPIO_FN(A26), \ + GPIO_FN(KEYIN6), + GPIO_FN(KEYIN7), + GPIO_FN(D0_NAF0), + GPIO_FN(D1_NAF1), + GPIO_FN(D2_NAF2), + GPIO_FN(D3_NAF3), + GPIO_FN(D4_NAF4), + GPIO_FN(D5_NAF5), + GPIO_FN(D6_NAF6), + GPIO_FN(D7_NAF7), + GPIO_FN(D8_NAF8), + GPIO_FN(D9_NAF9), + GPIO_FN(D10_NAF10), + GPIO_FN(D11_NAF11), + GPIO_FN(D12_NAF12), + GPIO_FN(D13_NAF13), + GPIO_FN(D14_NAF14), + GPIO_FN(D15_NAF15), + GPIO_FN(CS4_), + GPIO_FN(CS5A_), \ + GPIO_FN(PORT91_RDWR), + GPIO_FN(CS5B_), \ + GPIO_FN(FCE1_), + GPIO_FN(CS6B_), \ + GPIO_FN(DACK0), + GPIO_FN(FCE0_), \ + GPIO_FN(CS6A_), + GPIO_FN(WAIT_), \ + GPIO_FN(DREQ0), + GPIO_FN(RD__FSC), + GPIO_FN(WE0__FWE), \ + GPIO_FN(RDWR_FWE), + GPIO_FN(WE1_), + GPIO_FN(FRB), + GPIO_FN(CKO), + GPIO_FN(NBRSTOUT_), + GPIO_FN(NBRST_), + GPIO_FN(BBIF2_TXD), + GPIO_FN(BBIF2_RXD), + GPIO_FN(BBIF2_SYNC), + GPIO_FN(BBIF2_SCK), + GPIO_FN(SCIFA3_CTS_), \ + GPIO_FN(MFG3_IN2), + GPIO_FN(SCIFA3_RXD), \ + GPIO_FN(MFG3_IN1), + GPIO_FN(BBIF1_SS2), \ + GPIO_FN(SCIFA3_RTS_), \ + GPIO_FN(MFG3_OUT1), + GPIO_FN(SCIFA3_TXD), + GPIO_FN(HSI_RX_DATA), \ + GPIO_FN(BBIF1_RXD), + GPIO_FN(HSI_TX_WAKE), \ + GPIO_FN(BBIF1_TSCK), + GPIO_FN(HSI_TX_DATA), \ + GPIO_FN(BBIF1_TSYNC), + GPIO_FN(HSI_TX_READY), \ + GPIO_FN(BBIF1_TXD), + GPIO_FN(HSI_RX_READY), \ + GPIO_FN(BBIF1_RSCK), \ + GPIO_FN(PORT115_I2C_SCL2), \ + GPIO_FN(PORT115_I2C_SCL3), + GPIO_FN(HSI_RX_WAKE), \ + GPIO_FN(BBIF1_RSYNC), \ + GPIO_FN(PORT116_I2C_SDA2), \ + GPIO_FN(PORT116_I2C_SDA3), + GPIO_FN(HSI_RX_FLAG), \ + GPIO_FN(BBIF1_SS1), \ + GPIO_FN(BBIF1_FLOW), + GPIO_FN(HSI_TX_FLAG), + GPIO_FN(VIO_VD), \ + GPIO_FN(PORT128_LCD2VSYN), \ + GPIO_FN(VIO2_VD), \ + GPIO_FN(LCD2D0), + + GPIO_FN(VIO_HD), \ + GPIO_FN(PORT129_LCD2HSYN), \ + GPIO_FN(PORT129_LCD2CS_), \ + GPIO_FN(VIO2_HD), \ + GPIO_FN(LCD2D1), + GPIO_FN(VIO_D0), \ + GPIO_FN(PORT130_MSIOF2_RXD), \ + GPIO_FN(LCD2D10), + GPIO_FN(VIO_D1), \ + GPIO_FN(PORT131_KEYOUT6), \ + GPIO_FN(PORT131_MSIOF2_SS1), \ + GPIO_FN(PORT131_KEYOUT11), \ + GPIO_FN(LCD2D11), + GPIO_FN(VIO_D2), \ + GPIO_FN(PORT132_KEYOUT7), \ + GPIO_FN(PORT132_MSIOF2_SS2), \ + GPIO_FN(PORT132_KEYOUT10), \ + GPIO_FN(LCD2D12), + GPIO_FN(VIO_D3), \ + GPIO_FN(MSIOF2_TSYNC), \ + GPIO_FN(LCD2D13), + GPIO_FN(VIO_D4), \ + GPIO_FN(MSIOF2_TXD), \ + GPIO_FN(LCD2D14), + GPIO_FN(VIO_D5), \ + GPIO_FN(MSIOF2_TSCK), \ + GPIO_FN(LCD2D15), + GPIO_FN(VIO_D6), \ + GPIO_FN(PORT136_KEYOUT8), \ + GPIO_FN(LCD2D16), + GPIO_FN(VIO_D7), \ + GPIO_FN(PORT137_KEYOUT9), \ + GPIO_FN(LCD2D17), + GPIO_FN(VIO_D8), \ + GPIO_FN(PORT138_KEYOUT8), \ + GPIO_FN(VIO2_D0), \ + GPIO_FN(LCD2D6), + GPIO_FN(VIO_D9), \ + GPIO_FN(PORT139_KEYOUT9), \ + GPIO_FN(VIO2_D1), \ + GPIO_FN(LCD2D7), + GPIO_FN(VIO_D10), \ + GPIO_FN(TPU0TO2), \ + GPIO_FN(VIO2_D2), \ + GPIO_FN(LCD2D8), + GPIO_FN(VIO_D11), \ + GPIO_FN(TPU0TO3), \ + GPIO_FN(VIO2_D3), \ + GPIO_FN(LCD2D9), + GPIO_FN(VIO_D12), \ + GPIO_FN(PORT142_KEYOUT10), \ + GPIO_FN(VIO2_D4), \ + GPIO_FN(LCD2D2), + GPIO_FN(VIO_D13), \ + GPIO_FN(PORT143_KEYOUT11), \ + GPIO_FN(PORT143_KEYOUT6), \ + GPIO_FN(VIO2_D5), \ + GPIO_FN(LCD2D3), + GPIO_FN(VIO_D14), \ + GPIO_FN(PORT144_KEYOUT7), \ + GPIO_FN(VIO2_D6), \ + GPIO_FN(LCD2D4), + GPIO_FN(VIO_D15), \ + GPIO_FN(TPU1TO3), \ + GPIO_FN(PORT145_LCD2DISP), \ + GPIO_FN(PORT145_LCD2RS), \ + GPIO_FN(VIO2_D7), \ + GPIO_FN(LCD2D5), + GPIO_FN(VIO_CLK), \ + GPIO_FN(LCD2DCK), \ + GPIO_FN(PORT146_LCD2WR_), \ + GPIO_FN(VIO2_CLK), \ + GPIO_FN(LCD2D18), + GPIO_FN(VIO_FIELD), \ + GPIO_FN(LCD2RD_), \ + GPIO_FN(VIO2_FIELD), \ + GPIO_FN(LCD2D19), + GPIO_FN(VIO_CKO), + GPIO_FN(A27), \ + GPIO_FN(PORT149_RDWR), \ + GPIO_FN(MFG0_IN1), \ + GPIO_FN(PORT149_KEYOUT9), + GPIO_FN(MFG0_IN2), + GPIO_FN(TS_SPSYNC3), \ + GPIO_FN(MSIOF2_RSCK), + GPIO_FN(TS_SDAT3), \ + GPIO_FN(MSIOF2_RSYNC), + GPIO_FN(TPU1TO2), \ + GPIO_FN(TS_SDEN3), \ + GPIO_FN(PORT153_MSIOF2_SS1), + GPIO_FN(SCIFA2_TXD1), \ + GPIO_FN(MSIOF2_MCK0), + GPIO_FN(SCIFA2_RXD1), \ + GPIO_FN(MSIOF2_MCK1), + GPIO_FN(SCIFA2_RTS1_), \ + GPIO_FN(PORT156_MSIOF2_SS2), + GPIO_FN(SCIFA2_CTS1_), \ + GPIO_FN(PORT157_MSIOF2_RXD), + GPIO_FN(DINT_), \ + GPIO_FN(SCIFA2_SCK1), \ + GPIO_FN(TS_SCK3), + GPIO_FN(PORT159_SCIFB_SCK), \ + GPIO_FN(PORT159_SCIFA5_SCK), \ + GPIO_FN(NMI), + GPIO_FN(PORT160_SCIFB_TXD), \ + GPIO_FN(PORT160_SCIFA5_TXD), + GPIO_FN(PORT161_SCIFB_CTS_), \ + GPIO_FN(PORT161_SCIFA5_CTS_), + GPIO_FN(PORT162_SCIFB_RXD), \ + GPIO_FN(PORT162_SCIFA5_RXD), + GPIO_FN(PORT163_SCIFB_RTS_), \ + GPIO_FN(PORT163_SCIFA5_RTS_), \ + GPIO_FN(TPU3TO0), + GPIO_FN(LCDD0), + GPIO_FN(LCDD1), \ + GPIO_FN(PORT193_SCIFA5_CTS_), \ + GPIO_FN(BBIF2_TSYNC1), + GPIO_FN(LCDD2), \ + GPIO_FN(PORT194_SCIFA5_RTS_), \ + GPIO_FN(BBIF2_TSCK1), + GPIO_FN(LCDD3), \ + GPIO_FN(PORT195_SCIFA5_RXD), \ + GPIO_FN(BBIF2_TXD1), + GPIO_FN(LCDD4), \ + GPIO_FN(PORT196_SCIFA5_TXD), + GPIO_FN(LCDD5), \ + GPIO_FN(PORT197_SCIFA5_SCK), \ + GPIO_FN(MFG2_OUT2), \ + GPIO_FN(TPU2TO1), + GPIO_FN(LCDD6), + GPIO_FN(LCDD7), \ + GPIO_FN(TPU4TO1), \ + GPIO_FN(MFG4_OUT2), + GPIO_FN(LCDD8), \ + GPIO_FN(D16), + GPIO_FN(LCDD9), \ + GPIO_FN(D17), + GPIO_FN(LCDD10), \ + GPIO_FN(D18), + GPIO_FN(LCDD11), \ + GPIO_FN(D19), + GPIO_FN(LCDD12), \ + GPIO_FN(D20), + GPIO_FN(LCDD13), \ + GPIO_FN(D21), + GPIO_FN(LCDD14), \ + GPIO_FN(D22), + GPIO_FN(LCDD15), \ + GPIO_FN(PORT207_MSIOF0L_SS1), \ + GPIO_FN(D23), + GPIO_FN(LCDD16), \ + GPIO_FN(PORT208_MSIOF0L_SS2), \ + GPIO_FN(D24), + GPIO_FN(LCDD17), \ + GPIO_FN(D25), + GPIO_FN(LCDD18), \ + GPIO_FN(DREQ2), \ + GPIO_FN(PORT210_MSIOF0L_SS1), \ + GPIO_FN(D26), + GPIO_FN(LCDD19), \ + GPIO_FN(PORT211_MSIOF0L_SS2), \ + GPIO_FN(D27), + GPIO_FN(LCDD20), \ + GPIO_FN(TS_SPSYNC1), \ + GPIO_FN(MSIOF0L_MCK0), \ + GPIO_FN(D28), + GPIO_FN(LCDD21), \ + GPIO_FN(TS_SDAT1), \ + GPIO_FN(MSIOF0L_MCK1), \ + GPIO_FN(D29), + GPIO_FN(LCDD22), \ + GPIO_FN(TS_SDEN1), \ + GPIO_FN(MSIOF0L_RSCK), \ + GPIO_FN(D30), + GPIO_FN(LCDD23), \ + GPIO_FN(TS_SCK1), \ + GPIO_FN(MSIOF0L_RSYNC), \ + GPIO_FN(D31), + GPIO_FN(LCDDCK), \ + GPIO_FN(LCDWR_), + GPIO_FN(LCDRD_), \ + GPIO_FN(DACK2), \ + GPIO_FN(PORT217_LCD2RS), \ + GPIO_FN(MSIOF0L_TSYNC), \ + GPIO_FN(VIO2_FIELD3), \ + GPIO_FN(PORT217_LCD2DISP), + GPIO_FN(LCDHSYN), \ + GPIO_FN(LCDCS_), \ + GPIO_FN(LCDCS2_), \ + GPIO_FN(DACK3), \ + GPIO_FN(PORT218_VIO_CKOR), + GPIO_FN(LCDDISP), \ + GPIO_FN(LCDRS), \ + GPIO_FN(PORT219_LCD2WR_), \ + GPIO_FN(DREQ3), \ + GPIO_FN(MSIOF0L_TSCK), \ + GPIO_FN(VIO2_CLK3), \ + GPIO_FN(LCD2DCK_2), + GPIO_FN(LCDVSYN), \ + GPIO_FN(LCDVSYN2), + GPIO_FN(LCDLCLK), \ + GPIO_FN(DREQ1), \ + GPIO_FN(PORT221_LCD2CS_), \ + GPIO_FN(PWEN), \ + GPIO_FN(MSIOF0L_RXD), \ + GPIO_FN(VIO2_HD3), \ + GPIO_FN(PORT221_LCD2HSYN), + GPIO_FN(LCDDON), \ + GPIO_FN(LCDDON2), \ + GPIO_FN(DACK1), \ + GPIO_FN(OVCN), \ + GPIO_FN(MSIOF0L_TXD), \ + GPIO_FN(VIO2_VD3), \ + GPIO_FN(PORT222_LCD2VSYN), + + GPIO_FN(SCIFA1_TXD), \ + GPIO_FN(OVCN2), + GPIO_FN(EXTLP), \ + GPIO_FN(SCIFA1_SCK), \ + GPIO_FN(PORT226_VIO_CKO2), + GPIO_FN(SCIFA1_RTS_), \ + GPIO_FN(IDIN), + GPIO_FN(SCIFA1_RXD), + GPIO_FN(SCIFA1_CTS_), \ + GPIO_FN(MFG1_IN1), + GPIO_FN(MSIOF1_TXD), \ + GPIO_FN(SCIFA2_TXD2), + GPIO_FN(MSIOF1_TSYNC), \ + GPIO_FN(SCIFA2_CTS2_), + GPIO_FN(MSIOF1_TSCK), \ + GPIO_FN(SCIFA2_SCK2), + GPIO_FN(MSIOF1_RXD), \ + GPIO_FN(SCIFA2_RXD2), + GPIO_FN(MSIOF1_RSCK), \ + GPIO_FN(SCIFA2_RTS2_), \ + GPIO_FN(VIO2_CLK2), \ + GPIO_FN(LCD2D20), + GPIO_FN(MSIOF1_RSYNC), \ + GPIO_FN(MFG1_IN2), \ + GPIO_FN(VIO2_VD2), \ + GPIO_FN(LCD2D21), + GPIO_FN(MSIOF1_MCK0), \ + GPIO_FN(PORT236_I2C_SDA2), + GPIO_FN(MSIOF1_MCK1), \ + GPIO_FN(PORT237_I2C_SCL2), + GPIO_FN(MSIOF1_SS1), \ + GPIO_FN(VIO2_FIELD2), \ + GPIO_FN(LCD2D22), + GPIO_FN(MSIOF1_SS2), \ + GPIO_FN(VIO2_HD2), \ + GPIO_FN(LCD2D23), + GPIO_FN(SCIFA6_TXD), + GPIO_FN(PORT241_IRDA_OUT), \ + GPIO_FN(PORT241_IROUT), \ + GPIO_FN(MFG4_OUT1), \ + GPIO_FN(TPU4TO0), + GPIO_FN(PORT242_IRDA_IN), \ + GPIO_FN(MFG4_IN2), + GPIO_FN(PORT243_IRDA_FIRSEL), \ + GPIO_FN(PORT243_VIO_CKO2), + GPIO_FN(PORT244_SCIFA5_CTS_), \ + GPIO_FN(MFG2_IN1), \ + GPIO_FN(PORT244_SCIFB_CTS_), \ + GPIO_FN(MSIOF2R_RXD), + GPIO_FN(PORT245_SCIFA5_RTS_), \ + GPIO_FN(MFG2_IN2), \ + GPIO_FN(PORT245_SCIFB_RTS_), \ + GPIO_FN(MSIOF2R_TXD), + GPIO_FN(PORT246_SCIFA5_RXD), \ + GPIO_FN(MFG1_OUT1), \ + GPIO_FN(PORT246_SCIFB_RXD), \ + GPIO_FN(TPU1TO0), + GPIO_FN(PORT247_SCIFA5_TXD), \ + GPIO_FN(MFG3_OUT2), \ + GPIO_FN(PORT247_SCIFB_TXD), \ + GPIO_FN(TPU3TO1), + GPIO_FN(PORT248_SCIFA5_SCK), \ + GPIO_FN(MFG2_OUT1), \ + GPIO_FN(PORT248_SCIFB_SCK), \ + GPIO_FN(TPU2TO0), \ + GPIO_FN(PORT248_I2C_SCL3), \ + GPIO_FN(MSIOF2R_TSCK), + GPIO_FN(PORT249_IROUT), \ + GPIO_FN(MFG4_IN1), \ + GPIO_FN(PORT249_I2C_SDA3), \ + GPIO_FN(MSIOF2R_TSYNC), + GPIO_FN(SDHICLK0), + GPIO_FN(SDHICD0), + GPIO_FN(SDHID0_0), + GPIO_FN(SDHID0_1), + GPIO_FN(SDHID0_2), + GPIO_FN(SDHID0_3), + GPIO_FN(SDHICMD0), + GPIO_FN(SDHIWP0), + GPIO_FN(SDHICLK1), + GPIO_FN(SDHID1_0), \ + GPIO_FN(TS_SPSYNC2), + GPIO_FN(SDHID1_1), \ + GPIO_FN(TS_SDAT2), + GPIO_FN(SDHID1_2), \ + GPIO_FN(TS_SDEN2), + GPIO_FN(SDHID1_3), \ + GPIO_FN(TS_SCK2), + GPIO_FN(SDHICMD1), + GPIO_FN(SDHICLK2), + GPIO_FN(SDHID2_0), \ + GPIO_FN(TS_SPSYNC4), + GPIO_FN(SDHID2_1), \ + GPIO_FN(TS_SDAT4), + GPIO_FN(SDHID2_2), \ + GPIO_FN(TS_SDEN4), + GPIO_FN(SDHID2_3), \ + GPIO_FN(TS_SCK4), + GPIO_FN(SDHICMD2), + GPIO_FN(MMCCLK0), + GPIO_FN(MMCD0_0), + GPIO_FN(MMCD0_1), + GPIO_FN(MMCD0_2), + GPIO_FN(MMCD0_3), + GPIO_FN(MMCD0_4), \ + GPIO_FN(TS_SPSYNC5), + GPIO_FN(MMCD0_5), \ + GPIO_FN(TS_SDAT5), + GPIO_FN(MMCD0_6), \ + GPIO_FN(TS_SDEN5), + GPIO_FN(MMCD0_7), \ + GPIO_FN(TS_SCK5), + GPIO_FN(MMCCMD0), + GPIO_FN(RESETOUTS_), \ + GPIO_FN(EXTAL2OUT), + GPIO_FN(MCP_WAIT__MCP_FRB), + GPIO_FN(MCP_CKO), \ + GPIO_FN(MMCCLK1), + GPIO_FN(MCP_D15_MCP_NAF15), + GPIO_FN(MCP_D14_MCP_NAF14), + GPIO_FN(MCP_D13_MCP_NAF13), + GPIO_FN(MCP_D12_MCP_NAF12), + GPIO_FN(MCP_D11_MCP_NAF11), + GPIO_FN(MCP_D10_MCP_NAF10), + GPIO_FN(MCP_D9_MCP_NAF9), + GPIO_FN(MCP_D8_MCP_NAF8), \ + GPIO_FN(MMCCMD1), + GPIO_FN(MCP_D7_MCP_NAF7), \ + GPIO_FN(MMCD1_7), + + GPIO_FN(MCP_D6_MCP_NAF6), \ + GPIO_FN(MMCD1_6), + GPIO_FN(MCP_D5_MCP_NAF5), \ + GPIO_FN(MMCD1_5), + GPIO_FN(MCP_D4_MCP_NAF4), \ + GPIO_FN(MMCD1_4), + GPIO_FN(MCP_D3_MCP_NAF3), \ + GPIO_FN(MMCD1_3), + GPIO_FN(MCP_D2_MCP_NAF2), \ + GPIO_FN(MMCD1_2), + GPIO_FN(MCP_D1_MCP_NAF1), \ + GPIO_FN(MMCD1_1), + GPIO_FN(MCP_D0_MCP_NAF0), \ + GPIO_FN(MMCD1_0), + GPIO_FN(MCP_NBRSTOUT_), + GPIO_FN(MCP_WE0__MCP_FWE), \ + GPIO_FN(MCP_RDWR_MCP_FWE), + + /* MSEL2 special cases */ + GPIO_FN(TSIF2_TS_XX1), + GPIO_FN(TSIF2_TS_XX2), + GPIO_FN(TSIF2_TS_XX3), + GPIO_FN(TSIF2_TS_XX4), + GPIO_FN(TSIF2_TS_XX5), + GPIO_FN(TSIF1_TS_XX1), + GPIO_FN(TSIF1_TS_XX2), + GPIO_FN(TSIF1_TS_XX3), + GPIO_FN(TSIF1_TS_XX4), + GPIO_FN(TSIF1_TS_XX5), + GPIO_FN(TSIF0_TS_XX1), + GPIO_FN(TSIF0_TS_XX2), + GPIO_FN(TSIF0_TS_XX3), + GPIO_FN(TSIF0_TS_XX4), + GPIO_FN(TSIF0_TS_XX5), + GPIO_FN(MST1_TS_XX1), + GPIO_FN(MST1_TS_XX2), + GPIO_FN(MST1_TS_XX3), + GPIO_FN(MST1_TS_XX4), + GPIO_FN(MST1_TS_XX5), + GPIO_FN(MST0_TS_XX1), + GPIO_FN(MST0_TS_XX2), + GPIO_FN(MST0_TS_XX3), + GPIO_FN(MST0_TS_XX4), + GPIO_FN(MST0_TS_XX5), + + /* MSEL3 special cases */ + GPIO_FN(SDHI0_VCCQ_MC0_ON), + GPIO_FN(SDHI0_VCCQ_MC0_OFF), + GPIO_FN(DEBUG_MON_VIO), + GPIO_FN(DEBUG_MON_LCDD), + GPIO_FN(LCDC_LCDC0), + GPIO_FN(LCDC_LCDC1), + + /* MSEL4 special cases */ + GPIO_FN(IRQ9_MEM_INT), + GPIO_FN(IRQ9_MCP_INT), + GPIO_FN(A11), + GPIO_FN(KEYOUT8), + GPIO_FN(TPU4TO3), + GPIO_FN(RESETA_N_PU_ON), + GPIO_FN(RESETA_N_PU_OFF), + GPIO_FN(EDBGREQ_PD), + GPIO_FN(EDBGREQ_PU), + + /* Functions with pull-ups */ + GPIO_FN(KEYIN0_PU), + GPIO_FN(KEYIN1_PU), + GPIO_FN(KEYIN2_PU), + GPIO_FN(KEYIN3_PU), + GPIO_FN(KEYIN4_PU), + GPIO_FN(KEYIN5_PU), + GPIO_FN(KEYIN6_PU), + GPIO_FN(KEYIN7_PU), + GPIO_FN(SDHICD0_PU), + GPIO_FN(SDHID0_0_PU), + GPIO_FN(SDHID0_1_PU), + GPIO_FN(SDHID0_2_PU), + GPIO_FN(SDHID0_3_PU), + GPIO_FN(SDHICMD0_PU), + GPIO_FN(SDHIWP0_PU), + GPIO_FN(SDHID1_0_PU), + GPIO_FN(SDHID1_1_PU), + GPIO_FN(SDHID1_2_PU), + GPIO_FN(SDHID1_3_PU), + GPIO_FN(SDHICMD1_PU), + GPIO_FN(SDHID2_0_PU), + GPIO_FN(SDHID2_1_PU), + GPIO_FN(SDHID2_2_PU), + GPIO_FN(SDHID2_3_PU), + GPIO_FN(SDHICMD2_PU), + GPIO_FN(MMCCMD0_PU), + GPIO_FN(MMCCMD1_PU), + GPIO_FN(MMCD0_0_PU), + GPIO_FN(MMCD0_1_PU), + GPIO_FN(MMCD0_2_PU), + GPIO_FN(MMCD0_3_PU), + GPIO_FN(MMCD0_4_PU), + GPIO_FN(MMCD0_5_PU), + GPIO_FN(MMCD0_6_PU), + GPIO_FN(MMCD0_7_PU), + GPIO_FN(FSIACK_PU), + GPIO_FN(FSIAILR_PU), + GPIO_FN(FSIAIBT_PU), + GPIO_FN(FSIAISLD_PU), +}; + +static struct pinmux_cfg_reg pinmux_config_regs[] = { + PORTCR(0, 0xe6050000), /* PORT0CR */ + PORTCR(1, 0xe6050001), /* PORT1CR */ + PORTCR(2, 0xe6050002), /* PORT2CR */ + PORTCR(3, 0xe6050003), /* PORT3CR */ + PORTCR(4, 0xe6050004), /* PORT4CR */ + PORTCR(5, 0xe6050005), /* PORT5CR */ + PORTCR(6, 0xe6050006), /* PORT6CR */ + PORTCR(7, 0xe6050007), /* PORT7CR */ + PORTCR(8, 0xe6050008), /* PORT8CR */ + PORTCR(9, 0xe6050009), /* PORT9CR */ + + PORTCR(10, 0xe605000a), /* PORT10CR */ + PORTCR(11, 0xe605000b), /* PORT11CR */ + PORTCR(12, 0xe605000c), /* PORT12CR */ + PORTCR(13, 0xe605000d), /* PORT13CR */ + PORTCR(14, 0xe605000e), /* PORT14CR */ + PORTCR(15, 0xe605000f), /* PORT15CR */ + PORTCR(16, 0xe6050010), /* PORT16CR */ + PORTCR(17, 0xe6050011), /* PORT17CR */ + PORTCR(18, 0xe6050012), /* PORT18CR */ + PORTCR(19, 0xe6050013), /* PORT19CR */ + + PORTCR(20, 0xe6050014), /* PORT20CR */ + PORTCR(21, 0xe6050015), /* PORT21CR */ + PORTCR(22, 0xe6050016), /* PORT22CR */ + PORTCR(23, 0xe6050017), /* PORT23CR */ + PORTCR(24, 0xe6050018), /* PORT24CR */ + PORTCR(25, 0xe6050019), /* PORT25CR */ + PORTCR(26, 0xe605001a), /* PORT26CR */ + PORTCR(27, 0xe605001b), /* PORT27CR */ + PORTCR(28, 0xe605001c), /* PORT28CR */ + PORTCR(29, 0xe605001d), /* PORT29CR */ + + PORTCR(30, 0xe605001e), /* PORT30CR */ + PORTCR(31, 0xe605001f), /* PORT31CR */ + PORTCR(32, 0xe6051020), /* PORT32CR */ + PORTCR(33, 0xe6051021), /* PORT33CR */ + PORTCR(34, 0xe6051022), /* PORT34CR */ + PORTCR(35, 0xe6051023), /* PORT35CR */ + PORTCR(36, 0xe6051024), /* PORT36CR */ + PORTCR(37, 0xe6051025), /* PORT37CR */ + PORTCR(38, 0xe6051026), /* PORT38CR */ + PORTCR(39, 0xe6051027), /* PORT39CR */ + + PORTCR(40, 0xe6051028), /* PORT40CR */ + PORTCR(41, 0xe6051029), /* PORT41CR */ + PORTCR(42, 0xe605102a), /* PORT42CR */ + PORTCR(43, 0xe605102b), /* PORT43CR */ + PORTCR(44, 0xe605102c), /* PORT44CR */ + PORTCR(45, 0xe605102d), /* PORT45CR */ + PORTCR(46, 0xe605102e), /* PORT46CR */ + PORTCR(47, 0xe605102f), /* PORT47CR */ + PORTCR(48, 0xe6051030), /* PORT48CR */ + PORTCR(49, 0xe6051031), /* PORT49CR */ + + PORTCR(50, 0xe6051032), /* PORT50CR */ + PORTCR(51, 0xe6051033), /* PORT51CR */ + PORTCR(52, 0xe6051034), /* PORT52CR */ + PORTCR(53, 0xe6051035), /* PORT53CR */ + PORTCR(54, 0xe6051036), /* PORT54CR */ + PORTCR(55, 0xe6051037), /* PORT55CR */ + PORTCR(56, 0xe6051038), /* PORT56CR */ + PORTCR(57, 0xe6051039), /* PORT57CR */ + PORTCR(58, 0xe605103a), /* PORT58CR */ + PORTCR(59, 0xe605103b), /* PORT59CR */ + + PORTCR(60, 0xe605103c), /* PORT60CR */ + PORTCR(61, 0xe605103d), /* PORT61CR */ + PORTCR(62, 0xe605103e), /* PORT62CR */ + PORTCR(63, 0xe605103f), /* PORT63CR */ + PORTCR(64, 0xe6051040), /* PORT64CR */ + PORTCR(65, 0xe6051041), /* PORT65CR */ + PORTCR(66, 0xe6051042), /* PORT66CR */ + PORTCR(67, 0xe6051043), /* PORT67CR */ + PORTCR(68, 0xe6051044), /* PORT68CR */ + PORTCR(69, 0xe6051045), /* PORT69CR */ + + PORTCR(70, 0xe6051046), /* PORT70CR */ + PORTCR(71, 0xe6051047), /* PORT71CR */ + PORTCR(72, 0xe6051048), /* PORT72CR */ + PORTCR(73, 0xe6051049), /* PORT73CR */ + PORTCR(74, 0xe605104a), /* PORT74CR */ + PORTCR(75, 0xe605104b), /* PORT75CR */ + PORTCR(76, 0xe605104c), /* PORT76CR */ + PORTCR(77, 0xe605104d), /* PORT77CR */ + PORTCR(78, 0xe605104e), /* PORT78CR */ + PORTCR(79, 0xe605104f), /* PORT79CR */ + + PORTCR(80, 0xe6051050), /* PORT80CR */ + PORTCR(81, 0xe6051051), /* PORT81CR */ + PORTCR(82, 0xe6051052), /* PORT82CR */ + PORTCR(83, 0xe6051053), /* PORT83CR */ + PORTCR(84, 0xe6051054), /* PORT84CR */ + PORTCR(85, 0xe6051055), /* PORT85CR */ + PORTCR(86, 0xe6051056), /* PORT86CR */ + PORTCR(87, 0xe6051057), /* PORT87CR */ + PORTCR(88, 0xe6051058), /* PORT88CR */ + PORTCR(89, 0xe6051059), /* PORT89CR */ + + PORTCR(90, 0xe605105a), /* PORT90CR */ + PORTCR(91, 0xe605105b), /* PORT91CR */ + PORTCR(92, 0xe605105c), /* PORT92CR */ + PORTCR(93, 0xe605105d), /* PORT93CR */ + PORTCR(94, 0xe605105e), /* PORT94CR */ + PORTCR(95, 0xe605105f), /* PORT95CR */ + PORTCR(96, 0xe6052060), /* PORT96CR */ + PORTCR(97, 0xe6052061), /* PORT97CR */ + PORTCR(98, 0xe6052062), /* PORT98CR */ + PORTCR(99, 0xe6052063), /* PORT99CR */ + + PORTCR(100, 0xe6052064), /* PORT100CR */ + PORTCR(101, 0xe6052065), /* PORT101CR */ + PORTCR(102, 0xe6052066), /* PORT102CR */ + PORTCR(103, 0xe6052067), /* PORT103CR */ + PORTCR(104, 0xe6052068), /* PORT104CR */ + PORTCR(105, 0xe6052069), /* PORT105CR */ + PORTCR(106, 0xe605206a), /* PORT106CR */ + PORTCR(107, 0xe605206b), /* PORT107CR */ + PORTCR(108, 0xe605206c), /* PORT108CR */ + PORTCR(109, 0xe605206d), /* PORT109CR */ + + PORTCR(110, 0xe605206e), /* PORT110CR */ + PORTCR(111, 0xe605206f), /* PORT111CR */ + PORTCR(112, 0xe6052070), /* PORT112CR */ + PORTCR(113, 0xe6052071), /* PORT113CR */ + PORTCR(114, 0xe6052072), /* PORT114CR */ + PORTCR(115, 0xe6052073), /* PORT115CR */ + PORTCR(116, 0xe6052074), /* PORT116CR */ + PORTCR(117, 0xe6052075), /* PORT117CR */ + PORTCR(118, 0xe6052076), /* PORT118CR */ + + PORTCR(128, 0xe6052080), /* PORT128CR */ + PORTCR(129, 0xe6052081), /* PORT129CR */ + + PORTCR(130, 0xe6052082), /* PORT130CR */ + PORTCR(131, 0xe6052083), /* PORT131CR */ + PORTCR(132, 0xe6052084), /* PORT132CR */ + PORTCR(133, 0xe6052085), /* PORT133CR */ + PORTCR(134, 0xe6052086), /* PORT134CR */ + PORTCR(135, 0xe6052087), /* PORT135CR */ + PORTCR(136, 0xe6052088), /* PORT136CR */ + PORTCR(137, 0xe6052089), /* PORT137CR */ + PORTCR(138, 0xe605208a), /* PORT138CR */ + PORTCR(139, 0xe605208b), /* PORT139CR */ + + PORTCR(140, 0xe605208c), /* PORT140CR */ + PORTCR(141, 0xe605208d), /* PORT141CR */ + PORTCR(142, 0xe605208e), /* PORT142CR */ + PORTCR(143, 0xe605208f), /* PORT143CR */ + PORTCR(144, 0xe6052090), /* PORT144CR */ + PORTCR(145, 0xe6052091), /* PORT145CR */ + PORTCR(146, 0xe6052092), /* PORT146CR */ + PORTCR(147, 0xe6052093), /* PORT147CR */ + PORTCR(148, 0xe6052094), /* PORT148CR */ + PORTCR(149, 0xe6052095), /* PORT149CR */ + + PORTCR(150, 0xe6052096), /* PORT150CR */ + PORTCR(151, 0xe6052097), /* PORT151CR */ + PORTCR(152, 0xe6052098), /* PORT152CR */ + PORTCR(153, 0xe6052099), /* PORT153CR */ + PORTCR(154, 0xe605209a), /* PORT154CR */ + PORTCR(155, 0xe605209b), /* PORT155CR */ + PORTCR(156, 0xe605209c), /* PORT156CR */ + PORTCR(157, 0xe605209d), /* PORT157CR */ + PORTCR(158, 0xe605209e), /* PORT158CR */ + PORTCR(159, 0xe605209f), /* PORT159CR */ + + PORTCR(160, 0xe60520a0), /* PORT160CR */ + PORTCR(161, 0xe60520a1), /* PORT161CR */ + PORTCR(162, 0xe60520a2), /* PORT162CR */ + PORTCR(163, 0xe60520a3), /* PORT163CR */ + PORTCR(164, 0xe60520a4), /* PORT164CR */ + + PORTCR(192, 0xe60520c0), /* PORT192CR */ + PORTCR(193, 0xe60520c1), /* PORT193CR */ + PORTCR(194, 0xe60520c2), /* PORT194CR */ + PORTCR(195, 0xe60520c3), /* PORT195CR */ + PORTCR(196, 0xe60520c4), /* PORT196CR */ + PORTCR(197, 0xe60520c5), /* PORT197CR */ + PORTCR(198, 0xe60520c6), /* PORT198CR */ + PORTCR(199, 0xe60520c7), /* PORT199CR */ + + PORTCR(200, 0xe60520c8), /* PORT200CR */ + PORTCR(201, 0xe60520c9), /* PORT201CR */ + PORTCR(202, 0xe60520ca), /* PORT202CR */ + PORTCR(203, 0xe60520cb), /* PORT203CR */ + PORTCR(204, 0xe60520cc), /* PORT204CR */ + PORTCR(205, 0xe60520cd), /* PORT205CR */ + PORTCR(206, 0xe60520ce), /* PORT206CR */ + PORTCR(207, 0xe60520cf), /* PORT207CR */ + PORTCR(208, 0xe60520d0), /* PORT208CR */ + PORTCR(209, 0xe60520d1), /* PORT209CR */ + + PORTCR(210, 0xe60520d2), /* PORT210CR */ + PORTCR(211, 0xe60520d3), /* PORT211CR */ + PORTCR(212, 0xe60520d4), /* PORT212CR */ + PORTCR(213, 0xe60520d5), /* PORT213CR */ + PORTCR(214, 0xe60520d6), /* PORT214CR */ + PORTCR(215, 0xe60520d7), /* PORT215CR */ + PORTCR(216, 0xe60520d8), /* PORT216CR */ + PORTCR(217, 0xe60520d9), /* PORT217CR */ + PORTCR(218, 0xe60520da), /* PORT218CR */ + PORTCR(219, 0xe60520db), /* PORT219CR */ + + PORTCR(220, 0xe60520dc), /* PORT220CR */ + PORTCR(221, 0xe60520dd), /* PORT221CR */ + PORTCR(222, 0xe60520de), /* PORT222CR */ + PORTCR(223, 0xe60520df), /* PORT223CR */ + PORTCR(224, 0xe60530e0), /* PORT224CR */ + PORTCR(225, 0xe60530e1), /* PORT225CR */ + PORTCR(226, 0xe60530e2), /* PORT226CR */ + PORTCR(227, 0xe60530e3), /* PORT227CR */ + PORTCR(228, 0xe60530e4), /* PORT228CR */ + PORTCR(229, 0xe60530e5), /* PORT229CR */ + + PORTCR(230, 0xe60530e6), /* PORT230CR */ + PORTCR(231, 0xe60530e7), /* PORT231CR */ + PORTCR(232, 0xe60530e8), /* PORT232CR */ + PORTCR(233, 0xe60530e9), /* PORT233CR */ + PORTCR(234, 0xe60530ea), /* PORT234CR */ + PORTCR(235, 0xe60530eb), /* PORT235CR */ + PORTCR(236, 0xe60530ec), /* PORT236CR */ + PORTCR(237, 0xe60530ed), /* PORT237CR */ + PORTCR(238, 0xe60530ee), /* PORT238CR */ + PORTCR(239, 0xe60530ef), /* PORT239CR */ + + PORTCR(240, 0xe60530f0), /* PORT240CR */ + PORTCR(241, 0xe60530f1), /* PORT241CR */ + PORTCR(242, 0xe60530f2), /* PORT242CR */ + PORTCR(243, 0xe60530f3), /* PORT243CR */ + PORTCR(244, 0xe60530f4), /* PORT244CR */ + PORTCR(245, 0xe60530f5), /* PORT245CR */ + PORTCR(246, 0xe60530f6), /* PORT246CR */ + PORTCR(247, 0xe60530f7), /* PORT247CR */ + PORTCR(248, 0xe60530f8), /* PORT248CR */ + PORTCR(249, 0xe60530f9), /* PORT249CR */ + + PORTCR(250, 0xe60530fa), /* PORT250CR */ + PORTCR(251, 0xe60530fb), /* PORT251CR */ + PORTCR(252, 0xe60530fc), /* PORT252CR */ + PORTCR(253, 0xe60530fd), /* PORT253CR */ + PORTCR(254, 0xe60530fe), /* PORT254CR */ + PORTCR(255, 0xe60530ff), /* PORT255CR */ + PORTCR(256, 0xe6053100), /* PORT256CR */ + PORTCR(257, 0xe6053101), /* PORT257CR */ + PORTCR(258, 0xe6053102), /* PORT258CR */ + PORTCR(259, 0xe6053103), /* PORT259CR */ + + PORTCR(260, 0xe6053104), /* PORT260CR */ + PORTCR(261, 0xe6053105), /* PORT261CR */ + PORTCR(262, 0xe6053106), /* PORT262CR */ + PORTCR(263, 0xe6053107), /* PORT263CR */ + PORTCR(264, 0xe6053108), /* PORT264CR */ + PORTCR(265, 0xe6053109), /* PORT265CR */ + PORTCR(266, 0xe605310a), /* PORT266CR */ + PORTCR(267, 0xe605310b), /* PORT267CR */ + PORTCR(268, 0xe605310c), /* PORT268CR */ + PORTCR(269, 0xe605310d), /* PORT269CR */ + + PORTCR(270, 0xe605310e), /* PORT270CR */ + PORTCR(271, 0xe605310f), /* PORT271CR */ + PORTCR(272, 0xe6053110), /* PORT272CR */ + PORTCR(273, 0xe6053111), /* PORT273CR */ + PORTCR(274, 0xe6053112), /* PORT274CR */ + PORTCR(275, 0xe6053113), /* PORT275CR */ + PORTCR(276, 0xe6053114), /* PORT276CR */ + PORTCR(277, 0xe6053115), /* PORT277CR */ + PORTCR(278, 0xe6053116), /* PORT278CR */ + PORTCR(279, 0xe6053117), /* PORT279CR */ + + PORTCR(280, 0xe6053118), /* PORT280CR */ + PORTCR(281, 0xe6053119), /* PORT281CR */ + PORTCR(282, 0xe605311a), /* PORT282CR */ + + PORTCR(288, 0xe6052120), /* PORT288CR */ + PORTCR(289, 0xe6052121), /* PORT289CR */ + + PORTCR(290, 0xe6052122), /* PORT290CR */ + PORTCR(291, 0xe6052123), /* PORT291CR */ + PORTCR(292, 0xe6052124), /* PORT292CR */ + PORTCR(293, 0xe6052125), /* PORT293CR */ + PORTCR(294, 0xe6052126), /* PORT294CR */ + PORTCR(295, 0xe6052127), /* PORT295CR */ + PORTCR(296, 0xe6052128), /* PORT296CR */ + PORTCR(297, 0xe6052129), /* PORT297CR */ + PORTCR(298, 0xe605212a), /* PORT298CR */ + PORTCR(299, 0xe605212b), /* PORT299CR */ + + PORTCR(300, 0xe605212c), /* PORT300CR */ + PORTCR(301, 0xe605212d), /* PORT301CR */ + PORTCR(302, 0xe605212e), /* PORT302CR */ + PORTCR(303, 0xe605212f), /* PORT303CR */ + PORTCR(304, 0xe6052130), /* PORT304CR */ + PORTCR(305, 0xe6052131), /* PORT305CR */ + PORTCR(306, 0xe6052132), /* PORT306CR */ + PORTCR(307, 0xe6052133), /* PORT307CR */ + PORTCR(308, 0xe6052134), /* PORT308CR */ + PORTCR(309, 0xe6052135), /* PORT309CR */ + + { PINMUX_CFG_REG("MSEL2CR", 0xe605801c, 32, 1) { + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + MSEL2CR_MSEL19_0, MSEL2CR_MSEL19_1, + MSEL2CR_MSEL18_0, MSEL2CR_MSEL18_1, + MSEL2CR_MSEL17_0, MSEL2CR_MSEL17_1, + MSEL2CR_MSEL16_0, MSEL2CR_MSEL16_1, + 0, 0, + MSEL2CR_MSEL14_0, MSEL2CR_MSEL14_1, + MSEL2CR_MSEL13_0, MSEL2CR_MSEL13_1, + MSEL2CR_MSEL12_0, MSEL2CR_MSEL12_1, + MSEL2CR_MSEL11_0, MSEL2CR_MSEL11_1, + MSEL2CR_MSEL10_0, MSEL2CR_MSEL10_1, + MSEL2CR_MSEL9_0, MSEL2CR_MSEL9_1, + MSEL2CR_MSEL8_0, MSEL2CR_MSEL8_1, + MSEL2CR_MSEL7_0, MSEL2CR_MSEL7_1, + MSEL2CR_MSEL6_0, MSEL2CR_MSEL6_1, + MSEL2CR_MSEL5_0, MSEL2CR_MSEL5_1, + MSEL2CR_MSEL4_0, MSEL2CR_MSEL4_1, + MSEL2CR_MSEL3_0, MSEL2CR_MSEL3_1, + MSEL2CR_MSEL2_0, MSEL2CR_MSEL2_1, + MSEL2CR_MSEL1_0, MSEL2CR_MSEL1_1, + MSEL2CR_MSEL0_0, MSEL2CR_MSEL0_1, + } + }, + { PINMUX_CFG_REG("MSEL3CR", 0xe6058020, 32, 1) { + 0, 0, + 0, 0, + 0, 0, + MSEL3CR_MSEL28_0, MSEL3CR_MSEL28_1, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + MSEL3CR_MSEL15_0, MSEL3CR_MSEL15_1, + 0, 0, + 0, 0, + 0, 0, + MSEL3CR_MSEL11_0, MSEL3CR_MSEL11_1, + 0, 0, + MSEL3CR_MSEL9_0, MSEL3CR_MSEL9_1, + 0, 0, + 0, 0, + MSEL3CR_MSEL6_0, MSEL3CR_MSEL6_1, + 0, 0, + 0, 0, + 0, 0, + MSEL3CR_MSEL2_0, MSEL3CR_MSEL2_1, + 0, 0, + 0, 0, + } + }, + { PINMUX_CFG_REG("MSEL4CR", 0xe6058024, 32, 1) { + 0, 0, + 0, 0, + MSEL4CR_MSEL29_0, MSEL4CR_MSEL29_1, + 0, 0, + MSEL4CR_MSEL27_0, MSEL4CR_MSEL27_1, + MSEL4CR_MSEL26_0, MSEL4CR_MSEL26_1, + 0, 0, + 0, 0, + 0, 0, + MSEL4CR_MSEL22_0, MSEL4CR_MSEL22_1, + MSEL4CR_MSEL21_0, MSEL4CR_MSEL21_1, + MSEL4CR_MSEL20_0, MSEL4CR_MSEL20_1, + MSEL4CR_MSEL19_0, MSEL4CR_MSEL19_1, + 0, 0, + 0, 0, + 0, 0, + MSEL4CR_MSEL15_0, MSEL4CR_MSEL15_1, + 0, 0, + MSEL4CR_MSEL13_0, MSEL4CR_MSEL13_1, + MSEL4CR_MSEL12_0, MSEL4CR_MSEL12_1, + MSEL4CR_MSEL11_0, MSEL4CR_MSEL11_1, + MSEL4CR_MSEL10_0, MSEL4CR_MSEL10_1, + MSEL4CR_MSEL9_0, MSEL4CR_MSEL9_1, + MSEL4CR_MSEL8_0, MSEL4CR_MSEL8_1, + MSEL4CR_MSEL7_0, MSEL4CR_MSEL7_1, + 0, 0, + 0, 0, + MSEL4CR_MSEL4_0, MSEL4CR_MSEL4_1, + 0, 0, + 0, 0, + MSEL4CR_MSEL1_0, MSEL4CR_MSEL1_1, + 0, 0, + } + }, + { }, +}; + +static struct pinmux_data_reg pinmux_data_regs[] = { + { PINMUX_DATA_REG("PORTL031_000DR", 0xe6054000, 32) { + PORT31_DATA, PORT30_DATA, PORT29_DATA, PORT28_DATA, + PORT27_DATA, PORT26_DATA, PORT25_DATA, PORT24_DATA, + PORT23_DATA, PORT22_DATA, PORT21_DATA, PORT20_DATA, + PORT19_DATA, PORT18_DATA, PORT17_DATA, PORT16_DATA, + PORT15_DATA, PORT14_DATA, PORT13_DATA, PORT12_DATA, + PORT11_DATA, PORT10_DATA, PORT9_DATA, PORT8_DATA, + PORT7_DATA, PORT6_DATA, PORT5_DATA, PORT4_DATA, + PORT3_DATA, PORT2_DATA, PORT1_DATA, PORT0_DATA } + }, + { PINMUX_DATA_REG("PORTD063_032DR", 0xe6055000, 32) { + PORT63_DATA, PORT62_DATA, PORT61_DATA, PORT60_DATA, + PORT59_DATA, PORT58_DATA, PORT57_DATA, PORT56_DATA, + PORT55_DATA, PORT54_DATA, PORT53_DATA, PORT52_DATA, + PORT51_DATA, PORT50_DATA, PORT49_DATA, PORT48_DATA, + PORT47_DATA, PORT46_DATA, PORT45_DATA, PORT44_DATA, + PORT43_DATA, PORT42_DATA, PORT41_DATA, PORT40_DATA, + PORT39_DATA, PORT38_DATA, PORT37_DATA, PORT36_DATA, + PORT35_DATA, PORT34_DATA, PORT33_DATA, PORT32_DATA } + }, + { PINMUX_DATA_REG("PORTD095_064DR", 0xe6055004, 32) { + PORT95_DATA, PORT94_DATA, PORT93_DATA, PORT92_DATA, + PORT91_DATA, PORT90_DATA, PORT89_DATA, PORT88_DATA, + PORT87_DATA, PORT86_DATA, PORT85_DATA, PORT84_DATA, + PORT83_DATA, PORT82_DATA, PORT81_DATA, PORT80_DATA, + PORT79_DATA, PORT78_DATA, PORT77_DATA, PORT76_DATA, + PORT75_DATA, PORT74_DATA, PORT73_DATA, PORT72_DATA, + PORT71_DATA, PORT70_DATA, PORT69_DATA, PORT68_DATA, + PORT67_DATA, PORT66_DATA, PORT65_DATA, PORT64_DATA } + }, + { PINMUX_DATA_REG("PORTR127_096DR", 0xe6056000, 32) { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, PORT118_DATA, PORT117_DATA, PORT116_DATA, + PORT115_DATA, PORT114_DATA, PORT113_DATA, PORT112_DATA, + PORT111_DATA, PORT110_DATA, PORT109_DATA, PORT108_DATA, + PORT107_DATA, PORT106_DATA, PORT105_DATA, PORT104_DATA, + PORT103_DATA, PORT102_DATA, PORT101_DATA, PORT100_DATA, + PORT99_DATA, PORT98_DATA, PORT97_DATA, PORT96_DATA } + }, + { PINMUX_DATA_REG("PORTR159_128DR", 0xe6056004, 32) { + PORT159_DATA, PORT158_DATA, PORT157_DATA, PORT156_DATA, + PORT155_DATA, PORT154_DATA, PORT153_DATA, PORT152_DATA, + PORT151_DATA, PORT150_DATA, PORT149_DATA, PORT148_DATA, + PORT147_DATA, PORT146_DATA, PORT145_DATA, PORT144_DATA, + PORT143_DATA, PORT142_DATA, PORT141_DATA, PORT140_DATA, + PORT139_DATA, PORT138_DATA, PORT137_DATA, PORT136_DATA, + PORT135_DATA, PORT134_DATA, PORT133_DATA, PORT132_DATA, + PORT131_DATA, PORT130_DATA, PORT129_DATA, PORT128_DATA } + }, + { PINMUX_DATA_REG("PORTR191_160DR", 0xe6056008, 32) { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, PORT164_DATA, + PORT163_DATA, PORT162_DATA, PORT161_DATA, PORT160_DATA } + }, + { PINMUX_DATA_REG("PORTR223_192DR", 0xe605600C, 32) { + PORT223_DATA, PORT222_DATA, PORT221_DATA, PORT220_DATA, + PORT219_DATA, PORT218_DATA, PORT217_DATA, PORT216_DATA, + PORT215_DATA, PORT214_DATA, PORT213_DATA, PORT212_DATA, + PORT211_DATA, PORT210_DATA, PORT209_DATA, PORT208_DATA, + PORT207_DATA, PORT206_DATA, PORT205_DATA, PORT204_DATA, + PORT203_DATA, PORT202_DATA, PORT201_DATA, PORT200_DATA, + PORT199_DATA, PORT198_DATA, PORT197_DATA, PORT196_DATA, + PORT195_DATA, PORT194_DATA, PORT193_DATA, PORT192_DATA } + }, + { PINMUX_DATA_REG("PORTU255_224DR", 0xe6057000, 32) { + PORT255_DATA, PORT254_DATA, PORT253_DATA, PORT252_DATA, + PORT251_DATA, PORT250_DATA, PORT249_DATA, PORT248_DATA, + PORT247_DATA, PORT246_DATA, PORT245_DATA, PORT244_DATA, + PORT243_DATA, PORT242_DATA, PORT241_DATA, PORT240_DATA, + PORT239_DATA, PORT238_DATA, PORT237_DATA, PORT236_DATA, + PORT235_DATA, PORT234_DATA, PORT233_DATA, PORT232_DATA, + PORT231_DATA, PORT230_DATA, PORT229_DATA, PORT228_DATA, + PORT227_DATA, PORT226_DATA, PORT225_DATA, PORT224_DATA } + }, + { PINMUX_DATA_REG("PORTU287_256DR", 0xe6057004, 32) { + 0, 0, 0, 0, + 0, PORT282_DATA, PORT281_DATA, PORT280_DATA, + PORT279_DATA, PORT278_DATA, PORT277_DATA, PORT276_DATA, + PORT275_DATA, PORT274_DATA, PORT273_DATA, PORT272_DATA, + PORT271_DATA, PORT270_DATA, PORT269_DATA, PORT268_DATA, + PORT267_DATA, PORT266_DATA, PORT265_DATA, PORT264_DATA, + PORT263_DATA, PORT262_DATA, PORT261_DATA, PORT260_DATA, + PORT259_DATA, PORT258_DATA, PORT257_DATA, PORT256_DATA } + }, + { PINMUX_DATA_REG("PORTR319_288DR", 0xe6056010, 32) { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, PORT309_DATA, PORT308_DATA, + PORT307_DATA, PORT306_DATA, PORT305_DATA, PORT304_DATA, + PORT303_DATA, PORT302_DATA, PORT301_DATA, PORT300_DATA, + PORT299_DATA, PORT298_DATA, PORT297_DATA, PORT296_DATA, + PORT295_DATA, PORT294_DATA, PORT293_DATA, PORT292_DATA, + PORT291_DATA, PORT290_DATA, PORT289_DATA, PORT288_DATA } + }, + { }, +}; + +#if 0 +/* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */ +#define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5)) +#define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5)) +#else +#define EXT_IRQ16L(n) (n) +#define EXT_IRQ16H(n) (n) +#endif + +static struct pinmux_irq pinmux_irqs[] = { + PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0), + PINMUX_IRQ(EXT_IRQ16L(1), PORT10_FN0), + PINMUX_IRQ(EXT_IRQ16L(0), PORT11_FN0), + PINMUX_IRQ(EXT_IRQ16H(18), PORT13_FN0), + PINMUX_IRQ(EXT_IRQ16H(20), PORT14_FN0), + PINMUX_IRQ(EXT_IRQ16H(21), PORT15_FN0), + PINMUX_IRQ(EXT_IRQ16H(31), PORT26_FN0), + PINMUX_IRQ(EXT_IRQ16H(30), PORT27_FN0), + PINMUX_IRQ(EXT_IRQ16H(29), PORT28_FN0), + PINMUX_IRQ(EXT_IRQ16H(22), PORT40_FN0), + PINMUX_IRQ(EXT_IRQ16H(23), PORT53_FN0), + PINMUX_IRQ(EXT_IRQ16L(10), PORT54_FN0), + PINMUX_IRQ(EXT_IRQ16L(9), PORT56_FN0), + PINMUX_IRQ(EXT_IRQ16H(26), PORT115_FN0), + PINMUX_IRQ(EXT_IRQ16H(27), PORT116_FN0), + PINMUX_IRQ(EXT_IRQ16H(28), PORT117_FN0), + PINMUX_IRQ(EXT_IRQ16H(24), PORT118_FN0), + PINMUX_IRQ(EXT_IRQ16L(6), PORT147_FN0), + PINMUX_IRQ(EXT_IRQ16L(2), PORT149_FN0), + PINMUX_IRQ(EXT_IRQ16L(7), PORT150_FN0), + PINMUX_IRQ(EXT_IRQ16L(12), PORT156_FN0), + PINMUX_IRQ(EXT_IRQ16L(4), PORT159_FN0), + PINMUX_IRQ(EXT_IRQ16H(25), PORT164_FN0), + PINMUX_IRQ(EXT_IRQ16L(8), PORT223_FN0), + PINMUX_IRQ(EXT_IRQ16L(3), PORT224_FN0), + PINMUX_IRQ(EXT_IRQ16L(5), PORT227_FN0), + PINMUX_IRQ(EXT_IRQ16H(17), PORT234_FN0), + PINMUX_IRQ(EXT_IRQ16L(11), PORT238_FN0), + PINMUX_IRQ(EXT_IRQ16L(13), PORT239_FN0), + PINMUX_IRQ(EXT_IRQ16H(16), PORT249_FN0), + PINMUX_IRQ(EXT_IRQ16L(14), PORT251_FN0), + PINMUX_IRQ(EXT_IRQ16L(9), PORT308_FN0), +}; + +static struct pinmux_info sh73a0_pinmux_info = { + .name = "sh73a0_pfc", + .reserved_id = PINMUX_RESERVED, + .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END }, + .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END }, + .input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END }, + .input_pd = { PINMUX_INPUT_PULLDOWN_BEGIN, PINMUX_INPUT_PULLDOWN_END }, + .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END }, + .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END }, + .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, + + .first_gpio = GPIO_PORT0, + .last_gpio = GPIO_FN_FSIAISLD_PU, + + .gpios = pinmux_gpios, + .cfg_regs = pinmux_config_regs, + .data_regs = pinmux_data_regs, + + .gpio_data = pinmux_data, + .gpio_data_size = ARRAY_SIZE(pinmux_data), + + .gpio_irq = pinmux_irqs, + .gpio_irq_size = ARRAY_SIZE(pinmux_irqs), +}; + +void sh73a0_pinmux_init(void) +{ + register_pinmux(&sh73a0_pinmux_info); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/timer.c new file mode 100644 index 000000000..04700e7d3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/rmobile/timer.c @@ -0,0 +1,85 @@ +/* + * (C) Copyright 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> + * (C) Copyright 2012 Renesas Solutions Corp. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/arch-armv7/globaltimer.h> +#include <asm/arch/rmobile.h> + +static struct globaltimer *global_timer = \ + (struct globaltimer *)GLOBAL_TIMER_BASE_ADDR; + +#define CLK2MHZ(clk) (clk / 1000 / 1000) +static u64 get_cpu_global_timer(void) +{ + u32 low, high; + u64 timer; + + u32 old = readl(&global_timer->cnt_h); + while (1) { + low = readl(&global_timer->cnt_l); + high = readl(&global_timer->cnt_h); + if (old == high) + break; + else + old = high; + } + + timer = high; + return (u64)((timer << 32) | low); +} + +static u64 get_time_us(void) +{ + u64 timer = get_cpu_global_timer(); + + timer = ((timer << 2) + (CLK2MHZ(CONFIG_SYS_CPU_CLK) >> 1)); + do_div(timer, CLK2MHZ(CONFIG_SYS_CPU_CLK)); + return timer; +} + +static ulong get_time_ms(void) +{ + u64 us = get_time_us(); + + do_div(us, 1000); + return us; +} + +int timer_init(void) +{ + writel(0x01, &global_timer->ctl); + return 0; +} + +void __udelay(unsigned long usec) +{ + u64 start, current; + u64 wait; + + start = get_cpu_global_timer(); + wait = (u64)((usec * CLK2MHZ(CONFIG_SYS_CPU_CLK)) >> 2); + do { + current = get_cpu_global_timer(); + } while ((current - start) < wait); +} + +ulong get_timer(ulong base) +{ + return get_time_ms() - base; +} + +unsigned long long get_ticks(void) +{ + return get_cpu_global_timer(); +} + +ulong get_tbclk(void) +{ + return (ulong)(CONFIG_SYS_CPU_CLK >> 2); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/Makefile new file mode 100644 index 000000000..f571d8a0e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/Makefile @@ -0,0 +1,13 @@ +# +# Copyright (C) 2009 Samsung Electronics +# Minkyu Kang <mk7.kang@samsung.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += cpu_info.o +ifndef CONFIG_SPL_BUILD +obj-y += timer.o +obj-y += sromc.o +obj-$(CONFIG_PWM) += pwm.o +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/cpu_info.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/cpu_info.c new file mode 100644 index 000000000..a8d91e769 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/cpu_info.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang <mk7.kang@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clk.h> + +/* Default is s5pc100 */ +unsigned int s5p_cpu_id = 0xC100; +/* Default is EVT1 */ +unsigned int s5p_cpu_rev = 1; + +#ifdef CONFIG_ARCH_CPU_INIT +int arch_cpu_init(void) +{ + s5p_set_cpu_id(); + + return 0; +} +#endif + +u32 get_device_type(void) +{ + return s5p_cpu_id; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ + char buf[32]; + + printf("CPU:\t%s%X@%sMHz\n", + s5p_get_cpu_name(), s5p_cpu_id, + strmhz(buf, get_arm_clk())); + + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/pwm.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/pwm.c new file mode 100644 index 000000000..b8805c8d4 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/pwm.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2011 Samsung Electronics + * + * Donghwa Lee <dh09.lee@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <pwm.h> +#include <asm/io.h> +#include <asm/arch/pwm.h> +#include <asm/arch/clk.h> + +int pwm_enable(int pwm_id) +{ + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long tcon; + + tcon = readl(&pwm->tcon); + tcon |= TCON_START(pwm_id); + + writel(tcon, &pwm->tcon); + + return 0; +} + +void pwm_disable(int pwm_id) +{ + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long tcon; + + tcon = readl(&pwm->tcon); + tcon &= ~TCON_START(pwm_id); + + writel(tcon, &pwm->tcon); +} + +static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq) +{ + unsigned long tin_parent_rate; + unsigned int div; + + tin_parent_rate = get_pwm_clk(); + + for (div = 2; div <= 16; div *= 2) { + if ((tin_parent_rate / (div << 16)) < freq) + return tin_parent_rate / div; + } + + return tin_parent_rate / 16; +} + +#define NS_IN_SEC 1000000000UL + +int pwm_config(int pwm_id, int duty_ns, int period_ns) +{ + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned int offset; + unsigned long tin_rate; + unsigned long tin_ns; + unsigned long frequency; + unsigned long tcon; + unsigned long tcnt; + unsigned long tcmp; + + /* + * We currently avoid using 64bit arithmetic by using the + * fact that anything faster than 1GHz is easily representable + * by 32bits. + */ + if (period_ns > NS_IN_SEC || duty_ns > NS_IN_SEC || period_ns == 0) + return -ERANGE; + + if (duty_ns > period_ns) + return -EINVAL; + + frequency = NS_IN_SEC / period_ns; + + /* Check to see if we are changing the clock rate of the PWM */ + tin_rate = pwm_calc_tin(pwm_id, frequency); + + tin_ns = NS_IN_SEC / tin_rate; + tcnt = period_ns / tin_ns; + + /* Note, counters count down */ + tcmp = duty_ns / tin_ns; + tcmp = tcnt - tcmp; + + /* Update the PWM register block. */ + offset = pwm_id * 3; + if (pwm_id < 4) { + writel(tcnt, &pwm->tcntb0 + offset); + writel(tcmp, &pwm->tcmpb0 + offset); + } + + tcon = readl(&pwm->tcon); + tcon |= TCON_UPDATE(pwm_id); + if (pwm_id < 4) + tcon |= TCON_AUTO_RELOAD(pwm_id); + else + tcon |= TCON4_AUTO_RELOAD; + writel(tcon, &pwm->tcon); + + tcon &= ~TCON_UPDATE(pwm_id); + writel(tcon, &pwm->tcon); + + return 0; +} + +int pwm_init(int pwm_id, int div, int invert) +{ + u32 val; + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long ticks_per_period; + unsigned int offset, prescaler; + + /* + * Timer Freq(HZ) = + * PWM_CLK / { (prescaler_value + 1) * (divider_value) } + */ + + val = readl(&pwm->tcfg0); + if (pwm_id < 2) { + prescaler = PRESCALER_0; + val &= ~0xff; + val |= (prescaler & 0xff); + } else { + prescaler = PRESCALER_1; + val &= ~(0xff << 8); + val |= (prescaler & 0xff) << 8; + } + writel(val, &pwm->tcfg0); + val = readl(&pwm->tcfg1); + val &= ~(0xf << MUX_DIV_SHIFT(pwm_id)); + val |= (div & 0xf) << MUX_DIV_SHIFT(pwm_id); + writel(val, &pwm->tcfg1); + + if (pwm_id == 4) { + /* + * TODO(sjg): Use this as a countdown timer for now. We count + * down from the maximum value to 0, then reset. + */ + ticks_per_period = -1UL; + } else { + const unsigned long pwm_hz = 1000; + unsigned long timer_rate_hz = get_pwm_clk() / + ((prescaler + 1) * (1 << div)); + + ticks_per_period = timer_rate_hz / pwm_hz; + } + + /* set count value */ + offset = pwm_id * 3; + + writel(ticks_per_period, &pwm->tcntb0 + offset); + + val = readl(&pwm->tcon) & ~(0xf << TCON_OFFSET(pwm_id)); + if (invert && (pwm_id < 4)) + val |= TCON_INVERTER(pwm_id); + writel(val, &pwm->tcon); + + pwm_enable(pwm_id); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/sromc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/sromc.c new file mode 100644 index 000000000..806456fe8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/sromc.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Samsung Electronics + * Naveen Krishna Ch <ch.naveen@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/sromc.h> + +/* + * s5p_config_sromc() - select the proper SROMC Bank and configure the + * band width control and bank control registers + * srom_bank - SROM + * srom_bw_conf - SMC Band witdh reg configuration value + * srom_bc_conf - SMC Bank Control reg configuration value + */ +void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf) +{ + u32 tmp; + struct s5p_sromc *srom = + (struct s5p_sromc *)samsung_get_base_sromc(); + + /* Configure SMC_BW register to handle proper SROMC bank */ + tmp = srom->bw; + tmp &= ~(0xF << (srom_bank * 4)); + tmp |= srom_bw_conf; + srom->bw = tmp; + + /* Configure SMC_BC register */ + srom->bc[srom_bank] = srom_bc_conf; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/timer.c new file mode 100644 index 000000000..949abb1c8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5p-common/timer.c @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Heungjun Kim <riverful.kim@samsung.com> + * Inki Dae <inki.dae@samsung.com> + * Minkyu Kang <mk7.kang@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/arch/pwm.h> +#include <asm/arch/clk.h> +#include <pwm.h> + +DECLARE_GLOBAL_DATA_PTR; + +unsigned long get_current_tick(void); + +/* macro to read the 16 bit timer */ +static inline struct s5p_timer *s5p_get_base_timer(void) +{ + return (struct s5p_timer *)samsung_get_base_timer(); +} + +/** + * Read the countdown timer. + * + * This operates at 1MHz and counts downwards. It will wrap about every + * hour (2^32 microseconds). + * + * @return current value of timer + */ +static unsigned long timer_get_us_down(void) +{ + struct s5p_timer *const timer = s5p_get_base_timer(); + + return readl(&timer->tcnto4); +} + +int timer_init(void) +{ + /* PWM Timer 4 */ + pwm_init(4, MUX_DIV_4, 0); + pwm_config(4, 100000, 100000); + pwm_enable(4); + + /* Use this as the current monotonic time in us */ + gd->arch.timer_reset_value = 0; + + /* Use this as the last timer value we saw */ + gd->arch.lastinc = timer_get_us_down(); + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ +unsigned long get_timer(unsigned long base) +{ + unsigned long long time_ms; + + ulong now = timer_get_us_down(); + + /* + * Increment the time by the amount elapsed since the last read. + * The timer may have wrapped around, but it makes no difference to + * our arithmetic here. + */ + gd->arch.timer_reset_value += gd->arch.lastinc - now; + gd->arch.lastinc = now; + + /* Divide by 1000 to convert from us to ms */ + time_ms = gd->arch.timer_reset_value; + do_div(time_ms, 1000); + return time_ms - base; +} + +unsigned long __attribute__((no_instrument_function)) timer_get_us(void) +{ + static unsigned long base_time_us; + + struct s5p_timer *const timer = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long now_downward_us = readl(&timer->tcnto4); + + if (!base_time_us) + base_time_us = now_downward_us; + + /* Note that this timer counts downward. */ + return base_time_us - now_downward_us; +} + +/* delay x useconds */ +void __udelay(unsigned long usec) +{ + unsigned long count_value; + + count_value = timer_get_us_down(); + while ((int)(count_value - timer_get_us_down()) < (int)usec) + ; +} + +void reset_timer_masked(void) +{ + struct s5p_timer *const timer = s5p_get_base_timer(); + + /* reset time */ + gd->arch.lastinc = readl(&timer->tcnto4); + gd->arch.tbl = 0; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * 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) +{ + return CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/Makefile new file mode 100644 index 000000000..9f43ded1d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/Makefile @@ -0,0 +1,14 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2008 +# Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cache.o +obj-y += reset.o + +obj-y += clock.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/cache.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/cache.S new file mode 100644 index 000000000..3089592eb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/cache.S @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang <mk7.kang@samsung.com> + * + * based on arch/arm/cpu/armv7/omap3/cache.S + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.align 5 + +#include <linux/linkage.h> + +#ifndef CONFIG_SYS_L2CACHE_OFF +ENTRY(v7_outer_cache_enable) + push {r0, r1, r2, lr} + mrc 15, 0, r3, cr1, cr0, 1 + orr r3, r3, #2 + mcr 15, 0, r3, cr1, cr0, 1 + pop {r1, r2, r3, pc} +ENDPROC(v7_outer_cache_enable) + +ENTRY(v7_outer_cache_disable) + push {r0, r1, r2, lr} + mrc 15, 0, r3, cr1, cr0, 1 + bic r3, r3, #2 + mcr 15, 0, r3, cr1, cr0, 1 + pop {r1, r2, r3, pc} +ENDPROC(v7_outer_cache_disable) +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/clock.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/clock.c new file mode 100644 index 000000000..3da00717f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/clock.c @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang <mk7.kang@samsung.com> + * Heungjun Kim <riverful.kim@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/clk.h> + +#define CLK_M 0 +#define CLK_D 1 +#define CLK_P 2 + +#ifndef CONFIG_SYS_CLK_FREQ_C100 +#define CONFIG_SYS_CLK_FREQ_C100 12000000 +#endif +#ifndef CONFIG_SYS_CLK_FREQ_C110 +#define CONFIG_SYS_CLK_FREQ_C110 24000000 +#endif + +/* s5pc110: return pll clock frequency */ +static unsigned long s5pc100_get_pll_clk(int pllreg) +{ + struct s5pc100_clock *clk = + (struct s5pc100_clock *)samsung_get_base_clock(); + unsigned long r, m, p, s, mask, fout; + unsigned int freq; + + switch (pllreg) { + case APLL: + r = readl(&clk->apll_con); + break; + case MPLL: + r = readl(&clk->mpll_con); + break; + case EPLL: + r = readl(&clk->epll_con); + break; + case HPLL: + r = readl(&clk->hpll_con); + break; + default: + printf("Unsupported PLL (%d)\n", pllreg); + return 0; + } + + /* + * APLL_CON: MIDV [25:16] + * MPLL_CON: MIDV [23:16] + * EPLL_CON: MIDV [23:16] + * HPLL_CON: MIDV [23:16] + */ + if (pllreg == APLL) + mask = 0x3ff; + else + mask = 0x0ff; + + m = (r >> 16) & mask; + + /* PDIV [13:8] */ + p = (r >> 8) & 0x3f; + /* SDIV [2:0] */ + s = r & 0x7; + + /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */ + freq = CONFIG_SYS_CLK_FREQ_C100; + fout = m * (freq / (p * (1 << s))); + + return fout; +} + +/* s5pc100: return pll clock frequency */ +static unsigned long s5pc110_get_pll_clk(int pllreg) +{ + struct s5pc110_clock *clk = + (struct s5pc110_clock *)samsung_get_base_clock(); + unsigned long r, m, p, s, mask, fout; + unsigned int freq; + + switch (pllreg) { + case APLL: + r = readl(&clk->apll_con); + break; + case MPLL: + r = readl(&clk->mpll_con); + break; + case EPLL: + r = readl(&clk->epll_con); + break; + case VPLL: + r = readl(&clk->vpll_con); + break; + default: + printf("Unsupported PLL (%d)\n", pllreg); + return 0; + } + + /* + * APLL_CON: MIDV [25:16] + * MPLL_CON: MIDV [25:16] + * EPLL_CON: MIDV [24:16] + * VPLL_CON: MIDV [24:16] + */ + if (pllreg == APLL || pllreg == MPLL) + mask = 0x3ff; + else + mask = 0x1ff; + + m = (r >> 16) & mask; + + /* PDIV [13:8] */ + p = (r >> 8) & 0x3f; + /* SDIV [2:0] */ + s = r & 0x7; + + freq = CONFIG_SYS_CLK_FREQ_C110; + if (pllreg == APLL) { + if (s < 1) + s = 1; + /* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */ + fout = m * (freq / (p * (1 << (s - 1)))); + } else + /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */ + fout = m * (freq / (p * (1 << s))); + + return fout; +} + +/* s5pc110: return ARM clock frequency */ +static unsigned long s5pc110_get_arm_clk(void) +{ + struct s5pc110_clock *clk = + (struct s5pc110_clock *)samsung_get_base_clock(); + unsigned long div; + unsigned long dout_apll, armclk; + unsigned int apll_ratio; + + div = readl(&clk->div0); + + /* APLL_RATIO: [2:0] */ + apll_ratio = div & 0x7; + + dout_apll = get_pll_clk(APLL) / (apll_ratio + 1); + armclk = dout_apll; + + return armclk; +} + +/* s5pc100: return ARM clock frequency */ +static unsigned long s5pc100_get_arm_clk(void) +{ + struct s5pc100_clock *clk = + (struct s5pc100_clock *)samsung_get_base_clock(); + unsigned long div; + unsigned long dout_apll, armclk; + unsigned int apll_ratio, arm_ratio; + + div = readl(&clk->div0); + + /* ARM_RATIO: [6:4] */ + arm_ratio = (div >> 4) & 0x7; + /* APLL_RATIO: [0] */ + apll_ratio = div & 0x1; + + dout_apll = get_pll_clk(APLL) / (apll_ratio + 1); + armclk = dout_apll / (arm_ratio + 1); + + return armclk; +} + +/* s5pc100: return HCLKD0 frequency */ +static unsigned long get_hclk(void) +{ + struct s5pc100_clock *clk = + (struct s5pc100_clock *)samsung_get_base_clock(); + unsigned long hclkd0; + uint div, d0_bus_ratio; + + div = readl(&clk->div0); + /* D0_BUS_RATIO: [10:8] */ + d0_bus_ratio = (div >> 8) & 0x7; + + hclkd0 = get_arm_clk() / (d0_bus_ratio + 1); + + return hclkd0; +} + +/* s5pc100: return PCLKD1 frequency */ +static unsigned long get_pclkd1(void) +{ + struct s5pc100_clock *clk = + (struct s5pc100_clock *)samsung_get_base_clock(); + unsigned long d1_bus, pclkd1; + uint div, d1_bus_ratio, pclkd1_ratio; + + div = readl(&clk->div0); + /* D1_BUS_RATIO: [14:12] */ + d1_bus_ratio = (div >> 12) & 0x7; + /* PCLKD1_RATIO: [18:16] */ + pclkd1_ratio = (div >> 16) & 0x7; + + /* ASYNC Mode */ + d1_bus = get_pll_clk(MPLL) / (d1_bus_ratio + 1); + pclkd1 = d1_bus / (pclkd1_ratio + 1); + + return pclkd1; +} + +/* s5pc110: return HCLKs frequency */ +static unsigned long get_hclk_sys(int dom) +{ + struct s5pc110_clock *clk = + (struct s5pc110_clock *)samsung_get_base_clock(); + unsigned long hclk; + unsigned int div; + unsigned int offset; + unsigned int hclk_sys_ratio; + + if (dom == CLK_M) + return get_hclk(); + + div = readl(&clk->div0); + + /* + * HCLK_MSYS_RATIO: [10:8] + * HCLK_DSYS_RATIO: [19:16] + * HCLK_PSYS_RATIO: [27:24] + */ + offset = 8 + (dom << 0x3); + + hclk_sys_ratio = (div >> offset) & 0xf; + + hclk = get_pll_clk(MPLL) / (hclk_sys_ratio + 1); + + return hclk; +} + +/* s5pc110: return PCLKs frequency */ +static unsigned long get_pclk_sys(int dom) +{ + struct s5pc110_clock *clk = + (struct s5pc110_clock *)samsung_get_base_clock(); + unsigned long pclk; + unsigned int div; + unsigned int offset; + unsigned int pclk_sys_ratio; + + div = readl(&clk->div0); + + /* + * PCLK_MSYS_RATIO: [14:12] + * PCLK_DSYS_RATIO: [22:20] + * PCLK_PSYS_RATIO: [30:28] + */ + offset = 12 + (dom << 0x3); + + pclk_sys_ratio = (div >> offset) & 0x7; + + pclk = get_hclk_sys(dom) / (pclk_sys_ratio + 1); + + return pclk; +} + +/* s5pc110: return peripheral clock frequency */ +static unsigned long s5pc110_get_pclk(void) +{ + return get_pclk_sys(CLK_P); +} + +/* s5pc100: return peripheral clock frequency */ +static unsigned long s5pc100_get_pclk(void) +{ + return get_pclkd1(); +} + +/* s5pc1xx: return uart clock frequency */ +static unsigned long s5pc1xx_get_uart_clk(int dev_index) +{ + if (cpu_is_s5pc110()) + return s5pc110_get_pclk(); + else + return s5pc100_get_pclk(); +} + +/* s5pc1xx: return pwm clock frequency */ +static unsigned long s5pc1xx_get_pwm_clk(void) +{ + if (cpu_is_s5pc110()) + return s5pc110_get_pclk(); + else + return s5pc100_get_pclk(); +} + +unsigned long get_pll_clk(int pllreg) +{ + if (cpu_is_s5pc110()) + return s5pc110_get_pll_clk(pllreg); + else + return s5pc100_get_pll_clk(pllreg); +} + +unsigned long get_arm_clk(void) +{ + if (cpu_is_s5pc110()) + return s5pc110_get_arm_clk(); + else + return s5pc100_get_arm_clk(); +} + +unsigned long get_pwm_clk(void) +{ + return s5pc1xx_get_pwm_clk(); +} + +unsigned long get_uart_clk(int dev_index) +{ + return s5pc1xx_get_uart_clk(dev_index); +} + +void set_mmc_clk(int dev_index, unsigned int div) +{ + /* Do NOTHING */ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/reset.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/reset.S new file mode 100644 index 000000000..bd74f2b45 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/s5pc1xx/reset.S @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2009 Samsung Electronics. + * Minkyu Kang <mk7.kang@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/arch/cpu.h> +#include <linux/linkage.h> + +#define S5PC100_SWRESET 0xE0200000 +#define S5PC110_SWRESET 0xE0102000 + +ENTRY(reset_cpu) + ldr r1, =S5PC100_PRO_ID + ldr r2, [r1] + ldr r4, =0x00010000 + and r4, r2, r4 + cmp r4, #0 + bne 110f + /* S5PC100 */ + ldr r1, =S5PC100_SWRESET + ldr r2, =0xC100 + b 200f +110: /* S5PC110 */ + ldr r1, =S5PC110_SWRESET + mov r2, #1 +200: + str r2, [r1] +_loop_forever: + b _loop_forever +ENDPROC(reset_cpu) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/Makefile new file mode 100644 index 000000000..cbe1d406d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/Makefile @@ -0,0 +1,12 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2012 Altera Corporation <www.altera.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := lowlevel_init.o +obj-y += misc.o timer.o reset_manager.o system_manager.o clock_manager.o +obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/clock_manager.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/clock_manager.c new file mode 100644 index 000000000..23d697dee --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/clock_manager.c @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2013 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock_manager.h> + +static const struct socfpga_clock_manager *clock_manager_base = + (void *)SOCFPGA_CLKMGR_ADDRESS; + +#define CLKMGR_BYPASS_ENABLE 1 +#define CLKMGR_BYPASS_DISABLE 0 +#define CLKMGR_STAT_IDLE 0 +#define CLKMGR_STAT_BUSY 1 +#define CLKMGR_BYPASS_PERPLLSRC_SELECT_EOSC1 0 +#define CLKMGR_BYPASS_PERPLLSRC_SELECT_INPUT_MUX 1 +#define CLKMGR_BYPASS_SDRPLLSRC_SELECT_EOSC1 0 +#define CLKMGR_BYPASS_SDRPLLSRC_SELECT_INPUT_MUX 1 + +#define CLEAR_BGP_EN_PWRDN \ + (CLKMGR_MAINPLLGRP_VCO_PWRDN_SET(0)| \ + CLKMGR_MAINPLLGRP_VCO_EN_SET(0)| \ + CLKMGR_MAINPLLGRP_VCO_BGPWRDN_SET(0)) + +#define VCO_EN_BASE \ + (CLKMGR_MAINPLLGRP_VCO_PWRDN_SET(0)| \ + CLKMGR_MAINPLLGRP_VCO_EN_SET(1)| \ + CLKMGR_MAINPLLGRP_VCO_BGPWRDN_SET(0)) + +static inline void cm_wait_for_lock(uint32_t mask) +{ + register uint32_t inter_val; + do { + inter_val = readl(&clock_manager_base->inter) & mask; + } while (inter_val != mask); +} + +/* function to poll in the fsm busy bit */ +static inline void cm_wait_for_fsm(void) +{ + while (readl(&clock_manager_base->stat) & CLKMGR_STAT_BUSY) + ; +} + +/* + * function to write the bypass register which requires a poll of the + * busy bit + */ +static inline void cm_write_bypass(uint32_t val) +{ + writel(val, &clock_manager_base->bypass); + cm_wait_for_fsm(); +} + +/* function to write the ctrl register which requires a poll of the busy bit */ +static inline void cm_write_ctrl(uint32_t val) +{ + writel(val, &clock_manager_base->ctrl); + cm_wait_for_fsm(); +} + +/* function to write a clock register that has phase information */ +static inline void cm_write_with_phase(uint32_t value, + uint32_t reg_address, uint32_t mask) +{ + /* poll until phase is zero */ + while (readl(reg_address) & mask) + ; + + writel(value, reg_address); + + while (readl(reg_address) & mask) + ; +} + +/* + * Setup clocks while making no assumptions about previous state of the clocks. + * + * Start by being paranoid and gate all sw managed clocks + * Put all plls in bypass + * Put all plls VCO registers back to reset value (bandgap power down). + * Put peripheral and main pll src to reset value to avoid glitch. + * Delay 5 us. + * Deassert bandgap power down and set numerator and denominator + * Start 7 us timer. + * set internal dividers + * Wait for 7 us timer. + * Enable plls + * Set external dividers while plls are locking + * Wait for pll lock + * Assert/deassert outreset all. + * Take all pll's out of bypass + * Clear safe mode + * set source main and peripheral clocks + * Ungate clocks + */ + +void cm_basic_init(const cm_config_t *cfg) +{ + uint32_t start, timeout; + + /* Start by being paranoid and gate all sw managed clocks */ + + /* + * We need to disable nandclk + * and then do another apb access before disabling + * gatting off the rest of the periperal clocks. + */ + writel(~CLKMGR_PERPLLGRP_EN_NANDCLK_MASK & + readl(&clock_manager_base->per_pll_en), + &clock_manager_base->per_pll_en); + + /* DO NOT GATE OFF DEBUG CLOCKS & BRIDGE CLOCKS */ + writel(CLKMGR_MAINPLLGRP_EN_DBGTIMERCLK_MASK | + CLKMGR_MAINPLLGRP_EN_DBGTRACECLK_MASK | + CLKMGR_MAINPLLGRP_EN_DBGCLK_MASK | + CLKMGR_MAINPLLGRP_EN_DBGATCLK_MASK | + CLKMGR_MAINPLLGRP_EN_S2FUSER0CLK_MASK | + CLKMGR_MAINPLLGRP_EN_L4MPCLK_MASK, + &clock_manager_base->main_pll_en); + + writel(0, &clock_manager_base->sdr_pll_en); + + /* now we can gate off the rest of the peripheral clocks */ + writel(0, &clock_manager_base->per_pll_en); + + /* Put all plls in bypass */ + cm_write_bypass( + CLKMGR_BYPASS_PERPLLSRC_SET( + CLKMGR_BYPASS_PERPLLSRC_SELECT_EOSC1) | + CLKMGR_BYPASS_SDRPLLSRC_SET( + CLKMGR_BYPASS_SDRPLLSRC_SELECT_EOSC1) | + CLKMGR_BYPASS_PERPLL_SET(CLKMGR_BYPASS_ENABLE) | + CLKMGR_BYPASS_SDRPLL_SET(CLKMGR_BYPASS_ENABLE) | + CLKMGR_BYPASS_MAINPLL_SET(CLKMGR_BYPASS_ENABLE)); + + /* + * Put all plls VCO registers back to reset value. + * Some code might have messed with them. + */ + writel(CLKMGR_MAINPLLGRP_VCO_RESET_VALUE, + &clock_manager_base->main_pll_vco); + writel(CLKMGR_PERPLLGRP_VCO_RESET_VALUE, + &clock_manager_base->per_pll_vco); + writel(CLKMGR_SDRPLLGRP_VCO_RESET_VALUE, + &clock_manager_base->sdr_pll_vco); + + /* + * The clocks to the flash devices and the L4_MAIN clocks can + * glitch when coming out of safe mode if their source values + * are different from their reset value. So the trick it to + * put them back to their reset state, and change input + * after exiting safe mode but before ungating the clocks. + */ + writel(CLKMGR_PERPLLGRP_SRC_RESET_VALUE, + &clock_manager_base->per_pll_src); + writel(CLKMGR_MAINPLLGRP_L4SRC_RESET_VALUE, + &clock_manager_base->main_pll_l4src); + + /* read back for the required 5 us delay. */ + readl(&clock_manager_base->main_pll_vco); + readl(&clock_manager_base->per_pll_vco); + readl(&clock_manager_base->sdr_pll_vco); + + + /* + * We made sure bgpwr down was assert for 5 us. Now deassert BG PWR DN + * with numerator and denominator. + */ + writel(cfg->main_vco_base | CLEAR_BGP_EN_PWRDN | + CLKMGR_MAINPLLGRP_VCO_REGEXTSEL_MASK, + &clock_manager_base->main_pll_vco); + + writel(cfg->peri_vco_base | CLEAR_BGP_EN_PWRDN | + CLKMGR_PERPLLGRP_VCO_REGEXTSEL_MASK, + &clock_manager_base->per_pll_vco); + + writel(CLKMGR_SDRPLLGRP_VCO_OUTRESET_SET(0) | + CLKMGR_SDRPLLGRP_VCO_OUTRESETALL_SET(0) | + cfg->sdram_vco_base | CLEAR_BGP_EN_PWRDN | + CLKMGR_SDRPLLGRP_VCO_REGEXTSEL_MASK, + &clock_manager_base->sdr_pll_vco); + + /* + * Time starts here + * must wait 7 us from BGPWRDN_SET(0) to VCO_ENABLE_SET(1) + */ + reset_timer(); + start = get_timer(0); + /* timeout in unit of us as CONFIG_SYS_HZ = 1000*1000 */ + timeout = 7; + + /* main mpu */ + writel(cfg->mpuclk, &clock_manager_base->main_pll_mpuclk); + + /* main main clock */ + writel(cfg->mainclk, &clock_manager_base->main_pll_mainclk); + + /* main for dbg */ + writel(cfg->dbgatclk, &clock_manager_base->main_pll_dbgatclk); + + /* main for cfgs2fuser0clk */ + writel(cfg->cfg2fuser0clk, + &clock_manager_base->main_pll_cfgs2fuser0clk); + + /* Peri emac0 50 MHz default to RMII */ + writel(cfg->emac0clk, &clock_manager_base->per_pll_emac0clk); + + /* Peri emac1 50 MHz default to RMII */ + writel(cfg->emac1clk, &clock_manager_base->per_pll_emac1clk); + + /* Peri QSPI */ + writel(cfg->mainqspiclk, &clock_manager_base->main_pll_mainqspiclk); + + writel(cfg->perqspiclk, &clock_manager_base->per_pll_perqspiclk); + + /* Peri pernandsdmmcclk */ + writel(cfg->pernandsdmmcclk, + &clock_manager_base->per_pll_pernandsdmmcclk); + + /* Peri perbaseclk */ + writel(cfg->perbaseclk, &clock_manager_base->per_pll_perbaseclk); + + /* Peri s2fuser1clk */ + writel(cfg->s2fuser1clk, &clock_manager_base->per_pll_s2fuser1clk); + + /* 7 us must have elapsed before we can enable the VCO */ + while (get_timer(start) < timeout) + ; + + /* Enable vco */ + /* main pll vco */ + writel(cfg->main_vco_base | VCO_EN_BASE, + &clock_manager_base->main_pll_vco); + + /* periferal pll */ + writel(cfg->peri_vco_base | VCO_EN_BASE, + &clock_manager_base->per_pll_vco); + + /* sdram pll vco */ + writel(CLKMGR_SDRPLLGRP_VCO_OUTRESET_SET(0) | + CLKMGR_SDRPLLGRP_VCO_OUTRESETALL_SET(0) | + cfg->sdram_vco_base | VCO_EN_BASE, + &clock_manager_base->sdr_pll_vco); + + /* L3 MP and L3 SP */ + writel(cfg->maindiv, &clock_manager_base->main_pll_maindiv); + + writel(cfg->dbgdiv, &clock_manager_base->main_pll_dbgdiv); + + writel(cfg->tracediv, &clock_manager_base->main_pll_tracediv); + + /* L4 MP, L4 SP, can0, and can1 */ + writel(cfg->perdiv, &clock_manager_base->per_pll_div); + + writel(cfg->gpiodiv, &clock_manager_base->per_pll_gpiodiv); + +#define LOCKED_MASK \ + (CLKMGR_INTER_SDRPLLLOCKED_MASK | \ + CLKMGR_INTER_PERPLLLOCKED_MASK | \ + CLKMGR_INTER_MAINPLLLOCKED_MASK) + + cm_wait_for_lock(LOCKED_MASK); + + /* write the sdram clock counters before toggling outreset all */ + writel(cfg->ddrdqsclk & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK, + &clock_manager_base->sdr_pll_ddrdqsclk); + + writel(cfg->ddr2xdqsclk & CLKMGR_SDRPLLGRP_DDR2XDQSCLK_CNT_MASK, + &clock_manager_base->sdr_pll_ddr2xdqsclk); + + writel(cfg->ddrdqclk & CLKMGR_SDRPLLGRP_DDRDQCLK_CNT_MASK, + &clock_manager_base->sdr_pll_ddrdqclk); + + writel(cfg->s2fuser2clk & CLKMGR_SDRPLLGRP_S2FUSER2CLK_CNT_MASK, + &clock_manager_base->sdr_pll_s2fuser2clk); + + /* + * after locking, but before taking out of bypass + * assert/deassert outresetall + */ + uint32_t mainvco = readl(&clock_manager_base->main_pll_vco); + + /* assert main outresetall */ + writel(mainvco | CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK, + &clock_manager_base->main_pll_vco); + + uint32_t periphvco = readl(&clock_manager_base->per_pll_vco); + + /* assert pheriph outresetall */ + writel(periphvco | CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK, + &clock_manager_base->per_pll_vco); + + /* assert sdram outresetall */ + writel(cfg->sdram_vco_base | VCO_EN_BASE| + CLKMGR_SDRPLLGRP_VCO_OUTRESETALL_SET(1), + &clock_manager_base->sdr_pll_vco); + + /* deassert main outresetall */ + writel(mainvco & ~CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK, + &clock_manager_base->main_pll_vco); + + /* deassert pheriph outresetall */ + writel(periphvco & ~CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK, + &clock_manager_base->per_pll_vco); + + /* deassert sdram outresetall */ + writel(CLKMGR_SDRPLLGRP_VCO_OUTRESETALL_SET(0) | + cfg->sdram_vco_base | VCO_EN_BASE, + &clock_manager_base->sdr_pll_vco); + + /* + * now that we've toggled outreset all, all the clocks + * are aligned nicely; so we can change any phase. + */ + cm_write_with_phase(cfg->ddrdqsclk, + (uint32_t)&clock_manager_base->sdr_pll_ddrdqsclk, + CLKMGR_SDRPLLGRP_DDRDQSCLK_PHASE_MASK); + + /* SDRAM DDR2XDQSCLK */ + cm_write_with_phase(cfg->ddr2xdqsclk, + (uint32_t)&clock_manager_base->sdr_pll_ddr2xdqsclk, + CLKMGR_SDRPLLGRP_DDR2XDQSCLK_PHASE_MASK); + + cm_write_with_phase(cfg->ddrdqclk, + (uint32_t)&clock_manager_base->sdr_pll_ddrdqclk, + CLKMGR_SDRPLLGRP_DDRDQCLK_PHASE_MASK); + + cm_write_with_phase(cfg->s2fuser2clk, + (uint32_t)&clock_manager_base->sdr_pll_s2fuser2clk, + CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_MASK); + + /* Take all three PLLs out of bypass when safe mode is cleared. */ + cm_write_bypass( + CLKMGR_BYPASS_PERPLLSRC_SET( + CLKMGR_BYPASS_PERPLLSRC_SELECT_EOSC1) | + CLKMGR_BYPASS_SDRPLLSRC_SET( + CLKMGR_BYPASS_SDRPLLSRC_SELECT_EOSC1) | + CLKMGR_BYPASS_PERPLL_SET(CLKMGR_BYPASS_DISABLE) | + CLKMGR_BYPASS_SDRPLL_SET(CLKMGR_BYPASS_DISABLE) | + CLKMGR_BYPASS_MAINPLL_SET(CLKMGR_BYPASS_DISABLE)); + + /* clear safe mode */ + cm_write_ctrl(readl(&clock_manager_base->ctrl) | + CLKMGR_CTRL_SAFEMODE_SET(CLKMGR_CTRL_SAFEMODE_MASK)); + + /* + * now that safe mode is clear with clocks gated + * it safe to change the source mux for the flashes the the L4_MAIN + */ + writel(cfg->persrc, &clock_manager_base->per_pll_src); + writel(cfg->l4src, &clock_manager_base->main_pll_l4src); + + /* Now ungate non-hw-managed clocks */ + writel(~0, &clock_manager_base->main_pll_en); + writel(~0, &clock_manager_base->per_pll_en); + writel(~0, &clock_manager_base->sdr_pll_en); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/config.mk b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/config.mk new file mode 100644 index 000000000..3d1849157 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/config.mk @@ -0,0 +1,8 @@ +# +# Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ +# +# SPDX-License-Identifier: GPL-2.0+ +# +ifndef CONFIG_SPL_BUILD +ALL-y += u-boot.img +endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/freeze_controller.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/freeze_controller.c new file mode 100644 index 000000000..b8c9bce1e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/freeze_controller.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2013 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/freeze_controller.h> +#include <asm/arch/timer.h> +#include <asm/errno.h> + +DECLARE_GLOBAL_DATA_PTR; + +static const struct socfpga_freeze_controller *freeze_controller_base = + (void *)(SOCFPGA_SYSMGR_ADDRESS + SYSMGR_FRZCTRL_ADDRESS); + +/* + * Default state from cold reset is FREEZE_ALL; the global + * flag is set to TRUE to indicate the IO banks are frozen + */ +static uint32_t frzctrl_channel_freeze[FREEZE_CHANNEL_NUM] + = { FREEZE_CTRL_FROZEN, FREEZE_CTRL_FROZEN, + FREEZE_CTRL_FROZEN, FREEZE_CTRL_FROZEN}; + +/* Freeze HPS IOs */ +void sys_mgr_frzctrl_freeze_req(void) +{ + u32 ioctrl_reg_offset; + u32 reg_value; + u32 reg_cfg_mask; + u32 channel_id; + + /* select software FSM */ + writel(SYSMGR_FRZCTRL_SRC_VIO1_ENUM_SW, &freeze_controller_base->src); + + /* Freeze channel 0 to 2 */ + for (channel_id = 0; channel_id <= 2; channel_id++) { + ioctrl_reg_offset = (u32)( + &freeze_controller_base->vioctrl + + (channel_id << SYSMGR_FRZCTRL_VIOCTRL_SHIFT)); + + /* + * Assert active low enrnsl, plniotri + * and niotri signals + */ + reg_cfg_mask = + SYSMGR_FRZCTRL_VIOCTRL_SLEW_MASK + | SYSMGR_FRZCTRL_VIOCTRL_WKPULLUP_MASK + | SYSMGR_FRZCTRL_VIOCTRL_TRISTATE_MASK; + clrbits_le32(ioctrl_reg_offset, reg_cfg_mask); + + /* + * Note: Delay for 20ns at min + * Assert active low bhniotri signal and de-assert + * active high csrdone + */ + reg_cfg_mask + = SYSMGR_FRZCTRL_VIOCTRL_BUSHOLD_MASK + | SYSMGR_FRZCTRL_VIOCTRL_CFG_MASK; + clrbits_le32(ioctrl_reg_offset, reg_cfg_mask); + + /* Set global flag to indicate channel is frozen */ + frzctrl_channel_freeze[channel_id] = FREEZE_CTRL_FROZEN; + } + + /* Freeze channel 3 */ + /* + * Assert active low enrnsl, plniotri and + * niotri signals + */ + reg_cfg_mask + = SYSMGR_FRZCTRL_HIOCTRL_SLEW_MASK + | SYSMGR_FRZCTRL_HIOCTRL_WKPULLUP_MASK + | SYSMGR_FRZCTRL_HIOCTRL_TRISTATE_MASK; + clrbits_le32(&freeze_controller_base->hioctrl, reg_cfg_mask); + + /* + * assert active low bhniotri & nfrzdrv signals, + * de-assert active high csrdone and assert + * active high frzreg and nfrzdrv signals + */ + reg_value = readl(&freeze_controller_base->hioctrl); + reg_cfg_mask + = SYSMGR_FRZCTRL_HIOCTRL_BUSHOLD_MASK + | SYSMGR_FRZCTRL_HIOCTRL_CFG_MASK; + reg_value + = (reg_value & ~reg_cfg_mask) + | SYSMGR_FRZCTRL_HIOCTRL_REGRST_MASK + | SYSMGR_FRZCTRL_HIOCTRL_OCTRST_MASK; + writel(reg_value, &freeze_controller_base->hioctrl); + + /* + * assert active high reinit signal and de-assert + * active high pllbiasen signals + */ + reg_value = readl(&freeze_controller_base->hioctrl); + reg_value + = (reg_value & + ~SYSMGR_FRZCTRL_HIOCTRL_OCT_CFGEN_CALSTART_MASK) + | SYSMGR_FRZCTRL_HIOCTRL_DLLRST_MASK; + writel(reg_value, &freeze_controller_base->hioctrl); + + /* Set global flag to indicate channel is frozen */ + frzctrl_channel_freeze[channel_id] = FREEZE_CTRL_FROZEN; +} + +/* Unfreeze/Thaw HPS IOs */ +void sys_mgr_frzctrl_thaw_req(void) +{ + u32 ioctrl_reg_offset; + u32 reg_cfg_mask; + u32 reg_value; + u32 channel_id; + + /* select software FSM */ + writel(SYSMGR_FRZCTRL_SRC_VIO1_ENUM_SW, &freeze_controller_base->src); + + /* Thaw channel 0 to 2 */ + for (channel_id = 0; channel_id <= 2; channel_id++) { + ioctrl_reg_offset + = (u32)(&freeze_controller_base->vioctrl + + (channel_id << SYSMGR_FRZCTRL_VIOCTRL_SHIFT)); + + /* + * Assert active low bhniotri signal and + * de-assert active high csrdone + */ + reg_cfg_mask + = SYSMGR_FRZCTRL_VIOCTRL_BUSHOLD_MASK + | SYSMGR_FRZCTRL_VIOCTRL_CFG_MASK; + setbits_le32(ioctrl_reg_offset, reg_cfg_mask); + + /* + * Note: Delay for 20ns at min + * de-assert active low plniotri and niotri signals + */ + reg_cfg_mask + = SYSMGR_FRZCTRL_VIOCTRL_WKPULLUP_MASK + | SYSMGR_FRZCTRL_VIOCTRL_TRISTATE_MASK; + setbits_le32(ioctrl_reg_offset, reg_cfg_mask); + + /* + * Note: Delay for 20ns at min + * de-assert active low enrnsl signal + */ + setbits_le32(ioctrl_reg_offset, + SYSMGR_FRZCTRL_VIOCTRL_SLEW_MASK); + + /* Set global flag to indicate channel is thawed */ + frzctrl_channel_freeze[channel_id] = FREEZE_CTRL_THAWED; + } + + /* Thaw channel 3 */ + /* de-assert active high reinit signal */ + clrbits_le32(&freeze_controller_base->hioctrl, + SYSMGR_FRZCTRL_HIOCTRL_DLLRST_MASK); + + /* + * Note: Delay for 40ns at min + * assert active high pllbiasen signals + */ + setbits_le32(&freeze_controller_base->hioctrl, + SYSMGR_FRZCTRL_HIOCTRL_OCT_CFGEN_CALSTART_MASK); + + /* + * Delay 1000 intosc. intosc is based on eosc1 + * Use worst case which is fatest eosc1=50MHz, delay required + * is 1/50MHz * 1000 = 20us + */ + udelay(20); + + /* + * de-assert active low bhniotri signals, + * assert active high csrdone and nfrzdrv signal + */ + reg_value = readl(&freeze_controller_base->hioctrl); + reg_value = (reg_value + | SYSMGR_FRZCTRL_HIOCTRL_BUSHOLD_MASK + | SYSMGR_FRZCTRL_HIOCTRL_CFG_MASK) + & ~SYSMGR_FRZCTRL_HIOCTRL_OCTRST_MASK; + writel(reg_value, &freeze_controller_base->hioctrl); + + /* + * Delay 33 intosc + * Use worst case which is fatest eosc1=50MHz, delay required + * is 1/50MHz * 33 = 660ns ~= 1us + */ + udelay(1); + + /* de-assert active low plniotri and niotri signals */ + reg_cfg_mask + = SYSMGR_FRZCTRL_HIOCTRL_WKPULLUP_MASK + | SYSMGR_FRZCTRL_HIOCTRL_TRISTATE_MASK; + + setbits_le32(&freeze_controller_base->hioctrl, reg_cfg_mask); + + /* + * Note: Delay for 40ns at min + * de-assert active high frzreg signal + */ + clrbits_le32(&freeze_controller_base->hioctrl, + SYSMGR_FRZCTRL_HIOCTRL_REGRST_MASK); + + /* + * Note: Delay for 40ns at min + * de-assert active low enrnsl signal + */ + setbits_le32(&freeze_controller_base->hioctrl, + SYSMGR_FRZCTRL_HIOCTRL_SLEW_MASK); + + /* Set global flag to indicate channel is thawed */ + frzctrl_channel_freeze[channel_id] = FREEZE_CTRL_THAWED; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/lowlevel_init.S new file mode 100644 index 000000000..1caaa2759 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/lowlevel_init.S @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <version.h> + +/* Save the parameter pass in by previous boot loader */ +.global save_boot_params +save_boot_params: + /* save the parameter here */ + + /* + * Setup stack for exception, which is located + * at the end of on-chip RAM. We don't expect exception prior to + * relocation and if that happens, we won't worry -- it will overide + * global data region as the code will goto reset. After relocation, + * this region won't be used by other part of program. + * Hence it is safe. + */ + ldr r0, =(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE) + ldr r1, =IRQ_STACK_START_IN + str r0, [r1] + + bx lr + + +/* Set up the platform, once the cpu has been initialized */ +.globl lowlevel_init +lowlevel_init: + + /* Remap */ +#ifdef CONFIG_SPL_BUILD + /* + * SPL : configure the remap (L3 NIC-301 GPV) + * so the on-chip RAM at lower memory instead ROM. + */ + ldr r0, =SOCFPGA_L3REGS_ADDRESS + mov r1, #0x19 + str r1, [r0] +#else + /* + * U-Boot : configure the remap (L3 NIC-301 GPV) + * so the SDRAM at lower memory instead on-chip RAM. + */ + ldr r0, =SOCFPGA_L3REGS_ADDRESS + mov r1, #0x2 + str r1, [r0] + + /* Private components security */ + + /* + * U-Boot : configure private timer, global timer and cpu + * component access as non secure for kernel stage (as required + * by kernel) + */ + mrc p15,4,r0,c15,c0,0 + add r1, r0, #0x54 + ldr r2, [r1] + orr r2, r2, #0xff + orr r2, r2, #0xf00 + str r2, [r1] +#endif /* #ifdef CONFIG_SPL_BUILD */ + mov pc, lr diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/misc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/misc.c new file mode 100644 index 000000000..2f1c7160f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/misc.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2012 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE); + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/reset_manager.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/reset_manager.c new file mode 100644 index 000000000..e320c011a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/reset_manager.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2013 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/reset_manager.h> + +DECLARE_GLOBAL_DATA_PTR; + +static const struct socfpga_reset_manager *reset_manager_base = + (void *)SOCFPGA_RSTMGR_ADDRESS; + +/* + * Write the reset manager register to cause reset + */ +void reset_cpu(ulong addr) +{ + /* request a warm reset */ + writel((1 << RSTMGR_CTRL_SWWARMRSTREQ_LSB), + &reset_manager_base->ctrl); + /* + * infinite loop here as watchdog will trigger and reset + * the processor + */ + while (1) + ; +} + +/* + * Release peripherals from reset based on handoff + */ +void reset_deassert_peripherals_handoff(void) +{ + writel(0, &reset_manager_base->per_mod_reset); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/spl.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/spl.c new file mode 100644 index 000000000..2ae88bbd0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/spl.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2012 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/u-boot.h> +#include <asm/utils.h> +#include <version.h> +#include <image.h> +#include <asm/arch/reset_manager.h> +#include <spl.h> +#include <asm/arch/system_manager.h> +#include <asm/arch/freeze_controller.h> + +DECLARE_GLOBAL_DATA_PTR; + +u32 spl_boot_device(void) +{ + return BOOT_DEVICE_RAM; +} + +/* + * Board initialization after bss clearance + */ +void spl_board_init(void) +{ +#ifndef CONFIG_SOCFPGA_VIRTUAL_TARGET + cm_config_t cm_default_cfg = { + /* main group */ + MAIN_VCO_BASE, + CLKMGR_MAINPLLGRP_MPUCLK_CNT_SET( + CONFIG_HPS_MAINPLLGRP_MPUCLK_CNT), + CLKMGR_MAINPLLGRP_MAINCLK_CNT_SET( + CONFIG_HPS_MAINPLLGRP_MAINCLK_CNT), + CLKMGR_MAINPLLGRP_DBGATCLK_CNT_SET( + CONFIG_HPS_MAINPLLGRP_DBGATCLK_CNT), + CLKMGR_MAINPLLGRP_MAINQSPICLK_CNT_SET( + CONFIG_HPS_MAINPLLGRP_MAINQSPICLK_CNT), + CLKMGR_PERPLLGRP_PERNANDSDMMCCLK_CNT_SET( + CONFIG_HPS_MAINPLLGRP_MAINNANDSDMMCCLK_CNT), + CLKMGR_MAINPLLGRP_CFGS2FUSER0CLK_CNT_SET( + CONFIG_HPS_MAINPLLGRP_CFGS2FUSER0CLK_CNT), + CLKMGR_MAINPLLGRP_MAINDIV_L3MPCLK_SET( + CONFIG_HPS_MAINPLLGRP_MAINDIV_L3MPCLK) | + CLKMGR_MAINPLLGRP_MAINDIV_L3SPCLK_SET( + CONFIG_HPS_MAINPLLGRP_MAINDIV_L3SPCLK) | + CLKMGR_MAINPLLGRP_MAINDIV_L4MPCLK_SET( + CONFIG_HPS_MAINPLLGRP_MAINDIV_L4MPCLK) | + CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_SET( + CONFIG_HPS_MAINPLLGRP_MAINDIV_L4SPCLK), + CLKMGR_MAINPLLGRP_DBGDIV_DBGATCLK_SET( + CONFIG_HPS_MAINPLLGRP_DBGDIV_DBGATCLK) | + CLKMGR_MAINPLLGRP_DBGDIV_DBGCLK_SET( + CONFIG_HPS_MAINPLLGRP_DBGDIV_DBGCLK), + CLKMGR_MAINPLLGRP_TRACEDIV_TRACECLK_SET( + CONFIG_HPS_MAINPLLGRP_TRACEDIV_TRACECLK), + CLKMGR_MAINPLLGRP_L4SRC_L4MP_SET( + CONFIG_HPS_MAINPLLGRP_L4SRC_L4MP) | + CLKMGR_MAINPLLGRP_L4SRC_L4SP_SET( + CONFIG_HPS_MAINPLLGRP_L4SRC_L4SP), + + /* peripheral group */ + PERI_VCO_BASE, + CLKMGR_PERPLLGRP_EMAC0CLK_CNT_SET( + CONFIG_HPS_PERPLLGRP_EMAC0CLK_CNT), + CLKMGR_PERPLLGRP_EMAC1CLK_CNT_SET( + CONFIG_HPS_PERPLLGRP_EMAC1CLK_CNT), + CLKMGR_PERPLLGRP_PERQSPICLK_CNT_SET( + CONFIG_HPS_PERPLLGRP_PERQSPICLK_CNT), + CLKMGR_PERPLLGRP_PERNANDSDMMCCLK_CNT_SET( + CONFIG_HPS_PERPLLGRP_PERNANDSDMMCCLK_CNT), + CLKMGR_PERPLLGRP_PERBASECLK_CNT_SET( + CONFIG_HPS_PERPLLGRP_PERBASECLK_CNT), + CLKMGR_PERPLLGRP_S2FUSER1CLK_CNT_SET( + CONFIG_HPS_PERPLLGRP_S2FUSER1CLK_CNT), + CLKMGR_PERPLLGRP_DIV_USBCLK_SET( + CONFIG_HPS_PERPLLGRP_DIV_USBCLK) | + CLKMGR_PERPLLGRP_DIV_SPIMCLK_SET( + CONFIG_HPS_PERPLLGRP_DIV_SPIMCLK) | + CLKMGR_PERPLLGRP_DIV_CAN0CLK_SET( + CONFIG_HPS_PERPLLGRP_DIV_CAN0CLK) | + CLKMGR_PERPLLGRP_DIV_CAN1CLK_SET( + CONFIG_HPS_PERPLLGRP_DIV_CAN1CLK), + CLKMGR_PERPLLGRP_GPIODIV_GPIODBCLK_SET( + CONFIG_HPS_PERPLLGRP_GPIODIV_GPIODBCLK), + CLKMGR_PERPLLGRP_SRC_QSPI_SET( + CONFIG_HPS_PERPLLGRP_SRC_QSPI) | + CLKMGR_PERPLLGRP_SRC_NAND_SET( + CONFIG_HPS_PERPLLGRP_SRC_NAND) | + CLKMGR_PERPLLGRP_SRC_SDMMC_SET( + CONFIG_HPS_PERPLLGRP_SRC_SDMMC), + + /* sdram pll group */ + SDR_VCO_BASE, + CLKMGR_SDRPLLGRP_DDRDQSCLK_PHASE_SET( + CONFIG_HPS_SDRPLLGRP_DDRDQSCLK_PHASE) | + CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_SET( + CONFIG_HPS_SDRPLLGRP_DDRDQSCLK_CNT), + CLKMGR_SDRPLLGRP_DDR2XDQSCLK_PHASE_SET( + CONFIG_HPS_SDRPLLGRP_DDR2XDQSCLK_PHASE) | + CLKMGR_SDRPLLGRP_DDR2XDQSCLK_CNT_SET( + CONFIG_HPS_SDRPLLGRP_DDR2XDQSCLK_CNT), + CLKMGR_SDRPLLGRP_DDRDQCLK_PHASE_SET( + CONFIG_HPS_SDRPLLGRP_DDRDQCLK_PHASE) | + CLKMGR_SDRPLLGRP_DDRDQCLK_CNT_SET( + CONFIG_HPS_SDRPLLGRP_DDRDQCLK_CNT), + CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_SET( + CONFIG_HPS_SDRPLLGRP_S2FUSER2CLK_PHASE) | + CLKMGR_SDRPLLGRP_S2FUSER2CLK_CNT_SET( + CONFIG_HPS_SDRPLLGRP_S2FUSER2CLK_CNT), + }; + + debug("Freezing all I/O banks\n"); + /* freeze all IO banks */ + sys_mgr_frzctrl_freeze_req(); + + debug("Reconfigure Clock Manager\n"); + /* reconfigure the PLLs */ + cm_basic_init(&cm_default_cfg); + + /* configure the pin muxing through system manager */ + sysmgr_pinmux_init(); +#endif /* CONFIG_SOCFPGA_VIRTUAL_TARGET */ + + /* de-assert reset for peripherals and bridges based on handoff */ + reset_deassert_peripherals_handoff(); + + debug("Unfreezing/Thaw all I/O banks\n"); + /* unfreeze / thaw all IO banks */ + sys_mgr_frzctrl_thaw_req(); + + /* enable console uart printing */ + preloader_console_init(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/system_manager.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/system_manager.c new file mode 100644 index 000000000..d96521ba0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/system_manager.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2013 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/system_manager.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Configure all the pin muxes + */ +void sysmgr_pinmux_init(void) +{ + unsigned long offset = CONFIG_SYSMGR_PINMUXGRP_OFFSET; + + const unsigned long *pval = sys_mgr_init_table; + unsigned long i; + + for (i = 0; i < ARRAY_SIZE(sys_mgr_init_table); + i++, offset += sizeof(unsigned long)) { + writel(*pval++, (SOCFPGA_SYSMGR_ADDRESS + offset)); + } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/timer.c new file mode 100644 index 000000000..58fc789e6 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/timer.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/timer.h> + +static const struct socfpga_timer *timer_base = (void *)CONFIG_SYS_TIMERBASE; + +/* + * Timer initialization + */ +int timer_init(void) +{ + writel(TIMER_LOAD_VAL, &timer_base->load_val); + writel(TIMER_LOAD_VAL, &timer_base->curr_val); + writel(readl(&timer_base->ctrl) | 0x3, &timer_base->ctrl); + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/u-boot-spl.lds b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/u-boot-spl.lds new file mode 100644 index 000000000..4282beb39 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/socfpga/u-boot-spl.lds @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2012 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +MEMORY { .sdram : ORIGIN = (0), LENGTH = (0xffffffff) } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + arch/arm/cpu/armv7/start.o (.text*) + *(.text*) + } >.sdram + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } >.sdram + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sdram + + . = ALIGN(4); + __image_copy_end = .; + + .end : + { + *(.__end) + } + + .bss : { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } >.sdram + + . = ALIGN(8); + __malloc_start = .; + . = . + CONFIG_SPL_MALLOC_SIZE; + __malloc_end = .; + + . = . + CONFIG_SPL_STACK_SIZE; + . = ALIGN(8); + __stack_start = .; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/start.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/start.S new file mode 100644 index 000000000..27be451a8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/start.S @@ -0,0 +1,444 @@ +/* + * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core + * + * Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com> + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> +#include <asm/system.h> +#include <linux/linkage.h> + +.globl _start +_start: b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq +#ifdef CONFIG_SPL_BUILD +_undefined_instruction: .word _undefined_instruction +_software_interrupt: .word _software_interrupt +_prefetch_abort: .word _prefetch_abort +_data_abort: .word _data_abort +_not_used: .word _not_used +_irq: .word _irq +_fiq: .word _fiq +_pad: .word 0x12345678 /* now 16*4=64 */ +#else +.globl _undefined_instruction +_undefined_instruction: .word undefined_instruction +.globl _software_interrupt +_software_interrupt: .word software_interrupt +.globl _prefetch_abort +_prefetch_abort: .word prefetch_abort +.globl _data_abort +_data_abort: .word data_abort +.globl _not_used +_not_used: .word not_used +.globl _irq +_irq: .word irq +.globl _fiq +_fiq: .word fiq +_pad: .word 0x12345678 /* now 16*4=64 */ +#endif /* CONFIG_SPL_BUILD */ + +.global _end_vect +_end_vect: + + .balignl 16,0xdeadbeef +/************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + *************************************************************************/ + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +reset: + bl save_boot_params + /* + * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode, + * except if in HYP mode already + */ + mrs r0, cpsr + and r1, r0, #0x1f @ mask mode bits + teq r1, #0x1a @ test for HYP mode + bicne r0, r0, #0x1f @ clear all mode bits + orrne r0, r0, #0x13 @ set SVC mode + orr r0, r0, #0xc0 @ disable FIQ and IRQ + msr cpsr,r0 + +/* + * Setup vector: + * (OMAP4 spl TEXT_BASE is not 32 byte aligned. + * Continue to use ROM code vector only in OMAP4 spl) + */ +#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD)) + /* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */ + mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register + bic r0, #CR_V @ V = 0 + mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register + + /* Set vector address in CP15 VBAR register */ + ldr r0, =_start + mcr p15, 0, r0, c12, c0, 0 @Set VBAR +#endif + + /* the mask ROM code should have PLL and others stable */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_cp15 + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + +ENTRY(c_runtime_cpu_setup) +/* + * If I-cache is enabled invalidate it + */ +#ifndef CONFIG_SYS_ICACHE_OFF + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB +#endif +/* + * Move vector table + */ + /* Set vector address in CP15 VBAR register */ + ldr r0, =_start + mcr p15, 0, r0, c12, c0, 0 @Set VBAR + + bx lr + +ENDPROC(c_runtime_cpu_setup) + +/************************************************************************* + * + * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) + * __attribute__((weak)); + * + * Stack pointer is not yet initialized at this moment + * Don't save anything to stack even if compiled with -O0 + * + *************************************************************************/ +ENTRY(save_boot_params) + bx lr @ back to my caller +ENDPROC(save_boot_params) + .weak save_boot_params + +/************************************************************************* + * + * cpu_init_cp15 + * + * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless + * CONFIG_SYS_ICACHE_OFF is defined. + * + *************************************************************************/ +ENTRY(cpu_init_cp15) + /* + * Invalidate L1 I/D + */ + mov r0, #0 @ set up for MCR + mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002000 @ clear bits 13 (--V-) + bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) + orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB +#ifdef CONFIG_SYS_ICACHE_OFF + bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache +#else + orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache +#endif + mcr p15, 0, r0, c1, c0, 0 + +#ifdef CONFIG_ARM_ERRATA_716044 + mrc p15, 0, r0, c1, c0, 0 @ read system control register + orr r0, r0, #1 << 11 @ set bit #11 + mcr p15, 0, r0, c1, c0, 0 @ write system control register +#endif + +#if (defined(CONFIG_ARM_ERRATA_742230) || defined(CONFIG_ARM_ERRATA_794072)) + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 4 @ set bit #4 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif + +#ifdef CONFIG_ARM_ERRATA_743622 + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 6 @ set bit #6 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif + +#ifdef CONFIG_ARM_ERRATA_751472 + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 11 @ set bit #11 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif +#ifdef CONFIG_ARM_ERRATA_761320 + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 21 @ set bit #21 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif + + mov pc, lr @ back to my caller +ENDPROC(cpu_init_cp15) + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +/************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + *************************************************************************/ +ENTRY(cpu_init_crit) + /* + * Jump to board specific initialization... + * The Mask ROM will have already initialized + * basic memory. Go here to bump up clock rate and handle + * wake up conditions. + */ + b lowlevel_init @ go setup pll,mux,memory +ENDPROC(cpu_init_crit) +#endif + +#ifndef CONFIG_SPL_BUILD +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current + @ user stack + stmia sp, {r0 - r12} @ Save user registers (now in + @ svc mode) r0-r12 + ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort + @ stack + ldmia r2, {r2 - r3} @ get values for "aborted" pc + @ and cpsr (into parm regs) + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp @ save current stack into r0 + @ (param register) + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC @ !! R8 NEEDS to be saved !! + @ a reserved stack spot would + @ be good. + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into + @ cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter + @ in banked mode) + + str lr, [r13] @ save caller lr in position 0 + @ of saved stack + mrs lr, spsr @ get the spsr + str lr, [r13, #4] @ save spsr in position 1 of + @ saved stack + + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 @ switch modes, make sure + @ moves will execute + mov lr, pc @ capture return pc + movs pc, lr @ jump to next instruction & + @ switch modes. + .endm + + .macro get_bad_stack_swi + sub r13, r13, #4 @ space on current stack for + @ scratch reg. + str r0, [r13] @ save R0's value. + ldr r0, IRQ_STACK_START_IN @ get data regions start + @ spots for abort stack + str lr, [r0] @ save caller lr in position 0 + @ of saved stack + mrs lr, spsr @ get the spsr + str lr, [r0, #4] @ save spsr in position 1 of + @ saved stack + ldr lr, [r0] @ restore lr + ldr r0, [r13] @ restore r0 + add r13, r13, #4 @ pop stack entry + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack_swi + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effective fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif /* CONFIG_USE_IRQ */ +#endif /* CONFIG_SPL_BUILD */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/syslib.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/syslib.c new file mode 100644 index 000000000..4ae259606 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/syslib.c @@ -0,0 +1,43 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> + +/************************************************************ + * sdelay() - simple spin loop. Will be constant time as + * its generally used in bypass conditions only. This + * is necessary until timers are accessible. + * + * not inline to increase chances its in cache when called + *************************************************************/ +void sdelay(unsigned long loops) +{ + __asm__ volatile ("1:\n" "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0"(loops)); +} + +/********************************************************************* + * wait_on_value() - common routine to allow waiting for changes in + * volatile regs. + *********************************************************************/ +u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr, + u32 bound) +{ + u32 i = 0, val; + do { + ++i; + val = readl((u32)read_addr) & read_bit_mask; + if (val == match_value) + return 1; + if (i == bound) + return 0; + } while (1); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra-common/Makefile new file mode 100644 index 000000000..463c260f1 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra-common/Makefile @@ -0,0 +1,10 @@ +# +# (C) Copyright 2010,2011 Nvidia Corporation. +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra-common/cmd_enterrcm.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra-common/cmd_enterrcm.c new file mode 100644 index 000000000..a94ec93e7 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra-common/cmd_enterrcm.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * Derived from code (arch/arm/lib/reset.c) that is: + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2004 + * DAVE Srl + * http://www.dave-tech.it + * http://www.wawnet.biz + * mailto:info@wawnet.biz + * + * (C) Copyright 2004 Texas Insturments + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/pmc.h> + +static int do_enterrcm(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + puts("Entering RCM...\n"); + udelay(50000); + + pmc->pmc_scratch0 = 2; + disable_interrupts(); + reset_cpu(0); + + return 0; +} + +U_BOOT_CMD( + enterrcm, 1, 0, do_enterrcm, + "reset Tegra and enter USB Recovery Mode", + "" +); diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra114/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra114/Makefile new file mode 100644 index 000000000..77e231959 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra114/Makefile @@ -0,0 +1,21 @@ +# +# Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# necessary to create built-in.o +obj- := __dummy__.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra124/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra124/Makefile new file mode 100644 index 000000000..9478d447d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra124/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2013-2014 +# NVIDIA Corporation <www.nvidia.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# necessary to create built-in.o +obj- := __dummy__.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra20/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra20/Makefile new file mode 100644 index 000000000..9b4295c72 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra20/Makefile @@ -0,0 +1,11 @@ +# +# (C) Copyright 2010,2011 Nvidia Corporation. +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_PWM_TEGRA) += pwm.o +obj-$(CONFIG_VIDEO_TEGRA) += display.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra20/display.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra20/display.c new file mode 100644 index 000000000..488f0c639 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra20/display.c @@ -0,0 +1,393 @@ +/* + * (C) Copyright 2010 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/tegra.h> +#include <asm/arch/display.h> +#include <asm/arch/dc.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/timer.h> + +static struct fdt_disp_config config; + +static void update_window(struct dc_ctlr *dc, struct disp_ctl_win *win) +{ + unsigned h_dda, v_dda; + unsigned long val; + + val = readl(&dc->cmd.disp_win_header); + val |= WINDOW_A_SELECT; + writel(val, &dc->cmd.disp_win_header); + + writel(win->fmt, &dc->win.color_depth); + + clrsetbits_le32(&dc->win.byte_swap, BYTE_SWAP_MASK, + BYTE_SWAP_NOSWAP << BYTE_SWAP_SHIFT); + + val = win->out_x << H_POSITION_SHIFT; + val |= win->out_y << V_POSITION_SHIFT; + writel(val, &dc->win.pos); + + val = win->out_w << H_SIZE_SHIFT; + val |= win->out_h << V_SIZE_SHIFT; + writel(val, &dc->win.size); + + val = (win->w * win->bpp / 8) << H_PRESCALED_SIZE_SHIFT; + val |= win->h << V_PRESCALED_SIZE_SHIFT; + writel(val, &dc->win.prescaled_size); + + writel(0, &dc->win.h_initial_dda); + writel(0, &dc->win.v_initial_dda); + + h_dda = (win->w * 0x1000) / max(win->out_w - 1, 1); + v_dda = (win->h * 0x1000) / max(win->out_h - 1, 1); + + val = h_dda << H_DDA_INC_SHIFT; + val |= v_dda << V_DDA_INC_SHIFT; + writel(val, &dc->win.dda_increment); + + writel(win->stride, &dc->win.line_stride); + writel(0, &dc->win.buf_stride); + + val = WIN_ENABLE; + if (win->bpp < 24) + val |= COLOR_EXPAND; + writel(val, &dc->win.win_opt); + + writel((unsigned long)win->phys_addr, &dc->winbuf.start_addr); + writel(win->x, &dc->winbuf.addr_h_offset); + writel(win->y, &dc->winbuf.addr_v_offset); + + writel(0xff00, &dc->win.blend_nokey); + writel(0xff00, &dc->win.blend_1win); + + val = GENERAL_ACT_REQ | WIN_A_ACT_REQ; + val |= GENERAL_UPDATE | WIN_A_UPDATE; + writel(val, &dc->cmd.state_ctrl); +} + +static void write_pair(struct fdt_disp_config *config, int item, u32 *reg) +{ + writel(config->horiz_timing[item] | + (config->vert_timing[item] << 16), reg); +} + +static int update_display_mode(struct dc_disp_reg *disp, + struct fdt_disp_config *config) +{ + unsigned long val; + unsigned long rate; + unsigned long div; + + writel(0x0, &disp->disp_timing_opt); + write_pair(config, FDT_LCD_TIMING_REF_TO_SYNC, &disp->ref_to_sync); + write_pair(config, FDT_LCD_TIMING_SYNC_WIDTH, &disp->sync_width); + write_pair(config, FDT_LCD_TIMING_BACK_PORCH, &disp->back_porch); + write_pair(config, FDT_LCD_TIMING_FRONT_PORCH, &disp->front_porch); + + writel(config->width | (config->height << 16), &disp->disp_active); + + val = DE_SELECT_ACTIVE << DE_SELECT_SHIFT; + val |= DE_CONTROL_NORMAL << DE_CONTROL_SHIFT; + writel(val, &disp->data_enable_opt); + + val = DATA_FORMAT_DF1P1C << DATA_FORMAT_SHIFT; + val |= DATA_ALIGNMENT_MSB << DATA_ALIGNMENT_SHIFT; + val |= DATA_ORDER_RED_BLUE << DATA_ORDER_SHIFT; + writel(val, &disp->disp_interface_ctrl); + + /* + * The pixel clock divider is in 7.1 format (where the bottom bit + * represents 0.5). Here we calculate the divider needed to get from + * the display clock (typically 600MHz) to the pixel clock. We round + * up or down as requried. + */ + rate = clock_get_periph_rate(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL); + div = ((rate * 2 + config->pixel_clock / 2) / config->pixel_clock) - 2; + debug("Display clock %lu, divider %lu\n", rate, div); + + writel(0x00010001, &disp->shift_clk_opt); + + val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT; + val |= div << SHIFT_CLK_DIVIDER_SHIFT; + writel(val, &disp->disp_clk_ctrl); + + return 0; +} + +/* Start up the display and turn on power to PWMs */ +static void basic_init(struct dc_cmd_reg *cmd) +{ + u32 val; + + writel(0x00000100, &cmd->gen_incr_syncpt_ctrl); + writel(0x0000011a, &cmd->cont_syncpt_vsync); + writel(0x00000000, &cmd->int_type); + writel(0x00000000, &cmd->int_polarity); + writel(0x00000000, &cmd->int_mask); + writel(0x00000000, &cmd->int_enb); + + val = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE; + val |= PW3_ENABLE | PW4_ENABLE | PM0_ENABLE; + val |= PM1_ENABLE; + writel(val, &cmd->disp_pow_ctrl); + + val = readl(&cmd->disp_cmd); + val |= CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT; + writel(val, &cmd->disp_cmd); +} + +static void basic_init_timer(struct dc_disp_reg *disp) +{ + writel(0x00000020, &disp->mem_high_pri); + writel(0x00000001, &disp->mem_high_pri_timer); +} + +static const u32 rgb_enb_tab[PIN_REG_COUNT] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +static const u32 rgb_polarity_tab[PIN_REG_COUNT] = { + 0x00000000, + 0x01000000, + 0x00000000, + 0x00000000, +}; + +static const u32 rgb_data_tab[PIN_REG_COUNT] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +static const u32 rgb_sel_tab[PIN_OUTPUT_SEL_COUNT] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00210222, + 0x00002200, + 0x00020000, +}; + +static void rgb_enable(struct dc_com_reg *com) +{ + int i; + + for (i = 0; i < PIN_REG_COUNT; i++) { + writel(rgb_enb_tab[i], &com->pin_output_enb[i]); + writel(rgb_polarity_tab[i], &com->pin_output_polarity[i]); + writel(rgb_data_tab[i], &com->pin_output_data[i]); + } + + for (i = 0; i < PIN_OUTPUT_SEL_COUNT; i++) + writel(rgb_sel_tab[i], &com->pin_output_sel[i]); +} + +int setup_window(struct disp_ctl_win *win, struct fdt_disp_config *config) +{ + win->x = 0; + win->y = 0; + win->w = config->width; + win->h = config->height; + win->out_x = 0; + win->out_y = 0; + win->out_w = config->width; + win->out_h = config->height; + win->phys_addr = config->frame_buffer; + win->stride = config->width * (1 << config->log2_bpp) / 8; + debug("%s: depth = %d\n", __func__, config->log2_bpp); + switch (config->log2_bpp) { + case 5: + case 24: + win->fmt = COLOR_DEPTH_R8G8B8A8; + win->bpp = 32; + break; + case 4: + win->fmt = COLOR_DEPTH_B5G6R5; + win->bpp = 16; + break; + + default: + debug("Unsupported LCD bit depth"); + return -1; + } + + return 0; +} + +struct fdt_disp_config *tegra_display_get_config(void) +{ + return config.valid ? &config : NULL; +} + +static void debug_timing(const char *name, unsigned int timing[]) +{ +#ifdef DEBUG + int i; + + debug("%s timing: ", name); + for (i = 0; i < FDT_LCD_TIMING_COUNT; i++) + debug("%d ", timing[i]); + debug("\n"); +#endif +} + +/** + * Decode panel information from the fdt, according to a standard binding + * + * @param blob fdt blob + * @param node offset of fdt node to read from + * @param config structure to store fdt config into + * @return 0 if ok, -ve on error + */ +static int tegra_decode_panel(const void *blob, int node, + struct fdt_disp_config *config) +{ + int front, back, ref; + + config->width = fdtdec_get_int(blob, node, "xres", -1); + config->height = fdtdec_get_int(blob, node, "yres", -1); + config->pixel_clock = fdtdec_get_int(blob, node, "clock", 0); + if (!config->pixel_clock || config->width == -1 || + config->height == -1) { + debug("%s: Pixel parameters missing\n", __func__); + return -FDT_ERR_NOTFOUND; + } + + back = fdtdec_get_int(blob, node, "left-margin", -1); + front = fdtdec_get_int(blob, node, "right-margin", -1); + ref = fdtdec_get_int(blob, node, "hsync-len", -1); + if ((back | front | ref) == -1) { + debug("%s: Horizontal parameters missing\n", __func__); + return -FDT_ERR_NOTFOUND; + } + + /* Use a ref-to-sync of 1 always, and take this from the front porch */ + config->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; + config->horiz_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; + config->horiz_timing[FDT_LCD_TIMING_BACK_PORCH] = back; + config->horiz_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - + config->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC]; + debug_timing("horiz", config->horiz_timing); + + back = fdtdec_get_int(blob, node, "upper-margin", -1); + front = fdtdec_get_int(blob, node, "lower-margin", -1); + ref = fdtdec_get_int(blob, node, "vsync-len", -1); + if ((back | front | ref) == -1) { + debug("%s: Vertical parameters missing\n", __func__); + return -FDT_ERR_NOTFOUND; + } + + config->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; + config->vert_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; + config->vert_timing[FDT_LCD_TIMING_BACK_PORCH] = back; + config->vert_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - + config->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC]; + debug_timing("vert", config->vert_timing); + + return 0; +} + +/** + * Decode the display controller information from the fdt. + * + * @param blob fdt blob + * @param config structure to store fdt config into + * @return 0 if ok, -ve on error + */ +static int tegra_display_decode_config(const void *blob, + struct fdt_disp_config *config) +{ + int node, rgb; + int bpp, bit; + + /* TODO: Support multiple controllers */ + node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_DC); + if (node < 0) { + debug("%s: Cannot find display controller node in fdt\n", + __func__); + return node; + } + config->disp = (struct disp_ctlr *)fdtdec_get_addr(blob, node, "reg"); + if (!config->disp) { + debug("%s: No display controller address\n", __func__); + return -1; + } + + rgb = fdt_subnode_offset(blob, node, "rgb"); + + config->panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); + if (!config->panel_node < 0) { + debug("%s: Cannot find panel information\n", __func__); + return -1; + } + + if (tegra_decode_panel(blob, config->panel_node, config)) { + debug("%s: Failed to decode panel information\n", __func__); + return -1; + } + + bpp = fdtdec_get_int(blob, config->panel_node, "nvidia,bits-per-pixel", + -1); + bit = ffs(bpp) - 1; + if (bpp == (1 << bit)) + config->log2_bpp = bit; + else + config->log2_bpp = bpp; + if (bpp == -1) { + debug("%s: Pixel bpp parameters missing\n", __func__); + return -FDT_ERR_NOTFOUND; + } + config->bpp = bpp; + + config->valid = 1; /* we have a valid configuration */ + + return 0; +} + +int tegra_display_probe(const void *blob, void *default_lcd_base) +{ + struct disp_ctl_win window; + struct dc_ctlr *dc; + + if (tegra_display_decode_config(blob, &config)) + return -1; + + config.frame_buffer = (u32)default_lcd_base; + + dc = (struct dc_ctlr *)config.disp; + + /* + * A header file for clock constants was NAKed upstream. + * TODO: Put this into the FDT and fdt_lcd struct when we have clock + * support there + */ + clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_PERIPH, + 144 * 1000000); + clock_start_periph_pll(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL, + 600 * 1000000); + basic_init(&dc->cmd); + basic_init_timer(&dc->disp); + rgb_enable(&dc->com); + + if (config.pixel_clock) + update_display_mode(&dc->disp, &config); + + if (setup_window(&window, &config)) + return -1; + + update_window(dc, &window); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra20/pwm.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra20/pwm.c new file mode 100644 index 000000000..5b886363f --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra20/pwm.c @@ -0,0 +1,86 @@ +/* + * Tegra2 pulse width frequency modulator definitions + * + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fdtdec.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/pwm.h> + +struct pwm_info { + struct pwm_ctlr *pwm; /* Registers for our pwm controller */ + int pwm_node; /* PWM device tree node */ +} local; + +void pwm_enable(unsigned channel, int rate, int pulse_width, int freq_divider) +{ + u32 reg; + + assert(channel < PWM_NUM_CHANNELS); + + /* TODO: Can we use clock_adjust_periph_pll_div() here? */ + clock_start_periph_pll(PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ, rate); + + reg = PWM_ENABLE_MASK; + reg |= pulse_width << PWM_WIDTH_SHIFT; + reg |= freq_divider << PWM_DIVIDER_SHIFT; + writel(reg, &local.pwm[channel].control); + debug("%s: channel=%d, rate=%d\n", __func__, channel, rate); +} + +int pwm_request(const void *blob, int node, const char *prop_name) +{ + int pwm_node; + u32 data[3]; + + if (fdtdec_get_int_array(blob, node, prop_name, data, + ARRAY_SIZE(data))) { + debug("%s: Cannot decode PWM property '%s'\n", __func__, + prop_name); + return -1; + } + + pwm_node = fdt_node_offset_by_phandle(blob, data[0]); + if (pwm_node != local.pwm_node) { + debug("%s: PWM property '%s' phandle %d not recognised" + "- expecting %d\n", __func__, prop_name, data[0], + local.pwm_node); + return -1; + } + if (data[1] >= PWM_NUM_CHANNELS) { + debug("%s: PWM property '%s': invalid channel %u\n", __func__, + prop_name, data[1]); + return -1; + } + + /* + * TODO: We could maintain a list of requests, but it might not be + * worth it for U-Boot. + */ + return data[1]; +} + +int pwm_init(const void *blob) +{ + local.pwm_node = fdtdec_next_compatible(blob, 0, + COMPAT_NVIDIA_TEGRA20_PWM); + if (local.pwm_node < 0) { + debug("%s: Cannot find device tree node\n", __func__); + return -1; + } + + local.pwm = (struct pwm_ctlr *)fdtdec_get_addr(blob, local.pwm_node, + "reg"); + if (local.pwm == (struct pwm_ctlr *)FDT_ADDR_T_NONE) { + debug("%s: Cannot find pwm reg address\n", __func__); + return -1; + } + debug("Tegra PWM at %p, node %d\n", local.pwm, local.pwm_node); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra30/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra30/Makefile new file mode 100644 index 000000000..413eba102 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/tegra30/Makefile @@ -0,0 +1,21 @@ +# +# Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# necessary to create built-in.o +obj- := __dummy__.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/Makefile new file mode 100644 index 000000000..fad9d4ae3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := timer.o clock.o prcmu.o cpu.o +obj-y += lowlevel.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/clock.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/clock.c new file mode 100644 index 000000000..1e3b3d520 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/clock.c @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2009 ST-Ericsson + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct clkrst { + unsigned int pcken; + unsigned int pckdis; + unsigned int kcken; + unsigned int kckdis; +}; + +static unsigned int clkrst_base[] = { + U8500_CLKRST1_BASE, + U8500_CLKRST2_BASE, + U8500_CLKRST3_BASE, + 0, + U8500_CLKRST5_BASE, + U8500_CLKRST6_BASE, + U8500_CLKRST7_BASE, /* ED only */ +}; + +/* Turn on peripheral clock at PRCC level */ +void u8500_clock_enable(int periph, int cluster, int kern) +{ + struct clkrst *clkrst = (struct clkrst *) clkrst_base[periph - 1]; + + if (kern != -1) + writel(1 << kern, &clkrst->kcken); + + if (cluster != -1) + writel(1 << cluster, &clkrst->pcken); +} + +void db8500_clocks_init(void) +{ + /* + * Enable all clocks. This is u-boot, we can enable it all. There is no + * powersave in u-boot. + */ + + u8500_clock_enable(1, 9, -1); /* GPIO0 */ + u8500_clock_enable(2, 11, -1);/* GPIO1 */ + u8500_clock_enable(3, 8, -1); /* GPIO2 */ + u8500_clock_enable(5, 1, -1); /* GPIO3 */ + u8500_clock_enable(3, 6, 6); /* UART2 */ + u8500_clock_enable(3, 3, 3); /* I2C0 */ + u8500_clock_enable(1, 5, 5); /* SDI0 */ + u8500_clock_enable(2, 4, 2); /* SDI4 */ + u8500_clock_enable(6, 6, -1); /* MTU0 */ + u8500_clock_enable(3, 4, 4); /* SDI2 */ + + /* + * Enabling clocks for all devices which are AMBA devices in the + * kernel. Otherwise they will not get probe()'d because the + * peripheral ID register will not be powered. + */ + + /* XXX: some of these differ between ED/V1 */ + + u8500_clock_enable(1, 1, 1); /* UART1 */ + u8500_clock_enable(1, 0, 0); /* UART0 */ + u8500_clock_enable(3, 2, 2); /* SSP1 */ + u8500_clock_enable(3, 1, 1); /* SSP0 */ + u8500_clock_enable(2, 8, -1); /* SPI0 */ + u8500_clock_enable(2, 5, 3); /* MSP2 */ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/cpu.c new file mode 100644 index 000000000..d8634bebb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/cpu.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2012 Linaro Limited + * Mathieu Poirier <mathieu.poirier@linaro.org> + * + * Based on original code from Joakim Axelsson at ST-Ericsson + * (C) Copyright 2010 ST-Ericsson + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/prcmu.h> +#include <asm/arch/clock.h> +#include <asm/arch/hardware.h> + +#include <asm/arch/hardware.h> + +#define CPUID_DB8500V1 0x411fc091 +#define CPUID_DB8500V2 0x412fc091 +#define ASICID_DB8500V11 0x008500A1 + +#define CACHE_CONTR_BASE 0xA0412000 +/* Cache controller register offsets + * as found in ARM's technical reference manual + */ +#define CACHE_INVAL_BY_WAY (CACHE_CONTR_BASE + 0x77C) +#define CACHE_LOCKDOWN_BY_D (CACHE_CONTR_BASE + 0X900) +#define CACHE_LOCKDOWN_BY_I (CACHE_CONTR_BASE + 0X904) + +static unsigned int read_asicid(void); + +static inline unsigned int read_cpuid(void) +{ + unsigned int val; + + /* Main ID register (MIDR) */ + asm("mrc p15, 0, %0, c0, c0, 0" + : "=r" (val) + : + : "cc"); + + return val; +} + +static int cpu_is_u8500v11(void) +{ + return read_asicid() == ASICID_DB8500V11; +} + +static int cpu_is_u8500v2(void) +{ + return read_cpuid() == CPUID_DB8500V2; +} + +static unsigned int read_asicid(void) +{ + unsigned int *address; + + if (cpu_is_u8500v2()) + address = (void *) U8500_ASIC_ID_LOC_V2; + else + address = (void *) U8500_ASIC_ID_LOC_ED_V1; + + return readl(address); +} + +void cpu_cache_initialization(void) +{ + unsigned int value; + /* invalidate all cache entries */ + writel(0xFFFF, CACHE_INVAL_BY_WAY); + + /* ways are set to '0' when they are totally + * cleaned and invalidated + */ + do { + value = readl(CACHE_INVAL_BY_WAY); + } while (value & 0xFF); + + /* Invalidate register 9 D and I lockdown */ + writel(0xFF, CACHE_LOCKDOWN_BY_D); + writel(0xFF, CACHE_LOCKDOWN_BY_I); +} + +#ifdef CONFIG_ARCH_CPU_INIT +/* + * SOC specific cpu init + */ +int arch_cpu_init(void) +{ + db8500_prcmu_init(); + db8500_clocks_init(); + + return 0; +} +#endif /* CONFIG_ARCH_CPU_INIT */ + +#ifdef CONFIG_MMC + +int u8500_mmc_power_init(void) +{ + int ret; + int enable, voltage; + int ab8500_revision; + + if (!cpu_is_u8500v11() && !cpu_is_u8500v2()) + return 0; + + /* Get AB8500 revision */ + ret = ab8500_read(AB8500_MISC, AB8500_REV_REG); + if (ret < 0) + goto out; + + ab8500_revision = ret; + + /* + * On v1.1 HREF boards (HREF+), Vaux3 needs to be enabled for the SD + * card to work. This is done by enabling the regulators in the AB8500 + * via PRCMU I2C transactions. + * + * This code is derived from the handling of AB8500_LDO_VAUX3 in + * ab8500_ldo_enable() and ab8500_ldo_disable() in Linux. + * + * Turn off and delay is required to have it work across soft reboots. + */ + + /* Turn off (read-modify-write) */ + ret = ab8500_read(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_REGU_REG); + if (ret < 0) + goto out; + + enable = ret; + + /* Turn off */ + ret = ab8500_write(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_REGU_REG, + enable & ~LDO_VAUX3_ENABLE_MASK); + if (ret < 0) + goto out; + + udelay(10 * 1000); + + /* Set the voltage to 2.91 V or 2.9 V without overriding VRF1 value */ + ret = ab8500_read(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_SEL_REG); + if (ret < 0) + goto out; + + voltage = ret; + + if (ab8500_revision < 0x20) { + voltage &= ~LDO_VAUX3_SEL_MASK; + voltage |= LDO_VAUX3_SEL_2V9; + } else { + voltage &= ~LDO_VAUX3_V2_SEL_MASK; + voltage |= LDO_VAUX3_V2_SEL_2V91; + } + + ret = ab8500_write(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_SEL_REG, voltage); + if (ret < 0) + goto out; + + /* Turn on the supply */ + enable &= ~LDO_VAUX3_ENABLE_MASK; + enable |= LDO_VAUX3_ENABLE_VAL; + + ret = ab8500_write(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_REGU_REG, enable); + +out: + return ret; +} +#endif /* CONFIG_MMC */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/lowlevel.S b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/lowlevel.S new file mode 100644 index 000000000..d3e392060 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/lowlevel.S @@ -0,0 +1,21 @@ +/* + * (C) Copyright 2011 ST-Ericsson + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <linux/linkage.h> + +ENTRY(lowlevel_init) + mov pc, lr +ENDPROC(lowlevel_init) + + .align 5 +ENTRY(reset_cpu) + ldr r0, =CFG_PRCMU_BASE + ldr r1, =0x1 + str r1, [r0, #0x228] +_loop_forever: + b _loop_forever +ENDPROC(reset_cpu) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/prcmu.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/prcmu.c new file mode 100644 index 000000000..26ffdc2e0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/prcmu.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2009 ST-Ericsson SA + * + * Adapted from the Linux version: + * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * NOTE: This currently does not support the I2C workaround access method. + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/types.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/prcmu.h> + +/* CPU mailbox registers */ +#define PRCMU_I2C_WRITE(slave) \ + (((slave) << 1) | I2CWRITE | (1 << 6)) +#define PRCMU_I2C_READ(slave) \ + (((slave) << 1) | I2CREAD | (1 << 6)) + +#define I2C_MBOX_BIT (1 << 5) + +static int prcmu_is_ready(void) +{ + int ready = readb(PRCM_XP70_CUR_PWR_STATE) == AP_EXECUTE; + if (!ready) + printf("PRCMU firmware not ready\n"); + return ready; +} + +static int wait_for_i2c_mbx_rdy(void) +{ + int timeout = 10000; + + if (readl(PRCM_ARM_IT1_VAL) & I2C_MBOX_BIT) { + printf("prcmu: warning i2c mailbox was not acked\n"); + /* clear mailbox 5 ack irq */ + writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); + } + + /* check any already on-going transaction */ + while ((readl(PRCM_MBOX_CPU_VAL) & I2C_MBOX_BIT) && timeout) + timeout--; + + if (timeout == 0) + return -1; + + return 0; +} + +static int wait_for_i2c_req_done(void) +{ + int timeout = 10000; + + /* Set an interrupt to XP70 */ + writel(I2C_MBOX_BIT, PRCM_MBOX_CPU_SET); + + /* wait for mailbox 5 (i2c) ack */ + while (!(readl(PRCM_ARM_IT1_VAL) & I2C_MBOX_BIT) && timeout) + timeout--; + + if (timeout == 0) + return -1; + + return 0; +} + +/** + * prcmu_i2c_read - PRCMU - 4500 communication using PRCMU I2C + * @reg: - db8500 register bank to be accessed + * @slave: - db8500 register to be accessed + * Returns: ACK_MB5 value containing the status + */ +int prcmu_i2c_read(u8 reg, u16 slave) +{ + uint8_t i2c_status; + uint8_t i2c_val; + int ret; + + if (!prcmu_is_ready()) + return -1; + + debug("\nprcmu_4500_i2c_read:bank=%x;reg=%x;\n", + reg, slave); + + ret = wait_for_i2c_mbx_rdy(); + if (ret) { + printf("prcmu_i2c_read: mailbox became not ready\n"); + return ret; + } + + /* prepare the data for mailbox 5 */ + writeb(PRCMU_I2C_READ(reg), PRCM_REQ_MB5_I2COPTYPE_REG); + writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS); + writeb(slave, PRCM_REQ_MB5_I2CSLAVE); + writeb(0, PRCM_REQ_MB5_I2CVAL); + + ret = wait_for_i2c_req_done(); + if (ret) { + printf("prcmu_i2c_read: mailbox request timed out\n"); + return ret; + } + + /* retrieve values */ + debug("ack-mb5:transfer status = %x\n", + readb(PRCM_ACK_MB5_STATUS)); + debug("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1); + debug("ack-mb5:slave_add = %x\n", + readb(PRCM_ACK_MB5_SLAVE)); + debug("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL)); + + i2c_status = readb(PRCM_ACK_MB5_STATUS); + i2c_val = readb(PRCM_ACK_MB5_VAL); + /* clear mailbox 5 ack irq */ + writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); + + if (i2c_status == I2C_RD_OK) + return i2c_val; + + printf("prcmu_i2c_read:read return status= %d\n", i2c_status); + return -1; +} + +/** + * prcmu_i2c_write - PRCMU-db8500 communication using PRCMU I2C + * @reg: - db8500 register bank to be accessed + * @slave: - db800 register to be written to + * @reg_data: - the data to write + * Returns: ACK_MB5 value containing the status + */ +int prcmu_i2c_write(u8 reg, u16 slave, u8 reg_data) +{ + uint8_t i2c_status; + int ret; + + if (!prcmu_is_ready()) + return -1; + + debug("\nprcmu_4500_i2c_write:bank=%x;reg=%x;\n", + reg, slave); + + ret = wait_for_i2c_mbx_rdy(); + if (ret) { + printf("prcmu_i2c_write: mailbox became not ready\n"); + return ret; + } + + /* prepare the data for mailbox 5 */ + writeb(PRCMU_I2C_WRITE(reg), PRCM_REQ_MB5_I2COPTYPE_REG); + writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS); + writeb(slave, PRCM_REQ_MB5_I2CSLAVE); + writeb(reg_data, PRCM_REQ_MB5_I2CVAL); + + ret = wait_for_i2c_req_done(); + if (ret) { + printf("prcmu_i2c_write: mailbox request timed out\n"); + return ret; + } + + /* retrieve values */ + debug("ack-mb5:transfer status = %x\n", + readb(PRCM_ACK_MB5_STATUS)); + debug("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1); + debug("ack-mb5:slave_add = %x\n", + readb(PRCM_ACK_MB5_SLAVE)); + debug("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL)); + + i2c_status = readb(PRCM_ACK_MB5_STATUS); + debug("\ni2c_status = %x\n", i2c_status); + /* clear mailbox 5 ack irq */ + writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); + + if (i2c_status == I2C_WR_OK) + return 0; + + printf("%s: i2c_status : 0x%x\n", __func__, i2c_status); + return -1; +} + +void u8500_prcmu_enable(u32 *reg) +{ + writel(readl(reg) | (1 << 8), reg); +} + +void db8500_prcmu_init(void) +{ + /* Enable timers */ + writel(1 << 17, PRCM_TCR); + + u8500_prcmu_enable((u32 *)PRCM_PER1CLK_MGT_REG); + u8500_prcmu_enable((u32 *)PRCM_PER2CLK_MGT_REG); + u8500_prcmu_enable((u32 *)PRCM_PER3CLK_MGT_REG); + /* PER4CLK does not exist */ + u8500_prcmu_enable((u32 *)PRCM_PER5CLK_MGT_REG); + u8500_prcmu_enable((u32 *)PRCM_PER6CLK_MGT_REG); + /* Only exists in ED but is always ok to write to */ + u8500_prcmu_enable((u32 *)PRCM_PER7CLK_MGT_REG); + + u8500_prcmu_enable((u32 *)PRCM_UARTCLK_MGT_REG); + u8500_prcmu_enable((u32 *)PRCM_I2CCLK_MGT_REG); + + u8500_prcmu_enable((u32 *)PRCM_SDMMCCLK_MGT_REG); + + /* Clean up the mailbox interrupts after pre-u-boot code. */ + writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/timer.c new file mode 100644 index 000000000..6b74e13d9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/timer.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2010 Linaro Limited + * John Rigby <john.rigby@linaro.org> + * + * Based on original from Linux kernel source and + * internal ST-Ericsson U-Boot source. + * (C) Copyright 2009 Alessandro Rubini + * (C) Copyright 2010 ST-Ericsson + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * The MTU device has some interrupt control registers + * followed by 4 timers. + */ + +/* The timers */ +struct u8500_mtu_timer { + u32 lr; /* Load value */ + u32 cv; /* Current value */ + u32 cr; /* Control reg */ + u32 bglr; /* ??? */ +}; + +/* The MTU that contains the timers */ +struct u8500_mtu { + u32 imsc; /* Interrupt mask set/clear */ + u32 ris; /* Raw interrupt status */ + u32 mis; /* Masked interrupt status */ + u32 icr; /* Interrupt clear register */ + struct u8500_mtu_timer pt[4]; +}; + +/* bits for the control register */ +#define MTU_CR_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR */ +#define MTU_CR_32BITS 0x02 + +#define MTU_CR_PRESCALE_1 0x00 +#define MTU_CR_PRESCALE_16 0x04 +#define MTU_CR_PRESCALE_256 0x08 +#define MTU_CR_PRESCALE_MASK 0x0c + +#define MTU_CR_PERIODIC 0x40 /* if 0 = free-running */ +#define MTU_CR_ENA 0x80 + +/* + * The MTU is clocked at 133 MHz by default. (V1 and later) + */ +#define TIMER_CLOCK (133 * 1000 * 1000 / 16) +#define COUNT_TO_USEC(x) ((x) * 16 / 133) +#define USEC_TO_COUNT(x) ((x) * 133 / 16) +#define TICKS_PER_HZ (TIMER_CLOCK / CONFIG_SYS_HZ) +#define TICKS_TO_HZ(x) ((x) / TICKS_PER_HZ) +#define TIMER_LOAD_VAL 0xffffffff + +/* + * MTU timer to use (from 0 to 3). + */ +#define MTU_TIMER 2 + +static struct u8500_mtu_timer *timer_base = + &((struct u8500_mtu *)U8500_MTU0_BASE_V1)->pt[MTU_TIMER]; + +/* macro to read the 32 bit timer: since it decrements, we invert read value */ +#define READ_TIMER() (~readl(&timer_base->cv)) + +/* Configure a free-running, auto-wrap counter with /16 prescaler */ +int timer_init(void) +{ + writel(MTU_CR_ENA | MTU_CR_PRESCALE_16 | MTU_CR_32BITS, + &timer_base->cr); + return 0; +} + +ulong get_timer_masked(void) +{ + /* current tick value */ + ulong now = TICKS_TO_HZ(READ_TIMER()); + + if (now >= gd->arch.lastinc) { /* normal (non rollover) */ + gd->arch.tbl += (now - gd->arch.lastinc); + } else { /* rollover */ + gd->arch.tbl += (TICKS_TO_HZ(TIMER_LOAD_VAL) - + gd->arch.lastinc) + now; + } + gd->arch.lastinc = now; + return gd->arch.tbl; +} + +/* Delay x useconds */ +void __udelay(ulong usec) +{ + long tmo = usec * (TIMER_CLOCK / 1000) / 1000; + ulong now, last = READ_TIMER(); + + while (tmo > 0) { + now = READ_TIMER(); + if (now > last) /* normal (non rollover) */ + tmo -= now - last; + else /* rollover */ + tmo -= TIMER_LOAD_VAL - last + now; + last = now; + } +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* + * Emulation of Power architecture long long timebase. + * + * TODO: Support gd->arch.tbu for real long long timebase. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * Emulation of Power architecture timebase. + * NB: Low resolution compared to Power tbclk. + */ +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/vf610/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/vf610/Makefile new file mode 100644 index 000000000..68cb756d6 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/vf610/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2013 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += generic.o +obj-y += timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/vf610/generic.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/vf610/generic.c new file mode 100644 index 000000000..a26d63ebe --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/vf610/generic.c @@ -0,0 +1,318 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/crm_regs.h> +#include <netdev.h> +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> +#endif + +#ifdef CONFIG_FSL_ESDHC +DECLARE_GLOBAL_DATA_PTR; +#endif + +#ifdef CONFIG_MXC_OCOTP +void enable_ocotp_clk(unsigned char enable) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 reg; + + reg = readl(&ccm->ccgr6); + if (enable) + reg |= CCM_CCGR6_OCOTP_CTRL_MASK; + else + reg &= ~CCM_CCGR6_OCOTP_CTRL_MASK; + writel(reg, &ccm->ccgr6); +} +#endif + +static u32 get_mcu_main_clk(void) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 ccm_ccsr, ccm_cacrr, armclk_div; + u32 sysclk_sel, pll_pfd_sel = 0; + u32 freq = 0; + + ccm_ccsr = readl(&ccm->ccsr); + sysclk_sel = ccm_ccsr & CCM_CCSR_SYS_CLK_SEL_MASK; + sysclk_sel >>= CCM_CCSR_SYS_CLK_SEL_OFFSET; + + ccm_cacrr = readl(&ccm->cacrr); + armclk_div = ccm_cacrr & CCM_CACRR_ARM_CLK_DIV_MASK; + armclk_div >>= CCM_CACRR_ARM_CLK_DIV_OFFSET; + armclk_div += 1; + + switch (sysclk_sel) { + case 0: + freq = FASE_CLK_FREQ; + break; + case 1: + freq = SLOW_CLK_FREQ; + break; + case 2: + pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL2_PFD_CLK_SEL_MASK; + pll_pfd_sel >>= CCM_CCSR_PLL2_PFD_CLK_SEL_OFFSET; + if (pll_pfd_sel == 0) + freq = PLL2_MAIN_FREQ; + else if (pll_pfd_sel == 1) + freq = PLL2_PFD1_FREQ; + else if (pll_pfd_sel == 2) + freq = PLL2_PFD2_FREQ; + else if (pll_pfd_sel == 3) + freq = PLL2_PFD3_FREQ; + else if (pll_pfd_sel == 4) + freq = PLL2_PFD4_FREQ; + break; + case 3: + freq = PLL2_MAIN_FREQ; + break; + case 4: + pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL1_PFD_CLK_SEL_MASK; + pll_pfd_sel >>= CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET; + if (pll_pfd_sel == 0) + freq = PLL1_MAIN_FREQ; + else if (pll_pfd_sel == 1) + freq = PLL1_PFD1_FREQ; + else if (pll_pfd_sel == 2) + freq = PLL1_PFD2_FREQ; + else if (pll_pfd_sel == 3) + freq = PLL1_PFD3_FREQ; + else if (pll_pfd_sel == 4) + freq = PLL1_PFD4_FREQ; + break; + case 5: + freq = PLL3_MAIN_FREQ; + break; + default: + printf("unsupported system clock select\n"); + } + + return freq / armclk_div; +} + +static u32 get_bus_clk(void) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 ccm_cacrr, busclk_div; + + ccm_cacrr = readl(&ccm->cacrr); + + busclk_div = ccm_cacrr & CCM_CACRR_BUS_CLK_DIV_MASK; + busclk_div >>= CCM_CACRR_BUS_CLK_DIV_OFFSET; + busclk_div += 1; + + return get_mcu_main_clk() / busclk_div; +} + +static u32 get_ipg_clk(void) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 ccm_cacrr, ipgclk_div; + + ccm_cacrr = readl(&ccm->cacrr); + + ipgclk_div = ccm_cacrr & CCM_CACRR_IPG_CLK_DIV_MASK; + ipgclk_div >>= CCM_CACRR_IPG_CLK_DIV_OFFSET; + ipgclk_div += 1; + + return get_bus_clk() / ipgclk_div; +} + +static u32 get_uart_clk(void) +{ + return get_ipg_clk(); +} + +static u32 get_sdhc_clk(void) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 ccm_cscmr1, ccm_cscdr2, sdhc_clk_sel, sdhc_clk_div; + u32 freq = 0; + + ccm_cscmr1 = readl(&ccm->cscmr1); + sdhc_clk_sel = ccm_cscmr1 & CCM_CSCMR1_ESDHC1_CLK_SEL_MASK; + sdhc_clk_sel >>= CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET; + + ccm_cscdr2 = readl(&ccm->cscdr2); + sdhc_clk_div = ccm_cscdr2 & CCM_CSCDR2_ESDHC1_CLK_DIV_MASK; + sdhc_clk_div >>= CCM_CSCDR2_ESDHC1_CLK_DIV_OFFSET; + sdhc_clk_div += 1; + + switch (sdhc_clk_sel) { + case 0: + freq = PLL3_MAIN_FREQ; + break; + case 1: + freq = PLL3_PFD3_FREQ; + break; + case 2: + freq = PLL1_PFD3_FREQ; + break; + case 3: + freq = get_bus_clk(); + break; + } + + return freq / sdhc_clk_div; +} + +u32 get_fec_clk(void) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 ccm_cscmr2, rmii_clk_sel; + u32 freq = 0; + + ccm_cscmr2 = readl(&ccm->cscmr2); + rmii_clk_sel = ccm_cscmr2 & CCM_CSCMR2_RMII_CLK_SEL_MASK; + rmii_clk_sel >>= CCM_CSCMR2_RMII_CLK_SEL_OFFSET; + + switch (rmii_clk_sel) { + case 0: + freq = ENET_EXTERNAL_CLK; + break; + case 1: + freq = AUDIO_EXTERNAL_CLK; + break; + case 2: + freq = PLL5_MAIN_FREQ; + break; + case 3: + freq = PLL5_MAIN_FREQ / 2; + break; + } + + return freq; +} + +static u32 get_i2c_clk(void) +{ + return get_ipg_clk(); +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return get_mcu_main_clk(); + case MXC_BUS_CLK: + return get_bus_clk(); + case MXC_IPG_CLK: + return get_ipg_clk(); + case MXC_UART_CLK: + return get_uart_clk(); + case MXC_ESDHC_CLK: + return get_sdhc_clk(); + case MXC_FEC_CLK: + return get_fec_clk(); + case MXC_I2C_CLK: + return get_i2c_clk(); + default: + break; + } + return -1; +} + +/* Dump some core clocks */ +int do_vf610_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + printf("\n"); + printf("cpu clock : %8d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("bus clock : %8d MHz\n", mxc_get_clock(MXC_BUS_CLK) / 1000000); + printf("ipg clock : %8d MHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000000); + + return 0; +} + +U_BOOT_CMD( + clocks, CONFIG_SYS_MAXARGS, 1, do_vf610_showclocks, + "display clocks", + "" +); + +#ifdef CONFIG_FEC_MXC +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[4]; + struct fuse_bank4_regs *fuse = + (struct fuse_bank4_regs *)bank->fuse_regs; + + u32 value = readl(&fuse->mac_addr0); + mac[0] = (value >> 8); + mac[1] = value; + + value = readl(&fuse->mac_addr1); + mac[2] = value >> 24; + mac[3] = value >> 16; + mac[4] = value >> 8; + mac[5] = value; +} +#endif + +#if defined(CONFIG_DISPLAY_CPUINFO) +static char *get_reset_cause(void) +{ + u32 cause; + struct src *src_regs = (struct src *)SRC_BASE_ADDR; + + cause = readl(&src_regs->srsr); + writel(cause, &src_regs->srsr); + cause &= 0xff; + + switch (cause) { + case 0x08: + return "WDOG"; + case 0x20: + return "JTAG HIGH-Z"; + case 0x80: + return "EXTERNAL RESET"; + case 0xfd: + return "POR"; + default: + return "unknown reset"; + } +} + +int print_cpuinfo(void) +{ + printf("CPU: Freescale Vybrid VF610 at %d MHz\n", + mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("Reset cause: %s\n", get_reset_cause()); + + return 0; +} +#endif + +int cpu_eth_init(bd_t *bis) +{ + int rc = -ENODEV; + +#if defined(CONFIG_FEC_MXC) + rc = fecmxc_initialize(bis); +#endif + + return rc; +} + +#ifdef CONFIG_FSL_ESDHC +int cpu_mmc_init(bd_t *bis) +{ + return fsl_esdhc_mmc_init(bis); +} +#endif + +int get_clocks(void) +{ +#ifdef CONFIG_FSL_ESDHC + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); +#endif + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/vf610/timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/vf610/timer.c new file mode 100644 index 000000000..e51c6c6a2 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/vf610/timer.c @@ -0,0 +1,90 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <div64.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> + +static struct pit_reg *cur_pit = (struct pit_reg *)PIT_BASE_ADDR; + +DECLARE_GLOBAL_DATA_PTR; + +#define TIMER_LOAD_VAL 0xffffffff + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, mxc_get_clock(MXC_IPG_CLK)); + + return tick; +} + +static inline unsigned long long us_to_tick(unsigned long long usec) +{ + usec = usec * mxc_get_clock(MXC_IPG_CLK) + 999999; + do_div(usec, 1000000); + + return usec; +} + +int timer_init(void) +{ + __raw_writel(0, &cur_pit->mcr); + + __raw_writel(TIMER_LOAD_VAL, &cur_pit->ldval1); + __raw_writel(0, &cur_pit->tctrl1); + __raw_writel(1, &cur_pit->tctrl1); + + gd->arch.tbl = 0; + gd->arch.tbu = 0; + + return 0; +} + +unsigned long long get_ticks(void) +{ + ulong now = TIMER_LOAD_VAL - __raw_readl(&cur_pit->cval1); + + /* 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; +} + +ulong get_timer_masked(void) +{ + return tick_to_time(get_ticks()); +} + +ulong 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; + ulong 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. + */ +ulong get_tbclk(void) +{ + return mxc_get_clock(MXC_IPG_CLK); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/virt-v7.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/virt-v7.c new file mode 100644 index 000000000..2cd604f97 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/virt-v7.c @@ -0,0 +1,157 @@ +/* + * (C) Copyright 2013 + * Andre Przywara, Linaro <andre.przywara@linaro.org> + * + * Routines to transition ARMv7 processors from secure into non-secure state + * and from non-secure SVC into HYP mode + * needed to enable ARMv7 virtualization for current hypervisors + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/armv7.h> +#include <asm/gic.h> +#include <asm/io.h> + +unsigned long gic_dist_addr; + +static unsigned int read_cpsr(void) +{ + unsigned int reg; + + asm volatile ("mrs %0, cpsr\n" : "=r" (reg)); + return reg; +} + +static unsigned int read_id_pfr1(void) +{ + unsigned int reg; + + asm("mrc p15, 0, %0, c0, c1, 1\n" : "=r"(reg)); + return reg; +} + +static unsigned long get_gicd_base_address(void) +{ +#ifdef CONFIG_ARM_GIC_BASE_ADDRESS + return CONFIG_ARM_GIC_BASE_ADDRESS + GIC_DIST_OFFSET; +#else + unsigned midr; + unsigned periphbase; + + /* check whether we are an Cortex-A15 or A7. + * The actual HYP switch should work with all CPUs supporting + * the virtualization extension, but we need the GIC address, + * which we know only for sure for those two CPUs. + */ + asm("mrc p15, 0, %0, c0, c0, 0\n" : "=r"(midr)); + switch (midr & MIDR_PRIMARY_PART_MASK) { + case MIDR_CORTEX_A9_R0P1: + case MIDR_CORTEX_A15_R0P0: + case MIDR_CORTEX_A7_R0P0: + break; + default: + printf("nonsec: could not determine GIC address.\n"); + return -1; + } + + /* get the GIC base address from the CBAR register */ + asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase)); + + /* the PERIPHBASE can be mapped above 4 GB (lower 8 bits used to + * encode this). Bail out here since we cannot access this without + * enabling paging. + */ + if ((periphbase & 0xff) != 0) { + printf("nonsec: PERIPHBASE is above 4 GB, no access.\n"); + return -1; + } + + return (periphbase & CBAR_MASK) + GIC_DIST_OFFSET; +#endif +} + +static void kick_secondary_cpus_gic(unsigned long gicdaddr) +{ + /* kick all CPUs (except this one) by writing to GICD_SGIR */ + writel(1U << 24, gicdaddr + GICD_SGIR); +} + +void __weak smp_kick_all_cpus(void) +{ + kick_secondary_cpus_gic(gic_dist_addr); +} + +int armv7_switch_hyp(void) +{ + unsigned int reg; + + /* check whether we are in HYP mode already */ + if ((read_cpsr() & 0x1f) == 0x1a) { + debug("CPU already in HYP mode\n"); + return 0; + } + + /* check whether the CPU supports the virtualization extensions */ + reg = read_id_pfr1(); + if ((reg & CPUID_ARM_VIRT_MASK) != 1 << CPUID_ARM_VIRT_SHIFT) { + printf("HYP mode: Virtualization extensions not implemented.\n"); + return -1; + } + + /* call the HYP switching code on this CPU also */ + _switch_to_hyp(); + + if ((read_cpsr() & 0x1F) != 0x1a) { + printf("HYP mode: switch not successful.\n"); + return -1; + } + + return 0; +} + +int armv7_switch_nonsec(void) +{ + unsigned int reg; + unsigned itlinesnr, i; + + /* check whether the CPU supports the security extensions */ + reg = read_id_pfr1(); + if ((reg & 0xF0) == 0) { + printf("nonsec: Security extensions not implemented.\n"); + return -1; + } + + /* the SCR register will be set directly in the monitor mode handler, + * according to the spec one should not tinker with it in secure state + * in SVC mode. Do not try to read it once in non-secure state, + * any access to it will trap. + */ + + gic_dist_addr = get_gicd_base_address(); + if (gic_dist_addr == -1) + return -1; + + /* enable the GIC distributor */ + writel(readl(gic_dist_addr + GICD_CTLR) | 0x03, + gic_dist_addr + GICD_CTLR); + + /* TYPER[4:0] contains an encoded number of available interrupts */ + itlinesnr = readl(gic_dist_addr + GICD_TYPER) & 0x1f; + + /* set all bits in the GIC group registers to one to allow access + * from non-secure state. The first 32 interrupts are private per + * CPU and will be set later when enabling the GIC for each core + */ + for (i = 1; i <= itlinesnr; i++) + writel((unsigned)-1, gic_dist_addr + GICD_IGROUPRn + 4 * i); + + smp_set_core_boot_addr((unsigned long)_smp_pen, -1); + smp_kick_all_cpus(); + + /* call the non-sec switching code on this CPU also */ + _nonsec_init(); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/Makefile new file mode 100644 index 000000000..3363a3c71 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/Makefile @@ -0,0 +1,16 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2008 +# Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := timer.o +obj-y += cpu.o +obj-y += ddrc.o +obj-y += slcr.o +obj-y += clk.o +obj-$(CONFIG_SPL_BUILD) += spl.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/clk.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/clk.c new file mode 100644 index 000000000..d2885dc2b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/clk.c @@ -0,0 +1,664 @@ +/* + * Copyright (C) 2013 Soren Brinkmann <soren.brinkmann@xilinx.com> + * Copyright (C) 2013 Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <errno.h> +#include <clk.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/clk.h> + +/* Board oscillator frequency */ +#ifndef CONFIG_ZYNQ_PS_CLK_FREQ +# define CONFIG_ZYNQ_PS_CLK_FREQ 33333333UL +#endif + +/* Register bitfield defines */ +#define PLLCTRL_FBDIV_MASK 0x7f000 +#define PLLCTRL_FBDIV_SHIFT 12 +#define PLLCTRL_BPFORCE_MASK (1 << 4) +#define PLLCTRL_PWRDWN_MASK 2 +#define PLLCTRL_PWRDWN_SHIFT 1 +#define PLLCTRL_RESET_MASK 1 +#define PLLCTRL_RESET_SHIFT 0 + +#define ZYNQ_CLK_MAXDIV 0x3f +#define CLK_CTRL_DIV1_SHIFT 20 +#define CLK_CTRL_DIV1_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT) +#define CLK_CTRL_DIV0_SHIFT 8 +#define CLK_CTRL_DIV0_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) +#define CLK_CTRL_SRCSEL_SHIFT 4 +#define CLK_CTRL_SRCSEL_MASK (0x3 << CLK_CTRL_SRCSEL_SHIFT) + +#define CLK_CTRL_DIV2X_SHIFT 26 +#define CLK_CTRL_DIV2X_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV2X_SHIFT) +#define CLK_CTRL_DIV3X_SHIFT 20 +#define CLK_CTRL_DIV3X_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV3X_SHIFT) + +#define ZYNQ_CLKMUX_SEL_0 0 +#define ZYNQ_CLKMUX_SEL_1 1 +#define ZYNQ_CLKMUX_SEL_2 2 +#define ZYNQ_CLKMUX_SEL_3 3 + +DECLARE_GLOBAL_DATA_PTR; + +struct clk; + +/** + * struct clk_ops: + * @set_rate: Function pointer to set_rate() implementation + * @get_rate: Function pointer to get_rate() implementation + */ +struct clk_ops { + int (*set_rate)(struct clk *clk, unsigned long rate); + unsigned long (*get_rate)(struct clk *clk); +}; + +/** + * struct clk: + * @name: Clock name + * @frequency: Currenct frequency + * @parent: Parent clock + * @flags: Clock flags + * @reg: Clock control register + * @ops: Clock operations + */ +struct clk { + char *name; + unsigned long frequency; + enum zynq_clk parent; + unsigned int flags; + u32 *reg; + struct clk_ops ops; +}; +#define ZYNQ_CLK_FLAGS_HAS_2_DIVS 1 + +static struct clk clks[clk_max]; + +/** + * __zynq_clk_cpu_get_parent() - Decode clock multiplexer + * @srcsel: Mux select value + * Returns the clock identifier associated with the selected mux input. + */ +static int __zynq_clk_cpu_get_parent(unsigned int srcsel) +{ + unsigned int ret; + + switch (srcsel) { + case ZYNQ_CLKMUX_SEL_0: + case ZYNQ_CLKMUX_SEL_1: + ret = armpll_clk; + break; + case ZYNQ_CLKMUX_SEL_2: + ret = ddrpll_clk; + break; + case ZYNQ_CLKMUX_SEL_3: + ret = iopll_clk; + break; + default: + ret = armpll_clk; + break; + } + + return ret; +} + +/** + * ddr2x_get_rate() - Get clock rate of DDR2x clock + * @clk: Clock handle + * Returns the current clock rate of @clk. + */ +static unsigned long ddr2x_get_rate(struct clk *clk) +{ + u32 clk_ctrl = readl(clk->reg); + u32 div = (clk_ctrl & CLK_CTRL_DIV2X_MASK) >> CLK_CTRL_DIV2X_SHIFT; + + return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div); +} + +/** + * ddr3x_get_rate() - Get clock rate of DDR3x clock + * @clk: Clock handle + * Returns the current clock rate of @clk. + */ +static unsigned long ddr3x_get_rate(struct clk *clk) +{ + u32 clk_ctrl = readl(clk->reg); + u32 div = (clk_ctrl & CLK_CTRL_DIV3X_MASK) >> CLK_CTRL_DIV3X_SHIFT; + + return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div); +} + +static void init_ddr_clocks(void) +{ + u32 div0, div1; + unsigned long prate = zynq_clk_get_rate(ddrpll_clk); + u32 clk_ctrl = readl(&slcr_base->ddr_clk_ctrl); + + /* DDR2x */ + clks[ddr2x_clk].reg = &slcr_base->ddr_clk_ctrl; + clks[ddr2x_clk].parent = ddrpll_clk; + clks[ddr2x_clk].name = "ddr_2x"; + clks[ddr2x_clk].frequency = ddr2x_get_rate(&clks[ddr2x_clk]); + clks[ddr2x_clk].ops.get_rate = ddr2x_get_rate; + + /* DDR3x */ + clks[ddr3x_clk].reg = &slcr_base->ddr_clk_ctrl; + clks[ddr3x_clk].parent = ddrpll_clk; + clks[ddr3x_clk].name = "ddr_3x"; + clks[ddr3x_clk].frequency = ddr3x_get_rate(&clks[ddr3x_clk]); + clks[ddr3x_clk].ops.get_rate = ddr3x_get_rate; + + /* DCI */ + clk_ctrl = readl(&slcr_base->dci_clk_ctrl); + div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; + div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT; + clks[dci_clk].reg = &slcr_base->dci_clk_ctrl; + clks[dci_clk].parent = ddrpll_clk; + clks[dci_clk].frequency = DIV_ROUND_CLOSEST( + DIV_ROUND_CLOSEST(prate, div0), div1); + clks[dci_clk].name = "dci"; + + gd->bd->bi_ddr_freq = clks[ddr3x_clk].frequency / 1000000; +} + +static void init_cpu_clocks(void) +{ + int clk_621; + u32 reg, div, srcsel; + enum zynq_clk parent; + + reg = readl(&slcr_base->arm_clk_ctrl); + clk_621 = readl(&slcr_base->clk_621_true) & 1; + div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; + srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT; + parent = __zynq_clk_cpu_get_parent(srcsel); + + /* cpu clocks */ + clks[cpu_6or4x_clk].reg = &slcr_base->arm_clk_ctrl; + clks[cpu_6or4x_clk].parent = parent; + clks[cpu_6or4x_clk].frequency = DIV_ROUND_CLOSEST( + zynq_clk_get_rate(parent), div); + clks[cpu_6or4x_clk].name = "cpu_6or4x"; + + clks[cpu_3or2x_clk].reg = &slcr_base->arm_clk_ctrl; + clks[cpu_3or2x_clk].parent = cpu_6or4x_clk; + clks[cpu_3or2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / 2; + clks[cpu_3or2x_clk].name = "cpu_3or2x"; + + clks[cpu_2x_clk].reg = &slcr_base->arm_clk_ctrl; + clks[cpu_2x_clk].parent = cpu_6or4x_clk; + clks[cpu_2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / + (2 + clk_621); + clks[cpu_2x_clk].name = "cpu_2x"; + + clks[cpu_1x_clk].reg = &slcr_base->arm_clk_ctrl; + clks[cpu_1x_clk].parent = cpu_6or4x_clk; + clks[cpu_1x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / + (4 + 2 * clk_621); + clks[cpu_1x_clk].name = "cpu_1x"; +} + +/** + * periph_calc_two_divs() - Calculate clock dividers + * @cur_rate: Current clock rate + * @tgt_rate: Target clock rate + * @prate: Parent clock rate + * @div0: First divider (output) + * @div1: Second divider (output) + * Returns the actual clock rate possible. + * + * Calculates clock dividers for clocks with two 6-bit dividers. + */ +static unsigned long periph_calc_two_divs(unsigned long cur_rate, + unsigned long tgt_rate, unsigned long prate, u32 *div0, + u32 *div1) +{ + long err, best_err = (long)(~0UL >> 1); + unsigned long rate, best_rate = 0; + u32 d0, d1; + + for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) { + for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) { + rate = DIV_ROUND_CLOSEST(DIV_ROUND_CLOSEST(prate, d0), + d1); + err = abs(rate - tgt_rate); + + if (err < best_err) { + *div0 = d0; + *div1 = d1; + best_err = err; + best_rate = rate; + } + } + } + + return best_rate; +} + +/** + * zynq_clk_periph_set_rate() - Set clock rate + * @clk: Handle of the peripheral clock + * @rate: New clock rate + * Sets the clock frequency of @clk to @rate. Returns zero on success. + */ +static int zynq_clk_periph_set_rate(struct clk *clk, + unsigned long rate) +{ + u32 ctrl, div0 = 0, div1 = 0; + unsigned long prate, new_rate, cur_rate = clk->frequency; + + ctrl = readl(clk->reg); + prate = zynq_clk_get_rate(clk->parent); + ctrl &= ~CLK_CTRL_DIV0_MASK; + + if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS) { + ctrl &= ~CLK_CTRL_DIV1_MASK; + new_rate = periph_calc_two_divs(cur_rate, rate, prate, &div0, + &div1); + ctrl |= div1 << CLK_CTRL_DIV1_SHIFT; + } else { + div0 = DIV_ROUND_CLOSEST(prate, rate); + div0 &= ZYNQ_CLK_MAXDIV; + new_rate = DIV_ROUND_CLOSEST(rate, div0); + } + + /* write new divs to hardware */ + ctrl |= div0 << CLK_CTRL_DIV0_SHIFT; + writel(ctrl, clk->reg); + + /* update frequency in clk framework */ + clk->frequency = new_rate; + + return 0; +} + +/** + * zynq_clk_periph_get_rate() - Get clock rate + * @clk: Handle of the peripheral clock + * Returns the current clock rate of @clk. + */ +static unsigned long zynq_clk_periph_get_rate(struct clk *clk) +{ + u32 clk_ctrl = readl(clk->reg); + u32 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; + u32 div1 = 1; + + if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS) + div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT; + + /* a register value of zero == division by 1 */ + if (!div0) + div0 = 1; + if (!div1) + div1 = 1; + + return + DIV_ROUND_CLOSEST( + DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div0), + div1); +} + +/** + * __zynq_clk_periph_get_parent() - Decode clock multiplexer + * @srcsel: Mux select value + * Returns the clock identifier associated with the selected mux input. + */ +static enum zynq_clk __zynq_clk_periph_get_parent(u32 srcsel) +{ + switch (srcsel) { + case ZYNQ_CLKMUX_SEL_0: + case ZYNQ_CLKMUX_SEL_1: + return iopll_clk; + case ZYNQ_CLKMUX_SEL_2: + return armpll_clk; + case ZYNQ_CLKMUX_SEL_3: + return ddrpll_clk; + default: + return 0; + } +} + +/** + * zynq_clk_periph_get_parent() - Decode clock multiplexer + * @clk: Clock handle + * Returns the clock identifier associated with the selected mux input. + */ +static enum zynq_clk zynq_clk_periph_get_parent(struct clk *clk) +{ + u32 clk_ctrl = readl(clk->reg); + u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT; + + return __zynq_clk_periph_get_parent(srcsel); +} + +/** + * zynq_clk_register_periph_clk() - Set up a peripheral clock with the framework + * @clk: Pointer to struct clk for the clock + * @ctrl: Clock control register + * @name: PLL name + * @two_divs: Indicates whether the clock features one or two dividers + */ +static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl, char *name, + bool two_divs) +{ + clk->name = name; + clk->reg = ctrl; + if (two_divs) + clk->flags = ZYNQ_CLK_FLAGS_HAS_2_DIVS; + clk->parent = zynq_clk_periph_get_parent(clk); + clk->frequency = zynq_clk_periph_get_rate(clk); + clk->ops.get_rate = zynq_clk_periph_get_rate; + clk->ops.set_rate = zynq_clk_periph_set_rate; + + return 0; +} + +static void init_periph_clocks(void) +{ + zynq_clk_register_periph_clk(&clks[gem0_clk], &slcr_base->gem0_clk_ctrl, + "gem0", 1); + zynq_clk_register_periph_clk(&clks[gem1_clk], &slcr_base->gem1_clk_ctrl, + "gem1", 1); + + zynq_clk_register_periph_clk(&clks[smc_clk], &slcr_base->smc_clk_ctrl, + "smc", 0); + + zynq_clk_register_periph_clk(&clks[lqspi_clk], + &slcr_base->lqspi_clk_ctrl, "lqspi", 0); + + zynq_clk_register_periph_clk(&clks[sdio0_clk], + &slcr_base->sdio_clk_ctrl, "sdio0", 0); + zynq_clk_register_periph_clk(&clks[sdio1_clk], + &slcr_base->sdio_clk_ctrl, "sdio1", 0); + + zynq_clk_register_periph_clk(&clks[spi0_clk], &slcr_base->spi_clk_ctrl, + "spi0", 0); + zynq_clk_register_periph_clk(&clks[spi1_clk], &slcr_base->spi_clk_ctrl, + "spi1", 0); + + zynq_clk_register_periph_clk(&clks[uart0_clk], + &slcr_base->uart_clk_ctrl, "uart0", 0); + zynq_clk_register_periph_clk(&clks[uart1_clk], + &slcr_base->uart_clk_ctrl, "uart1", 0); + + zynq_clk_register_periph_clk(&clks[dbg_trc_clk], + &slcr_base->dbg_clk_ctrl, "dbg_trc", 0); + zynq_clk_register_periph_clk(&clks[dbg_apb_clk], + &slcr_base->dbg_clk_ctrl, "dbg_apb", 0); + + zynq_clk_register_periph_clk(&clks[pcap_clk], + &slcr_base->pcap_clk_ctrl, "pcap", 0); + + zynq_clk_register_periph_clk(&clks[fclk0_clk], + &slcr_base->fpga0_clk_ctrl, "fclk0", 1); + zynq_clk_register_periph_clk(&clks[fclk1_clk], + &slcr_base->fpga1_clk_ctrl, "fclk1", 1); + zynq_clk_register_periph_clk(&clks[fclk2_clk], + &slcr_base->fpga2_clk_ctrl, "fclk2", 1); + zynq_clk_register_periph_clk(&clks[fclk3_clk], + &slcr_base->fpga3_clk_ctrl, "fclk3", 1); +} + +/** + * zynq_clk_register_aper_clk() - Set up a APER clock with the framework + * @clk: Pointer to struct clk for the clock + * @ctrl: Clock control register + * @name: PLL name + */ +static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl, char *name) +{ + clk->name = name; + clk->reg = ctrl; + clk->parent = cpu_1x_clk; + clk->frequency = zynq_clk_get_rate(clk->parent); +} + +static void init_aper_clocks(void) +{ + zynq_clk_register_aper_clk(&clks[usb0_aper_clk], + &slcr_base->aper_clk_ctrl, "usb0_aper"); + zynq_clk_register_aper_clk(&clks[usb1_aper_clk], + &slcr_base->aper_clk_ctrl, "usb1_aper"); + + zynq_clk_register_aper_clk(&clks[gem0_aper_clk], + &slcr_base->aper_clk_ctrl, "gem0_aper"); + zynq_clk_register_aper_clk(&clks[gem1_aper_clk], + &slcr_base->aper_clk_ctrl, "gem1_aper"); + + zynq_clk_register_aper_clk(&clks[sdio0_aper_clk], + &slcr_base->aper_clk_ctrl, "sdio0_aper"); + zynq_clk_register_aper_clk(&clks[sdio1_aper_clk], + &slcr_base->aper_clk_ctrl, "sdio1_aper"); + + zynq_clk_register_aper_clk(&clks[spi0_aper_clk], + &slcr_base->aper_clk_ctrl, "spi0_aper"); + zynq_clk_register_aper_clk(&clks[spi1_aper_clk], + &slcr_base->aper_clk_ctrl, "spi1_aper"); + + zynq_clk_register_aper_clk(&clks[can0_aper_clk], + &slcr_base->aper_clk_ctrl, "can0_aper"); + zynq_clk_register_aper_clk(&clks[can1_aper_clk], + &slcr_base->aper_clk_ctrl, "can1_aper"); + + zynq_clk_register_aper_clk(&clks[i2c0_aper_clk], + &slcr_base->aper_clk_ctrl, "i2c0_aper"); + zynq_clk_register_aper_clk(&clks[i2c1_aper_clk], + &slcr_base->aper_clk_ctrl, "i2c1_aper"); + + zynq_clk_register_aper_clk(&clks[uart0_aper_clk], + &slcr_base->aper_clk_ctrl, "uart0_aper"); + zynq_clk_register_aper_clk(&clks[uart1_aper_clk], + &slcr_base->aper_clk_ctrl, "uart1_aper"); + + zynq_clk_register_aper_clk(&clks[gpio_aper_clk], + &slcr_base->aper_clk_ctrl, "gpio_aper"); + + zynq_clk_register_aper_clk(&clks[lqspi_aper_clk], + &slcr_base->aper_clk_ctrl, "lqspi_aper"); + + zynq_clk_register_aper_clk(&clks[smc_aper_clk], + &slcr_base->aper_clk_ctrl, "smc_aper"); +} + +/** + * __zynq_clk_pll_get_rate() - Get PLL rate + * @addr: Address of the PLL's control register + * Returns the current PLL output rate. + */ +static unsigned long __zynq_clk_pll_get_rate(u32 *addr) +{ + u32 reg, mul, bypass; + + reg = readl(addr); + bypass = reg & PLLCTRL_BPFORCE_MASK; + if (bypass) + mul = 1; + else + mul = (reg & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT; + + return CONFIG_ZYNQ_PS_CLK_FREQ * mul; +} + +/** + * zynq_clk_pll_get_rate() - Get PLL rate + * @pll: Handle of the PLL + * Returns the current clock rate of @pll. + */ +static unsigned long zynq_clk_pll_get_rate(struct clk *pll) +{ + return __zynq_clk_pll_get_rate(pll->reg); +} + +/** + * zynq_clk_register_pll() - Set up a PLL with the framework + * @clk: Pointer to struct clk for the PLL + * @ctrl: PLL control register + * @name: PLL name + * @prate: PLL input clock rate + */ +static void zynq_clk_register_pll(struct clk *clk, u32 *ctrl, char *name, + unsigned long prate) +{ + clk->name = name; + clk->reg = ctrl; + clk->frequency = zynq_clk_pll_get_rate(clk); + clk->ops.get_rate = zynq_clk_pll_get_rate; +} + +/** + * clkid_2_register() - Get clock control register + * @id: Clock identifier of one of the PLLs + * Returns the address of the requested PLL's control register. + */ +static u32 *clkid_2_register(enum zynq_clk id) +{ + switch (id) { + case armpll_clk: + return &slcr_base->arm_pll_ctrl; + case ddrpll_clk: + return &slcr_base->ddr_pll_ctrl; + case iopll_clk: + return &slcr_base->io_pll_ctrl; + default: + return &slcr_base->io_pll_ctrl; + } +} + +/* API */ +/** + * zynq_clk_early_init() - Early init for the clock framework + * + * This function is called from before relocation and sets up the CPU clock + * frequency in the global data struct. + */ +void zynq_clk_early_init(void) +{ + u32 reg = readl(&slcr_base->arm_clk_ctrl); + u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; + u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT; + enum zynq_clk parent = __zynq_clk_cpu_get_parent(srcsel); + u32 *pllreg = clkid_2_register(parent); + unsigned long prate = __zynq_clk_pll_get_rate(pllreg); + + if (!div) + div = 1; + + gd->cpu_clk = DIV_ROUND_CLOSEST(prate, div); +} + +/** + * get_uart_clk() - Get UART input frequency + * @dev_index: UART ID + * Returns UART input clock frequency in Hz. + * + * Compared to zynq_clk_get_rate() this function is designed to work before + * relocation and can be called when the serial UART is set up. + */ +unsigned long get_uart_clk(int dev_index) +{ + u32 reg = readl(&slcr_base->uart_clk_ctrl); + u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; + u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT; + enum zynq_clk parent = __zynq_clk_periph_get_parent(srcsel); + u32 *pllreg = clkid_2_register(parent); + unsigned long prate = __zynq_clk_pll_get_rate(pllreg); + + if (!div) + div = 1; + + return DIV_ROUND_CLOSEST(prate, div); +} + +/** + * set_cpu_clk_info() - Initialize clock framework + * Always returns zero. + * + * This function is called from common code after relocation and sets up the + * clock framework. The framework must not be used before this function had been + * called. + */ +int set_cpu_clk_info(void) +{ + zynq_clk_register_pll(&clks[armpll_clk], &slcr_base->arm_pll_ctrl, + "armpll", CONFIG_ZYNQ_PS_CLK_FREQ); + zynq_clk_register_pll(&clks[ddrpll_clk], &slcr_base->ddr_pll_ctrl, + "ddrpll", CONFIG_ZYNQ_PS_CLK_FREQ); + zynq_clk_register_pll(&clks[iopll_clk], &slcr_base->io_pll_ctrl, + "iopll", CONFIG_ZYNQ_PS_CLK_FREQ); + + init_ddr_clocks(); + init_cpu_clocks(); + init_periph_clocks(); + init_aper_clocks(); + + gd->bd->bi_arm_freq = gd->cpu_clk / 1000000; + gd->bd->bi_dsp_freq = 0; + + return 0; +} + +/** + * zynq_clk_get_rate() - Get clock rate + * @clk: Clock identifier + * Returns the current clock rate of @clk on success or zero for an invalid + * clock id. + */ +unsigned long zynq_clk_get_rate(enum zynq_clk clk) +{ + if (clk < 0 || clk >= clk_max) + return 0; + + return clks[clk].frequency; +} + +/** + * zynq_clk_set_rate() - Set clock rate + * @clk: Clock identifier + * @rate: Requested clock rate + * Passes on the return value from the clock's set_rate() function or negative + * errno. + */ +int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate) +{ + if (clk < 0 || clk >= clk_max) + return -ENODEV; + + if (clks[clk].ops.set_rate) + return clks[clk].ops.set_rate(&clks[clk], rate); + + return -ENXIO; +} + +/** + * zynq_clk_get_name() - Get clock name + * @clk: Clock identifier + * Returns the name of @clk. + */ +const char *zynq_clk_get_name(enum zynq_clk clk) +{ + return clks[clk].name; +} + +/** + * soc_clk_dump() - Print clock frequencies + * Returns zero on success + * + * Implementation for the clk dump command. + */ +int soc_clk_dump(void) +{ + int i; + + printf("clk\t\tfrequency\n"); + for (i = 0; i < clk_max; i++) { + const char *name = zynq_clk_get_name(i); + if (name) + printf("%10s%20lu\n", name, zynq_clk_get_rate(i)); + } + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/cpu.c new file mode 100644 index 000000000..7626b5c1a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/cpu.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2012 Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clk.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/hardware.h> + +void lowlevel_init(void) +{ +} + +int arch_cpu_init(void) +{ + zynq_slcr_unlock(); +#ifndef CONFIG_SPL_BUILD + /* Device config APB, unlock the PCAP */ + writel(0x757BDF0D, &devcfg_base->unlock); + writel(0xFFFFFFFF, &devcfg_base->rom_shadow); + +#if (CONFIG_SYS_SDRAM_BASE == 0) + /* remap DDR to zero, FILTERSTART */ + writel(0, &scu_base->filter_start); + + /* OCM_CFG, Mask out the ROM, map ram into upper addresses */ + writel(0x1F, &slcr_base->ocm_cfg); + /* FPGA_RST_CTRL, clear resets on AXI fabric ports */ + writel(0x0, &slcr_base->fpga_rst_ctrl); + /* Set urgent bits with register */ + writel(0x0, &slcr_base->ddr_urgent_sel); + /* Urgent write, ports S2/S3 */ + writel(0xC, &slcr_base->ddr_urgent); +#endif +#endif + zynq_clk_early_init(); + zynq_slcr_lock(); + + return 0; +} + +void reset_cpu(ulong addr) +{ + zynq_slcr_cpu_reset(); + while (1) + ; +} + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/ddrc.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/ddrc.c new file mode 100644 index 000000000..ba6a6aee5 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/ddrc.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 - 2013 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2012 - 2013 Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/hardware.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Control regsiter bitfield definitions */ +#define ZYNQ_DDRC_CTRLREG_BUSWIDTH_MASK 0xC +#define ZYNQ_DDRC_CTRLREG_BUSWIDTH_SHIFT 2 +#define ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT 1 + +/* ECC scrub regsiter definitions */ +#define ZYNQ_DDRC_ECC_SCRUBREG_ECC_MODE_MASK 0x7 +#define ZYNQ_DDRC_ECC_SCRUBREG_ECCMODE_SECDED 0x4 + +void zynq_ddrc_init(void) +{ + u32 width, ecctype; + + width = readl(&ddrc_base->ddrc_ctrl); + width = (width & ZYNQ_DDRC_CTRLREG_BUSWIDTH_MASK) >> + ZYNQ_DDRC_CTRLREG_BUSWIDTH_SHIFT; + ecctype = (readl(&ddrc_base->ecc_scrub) & + ZYNQ_DDRC_ECC_SCRUBREG_ECC_MODE_MASK); + + /* ECC is enabled when memory is in 16bit mode and it is enabled */ + if ((ecctype == ZYNQ_DDRC_ECC_SCRUBREG_ECCMODE_SECDED) && + (width == ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT)) { + puts("Memory: ECC enabled\n"); + /* + * Clear the first 1MB because it is not initialized from + * first stage bootloader. To get ECC to work all memory has + * been initialized by writing any value. + */ + memset(0, 0, 1 * 1024 * 1024); + } else { + puts("Memory: ECC disabled\n"); + } + + if (width == ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT) + gd->ram_size /= 2; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/slcr.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/slcr.c new file mode 100644 index 000000000..d7c188233 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/slcr.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013 Xilinx Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <malloc.h> +#include <asm/arch/hardware.h> +#include <asm/arch/clk.h> + +#define SLCR_LOCK_MAGIC 0x767B +#define SLCR_UNLOCK_MAGIC 0xDF0D + +#define SLCR_IDCODE_MASK 0x1F000 +#define SLCR_IDCODE_SHIFT 12 + +static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */ + +void zynq_slcr_lock(void) +{ + if (!slcr_lock) + writel(SLCR_LOCK_MAGIC, &slcr_base->slcr_lock); +} + +void zynq_slcr_unlock(void) +{ + if (slcr_lock) + writel(SLCR_UNLOCK_MAGIC, &slcr_base->slcr_unlock); +} + +/* Reset the entire system */ +void zynq_slcr_cpu_reset(void) +{ + /* + * Unlock the SLCR then reset the system. + * Note that this seems to require raw i/o + * functions or there's a lockup? + */ + zynq_slcr_unlock(); + + /* + * Clear 0x0F000000 bits of reboot status register to workaround + * the FSBL not loading the bitstream after soft-reboot + * This is a temporary solution until we know more. + */ + clrbits_le32(&slcr_base->reboot_status, 0xF000000); + + writel(1, &slcr_base->pss_rst_ctrl); +} + +/* Setup clk for network */ +void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate) +{ + int ret; + + zynq_slcr_unlock(); + + if (gem_id > 1) { + printf("Non existing GEM id %d\n", gem_id); + goto out; + } + + ret = zynq_clk_set_rate(gem0_clk + gem_id, clk_rate); + if (ret) + goto out; + + if (gem_id) { + /* Configure GEM_RCLK_CTRL */ + writel(1, &slcr_base->gem1_rclk_ctrl); + } else { + /* Configure GEM_RCLK_CTRL */ + writel(1, &slcr_base->gem0_rclk_ctrl); + } + udelay(100000); +out: + zynq_slcr_lock(); +} + +void zynq_slcr_devcfg_disable(void) +{ + zynq_slcr_unlock(); + + /* Disable AXI interface */ + writel(0xFFFFFFFF, &slcr_base->fpga_rst_ctrl); + + /* Set Level Shifters DT618760 */ + writel(0xA, &slcr_base->lvl_shftr_en); + + zynq_slcr_lock(); +} + +void zynq_slcr_devcfg_enable(void) +{ + zynq_slcr_unlock(); + + /* Set Level Shifters DT618760 */ + writel(0xF, &slcr_base->lvl_shftr_en); + + /* Disable AXI interface */ + writel(0x0, &slcr_base->fpga_rst_ctrl); + + zynq_slcr_lock(); +} + +u32 zynq_slcr_get_boot_mode(void) +{ + /* Get the bootmode register value */ + return readl(&slcr_base->boot_mode); +} + +u32 zynq_slcr_get_idcode(void) +{ + return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >> + SLCR_IDCODE_SHIFT; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/spl.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/spl.c new file mode 100644 index 000000000..fcad762c0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/spl.c @@ -0,0 +1,69 @@ +/* + * (C) Copyright 2014 Xilinx, Inc. Michal Simek + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <spl.h> + +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spl.h> +#include <asm/arch/sys_proto.h> + +DECLARE_GLOBAL_DATA_PTR; + +void board_init_f(ulong dummy) +{ + ps7_init(); + + /* Clear the BSS. */ + memset(__bss_start, 0, __bss_end - __bss_start); + + /* Set global data pointer. */ + gd = &gdata; + + preloader_console_init(); + arch_cpu_init(); + board_init_r(NULL, 0); +} + +u32 spl_boot_device(void) +{ + u32 mode; + + switch ((zynq_slcr_get_boot_mode()) & ZYNQ_BM_MASK) { +#ifdef CONFIG_SPL_SPI_SUPPORT + case ZYNQ_BM_QSPI: + puts("qspi boot\n"); + mode = BOOT_DEVICE_SPI; + break; +#endif +#ifdef CONFIG_SPL_MMC_SUPPORT + case ZYNQ_BM_SD: + puts("mmc boot\n"); + mode = BOOT_DEVICE_MMC1; + break; +#endif + default: + puts("Unsupported boot mode selected\n"); + hang(); + } + + return mode; +} + +#ifdef CONFIG_SPL_MMC_SUPPORT +u32 spl_boot_mode(void) +{ + return MMCSD_MODE_FAT; +} +#endif + +#ifdef CONFIG_SPL_OS_BOOT +int spl_start_uboot(void) +{ + /* boot linux */ + return 0; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/timer.c new file mode 100644 index 000000000..303dbcfce --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/timer.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved. + * + * (C) Copyright 2008 + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2003 + * Texas Instruments <www.ti.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/clk.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct scu_timer { + u32 load; /* Timer Load Register */ + u32 counter; /* Timer Counter Register */ + u32 control; /* Timer Control Register */ +}; + +static struct scu_timer *timer_base = + (struct scu_timer *)ZYNQ_SCUTIMER_BASEADDR; + +#define SCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00 /* Prescaler */ +#define SCUTIMER_CONTROL_PRESCALER_SHIFT 8 +#define SCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002 /* Auto-reload */ +#define SCUTIMER_CONTROL_ENABLE_MASK 0x00000001 /* Timer enable */ + +#define TIMER_LOAD_VAL 0xFFFFFFFF +#define TIMER_PRESCALE 255 + +int timer_init(void) +{ + const u32 emask = SCUTIMER_CONTROL_AUTO_RELOAD_MASK | + (TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) | + SCUTIMER_CONTROL_ENABLE_MASK; + + gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE + 1); + + /* Load the timer counter register */ + writel(0xFFFFFFFF, &timer_base->load); + + /* + * Start the A9Timer device + * Enable Auto reload mode, Clear prescaler control bits + * Set prescaler value, Enable the decrementer + */ + clrsetbits_le32(&timer_base->control, SCUTIMER_CONTROL_PRESCALER_MASK, + emask); + + /* Reset time */ + gd->arch.lastinc = readl(&timer_base->counter) / + (gd->arch.timer_rate_hz / CONFIG_SYS_HZ); + gd->arch.tbl = 0; + + return 0; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +ulong get_timer_masked(void) +{ + ulong now; + + now = readl(&timer_base->counter) / + (gd->arch.timer_rate_hz / CONFIG_SYS_HZ); + + if (gd->arch.lastinc >= now) { + /* Normal mode */ + gd->arch.tbl += gd->arch.lastinc - now; + } else { + /* We have an overflow ... */ + gd->arch.tbl += gd->arch.lastinc + TIMER_LOAD_VAL - now + 1; + } + gd->arch.lastinc = now; + + return gd->arch.tbl; +} + +void __udelay(unsigned long usec) +{ + u32 countticks; + u32 timeend; + u32 timediff; + u32 timenow; + + if (usec == 0) + return; + + countticks = lldiv(((unsigned long long)gd->arch.timer_rate_hz * usec), + 1000000); + + /* decrementing timer */ + timeend = readl(&timer_base->counter) - countticks; + +#if TIMER_LOAD_VAL != 0xFFFFFFFF + /* do not manage multiple overflow */ + if (countticks >= TIMER_LOAD_VAL) + countticks = TIMER_LOAD_VAL - 1; +#endif + + do { + timenow = readl(&timer_base->counter); + + if (timenow >= timeend) { + /* normal case */ + timediff = timenow - timeend; + } else { + if ((TIMER_LOAD_VAL - timeend + timenow) <= + countticks) { + /* overflow */ + timediff = TIMER_LOAD_VAL - timeend + timenow; + } else { + /* missed the exact match */ + break; + } + } + } while (timediff > 0); +} + +/* Timer without interrupts */ +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/u-boot-spl.lds b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/u-boot-spl.lds new file mode 100644 index 000000000..0c4501e5c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/u-boot-spl.lds @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014 Xilinx, Inc. Michal Simek + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = ALIGN(4); + .text : + { + __image_copy_start = .; + CPUDIR/start.o (.text*) + *(.text*) + } > .sram + + . = ALIGN(4); + .rodata : { + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } > .sram + + . = ALIGN(4); + .data : { + *(.data*) + } > .sram + + . = ALIGN(4); + + . = .; + + __image_copy_end = .; + + _end = .; + + /* Move BSS section to RAM because of FAT */ + .bss (NOLOAD) : { + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } > .sdram + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/u-boot.lds b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/u-boot.lds new file mode 100644 index 000000000..f2a596598 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv7/zynq/u-boot.lds @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.__image_copy_start) + CPUDIR/start.o (.text*) + *(.text*) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + + . = .; + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + + .image_copy_end : + { + *(.__image_copy_end) + } + + .rel_dyn_start : + { + *(.__rel_dyn_start) + } + + .rel.dyn : { + *(.rel*) + } + + .rel_dyn_end : + { + *(.__rel_dyn_end) + } + + .end : + { + *(.__end) + } + + _image_binary_end = .; + +/* + * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c + * __bss_base and __bss_limit are for linker only (overlay ordering) + */ + + .bss_start __rel_dyn_start (OVERLAY) : { + KEEP(*(.__bss_start)); + __bss_base = .; + } + + .bss __bss_base (OVERLAY) : { + *(.bss*) + . = ALIGN(4); + __bss_limit = .; + } + + .bss_end __bss_limit (OVERLAY) : { + KEEP(*(.__bss_end)); + } + + /* + * Zynq needs to discard more sections because the user + * is expected to pass this image on to tools for boot.bin + * generation that require them to be dropped. + */ + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynbss*) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } + /DISCARD/ : { *(.ARM.exidx*) } + /DISCARD/ : { *(.gnu.linkonce.armexidx.*) } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/Makefile b/qemu/roms/u-boot/arch/arm/cpu/armv8/Makefile new file mode 100644 index 000000000..7d93f5942 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/Makefile @@ -0,0 +1,16 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y := start.o + +obj-y += cpu.o +obj-y += generic_timer.o +obj-y += cache_v8.o +obj-y += exceptions.o +obj-y += cache.o +obj-y += tlb.o +obj-y += transition.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/cache.S b/qemu/roms/u-boot/arch/arm/cpu/armv8/cache.S new file mode 100644 index 000000000..4b3ee6ed6 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/cache.S @@ -0,0 +1,157 @@ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * This file is based on sample code from ARMv8 ARM. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> +#include <asm/macro.h> +#include <linux/linkage.h> + +/* + * void __asm_flush_dcache_level(level) + * + * clean and invalidate one level cache. + * + * x0: cache level + * x1: 0 flush & invalidate, 1 invalidate only + * x2~x9: clobbered + */ +ENTRY(__asm_flush_dcache_level) + lsl x12, x0, #1 + msr csselr_el1, x12 /* select cache level */ + isb /* sync change of cssidr_el1 */ + mrs x6, ccsidr_el1 /* read the new cssidr_el1 */ + and x2, x6, #7 /* x2 <- log2(cache line size)-4 */ + add x2, x2, #4 /* x2 <- log2(cache line size) */ + mov x3, #0x3ff + and x3, x3, x6, lsr #3 /* x3 <- max number of #ways */ + clz w5, w3 /* bit position of #ways */ + mov x4, #0x7fff + and x4, x4, x6, lsr #13 /* x4 <- max number of #sets */ + /* x12 <- cache level << 1 */ + /* x2 <- line length offset */ + /* x3 <- number of cache ways - 1 */ + /* x4 <- number of cache sets - 1 */ + /* x5 <- bit position of #ways */ + +loop_set: + mov x6, x3 /* x6 <- working copy of #ways */ +loop_way: + lsl x7, x6, x5 + orr x9, x12, x7 /* map way and level to cisw value */ + lsl x7, x4, x2 + orr x9, x9, x7 /* map set number to cisw value */ + tbz w1, #0, 1f + dc isw, x9 + b 2f +1: dc cisw, x9 /* clean & invalidate by set/way */ +2: subs x6, x6, #1 /* decrement the way */ + b.ge loop_way + subs x4, x4, #1 /* decrement the set */ + b.ge loop_set + + ret +ENDPROC(__asm_flush_dcache_level) + +/* + * void __asm_flush_dcache_all(int invalidate_only) + * + * x0: 0 flush & invalidate, 1 invalidate only + * + * clean and invalidate all data cache by SET/WAY. + */ +ENTRY(__asm_dcache_all) + mov x1, x0 + dsb sy + mrs x10, clidr_el1 /* read clidr_el1 */ + lsr x11, x10, #24 + and x11, x11, #0x7 /* x11 <- loc */ + cbz x11, finished /* if loc is 0, exit */ + mov x15, lr + mov x0, #0 /* start flush at cache level 0 */ + /* x0 <- cache level */ + /* x10 <- clidr_el1 */ + /* x11 <- loc */ + /* x15 <- return address */ + +loop_level: + lsl x12, x0, #1 + add x12, x12, x0 /* x0 <- tripled cache level */ + lsr x12, x10, x12 + and x12, x12, #7 /* x12 <- cache type */ + cmp x12, #2 + b.lt skip /* skip if no cache or icache */ + bl __asm_flush_dcache_level /* x1 = 0 flush, 1 invalidate */ +skip: + add x0, x0, #1 /* increment cache level */ + cmp x11, x0 + b.gt loop_level + + mov x0, #0 + msr csselr_el1, x0 /* resotre csselr_el1 */ + dsb sy + isb + mov lr, x15 + +finished: + ret +ENDPROC(__asm_dcache_all) + +ENTRY(__asm_flush_dcache_all) + mov x16, lr + mov x0, #0 + bl __asm_dcache_all + mov lr, x16 + ret +ENDPROC(__asm_flush_dcache_all) + +ENTRY(__asm_invalidate_dcache_all) + mov x16, lr + mov x0, #0xffff + bl __asm_dcache_all + mov lr, x16 + ret +ENDPROC(__asm_invalidate_dcache_all) + +/* + * void __asm_flush_dcache_range(start, end) + * + * clean & invalidate data cache in the range + * + * x0: start address + * x1: end address + */ +ENTRY(__asm_flush_dcache_range) + mrs x3, ctr_el0 + lsr x3, x3, #16 + and x3, x3, #0xf + mov x2, #4 + lsl x2, x2, x3 /* cache line size */ + + /* x2 <- minimal cache line size in cache system */ + sub x3, x2, #1 + bic x0, x0, x3 +1: dc civac, x0 /* clean & invalidate data or unified cache */ + add x0, x0, x2 + cmp x0, x1 + b.lo 1b + dsb sy + ret +ENDPROC(__asm_flush_dcache_range) + +/* + * void __asm_invalidate_icache_all(void) + * + * invalidate all tlb entries. + */ +ENTRY(__asm_invalidate_icache_all) + ic ialluis + isb sy + ret +ENDPROC(__asm_invalidate_icache_all) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/cache_v8.c b/qemu/roms/u-boot/arch/arm/cpu/armv8/cache_v8.c new file mode 100644 index 000000000..a96ecda7e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/cache_v8.c @@ -0,0 +1,236 @@ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/system.h> +#include <asm/armv8/mmu.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_DCACHE_OFF + +static void set_pgtable_section(u64 section, u64 memory_type) +{ + u64 *page_table = (u64 *)gd->arch.tlb_addr; + u64 value; + + value = (section << SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; + value |= PMD_ATTRINDX(memory_type); + page_table[section] = value; +} + +/* to activate the MMU we need to set up virtual memory */ +static void mmu_setup(void) +{ + int i, j, el; + bd_t *bd = gd->bd; + + /* Setup an identity-mapping for all spaces */ + for (i = 0; i < (PGTABLE_SIZE >> 3); i++) + set_pgtable_section(i, MT_DEVICE_NGNRNE); + + /* Setup an identity-mapping for all RAM space */ + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + ulong start = bd->bi_dram[i].start; + ulong end = bd->bi_dram[i].start + bd->bi_dram[i].size; + for (j = start >> SECTION_SHIFT; + j < end >> SECTION_SHIFT; j++) { + set_pgtable_section(j, MT_NORMAL); + } + } + + /* load TTBR0 */ + el = current_el(); + if (el == 1) { + asm volatile("msr ttbr0_el1, %0" + : : "r" (gd->arch.tlb_addr) : "memory"); + asm volatile("msr tcr_el1, %0" + : : "r" (TCR_FLAGS | TCR_EL1_IPS_BITS) + : "memory"); + asm volatile("msr mair_el1, %0" + : : "r" (MEMORY_ATTRIBUTES) : "memory"); + } else if (el == 2) { + asm volatile("msr ttbr0_el2, %0" + : : "r" (gd->arch.tlb_addr) : "memory"); + asm volatile("msr tcr_el2, %0" + : : "r" (TCR_FLAGS | TCR_EL2_IPS_BITS) + : "memory"); + asm volatile("msr mair_el2, %0" + : : "r" (MEMORY_ATTRIBUTES) : "memory"); + } else { + asm volatile("msr ttbr0_el3, %0" + : : "r" (gd->arch.tlb_addr) : "memory"); + asm volatile("msr tcr_el3, %0" + : : "r" (TCR_FLAGS | TCR_EL2_IPS_BITS) + : "memory"); + asm volatile("msr mair_el3, %0" + : : "r" (MEMORY_ATTRIBUTES) : "memory"); + } + + /* enable the mmu */ + set_sctlr(get_sctlr() | CR_M); +} + +/* + * Performs a invalidation of the entire data cache at all levels + */ +void invalidate_dcache_all(void) +{ + __asm_invalidate_dcache_all(); +} + +/* + * Performs a clean & invalidation of the entire data cache at all levels + */ +void flush_dcache_all(void) +{ + __asm_flush_dcache_all(); +} + +/* + * Invalidates range in all levels of D-cache/unified cache + */ +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + __asm_flush_dcache_range(start, stop); +} + +/* + * Flush range(clean & invalidate) from all levels of D-cache/unified cache + */ +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + __asm_flush_dcache_range(start, stop); +} + +void dcache_enable(void) +{ + /* The data cache is not active unless the mmu is enabled */ + if (!(get_sctlr() & CR_M)) { + invalidate_dcache_all(); + __asm_invalidate_tlb_all(); + mmu_setup(); + } + + set_sctlr(get_sctlr() | CR_C); +} + +void dcache_disable(void) +{ + uint32_t sctlr; + + sctlr = get_sctlr(); + + /* if cache isn't enabled no need to disable */ + if (!(sctlr & CR_C)) + return; + + set_sctlr(sctlr & ~(CR_C|CR_M)); + + flush_dcache_all(); + __asm_invalidate_tlb_all(); +} + +int dcache_status(void) +{ + return (get_sctlr() & CR_C) != 0; +} + +#else /* CONFIG_SYS_DCACHE_OFF */ + +void invalidate_dcache_all(void) +{ +} + +void flush_dcache_all(void) +{ +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void dcache_enable(void) +{ +} + +void dcache_disable(void) +{ +} + +int dcache_status(void) +{ + return 0; +} + +#endif /* CONFIG_SYS_DCACHE_OFF */ + +#ifndef CONFIG_SYS_ICACHE_OFF + +void icache_enable(void) +{ + __asm_invalidate_icache_all(); + set_sctlr(get_sctlr() | CR_I); +} + +void icache_disable(void) +{ + set_sctlr(get_sctlr() & ~CR_I); +} + +int icache_status(void) +{ + return (get_sctlr() & CR_I) != 0; +} + +void invalidate_icache_all(void) +{ + __asm_invalidate_icache_all(); +} + +#else /* CONFIG_SYS_ICACHE_OFF */ + +void icache_enable(void) +{ +} + +void icache_disable(void) +{ +} + +int icache_status(void) +{ + return 0; +} + +void invalidate_icache_all(void) +{ +} + +#endif /* CONFIG_SYS_ICACHE_OFF */ + +/* + * Enable dCache & iCache, whether cache is actually enabled + * depend on CONFIG_SYS_DCACHE_OFF and CONFIG_SYS_ICACHE_OFF + */ +void enable_caches(void) +{ + icache_enable(); + dcache_enable(); +} + +/* + * Flush range from all levels of d-cache/unified-cache + */ +void flush_cache(unsigned long start, unsigned long size) +{ + flush_dcache_range(start, start + size); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/config.mk b/qemu/roms/u-boot/arch/arm/cpu/armv8/config.mk new file mode 100644 index 000000000..f5b95591a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/config.mk @@ -0,0 +1,12 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# +PLATFORM_RELFLAGS += -fno-common -ffixed-x18 + +PF_CPPFLAGS_ARMV8 := $(call cc-option, -march=armv8-a) +PF_NO_UNALIGNED := $(call cc-option, -mstrict-align) +PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV8) +PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/armv8/cpu.c new file mode 100644 index 000000000..e06c3cc04 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/cpu.c @@ -0,0 +1,43 @@ +/* + * (C) Copyright 2008 Texas Insturments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> +#include <linux/compiler.h> + +int cleanup_before_linux(void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * disable interrupt and turn off caches etc ... + */ + disable_interrupts(); + + /* + * Turn off I-cache and invalidate it + */ + icache_disable(); + invalidate_icache_all(); + + /* + * turn off D-cache + * dcache_disable() in turn flushes the d-cache and disables MMU + */ + dcache_disable(); + invalidate_dcache_all(); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/exceptions.S b/qemu/roms/u-boot/arch/arm/cpu/armv8/exceptions.S new file mode 100644 index 000000000..b91a1b662 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/exceptions.S @@ -0,0 +1,113 @@ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> +#include <asm/ptrace.h> +#include <asm/macro.h> +#include <linux/linkage.h> + +/* + * Enter Exception. + * This will save the processor state that is ELR/X0~X30 + * to the stack frame. + */ +.macro exception_entry + stp x29, x30, [sp, #-16]! + stp x27, x28, [sp, #-16]! + stp x25, x26, [sp, #-16]! + stp x23, x24, [sp, #-16]! + stp x21, x22, [sp, #-16]! + stp x19, x20, [sp, #-16]! + stp x17, x18, [sp, #-16]! + stp x15, x16, [sp, #-16]! + stp x13, x14, [sp, #-16]! + stp x11, x12, [sp, #-16]! + stp x9, x10, [sp, #-16]! + stp x7, x8, [sp, #-16]! + stp x5, x6, [sp, #-16]! + stp x3, x4, [sp, #-16]! + stp x1, x2, [sp, #-16]! + + /* Could be running at EL3/EL2/EL1 */ + switch_el x11, 3f, 2f, 1f +3: mrs x1, esr_el3 + mrs x2, elr_el3 + b 0f +2: mrs x1, esr_el2 + mrs x2, elr_el2 + b 0f +1: mrs x1, esr_el1 + mrs x2, elr_el1 +0: + stp x2, x0, [sp, #-16]! + mov x0, sp +.endm + +/* + * Exception vectors. + */ + .align 11 + .globl vectors +vectors: + .align 7 + b _do_bad_sync /* Current EL Synchronous Thread */ + + .align 7 + b _do_bad_irq /* Current EL IRQ Thread */ + + .align 7 + b _do_bad_fiq /* Current EL FIQ Thread */ + + .align 7 + b _do_bad_error /* Current EL Error Thread */ + + .align 7 + b _do_sync /* Current EL Synchronous Handler */ + + .align 7 + b _do_irq /* Current EL IRQ Handler */ + + .align 7 + b _do_fiq /* Current EL FIQ Handler */ + + .align 7 + b _do_error /* Current EL Error Handler */ + + +_do_bad_sync: + exception_entry + bl do_bad_sync + +_do_bad_irq: + exception_entry + bl do_bad_irq + +_do_bad_fiq: + exception_entry + bl do_bad_fiq + +_do_bad_error: + exception_entry + bl do_bad_error + +_do_sync: + exception_entry + bl do_sync + +_do_irq: + exception_entry + bl do_irq + +_do_fiq: + exception_entry + bl do_fiq + +_do_error: + exception_entry + bl do_error diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/generic_timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv8/generic_timer.c new file mode 100644 index 000000000..223b95e21 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/generic_timer.c @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +/* + * Generic timer implementation of get_tbclk() + */ +unsigned long get_tbclk(void) +{ + unsigned long cntfrq; + asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq)); + return cntfrq; +} + +/* + * Generic timer implementation of timer_read_counter() + */ +unsigned long timer_read_counter(void) +{ + unsigned long cntpct; + isb(); + asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); + return cntpct; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/start.S b/qemu/roms/u-boot/arch/arm/cpu/armv8/start.S new file mode 100644 index 000000000..33d3f3688 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/start.S @@ -0,0 +1,170 @@ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> +#include <linux/linkage.h> +#include <asm/macro.h> +#include <asm/armv8/mmu.h> + +/************************************************************************* + * + * Startup Code (reset vector) + * + *************************************************************************/ + +.globl _start +_start: + b reset + + .align 3 + +.globl _TEXT_BASE +_TEXT_BASE: + .quad CONFIG_SYS_TEXT_BASE + +/* + * These are defined in the linker script. + */ +.globl _end_ofs +_end_ofs: + .quad _end - _start + +.globl _bss_start_ofs +_bss_start_ofs: + .quad __bss_start - _start + +.globl _bss_end_ofs +_bss_end_ofs: + .quad __bss_end - _start + +reset: + /* + * Could be EL3/EL2/EL1, Initial State: + * Little Endian, MMU Disabled, i/dCache Disabled + */ + adr x0, vectors + switch_el x1, 3f, 2f, 1f +3: mrs x0, scr_el3 + orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */ + msr scr_el3, x0 + msr vbar_el3, x0 + msr cptr_el3, xzr /* Enable FP/SIMD */ + ldr x0, =COUNTER_FREQUENCY + msr cntfrq_el0, x0 /* Initialize CNTFRQ */ + b 0f +2: msr vbar_el2, x0 + mov x0, #0x33ff + msr cptr_el2, x0 /* Enable FP/SIMD */ + b 0f +1: msr vbar_el1, x0 + mov x0, #3 << 20 + msr cpacr_el1, x0 /* Enable FP/SIMD */ +0: + + /* + * Cache/BPB/TLB Invalidate + * i-cache is invalidated before enabled in icache_enable() + * tlb is invalidated before mmu is enabled in dcache_enable() + * d-cache is invalidated before enabled in dcache_enable() + */ + + /* Processor specific initialization */ + bl lowlevel_init + + branch_if_master x0, x1, master_cpu + + /* + * Slave CPUs + */ +slave_cpu: + wfe + ldr x1, =CPU_RELEASE_ADDR + ldr x0, [x1] + cbz x0, slave_cpu + br x0 /* branch to the given address */ + + /* + * Master CPU + */ +master_cpu: + bl _main + +/*-----------------------------------------------------------------------*/ + +WEAK(lowlevel_init) + mov x29, lr /* Save LR */ + +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) + branch_if_slave x0, 1f + ldr x0, =GICD_BASE + bl gic_init_secure +1: +#if defined(CONFIG_GICV3) + ldr x0, =GICR_BASE + bl gic_init_secure_percpu +#elif defined(CONFIG_GICV2) + ldr x0, =GICD_BASE + ldr x1, =GICC_BASE + bl gic_init_secure_percpu +#endif +#endif + + branch_if_master x0, x1, 2f + + /* + * Slave should wait for master clearing spin table. + * This sync prevent salves observing incorrect + * value of spin table and jumping to wrong place. + */ +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) +#ifdef CONFIG_GICV2 + ldr x0, =GICC_BASE +#endif + bl gic_wait_for_interrupt +#endif + + /* + * All slaves will enter EL2 and optionally EL1. + */ + bl armv8_switch_to_el2 +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + bl armv8_switch_to_el1 +#endif + +2: + mov lr, x29 /* Restore LR */ + ret +ENDPROC(lowlevel_init) + +WEAK(smp_kick_all_cpus) + /* Kick secondary cpus up by SGI 0 interrupt */ + mov x29, lr /* Save LR */ +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) + ldr x0, =GICD_BASE + bl gic_kick_secondary_cpus +#endif + mov lr, x29 /* Restore LR */ + ret +ENDPROC(smp_kick_all_cpus) + +/*-----------------------------------------------------------------------*/ + +ENTRY(c_runtime_cpu_setup) + /* Relocate vBAR */ + adr x0, vectors + switch_el x1, 3f, 2f, 1f +3: msr vbar_el3, x0 + b 0f +2: msr vbar_el2, x0 + b 0f +1: msr vbar_el1, x0 +0: + + ret +ENDPROC(c_runtime_cpu_setup) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/tlb.S b/qemu/roms/u-boot/arch/arm/cpu/armv8/tlb.S new file mode 100644 index 000000000..f840b04df --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/tlb.S @@ -0,0 +1,34 @@ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> +#include <linux/linkage.h> +#include <asm/macro.h> + +/* + * void __asm_invalidate_tlb_all(void) + * + * invalidate all tlb entries. + */ +ENTRY(__asm_invalidate_tlb_all) + switch_el x9, 3f, 2f, 1f +3: tlbi alle3 + dsb sy + isb + b 0f +2: tlbi alle2 + dsb sy + isb + b 0f +1: tlbi vmalle1 + dsb sy + isb +0: + ret +ENDPROC(__asm_invalidate_tlb_all) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/transition.S b/qemu/roms/u-boot/arch/arm/cpu/armv8/transition.S new file mode 100644 index 000000000..e0a594600 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/transition.S @@ -0,0 +1,83 @@ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> +#include <linux/linkage.h> +#include <asm/macro.h> + +ENTRY(armv8_switch_to_el2) + switch_el x0, 1f, 0f, 0f +0: ret +1: + mov x0, #0x5b1 /* Non-secure EL0/EL1 | HVC | 64bit EL2 */ + msr scr_el3, x0 + msr cptr_el3, xzr /* Disable coprocessor traps to EL3 */ + mov x0, #0x33ff + msr cptr_el2, x0 /* Disable coprocessor traps to EL2 */ + + /* Initialize SCTLR_EL2 */ + msr sctlr_el2, xzr + + /* Return to the EL2_SP2 mode from EL3 */ + mov x0, sp + msr sp_el2, x0 /* Migrate SP */ + mrs x0, vbar_el3 + msr vbar_el2, x0 /* Migrate VBAR */ + mov x0, #0x3c9 + msr spsr_el3, x0 /* EL2_SP2 | D | A | I | F */ + msr elr_el3, lr + eret +ENDPROC(armv8_switch_to_el2) + +ENTRY(armv8_switch_to_el1) + switch_el x0, 0f, 1f, 0f +0: ret +1: + /* Initialize Generic Timers */ + mrs x0, cnthctl_el2 + orr x0, x0, #0x3 /* Enable EL1 access to timers */ + msr cnthctl_el2, x0 + msr cntvoff_el2, x0 + mrs x0, cntkctl_el1 + orr x0, x0, #0x3 /* Enable EL0 access to timers */ + msr cntkctl_el1, x0 + + /* Initilize MPID/MPIDR registers */ + mrs x0, midr_el1 + mrs x1, mpidr_el1 + msr vpidr_el2, x0 + msr vmpidr_el2, x1 + + /* Disable coprocessor traps */ + mov x0, #0x33ff + msr cptr_el2, x0 /* Disable coprocessor traps to EL2 */ + msr hstr_el2, xzr /* Disable coprocessor traps to EL2 */ + mov x0, #3 << 20 + msr cpacr_el1, x0 /* Enable FP/SIMD at EL1 */ + + /* Initialize HCR_EL2 */ + mov x0, #(1 << 31) /* 64bit EL1 */ + orr x0, x0, #(1 << 29) /* Disable HVC */ + msr hcr_el2, x0 + + /* SCTLR_EL1 initialization */ + mov x0, #0x0800 + movk x0, #0x30d0, lsl #16 + msr sctlr_el1, x0 + + /* Return to the EL1_SP1 mode from EL2 */ + mov x0, sp + msr sp_el1, x0 /* Migrate SP */ + mrs x0, vbar_el2 + msr vbar_el1, x0 /* Migrate VBAR */ + mov x0, #0x3c5 + msr spsr_el2, x0 /* EL1_SP1 | D | A | I | F */ + msr elr_el2, lr + eret +ENDPROC(armv8_switch_to_el1) diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv8/u-boot.lds b/qemu/roms/u-boot/arch/arm/cpu/armv8/u-boot.lds new file mode 100644 index 000000000..4c1222237 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/armv8/u-boot.lds @@ -0,0 +1,89 @@ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(8); + .text : + { + *(.__image_copy_start) + CPUDIR/start.o (.text*) + *(.text*) + } + + . = ALIGN(8); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(8); + .data : { + *(.data*) + } + + . = ALIGN(8); + + . = .; + + . = ALIGN(8); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(8); + + .image_copy_end : + { + *(.__image_copy_end) + } + + . = ALIGN(8); + + .rel_dyn_start : + { + *(.__rel_dyn_start) + } + + .rela.dyn : { + *(.rela*) + } + + .rel_dyn_end : + { + *(.__rel_dyn_end) + } + + _end = .; + + . = ALIGN(8); + + .bss_start : { + KEEP(*(.__bss_start)); + } + + .bss : { + *(.bss*) + . = ALIGN(8); + } + + .bss_end : { + KEEP(*(.__bss_end)); + } + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/at91-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/at91-common/Makefile new file mode 100644 index 000000000..5b978384e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/at91-common/Makefile @@ -0,0 +1,12 @@ +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2013 Atmel Corporation +# Bo Shen <voice.shen@atmel.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_AT91_WANTS_COMMON_PHY) += phy.o +obj-$(CONFIG_SPL_BUILD) += mpddrc.o spl.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/at91-common/mpddrc.c b/qemu/roms/u-boot/arch/arm/cpu/at91-common/mpddrc.c new file mode 100644 index 000000000..813639640 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/at91-common/mpddrc.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2013 Atmel Corporation + * Bo Shen <voice.shen@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/atmel_mpddrc.h> + +static inline void atmel_mpddr_op(int mode, u32 ram_address) +{ + struct atmel_mpddr *mpddr = (struct atmel_mpddr *)ATMEL_BASE_MPDDRC; + + writel(mode, &mpddr->mr); + writel(0, ram_address); +} + +int ddr2_init(const unsigned int ram_address, + const struct atmel_mpddr *mpddr_value) +{ + struct atmel_mpddr *mpddr = (struct atmel_mpddr *)ATMEL_BASE_MPDDRC; + u32 ba_off, cr; + + /* Compute bank offset according to NC in configuration register */ + ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9; + if (!(mpddr_value->cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED)) + ba_off += ((mpddr->cr & ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11; + + ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2; + + /* Program the memory device type into the memory device register */ + writel(mpddr_value->md, &mpddr->md); + + /* Program the configuration register */ + writel(mpddr_value->cr, &mpddr->cr); + + /* Program the timing register */ + writel(mpddr_value->tpr0, &mpddr->tpr0); + writel(mpddr_value->tpr1, &mpddr->tpr1); + writel(mpddr_value->tpr2, &mpddr->tpr2); + + /* Issue a NOP command */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address); + + /* A 200 us is provided to precede any signal toggle */ + udelay(200); + + /* Issue a NOP command */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address); + + /* Issue an all banks precharge command */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address); + + /* Issue an extended mode register set(EMRS2) to choose operation */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, + ram_address + (0x2 << ba_off)); + + /* Issue an extended mode register set(EMRS3) to set EMSR to 0 */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, + ram_address + (0x3 << ba_off)); + + /* + * Issue an extended mode register set(EMRS1) to enable DLL and + * program D.I.C (output driver impedance control) + */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, + ram_address + (0x1 << ba_off)); + + /* Enable DLL reset */ + cr = readl(&mpddr->cr); + writel(cr | ATMEL_MPDDRC_CR_DLL_RESET_ENABLED, &mpddr->cr); + + /* A mode register set(MRS) cycle is issued to reset DLL */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address); + + /* Issue an all banks precharge command */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address); + + /* Two auto-refresh (CBR) cycles are provided */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address); + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address); + + /* Disable DLL reset */ + cr = readl(&mpddr->cr); + writel(cr & (~ATMEL_MPDDRC_CR_DLL_RESET_ENABLED), &mpddr->cr); + + /* A mode register set (MRS) cycle is issued to disable DLL reset */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address); + + /* Set OCD calibration in default state */ + cr = readl(&mpddr->cr); + writel(cr | ATMEL_MPDDRC_CR_OCD_DEFAULT, &mpddr->cr); + + /* + * An extended mode register set (EMRS1) cycle is issued + * to OCD default value + */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, + ram_address + (0x1 << ba_off)); + + /* OCD calibration mode exit */ + cr = readl(&mpddr->cr); + writel(cr & (~ATMEL_MPDDRC_CR_OCD_DEFAULT), &mpddr->cr); + + /* + * An extended mode register set (EMRS1) cycle is issued + * to enable OCD exit + */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, + ram_address + (0x1 << ba_off)); + + /* A nornal mode command is provided */ + atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address); + + /* Perform a write access to any DDR2-SDRAM address */ + writel(0, ram_address); + + /* Write the refresh rate */ + writel(mpddr_value->rtr, &mpddr->rtr); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/at91-common/phy.c b/qemu/roms/u-boot/arch/arm/cpu/at91-common/phy.c new file mode 100644 index 000000000..2cba7169e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/at91-common/phy.c @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * (C) Copyright 2012 + * Markus Hubig <mhubig@imko.de> + * IMKO GmbH <www.imko.de> + * + * Copyright (C) 2013 DENX Software Engineering, hs@denx.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/sizes.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_rstc.h> +#include <watchdog.h> + +void at91_phy_reset(void) +{ + unsigned long erstl; + unsigned long start = get_timer(0); + unsigned long const timeout = 1000; /* 1000ms */ + at91_rstc_t *rstc = (at91_rstc_t *)ATMEL_BASE_RSTC; + + erstl = readl(&rstc->mr) & AT91_RSTC_MR_ERSTL_MASK; + + /* + * Need to reset PHY -> 500ms reset + * Reset PHY by pulling the NRST line for 500ms to low. To do so + * disable user reset for low level on NRST pin and poll the NRST + * level in reset status register. + */ + writel(AT91_RSTC_KEY | AT91_RSTC_MR_ERSTL(0x0D) | + AT91_RSTC_MR_URSTEN, &rstc->mr); + + writel(AT91_RSTC_KEY | AT91_RSTC_CR_EXTRST, &rstc->cr); + + /* Wait for end of hardware reset */ + while (!(readl(&rstc->sr) & AT91_RSTC_SR_NRSTL)) { + /* avoid shutdown by watchdog */ + WATCHDOG_RESET(); + mdelay(10); + + /* timeout for not getting stuck in an endless loop */ + if (get_timer(start) >= timeout) { + puts("*** ERROR: Timeout waiting for PHY reset!\n"); + break; + } + }; + + /* Restore NRST value */ + writel(AT91_RSTC_KEY | erstl | AT91_RSTC_MR_URSTEN, &rstc->mr); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/at91-common/spl.c b/qemu/roms/u-boot/arch/arm/cpu/at91-common/spl.c new file mode 100644 index 000000000..7f4debb91 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/at91-common/spl.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2013 Atmel Corporation + * Bo Shen <voice.shen@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_wdt.h> +#include <asm/arch/clk.h> +#include <spl.h> + +static void at91_disable_wdt(void) +{ + struct at91_wdt *wdt = (struct at91_wdt *)ATMEL_BASE_WDT; + + writel(AT91_WDT_MR_WDDIS, &wdt->mr); +} + +void at91_plla_init(u32 pllar) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + writel(pllar, &pmc->pllar); + while (!(readl(&pmc->sr) & (AT91_PMC_LOCKA | AT91_PMC_MCKRDY))) + ; +} + +void at91_mck_init(u32 mckr) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + u32 tmp; + + tmp = readl(&pmc->mckr); + tmp &= ~(AT91_PMC_MCKR_PRES_MASK | + AT91_PMC_MCKR_MDIV_MASK | + AT91_PMC_MCKR_PLLADIV_2); + tmp |= mckr & (AT91_PMC_MCKR_PRES_MASK | + AT91_PMC_MCKR_MDIV_MASK | + AT91_PMC_MCKR_PLLADIV_2); + writel(tmp, &pmc->mckr); + + while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) + ; +} + + +u32 spl_boot_device(void) +{ +#ifdef CONFIG_SYS_USE_MMC + return BOOT_DEVICE_MMC1; +#elif CONFIG_SYS_USE_NANDFLASH + return BOOT_DEVICE_NAND; +#elif CONFIG_SYS_USE_SERIALFLASH + return BOOT_DEVICE_SPI; +#endif + return BOOT_DEVICE_NONE; +} + +u32 spl_boot_mode(void) +{ + switch (spl_boot_device()) { +#ifdef CONFIG_SYS_USE_MMC + case BOOT_DEVICE_MMC1: + return MMCSD_MODE_FAT; + break; +#endif + case BOOT_DEVICE_NONE: + default: + hang(); + } +} + +void s_init(void) +{ + /* disable watchdog */ + at91_disable_wdt(); + + /* PMC configuration */ + at91_pmc_init(); + + at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); + + timer_init(); + + board_early_init_f(); + + preloader_console_init(); + + mem_init(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/at91-common/u-boot-spl.lds b/qemu/roms/u-boot/arch/arm/cpu/at91-common/u-boot-spl.lds new file mode 100644 index 000000000..57ac1eb24 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/at91-common/u-boot-spl.lds @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + * + * (C) 2013 Atmel Corporation + * Bo Shen <voice.shen@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE, \ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : + { + __start = .; + arch/arm/cpu/armv7/start.o (.text*) + *(.text*) + } >.sram + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram + + . = ALIGN(4); + __image_copy_end = .; + + .end : + { + *(.__end) + } >.sram + + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } >.sdram +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/pxa/Makefile b/qemu/roms/u-boot/arch/arm/cpu/pxa/Makefile new file mode 100644 index 000000000..8cd475e3a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/pxa/Makefile @@ -0,0 +1,15 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y = start.o + +obj-$(CONFIG_CPU_PXA25X) += pxa2xx.o +obj-$(CONFIG_CPU_PXA27X) += pxa2xx.o + +obj-y += cpuinfo.o +obj-y += timer.o +obj-y += usb.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/pxa/config.mk b/qemu/roms/u-boot/arch/arm/cpu/pxa/config.mk new file mode 100644 index 000000000..525f5d33b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/pxa/config.mk @@ -0,0 +1,22 @@ +# +# (C) Copyright 2002 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +PLATFORM_CPPFLAGS += -mcpu=xscale + +# +# !WARNING! +# The PXA's OneNAND SPL uses .text.0 and .text.1 segments to allow booting from +# really small OneNAND memories where the mmap'd window is only 1KiB big. The +# .text.0 contains only the bare minimum needed to load the real SPL into SRAM. +# Add .text.0 and .text.1 into OBJFLAGS, so when the SPL is being objcopy'd, +# they are not discarded. +# + +#ifdef CONFIG_SPL_BUILD +OBJCOPYFLAGS += -j .text.0 -j .text.1 +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/pxa/cpuinfo.c b/qemu/roms/u-boot/arch/arm/cpu/pxa/cpuinfo.c new file mode 100644 index 000000000..9d1607995 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/pxa/cpuinfo.c @@ -0,0 +1,126 @@ +/* + * PXA CPU information display + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <errno.h> +#include <linux/compiler.h> + +#define CPU_MASK_PXA_PRODID 0x000003f0 +#define CPU_MASK_PXA_REVID 0x0000000f + +#define CPU_MASK_PRODREV (CPU_MASK_PXA_PRODID | CPU_MASK_PXA_REVID) + +#define CPU_VALUE_PXA25X 0x100 +#define CPU_VALUE_PXA27X 0x110 + +static uint32_t pxa_get_cpuid(void) +{ + uint32_t cpuid; + asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r"(cpuid)); + return cpuid; +} + +int cpu_is_pxa25x(void) +{ + uint32_t id = pxa_get_cpuid(); + id &= CPU_MASK_PXA_PRODID; + return id == CPU_VALUE_PXA25X; +} + +int cpu_is_pxa27x(void) +{ + uint32_t id = pxa_get_cpuid(); + id &= CPU_MASK_PXA_PRODID; + return id == CPU_VALUE_PXA27X; +} + +uint32_t pxa_get_cpu_revision(void) +{ + return pxa_get_cpuid() & CPU_MASK_PRODREV; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +static const char *pxa25x_get_revision(void) +{ + static __maybe_unused const char * const revs_25x[] = { "A0" }; + static __maybe_unused const char * const revs_26x[] = { + "A0", "B0", "B1" + }; + static const char *unknown = "Unknown"; + uint32_t id; + + if (!cpu_is_pxa25x()) + return unknown; + + id = pxa_get_cpuid() & CPU_MASK_PXA_REVID; + +/* PXA26x is a sick special case as it can't be told apart from PXA25x :-( */ +#ifdef CONFIG_CPU_PXA26X + switch (id) { + case 3: return revs_26x[0]; + case 5: return revs_26x[1]; + case 6: return revs_26x[2]; + } +#else + if (id == 6) + return revs_25x[0]; +#endif + return unknown; +} + +static const char *pxa27x_get_revision(void) +{ + static const char *const rev[] = { "A0", "A1", "B0", "B1", "C0", "C5" }; + static const char *unknown = "Unknown"; + uint32_t id; + + if (!cpu_is_pxa27x()) + return unknown; + + id = pxa_get_cpuid() & CPU_MASK_PXA_REVID; + + if ((id == 5) || (id == 6) || (id > 7)) + return unknown; + + /* Cap the special PXA270 C5 case. */ + if (id == 7) + id = 5; + + return rev[id]; +} + +static int print_cpuinfo_pxa2xx(void) +{ + if (cpu_is_pxa25x()) { + puts("Marvell PXA25x rev. "); + puts(pxa25x_get_revision()); + } else if (cpu_is_pxa27x()) { + puts("Marvell PXA27x rev. "); + puts(pxa27x_get_revision()); + } else + return -EINVAL; + + puts("\n"); + + return 0; +} + +int print_cpuinfo(void) +{ + int ret; + + puts("CPU: "); + + ret = print_cpuinfo_pxa2xx(); + if (!ret) + return ret; + + return ret; +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/pxa/pxa2xx.c b/qemu/roms/u-boot/arch/arm/cpu/pxa/pxa2xx.c new file mode 100644 index 000000000..7e861e26d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/pxa/pxa2xx.c @@ -0,0 +1,286 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/io.h> +#include <asm/system.h> +#include <command.h> +#include <common.h> +#include <asm/arch/pxa-regs.h> + +/* Flush I/D-cache */ +static void cache_flush(void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (i)); +} + +int cleanup_before_linux(void) +{ + /* + * This function is called just before we call Linux. It prepares + * the processor for Linux by just disabling everything that can + * disturb booting Linux. + */ + + disable_interrupts(); + icache_disable(); + dcache_disable(); + cache_flush(); + + return 0; +} + +void pxa_wait_ticks(int ticks) +{ + writel(0, OSCR); + while (readl(OSCR) < ticks) + asm volatile("" : : : "memory"); +} + +inline void writelrb(uint32_t val, uint32_t addr) +{ + writel(val, addr); + asm volatile("" : : : "memory"); + readl(addr); + asm volatile("" : : : "memory"); +} + +void pxa2xx_dram_init(void) +{ + uint32_t tmp; + int i; + /* + * 1) Initialize Asynchronous static memory controller + */ + + writelrb(CONFIG_SYS_MSC0_VAL, MSC0); + writelrb(CONFIG_SYS_MSC1_VAL, MSC1); + writelrb(CONFIG_SYS_MSC2_VAL, MSC2); + /* + * 2) Initialize Card Interface + */ + + /* MECR: Memory Expansion Card Register */ + writelrb(CONFIG_SYS_MECR_VAL, MECR); + /* MCMEM0: Card Interface slot 0 timing */ + writelrb(CONFIG_SYS_MCMEM0_VAL, MCMEM0); + /* MCMEM1: Card Interface slot 1 timing */ + writelrb(CONFIG_SYS_MCMEM1_VAL, MCMEM1); + /* MCATT0: Card Interface Attribute Space Timing, slot 0 */ + writelrb(CONFIG_SYS_MCATT0_VAL, MCATT0); + /* MCATT1: Card Interface Attribute Space Timing, slot 1 */ + writelrb(CONFIG_SYS_MCATT1_VAL, MCATT1); + /* MCIO0: Card Interface I/O Space Timing, slot 0 */ + writelrb(CONFIG_SYS_MCIO0_VAL, MCIO0); + /* MCIO1: Card Interface I/O Space Timing, slot 1 */ + writelrb(CONFIG_SYS_MCIO1_VAL, MCIO1); + + /* + * 3) Configure Fly-By DMA register + */ + + writelrb(CONFIG_SYS_FLYCNFG_VAL, FLYCNFG); + + /* + * 4) Initialize Timing for Sync Memory (SDCLK0) + */ + + /* + * Before accessing MDREFR we need a valid DRI field, so we set + * this to power on defaults + DRI field. + */ + + /* Read current MDREFR config and zero out DRI */ + tmp = readl(MDREFR) & ~0xfff; + /* Add user-specified DRI */ + tmp |= CONFIG_SYS_MDREFR_VAL & 0xfff; + /* Configure important bits */ + tmp |= MDREFR_K0RUN | MDREFR_SLFRSH; + tmp &= ~(MDREFR_APD | MDREFR_E1PIN); + + /* Write MDREFR back */ + writelrb(tmp, MDREFR); + + /* + * 5) Initialize Synchronous Static Memory (Flash/Peripherals) + */ + + /* Initialize SXCNFG register. Assert the enable bits. + * + * Write SXMRS to cause an MRS command to all enabled banks of + * synchronous static memory. Note that SXLCR need not be written + * at this time. + */ + writelrb(CONFIG_SYS_SXCNFG_VAL, SXCNFG); + + /* + * 6) Initialize SDRAM + */ + + writelrb(CONFIG_SYS_MDREFR_VAL & ~MDREFR_SLFRSH, MDREFR); + writelrb(CONFIG_SYS_MDREFR_VAL | MDREFR_E1PIN, MDREFR); + + /* + * 7) Write MDCNFG with MDCNFG:DEx deasserted (set to 0), to configure + * but not enable each SDRAM partition pair. + */ + + writelrb(CONFIG_SYS_MDCNFG_VAL & + ~(MDCNFG_DE0 | MDCNFG_DE1 | MDCNFG_DE2 | MDCNFG_DE3), MDCNFG); + /* Wait for the clock to the SDRAMs to stabilize, 100..200 usec. */ + pxa_wait_ticks(0x300); + + /* + * 8) Trigger a number (usually 8) refresh cycles by attempting + * non-burst read or write accesses to disabled SDRAM, as commonly + * specified in the power up sequence documented in SDRAM data + * sheets. The address(es) used for this purpose must not be + * cacheable. + */ + for (i = 9; i >= 0; i--) { + writel(i, 0xa0000000); + asm volatile("" : : : "memory"); + } + /* + * 9) Write MDCNFG with enable bits asserted (MDCNFG:DEx set to 1). + */ + + tmp = CONFIG_SYS_MDCNFG_VAL & + (MDCNFG_DE0 | MDCNFG_DE1 | MDCNFG_DE2 | MDCNFG_DE3); + tmp |= readl(MDCNFG); + writelrb(tmp, MDCNFG); + + /* + * 10) Write MDMRS. + */ + + writelrb(CONFIG_SYS_MDMRS_VAL, MDMRS); + + /* + * 11) Enable APD + */ + + if (CONFIG_SYS_MDREFR_VAL & MDREFR_APD) { + tmp = readl(MDREFR); + tmp |= MDREFR_APD; + writelrb(tmp, MDREFR); + } +} + +void pxa_gpio_setup(void) +{ + writel(CONFIG_SYS_GPSR0_VAL, GPSR0); + writel(CONFIG_SYS_GPSR1_VAL, GPSR1); + writel(CONFIG_SYS_GPSR2_VAL, GPSR2); +#if defined(CONFIG_CPU_PXA27X) + writel(CONFIG_SYS_GPSR3_VAL, GPSR3); +#endif + + writel(CONFIG_SYS_GPCR0_VAL, GPCR0); + writel(CONFIG_SYS_GPCR1_VAL, GPCR1); + writel(CONFIG_SYS_GPCR2_VAL, GPCR2); +#if defined(CONFIG_CPU_PXA27X) + writel(CONFIG_SYS_GPCR3_VAL, GPCR3); +#endif + + writel(CONFIG_SYS_GPDR0_VAL, GPDR0); + writel(CONFIG_SYS_GPDR1_VAL, GPDR1); + writel(CONFIG_SYS_GPDR2_VAL, GPDR2); +#if defined(CONFIG_CPU_PXA27X) + writel(CONFIG_SYS_GPDR3_VAL, GPDR3); +#endif + + writel(CONFIG_SYS_GAFR0_L_VAL, GAFR0_L); + writel(CONFIG_SYS_GAFR0_U_VAL, GAFR0_U); + writel(CONFIG_SYS_GAFR1_L_VAL, GAFR1_L); + writel(CONFIG_SYS_GAFR1_U_VAL, GAFR1_U); + writel(CONFIG_SYS_GAFR2_L_VAL, GAFR2_L); + writel(CONFIG_SYS_GAFR2_U_VAL, GAFR2_U); +#if defined(CONFIG_CPU_PXA27X) + writel(CONFIG_SYS_GAFR3_L_VAL, GAFR3_L); + writel(CONFIG_SYS_GAFR3_U_VAL, GAFR3_U); +#endif + + writel(CONFIG_SYS_PSSR_VAL, PSSR); +} + +void pxa_interrupt_setup(void) +{ + writel(0, ICLR); + writel(0, ICMR); +#if defined(CONFIG_CPU_PXA27X) + writel(0, ICLR2); + writel(0, ICMR2); +#endif +} + +void pxa_clock_setup(void) +{ + writel(CONFIG_SYS_CKEN, CKEN); + writel(CONFIG_SYS_CCCR, CCCR); + asm volatile("mcr p14, 0, %0, c6, c0, 0" : : "r"(0x0b)); + + /* enable the 32Khz oscillator for RTC and PowerManager */ + writel(OSCC_OON, OSCC); + while (!(readl(OSCC) & OSCC_OOK)) + asm volatile("" : : : "memory"); +} + +void pxa_wakeup(void) +{ + uint32_t rcsr; + + rcsr = readl(RCSR); + writel(rcsr & (RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR), RCSR); + + /* Wakeup */ + if (rcsr & RCSR_SMR) { + writel(PSSR_PH, PSSR); + pxa2xx_dram_init(); + icache_disable(); + dcache_disable(); + asm volatile("mov pc, %0" : : "r"(readl(PSPR))); + } +} + +int arch_cpu_init(void) +{ + pxa_gpio_setup(); + pxa_wakeup(); + pxa_interrupt_setup(); + pxa_clock_setup(); + return 0; +} + +void i2c_clk_enable(void) +{ + /* Set the global I2C clock on */ + writel(readl(CKEN) | CKEN14_I2C, CKEN); +} + +void __attribute__((weak)) reset_cpu(ulong ignored) __attribute__((noreturn)); + +void reset_cpu(ulong ignored) +{ + uint32_t tmp; + + setbits_le32(OWER, OWER_WME); + + tmp = readl(OSCR); + tmp += 0x1000; + writel(tmp, OSMR3); + writel(MDREFR_SLFRSH, MDREFR); + + for (;;) + ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/pxa/start.S b/qemu/roms/u-boot/arch/arm/cpu/pxa/start.S new file mode 100644 index 000000000..ae0d13ce8 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/pxa/start.S @@ -0,0 +1,450 @@ +/* + * armboot - Startup Code for XScale CPU-core + * + * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> + * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (C) 2000 Wolfgang Denk <wd@denx.de> + * Copyright (C) 2001 Alex Zuepke <azu@sysgo.de> + * Copyright (C) 2001 Marius Groger <mag@sysgo.de> + * Copyright (C) 2002 Alex Zupke <azu@sysgo.de> + * Copyright (C) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (C) 2002 Kyle Harris <kharris@nexus-tech.net> + * Copyright (C) 2003 Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de> + * Copyright (C) 2003 Kshitij <kshitij@ti.com> + * Copyright (C) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de> + * Copyright (C) 2004 Texas Instruments <r-woodruff2@ti.com> + * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> + +#ifdef CONFIG_CPU_PXA25X +#if ((CONFIG_SYS_INIT_SP_ADDR) != 0xfffff800) +#error "Init SP address must be set to 0xfffff800 for PXA250" +#endif +#endif + +.globl _start +_start: b reset +#ifdef CONFIG_SPL_BUILD + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + +_hang: + .word do_hang + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 /* now 16*4=64 */ +#else + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq +_pad: .word 0x12345678 /* now 16*4=64 */ +#endif /* CONFIG_SPL_BUILD */ +.global _end_vect +_end_vect: + + .balignl 16,0xdeadbeef +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + +#ifdef CONFIG_CPU_PXA25X + bl lock_cache_for_stack +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + +#ifdef CONFIG_CPU_PXA25X + /* + * Unlock (actually, disable) the cache now that board_init_f + * is done. We could do this earlier but we would need to add + * a new C runtime hook, whereas c_runtime_cpu_setup already + * exists. + * As this routine is just a call to cpu_init_crit, let us + * tail-optimize and do a simple branch here. + */ + b cpu_init_crit +#else + bx lr +#endif + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) || defined(CONFIG_CPU_PXA25X) +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* Invalidate I+D+BTB caches */ + mcr p15, 0, r0, c8, c7, 0 /* Invalidate Unified TLB */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00003300 @ clear bits 13:12, 9:8 (--VI --RS) + bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) + orr r0, r0, #0x00000002 @ set bit 2 (A) Align + mcr p15, 0, r0, c1, c0, 0 + + mov pc, lr /* back to my caller */ +#endif /* !CONFIG_SKIP_LOWLEVEL_INIT || CONFIG_CPU_PXA25X */ + +#ifndef CONFIG_SPL_BUILD +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current user stack + stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 + + ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort stack + ldmia r2, {r2 - r3} @ get values for "aborted" pc and cpsr (into parm regs) + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp @ save current stack into r0 (param register) + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter in banked mode) + + str lr, [r13] @ save caller lr in position 0 of saved stack + mrs lr, spsr @ get the spsr + str lr, [r13, #4] @ save spsr in position 1 of saved stack + + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 @ switch modes, make sure moves will execute + mov lr, pc @ capture return pc + movs pc, lr @ jump to next instruction & switch modes. + .endm + + .macro get_bad_stack_swi + sub r13, r13, #4 @ space on current stack for scratch reg. + str r0, [r13] @ save R0's value. + ldr r0, IRQ_STACK_START_IN @ get data regions start + str lr, [r0] @ save caller lr in position 0 of saved stack + mrs lr, spsr @ get the spsr + str lr, [r0, #4] @ save spsr in position 1 of saved stack + ldr lr, [r0] @ restore lr + ldr r0, [r13] @ restore r0 + add r13, r13, #4 @ pop stack entry + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm +#endif /* CONFIG_SPL_BUILD */ + +/* + * exception handlers + */ +#ifdef CONFIG_SPL_BUILD + .align 5 +do_hang: + bl hang /* hang and never return */ +#else /* !CONFIG_SPL_BUILD */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack_swi + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif + .align 5 +#endif /* CONFIG_SPL_BUILD */ + + +/* + * Enable MMU to use DCache as DRAM. + * + * This is useful on PXA25x and PXA26x in early bootstages, where there is no + * other possible memory available to hold stack. + */ +#ifdef CONFIG_CPU_PXA25X +.macro CPWAIT reg + mrc p15, 0, \reg, c2, c0, 0 + mov \reg, \reg + sub pc, pc, #4 +.endm +lock_cache_for_stack: + /* Domain access -- enable for all CPs */ + ldr r0, =0x0000ffff + mcr p15, 0, r0, c3, c0, 0 + + /* Point TTBR to MMU table */ + ldr r0, =mmutable + mcr p15, 0, r0, c2, c0, 0 + + /* Kick in MMU, ICache, DCache, BTB */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, #0x1b00 + bic r0, #0x0087 + orr r0, #0x1800 + orr r0, #0x0005 + mcr p15, 0, r0, c1, c0, 0 + CPWAIT r0 + + /* Unlock Icache, Dcache */ + mcr p15, 0, r0, c9, c1, 1 + mcr p15, 0, r0, c9, c2, 1 + + /* Flush Icache, Dcache, BTB */ + mcr p15, 0, r0, c7, c7, 0 + + /* Unlock I-TLB, D-TLB */ + mcr p15, 0, r0, c10, c4, 1 + mcr p15, 0, r0, c10, c8, 1 + + /* Flush TLB */ + mcr p15, 0, r0, c8, c7, 0 + + /* Allocate 4096 bytes of Dcache as RAM */ + + /* Drain pending loads and stores */ + mcr p15, 0, r0, c7, c10, 4 + + mov r4, #0x00 + mov r5, #0x00 + mov r2, #0x01 + mcr p15, 0, r0, c9, c2, 0 + CPWAIT r0 + + /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */ + mov r0, #128 + ldr r1, =0xfffff000 + +alloc: + mcr p15, 0, r1, c7, c2, 5 + /* Drain pending loads and stores */ + mcr p15, 0, r0, c7, c10, 4 + strd r4, [r1], #8 + strd r4, [r1], #8 + strd r4, [r1], #8 + strd r4, [r1], #8 + subs r0, #0x01 + bne alloc + /* Drain pending loads and stores */ + mcr p15, 0, r0, c7, c10, 4 + mov r2, #0x00 + mcr p15, 0, r2, c9, c2, 0 + CPWAIT r0 + + mov pc, lr + +.section .mmutable, "a" +mmutable: + .align 14 + /* 0x00000000 - 0xffe00000 : 1:1, uncached mapping */ + .set __base, 0 + .rept 0xfff + .word (__base << 20) | 0xc12 + .set __base, __base + 1 + .endr + + /* 0xfff00000 : 1:1, cached mapping */ + .word (0xfff << 20) | 0x1c1e +#endif /* CONFIG_CPU_PXA25X */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/pxa/timer.c b/qemu/roms/u-boot/arch/arm/cpu/pxa/timer.c new file mode 100644 index 000000000..c4717de6a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/pxa/timer.c @@ -0,0 +1,85 @@ +/* + * Marvell PXA2xx/3xx timer driver + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/arch/pxa-regs.h> +#include <asm/io.h> +#include <common.h> +#include <div64.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define TIMER_LOAD_VAL 0xffffffff + +#define timestamp (gd->arch.tbl) +#define lastinc (gd->arch.lastinc) + +#if defined(CONFIG_CPU_PXA27X) || defined(CONFIG_CPU_MONAHANS) +#define TIMER_FREQ_HZ 3250000 +#elif defined(CONFIG_CPU_PXA25X) +#define TIMER_FREQ_HZ 3686400 +#else +#error "Timer frequency unknown - please config PXA CPU type" +#endif + +static unsigned long long tick_to_time(unsigned long long tick) +{ + return lldiv(tick * CONFIG_SYS_HZ, TIMER_FREQ_HZ); +} + +static unsigned long long us_to_tick(unsigned long long us) +{ + return lldiv(us * TIMER_FREQ_HZ, 1000000); +} + +int timer_init(void) +{ + writel(0, OSCR); + return 0; +} + +unsigned long long get_ticks(void) +{ + /* Current tick value */ + uint32_t now = readl(OSCR); + + if (now >= lastinc) { + /* + * Normal mode (non roll) + * Move stamp forward with absolute diff ticks + */ + timestamp += (now - lastinc); + } else { + /* We have rollover of incrementer */ + timestamp += (TIMER_LOAD_VAL - lastinc) + now; + } + + lastinc = now; + return timestamp; +} + +ulong get_timer(ulong base) +{ + return tick_to_time(get_ticks()) - base; +} + +void __udelay(unsigned long usec) +{ + unsigned long long tmp; + ulong tmo; + + tmo = us_to_tick(usec); + tmp = get_ticks() + tmo; /* get current timestamp */ + + while (get_ticks() < tmp) /* loop till event */ + /*NOP*/; +} + +ulong get_tbclk(void) +{ + return TIMER_FREQ_HZ; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/pxa/usb.c b/qemu/roms/u-boot/arch/arm/cpu/pxa/usb.c new file mode 100644 index 000000000..c31c2d733 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/pxa/usb.c @@ -0,0 +1,89 @@ +/* + * (C) Copyright 2006 + * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) +# if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_CPU_PXA27X) + +#include <asm/arch/pxa-regs.h> +#include <asm/io.h> +#include <usb.h> + +int usb_cpu_init(void) +{ +#if defined(CONFIG_CPU_MONAHANS) + /* Enable USB host clock. */ + writel(readl(CKENA) | CKENA_2_USBHOST | CKENA_20_UDC, CKENA); + udelay(100); +#endif +#if defined(CONFIG_CPU_PXA27X) + /* Enable USB host clock. */ + writel(readl(CKEN) | CKEN10_USBHOST, CKEN); +#endif + +#if defined(CONFIG_CPU_MONAHANS) + /* Configure Port 2 for Host (USB Client Registers) */ + writel(0x3000c, UP2OCR); +#endif + + writel(readl(UHCHR) | UHCHR_FHR, UHCHR); + mdelay(11); + writel(readl(UHCHR) & ~UHCHR_FHR, UHCHR); + + writel(readl(UHCHR) | UHCHR_FSBIR, UHCHR); + while (readl(UHCHR) & UHCHR_FSBIR) + udelay(1); + +#if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_PXA27X) + writel(readl(UHCHR) & ~UHCHR_SSEP0, UHCHR); +#endif +#if defined(CONFIG_CPU_PXA27X) + writel(readl(UHCHR) & ~UHCHR_SSEP2, UHCHR); +#endif + writel(readl(UHCHR) & ~(UHCHR_SSEP1 | UHCHR_SSE), UHCHR); + + return 0; +} + +int usb_cpu_stop(void) +{ + writel(readl(UHCHR) | UHCHR_FHR, UHCHR); + udelay(11); + writel(readl(UHCHR) & ~UHCHR_FHR, UHCHR); + + writel(readl(UHCCOMS) | UHCCOMS_HCR, UHCCOMS); + udelay(10); + +#if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_PXA27X) + writel(readl(UHCHR) | UHCHR_SSEP0, UHCHR); +#endif +#if defined(CONFIG_CPU_PXA27X) + writel(readl(UHCHR) | UHCHR_SSEP2, UHCHR); +#endif + writel(readl(UHCHR) | UHCHR_SSEP1 | UHCHR_SSE, UHCHR); + +#if defined(CONFIG_CPU_MONAHANS) + /* Disable USB host clock. */ + writel(readl(CKENA) & ~(CKENA_2_USBHOST | CKENA_20_UDC), CKENA); + udelay(100); +#endif +#if defined(CONFIG_CPU_PXA27X) + /* Disable USB host clock. */ + writel(readl(CKEN) & ~CKEN10_USBHOST, CKEN); +#endif + + return 0; +} + +int usb_cpu_init_fail(void) +{ + return usb_cpu_stop(); +} + +# endif /* defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_CPU_PXA27X) */ +#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/sa1100/Makefile b/qemu/roms/u-boot/arch/arm/cpu/sa1100/Makefile new file mode 100644 index 000000000..85a0d28f4 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/sa1100/Makefile @@ -0,0 +1,11 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y = start.o + +obj-y += cpu.o +obj-y += timer.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/sa1100/config.mk b/qemu/roms/u-boot/arch/arm/cpu/sa1100/config.mk new file mode 100644 index 000000000..3afa685b3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/sa1100/config.mk @@ -0,0 +1,9 @@ +# +# (C) Copyright 2002 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +PLATFORM_CPPFLAGS += -march=armv4 -mtune=strongarm1100 diff --git a/qemu/roms/u-boot/arch/arm/cpu/sa1100/cpu.c b/qemu/roms/u-boot/arch/arm/cpu/sa1100/cpu.c new file mode 100644 index 000000000..6651898de --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/sa1100/cpu.c @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +#ifdef CONFIG_USE_IRQ +DECLARE_GLOBAL_DATA_PTR; +#endif + +static void cache_flush(void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * just disable everything that can disturb booting linux + */ + + disable_interrupts (); + + /* turn off I-cache */ + icache_disable(); + dcache_disable(); + + /* flush I-cache */ + cache_flush(); + + return (0); +} + +/* flush I/D-cache */ +static void cache_flush (void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (i)); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/sa1100/start.S b/qemu/roms/u-boot/arch/arm/cpu/sa1100/start.S new file mode 100644 index 000000000..bf80937a7 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/sa1100/start.S @@ -0,0 +1,349 @@ +/* + * armboot - Startup Code for SA1100 CPU + * + * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> + * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (C) 2000 Wolfgang Denk <wd@denx.de> + * Copyright (c) 2001 Alex Züpke <azu@sysgo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + + +.globl _start +_start: b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq + + .balignl 16,0xdeadbeef + + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * relocate armboot to ram + * setup stack + * jump to second stage + * + ************************************************************************* + */ + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + + +/* Interrupt-Controller base address */ +IC_BASE: .word 0x90050000 +#define ICMR 0x04 + + +/* Reset-Controller */ +RST_BASE: .word 0x90030000 +#define RSRR 0x00 +#define RCSR 0x04 + + +/* PWR */ +PWR_BASE: .word 0x90020000 +#define PSPR 0x08 +#define PPCR 0x14 +cpuspeed: .word CONFIG_SYS_CPUSPEED + + +cpu_init_crit: + /* + * mask all IRQs + */ + ldr r0, IC_BASE + mov r1, #0x00 + str r1, [r0, #ICMR] + + /* set clock speed */ + ldr r0, PWR_BASE + ldr r1, cpuspeed + str r1, [r0, #PPCR] + + /* + * before relocating, we have to setup RAM timing + * because memory timing is board-dependend, you will + * find a lowlevel_init.S in your board directory. + */ + mov ip, lr + bl lowlevel_init + mov lr, ip + + /* + * disable MMU stuff and enable I-cache + */ + mrc p15,0,r0,c1,c0 + bic r0, r0, #0x00002000 @ clear bit 13 (X) + bic r0, r0, #0x0000000f @ clear bits 3-0 (WCAM) + orr r0, r0, #0x00001000 @ set bit 12 (I) Icache + orr r0, r0, #0x00000002 @ set bit 2 (A) Align + mcr p15,0,r0,c1,c0 + + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + + mov pc, lr + + +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC + + ldr r2, IRQ_STACK_START_IN + ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 + add r0, sp, #S_FRAME_SIZE @ restore sp_SVC + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r + mov r0, sp + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + + str lr, [r13] @ save caller lr / spsr + mrs lr, spsr + str lr, [r13, #4] + + mov r13, #MODE_SVC @ prepare SVC-Mode + msr spsr_c, r13 + mov lr, pc + movs pc, lr + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif + + .align 5 +.globl reset_cpu +reset_cpu: + ldr r0, RST_BASE + mov r1, #0x0 @ set bit 3-0 ... + str r1, [r0, #RCSR] @ ... to clear in RCSR + mov r1, #0x1 + str r1, [r0, #RSRR] @ and perform reset + b reset_cpu @ silly, but repeat endlessly diff --git a/qemu/roms/u-boot/arch/arm/cpu/sa1100/timer.c b/qemu/roms/u-boot/arch/arm/cpu/sa1100/timer.c new file mode 100644 index 000000000..0a0006b42 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/sa1100/timer.c @@ -0,0 +1,73 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <SA-1100.h> + +ulong get_timer (ulong base) +{ + return get_timer_masked (); +} + +void __udelay (unsigned long usec) +{ + udelay_masked (usec); +} + +ulong get_timer_masked (void) +{ + return OSCR; +} + +void udelay_masked (unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + if (usec >= 1000) { + tmo = usec / 1000; + tmo *= CONFIG_SYS_HZ; + tmo /= 1000; + } else { + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000*1000); + } + + endtime = get_timer_masked () + tmo; + + do { + ulong now = get_timer_masked (); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + ulong tbclk; + + tbclk = CONFIG_SYS_HZ; + return tbclk; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/Makefile new file mode 100644 index 000000000..892556e64 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/Makefile @@ -0,0 +1,16 @@ +# +# (C) Copyright 2010,2011 Nvidia Corporation. +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += ap.o +obj-y += board.o +obj-y += cache.o +obj-y += clock.o +obj-y += lowlevel_init.o +obj-y += pinmux-common.o +obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra-common/ap.c b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/ap.c new file mode 100644 index 000000000..91d70da65 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/ap.c @@ -0,0 +1,166 @@ +/* +* (C) Copyright 2010-2014 +* NVIDIA Corporation <www.nvidia.com> +* + * SPDX-License-Identifier: GPL-2.0+ +*/ + +/* Tegra AP (Application Processor) code */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/gp_padctrl.h> +#include <asm/arch-tegra/ap.h> +#include <asm/arch-tegra/clock.h> +#include <asm/arch-tegra/fuse.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/scu.h> +#include <asm/arch-tegra/tegra.h> +#include <asm/arch-tegra/warmboot.h> + +int tegra_get_chip(void) +{ + int rev; + struct apb_misc_gp_ctlr *gp = + (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; + + /* + * This is undocumented, Chip ID is bits 15:8 of the register + * APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for + * Tegra30, 0x35 for T114, and 0x40 for Tegra124. + */ + rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT; + debug("%s: CHIPID is 0x%02X\n", __func__, rev); + + return rev; +} + +int tegra_get_sku_info(void) +{ + int sku_id; + struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; + + sku_id = readl(&fuse->sku_info) & 0xff; + debug("%s: SKU info byte is 0x%02X\n", __func__, sku_id); + + return sku_id; +} + +int tegra_get_chip_sku(void) +{ + uint sku_id, chip_id; + + chip_id = tegra_get_chip(); + sku_id = tegra_get_sku_info(); + + switch (chip_id) { + case CHIPID_TEGRA20: + switch (sku_id) { + case SKU_ID_T20_7: + case SKU_ID_T20: + return TEGRA_SOC_T20; + case SKU_ID_T25SE: + case SKU_ID_AP25: + case SKU_ID_T25: + case SKU_ID_AP25E: + case SKU_ID_T25E: + return TEGRA_SOC_T25; + } + break; + case CHIPID_TEGRA30: + switch (sku_id) { + case SKU_ID_T33: + case SKU_ID_T30: + case SKU_ID_TM30MQS_P_A3: + default: + return TEGRA_SOC_T30; + } + break; + case CHIPID_TEGRA114: + switch (sku_id) { + case SKU_ID_T114_ENG: + case SKU_ID_T114_1: + default: + return TEGRA_SOC_T114; + } + break; + case CHIPID_TEGRA124: + switch (sku_id) { + case SKU_ID_T124_ENG: + default: + return TEGRA_SOC_T124; + } + break; + } + + /* unknown chip/sku id */ + printf("%s: ERROR: UNKNOWN CHIP/SKU ID COMBO (0x%02X/0x%02X)\n", + __func__, chip_id, sku_id); + return TEGRA_SOC_UNKNOWN; +} + +static void enable_scu(void) +{ + struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE; + u32 reg; + + /* Only enable the SCU on T20/T25 */ + if (tegra_get_chip() != CHIPID_TEGRA20) + return; + + /* If SCU already setup/enabled, return */ + if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE) + return; + + /* Invalidate all ways for all processors */ + writel(0xFFFF, &scu->scu_inv_all); + + /* Enable SCU - bit 0 */ + reg = readl(&scu->scu_ctrl); + reg |= SCU_CTRL_ENABLE; + writel(reg, &scu->scu_ctrl); +} + +static u32 get_odmdata(void) +{ + /* + * ODMDATA is stored in the BCT in IRAM by the BootROM. + * The BCT start and size are stored in the BIT in IRAM. + * Read the data @ bct_start + (bct_size - 12). This works + * on BCTs for currently supported SoCs, which are locked down. + * If this changes in new chips, we can revisit this algorithm. + */ + + u32 bct_start, odmdata; + + bct_start = readl(NV_PA_BASE_SRAM + NVBOOTINFOTABLE_BCTPTR); + odmdata = readl(bct_start + BCT_ODMDATA_OFFSET); + + return odmdata; +} + +static void init_pmc_scratch(void) +{ + struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 odmdata; + int i; + + /* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */ + for (i = 0; i < 23; i++) + writel(0, &pmc->pmc_scratch1+i); + + /* ODMDATA is for kernel use to determine RAM size, LP config, etc. */ + odmdata = get_odmdata(); + writel(odmdata, &pmc->pmc_scratch20); +} + +void s_init(void) +{ + /* Init PMC scratch memory */ + init_pmc_scratch(); + + enable_scu(); + + /* init the cache */ + config_cache(); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra-common/board.c b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/board.c new file mode 100644 index 000000000..6a6faf4b2 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/board.c @@ -0,0 +1,181 @@ +/* + * (C) Copyright 2010-2014 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/board.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/sys_proto.h> +#include <asm/arch-tegra/warmboot.h> + +DECLARE_GLOBAL_DATA_PTR; + +enum { + /* UARTs which we can enable */ + UARTA = 1 << 0, + UARTB = 1 << 1, + UARTC = 1 << 2, + UARTD = 1 << 3, + UARTE = 1 << 4, + UART_COUNT = 5, +}; + +/* + * Boot ROM initializes the odmdata in APBDEV_PMC_SCRATCH20_0, + * so we are using this value to identify memory size. + */ + +unsigned int query_sdram_size(void) +{ + struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 reg; + + reg = readl(&pmc->pmc_scratch20); + debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg); + +#if defined(CONFIG_TEGRA20) + /* bits 30:28 in OdmData are used for RAM size on T20 */ + reg &= 0x70000000; + + switch ((reg) >> 28) { + case 1: + return 0x10000000; /* 256 MB */ + case 0: + case 2: + default: + return 0x20000000; /* 512 MB */ + case 3: + return 0x40000000; /* 1GB */ + } +#else /* Tegra30/Tegra114 */ + /* bits 31:28 in OdmData are used for RAM size on T30 */ + switch ((reg) >> 28) { + case 0: + case 1: + default: + return 0x10000000; /* 256 MB */ + case 2: + return 0x20000000; /* 512 MB */ + case 3: + return 0x30000000; /* 768 MB */ + case 4: + return 0x40000000; /* 1GB */ + case 8: + return 0x7ff00000; /* 2GB - 1MB */ + } +#endif +} + +int dram_init(void) +{ + /* We do not initialise DRAM here. We just query the size */ + gd->ram_size = query_sdram_size(); + return 0; +} + +#ifdef CONFIG_DISPLAY_BOARDINFO +int checkboard(void) +{ + printf("Board: %s\n", sysinfo.board_string); + return 0; +} +#endif /* CONFIG_DISPLAY_BOARDINFO */ + +static int uart_configs[] = { +#if defined(CONFIG_TEGRA20) + #if defined(CONFIG_TEGRA_UARTA_UAA_UAB) + FUNCMUX_UART1_UAA_UAB, + #elif defined(CONFIG_TEGRA_UARTA_GPU) + FUNCMUX_UART1_GPU, + #elif defined(CONFIG_TEGRA_UARTA_SDIO1) + FUNCMUX_UART1_SDIO1, + #else + FUNCMUX_UART1_IRRX_IRTX, +#endif + FUNCMUX_UART2_UAD, + -1, + FUNCMUX_UART4_GMC, + -1, +#elif defined(CONFIG_TEGRA30) + FUNCMUX_UART1_ULPI, /* UARTA */ + -1, + -1, + -1, + -1, +#elif defined(CONFIG_TEGRA114) + -1, + -1, + -1, + FUNCMUX_UART4_GMI, /* UARTD */ + -1, +#else /* Tegra124 */ + FUNCMUX_UART1_KBC, /* UARTA */ + -1, + -1, + FUNCMUX_UART4_GPIO, /* UARTD */ + -1, +#endif +}; + +/** + * Set up the specified uarts + * + * @param uarts_ids Mask containing UARTs to init (UARTx) + */ +static void setup_uarts(int uart_ids) +{ + static enum periph_id id_for_uart[] = { + PERIPH_ID_UART1, + PERIPH_ID_UART2, + PERIPH_ID_UART3, + PERIPH_ID_UART4, + PERIPH_ID_UART5, + }; + size_t i; + + for (i = 0; i < UART_COUNT; i++) { + if (uart_ids & (1 << i)) { + enum periph_id id = id_for_uart[i]; + + funcmux_select(id, uart_configs[i]); + clock_ll_start_uart(id); + } + } +} + +void board_init_uart_f(void) +{ + int uart_ids = 0; /* bit mask of which UART ids to enable */ + +#ifdef CONFIG_TEGRA_ENABLE_UARTA + uart_ids |= UARTA; +#endif +#ifdef CONFIG_TEGRA_ENABLE_UARTB + uart_ids |= UARTB; +#endif +#ifdef CONFIG_TEGRA_ENABLE_UARTC + uart_ids |= UARTC; +#endif +#ifdef CONFIG_TEGRA_ENABLE_UARTD + uart_ids |= UARTD; +#endif +#ifdef CONFIG_TEGRA_ENABLE_UARTE + uart_ids |= UARTE; +#endif + setup_uarts(uart_ids); +} + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra-common/cache.c b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/cache.c new file mode 100644 index 000000000..94f5bce90 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/cache.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Tegra cache routines */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch-tegra/ap.h> +#include <asm/arch/gp_padctrl.h> + +void config_cache(void) +{ + u32 reg = 0; + + /* enable SMP mode and FW for CPU0, by writing to Auxiliary Ctl reg */ + asm volatile( + "mrc p15, 0, r0, c1, c0, 1\n" + "orr r0, r0, #0x41\n" + "mcr p15, 0, r0, c1, c0, 1\n"); + + /* Currently, only Tegra114+ needs this L2 cache change to boot Linux */ + if (tegra_get_chip() < CHIPID_TEGRA114) + return; + + /* + * Systems with an architectural L2 cache must not use the PL310. + * Config L2CTLR here for a data RAM latency of 3 cycles. + */ + asm("mrc p15, 1, %0, c9, c0, 2" : : "r" (reg)); + reg &= ~7; + reg |= 2; + asm("mcr p15, 1, %0, c9, c0, 2" : : "r" (reg)); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra-common/clock.c b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/clock.c new file mode 100644 index 000000000..11c743550 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/clock.c @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Tegra SoC common clock control functions */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/timer.h> +#include <div64.h> +#include <fdtdec.h> + +/* + * This is our record of the current clock rate of each clock. We don't + * fill all of these in since we are only really interested in clocks which + * we use as parents. + */ +static unsigned pll_rate[CLOCK_ID_COUNT]; + +/* + * The oscillator frequency is fixed to one of four set values. Based on this + * the other clocks are set up appropriately. + */ +static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = { + 13000000, + 19200000, + 12000000, + 26000000, +}; + +/* return 1 if a peripheral ID is in range */ +#define clock_type_id_isvalid(id) ((id) >= 0 && \ + (id) < CLOCK_TYPE_COUNT) + +char pllp_valid = 1; /* PLLP is set up correctly */ + +/* return 1 if a periphc_internal_id is in range */ +#define periphc_internal_id_isvalid(id) ((id) >= 0 && \ + (id) < PERIPHC_COUNT) + +/* number of clock outputs of a PLL */ +static const u8 pll_num_clkouts[] = { + 1, /* PLLC */ + 1, /* PLLM */ + 4, /* PLLP */ + 1, /* PLLA */ + 0, /* PLLU */ + 0, /* PLLD */ +}; + +int clock_get_osc_bypass(void) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + reg = readl(&clkrst->crc_osc_ctrl); + return (reg & OSC_XOBP_MASK) >> OSC_XOBP_SHIFT; +} + +/* Returns a pointer to the registers of the given pll */ +static struct clk_pll *get_pll(enum clock_id clkid) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + + assert(clock_id_is_pll(clkid)); + return &clkrst->crc_pll[clkid]; +} + +int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn, + u32 *divp, u32 *cpcon, u32 *lfcon) +{ + struct clk_pll *pll = get_pll(clkid); + u32 data; + + assert(clkid != CLOCK_ID_USB); + + /* Safety check, adds to code size but is small */ + if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB) + return -1; + data = readl(&pll->pll_base); + *divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT; + *divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT; + *divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT; + data = readl(&pll->pll_misc); + *cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT; + *lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT; + + return 0; +} + +unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn, + u32 divp, u32 cpcon, u32 lfcon) +{ + struct clk_pll *pll = get_pll(clkid); + u32 data; + + /* + * We cheat by treating all PLL (except PLLU) in the same fashion. + * This works only because: + * - same fields are always mapped at same offsets, except DCCON + * - DCCON is always 0, doesn't conflict + * - M,N, P of PLLP values are ignored for PLLP + */ + data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT); + writel(data, &pll->pll_misc); + + data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) | + (0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT); + + if (clkid == CLOCK_ID_USB) + data |= divp << PLLU_VCO_FREQ_SHIFT; + else + data |= divp << PLL_DIVP_SHIFT; + writel(data, &pll->pll_base); + + /* calculate the stable time */ + return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US; +} + +void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source, + unsigned divisor) +{ + u32 *reg = get_periph_source_reg(periph_id); + u32 value; + + value = readl(reg); + + value &= ~OUT_CLK_SOURCE_31_30_MASK; + value |= source << OUT_CLK_SOURCE_31_30_SHIFT; + + value &= ~OUT_CLK_DIVISOR_MASK; + value |= divisor << OUT_CLK_DIVISOR_SHIFT; + + writel(value, reg); +} + +void clock_ll_set_source(enum periph_id periph_id, unsigned source) +{ + u32 *reg = get_periph_source_reg(periph_id); + + clrsetbits_le32(reg, OUT_CLK_SOURCE_31_30_MASK, + source << OUT_CLK_SOURCE_31_30_SHIFT); +} + +/** + * Given the parent's rate and the required rate for the children, this works + * out the peripheral clock divider to use, in 7.1 binary format. + * + * @param divider_bits number of divider bits (8 or 16) + * @param parent_rate clock rate of parent clock in Hz + * @param rate required clock rate for this clock + * @return divider which should be used + */ +static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate, + unsigned long rate) +{ + u64 divider = parent_rate * 2; + unsigned max_divider = 1 << divider_bits; + + divider += rate - 1; + do_div(divider, rate); + + if ((s64)divider - 2 < 0) + return 0; + + if ((s64)divider - 2 >= max_divider) + return -1; + + return divider - 2; +} + +int clock_set_pllout(enum clock_id clkid, enum pll_out_id pllout, unsigned rate) +{ + struct clk_pll *pll = get_pll(clkid); + int data = 0, div = 0, offset = 0; + + if (!clock_id_is_pll(clkid)) + return -1; + + if (pllout + 1 > pll_num_clkouts[clkid]) + return -1; + + div = clk_get_divider(8, pll_rate[clkid], rate); + + if (div < 0) + return -1; + + /* out2 and out4 are in the high part of the register */ + if (pllout == PLL_OUT2 || pllout == PLL_OUT4) + offset = 16; + + data = (div << PLL_OUT_RATIO_SHIFT) | + PLL_OUT_OVRRIDE | PLL_OUT_CLKEN | PLL_OUT_RSTN; + clrsetbits_le32(&pll->pll_out[pllout >> 1], + PLL_OUT_RATIO_MASK << offset, data << offset); + + return 0; +} + +/** + * Given the parent's rate and the divider in 7.1 format, this works out the + * resulting peripheral clock rate. + * + * @param parent_rate clock rate of parent clock in Hz + * @param divider which should be used in 7.1 format + * @return effective clock rate of peripheral + */ +static unsigned long get_rate_from_divider(unsigned long parent_rate, + int divider) +{ + u64 rate; + + rate = (u64)parent_rate * 2; + do_div(rate, divider + 2); + return rate; +} + +unsigned long clock_get_periph_rate(enum periph_id periph_id, + enum clock_id parent) +{ + u32 *reg = get_periph_source_reg(periph_id); + + return get_rate_from_divider(pll_rate[parent], + (readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT); +} + +/** + * Find the best available 7.1 format divisor given a parent clock rate and + * required child clock rate. This function assumes that a second-stage + * divisor is available which can divide by powers of 2 from 1 to 256. + * + * @param divider_bits number of divider bits (8 or 16) + * @param parent_rate clock rate of parent clock in Hz + * @param rate required clock rate for this clock + * @param extra_div value for the second-stage divisor (not set if this + * function returns -1. + * @return divider which should be used, or -1 if nothing is valid + * + */ +static int find_best_divider(unsigned divider_bits, unsigned long parent_rate, + unsigned long rate, int *extra_div) +{ + int shift; + int best_divider = -1; + int best_error = rate; + + /* try dividers from 1 to 256 and find closest match */ + for (shift = 0; shift <= 8 && best_error > 0; shift++) { + unsigned divided_parent = parent_rate >> shift; + int divider = clk_get_divider(divider_bits, divided_parent, + rate); + unsigned effective_rate = get_rate_from_divider(divided_parent, + divider); + int error = rate - effective_rate; + + /* Given a valid divider, look for the lowest error */ + if (divider != -1 && error < best_error) { + best_error = error; + *extra_div = 1 << shift; + best_divider = divider; + } + } + + /* return what we found - *extra_div will already be set */ + return best_divider; +} + +/** + * Adjust peripheral PLL to use the given divider and source. + * + * @param periph_id peripheral to adjust + * @param source Source number (0-3 or 0-7) + * @param mux_bits Number of mux bits (2 or 4) + * @param divider Required divider in 7.1 or 15.1 format + * @return 0 if ok, -1 on error (requesting a parent clock which is not valid + * for this peripheral) + */ +static int adjust_periph_pll(enum periph_id periph_id, int source, + int mux_bits, unsigned divider) +{ + u32 *reg = get_periph_source_reg(periph_id); + + clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK, + divider << OUT_CLK_DIVISOR_SHIFT); + udelay(1); + + /* work out the source clock and set it */ + if (source < 0) + return -1; + + switch (mux_bits) { + case MASK_BITS_31_30: + clrsetbits_le32(reg, OUT_CLK_SOURCE_31_30_MASK, + source << OUT_CLK_SOURCE_31_30_SHIFT); + break; + + case MASK_BITS_31_29: + clrsetbits_le32(reg, OUT_CLK_SOURCE_31_29_MASK, + source << OUT_CLK_SOURCE_31_29_SHIFT); + break; + + case MASK_BITS_31_28: + clrsetbits_le32(reg, OUT_CLK_SOURCE_31_28_MASK, + source << OUT_CLK_SOURCE_31_28_SHIFT); + break; + + default: + return -1; + } + + udelay(2); + return 0; +} + +unsigned clock_adjust_periph_pll_div(enum periph_id periph_id, + enum clock_id parent, unsigned rate, int *extra_div) +{ + unsigned effective_rate; + int mux_bits, divider_bits, source; + int divider; + int xdiv = 0; + + /* work out the source clock and set it */ + source = get_periph_clock_source(periph_id, parent, &mux_bits, + ÷r_bits); + + divider = find_best_divider(divider_bits, pll_rate[parent], + rate, &xdiv); + if (extra_div) + *extra_div = xdiv; + + assert(divider >= 0); + if (adjust_periph_pll(periph_id, source, mux_bits, divider)) + return -1U; + debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate, + get_periph_source_reg(periph_id), + readl(get_periph_source_reg(periph_id))); + + /* Check what we ended up with. This shouldn't matter though */ + effective_rate = clock_get_periph_rate(periph_id, parent); + if (extra_div) + effective_rate /= *extra_div; + if (rate != effective_rate) + debug("Requested clock rate %u not honored (got %u)\n", + rate, effective_rate); + return effective_rate; +} + +unsigned clock_start_periph_pll(enum periph_id periph_id, + enum clock_id parent, unsigned rate) +{ + unsigned effective_rate; + + reset_set_enable(periph_id, 1); + clock_enable(periph_id); + + effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate, + NULL); + + reset_set_enable(periph_id, 0); + return effective_rate; +} + +void clock_enable(enum periph_id clkid) +{ + clock_set_enable(clkid, 1); +} + +void clock_disable(enum periph_id clkid) +{ + clock_set_enable(clkid, 0); +} + +void reset_periph(enum periph_id periph_id, int us_delay) +{ + /* Put peripheral into reset */ + reset_set_enable(periph_id, 1); + udelay(us_delay); + + /* Remove reset */ + reset_set_enable(periph_id, 0); + + udelay(us_delay); +} + +void reset_cmplx_set_enable(int cpu, int which, int reset) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 mask; + + /* Form the mask, which depends on the cpu chosen (2 or 4) */ + assert(cpu >= 0 && cpu < MAX_NUM_CPU); + mask = which << cpu; + + /* either enable or disable those reset for that CPU */ + if (reset) + writel(mask, &clkrst->crc_cpu_cmplx_set); + else + writel(mask, &clkrst->crc_cpu_cmplx_clr); +} + +unsigned clock_get_rate(enum clock_id clkid) +{ + struct clk_pll *pll; + u32 base; + u32 divm; + u64 parent_rate; + u64 rate; + + parent_rate = osc_freq[clock_get_osc_freq()]; + if (clkid == CLOCK_ID_OSC) + return parent_rate; + + pll = get_pll(clkid); + base = readl(&pll->pll_base); + + /* Oh for bf_unpack()... */ + rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT); + divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT; + if (clkid == CLOCK_ID_USB) + divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT; + else + divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT; + do_div(rate, divm); + return rate; +} + +/** + * Set the output frequency you want for each PLL clock. + * PLL output frequencies are programmed by setting their N, M and P values. + * The governing equations are: + * VCO = (Fi / m) * n, Fo = VCO / (2^p) + * where Fo is the output frequency from the PLL. + * Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi) + * 216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1 + * Please see Tegra TRM section 5.3 to get the detail for PLL Programming + * + * @param n PLL feedback divider(DIVN) + * @param m PLL input divider(DIVN) + * @param p post divider(DIVP) + * @param cpcon base PLL charge pump(CPCON) + * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot + * be overriden), 1 if PLL is already correct + */ +int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon) +{ + u32 base_reg; + u32 misc_reg; + struct clk_pll *pll; + + pll = get_pll(clkid); + + base_reg = readl(&pll->pll_base); + + /* Set BYPASS, m, n and p to PLL_BASE */ + base_reg &= ~PLL_DIVM_MASK; + base_reg |= m << PLL_DIVM_SHIFT; + + base_reg &= ~PLL_DIVN_MASK; + base_reg |= n << PLL_DIVN_SHIFT; + + base_reg &= ~PLL_DIVP_MASK; + base_reg |= p << PLL_DIVP_SHIFT; + + if (clkid == CLOCK_ID_PERIPH) { + /* + * If the PLL is already set up, check that it is correct + * and record this info for clock_verify() to check. + */ + if (base_reg & PLL_BASE_OVRRIDE_MASK) { + base_reg |= PLL_ENABLE_MASK; + if (base_reg != readl(&pll->pll_base)) + pllp_valid = 0; + return pllp_valid ? 1 : -1; + } + base_reg |= PLL_BASE_OVRRIDE_MASK; + } + + base_reg |= PLL_BYPASS_MASK; + writel(base_reg, &pll->pll_base); + + /* Set cpcon to PLL_MISC */ + misc_reg = readl(&pll->pll_misc); + misc_reg &= ~PLL_CPCON_MASK; + misc_reg |= cpcon << PLL_CPCON_SHIFT; + writel(misc_reg, &pll->pll_misc); + + /* Enable PLL */ + base_reg |= PLL_ENABLE_MASK; + writel(base_reg, &pll->pll_base); + + /* Disable BYPASS */ + base_reg &= ~PLL_BYPASS_MASK; + writel(base_reg, &pll->pll_base); + + return 0; +} + +void clock_ll_start_uart(enum periph_id periph_id) +{ + /* Assert UART reset and enable clock */ + reset_set_enable(periph_id, 1); + clock_enable(periph_id); + clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */ + + /* wait for 2us */ + udelay(2); + + /* De-assert reset to UART */ + reset_set_enable(periph_id, 0); +} + +#ifdef CONFIG_OF_CONTROL +int clock_decode_periph_id(const void *blob, int node) +{ + enum periph_id id; + u32 cell[2]; + int err; + + err = fdtdec_get_int_array(blob, node, "clocks", cell, + ARRAY_SIZE(cell)); + if (err) + return -1; + id = clk_id_to_periph_id(cell[1]); + assert(clock_periph_id_isvalid(id)); + return id; +} +#endif /* CONFIG_OF_CONTROL */ + +int clock_verify(void) +{ + struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH); + u32 reg = readl(&pll->pll_base); + + if (!pllp_valid) { + printf("Warning: PLLP %x is not correct\n", reg); + return -1; + } + debug("PLLP %x is correct\n", reg); + return 0; +} + +void clock_init(void) +{ + pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY); + pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH); + pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL); + pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC); + pll_rate[CLOCK_ID_SFROM32KHZ] = 32768; + pll_rate[CLOCK_ID_XCPU] = clock_get_rate(CLOCK_ID_XCPU); + debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]); + debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]); + debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]); + debug("PLLC = %d\n", pll_rate[CLOCK_ID_CGENERAL]); + debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]); + + /* Do any special system timer/TSC setup */ + arch_timer_init(); +} + +static void set_avp_clock_source(u32 src) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 val; + + val = (src << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT) | + (src << SCLK_SWAKEUP_IRQ_SOURCE_SHIFT) | + (src << SCLK_SWAKEUP_RUN_SOURCE_SHIFT) | + (src << SCLK_SWAKEUP_IDLE_SOURCE_SHIFT) | + (SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT); + writel(val, &clkrst->crc_sclk_brst_pol); + udelay(3); +} + +/* + * This function is useful on Tegra30, and any later SoCs that have compatible + * PLLP configuration registers. + */ +void tegra30_set_up_pllp(void) +{ + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + /* + * Based on the Tegra TRM, the system clock (which is the AVP clock) can + * run up to 275MHz. On power on, the default sytem clock source is set + * to PLLP_OUT0. This function sets PLLP's (hence PLLP_OUT0's) rate to + * 408MHz which is beyond system clock's upper limit. + * + * The fix is to set the system clock to CLK_M before initializing PLLP, + * and then switch back to PLLP_OUT4, which has an appropriate divider + * configured, after PLLP has been configured + */ + set_avp_clock_source(SCLK_SOURCE_CLKM); + + /* + * PLLP output frequency set to 408Mhz + * PLLC output frequency set to 228Mhz + */ + switch (clock_get_osc_freq()) { + case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */ + clock_set_rate(CLOCK_ID_PERIPH, 408, 12, 0, 8); + clock_set_rate(CLOCK_ID_CGENERAL, 456, 12, 1, 8); + break; + + case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */ + clock_set_rate(CLOCK_ID_PERIPH, 408, 26, 0, 8); + clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8); + break; + + case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */ + clock_set_rate(CLOCK_ID_PERIPH, 408, 13, 0, 8); + clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8); + break; + case CLOCK_OSC_FREQ_19_2: + default: + /* + * These are not supported. It is too early to print a + * message and the UART likely won't work anyway due to the + * oscillator being wrong. + */ + break; + } + + /* Set PLLP_OUT1, 2, 3 & 4 freqs to 9.6, 48, 102 & 204MHz */ + + /* OUT1, 2 */ + /* Assert RSTN before enable */ + reg = PLLP_OUT2_RSTN_EN | PLLP_OUT1_RSTN_EN; + writel(reg, &clkrst->crc_pll[CLOCK_ID_PERIPH].pll_out[0]); + /* Set divisor and reenable */ + reg = (IN_408_OUT_48_DIVISOR << PLLP_OUT2_RATIO) + | PLLP_OUT2_OVR | PLLP_OUT2_CLKEN | PLLP_OUT2_RSTN_DIS + | (IN_408_OUT_9_6_DIVISOR << PLLP_OUT1_RATIO) + | PLLP_OUT1_OVR | PLLP_OUT1_CLKEN | PLLP_OUT1_RSTN_DIS; + writel(reg, &clkrst->crc_pll[CLOCK_ID_PERIPH].pll_out[0]); + + /* OUT3, 4 */ + /* Assert RSTN before enable */ + reg = PLLP_OUT4_RSTN_EN | PLLP_OUT3_RSTN_EN; + writel(reg, &clkrst->crc_pll[CLOCK_ID_PERIPH].pll_out[1]); + /* Set divisor and reenable */ + reg = (IN_408_OUT_204_DIVISOR << PLLP_OUT4_RATIO) + | PLLP_OUT4_OVR | PLLP_OUT4_CLKEN | PLLP_OUT4_RSTN_DIS + | (IN_408_OUT_102_DIVISOR << PLLP_OUT3_RATIO) + | PLLP_OUT3_OVR | PLLP_OUT3_CLKEN | PLLP_OUT3_RSTN_DIS; + writel(reg, &clkrst->crc_pll[CLOCK_ID_PERIPH].pll_out[1]); + + set_avp_clock_source(SCLK_SOURCE_PLLP_OUT4); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra-common/lowlevel_init.S b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/lowlevel_init.S new file mode 100644 index 000000000..a211bb3b1 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/lowlevel_init.S @@ -0,0 +1,26 @@ +/* + * SoC-specific setup info + * + * (C) Copyright 2010,2011 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <version.h> +#include <linux/linkage.h> + + .align 5 +ENTRY(reset_cpu) + ldr r1, rstctl @ get addr for global reset + @ reg + ldr r3, [r1] + orr r3, r3, #0x10 + str r3, [r1] @ force reset + mov r0, r0 +_loop_forever: + b _loop_forever +rstctl: + .word PRM_RSTCTRL +ENDPROC(reset_cpu) diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra-common/pinmux-common.c b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/pinmux-common.c new file mode 100644 index 000000000..d62618cd0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/pinmux-common.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +/* return 1 if a pingrp is in range */ +#define pmux_pingrp_isvalid(pin) (((pin) >= 0) && ((pin) < PMUX_PINGRP_COUNT)) + +/* return 1 if a pmux_func is in range */ +#define pmux_func_isvalid(func) \ + (((func) >= 0) && ((func) < PMUX_FUNC_COUNT)) + +/* return 1 if a pin_pupd_is in range */ +#define pmux_pin_pupd_isvalid(pupd) \ + (((pupd) >= PMUX_PULL_NORMAL) && ((pupd) <= PMUX_PULL_UP)) + +/* return 1 if a pin_tristate_is in range */ +#define pmux_pin_tristate_isvalid(tristate) \ + (((tristate) >= PMUX_TRI_NORMAL) && ((tristate) <= PMUX_TRI_TRISTATE)) + +#ifdef TEGRA_PMX_HAS_PIN_IO_BIT_ETC +/* return 1 if a pin_io_is in range */ +#define pmux_pin_io_isvalid(io) \ + (((io) >= PMUX_PIN_OUTPUT) && ((io) <= PMUX_PIN_INPUT)) + +/* return 1 if a pin_lock is in range */ +#define pmux_pin_lock_isvalid(lock) \ + (((lock) >= PMUX_PIN_LOCK_DISABLE) && ((lock) <= PMUX_PIN_LOCK_ENABLE)) + +/* return 1 if a pin_od is in range */ +#define pmux_pin_od_isvalid(od) \ + (((od) >= PMUX_PIN_OD_DISABLE) && ((od) <= PMUX_PIN_OD_ENABLE)) + +/* return 1 if a pin_ioreset_is in range */ +#define pmux_pin_ioreset_isvalid(ioreset) \ + (((ioreset) >= PMUX_PIN_IO_RESET_DISABLE) && \ + ((ioreset) <= PMUX_PIN_IO_RESET_ENABLE)) + +#ifdef TEGRA_PMX_HAS_RCV_SEL +/* return 1 if a pin_rcv_sel_is in range */ +#define pmux_pin_rcv_sel_isvalid(rcv_sel) \ + (((rcv_sel) >= PMUX_PIN_RCV_SEL_NORMAL) && \ + ((rcv_sel) <= PMUX_PIN_RCV_SEL_HIGH)) +#endif /* TEGRA_PMX_HAS_RCV_SEL */ +#endif /* TEGRA_PMX_HAS_PIN_IO_BIT_ETC */ + +#define _R(offset) (u32 *)(NV_PA_APB_MISC_BASE + (offset)) + +#if defined(CONFIG_TEGRA20) + +#define MUX_REG(grp) _R(0x80 + ((tegra_soc_pingroups[grp].ctl_id / 16) * 4)) +#define MUX_SHIFT(grp) ((tegra_soc_pingroups[grp].ctl_id % 16) * 2) + +#define PULL_REG(grp) _R(0xa0 + ((tegra_soc_pingroups[grp].pull_id / 16) * 4)) +#define PULL_SHIFT(grp) ((tegra_soc_pingroups[grp].pull_id % 16) * 2) + +#define TRI_REG(grp) _R(0x14 + (((grp) / 32) * 4)) +#define TRI_SHIFT(grp) ((grp) % 32) + +#else + +#define REG(pin) _R(0x3000 + ((pin) * 4)) + +#define MUX_REG(pin) REG(pin) +#define MUX_SHIFT(pin) 0 + +#define PULL_REG(pin) REG(pin) +#define PULL_SHIFT(pin) 2 + +#define TRI_REG(pin) REG(pin) +#define TRI_SHIFT(pin) 4 + +#endif /* CONFIG_TEGRA20 */ + +#define DRV_REG(group) _R(0x868 + ((group) * 4)) + +#define IO_SHIFT 5 +#define OD_SHIFT 6 +#define LOCK_SHIFT 7 +#define IO_RESET_SHIFT 8 +#define RCV_SEL_SHIFT 9 + +void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func) +{ + u32 *reg = MUX_REG(pin); + int i, mux = -1; + u32 val; + + /* Error check on pin and func */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_func_isvalid(func)); + + if (func >= PMUX_FUNC_RSVD1) { + mux = (func - PMUX_FUNC_RSVD1) & 3; + } else { + /* Search for the appropriate function */ + for (i = 0; i < 4; i++) { + if (tegra_soc_pingroups[pin].funcs[i] == func) { + mux = i; + break; + } + } + } + assert(mux != -1); + + val = readl(reg); + val &= ~(3 << MUX_SHIFT(pin)); + val |= (mux << MUX_SHIFT(pin)); + writel(val, reg); +} + +void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd) +{ + u32 *reg = PULL_REG(pin); + u32 val; + + /* Error check on pin and pupd */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_pupd_isvalid(pupd)); + + val = readl(reg); + val &= ~(3 << PULL_SHIFT(pin)); + val |= (pupd << PULL_SHIFT(pin)); + writel(val, reg); +} + +static void pinmux_set_tristate(enum pmux_pingrp pin, int tri) +{ + u32 *reg = TRI_REG(pin); + u32 val; + + /* Error check on pin */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_tristate_isvalid(tri)); + + val = readl(reg); + if (tri == PMUX_TRI_TRISTATE) + val |= (1 << TRI_SHIFT(pin)); + else + val &= ~(1 << TRI_SHIFT(pin)); + writel(val, reg); +} + +void pinmux_tristate_enable(enum pmux_pingrp pin) +{ + pinmux_set_tristate(pin, PMUX_TRI_TRISTATE); +} + +void pinmux_tristate_disable(enum pmux_pingrp pin) +{ + pinmux_set_tristate(pin, PMUX_TRI_NORMAL); +} + +#ifdef TEGRA_PMX_HAS_PIN_IO_BIT_ETC +void pinmux_set_io(enum pmux_pingrp pin, enum pmux_pin_io io) +{ + u32 *reg = REG(pin); + u32 val; + + if (io == PMUX_PIN_NONE) + return; + + /* Error check on pin and io */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_io_isvalid(io)); + + val = readl(reg); + if (io == PMUX_PIN_INPUT) + val |= (io & 1) << IO_SHIFT; + else + val &= ~(1 << IO_SHIFT); + writel(val, reg); +} + +static void pinmux_set_lock(enum pmux_pingrp pin, enum pmux_pin_lock lock) +{ + u32 *reg = REG(pin); + u32 val; + + if (lock == PMUX_PIN_LOCK_DEFAULT) + return; + + /* Error check on pin and lock */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_lock_isvalid(lock)); + + val = readl(reg); + if (lock == PMUX_PIN_LOCK_ENABLE) { + val |= (1 << LOCK_SHIFT); + } else { + if (val & (1 << LOCK_SHIFT)) + printf("%s: Cannot clear LOCK bit!\n", __func__); + val &= ~(1 << LOCK_SHIFT); + } + writel(val, reg); + + return; +} + +static void pinmux_set_od(enum pmux_pingrp pin, enum pmux_pin_od od) +{ + u32 *reg = REG(pin); + u32 val; + + if (od == PMUX_PIN_OD_DEFAULT) + return; + + /* Error check on pin and od */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_od_isvalid(od)); + + val = readl(reg); + if (od == PMUX_PIN_OD_ENABLE) + val |= (1 << OD_SHIFT); + else + val &= ~(1 << OD_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_set_ioreset(enum pmux_pingrp pin, + enum pmux_pin_ioreset ioreset) +{ + u32 *reg = REG(pin); + u32 val; + + if (ioreset == PMUX_PIN_IO_RESET_DEFAULT) + return; + + /* Error check on pin and ioreset */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_ioreset_isvalid(ioreset)); + + val = readl(reg); + if (ioreset == PMUX_PIN_IO_RESET_ENABLE) + val |= (1 << IO_RESET_SHIFT); + else + val &= ~(1 << IO_RESET_SHIFT); + writel(val, reg); + + return; +} + +#ifdef TEGRA_PMX_HAS_RCV_SEL +static void pinmux_set_rcv_sel(enum pmux_pingrp pin, + enum pmux_pin_rcv_sel rcv_sel) +{ + u32 *reg = REG(pin); + u32 val; + + if (rcv_sel == PMUX_PIN_RCV_SEL_DEFAULT) + return; + + /* Error check on pin and rcv_sel */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_rcv_sel_isvalid(rcv_sel)); + + val = readl(reg); + if (rcv_sel == PMUX_PIN_RCV_SEL_HIGH) + val |= (1 << RCV_SEL_SHIFT); + else + val &= ~(1 << RCV_SEL_SHIFT); + writel(val, reg); + + return; +} +#endif /* TEGRA_PMX_HAS_RCV_SEL */ +#endif /* TEGRA_PMX_HAS_PIN_IO_BIT_ETC */ + +static void pinmux_config_pingrp(const struct pmux_pingrp_config *config) +{ + enum pmux_pingrp pin = config->pingrp; + + pinmux_set_func(pin, config->func); + pinmux_set_pullupdown(pin, config->pull); + pinmux_set_tristate(pin, config->tristate); +#ifdef TEGRA_PMX_HAS_PIN_IO_BIT_ETC + pinmux_set_io(pin, config->io); + pinmux_set_lock(pin, config->lock); + pinmux_set_od(pin, config->od); + pinmux_set_ioreset(pin, config->ioreset); +#ifdef TEGRA_PMX_HAS_RCV_SEL + pinmux_set_rcv_sel(pin, config->rcv_sel); +#endif +#endif +} + +void pinmux_config_pingrp_table(const struct pmux_pingrp_config *config, + int len) +{ + int i; + + for (i = 0; i < len; i++) + pinmux_config_pingrp(&config[i]); +} + +#ifdef TEGRA_PMX_HAS_DRVGRPS + +#define pmux_drvgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PMUX_DRVGRP_COUNT)) + +#define pmux_slw_isvalid(slw) \ + (((slw) >= PMUX_SLWF_MIN) && ((slw) <= PMUX_SLWF_MAX)) + +#define pmux_drv_isvalid(drv) \ + (((drv) >= PMUX_DRVUP_MIN) && ((drv) <= PMUX_DRVUP_MAX)) + +#define pmux_lpmd_isvalid(lpm) \ + (((lpm) >= PMUX_LPMD_X8) && ((lpm) <= PMUX_LPMD_X)) + +#define pmux_schmt_isvalid(schmt) \ + (((schmt) >= PMUX_SCHMT_DISABLE) && ((schmt) <= PMUX_SCHMT_ENABLE)) + +#define pmux_hsm_isvalid(hsm) \ + (((hsm) >= PMUX_HSM_DISABLE) && ((hsm) <= PMUX_HSM_ENABLE)) + +#define HSM_SHIFT 2 +#define SCHMT_SHIFT 3 +#define LPMD_SHIFT 4 +#define LPMD_MASK (3 << LPMD_SHIFT) +#define DRVDN_SHIFT 12 +#define DRVDN_MASK (0x7F << DRVDN_SHIFT) +#define DRVUP_SHIFT 20 +#define DRVUP_MASK (0x7F << DRVUP_SHIFT) +#define SLWR_SHIFT 28 +#define SLWR_MASK (3 << SLWR_SHIFT) +#define SLWF_SHIFT 30 +#define SLWF_MASK (3 << SLWF_SHIFT) + +static void pinmux_set_drvup_slwf(enum pmux_drvgrp grp, int slwf) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (slwf == PMUX_SLWF_NONE) + return; + + /* Error check on pad and slwf */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_slw_isvalid(slwf)); + + val = readl(reg); + val &= ~SLWF_MASK; + val |= (slwf << SLWF_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_set_drvdn_slwr(enum pmux_drvgrp grp, int slwr) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (slwr == PMUX_SLWR_NONE) + return; + + /* Error check on pad and slwr */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_slw_isvalid(slwr)); + + val = readl(reg); + val &= ~SLWR_MASK; + val |= (slwr << SLWR_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_set_drvup(enum pmux_drvgrp grp, int drvup) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (drvup == PMUX_DRVUP_NONE) + return; + + /* Error check on pad and drvup */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_drv_isvalid(drvup)); + + val = readl(reg); + val &= ~DRVUP_MASK; + val |= (drvup << DRVUP_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_set_drvdn(enum pmux_drvgrp grp, int drvdn) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (drvdn == PMUX_DRVDN_NONE) + return; + + /* Error check on pad and drvdn */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_drv_isvalid(drvdn)); + + val = readl(reg); + val &= ~DRVDN_MASK; + val |= (drvdn << DRVDN_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_set_lpmd(enum pmux_drvgrp grp, enum pmux_lpmd lpmd) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (lpmd == PMUX_LPMD_NONE) + return; + + /* Error check pad and lpmd value */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_lpmd_isvalid(lpmd)); + + val = readl(reg); + val &= ~LPMD_MASK; + val |= (lpmd << LPMD_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_set_schmt(enum pmux_drvgrp grp, enum pmux_schmt schmt) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (schmt == PMUX_SCHMT_NONE) + return; + + /* Error check pad */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_schmt_isvalid(schmt)); + + val = readl(reg); + if (schmt == PMUX_SCHMT_ENABLE) + val |= (1 << SCHMT_SHIFT); + else + val &= ~(1 << SCHMT_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_set_hsm(enum pmux_drvgrp grp, enum pmux_hsm hsm) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (hsm == PMUX_HSM_NONE) + return; + + /* Error check pad */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_hsm_isvalid(hsm)); + + val = readl(reg); + if (hsm == PMUX_HSM_ENABLE) + val |= (1 << HSM_SHIFT); + else + val &= ~(1 << HSM_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_config_drvgrp(const struct pmux_drvgrp_config *config) +{ + enum pmux_drvgrp grp = config->drvgrp; + + pinmux_set_drvup_slwf(grp, config->slwf); + pinmux_set_drvdn_slwr(grp, config->slwr); + pinmux_set_drvup(grp, config->drvup); + pinmux_set_drvdn(grp, config->drvdn); + pinmux_set_lpmd(grp, config->lpmd); + pinmux_set_schmt(grp, config->schmt); + pinmux_set_hsm(grp, config->hsm); +} + +void pinmux_config_drvgrp_table(const struct pmux_drvgrp_config *config, + int len) +{ + int i; + + for (i = 0; i < len; i++) + pinmux_config_drvgrp(&config[i]); +} +#endif /* TEGRA_PMX_HAS_DRVGRPS */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra-common/sys_info.c b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/sys_info.c new file mode 100644 index 000000000..de20325ec --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra-common/sys_info.c @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2010,2011 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <linux/ctype.h> + +void upstring(char *s) +{ + while (*s) { + *s = toupper(*s); + s++; + } +} + +/* Print CPU information */ +int print_cpuinfo(void) +{ + char soc_name[10]; + + strncpy(soc_name, CONFIG_SYS_SOC, 10); + upstring(soc_name); + puts(soc_name); + puts("\n"); + + /* TBD: Add printf of major/minor rev info, stepping, etc. */ + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/Makefile new file mode 100644 index 000000000..d959b575c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +obj-y += clock.o funcmux.o pinmux.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/clock.c b/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/clock.c new file mode 100644 index 000000000..d5194e11b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/clock.c @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Tegra114 Clock control functions */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/sysctr.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/timer.h> +#include <div64.h> +#include <fdtdec.h> + +/* + * Clock types that we can use as a source. The Tegra114 has muxes for the + * peripheral clocks, and in most cases there are four options for the clock + * source. This gives us a clock 'type' and exploits what commonality exists + * in the device. + * + * Letters are obvious, except for T which means CLK_M, and S which means the + * clock derived from 32KHz. Beware that CLK_M (also called OSC in the + * datasheet) and PLL_M are different things. The former is the basic + * clock supplied to the SOC from an external oscillator. The latter is the + * memory clock PLL. + * + * See definitions in clock_id in the header file. + */ +enum clock_type_id { + CLOCK_TYPE_AXPT, /* PLL_A, PLL_X, PLL_P, CLK_M */ + CLOCK_TYPE_MCPA, /* and so on */ + CLOCK_TYPE_MCPT, + CLOCK_TYPE_PCM, + CLOCK_TYPE_PCMT, + CLOCK_TYPE_PCMT16, + CLOCK_TYPE_PDCT, + CLOCK_TYPE_ACPT, + CLOCK_TYPE_ASPTE, + CLOCK_TYPE_PMDACD2T, + CLOCK_TYPE_PCST, + + CLOCK_TYPE_COUNT, + CLOCK_TYPE_NONE = -1, /* invalid clock type */ +}; + +enum { + CLOCK_MAX_MUX = 8 /* number of source options for each clock */ +}; + +/* + * Clock source mux for each clock type. This just converts our enum into + * a list of mux sources for use by the code. + * + * Note: + * The extra column in each clock source array is used to store the mask + * bits in its register for the source. + */ +#define CLK(x) CLOCK_ID_ ## x +static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX+1] = { + { CLK(AUDIO), CLK(XCPU), CLK(PERIPH), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(AUDIO), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(NONE), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(AUDIO), CLK(CGENERAL), CLK(PERIPH), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(AUDIO), CLK(SFROM32KHZ), CLK(PERIPH), CLK(OSC), + CLK(EPCI), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_29}, + { CLK(PERIPH), CLK(MEMORY), CLK(DISPLAY), CLK(AUDIO), + CLK(CGENERAL), CLK(DISPLAY2), CLK(OSC), CLK(NONE), + MASK_BITS_31_29}, + { CLK(PERIPH), CLK(CGENERAL), CLK(SFROM32KHZ), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_28} +}; + +/* + * Clock type for each peripheral clock source. We put the name in each + * record just so it is easy to match things up + */ +#define TYPE(name, type) type +static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = { + /* 0x00 */ + TYPE(PERIPHC_I2S1, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_I2S2, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_SPDIF_IN, CLOCK_TYPE_PCM), + TYPE(PERIPHC_PWM, CLOCK_TYPE_PCST), /* only PWM uses b29:28 */ + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SBC2, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SBC3, CLOCK_TYPE_PCMT), + + /* 0x08 */ + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_I2C1, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_I2C5, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SBC1, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_DISP1, CLOCK_TYPE_PMDACD2T), + TYPE(PERIPHC_DISP2, CLOCK_TYPE_PMDACD2T), + + /* 0x10 */ + TYPE(PERIPHC_CVE, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SDMMC1, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SDMMC2, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_G3D, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_G2D, CLOCK_TYPE_MCPA), + + /* 0x18 */ + TYPE(PERIPHC_NDFLASH, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SDMMC4, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_VFIR, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_EPP, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_MPE, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_MIPI, CLOCK_TYPE_PCMT), /* MIPI base-band HSI */ + TYPE(PERIPHC_UART1, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_UART2, CLOCK_TYPE_PCMT), + + /* 0x20 */ + TYPE(PERIPHC_HOST1X, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_TVO, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_HDMI, CLOCK_TYPE_PMDACD2T), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_I2C2, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPT), + + /* 0x28 */ + TYPE(PERIPHC_UART3, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SBC4, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_I2C3, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PCMT), + + /* 0x30 */ + TYPE(PERIPHC_UART4, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_UART5, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_VDE, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_OWR, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_NOR, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_CSITE, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_I2S0, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + + /* 0x38h */ /* Jumps to reg offset 0x3B0h */ + TYPE(PERIPHC_G3D2, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_MSELECT, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_TSENSOR, CLOCK_TYPE_PCST), /* s/b PCTS */ + TYPE(PERIPHC_I2S3, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_I2S4, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_I2C4, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_SBC5, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SBC6, CLOCK_TYPE_PCMT), + + /* 0x40 */ + TYPE(PERIPHC_AUDIO, CLOCK_TYPE_ACPT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_DAM0, CLOCK_TYPE_ACPT), + TYPE(PERIPHC_DAM1, CLOCK_TYPE_ACPT), + TYPE(PERIPHC_DAM2, CLOCK_TYPE_ACPT), + TYPE(PERIPHC_HDA2CODEC2X, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_ACTMON, CLOCK_TYPE_PCST), /* MASK 31:30 */ + TYPE(PERIPHC_EXTPERIPH1, CLOCK_TYPE_ASPTE), + + /* 0x48 */ + TYPE(PERIPHC_EXTPERIPH2, CLOCK_TYPE_ASPTE), + TYPE(PERIPHC_EXTPERIPH3, CLOCK_TYPE_ASPTE), + TYPE(PERIPHC_NANDSPEED, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_I2CSLOW, CLOCK_TYPE_PCST), /* MASK 31:30 */ + TYPE(PERIPHC_SYS, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SPEEDO, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + + /* 0x50 */ + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SATAOOB, CLOCK_TYPE_PCMT), /* offset 0x420h */ + TYPE(PERIPHC_SATA, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_HDA, CLOCK_TYPE_PCMT), +}; + +/* + * This array translates a periph_id to a periphc_internal_id + * + * Not present/matched up: + * uint vi_sensor; _VI_SENSOR_0, 0x1A8 + * SPDIF - which is both 0x08 and 0x0c + * + */ +#define NONE(name) (-1) +#define OFFSET(name, value) PERIPHC_ ## name +static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { + /* Low word: 31:0 */ + NONE(CPU), + NONE(COP), + NONE(TRIGSYS), + NONE(RESERVED3), + NONE(RTC), + NONE(TMR), + PERIPHC_UART1, + PERIPHC_UART2, /* and vfir 0x68 */ + + /* 8 */ + NONE(GPIO), + PERIPHC_SDMMC2, + NONE(SPDIF), /* 0x08 and 0x0c, unclear which to use */ + PERIPHC_I2S1, + PERIPHC_I2C1, + PERIPHC_NDFLASH, + PERIPHC_SDMMC1, + PERIPHC_SDMMC4, + + /* 16 */ + NONE(RESERVED16), + PERIPHC_PWM, + PERIPHC_I2S2, + PERIPHC_EPP, + PERIPHC_VI, + PERIPHC_G2D, + NONE(USBD), + NONE(ISP), + + /* 24 */ + PERIPHC_G3D, + NONE(RESERVED25), + PERIPHC_DISP2, + PERIPHC_DISP1, + PERIPHC_HOST1X, + NONE(VCP), + PERIPHC_I2S0, + NONE(CACHE2), + + /* Middle word: 63:32 */ + NONE(MEM), + NONE(AHBDMA), + NONE(APBDMA), + NONE(RESERVED35), + NONE(RESERVED36), + NONE(STAT_MON), + NONE(RESERVED38), + NONE(RESERVED39), + + /* 40 */ + NONE(KFUSE), + NONE(SBC1), /* SBC1, 0x34, is this SPI1? */ + PERIPHC_NOR, + NONE(RESERVED43), + PERIPHC_SBC2, + NONE(RESERVED45), + PERIPHC_SBC3, + PERIPHC_I2C5, + + /* 48 */ + NONE(DSI), + PERIPHC_TVO, /* also CVE 0x40 */ + PERIPHC_MIPI, + PERIPHC_HDMI, + NONE(CSI), + PERIPHC_TVDAC, + PERIPHC_I2C2, + PERIPHC_UART3, + + /* 56 */ + NONE(RESERVED56), + PERIPHC_EMC, + NONE(USB2), + NONE(USB3), + PERIPHC_MPE, + PERIPHC_VDE, + NONE(BSEA), + NONE(BSEV), + + /* Upper word 95:64 */ + PERIPHC_SPEEDO, + PERIPHC_UART4, + PERIPHC_UART5, + PERIPHC_I2C3, + PERIPHC_SBC4, + PERIPHC_SDMMC3, + NONE(PCIE), + PERIPHC_OWR, + + /* 72 */ + NONE(AFI), + PERIPHC_CSITE, + NONE(PCIEXCLK), + NONE(AVPUCQ), + NONE(RESERVED76), + NONE(RESERVED77), + NONE(RESERVED78), + NONE(DTV), + + /* 80 */ + PERIPHC_NANDSPEED, + PERIPHC_I2CSLOW, + NONE(DSIB), + NONE(RESERVED83), + NONE(IRAMA), + NONE(IRAMB), + NONE(IRAMC), + NONE(IRAMD), + + /* 88 */ + NONE(CRAM2), + NONE(RESERVED89), + NONE(MDOUBLER), + NONE(RESERVED91), + NONE(SUSOUT), + NONE(RESERVED93), + NONE(RESERVED94), + NONE(RESERVED95), + + /* V word: 31:0 */ + NONE(CPUG), + NONE(CPULP), + PERIPHC_G3D2, + PERIPHC_MSELECT, + PERIPHC_TSENSOR, + PERIPHC_I2S3, + PERIPHC_I2S4, + PERIPHC_I2C4, + + /* 08 */ + PERIPHC_SBC5, + PERIPHC_SBC6, + PERIPHC_AUDIO, + NONE(APBIF), + PERIPHC_DAM0, + PERIPHC_DAM1, + PERIPHC_DAM2, + PERIPHC_HDA2CODEC2X, + + /* 16 */ + NONE(ATOMICS), + NONE(RESERVED17), + NONE(RESERVED18), + NONE(RESERVED19), + NONE(RESERVED20), + NONE(RESERVED21), + NONE(RESERVED22), + PERIPHC_ACTMON, + + /* 24 */ + NONE(RESERVED24), + NONE(RESERVED25), + NONE(RESERVED26), + NONE(RESERVED27), + PERIPHC_SATA, + PERIPHC_HDA, + NONE(RESERVED30), + NONE(RESERVED31), + + /* W word: 31:0 */ + NONE(HDA2HDMICODEC), + NONE(RESERVED1_SATACOLD), + NONE(RESERVED2_PCIERX0), + NONE(RESERVED3_PCIERX1), + NONE(RESERVED4_PCIERX2), + NONE(RESERVED5_PCIERX3), + NONE(RESERVED6_PCIERX4), + NONE(RESERVED7_PCIERX5), + + /* 40 */ + NONE(CEC), + NONE(PCIE2_IOBIST), + NONE(EMC_IOBIST), + NONE(HDMI_IOBIST), + NONE(SATA_IOBIST), + NONE(MIPI_IOBIST), + NONE(EMC1_IOBIST), + NONE(XUSB), + + /* 48 */ + NONE(CILAB), + NONE(CILCD), + NONE(CILE), + NONE(DSIA_LP), + NONE(DSIB_LP), + NONE(RESERVED21_ENTROPY), + NONE(RESERVED22_W), + NONE(RESERVED23_W), + + /* 56 */ + NONE(RESERVED24_W), + NONE(AMX0), + NONE(ADX0), + NONE(DVFS), + NONE(XUSB_SS), + NONE(EMC_DLL), + NONE(MC1), + NONE(EMC1), +}; + +/* + * Get the oscillator frequency, from the corresponding hardware configuration + * field. Note that T30/T114 support 3 new higher freqs, but we map back + * to the old T20 freqs. Support for the higher oscillators is TBD. + */ +enum clock_osc_freq clock_get_osc_freq(void) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + reg = readl(&clkrst->crc_osc_ctrl); + reg = (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; + + if (reg & 1) /* one of the newer freqs */ + printf("Warning: OSC_FREQ is unsupported! (%d)\n", reg); + + return reg >> 2; /* Map to most common (T20) freqs */ +} + +/* Returns a pointer to the clock source register for a peripheral */ +u32 *get_periph_source_reg(enum periph_id periph_id) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + enum periphc_internal_id internal_id; + + /* Coresight is a special case */ + if (periph_id == PERIPH_ID_CSI) + return &clkrst->crc_clk_src[PERIPH_ID_CSI+1]; + + assert(periph_id >= PERIPH_ID_FIRST && periph_id < PERIPH_ID_COUNT); + internal_id = periph_id_to_internal_id[periph_id]; + assert(internal_id != -1); + if (internal_id >= PERIPHC_VW_FIRST) { + internal_id -= PERIPHC_VW_FIRST; + return &clkrst->crc_clk_src_vw[internal_id]; + } else + return &clkrst->crc_clk_src[internal_id]; +} + +/** + * Given a peripheral ID and the required source clock, this returns which + * value should be programmed into the source mux for that peripheral. + * + * There is special code here to handle the one source type with 5 sources. + * + * @param periph_id peripheral to start + * @param source PLL id of required parent clock + * @param mux_bits Set to number of bits in mux register: 2 or 4 + * @param divider_bits Set to number of divider bits (8 or 16) + * @return mux value (0-4, or -1 if not found) + */ +int get_periph_clock_source(enum periph_id periph_id, + enum clock_id parent, int *mux_bits, int *divider_bits) +{ + enum clock_type_id type; + enum periphc_internal_id internal_id; + int mux; + + assert(clock_periph_id_isvalid(periph_id)); + + internal_id = periph_id_to_internal_id[periph_id]; + assert(periphc_internal_id_isvalid(internal_id)); + + type = clock_periph_type[internal_id]; + assert(clock_type_id_isvalid(type)); + + *mux_bits = clock_source[type][CLOCK_MAX_MUX]; + + if (type == CLOCK_TYPE_PCMT16) + *divider_bits = 16; + else + *divider_bits = 8; + + for (mux = 0; mux < CLOCK_MAX_MUX; mux++) + if (clock_source[type][mux] == parent) + return mux; + + /* if we get here, either us or the caller has made a mistake */ + printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id, + parent); + return -1; +} + +void clock_set_enable(enum periph_id periph_id, int enable) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 *clk; + u32 reg; + + /* Enable/disable the clock to this peripheral */ + assert(clock_periph_id_isvalid(periph_id)); + if ((int)periph_id < (int)PERIPH_ID_VW_FIRST) + clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)]; + else + clk = &clkrst->crc_clk_out_enb_vw[PERIPH_REG(periph_id)]; + reg = readl(clk); + if (enable) + reg |= PERIPH_MASK(periph_id); + else + reg &= ~PERIPH_MASK(periph_id); + writel(reg, clk); +} + +void reset_set_enable(enum periph_id periph_id, int enable) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 *reset; + u32 reg; + + /* Enable/disable reset to the peripheral */ + assert(clock_periph_id_isvalid(periph_id)); + if (periph_id < PERIPH_ID_VW_FIRST) + reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)]; + else + reset = &clkrst->crc_rst_dev_vw[PERIPH_REG(periph_id)]; + reg = readl(reset); + if (enable) + reg |= PERIPH_MASK(periph_id); + else + reg &= ~PERIPH_MASK(periph_id); + writel(reg, reset); +} + +#ifdef CONFIG_OF_CONTROL +/* + * Convert a device tree clock ID to our peripheral ID. They are mostly + * the same but we are very cautious so we check that a valid clock ID is + * provided. + * + * @param clk_id Clock ID according to tegra114 device tree binding + * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid + */ +enum periph_id clk_id_to_periph_id(int clk_id) +{ + if (clk_id > PERIPH_ID_COUNT) + return PERIPH_ID_NONE; + + switch (clk_id) { + case PERIPH_ID_RESERVED3: + case PERIPH_ID_RESERVED16: + case PERIPH_ID_RESERVED24: + case PERIPH_ID_RESERVED35: + case PERIPH_ID_RESERVED43: + case PERIPH_ID_RESERVED45: + case PERIPH_ID_RESERVED56: + case PERIPH_ID_RESERVED76: + case PERIPH_ID_RESERVED77: + case PERIPH_ID_RESERVED78: + case PERIPH_ID_RESERVED83: + case PERIPH_ID_RESERVED89: + case PERIPH_ID_RESERVED91: + case PERIPH_ID_RESERVED93: + case PERIPH_ID_RESERVED94: + case PERIPH_ID_RESERVED95: + return PERIPH_ID_NONE; + default: + return clk_id; + } +} +#endif /* CONFIG_OF_CONTROL */ + +void clock_early_init(void) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + + tegra30_set_up_pllp(); + + /* + * PLLC output frequency set to 600Mhz + * PLLD output frequency set to 925Mhz + */ + switch (clock_get_osc_freq()) { + case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */ + clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8); + clock_set_rate(CLOCK_ID_DISPLAY, 925, 12, 0, 12); + break; + + case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */ + clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8); + clock_set_rate(CLOCK_ID_DISPLAY, 925, 26, 0, 12); + break; + + case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */ + clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8); + clock_set_rate(CLOCK_ID_DISPLAY, 925, 13, 0, 12); + break; + case CLOCK_OSC_FREQ_19_2: + default: + /* + * These are not supported. It is too early to print a + * message and the UART likely won't work anyway due to the + * oscillator being wrong. + */ + break; + } + + /* PLLC_MISC2: Set dynramp_stepA/B. MISC2 maps to pll_out[1] */ + writel(0x00561600, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_out[1]); + + /* PLLC_MISC: Set LOCK_ENABLE */ + writel(0x01000000, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc); + udelay(2); + + /* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1 */ + writel(0x40000C10, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc); + udelay(2); +} + +void arch_timer_init(void) +{ + struct sysctr_ctlr *sysctr = (struct sysctr_ctlr *)NV_PA_TSC_BASE; + u32 freq, val; + + freq = clock_get_rate(CLOCK_ID_OSC); + debug("%s: osc freq is %dHz [0x%08X]\n", __func__, freq, freq); + + /* ARM CNTFRQ */ + asm("mcr p15, 0, %0, c14, c0, 0\n" : : "r" (freq)); + + /* Only T114 has the System Counter regs */ + debug("%s: setting CNTFID0 to 0x%08X\n", __func__, freq); + writel(freq, &sysctr->cntfid0); + + val = readl(&sysctr->cntcr); + val |= TSC_CNTCR_ENABLE | TSC_CNTCR_HDBG; + writel(val, &sysctr->cntcr); + debug("%s: TSC CNTCR = 0x%08X\n", __func__, val); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/funcmux.c b/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/funcmux.c new file mode 100644 index 000000000..52441c71e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/funcmux.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Tegra114 high-level function multiplexing */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/pinmux.h> + +int funcmux_select(enum periph_id id, int config) +{ + int bad_config = config != FUNCMUX_DEFAULT; + + switch (id) { + case PERIPH_ID_UART4: + switch (config) { + case FUNCMUX_UART4_GMI: + pinmux_set_func(PMUX_PINGRP_GMI_A16_PJ7, + PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_GMI_A17_PB0, + PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_GMI_A18_PB1, + PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_GMI_A19_PK7, + PMUX_FUNC_UARTD); + + pinmux_set_io(PMUX_PINGRP_GMI_A16_PJ7, PMUX_PIN_OUTPUT); + pinmux_set_io(PMUX_PINGRP_GMI_A17_PB0, PMUX_PIN_INPUT); + pinmux_set_io(PMUX_PINGRP_GMI_A18_PB1, PMUX_PIN_INPUT); + pinmux_set_io(PMUX_PINGRP_GMI_A19_PK7, PMUX_PIN_OUTPUT); + + pinmux_tristate_disable(PMUX_PINGRP_GMI_A16_PJ7); + pinmux_tristate_disable(PMUX_PINGRP_GMI_A17_PB0); + pinmux_tristate_disable(PMUX_PINGRP_GMI_A18_PB1); + pinmux_tristate_disable(PMUX_PINGRP_GMI_A19_PK7); + break; + } + break; + + /* Add other periph IDs here as needed */ + + default: + debug("%s: invalid periph_id %d", __func__, id); + return -1; + } + + if (bad_config) { + debug("%s: invalid config %d for periph_id %d", __func__, + config, id); + return -1; + } + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/pinmux.c b/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/pinmux.c new file mode 100644 index 000000000..3e5acb93c --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra114-common/pinmux.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +#define PIN(pin, f0, f1, f2, f3) \ + { \ + .funcs = { \ + PMUX_FUNC_##f0, \ + PMUX_FUNC_##f1, \ + PMUX_FUNC_##f2, \ + PMUX_FUNC_##f3, \ + }, \ + } + +#define PIN_RESERVED {} + +static const struct pmux_pingrp_desc tegra114_pingroups[] = { + /* pin, f0, f1, f2, f3 */ + /* Offset 0x3000 */ + PIN(ULPI_DATA0_PO1, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA1_PO2, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA2_PO3, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA3_PO4, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA4_PO5, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA5_PO6, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA6_PO7, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA7_PO0, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_CLK_PY0, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_DIR_PY1, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_NXT_PY2, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_STP_PY3, SPI1, SPI5, UARTD, ULPI), + PIN(DAP3_FS_PP0, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(DAP3_DIN_PP1, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(DAP3_DOUT_PP2, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(DAP3_SCLK_PP3, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(PV0, USB, RSVD2, RSVD3, RSVD4), + PIN(PV1, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(SDMMC1_CLK_PZ0, SDMMC1, CLK12, RSVD3, RSVD4), + PIN(SDMMC1_CMD_PZ1, SDMMC1, SPDIF, SPI4, UARTA), + PIN(SDMMC1_DAT3_PY4, SDMMC1, SPDIF, SPI4, UARTA), + PIN(SDMMC1_DAT2_PY5, SDMMC1, PWM0, SPI4, UARTA), + PIN(SDMMC1_DAT1_PY6, SDMMC1, PWM1, SPI4, UARTA), + PIN(SDMMC1_DAT0_PY7, SDMMC1, RSVD2, SPI4, UARTA), + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3068 */ + PIN(CLK2_OUT_PW5, EXTPERIPH2, RSVD2, RSVD3, RSVD4), + PIN(CLK2_REQ_PCC5, DAP, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3110 */ + PIN(HDMI_INT_PN7, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(DDC_SCL_PV4, I2C4, RSVD2, RSVD3, RSVD4), + PIN(DDC_SDA_PV5, I2C4, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3164 */ + PIN(UART2_RXD_PC3, IRDA, SPDIF, UARTA, SPI4), + PIN(UART2_TXD_PC2, IRDA, SPDIF, UARTA, SPI4), + PIN(UART2_RTS_N_PJ6, UARTA, UARTB, RSVD3, SPI4), + PIN(UART2_CTS_N_PJ5, UARTA, UARTB, RSVD3, SPI4), + PIN(UART3_TXD_PW6, UARTC, RSVD2, RSVD3, SPI4), + PIN(UART3_RXD_PW7, UARTC, RSVD2, RSVD3, SPI4), + PIN(UART3_CTS_N_PA1, UARTC, SDMMC1, DTV, SPI4), + PIN(UART3_RTS_N_PC0, UARTC, PWM0, DTV, DISPLAYA), + PIN(PU0, OWR, UARTA, RSVD3, RSVD4), + PIN(PU1, RSVD1, UARTA, RSVD3, RSVD4), + PIN(PU2, RSVD1, UARTA, RSVD3, RSVD4), + PIN(PU3, PWM0, UARTA, DISPLAYA, DISPLAYB), + PIN(PU4, PWM1, UARTA, DISPLAYA, DISPLAYB), + PIN(PU5, PWM2, UARTA, DISPLAYA, DISPLAYB), + PIN(PU6, PWM3, UARTA, USB, DISPLAYB), + PIN(GEN1_I2C_SDA_PC5, I2C1, RSVD2, RSVD3, RSVD4), + PIN(GEN1_I2C_SCL_PC4, I2C1, RSVD2, RSVD3, RSVD4), + PIN(DAP4_FS_PP4, I2S3, RSVD2, DTV, RSVD4), + PIN(DAP4_DIN_PP5, I2S3, RSVD2, RSVD3, RSVD4), + PIN(DAP4_DOUT_PP6, I2S3, RSVD2, DTV, RSVD4), + PIN(DAP4_SCLK_PP7, I2S3, RSVD2, RSVD3, RSVD4), + PIN(CLK3_OUT_PEE0, EXTPERIPH3, RSVD2, RSVD3, RSVD4), + PIN(CLK3_REQ_PEE1, DEV3, RSVD2, RSVD3, RSVD4), + PIN(GMI_WP_N_PC7, RSVD1, NAND, GMI, GMI_ALT), + PIN(GMI_IORDY_PI5, SDMMC2, RSVD2, GMI, TRACE), + PIN(GMI_WAIT_PI7, SPI4, NAND, GMI, DTV), + PIN(GMI_ADV_N_PK0, RSVD1, NAND, GMI, TRACE), + PIN(GMI_CLK_PK1, SDMMC2, NAND, GMI, TRACE), + PIN(GMI_CS0_N_PJ0, RSVD1, NAND, GMI, USB), + PIN(GMI_CS1_N_PJ2, RSVD1, NAND, GMI, SOC), + PIN(GMI_CS2_N_PK3, SDMMC2, NAND, GMI, TRACE), + PIN(GMI_CS3_N_PK4, SDMMC2, NAND, GMI, GMI_ALT), + PIN(GMI_CS4_N_PK2, USB, NAND, GMI, TRACE), + PIN(GMI_CS6_N_PI3, NAND, NAND_ALT, GMI, SPI4), + PIN(GMI_CS7_N_PI6, NAND, NAND_ALT, GMI, SDMMC2), + PIN(GMI_AD0_PG0, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD1_PG1, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD2_PG2, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD3_PG3, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD4_PG4, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD5_PG5, RSVD1, NAND, GMI, SPI4), + PIN(GMI_AD6_PG6, RSVD1, NAND, GMI, SPI4), + PIN(GMI_AD7_PG7, RSVD1, NAND, GMI, SPI4), + PIN(GMI_AD8_PH0, PWM0, NAND, GMI, DTV), + PIN(GMI_AD9_PH1, PWM1, NAND, GMI, CLDVFS), + PIN(GMI_AD10_PH2, PWM2, NAND, GMI, CLDVFS), + PIN(GMI_AD11_PH3, PWM3, NAND, GMI, USB), + PIN(GMI_AD12_PH4, SDMMC2, NAND, GMI, RSVD4), + PIN(GMI_AD13_PH5, SDMMC2, NAND, GMI, RSVD4), + PIN(GMI_AD14_PH6, SDMMC2, NAND, GMI, DTV), + PIN(GMI_AD15_PH7, SDMMC2, NAND, GMI, DTV), + PIN(GMI_A16_PJ7, UARTD, TRACE, GMI, GMI_ALT), + PIN(GMI_A17_PB0, UARTD, RSVD2, GMI, TRACE), + PIN(GMI_A18_PB1, UARTD, RSVD2, GMI, TRACE), + PIN(GMI_A19_PK7, UARTD, SPI4, GMI, TRACE), + PIN(GMI_WR_N_PI0, RSVD1, NAND, GMI, SPI4), + PIN(GMI_OE_N_PI1, RSVD1, NAND, GMI, SOC), + PIN(GMI_DQS_P_PJ3, SDMMC2, NAND, GMI, TRACE), + PIN(GMI_RST_N_PI4, NAND, NAND_ALT, GMI, RSVD4), + PIN(GEN2_I2C_SCL_PT5, I2C2, RSVD2, GMI, RSVD4), + PIN(GEN2_I2C_SDA_PT6, I2C2, RSVD2, GMI, RSVD4), + PIN(SDMMC4_CLK_PCC4, SDMMC4, RSVD2, GMI, RSVD4), + PIN(SDMMC4_CMD_PT7, SDMMC4, RSVD2, GMI, RSVD4), + PIN(SDMMC4_DAT0_PAA0, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT1_PAA1, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT2_PAA2, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT3_PAA3, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT4_PAA4, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT5_PAA5, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT6_PAA6, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT7_PAA7, SDMMC4, RSVD2, GMI, RSVD4), + PIN_RESERVED, + /* Offset 0x3284 */ + PIN(CAM_MCLK_PCC0, VI, VI_ALT1, VI_ALT3, RSVD4), + PIN(PCC1, I2S4, RSVD2, RSVD3, RSVD4), + PIN(PBB0, I2S4, VI, VI_ALT1, VI_ALT3), + PIN(CAM_I2C_SCL_PBB1, VGP1, I2C3, RSVD3, RSVD4), + PIN(CAM_I2C_SDA_PBB2, VGP2, I2C3, RSVD3, RSVD4), + PIN(PBB3, VGP3, DISPLAYA, DISPLAYB, RSVD4), + PIN(PBB4, VGP4, DISPLAYA, DISPLAYB, RSVD4), + PIN(PBB5, VGP5, DISPLAYA, DISPLAYB, RSVD4), + PIN(PBB6, VGP6, DISPLAYA, DISPLAYB, RSVD4), + PIN(PBB7, I2S4, RSVD2, RSVD3, RSVD4), + PIN(PCC2, I2S4, RSVD2, RSVD3, RSVD4), + PIN(JTAG_RTCK, RTCK, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SCL_PZ6, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SDA_PZ7, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW0_PR0, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW1_PR1, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW2_PR2, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW3_PR3, KBC, DISPLAYA, RSVD3, DISPLAYB), + PIN(KB_ROW4_PR4, KBC, DISPLAYA, SPI2, DISPLAYB), + PIN(KB_ROW5_PR5, KBC, DISPLAYA, SPI2, DISPLAYB), + PIN(KB_ROW6_PR6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB), + PIN(KB_ROW7_PR7, KBC, RSVD2, CLDVFS, UARTA), + PIN(KB_ROW8_PS0, KBC, RSVD2, CLDVFS, UARTA), + PIN(KB_ROW9_PS1, KBC, RSVD2, RSVD3, UARTA), + PIN(KB_ROW10_PS2, KBC, RSVD2, RSVD3, UARTA), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x32fc */ + PIN(KB_COL0_PQ0, KBC, USB, SPI2, EMC_DLL), + PIN(KB_COL1_PQ1, KBC, RSVD2, SPI2, EMC_DLL), + PIN(KB_COL2_PQ2, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_COL3_PQ3, KBC, DISPLAYA, PWM2, UARTA), + PIN(KB_COL4_PQ4, KBC, OWR, SDMMC3, UARTA), + PIN(KB_COL5_PQ5, KBC, RSVD2, SDMMC1, RSVD4), + PIN(KB_COL6_PQ6, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_COL7_PQ7, KBC, RSVD2, SPI2, RSVD4), + PIN(CLK_32K_OUT_PA0, BLINK, SOC, RSVD3, RSVD4), + PIN(SYS_CLK_REQ_PZ5, SYSCLK, RSVD2, RSVD3, RSVD4), + PIN(CORE_PWR_REQ, PWRON, RSVD2, RSVD3, RSVD4), + PIN(CPU_PWR_REQ, CPU, RSVD2, RSVD3, RSVD4), + PIN(PWR_INT_N, PMI, RSVD2, RSVD3, RSVD4), + PIN(CLK_32K_IN, CLK, RSVD2, RSVD3, RSVD4), + PIN(OWR, OWR, RSVD2, RSVD3, RSVD4), + PIN(DAP1_FS_PN0, I2S0, HDA, GMI, RSVD4), + PIN(DAP1_DIN_PN1, I2S0, HDA, GMI, RSVD4), + PIN(DAP1_DOUT_PN2, I2S0, HDA, GMI, RSVD4), + PIN(DAP1_SCLK_PN3, I2S0, HDA, GMI, RSVD4), + PIN(CLK1_REQ_PEE2, DAP, DAP1, RSVD3, RSVD4), + PIN(CLK1_OUT_PW4, EXTPERIPH1, DAP2, RSVD3, RSVD4), + PIN(SPDIF_IN_PK6, SPDIF, USB, RSVD3, RSVD4), + PIN(SPDIF_OUT_PK5, SPDIF, RSVD2, RSVD3, RSVD4), + PIN(DAP2_FS_PA2, I2S1, HDA, RSVD3, RSVD4), + PIN(DAP2_DIN_PA4, I2S1, HDA, RSVD3, RSVD4), + PIN(DAP2_DOUT_PA5, I2S1, HDA, RSVD3, RSVD4), + PIN(DAP2_SCLK_PA3, I2S1, HDA, RSVD3, RSVD4), + PIN(DVFS_PWM_PX0, SPI6, CLDVFS, RSVD3, RSVD4), + PIN(GPIO_X1_AUD_PX1, SPI6, RSVD2, RSVD3, RSVD4), + PIN(GPIO_X3_AUD_PX3, SPI6, SPI1, RSVD3, RSVD4), + PIN(DVFS_CLK_PX2, SPI6, CLDVFS, RSVD3, RSVD4), + PIN(GPIO_X4_AUD_PX4, RSVD1, SPI1, SPI2, DAP2), + PIN(GPIO_X5_AUD_PX5, RSVD1, SPI1, SPI2, RSVD4), + PIN(GPIO_X6_AUD_PX6, SPI6, SPI1, SPI2, RSVD4), + PIN(GPIO_X7_AUD_PX7, RSVD1, SPI1, SPI2, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3390 */ + PIN(SDMMC3_CLK_PA6, SDMMC3, RSVD2, RSVD3, SPI3), + PIN(SDMMC3_CMD_PA7, SDMMC3, PWM3, UARTA, SPI3), + PIN(SDMMC3_DAT0_PB7, SDMMC3, RSVD2, RSVD3, SPI3), + PIN(SDMMC3_DAT1_PB6, SDMMC3, PWM2, UARTA, SPI3), + PIN(SDMMC3_DAT2_PB5, SDMMC3, PWM1, DISPLAYA, SPI3), + PIN(SDMMC3_DAT3_PB4, SDMMC3, PWM0, DISPLAYB, SPI3), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x33e0 */ + PIN(HDMI_CEC_PEE3, CEC, SDMMC3, RSVD3, SOC), + PIN(SDMMC1_WP_N_PV3, SDMMC1, CLK12, SPI4, UARTA), + PIN(SDMMC3_CD_N_PV2, SDMMC3, OWR, RSVD3, RSVD4), + PIN(GPIO_W2_AUD_PW2, SPI6, RSVD2, SPI2, I2C1), + PIN(GPIO_W3_AUD_PW3, SPI6, SPI1, SPI2, I2C1), + PIN(USB_VBUS_EN0_PN4, USB, RSVD2, RSVD3, RSVD4), + PIN(USB_VBUS_EN1_PN5, USB, RSVD2, RSVD3, RSVD4), + PIN(SDMMC3_CLK_LB_IN_PEE5, SDMMC3, RSVD2, RSVD3, RSVD4), + PIN(SDMMC3_CLK_LB_OUT_PEE4, SDMMC3, RSVD2, RSVD3, RSVD4), + PIN(GMI_CLK_LB, SDMMC2, NAND, GMI, RSVD4), + PIN(RESET_OUT_N, RSVD1, RSVD2, RSVD3, RESET_OUT_N), +}; +const struct pmux_pingrp_desc *tegra_soc_pingroups = tegra114_pingroups; diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/Makefile new file mode 100644 index 000000000..ff77992b3 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/Makefile @@ -0,0 +1,10 @@ +# +# (C) Copyright 2013-2014 +# NVIDIA Corporation <www.nvidia.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += clock.o +obj-y += funcmux.o +obj-y += pinmux.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/clock.c b/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/clock.c new file mode 100644 index 000000000..739436326 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/clock.c @@ -0,0 +1,826 @@ +/* + * (C) Copyright 2013 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* Tegra124 Clock control functions */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/sysctr.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/timer.h> +#include <div64.h> +#include <fdtdec.h> + +/* + * Clock types that we can use as a source. The Tegra124 has muxes for the + * peripheral clocks, and in most cases there are four options for the clock + * source. This gives us a clock 'type' and exploits what commonality exists + * in the device. + * + * Letters are obvious, except for T which means CLK_M, and S which means the + * clock derived from 32KHz. Beware that CLK_M (also called OSC in the + * datasheet) and PLL_M are different things. The former is the basic + * clock supplied to the SOC from an external oscillator. The latter is the + * memory clock PLL. + * + * See definitions in clock_id in the header file. + */ +enum clock_type_id { + CLOCK_TYPE_AXPT, /* PLL_A, PLL_X, PLL_P, CLK_M */ + CLOCK_TYPE_MCPA, /* and so on */ + CLOCK_TYPE_MCPT, + CLOCK_TYPE_PCM, + CLOCK_TYPE_PCMT, + CLOCK_TYPE_PDCT, + CLOCK_TYPE_ACPT, + CLOCK_TYPE_ASPTE, + CLOCK_TYPE_PMDACD2T, + CLOCK_TYPE_PCST, + + CLOCK_TYPE_PC2CC3M, + CLOCK_TYPE_PC2CC3S_T, + CLOCK_TYPE_PC2CC3M_T, + CLOCK_TYPE_PC2CC3M_T16, /* PC2CC3M_T, but w/16-bit divisor (I2C) */ + CLOCK_TYPE_MC2CC3P_A, + CLOCK_TYPE_M, + CLOCK_TYPE_MCPTM2C2C3, + CLOCK_TYPE_PC2CC3T_S, + CLOCK_TYPE_AC2CC3P_TS2, + + CLOCK_TYPE_COUNT, + CLOCK_TYPE_NONE = -1, /* invalid clock type */ +}; + +enum { + CLOCK_MAX_MUX = 8 /* number of source options for each clock */ +}; + +/* + * Clock source mux for each clock type. This just converts our enum into + * a list of mux sources for use by the code. + * + * Note: + * The extra column in each clock source array is used to store the mask + * bits in its register for the source. + */ +#define CLK(x) CLOCK_ID_ ## x +static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX+1] = { + { CLK(AUDIO), CLK(XCPU), CLK(PERIPH), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(AUDIO), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(NONE), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(AUDIO), CLK(CGENERAL), CLK(PERIPH), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(AUDIO), CLK(SFROM32KHZ), CLK(PERIPH), CLK(OSC), + CLK(EPCI), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_29}, + { CLK(PERIPH), CLK(MEMORY), CLK(DISPLAY), CLK(AUDIO), + CLK(CGENERAL), CLK(DISPLAY2), CLK(OSC), CLK(NONE), + MASK_BITS_31_29}, + { CLK(PERIPH), CLK(CGENERAL), CLK(SFROM32KHZ), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_28}, + + /* Additional clock types on Tegra114+ */ + /* CLOCK_TYPE_PC2CC3M */ + { CLK(PERIPH), CLK(CGENERAL2), CLK(CGENERAL), CLK(CGENERAL3), + CLK(MEMORY), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_29}, + /* CLOCK_TYPE_PC2CC3S_T */ + { CLK(PERIPH), CLK(CGENERAL2), CLK(CGENERAL), CLK(CGENERAL3), + CLK(SFROM32KHZ), CLK(NONE), CLK(OSC), CLK(NONE), + MASK_BITS_31_29}, + /* CLOCK_TYPE_PC2CC3M_T */ + { CLK(PERIPH), CLK(CGENERAL2), CLK(CGENERAL), CLK(CGENERAL3), + CLK(MEMORY), CLK(NONE), CLK(OSC), CLK(NONE), + MASK_BITS_31_29}, + /* CLOCK_TYPE_PC2CC3M_T, w/16-bit divisor (I2C) */ + { CLK(PERIPH), CLK(CGENERAL2), CLK(CGENERAL), CLK(CGENERAL3), + CLK(MEMORY), CLK(NONE), CLK(OSC), CLK(NONE), + MASK_BITS_31_29}, + /* CLOCK_TYPE_MC2CC3P_A */ + { CLK(MEMORY), CLK(CGENERAL2), CLK(CGENERAL), CLK(CGENERAL3), + CLK(PERIPH), CLK(NONE), CLK(AUDIO), CLK(NONE), + MASK_BITS_31_29}, + /* CLOCK_TYPE_M */ + { CLK(MEMORY), CLK(NONE), CLK(NONE), CLK(NONE), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + /* CLOCK_TYPE_MCPTM2C2C3 */ + { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC), + CLK(MEMORY2), CLK(CGENERAL2), CLK(CGENERAL3), CLK(NONE), + MASK_BITS_31_29}, + /* CLOCK_TYPE_PC2CC3T_S */ + { CLK(PERIPH), CLK(CGENERAL2), CLK(CGENERAL), CLK(CGENERAL3), + CLK(OSC), CLK(NONE), CLK(SFROM32KHZ), CLK(NONE), + MASK_BITS_31_29}, + /* CLOCK_TYPE_AC2CC3P_TS2 */ + { CLK(AUDIO), CLK(CGENERAL2), CLK(CGENERAL), CLK(CGENERAL3), + CLK(PERIPH), CLK(NONE), CLK(OSC), CLK(SRC2), + MASK_BITS_31_29}, +}; + +/* + * Clock type for each peripheral clock source. We put the name in each + * record just so it is easy to match things up + */ +#define TYPE(name, type) type +static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = { + /* 0x00 */ + TYPE(PERIPHC_I2S1, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_I2S2, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_SPDIF_IN, CLOCK_TYPE_PC2CC3M), + TYPE(PERIPHC_PWM, CLOCK_TYPE_PC2CC3S_T), + TYPE(PERIPHC_05h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SBC2, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_SBC3, CLOCK_TYPE_PC2CC3M_T), + + /* 0x08 */ + TYPE(PERIPHC_08h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_I2C1, CLOCK_TYPE_PC2CC3M_T16), + TYPE(PERIPHC_I2C5, CLOCK_TYPE_PC2CC3M_T16), + TYPE(PERIPHC_0bh, CLOCK_TYPE_NONE), + TYPE(PERIPHC_0ch, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SBC1, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_DISP1, CLOCK_TYPE_PMDACD2T), + TYPE(PERIPHC_DISP2, CLOCK_TYPE_PMDACD2T), + + /* 0x10 */ + TYPE(PERIPHC_10h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_11h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_VI, CLOCK_TYPE_MC2CC3P_A), + TYPE(PERIPHC_13h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SDMMC1, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_SDMMC2, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_16h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_17h, CLOCK_TYPE_NONE), + + /* 0x18 */ + TYPE(PERIPHC_18h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SDMMC4, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_VFIR, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_1Bh, CLOCK_TYPE_NONE), + TYPE(PERIPHC_1Ch, CLOCK_TYPE_NONE), + TYPE(PERIPHC_HSI, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_UART1, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_UART2, CLOCK_TYPE_PC2CC3M_T), + + /* 0x20 */ + TYPE(PERIPHC_HOST1X, CLOCK_TYPE_MC2CC3P_A), + TYPE(PERIPHC_21h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_22h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_HDMI, CLOCK_TYPE_PMDACD2T), + TYPE(PERIPHC_24h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_25h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_I2C2, CLOCK_TYPE_PC2CC3M_T16), + TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPTM2C2C3), + + /* 0x28 */ + TYPE(PERIPHC_UART3, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_29h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_VI_SENSOR, CLOCK_TYPE_MC2CC3P_A), + TYPE(PERIPHC_2bh, CLOCK_TYPE_NONE), + TYPE(PERIPHC_2ch, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SBC4, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_I2C3, CLOCK_TYPE_PC2CC3M_T16), + TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PC2CC3M_T), + + /* 0x30 */ + TYPE(PERIPHC_UART4, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_UART5, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_VDE, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_OWR, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_NOR, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_CSITE, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_I2S0, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_DTV, CLOCK_TYPE_NONE), + + /* 0x38 */ + TYPE(PERIPHC_38h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_39h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_3ah, CLOCK_TYPE_NONE), + TYPE(PERIPHC_3bh, CLOCK_TYPE_NONE), + TYPE(PERIPHC_MSENC, CLOCK_TYPE_MC2CC3P_A), + TYPE(PERIPHC_TSEC, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_3eh, CLOCK_TYPE_NONE), + TYPE(PERIPHC_OSC, CLOCK_TYPE_NONE), + + /* 0x40 */ + TYPE(PERIPHC_40h, CLOCK_TYPE_NONE), /* start with 0x3b0 */ + TYPE(PERIPHC_MSELECT, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_TSENSOR, CLOCK_TYPE_PC2CC3T_S), + TYPE(PERIPHC_I2S3, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_I2S4, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_I2C4, CLOCK_TYPE_PC2CC3M_T16), + TYPE(PERIPHC_SBC5, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_SBC6, CLOCK_TYPE_PC2CC3M_T), + + /* 0x48 */ + TYPE(PERIPHC_AUDIO, CLOCK_TYPE_AC2CC3P_TS2), + TYPE(PERIPHC_49h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_DAM0, CLOCK_TYPE_AC2CC3P_TS2), + TYPE(PERIPHC_DAM1, CLOCK_TYPE_AC2CC3P_TS2), + TYPE(PERIPHC_DAM2, CLOCK_TYPE_AC2CC3P_TS2), + TYPE(PERIPHC_HDA2CODEC2X, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_ACTMON, CLOCK_TYPE_PC2CC3S_T), + TYPE(PERIPHC_EXTPERIPH1, CLOCK_TYPE_ASPTE), + + /* 0x50 */ + TYPE(PERIPHC_EXTPERIPH2, CLOCK_TYPE_ASPTE), + TYPE(PERIPHC_EXTPERIPH3, CLOCK_TYPE_ASPTE), + TYPE(PERIPHC_52h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_I2CSLOW, CLOCK_TYPE_PC2CC3S_T), + TYPE(PERIPHC_SYS, CLOCK_TYPE_NONE), + TYPE(PERIPHC_55h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_56h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_57h, CLOCK_TYPE_NONE), + + /* 0x58 */ + TYPE(PERIPHC_58h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_59h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_5ah, CLOCK_TYPE_NONE), + TYPE(PERIPHC_5bh, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SATAOOB, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SATA, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_HDA, CLOCK_TYPE_PC2CC3M_T), + TYPE(PERIPHC_5fh, CLOCK_TYPE_NONE), + + /* 0x60 */ + TYPE(PERIPHC_XUSB_CORE_HOST, CLOCK_TYPE_NONE), + TYPE(PERIPHC_XUSB_FALCON, CLOCK_TYPE_NONE), + TYPE(PERIPHC_XUSB_FS, CLOCK_TYPE_NONE), + TYPE(PERIPHC_XUSB_CORE_DEV, CLOCK_TYPE_NONE), + TYPE(PERIPHC_XUSB_SS, CLOCK_TYPE_NONE), + TYPE(PERIPHC_CILAB, CLOCK_TYPE_NONE), + TYPE(PERIPHC_CILCD, CLOCK_TYPE_NONE), + TYPE(PERIPHC_CILE, CLOCK_TYPE_NONE), + + /* 0x68 */ + TYPE(PERIPHC_DSIA_LP, CLOCK_TYPE_NONE), + TYPE(PERIPHC_DSIB_LP, CLOCK_TYPE_NONE), + TYPE(PERIPHC_ENTROPY, CLOCK_TYPE_NONE), + TYPE(PERIPHC_DVFS_REF, CLOCK_TYPE_NONE), + TYPE(PERIPHC_DVFS_SOC, CLOCK_TYPE_NONE), + TYPE(PERIPHC_TRACECLKIN, CLOCK_TYPE_NONE), + TYPE(PERIPHC_ADX0, CLOCK_TYPE_NONE), + TYPE(PERIPHC_AMX0, CLOCK_TYPE_NONE), + + /* 0x70 */ + TYPE(PERIPHC_EMC_LATENCY, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SOC_THERM, CLOCK_TYPE_NONE), + TYPE(PERIPHC_72h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_73h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_74h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_75h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_VI_SENSOR2, CLOCK_TYPE_NONE), + TYPE(PERIPHC_I2C6, CLOCK_TYPE_PC2CC3M_T16), + + /* 0x78 */ + TYPE(PERIPHC_78h, CLOCK_TYPE_NONE), + TYPE(PERIPHC_EMC_DLL, CLOCK_TYPE_MCPTM2C2C3), + TYPE(PERIPHC_HDMI_AUDIO, CLOCK_TYPE_NONE), + TYPE(PERIPHC_CLK72MHZ, CLOCK_TYPE_NONE), + TYPE(PERIPHC_ADX1, CLOCK_TYPE_AC2CC3P_TS2), + TYPE(PERIPHC_AMX1, CLOCK_TYPE_AC2CC3P_TS2), + TYPE(PERIPHC_VIC, CLOCK_TYPE_NONE), + TYPE(PERIPHC_7Fh, CLOCK_TYPE_NONE), +}; + +/* + * This array translates a periph_id to a periphc_internal_id + * + * Not present/matched up: + * uint vi_sensor; _VI_SENSOR_0, 0x1A8 + * SPDIF - which is both 0x08 and 0x0c + * + */ +#define NONE(name) (-1) +#define OFFSET(name, value) PERIPHC_ ## name +static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { + /* Low word: 31:0 */ + NONE(CPU), + NONE(COP), + NONE(TRIGSYS), + NONE(ISPB), + NONE(RESERVED4), + NONE(TMR), + PERIPHC_UART1, + PERIPHC_UART2, /* and vfir 0x68 */ + + /* 8 */ + NONE(GPIO), + PERIPHC_SDMMC2, + PERIPHC_SPDIF_IN, + PERIPHC_I2S1, + PERIPHC_I2C1, + NONE(RESERVED13), + PERIPHC_SDMMC1, + PERIPHC_SDMMC4, + + /* 16 */ + NONE(TCW), + PERIPHC_PWM, + PERIPHC_I2S2, + NONE(RESERVED19), + PERIPHC_VI, + NONE(RESERVED21), + NONE(USBD), + NONE(ISP), + + /* 24 */ + NONE(RESERVED24), + NONE(RESERVED25), + PERIPHC_DISP2, + PERIPHC_DISP1, + PERIPHC_HOST1X, + NONE(VCP), + PERIPHC_I2S0, + NONE(CACHE2), + + /* Middle word: 63:32 */ + NONE(MEM), + NONE(AHBDMA), + NONE(APBDMA), + NONE(RESERVED35), + NONE(RESERVED36), + NONE(STAT_MON), + NONE(RESERVED38), + NONE(FUSE), + + /* 40 */ + NONE(KFUSE), + PERIPHC_SBC1, /* SBCx = SPIx */ + PERIPHC_NOR, + NONE(RESERVED43), + PERIPHC_SBC2, + NONE(XIO), + PERIPHC_SBC3, + PERIPHC_I2C5, + + /* 48 */ + NONE(DSI), + NONE(RESERVED49), + PERIPHC_HSI, + PERIPHC_HDMI, + NONE(CSI), + NONE(RESERVED53), + PERIPHC_I2C2, + PERIPHC_UART3, + + /* 56 */ + NONE(MIPI_CAL), + PERIPHC_EMC, + NONE(USB2), + NONE(USB3), + NONE(RESERVED60), + PERIPHC_VDE, + NONE(BSEA), + NONE(BSEV), + + /* Upper word 95:64 */ + NONE(RESERVED64), + PERIPHC_UART4, + PERIPHC_UART5, + PERIPHC_I2C3, + PERIPHC_SBC4, + PERIPHC_SDMMC3, + NONE(PCIE), + PERIPHC_OWR, + + /* 72 */ + NONE(AFI), + PERIPHC_CSITE, + NONE(PCIEXCLK), + NONE(AVPUCQ), + NONE(LA), + NONE(TRACECLKIN), + NONE(SOC_THERM), + NONE(DTV), + + /* 80 */ + NONE(RESERVED80), + PERIPHC_I2CSLOW, + NONE(DSIB), + PERIPHC_TSEC, + NONE(RESERVED84), + NONE(RESERVED85), + NONE(RESERVED86), + NONE(EMUCIF), + + /* 88 */ + NONE(RESERVED88), + NONE(XUSB_HOST), + NONE(RESERVED90), + PERIPHC_MSENC, + NONE(RESERVED92), + NONE(RESERVED93), + NONE(RESERVED94), + NONE(XUSB_DEV), + + /* V word: 31:0 */ + NONE(CPUG), + NONE(CPULP), + NONE(V_RESERVED2), + PERIPHC_MSELECT, + NONE(V_RESERVED4), + PERIPHC_I2S3, + PERIPHC_I2S4, + PERIPHC_I2C4, + + /* 104 */ + PERIPHC_SBC5, + PERIPHC_SBC6, + PERIPHC_AUDIO, + NONE(APBIF), + PERIPHC_DAM0, + PERIPHC_DAM1, + PERIPHC_DAM2, + PERIPHC_HDA2CODEC2X, + + /* 112 */ + NONE(ATOMICS), + NONE(V_RESERVED17), + NONE(V_RESERVED18), + NONE(V_RESERVED19), + NONE(V_RESERVED20), + NONE(V_RESERVED21), + NONE(V_RESERVED22), + PERIPHC_ACTMON, + + /* 120 */ + NONE(EXTPERIPH1), + NONE(EXTPERIPH2), + NONE(EXTPERIPH3), + NONE(OOB), + PERIPHC_SATA, + PERIPHC_HDA, + NONE(TZRAM), + NONE(SE), + + /* W word: 31:0 */ + NONE(HDA2HDMICODEC), + NONE(SATACOLD), + NONE(W_RESERVED2), + NONE(W_RESERVED3), + NONE(W_RESERVED4), + NONE(W_RESERVED5), + NONE(W_RESERVED6), + NONE(W_RESERVED7), + + /* 136 */ + NONE(CEC), + NONE(W_RESERVED9), + NONE(W_RESERVED10), + NONE(W_RESERVED11), + NONE(W_RESERVED12), + NONE(W_RESERVED13), + NONE(XUSB_PADCTL), + NONE(W_RESERVED15), + + /* 144 */ + NONE(W_RESERVED16), + NONE(W_RESERVED17), + NONE(W_RESERVED18), + NONE(W_RESERVED19), + NONE(W_RESERVED20), + NONE(ENTROPY), + NONE(DDS), + NONE(W_RESERVED23), + + /* 152 */ + NONE(DP2), + NONE(AMX0), + NONE(ADX0), + NONE(DVFS), + NONE(XUSB_SS), + NONE(W_RESERVED29), + NONE(W_RESERVED30), + NONE(W_RESERVED31), + + /* X word: 31:0 */ + NONE(SPARE), + NONE(X_RESERVED1), + NONE(X_RESERVED2), + NONE(X_RESERVED3), + NONE(CAM_MCLK), + NONE(CAM_MCLK2), + PERIPHC_I2C6, + NONE(X_RESERVED7), + + /* 168 */ + NONE(X_RESERVED8), + NONE(X_RESERVED9), + NONE(X_RESERVED10), + NONE(VIM2_CLK), + NONE(X_RESERVED12), + NONE(X_RESERVED13), + NONE(EMC_DLL), + NONE(X_RESERVED15), + + /* 176 */ + NONE(HDMI_AUDIO), + NONE(CLK72MHZ), + NONE(VIC), + NONE(X_RESERVED19), + NONE(ADX1), + NONE(DPAUX), + NONE(SOR0), + NONE(X_RESERVED23), + + /* 184 */ + NONE(GPU), + NONE(AMX1), + NONE(X_RESERVED26), + NONE(X_RESERVED27), + NONE(X_RESERVED28), + NONE(X_RESERVED29), + NONE(X_RESERVED30), + NONE(X_RESERVED31), +}; + +/* + * Get the oscillator frequency, from the corresponding hardware configuration + * field. Note that Tegra30+ support 3 new higher freqs, but we map back + * to the old T20 freqs. Support for the higher oscillators is TBD. + */ +enum clock_osc_freq clock_get_osc_freq(void) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + reg = readl(&clkrst->crc_osc_ctrl); + reg = (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; + + if (reg & 1) /* one of the newer freqs */ + printf("Warning: OSC_FREQ is unsupported! (%d)\n", reg); + + return reg >> 2; /* Map to most common (T20) freqs */ +} + +/* Returns a pointer to the clock source register for a peripheral */ +u32 *get_periph_source_reg(enum periph_id periph_id) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + enum periphc_internal_id internal_id; + + /* Coresight is a special case */ + if (periph_id == PERIPH_ID_CSI) + return &clkrst->crc_clk_src[PERIPH_ID_CSI+1]; + + assert(periph_id >= PERIPH_ID_FIRST && periph_id < PERIPH_ID_COUNT); + internal_id = periph_id_to_internal_id[periph_id]; + assert(internal_id != -1); + if (internal_id >= PERIPHC_VW_FIRST) { + internal_id -= PERIPHC_VW_FIRST; + return &clkrst->crc_clk_src_vw[internal_id]; + } else { + return &clkrst->crc_clk_src[internal_id]; + } +} + +/** + * Given a peripheral ID and the required source clock, this returns which + * value should be programmed into the source mux for that peripheral. + * + * There is special code here to handle the one source type with 5 sources. + * + * @param periph_id peripheral to start + * @param source PLL id of required parent clock + * @param mux_bits Set to number of bits in mux register: 2 or 4 + * @param divider_bits Set to number of divider bits (8 or 16) + * @return mux value (0-4, or -1 if not found) + */ +int get_periph_clock_source(enum periph_id periph_id, + enum clock_id parent, int *mux_bits, int *divider_bits) +{ + enum clock_type_id type; + enum periphc_internal_id internal_id; + int mux; + + assert(clock_periph_id_isvalid(periph_id)); + + internal_id = periph_id_to_internal_id[periph_id]; + assert(periphc_internal_id_isvalid(internal_id)); + + type = clock_periph_type[internal_id]; + assert(clock_type_id_isvalid(type)); + + *mux_bits = clock_source[type][CLOCK_MAX_MUX]; + + if (type == CLOCK_TYPE_PC2CC3M_T16) + *divider_bits = 16; + else + *divider_bits = 8; + + for (mux = 0; mux < CLOCK_MAX_MUX; mux++) + if (clock_source[type][mux] == parent) + return mux; + + /* if we get here, either us or the caller has made a mistake */ + printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id, + parent); + return -1; +} + +void clock_set_enable(enum periph_id periph_id, int enable) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 *clk; + u32 reg; + + /* Enable/disable the clock to this peripheral */ + assert(clock_periph_id_isvalid(periph_id)); + if ((int)periph_id < (int)PERIPH_ID_VW_FIRST) + clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)]; + else + clk = &clkrst->crc_clk_out_enb_vw[PERIPH_REG(periph_id)]; + reg = readl(clk); + if (enable) + reg |= PERIPH_MASK(periph_id); + else + reg &= ~PERIPH_MASK(periph_id); + writel(reg, clk); +} + +void reset_set_enable(enum periph_id periph_id, int enable) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 *reset; + u32 reg; + + /* Enable/disable reset to the peripheral */ + assert(clock_periph_id_isvalid(periph_id)); + if (periph_id < PERIPH_ID_VW_FIRST) + reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)]; + else + reset = &clkrst->crc_rst_dev_vw[PERIPH_REG(periph_id)]; + reg = readl(reset); + if (enable) + reg |= PERIPH_MASK(periph_id); + else + reg &= ~PERIPH_MASK(periph_id); + writel(reg, reset); +} + +#ifdef CONFIG_OF_CONTROL +/* + * Convert a device tree clock ID to our peripheral ID. They are mostly + * the same but we are very cautious so we check that a valid clock ID is + * provided. + * + * @param clk_id Clock ID according to tegra124 device tree binding + * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid + */ +enum periph_id clk_id_to_periph_id(int clk_id) +{ + if (clk_id > PERIPH_ID_COUNT) + return PERIPH_ID_NONE; + + switch (clk_id) { + case PERIPH_ID_RESERVED4: + case PERIPH_ID_RESERVED25: + case PERIPH_ID_RESERVED35: + case PERIPH_ID_RESERVED36: + case PERIPH_ID_RESERVED38: + case PERIPH_ID_RESERVED43: + case PERIPH_ID_RESERVED49: + case PERIPH_ID_RESERVED53: + case PERIPH_ID_RESERVED64: + case PERIPH_ID_RESERVED84: + case PERIPH_ID_RESERVED85: + case PERIPH_ID_RESERVED86: + case PERIPH_ID_RESERVED88: + case PERIPH_ID_RESERVED90: + case PERIPH_ID_RESERVED92: + case PERIPH_ID_RESERVED93: + case PERIPH_ID_RESERVED94: + case PERIPH_ID_V_RESERVED2: + case PERIPH_ID_V_RESERVED4: + case PERIPH_ID_V_RESERVED17: + case PERIPH_ID_V_RESERVED18: + case PERIPH_ID_V_RESERVED19: + case PERIPH_ID_V_RESERVED20: + case PERIPH_ID_V_RESERVED21: + case PERIPH_ID_V_RESERVED22: + case PERIPH_ID_W_RESERVED2: + case PERIPH_ID_W_RESERVED3: + case PERIPH_ID_W_RESERVED4: + case PERIPH_ID_W_RESERVED5: + case PERIPH_ID_W_RESERVED6: + case PERIPH_ID_W_RESERVED7: + case PERIPH_ID_W_RESERVED9: + case PERIPH_ID_W_RESERVED10: + case PERIPH_ID_W_RESERVED11: + case PERIPH_ID_W_RESERVED12: + case PERIPH_ID_W_RESERVED13: + case PERIPH_ID_W_RESERVED15: + case PERIPH_ID_W_RESERVED16: + case PERIPH_ID_W_RESERVED17: + case PERIPH_ID_W_RESERVED18: + case PERIPH_ID_W_RESERVED19: + case PERIPH_ID_W_RESERVED20: + case PERIPH_ID_W_RESERVED23: + case PERIPH_ID_W_RESERVED29: + case PERIPH_ID_W_RESERVED30: + case PERIPH_ID_W_RESERVED31: + return PERIPH_ID_NONE; + default: + return clk_id; + } +} +#endif /* CONFIG_OF_CONTROL */ + +void clock_early_init(void) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + + tegra30_set_up_pllp(); + + /* + * PLLC output frequency set to 600Mhz + * PLLD output frequency set to 925Mhz + */ + switch (clock_get_osc_freq()) { + case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */ + clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8); + clock_set_rate(CLOCK_ID_DISPLAY, 925, 12, 0, 12); + break; + + case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */ + clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8); + clock_set_rate(CLOCK_ID_DISPLAY, 925, 26, 0, 12); + break; + + case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */ + clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8); + clock_set_rate(CLOCK_ID_DISPLAY, 925, 13, 0, 12); + break; + case CLOCK_OSC_FREQ_19_2: + default: + /* + * These are not supported. It is too early to print a + * message and the UART likely won't work anyway due to the + * oscillator being wrong. + */ + break; + } + + /* PLLC_MISC2: Set dynramp_stepA/B. MISC2 maps to pll_out[1] */ + writel(0x00561600, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_out[1]); + + /* PLLC_MISC: Set LOCK_ENABLE */ + writel(0x01000000, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc); + udelay(2); + + /* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1 */ + writel(0x40000C10, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc); + udelay(2); +} + +void arch_timer_init(void) +{ + struct sysctr_ctlr *sysctr = (struct sysctr_ctlr *)NV_PA_TSC_BASE; + u32 freq, val; + + freq = clock_get_rate(CLOCK_ID_OSC); + debug("%s: osc freq is %dHz [0x%08X]\n", __func__, freq, freq); + + /* ARM CNTFRQ */ + asm("mcr p15, 0, %0, c14, c0, 0\n" : : "r" (freq)); + + /* Only Tegra114+ has the System Counter regs */ + debug("%s: setting CNTFID0 to 0x%08X\n", __func__, freq); + writel(freq, &sysctr->cntfid0); + + val = readl(&sysctr->cntcr); + val |= TSC_CNTCR_ENABLE | TSC_CNTCR_HDBG; + writel(val, &sysctr->cntcr); + debug("%s: TSC CNTCR = 0x%08X\n", __func__, val); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/funcmux.c b/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/funcmux.c new file mode 100644 index 000000000..cced787e6 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/funcmux.c @@ -0,0 +1,71 @@ +/* + * (C) Copyright 2013 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* Tegra124 high-level function multiplexing */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/pinmux.h> + +int funcmux_select(enum periph_id id, int config) +{ + int bad_config = config != FUNCMUX_DEFAULT; + + switch (id) { + case PERIPH_ID_UART4: + switch (config) { + case FUNCMUX_UART4_GPIO: /* TXD,RXD,CTS,RTS */ + pinmux_set_func(PMUX_PINGRP_PJ7, PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_PB0, PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_PB1, PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_PK7, PMUX_FUNC_UARTD); + + pinmux_set_io(PMUX_PINGRP_PJ7, PMUX_PIN_OUTPUT); + pinmux_set_io(PMUX_PINGRP_PB0, PMUX_PIN_INPUT); + pinmux_set_io(PMUX_PINGRP_PB1, PMUX_PIN_INPUT); + pinmux_set_io(PMUX_PINGRP_PK7, PMUX_PIN_OUTPUT); + + pinmux_tristate_disable(PMUX_PINGRP_PJ7); + pinmux_tristate_disable(PMUX_PINGRP_PB0); + pinmux_tristate_disable(PMUX_PINGRP_PB1); + pinmux_tristate_disable(PMUX_PINGRP_PK7); + break; + } + break; + + case PERIPH_ID_UART1: + switch (config) { + case FUNCMUX_UART1_KBC: + pinmux_set_func(PMUX_PINGRP_KB_ROW9_PS1, + PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_KB_ROW10_PS2, + PMUX_FUNC_UARTA); + + pinmux_set_io(PMUX_PINGRP_KB_ROW9_PS1, PMUX_PIN_OUTPUT); + pinmux_set_io(PMUX_PINGRP_KB_ROW10_PS2, PMUX_PIN_INPUT); + + pinmux_tristate_disable(PMUX_PINGRP_KB_ROW9_PS1); + pinmux_tristate_disable(PMUX_PINGRP_KB_ROW10_PS2); + break; + } + break; + + /* Add other periph IDs here as needed */ + + default: + debug("%s: invalid periph_id %d", __func__, id); + return -1; + } + + if (bad_config) { + debug("%s: invalid config %d for periph_id %d", __func__, + config, id); + return -1; + } + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/pinmux.c b/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/pinmux.c new file mode 100644 index 000000000..c6685eaae --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra124-common/pinmux.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +#define PIN(pin, f0, f1, f2, f3) \ + { \ + .funcs = { \ + PMUX_FUNC_##f0, \ + PMUX_FUNC_##f1, \ + PMUX_FUNC_##f2, \ + PMUX_FUNC_##f3, \ + }, \ + } + +#define PIN_RESERVED {} + +static const struct pmux_pingrp_desc tegra124_pingroups[] = { + /* pin, f0, f1, f2, f3 */ + /* Offset 0x3000 */ + PIN(ULPI_DATA0_PO1, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA1_PO2, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA2_PO3, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA3_PO4, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA4_PO5, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA5_PO6, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA6_PO7, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA7_PO0, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_CLK_PY0, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_DIR_PY1, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_NXT_PY2, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_STP_PY3, SPI1, SPI5, UARTD, ULPI), + PIN(DAP3_FS_PP0, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(DAP3_DIN_PP1, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(DAP3_DOUT_PP2, I2S2, SPI5, DISPLAYA, RSVD4), + PIN(DAP3_SCLK_PP3, I2S2, SPI5, RSVD3, DISPLAYB), + PIN(PV0, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(PV1, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(SDMMC1_CLK_PZ0, SDMMC1, CLK12, RSVD3, RSVD4), + PIN(SDMMC1_CMD_PZ1, SDMMC1, SPDIF, SPI4, UARTA), + PIN(SDMMC1_DAT3_PY4, SDMMC1, SPDIF, SPI4, UARTA), + PIN(SDMMC1_DAT2_PY5, SDMMC1, PWM0, SPI4, UARTA), + PIN(SDMMC1_DAT1_PY6, SDMMC1, PWM1, SPI4, UARTA), + PIN(SDMMC1_DAT0_PY7, SDMMC1, RSVD2, SPI4, UARTA), + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3068 */ + PIN(CLK2_OUT_PW5, EXTPERIPH2, RSVD2, RSVD3, RSVD4), + PIN(CLK2_REQ_PCC5, DAP, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3110 */ + PIN(HDMI_INT_PN7, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(DDC_SCL_PV4, I2C4, RSVD2, RSVD3, RSVD4), + PIN(DDC_SDA_PV5, I2C4, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3164 */ + PIN(UART2_RXD_PC3, IRDA, SPDIF, UARTA, SPI4), + PIN(UART2_TXD_PC2, IRDA, SPDIF, UARTA, SPI4), + PIN(UART2_RTS_N_PJ6, UARTA, UARTB, GMI, SPI4), + PIN(UART2_CTS_N_PJ5, UARTA, UARTB, GMI, SPI4), + PIN(UART3_TXD_PW6, UARTC, RSVD2, GMI, SPI4), + PIN(UART3_RXD_PW7, UARTC, RSVD2, GMI, SPI4), + PIN(UART3_CTS_N_PA1, UARTC, SDMMC1, DTV, GMI), + PIN(UART3_RTS_N_PC0, UARTC, PWM0, DTV, GMI), + PIN(PU0, OWR, UARTA, GMI, RSVD4), + PIN(PU1, RSVD1, UARTA, GMI, RSVD4), + PIN(PU2, RSVD1, UARTA, GMI, RSVD4), + PIN(PU3, PWM0, UARTA, GMI, DISPLAYB), + PIN(PU4, PWM1, UARTA, GMI, DISPLAYB), + PIN(PU5, PWM2, UARTA, GMI, DISPLAYB), + PIN(PU6, PWM3, UARTA, RSVD3, GMI), + PIN(GEN1_I2C_SDA_PC5, I2C1, RSVD2, RSVD3, RSVD4), + PIN(GEN1_I2C_SCL_PC4, I2C1, RSVD2, RSVD3, RSVD4), + PIN(DAP4_FS_PP4, I2S3, GMI, DTV, RSVD4), + PIN(DAP4_DIN_PP5, I2S3, GMI, RSVD3, RSVD4), + PIN(DAP4_DOUT_PP6, I2S3, GMI, DTV, RSVD4), + PIN(DAP4_SCLK_PP7, I2S3, GMI, RSVD3, RSVD4), + PIN(CLK3_OUT_PEE0, EXTPERIPH3, RSVD2, RSVD3, RSVD4), + PIN(CLK3_REQ_PEE1, DEV3, RSVD2, RSVD3, RSVD4), + PIN(PC7, RSVD1, RSVD2, GMI, GMI_ALT), + PIN(PI5, SDMMC2, RSVD2, GMI, RSVD4), + PIN(PI7, RSVD1, TRACE, GMI, DTV), + PIN(PK0, RSVD1, SDMMC3, GMI, SOC), + PIN(PK1, SDMMC2, TRACE, GMI, RSVD4), + PIN(PJ0, RSVD1, RSVD2, GMI, USB), + PIN(PJ2, RSVD1, RSVD2, GMI, SOC), + PIN(PK3, SDMMC2, TRACE, GMI, CCLA), + PIN(PK4, SDMMC2, RSVD2, GMI, GMI_ALT), + PIN(PK2, RSVD1, RSVD2, GMI, RSVD4), + PIN(PI3, RSVD1, RSVD2, GMI, SPI4), + PIN(PI6, RSVD1, RSVD2, GMI, SDMMC2), + PIN(PG0, RSVD1, RSVD2, GMI, RSVD4), + PIN(PG1, RSVD1, RSVD2, GMI, RSVD4), + PIN(PG2, RSVD1, TRACE, GMI, RSVD4), + PIN(PG3, RSVD1, TRACE, GMI, RSVD4), + PIN(PG4, RSVD1, TMDS, GMI, SPI4), + PIN(PG5, RSVD1, RSVD2, GMI, SPI4), + PIN(PG6, RSVD1, RSVD2, GMI, SPI4), + PIN(PG7, RSVD1, RSVD2, GMI, SPI4), + PIN(PH0, PWM0, TRACE, GMI, DTV), + PIN(PH1, PWM1, TMDS, GMI, DISPLAYA), + PIN(PH2, PWM2, TMDS, GMI, CLDVFS), + PIN(PH3, PWM3, SPI4, GMI, CLDVFS), + PIN(PH4, SDMMC2, RSVD2, GMI, RSVD4), + PIN(PH5, SDMMC2, RSVD2, GMI, RSVD4), + PIN(PH6, SDMMC2, TRACE, GMI, DTV), + PIN(PH7, SDMMC2, TRACE, GMI, DTV), + PIN(PJ7, UARTD, RSVD2, GMI, GMI_ALT), + PIN(PB0, UARTD, RSVD2, GMI, RSVD4), + PIN(PB1, UARTD, RSVD2, GMI, RSVD4), + PIN(PK7, UARTD, RSVD2, GMI, RSVD4), + PIN(PI0, RSVD1, RSVD2, GMI, RSVD4), + PIN(PI1, RSVD1, RSVD2, GMI, RSVD4), + PIN(PI2, SDMMC2, TRACE, GMI, RSVD4), + PIN(PI4, SPI4, TRACE, GMI, DISPLAYA), + PIN(GEN2_I2C_SCL_PT5, I2C2, RSVD2, GMI, RSVD4), + PIN(GEN2_I2C_SDA_PT6, I2C2, RSVD2, GMI, RSVD4), + PIN(SDMMC4_CLK_PCC4, SDMMC4, RSVD2, GMI, RSVD4), + PIN(SDMMC4_CMD_PT7, SDMMC4, RSVD2, GMI, RSVD4), + PIN(SDMMC4_DAT0_PAA0, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT1_PAA1, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT2_PAA2, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT3_PAA3, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT4_PAA4, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT5_PAA5, SDMMC4, SPI3, RSVD3, RSVD4), + PIN(SDMMC4_DAT6_PAA6, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT7_PAA7, SDMMC4, RSVD2, GMI, RSVD4), + PIN_RESERVED, + /* Offset 0x3284 */ + PIN(CAM_MCLK_PCC0, VI, VI_ALT1, VI_ALT3, SDMMC2), + PIN(PCC1, I2S4, RSVD2, RSVD3, SDMMC2), + PIN(PBB0, VGP6, VIMCLK2, SDMMC2, VIMCLK2_ALT), + PIN(CAM_I2C_SCL_PBB1, VGP1, I2C3, RSVD3, SDMMC2), + PIN(CAM_I2C_SDA_PBB2, VGP2, I2C3, RSVD3, SDMMC2), + PIN(PBB3, VGP3, DISPLAYA, DISPLAYB, SDMMC2), + PIN(PBB4, VGP4, DISPLAYA, DISPLAYB, SDMMC2), + PIN(PBB5, VGP5, DISPLAYA, RSVD3, SDMMC2), + PIN(PBB6, I2S4, RSVD2, DISPLAYB, SDMMC2), + PIN(PBB7, I2S4, RSVD2, RSVD3, SDMMC2), + PIN(PCC2, I2S4, RSVD2, SDMMC3, SDMMC2), + PIN(JTAG_RTCK, RTCK, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SCL_PZ6, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SDA_PZ7, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW0_PR0, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW1_PR1, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW2_PR2, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW3_PR3, KBC, DISPLAYA, SYS, DISPLAYB), + PIN(KB_ROW4_PR4, KBC, DISPLAYA, RSVD3, DISPLAYB), + PIN(KB_ROW5_PR5, KBC, DISPLAYA, RSVD3, DISPLAYB), + PIN(KB_ROW6_PR6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB), + PIN(KB_ROW7_PR7, KBC, RSVD2, CLDVFS, UARTA), + PIN(KB_ROW8_PS0, KBC, RSVD2, CLDVFS, UARTA), + PIN(KB_ROW9_PS1, KBC, RSVD2, RSVD3, UARTA), + PIN(KB_ROW10_PS2, KBC, RSVD2, RSVD3, UARTA), + PIN(KB_ROW11_PS3, KBC, RSVD2, RSVD3, IRDA), + PIN(KB_ROW12_PS4, KBC, RSVD2, RSVD3, IRDA), + PIN(KB_ROW13_PS5, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_ROW14_PS6, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_ROW15_PS7, KBC, SOC, RSVD3, RSVD4), + PIN(KB_COL0_PQ0, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_COL1_PQ1, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_COL2_PQ2, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_COL3_PQ3, KBC, DISPLAYA, PWM2, UARTA), + PIN(KB_COL4_PQ4, KBC, OWR, SDMMC3, UARTA), + PIN(KB_COL5_PQ5, KBC, RSVD2, SDMMC3, RSVD4), + PIN(KB_COL6_PQ6, KBC, RSVD2, SPI2, UARTD), + PIN(KB_COL7_PQ7, KBC, RSVD2, SPI2, UARTD), + PIN(CLK_32K_OUT_PA0, BLINK, SOC, RSVD3, RSVD4), + PIN_RESERVED, + /* Offset 0x3324 */ + PIN(CORE_PWR_REQ, PWRON, RSVD2, RSVD3, RSVD4), + PIN(CPU_PWR_REQ, CPU, RSVD2, RSVD3, RSVD4), + PIN(PWR_INT_N, PMI, RSVD2, RSVD3, RSVD4), + PIN(CLK_32K_IN, CLK, RSVD2, RSVD3, RSVD4), + PIN(OWR, OWR, RSVD2, RSVD3, RSVD4), + PIN(DAP1_FS_PN0, I2S0, HDA, GMI, RSVD4), + PIN(DAP1_DIN_PN1, I2S0, HDA, GMI, RSVD4), + PIN(DAP1_DOUT_PN2, I2S0, HDA, GMI, SATA), + PIN(DAP1_SCLK_PN3, I2S0, HDA, GMI, RSVD4), + PIN(DAP_MCLK1_REQ_PEE2, DAP, DAP1, SATA, RSVD4), + PIN(DAP_MCLK1_PW4, EXTPERIPH1, DAP2, RSVD3, RSVD4), + PIN(SPDIF_IN_PK6, SPDIF, RSVD2, RSVD3, I2C3), + PIN(SPDIF_OUT_PK5, SPDIF, RSVD2, RSVD3, I2C3), + PIN(DAP2_FS_PA2, I2S1, HDA, GMI, RSVD4), + PIN(DAP2_DIN_PA4, I2S1, HDA, GMI, RSVD4), + PIN(DAP2_DOUT_PA5, I2S1, HDA, GMI, RSVD4), + PIN(DAP2_SCLK_PA3, I2S1, HDA, GMI, RSVD4), + PIN(DVFS_PWM_PX0, SPI6, CLDVFS, GMI, RSVD4), + PIN(GPIO_X1_AUD_PX1, SPI6, RSVD2, GMI, RSVD4), + PIN(GPIO_X3_AUD_PX3, SPI6, SPI1, GMI, RSVD4), + PIN(DVFS_CLK_PX2, SPI6, CLDVFS, GMI, RSVD4), + PIN(GPIO_X4_AUD_PX4, GMI, SPI1, SPI2, DAP2), + PIN(GPIO_X5_AUD_PX5, GMI, SPI1, SPI2, RSVD4), + PIN(GPIO_X6_AUD_PX6, SPI6, SPI1, SPI2, GMI), + PIN(GPIO_X7_AUD_PX7, RSVD1, SPI1, SPI2, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3390 */ + PIN(SDMMC3_CLK_PA6, SDMMC3, RSVD2, RSVD3, SPI3), + PIN(SDMMC3_CMD_PA7, SDMMC3, PWM3, UARTA, SPI3), + PIN(SDMMC3_DAT0_PB7, SDMMC3, RSVD2, RSVD3, SPI3), + PIN(SDMMC3_DAT1_PB6, SDMMC3, PWM2, UARTA, SPI3), + PIN(SDMMC3_DAT2_PB5, SDMMC3, PWM1, DISPLAYA, SPI3), + PIN(SDMMC3_DAT3_PB4, SDMMC3, PWM0, DISPLAYB, SPI3), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x33bc */ + PIN(PEX_L0_RST_N_PDD1, PE0, RSVD2, RSVD3, RSVD4), + PIN(PEX_L0_CLKREQ_N_PDD2, PE0, RSVD2, RSVD3, RSVD4), + PIN(PEX_WAKE_N_PDD3, PE, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + /* Offset 0x33cc */ + PIN(PEX_L1_RST_N_PDD5, PE1, RSVD2, RSVD3, RSVD4), + PIN(PEX_L1_CLKREQ_N_PDD6, PE1, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x33e0 */ + PIN(HDMI_CEC_PEE3, CEC, RSVD2, RSVD3, RSVD4), + PIN(SDMMC1_WP_N_PV3, SDMMC1, CLK12, SPI4, UARTA), + PIN(SDMMC3_CD_N_PV2, SDMMC3, OWR, RSVD3, RSVD4), + PIN(GPIO_W2_AUD_PW2, SPI6, RSVD2, SPI2, I2C1), + PIN(GPIO_W3_AUD_PW3, SPI6, SPI1, SPI2, I2C1), + PIN(USB_VBUS_EN0_PN4, USB, RSVD2, RSVD3, RSVD4), + PIN(USB_VBUS_EN1_PN5, USB, RSVD2, RSVD3, RSVD4), + PIN(SDMMC3_CLK_LB_IN_PEE5, SDMMC3, RSVD2, RSVD3, RSVD4), + PIN(SDMMC3_CLK_LB_OUT_PEE4, SDMMC3, RSVD2, RSVD3, RSVD4), + PIN(GMI_CLK_LB, SDMMC2, RSVD2, GMI, RSVD4), + PIN(RESET_OUT_N, RSVD1, RSVD2, RSVD3, RESET_OUT_N), + PIN(KB_ROW16_PT0, KBC, RSVD2, RSVD3, UARTC), + PIN(KB_ROW17_PT1, KBC, RSVD2, RSVD3, UARTC), + PIN(USB_VBUS_EN2_PFF1, USB, RSVD2, RSVD3, RSVD4), + PIN(PFF2, SATA, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3430 */ + PIN(DP_HPD_PFF0, DP, RSVD2, RSVD3, RSVD4), +}; +const struct pmux_pingrp_desc *tegra_soc_pingroups = tegra124_pingroups; diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/Makefile new file mode 100644 index 000000000..0e4b3fc1d --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/Makefile @@ -0,0 +1,17 @@ +# +# (C) Copyright 2010,2011 Nvidia Corporation. +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# The AVP is ARMv4T architecture so we must use special compiler +# flags for any startup files it might use. +CFLAGS_warmboot_avp.o += -march=armv4t + +obj-y += clock.o funcmux.o pinmux.o +obj-$(CONFIG_TEGRA_LP0) += warmboot.o crypto.o warmboot_avp.o +obj-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o +obj-$(CONFIG_TEGRA_PMU) += pmu.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/clock.c b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/clock.c new file mode 100644 index 000000000..0c4f5fb28 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/clock.c @@ -0,0 +1,550 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* Tegra20 Clock control functions */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/timer.h> +#include <div64.h> +#include <fdtdec.h> + +/* + * Clock types that we can use as a source. The Tegra20 has muxes for the + * peripheral clocks, and in most cases there are four options for the clock + * source. This gives us a clock 'type' and exploits what commonality exists + * in the device. + * + * Letters are obvious, except for T which means CLK_M, and S which means the + * clock derived from 32KHz. Beware that CLK_M (also called OSC in the + * datasheet) and PLL_M are different things. The former is the basic + * clock supplied to the SOC from an external oscillator. The latter is the + * memory clock PLL. + * + * See definitions in clock_id in the header file. + */ +enum clock_type_id { + CLOCK_TYPE_AXPT, /* PLL_A, PLL_X, PLL_P, CLK_M */ + CLOCK_TYPE_MCPA, /* and so on */ + CLOCK_TYPE_MCPT, + CLOCK_TYPE_PCM, + CLOCK_TYPE_PCMT, + CLOCK_TYPE_PCMT16, /* CLOCK_TYPE_PCMT with 16-bit divider */ + CLOCK_TYPE_PCXTS, + CLOCK_TYPE_PDCT, + + CLOCK_TYPE_COUNT, + CLOCK_TYPE_NONE = -1, /* invalid clock type */ +}; + +enum { + CLOCK_MAX_MUX = 4 /* number of source options for each clock */ +}; + +/* + * Clock source mux for each clock type. This just converts our enum into + * a list of mux sources for use by the code. Note that CLOCK_TYPE_PCXTS + * is special as it has 5 sources. Since it also has a different number of + * bits in its register for the source, we just handle it with a special + * case in the code. + */ +#define CLK(x) CLOCK_ID_ ## x +static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX] = { + { CLK(AUDIO), CLK(XCPU), CLK(PERIPH), CLK(OSC) }, + { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(AUDIO) }, + { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC) }, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(NONE) }, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC) }, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC) }, + { CLK(PERIPH), CLK(CGENERAL), CLK(XCPU), CLK(OSC) }, + { CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC) }, +}; + +/* + * Clock peripheral IDs which sadly don't match up with PERIPH_ID. This is + * not in the header file since it is for purely internal use - we want + * callers to use the PERIPH_ID for all access to peripheral clocks to avoid + * confusion bewteen PERIPH_ID_... and PERIPHC_... + * + * We don't call this CLOCK_PERIPH_ID or PERIPH_CLOCK_ID as it would just be + * confusing. + * + * Note to SOC vendors: perhaps define a unified numbering for peripherals and + * use it for reset, clock enable, clock source/divider and even pinmuxing + * if you can. + */ +enum periphc_internal_id { + /* 0x00 */ + PERIPHC_I2S1, + PERIPHC_I2S2, + PERIPHC_SPDIF_OUT, + PERIPHC_SPDIF_IN, + PERIPHC_PWM, + PERIPHC_SPI1, + PERIPHC_SPI2, + PERIPHC_SPI3, + + /* 0x08 */ + PERIPHC_XIO, + PERIPHC_I2C1, + PERIPHC_DVC_I2C, + PERIPHC_TWC, + PERIPHC_0c, + PERIPHC_10, /* PERIPHC_SPI1, what is this really? */ + PERIPHC_DISP1, + PERIPHC_DISP2, + + /* 0x10 */ + PERIPHC_CVE, + PERIPHC_IDE0, + PERIPHC_VI, + PERIPHC_1c, + PERIPHC_SDMMC1, + PERIPHC_SDMMC2, + PERIPHC_G3D, + PERIPHC_G2D, + + /* 0x18 */ + PERIPHC_NDFLASH, + PERIPHC_SDMMC4, + PERIPHC_VFIR, + PERIPHC_EPP, + PERIPHC_MPE, + PERIPHC_MIPI, + PERIPHC_UART1, + PERIPHC_UART2, + + /* 0x20 */ + PERIPHC_HOST1X, + PERIPHC_21, + PERIPHC_TVO, + PERIPHC_HDMI, + PERIPHC_24, + PERIPHC_TVDAC, + PERIPHC_I2C2, + PERIPHC_EMC, + + /* 0x28 */ + PERIPHC_UART3, + PERIPHC_29, + PERIPHC_VI_SENSOR, + PERIPHC_2b, + PERIPHC_2c, + PERIPHC_SPI4, + PERIPHC_I2C3, + PERIPHC_SDMMC3, + + /* 0x30 */ + PERIPHC_UART4, + PERIPHC_UART5, + PERIPHC_VDE, + PERIPHC_OWR, + PERIPHC_NOR, + PERIPHC_CSITE, + + PERIPHC_COUNT, + + PERIPHC_NONE = -1, +}; + +/* + * Clock type for each peripheral clock source. We put the name in each + * record just so it is easy to match things up + */ +#define TYPE(name, type) type +static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = { + /* 0x00 */ + TYPE(PERIPHC_I2S1, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_I2S2, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_SPDIF_IN, CLOCK_TYPE_PCM), + TYPE(PERIPHC_PWM, CLOCK_TYPE_PCXTS), + TYPE(PERIPHC_SPI1, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SPI22, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SPI3, CLOCK_TYPE_PCMT), + + /* 0x08 */ + TYPE(PERIPHC_XIO, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_I2C1, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_DVC_I2C, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_TWC, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SPI1, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_DISP1, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_DISP2, CLOCK_TYPE_PDCT), + + /* 0x10 */ + TYPE(PERIPHC_CVE, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_IDE0, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SDMMC1, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SDMMC2, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_G3D, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_G2D, CLOCK_TYPE_MCPA), + + /* 0x18 */ + TYPE(PERIPHC_NDFLASH, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SDMMC4, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_VFIR, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_EPP, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_MPE, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_MIPI, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_UART1, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_UART2, CLOCK_TYPE_PCMT), + + /* 0x20 */ + TYPE(PERIPHC_HOST1X, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_TVO, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_HDMI, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_I2C2, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPT), + + /* 0x28 */ + TYPE(PERIPHC_UART3, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SPI4, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_I2C3, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PCMT), + + /* 0x30 */ + TYPE(PERIPHC_UART4, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_UART5, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_VDE, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_OWR, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_NOR, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_CSITE, CLOCK_TYPE_PCMT), +}; + +/* + * This array translates a periph_id to a periphc_internal_id + * + * Not present/matched up: + * uint vi_sensor; _VI_SENSOR_0, 0x1A8 + * SPDIF - which is both 0x08 and 0x0c + * + */ +#define NONE(name) (-1) +#define OFFSET(name, value) PERIPHC_ ## name +static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { + /* Low word: 31:0 */ + NONE(CPU), + NONE(RESERVED1), + NONE(RESERVED2), + NONE(AC97), + NONE(RTC), + NONE(TMR), + PERIPHC_UART1, + PERIPHC_UART2, /* and vfir 0x68 */ + + /* 0x08 */ + NONE(GPIO), + PERIPHC_SDMMC2, + NONE(SPDIF), /* 0x08 and 0x0c, unclear which to use */ + PERIPHC_I2S1, + PERIPHC_I2C1, + PERIPHC_NDFLASH, + PERIPHC_SDMMC1, + PERIPHC_SDMMC4, + + /* 0x10 */ + PERIPHC_TWC, + PERIPHC_PWM, + PERIPHC_I2S2, + PERIPHC_EPP, + PERIPHC_VI, + PERIPHC_G2D, + NONE(USBD), + NONE(ISP), + + /* 0x18 */ + PERIPHC_G3D, + PERIPHC_IDE0, + PERIPHC_DISP2, + PERIPHC_DISP1, + PERIPHC_HOST1X, + NONE(VCP), + NONE(RESERVED30), + NONE(CACHE2), + + /* Middle word: 63:32 */ + NONE(MEM), + NONE(AHBDMA), + NONE(APBDMA), + NONE(RESERVED35), + NONE(KBC), + NONE(STAT_MON), + NONE(PMC), + NONE(FUSE), + + /* 0x28 */ + NONE(KFUSE), + NONE(SBC1), /* SBC1, 0x34, is this SPI1? */ + PERIPHC_NOR, + PERIPHC_SPI1, + PERIPHC_SPI2, + PERIPHC_XIO, + PERIPHC_SPI3, + PERIPHC_DVC_I2C, + + /* 0x30 */ + NONE(DSI), + PERIPHC_TVO, /* also CVE 0x40 */ + PERIPHC_MIPI, + PERIPHC_HDMI, + PERIPHC_CSITE, + PERIPHC_TVDAC, + PERIPHC_I2C2, + PERIPHC_UART3, + + /* 0x38 */ + NONE(RESERVED56), + PERIPHC_EMC, + NONE(USB2), + NONE(USB3), + PERIPHC_MPE, + PERIPHC_VDE, + NONE(BSEA), + NONE(BSEV), + + /* Upper word 95:64 */ + NONE(SPEEDO), + PERIPHC_UART4, + PERIPHC_UART5, + PERIPHC_I2C3, + PERIPHC_SPI4, + PERIPHC_SDMMC3, + NONE(PCIE), + PERIPHC_OWR, + + /* 0x48 */ + NONE(AFI), + NONE(CORESIGHT), + NONE(RESERVED74), + NONE(AVPUCQ), + NONE(RESERVED76), + NONE(RESERVED77), + NONE(RESERVED78), + NONE(RESERVED79), + + /* 0x50 */ + NONE(RESERVED80), + NONE(RESERVED81), + NONE(RESERVED82), + NONE(RESERVED83), + NONE(IRAMA), + NONE(IRAMB), + NONE(IRAMC), + NONE(IRAMD), + + /* 0x58 */ + NONE(CRAM2), +}; + +/* + * Get the oscillator frequency, from the corresponding hardware configuration + * field. T20 has 4 frequencies that it supports. + */ +enum clock_osc_freq clock_get_osc_freq(void) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + reg = readl(&clkrst->crc_osc_ctrl); + return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; +} + +/* Returns a pointer to the clock source register for a peripheral */ +u32 *get_periph_source_reg(enum periph_id periph_id) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + enum periphc_internal_id internal_id; + + assert(clock_periph_id_isvalid(periph_id)); + internal_id = periph_id_to_internal_id[periph_id]; + assert(internal_id != -1); + return &clkrst->crc_clk_src[internal_id]; +} + +/** + * Given a peripheral ID and the required source clock, this returns which + * value should be programmed into the source mux for that peripheral. + * + * There is special code here to handle the one source type with 5 sources. + * + * @param periph_id peripheral to start + * @param source PLL id of required parent clock + * @param mux_bits Set to number of bits in mux register: 2 or 4 + * @param divider_bits Set to number of divider bits (8 or 16) + * @return mux value (0-4, or -1 if not found) + */ +int get_periph_clock_source(enum periph_id periph_id, + enum clock_id parent, int *mux_bits, int *divider_bits) +{ + enum clock_type_id type; + enum periphc_internal_id internal_id; + int mux; + + assert(clock_periph_id_isvalid(periph_id)); + + internal_id = periph_id_to_internal_id[periph_id]; + assert(periphc_internal_id_isvalid(internal_id)); + + type = clock_periph_type[internal_id]; + assert(clock_type_id_isvalid(type)); + + /* + * Special cases here for the clock with a 4-bit source mux and I2C + * with its 16-bit divisor + */ + if (type == CLOCK_TYPE_PCXTS) + *mux_bits = MASK_BITS_31_28; + else + *mux_bits = MASK_BITS_31_30; + if (type == CLOCK_TYPE_PCMT16) + *divider_bits = 16; + else + *divider_bits = 8; + + for (mux = 0; mux < CLOCK_MAX_MUX; mux++) + if (clock_source[type][mux] == parent) + return mux; + + /* + * Not found: it might be looking for the 'S' in CLOCK_TYPE_PCXTS + * which is not in our table. If not, then they are asking for a + * source which this peripheral can't access through its mux. + */ + assert(type == CLOCK_TYPE_PCXTS); + assert(parent == CLOCK_ID_SFROM32KHZ); + if (type == CLOCK_TYPE_PCXTS && parent == CLOCK_ID_SFROM32KHZ) + return 4; /* mux value for this clock */ + + /* if we get here, either us or the caller has made a mistake */ + printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id, + parent); + return -1; +} + +void clock_set_enable(enum periph_id periph_id, int enable) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 *clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)]; + u32 reg; + + /* Enable/disable the clock to this peripheral */ + assert(clock_periph_id_isvalid(periph_id)); + reg = readl(clk); + if (enable) + reg |= PERIPH_MASK(periph_id); + else + reg &= ~PERIPH_MASK(periph_id); + writel(reg, clk); +} + +void reset_set_enable(enum periph_id periph_id, int enable) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 *reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)]; + u32 reg; + + /* Enable/disable reset to the peripheral */ + assert(clock_periph_id_isvalid(periph_id)); + reg = readl(reset); + if (enable) + reg |= PERIPH_MASK(periph_id); + else + reg &= ~PERIPH_MASK(periph_id); + writel(reg, reset); +} + +#ifdef CONFIG_OF_CONTROL +/* + * Convert a device tree clock ID to our peripheral ID. They are mostly + * the same but we are very cautious so we check that a valid clock ID is + * provided. + * + * @param clk_id Clock ID according to tegra20 device tree binding + * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid + */ +enum periph_id clk_id_to_periph_id(int clk_id) +{ + if (clk_id > PERIPH_ID_COUNT) + return PERIPH_ID_NONE; + + switch (clk_id) { + case PERIPH_ID_RESERVED1: + case PERIPH_ID_RESERVED2: + case PERIPH_ID_RESERVED30: + case PERIPH_ID_RESERVED35: + case PERIPH_ID_RESERVED56: + case PERIPH_ID_RESERVED74: + case PERIPH_ID_RESERVED76: + case PERIPH_ID_RESERVED77: + case PERIPH_ID_RESERVED78: + case PERIPH_ID_RESERVED79: + case PERIPH_ID_RESERVED80: + case PERIPH_ID_RESERVED81: + case PERIPH_ID_RESERVED82: + case PERIPH_ID_RESERVED83: + case PERIPH_ID_RESERVED91: + return PERIPH_ID_NONE; + default: + return clk_id; + } +} +#endif /* CONFIG_OF_CONTROL */ + +void clock_early_init(void) +{ + /* + * PLLP output frequency set to 216MHz + * PLLC output frequency set to 600Mhz + * + * TODO: Can we calculate these values instead of hard-coding? + */ + switch (clock_get_osc_freq()) { + case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */ + clock_set_rate(CLOCK_ID_PERIPH, 432, 12, 1, 8); + clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8); + break; + + case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */ + clock_set_rate(CLOCK_ID_PERIPH, 432, 26, 1, 8); + clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8); + break; + + case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */ + clock_set_rate(CLOCK_ID_PERIPH, 432, 13, 1, 8); + clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8); + break; + case CLOCK_OSC_FREQ_19_2: + default: + /* + * These are not supported. It is too early to print a + * message and the UART likely won't work anyway due to the + * oscillator being wrong. + */ + break; + } +} + +void arch_timer_init(void) +{ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/crypto.c b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/crypto.c new file mode 100644 index 000000000..ec95d7ceb --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/crypto.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/errno.h> +#include "crypto.h" +#include "aes.h" + +static u8 zero_key[16]; + +#define AES_CMAC_CONST_RB 0x87 /* from RFC 4493, Figure 2.2 */ + +enum security_op { + SECURITY_SIGN = 1 << 0, /* Sign the data */ + SECURITY_ENCRYPT = 1 << 1, /* Encrypt the data */ +}; + +/** + * Shift a vector left by one bit + * + * \param in Input vector + * \param out Output vector + * \param size Length of vector in bytes + */ +static void left_shift_vector(u8 *in, u8 *out, int size) +{ + int carry = 0; + int i; + + for (i = size - 1; i >= 0; i--) { + out[i] = (in[i] << 1) | carry; + carry = in[i] >> 7; /* get most significant bit */ + } +} + +/** + * Sign a block of data, putting the result into dst. + * + * \param key Input AES key, length AES_KEY_LENGTH + * \param key_schedule Expanded key to use + * \param src Source data of length 'num_aes_blocks' blocks + * \param dst Destination buffer, length AES_KEY_LENGTH + * \param num_aes_blocks Number of AES blocks to encrypt + */ +static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst, + u32 num_aes_blocks) +{ + u8 tmp_data[AES_KEY_LENGTH]; + u8 left[AES_KEY_LENGTH]; + u8 k1[AES_KEY_LENGTH]; + u8 *cbc_chain_data; + unsigned i; + + cbc_chain_data = zero_key; /* Convenient array of 0's for IV */ + + /* compute K1 constant needed by AES-CMAC calculation */ + for (i = 0; i < AES_KEY_LENGTH; i++) + tmp_data[i] = 0; + + aes_cbc_encrypt_blocks(key_schedule, tmp_data, left, 1); + + left_shift_vector(left, k1, sizeof(left)); + + if ((left[0] >> 7) != 0) /* get MSB of L */ + k1[AES_KEY_LENGTH-1] ^= AES_CMAC_CONST_RB; + + /* compute the AES-CMAC value */ + for (i = 0; i < num_aes_blocks; i++) { + /* Apply the chain data */ + aes_apply_cbc_chain_data(cbc_chain_data, src, tmp_data); + + /* for the final block, XOR K1 into the IV */ + if (i == num_aes_blocks - 1) + aes_apply_cbc_chain_data(tmp_data, k1, tmp_data); + + /* encrypt the AES block */ + aes_encrypt(tmp_data, key_schedule, dst); + + debug("sign_obj: block %d of %d\n", i, num_aes_blocks); + + /* Update pointers for next loop. */ + cbc_chain_data = dst; + src += AES_KEY_LENGTH; + } +} + +/** + * Encrypt and sign a block of data (depending on security mode). + * + * \param key Input AES key, length AES_KEY_LENGTH + * \param oper Security operations mask to perform (enum security_op) + * \param src Source data + * \param length Size of source data + * \param sig_dst Destination address for signature, AES_KEY_LENGTH bytes + */ +static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src, + u32 length, u8 *sig_dst) +{ + u32 num_aes_blocks; + u8 key_schedule[AES_EXPAND_KEY_LENGTH]; + + debug("encrypt_and_sign: length = %d\n", length); + + /* + * The only need for a key is for signing/checksum purposes, so + * if not encrypting, expand a key of 0s. + */ + aes_expand_key(oper & SECURITY_ENCRYPT ? key : zero_key, key_schedule); + + num_aes_blocks = (length + AES_KEY_LENGTH - 1) / AES_KEY_LENGTH; + + if (oper & SECURITY_ENCRYPT) { + /* Perform this in place, resulting in src being encrypted. */ + debug("encrypt_and_sign: begin encryption\n"); + aes_cbc_encrypt_blocks(key_schedule, src, src, num_aes_blocks); + debug("encrypt_and_sign: end encryption\n"); + } + + if (oper & SECURITY_SIGN) { + /* encrypt the data, overwriting the result in signature. */ + debug("encrypt_and_sign: begin signing\n"); + sign_object(key, key_schedule, src, sig_dst, num_aes_blocks); + debug("encrypt_and_sign: end signing\n"); + } + + return 0; +} + +int sign_data_block(u8 *source, unsigned length, u8 *signature) +{ + return encrypt_and_sign(zero_key, SECURITY_SIGN, source, + length, signature); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/crypto.h b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/crypto.h new file mode 100644 index 000000000..f59b92768 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/crypto.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CRYPTO_H_ +#define _CRYPTO_H_ + +/** + * Sign a block of data + * + * \param source Source data + * \param length Size of source data + * \param signature Destination address for signature, AES_KEY_LENGTH bytes + */ +int sign_data_block(u8 *source, unsigned length, u8 *signature); + +#endif /* #ifndef _CRYPTO_H_ */ diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/emc.c b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/emc.c new file mode 100644 index 000000000..ed2462ab0 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/emc.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fdtdec.h> +#include <asm/io.h> +#include <asm/arch-tegra/ap.h> +#include <asm/arch-tegra/apb_misc.h> +#include <asm/arch/clock.h> +#include <asm/arch/emc.h> +#include <asm/arch/tegra.h> + +/* + * The EMC registers have shadow registers. When the EMC clock is updated + * in the clock controller, the shadow registers are copied to the active + * registers, allowing glitchless memory bus frequency changes. + * This function updates the shadow registers for a new clock frequency, + * and relies on the clock lock on the emc clock to avoid races between + * multiple frequency changes + */ + +/* + * This table defines the ordering of the registers provided to + * tegra_set_mmc() + * TODO: Convert to fdt version once available + */ +static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = { + 0x2c, /* RC */ + 0x30, /* RFC */ + 0x34, /* RAS */ + 0x38, /* RP */ + 0x3c, /* R2W */ + 0x40, /* W2R */ + 0x44, /* R2P */ + 0x48, /* W2P */ + 0x4c, /* RD_RCD */ + 0x50, /* WR_RCD */ + 0x54, /* RRD */ + 0x58, /* REXT */ + 0x5c, /* WDV */ + 0x60, /* QUSE */ + 0x64, /* QRST */ + 0x68, /* QSAFE */ + 0x6c, /* RDV */ + 0x70, /* REFRESH */ + 0x74, /* BURST_REFRESH_NUM */ + 0x78, /* PDEX2WR */ + 0x7c, /* PDEX2RD */ + 0x80, /* PCHG2PDEN */ + 0x84, /* ACT2PDEN */ + 0x88, /* AR2PDEN */ + 0x8c, /* RW2PDEN */ + 0x90, /* TXSR */ + 0x94, /* TCKE */ + 0x98, /* TFAW */ + 0x9c, /* TRPAB */ + 0xa0, /* TCLKSTABLE */ + 0xa4, /* TCLKSTOP */ + 0xa8, /* TREFBW */ + 0xac, /* QUSE_EXTRA */ + 0x114, /* FBIO_CFG6 */ + 0xb0, /* ODT_WRITE */ + 0xb4, /* ODT_READ */ + 0x104, /* FBIO_CFG5 */ + 0x2bc, /* CFG_DIG_DLL */ + 0x2c0, /* DLL_XFORM_DQS */ + 0x2c4, /* DLL_XFORM_QUSE */ + 0x2e0, /* ZCAL_REF_CNT */ + 0x2e4, /* ZCAL_WAIT_CNT */ + 0x2a8, /* AUTO_CAL_INTERVAL */ + 0x2d0, /* CFG_CLKTRIM_0 */ + 0x2d4, /* CFG_CLKTRIM_1 */ + 0x2d8, /* CFG_CLKTRIM_2 */ +}; + +struct emc_ctlr *emc_get_controller(const void *blob) +{ + fdt_addr_t addr; + int node; + + node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC); + if (node > 0) { + addr = fdtdec_get_addr(blob, node, "reg"); + if (addr != FDT_ADDR_T_NONE) + return (struct emc_ctlr *)addr; + } + return NULL; +} + +/* Error codes we use */ +enum { + ERR_NO_EMC_NODE = -10, + ERR_NO_EMC_REG, + ERR_NO_FREQ, + ERR_FREQ_NOT_FOUND, + ERR_BAD_REGS, + ERR_NO_RAM_CODE, + ERR_RAM_CODE_NOT_FOUND, +}; + +/** + * Find EMC tables for the given ram code. + * + * The tegra EMC binding has two options, one using the ram code and one not. + * We detect which is in use by looking for the nvidia,use-ram-code property. + * If this is not present, then the EMC tables are directly below 'node', + * otherwise we select the correct emc-tables subnode based on the 'ram_code' + * value. + * + * @param blob Device tree blob + * @param node EMC node (nvidia,tegra20-emc compatible string) + * @param ram_code RAM code to select (0-3, or -1 if unknown) + * @return 0 if ok, otherwise a -ve ERR_ code (see enum above) + */ +static int find_emc_tables(const void *blob, int node, int ram_code) +{ + int need_ram_code; + int depth; + int offset; + + /* If we are using RAM codes, scan through the tables for our code */ + need_ram_code = fdtdec_get_bool(blob, node, "nvidia,use-ram-code"); + if (!need_ram_code) + return node; + if (ram_code == -1) { + debug("%s: RAM code required but not supplied\n", __func__); + return ERR_NO_RAM_CODE; + } + + offset = node; + depth = 0; + do { + /* + * Sadly there is no compatible string so we cannot use + * fdtdec_next_compatible_subnode(). + */ + offset = fdt_next_node(blob, offset, &depth); + if (depth <= 0) + break; + + /* Make sure this is a direct subnode */ + if (depth != 1) + continue; + if (strcmp("emc-tables", fdt_get_name(blob, offset, NULL))) + continue; + + if (fdtdec_get_int(blob, offset, "nvidia,ram-code", -1) + == ram_code) + return offset; + } while (1); + + debug("%s: Could not find tables for RAM code %d\n", __func__, + ram_code); + return ERR_RAM_CODE_NOT_FOUND; +} + +/** + * Decode the EMC node of the device tree, returning a pointer to the emc + * controller and the table to be used for the given rate. + * + * @param blob Device tree blob + * @param rate Clock speed of memory controller in Hz (=2x memory bus rate) + * @param emcp Returns address of EMC controller registers + * @param tablep Returns pointer to table to program into EMC. There are + * TEGRA_EMC_NUM_REGS entries, destined for offsets as per the + * emc_reg_addr array. + * @return 0 if ok, otherwise a -ve error code which will allow someone to + * figure out roughly what went wrong by looking at this code. + */ +static int decode_emc(const void *blob, unsigned rate, struct emc_ctlr **emcp, + const u32 **tablep) +{ + struct apb_misc_pp_ctlr *pp = + (struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE; + int ram_code; + int depth; + int node; + + ram_code = (readl(&pp->strapping_opt_a) & RAM_CODE_MASK) + >> RAM_CODE_SHIFT; + /* + * The EMC clock rate is twice the bus rate, and the bus rate is + * measured in kHz + */ + rate = rate / 2 / 1000; + + node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC); + if (node < 0) { + debug("%s: No EMC node found in FDT\n", __func__); + return ERR_NO_EMC_NODE; + } + *emcp = (struct emc_ctlr *)fdtdec_get_addr(blob, node, "reg"); + if (*emcp == (struct emc_ctlr *)FDT_ADDR_T_NONE) { + debug("%s: No EMC node reg property\n", __func__); + return ERR_NO_EMC_REG; + } + + /* Work out the parent node which contains our EMC tables */ + node = find_emc_tables(blob, node, ram_code & 3); + if (node < 0) + return node; + + depth = 0; + for (;;) { + int node_rate; + + node = fdtdec_next_compatible_subnode(blob, node, + COMPAT_NVIDIA_TEGRA20_EMC_TABLE, &depth); + if (node < 0) + break; + node_rate = fdtdec_get_int(blob, node, "clock-frequency", -1); + if (node_rate == -1) { + debug("%s: Missing clock-frequency\n", __func__); + return ERR_NO_FREQ; /* we expect this property */ + } + + if (node_rate == rate) + break; + } + if (node < 0) { + debug("%s: No node found for clock frequency %d\n", __func__, + rate); + return ERR_FREQ_NOT_FOUND; + } + + *tablep = fdtdec_locate_array(blob, node, "nvidia,emc-registers", + TEGRA_EMC_NUM_REGS); + if (!*tablep) { + debug("%s: node '%s' array missing / wrong size\n", __func__, + fdt_get_name(blob, node, NULL)); + return ERR_BAD_REGS; + } + + /* All seems well */ + return 0; +} + +int tegra_set_emc(const void *blob, unsigned rate) +{ + struct emc_ctlr *emc; + const u32 *table = NULL; + int err, i; + + err = decode_emc(blob, rate, &emc, &table); + if (err) { + debug("Warning: no valid EMC (%d), memory timings unset\n", + err); + return err; + } + + debug("%s: Table found, setting EMC values as follows:\n", __func__); + for (i = 0; i < TEGRA_EMC_NUM_REGS; i++) { + u32 value = fdt32_to_cpu(table[i]); + u32 addr = (uintptr_t)emc + emc_reg_addr[i]; + + debug(" %#x: %#x\n", addr, value); + writel(value, addr); + } + + /* trigger emc with new settings */ + clock_adjust_periph_pll_div(PERIPH_ID_EMC, CLOCK_ID_MEMORY, + clock_get_rate(CLOCK_ID_MEMORY), NULL); + debug("EMC clock set to %lu\n", + clock_get_periph_rate(PERIPH_ID_EMC, CLOCK_ID_MEMORY)); + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/funcmux.c b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/funcmux.c new file mode 100644 index 000000000..0df4a0738 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/funcmux.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* Tegra20 high-level function multiplexing */ +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/pinmux.h> + +/* + * The PINMUX macro is used to set up pinmux tables. + */ +#define PINMUX(grp, mux, pupd, tri) \ + {PMUX_PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri} + +static const struct pmux_pingrp_config disp1_default[] = { + PINMUX(LDI, DISPA, NORMAL, NORMAL), + PINMUX(LHP0, DISPA, NORMAL, NORMAL), + PINMUX(LHP1, DISPA, NORMAL, NORMAL), + PINMUX(LHP2, DISPA, NORMAL, NORMAL), + PINMUX(LHS, DISPA, NORMAL, NORMAL), + PINMUX(LM0, RSVD4, NORMAL, NORMAL), + PINMUX(LPP, DISPA, NORMAL, NORMAL), + PINMUX(LPW0, DISPA, NORMAL, NORMAL), + PINMUX(LPW2, DISPA, NORMAL, NORMAL), + PINMUX(LSC0, DISPA, NORMAL, NORMAL), + PINMUX(LSPI, DISPA, NORMAL, NORMAL), + PINMUX(LVP1, DISPA, NORMAL, NORMAL), + PINMUX(LVS, DISPA, NORMAL, NORMAL), + PINMUX(SLXD, SPDIF, NORMAL, NORMAL), +}; + + +int funcmux_select(enum periph_id id, int config) +{ + int bad_config = config != FUNCMUX_DEFAULT; + + switch (id) { + case PERIPH_ID_UART1: + switch (config) { + case FUNCMUX_UART1_IRRX_IRTX: + pinmux_set_func(PMUX_PINGRP_IRRX, PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_IRTX, PMUX_FUNC_UARTA); + pinmux_tristate_disable(PMUX_PINGRP_IRRX); + pinmux_tristate_disable(PMUX_PINGRP_IRTX); + break; + case FUNCMUX_UART1_UAA_UAB: + pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_UARTA); + pinmux_tristate_disable(PMUX_PINGRP_UAA); + pinmux_tristate_disable(PMUX_PINGRP_UAB); + bad_config = 0; + break; + case FUNCMUX_UART1_GPU: + pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA); + pinmux_tristate_disable(PMUX_PINGRP_GPU); + bad_config = 0; + break; + case FUNCMUX_UART1_SDIO1: + pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA); + pinmux_tristate_disable(PMUX_PINGRP_SDIO1); + bad_config = 0; + break; + } + if (!bad_config) { + /* + * Tegra appears to boot with function UARTA pre- + * selected on mux group SDB. If two mux groups are + * both set to the same function, it's unclear which + * group's pins drive the RX signals into the HW. + * For UARTA, SDB certainly overrides group IRTX in + * practice. To solve this, configure some alternative + * function on SDB to avoid the conflict. Also, tri- + * state the group to avoid driving any signal onto it + * until we know what's connected. + */ + pinmux_tristate_enable(PMUX_PINGRP_SDB); + pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3); + } + break; + + case PERIPH_ID_UART2: + if (config == FUNCMUX_UART2_UAD) { + pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB); + pinmux_tristate_disable(PMUX_PINGRP_UAD); + } + break; + + case PERIPH_ID_UART4: + if (config == FUNCMUX_UART4_GMC) { + pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD); + pinmux_tristate_disable(PMUX_PINGRP_GMC); + } + break; + + case PERIPH_ID_DVC_I2C: + /* there is only one selection, pinmux_config is ignored */ + if (config == FUNCMUX_DVC_I2CP) { + pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C); + pinmux_tristate_disable(PMUX_PINGRP_I2CP); + } + break; + + case PERIPH_ID_I2C1: + /* support pinmux_config of 0 for now, */ + if (config == FUNCMUX_I2C1_RM) { + pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C); + pinmux_tristate_disable(PMUX_PINGRP_RM); + } + break; + case PERIPH_ID_I2C2: /* I2C2 */ + switch (config) { + case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */ + pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2); + /* PTA to HDMI */ + pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI); + pinmux_tristate_disable(PMUX_PINGRP_DDC); + break; + case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */ + pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2); + /* set DDC_SEL to RSVDx (RSVD2 works for now) */ + pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2); + pinmux_tristate_disable(PMUX_PINGRP_PTA); + bad_config = 0; + break; + } + break; + case PERIPH_ID_I2C3: /* I2C3 */ + /* support pinmux_config of 0 for now */ + if (config == FUNCMUX_I2C3_DTF) { + pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3); + pinmux_tristate_disable(PMUX_PINGRP_DTF); + } + break; + + case PERIPH_ID_SDMMC1: + if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) { + pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1); + pinmux_tristate_disable(PMUX_PINGRP_SDIO1); + } + break; + + case PERIPH_ID_SDMMC2: + if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) { + pinmux_set_func(PMUX_PINGRP_DTA, PMUX_FUNC_SDIO2); + pinmux_set_func(PMUX_PINGRP_DTD, PMUX_FUNC_SDIO2); + + pinmux_tristate_disable(PMUX_PINGRP_DTA); + pinmux_tristate_disable(PMUX_PINGRP_DTD); + } + break; + + case PERIPH_ID_SDMMC3: + switch (config) { + case FUNCMUX_SDMMC3_SDB_SLXA_8BIT: + pinmux_set_func(PMUX_PINGRP_SLXA, PMUX_FUNC_SDIO3); + pinmux_set_func(PMUX_PINGRP_SLXC, PMUX_FUNC_SDIO3); + pinmux_set_func(PMUX_PINGRP_SLXD, PMUX_FUNC_SDIO3); + pinmux_set_func(PMUX_PINGRP_SLXK, PMUX_FUNC_SDIO3); + + pinmux_tristate_disable(PMUX_PINGRP_SLXA); + pinmux_tristate_disable(PMUX_PINGRP_SLXC); + pinmux_tristate_disable(PMUX_PINGRP_SLXD); + pinmux_tristate_disable(PMUX_PINGRP_SLXK); + /* fall through */ + + case FUNCMUX_SDMMC3_SDB_4BIT: + pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3); + pinmux_set_func(PMUX_PINGRP_SDC, PMUX_FUNC_SDIO3); + pinmux_set_func(PMUX_PINGRP_SDD, PMUX_FUNC_SDIO3); + + pinmux_tristate_disable(PMUX_PINGRP_SDB); + pinmux_tristate_disable(PMUX_PINGRP_SDC); + pinmux_tristate_disable(PMUX_PINGRP_SDD); + bad_config = 0; + break; + } + break; + + case PERIPH_ID_SDMMC4: + switch (config) { + case FUNCMUX_SDMMC4_ATC_ATD_8BIT: + pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_SDIO4); + pinmux_set_func(PMUX_PINGRP_ATD, PMUX_FUNC_SDIO4); + + pinmux_tristate_disable(PMUX_PINGRP_ATC); + pinmux_tristate_disable(PMUX_PINGRP_ATD); + break; + + case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT: + pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4); + pinmux_tristate_disable(PMUX_PINGRP_GME); + /* fall through */ + + case FUNCMUX_SDMMC4_ATB_GMA_4_BIT: + pinmux_set_func(PMUX_PINGRP_ATB, PMUX_FUNC_SDIO4); + pinmux_set_func(PMUX_PINGRP_GMA, PMUX_FUNC_SDIO4); + + pinmux_tristate_disable(PMUX_PINGRP_ATB); + pinmux_tristate_disable(PMUX_PINGRP_GMA); + bad_config = 0; + break; + } + break; + + case PERIPH_ID_KBC: + if (config == FUNCMUX_DEFAULT) { + enum pmux_pingrp grp[] = {PMUX_PINGRP_KBCA, + PMUX_PINGRP_KBCB, PMUX_PINGRP_KBCC, + PMUX_PINGRP_KBCD, PMUX_PINGRP_KBCE, + PMUX_PINGRP_KBCF}; + int i; + + for (i = 0; i < ARRAY_SIZE(grp); i++) { + pinmux_tristate_disable(grp[i]); + pinmux_set_func(grp[i], PMUX_FUNC_KBC); + pinmux_set_pullupdown(grp[i], PMUX_PULL_UP); + } + } + break; + + case PERIPH_ID_USB2: + if (config == FUNCMUX_USB2_ULPI) { + pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_ULPI); + pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_ULPI); + pinmux_set_func(PMUX_PINGRP_UDA, PMUX_FUNC_ULPI); + + pinmux_tristate_disable(PMUX_PINGRP_UAA); + pinmux_tristate_disable(PMUX_PINGRP_UAB); + pinmux_tristate_disable(PMUX_PINGRP_UDA); + } + break; + + case PERIPH_ID_SPI1: + if (config == FUNCMUX_SPI1_GMC_GMD) { + pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH); + pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH); + + pinmux_tristate_disable(PMUX_PINGRP_GMC); + pinmux_tristate_disable(PMUX_PINGRP_GMD); + } + break; + + case PERIPH_ID_NDFLASH: + switch (config) { + case FUNCMUX_NDFLASH_ATC: + pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND); + pinmux_tristate_disable(PMUX_PINGRP_ATC); + break; + case FUNCMUX_NDFLASH_KBC_8_BIT: + pinmux_set_func(PMUX_PINGRP_KBCA, PMUX_FUNC_NAND); + pinmux_set_func(PMUX_PINGRP_KBCC, PMUX_FUNC_NAND); + pinmux_set_func(PMUX_PINGRP_KBCD, PMUX_FUNC_NAND); + pinmux_set_func(PMUX_PINGRP_KBCE, PMUX_FUNC_NAND); + pinmux_set_func(PMUX_PINGRP_KBCF, PMUX_FUNC_NAND); + + pinmux_tristate_disable(PMUX_PINGRP_KBCA); + pinmux_tristate_disable(PMUX_PINGRP_KBCC); + pinmux_tristate_disable(PMUX_PINGRP_KBCD); + pinmux_tristate_disable(PMUX_PINGRP_KBCE); + pinmux_tristate_disable(PMUX_PINGRP_KBCF); + + bad_config = 0; + break; + } + break; + case PERIPH_ID_DISP1: + if (config == FUNCMUX_DEFAULT) { + int i; + + for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) { + pinmux_set_func(i, PMUX_FUNC_DISPA); + pinmux_tristate_disable(i); + pinmux_set_pullupdown(i, PMUX_PULL_NORMAL); + } + pinmux_config_pingrp_table(disp1_default, + ARRAY_SIZE(disp1_default)); + } + break; + + default: + debug("%s: invalid periph_id %d", __func__, id); + return -1; + } + + if (bad_config) { + debug("%s: invalid config %d for periph_id %d", __func__, + config, id); + return -1; + } + + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/pinmux.c b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/pinmux.c new file mode 100644 index 000000000..e484f991b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/pinmux.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* Tegra20 pin multiplexing functions */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +/* + * This defines the order of the pin mux control bits in the registers. For + * some reason there is no correspendence between the tristate, pin mux and + * pullup/pulldown registers. + */ +enum pmux_ctlid { + /* 0: APB_MISC_PP_PIN_MUX_CTL_A_0 */ + MUXCTL_UAA, + MUXCTL_UAB, + MUXCTL_UAC, + MUXCTL_UAD, + MUXCTL_UDA, + MUXCTL_RESERVED5, + MUXCTL_ATE, + MUXCTL_RM, + + MUXCTL_ATB, + MUXCTL_RESERVED9, + MUXCTL_ATD, + MUXCTL_ATC, + MUXCTL_ATA, + MUXCTL_KBCF, + MUXCTL_KBCE, + MUXCTL_SDMMC1, + + /* 16: APB_MISC_PP_PIN_MUX_CTL_B_0 */ + MUXCTL_GMA, + MUXCTL_GMC, + MUXCTL_HDINT, + MUXCTL_SLXA, + MUXCTL_OWC, + MUXCTL_SLXC, + MUXCTL_SLXD, + MUXCTL_SLXK, + + MUXCTL_UCA, + MUXCTL_UCB, + MUXCTL_DTA, + MUXCTL_DTB, + MUXCTL_RESERVED28, + MUXCTL_DTC, + MUXCTL_DTD, + MUXCTL_DTE, + + /* 32: APB_MISC_PP_PIN_MUX_CTL_C_0 */ + MUXCTL_DDC, + MUXCTL_CDEV1, + MUXCTL_CDEV2, + MUXCTL_CSUS, + MUXCTL_I2CP, + MUXCTL_KBCA, + MUXCTL_KBCB, + MUXCTL_KBCC, + + MUXCTL_IRTX, + MUXCTL_IRRX, + MUXCTL_DAP1, + MUXCTL_DAP2, + MUXCTL_DAP3, + MUXCTL_DAP4, + MUXCTL_GMB, + MUXCTL_GMD, + + /* 48: APB_MISC_PP_PIN_MUX_CTL_D_0 */ + MUXCTL_GME, + MUXCTL_GPV, + MUXCTL_GPU, + MUXCTL_SPDO, + MUXCTL_SPDI, + MUXCTL_SDB, + MUXCTL_SDC, + MUXCTL_SDD, + + MUXCTL_SPIH, + MUXCTL_SPIG, + MUXCTL_SPIF, + MUXCTL_SPIE, + MUXCTL_SPID, + MUXCTL_SPIC, + MUXCTL_SPIB, + MUXCTL_SPIA, + + /* 64: APB_MISC_PP_PIN_MUX_CTL_E_0 */ + MUXCTL_LPW0, + MUXCTL_LPW1, + MUXCTL_LPW2, + MUXCTL_LSDI, + MUXCTL_LSDA, + MUXCTL_LSPI, + MUXCTL_LCSN, + MUXCTL_LDC, + + MUXCTL_LSCK, + MUXCTL_LSC0, + MUXCTL_LSC1, + MUXCTL_LHS, + MUXCTL_LVS, + MUXCTL_LM0, + MUXCTL_LM1, + MUXCTL_LVP0, + + /* 80: APB_MISC_PP_PIN_MUX_CTL_F_0 */ + MUXCTL_LD0, + MUXCTL_LD1, + MUXCTL_LD2, + MUXCTL_LD3, + MUXCTL_LD4, + MUXCTL_LD5, + MUXCTL_LD6, + MUXCTL_LD7, + + MUXCTL_LD8, + MUXCTL_LD9, + MUXCTL_LD10, + MUXCTL_LD11, + MUXCTL_LD12, + MUXCTL_LD13, + MUXCTL_LD14, + MUXCTL_LD15, + + /* 96: APB_MISC_PP_PIN_MUX_CTL_G_0 */ + MUXCTL_LD16, + MUXCTL_LD17, + MUXCTL_LHP1, + MUXCTL_LHP2, + MUXCTL_LVP1, + MUXCTL_LHP0, + MUXCTL_RESERVED102, + MUXCTL_LPP, + + MUXCTL_LDI, + MUXCTL_PMC, + MUXCTL_CRTP, + MUXCTL_PTA, + MUXCTL_RESERVED108, + MUXCTL_KBCD, + MUXCTL_GPU7, + MUXCTL_DTF, + + MUXCTL_NONE = -1, +}; + +/* + * And this defines the order of the pullup/pulldown controls which are again + * in a different order + */ +enum pmux_pullid { + /* 0: APB_MISC_PP_PULLUPDOWN_REG_A_0 */ + PUCTL_ATA, + PUCTL_ATB, + PUCTL_ATC, + PUCTL_ATD, + PUCTL_ATE, + PUCTL_DAP1, + PUCTL_DAP2, + PUCTL_DAP3, + + PUCTL_DAP4, + PUCTL_DTA, + PUCTL_DTB, + PUCTL_DTC, + PUCTL_DTD, + PUCTL_DTE, + PUCTL_DTF, + PUCTL_GPV, + + /* 16: APB_MISC_PP_PULLUPDOWN_REG_B_0 */ + PUCTL_RM, + PUCTL_I2CP, + PUCTL_PTA, + PUCTL_GPU7, + PUCTL_KBCA, + PUCTL_KBCB, + PUCTL_KBCC, + PUCTL_KBCD, + + PUCTL_SPDI, + PUCTL_SPDO, + PUCTL_GPSLXAU, + PUCTL_CRTP, + PUCTL_SLXC, + PUCTL_SLXD, + PUCTL_SLXK, + + /* 32: APB_MISC_PP_PULLUPDOWN_REG_C_0 */ + PUCTL_CDEV1, + PUCTL_CDEV2, + PUCTL_SPIA, + PUCTL_SPIB, + PUCTL_SPIC, + PUCTL_SPID, + PUCTL_SPIE, + PUCTL_SPIF, + + PUCTL_SPIG, + PUCTL_SPIH, + PUCTL_IRTX, + PUCTL_IRRX, + PUCTL_GME, + PUCTL_RESERVED45, + PUCTL_XM2D, + PUCTL_XM2C, + + /* 48: APB_MISC_PP_PULLUPDOWN_REG_D_0 */ + PUCTL_UAA, + PUCTL_UAB, + PUCTL_UAC, + PUCTL_UAD, + PUCTL_UCA, + PUCTL_UCB, + PUCTL_LD17, + PUCTL_LD19_18, + + PUCTL_LD21_20, + PUCTL_LD23_22, + PUCTL_LS, + PUCTL_LC, + PUCTL_CSUS, + PUCTL_DDRC, + PUCTL_SDC, + PUCTL_SDD, + + /* 64: APB_MISC_PP_PULLUPDOWN_REG_E_0 */ + PUCTL_KBCF, + PUCTL_KBCE, + PUCTL_PMCA, + PUCTL_PMCB, + PUCTL_PMCC, + PUCTL_PMCD, + PUCTL_PMCE, + PUCTL_CK32, + + PUCTL_UDA, + PUCTL_SDMMC1, + PUCTL_GMA, + PUCTL_GMB, + PUCTL_GMC, + PUCTL_GMD, + PUCTL_DDC, + PUCTL_OWC, + + PUCTL_NONE = -1 +}; + +/* Convenient macro for defining pin group properties */ +#define PINALL(pingrp, f0, f1, f2, f3, mux, pupd) \ + { \ + .funcs = { \ + PMUX_FUNC_ ## f0, \ + PMUX_FUNC_ ## f1, \ + PMUX_FUNC_ ## f2, \ + PMUX_FUNC_ ## f3, \ + }, \ + .ctl_id = mux, \ + .pull_id = pupd \ + } + +/* A normal pin group where the mux name and pull-up name match */ +#define PIN(pingrp, f0, f1, f2, f3) \ + PINALL(pingrp, f0, f1, f2, f3, MUXCTL_##pingrp, PUCTL_##pingrp) + +/* A pin group where the pull-up name doesn't have a 1-1 mapping */ +#define PINP(pingrp, f0, f1, f2, f3, pupd) \ + PINALL(pingrp, f0, f1, f2, f3, MUXCTL_##pingrp, PUCTL_##pupd) + +/* A pin group number which is not used */ +#define PIN_RESERVED \ + PIN(NONE, RSVD1, RSVD2, RSVD3, RSVD4) + +#define DRVGRP(drvgrp) \ + PINALL(drvgrp, RSVD1, RSVD2, RSVD3, RSVD4, MUXCTL_NONE, PUCTL_NONE) + +static const struct pmux_pingrp_desc tegra20_pingroups[] = { + PIN(ATA, IDE, NAND, GMI, RSVD4), + PIN(ATB, IDE, NAND, GMI, SDIO4), + PIN(ATC, IDE, NAND, GMI, SDIO4), + PIN(ATD, IDE, NAND, GMI, SDIO4), + PIN(CDEV1, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC), + PIN(CDEV2, OSC, AHB_CLK, APB_CLK, PLLP_OUT4), + PIN(CSUS, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK), + PIN(DAP1, DAP1, RSVD2, GMI, SDIO2), + + PIN(DAP2, DAP2, TWC, RSVD3, GMI), + PIN(DAP3, DAP3, RSVD2, RSVD3, RSVD4), + PIN(DAP4, DAP4, RSVD2, GMI, RSVD4), + PIN(DTA, RSVD1, SDIO2, VI, RSVD4), + PIN(DTB, RSVD1, RSVD2, VI, SPI1), + PIN(DTC, RSVD1, RSVD2, VI, RSVD4), + PIN(DTD, RSVD1, SDIO2, VI, RSVD4), + PIN(DTE, RSVD1, RSVD2, VI, SPI1), + + PINP(GPU, PWM, UARTA, GMI, RSVD4, GPSLXAU), + PIN(GPV, PCIE, RSVD2, RSVD3, RSVD4), + PIN(I2CP, I2C, RSVD2, RSVD3, RSVD4), + PIN(IRTX, UARTA, UARTB, GMI, SPI4), + PIN(IRRX, UARTA, UARTB, GMI, SPI4), + PIN(KBCB, KBC, NAND, SDIO2, MIO), + PIN(KBCA, KBC, NAND, SDIO2, EMC_TEST0_DLL), + PINP(PMC, PWR_ON, PWR_INTR, RSVD3, RSVD4, NONE), + + PIN(PTA, I2C2, HDMI, GMI, RSVD4), + PIN(RM, I2C, RSVD2, RSVD3, RSVD4), + PIN(KBCE, KBC, NAND, OWR, RSVD4), + PIN(KBCF, KBC, NAND, TRACE, MIO), + PIN(GMA, UARTE, SPI3, GMI, SDIO4), + PIN(GMC, UARTD, SPI4, GMI, SFLASH), + PIN(SDMMC1, SDIO1, RSVD2, UARTE, UARTA), + PIN(OWC, OWR, RSVD2, RSVD3, RSVD4), + + PIN(GME, RSVD1, DAP5, GMI, SDIO4), + PIN(SDC, PWM, TWC, SDIO3, SPI3), + PIN(SDD, UARTA, PWM, SDIO3, SPI3), + PIN_RESERVED, + PINP(SLXA, PCIE, SPI4, SDIO3, SPI2, CRTP), + PIN(SLXC, SPDIF, SPI4, SDIO3, SPI2), + PIN(SLXD, SPDIF, SPI4, SDIO3, SPI2), + PIN(SLXK, PCIE, SPI4, SDIO3, SPI2), + + PIN(SPDI, SPDIF, RSVD2, I2C, SDIO2), + PIN(SPDO, SPDIF, RSVD2, I2C, SDIO2), + PIN(SPIA, SPI1, SPI2, SPI3, GMI), + PIN(SPIB, SPI1, SPI2, SPI3, GMI), + PIN(SPIC, SPI1, SPI2, SPI3, GMI), + PIN(SPID, SPI2, SPI1, SPI2_ALT, GMI), + PIN(SPIE, SPI2, SPI1, SPI2_ALT, GMI), + PIN(SPIF, SPI3, SPI1, SPI2, RSVD4), + + PIN(SPIG, SPI3, SPI2, SPI2_ALT, I2C), + PIN(SPIH, SPI3, SPI2, SPI2_ALT, I2C), + PIN(UAA, SPI3, MIPI_HS, UARTA, ULPI), + PIN(UAB, SPI2, MIPI_HS, UARTA, ULPI), + PIN(UAC, OWR, RSVD2, RSVD3, RSVD4), + PIN(UAD, UARTB, SPDIF, UARTA, SPI4), + PIN(UCA, UARTC, RSVD2, GMI, RSVD4), + PIN(UCB, UARTC, PWM, GMI, RSVD4), + + PIN_RESERVED, + PIN(ATE, IDE, NAND, GMI, RSVD4), + PIN(KBCC, KBC, NAND, TRACE, EMC_TEST1_DLL), + PIN_RESERVED, + PIN_RESERVED, + PIN(GMB, IDE, NAND, GMI, GMI_INT), + PIN(GMD, RSVD1, NAND, GMI, SFLASH), + PIN(DDC, I2C2, RSVD2, RSVD3, RSVD4), + + /* 64 */ + PINP(LD0, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD1, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD2, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD3, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD4, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD5, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD6, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD7, DISPA, DISPB, XIO, RSVD4, LD17), + + PINP(LD8, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD9, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD10, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD11, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD12, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD13, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD14, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD15, DISPA, DISPB, XIO, RSVD4, LD17), + + PINP(LD16, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD17, DISPA, DISPB, RSVD3, RSVD4, LD17), + PINP(LHP0, DISPA, DISPB, RSVD3, RSVD4, LD21_20), + PINP(LHP1, DISPA, DISPB, RSVD3, RSVD4, LD19_18), + PINP(LHP2, DISPA, DISPB, RSVD3, RSVD4, LD19_18), + PINP(LVP0, DISPA, DISPB, RSVD3, RSVD4, LC), + PINP(LVP1, DISPA, DISPB, RSVD3, RSVD4, LD21_20), + PINP(HDINT, HDMI, RSVD2, RSVD3, RSVD4, LC), + + PINP(LM0, DISPA, DISPB, SPI3, RSVD4, LC), + PINP(LM1, DISPA, DISPB, RSVD3, CRT, LC), + PINP(LVS, DISPA, DISPB, XIO, RSVD4, LC), + PINP(LSC0, DISPA, DISPB, XIO, RSVD4, LC), + PINP(LSC1, DISPA, DISPB, SPI3, HDMI, LS), + PINP(LSCK, DISPA, DISPB, SPI3, HDMI, LS), + PINP(LDC, DISPA, DISPB, RSVD3, RSVD4, LS), + PINP(LCSN, DISPA, DISPB, SPI3, RSVD4, LS), + + /* 96 */ + PINP(LSPI, DISPA, DISPB, XIO, HDMI, LC), + PINP(LSDA, DISPA, DISPB, SPI3, HDMI, LS), + PINP(LSDI, DISPA, DISPB, SPI3, RSVD4, LS), + PINP(LPW0, DISPA, DISPB, SPI3, HDMI, LS), + PINP(LPW1, DISPA, DISPB, RSVD3, RSVD4, LS), + PINP(LPW2, DISPA, DISPB, SPI3, HDMI, LS), + PINP(LDI, DISPA, DISPB, RSVD3, RSVD4, LD23_22), + PINP(LHS, DISPA, DISPB, XIO, RSVD4, LC), + + PINP(LPP, DISPA, DISPB, RSVD3, RSVD4, LD23_22), + PIN_RESERVED, + PIN(KBCD, KBC, NAND, SDIO2, MIO), + PIN(GPU7, RTCK, RSVD2, RSVD3, RSVD4), + PIN(DTF, I2C3, RSVD2, VI, RSVD4), + PIN(UDA, SPI1, RSVD2, UARTD, ULPI), + PIN(CRTP, CRT, RSVD2, RSVD3, RSVD4), + PINP(SDB, UARTA, PWM, SDIO3, SPI2, NONE), + + /* these pin groups only have pullup and pull down control */ + DRVGRP(CK32), + DRVGRP(DDRC), + DRVGRP(PMCA), + DRVGRP(PMCB), + DRVGRP(PMCC), + DRVGRP(PMCD), + DRVGRP(PMCE), + DRVGRP(XM2C), + DRVGRP(XM2D), +}; +const struct pmux_pingrp_desc *tegra_soc_pingroups = tegra20_pingroups; diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/pmu.c b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/pmu.c new file mode 100644 index 000000000..c595f70e9 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/pmu.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010,2011 NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <tps6586x.h> +#include <asm/io.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/ap.h> +#include <asm/arch-tegra/tegra_i2c.h> +#include <asm/arch-tegra/sys_proto.h> + +#define VDD_CORE_NOMINAL_T25 0x17 /* 1.3v */ +#define VDD_CPU_NOMINAL_T25 0x10 /* 1.125v */ + +#define VDD_CORE_NOMINAL_T20 0x16 /* 1.275v */ +#define VDD_CPU_NOMINAL_T20 0x0f /* 1.1v */ + +#define VDD_RELATION 0x02 /* 50mv */ +#define VDD_TRANSITION_STEP 0x06 /* 150mv */ +#define VDD_TRANSITION_RATE 0x06 /* 3.52mv/us */ + +int pmu_set_nominal(void) +{ + int core, cpu, bus; + + /* by default, the table has been filled with T25 settings */ + switch (tegra_get_chip_sku()) { + case TEGRA_SOC_T20: + core = VDD_CORE_NOMINAL_T20; + cpu = VDD_CPU_NOMINAL_T20; + break; + case TEGRA_SOC_T25: + core = VDD_CORE_NOMINAL_T25; + cpu = VDD_CPU_NOMINAL_T25; + break; + default: + debug("%s: Unknown SKU id\n", __func__); + return -1; + } + + bus = tegra_i2c_get_dvc_bus_num(); + if (bus == -1) { + debug("%s: Cannot find DVC I2C bus\n", __func__); + return -1; + } + tps6586x_init(bus); + tps6586x_set_pwm_mode(TPS6586X_PWM_SM1); + return tps6586x_adjust_sm0_sm1(core, cpu, VDD_TRANSITION_STEP, + VDD_TRANSITION_RATE, VDD_RELATION); +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/warmboot.c b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/warmboot.c new file mode 100644 index 000000000..5fdc4bbb5 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/warmboot.c @@ -0,0 +1,372 @@ +/* + * (C) Copyright 2010 - 2011 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/clock.h> +#include <asm/arch/emc.h> +#include <asm/arch/gp_padctrl.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/sdram_param.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/ap.h> +#include <asm/arch-tegra/apb_misc.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/fuse.h> +#include <asm/arch-tegra/warmboot.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_TEGRA_CLOCK_SCALING +#error "You must enable CONFIG_TEGRA_CLOCK_SCALING to use CONFIG_TEGRA_LP0" +#endif + +/* + * This is the place in SRAM where the SDRAM parameters are stored. There + * are 4 blocks, one for each RAM code + */ +#define SDRAM_PARAMS_BASE (NV_PA_BASE_SRAM + 0x188) + +/* TODO: If we later add support for the Misc GP controller, refactor this */ +union xm2cfga_reg { + struct { + u32 reserved0:2; + u32 hsm_en:1; + u32 reserved1:2; + u32 preemp_en:1; + u32 vref_en:1; + u32 reserved2:5; + u32 cal_drvdn:5; + u32 reserved3:3; + u32 cal_drvup:5; + u32 reserved4:3; + u32 cal_drvdn_slwr:2; + u32 cal_drvup_slwf:2; + }; + u32 word; +}; + +union xm2cfgd_reg { + struct { + u32 reserved0:2; + u32 hsm_en:1; + u32 schmt_en:1; + u32 lpmd:2; + u32 vref_en:1; + u32 reserved1:5; + u32 cal_drvdn:5; + u32 reserved2:3; + u32 cal_drvup:5; + u32 reserved3:3; + u32 cal_drvdn_slwr:2; + u32 cal_drvup_slwf:2; + }; + u32 word; +}; + +/* + * TODO: This register is not documented in the TRM yet. We could move this + * into the EMC and give it a proper interface, but not while it is + * undocumented. + */ +union fbio_spare_reg { + struct { + u32 reserved:24; + u32 cfg_wb0:8; + }; + u32 word; +}; + +/* We pack the resume information into these unions for later */ +union scratch2_reg { + struct { + u32 pllm_base_divm:5; + u32 pllm_base_divn:10; + u32 pllm_base_divp:3; + u32 pllm_misc_lfcon:4; + u32 pllm_misc_cpcon:4; + u32 gp_xm2cfga_padctrl_preemp:1; + u32 gp_xm2cfgd_padctrl_schmt:1; + u32 osc_ctrl_xobp:1; + u32 memory_type:3; + }; + u32 word; +}; + +union scratch4_reg { + struct { + u32 emc_clock_divider:8; + u32 pllm_stable_time:8; + u32 pllx_stable_time:8; + u32 emc_fbio_spare_cfg_wb0:8; + }; + u32 word; +}; + +union scratch24_reg { + struct { + u32 emc_auto_cal_wait:8; + u32 emc_pin_program_wait:8; + u32 warmboot_wait:8; + u32 reserved:8; + }; + u32 word; +}; + +int warmboot_save_sdram_params(void) +{ + u32 ram_code; + struct sdram_params sdram; + struct apb_misc_pp_ctlr *apb_misc = + (struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE; + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + struct apb_misc_gp_ctlr *gp = + (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; + struct emc_ctlr *emc = emc_get_controller(gd->fdt_blob); + union scratch2_reg scratch2; + union scratch4_reg scratch4; + union scratch24_reg scratch24; + union xm2cfga_reg xm2cfga; + union xm2cfgd_reg xm2cfgd; + union fbio_spare_reg fbio_spare; + + /* get ram code that is used as index to array sdram_params in BCT */ + ram_code = (readl(&apb_misc->strapping_opt_a) >> + STRAP_OPT_A_RAM_CODE_SHIFT) & 3; + memcpy(&sdram, + (char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code), + sizeof(sdram)); + + xm2cfga.word = readl(&gp->xm2cfga); + xm2cfgd.word = readl(&gp->xm2cfgd); + + scratch2.word = 0; + scratch2.osc_ctrl_xobp = clock_get_osc_bypass(); + + /* Get the memory PLL settings */ + { + u32 divm, divn, divp, cpcon, lfcon; + + if (clock_ll_read_pll(CLOCK_ID_MEMORY, &divm, &divn, &divp, + &cpcon, &lfcon)) + return -1; + scratch2.pllm_base_divm = divm; + scratch2.pllm_base_divn = divn; + scratch2.pllm_base_divp = divp; + scratch2.pllm_misc_cpcon = cpcon; + scratch2.pllm_misc_lfcon = lfcon; + } + + scratch2.gp_xm2cfga_padctrl_preemp = xm2cfga.preemp_en; + scratch2.gp_xm2cfgd_padctrl_schmt = xm2cfgd.schmt_en; + scratch2.memory_type = sdram.memory_type; + writel(scratch2.word, &pmc->pmc_scratch2); + + /* collect data from various sources for pmc_scratch4 */ + fbio_spare.word = readl(&emc->fbio_spare); + scratch4.word = 0; + scratch4.emc_fbio_spare_cfg_wb0 = fbio_spare.cfg_wb0; + scratch4.emc_clock_divider = sdram.emc_clock_divider; + scratch4.pllm_stable_time = -1; + scratch4.pllx_stable_time = -1; + writel(scratch4.word, &pmc->pmc_scratch4); + + /* collect various data from sdram for pmc_scratch24 */ + scratch24.word = 0; + scratch24.emc_pin_program_wait = sdram.emc_pin_program_wait; + scratch24.emc_auto_cal_wait = sdram.emc_auto_cal_wait; + scratch24.warmboot_wait = sdram.warm_boot_wait; + writel(scratch24.word, &pmc->pmc_scratch24); + + return 0; +} + +static u32 get_major_version(void) +{ + u32 major_id; + struct apb_misc_gp_ctlr *gp = + (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; + + major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >> + HIDREV_MAJORPREV_SHIFT; + return major_id; +} + +static int is_production_mode_fuse_set(struct fuse_regs *fuse) +{ + return readl(&fuse->production_mode); +} + +static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse) +{ + return readl(&fuse->security_mode); +} + +static int is_failure_analysis_mode(struct fuse_regs *fuse) +{ + return readl(&fuse->fa); +} + +static int ap20_is_odm_production_mode(void) +{ + struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; + + if (!is_failure_analysis_mode(fuse) && + is_odm_production_mode_fuse_set(fuse)) + return 1; + else + return 0; +} + +static int ap20_is_production_mode(void) +{ + struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; + + if (get_major_version() == 0) + return 1; + + if (!is_failure_analysis_mode(fuse) && + is_production_mode_fuse_set(fuse) && + !is_odm_production_mode_fuse_set(fuse)) + return 1; + else + return 0; +} + +static enum fuse_operating_mode fuse_get_operation_mode(void) +{ + u32 chip_id; + struct apb_misc_gp_ctlr *gp = + (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; + + chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> + HIDREV_CHIPID_SHIFT; + if (chip_id == CHIPID_TEGRA20) { + if (ap20_is_odm_production_mode()) { + printf("!! odm_production_mode is not supported !!\n"); + return MODE_UNDEFINED; + } else + if (ap20_is_production_mode()) + return MODE_PRODUCTION; + else + return MODE_UNDEFINED; + } + return MODE_UNDEFINED; +} + +static void determine_crypto_options(int *is_encrypted, int *is_signed, + int *use_zero_key) +{ + switch (fuse_get_operation_mode()) { + case MODE_PRODUCTION: + *is_encrypted = 0; + *is_signed = 1; + *use_zero_key = 1; + break; + case MODE_UNDEFINED: + default: + *is_encrypted = 0; + *is_signed = 0; + *use_zero_key = 0; + break; + } +} + +static int sign_wb_code(u32 start, u32 length, int use_zero_key) +{ + int err; + u8 *source; /* Pointer to source */ + u8 *hash; + + /* Calculate AES block parameters. */ + source = (u8 *)(start + offsetof(struct wb_header, random_aes_block)); + length -= offsetof(struct wb_header, random_aes_block); + hash = (u8 *)(start + offsetof(struct wb_header, hash)); + err = sign_data_block(source, length, hash); + + return err; +} + +int warmboot_prepare_code(u32 seg_address, u32 seg_length) +{ + int err = 0; + u32 length; /* length of the signed/encrypt code */ + struct wb_header *dst_header; /* Pointer to dest WB header */ + int is_encrypted; /* Segment is encrypted */ + int is_signed; /* Segment is signed */ + int use_zero_key; /* Use key of all zeros */ + + /* Determine crypto options. */ + determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key); + + /* Get the actual code limits. */ + length = roundup(((u32)wb_end - (u32)wb_start), 16); + + /* + * The region specified by seg_address must be in SDRAM and must be + * nonzero in length. + */ + if (seg_length == 0 || seg_address < NV_PA_SDRAM_BASE || + seg_address + seg_length >= NV_PA_SDRAM_BASE + gd->ram_size) { + err = -EFAULT; + goto fail; + } + + /* Things must be 16-byte aligned. */ + if ((seg_length & 0xF) || (seg_address & 0xF)) { + err = -EINVAL; + goto fail; + } + + /* Will the code fit? (destination includes wb_header + wb code) */ + if (seg_length < (length + sizeof(struct wb_header))) { + err = -EINVAL; + goto fail; + } + + dst_header = (struct wb_header *)seg_address; + memset((char *)dst_header, 0, sizeof(struct wb_header)); + + /* Populate the random_aes_block as requested. */ + { + u32 *aes_block = (u32 *)&(dst_header->random_aes_block); + u32 *end = (u32 *)(((u32)aes_block) + + sizeof(dst_header->random_aes_block)); + + do { + *aes_block++ = 0; + } while (aes_block < end); + } + + /* Populate the header. */ + dst_header->length_insecure = length + sizeof(struct wb_header); + dst_header->length_secure = length + sizeof(struct wb_header); + dst_header->destination = NV_WB_RUN_ADDRESS; + dst_header->entry_point = NV_WB_RUN_ADDRESS; + dst_header->code_length = length; + + if (is_encrypted) { + printf("!!!! Encryption is not supported !!!!\n"); + dst_header->length_insecure = 0; + err = -EACCES; + goto fail; + } else + /* copy the wb code directly following dst_header. */ + memcpy((char *)(dst_header+1), (char *)wb_start, length); + + if (is_signed) + err = sign_wb_code(seg_address, dst_header->length_insecure, + use_zero_key); + +fail: + if (err) + printf("Warning: warmboot code copy failed (error=%d)\n", err); + + return err; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/warmboot_avp.c b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/warmboot_avp.c new file mode 100644 index 000000000..27ce5f480 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/warmboot_avp.c @@ -0,0 +1,236 @@ +/* + * (C) Copyright 2010 - 2011 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/flow.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/ap.h> +#include <asm/arch-tegra/apb_misc.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/warmboot.h> +#include "warmboot_avp.h" + +#define DEBUG_RESET_CORESIGHT + +void wb_start(void) +{ + struct apb_misc_pp_ctlr *apb_misc = + (struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE; + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + union osc_ctrl_reg osc_ctrl; + union pllx_base_reg pllx_base; + union pllx_misc_reg pllx_misc; + union scratch3_reg scratch3; + u32 reg; + + /* enable JTAG & TBE */ + writel(CONFIG_CTL_TBE | CONFIG_CTL_JTAG, &apb_misc->cfg_ctl); + + /* Are we running where we're supposed to be? */ + asm volatile ( + "adr %0, wb_start;" /* reg: wb_start address */ + : "=r"(reg) /* output */ + /* no input, no clobber list */ + ); + + if (reg != NV_WB_RUN_ADDRESS) + goto do_reset; + + /* Are we running with AVP? */ + if (readl(NV_PA_PG_UP_BASE + PG_UP_TAG_0) != PG_UP_TAG_AVP) + goto do_reset; + +#ifdef DEBUG_RESET_CORESIGHT + /* Assert CoreSight reset */ + reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]); + reg |= SWR_CSITE_RST; + writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]); +#endif + + /* TODO: Set the drive strength - maybe make this a board parameter? */ + osc_ctrl.word = readl(&clkrst->crc_osc_ctrl); + osc_ctrl.xofs = 4; + osc_ctrl.xoe = 1; + writel(osc_ctrl.word, &clkrst->crc_osc_ctrl); + + /* Power up the CPU complex if necessary */ + if (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU)) { + reg = PWRGATE_TOGGLE_PARTID_CPU | PWRGATE_TOGGLE_START; + writel(reg, &pmc->pmc_pwrgate_toggle); + while (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU)) + ; + } + + /* Remove the I/O clamps from the CPU power partition. */ + reg = readl(&pmc->pmc_remove_clamping); + reg |= CPU_CLMP; + writel(reg, &pmc->pmc_remove_clamping); + + reg = EVENT_ZERO_VAL_20 | EVENT_MSEC | EVENT_MODE_STOP; + writel(reg, &flow->halt_cop_events); + + /* Assert CPU complex reset */ + reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]); + reg |= CPU_RST; + writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]); + + /* Hold both CPUs in reset */ + reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_CPURESET1 | CPU_CMPLX_DERESET0 | + CPU_CMPLX_DERESET1 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DBGRESET1; + writel(reg, &clkrst->crc_cpu_cmplx_set); + + /* Halt CPU1 at the flow controller for uni-processor configurations */ + writel(EVENT_MODE_STOP, &flow->halt_cpu1_events); + + /* + * Set the CPU reset vector. SCRATCH41 contains the physical + * address of the CPU-side restoration code. + */ + reg = readl(&pmc->pmc_scratch41); + writel(reg, EXCEP_VECTOR_CPU_RESET_VECTOR); + + /* Select CPU complex clock source */ + writel(CCLK_PLLP_BURST_POLICY, &clkrst->crc_cclk_brst_pol); + + /* Start the CPU0 clock and stop the CPU1 clock */ + reg = CPU_CMPLX_CPU_BRIDGE_CLKDIV_4 | CPU_CMPLX_CPU0_CLK_STP_RUN | + CPU_CMPLX_CPU1_CLK_STP_STOP; + writel(reg, &clkrst->crc_clk_cpu_cmplx); + + /* Enable the CPU complex clock */ + reg = readl(&clkrst->crc_clk_out_enb[TEGRA_DEV_L]); + reg |= CLK_ENB_CPU; + writel(reg, &clkrst->crc_clk_out_enb[TEGRA_DEV_L]); + + /* Make sure the resets were held for at least 2 microseconds */ + reg = readl(TIMER_USEC_CNTR); + while (readl(TIMER_USEC_CNTR) <= (reg + 2)) + ; + +#ifdef DEBUG_RESET_CORESIGHT + /* + * De-assert CoreSight reset. + * NOTE: We're leaving the CoreSight clock on the oscillator for + * now. It will be restored to its original clock source + * when the CPU-side restoration code runs. + */ + reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]); + reg &= ~SWR_CSITE_RST; + writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]); +#endif + + /* Unlock the CPU CoreSight interfaces */ + reg = 0xC5ACCE55; + writel(reg, CSITE_CPU_DBG0_LAR); + writel(reg, CSITE_CPU_DBG1_LAR); + + /* + * Sample the microsecond timestamp again. This is the time we must + * use when returning from LP0 for PLL stabilization delays. + */ + reg = readl(TIMER_USEC_CNTR); + writel(reg, &pmc->pmc_scratch1); + + pllx_base.word = 0; + pllx_misc.word = 0; + scratch3.word = readl(&pmc->pmc_scratch3); + + /* Get the OSC. For 19.2 MHz, use 19 to make the calculations easier */ + reg = (readl(TIMER_USEC_CFG) & USEC_CFG_DIVISOR_MASK) + 1; + + /* + * According to the TRM, for 19.2MHz OSC, the USEC_DIVISOR is 0x5f, and + * USEC_DIVIDEND is 0x04. So, if USEC_DIVISOR > 26, OSC is 19.2 MHz. + * + * reg is used to calculate the pllx freq, which is used to determine if + * to set dccon or not. + */ + if (reg > 26) + reg = 19; + + /* PLLX_BASE.PLLX_DIVM */ + if (scratch3.pllx_base_divm == reg) + reg = 0; + else + reg = 1; + + /* PLLX_BASE.PLLX_DIVN */ + pllx_base.divn = scratch3.pllx_base_divn; + reg = scratch3.pllx_base_divn << reg; + + /* PLLX_BASE.PLLX_DIVP */ + pllx_base.divp = scratch3.pllx_base_divp; + reg = reg >> scratch3.pllx_base_divp; + + pllx_base.bypass = 1; + + /* PLLX_MISC_DCCON must be set for pllx frequency > 600 MHz. */ + if (reg > 600) + pllx_misc.dccon = 1; + + /* PLLX_MISC_LFCON */ + pllx_misc.lfcon = scratch3.pllx_misc_lfcon; + + /* PLLX_MISC_CPCON */ + pllx_misc.cpcon = scratch3.pllx_misc_cpcon; + + writel(pllx_misc.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_misc); + writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); + + pllx_base.enable = 1; + writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); + pllx_base.bypass = 0; + writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); + + writel(0, flow->halt_cpu_events); + + reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DERESET0; + writel(reg, &clkrst->crc_cpu_cmplx_clr); + + reg = PLLM_OUT1_RSTN_RESET_DISABLE | PLLM_OUT1_CLKEN_ENABLE | + PLLM_OUT1_RATIO_VAL_8; + writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out[0]); + + reg = SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 | SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 | + SCLK_SWAKE_RUN_SRC_PLLM_OUT1 | SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 | + SCLK_SYS_STATE_IDLE; + writel(reg, &clkrst->crc_sclk_brst_pol); + + /* avp_resume: no return after the write */ + reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]); + reg &= ~CPU_RST; + writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]); + + /* avp_halt: */ +avp_halt: + reg = EVENT_MODE_STOP | EVENT_JTAG; + writel(reg, flow->halt_cop_events); + goto avp_halt; + +do_reset: + /* + * Execution comes here if something goes wrong. The chip is reset and + * a cold boot is performed. + */ + writel(SWR_TRIG_SYS_RST, &clkrst->crc_rst_dev[TEGRA_DEV_L]); + goto do_reset; +} + +/* + * wb_end() is a dummy function, and must be directly following wb_start(), + * and is used to calculate the size of wb_start(). + */ +void wb_end(void) +{ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/warmboot_avp.h b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/warmboot_avp.h new file mode 100644 index 000000000..7b86acb15 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra20-common/warmboot_avp.h @@ -0,0 +1,65 @@ +/* + * (C) Copyright 2010, 2011 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _WARMBOOT_AVP_H_ +#define _WARMBOOT_AVP_H_ + +#define TEGRA_DEV_L 0 +#define TEGRA_DEV_H 1 +#define TEGRA_DEV_U 2 + +#define SIMPLE_PLLX (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE) +#define SIMPLE_PLLE (CLOCK_ID_EPCI - CLOCK_ID_FIRST_SIMPLE) + +#define TIMER_USEC_CNTR (NV_PA_TMRUS_BASE + 0) +#define TIMER_USEC_CFG (NV_PA_TMRUS_BASE + 4) + +#define USEC_CFG_DIVISOR_MASK 0xffff + +#define CONFIG_CTL_TBE (1 << 7) +#define CONFIG_CTL_JTAG (1 << 6) + +#define CPU_RST (1 << 0) +#define CLK_ENB_CPU (1 << 0) +#define SWR_TRIG_SYS_RST (1 << 2) +#define SWR_CSITE_RST (1 << 9) + +#define PWRGATE_STATUS_CPU (1 << 0) +#define PWRGATE_TOGGLE_PARTID_CPU (0 << 0) +#define PWRGATE_TOGGLE_START (1 << 8) + +#define CPU_CMPLX_CPU_BRIDGE_CLKDIV_4 (3 << 0) +#define CPU_CMPLX_CPU0_CLK_STP_STOP (1 << 8) +#define CPU_CMPLX_CPU0_CLK_STP_RUN (0 << 8) +#define CPU_CMPLX_CPU1_CLK_STP_STOP (1 << 9) +#define CPU_CMPLX_CPU1_CLK_STP_RUN (0 << 9) + +#define CPU_CMPLX_CPURESET0 (1 << 0) +#define CPU_CMPLX_CPURESET1 (1 << 1) +#define CPU_CMPLX_DERESET0 (1 << 4) +#define CPU_CMPLX_DERESET1 (1 << 5) +#define CPU_CMPLX_DBGRESET0 (1 << 12) +#define CPU_CMPLX_DBGRESET1 (1 << 13) + +#define PLLM_OUT1_RSTN_RESET_DISABLE (1 << 0) +#define PLLM_OUT1_CLKEN_ENABLE (1 << 1) +#define PLLM_OUT1_RATIO_VAL_8 (8 << 8) + +#define SCLK_SYS_STATE_IDLE (1 << 28) +#define SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 (7 << 12) +#define SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 (7 << 8) +#define SCLK_SWAKE_RUN_SRC_PLLM_OUT1 (7 << 4) +#define SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 (7 << 0) + +#define EVENT_ZERO_VAL_20 (20 << 0) +#define EVENT_MSEC (1 << 24) +#define EVENT_JTAG (1 << 28) +#define EVENT_MODE_STOP (2 << 29) + +#define CCLK_PLLP_BURST_POLICY 0x20004444 + +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/Makefile b/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/Makefile new file mode 100644 index 000000000..d2d616e8a --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +obj-y += clock.o funcmux.o pinmux.o diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/clock.c b/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/clock.c new file mode 100644 index 000000000..80ba2d8c1 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/clock.c @@ -0,0 +1,589 @@ +/* + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Tegra30 Clock control functions */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/timer.h> +#include <div64.h> +#include <fdtdec.h> + +/* + * Clock types that we can use as a source. The Tegra30 has muxes for the + * peripheral clocks, and in most cases there are four options for the clock + * source. This gives us a clock 'type' and exploits what commonality exists + * in the device. + * + * Letters are obvious, except for T which means CLK_M, and S which means the + * clock derived from 32KHz. Beware that CLK_M (also called OSC in the + * datasheet) and PLL_M are different things. The former is the basic + * clock supplied to the SOC from an external oscillator. The latter is the + * memory clock PLL. + * + * See definitions in clock_id in the header file. + */ +enum clock_type_id { + CLOCK_TYPE_AXPT, /* PLL_A, PLL_X, PLL_P, CLK_M */ + CLOCK_TYPE_MCPA, /* and so on */ + CLOCK_TYPE_MCPT, + CLOCK_TYPE_PCM, + CLOCK_TYPE_PCMT, + CLOCK_TYPE_PCMT16, + CLOCK_TYPE_PDCT, + CLOCK_TYPE_ACPT, + CLOCK_TYPE_ASPTE, + CLOCK_TYPE_PMDACD2T, + CLOCK_TYPE_PCST, + + CLOCK_TYPE_COUNT, + CLOCK_TYPE_NONE = -1, /* invalid clock type */ +}; + +enum { + CLOCK_MAX_MUX = 8 /* number of source options for each clock */ +}; + +/* + * Clock source mux for each clock type. This just converts our enum into + * a list of mux sources for use by the code. + * + * Note: + * The extra column in each clock source array is used to store the mask + * bits in its register for the source. + */ +#define CLK(x) CLOCK_ID_ ## x +static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX+1] = { + { CLK(AUDIO), CLK(XCPU), CLK(PERIPH), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(AUDIO), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(NONE), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(AUDIO), CLK(CGENERAL), CLK(PERIPH), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_30}, + { CLK(AUDIO), CLK(SFROM32KHZ), CLK(PERIPH), CLK(OSC), + CLK(EPCI), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_29}, + { CLK(PERIPH), CLK(MEMORY), CLK(DISPLAY), CLK(AUDIO), + CLK(CGENERAL), CLK(DISPLAY2), CLK(OSC), CLK(NONE), + MASK_BITS_31_29}, + { CLK(PERIPH), CLK(CGENERAL), CLK(SFROM32KHZ), CLK(OSC), + CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), + MASK_BITS_31_28} +}; + +/* + * Clock type for each peripheral clock source. We put the name in each + * record just so it is easy to match things up + */ +#define TYPE(name, type) type +static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = { + /* 0x00 */ + TYPE(PERIPHC_I2S1, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_I2S2, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_SPDIF_IN, CLOCK_TYPE_PCM), + TYPE(PERIPHC_PWM, CLOCK_TYPE_PCST), /* only PWM uses b29:28 */ + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SBC2, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SBC3, CLOCK_TYPE_PCMT), + + /* 0x08 */ + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_I2C1, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_DVC_I2C, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SBC1, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_DISP1, CLOCK_TYPE_PMDACD2T), + TYPE(PERIPHC_DISP2, CLOCK_TYPE_PMDACD2T), + + /* 0x10 */ + TYPE(PERIPHC_CVE, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SDMMC1, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SDMMC2, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_G3D, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_G2D, CLOCK_TYPE_MCPA), + + /* 0x18 */ + TYPE(PERIPHC_NDFLASH, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SDMMC4, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_VFIR, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_EPP, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_MPE, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_MIPI, CLOCK_TYPE_PCMT), /* MIPI base-band HSI */ + TYPE(PERIPHC_UART1, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_UART2, CLOCK_TYPE_PCMT), + + /* 0x20 */ + TYPE(PERIPHC_HOST1X, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_TVO, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_HDMI, CLOCK_TYPE_PMDACD2T), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT), + TYPE(PERIPHC_I2C2, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPT), + + /* 0x28 */ + TYPE(PERIPHC_UART3, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SBC4, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_I2C3, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PCMT), + + /* 0x30 */ + TYPE(PERIPHC_UART4, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_UART5, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_VDE, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_OWR, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_NOR, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_CSITE, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_I2S0, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + + /* 0x38h */ /* Jumps to reg offset 0x3B0h - new for T30 */ + TYPE(PERIPHC_G3D2, CLOCK_TYPE_MCPA), + TYPE(PERIPHC_MSELECT, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_TSENSOR, CLOCK_TYPE_PCST), /* s/b PCTS */ + TYPE(PERIPHC_I2S3, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_I2S4, CLOCK_TYPE_AXPT), + TYPE(PERIPHC_I2C4, CLOCK_TYPE_PCMT16), + TYPE(PERIPHC_SBC5, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_SBC6, CLOCK_TYPE_PCMT), + + /* 0x40 */ + TYPE(PERIPHC_AUDIO, CLOCK_TYPE_ACPT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_DAM0, CLOCK_TYPE_ACPT), + TYPE(PERIPHC_DAM1, CLOCK_TYPE_ACPT), + TYPE(PERIPHC_DAM2, CLOCK_TYPE_ACPT), + TYPE(PERIPHC_HDA2CODEC2X, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_ACTMON, CLOCK_TYPE_PCST), /* MASK 31:30 */ + TYPE(PERIPHC_EXTPERIPH1, CLOCK_TYPE_ASPTE), + + /* 0x48 */ + TYPE(PERIPHC_EXTPERIPH2, CLOCK_TYPE_ASPTE), + TYPE(PERIPHC_EXTPERIPH3, CLOCK_TYPE_ASPTE), + TYPE(PERIPHC_NANDSPEED, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_I2CSLOW, CLOCK_TYPE_PCST), /* MASK 31:30 */ + TYPE(PERIPHC_SYS, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SPEEDO, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + + /* 0x50 */ + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), + TYPE(PERIPHC_SATAOOB, CLOCK_TYPE_PCMT), /* offset 0x420h */ + TYPE(PERIPHC_SATA, CLOCK_TYPE_PCMT), + TYPE(PERIPHC_HDA, CLOCK_TYPE_PCMT), +}; + +/* + * This array translates a periph_id to a periphc_internal_id + * + * Not present/matched up: + * uint vi_sensor; _VI_SENSOR_0, 0x1A8 + * SPDIF - which is both 0x08 and 0x0c + * + */ +#define NONE(name) (-1) +#define OFFSET(name, value) PERIPHC_ ## name +static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { + /* Low word: 31:0 */ + NONE(CPU), + NONE(COP), + NONE(TRIGSYS), + NONE(RESERVED3), + NONE(RESERVED4), + NONE(TMR), + PERIPHC_UART1, + PERIPHC_UART2, /* and vfir 0x68 */ + + /* 8 */ + NONE(GPIO), + PERIPHC_SDMMC2, + NONE(SPDIF), /* 0x08 and 0x0c, unclear which to use */ + PERIPHC_I2S1, + PERIPHC_I2C1, + PERIPHC_NDFLASH, + PERIPHC_SDMMC1, + PERIPHC_SDMMC4, + + /* 16 */ + NONE(RESERVED16), + PERIPHC_PWM, + PERIPHC_I2S2, + PERIPHC_EPP, + PERIPHC_VI, + PERIPHC_G2D, + NONE(USBD), + NONE(ISP), + + /* 24 */ + PERIPHC_G3D, + NONE(RESERVED25), + PERIPHC_DISP2, + PERIPHC_DISP1, + PERIPHC_HOST1X, + NONE(VCP), + PERIPHC_I2S0, + NONE(CACHE2), + + /* Middle word: 63:32 */ + NONE(MEM), + NONE(AHBDMA), + NONE(APBDMA), + NONE(RESERVED35), + NONE(RESERVED36), + NONE(STAT_MON), + NONE(RESERVED38), + NONE(RESERVED39), + + /* 40 */ + NONE(KFUSE), + PERIPHC_SBC1, + PERIPHC_NOR, + NONE(RESERVED43), + PERIPHC_SBC2, + NONE(RESERVED45), + PERIPHC_SBC3, + PERIPHC_DVC_I2C, + + /* 48 */ + NONE(DSI), + PERIPHC_TVO, /* also CVE 0x40 */ + PERIPHC_MIPI, + PERIPHC_HDMI, + NONE(CSI), + PERIPHC_TVDAC, + PERIPHC_I2C2, + PERIPHC_UART3, + + /* 56 */ + NONE(RESERVED56), + PERIPHC_EMC, + NONE(USB2), + NONE(USB3), + PERIPHC_MPE, + PERIPHC_VDE, + NONE(BSEA), + NONE(BSEV), + + /* Upper word 95:64 */ + PERIPHC_SPEEDO, + PERIPHC_UART4, + PERIPHC_UART5, + PERIPHC_I2C3, + PERIPHC_SBC4, + PERIPHC_SDMMC3, + NONE(PCIE), + PERIPHC_OWR, + + /* 72 */ + NONE(AFI), + PERIPHC_CSITE, + NONE(PCIEXCLK), + NONE(AVPUCQ), + NONE(RESERVED76), + NONE(RESERVED77), + NONE(RESERVED78), + NONE(DTV), + + /* 80 */ + PERIPHC_NANDSPEED, + PERIPHC_I2CSLOW, + NONE(DSIB), + NONE(RESERVED83), + NONE(IRAMA), + NONE(IRAMB), + NONE(IRAMC), + NONE(IRAMD), + + /* 88 */ + NONE(CRAM2), + NONE(RESERVED89), + NONE(MDOUBLER), + NONE(RESERVED91), + NONE(SUSOUT), + NONE(RESERVED93), + NONE(RESERVED94), + NONE(RESERVED95), + + /* V word: 31:0 */ + NONE(CPUG), + NONE(CPULP), + PERIPHC_G3D2, + PERIPHC_MSELECT, + PERIPHC_TSENSOR, + PERIPHC_I2S3, + PERIPHC_I2S4, + PERIPHC_I2C4, + + /* 08 */ + PERIPHC_SBC5, + PERIPHC_SBC6, + PERIPHC_AUDIO, + NONE(APBIF), + PERIPHC_DAM0, + PERIPHC_DAM1, + PERIPHC_DAM2, + PERIPHC_HDA2CODEC2X, + + /* 16 */ + NONE(ATOMICS), + NONE(RESERVED17), + NONE(RESERVED18), + NONE(RESERVED19), + NONE(RESERVED20), + NONE(RESERVED21), + NONE(RESERVED22), + PERIPHC_ACTMON, + + /* 24 */ + NONE(RESERVED24), + NONE(RESERVED25), + NONE(RESERVED26), + NONE(RESERVED27), + PERIPHC_SATA, + PERIPHC_HDA, + NONE(RESERVED30), + NONE(RESERVED31), + + /* W word: 31:0 */ + NONE(HDA2HDMICODEC), + NONE(SATACOLD), + NONE(RESERVED0_PCIERX0), + NONE(RESERVED1_PCIERX1), + NONE(RESERVED2_PCIERX2), + NONE(RESERVED3_PCIERX3), + NONE(RESERVED4_PCIERX4), + NONE(RESERVED5_PCIERX5), + + /* 40 */ + NONE(CEC), + NONE(RESERVED6_PCIE2), + NONE(RESERVED7_EMC), + NONE(RESERVED8_HDMI), + NONE(RESERVED9_SATA), + NONE(RESERVED10_MIPI), + NONE(EX_RESERVED46), + NONE(EX_RESERVED47), +}; + +/* + * Get the oscillator frequency, from the corresponding hardware configuration + * field. Note that T30 supports 3 new higher freqs, but we map back + * to the old T20 freqs. Support for the higher oscillators is TBD. + */ +enum clock_osc_freq clock_get_osc_freq(void) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + reg = readl(&clkrst->crc_osc_ctrl); + reg = (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; + + if (reg & 1) /* one of the newer freqs */ + printf("Warning: OSC_FREQ is unsupported! (%d)\n", reg); + + return reg >> 2; /* Map to most common (T20) freqs */ +} + +/* Returns a pointer to the clock source register for a peripheral */ +u32 *get_periph_source_reg(enum periph_id periph_id) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + enum periphc_internal_id internal_id; + + /* Coresight is a special case */ + if (periph_id == PERIPH_ID_CSI) + return &clkrst->crc_clk_src[PERIPH_ID_CSI+1]; + + assert(periph_id >= PERIPH_ID_FIRST && periph_id < PERIPH_ID_COUNT); + internal_id = periph_id_to_internal_id[periph_id]; + assert(internal_id != -1); + if (internal_id >= PERIPHC_VW_FIRST) { + internal_id -= PERIPHC_VW_FIRST; + return &clkrst->crc_clk_src_vw[internal_id]; + } else + return &clkrst->crc_clk_src[internal_id]; +} + +/** + * Given a peripheral ID and the required source clock, this returns which + * value should be programmed into the source mux for that peripheral. + * + * There is special code here to handle the one source type with 5 sources. + * + * @param periph_id peripheral to start + * @param source PLL id of required parent clock + * @param mux_bits Set to number of bits in mux register: 2 or 4 + * @param divider_bits Set to number of divider bits (8 or 16) + * @return mux value (0-4, or -1 if not found) + */ +int get_periph_clock_source(enum periph_id periph_id, + enum clock_id parent, int *mux_bits, int *divider_bits) +{ + enum clock_type_id type; + enum periphc_internal_id internal_id; + int mux; + + assert(clock_periph_id_isvalid(periph_id)); + + internal_id = periph_id_to_internal_id[periph_id]; + assert(periphc_internal_id_isvalid(internal_id)); + + type = clock_periph_type[internal_id]; + assert(clock_type_id_isvalid(type)); + + *mux_bits = clock_source[type][CLOCK_MAX_MUX]; + + if (type == CLOCK_TYPE_PCMT16) + *divider_bits = 16; + else + *divider_bits = 8; + + for (mux = 0; mux < CLOCK_MAX_MUX; mux++) + if (clock_source[type][mux] == parent) + return mux; + + /* if we get here, either us or the caller has made a mistake */ + printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id, + parent); + return -1; +} + +void clock_set_enable(enum periph_id periph_id, int enable) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 *clk; + u32 reg; + + /* Enable/disable the clock to this peripheral */ + assert(clock_periph_id_isvalid(periph_id)); + if ((int)periph_id < (int)PERIPH_ID_VW_FIRST) + clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)]; + else + clk = &clkrst->crc_clk_out_enb_vw[PERIPH_REG(periph_id)]; + reg = readl(clk); + if (enable) + reg |= PERIPH_MASK(periph_id); + else + reg &= ~PERIPH_MASK(periph_id); + writel(reg, clk); +} + +void reset_set_enable(enum periph_id periph_id, int enable) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 *reset; + u32 reg; + + /* Enable/disable reset to the peripheral */ + assert(clock_periph_id_isvalid(periph_id)); + if (periph_id < PERIPH_ID_VW_FIRST) + reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)]; + else + reset = &clkrst->crc_rst_dev_vw[PERIPH_REG(periph_id)]; + reg = readl(reset); + if (enable) + reg |= PERIPH_MASK(periph_id); + else + reg &= ~PERIPH_MASK(periph_id); + writel(reg, reset); +} + +#ifdef CONFIG_OF_CONTROL +/* + * Convert a device tree clock ID to our peripheral ID. They are mostly + * the same but we are very cautious so we check that a valid clock ID is + * provided. + * + * @param clk_id Clock ID according to tegra30 device tree binding + * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid + */ +enum periph_id clk_id_to_periph_id(int clk_id) +{ + if (clk_id > PERIPH_ID_COUNT) + return PERIPH_ID_NONE; + + switch (clk_id) { + case PERIPH_ID_RESERVED3: + case PERIPH_ID_RESERVED4: + case PERIPH_ID_RESERVED16: + case PERIPH_ID_RESERVED24: + case PERIPH_ID_RESERVED35: + case PERIPH_ID_RESERVED43: + case PERIPH_ID_RESERVED45: + case PERIPH_ID_RESERVED56: + case PERIPH_ID_RESERVED76: + case PERIPH_ID_RESERVED77: + case PERIPH_ID_RESERVED78: + case PERIPH_ID_RESERVED83: + case PERIPH_ID_RESERVED89: + case PERIPH_ID_RESERVED91: + case PERIPH_ID_RESERVED93: + case PERIPH_ID_RESERVED94: + case PERIPH_ID_RESERVED95: + return PERIPH_ID_NONE; + default: + return clk_id; + } +} +#endif /* CONFIG_OF_CONTROL */ + +void clock_early_init(void) +{ + tegra30_set_up_pllp(); +} + +void arch_timer_init(void) +{ +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/funcmux.c b/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/funcmux.c new file mode 100644 index 000000000..409335ce1 --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/funcmux.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Tegra30 high-level function multiplexing */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/pinmux.h> + +int funcmux_select(enum periph_id id, int config) +{ + int bad_config = config != FUNCMUX_DEFAULT; + + switch (id) { + case PERIPH_ID_UART1: + switch (config) { + case FUNCMUX_UART1_ULPI: + pinmux_set_func(PMUX_PINGRP_ULPI_DATA0_PO1, + PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_ULPI_DATA1_PO2, + PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_ULPI_DATA2_PO3, + PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_ULPI_DATA3_PO4, + PMUX_FUNC_UARTA); + pinmux_tristate_disable(PMUX_PINGRP_ULPI_DATA0_PO1); + pinmux_tristate_disable(PMUX_PINGRP_ULPI_DATA1_PO2); + pinmux_tristate_disable(PMUX_PINGRP_ULPI_DATA2_PO3); + pinmux_tristate_disable(PMUX_PINGRP_ULPI_DATA3_PO4); + break; + } + break; + + /* Add other periph IDs here as needed */ + + default: + debug("%s: invalid periph_id %d", __func__, id); + return -1; + } + + if (bad_config) { + debug("%s: invalid config %d for periph_id %d", __func__, + config, id); + return -1; + } + return 0; +} diff --git a/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/pinmux.c b/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/pinmux.c new file mode 100644 index 000000000..7eb05743b --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/tegra30-common/pinmux.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +#define PIN(pin, f0, f1, f2, f3) \ + { \ + .funcs = { \ + PMUX_FUNC_##f0, \ + PMUX_FUNC_##f1, \ + PMUX_FUNC_##f2, \ + PMUX_FUNC_##f3, \ + }, \ + } + +#define PIN_RESERVED {} + +static const struct pmux_pingrp_desc tegra30_pingroups[] = { + /* pin, f0, f1, f2, f3 */ + /* Offset 0x3000 */ + PIN(ULPI_DATA0_PO1, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA1_PO2, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA2_PO3, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA3_PO4, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA4_PO5, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA5_PO6, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA6_PO7, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA7_PO0, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_CLK_PY0, SPI1, RSVD2, UARTD, ULPI), + PIN(ULPI_DIR_PY1, SPI1, RSVD2, UARTD, ULPI), + PIN(ULPI_NXT_PY2, SPI1, RSVD2, UARTD, ULPI), + PIN(ULPI_STP_PY3, SPI1, RSVD2, UARTD, ULPI), + PIN(DAP3_FS_PP0, I2S2, RSVD2, DISPLAYA, DISPLAYB), + PIN(DAP3_DIN_PP1, I2S2, RSVD2, DISPLAYA, DISPLAYB), + PIN(DAP3_DOUT_PP2, I2S2, RSVD2, DISPLAYA, DISPLAYB), + PIN(DAP3_SCLK_PP3, I2S2, RSVD2, DISPLAYA, DISPLAYB), + PIN(PV0, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(PV1, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(SDMMC1_CLK_PZ0, SDMMC1, RSVD2, RSVD3, UARTA), + PIN(SDMMC1_CMD_PZ1, SDMMC1, RSVD2, RSVD3, UARTA), + PIN(SDMMC1_DAT3_PY4, SDMMC1, RSVD2, UARTE, UARTA), + PIN(SDMMC1_DAT2_PY5, SDMMC1, RSVD2, UARTE, UARTA), + PIN(SDMMC1_DAT1_PY6, SDMMC1, RSVD2, UARTE, UARTA), + PIN(SDMMC1_DAT0_PY7, SDMMC1, RSVD2, UARTE, UARTA), + PIN(PV2, OWR, RSVD2, RSVD3, RSVD4), + PIN(PV3, CLK_12M_OUT, RSVD2, RSVD3, RSVD4), + PIN(CLK2_OUT_PW5, EXTPERIPH2, RSVD2, RSVD3, RSVD4), + PIN(CLK2_REQ_PCC5, DAP, RSVD2, RSVD3, RSVD4), + PIN(LCD_PWR1_PC1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_PWR2_PC6, DISPLAYA, DISPLAYB, SPI5, HDCP), + PIN(LCD_SDIN_PZ2, DISPLAYA, DISPLAYB, SPI5, RSVD4), + PIN(LCD_SDOUT_PN5, DISPLAYA, DISPLAYB, SPI5, HDCP), + PIN(LCD_WR_N_PZ3, DISPLAYA, DISPLAYB, SPI5, HDCP), + PIN(LCD_CS0_N_PN4, DISPLAYA, DISPLAYB, SPI5, RSVD4), + PIN(LCD_DC0_PN6, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_SCK_PZ4, DISPLAYA, DISPLAYB, SPI5, HDCP), + PIN(LCD_PWR0_PB2, DISPLAYA, DISPLAYB, SPI5, HDCP), + PIN(LCD_PCLK_PB3, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_DE_PJ1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_HSYNC_PJ3, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_VSYNC_PJ4, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D0_PE0, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D1_PE1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D2_PE2, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D3_PE3, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D4_PE4, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D5_PE5, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D6_PE6, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D7_PE7, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D8_PF0, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D9_PF1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D10_PF2, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D11_PF3, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D12_PF4, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D13_PF5, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D14_PF6, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D15_PF7, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D16_PM0, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D17_PM1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D18_PM2, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D19_PM3, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D20_PM4, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D21_PM5, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D22_PM6, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D23_PM7, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_CS1_N_PW0, DISPLAYA, DISPLAYB, SPI5, RSVD4), + PIN(LCD_M1_PW1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_DC1_PD2, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(HDMI_INT_PN7, HDMI, RSVD2, RSVD3, RSVD4), + PIN(DDC_SCL_PV4, I2C4, RSVD2, RSVD3, RSVD4), + PIN(DDC_SDA_PV5, I2C4, RSVD2, RSVD3, RSVD4), + PIN(CRT_HSYNC_PV6, CRT, RSVD2, RSVD3, RSVD4), + PIN(CRT_VSYNC_PV7, CRT, RSVD2, RSVD3, RSVD4), + PIN(VI_D0_PT4, DDR, RSVD2, VI, RSVD4), + PIN(VI_D1_PD5, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D2_PL0, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D3_PL1, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D4_PL2, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D5_PL3, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D6_PL4, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D7_PL5, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D8_PL6, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D9_PL7, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D10_PT2, DDR, RSVD2, VI, RSVD4), + PIN(VI_D11_PT3, DDR, RSVD2, VI, RSVD4), + PIN(VI_PCLK_PT0, RSVD1, SDMMC2, VI, RSVD4), + PIN(VI_MCLK_PT1, VI, VI_ALT1, VI_ALT2, VI_ALT3), + PIN(VI_VSYNC_PD6, DDR, RSVD2, VI, RSVD4), + PIN(VI_HSYNC_PD7, DDR, RSVD2, VI, RSVD4), + PIN(UART2_RXD_PC3, UARTB, SPDIF, UARTA, SPI4), + PIN(UART2_TXD_PC2, UARTB, SPDIF, UARTA, SPI4), + PIN(UART2_RTS_N_PJ6, UARTA, UARTB, GMI, SPI4), + PIN(UART2_CTS_N_PJ5, UARTA, UARTB, GMI, SPI4), + PIN(UART3_TXD_PW6, UARTC, RSVD2, GMI, RSVD4), + PIN(UART3_RXD_PW7, UARTC, RSVD2, GMI, RSVD4), + PIN(UART3_CTS_N_PA1, UARTC, RSVD2, GMI, RSVD4), + PIN(UART3_RTS_N_PC0, UARTC, PWM0, GMI, RSVD4), + PIN(PU0, OWR, UARTA, GMI, RSVD4), + PIN(PU1, RSVD1, UARTA, GMI, RSVD4), + PIN(PU2, RSVD1, UARTA, GMI, RSVD4), + PIN(PU3, PWM0, UARTA, GMI, RSVD4), + PIN(PU4, PWM1, UARTA, GMI, RSVD4), + PIN(PU5, PWM2, UARTA, GMI, RSVD4), + PIN(PU6, PWM3, UARTA, GMI, RSVD4), + PIN(GEN1_I2C_SDA_PC5, I2C1, RSVD2, RSVD3, RSVD4), + PIN(GEN1_I2C_SCL_PC4, I2C1, RSVD2, RSVD3, RSVD4), + PIN(DAP4_FS_PP4, I2S3, RSVD2, GMI, RSVD4), + PIN(DAP4_DIN_PP5, I2S3, RSVD2, GMI, RSVD4), + PIN(DAP4_DOUT_PP6, I2S3, RSVD2, GMI, RSVD4), + PIN(DAP4_SCLK_PP7, I2S3, RSVD2, GMI, RSVD4), + PIN(CLK3_OUT_PEE0, EXTPERIPH3, RSVD2, RSVD3, RSVD4), + PIN(CLK3_REQ_PEE1, DEV3, RSVD2, RSVD3, RSVD4), + PIN(GMI_WP_N_PC7, RSVD1, NAND, GMI, GMI_ALT), + PIN(GMI_IORDY_PI5, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_WAIT_PI7, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_ADV_N_PK0, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_CLK_PK1, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_CS0_N_PJ0, RSVD1, NAND, GMI, DTV), + PIN(GMI_CS1_N_PJ2, RSVD1, NAND, GMI, DTV), + PIN(GMI_CS2_N_PK3, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_CS3_N_PK4, RSVD1, NAND, GMI, GMI_ALT), + PIN(GMI_CS4_N_PK2, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_CS6_N_PI3, NAND, NAND_ALT, GMI, SATA), + PIN(GMI_CS7_N_PI6, NAND, NAND_ALT, GMI, GMI_ALT), + PIN(GMI_AD0_PG0, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD1_PG1, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD2_PG2, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD3_PG3, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD4_PG4, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD5_PG5, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD6_PG6, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD7_PG7, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD8_PH0, PWM0, NAND, GMI, RSVD4), + PIN(GMI_AD9_PH1, PWM1, NAND, GMI, RSVD4), + PIN(GMI_AD10_PH2, PWM2, NAND, GMI, RSVD4), + PIN(GMI_AD11_PH3, PWM3, NAND, GMI, RSVD4), + PIN(GMI_AD12_PH4, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD13_PH5, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD14_PH6, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD15_PH7, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_A16_PJ7, UARTD, SPI4, GMI, GMI_ALT), + PIN(GMI_A17_PB0, UARTD, SPI4, GMI, DTV), + PIN(GMI_A18_PB1, UARTD, SPI4, GMI, DTV), + PIN(GMI_A19_PK7, UARTD, SPI4, GMI, RSVD4), + PIN(GMI_WR_N_PI0, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_OE_N_PI1, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_DQS_PI2, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_RST_N_PI4, NAND, NAND_ALT, GMI, RSVD4), + PIN(GEN2_I2C_SCL_PT5, I2C2, HDCP, GMI, RSVD4), + PIN(GEN2_I2C_SDA_PT6, I2C2, HDCP, GMI, RSVD4), + PIN(SDMMC4_CLK_PCC4, INVALID, NAND, GMI, SDMMC4), + PIN(SDMMC4_CMD_PT7, I2C3, NAND, GMI, SDMMC4), + PIN(SDMMC4_DAT0_PAA0, UARTE, SPI3, GMI, SDMMC4), + PIN(SDMMC4_DAT1_PAA1, UARTE, SPI3, GMI, SDMMC4), + PIN(SDMMC4_DAT2_PAA2, UARTE, SPI3, GMI, SDMMC4), + PIN(SDMMC4_DAT3_PAA3, UARTE, SPI3, GMI, SDMMC4), + PIN(SDMMC4_DAT4_PAA4, I2C3, I2S4, GMI, SDMMC4), + PIN(SDMMC4_DAT5_PAA5, VGP3, I2S4, GMI, SDMMC4), + PIN(SDMMC4_DAT6_PAA6, VGP4, I2S4, GMI, SDMMC4), + PIN(SDMMC4_DAT7_PAA7, VGP5, I2S4, GMI, SDMMC4), + PIN(SDMMC4_RST_N_PCC3, VGP6, RSVD2, RSVD3, SDMMC4), + PIN(CAM_MCLK_PCC0, VI, VI_ALT1, VI_ALT3, SDMMC4), + PIN(PCC1, I2S4, RSVD2, RSVD3, SDMMC4), + PIN(PBB0, I2S4, RSVD2, RSVD3, SDMMC4), + PIN(CAM_I2C_SCL_PBB1, VGP1, I2C3, RSVD3, SDMMC4), + PIN(CAM_I2C_SDA_PBB2, VGP2, I2C3, RSVD3, SDMMC4), + PIN(PBB3, VGP3, DISPLAYA, DISPLAYB, SDMMC4), + PIN(PBB4, VGP4, DISPLAYA, DISPLAYB, SDMMC4), + PIN(PBB5, VGP5, DISPLAYA, DISPLAYB, SDMMC4), + PIN(PBB6, VGP6, DISPLAYA, DISPLAYB, SDMMC4), + PIN(PBB7, I2S4, RSVD2, RSVD3, SDMMC4), + PIN(PCC2, I2S4, RSVD2, RSVD3, RSVD4), + PIN(JTAG_RTCK_PU7, RTCK, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SCL_PZ6, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SDA_PZ7, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW0_PR0, KBC, NAND, RSVD3, RSVD4), + PIN(KB_ROW1_PR1, KBC, NAND, RSVD3, RSVD4), + PIN(KB_ROW2_PR2, KBC, NAND, RSVD3, RSVD4), + PIN(KB_ROW3_PR3, KBC, NAND, RSVD3, INVALID), + PIN(KB_ROW4_PR4, KBC, NAND, TRACE, RSVD4), + PIN(KB_ROW5_PR5, KBC, NAND, TRACE, OWR), + PIN(KB_ROW6_PR6, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW7_PR7, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW8_PS0, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW9_PS1, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW10_PS2, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW11_PS3, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW12_PS4, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW13_PS5, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW14_PS6, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW15_PS7, KBC, NAND, SDMMC2, MIO), + PIN(KB_COL0_PQ0, KBC, NAND, TRACE, TEST), + PIN(KB_COL1_PQ1, KBC, NAND, TRACE, TEST), + PIN(KB_COL2_PQ2, KBC, NAND, TRACE, RSVD4), + PIN(KB_COL3_PQ3, KBC, NAND, TRACE, RSVD4), + PIN(KB_COL4_PQ4, KBC, NAND, TRACE, RSVD4), + PIN(KB_COL5_PQ5, KBC, NAND, TRACE, RSVD4), + PIN(KB_COL6_PQ6, KBC, NAND, TRACE, MIO), + PIN(KB_COL7_PQ7, KBC, NAND, TRACE, MIO), + PIN(CLK_32K_OUT_PA0, BLINK, RSVD2, RSVD3, RSVD4), + PIN(SYS_CLK_REQ_PZ5, SYSCLK, RSVD2, RSVD3, RSVD4), + PIN(CORE_PWR_REQ, CORE_PWR_REQ, RSVD2, RSVD3, RSVD4), + PIN(CPU_PWR_REQ, CPU_PWR_REQ, RSVD2, RSVD3, RSVD4), + PIN(PWR_INT_N, PWR_INT_N, RSVD2, RSVD3, RSVD4), + PIN(CLK_32K_IN, CLK_32K_IN, RSVD2, RSVD3, RSVD4), + PIN(OWR, OWR, CEC, RSVD3, RSVD4), + PIN(DAP1_FS_PN0, I2S0, HDA, GMI, SDMMC2), + PIN(DAP1_DIN_PN1, I2S0, HDA, GMI, SDMMC2), + PIN(DAP1_DOUT_PN2, I2S0, HDA, GMI, SDMMC2), + PIN(DAP1_SCLK_PN3, I2S0, HDA, GMI, SDMMC2), + PIN(CLK1_REQ_PEE2, DAP, HDA, RSVD3, RSVD4), + PIN(CLK1_OUT_PW4, EXTPERIPH1, RSVD2, RSVD3, RSVD4), + PIN(SPDIF_IN_PK6, SPDIF, HDA, I2C1, SDMMC2), + PIN(SPDIF_OUT_PK5, SPDIF, RSVD2, I2C1, SDMMC2), + PIN(DAP2_FS_PA2, I2S1, HDA, RSVD3, GMI), + PIN(DAP2_DIN_PA4, I2S1, HDA, RSVD3, GMI), + PIN(DAP2_DOUT_PA5, I2S1, HDA, RSVD3, GMI), + PIN(DAP2_SCLK_PA3, I2S1, HDA, RSVD3, GMI), + PIN(SPI2_MOSI_PX0, SPI6, SPI2, SPI3, GMI), + PIN(SPI2_MISO_PX1, SPI6, SPI2, SPI3, GMI), + PIN(SPI2_CS0_N_PX3, SPI6, SPI2, SPI3, GMI), + PIN(SPI2_SCK_PX2, SPI6, SPI2, SPI3, GMI), + PIN(SPI1_MOSI_PX4, SPI2, SPI1, SPI2_ALT, GMI), + PIN(SPI1_SCK_PX5, SPI2, SPI1, SPI2_ALT, GMI), + PIN(SPI1_CS0_N_PX6, SPI2, SPI1, SPI2_ALT, GMI), + PIN(SPI1_MISO_PX7, SPI3, SPI1, SPI2_ALT, RSVD4), + PIN(SPI2_CS1_N_PW2, SPI3, SPI2, SPI2_ALT, I2C1), + PIN(SPI2_CS2_N_PW3, SPI3, SPI2, SPI2_ALT, I2C1), + PIN(SDMMC3_CLK_PA6, UARTA, PWM2, SDMMC3, SPI3), + PIN(SDMMC3_CMD_PA7, UARTA, PWM3, SDMMC3, SPI2), + PIN(SDMMC3_DAT0_PB7, RSVD1, RSVD2, SDMMC3, SPI3), + PIN(SDMMC3_DAT1_PB6, RSVD1, RSVD2, SDMMC3, SPI3), + PIN(SDMMC3_DAT2_PB5, RSVD1, PWM1, SDMMC3, SPI3), + PIN(SDMMC3_DAT3_PB4, RSVD1, PWM0, SDMMC3, SPI3), + PIN(SDMMC3_DAT4_PD1, PWM1, SPI4, SDMMC3, SPI2), + PIN(SDMMC3_DAT5_PD0, PWM0, SPI4, SDMMC3, SPI2), + PIN(SDMMC3_DAT6_PD3, SPDIF, SPI4, SDMMC3, SPI2), + PIN(SDMMC3_DAT7_PD4, SPDIF, SPI4, SDMMC3, SPI2), + PIN(PEX_L0_PRSNT_N_PDD0, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L0_RST_N_PDD1, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L0_CLKREQ_N_PDD2, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_WAKE_N_PDD3, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L1_PRSNT_N_PDD4, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L1_RST_N_PDD5, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L1_CLKREQ_N_PDD6, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L2_PRSNT_N_PDD7, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L2_RST_N_PCC6, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L2_CLKREQ_N_PCC7, PCIE, HDA, RSVD3, RSVD4), + PIN(HDMI_CEC_PEE3, CEC, RSVD2, RSVD3, RSVD4), +}; +const struct pmux_pingrp_desc *tegra_soc_pingroups = tegra30_pingroups; diff --git a/qemu/roms/u-boot/arch/arm/cpu/u-boot-spl.lds b/qemu/roms/u-boot/arch/arm/cpu/u-boot-spl.lds new file mode 100644 index 000000000..3e886680e --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/u-boot-spl.lds @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + __image_copy_start = .; + CPUDIR/start.o (.text*) + *(.text*) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + + . = .; + + __image_copy_end = .; + + .rel.dyn : { + __rel_dyn_start = .; + *(.rel*) + __rel_dyn_end = .; + } + + .end : + { + *(.__end) + } + + _image_binary_end = .; + + .bss __rel_dyn_start (OVERLAY) : { + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } + + .dynsym _image_binary_end : { *(.dynsym) } + .dynbss : { *(.dynbss) } + .dynstr : { *(.dynstr*) } + .dynamic : { *(.dynamic*) } + .hash : { *(.hash*) } + .plt : { *(.plt*) } + .interp : { *(.interp*) } + .gnu : { *(.gnu*) } + .ARM.exidx : { *(.ARM.exidx*) } +} + +#if defined(CONFIG_SPL_MAX_SIZE) +ASSERT(__image_copy_end - __image_copy_start < (CONFIG_SPL_MAX_SIZE), \ + "SPL image too big"); +#endif + +#if defined(CONFIG_SPL_BSS_MAX_SIZE) +ASSERT(__bss_end - __bss_start < (CONFIG_SPL_BSS_MAX_SIZE), \ + "SPL image BSS too big"); +#endif + +#if defined(CONFIG_SPL_MAX_FOOTPRINT) +ASSERT(__bss_end - _start < (CONFIG_SPL_MAX_FOOTPRINT), \ + "SPL image plus BSS too big"); +#endif diff --git a/qemu/roms/u-boot/arch/arm/cpu/u-boot.lds b/qemu/roms/u-boot/arch/arm/cpu/u-boot.lds new file mode 100644 index 000000000..33c1f99fc --- /dev/null +++ b/qemu/roms/u-boot/arch/arm/cpu/u-boot.lds @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.__image_copy_start) + CPUDIR/start.o (.text*) + *(.text*) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + + . = .; + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + + .image_copy_end : + { + *(.__image_copy_end) + } + + .rel_dyn_start : + { + *(.__rel_dyn_start) + } + + .rel.dyn : { + *(.rel*) + } + + .rel_dyn_end : + { + *(.__rel_dyn_end) + } + + .end : + { + *(.__end) + } + + _image_binary_end = .; + + /* + * Deprecated: this MMU section is used by pxa at present but + * should not be used by new boards/CPUs. + */ + . = ALIGN(4096); + .mmutable : { + *(.mmutable) + } + +/* + * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c + * __bss_base and __bss_limit are for linker only (overlay ordering) + */ + + .bss_start __rel_dyn_start (OVERLAY) : { + KEEP(*(.__bss_start)); + __bss_base = .; + } + + .bss __bss_base (OVERLAY) : { + *(.bss*) + . = ALIGN(4); + __bss_limit = .; + } + + .bss_end __bss_limit (OVERLAY) : { + KEEP(*(.__bss_end)); + } + + .dynsym _image_binary_end : { *(.dynsym) } + .dynbss : { *(.dynbss) } + .dynstr : { *(.dynstr*) } + .dynamic : { *(.dynamic*) } + .plt : { *(.plt*) } + .interp : { *(.interp*) } + .gnu.hash : { *(.gnu.hash) } + .gnu : { *(.gnu*) } + .ARM.exidx : { *(.ARM.exidx*) } + .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) } +} |