[U-Boot] [PATCH 06/13 v4] ARM: OMAP3: Add board, clock and interrupts common files

Jean-Christophe PLAGNIOL-VILLARD plagnioj at jcrosoft.com
Sun Oct 26 18:07:36 CET 2008


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 <dirk.behme at gmail.com>
> 
> Add board, clock, cpu and interrupts common files
> 
> Signed-off-by: Dirk Behme <dirk.behme at gmail.com>
> 
> ---
> 
> 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, <www.ti.com>
> +
> +/******************************************************************************
> + * 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, <www.ti.com>
> + *
> + * Author :
> + *      Manikandan Pillai <mani.pillai at ti.com>
> + *
> + * Derived from Beagle Board and OMAP3 SDP code by
> + *      Richard Woodruff <r-woodruff2 at ti.com>
> + *      Syed Mohammed Khasim <khasim at 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/bits.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, 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 <r-woodruff2 at ti.com>
> + * Syed Moahmmed Khasim <khasim at ti.com>
> + *
> + * (C) Copyright 2002
> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
> + * Marius Groeger <mgroeger at sysgo.de>
> + * Alex Zuepke <azu at sysgo.de>
> + *
> + * (C) Copyright 2002
> + * Gary Jennejohn, DENX Software Engineering, <gj at 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 <common.h>
> +#include <asm/arch/bits.h>
> +
> +#include <asm/proc-armv/ptrace.h>
> +
> +#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.


More information about the U-Boot mailing list