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 | u-boot-d10237d275300562bbfecbbe2f59a97cfb9dc180.tar.gz |
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 0000000000..e7b475d162 --- /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 (;;) + ; +} |