This patch adds cpu directory for OMAP3 processor. Signed-off-by: Shashi Ranjan Sunil Kumar Syed Mohammed Khasim --- Makefile | 43 ++++ config.mk | 34 +++ cpu.c | 231 ++++++++++++++++++++++++ interrupts.c | 299 +++++++++++++++++++++++++++++++ mmc.c | 545 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mmc_host_def.h | 164 +++++++++++++++++ mmc_protocol.h | 253 ++++++++++++++++++++++++++ start.S | 484 ++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 2053 insertions(+) diff -purN orig_u-boot/cpu/omap3/config.mk u-boot_beagle/cpu/omap3/config.mk --- orig_u-boot/cpu/omap3/config.mk 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_beagle/cpu/omap3/config.mk 2008-04-02 11:06:27.000000000 +0530 @@ -0,0 +1,34 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, +# +# 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 +# +PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ + -msoft-float + +PLATFORM_CPPFLAGS += -march=armv7a +# ========================================================================= +# +# Supply options according to compiler version +# +# ========================================================================= +#PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) +PLATFORM_CPPFLAGS +=$(call cc-option) +PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) diff -purN orig_u-boot/cpu/omap3/cpu.c u-boot_beagle/cpu/omap3/cpu.c --- orig_u-boot/cpu/omap3/cpu.c 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_beagle/cpu/omap3/cpu.c 2008-04-02 16:46:33.000000000 +0530 @@ -0,0 +1,231 @@ +/* + * (C) Copyright 2008 Texas Insturments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Marius Groeger + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * 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 + */ + +/* + * CPU specific code + */ + +#include +#include +#include +#if !defined(CONFIG_INTEGRATOR) && ! defined(CONFIG_ARCH_CINTEGRATOR) +#include +#endif +#include + +#ifdef CONFIG_USE_IRQ +DECLARE_GLOBAL_DATA_PTR; +#endif + +#ifndef CONFIG_L2_OFF +void l2cache_disable(void); +#endif + +/* read co-processor 15, register #1 (control register) */ +static unsigned long read_p15_c1(void) +{ + unsigned long value; + + __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 0 @ read control reg\n":"=r"(value) + ::"memory"); + return value; +} + +/* write to co-processor 15, register #1 (control register) */ +static void write_p15_c1(unsigned long value) +{ + __asm__ + __volatile__ + ("mcr p15, 0, %0, c1, c0, 0 @ write it back\n"::"r"(value) + : "memory"); + + read_p15_c1(); +} + +static void cp_delay(void) +{ + volatile int i; + + /* Many OMAP regs need at least 2 nops */ + for (i = 0; i < 100; i++) ; +} + +/* See also ARM Ref. Man. */ +#define C1_MMU (1<<0) /* mmu off/on */ +#define C1_ALIGN (1<<1) /* alignment faults off/on */ +#define C1_DC (1<<2) /* dcache off/on */ +#define C1_WB (1<<3) /* merging write buffer on/off */ +#define C1_BIG_ENDIAN (1<<7) /* big endian off/on */ +#define C1_SYS_PROT (1<<8) /* system protection */ +#define C1_ROM_PROT (1<<9) /* ROM protection */ +#define C1_IC (1<<12) /* icache off/on */ +#define C1_HIGH_VECTORS (1<<13) /* location of vectors: low/high addresses */ +#define RESERVED_1 (0xf << 3) /* must be 111b for R/W */ + +int cpu_init(void) +{ + /* + * setup up stacks if necessary + */ +#ifdef CONFIG_USE_IRQ + IRQ_STACK_START = + _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4; + FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; +#endif + return 0; +} + +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 + + { + unsigned int i; + + /* turn off I/D-cache */ + asm("mrc p15, 0, %0, c1, c0, 0":"=r"(i)); + i &= ~(C1_DC | C1_IC); + asm("mcr p15, 0, %0, c1, c0, 0": :"r"(i)); + + /* invalidate I-cache */ + arm_cache_flush(); +#ifndef CONFIG_L2_OFF + /* turn off L2 cache */ + l2cache_disable(); + /* invalidate L2 cache also */ + v7_flush_dcache_all(get_device_type()); +#endif + i = 0; + /* mem barrier to sync up things */ + asm("mcr p15, 0, %0, c7, c10, 4": :"r"(i)); + } + + return (0); +} + +int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + disable_interrupts(); + reset_cpu(0); + /*NOTREACHED*/ return (0); +} + +void icache_enable(void) +{ + ulong reg; + + reg = read_p15_c1(); /* get control reg. */ + cp_delay(); + write_p15_c1(reg | C1_IC); +} + +void icache_disable(void) +{ + ulong reg; + + reg = read_p15_c1(); + cp_delay(); + write_p15_c1(reg & ~C1_IC); +} + +void l2cache_enable() +{ + unsigned long i; + volatile unsigned int j; + + /* ES2 onwards we can disable/enable L2 ourselves */ + if (get_cpu_rev() == CPU_3430_ES2) { + __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i)); + __asm__ __volatile__("orr %0, %0, #0x2":"=r"(i)); + __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i)); + } else { + /* Save r0, r12 and restore them after usage */ + __asm__ __volatile__("mov %0, r12":"=r"(j)); + __asm__ __volatile__("mov %0, r0":"=r"(i)); + + /* GP Device ROM code API usage here */ + /* r12 = AUXCR Write function and r0 value */ + __asm__ __volatile__("mov r12, #0x3"); + __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1"); + __asm__ __volatile__("orr r0, r0, #0x2"); + /* SMI instruction to call ROM Code API */ + __asm__ __volatile__(".word 0xE1600070"); + __asm__ __volatile__("mov r0, %0":"=r"(i)); + __asm__ __volatile__("mov r12, %0":"=r"(j)); + } + +} + +void l2cache_disable() +{ + unsigned long i; + volatile unsigned int j; + + /* ES2 onwards we can disable/enable L2 ourselves */ + if (get_cpu_rev() == CPU_3430_ES2) { + __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i)); + __asm__ __volatile__("bic %0, %0, #0x2":"=r"(i)); + __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i)); + } else { + /* Save r0, r12 and restore them after usage */ + __asm__ __volatile__("mov %0, r12":"=r"(j)); + __asm__ __volatile__("mov %0, r0":"=r"(i)); + + /* GP Device ROM code API usage here */ + /* r12 = AUXCR Write function and r0 value */ + __asm__ __volatile__("mov r12, #0x3"); + __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1"); + __asm__ __volatile__("bic r0, r0, #0x2"); + /* SMI instruction to call ROM Code API */ + __asm__ __volatile__(".word 0xE1600070"); + __asm__ __volatile__("mov r0, %0":"=r"(i)); + __asm__ __volatile__("mov r12, %0":"=r"(j)); + } +} + +int icache_status(void) +{ + return (read_p15_c1() & C1_IC) != 0; +} diff -purN orig_u-boot/cpu/omap3/interrupts.c u-boot_beagle/cpu/omap3/interrupts.c --- orig_u-boot/cpu/omap3/interrupts.c 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_beagle/cpu/omap3/interrupts.c 2008-04-02 16:47:26.000000000 +0530 @@ -0,0 +1,299 @@ +/* + * (C) Copyright 2008 + * Texas Instruments + * + * Richard Woodruff + * Syed Moahmmed Khasim + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Marius Groeger + * Alex Zuepke + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * 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 +#include + +#if !defined(CONFIG_INTEGRATOR) && ! defined(CONFIG_ARCH_CINTEGRATOR) +# include +#endif + +#include + +#define TIMER_LOAD_VAL 0 + +/* macro to read the 32 bit timer */ +#define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+TCRR)) + +#ifdef CONFIG_USE_IRQ +/* enable IRQ interrupts */ +void enable_interrupts(void) +{ + unsigned long temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "bic %0, %0, #0x80\n" "msr cpsr_c, %0":"=r"(temp) + ::"memory"); +} + +/* + * disable IRQ/FIQ interrupts + * returns true if interrupts had been enabled before we disabled them + */ +int disable_interrupts(void) +{ + unsigned long old, temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0xc0\n" + "msr cpsr_c, %1":"=r"(old), "=r"(temp) + ::"memory"); + return (old & 0x80) == 0; +} +#else +void enable_interrupts(void) +{ + return; +} +int disable_interrupts(void) +{ + return 0; +} +#endif + +void bad_mode(void) +{ + panic("Resetting CPU ...\n"); + reset_cpu(0); +} + +void show_regs(struct pt_regs *regs) +{ + unsigned long flags; + const char *processor_modes[] = { + "USER_26", "FIQ_26", "IRQ_26", "SVC_26", + "UK4_26", "UK5_26", "UK6_26", "UK7_26", + "UK8_26", "UK9_26", "UK10_26", "UK11_26", + "UK12_26", "UK13_26", "UK14_26", "UK15_26", + "USER_32", "FIQ_32", "IRQ_32", "SVC_32", + "UK4_32", "UK5_32", "UK6_32", "ABT_32", + "UK8_32", "UK9_32", "UK10_32", "UND_32", + "UK12_32", "UK13_32", "UK14_32", "SYS_32", + }; + + flags = condition_codes(regs); + + printf("pc : [<%08lx>] lr : [<%08lx>]\n" + "sp : %08lx ip : %08lx fp : %08lx\n", + instruction_pointer(regs), + regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); + printf("r10: %08lx r9 : %08lx r8 : %08lx\n", + regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); + printf("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", + regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); + printf("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", + regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); + printf("Flags: %c%c%c%c", + flags & CC_N_BIT ? 'N' : 'n', + flags & CC_Z_BIT ? 'Z' : 'z', + flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); + printf(" IRQs %s FIQs %s Mode %s%s\n", + interrupts_enabled(regs) ? "on" : "off", + fast_interrupts_enabled(regs) ? "on" : "off", + processor_modes[processor_mode(regs)], + thumb_mode(regs) ? " (T)" : ""); +} + +void do_undefined_instruction(struct pt_regs *pt_regs) +{ + printf("undefined instruction\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_software_interrupt(struct pt_regs *pt_regs) +{ + printf("software interrupt\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_prefetch_abort(struct pt_regs *pt_regs) +{ + printf("prefetch abort\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_data_abort(struct pt_regs *pt_regs) +{ + printf("data abort\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_not_used(struct pt_regs *pt_regs) +{ + printf("not used\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_fiq(struct pt_regs *pt_regs) +{ + printf("fast interrupt request\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_irq(struct pt_regs *pt_regs) +{ + printf("interrupt request\n"); + show_regs(pt_regs); + bad_mode(); +} + +#if defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_CINTEGRATOR) +/* Use the IntegratorCP function from board/integratorcp.c */ +#else + +static ulong timestamp; +static ulong lastinc; + +/* nothing really to do with interrupts, just starts up a counter. */ +int interrupt_init(void) +{ + int32_t val; + + /* Start the counter ticking up */ + *((int32_t *) (CFG_TIMERBASE + TLDR)) = TIMER_LOAD_VAL; /* reload value on overflow */ + val = (CFG_PVT << 2) | BIT5 | BIT1 | BIT0; /* mask to enable timer */ + *((int32_t *) (CFG_TIMERBASE + TCLR)) = val; /* start timer */ + + reset_timer_masked(); /* init the timestamp and lastinc value */ + + return (0); +} + +/* + * timer without interrupts + */ +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void set_timer(ulong t) +{ + timestamp = t; +} + +/* delay x useconds AND perserve advance timstamp 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 *= CFG_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 * CFG_HZ; + tmo /= (1000 * 1000); + } + + tmp = get_timer(0); /* get current timestamp */ + if ((tmo + tmp + 1) < tmp) /* if setting this forward will roll time stamp */ + reset_timer_masked(); /* reset "advancing" timestamp to 0, set lastinc 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 */ + lastinc = READ_TIMER; /* capture current incrementer value time */ + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +ulong get_timer_masked(void) +{ + ulong now = READ_TIMER; /* current tick value */ + + if (now >= lastinc) /* normal mode (non roll) */ + timestamp += (now - lastinc); /* move stamp fordward with absoulte diff ticks */ + else /* we have rollover of incrementer */ + timestamp += (0xFFFFFFFF - lastinc) + now; + lastinc = 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 *= CFG_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 * CFG_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 = CFG_HZ; + return tbclk; +} +#endif /* !Integrator/CP */ diff -purN orig_u-boot/cpu/omap3/Makefile u-boot_beagle/cpu/omap3/Makefile --- orig_u-boot/cpu/omap3/Makefile 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_beagle/cpu/omap3/Makefile 2008-04-02 11:06:27.000000000 +0530 @@ -0,0 +1,43 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.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 $(TOPDIR)/config.mk + +LIB = lib$(CPU).a + +START = start.o +OBJS = interrupts.o cpu.o mmc.o + +all: .depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff -purN orig_u-boot/cpu/omap3/mmc.c u-boot_beagle/cpu/omap3/mmc.c --- orig_u-boot/cpu/omap3/mmc.c 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_beagle/cpu/omap3/mmc.c 2008-04-02 17:05:31.000000000 +0530 @@ -0,0 +1,545 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, + * Syed Mohammed Khasim + * + * 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's 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include "mmc_host_def.h" +#include "mmc_protocol.h" + +extern int fat_register_device(block_dev_desc_t * dev_desc, int part_no); + +mmc_card_data cur_card_data; +static block_dev_desc_t mmc_blk_dev; + +block_dev_desc_t *mmc_get_dev(int dev) +{ + return ((block_dev_desc_t *) & mmc_blk_dev); +} + +void twl4030_mmc_config(void) +{ + unsigned char data; + + data = 0x20; + i2c_write(0x4B, 0x82, 1, &data, 1); + data = 0x2; + i2c_write(0x4B, 0x85, 1, &data, 1); +} + +unsigned char mmc_board_init(void) +{ + unsigned int value = 0; + + twl4030_mmc_config(); + + value = CONTROL_PBIAS_LITE; + CONTROL_PBIAS_LITE = value | (1 << 2) | (1 << 1) | (1 << 9); + + value = CONTROL_DEV_CONF0; + CONTROL_DEV_CONF0 = value | (1 << 24); + + return 1; +} + +void mmc_init_stream(void) +{ + OMAP_HSMMC_CON |= INIT_INITSTREAM; + + OMAP_HSMMC_CMD = MMC_CMD0; + while (!(OMAP_HSMMC_STAT & CC_MASK)) { + } + OMAP_HSMMC_STAT = CC_MASK; + + OMAP_HSMMC_CMD = MMC_CMD0; + while (!(OMAP_HSMMC_STAT & CC_MASK)) { + } + + OMAP_HSMMC_STAT = OMAP_HSMMC_STAT; + OMAP_HSMMC_CON &= ~INIT_INITSTREAM; +} + +unsigned char mmc_clock_config(unsigned int iclk, unsigned short clk_div) +{ + unsigned int val; + + mmc_reg_out(OMAP_HSMMC_SYSCTL, (ICE_MASK | DTO_MASK | CEN_MASK), + (ICE_STOP | DTO_15THDTO | CEN_DISABLE)); + + switch (iclk) { + case CLK_INITSEQ: + val = MMC_INIT_SEQ_CLK / 2; + break; + case CLK_400KHZ: + val = MMC_400kHz_CLK; + break; + case CLK_MISC: + val = clk_div; + break; + default: + return 0; + } + mmc_reg_out(OMAP_HSMMC_SYSCTL, + ICE_MASK | CLKD_MASK, (val << CLKD_OFFSET) | ICE_OSCILLATE); + + while ((OMAP_HSMMC_SYSCTL & ICS_MASK) == ICS_NOTREADY) { + } + + OMAP_HSMMC_SYSCTL |= CEN_ENABLE; + return 1; +} + +unsigned char mmc_init_setup(void) +{ + unsigned int reg_val; + + mmc_board_init(); + + OMAP_HSMMC_SYSCONFIG |= MMC_SOFTRESET; + while ((OMAP_HSMMC_SYSSTATUS & RESETDONE) == 0) ; + + OMAP_HSMMC_SYSCTL |= SOFTRESETALL; + while ((OMAP_HSMMC_SYSCTL & SOFTRESETALL) != 0x0) ; + + OMAP_HSMMC_HCTL = DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0; + OMAP_HSMMC_CAPA |= VS30_3V0SUP | VS18_1V8SUP; + + reg_val = OMAP_HSMMC_CON & RESERVED_MASK; + + OMAP_HSMMC_CON = CTPL_MMC_SD | reg_val | WPP_ACTIVEHIGH | + CDP_ACTIVEHIGH | MIT_CTO | DW8_1_4BITMODE | MODE_FUNC | + STR_BLOCK | HR_NOHOSTRESP | INIT_NOINIT | NOOPENDRAIN; + + mmc_clock_config(CLK_INITSEQ, 0); + OMAP_HSMMC_HCTL |= SDBP_PWRON; + + OMAP_HSMMC_IE = 0x307f0033; + + mmc_init_stream(); + return 1; +} + +unsigned char mmc_send_cmd(unsigned int cmd, unsigned int arg, + unsigned int *response) +{ + volatile unsigned int mmc_stat; + + while ((OMAP_HSMMC_PSTATE & DATI_MASK) == DATI_CMDDIS) { + } + + OMAP_HSMMC_BLK = BLEN_512BYTESLEN | NBLK_STPCNT; + OMAP_HSMMC_STAT = 0xFFFFFFFF; + OMAP_HSMMC_ARG = arg; + OMAP_HSMMC_CMD = cmd | CMD_TYPE_NORMAL | CICE_NOCHECK | + CCCE_NOCHECK | MSBS_SGLEBLK | ACEN_DISABLE | BCE_DISABLE | + DE_DISABLE; + + while (1) { + do { + mmc_stat = OMAP_HSMMC_STAT; + } while (mmc_stat == 0); + + if ((mmc_stat & ERRI_MASK) != 0) { + return (unsigned char) mmc_stat; + } + + if (mmc_stat & CC_MASK) { + OMAP_HSMMC_STAT = CC_MASK; + response[0] = OMAP_HSMMC_RSP10; + if ((cmd & RSP_TYPE_MASK) == RSP_TYPE_LGHT136) { + response[1] = OMAP_HSMMC_RSP32; + response[2] = OMAP_HSMMC_RSP54; + response[3] = OMAP_HSMMC_RSP76; + } + break; + } + } + return 1; +} + +unsigned char mmc_read_data(unsigned int *output_buf) +{ + volatile unsigned int mmc_stat; + unsigned int read_count = 0; + + /* + * Start Polled Read + */ + while (1) { + do { + mmc_stat = OMAP_HSMMC_STAT; + } while (mmc_stat == 0); + + if ((mmc_stat & ERRI_MASK) != 0) + return (unsigned char) mmc_stat; + + if (mmc_stat & BRR_MASK) { + unsigned int k; + + OMAP_HSMMC_STAT |= BRR_MASK; + for (k = 0; k < MMCSD_SECTOR_SIZE / 4; k++) { + *output_buf = OMAP_HSMMC_DATA; + output_buf++; + read_count += 4; + } + } + + if (mmc_stat & BWR_MASK) + OMAP_HSMMC_STAT |= BWR_MASK; + + if (mmc_stat & TC_MASK) { + OMAP_HSMMC_STAT |= TC_MASK; + break; + } + } + return 1; +} + +unsigned char mmc_detect_card(mmc_card_data * mmc_card_cur) +{ + unsigned char err; + unsigned int argument = 0; + unsigned int ocr_value, ocr_recvd, ret_cmd41, hcs_val; + unsigned int resp[4]; + unsigned short retry_cnt = 2000; + + /* Set to Initialization Clock */ + err = mmc_clock_config(CLK_400KHZ, 0); + if (err != 1) + return err; + + mmc_card_cur->RCA = MMC_RELATIVE_CARD_ADDRESS; + argument = 0x00000000; + + ocr_value = (0x1FF << 15); + err = mmc_send_cmd(MMC_CMD0, argument, resp); + if (err != 1) + return err; + + argument = SD_CMD8_CHECK_PATTERN | SD_CMD8_2_7_3_6_V_RANGE; + err = mmc_send_cmd(MMC_SDCMD8, argument, resp); + hcs_val = (err == 1) ? + MMC_OCR_REG_HOST_CAPACITY_SUPPORT_SECTOR : + MMC_OCR_REG_HOST_CAPACITY_SUPPORT_BYTE; + + argument = 0x0000 << 16; + err = mmc_send_cmd(MMC_CMD55, argument, resp); + if (err == 1) { + mmc_card_cur->card_type = SD_CARD; + ocr_value |= hcs_val; + ret_cmd41 = MMC_ACMD41; + } else { + mmc_card_cur->card_type = MMC_CARD; + ocr_value |= MMC_OCR_REG_ACCESS_MODE_SECTOR; + ret_cmd41 = MMC_CMD1; + OMAP_HSMMC_CON &= ~OD; + OMAP_HSMMC_CON |= OPENDRAIN; + } + + argument = ocr_value; + err = mmc_send_cmd(ret_cmd41, argument, resp); + if (err != 1) { + return err; + } + ocr_recvd = ((mmc_resp_r3 *) resp)->ocr; + + while (!(ocr_recvd & (0x1 << 31)) && (retry_cnt > 0)) { + retry_cnt--; + if (mmc_card_cur->card_type == SD_CARD) { + argument = 0x0000 << 16; + err = mmc_send_cmd(MMC_CMD55, argument, resp); + } + + argument = ocr_value; + err = mmc_send_cmd(ret_cmd41, argument, resp); + if (err != 1) + return err; + ocr_recvd = ((mmc_resp_r3 *) resp)->ocr; + } + + if (!(ocr_recvd & (0x1 << 31))) + return 0; + + if (mmc_card_cur->card_type == MMC_CARD) { + if ((ocr_recvd & MMC_OCR_REG_ACCESS_MODE_MASK) == + MMC_OCR_REG_ACCESS_MODE_SECTOR) { + mmc_card_cur->mode = SECTOR_MODE; + } else { + mmc_card_cur->mode = BYTE_MODE; + } + + ocr_recvd &= ~MMC_OCR_REG_ACCESS_MODE_MASK; + } else { + if ((ocr_recvd & MMC_OCR_REG_HOST_CAPACITY_SUPPORT_MASK) + == MMC_OCR_REG_HOST_CAPACITY_SUPPORT_SECTOR) { + mmc_card_cur->mode = SECTOR_MODE; + } else { + mmc_card_cur->mode = BYTE_MODE; + } + ocr_recvd &= ~MMC_OCR_REG_HOST_CAPACITY_SUPPORT_MASK; + } + + ocr_recvd &= ~(0x1 << 31); + if (!(ocr_recvd & ocr_value)) + return 0; + + err = mmc_send_cmd(MMC_CMD2, argument, resp); + if (err != 1) + return err; + + if (mmc_card_cur->card_type == MMC_CARD) { + argument = mmc_card_cur->RCA << 16; + err = mmc_send_cmd(MMC_CMD3, argument, resp); + if (err != 1) + return err; + } else { + argument = 0x00000000; + err = mmc_send_cmd(MMC_SDCMD3, argument, resp); + if (err != 1) + return err; + + mmc_card_cur->RCA = ((mmc_resp_r6 *) resp)->newpublishedrca; + } + + OMAP_HSMMC_CON &= ~OD; + OMAP_HSMMC_CON |= NOOPENDRAIN; + return 1; +} + +unsigned char mmc_read_cardsize(mmc_card_data * mmc_dev_data, + mmc_csd_reg_t * cur_csd) +{ + mmc_extended_csd_reg_t ext_csd; + unsigned int size, count, blk_len, blk_no, card_size, argument; + unsigned char err; + unsigned int resp[4]; + + if (mmc_dev_data->mode == SECTOR_MODE) { + if (mmc_dev_data->card_type == SD_CARD) { + card_size = + (((mmc_sd2_csd_reg_t *) cur_csd)-> + c_size_lsb & MMC_SD2_CSD_C_SIZE_LSB_MASK) | + ((((mmc_sd2_csd_reg_t *) cur_csd)-> + c_size_msb & MMC_SD2_CSD_C_SIZE_MSB_MASK) + << MMC_SD2_CSD_C_SIZE_MSB_OFFSET); + mmc_dev_data->size = card_size * 1024; + if (mmc_dev_data->size == 0) + return 0; + } else { + argument = 0x00000000; + err = mmc_send_cmd(MMC_CMD8, argument, resp); + if (err != 1) + return err; + err = mmc_read_data((unsigned int *) &ext_csd); + if (err != 1) + return err; + mmc_dev_data->size = ext_csd.sectorcount; + + if (mmc_dev_data->size == 0) + mmc_dev_data->size = 8388608; + } + } else { + if (cur_csd->c_size_mult >= 8) + return 0; + + if (cur_csd->read_bl_len >= 12) + return 0; + + /* Compute size */ + count = 1 << (cur_csd->c_size_mult + 2); + card_size = (cur_csd->c_size_lsb & MMC_CSD_C_SIZE_LSB_MASK) | + ((cur_csd->c_size_msb & MMC_CSD_C_SIZE_MSB_MASK) + << MMC_CSD_C_SIZE_MSB_OFFSET); + blk_no = (card_size + 1) * count; + blk_len = 1 << cur_csd->read_bl_len; + size = blk_no * blk_len; + mmc_dev_data->size = size / MMCSD_SECTOR_SIZE; + if (mmc_dev_data->size == 0) + return 0; + } + return 1; +} + +unsigned char omap_mmc_read_sect(unsigned int start_sec, unsigned int num_bytes, + mmc_card_data * mmc_c, + unsigned long *output_buf) +{ + unsigned char err; + unsigned int argument; + unsigned int resp[4]; + unsigned int num_sec_val = + (num_bytes + (MMCSD_SECTOR_SIZE - 1)) / MMCSD_SECTOR_SIZE; + unsigned int sec_inc_val; + + if (num_sec_val == 0) + return 1; + + if (mmc_c->mode == SECTOR_MODE) { + argument = start_sec; + sec_inc_val = 1; + } else { + argument = start_sec * MMCSD_SECTOR_SIZE; + sec_inc_val = MMCSD_SECTOR_SIZE; + } + + while (num_sec_val) { + err = mmc_send_cmd(MMC_CMD17, argument, resp); + if (err != 1) { + return err; + } + + err = mmc_read_data((unsigned int *) output_buf); + if (err != 1) { + return err; + } + output_buf += (MMCSD_SECTOR_SIZE / 4); + argument += sec_inc_val; + num_sec_val--; + } + return 1; +} + +unsigned char configure_mmc(mmc_card_data * mmc_card_cur) +{ + unsigned char ret_val; + unsigned int argument; + unsigned int resp[4]; + unsigned int trans_clk, trans_fact, trans_unit, retries = 2; + mmc_csd_reg_t Card_CSD; + unsigned char trans_speed; + + ret_val = mmc_init_setup(); + if (ret_val != 1) { + return ret_val; + } + + do { + ret_val = mmc_detect_card(mmc_card_cur); + retries--; + } while ((retries > 0) && (ret_val != 1)); + + argument = mmc_card_cur->RCA << 16; + ret_val = mmc_send_cmd(MMC_CMD9, argument, resp); + if (ret_val != 1) + return ret_val; + + ((unsigned int *) &Card_CSD)[3] = resp[3]; + ((unsigned int *) &Card_CSD)[2] = resp[2]; + ((unsigned int *) &Card_CSD)[1] = resp[1]; + ((unsigned int *) &Card_CSD)[0] = resp[0]; + + if (mmc_card_cur->card_type == MMC_CARD) { + mmc_card_cur->version = Card_CSD.spec_vers; + } + + trans_speed = Card_CSD.tran_speed; + + ret_val = mmc_send_cmd(MMC_CMD4, MMC_DSR_DEFAULT << 16, resp); + if (ret_val != 1) + return ret_val; + + trans_unit = trans_speed & MMC_CSD_TRAN_SPEED_UNIT_MASK; + trans_fact = trans_speed & MMC_CSD_TRAN_SPEED_FACTOR_MASK; + + if (trans_unit > MMC_CSD_TRAN_SPEED_UNIT_100MHZ) + return 0; + + if ((trans_fact < MMC_CSD_TRAN_SPEED_FACTOR_1_0) || + (trans_fact > MMC_CSD_TRAN_SPEED_FACTOR_8_0)) + return 0; + + trans_unit >>= 0; + trans_fact >>= 3; + + trans_clk = mmc_transspeed_val[trans_fact - 1][trans_unit] * 2; + ret_val = mmc_clock_config(CLK_MISC, trans_clk); + + if (ret_val != 1) + return ret_val; + + argument = mmc_card_cur->RCA << 16; + ret_val = mmc_send_cmd(MMC_CMD7_SELECT, argument, resp); + if (ret_val != 1) + return ret_val; + + /* Configure the block length to 512 bytes */ + argument = MMCSD_SECTOR_SIZE; + ret_val = mmc_send_cmd(MMC_CMD16, argument, resp); + if (ret_val != 1) + return ret_val; + + /* get the card size in sectors */ + ret_val = mmc_read_cardsize(mmc_card_cur, &Card_CSD); + if (ret_val != 1) + return ret_val; + + return 1; +} +unsigned long mmc_bread(int dev_num, unsigned long blknr, lbaint_t blkcnt, + void *dst) +{ + omap_mmc_read_sect(blknr, (blkcnt * MMCSD_SECTOR_SIZE), &cur_card_data, + (unsigned long *) dst); + return 1; +} + +int mmc_init(int verbose) +{ + configure_mmc(&cur_card_data); + + mmc_blk_dev.if_type = IF_TYPE_MMC; + mmc_blk_dev.part_type = PART_TYPE_DOS; + mmc_blk_dev.dev = 0; + mmc_blk_dev.lun = 0; + mmc_blk_dev.type = 0; + + /* FIXME fill in the correct size (is set to 32MByte) */ + mmc_blk_dev.blksz = MMCSD_SECTOR_SIZE; + mmc_blk_dev.lba = 0x10000; + mmc_blk_dev.removable = 0; + mmc_blk_dev.block_read = mmc_bread; + + fat_register_device(&mmc_blk_dev, 1); + return 0; +} + +int mmc_read(ulong src, uchar * dst, int size) +{ + /* not implemented */ + return (0); +} + +int mmc_write(uchar * src, ulong dst, int size) +{ + /* not implementd */ + return (0); +} + +int mmc2info(ulong addr) +{ + /*not implemented */ + return (0); +} diff -purN orig_u-boot/cpu/omap3/mmc_host_def.h u-boot_beagle/cpu/omap3/mmc_host_def.h --- orig_u-boot/cpu/omap3/mmc_host_def.h 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_beagle/cpu/omap3/mmc_host_def.h 2008-04-02 12:31:45.000000000 +0530 @@ -0,0 +1,164 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, + * Syed Mohammed Khasim + * + * 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's 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef MMC_HOST_DEFINITIONS_H +#define MMC_HOST_DEFINITIONS_H + +/* + * OMAP HSMMC register definitions + */ +#define OMAP_HSMMC_SYSCONFIG (*(unsigned int *) 0x4809C010) +#define OMAP_HSMMC_SYSSTATUS (*(unsigned int *) 0x4809C014) +#define OMAP_HSMMC_CON (*(unsigned int *) 0x4809C02C) +#define OMAP_HSMMC_BLK (*(unsigned int *) 0x4809C104) +#define OMAP_HSMMC_ARG (*(unsigned int *) 0x4809C108) +#define OMAP_HSMMC_CMD (*(unsigned int *) 0x4809C10C) +#define OMAP_HSMMC_RSP10 (*(unsigned int *) 0x4809C110) +#define OMAP_HSMMC_RSP32 (*(unsigned int *) 0x4809C114) +#define OMAP_HSMMC_RSP54 (*(unsigned int *) 0x4809C118) +#define OMAP_HSMMC_RSP76 (*(unsigned int *) 0x4809C11C) +#define OMAP_HSMMC_DATA (*(unsigned int *) 0x4809C120) +#define OMAP_HSMMC_PSTATE (*(unsigned int *) 0x4809C124) +#define OMAP_HSMMC_HCTL (*(unsigned int *) 0x4809C128) +#define OMAP_HSMMC_SYSCTL (*(unsigned int *) 0x4809C12C) +#define OMAP_HSMMC_STAT (*(unsigned int *) 0x4809C130) +#define OMAP_HSMMC_IE (*(unsigned int *) 0x4809C134) +#define OMAP_HSMMC_CAPA (*(unsigned int *) 0x4809C140) + +/* T2 Register definitions */ +#define CONTROL_DEV_CONF0 (*(unsigned int *) 0x48002274) +#define CONTROL_PBIAS_LITE (*(unsigned int *) 0x48002520) + +/* + * OMAP HS MMC Bit definitions + */ +#define MMC_SOFTRESET (0x1 << 1) +#define RESETDONE (0x1 << 0) +#define NOOPENDRAIN (0x0 << 0) +#define OPENDRAIN (0x1 << 0) +#define OD (0x1 << 0) +#define INIT_NOINIT (0x0 << 1) +#define INIT_INITSTREAM (0x1 << 1) +#define HR_NOHOSTRESP (0x0 << 2) +#define STR_BLOCK (0x0 << 3) +#define MODE_FUNC (0x0 << 4) +#define DW8_1_4BITMODE (0x0 << 5) +#define MIT_CTO (0x0 << 6) +#define CDP_ACTIVEHIGH (0x0 << 7) +#define WPP_ACTIVEHIGH (0x0 << 8) +#define RESERVED_MASK (0x3 << 9) +#define CTPL_MMC_SD (0x0 << 11) +#define BLEN_512BYTESLEN (0x200 << 0) +#define NBLK_STPCNT (0x0 << 16) +#define DE_DISABLE (0x0 << 0) +#define BCE_DISABLE (0x0 << 1) +#define ACEN_DISABLE (0x0 << 2) +#define DDIR_OFFSET (4) +#define DDIR_MASK (0x1 << 4) +#define DDIR_WRITE (0x0 << 4) +#define DDIR_READ (0x1 << 4) +#define MSBS_SGLEBLK (0x0 << 5) +#define RSP_TYPE_OFFSET (16) +#define RSP_TYPE_MASK (0x3 << 16) +#define RSP_TYPE_NORSP (0x0 << 16) +#define RSP_TYPE_LGHT136 (0x1 << 16) +#define RSP_TYPE_LGHT48 (0x2 << 16) +#define RSP_TYPE_LGHT48B (0x3 << 16) +#define CCCE_NOCHECK (0x0 << 19) +#define CCCE_CHECK (0x1 << 19) +#define CICE_NOCHECK (0x0 << 20) +#define CICE_CHECK (0x1 << 20) +#define DP_OFFSET (21) +#define DP_MASK (0x1 << 21) +#define DP_NO_DATA (0x0 << 21) +#define DP_DATA (0x1 << 21) +#define CMD_TYPE_NORMAL (0x0 << 22) +#define INDEX_OFFSET (24) +#define INDEX_MASK (0x3f << 24) +#define INDEX(i) (i << 24) +#define DATI_MASK (0x1 << 1) +#define DATI_CMDDIS (0x1 << 1) +#define DTW_1_BITMODE (0x0 << 1) +#define DTW_4_BITMODE (0x1 << 1) +#define SDBP_PWROFF (0x0 << 8) +#define SDBP_PWRON (0x1 << 8) +#define SDVS_1V8 (0x5 << 9) +#define SDVS_3V0 (0x6 << 9) +#define ICE_MASK (0x1 << 0) +#define ICE_STOP (0x0 << 0) +#define ICS_MASK (0x1 << 1) +#define ICS_NOTREADY (0x0 << 1) +#define ICE_OSCILLATE (0x1 << 0) +#define CEN_MASK (0x1 << 2) +#define CEN_DISABLE (0x0 << 2) +#define CEN_ENABLE (0x1 << 2) +#define CLKD_OFFSET (6) +#define CLKD_MASK (0x3FF << 6) +#define DTO_MASK (0xF << 16) +#define DTO_15THDTO (0xE << 16) +#define SOFTRESETALL (0x1 << 24) +#define CC_MASK (0x1 << 0) +#define TC_MASK (0x1 << 1) +#define BWR_MASK (0x1 << 4) +#define BRR_MASK (0x1 << 5) +#define ERRI_MASK (0x1 << 15) +#define IE_CC (0x01 << 0) +#define IE_TC (0x01 << 1) +#define IE_BWR (0x01 << 4) +#define IE_BRR (0x01 << 5) +#define IE_CTO (0x01 << 16) +#define IE_CCRC (0x01 << 17) +#define IE_CEB (0x01 << 18) +#define IE_CIE (0x01 << 19) +#define IE_DTO (0x01 << 20) +#define IE_DCRC (0x01 << 21) +#define IE_DEB (0x01 << 22) +#define IE_CERR (0x01 << 28) +#define IE_BADA (0x01 << 29) + +#define VS30_3V0SUP (1 << 25) +#define VS18_1V8SUP (1 << 26) + +/* Driver definitions */ +#define MMCSD_SECTOR_SIZE (512) +#define MMC_CARD 0 +#define SD_CARD 1 +#define BYTE_MODE 0 +#define SECTOR_MODE 1 +#define CLK_INITSEQ 0 +#define CLK_400KHZ 1 +#define CLK_MISC 2 + +typedef struct { + unsigned int card_type; + unsigned int version; + unsigned int mode; + unsigned int size; + unsigned int RCA; +} mmc_card_data; + +#define mmc_reg_out(addr, mask, val) (addr) = ( ((addr)) & (~(mask)) ) | ( (val) & (mask) ); +#define mmc_reg_out(addr, mask, val) (addr) = ( ((addr)) & (~(mask)) ) | ( (val) & (mask) ); + +#endif /* MMC_HOST_DEFINITIONS_H */ diff -purN orig_u-boot/cpu/omap3/mmc_protocol.h u-boot_beagle/cpu/omap3/mmc_protocol.h --- orig_u-boot/cpu/omap3/mmc_protocol.h 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_beagle/cpu/omap3/mmc_protocol.h 2008-04-02 12:31:59.000000000 +0530 @@ -0,0 +1,253 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, + * Syed Mohammed Khasim + * + * 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's 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef MMC_PROTOCOL_H +#define MMC_PROTOCOL_H + +#include "mmc_host_def.h" + +/* Responses */ +#define RSP_TYPE_NONE (RSP_TYPE_NORSP | CCCE_NOCHECK | CICE_NOCHECK) +#define RSP_TYPE_R1 (RSP_TYPE_LGHT48 | CCCE_CHECK | CICE_CHECK) +#define RSP_TYPE_R1B (RSP_TYPE_LGHT48B | CCCE_CHECK | CICE_CHECK) +#define RSP_TYPE_R2 (RSP_TYPE_LGHT136 | CCCE_CHECK | CICE_NOCHECK) +#define RSP_TYPE_R3 (RSP_TYPE_LGHT48 | CCCE_NOCHECK | CICE_NOCHECK) +#define RSP_TYPE_R4 (RSP_TYPE_LGHT48 | CCCE_NOCHECK | CICE_NOCHECK) +#define RSP_TYPE_R5 (RSP_TYPE_LGHT48 | CCCE_CHECK | CICE_CHECK) +#define RSP_TYPE_R6 (RSP_TYPE_LGHT48 | CCCE_CHECK | CICE_CHECK) +#define RSP_TYPE_R7 (RSP_TYPE_LGHT48 | CCCE_CHECK | CICE_CHECK) + +/* All supported commands */ +#define MMC_CMD0 ( INDEX(0) | RSP_TYPE_NONE | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD1 ( INDEX(1) | RSP_TYPE_R3 | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD2 ( INDEX(2) | RSP_TYPE_R2 | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD3 ( INDEX(3) | RSP_TYPE_R1 | DP_NO_DATA | DDIR_WRITE) +#define MMC_SDCMD3 ( INDEX(3) | RSP_TYPE_R6 | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD4 ( INDEX(4) | RSP_TYPE_NONE | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD6 ( INDEX(6) | RSP_TYPE_R1B | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD7_SELECT ( INDEX(7) | RSP_TYPE_R1B | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD7_DESELECT ( INDEX(7) | RSP_TYPE_NONE | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD8 ( INDEX(8) | RSP_TYPE_R1 | DP_DATA | DDIR_READ) +#define MMC_SDCMD8 ( INDEX(8) | RSP_TYPE_R7 | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD9 ( INDEX(9) | RSP_TYPE_R2 | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD12 ( INDEX(12) | RSP_TYPE_R1B | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD13 ( INDEX(13) | RSP_TYPE_R1 | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD15 ( INDEX(15) | RSP_TYPE_NONE | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD16 ( INDEX(16) | RSP_TYPE_R1 | DP_NO_DATA | DDIR_WRITE) +#define MMC_CMD17 ( INDEX(17) | RSP_TYPE_R1 | DP_DATA | DDIR_READ) +#define MMC_CMD24 ( INDEX(24) | RSP_TYPE_R1 | DP_DATA | DDIR_WRITE) +#define MMC_ACMD6 ( INDEX(6) | RSP_TYPE_R1 | DP_NO_DATA | DDIR_WRITE) +#define MMC_ACMD41 ( INDEX(41) | RSP_TYPE_R3 | DP_NO_DATA | DDIR_WRITE) +#define MMC_ACMD51 ( INDEX(51) | RSP_TYPE_R1 | DP_DATA | DDIR_READ) +#define MMC_CMD55 ( INDEX(55) | RSP_TYPE_R1 | DP_NO_DATA | DDIR_WRITE) + +#define MMC_AC_CMD_RCA_MASK (unsigned int)(0xFFFF << 16) +#define MMC_BC_CMD_DSR_MASK (unsigned int)(0xFFFF << 16) +#define MMC_DSR_DEFAULT (0x0404) +#define SD_CMD8_CHECK_PATTERN (0xAA) +#define SD_CMD8_2_7_3_6_V_RANGE (0x01 << 8) + +/* Clock Configurations and Macros */ + +#define MMC_CLOCK_REFERENCE (96) +#define MMC_RELATIVE_CARD_ADDRESS (0x1234) +#define MMC_INIT_SEQ_CLK (MMC_CLOCK_REFERENCE * 1000 / 80) +#define MMC_400kHz_CLK (MMC_CLOCK_REFERENCE * 1000 / 400) +#define CLKDR(r,f,u) ( ( ((r)*100) / ((f)*(u)) ) + 1 ) +#define CLKD(f,u) (CLKDR(MMC_CLOCK_REFERENCE,f,u)) + +#define MMC_OCR_REG_ACCESS_MODE_MASK (0x3 << 29) +#define MMC_OCR_REG_ACCESS_MODE_BYTE (0x0 << 29) +#define MMC_OCR_REG_ACCESS_MODE_SECTOR (0x2 << 29) + +#define MMC_OCR_REG_HOST_CAPACITY_SUPPORT_MASK (0x1 << 30) +#define MMC_OCR_REG_HOST_CAPACITY_SUPPORT_BYTE (0x0 << 30) +#define MMC_OCR_REG_HOST_CAPACITY_SUPPORT_SECTOR (0x1 << 30) + +#define MMC_SD2_CSD_C_SIZE_LSB_MASK (0xFFFF) +#define MMC_SD2_CSD_C_SIZE_MSB_MASK (0x003F) +#define MMC_SD2_CSD_C_SIZE_MSB_OFFSET (16) +#define MMC_CSD_C_SIZE_LSB_MASK (0x0003) +#define MMC_CSD_C_SIZE_MSB_MASK (0x03FF) +#define MMC_CSD_C_SIZE_MSB_OFFSET (2) + +#define MMC_CSD_TRAN_SPEED_UNIT_MASK (0x07 << 0) +#define MMC_CSD_TRAN_SPEED_FACTOR_MASK (0x0F << 3) +#define MMC_CSD_TRAN_SPEED_UNIT_100MHZ (0x3 << 0) +#define MMC_CSD_TRAN_SPEED_FACTOR_1_0 (0x01 << 3) +#define MMC_CSD_TRAN_SPEED_FACTOR_8_0 (0x0F << 3) + +const unsigned short mmc_transspeed_val[15][4] = { + {CLKD(10, 1), CLKD(10, 10), CLKD(10, 100), CLKD(10, 1000)}, + {CLKD(12, 1), CLKD(12, 10), CLKD(12, 100), CLKD(12, 1000)}, + {CLKD(13, 1), CLKD(13, 10), CLKD(13, 100), CLKD(13, 1000)}, + {CLKD(15, 1), CLKD(15, 10), CLKD(15, 100), CLKD(15, 1000)}, + {CLKD(20, 1), CLKD(20, 10), CLKD(20, 100), CLKD(20, 1000)}, + {CLKD(26, 1), CLKD(26, 10), CLKD(26, 100), CLKD(26, 1000)}, + {CLKD(30, 1), CLKD(30, 10), CLKD(30, 100), CLKD(30, 1000)}, + {CLKD(35, 1), CLKD(35, 10), CLKD(35, 100), CLKD(35, 1000)}, + {CLKD(40, 1), CLKD(40, 10), CLKD(40, 100), CLKD(40, 1000)}, + {CLKD(45, 1), CLKD(45, 10), CLKD(45, 100), CLKD(45, 1000)}, + {CLKD(52, 1), CLKD(52, 10), CLKD(52, 100), CLKD(52, 1000)}, + {CLKD(55, 1), CLKD(55, 10), CLKD(55, 100), CLKD(55, 1000)}, + {CLKD(60, 1), CLKD(60, 10), CLKD(60, 100), CLKD(60, 1000)}, + {CLKD(70, 1), CLKD(70, 10), CLKD(70, 100), CLKD(70, 1000)}, + {CLKD(80, 1), CLKD(80, 10), CLKD(80, 100), CLKD(80, 1000)} +}; + +typedef struct { + unsigned not_used:1; + unsigned crc:7; + unsigned ecc:2; + unsigned file_format:2; + unsigned tmp_write_protect:1; + unsigned perm_write_protect:1; + unsigned copy:1; + unsigned file_format_grp:1; + unsigned content_prot_app:1; + unsigned reserved_1:4; + unsigned write_bl_partial:1; + unsigned write_bl_len:4; + unsigned r2w_factor:3; + unsigned default_ecc:2; + unsigned wp_grp_enable:1; + unsigned wp_grp_size:5; + unsigned erase_grp_mult:5; + unsigned erase_grp_size:5; + unsigned c_size_mult:3; + unsigned vdd_w_curr_max:3; + unsigned vdd_w_curr_min:3; + unsigned vdd_r_curr_max:3; + unsigned vdd_r_curr_min:3; + unsigned c_size_lsb:2; + unsigned c_size_msb:10; + unsigned reserved_2:2; + unsigned dsr_imp:1; + unsigned read_blk_misalign:1; + unsigned write_blk_misalign:1; + unsigned read_bl_partial:1; + unsigned read_bl_len:4; + unsigned ccc:12; + unsigned tran_speed:8; + unsigned nsac:8; + unsigned taac:8; + unsigned reserved_3:2; + unsigned spec_vers:4; + unsigned csd_structure:2; +} mmc_csd_reg_t; + +/* csd for sd2.0 */ +typedef struct { + unsigned not_used:1; + unsigned crc:7; + unsigned reserved_1:2; + unsigned file_format:2; + unsigned tmp_write_protect:1; + unsigned perm_write_protect:1; + unsigned copy:1; + unsigned file_format_grp:1; + unsigned reserved_2:5; + unsigned write_bl_partial:1; + unsigned write_bl_len:4; + unsigned r2w_factor:3; + unsigned reserved_3:2; + unsigned wp_grp_enable:1; + unsigned wp_grp_size:7; + unsigned sector_size:7; + unsigned erase_blk_len:1; + unsigned reserved_4:1; + unsigned c_size_lsb:16; + unsigned c_size_msb:6; + unsigned reserved_5:6; + unsigned dsr_imp:1; + unsigned read_blk_misalign:1; + unsigned write_blk_misalign:1; + unsigned read_bl_partial:1; + unsigned read_bl_len:4; + unsigned ccc:12; + unsigned tran_speed:8; + unsigned nsac:8; + unsigned taac:8; + unsigned reserved_6:6; + unsigned csd_structure:2; +} mmc_sd2_csd_reg_t; + +/* extended csd - 512 bytes long */ +typedef struct { + unsigned char reserved_1[181]; + unsigned char erasedmemorycontent; + unsigned char reserved_2; + unsigned char buswidthmode; + unsigned char reserved_3; + unsigned char highspeedinterfacetiming; + unsigned char reserved_4; + unsigned char powerclass; + unsigned char reserved_5; + unsigned char commandsetrevision; + unsigned char reserved_6; + unsigned char commandset; + unsigned char extendedcsdrevision; + unsigned char reserved_7; + unsigned char csdstructureversion; + unsigned char reserved_8; + unsigned char cardtype; + unsigned char reserved_9[3]; + unsigned char powerclass_52mhz_1_95v; + unsigned char powerclass_26mhz_1_95v; + unsigned char powerclass_52mhz_3_6v; + unsigned char powerclass_26mhz_3_6v; + unsigned char reserved_10; + unsigned char minreadperf_4b_26mhz; + unsigned char minwriteperf_4b_26mhz; + unsigned char minreadperf_8b_26mhz_4b_52mhz; + unsigned char minwriteperf_8b_26mhz_4b_52mhz; + unsigned char minreadperf_8b_52mhz; + unsigned char minwriteperf_8b_52mhz; + unsigned char reserved_11; + unsigned int sectorcount; + unsigned char reserved_12[288]; + unsigned char supportedcommandsets; + unsigned char reserved_13[7]; +} mmc_extended_csd_reg_t; + +/* mmc sd responce */ +typedef struct { + unsigned int ocr; +} mmc_resp_r3; + +typedef struct { + unsigned short cardstatus; + unsigned short newpublishedrca; +} mmc_resp_r6; + +extern mmc_card_data mmc_dev; + +unsigned char mmc_lowlevel_init(void); +unsigned char mmc_send_command(unsigned int cmd, unsigned int arg, + unsigned int *response); +unsigned char mmc_setup_clock(unsigned int iclk, unsigned short clkd); +unsigned char mmc_set_opendrain(unsigned char state); +unsigned char mmc_read_data(unsigned int *output_buf); + +#endif /*MMC_PROTOCOL_H */ diff -purN orig_u-boot/cpu/omap3/start.S u-boot_beagle/cpu/omap3/start.S --- orig_u-boot/cpu/omap3/start.S 1970-01-01 05:30:00.000000000 +0530 +++ u-boot_beagle/cpu/omap3/start.S 2008-04-02 11:06:27.000000000 +0530 @@ -0,0 +1,484 @@ +/* + * armboot - Startup Code for OMAP3430/ARM Cortex CPU-core + * + * Copyright (c) 2004 Texas Instruments + * + * Copyright (c) 2001 Marius Gr�ger + * Copyright (c) 2002 Alex Z�pke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * Copyright (c) 2006 Syed Mohammed Khasim + * + * 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 +#include +#if !defined(CONFIG_INTEGRATOR) && ! defined(CONFIG_ARCH_CINTEGRATOR) +#include +#endif +.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 +_pad: .word 0x12345678 /* now 16*4=64 */ +.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 + * + ************************************************************************* + */ + +_TEXT_BASE: + .word TEXT_BASE + +.globl _armboot_start +_armboot_start: + .word _start + +/* + * These are defined in the board-specific linker script. + */ +.globl _bss_start +_bss_start: + .word __bss_start + +.globl _bss_end +_bss_end: + .word _end + +#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 + +/* + * 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 + +#if (CONFIG_OMAP34XX) + /* Copy vectors to mask ROM indirect addr */ + adr r0, _start /* r0 <- current position of code */ + add r0, r0, #4 /* skip reset vector */ + mov r2, #64 /* r2 <- size to copy */ + add r2, r0, r2 /* r2 <- source end address */ + mov r1, #SRAM_OFFSET0 /* build vect addr */ + mov r3, #SRAM_OFFSET1 + add r1, r1, r3 + mov r3, #SRAM_OFFSET2 + add r1, r1, r3 +next: + 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] */ + bne next /* loop until equal */ +#if !defined(CFG_NAND_BOOT) && !defined(CFG_ONENAND_BOOT) + /* No need to copy/exec the clock code - DPLL adjust already done + * in NAND/oneNAND Boot. + */ + bl cpy_clk_code /* put dpll adjust code behind vectors */ +#endif /* NAND Boot */ +#endif /* 24xx */ + /* the mask ROM code should have PLL and others stable */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + +#ifndef CONFIG_SKIP_RELOCATE_UBOOT +relocate: /* relocate U-Boot to RAM */ + adr r0, _start /* r0 <- current position of code */ + ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ + cmp r0, r1 /* don't reloc during debug */ + beq stack_setup + + ldr r2, _armboot_start + ldr r3, _bss_start + sub r2, r3, r2 /* r2 <- size of armboot */ + add r2, r0, r2 /* r2 <- source end address */ + +copy_loop: /* copy 32 bytes at a time */ + ldmia r0!, {r3-r10} /* copy from source address [r0] */ + stmia r1!, {r3-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end addreee [r2] */ + ble copy_loop +#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ + + /* Set up the stack */ +stack_setup: + ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ + sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ + sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ +#ifdef CONFIG_USE_IRQ + sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) +#endif + sub sp, r0, #12 /* leave 3 words for abort-stack */ + and sp, sp, #~7 /* 8 byte alinged for (ldr/str)d */ + + /* Clear BSS (if any). Is below tx (watch load addr - need space) */ +clear_bss: + ldr r0, _bss_start /* find start of bss segment */ + ldr r1, _bss_end /* stop here */ + mov r2, #0x00000000 /* clear value */ +clbss_l: + str r2, [r0] /* clear BSS location */ + cmp r0, r1 /* are we at the end yet */ + add r0, r0, #4 /* increment clear index pointer */ + bne clbss_l /* keep clearing till at end */ + + ldr pc, _start_armboot /* jump to C code */ + +_start_armboot: .word start_armboot + + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +cpu_init_crit: + /* + * 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 */ + + /* + * 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 12 (Z---) BTB + 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 */ +/* + ************************************************************************* + * + * 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, _armboot_start + sub r2, r2, #(CFG_MALLOC_LEN) + sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ 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, _armboot_start @ setup our mode stack (enter in banked mode) + sub r13, r13, #(CFG_MALLOC_LEN) @ move past malloc pool + sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort 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_bad_stack_swi + sub r13, r13, #4 @ space on current stack for scratch reg. + str r0, [r13] @ save R0's value. + ldr r0, _armboot_start @ get data regions start + sub r0, r0, #(CFG_MALLOC_LEN) @ move past malloc pool + sub r0, r0, #(CFG_GBL_DATA_SIZE+8) @ move past gbl and a couple spots for abort stack + str lr, [r0] @ save caller lr in position 0 of saved stack + mrs r0, spsr @ get the spsr + str lr, [r0, #4] @ save spsr in position 1 of saved stack + 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 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 arm_cache_flush +arm_cache_flush: + mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache + mov pc, lr @ back to caller + +/* + * v7_flush_dcache_all() + * + * Flush the whole D-cache. + * + * Corrupted registers: r0-r5, r7, r9-r11 + * + * - mm - mm_struct describing address space + */ + .align 5 +.global v7_flush_dcache_all +v7_flush_dcache_all: + stmfd r13!, {r0-r5, r7, r9-r12,r14} + + mov r7, r0 @ take a backup of device type + cmp r0, #0x3 @ check if the device type is GP + moveq r12, #0x1 @ set up to invalide L2 +smi: .word 0x01600070 @ Call SMI monitor (smieq) + cmp r7, #0x3 @ compare again in case its lost + beq finished_inval @ if GP device, inval done above + + mrc p15, 1, r0, c0, c0, 1 @ read clidr + ands r3, r0, #0x7000000 @ extract loc from clidr + mov r3, r3, lsr #23 @ left align loc bit field + beq finished_inval @ if loc is 0, then no need to clean + mov r10, #0 @ start clean at cache level 0 +inval_loop1: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip_inval @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + isb @ isb to sych the new cssr&csidr + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +inval_loop2: + mov r9, r4 @ create working copy of max way size +inval_loop3: + orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 + orr r11, r11, r7, lsl r2 @ factor index number into r11 + mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way + subs r9, r9, #1 @ decrement the way + bge inval_loop3 + subs r7, r7, #1 @ decrement the index + bge inval_loop2 +skip_inval: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt inval_loop1 +finished_inval: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + isb + + ldmfd r13!, {r0-r5, r7, r9-r12,pc} + + + .align 5 +.global reset_cpu +reset_cpu: + ldr r1, rstctl /* get addr for global reset reg */ + mov r3, #0x2 /* full reset pll+mpu */ + str r3, [r1] /* force reset */ + mov r0, r0 +_loop_forever: + b _loop_forever +rstctl: + .word PRM_RSTCTRL +