From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 26 Oct 2008 18:07:36 +0100 Subject: [U-Boot] [PATCH 06/13 v4] ARM: OMAP3: Add board, clock and interrupts common files In-Reply-To: <48f8e741.1f205e0a.39d1.5454@mx.google.com> References: <48f8e727.1c185e0a.4360.53fa@mx.google.com> <48f8e741.1f205e0a.39d1.5454@mx.google.com> Message-ID: <20081026170736.GC4780@game.jcrosoft.org> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 21:27 Fri 17 Oct , dirk.behme at googlemail.com wrote: > Subject: [PATCH 06/13 v4] ARM: OMAP3: Add board, clock and interrupts common files > > From: Dirk Behme > > Add board, clock, cpu and interrupts common files > > Signed-off-by: Dirk Behme > > --- > > Changes in version v3: > > - Add detection and support for 128MB/256MB RAM by Mans Rullgard > > Changes in version v2: > > - Move common ARM Cortex A8 code to cpu/arm_cortexa8/ and OMAP3 SoC specific common code to cpu/arm_cortexa8/omap3 as proposed by Wolfgang. > > cpu/arm_cortexa8/omap3/Makefile | 2 > cpu/arm_cortexa8/omap3/board.c | 326 ++++++++++++++++++++++++++++++++++++ > cpu/arm_cortexa8/omap3/clock.c | 305 +++++++++++++++++++++++++++++++++ > cpu/arm_cortexa8/omap3/interrupts.c | 304 +++++++++++++++++++++++++++++++++ > 4 files changed, 936 insertions(+), 1 deletion(-) > > Index: u-boot-arm/cpu/arm_cortexa8/omap3/Makefile > =================================================================== > --- u-boot-arm.orig/cpu/arm_cortexa8/omap3/Makefile > +++ u-boot-arm/cpu/arm_cortexa8/omap3/Makefile > @@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk > LIB = lib$(SOC).a > > SOBJS := lowlevel_init.o > -OBJS := sys_info.o > +OBJS := sys_info.o board.o clock.o interrupts.o > > all: .depend $(LIB) please use the current way to allow builddir > > Index: u-boot-arm/cpu/arm_cortexa8/omap3/board.c > =================================================================== > --- /dev/null > +++ u-boot-arm/cpu/arm_cortexa8/omap3/board.c > @@ -0,0 +1,326 @@ > +/* > + * > + * Common board functions for OMAP3 based boards. > + * > + * (C) Copyright 2004-2008 > + * Texas Instruments, > + > +/****************************************************************************** > + * 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 *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->help); > + return 1; > +} > + > +U_BOOT_CMD( > + nandecc, 2, 1, do_switch_ecc, > + "nandecc - switch OMAP3 NAND ECC calculation algorithm\n", > + "[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm\n" > + ); > + please add a README about it > +#endif /* CONFIG_NAND_OMAP_GPMC */ > Index: u-boot-arm/cpu/arm_cortexa8/omap3/clock.c > =================================================================== > --- /dev/null > +++ u-boot-arm/cpu/arm_cortexa8/omap3/clock.c > @@ -0,0 +1,305 @@ > +/* > + * (C) Copyright 2008 > + * Texas Instruments, > + * > + * Author : > + * Manikandan Pillai > + * > + * Derived from Beagle Board and OMAP3 SDP code by > + * Richard Woodruff > + * Syed Mohammed Khasim > + * > + * 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 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/****************************************************************************** > + * 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, val; > + > + val = readl(PRM_CLKSRC_CTRL); > + > + /* If SYS_CLK is being divided by 2, remove for now */ > + val = (val & (~BIT7)) | BIT6; > + writel(val, PRM_CLKSRC_CTRL); > + > + /* enable timer2 */ > + val = readl(CM_CLKSEL_WKUP) | BIT0; > + writel(val, CM_CLKSEL_WKUP); /* select sys_clk for GPT1 */ > + > + /* Enable I and F Clocks for GPT1 */ > + val = readl(CM_ICLKEN_WKUP) | BIT0 | BIT2; > + writel(val, CM_ICLKEN_WKUP); > + val = readl(CM_FCLKEN_WKUP) | BIT0; > + writel(val, CM_FCLKEN_WKUP); > + > + writel(0, OMAP34XX_GPT1 + TLDR); /* start counting at 0 */ > + writel(GPT_EN, OMAP34XX_GPT1 + TCLR); /* enable clock */ > + > + /* enable 32kHz source, determine sys_clk via gauging */ > + start = 20 + readl(S32K_CR); /* start time in 20 cycles */ > + while (readl(S32K_CR) < start) ; /* dead loop till start time */ > + /* get start sys_clk count */ > + cstart = readl(OMAP34XX_GPT1 + TCRR); > + /* wait for 40 cycles */ > + while (readl(S32K_CR) < (start + 20)) ; > + cend = readl(OMAP34XX_GPT1 + TCRR); /* get end sys_clk count */ > + cdiff = cend - cstart; /* get elapsed ticks */ > + > + /* 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) > +{ > + if (osc_clk == S38_4M) > + *sys_clkin_sel = 4; > + else if (osc_clk == S26M) > + *sys_clkin_sel = 3; > + else if (osc_clk == S19_2M) > + *sys_clkin_sel = 2; > + else if (osc_clk == S13M) > + *sys_clkin_sel = 1; > + else if (osc_clk == S12M) > + *sys_clkin_sel = 0; please use switch instead > +} > + > +/****************************************************************************** > + * 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; > + dpll_param *dpll_param_p; > + > + f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start + > + SRAM_VECT_CODE); > + > + xip_safe = 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); > + > + sr32(PRM_CLKSEL, 0, 3, sys_clkin_sel); /* set input crystal speed */ > + > + /* If the input clock is greater than 19.2M always divide/2 */ > + if (sys_clkin_sel > 2) { > + sr32(PRM_CLKSRC_CTRL, 6, 2, 2); /* input clock divider */ > + clk_index = sys_clkin_sel / 2; > + } else { > + sr32(PRM_CLKSRC_CTRL, 6, 2, 1); /* input clock divider */ > + 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. > + */ > + sil_index = get_cpu_rev() - 1; this part is unreadable maybe you can add some blank line > + /* Unlock MPU DPLL (slows things down, and needed later) */ > + sr32(CM_CLKEN_PLL_MPU, 0, 3, PLL_LOW_POWER_BYPASS); > + wait_on_value(BIT0, 0, CM_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(CM_CLKEN_PLL, 0, 3, PLL_FAST_RELOCK_BYPASS); > + wait_on_value(BIT0, 0, CM_IDLEST_CKGEN, LDELAY); > + /* For OMAP3 ES1.0 Errata 1.50, default value directly doesnt > + work. write another value and then default value. */ please use this style of comment /* * */ please also fix the whitespace > + sr32(CM_CLKSEL1_EMU, 16, 5, CORE_M3X2 + 1); /* m3x2 */ > + sr32(CM_CLKSEL1_EMU, 16, 5, CORE_M3X2); /* m3x2 */ > + sr32(CM_CLKSEL1_PLL, 27, 2, dpll_param_p->m2); /* Set M2 */ > + sr32(CM_CLKSEL1_PLL, 16, 11, dpll_param_p->m); /* Set M */ > + sr32(CM_CLKSEL1_PLL, 8, 7, dpll_param_p->n); /* Set N */ > + sr32(CM_CLKSEL1_PLL, 6, 1, 0); /* 96M Src */ > + sr32(CM_CLKSEL_CORE, 8, 4, CORE_SSI_DIV); /* ssi */ > + sr32(CM_CLKSEL_CORE, 4, 2, CORE_FUSB_DIV); /* fsusb */ > + sr32(CM_CLKSEL_CORE, 2, 2, CORE_L4_DIV); /* l4 */ > Index: u-boot-arm/cpu/arm_cortexa8/omap3/interrupts.c > =================================================================== > --- /dev/null > +++ u-boot-arm/cpu/arm_cortexa8/omap3/interrupts.c > @@ -0,0 +1,304 @@ > +/* > + * (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 > + > +#include > + > +#define TIMER_LOAD_VAL 0 > + > +/* macro to read the 32 bit timer */ > +#define READ_TIMER (*(volatile ulong *)(CONFIG_SYS_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); > + please fix the whitespace > + 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(); > +} > + > + > +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 */ Best Regards, J.