diff options
Diffstat (limited to 'arch/arm/cpu/armv7/omap3')
-rw-r--r-- | arch/arm/cpu/armv7/omap3/Makefile | 56 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap3/board.c | 329 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap3/cache.S | 191 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap3/clock.c | 416 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap3/emif4.c | 168 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap3/gpio.c | 185 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap3/lowlevel_init.S | 361 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap3/mem.c | 191 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap3/sdrc.c | 202 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap3/sys_info.c | 258 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap3/syslib.c | 72 |
11 files changed, 2429 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/omap3/Makefile b/arch/arm/cpu/armv7/omap3/Makefile new file mode 100644 index 0000000..79ae267 --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/Makefile @@ -0,0 +1,56 @@ +# +# (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 = $(obj)lib$(SOC).a + +SOBJS := lowlevel_init.o +SOBJS += cache.o + +COBJS += board.o +COBJS += clock.o +COBJS += gpio.o +COBJS += mem.o +COBJS += syslib.o +COBJS += sys_info.o + +COBJS-$(CONFIG_EMIF4) += emif4.o +COBJS-$(CONFIG_SDRC) += sdrc.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(COBJS-y) $(SOBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c new file mode 100644 index 0000000..69e56f5 --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/board.c @@ -0,0 +1,329 @@ +/* + * + * 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> + * + * + * 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 <asm/io.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/mem.h> +#include <asm/cache.h> + +extern omap3_sysinfo sysinfo; + +/****************************************************************************** + * Routine: delay + * Description: spinning delay to use before udelay works + *****************************************************************************/ +static inline void delay(unsigned long loops) +{ + __asm__ volatile ("1:\n" "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0"(loops)); +} + +/****************************************************************************** + * 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; + + /* configrue 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: setup_auxcr() + * Description: Write to AuxCR desired value using SMI. + * general use. + *****************************************************************************/ +void setup_auxcr() +{ + unsigned long i; + volatile unsigned int j; + /* 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"); + /* Enabling ASA */ + __asm__ __volatile__("orr r0, r0, #0x10"); + /* Enable L1NEON */ + __asm__ __volatile__("orr r0, r0, #1 << 5"); + /* SMI instruction to call ROM Code API */ + __asm__ __volatile__(".word 0xE1600070"); + /* Set PLD_FWD bit in L2AUXCR (Cortex-A8 erratum 725233 workaround) */ + __asm__ __volatile__("mov r12, #0x2"); + __asm__ __volatile__("mrc p15, 1, r0, c9, c0, 2"); + __asm__ __volatile__("orr r0, r0, #1 << 27"); + /* 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)); +} + +/****************************************************************************** + * 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(); + + /* + * Right now flushing at low MPU speed. + * Need to move after clock init + */ + invalidate_dcache(get_device_type()); +#ifndef CONFIG_ICACHE_OFF + icache_enable(); +#endif + +#ifdef CONFIG_L2_OFF + l2_cache_disable(); +#else + l2_cache_enable(); +#endif + /* + * Writing to AuxCR in U-boot using SMI for GP DEV + * Currently SMI in Kernel on ES2 devices seems to have an issue + * Once that is resolved, we can postpone this config to kernel + */ + if (get_device_type() == GP_DEVICE) + setup_auxcr(); + + set_muxconf_regs(); + delay(100); + + prcm_init(); + + per_clocks_enable(); + + if (!in_sdram) + mem_init(); +} + +/****************************************************************************** + * 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. + */ + + sr32(&prcm_base->fclken_wkup, 5, 1, 1); + sr32(&prcm_base->iclken_wkup, 5, 1, 1); + 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) +{ +} + +#ifdef CONFIG_NAND_OMAP_GPMC +/****************************************************************************** + * 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) + goto usage; + if (strncmp(argv[1], "hw", 2) == 0) + omap_nand_switch_ecc(1); + else if (strncmp(argv[1], "sw", 2) == 0) + omap_nand_switch_ecc(0); + else + goto usage; + + return 0; + +usage: + printf ("Usage: nandecc %s\n", cmdtp->usage); + return 1; +} + +U_BOOT_CMD( + nandecc, 2, 1, do_switch_ecc, + "switch OMAP3 NAND ECC calculation algorithm", + "[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm" +); + +#endif /* CONFIG_NAND_OMAP_GPMC */ + +#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 */ diff --git a/arch/arm/cpu/armv7/omap3/cache.S b/arch/arm/cpu/armv7/omap3/cache.S new file mode 100644 index 0000000..4b65ac5 --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/cache.S @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2009 Wind River Systems, Inc. + * Tom Rix <Tom.Rix@windriver.com> + * + * This file is based on and replaces the existing cache.c file + * The copyrights for the cache.c file are: + * + * (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, <gj@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 <asm/arch/omap3.h> + +/* + * omap3 cache code + */ + +.align 5 +.global invalidate_dcache +.global l2_cache_enable +.global l2_cache_disable + +/* + * invalidate_dcache() + * + * Invalidate the whole D-cache. + * + * Corrupted registers: r0-r5, r7, r9-r11 + * + * - mm - mm_struct describing address space + */ +invalidate_dcache: + 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 + mov r2, #0 @ operand for mcr SBZ + mcr p15, 0, r2, c7, c5, 4 @ flush prefetch buffer to + @ sych the new cssr&csidr, + @ with armv7 this is 'isb', + @ but we compile with armv5 + 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 + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + + ldmfd r13!, {r0 - r5, r7, r9 - r12, pc} + + +l2_cache_enable: + stmfd r13!, {r0, r1, r2, lr} + @ ES2 onwards we can disable/enable L2 ourselves + bl get_cpu_rev + cmp r0, #CPU_3XX_ES20 + blt l2_cache_disable_EARLIER_THAN_ES2 + mrc 15, 0, r3, cr1, cr0, 1 + orr r3, r3, #2 + mcr 15, 0, r3, cr1, cr0, 1 + b l2_cache_enable_END +l2_cache_enable_EARLIER_THAN_ES2: + @ Save r0, r12 and restore them after usage + mov r3, ip + str r3, [sp, #4] + mov r3, r0 + @ + @ GP Device ROM code API usage here + @ r12 = AUXCR Write function and r0 value + @ + mov ip, #3 + mrc 15, 0, r0, cr1, cr0, 1 + orr r0, r0, #2 + @ SMI instruction to call ROM Code API + .word 0xe1600070 + mov r0, r3 + mov ip, r3 + str r3, [sp, #4] +l2_cache_enable_END: + ldmfd r13!, {r1, r2, r3, pc} + + +l2_cache_disable: + stmfd r13!, {r0, r1, r2, lr} + @ ES2 onwards we can disable/enable L2 ourselves + bl get_cpu_rev + cmp r0, #CPU_3XX_ES20 + blt l2_cache_disable_EARLIER_THAN_ES2 + mrc 15, 0, r3, cr1, cr0, 1 + bic r3, r3, #2 + mcr 15, 0, r3, cr1, cr0, 1 + b l2_cache_disable_END +l2_cache_disable_EARLIER_THAN_ES2: + @ Save r0, r12 and restore them after usage + mov r3, ip + str r3, [sp, #4] + mov r3, r0 + @ + @ GP Device ROM code API usage here + @ r12 = AUXCR Write function and r0 value + @ + mov ip, #3 + mrc 15, 0, r0, cr1, cr0, 1 + bic r0, r0, #2 + @ SMI instruction to call ROM Code API + .word 0xe1600070 + mov r0, r3 + mov ip, r3 + str r3, [sp, #4] +l2_cache_disable_END: + ldmfd r13!, {r1, r2, r3, pc} diff --git a/arch/arm/cpu/armv7/omap3/clock.c b/arch/arm/cpu/armv7/omap3/clock.c new file mode 100644 index 0000000..6330c9e --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/clock.c @@ -0,0 +1,416 @@ +/* + * (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> + * + * 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 <asm/io.h> +#include <asm/arch/clocks.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 if (val & SYSCLKDIV_1) + cdiv = 1; + else + /* + * Should never reach here! (Assume divider as 1) + */ + 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 */ + + if (cdiv == 2) + { + cdiff *= 2; + } + + /* 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; + } +} + +/****************************************************************************** + * prcm_init() - inits clocks for PRCM as defined in clocks.h + * called from SRAM, or Flash (using temp SRAM stack). + *****************************************************************************/ +void prcm_init(void) +{ + void (*f_lock_pll) (u32, u32, u32, u32); + int xip_safe, p0, p1, p2, p3; + 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; + dpll_param *dpll_param_p; + + f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start + + SRAM_VECT_CODE); + + xip_safe = is_running_in_sram(); + + /* + * 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 */ + sr32(&prm_base->clksel, 0, 3, sys_clkin_sel); + + /* If the input clock is greater than 19.2M always divide/2 */ + if (sys_clkin_sel > 2) { + /* input clock divider */ + sr32(&prm_base->clksrc_ctrl, 6, 2, 2); + clk_index = sys_clkin_sel / 2; + } else { + /* input clock divider */ + sr32(&prm_base->clksrc_ctrl, 6, 2, 1); + clk_index = sys_clkin_sel; + } + + /* + * 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_rev()) + sil_index = 1; + + /* Unlock MPU DPLL (slows things down, and needed later) */ + sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOW_POWER_BYPASS); + wait_on_value(ST_MPU_CLK, 0, &prcm_base->idlest_pll_mpu, LDELAY); + + /* Getting the base address of Core DPLL param table */ + dpll_param_p = (dpll_param *) get_core_dpll_param(); + + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; + if (xip_safe) { + /* + * CORE DPLL + * sr32(CM_CLKSEL2_EMU) set override to work when asleep + */ + sr32(&prcm_base->clken_pll, 0, 3, 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. + */ + + /* m3x2 */ + sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2 + 1); + /* m3x2 */ + sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2); + /* Set M2 */ + sr32(&prcm_base->clksel1_pll, 27, 2, dpll_param_p->m2); + /* Set M */ + sr32(&prcm_base->clksel1_pll, 16, 11, dpll_param_p->m); + /* Set N */ + sr32(&prcm_base->clksel1_pll, 8, 7, dpll_param_p->n); + /* 96M Src */ + sr32(&prcm_base->clksel1_pll, 6, 1, 0); + /* ssi */ + sr32(&prcm_base->clksel_core, 8, 4, CORE_SSI_DIV); + /* fsusb */ + sr32(&prcm_base->clksel_core, 4, 2, CORE_FUSB_DIV); + /* l4 */ + sr32(&prcm_base->clksel_core, 2, 2, CORE_L4_DIV); + /* l3 */ + sr32(&prcm_base->clksel_core, 0, 2, CORE_L3_DIV); + /* gfx */ + sr32(&prcm_base->clksel_gfx, 0, 3, GFX_DIV); + /* reset mgr */ + sr32(&prcm_base->clksel_wkup, 1, 2, WKUP_RSM); + /* FREQSEL */ + sr32(&prcm_base->clken_pll, 4, 4, dpll_param_p->fsel); + /* lock mode */ + sr32(&prcm_base->clken_pll, 0, 3, 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. + */ + p0 = readl(&prcm_base->clken_pll); + sr32(&p0, 0, 3, PLL_FAST_RELOCK_BYPASS); + sr32(&p0, 4, 4, dpll_param_p->fsel); /* FREQSEL */ + + p1 = readl(&prcm_base->clksel1_pll); + sr32(&p1, 27, 2, dpll_param_p->m2); /* Set M2 */ + sr32(&p1, 16, 11, dpll_param_p->m); /* Set M */ + sr32(&p1, 8, 7, dpll_param_p->n); /* Set N */ + sr32(&p1, 6, 1, 0); /* set source for 96M */ + + p2 = readl(&prcm_base->clksel_core); + sr32(&p2, 8, 4, CORE_SSI_DIV); /* ssi */ + sr32(&p2, 4, 2, CORE_FUSB_DIV); /* fsusb */ + sr32(&p2, 2, 2, CORE_L4_DIV); /* l4 */ + sr32(&p2, 0, 2, CORE_L3_DIV); /* l3 */ + + p3 = (u32)&prcm_base->idlest_ckgen; + + (*f_lock_pll) (p0, p1, p2, p3); + } + + /* PER DPLL */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_STOP); + wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY); + + /* Getting the base address to PER DPLL param table */ + + /* Set N */ + dpll_param_p = (dpll_param *) get_per_dpll_param(); + + /* Moving it to the right sysclk base */ + dpll_param_p = dpll_param_p + clk_index; + + /* + * Errata 1.50 Workaround for OMAP3 ES1.0 only + * If using default divisors, write default divisor + 1 + * and then the actual divisor value + */ + sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2 + 1); /* set M6 */ + sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2); /* set M6 */ + sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2 + 1); /* set M5 */ + sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2); /* set M5 */ + sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2 + 1); /* set M4 */ + sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2); /* set M4 */ + sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2 + 1); /* set M3 */ + sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2); /* set M3 */ + sr32(&prcm_base->clksel3_pll, 0, 5, dpll_param_p->m2 + 1); /* set M2 */ + sr32(&prcm_base->clksel3_pll, 0, 5, dpll_param_p->m2); /* set M2 */ + /* Workaround end */ + + sr32(&prcm_base->clksel2_pll, 8, 11, dpll_param_p->m); /* set m */ + sr32(&prcm_base->clksel2_pll, 0, 7, dpll_param_p->n); /* set n */ + sr32(&prcm_base->clken_pll, 20, 4, dpll_param_p->fsel); /* FREQSEL */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_LOCK); /* lock mode */ + wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY); + + /* Getting the base address to MPU DPLL param table */ + dpll_param_p = (dpll_param *) get_mpu_dpll_param(); + + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; + + /* MPU DPLL (unlocked already) */ + + /* Set M2 */ + sr32(&prcm_base->clksel2_pll_mpu, 0, 5, dpll_param_p->m2); + /* Set M */ + sr32(&prcm_base->clksel1_pll_mpu, 8, 11, dpll_param_p->m); + /* Set N */ + sr32(&prcm_base->clksel1_pll_mpu, 0, 7, dpll_param_p->n); + /* FREQSEL */ + sr32(&prcm_base->clken_pll_mpu, 4, 4, dpll_param_p->fsel); + /* lock mode */ + sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOCK); + wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, LDELAY); + + /* Getting the base address to IVA DPLL param table */ + dpll_param_p = (dpll_param *) get_iva_dpll_param(); + + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; + + /* IVA DPLL (set to 12*20=240MHz) */ + sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_STOP); + wait_on_value(ST_IVA2_CLK, 0, &prcm_base->idlest_pll_iva2, LDELAY); + /* set M2 */ + sr32(&prcm_base->clksel2_pll_iva2, 0, 5, dpll_param_p->m2); + /* set M */ + sr32(&prcm_base->clksel1_pll_iva2, 8, 11, dpll_param_p->m); + /* set N */ + sr32(&prcm_base->clksel1_pll_iva2, 0, 7, dpll_param_p->n); + /* FREQSEL */ + sr32(&prcm_base->clken_pll_iva2, 4, 4, dpll_param_p->fsel); + /* lock mode */ + sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_LOCK); + wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY); + + /* Set up GPTimers to sys_clk source only */ + sr32(&prcm_base->clksel_per, 0, 8, 0xff); + sr32(&prcm_base->clksel_wkup, 0, 1, 1); + + sdelay(5000); +} + +/****************************************************************************** + * 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. */ + sr32(&prcm_base->clksel_per, 0, 1, 0x1); /* GPT2 = sys clk */ + sr32(&prcm_base->iclken_per, 3, 1, 0x1); /* ICKen GPT2 */ + sr32(&prcm_base->fclken_per, 3, 1, 0x1); /* FCKen GPT2 */ + +#ifdef CONFIG_SYS_NS16550 + /* Enable UART1 clocks */ + sr32(&prcm_base->fclken1_core, 13, 1, 0x1); + sr32(&prcm_base->iclken1_core, 13, 1, 0x1); + + /* UART 3 Clocks */ + sr32(&prcm_base->fclken_per, 11, 1, 0x1); + sr32(&prcm_base->iclken_per, 11, 1, 0x1); +#endif + +#ifdef CONFIG_OMAP3_GPIO_2 + sr32(&prcm_base->fclken_per, 13, 1, 1); + sr32(&prcm_base->iclken_per, 13, 1, 1); +#endif +#ifdef CONFIG_OMAP3_GPIO_3 + sr32(&prcm_base->fclken_per, 14, 1, 1); + sr32(&prcm_base->iclken_per, 14, 1, 1); +#endif +#ifdef CONFIG_OMAP3_GPIO_4 + sr32(&prcm_base->fclken_per, 15, 1, 1); + sr32(&prcm_base->iclken_per, 15, 1, 1); +#endif +#ifdef CONFIG_OMAP3_GPIO_5 + sr32(&prcm_base->fclken_per, 16, 1, 1); + sr32(&prcm_base->iclken_per, 16, 1, 1); +#endif +#ifdef CONFIG_OMAP3_GPIO_6 + sr32(&prcm_base->fclken_per, 17, 1, 1); + sr32(&prcm_base->iclken_per, 17, 1, 1); +#endif + +#ifdef CONFIG_DRIVER_OMAP34XX_I2C + /* Turn on all 3 I2C clocks */ + sr32(&prcm_base->fclken1_core, 15, 3, 0x7); + sr32(&prcm_base->iclken1_core, 15, 3, 0x7); /* I2C1,2,3 = on */ +#endif + /* Enable the ICLK for 32K Sync Timer as its used in udelay */ + sr32(&prcm_base->iclken_wkup, 2, 1, 0x1); + + sr32(&prcm_base->fclken_iva2, 0, 32, FCK_IVA2_ON); + sr32(&prcm_base->fclken1_core, 0, 32, FCK_CORE1_ON); + sr32(&prcm_base->iclken1_core, 0, 32, ICK_CORE1_ON); + sr32(&prcm_base->iclken2_core, 0, 32, ICK_CORE2_ON); + sr32(&prcm_base->fclken_wkup, 0, 32, FCK_WKUP_ON); + sr32(&prcm_base->iclken_wkup, 0, 32, ICK_WKUP_ON); + sr32(&prcm_base->fclken_dss, 0, 32, FCK_DSS_ON); + sr32(&prcm_base->iclken_dss, 0, 32, ICK_DSS_ON); + sr32(&prcm_base->fclken_cam, 0, 32, FCK_CAM_ON); + sr32(&prcm_base->iclken_cam, 0, 32, ICK_CAM_ON); + sr32(&prcm_base->fclken_per, 0, 32, FCK_PER_ON); + sr32(&prcm_base->iclken_per, 0, 32, ICK_PER_ON); + + sdelay(1000); +} diff --git a/arch/arm/cpu/armv7/omap3/emif4.c b/arch/arm/cpu/armv7/omap3/emif4.c new file mode 100644 index 0000000..fae5b11 --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/emif4.c @@ -0,0 +1,168 @@ +/* + * Author : + * Vaibhav Hiremath <hvaibhav@ti.com> + * + * Based on mem.c and sdrc.c + * + * Copyright (C) 2010 + * 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; 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 <asm/io.h> +#include <asm/arch/mem.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/emif4.h> + +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; + + /* TODO: Calculate the size based on EMIF4 configuration */ + 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) +{ + DECLARE_GLOBAL_DATA_PTR; + 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->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; + + return 0; +} + +/* + * mem_init() - + * - Initialize memory subsystem + */ +void mem_init(void) +{ + do_emif4_init(); +} diff --git a/arch/arm/cpu/armv7/omap3/gpio.c b/arch/arm/cpu/armv7/omap3/gpio.c new file mode 100644 index 0000000..aeb6066 --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/gpio.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2009 Wind River Systems, Inc. + * Tom Rix <Tom.Rix@windriver.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; 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 + * + * This work is derived from the linux 2.6.27 kernel source + * To fetch, use the kernel repository + * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git + * Use the v2.6.27 tag. + * + * Below is the original's header including its copyright + * + * linux/arch/arm/plat-omap/gpio.c + * + * Support functions for OMAP GPIO + * + * Copyright (C) 2003-2005 Nokia Corporation + * Written by Juha Yrjölä <juha.yrjola@nokia.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 <asm/arch/gpio.h> +#include <asm/io.h> +#include <asm/errno.h> + +static 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 }, +}; + +static struct gpio_bank *gpio_bank = &gpio_bank_34xx[0]; + +static inline struct gpio_bank *get_gpio_bank(int gpio) +{ + return &gpio_bank[gpio >> 5]; +} + +static inline int get_gpio_index(int gpio) +{ + return gpio & 0x1f; +} + +static inline int gpio_valid(int gpio) +{ + if (gpio < 0) + return -1; + if (gpio < 192) + return 0; + return -1; +} + +static int check_gpio(int gpio) +{ + if (gpio_valid(gpio) < 0) { + printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); + return -1; + } + return 0; +} + +static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) +{ + void *reg = bank->base; + u32 l; + + switch (bank->method) { + case METHOD_GPIO_24XX: + reg += OMAP24XX_GPIO_OE; + break; + default: + return; + } + l = __raw_readl(reg); + if (is_input) + l |= 1 << gpio; + else + l &= ~(1 << gpio); + __raw_writel(l, reg); +} + +void omap_set_gpio_direction(int gpio, int is_input) +{ + struct gpio_bank *bank; + + if (check_gpio(gpio) < 0) + return; + bank = get_gpio_bank(gpio); + _set_gpio_direction(bank, get_gpio_index(gpio), is_input); +} + +static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) +{ + void *reg = bank->base; + u32 l = 0; + + switch (bank->method) { + case METHOD_GPIO_24XX: + if (enable) + reg += OMAP24XX_GPIO_SETDATAOUT; + else + reg += OMAP24XX_GPIO_CLEARDATAOUT; + l = 1 << gpio; + break; + default: + printf("omap3-gpio unknown bank method %s %d\n", + __FILE__, __LINE__); + return; + } + __raw_writel(l, reg); +} + +void omap_set_gpio_dataout(int gpio, int enable) +{ + struct gpio_bank *bank; + + if (check_gpio(gpio) < 0) + return; + bank = get_gpio_bank(gpio); + _set_gpio_dataout(bank, get_gpio_index(gpio), enable); +} + +int omap_get_gpio_datain(int gpio) +{ + struct gpio_bank *bank; + void *reg; + + if (check_gpio(gpio) < 0) + return -EINVAL; + bank = get_gpio_bank(gpio); + reg = bank->base; + switch (bank->method) { + case METHOD_GPIO_24XX: + reg += OMAP24XX_GPIO_DATAIN; + break; + default: + return -EINVAL; + } + return (__raw_readl(reg) + & (1 << get_gpio_index(gpio))) != 0; +} + +static void _reset_gpio(struct gpio_bank *bank, int gpio) +{ + _set_gpio_direction(bank, get_gpio_index(gpio), 1); +} + +int omap_request_gpio(int gpio) +{ + if (check_gpio(gpio) < 0) + return -EINVAL; + + return 0; +} + +void omap_free_gpio(int gpio) +{ + struct gpio_bank *bank; + + if (check_gpio(gpio) < 0) + return; + bank = get_gpio_bank(gpio); + + _reset_gpio(bank, gpio); +} diff --git a/arch/arm/cpu/armv7/omap3/lowlevel_init.S b/arch/arm/cpu/armv7/omap3/lowlevel_init.S new file mode 100644 index 0000000..73063ec --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/lowlevel_init.S @@ -0,0 +1,361 @@ +/* + * 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> + * + * 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 <version.h> +#include <asm/arch/mem.h> +#include <asm/arch/clocks_omap3.h> + +_TEXT_BASE: + .word TEXT_BASE /* sdram load addr from config.mk */ + +#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. + *************************************************************************/ +.global cpy_clk_code + cpy_clk_code: + /* Copy DPLL code into SRAM */ + adr r0, go_to_speed /* get addr of clock setting code */ + mov r2, #384 /* r2 size to copy (div by 32 bytes) */ + mov r1, r1 /* r1 <- dest address (passed in) */ + add r2, r2, r0 /* r2 <- source end address */ +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] */ + bne next2 + mov pc, lr /* back to caller */ + +/* *************************************************************************** + * 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. + ****************************************************************************/ +.global go_to_speed + 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 */ + +_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 + +.globl lowlevel_init +lowlevel_init: + ldr sp, SRAM_STACK + str ip, [sp] /* stash old link register */ + mov ip, lr /* save link reg across call */ + bl s_init /* go setup pll, mux, memory */ + ldr ip, [sp] /* restore save ip */ + mov lr, ip /* restore link reg */ + + /* back to arch calling code */ + mov pc, lr + + /* 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 diff --git a/arch/arm/cpu/armv7/omap3/mem.c b/arch/arm/cpu/armv7/omap3/mem.c new file mode 100644 index 0000000..bd914b0 --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/mem.c @@ -0,0 +1,191 @@ +/* + * (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> + * + * 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 <asm/io.h> +#include <asm/arch/mem.h> +#include <asm/arch/sys_proto.h> +#include <command.h> + +/* + * Only One NAND allowed on board at a time. + * The GPMC CS Base for the same + */ +unsigned int boot_flash_base; +unsigned int boot_flash_off; +unsigned int boot_flash_sec; +unsigned int boot_flash_type; +volatile unsigned int boot_flash_env_addr; + +struct gpmc *gpmc_cfg; + +#if defined(CONFIG_CMD_NAND) +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 +}; + +#if defined(CONFIG_ENV_IS_IN_NAND) +#define GPMC_CS 0 +#else +#define GPMC_CS 1 +#endif + +#endif + +#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 +}; + +#if defined(CONFIG_ENV_IS_IN_ONENAND) +#define GPMC_CS 0 +#else +#define GPMC_CS 1 +#endif + +#endif + +/******************************************************** + * 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 */ + + 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 */ + 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_CMD_NAND) || defined(CONFIG_CMD_ONENAND) + const u32 *gpmc_config = NULL; + u32 base = 0; + u32 size = 0; +#if defined(CONFIG_ENV_IS_IN_NAND) || defined(CONFIG_ENV_IS_IN_ONENAND) + u32 f_off = CONFIG_SYS_MONITOR_LEN; + u32 f_sec = 0; +#endif +#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); +#if defined(CONFIG_ENV_IS_IN_NAND) + f_off = SMNAND_ENV_OFFSET; + f_sec = (128 << 10); /* 128 KiB */ + /* env setup */ + boot_flash_base = base; + boot_flash_off = f_off; + boot_flash_sec = f_sec; + boot_flash_env_addr = f_off; +#endif +#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); +#if defined(CONFIG_ENV_IS_IN_ONENAND) + f_off = ONENAND_ENV_OFFSET; + f_sec = (128 << 10); /* 128 KiB */ + /* env setup */ + boot_flash_base = base; + boot_flash_off = f_off; + boot_flash_sec = f_sec; + boot_flash_env_addr = f_off; +#endif +#endif +} diff --git a/arch/arm/cpu/armv7/omap3/sdrc.c b/arch/arm/cpu/armv7/omap3/sdrc.c new file mode 100644 index 0000000..96fd990c --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/sdrc.c @@ -0,0 +1,202 @@ +/* + * 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/ + * + * 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> + * + * 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 <asm/io.h> +#include <asm/arch/mem.h> +#include <asm/arch/sys_proto.h> + +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 - + * - For es2 and above remap cs1 behind cs0 to allow command line + * mem=xyz use all memory with out discontinuous support compiled in. + * Could do it at the ATAG, but there really is two banks... + * - Called as part of 2nd phase DDR init. + */ +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 & 0x30) >> 17; + + return offset; +} + +/* + * do_sdrc_init - + * - Initialize the SDRAM for use. + * - Sets up SDRC timings for CS0 + * - code called once in C-Stack only context for CS0 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_base; + + if (cs) + sdrc_actim_base = (struct sdrc_actim *)SDRC_ACTIM_CTRL1_BASE; + else + sdrc_actim_base = (struct sdrc_actim *)SDRC_ACTIM_CTRL0_BASE; + + 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 cuz of 1 CKE on combo part */ + writel(WAKEUPPROC | SRFRONRESET | PAGEPOLICY_HIGH, + &sdrc_base->power); + + writel(ENADLL | DLLPHASE_90, &sdrc_base->dlla_ctrl); + sdelay(0x20000); + } + + writel(RASWIDTH_13BITS | CASWIDTH_10BITS | ADDRMUXLEGACY | + RAMSIZE_128 | BANKALLOCATION | B32NOT16 | B32NOT16 | + DEEPPD | DDR_SDRAM, &sdrc_base->cs[cs].mcfg); + writel(ARCV | ARE_ARCV_1, &sdrc_base->cs[cs].rfr_ctrl); + writel(V_ACTIMA_165, &sdrc_actim_base->ctrla); + writel(V_ACTIMB_165, &sdrc_actim_base->ctrlb); + + 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); + + /* + * CAS latency 3, Write Burst = Read Burst, Serial Mode, + * Burst length = 4 + */ + writel(CASL3 | BURSTLENGTH4, &sdrc_base->cs[cs].mr); + + if (!mem_ok(cs)) + writel(0, &sdrc_base->cs[cs].mcfg); +} + +/* + * dram_init - + * - Sets uboots idea of sdram size + */ +int dram_init(void) +{ + DECLARE_GLOBAL_DATA_PTR; + 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)) { + do_sdrc_init(CS1, NOT_EARLY); + make_cs1_contiguous(); + + 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; + + return 0; +} + +/* + * 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/arch/arm/cpu/armv7/omap3/sys_info.c b/arch/arm/cpu/armv7/omap3/sys_info.c new file mode 100644 index 0000000..1df4401 --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/sys_info.c @@ -0,0 +1,258 @@ +/* + * (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> + * + * 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 <asm/io.h> +#include <asm/arch/mem.h> /* get mem tables */ +#include <asm/arch/sys_proto.h> +#include <i2c.h> + +extern omap3_sysinfo sysinfo; +static struct ctrl *ctrl_base = (struct ctrl *)OMAP34XX_CTRL_BASE; +static char *rev_s[CPU_3XX_MAX_REV] = { + "1.0", + "2.0", + "2.1", + "3.0", + "3.1"}; + +/***************************************************************** + * dieid_num_r(void) - read and set die ID + *****************************************************************/ +void dieid_num_r(void) +{ + struct ctrl_id *id_base = (struct ctrl_id *)OMAP34XX_ID_L4_IO_BASE; + char *uid_s, die_id[34]; + u32 id[4]; + + memset(die_id, 0, sizeof(die_id)); + + uid_s = getenv("dieid#"); + + if (uid_s == NULL) { + 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); + 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_rev(void) - extract version info + ******************************************/ +u32 get_cpu_rev(void) +{ + u32 cpuid = 0; + struct ctrl_id *id_base; + + /* + * 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 CPU_3XX_ES10; + else { + /* Decode the IDs on > ES1.0 */ + id_base = (struct ctrl_id *) OMAP34XX_ID_L4_IO_BASE; + + cpuid = (readl(&id_base->idcode) >> CPU_3XX_ID_SHIFT) & 0xf; + + /* Some early ES2.0 seem to report ID 0, fix this */ + if(cpuid == 0) + cpuid = CPU_3XX_ES20; + + return cpuid; + } +} + +/*************************************************************************** + * 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 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_s, *sec_s; + + 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; + } + + 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("OMAP%s-%s ES%s, CPU-OPP2 L3-165MHz\n", + cpu_s, sec_s, rev_s[get_cpu_rev()]); + + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ diff --git a/arch/arm/cpu/armv7/omap3/syslib.c b/arch/arm/cpu/armv7/omap3/syslib.c new file mode 100644 index 0000000..9ced495 --- /dev/null +++ b/arch/arm/cpu/armv7/omap3/syslib.c @@ -0,0 +1,72 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@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; 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 <asm/io.h> +#include <asm/arch/mem.h> +#include <asm/arch/clocks.h> +#include <asm/arch/sys_proto.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)); +} + +/***************************************************************** + * sr32 - clear & set a value in a bit range for a 32 bit address + *****************************************************************/ +void sr32(void *addr, u32 start_bit, u32 num_bits, u32 value) +{ + u32 tmp, msk = 0; + msk = 1 << num_bits; + --msk; + tmp = readl((u32)addr) & ~(msk << start_bit); + tmp |= value << start_bit; + writel(tmp, (u32)addr); +} + +/********************************************************************* + * 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); +} |