diff options
| author | Marek Vasut <marek.vasut@gmail.com> | 2011-11-26 07:32:24 +0100 | 
|---|---|---|
| committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2011-12-06 23:59:32 +0100 | 
| commit | d10237d275300562bbfecbbe2f59a97cfb9dc180 (patch) | |
| tree | 95b93e26855535cee1ac2dd91c29fc230b3a264b /arch/arm/cpu/pxa/pxa2xx.c | |
| parent | abc20aba1834c321a638b367c18dcce1bb4e232d (diff) | |
| download | olio-uboot-2014.01-d10237d275300562bbfecbbe2f59a97cfb9dc180.tar.xz olio-uboot-2014.01-d10237d275300562bbfecbbe2f59a97cfb9dc180.zip | |
PXA: Separate PXA2xx CPU init
Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Diffstat (limited to 'arch/arm/cpu/pxa/pxa2xx.c')
| -rw-r--r-- | arch/arm/cpu/pxa/pxa2xx.c | 301 | 
1 files changed, 301 insertions, 0 deletions
| diff --git a/arch/arm/cpu/pxa/pxa2xx.c b/arch/arm/cpu/pxa/pxa2xx.c new file mode 100644 index 000000000..e7b475d16 --- /dev/null +++ b/arch/arm/cpu/pxa/pxa2xx.c @@ -0,0 +1,301 @@ +/* + * (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> + * + * 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 <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 pxa_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"(2)); + +	/* 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); +		pxa_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 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); + +	for (;;) +		; +} |