From 6052ac8386725056629357c197d13909ff0658eb Mon Sep 17 00:00:00 2001 From: Matthias Weisser Date: Mon, 9 Aug 2010 13:31:49 +0200 Subject: ARM: Add support for MB86R0x SoCs Signed-off-by: Matthias Weisser --- arch/arm/cpu/arm926ejs/mb86r0x/Makefile | 47 +++++++++++ arch/arm/cpu/arm926ejs/mb86r0x/clock.c | 43 ++++++++++ arch/arm/cpu/arm926ejs/mb86r0x/reset.c | 40 +++++++++ arch/arm/cpu/arm926ejs/mb86r0x/timer.c | 142 ++++++++++++++++++++++++++++++++ 4 files changed, 272 insertions(+) create mode 100644 arch/arm/cpu/arm926ejs/mb86r0x/Makefile create mode 100644 arch/arm/cpu/arm926ejs/mb86r0x/clock.c create mode 100644 arch/arm/cpu/arm926ejs/mb86r0x/reset.c create mode 100644 arch/arm/cpu/arm926ejs/mb86r0x/timer.c (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/mb86r0x/Makefile b/arch/arm/cpu/arm926ejs/mb86r0x/Makefile new file mode 100644 index 0000000000..ce3e5a5a5a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mb86r0x/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2000-2006 +# 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 + +COBJS = clock.o reset.o timer.o +SOBJS = + +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) +START := $(addprefix $(obj),$(START)) + +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/arm926ejs/mb86r0x/clock.c b/arch/arm/cpu/arm926ejs/mb86r0x/clock.c new file mode 100644 index 0000000000..70c8c8b04a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mb86r0x/clock.c @@ -0,0 +1,43 @@ +/* + * (C) Copyright 2010 + * Matthias Weisser + * + * 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 + +/* + * Get the peripheral bus frequency depending on pll pin settings + */ +ulong get_bus_freq(ulong dummy) +{ + struct mb86r0x_crg * crg = (struct mb86r0x_crg *) + MB86R0x_CRG_BASE; + uint32_t pllmode; + + pllmode = readl(&crg->crpr) & MB86R0x_CRG_CRPR_PLLMODE; + + if (pllmode == MB86R0x_CRG_CRPR_PLLMODE_X20) + return 40000000; + + return 41164767; +} diff --git a/arch/arm/cpu/arm926ejs/mb86r0x/reset.c b/arch/arm/cpu/arm926ejs/mb86r0x/reset.c new file mode 100644 index 0000000000..e7f0f6788b --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mb86r0x/reset.c @@ -0,0 +1,40 @@ +/* + * (C) Copyright 2010 + * Matthias Weisser + * + * 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 + +/* + * Reset the cpu by setting software reset request bit + */ +void reset_cpu(ulong ignored) +{ + struct mb86r0x_crg * crg = (struct mb86r0x_crg *) + MB86R0x_CRG_BASE; + + writel(MB86R0x_CRSR_SWRSTREQ, &crg->crsr); + while (1) + /* NOP */; + /* Never reached */ +} diff --git a/arch/arm/cpu/arm926ejs/mb86r0x/timer.c b/arch/arm/cpu/arm926ejs/mb86r0x/timer.c new file mode 100644 index 0000000000..9175b71d16 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mb86r0x/timer.c @@ -0,0 +1,142 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop + * Lead Tech Design + * + * (C) Copyright 2010 + * Matthias Weisser, Graf-Syteco + * + * 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 +#include + +#define TIMER_LOAD_VAL 0xffffffff +#define TIMER_FREQ (CONFIG_MB86R0x_IOCLK / 256) + +static unsigned long long timestamp; +static ulong lastdec; + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, TIMER_FREQ); + + return tick; +} + +static inline unsigned long long usec_to_tick(unsigned long long usec) +{ + usec *= TIMER_FREQ; + do_div(usec, 1000000); + + return usec; +} + +/* nothing really to do with interrupts, just starts up a counter. */ +int timer_init(void) +{ + struct mb86r0x_timer * timer = (struct mb86r0x_timer *) + MB86R0x_TIMER_BASE; + ulong ctrl = readl(&timer->control); + + writel(TIMER_LOAD_VAL, &timer->load); + + ctrl |= MB86R0x_TIMER_ENABLE | MB86R0x_TIMER_PRS_8S | + MB86R0x_TIMER_SIZE_32; + + writel(ctrl, &timer->control); + + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ +unsigned long long get_ticks(void) +{ + struct mb86r0x_timer * timer = (struct mb86r0x_timer *) + MB86R0x_TIMER_BASE; + ulong now = readl(&timer->value); + + if (now <= lastdec) { + /* normal mode (non roll) */ + /* move stamp forward with absolut diff ticks */ + timestamp += lastdec - now; + } else { + /* we have rollover of incrementer */ + timestamp += lastdec + TIMER_LOAD_VAL - now; + } + lastdec = now; + return timestamp; +} + +void reset_timer_masked(void) +{ + struct mb86r0x_timer * timer = (struct mb86r0x_timer *) + MB86R0x_TIMER_BASE; + + /* capture current value time */ + lastdec = readl(&timer->value); + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +ulong get_timer_masked(void) +{ + return tick_to_time(get_ticks()); +} + +void __udelay(unsigned long usec) +{ + unsigned long long tmp; + ulong tmo; + + tmo = usec_to_tick(usec); + tmp = get_ticks(); /* get current timestamp */ + + while ((get_ticks() - tmp) < tmo) /* loop till event */ + /*NOP*/; +} + +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + ulong tbclk; + + tbclk = TIMER_FREQ; + return tbclk; +} -- cgit v1.2.3 From d93d0f0cfef46293db97cbdc5e72c9e5bceadd02 Mon Sep 17 00:00:00 2001 From: Minkyu Kang Date: Fri, 13 Aug 2010 16:07:35 +0900 Subject: S5P: Use accessor functions instead of SoC specific defines to access the base address This patch is intended to prepare the other S5P SoC. (s5pc210) If use SoC specific defines then can't share with other SoC. So, make the accessor functions for access the base address by common way. Signed-off-by: Minkyu Kang Signed-off-by: Kyungmin Park --- arch/arm/cpu/armv7/s5pc1xx/clock.c | 24 ++++++++++++++++-------- arch/arm/cpu/armv7/s5pc1xx/cpu_info.c | 2 +- arch/arm/cpu/armv7/s5pc1xx/reset.S | 2 +- arch/arm/cpu/armv7/s5pc1xx/sromc.c | 8 ++------ arch/arm/cpu/armv7/s5pc1xx/timer.c | 5 +---- 5 files changed, 21 insertions(+), 20 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/s5pc1xx/clock.c b/arch/arm/cpu/armv7/s5pc1xx/clock.c index 19619f92cd..67af84a840 100644 --- a/arch/arm/cpu/armv7/s5pc1xx/clock.c +++ b/arch/arm/cpu/armv7/s5pc1xx/clock.c @@ -45,7 +45,8 @@ unsigned long (*get_pll_clk)(int); /* s5pc110: return pll clock frequency */ static unsigned long s5pc100_get_pll_clk(int pllreg) { - struct s5pc100_clock *clk = (struct s5pc100_clock *)S5PC1XX_CLOCK_BASE; + struct s5pc100_clock *clk = + (struct s5pc100_clock *)samsung_get_base_clock(); unsigned long r, m, p, s, mask, fout; unsigned int freq; @@ -95,7 +96,8 @@ static unsigned long s5pc100_get_pll_clk(int pllreg) /* s5pc100: return pll clock frequency */ static unsigned long s5pc110_get_pll_clk(int pllreg) { - struct s5pc110_clock *clk = (struct s5pc110_clock *)S5PC1XX_CLOCK_BASE; + struct s5pc110_clock *clk = + (struct s5pc110_clock *)samsung_get_base_clock(); unsigned long r, m, p, s, mask, fout; unsigned int freq; @@ -151,7 +153,8 @@ static unsigned long s5pc110_get_pll_clk(int pllreg) /* s5pc110: return ARM clock frequency */ static unsigned long s5pc110_get_arm_clk(void) { - struct s5pc110_clock *clk = (struct s5pc110_clock *)S5PC1XX_CLOCK_BASE; + struct s5pc110_clock *clk = + (struct s5pc110_clock *)samsung_get_base_clock(); unsigned long div; unsigned long dout_apll, armclk; unsigned int apll_ratio; @@ -170,7 +173,8 @@ static unsigned long s5pc110_get_arm_clk(void) /* s5pc100: return ARM clock frequency */ static unsigned long s5pc100_get_arm_clk(void) { - struct s5pc100_clock *clk = (struct s5pc100_clock *)S5PC1XX_CLOCK_BASE; + struct s5pc100_clock *clk = + (struct s5pc100_clock *)samsung_get_base_clock(); unsigned long div; unsigned long dout_apll, armclk; unsigned int apll_ratio, arm_ratio; @@ -191,7 +195,8 @@ static unsigned long s5pc100_get_arm_clk(void) /* s5pc100: return HCLKD0 frequency */ static unsigned long get_hclk(void) { - struct s5pc100_clock *clk = (struct s5pc100_clock *)S5PC1XX_CLOCK_BASE; + struct s5pc100_clock *clk = + (struct s5pc100_clock *)samsung_get_base_clock(); unsigned long hclkd0; uint div, d0_bus_ratio; @@ -207,7 +212,8 @@ static unsigned long get_hclk(void) /* s5pc100: return PCLKD1 frequency */ static unsigned long get_pclkd1(void) { - struct s5pc100_clock *clk = (struct s5pc100_clock *)S5PC1XX_CLOCK_BASE; + struct s5pc100_clock *clk = + (struct s5pc100_clock *)samsung_get_base_clock(); unsigned long d1_bus, pclkd1; uint div, d1_bus_ratio, pclkd1_ratio; @@ -227,7 +233,8 @@ static unsigned long get_pclkd1(void) /* s5pc110: return HCLKs frequency */ static unsigned long get_hclk_sys(int dom) { - struct s5pc110_clock *clk = (struct s5pc110_clock *)S5PC1XX_CLOCK_BASE; + struct s5pc110_clock *clk = + (struct s5pc110_clock *)samsung_get_base_clock(); unsigned long hclk; unsigned int div; unsigned int offset; @@ -255,7 +262,8 @@ static unsigned long get_hclk_sys(int dom) /* s5pc110: return PCLKs frequency */ static unsigned long get_pclk_sys(int dom) { - struct s5pc110_clock *clk = (struct s5pc110_clock *)S5PC1XX_CLOCK_BASE; + struct s5pc110_clock *clk = + (struct s5pc110_clock *)samsung_get_base_clock(); unsigned long pclk; unsigned int div; unsigned int offset; diff --git a/arch/arm/cpu/armv7/s5pc1xx/cpu_info.c b/arch/arm/cpu/armv7/s5pc1xx/cpu_info.c index f16c0ff130..454175ca5c 100644 --- a/arch/arm/cpu/armv7/s5pc1xx/cpu_info.c +++ b/arch/arm/cpu/armv7/s5pc1xx/cpu_info.c @@ -30,7 +30,7 @@ unsigned int s5pc1xx_cpu_id = 0xC100; #ifdef CONFIG_ARCH_CPU_INIT int arch_cpu_init(void) { - s5pc1xx_cpu_id = readl(S5PC1XX_PRO_ID); + s5pc1xx_cpu_id = readl(samsung_get_base_pro_id()); s5pc1xx_cpu_id = 0xC000 | ((s5pc1xx_cpu_id & 0x00FFF000) >> 12); s5pc1xx_clock_init(); diff --git a/arch/arm/cpu/armv7/s5pc1xx/reset.S b/arch/arm/cpu/armv7/s5pc1xx/reset.S index 7f6ff9c35f..70fa146cf3 100644 --- a/arch/arm/cpu/armv7/s5pc1xx/reset.S +++ b/arch/arm/cpu/armv7/s5pc1xx/reset.S @@ -28,7 +28,7 @@ .globl reset_cpu reset_cpu: - ldr r1, =S5PC1XX_PRO_ID + ldr r1, =S5PC100_PRO_ID ldr r2, [r1] ldr r4, =0x00010000 and r4, r2, r4 diff --git a/arch/arm/cpu/armv7/s5pc1xx/sromc.c b/arch/arm/cpu/armv7/s5pc1xx/sromc.c index 380be81be5..044d12298d 100644 --- a/arch/arm/cpu/armv7/s5pc1xx/sromc.c +++ b/arch/arm/cpu/armv7/s5pc1xx/sromc.c @@ -35,12 +35,8 @@ void s5pc1xx_config_sromc(u32 srom_bank, u32 smc_bw_conf, u32 smc_bc_conf) { u32 tmp; - struct s5pc1xx_smc *srom; - - if (cpu_is_s5pc100()) - srom = (struct s5pc1xx_smc *)S5PC100_SROMC_BASE; - else - srom = (struct s5pc1xx_smc *)S5PC110_SROMC_BASE; + struct s5pc1xx_smc *srom = + (struct s5pc1xx_smc *)samsung_get_base_sromc(); /* Configure SMC_BW register to handle proper SROMC bank */ tmp = srom->bw; diff --git a/arch/arm/cpu/armv7/s5pc1xx/timer.c b/arch/arm/cpu/armv7/s5pc1xx/timer.c index c5df5c5ab5..6487c0f3a3 100644 --- a/arch/arm/cpu/armv7/s5pc1xx/timer.c +++ b/arch/arm/cpu/armv7/s5pc1xx/timer.c @@ -46,10 +46,7 @@ static unsigned long lastdec; /* Last decremneter snapshot */ /* macro to read the 16 bit timer */ static inline struct s5pc1xx_timer *s5pc1xx_get_base_timer(void) { - if (cpu_is_s5pc110()) - return (struct s5pc1xx_timer *)S5PC110_TIMER_BASE; - else - return (struct s5pc1xx_timer *)S5PC100_TIMER_BASE; + return (struct s5pc1xx_timer *)samsung_get_base_timer(); } int timer_init(void) -- cgit v1.2.3 From 852bd07c80b27f330da8da367989bcd8121569a7 Mon Sep 17 00:00:00 2001 From: Minkyu Kang Date: Thu, 19 Aug 2010 13:48:11 +0900 Subject: ARMV7: S5P: make s5p-common for sharing the code between s5pc1xx and s5pc2xx This patch adds basic support for s5pc210. s5p-common will be used by all of s5p SoCs. Signed-off-by: Minkyu Kang Signed-off-by: Kyungmin Park --- arch/arm/cpu/armv7/s5p-common/Makefile | 46 ++++++++ arch/arm/cpu/armv7/s5p-common/cpu_info.c | 57 +++++++++ arch/arm/cpu/armv7/s5p-common/timer.c | 192 +++++++++++++++++++++++++++++++ arch/arm/cpu/armv7/s5pc1xx/Makefile | 2 - arch/arm/cpu/armv7/s5pc1xx/cpu_info.c | 57 --------- arch/arm/cpu/armv7/s5pc1xx/timer.c | 192 ------------------------------- 6 files changed, 295 insertions(+), 251 deletions(-) create mode 100644 arch/arm/cpu/armv7/s5p-common/Makefile create mode 100644 arch/arm/cpu/armv7/s5p-common/cpu_info.c create mode 100644 arch/arm/cpu/armv7/s5p-common/timer.c delete mode 100644 arch/arm/cpu/armv7/s5pc1xx/cpu_info.c delete mode 100644 arch/arm/cpu/armv7/s5pc1xx/timer.c (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/s5p-common/Makefile b/arch/arm/cpu/armv7/s5p-common/Makefile new file mode 100644 index 0000000000..37371f6fda --- /dev/null +++ b/arch/arm/cpu/armv7/s5p-common/Makefile @@ -0,0 +1,46 @@ +# +# Copyright (C) 2009 Samsung Electronics +# Minkyu Kang +# +# 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)libs5p-common.a + +COBJS-y += cpu_info.o +COBJS-y += timer.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(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/s5p-common/cpu_info.c b/arch/arm/cpu/armv7/s5p-common/cpu_info.c new file mode 100644 index 0000000000..454175ca5c --- /dev/null +++ b/arch/arm/cpu/armv7/s5p-common/cpu_info.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * + * 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 + +/* Default is s5pc100 */ +unsigned int s5pc1xx_cpu_id = 0xC100; + +#ifdef CONFIG_ARCH_CPU_INIT +int arch_cpu_init(void) +{ + s5pc1xx_cpu_id = readl(samsung_get_base_pro_id()); + s5pc1xx_cpu_id = 0xC000 | ((s5pc1xx_cpu_id & 0x00FFF000) >> 12); + + s5pc1xx_clock_init(); + + return 0; +} +#endif + +u32 get_device_type(void) +{ + return s5pc1xx_cpu_id; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ + char buf[32]; + + printf("CPU:\tS5P%X@%sMHz\n", + s5pc1xx_cpu_id, strmhz(buf, get_arm_clk())); + + return 0; +} +#endif diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c new file mode 100644 index 0000000000..6487c0f3a3 --- /dev/null +++ b/arch/arm/cpu/armv7/s5p-common/timer.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Heungjun Kim + * Inki Dae + * Minkyu Kang + * + * 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 +#include + +#define PRESCALER_1 (16 - 1) /* prescaler of timer 2, 3, 4 */ +#define MUX_DIV_2 1 /* 1/2 period */ +#define MUX_DIV_4 2 /* 1/4 period */ +#define MUX_DIV_8 3 /* 1/8 period */ +#define MUX_DIV_16 4 /* 1/16 period */ +#define MUX4_DIV_SHIFT 16 + +#define TCON_TIMER4_SHIFT 20 + +static unsigned long count_value; + +/* Internal tick units */ +static unsigned long long timestamp; /* Monotonic incrementing timer */ +static unsigned long lastdec; /* Last decremneter snapshot */ + +/* macro to read the 16 bit timer */ +static inline struct s5pc1xx_timer *s5pc1xx_get_base_timer(void) +{ + return (struct s5pc1xx_timer *)samsung_get_base_timer(); +} + +int timer_init(void) +{ + struct s5pc1xx_timer *const timer = s5pc1xx_get_base_timer(); + u32 val; + + /* + * @ PWM Timer 4 + * Timer Freq(HZ) = + * PCLK / { (prescaler_value + 1) * (divider_value) } + */ + + /* set prescaler : 16 */ + /* set divider : 2 */ + writel((PRESCALER_1 & 0xff) << 8, &timer->tcfg0); + writel((MUX_DIV_2 & 0xf) << MUX4_DIV_SHIFT, &timer->tcfg1); + + if (count_value == 0) { + /* reset initial value */ + /* count_value = 2085937.5(HZ) (per 1 sec)*/ + count_value = get_pclk() / ((PRESCALER_1 + 1) * + (MUX_DIV_2 + 1)); + + /* count_value / 100 = 20859.375(HZ) (per 10 msec) */ + count_value = count_value / 100; + } + + /* set count value */ + writel(count_value, &timer->tcntb4); + lastdec = count_value; + + val = (readl(&timer->tcon) & ~(0x07 << TCON_TIMER4_SHIFT)) | + S5PC1XX_TCON4_AUTO_RELOAD; + + /* auto reload & manual update */ + writel(val | S5PC1XX_TCON4_UPDATE, &timer->tcon); + + /* start PWM timer 4 */ + writel(val | S5PC1XX_TCON4_START, &timer->tcon); + + timestamp = 0; + + return 0; +} + +/* + * timer without interrupts + */ +void reset_timer(void) +{ + reset_timer_masked(); +} + +unsigned long get_timer(unsigned long base) +{ + return get_timer_masked() - base; +} + +void set_timer(unsigned long t) +{ + timestamp = t; +} + +/* delay x useconds */ +void __udelay(unsigned long usec) +{ + unsigned long tmo, tmp; + + if (usec >= 1000) { + /* + * if "big" number, spread normalization + * to seconds + * 1. start to normalize for usec to ticks per sec + * 2. find number of "ticks" to wait to achieve target + * 3. finish normalize. + */ + tmo = usec / 1000; + tmo *= (CONFIG_SYS_HZ * count_value / 10); + tmo /= 1000; + } else { + /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CONFIG_SYS_HZ * count_value / 10; + tmo /= (1000 * 1000); + } + + /* get current timestamp */ + tmp = get_timer(0); + + /* if setting this fordward will roll time stamp */ + /* reset "advancing" timestamp to 0, set lastdec value */ + /* else, set advancing stamp wake up time */ + if ((tmo + tmp + 1) < tmp) + reset_timer_masked(); + else + tmo += tmp; + + /* loop till event */ + while (get_timer_masked() < tmo) + ; /* nop */ +} + +void reset_timer_masked(void) +{ + struct s5pc1xx_timer *const timer = s5pc1xx_get_base_timer(); + + /* reset time */ + lastdec = readl(&timer->tcnto4); + timestamp = 0; +} + +unsigned long get_timer_masked(void) +{ + struct s5pc1xx_timer *const timer = s5pc1xx_get_base_timer(); + unsigned long now = readl(&timer->tcnto4); + + if (lastdec >= now) + timestamp += lastdec - now; + else + timestamp += lastdec + count_value - now; + + lastdec = now; + + return timestamp; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +unsigned long get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/arch/arm/cpu/armv7/s5pc1xx/Makefile b/arch/arm/cpu/armv7/s5pc1xx/Makefile index 3785593d25..263945f4e7 100644 --- a/arch/arm/cpu/armv7/s5pc1xx/Makefile +++ b/arch/arm/cpu/armv7/s5pc1xx/Makefile @@ -32,9 +32,7 @@ SOBJS = cache.o SOBJS += reset.o COBJS += clock.o -COBJS += cpu_info.o COBJS += sromc.o -COBJS += timer.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) diff --git a/arch/arm/cpu/armv7/s5pc1xx/cpu_info.c b/arch/arm/cpu/armv7/s5pc1xx/cpu_info.c deleted file mode 100644 index 454175ca5c..0000000000 --- a/arch/arm/cpu/armv7/s5pc1xx/cpu_info.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Minkyu Kang - * - * 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 - -/* Default is s5pc100 */ -unsigned int s5pc1xx_cpu_id = 0xC100; - -#ifdef CONFIG_ARCH_CPU_INIT -int arch_cpu_init(void) -{ - s5pc1xx_cpu_id = readl(samsung_get_base_pro_id()); - s5pc1xx_cpu_id = 0xC000 | ((s5pc1xx_cpu_id & 0x00FFF000) >> 12); - - s5pc1xx_clock_init(); - - return 0; -} -#endif - -u32 get_device_type(void) -{ - return s5pc1xx_cpu_id; -} - -#ifdef CONFIG_DISPLAY_CPUINFO -int print_cpuinfo(void) -{ - char buf[32]; - - printf("CPU:\tS5P%X@%sMHz\n", - s5pc1xx_cpu_id, strmhz(buf, get_arm_clk())); - - return 0; -} -#endif diff --git a/arch/arm/cpu/armv7/s5pc1xx/timer.c b/arch/arm/cpu/armv7/s5pc1xx/timer.c deleted file mode 100644 index 6487c0f3a3..0000000000 --- a/arch/arm/cpu/armv7/s5pc1xx/timer.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Heungjun Kim - * Inki Dae - * Minkyu Kang - * - * 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 -#include - -#define PRESCALER_1 (16 - 1) /* prescaler of timer 2, 3, 4 */ -#define MUX_DIV_2 1 /* 1/2 period */ -#define MUX_DIV_4 2 /* 1/4 period */ -#define MUX_DIV_8 3 /* 1/8 period */ -#define MUX_DIV_16 4 /* 1/16 period */ -#define MUX4_DIV_SHIFT 16 - -#define TCON_TIMER4_SHIFT 20 - -static unsigned long count_value; - -/* Internal tick units */ -static unsigned long long timestamp; /* Monotonic incrementing timer */ -static unsigned long lastdec; /* Last decremneter snapshot */ - -/* macro to read the 16 bit timer */ -static inline struct s5pc1xx_timer *s5pc1xx_get_base_timer(void) -{ - return (struct s5pc1xx_timer *)samsung_get_base_timer(); -} - -int timer_init(void) -{ - struct s5pc1xx_timer *const timer = s5pc1xx_get_base_timer(); - u32 val; - - /* - * @ PWM Timer 4 - * Timer Freq(HZ) = - * PCLK / { (prescaler_value + 1) * (divider_value) } - */ - - /* set prescaler : 16 */ - /* set divider : 2 */ - writel((PRESCALER_1 & 0xff) << 8, &timer->tcfg0); - writel((MUX_DIV_2 & 0xf) << MUX4_DIV_SHIFT, &timer->tcfg1); - - if (count_value == 0) { - /* reset initial value */ - /* count_value = 2085937.5(HZ) (per 1 sec)*/ - count_value = get_pclk() / ((PRESCALER_1 + 1) * - (MUX_DIV_2 + 1)); - - /* count_value / 100 = 20859.375(HZ) (per 10 msec) */ - count_value = count_value / 100; - } - - /* set count value */ - writel(count_value, &timer->tcntb4); - lastdec = count_value; - - val = (readl(&timer->tcon) & ~(0x07 << TCON_TIMER4_SHIFT)) | - S5PC1XX_TCON4_AUTO_RELOAD; - - /* auto reload & manual update */ - writel(val | S5PC1XX_TCON4_UPDATE, &timer->tcon); - - /* start PWM timer 4 */ - writel(val | S5PC1XX_TCON4_START, &timer->tcon); - - timestamp = 0; - - return 0; -} - -/* - * timer without interrupts - */ -void reset_timer(void) -{ - reset_timer_masked(); -} - -unsigned long get_timer(unsigned long base) -{ - return get_timer_masked() - base; -} - -void set_timer(unsigned long t) -{ - timestamp = t; -} - -/* delay x useconds */ -void __udelay(unsigned long usec) -{ - unsigned long tmo, tmp; - - if (usec >= 1000) { - /* - * if "big" number, spread normalization - * to seconds - * 1. start to normalize for usec to ticks per sec - * 2. find number of "ticks" to wait to achieve target - * 3. finish normalize. - */ - tmo = usec / 1000; - tmo *= (CONFIG_SYS_HZ * count_value / 10); - tmo /= 1000; - } else { - /* else small number, don't kill it prior to HZ multiply */ - tmo = usec * CONFIG_SYS_HZ * count_value / 10; - tmo /= (1000 * 1000); - } - - /* get current timestamp */ - tmp = get_timer(0); - - /* if setting this fordward will roll time stamp */ - /* reset "advancing" timestamp to 0, set lastdec value */ - /* else, set advancing stamp wake up time */ - if ((tmo + tmp + 1) < tmp) - reset_timer_masked(); - else - tmo += tmp; - - /* loop till event */ - while (get_timer_masked() < tmo) - ; /* nop */ -} - -void reset_timer_masked(void) -{ - struct s5pc1xx_timer *const timer = s5pc1xx_get_base_timer(); - - /* reset time */ - lastdec = readl(&timer->tcnto4); - timestamp = 0; -} - -unsigned long get_timer_masked(void) -{ - struct s5pc1xx_timer *const timer = s5pc1xx_get_base_timer(); - unsigned long now = readl(&timer->tcnto4); - - if (lastdec >= now) - timestamp += lastdec - now; - else - timestamp += lastdec + count_value - now; - - lastdec = now; - - return timestamp; -} - -/* - * This function is derived from PowerPC code (read timebase as long long). - * On ARM it just returns the timer value. - */ -unsigned long long get_ticks(void) -{ - return get_timer(0); -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -unsigned long get_tbclk(void) -{ - return CONFIG_SYS_HZ; -} -- cgit v1.2.3 From 37168dab52bf8419a2fd91d2c098aed5c675ae50 Mon Sep 17 00:00:00 2001 From: Minkyu Kang Date: Thu, 19 Aug 2010 20:41:50 +0900 Subject: ARMV7: S5P: rename from s5pc1xx to s5p Because of these are common files around s5p Socs, rename from s5pc1xx to s5p. And getting cpu_id is SoC specific, so move to SoC's header file. Signed-off-by: Minkyu Kang Signed-off-by: Kyungmin Park --- arch/arm/cpu/armv7/s5p-common/cpu_info.c | 11 +++++------ arch/arm/cpu/armv7/s5p-common/timer.c | 16 ++++++++-------- arch/arm/cpu/armv7/s5pc1xx/clock.c | 2 +- 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/s5p-common/cpu_info.c b/arch/arm/cpu/armv7/s5p-common/cpu_info.c index 454175ca5c..2f6c708554 100644 --- a/arch/arm/cpu/armv7/s5p-common/cpu_info.c +++ b/arch/arm/cpu/armv7/s5p-common/cpu_info.c @@ -25,15 +25,14 @@ #include /* Default is s5pc100 */ -unsigned int s5pc1xx_cpu_id = 0xC100; +unsigned int s5p_cpu_id = 0xC100; #ifdef CONFIG_ARCH_CPU_INIT int arch_cpu_init(void) { - s5pc1xx_cpu_id = readl(samsung_get_base_pro_id()); - s5pc1xx_cpu_id = 0xC000 | ((s5pc1xx_cpu_id & 0x00FFF000) >> 12); + s5p_set_cpu_id(); - s5pc1xx_clock_init(); + s5p_clock_init(); return 0; } @@ -41,7 +40,7 @@ int arch_cpu_init(void) u32 get_device_type(void) { - return s5pc1xx_cpu_id; + return s5p_cpu_id; } #ifdef CONFIG_DISPLAY_CPUINFO @@ -50,7 +49,7 @@ int print_cpuinfo(void) char buf[32]; printf("CPU:\tS5P%X@%sMHz\n", - s5pc1xx_cpu_id, strmhz(buf, get_arm_clk())); + s5p_cpu_id, strmhz(buf, get_arm_clk())); return 0; } diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c index 6487c0f3a3..1f1c7ff340 100644 --- a/arch/arm/cpu/armv7/s5p-common/timer.c +++ b/arch/arm/cpu/armv7/s5p-common/timer.c @@ -44,14 +44,14 @@ static unsigned long long timestamp; /* Monotonic incrementing timer */ static unsigned long lastdec; /* Last decremneter snapshot */ /* macro to read the 16 bit timer */ -static inline struct s5pc1xx_timer *s5pc1xx_get_base_timer(void) +static inline struct s5p_timer *s5p_get_base_timer(void) { - return (struct s5pc1xx_timer *)samsung_get_base_timer(); + return (struct s5p_timer *)samsung_get_base_timer(); } int timer_init(void) { - struct s5pc1xx_timer *const timer = s5pc1xx_get_base_timer(); + struct s5p_timer *const timer = s5p_get_base_timer(); u32 val; /* @@ -80,13 +80,13 @@ int timer_init(void) lastdec = count_value; val = (readl(&timer->tcon) & ~(0x07 << TCON_TIMER4_SHIFT)) | - S5PC1XX_TCON4_AUTO_RELOAD; + TCON4_AUTO_RELOAD; /* auto reload & manual update */ - writel(val | S5PC1XX_TCON4_UPDATE, &timer->tcon); + writel(val | TCON4_UPDATE, &timer->tcon); /* start PWM timer 4 */ - writel(val | S5PC1XX_TCON4_START, &timer->tcon); + writel(val | TCON4_START, &timer->tcon); timestamp = 0; @@ -151,7 +151,7 @@ void __udelay(unsigned long usec) void reset_timer_masked(void) { - struct s5pc1xx_timer *const timer = s5pc1xx_get_base_timer(); + struct s5p_timer *const timer = s5p_get_base_timer(); /* reset time */ lastdec = readl(&timer->tcnto4); @@ -160,7 +160,7 @@ void reset_timer_masked(void) unsigned long get_timer_masked(void) { - struct s5pc1xx_timer *const timer = s5pc1xx_get_base_timer(); + struct s5p_timer *const timer = s5p_get_base_timer(); unsigned long now = readl(&timer->tcnto4); if (lastdec >= now) diff --git a/arch/arm/cpu/armv7/s5pc1xx/clock.c b/arch/arm/cpu/armv7/s5pc1xx/clock.c index 67af84a840..c9b54856e3 100644 --- a/arch/arm/cpu/armv7/s5pc1xx/clock.c +++ b/arch/arm/cpu/armv7/s5pc1xx/clock.c @@ -297,7 +297,7 @@ static unsigned long s5pc100_get_pclk(void) return get_pclkd1(); } -void s5pc1xx_clock_init(void) +void s5p_clock_init(void) { if (cpu_is_s5pc110()) { get_pll_clk = s5pc110_get_pll_clk; -- cgit v1.2.3 From 4e4479a8922833025a8aac4f33fff9fa1e294ac9 Mon Sep 17 00:00:00 2001 From: Albert Aribaud <[albert.aribaud@free.fr]> Date: Thu, 26 Aug 2010 14:05:19 +0530 Subject: Orion5x: bugfix: window size (mis)calculation Fix orion5x_winctrl_calcsize() off-by-1 bug which caused mapping windows to be cut by half. This afected all windows including NOR flash (causing half the flash to be unaccessible) but DRAM was and still is fine as its size is determined otherwise. Signed-off-by: Albert Aribaud --- arch/arm/cpu/arm926ejs/orion5x/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/orion5x/cpu.c b/arch/arm/cpu/arm926ejs/orion5x/cpu.c index 3740e33e9d..260f88b46e 100644 --- a/arch/arm/cpu/arm926ejs/orion5x/cpu.c +++ b/arch/arm/cpu/arm926ejs/orion5x/cpu.c @@ -61,7 +61,7 @@ unsigned int orion5x_winctrl_calcsize(unsigned int sizeval) unsigned int j = 0; u32 val = sizeval >> 1; - for (i = 0; val > 0x10000; i++) { + for (i = 0; val >= 0x10000; i++) { j |= (1 << i); val = val >> 1; } -- cgit v1.2.3 From f106056095049c2c748c2a2797e5353295240e04 Mon Sep 17 00:00:00 2001 From: Prafulla Wadaskar Date: Thu, 26 Aug 2010 14:43:55 +0530 Subject: Kirkwood: bugfix: window size (mis)calculation Fixed kw_winctrl_calcsize() off-by-1 bug which caused mapping windows size to be cut by half. This corrected all windows address configuration Signed-off-by: Prafulla Wadaskar --- arch/arm/cpu/arm926ejs/kirkwood/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c b/arch/arm/cpu/arm926ejs/kirkwood/cpu.c index c63e8641f2..82c978bd93 100644 --- a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c +++ b/arch/arm/cpu/arm926ejs/kirkwood/cpu.c @@ -81,7 +81,7 @@ unsigned int kw_winctrl_calcsize(unsigned int sizeval) unsigned int j = 0; u32 val = sizeval >> 1; - for (i = 0; val > 0x10000; i++) { + for (i = 0; val >= 0x10000; i++) { j |= (1 << i); val = val >> 1; } -- cgit v1.2.3 From f70409aff3a10e22ff9c66f87e9cbc3de7cbd7f7 Mon Sep 17 00:00:00 2001 From: Minkyu Kang Date: Tue, 24 Aug 2010 15:51:55 +0900 Subject: ARMV7: S5P: separate the peripheral clocks Because of peripheral devices can select clock sources, separate the peripheral clocks. (pwm, uart and so on) It just return the pclk at s5pc1xx SoC, but s5pc210 SoC must be calculated by own clock register setting. Signed-off-by: Minkyu Kang Signed-off-by: Kyungmin Park --- arch/arm/cpu/armv7/s5p-common/timer.c | 4 ++-- arch/arm/cpu/armv7/s5pc1xx/clock.c | 25 ++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c index 1f1c7ff340..04906503e6 100644 --- a/arch/arm/cpu/armv7/s5p-common/timer.c +++ b/arch/arm/cpu/armv7/s5p-common/timer.c @@ -57,7 +57,7 @@ int timer_init(void) /* * @ PWM Timer 4 * Timer Freq(HZ) = - * PCLK / { (prescaler_value + 1) * (divider_value) } + * PWM_CLK / { (prescaler_value + 1) * (divider_value) } */ /* set prescaler : 16 */ @@ -68,7 +68,7 @@ int timer_init(void) if (count_value == 0) { /* reset initial value */ /* count_value = 2085937.5(HZ) (per 1 sec)*/ - count_value = get_pclk() / ((PRESCALER_1 + 1) * + count_value = get_pwm_clk() / ((PRESCALER_1 + 1) * (MUX_DIV_2 + 1)); /* count_value / 100 = 20859.375(HZ) (per 10 msec) */ diff --git a/arch/arm/cpu/armv7/s5pc1xx/clock.c b/arch/arm/cpu/armv7/s5pc1xx/clock.c index c9b54856e3..98a27e551d 100644 --- a/arch/arm/cpu/armv7/s5pc1xx/clock.c +++ b/arch/arm/cpu/armv7/s5pc1xx/clock.c @@ -38,7 +38,8 @@ #define CONFIG_SYS_CLK_FREQ_C110 24000000 #endif -unsigned long (*get_pclk)(void); +unsigned long (*get_uart_clk)(int dev_index); +unsigned long (*get_pwm_clk)(void); unsigned long (*get_arm_clk)(void); unsigned long (*get_pll_clk)(int); @@ -297,15 +298,33 @@ static unsigned long s5pc100_get_pclk(void) return get_pclkd1(); } +/* s5pc1xx: return uart clock frequency */ +static unsigned long s5pc1xx_get_uart_clk(int dev_index) +{ + if (cpu_is_s5pc110()) + return s5pc110_get_pclk(); + else + return s5pc100_get_pclk(); +} + +/* s5pc1xx: return pwm clock frequency */ +static unsigned long s5pc1xx_get_pwm_clk(void) +{ + if (cpu_is_s5pc110()) + return s5pc110_get_pclk(); + else + return s5pc100_get_pclk(); +} + void s5p_clock_init(void) { if (cpu_is_s5pc110()) { get_pll_clk = s5pc110_get_pll_clk; get_arm_clk = s5pc110_get_arm_clk; - get_pclk = s5pc110_get_pclk; } else { get_pll_clk = s5pc100_get_pll_clk; get_arm_clk = s5pc100_get_arm_clk; - get_pclk = s5pc100_get_pclk; } + get_uart_clk = s5pc1xx_get_uart_clk; + get_pwm_clk = s5pc1xx_get_pwm_clk; } -- cgit v1.2.3 From c982d866eaee5e8469af9e22eb8f51c63adcfafa Mon Sep 17 00:00:00 2001 From: Jens Scharsig Date: Sat, 7 Aug 2010 19:49:42 +0200 Subject: AT91 Fix: return value of get_tbclk * Fix: return value of get_tbclk * this fixes issue with prematurely restart/retry, if BOOT_RETRY_TIMEOUT is used Signed-off-by: Jens Scharsig --- arch/arm/cpu/arm926ejs/at91/timer.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/at91/timer.c b/arch/arm/cpu/arm926ejs/at91/timer.c index d21eebfb4e..8efc34bcf1 100644 --- a/arch/arm/cpu/arm926ejs/at91/timer.c +++ b/arch/arm/cpu/arm926ejs/at91/timer.c @@ -138,8 +138,5 @@ ulong get_timer(ulong base) */ ulong get_tbclk(void) { - ulong tbclk; - - tbclk = CONFIG_SYS_HZ; - return tbclk; + return timer_freq; } -- cgit v1.2.3 From 1592ef8596fffd937a30462eb15f1d64e237ae49 Mon Sep 17 00:00:00 2001 From: Reinhard Meyer Date: Fri, 13 Aug 2010 10:31:06 +0200 Subject: AT91: MCI: add SD/MMC driver using mmc framework Signed-off-by: Reinhard Meyer --- arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c b/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c index 77d49ab1c7..2d8848152a 100644 --- a/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c +++ b/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c @@ -194,3 +194,24 @@ void at91_macb_hw_init(void) #endif } #endif + +#if defined(CONFIG_ATMEL_MCI) || defined(CONFIG_GENERIC_ATMEL_MCI) +void at91_mci_hw_init(void) +{ + at91_set_a_periph(AT91_PIO_PORTA, 8, 1); /* MCCK */ +#if defined(CONFIG_ATMEL_MCI_PORTB) + at91_set_b_periph(AT91_PIO_PORTA, 1, 1); /* MCCDB */ + at91_set_b_periph(AT91_PIO_PORTA, 0, 1); /* MCDB0 */ + at91_set_b_periph(AT91_PIO_PORTA, 5, 1); /* MCDB1 */ + at91_set_b_periph(AT91_PIO_PORTA, 4, 1); /* MCDB2 */ + at91_set_b_periph(AT91_PIO_PORTA, 3, 1); /* MCDB3 */ +#else + at91_set_a_periph(AT91_PIO_PORTA, 7, 1); /* MCCDA */ + at91_set_a_periph(AT91_PIO_PORTA, 6, 1); /* MCDA0 */ + at91_set_a_periph(AT91_PIO_PORTA, 9, 1); /* MCDA1 */ + at91_set_a_periph(AT91_PIO_PORTA, 10, 1); /* MCDA2 */ + at91_set_a_periph(AT91_PIO_PORTA, 11, 1); /* MCDA3 */ +#endif +} +#endif + -- cgit v1.2.3 From d88bebe16d8141e85adcc894a10165a6dfd44805 Mon Sep 17 00:00:00 2001 From: Reinhard Meyer Date: Tue, 27 Jul 2010 15:18:38 +0200 Subject: AT91SAM9XE: add embedded flash support Signed-off-by: Reinhard Meyer --- arch/arm/cpu/arm926ejs/at91/Makefile | 1 + arch/arm/cpu/arm926ejs/at91/eflash.c | 271 +++++++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 arch/arm/cpu/arm926ejs/at91/eflash.c (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/at91/Makefile b/arch/arm/cpu/arm926ejs/at91/Makefile index 4f467be91c..def3980b63 100644 --- a/arch/arm/cpu/arm926ejs/at91/Makefile +++ b/arch/arm/cpu/arm926ejs/at91/Makefile @@ -34,6 +34,7 @@ COBJS-$(CONFIG_AT91SAM9263) += at91sam9263_devices.o COBJS-$(CONFIG_AT91SAM9RL) += at91sam9rl_devices.o COBJS-$(CONFIG_AT91SAM9M10G45) += at91sam9m10g45_devices.o COBJS-$(CONFIG_AT91SAM9G45) += at91sam9m10g45_devices.o +COBJS-$(CONFIG_AT91_EFLASH) += eflash.o COBJS-$(CONFIG_AT91_LED) += led.o COBJS-y += clock.o COBJS-y += cpu.o diff --git a/arch/arm/cpu/arm926ejs/at91/eflash.c b/arch/arm/cpu/arm926ejs/at91/eflash.c new file mode 100644 index 0000000000..2e851dbd2c --- /dev/null +++ b/arch/arm/cpu/arm926ejs/at91/eflash.c @@ -0,0 +1,271 @@ +/* + * (C) Copyright 2010 + * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.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 + */ + +/* + * this driver supports the enhanced embedded flash in the Atmel + * AT91SAM9XE devices with the following geometry: + * + * AT91SAM9XE128: 1 plane of 8 regions of 32 pages (total 256 pages) + * AT91SAM9XE256: 1 plane of 16 regions of 32 pages (total 512 pages) + * AT91SAM9XE512: 1 plane of 32 regions of 32 pages (total 1024 pages) + * (the exact geometry is read from the flash at runtime, so any + * future devices should already be covered) + * + * Regions can be write/erase protected. + * Whole (!) pages can be individually written with erase on the fly. + * Writing partial pages will corrupt the rest of the page. + * + * The flash is presented to u-boot with each region being a sector, + * having the following effects: + * Each sector can be hardware protected (protect on/off). + * Each page in a sector can be rewritten anytime. + * Since pages are erased when written, the "erase" does nothing. + * The first "CONFIG_EFLASH_PROTSECTORS" cannot be unprotected + * by u-Boot commands. + * + * Note: Redundant environment will not work in this flash since + * it does use partial page writes. Make sure the environent spans + * whole pages! + */ + +/* + * optional TODOs (nice to have features): + * + * make the driver coexist with other NOR flash drivers + * (use an index into flash_info[], requires work + * in those other drivers, too) + * Make the erase command fill the sectors with 0xff + * (if the flashes grow larger in the future and + * someone puts a jffs2 into them) + * do a read-modify-write for partially programmed pages + */ +#include +#include +#include +#include +#include +#include + +/* checks to detect configuration errors */ +#if CONFIG_SYS_MAX_FLASH_BANKS!=1 +#error eflash: this driver can only handle 1 bank +#endif + +/* global structure */ +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; +static u32 pagesize; + +unsigned long flash_init (void) +{ + at91_eefc_t *eefc = (at91_eefc_t *) 0xfffffa00; + at91_dbu_t *dbu = (at91_dbu_t *) 0xfffff200; + u32 id, size, nplanes, planesize, nlocks; + u32 addr, i, tmp=0; + + debug("eflash: init\n"); + + flash_info[0].flash_id = FLASH_UNKNOWN; + + /* check if its an AT91ARM9XE SoC */ + if ((readl(&dbu->cidr) & AT91_DBU_CID_ARCH_MASK) != AT91_DBU_CID_ARCH_9XExx) { + puts("eflash: not an AT91SAM9XE\n"); + return 0; + } + + /* now query the eflash for its structure */ + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GETD, &eefc->fcr); + while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0) + ; + id = readl(&eefc->frr); /* word 0 */ + size = readl(&eefc->frr); /* word 1 */ + pagesize = readl(&eefc->frr); /* word 2 */ + nplanes = readl(&eefc->frr); /* word 3 */ + planesize = readl(&eefc->frr); /* word 4 */ + debug("id=%08x size=%u pagesize=%u planes=%u planesize=%u\n", + id, size, pagesize, nplanes, planesize); + for (i=1; ifrr); /* words 5..4+nplanes-1 */ + }; + nlocks = readl(&eefc->frr); /* word 4+nplanes */ + debug("nlocks=%u\n", nlocks); + /* since we are going to use the lock regions as sectors, check count */ + if (nlocks > CONFIG_SYS_MAX_FLASH_SECT) { + printf("eflash: number of lock regions(%u) "\ + "> CONFIG_SYS_MAX_FLASH_SECT. reducing...\n", + nlocks); + nlocks = CONFIG_SYS_MAX_FLASH_SECT; + } + flash_info[0].size = size; + flash_info[0].sector_count = nlocks; + flash_info[0].flash_id = id; + + addr = AT91SAM9XE_FLASH_BASE; + for (i=0; ifrr); /* words 4+nplanes+1.. */ + flash_info[0].start[i] = addr; + flash_info[0].protect[i] = 0; + addr += tmp; + }; + + /* now read the protection information for all regions */ + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr); + while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0) + ; + for (i=0; ifrr); + flash_info[0].protect[i] = (tmp >> (i%32)) & 1; +#if defined(CONFIG_EFLASH_PROTSECTORS) + if (i < CONFIG_EFLASH_PROTSECTORS) + flash_info[0].protect[i] = 1; +#endif + } + + return size; +} + +void flash_print_info (flash_info_t *info) +{ + int i; + + puts("AT91SAM9XE embedded flash\n Size: "); + print_size(info->size, " in "); + printf("%d Sectors\n", info->sector_count); + + printf(" Sector Start Addresses:"); + for (i=0; isector_count; ++i) { + if ((i % 5) == 0) + printf("\n "); + printf(" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + +int flash_real_protect (flash_info_t *info, long sector, int prot) +{ + at91_eefc_t *eefc = (at91_eefc_t *) 0xfffffa00; + u32 pagenum = (info->start[sector]-AT91SAM9XE_FLASH_BASE)/pagesize; + u32 i, tmp=0; + + debug("protect sector=%ld prot=%d\n", sector, prot); + +#if defined(CONFIG_EFLASH_PROTSECTORS) + if (sector < CONFIG_EFLASH_PROTSECTORS) { + if (!prot) { + printf("eflash: sector %lu cannot be unprotected\n", + sector); + } + return 1; /* return anyway, caller does not care for result */ + } +#endif + if (prot) { + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_SLB | + (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr); + } else { + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_CLB | + (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr); + } + while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0) + ; + /* now re-read the protection information for all regions */ + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr); + while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0) + ; + for (i=0; isector_count; i++) { + if (i%32 == 0) + tmp = readl(&eefc->frr); + info->protect[i] = (tmp >> (i%32)) & 1; + } + return 0; +} + +static u32 erase_write_page (u32 pagenum) +{ + at91_eefc_t *eefc = (at91_eefc_t *) 0xfffffa00; + + debug("erase+write page=%u\n", pagenum); + + /* give erase and write page command */ + writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_EWP | + (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr); + while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0) + ; + /* return status */ + return readl(&eefc->fsr) + & (AT91_EEFC_FSR_FCMDE | AT91_EEFC_FSR_FLOCKE); +} + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + debug("erase first=%d last=%d\n", s_first, s_last); + puts("this flash does not need and support erasing!\n"); + return 0; +} + +/* + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + u32 pagenum; + u32 *src32, *dst32; + u32 i; + + debug("write src=%08lx addr=%08lx cnt=%lx\n", + (ulong)src, addr, cnt); + + /* REQUIRE addr to be on a page start, abort if not */ + if (addr % pagesize) { + printf ("eflash: start %08lx is not on page start\n"\ + " write aborted\n", addr); + return 1; + } + + /* now start copying data */ + pagenum = (addr-AT91SAM9XE_FLASH_BASE)/pagesize; + src32 = (u32 *) src; + dst32 = (u32 *) addr; + while (cnt > 0) { + i = pagesize / 4; + /* fill page buffer */ + while (i--) + *dst32++ = *src32++; + /* write page */ + if (erase_write_page(pagenum)) + return 1; + pagenum++; + if (cnt > pagesize) + cnt -= pagesize; + else + cnt = 0; + } + return 0; +} + -- cgit v1.2.3 From e0cd44c3c1209c281d67b18372e584b143885303 Mon Sep 17 00:00:00 2001 From: Reinhard Meyer Date: Mon, 9 Aug 2010 13:25:37 +0200 Subject: AT91: reset.c: fix comments, add option Signed-off-by: Reinhard Meyer --- arch/arm/cpu/arm926ejs/at91/reset.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/at91/reset.c b/arch/arm/cpu/arm926ejs/at91/reset.c index 1b67e77887..d2569d8bae 100644 --- a/arch/arm/cpu/arm926ejs/at91/reset.c +++ b/arch/arm/cpu/arm926ejs/at91/reset.c @@ -27,18 +27,19 @@ #include #include -/* - * Reset the cpu by setting up the watchdog timer and let him time out. - */ +/* Reset the cpu by telling the reset controller to do so */ void reset_cpu(ulong ignored) { at91_rstc_t *rstc = (at91_rstc_t *) AT91_RSTC_BASE; - /* this is the way Linux does it */ - - writel(AT91_RSTC_KEY | AT91_RSTC_CR_PROCRST | AT91_RSTC_CR_PERRST, - &rstc->cr); - - while (1); - /* Never reached */ + writel(AT91_RSTC_KEY + | AT91_RSTC_CR_PROCRST /* Processor Reset */ + | AT91_RSTC_CR_PERRST /* Peripheral Reset */ +#ifdef CONFIG_AT91RESET_EXTRST + | AT91_RSTC_CR_EXTRST /* External Reset (assert nRST pin) */ +#endif + , &rstc->cr); + /* never reached */ + while (1) + ; } -- cgit v1.2.3 From 7588ad12bafe596c273e13cd80bb3bfbac0e08c7 Mon Sep 17 00:00:00 2001 From: Reinhard Meyer Date: Wed, 25 Aug 2010 12:32:53 +0200 Subject: AT91: add option to enable pullups in at91sam9260_devices.c Signed-off-by: Reinhard Meyer --- arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c | 35 ++++++++++++++++------- 1 file changed, 25 insertions(+), 10 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c b/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c index 2d8848152a..87b04426b9 100644 --- a/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c +++ b/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c @@ -28,12 +28,27 @@ #include #include +/* + * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all + * peripheral pins. Good to have if hardware is soldered optionally + * or in case of SPI no slave is selected. Avoid lines to float + * needlessly. Use a short local PUP define. + * + * Due to errata "TXD floats when CTS is inactive" pullups are always + * on for TXD pins. + */ +#ifdef CONFIG_AT91_GPIO_PULLUP +# define PUP CONFIG_AT91_GPIO_PULLUP +#else +# define PUP 0 +#endif + void at91_serial0_hw_init(void) { at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; at91_set_a_periph(AT91_PIO_PORTB, 4, 1); /* TXD0 */ - at91_set_a_periph(AT91_PIO_PORTB, 5, 0); /* RXD0 */ + at91_set_a_periph(AT91_PIO_PORTB, 5, PUP); /* RXD0 */ writel(1 << AT91SAM9260_ID_US0, &pmc->pcer); } @@ -42,7 +57,7 @@ void at91_serial1_hw_init(void) at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; at91_set_a_periph(AT91_PIO_PORTB, 6, 1); /* TXD1 */ - at91_set_a_periph(AT91_PIO_PORTB, 7, 0); /* RXD1 */ + at91_set_a_periph(AT91_PIO_PORTB, 7, PUP); /* RXD1 */ writel(1 << AT91SAM9260_ID_US1, &pmc->pcer); } @@ -51,7 +66,7 @@ void at91_serial2_hw_init(void) at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; at91_set_a_periph(AT91_PIO_PORTB, 8, 1); /* TXD2 */ - at91_set_a_periph(AT91_PIO_PORTB, 9, 0); /* RXD2 */ + at91_set_a_periph(AT91_PIO_PORTB, 9, PUP); /* RXD2 */ writel(1 << AT91SAM9260_ID_US2, &pmc->pcer); } @@ -59,7 +74,7 @@ void at91_serial3_hw_init(void) { at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; - at91_set_a_periph(AT91_PIO_PORTB, 14, 0); /* DRXD */ + at91_set_a_periph(AT91_PIO_PORTB, 14, PUP); /* DRXD */ at91_set_a_periph(AT91_PIO_PORTB, 15, 1); /* DTXD */ writel(1 << AT91_ID_SYS, &pmc->pcer); } @@ -88,9 +103,9 @@ void at91_spi0_hw_init(unsigned long cs_mask) { at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; - at91_set_a_periph(AT91_PIO_PORTA, 0, 0); /* SPI0_MISO */ - at91_set_a_periph(AT91_PIO_PORTA, 1, 0); /* SPI0_MOSI */ - at91_set_a_periph(AT91_PIO_PORTA, 2, 0); /* SPI0_SPCK */ + at91_set_a_periph(AT91_PIO_PORTA, 0, PUP); /* SPI0_MISO */ + at91_set_a_periph(AT91_PIO_PORTA, 1, PUP); /* SPI0_MOSI */ + at91_set_a_periph(AT91_PIO_PORTA, 2, PUP); /* SPI0_SPCK */ /* Enable clock */ writel(1 << AT91SAM9260_ID_SPI0, &pmc->pcer); @@ -125,9 +140,9 @@ void at91_spi1_hw_init(unsigned long cs_mask) { at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; - at91_set_a_periph(AT91_PIO_PORTB, 0, 0); /* SPI1_MISO */ - at91_set_a_periph(AT91_PIO_PORTB, 1, 0); /* SPI1_MOSI */ - at91_set_a_periph(AT91_PIO_PORTB, 2, 0); /* SPI1_SPCK */ + at91_set_a_periph(AT91_PIO_PORTB, 0, PUP); /* SPI1_MISO */ + at91_set_a_periph(AT91_PIO_PORTB, 1, PUP); /* SPI1_MOSI */ + at91_set_a_periph(AT91_PIO_PORTB, 2, PUP); /* SPI1_SPCK */ /* Enable clock */ writel(1 << AT91SAM9260_ID_SPI1, &pmc->pcer); -- cgit v1.2.3 From 0e7b62179fa56dc01baccc52ba0bcce8f7e07397 Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Wed, 4 Aug 2010 09:39:40 -0700 Subject: ARMV7: OMAP: Move syslib.c to omap-common since it can be shared by OMAP3 and OMAP4 The functions in syslib.c can be shared, so this patch moves it from cpu/omap3 to cpu/omap-common Signed-off-by: Steve Sakoman Signed-off-by: Sandeep Paulraj --- arch/arm/cpu/armv7/omap-common/Makefile | 2 + arch/arm/cpu/armv7/omap-common/syslib.c | 70 ++++++++++++++++++++++++++++++++ arch/arm/cpu/armv7/omap3/Makefile | 1 - arch/arm/cpu/armv7/omap3/syslib.c | 72 --------------------------------- 4 files changed, 72 insertions(+), 73 deletions(-) create mode 100644 arch/arm/cpu/armv7/omap-common/syslib.c delete mode 100644 arch/arm/cpu/armv7/omap3/syslib.c (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap-common/Makefile b/arch/arm/cpu/armv7/omap-common/Makefile index 3a4a304e45..caee7263b1 100644 --- a/arch/arm/cpu/armv7/omap-common/Makefile +++ b/arch/arm/cpu/armv7/omap-common/Makefile @@ -26,7 +26,9 @@ include $(TOPDIR)/config.mk LIB = $(obj)libomap-common.a SOBJS := reset.o + COBJS := timer.o +COBJS += syslib.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/arch/arm/cpu/armv7/omap-common/syslib.c b/arch/arm/cpu/armv7/omap-common/syslib.c new file mode 100644 index 0000000000..f9ed9a307b --- /dev/null +++ b/arch/arm/cpu/armv7/omap-common/syslib.c @@ -0,0 +1,70 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, + * + * 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 + +/************************************************************ + * 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); +} diff --git a/arch/arm/cpu/armv7/omap3/Makefile b/arch/arm/cpu/armv7/omap3/Makefile index 79ae26706e..95526d6893 100644 --- a/arch/arm/cpu/armv7/omap3/Makefile +++ b/arch/arm/cpu/armv7/omap3/Makefile @@ -32,7 +32,6 @@ COBJS += board.o COBJS += clock.o COBJS += gpio.o COBJS += mem.o -COBJS += syslib.o COBJS += sys_info.o COBJS-$(CONFIG_EMIF4) += emif4.o diff --git a/arch/arm/cpu/armv7/omap3/syslib.c b/arch/arm/cpu/armv7/omap3/syslib.c deleted file mode 100644 index 9ced495c8d..0000000000 --- a/arch/arm/cpu/armv7/omap3/syslib.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * (C) Copyright 2008 - * Texas Instruments, - * - * 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 - -/************************************************************ - * 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); -} -- cgit v1.2.3 From b2b9169f0bc860ac34d7828df8730744394d8f6e Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Tue, 17 Aug 2010 14:39:34 -0700 Subject: ARMV7: OMAP3: Update CPU type detection for AM35XX/OMAP36XX/37XX TI has added new processors to the OMAP3 family. This patch enhances the code in sysinfo.c to detect which family member is present. Signed-off-by: Steve Sakoman Signed-off-by: Sandeep Paulraj --- arch/arm/cpu/armv7/omap3/sys_info.c | 147 +++++++++++++++++++++++++++++------- 1 file changed, 121 insertions(+), 26 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap3/sys_info.c b/arch/arm/cpu/armv7/omap3/sys_info.c index 1df4401d49..549ac19189 100644 --- a/arch/arm/cpu/armv7/omap3/sys_info.c +++ b/arch/arm/cpu/armv7/omap3/sys_info.c @@ -38,7 +38,10 @@ static char *rev_s[CPU_3XX_MAX_REV] = { "2.0", "2.1", "3.0", - "3.1"}; + "3.1", + "UNKNOWN", + "UNKNOWN", + "3.1.2"}; /***************************************************************** * dieid_num_r(void) - read and set die ID @@ -75,32 +78,81 @@ u32 get_cpu_type(void) } /****************************************** - * get_cpu_rev(void) - extract version info + * get_cpu_id(void) - extract cpu id + * returns 0 for ES1.0, cpuid otherwise ******************************************/ -u32 get_cpu_rev(void) +u32 get_cpu_id(void) { - u32 cpuid = 0; struct ctrl_id *id_base; + u32 cpuid = 0; /* * 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 { + if ((cpuid & 0xf) == 0x0) { + return 0; + } 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; + cpuid = readl(&id_base->idcode); + } - /* Some early ES2.0 seem to report ID 0, fix this */ - if(cpuid == 0) - cpuid = CPU_3XX_ES20; + return cpuid; +} - return cpuid; +/****************************************** + * get_cpu_family(void) - extract cpu info + ******************************************/ +u32 get_cpu_family(void) +{ + u16 hawkeye; + u32 cpu_family; + u32 cpuid = get_cpu_id(); + + if (cpuid == 0) + return CPU_OMAP34XX; + + hawkeye = (cpuid >> HAWKEYE_SHIFT) & 0xffff; + switch (hawkeye) { + case HAWKEYE_OMAP34XX: + cpu_family = CPU_OMAP34XX; + break; + case HAWKEYE_AM35XX: + cpu_family = CPU_AM35XX; + break; + case HAWKEYE_OMAP36XX: + cpu_family = CPU_OMAP36XX; + break; + default: + cpu_family = CPU_OMAP34XX; } + + return cpu_family; +} + +/****************************************** + * get_cpu_rev(void) - extract version info + ******************************************/ +u32 get_cpu_rev(void) +{ + u32 cpuid = get_cpu_id(); + + if (cpuid == 0) + return CPU_3XX_ES10; + else + return (cpuid >> CPU_3XX_ID_SHIFT) & 0xf; +} + +/***************************************************************** + * get_sku_id(void) - read sku_id to get info on max clock rate + *****************************************************************/ +u32 get_sku_id(void) +{ + struct ctrl_id *id_base = (struct ctrl_id *)OMAP34XX_ID_L4_IO_BASE; + return readl(&id_base->sku_id) & SKUID_CLK_MASK; } /*************************************************************************** @@ -213,24 +265,66 @@ u32 get_device_type(void) */ int print_cpuinfo (void) { - char *cpu_s, *sec_s; + char *cpu_family_s, *cpu_s, *sec_s, *max_clk; + + switch (get_cpu_family()) { + case CPU_OMAP34XX: + cpu_family_s = "OMAP"; + 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; + } + if ((get_cpu_rev() >= CPU_3XX_ES31) && + (get_sku_id() == SKUID_CLK_720MHZ)) + max_clk = "720 mHz"; + else + max_clk = "600 mHz"; - switch (get_cpu_type()) { - case OMAP3503: - cpu_s = "3503"; break; - case OMAP3515: - cpu_s = "3515"; + case CPU_AM35XX: + cpu_family_s = "AM"; + switch (get_cpu_type()) { + case AM3505: + cpu_s = "3505"; + break; + case AM3517: + cpu_s = "3517"; + break; + default: + cpu_s = "35XX"; + break; + } + max_clk = "600 Mhz"; break; - case OMAP3525: - cpu_s = "3525"; - break; - case OMAP3530: - cpu_s = "3530"; + case CPU_OMAP36XX: + cpu_family_s = "OMAP"; + switch (get_cpu_type()) { + case OMAP3730: + cpu_s = "3630/3730"; + break; + default: + cpu_s = "36XX/37XX"; + break; + } + max_clk = "1 Ghz"; break; default: + cpu_family_s = "OMAP"; cpu_s = "35XX"; - break; + max_clk = "600 Mhz"; } switch (get_device_type()) { @@ -250,8 +344,9 @@ int print_cpuinfo (void) sec_s = "?"; } - printf("OMAP%s-%s ES%s, CPU-OPP2 L3-165MHz\n", - cpu_s, sec_s, rev_s[get_cpu_rev()]); + printf("%s%s-%s ES%s, CPU-OPP2, L3-165MHz, Max CPU Clock %s\n", + cpu_family_s, cpu_s, sec_s, + rev_s[get_cpu_rev()], max_clk); return 0; } -- cgit v1.2.3 From 7c281c985c33318d0795e43909e0d26f870f98ed Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Wed, 18 Aug 2010 07:34:09 -0700 Subject: ARMV7: OMAP3: Add clock setup for OMAP36XX/37XX This patch configures clocks properly when a 36XX/37XX processor is detected. Signed-off-by: Steve Sakoman Signed-off-by: Sandeep Paulraj --- arch/arm/cpu/armv7/omap3/clock.c | 549 ++++++++++++++++++++++--------- arch/arm/cpu/armv7/omap3/lowlevel_init.S | 69 ++++ 2 files changed, 471 insertions(+), 147 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap3/clock.c b/arch/arm/cpu/armv7/omap3/clock.c index 6330c9e5da..2238c52e3b 100644 --- a/arch/arm/cpu/armv7/omap3/clock.c +++ b/arch/arm/cpu/armv7/omap3/clock.c @@ -50,12 +50,7 @@ u32 get_osc_clk_speed(void) 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 */ @@ -89,11 +84,7 @@ u32 get_osc_clk_speed(void) 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; - } + cdiff *= cdiv; /* based on number of ticks assign speed */ if (cdiff > 19000) @@ -135,65 +126,22 @@ void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel) } } -/****************************************************************************** - * prcm_init() - inits clocks for PRCM as defined in clocks.h - * called from SRAM, or Flash (using temp SRAM stack). - *****************************************************************************/ -void prcm_init(void) +/* + * OMAP34XX/35XX specific functions + */ + +static void dpll3_init_34xx(u32 sil_index, u32 clk_index) { + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_core_dpll_param(); 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); + /* Moving to the right sysclk and ES rev base */ + ptr = ptr + (3 * clk_index) + sil_index; - /* 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 @@ -208,34 +156,38 @@ void prcm_init(void) * work. write another value and then default value. */ - /* m3x2 */ - sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2 + 1); - /* m3x2 */ + /* CM_CLKSEL1_EMU[DIV_DPLL3] */ + sr32(&prcm_base->clksel1_emu, 16, 5, (CORE_M3X2 + 1)) ; 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 */ + + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + sr32(&prcm_base->clksel1_pll, 27, 5, ptr->m2); + + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + sr32(&prcm_base->clksel1_pll, 16, 11, ptr->m); + + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + sr32(&prcm_base->clksel1_pll, 8, 7, ptr->n); + + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ sr32(&prcm_base->clksel1_pll, 6, 1, 0); - /* ssi */ + + /* SSI */ sr32(&prcm_base->clksel_core, 8, 4, CORE_SSI_DIV); - /* fsusb */ + /* FSUSB */ sr32(&prcm_base->clksel_core, 4, 2, CORE_FUSB_DIV); - /* l4 */ + /* L4 */ sr32(&prcm_base->clksel_core, 2, 2, CORE_L4_DIV); - /* l3 */ + /* L3 */ sr32(&prcm_base->clksel_core, 0, 2, CORE_L3_DIV); - /* gfx */ - sr32(&prcm_base->clksel_gfx, 0, 3, GFX_DIV); - /* reset mgr */ + /* 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); + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + sr32(&prcm_base->clken_pll, 4, 4, ptr->fsel); + /* LOCK MODE */ + sr32(&prcm_base->clken_pll, 0, 3, PLL_LOCK); wait_on_value(ST_CORE_CLK, 1, &prcm_base->idlest_ckgen, LDELAY); @@ -244,102 +196,405 @@ void prcm_init(void) * if running from flash, jump to small relocated code * area in SRAM. */ + f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start + + SRAM_VECT_CODE); + p0 = readl(&prcm_base->clken_pll); sr32(&p0, 0, 3, PLL_FAST_RELOCK_BYPASS); - sr32(&p0, 4, 4, dpll_param_p->fsel); /* FREQSEL */ + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + sr32(&p0, 4, 4, ptr->fsel); 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 */ + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + sr32(&p1, 27, 5, ptr->m2); + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + sr32(&p1, 16, 11, ptr->m); + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + sr32(&p1, 8, 7, ptr->n); + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + sr32(&p1, 6, 1, 0); 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 */ + /* SSI */ + sr32(&p2, 8, 4, CORE_SSI_DIV); + /* FSUSB */ + sr32(&p2, 4, 2, CORE_FUSB_DIV); + /* L4 */ + sr32(&p2, 2, 2, CORE_L4_DIV); + /* L3 */ + sr32(&p2, 0, 2, CORE_L3_DIV); 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(); +static void dpll4_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_per_dpll_param(); /* Moving it to the right sysclk base */ - dpll_param_p = dpll_param_p + clk_index; + ptr = ptr + clk_index; + + /* EN_PERIPH_DPLL: CM_CLKEN_PLL[16:18] */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_STOP); + wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY); /* * 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 */ + /* M6 */ + sr32(&prcm_base->clksel1_emu, 24, 5, (PER_M6X2 + 1)); + sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2); + /* M5 */ + sr32(&prcm_base->clksel_cam, 0, 5, (PER_M5X2 + 1)); + sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2); + /* M4 */ + sr32(&prcm_base->clksel_dss, 0, 5, (PER_M4X2 + 1)); + sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2); + /* M3 */ + sr32(&prcm_base->clksel_dss, 8, 5, (PER_M3X2 + 1)); + sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2); + /* M2 (DIV_96M): CM_CLKSEL3_PLL[0:4] */ + sr32(&prcm_base->clksel3_pll, 0, 5, (ptr->m2 + 1)); + sr32(&prcm_base->clksel3_pll, 0, 5, ptr->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 */ + /* M (PERIPH_DPLL_MULT): CM_CLKSEL2_PLL[8:18] */ + sr32(&prcm_base->clksel2_pll, 8, 11, ptr->m); + + /* N (PERIPH_DPLL_DIV): CM_CLKSEL2_PLL[0:6] */ + sr32(&prcm_base->clksel2_pll, 0, 7, ptr->n); + + /* FREQSEL (PERIPH_DPLL_FREQSEL): CM_CLKEN_PLL[20:23] */ + sr32(&prcm_base->clken_pll, 20, 4, ptr->fsel); + + /* LOCK MODE (EN_PERIPH_DPLL): CM_CLKEN_PLL[16:18] */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_LOCK); 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(); +static void mpu_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (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; + /* Moving to the right sysclk and ES rev base */ + ptr = ptr + (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) */ + /* M2 (MPU_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_MPU[0:4] */ + sr32(&prcm_base->clksel2_pll_mpu, 0, 5, ptr->m2); + + /* M (MPU_DPLL_MULT) : CM_CLKSEL2_PLL_MPU[8:18] */ + sr32(&prcm_base->clksel1_pll_mpu, 8, 11, ptr->m); + + /* N (MPU_DPLL_DIV) : CM_CLKSEL2_PLL_MPU[0:6] */ + sr32(&prcm_base->clksel1_pll_mpu, 0, 7, ptr->n); + + /* FREQSEL (MPU_DPLL_FREQSEL) : CM_CLKEN_PLL_MPU[4:7] */ + sr32(&prcm_base->clken_pll_mpu, 4, 4, ptr->fsel); +} + +static void iva_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_iva_dpll_param(); + + /* Moving to the right sysclk and ES rev base */ + ptr = ptr + (3 * clk_index) + sil_index; + + /* IVA DPLL */ + /* EN_IVA2_DPLL : CM_CLKEN_PLL_IVA2[0:2] */ + sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_STOP); + wait_on_value(ST_IVA2_CLK, 0, &prcm_base->idlest_pll_iva2, LDELAY); + + /* M2 (IVA2_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_IVA2[0:4] */ + sr32(&prcm_base->clksel2_pll_iva2, 0, 5, ptr->m2); + + /* M (IVA2_DPLL_MULT) : CM_CLKSEL1_PLL_IVA2[8:18] */ + sr32(&prcm_base->clksel1_pll_iva2, 8, 11, ptr->m); + + /* N (IVA2_DPLL_DIV) : CM_CLKSEL1_PLL_IVA2[0:6] */ + sr32(&prcm_base->clksel1_pll_iva2, 0, 7, ptr->n); + + /* FREQSEL (IVA2_DPLL_FREQSEL) : CM_CLKEN_PLL_IVA2[4:7] */ + sr32(&prcm_base->clken_pll_iva2, 4, 4, ptr->fsel); + + /* LOCK MODE (EN_IVA2_DPLL) : CM_CLKEN_PLL_IVA2[0:2] */ + sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_LOCK); + + wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY); +} + +/* + * OMAP3630 specific functions + */ + +static void dpll3_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_36x_core_dpll_param(); + void (*f_lock_pll) (u32, u32, u32, u32); + int xip_safe, p0, p1, p2, p3; + + xip_safe = is_running_in_sram(); + + /* Moving it to the right sysclk base */ + ptr += clk_index; + + if (xip_safe) { + /* CORE DPLL */ + + /* Select relock bypass: CM_CLKEN_PLL[0:2] */ + sr32(&prcm_base->clken_pll, 0, 3, PLL_FAST_RELOCK_BYPASS); + wait_on_value(ST_CORE_CLK, 0, &prcm_base->idlest_ckgen, + LDELAY); + + /* CM_CLKSEL1_EMU[DIV_DPLL3] */ + sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2); + + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + sr32(&prcm_base->clksel1_pll, 27, 5, ptr->m2); + + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + sr32(&prcm_base->clksel1_pll, 16, 11, ptr->m); + + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + sr32(&prcm_base->clksel1_pll, 8, 7, ptr->n); + + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + 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 (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + sr32(&prcm_base->clken_pll, 4, 4, ptr->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. + */ + f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start + + SRAM_VECT_CODE); + + p0 = readl(&prcm_base->clken_pll); + sr32(&p0, 0, 3, PLL_FAST_RELOCK_BYPASS); + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + sr32(&p0, 4, 4, ptr->fsel); + + p1 = readl(&prcm_base->clksel1_pll); + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + sr32(&p1, 27, 5, ptr->m2); + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + sr32(&p1, 16, 11, ptr->m); + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + sr32(&p1, 8, 7, ptr->n); + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + sr32(&p1, 6, 1, 0); + + p2 = readl(&prcm_base->clksel_core); + /* SSI */ + sr32(&p2, 8, 4, CORE_SSI_DIV); + /* FSUSB */ + sr32(&p2, 4, 2, CORE_FUSB_DIV); + /* L4 */ + sr32(&p2, 2, 2, CORE_L4_DIV); + /* L3 */ + sr32(&p2, 0, 2, CORE_L3_DIV); + + p3 = (u32)&prcm_base->idlest_ckgen; + + (*f_lock_pll) (p0, p1, p2, p3); + } +} + +static void dpll4_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + struct dpll_per_36x_param *ptr; + + ptr = (struct dpll_per_36x_param *)get_36x_per_dpll_param(); + + /* Moving it to the right sysclk base */ + ptr += clk_index; + + /* EN_PERIPH_DPLL: CM_CLKEN_PLL[16:18] */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_STOP); + wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY); + + /* M6 (DIV_DPLL4): CM_CLKSEL1_EMU[24:29] */ + sr32(&prcm_base->clksel1_emu, 24, 6, ptr->m6); + + /* M5 (CLKSEL_CAM): CM_CLKSEL1_EMU[0:5] */ + sr32(&prcm_base->clksel_cam, 0, 6, ptr->m5); + + /* M4 (CLKSEL_DSS1): CM_CLKSEL_DSS[0:5] */ + sr32(&prcm_base->clksel_dss, 0, 6, ptr->m4); + + /* M3 (CLKSEL_DSS1): CM_CLKSEL_DSS[8:13] */ + sr32(&prcm_base->clksel_dss, 8, 6, ptr->m3); + + /* M2 (DIV_96M): CM_CLKSEL3_PLL[0:4] */ + sr32(&prcm_base->clksel3_pll, 0, 5, ptr->m2); + + /* M (PERIPH_DPLL_MULT): CM_CLKSEL2_PLL[8:19] */ + sr32(&prcm_base->clksel2_pll, 8, 12, ptr->m); + + /* N (PERIPH_DPLL_DIV): CM_CLKSEL2_PLL[0:6] */ + sr32(&prcm_base->clksel2_pll, 0, 7, ptr->n); + + /* M2DIV (CLKSEL_96M): CM_CLKSEL_CORE[12:13] */ + sr32(&prcm_base->clksel_core, 12, 2, ptr->m2div); + + /* LOCK MODE (EN_PERIPH_DPLL): CM_CLKEN_PLL[16:18] */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_LOCK); + wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY); +} + +static void mpu_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_36x_mpu_dpll_param(); + + /* Moving to the right sysclk */ + ptr += clk_index; + + /* MPU DPLL (unlocked already */ + + /* M2 (MPU_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_MPU[0:4] */ + sr32(&prcm_base->clksel2_pll_mpu, 0, 5, ptr->m2); + + /* M (MPU_DPLL_MULT) : CM_CLKSEL2_PLL_MPU[8:18] */ + sr32(&prcm_base->clksel1_pll_mpu, 8, 11, ptr->m); + + /* N (MPU_DPLL_DIV) : CM_CLKSEL2_PLL_MPU[0:6] */ + sr32(&prcm_base->clksel1_pll_mpu, 0, 7, ptr->n); +} + +static void iva_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *)get_36x_iva_dpll_param(); + + /* Moving to the right sysclk */ + ptr += clk_index; + + /* IVA DPLL */ + /* EN_IVA2_DPLL : CM_CLKEN_PLL_IVA2[0:2] */ 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 */ + + /* M2 (IVA2_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_IVA2[0:4] */ + sr32(&prcm_base->clksel2_pll_iva2, 0, 5, ptr->m2); + + /* M (IVA2_DPLL_MULT) : CM_CLKSEL1_PLL_IVA2[8:18] */ + sr32(&prcm_base->clksel1_pll_iva2, 8, 11, ptr->m); + + /* N (IVA2_DPLL_DIV) : CM_CLKSEL1_PLL_IVA2[0:6] */ + sr32(&prcm_base->clksel1_pll_iva2, 0, 7, ptr->n); + + /* LOCK (MODE (EN_IVA2_DPLL) : CM_CLKEN_PLL_IVA2[0:2] */ sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_LOCK); + wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY); +} + +/****************************************************************************** + * prcm_init() - inits clocks for PRCM as defined in clocks.h + * called from SRAM, or Flash (using temp SRAM stack). + *****************************************************************************/ +void prcm_init(void) +{ + 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; + + /* + * 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; + } + + if (get_cpu_family() == CPU_OMAP36XX) { + /* 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); + + dpll3_init_36xx(0, clk_index); + dpll4_init_36xx(0, clk_index); + iva_init_36xx(0, clk_index); + mpu_init_36xx(0, clk_index); + + /* Lock MPU DPLL to set frequency */ + sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOCK); + wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, + LDELAY); + } else { + /* + * 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_family() == CPU_OMAP34XX) + && (get_cpu_rev() >= CPU_3XX_ES20)) || + (get_cpu_family() == CPU_AM35XX)) + 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); + + dpll3_init_34xx(sil_index, clk_index); + dpll4_init_34xx(sil_index, clk_index); + iva_init_34xx(sil_index, clk_index); + mpu_init_34xx(sil_index, clk_index); + + /* Lock MPU DPLL to set frequency */ + sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOCK); + wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, + LDELAY); + } /* Set up GPTimers to sys_clk source only */ sr32(&prcm_base->clksel_per, 0, 8, 0xff); diff --git a/arch/arm/cpu/armv7/omap3/lowlevel_init.S b/arch/arm/cpu/armv7/omap3/lowlevel_init.S index 73063ec8e6..91c6dbcc09 100644 --- a/arch/arm/cpu/armv7/omap3/lowlevel_init.S +++ b/arch/arm/cpu/armv7/omap3/lowlevel_init.S @@ -359,3 +359,72 @@ per_dpll_param: get_per_dpll_param: adr r0, per_dpll_param mov pc, lr + +/* + * Tables for 36XX/37XX devices + * + */ +mpu_36x_dpll_param: +/* 12MHz */ +.word 50, 0, 0, 1 +/* 13MHz */ +.word 600, 12, 0, 1 +/* 19.2MHz */ +.word 125, 3, 0, 1 +/* 26MHz */ +.word 300, 12, 0, 1 +/* 38.4MHz */ +.word 125, 7, 0, 1 + +iva_36x_dpll_param: +/* 12MHz */ +.word 130, 2, 0, 1 +/* 13MHz */ +.word 20, 0, 0, 1 +/* 19.2MHz */ +.word 325, 11, 0, 1 +/* 26MHz */ +.word 10, 0, 0, 1 +/* 38.4MHz */ +.word 325, 23, 0, 1 + +core_36x_dpll_param: +/* 12MHz */ +.word 100, 2, 0, 1 +/* 13MHz */ +.word 400, 12, 0, 1 +/* 19.2MHz */ +.word 375, 17, 0, 1 +/* 26MHz */ +.word 200, 12, 0, 1 +/* 38.4MHz */ +.word 375, 35, 0, 1 + +per_36x_dpll_param: +/* SYSCLK M N M2 M3 M4 M5 M6 m2DIV */ +.word 12000, 360, 4, 9, 16, 5, 4, 3, 1 +.word 13000, 864, 12, 9, 16, 9, 4, 3, 1 +.word 19200, 360, 7, 9, 16, 5, 4, 3, 1 +.word 26000, 432, 12, 9, 16, 9, 4, 3, 1 +.word 38400, 360, 15, 9, 16, 5, 4, 3, 1 + +.globl get_36x_mpu_dpll_param +get_36x_mpu_dpll_param: + adr r0, mpu_36x_dpll_param + mov pc, lr + +.globl get_36x_iva_dpll_param +get_36x_iva_dpll_param: + adr r0, iva_36x_dpll_param + mov pc, lr + +.globl get_36x_core_dpll_param +get_36x_core_dpll_param: + adr r0, core_36x_dpll_param + mov pc, lr + +.globl get_36x_per_dpll_param +get_36x_per_dpll_param: + adr r0, per_36x_dpll_param + mov pc, lr + -- cgit v1.2.3 From 29844707469854d9fab181edd6abe2f25fb5d208 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 14 Apr 2010 11:08:00 +0100 Subject: ARMV7: OMAP3: Fix and clean up L2 cache enable/disable functions On OMAP34xx ES1.0, the L2 enable bit can only be set in secure mode, so an SMC call to the ROM monitor is required. On later versions, and on newer devices, this bit is banked and we can set it directly. The code checked only the ES revision of the chip, and hence incorrectly used the ROM call on ES1.0 versions of other devices. This patch adds a check for chip family as well as revision, and also removes some code duplication between the enable and disable functions. Signed-off-by: Mans Rullgard Signed-off-by: Steve Sakoman Signed-off-by: Sandeep Paulraj --- arch/arm/cpu/armv7/omap3/cache.S | 75 +++++++++++----------------------------- 1 file changed, 21 insertions(+), 54 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap3/cache.S b/arch/arm/cpu/armv7/omap3/cache.S index 4b65ac58a5..cb7ca11dab 100644 --- a/arch/arm/cpu/armv7/omap3/cache.S +++ b/arch/arm/cpu/armv7/omap3/cache.S @@ -128,64 +128,31 @@ finished_inval: 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 +l2_cache_set: + stmfd r13!, {r4 - r6, lr} + mov r5, r0 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 - @ + mov r4, r0 + bl get_cpu_family + @ ES2 onwards we can disable/enable L2 ourselves + cmp r0, #CPU_OMAP34XX + cmpeq r4, #CPU_3XX_ES10 + mrc 15, 0, r0, cr1, cr0, 1 + bic r0, r0, #2 + orr r0, r0, r5, lsl #1 + mcreq 15, 0, r0, cr1, cr0, 1 @ 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} + @ SMCNE instruction to call ROM Code API + .word 0x11600070 + ldmfd r13!, {r4 - r6, pc} +l2_cache_enable: + mov r0, #1 + b l2_cache_set 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} + mov r0, #0 + b l2_cache_set + -- cgit v1.2.3 From 096ca838b514be0a20e62500413e42f0a2bb7481 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 14 Apr 2010 15:49:57 +0100 Subject: ARMV7: OMAP3: Convert setup_auxcr() to pure asm This function consists entirely of inline asm statements, so writing it directly in a .S file is simpler. Additionally, the inline asm is not safe as is, since registers are not guaranteed to be preserved between asm() statements. Signed-off-by: Mans Rullgard Signed-off-by: Steve Sakoman Signed-off-by: Sandeep Paulraj --- arch/arm/cpu/armv7/omap3/board.c | 35 ----------------------------------- arch/arm/cpu/armv7/omap3/cache.S | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 35 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c index 69e56f55c5..6c2a132b63 100644 --- a/arch/arm/cpu/armv7/omap3/board.c +++ b/arch/arm/cpu/armv7/omap3/board.c @@ -119,41 +119,6 @@ void secureworld_exit() __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 diff --git a/arch/arm/cpu/armv7/omap3/cache.S b/arch/arm/cpu/armv7/omap3/cache.S index cb7ca11dab..5a19051191 100644 --- a/arch/arm/cpu/armv7/omap3/cache.S +++ b/arch/arm/cpu/armv7/omap3/cache.S @@ -43,6 +43,7 @@ .global invalidate_dcache .global l2_cache_enable .global l2_cache_disable +.global setup_auxcr /* * invalidate_dcache() @@ -156,3 +157,21 @@ l2_cache_disable: mov r0, #0 b l2_cache_set +/****************************************************************************** + * Routine: setup_auxcr() + * Description: Write to AuxCR desired value using SMI. + * general use. + *****************************************************************************/ +setup_auxcr: + mov r12, #0x3 + mrc p15, 0, r0, c1, c0, 1 + orr r0, r0, #0x10 @ Enable ASA + orr r0, r0, #1 << 5 @ Enable L1NEON + .word 0xE1600070 @ SMC + mov r12, #0x2 + mrc p15, 1, r0, c9, c0, 2 + @ Set PLD_FWD bit in L2AUXCR (Cortex-A8 erratum 725233 workaround) + orr r0, r0, #1 << 27 + .word 0xE1600070 @ SMC + bx lr + -- cgit v1.2.3 From 0c0a0e07811965188d5f64cdbc186331c0598fa6 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 14 Apr 2010 16:10:28 +0100 Subject: ARMV7: OMAP3: Apply Cortex-A8 errata workarounds only on affected revisions The workarounds for errata 621766 and 725233 should only be applied on affected Cortex-A8 revisions. Recent chips use r3px cores where these have been fixed. Signed-off-by: Mans Rullgard Signed-off-by: Steve Sakoman Signed-off-by: Sandeep Paulraj --- arch/arm/cpu/armv7/omap3/cache.S | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap3/cache.S b/arch/arm/cpu/armv7/omap3/cache.S index 5a19051191..24e950f38c 100644 --- a/arch/arm/cpu/armv7/omap3/cache.S +++ b/arch/arm/cpu/armv7/omap3/cache.S @@ -163,15 +163,22 @@ l2_cache_disable: * general use. *****************************************************************************/ setup_auxcr: + mrc p15, 0, r0, c0, c0, 0 @ read main ID register + and r2, r0, #0x00f00000 @ variant + and r3, r0, #0x0000000f @ revision + orr r1, r3, r2, lsr #20-4 @ combine variant and revision mov r12, #0x3 mrc p15, 0, r0, c1, c0, 1 orr r0, r0, #0x10 @ Enable ASA - orr r0, r0, #1 << 5 @ Enable L1NEON + @ Enable L1NEON on pre-r2p1 (erratum 621766 workaround) + cmp r1, #0x21 + orrlt r0, r0, #1 << 5 .word 0xE1600070 @ SMC mov r12, #0x2 mrc p15, 1, r0, c9, c0, 2 - @ Set PLD_FWD bit in L2AUXCR (Cortex-A8 erratum 725233 workaround) - orr r0, r0, #1 << 27 + @ Set PLD_FWD bit in L2AUXCR on pre-r2p1 (erratum 725233 workaround) + cmp r1, #0x21 + orrlt r0, r0, #1 << 27 .word 0xE1600070 @ SMC bx lr -- cgit v1.2.3 From 543431b66dd9f3526f23546cac962c29ad0f485a Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Wed, 25 Aug 2010 13:22:44 -0700 Subject: ARMV7: OMAP3: Fix broken reset command on OMAP36XX/37XX and OMAP4 Using the reset command on OMAP36XX/37XX and OMAP4 caused a hang. This patch uses the reset bit appropriate for each CPU architecture. Signed-off-by: Steve Sakoman Signed-off-by: Sandeep Paulraj --- arch/arm/cpu/armv7/omap-common/reset.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap-common/reset.S b/arch/arm/cpu/armv7/omap-common/reset.S index a53c408195..838b1221ee 100644 --- a/arch/arm/cpu/armv7/omap-common/reset.S +++ b/arch/arm/cpu/armv7/omap-common/reset.S @@ -27,10 +27,12 @@ reset_cpu: ldr r1, rstctl @ get addr for global reset @ reg - mov r3, #0x2 @ full reset pll + mpu + ldr r3, rstbit @ sw reset bit str r3, [r1] @ force reset mov r0, r0 _loop_forever: b _loop_forever rstctl: .word PRM_RSTCTRL +rstbit: + .word PRM_RSTCTRL_RESET -- cgit v1.2.3 From 3667cbeed5e3c4067e624e52a916b1ebb02c8f05 Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Thu, 19 Aug 2010 20:09:57 -0700 Subject: ARMV7: OMAP3: Remove erroneous hard coded sdram setup for 128MB/bank Upcoming Beagle and Overo revisions use POP memory with 256MB or 512MB per bank. This patches uses the SDRC settings from x-load or the config header to set up timing properly. Signed-off-by: Steve Sakoman Signed-off-by: Sandeep Paulraj --- arch/arm/cpu/armv7/omap3/sdrc.c | 43 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap3/sdrc.c b/arch/arm/cpu/armv7/omap3/sdrc.c index 96fd990c71..8905224439 100644 --- a/arch/arm/cpu/armv7/omap3/sdrc.c +++ b/arch/arm/cpu/armv7/omap3/sdrc.c @@ -107,18 +107,12 @@ u32 get_sdr_cs_offset(u32 cs) /* * 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; + struct sdrc_actim *sdrc_actim_base0, *sdrc_actim_base1; if (early) { /* reset sdrc controller */ @@ -138,24 +132,29 @@ void do_sdrc_init(u32 cs, u32 early) 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 + * SDRC timings are set up by x-load or config header + * We don't need to redo them here. + * Older x-loads configure only CS0 + * configure CS1 to handle this ommission */ - writel(CASL3 | BURSTLENGTH4, &sdrc_base->cs[cs].mr); + if (cs) { + sdrc_actim_base0 = (struct sdrc_actim *)SDRC_ACTIM_CTRL0_BASE; + sdrc_actim_base1 = (struct sdrc_actim *)SDRC_ACTIM_CTRL1_BASE; + writel(readl(&sdrc_base->cs[CS0].mcfg), + &sdrc_base->cs[CS1].mcfg); + writel(readl(&sdrc_base->cs[CS0].rfr_ctrl), + &sdrc_base->cs[CS1].rfr_ctrl); + writel(readl(&sdrc_actim_base0->ctrla), + &sdrc_actim_base1->ctrla); + writel(readl(&sdrc_actim_base0->ctrlb), + &sdrc_actim_base1->ctrlb); + } + /* + * Test ram in this bank + * Disable if bad or not present + */ if (!mem_ok(cs)) writel(0, &sdrc_base->cs[cs].mcfg); } -- cgit v1.2.3