[U-Boot] [PATCH 0/7] Add support to MINI2416 board

Support for the MINI2416 board based on a Samsung's S3C2416 SoC with 64MB DDR2 SDRAM, 256MB NAND Flash, a LAN9220 Ethernet Controller and a WM8731 Audio CODEC.
José Miguel Gonçalves (7): ARM: fix relocation on ARM926EJS S3C24XX: Add core support for Samsung's S3C24XX SoCs S3C24XX: Add serial driver S3C24XX: Add RTC driver S3C24XX: Add NAND Flash driver Add u-boot-ubl.bin target to the Makefile S3C24XX: Add support to MINI2416 board
MAINTAINERS | 4 + Makefile | 7 +- arch/arm/cpu/arm926ejs/s3c24xx/Makefile | 52 +++ arch/arm/cpu/arm926ejs/s3c24xx/cpu.c | 56 +++ arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c | 56 +++ arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c | 114 +++++ arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c | 113 +++++ arch/arm/cpu/arm926ejs/s3c24xx/timer.c | 159 +++++++ arch/arm/cpu/arm926ejs/start.S | 4 +- arch/arm/include/asm/arch-s3c24xx/s3c2412.h | 120 ++++++ arch/arm/include/asm/arch-s3c24xx/s3c2416.h | 149 +++++++ arch/arm/include/asm/arch-s3c24xx/s3c24xx.h | 503 +++++++++++++++++++++++ arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h | 30 ++ board/boardcon/mini2416/Makefile | 47 +++ board/boardcon/mini2416/config.mk | 4 + board/boardcon/mini2416/mini2416.c | 100 +++++ board/boardcon/mini2416/mini2416_spl.c | 213 ++++++++++ board/boardcon/mini2416/u-boot-spl.lds | 63 +++ boards.cfg | 1 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/s3c24xx_nand.c | 269 ++++++++++++ drivers/rtc/Makefile | 1 + drivers/rtc/s3c24xx_rtc.c | 166 ++++++++ drivers/serial/Makefile | 1 + drivers/serial/s3c24xx_serial.c | 146 +++++++ include/common.h | 1 + include/configs/mini2416.h | 200 +++++++++ 27 files changed, 2576 insertions(+), 4 deletions(-) create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/Makefile create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/cpu.c create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/timer.c create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c2412.h create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c2416.h create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c24xx.h create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h create mode 100644 board/boardcon/mini2416/Makefile create mode 100644 board/boardcon/mini2416/config.mk create mode 100644 board/boardcon/mini2416/mini2416.c create mode 100644 board/boardcon/mini2416/mini2416_spl.c create mode 100644 board/boardcon/mini2416/u-boot-spl.lds create mode 100644 drivers/mtd/nand/s3c24xx_nand.c create mode 100644 drivers/rtc/s3c24xx_rtc.c create mode 100644 drivers/serial/s3c24xx_serial.c create mode 100644 include/configs/mini2416.h

Jumping to board_init_r is not performed due to a bug on address computation. Relocation offsets are not needed when building SPL.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt --- arch/arm/cpu/arm926ejs/start.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/arm926ejs/start.S b/arch/arm/cpu/arm926ejs/start.S index 6f05f1a..2da5342 100644 --- a/arch/arm/cpu/arm926ejs/start.S +++ b/arch/arm/cpu/arm926ejs/start.S @@ -325,7 +325,7 @@ _nand_boot_ofs: .word nand_boot #else ldr r0, _board_init_r_ofs - ldr r1, _TEXT_BASE + adr r1, _start add lr, r0, r1 add lr, lr, r9 /* setup parameters for board_init_r */ @@ -338,12 +338,14 @@ _board_init_r_ofs: .word board_init_r - _start #endif
+#ifndef CONFIG_SPL_BUILD _rel_dyn_start_ofs: .word __rel_dyn_start - _start _rel_dyn_end_ofs: .word __rel_dyn_end - _start _dynsym_start_ofs: .word __dynsym_start - _start +#endif
/* *************************************************************************

This patch adds the support for Samsung's S3C24XX SoCs that have an ARM926EJS core. Currently it supports S3C2412, S3C2413, S3C2416 and S3C2450. Tested on an S3C2416 platform.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt --- arch/arm/cpu/arm926ejs/s3c24xx/Makefile | 52 +++ arch/arm/cpu/arm926ejs/s3c24xx/cpu.c | 56 +++ arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c | 56 +++ arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c | 114 +++++ arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c | 113 +++++ arch/arm/cpu/arm926ejs/s3c24xx/timer.c | 159 +++++++ arch/arm/include/asm/arch-s3c24xx/s3c2412.h | 120 ++++++ arch/arm/include/asm/arch-s3c24xx/s3c2416.h | 149 +++++++ arch/arm/include/asm/arch-s3c24xx/s3c24xx.h | 503 +++++++++++++++++++++++ arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h | 30 ++ include/common.h | 1 + 11 files changed, 1353 insertions(+) create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/Makefile create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/cpu.c create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/timer.c create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c2412.h create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c2416.h create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c24xx.h create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h
diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/Makefile b/arch/arm/cpu/arm926ejs/s3c24xx/Makefile new file mode 100644 index 0000000..62b8378 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/s3c24xx/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2012 INOV - INESC Inovacao +# Jose Goncalves jose.goncalves@inov.pt +# +# 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).o + +COBJS-$(CONFIG_DISPLAY_CPUINFO) += cpu_info.o +ifeq ($(filter y,$(CONFIG_S3C2412) $(CONFIG_S3C2413)),y) +COBJS-y += s3c2412_speed.o +else +COBJS-y += s3c2416_speed.o +endif +COBJS-y += cpu.o +COBJS-y += timer.o + +SRCS := $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/cpu.c b/arch/arm/cpu/arm926ejs/s3c24xx/cpu.c new file mode 100644 index 0000000..326748c --- /dev/null +++ b/arch/arm/cpu/arm926ejs/s3c24xx/cpu.c @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/s3c24xx_cpu.h> + +void enable_caches(void) +{ +#ifndef CONFIG_SYS_ICACHE_OFF + icache_enable(); +#endif +#ifndef CONFIG_SYS_DCACHE_OFF + dcache_enable(); +#endif +} + +/* + * Reset the cpu by setting up the watchdog timer and let him time out. + */ +void reset_cpu(ulong addr) +{ + s3c24xx_watchdog *const watchdog = s3c24xx_get_base_watchdog(); + + /* Disable watchdog */ + writel(0x0000, &watchdog->wtcon); + + /* Initialize watchdog timer count register */ + writel(0x0001, &watchdog->wtcnt); + + /* Enable watchdog timer; assert reset at timer timeout */ + writel(0x0021, &watchdog->wtcon); + + while (1) + /* loop forever and wait for reset to happen */ ; +} diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c b/arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c new file mode 100644 index 0000000..37dbff4 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2010 + * David Mueller d.mueller@elsoft.ch + * + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/s3c24xx_cpu.h> + +typedef ulong(*getfreq) (void); + +static const getfreq freq_f[] = { + get_FCLK, + get_HCLK, + get_PCLK, +}; + +static const char freq_c[] = { 'F', 'H', 'P' }; + +int print_cpuinfo(void) +{ + int i; + char buf[32]; + ulong cpuid; + s3c24xx_gpio *const gpio = s3c24xx_get_base_gpio(); + + cpuid = readl(&gpio->gstatus[1]); + printf("CPU: %8s (id %08lX) @ %s MHz\n", s3c24xx_get_cpu_name(), + cpuid, strmhz(buf, get_ARMCLK())); + for (i = 0; i < ARRAY_SIZE(freq_f); i++) + printf("%cCLK: %8s MHz\n", freq_c[i], + strmhz(buf, freq_f[i] ())); + + return 0; +} diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c b/arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c new file mode 100644 index 0000000..2b9c905 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c @@ -0,0 +1,114 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * Based on U-Boot 1.3.4 from Samsung. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/s3c2412.h> + +#define MPLL 0 +#define UPLL 1 + +/* ------------------------------------------------------------------------- */ +/* + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ +/* ------------------------------------------------------------------------- */ + +static ulong get_PLLCLK(int pllreg) +{ + s3c2412_sysctl *const sysctl = s3c2412_get_base_sysctl(); + u32 pllcon, f; + u16 mdiv, pdiv, sdiv; + + if (pllreg == MPLL) + pllcon = readl(&sysctl->mpllcon); + else if (pllreg == UPLL) + pllcon = readl(&sysctl->upllcon); + else + hang(); + + mdiv = (pllcon >> 12) & 0xFF; + pdiv = (pllcon >> 4) & 0x3F; + sdiv = pllcon & 0x3; + + f = (mdiv + 8) * (CONFIG_SYS_CLK_FREQ / ((pdiv + 2) << sdiv)); + if (pllreg == MPLL) + f <<= 1; + + return f; +} + +/* return FCLK frequency */ +ulong get_FCLK(void) +{ + return get_PLLCLK(MPLL); +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + s3c2412_sysctl *const sysctl = s3c2412_get_base_sysctl(); + u32 clkdivn; + u16 hclk_div, arm_div; + + clkdivn = readl(&sysctl->clkdivn); + hclk_div = (clkdivn & 0x3) + 1; + arm_div = ((clkdivn >> 3) & 0x1) + 1; + + return get_FCLK() / (hclk_div * arm_div); +} + +/* return PCLK frequency */ +ulong get_PCLK(void) +{ + s3c2412_sysctl *const sysctl = s3c2412_get_base_sysctl(); + u32 clkdivn; + + clkdivn = readl(&sysctl->clkdivn); + + return (clkdivn & 0x4) ? get_HCLK() / 2 : get_HCLK(); +} + +/* return UCLK frequency */ +ulong get_UCLK(void) +{ + return get_PLLCLK(UPLL); +} + +/* return ARMCORE frequency */ +ulong get_ARMCLK(void) +{ + s3c2412_sysctl *const sysctl = s3c2412_get_base_sysctl(); + u32 clkdivn; + + clkdivn = readl(&sysctl->clkdivn); + if (clkdivn & 0x10) + return get_FCLK(); + + return (clkdivn & 0x8) ? get_FCLK() / 2 : get_FCLK(); +} diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c b/arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c new file mode 100644 index 0000000..40463e2 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c @@ -0,0 +1,113 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * Based on U-Boot 1.3.4 from Samsung. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/s3c2416.h> + +#define MPLL 0 +#define EPLL 1 + +/* ------------------------------------------------------------------------- */ +/* + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ +/* ------------------------------------------------------------------------- */ + +static ulong get_PLLCLK(int pllreg) +{ + s3c2416_sysctl *const sysctl = s3c2416_get_base_sysctl(); + u32 pllcon; + u16 mdiv, pdiv, sdiv; + + if (pllreg == MPLL) + pllcon = readl(&sysctl->mpllcon); + else if (pllreg == EPLL) + pllcon = readl(&sysctl->epllcon); + else + hang(); + + mdiv = (pllcon >> 14) & 0x3FF; + pdiv = (pllcon >> 5) & 0x3F; + sdiv = pllcon & 0x7; + + return mdiv * (CONFIG_SYS_CLK_FREQ / (pdiv << sdiv)); +} + +/* return FCLK frequency */ +ulong get_FCLK(void) +{ + return get_PLLCLK(MPLL); +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + s3c2416_sysctl *const sysctl = s3c2416_get_base_sysctl(); + u32 clkdiv0; + u16 hclk_div, pre_div; + + clkdiv0 = readl(&sysctl->clkdiv0); + hclk_div = (clkdiv0 & 0x3) + 1; + pre_div = ((clkdiv0 >> 4) & 0x3) + 1; + + return get_FCLK() / (hclk_div * pre_div); +} + +/* return PCLK frequency */ +ulong get_PCLK(void) +{ + s3c2416_sysctl *const sysctl = s3c2416_get_base_sysctl(); + u32 clkdiv0; + + clkdiv0 = readl(&sysctl->clkdiv0); + + return (clkdiv0 & 0x4) ? get_HCLK() / 2 : get_HCLK(); +} + +/* return UCLK frequency */ +ulong get_UCLK(void) +{ + return get_PLLCLK(EPLL); +} + +/* return ARMCORE frequency */ +ulong get_ARMCLK(void) +{ + s3c2416_sysctl *const sysctl = s3c2416_get_base_sysctl(); + u32 clkdiv0; + u16 arm_div; + + clkdiv0 = readl(&sysctl->clkdiv0); + if (clkdiv0 & 0x2000) + return get_FCLK(); + + arm_div = ((clkdiv0 >> 9) & 0x7) + 1; + + return get_FCLK() / arm_div; +} diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/timer.c b/arch/arm/cpu/arm926ejs/s3c24xx/timer.c new file mode 100644 index 0000000..1ffe169 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/s3c24xx/timer.c @@ -0,0 +1,159 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * Based on arch/arm/cpu/armv7/s5p-common/timer.c and U-Boot 1.3.4 from Samsung. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/s3c24xx_cpu.h> + +DECLARE_GLOBAL_DATA_PTR; + +static ulong get_current_tick(void) +{ + s3c24xx_timers *const timers = s3c24xx_get_base_timers(); + ulong now = readl(&timers->tcnto4); + + if (gd->lastinc >= now) + gd->tbl += gd->lastinc - now; + else + gd->tbl += gd->lastinc + gd->tbu - now; + + gd->lastinc = now; + + return gd->tbl; +} + +int timer_init(void) +{ + s3c24xx_timers *const timers = s3c24xx_get_base_timers(); + ulong tmr; + + /* use PWM Timer 4 because it has no output */ + if (gd->tbu == 0) { + /* set divider value for Timer 4 to 2 */ + tmr = readl(&timers->tcfg1); + tmr &= ~(0xf << 16); + writel(tmr, &timers->tcfg1); + /* set prescaler value for Timer 4 to 15 */ + tmr = readl(&timers->tcfg0); + tmr &= ~(0xff << 8); + tmr |= (15 << 8); + writel(tmr, &timers->tcfg0); + /* + * Timer Freq(HZ) = + * PCLK / (prescaler_value + 1) / (divider_value) + */ + gd->timer_rate_hz = get_PCLK() / (15 + 1) / 2; + gd->tbu = gd->timer_rate_hz / CONFIG_SYS_HZ; + } + /* load value for selected timeout */ + writel(gd->tbu, &timers->tcntb4); + /* auto load, manual update of timer 4 */ + tmr = readl(&timers->tcon); + tmr &= ~(0x7 << 20); + tmr |= (0x6 << 20); + writel(tmr, &timers->tcon); + /* auto load, start timer 4 */ + tmr &= ~(0x7 << 20); + tmr |= (0x5 << 20); + writel(tmr, &timers->tcon); + gd->lastinc = 0; + gd->tbl = 0; + + return 0; +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void __udelay(unsigned long usec) +{ + ulong 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 *= gd->timer_rate_hz; + tmo /= 1000; + } else { + /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * gd->timer_rate_hz; + tmo /= (1000 * 1000); + } + + /* get current timestamp */ + tmp = get_current_tick(); + + /* if setting this fordward will roll time stamp */ + /* reset "advancing" timestamp to 0, set lastinc value */ + /* else, set advancing stamp wake up time */ + if ((tmo + tmp + 1) < tmp) + reset_timer_masked(); + else + tmo += tmp; + + /* loop till event */ + while (get_current_tick() < tmo) + /* NOP */ ; +} + +void reset_timer_masked(void) +{ + s3c24xx_timers *const timers = s3c24xx_get_base_timers(); + + /* reset time */ + gd->lastinc = readl(&timers->tcnto4); + gd->tbl = 0; +} + +ulong get_timer_masked(void) +{ + return get_current_tick() / gd->tbu; +} + +/* + * 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_masked(); +} + +/* + * 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) +{ + return CONFIG_SYS_HZ; +} diff --git a/arch/arm/include/asm/arch-s3c24xx/s3c2412.h b/arch/arm/include/asm/arch-s3c24xx/s3c2412.h new file mode 100644 index 0000000..772e814 --- /dev/null +++ b/arch/arm/include/asm/arch-s3c24xx/s3c2412.h @@ -0,0 +1,120 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * 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 + */ + +/************************************************ + * NAME : s3c2412.h + * + * Based on S3C2412 User's manual Rev 1.06a + ************************************************/ + +#ifndef __S3C2412_H__ +#define __S3C2412_H__ + +/* Base addresses for S3C2412 specific modules */ +#define S3C2412_INTERRUPT_BASE 0x4A000000 +#define S3C2412_SYSCTL_BASE 0x4C000000 +#define S3C2412_LCD_BASE 0x4D000000 +#define S3C2412_USB_DEVICE_BASE 0x52000000 +#define S3C2412_ADC_BASE 0x58000000 +#define S3C2412_SPI_BASE 0x59000000 +#define S3C2412_SDIO_BASE 0x5A000000 + +#define S3C24XX_UART_CHANNELS 3 +#define S3C24XX_DMA_CHANNELS 4 +#define S3C24XX_SMC_BANKS 8 + +#ifdef CONFIG_S3C2412 +#define S3C24XX_CPU_NAME "S3C2412" +#else +#define S3C24XX_CPU_NAME "S3C2413" +#endif + +enum s3c24xx_uarts_nr { + S3C24XX_UART0, + S3C24XX_UART1, + S3C24XX_UART2 +}; + +enum s3c24xx_dmas_nr { + S3C24XX_DMA0, + S3C24XX_DMA1, + S3C24XX_DMA2, + S3C24XX_DMA3 +}; + +enum s3c24xx_smcs_nr { + S3C24XX_SMC0, + S3C24XX_SMC1, + S3C24XX_SMC2, + S3C24XX_SMC3, + S3C24XX_SMC4, + S3C24XX_SMC5, + S3C24XX_SMC6, + S3C24XX_SMC7 +}; + +/* Interrupt Controller */ +typedef struct { + u32 srcpnd; + u32 intmod; + u32 intmsk; + u32 priority; + u32 intpnd; + u32 intoffset; + u32 subsrcpnd; + u32 intsubmsk; +} volatile s3c2412_interrupt; + +/* System Controller */ +typedef struct { + u32 locktime; + u32 mpllcon; + u32 upllcon; + u32 clkcon; + u32 _res1[1]; + u32 clkdivn; + u32 oscset; + u32 clksrc; + u32 _res2[1]; + u32 pwrcfg; + u32 _res3[2]; + u32 swrstcon; + u32 rstcon; + u32 _res4[13]; + u32 inform[4]; +} volatile s3c2412_sysctl; + +static inline s3c2412_interrupt *s3c2412_get_base_interrupt(void) +{ + return (s3c2412_interrupt *) S3C2412_INTERRUPT_BASE; +} + +static inline s3c2412_sysctl *s3c2412_get_base_sysctl(void) +{ + return (s3c2412_sysctl *) S3C2412_SYSCTL_BASE; +} + +/* Include common stuff */ +#include <asm/arch/s3c24xx.h> + +#endif /*__S3C2412_H__*/ diff --git a/arch/arm/include/asm/arch-s3c24xx/s3c2416.h b/arch/arm/include/asm/arch-s3c24xx/s3c2416.h new file mode 100644 index 0000000..42f4ad6 --- /dev/null +++ b/arch/arm/include/asm/arch-s3c24xx/s3c2416.h @@ -0,0 +1,149 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * 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 + */ + +/************************************************ + * NAME : s3c2416.h + * + * Based on S3C2416 User's manual Rev 1.40 + ************************************************/ + +#ifndef __S3C2416_H__ +#define __S3C2416_H__ + +/* Base addresses for S3C2416 specific modules */ +#define S3C2416_USB_DEVICE_BASE 0x49800000 +#define S3C2416_INTERRUPT_BASE 0x4A000000 +#define S3C2416_HSMMC_BASE 0x4A800000 +#define S3C2416_SYSCTL_BASE 0x4C000000 +#define S3C2416_LCD_BASE 0x4C800000 +#define S3C2416_HSSPI_BASE 0x52000000 +#define S3C2416_ADC_BASE 0x58000000 + +#define S3C24XX_UART_CHANNELS 4 +#define S3C24XX_DMA_CHANNELS 6 +#define S3C24XX_SMC_BANKS 6 + +#ifdef CONFIG_S3C2416 +#define S3C24XX_CPU_NAME "S3C2416" +#else +#define S3C24XX_CPU_NAME "S3C2450" +#endif + +enum s3c24xx_uarts_nr { + S3C24XX_UART0, + S3C24XX_UART1, + S3C24XX_UART2, + S3C24XX_UART3 +}; + +enum s3c24xx_dmas_nr { + S3C24XX_DMA0, + S3C24XX_DMA1, + S3C24XX_DMA2, + S3C24XX_DMA3, + S3C24XX_DMA4, + S3C24XX_DMA5 +}; + +enum s3c24xx_smcs_nr { + S3C24XX_SMC0, + S3C24XX_SMC1, + S3C24XX_SMC2, + S3C24XX_SMC3, + S3C24XX_SMC4, + S3C24XX_SMC5 +}; + +/* Interrupt Controller */ +typedef struct { + u32 srcpnd1; + u32 intmod1; + u32 intmsk1; + u32 _res1[1]; + u32 intpnd1; + u32 intoffset1; + u32 subsrcpnd; + u32 intsubmsk; + u32 _res2[4]; + u32 priority_mode1; + u32 priority_update1; + u32 _res3[2]; + u32 srcpnd2; + u32 intmod2; + u32 intmsk2; + u32 _res4[1]; + u32 intpnd2; + u32 intoffset2; + u32 _res5[6]; + u32 priority_mode2; + u32 priority_update2; +} volatile s3c2416_interrupt; + +/* System Controller */ +typedef struct { + u32 lockcon0; + u32 lockcon1; + u32 oscset; + u32 _res1[1]; + u32 mpllcon; + u32 _res2[1]; + u32 epllcon; + u32 epllcon_k; + u32 clksrc; + u32 clkdiv0; + u32 clkdiv1; + u32 clkdiv2; + u32 hclkcon; + u32 pclkcon; + u32 sclkcon; + u32 _res3[1]; + u32 pwrmode; + u32 swrst; + u32 _res4[2]; + u32 busprio; + u32 _res5[3]; + u32 pwrcfg; + u32 rstcon; + u32 rststat; + u32 wkupstat; + u32 inform[4]; + u32 uphyctrl; + u32 uphypwr; + u32 urstcon; + u32 uclkcon; +} volatile s3c2416_sysctl; + +static inline s3c2416_interrupt *s3c2416_get_base_interrupt(void) +{ + return (s3c2416_interrupt *) S3C2416_INTERRUPT_BASE; +} + +static inline s3c2416_sysctl *s3c2416_get_base_sysctl(void) +{ + return (s3c2416_sysctl *) S3C2416_SYSCTL_BASE; +} + +/* Include common stuff */ +#include <asm/arch/s3c24xx.h> + +#endif /*__S3C2416_H__*/ diff --git a/arch/arm/include/asm/arch-s3c24xx/s3c24xx.h b/arch/arm/include/asm/arch-s3c24xx/s3c24xx.h new file mode 100644 index 0000000..edcdb8a --- /dev/null +++ b/arch/arm/include/asm/arch-s3c24xx/s3c24xx.h @@ -0,0 +1,503 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * 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 + */ + +/****************************************************** + * NAME : s3c24xx.h + * + * Common stuff for SAMSUNG S3C24XX SoC (ARM926EJ core) + ******************************************************/ + +#ifndef __S3C24XX_H__ +#define __S3C24XX_H__ + +/* Base addresses for S3C24XX common modules */ +#define S3C24XX_DRAMCTL_BASE 0x48000000 +#define S3C24XX_USB_HOST_BASE 0x49000000 +#define S3C24XX_DMA_BASE 0x4B000000 +#define S3C24XX_NAND_BASE 0x4E000000 +#define S3C24XX_SMC_BASE 0x4F000000 +#define S3C24XX_UART_BASE 0x50000000 +#define S3C24XX_TIMER_BASE 0x51000000 +#define S3C24XX_WATCHDOG_BASE 0x53000000 +#define S3C24XX_I2C_BASE 0x54000000 +#define S3C24XX_I2S_BASE 0x55000000 +#define S3C24XX_GPIO_BASE 0x56000000 +#define S3C24XX_RTC_BASE 0x57000000 +#define S3C24XX_ADC_BASE 0x58000000 + +/* Mobile DRAM Controller */ +typedef struct { + u32 bankcfg; + u32 bankcon1; + u32 bankcon2; + u32 bankcon3; + u32 refresh; + u32 timeout; +} volatile s3c24xx_dramctl; + +/* USB Host Controller */ +typedef struct { + u32 HcRevision; + u32 HcControl; + u32 HcCommonStatus; + u32 HcInterruptStatus; + u32 HcInterruptEnable; + u32 HcInterruptDisable; + u32 HcHCCA; + u32 HcPeriodCuttendED; + u32 HcControlHeadED; + u32 HcControlCurrentED; + u32 HcBulkHeadED; + u32 HcBuldCurrentED; + u32 HcDoneHead; + u32 HcRmInterval; + u32 HcFmRemaining; + u32 HcFmNumber; + u32 HcPeriodicStart; + u32 HcLSThreshold; + u32 HcRhDescriptorA; + u32 HcRhDescriptorB; + u32 HcRhStatus; + u32 HcRhPortStatus1; + u32 HcRhPortStatus2; +} volatile s3c24xx_usb_host; + +/* DMA Controller */ +typedef struct { + u32 disrc; + u32 disrcc; + u32 didst; + u32 didstc; + u32 dcon; + u32 dstat; + u32 dcsrc; + u32 dcdst; + u32 dmasktrig; + u32 dmareqsel0; +} volatile s3c24xx_dma; + +/* NAND Flash Controller */ +typedef struct { + u32 nfconf; + u32 nfcont; + u32 nfcmmd; + u32 nfaddr; + u32 nfdata; + u32 nfmeccd[2]; + u32 nfseccd; + u32 nfsblk; + u32 nfeblk; + u32 nfstat; + u32 nfeccerr[2]; + u32 nfmecc[2]; + u32 nfsecc; + u32 nfmlcbitpt; +#if !(defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)) + u32 nf8eccerr[3]; + u32 nfm8ecc[4]; + u32 nfmlc8bitpt[2]; +#endif +} volatile s3c24xx_nand; + +/* SMC */ +typedef struct { + u32 smbidcy; + u32 smbwstrd; + u32 smbwstwr; + u32 smbwstoen; + u32 smbwstwen; + u32 smbc; + u32 smbs; + u32 smbwstbrd; +} volatile s3c24xx_smc; + +/* UART */ +typedef struct { + u32 ulcon; + u32 ucon; + u32 ufcon; + u32 umcon; + u32 utrstat; + u32 uerstat; + u32 ufstat; + u32 umstat; +#ifdef __BIG_ENDIAN + u8 _res1[3]; + u8 utxh; + u8 _res2[3]; + u8 urxh; +#else /* Little Endian */ + u8 utxh; + u8 _res1[3]; + u8 urxh; + u8 _res2[3]; +#endif + u32 ubrdiv; + u32 udivslot; +} volatile s3c24xx_uart; + +/* PWM Timer */ +typedef struct { + u32 tcntb; + u32 tcmpb; + u32 tcnto; +} s3c24xx_timer; + +typedef struct { + u32 tcfg0; + u32 tcfg1; + u32 tcon; + s3c24xx_timer ch[4]; + u32 tcntb4; + u32 tcnto4; +} volatile s3c24xx_timers; + +/* Watchdog Timer */ +typedef struct { + u32 wtcon; + u32 wtdat; + u32 wtcnt; +} volatile s3c24xx_watchdog; + +/* IIC-Bus Interface */ +typedef struct { + u32 iiccon; + u32 iicstat; + u32 iicadd; + u32 iicds; + u32 iiclc; +} volatile s3c24xx_i2c; + +/* IIS-Bus Interface */ +typedef struct { + u32 iiscon; + u32 iismod; + u32 iisfic; + u32 iispsr; + u32 iistxd; + u32 iisrxd; +} volatile s3c24xx_i2s; + +/* I/O Ports */ +typedef struct { +#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413) + u32 gpacon; + u32 gpadat; + u32 _res1[2]; + u32 gpbcon; + u32 gpbdat; + u32 gpbdn; + u32 gpbslpcon; + u32 gpccon; + u32 gpcdat; + u32 gpcdn; + u32 gpcslpcon; + u32 gpdcon; + u32 gpddat; + u32 gpddn; + u32 gpdslpcon; + u32 gpecon; + u32 gpedat; + u32 gpedn; + u32 gpeslpcon; + u32 gpfcon; + u32 gpfdat; + u32 gpfdn; + u32 _res2; + u32 gpgcon; + u32 gpgdat; + u32 gpgdn; + u32 gpgslpcon; + u32 gphcon; + u32 gphdat; + u32 gphdn; + u32 gphslpcon; + u32 gpjcon; + u32 gpjdat; + u32 gpjdn; + u32 gpjslpcon; + + u32 misccr; + u32 dclkcon; + u32 extint[3]; + u32 eintflt[4]; + u32 eintmask; + u32 eintpend; + u32 gstatus[6]; + u32 mstcon; + u32 mslcon; + u32 dsc[2]; +#else + u32 gpacon; + u32 gpadat; + u32 _res1[2]; + u32 gpbcon; + u32 gpbdat; + u32 gpbudp; + u32 gpbsel; + u32 gpccon; + u32 gpcdat; + u32 gpcudp; + u32 _res2; + u32 gpdcon; + u32 gpddat; + u32 gpdudp; + u32 _res3; + u32 gpecon; + u32 gpedat; + u32 gpeudp; + u32 gpesel; + u32 gpfcon; + u32 gpfdat; + u32 gpfudp; + u32 _res4; + u32 gpgcon; + u32 gpgdat; + u32 gpgudp; + u32 _res5; + u32 gphcon; + u32 gphdat; + u32 gphudp; + u32 _res6; + + u32 misccr; + u32 dclkcon; + u32 extint[3]; + u32 _res7[2]; + u32 eintflt2; + u32 eintflt3; + u32 eintmask; + u32 eintpend; + u32 gstatus[2]; + u32 _res8[3]; + u32 dsc[4]; + + u32 gpjcon; + u32 gpjdat; + u32 gpjudp; + u32 gpjsel; + u32 gpkcon; + u32 gpkdat; + u32 gpkudp; + u32 _res9; + u32 gplcon; + u32 gpldat; + u32 gpludp; + u32 gplsel; + u32 gpmcon; + u32 gpmdat; + u32 gpmudp; + u32 _res10; + + u32 dsc3; + u32 pddmcon; + u32 pdsmcon; +#endif +} volatile s3c24xx_gpio; + +/* RTC */ +typedef struct { +#ifdef __BIG_ENDIAN + u8 _res1[67]; + u8 rtccon; + u8 _res2[3]; + u8 ticnt0; +#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413) + u8 _res3[4]; +#else + u8 _res3[3]; + u8 ticnt2; +#endif + u8 _res4[3]; + u8 ticnt1; + u8 _res5[3]; + u8 rtcalm; + u8 _res6[3]; + u8 almsec; + u8 _res7[3]; + u8 almmin; + u8 _res8[3]; + u8 almhour; + u8 _res9[3]; + u8 almdate; + u8 _res10[3]; + u8 almmon; + u8 _res11[3]; + u8 almyear; + u8 _res12[7]; + u8 bcdsec; + u8 _res13[3]; + u8 bcdmin; + u8 _res14[3]; + u8 bcdhour; + u8 _res15[3]; + u8 bcddate; + u8 _res16[3]; + u8 bcdday; + u8 _res17[3]; + u8 bcdmon; + u8 _res18[3]; + u8 bcdyear; +#if !(defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)) + u8 _res19[3]; + u8 tickcnt; +#endif +#else /* little endian */ + u8 _res0[64]; + u8 rtccon; + u8 _res1[3]; + u8 ticnt0; + u8 _res2[3]; +#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413) + u8 _res3[4]; +#else + u8 ticnt2; + u8 _res3[3]; +#endif + u8 ticnt1; + u8 _res4[3]; + u8 rtcalm; + u8 _res5[3]; + u8 almsec; + u8 _res6[3]; + u8 almmin; + u8 _res7[3]; + u8 almhour; + u8 _res8[3]; + u8 almdate; + u8 _res9[3]; + u8 almmon; + u8 _res10[3]; + u8 almyear; + u8 _res11[7]; + u8 bcdsec; + u8 _res12[3]; + u8 bcdmin; + u8 _res13[3]; + u8 bcdhour; + u8 _res14[3]; + u8 bcddate; + u8 _res15[3]; + u8 bcdday; + u8 _res16[3]; + u8 bcdmon; + u8 _res17[3]; + u8 bcdyear; + u8 _res18[3]; +#if !(defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)) + u8 tickcnt; + u8 _res19[3]; +#endif +#endif +} volatile s3c24xx_rtc; + +/* ADC & Touch Screen Interface */ +typedef struct { + u32 adccon; + u32 adctsc; + u32 adcdly; + u32 adcdat0; + u32 adcdat1; +#if !(defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)) + u32 adcupdn; + u32 adcmux; +#endif +} volatile s3c24xx_adc; + +static inline s3c24xx_dramctl *s3c24xx_get_base_dramctl(void) +{ + return (s3c24xx_dramctl *) S3C24XX_DRAMCTL_BASE; +} + +static inline s3c24xx_usb_host *s3c24xx_get_base_usb_host(void) +{ + return (s3c24xx_usb_host *) S3C24XX_USB_HOST_BASE; +} + +static inline s3c24xx_dma *s3c24xx_get_base_dma(enum s3c24xx_dmas_nr n) +{ +#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413) + return (s3c24xx_dma *) (S3C24XX_DMA_BASE + (n * 0x40)); +#else + return (s3c24xx_dma *) (S3C24XX_DMA_BASE + (n * 0x100)); +#endif +} + +static inline s3c24xx_nand *s3c24xx_get_base_nand(void) +{ + return (s3c24xx_nand *) S3C24XX_NAND_BASE; +} + +static inline s3c24xx_smc *s3c24xx_get_base_smc(enum s3c24xx_smcs_nr n) +{ + return (s3c24xx_smc *) (S3C24XX_SMC_BASE + (n * 0x20)); +} + +static inline s3c24xx_uart *s3c24xx_get_base_uart(enum s3c24xx_uarts_nr n) +{ + return (s3c24xx_uart *) (S3C24XX_UART_BASE + (n * 0x4000)); +} + +static inline s3c24xx_timers *s3c24xx_get_base_timers(void) +{ + return (s3c24xx_timers *) S3C24XX_TIMER_BASE; +} + +static inline s3c24xx_watchdog *s3c24xx_get_base_watchdog(void) +{ + return (s3c24xx_watchdog *) S3C24XX_WATCHDOG_BASE; +} + +static inline s3c24xx_i2c *s3c24xx_get_base_i2c(void) +{ + return (s3c24xx_i2c *) S3C24XX_I2C_BASE; +} + +static inline s3c24xx_i2s *s3c24xx_get_base_i2s(void) +{ + return (s3c24xx_i2s *) S3C24XX_I2S_BASE; +} + +static inline s3c24xx_gpio *s3c24xx_get_base_gpio(void) +{ + return (s3c24xx_gpio *) S3C24XX_GPIO_BASE; +} + +static inline s3c24xx_rtc *s3c24xx_get_base_rtc(void) +{ + return (s3c24xx_rtc *) S3C24XX_RTC_BASE; +} + +static inline s3c24xx_adc *s3c24xx_get_base_adc(void) +{ + return (s3c24xx_adc *) S3C24XX_ADC_BASE; +} + +static inline char *s3c24xx_get_cpu_name(void) +{ + return S3C24XX_CPU_NAME; +} + +extern ulong get_ARMCLK(void); + +#endif /*__S3C24XX_H__*/ diff --git a/arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h b/arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h new file mode 100644 index 0000000..59ccfd4 --- /dev/null +++ b/arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h @@ -0,0 +1,30 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * 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 + */ + +#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413) +#include <asm/arch/s3c2412.h> +#elif defined(CONFIG_S3C2416) || defined(CONFIG_S3C2450) +#include <asm/arch/s3c2416.h> +#else +#error Please define the S3C24XX SoC type +#endif diff --git a/include/common.h b/include/common.h index 55025c0..36f0636 100644 --- a/include/common.h +++ b/include/common.h @@ -628,6 +628,7 @@ ulong get_OPB_freq (void); ulong get_PCI_freq (void); #endif #if defined(CONFIG_S3C24X0) || \ + defined(CONFIG_S3C24XX) || \ defined(CONFIG_LH7A40X) || \ defined(CONFIG_S3C6400) || \ defined(CONFIG_EP93XX)

Serial driver for the S3C24XX SoCs.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt --- drivers/serial/Makefile | 1 + drivers/serial/s3c24xx_serial.c | 146 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 drivers/serial/s3c24xx_serial.c
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 65d0f23..2cbdaac 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -52,6 +52,7 @@ COBJS-$(CONFIG_PL011_SERIAL) += serial_pl01x.o COBJS-$(CONFIG_PXA_SERIAL) += serial_pxa.o COBJS-$(CONFIG_SA1100_SERIAL) += serial_sa1100.o COBJS-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o +COBJS-$(CONFIG_S3C24XX_SERIAL) += s3c24xx_serial.o COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o diff --git a/drivers/serial/s3c24xx_serial.c b/drivers/serial/s3c24xx_serial.c new file mode 100644 index 0000000..11f13a5 --- /dev/null +++ b/drivers/serial/s3c24xx_serial.c @@ -0,0 +1,146 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * Based on drivers/serial/s3c64xx.c + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/arch/s3c24xx_cpu.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_SERIAL0 +#define UART_NR S3C24XX_UART0 + +#elif defined(CONFIG_SERIAL1) +#define UART_NR S3C24XX_UART1 + +#elif defined(CONFIG_SERIAL2) +#define UART_NR S3C24XX_UART2 + +#elif defined(CONFIG_SERIAL3) +#define UART_NR S3C24XX_UART3 + +#else +#error "Bad: you didn't configure serial ..." +#endif + +#define barrier() asm volatile("" ::: "memory") + +/* + * The coefficient, used to calculate the baudrate on S3C24XX UARTs is + * calculated as C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT + * however, section 2.1.10 of the S3C2416 User's Manual doesn't recommend + * using 1 for 1, 3 for 2, ... (2^n - 1) for n, instead, they suggest using + * these constants: + */ +static const int udivslot[] = { + 0x0000, 0x0080, 0x0808, 0x0888, 0x2222, 0x4924, 0x4A52, 0x54AA, + 0x5555, 0xD555, 0xD5D5, 0xDDD5, 0xDDDD, 0xDFDD, 0xDFDF, 0xFFDF, +}; + +void serial_setbrg(void) +{ + s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR); + u32 pclk; + u32 baudrate; + int i; + + pclk = get_PCLK(); + baudrate = gd->baudrate; + + uart->ubrdiv = (pclk / baudrate / 16) - 1; + uart->udivslot = udivslot[(pclk / baudrate) % 16]; + + for (i = 0; i < 100; i++) + barrier(); +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + */ +int serial_init(void) +{ + s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR); + + /* FIFO enable, Tx/Rx FIFO clear */ + uart->ufcon = 0x07; + uart->umcon = 0x00; + /* Normal mode, No parity, 1 stop bit, 8 data bits */ + uart->ulcon = 0x03; + /* Polling mode */ + uart->ucon = 0x005; + + serial_setbrg(); + + return 0; +} + +/* + * Read a single byte from the serial port. + */ +int serial_getc(void) +{ + s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR); + + /* Wait for character to arrive */ + while (!(uart->utrstat & 0x1)) ; + + return uart->urxh & 0xff; +} + +/* + * Output a single byte to the serial port. + */ +void serial_putc(const char c) +{ + s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR); + + /* Wait for room in the TX FIFO */ + while (!(uart->utrstat & 0x2)) ; + + uart->utxh = c; + + /* If \n, also do \r */ + if (c == '\n') + serial_putc('\r'); +} + +/* + * Test whether a character is in the RX buffer. + */ +int serial_tstc(void) +{ + s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR); + + return uart->utrstat & 0x1; +} + +/* + * Output a string to the serial port. + */ +void serial_puts(const char *s) +{ + while (*s) + serial_putc(*s++); +}

Dear José Miguel Gonçalves,
Serial driver for the S3C24XX SoCs.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt
drivers/serial/Makefile | 1 + drivers/serial/s3c24xx_serial.c | 146 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 drivers/serial/s3c24xx_serial.c
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 65d0f23..2cbdaac 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -52,6 +52,7 @@ COBJS-$(CONFIG_PL011_SERIAL) += serial_pl01x.o COBJS-$(CONFIG_PXA_SERIAL) += serial_pxa.o COBJS-$(CONFIG_SA1100_SERIAL) += serial_sa1100.o COBJS-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o +COBJS-$(CONFIG_S3C24XX_SERIAL) += s3c24xx_serial.o
What's the difference between those two drivers ?!
COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o diff --git a/drivers/serial/s3c24xx_serial.c b/drivers/serial/s3c24xx_serial.c new file mode 100644 index 0000000..11f13a5 --- /dev/null +++ b/drivers/serial/s3c24xx_serial.c @@ -0,0 +1,146 @@ +/*
- (C) Copyright 2012 INOV - INESC Inovacao
- Jose Goncalves jose.goncalves@inov.pt
- Based on drivers/serial/s3c64xx.c
- See file CREDITS for list of people who contributed to this
- project.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- */
+#include <common.h> +#include <asm/arch/s3c24xx_cpu.h>
+DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_SERIAL0 +#define UART_NR S3C24XX_UART0
+#elif defined(CONFIG_SERIAL1) +#define UART_NR S3C24XX_UART1
+#elif defined(CONFIG_SERIAL2) +#define UART_NR S3C24XX_UART2
+#elif defined(CONFIG_SERIAL3) +#define UART_NR S3C24XX_UART3
+#else +#error "Bad: you didn't configure serial ..."
Error itself is "Bad:" so remove it
+#endif
+#define barrier() asm volatile("" ::: "memory")
Is that even used ?
+/*
- The coefficient, used to calculate the baudrate on S3C24XX UARTs is
- calculated as C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT
- however, section 2.1.10 of the S3C2416 User's Manual doesn't recommend
- using 1 for 1, 3 for 2, ... (2^n - 1) for n, instead, they suggest
using + * these constants:
- */
+static const int udivslot[] = {
const int const ... const array const members
- 0x0000, 0x0080, 0x0808, 0x0888, 0x2222, 0x4924, 0x4A52, 0x54AA,
- 0x5555, 0xD555, 0xD5D5, 0xDDD5, 0xDDDD, 0xDFDD, 0xDFDF, 0xFFDF,
+};
+void serial_setbrg(void) +{
- s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR);
- u32 pclk;
- u32 baudrate;
- int i;
- pclk = get_PCLK();
- baudrate = gd->baudrate;
- uart->ubrdiv = (pclk / baudrate / 16) - 1;
- uart->udivslot = udivslot[(pclk / baudrate) % 16];
- for (i = 0; i < 100; i++)
barrier();
+}
+/*
- Initialise the serial port with the given baudrate. The settings
- are always 8 data bits, no parity, 1 stop bit, no start bits.
- */
+int serial_init(void) +{
- s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR);
- /* FIFO enable, Tx/Rx FIFO clear */
- uart->ufcon = 0x07;
- uart->umcon = 0x00;
Magic numbers, fix
- /* Normal mode, No parity, 1 stop bit, 8 data bits */
- uart->ulcon = 0x03;
- /* Polling mode */
- uart->ucon = 0x005;
- serial_setbrg();
- return 0;
+}
+/*
- Read a single byte from the serial port.
- */
+int serial_getc(void) +{
- s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR);
- /* Wait for character to arrive */
- while (!(uart->utrstat & 0x1)) ;
- return uart->urxh & 0xff;
+}
+/*
- Output a single byte to the serial port.
- */
+void serial_putc(const char c) +{
- s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR);
- /* Wait for room in the TX FIFO */
- while (!(uart->utrstat & 0x2)) ;
- uart->utxh = c;
- /* If \n, also do \r */
- if (c == '\n')
serial_putc('\r');
+}
+/*
- Test whether a character is in the RX buffer.
- */
+int serial_tstc(void) +{
- s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR);
- return uart->utrstat & 0x1;
+}
+/*
- Output a string to the serial port.
- */
+void serial_puts(const char *s) +{
- while (*s)
serial_putc(*s++);
+}
Can you implement it as a serial multi (CONFIG_SERIAL_MULTI) right away ? thanks.
Best regards, Marek Vasut

Hi Marek,
On 09/12/2012 10:01 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
Serial driver for the S3C24XX SoCs.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt
drivers/serial/Makefile | 1 + drivers/serial/s3c24xx_serial.c | 146 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 drivers/serial/s3c24xx_serial.c
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 65d0f23..2cbdaac 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -52,6 +52,7 @@ COBJS-$(CONFIG_PL011_SERIAL) += serial_pl01x.o COBJS-$(CONFIG_PXA_SERIAL) += serial_pxa.o COBJS-$(CONFIG_SA1100_SERIAL) += serial_sa1100.o COBJS-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o +COBJS-$(CONFIG_S3C24XX_SERIAL) += s3c24xx_serial.o
What's the difference between those two drivers ?!
No substantial differences exists. The UART controller block is the same in all S3C24XX chips. One difference is the number of UARTs. The more recent chips (S3C2416 & S3C2450) have 4 instead of the 3 found on the old ones. Besides that, the driver that I submitted uses a more precise method for baudrate generation.
+#ifdef CONFIG_SERIAL0 +#define UART_NR S3C24XX_UART0
+#elif defined(CONFIG_SERIAL1) +#define UART_NR S3C24XX_UART1
+#elif defined(CONFIG_SERIAL2) +#define UART_NR S3C24XX_UART2
+#elif defined(CONFIG_SERIAL3) +#define UART_NR S3C24XX_UART3
+#else +#error "Bad: you didn't configure serial ..."
Error itself is "Bad:" so remove it
OK.
+#endif
+#define barrier() asm volatile("" ::: "memory")
Is that even used ?
Yes. Without it the GCC optimization removes the loop at the end of the baurate generation routine.
+/*
- The coefficient, used to calculate the baudrate on S3C24XX UARTs is
- calculated as C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT
- however, section 2.1.10 of the S3C2416 User's Manual doesn't recommend
- using 1 for 1, 3 for 2, ... (2^n - 1) for n, instead, they suggest
using + * these constants:
- */
+static const int udivslot[] = {
const int const ... const array const members
It don't see the need for that because you have a constant array when their members are constant and;
static const int udivslot[]; static int const udivslot[];
are both (correct) forms to declare an array of constant integers.
- 0x0000, 0x0080, 0x0808, 0x0888, 0x2222, 0x4924, 0x4A52, 0x54AA,
- 0x5555, 0xD555, 0xD5D5, 0xDDD5, 0xDDDD, 0xDFDD, 0xDFDF, 0xFFDF,
+};
+void serial_setbrg(void) +{
- s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR);
- u32 pclk;
- u32 baudrate;
- int i;
- pclk = get_PCLK();
- baudrate = gd->baudrate;
- uart->ubrdiv = (pclk / baudrate / 16) - 1;
- uart->udivslot = udivslot[(pclk / baudrate) % 16];
- for (i = 0; i < 100; i++)
barrier();
+}
+/*
- Initialise the serial port with the given baudrate. The settings
- are always 8 data bits, no parity, 1 stop bit, no start bits.
- */
+int serial_init(void) +{
- s3c24xx_uart *const uart = s3c24xx_get_base_uart(UART_NR);
- /* FIFO enable, Tx/Rx FIFO clear */
- uart->ufcon = 0x07;
- uart->umcon = 0x00;
Magic numbers, fix
OK.
Can you implement it as a serial multi (CONFIG_SERIAL_MULTI) right away ? thanks.
I will look at that option and change the driver to support it.
Best regards, José Gonçalves

Dear José Miguel Gonçalves,
Hi Marek,
On 09/12/2012 10:01 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
Serial driver for the S3C24XX SoCs.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt
drivers/serial/Makefile | 1 + drivers/serial/s3c24xx_serial.c | 146
+++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+)
create mode 100644 drivers/serial/s3c24xx_serial.c
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 65d0f23..2cbdaac 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -52,6 +52,7 @@ COBJS-$(CONFIG_PL011_SERIAL) += serial_pl01x.o
COBJS-$(CONFIG_PXA_SERIAL) += serial_pxa.o COBJS-$(CONFIG_SA1100_SERIAL) += serial_sa1100.o COBJS-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o
+COBJS-$(CONFIG_S3C24XX_SERIAL) += s3c24xx_serial.o
What's the difference between those two drivers ?!
No substantial differences exists. The UART controller block is the same in all S3C24XX chips. One difference is the number of UARTs. The more recent chips (S3C2416 & S3C2450) have 4 instead of the 3 found on the old ones. Besides that, the driver that I submitted uses a more precise method for baudrate generation.
So we will have two drivers for the same hardware? No way ... Use the original one and apply incremental patches onto it to improve it.
+#ifdef CONFIG_SERIAL0 +#define UART_NR S3C24XX_UART0
+#elif defined(CONFIG_SERIAL1) +#define UART_NR S3C24XX_UART1
+#elif defined(CONFIG_SERIAL2) +#define UART_NR S3C24XX_UART2
+#elif defined(CONFIG_SERIAL3) +#define UART_NR S3C24XX_UART3
+#else +#error "Bad: you didn't configure serial ..."
Error itself is "Bad:" so remove it
OK.
+#endif
+#define barrier() asm volatile("" ::: "memory")
Is that even used ?
Yes. Without it the GCC optimization removes the loop at the end of the baurate generation routine.
So it's yet another accessor issue. [...]
But anyway, there's more. I'd like to teach you how to do things properly. So let's focus on the in-tree driver and fix that one. Incrementally and in small steps. Best regards, Marek Vasut

Hi Marek,
On 09/13/2012 10:17 AM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
Hi Marek,
On 09/12/2012 10:01 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
Serial driver for the S3C24XX SoCs.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt
drivers/serial/Makefile | 1 + drivers/serial/s3c24xx_serial.c | 146
+++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+)
create mode 100644 drivers/serial/s3c24xx_serial.c
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 65d0f23..2cbdaac 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -52,6 +52,7 @@ COBJS-$(CONFIG_PL011_SERIAL) += serial_pl01x.o
COBJS-$(CONFIG_PXA_SERIAL) += serial_pxa.o COBJS-$(CONFIG_SA1100_SERIAL) += serial_sa1100.o COBJS-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o
+COBJS-$(CONFIG_S3C24XX_SERIAL) += s3c24xx_serial.o
What's the difference between those two drivers ?!
No substantial differences exists. The UART controller block is the same in all S3C24XX chips. One difference is the number of UARTs. The more recent chips (S3C2416 & S3C2450) have 4 instead of the 3 found on the old ones. Besides that, the driver that I submitted uses a more precise method for baudrate generation.
So we will have two drivers for the same hardware? No way ... Use the original one and apply incremental patches onto it to improve it.
+#ifdef CONFIG_SERIAL0 +#define UART_NR S3C24XX_UART0
+#elif defined(CONFIG_SERIAL1) +#define UART_NR S3C24XX_UART1
+#elif defined(CONFIG_SERIAL2) +#define UART_NR S3C24XX_UART2
+#elif defined(CONFIG_SERIAL3) +#define UART_NR S3C24XX_UART3
+#else +#error "Bad: you didn't configure serial ..."
Error itself is "Bad:" so remove it
OK.
+#endif
+#define barrier() asm volatile("" ::: "memory")
Is that even used ?
Yes. Without it the GCC optimization removes the loop at the end of the baurate generation routine.
So it's yet another accessor issue. [...]
But anyway, there's more. I'd like to teach you how to do things properly. So let's focus on the in-tree driver and fix that one. Incrementally and in small steps.
OK, I will figure out the best way to do this. If I have any doubts I'll be back to you...
Best regards, José Gonçalves

RTC driver for the S3C24XX SoCs.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt --- drivers/rtc/Makefile | 1 + drivers/rtc/s3c24xx_rtc.c | 166 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 drivers/rtc/s3c24xx_rtc.c
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 8316e8f..bd8b1eb 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_RTC_RTC4543) += rtc4543.o COBJS-$(CONFIG_RTC_RV3029) += rv3029.o COBJS-$(CONFIG_RTC_RX8025) += rx8025.o COBJS-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o +COBJS-$(CONFIG_RTC_S3C24XX) += s3c24xx_rtc.o COBJS-$(CONFIG_RTC_S3C44B0) += s3c44b0_rtc.o COBJS-$(CONFIG_RTC_X1205) += x1205.o
diff --git a/drivers/rtc/s3c24xx_rtc.c b/drivers/rtc/s3c24xx_rtc.c new file mode 100644 index 0000000..3844e44 --- /dev/null +++ b/drivers/rtc/s3c24xx_rtc.c @@ -0,0 +1,166 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * Based on drivers/rtc/s3c24x0_rtc.c + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#if defined(CONFIG_CMD_DATE) + +#include <rtc.h> +#include <asm/io.h> +#include <asm/arch/s3c24xx_cpu.h> + +static inline void rtc_access_enable(void) +{ + s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc(); + uchar rtccon; + + rtccon = readb(&rtc->rtccon); + rtccon |= 0x01; + writeb(rtccon, &rtc->rtccon); +} + +static inline void rtc_access_disable(void) +{ + s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc(); + uchar rtccon; + + rtccon = readb(&rtc->rtccon); + rtccon &= ~0x01; + writeb(rtccon, &rtc->rtccon); +} + +/* ------------------------------------------------------------------------- */ + +int rtc_get(struct rtc_time *tmp) +{ + s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc(); + uchar sec, min, hour, mday, wday, mon, year; + int have_retried = 0; + + rtc_access_enable(); + + /* Read RTC registers */ +retry_get_time: + min = readb(&rtc->bcdmin); + hour = readb(&rtc->bcdhour); + mday = readb(&rtc->bcddate); + wday = readb(&rtc->bcdday); + mon = readb(&rtc->bcdmon); + year = readb(&rtc->bcdyear); + sec = readb(&rtc->bcdsec); + + /* The only way to work out whether the RTC was mid-update + * when we read it is to check the seconds counter. + * If it's zero, then we re-try the entire read. + */ + if (rtc->bcdsec == 0 && !have_retried) { + have_retried = 1; + goto retry_get_time; + } + + rtc_access_disable(); + + debug("Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x " + "hr: %02x min: %02x sec: %02x\n", + year, mon, mday, wday, hour, min, sec); + + tmp->tm_sec = bcd2bin(sec & 0x7F); + tmp->tm_min = bcd2bin(min & 0x7F); + tmp->tm_hour = bcd2bin(hour & 0x3F); + tmp->tm_mday = bcd2bin(mday & 0x3F); + tmp->tm_wday = bcd2bin(wday & 0x07); + tmp->tm_mon = bcd2bin(mon & 0x1F); + tmp->tm_year = bcd2bin(year); + if (tmp->tm_year < 70) + tmp->tm_year += 2000; + else + tmp->tm_year += 1900; + tmp->tm_yday = 0; + tmp->tm_isdst = 0; + + debug("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + return 0; +} + +int rtc_set(struct rtc_time *tmp) +{ + s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc(); + uchar sec, min, hour, mday, wday, mon, year; + + debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + if (tmp->tm_year < 1970 || tmp->tm_year > 2069) { + puts("ERROR: year should be between 1970 and 2069!\n"); + return -1; + } + + year = bin2bcd(tmp->tm_year % 100); + mon = bin2bcd(tmp->tm_mon); + wday = bin2bcd(tmp->tm_wday); + mday = bin2bcd(tmp->tm_mday); + hour = bin2bcd(tmp->tm_hour); + min = bin2bcd(tmp->tm_min); + sec = bin2bcd(tmp->tm_sec); + + debug("Set RTC year: %02x mon/cent: %02x mday: %02x wday: %02x " + "hr: %02x min: %02x sec: %02x\n", + year, mon, mday, wday, hour, min, sec); + + rtc_access_enable(); + + /* Write RTC registers */ + writeb(sec, &rtc->bcdsec); + writeb(min, &rtc->bcdmin); + writeb(hour, &rtc->bcdhour); + writeb(mday, &rtc->bcddate); + writeb(wday, &rtc->bcdday); + writeb(mon, &rtc->bcdmon); + writeb(year, &rtc->bcdyear); + + rtc_access_disable(); + + return 0; +} + +void rtc_reset(void) +{ + s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc(); + uchar rtccon; + + rtccon = readb(&rtc->rtccon); + rtccon &= ~0x06; + rtccon |= 0x08; + writeb(rtccon, &rtc->rtccon); + rtccon = readb(&rtc->rtccon); + rtccon &= ~0x08; + writeb(rtccon, &rtc->rtccon); +} + +#endif

Dear José Miguel Gonçalves,
RTC driver for the S3C24XX SoCs.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt
drivers/rtc/Makefile | 1 + drivers/rtc/s3c24xx_rtc.c | 166 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 drivers/rtc/s3c24xx_rtc.c
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 8316e8f..bd8b1eb 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_RTC_RTC4543) += rtc4543.o COBJS-$(CONFIG_RTC_RV3029) += rv3029.o COBJS-$(CONFIG_RTC_RX8025) += rx8025.o COBJS-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o +COBJS-$(CONFIG_RTC_S3C24XX) += s3c24xx_rtc.o COBJS-$(CONFIG_RTC_S3C44B0) += s3c44b0_rtc.o COBJS-$(CONFIG_RTC_X1205) += x1205.o
diff --git a/drivers/rtc/s3c24xx_rtc.c b/drivers/rtc/s3c24xx_rtc.c new file mode 100644 index 0000000..3844e44 --- /dev/null +++ b/drivers/rtc/s3c24xx_rtc.c @@ -0,0 +1,166 @@ +/*
- (C) Copyright 2012 INOV - INESC Inovacao
- Jose Goncalves jose.goncalves@inov.pt
- Based on drivers/rtc/s3c24x0_rtc.c
- See file CREDITS for list of people who contributed to this
- project.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- */
+#include <common.h>
+#if defined(CONFIG_CMD_DATE)
+#include <rtc.h> +#include <asm/io.h> +#include <asm/arch/s3c24xx_cpu.h>
+static inline void rtc_access_enable(void) +{
- s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc();
- uchar rtccon;
- rtccon = readb(&rtc->rtccon);
- rtccon |= 0x01;
- writeb(rtccon, &rtc->rtccon);
+}
+static inline void rtc_access_disable(void) +{
- s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc();
- uchar rtccon;
- rtccon = readb(&rtc->rtccon);
- rtccon &= ~0x01;
Magic numbers, fix globally in the patchset
- writeb(rtccon, &rtc->rtccon);
+}
+/*
*/ + +int rtc_get(struct rtc_time *tmp) +{
- s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc();
- uchar sec, min, hour, mday, wday, mon, year;
- int have_retried = 0;
- rtc_access_enable();
- /* Read RTC registers */
+retry_get_time:
- min = readb(&rtc->bcdmin);
- hour = readb(&rtc->bcdhour);
- mday = readb(&rtc->bcddate);
- wday = readb(&rtc->bcdday);
- mon = readb(&rtc->bcdmon);
- year = readb(&rtc->bcdyear);
- sec = readb(&rtc->bcdsec);
- /* The only way to work out whether the RTC was mid-update
* when we read it is to check the seconds counter.
* If it's zero, then we re-try the entire read.
*/
Wrong multiline comment style ... use ./tools/checkpatch.pl before resending
- if (rtc->bcdsec == 0 && !have_retried) {
I'm sure you can avoid the goto here ...besides, this rtc->bcdsec doesn't make much sense
have_retried = 1;
goto retry_get_time;
- }
- rtc_access_disable();
- debug("Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
"hr: %02x min: %02x sec: %02x\n",
year, mon, mday, wday, hour, min, sec);
- tmp->tm_sec = bcd2bin(sec & 0x7F);
- tmp->tm_min = bcd2bin(min & 0x7F);
- tmp->tm_hour = bcd2bin(hour & 0x3F);
- tmp->tm_mday = bcd2bin(mday & 0x3F);
- tmp->tm_wday = bcd2bin(wday & 0x07);
- tmp->tm_mon = bcd2bin(mon & 0x1F);
- tmp->tm_year = bcd2bin(year);
- if (tmp->tm_year < 70)
tmp->tm_year += 2000;
- else
tmp->tm_year += 1900;
- tmp->tm_yday = 0;
- tmp->tm_isdst = 0;
- debug("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
- return 0;
+}
+int rtc_set(struct rtc_time *tmp) +{
- s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc();
- uchar sec, min, hour, mday, wday, mon, year;
- debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
- if (tmp->tm_year < 1970 || tmp->tm_year > 2069) {
puts("ERROR: year should be between 1970 and 2069!\n");
return -1;
- }
- year = bin2bcd(tmp->tm_year % 100);
- mon = bin2bcd(tmp->tm_mon);
- wday = bin2bcd(tmp->tm_wday);
- mday = bin2bcd(tmp->tm_mday);
- hour = bin2bcd(tmp->tm_hour);
- min = bin2bcd(tmp->tm_min);
- sec = bin2bcd(tmp->tm_sec);
- debug("Set RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
"hr: %02x min: %02x sec: %02x\n",
year, mon, mday, wday, hour, min, sec);
- rtc_access_enable();
- /* Write RTC registers */
- writeb(sec, &rtc->bcdsec);
- writeb(min, &rtc->bcdmin);
- writeb(hour, &rtc->bcdhour);
- writeb(mday, &rtc->bcddate);
- writeb(wday, &rtc->bcdday);
- writeb(mon, &rtc->bcdmon);
- writeb(year, &rtc->bcdyear);
- rtc_access_disable();
- return 0;
+}
+void rtc_reset(void) +{
- s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc();
- uchar rtccon;
- rtccon = readb(&rtc->rtccon);
- rtccon &= ~0x06;
- rtccon |= 0x08;
- writeb(rtccon, &rtc->rtccon);
- rtccon = readb(&rtc->rtccon);
- rtccon &= ~0x08;
- writeb(rtccon, &rtc->rtccon);
+}
+#endif

Hi Marek,
On 09/12/2012 10:03 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
+static inline void rtc_access_disable(void) +{
- s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc();
- uchar rtccon;
- rtccon = readb(&rtc->rtccon);
- rtccon &= ~0x01;
Magic numbers, fix globally in the patchset
OK.
- writeb(rtccon, &rtc->rtccon);
+}
+/*
*/ + +int rtc_get(struct rtc_time *tmp) +{
- s3c24xx_rtc *const rtc = s3c24xx_get_base_rtc();
- uchar sec, min, hour, mday, wday, mon, year;
- int have_retried = 0;
- rtc_access_enable();
- /* Read RTC registers */
+retry_get_time:
- min = readb(&rtc->bcdmin);
- hour = readb(&rtc->bcdhour);
- mday = readb(&rtc->bcddate);
- wday = readb(&rtc->bcdday);
- mon = readb(&rtc->bcdmon);
- year = readb(&rtc->bcdyear);
- sec = readb(&rtc->bcdsec);
- /* The only way to work out whether the RTC was mid-update
* when we read it is to check the seconds counter.
* If it's zero, then we re-try the entire read.
*/
Wrong multiline comment style ... use ./tools/checkpatch.pl before resending
OK.
- if (rtc->bcdsec == 0 && !have_retried) {
I'm sure you can avoid the goto here ...besides, this rtc->bcdsec doesn't make much sense
I could do it with a do..while loop instead... this part was copied from the linux driver. And there is a bug... instead of 'rtc->bcdsec' it should be 'sec'!
Regards, José Gonçalves

NAND Flash driver with HW ECC for the S3C24XX SoCs. Currently it only supports SLC NAND chips.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt --- drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/s3c24xx_nand.c | 269 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 drivers/mtd/nand/s3c24xx_nand.c
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 29dc20e..791ec44 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -60,6 +60,7 @@ COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o COBJS-$(CONFIG_NAND_NDFC) += ndfc.o COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o +COBJS-$(CONFIG_NAND_S3C24XX) += s3c24xx_nand.o COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o COBJS-$(CONFIG_NAND_SPEAR) += spr_nand.o COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o diff --git a/drivers/mtd/nand/s3c24xx_nand.c b/drivers/mtd/nand/s3c24xx_nand.c new file mode 100644 index 0000000..eed72d5 --- /dev/null +++ b/drivers/mtd/nand/s3c24xx_nand.c @@ -0,0 +1,269 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * Based on drivers/mtd/nand/s3c64xx.c and U-Boot 1.3.4 from Samsung. + * Supports only SLC NAND Flash chips. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <nand.h> +#include <asm/io.h> +#include <asm/arch/s3c24xx_cpu.h> +#include <asm/errno.h> + +#define NFCONT_ECC_ENC (1<<18) +#define NFCONT_WP (1<<16) +#define NFCONT_MECCLOCK (1<<7) +#define NFCONT_SECCLOCK (1<<6) +#define NFCONT_INITMECC (1<<5) +#define NFCONT_INITSECC (1<<4) +#define NFCONT_NCE1 (1<<2) +#define NFCONT_NCE0 (1<<1) +#define NFCONT_ENABLE (1<<0) + +#define NFSTAT_RNB (1<<0) + +#define MAX_CHIPS 2 +static int nand_cs[MAX_CHIPS] = { 0, 1 }; + +#ifdef CONFIG_SPL_BUILD +#define printf(arg...) do {} while (0) +#endif + +static void s3c_nand_select_chip(struct mtd_info *mtd, int chip) +{ + s3c24xx_nand *const nand = s3c24xx_get_base_nand(); + u_long nfcont; + + nfcont = readl(&nand->nfcont); + + switch (chip) { + case -1: + nfcont |= NFCONT_NCE1 | NFCONT_NCE0; + break; + case 0: + nfcont &= ~NFCONT_NCE0; + break; + case 1: + nfcont &= ~NFCONT_NCE1; + break; + default: + return; + } + + writel(nfcont, &nand->nfcont); +} + +/* + * Hardware specific access to control-lines function + */ +static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + s3c24xx_nand *const nand = s3c24xx_get_base_nand(); + struct nand_chip *this = mtd->priv; + + if (ctrl & NAND_CTRL_CHANGE) { + if (ctrl & NAND_CLE) + this->IO_ADDR_W = (void __iomem *)&nand->nfcmmd; + else if (ctrl & NAND_ALE) + this->IO_ADDR_W = (void __iomem *)&nand->nfaddr; + else + this->IO_ADDR_W = (void __iomem *)&nand->nfdata; + if (ctrl & NAND_NCE) + s3c_nand_select_chip(mtd, *(int *)this->priv); + else + s3c_nand_select_chip(mtd, -1); + } + + if (cmd != NAND_CMD_NONE) + writeb(cmd, this->IO_ADDR_W); +} + +/* + * Function for checking device ready pin + */ +static int s3c_nand_device_ready(struct mtd_info *mtdinfo) +{ + s3c24xx_nand *const nand = s3c24xx_get_base_nand(); + + return readl(&nand->nfstat) & NFSTAT_RNB; +} + +#ifdef CONFIG_S3C24XX_NAND_HWECC +/* + * This function is called before encoding ECC codes to ready ECC engine. + */ +static void s3c_nand_enable_hwecc(struct mtd_info *mtd, int mode) +{ + s3c24xx_nand *const nand = s3c24xx_get_base_nand(); + u_long nfcont, nfconf; + + /* Set 1-bit ECC */ + nfconf = readl(&nand->nfconf); +#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413) + nfconf &= ~(0x1 << 24); +#else + nfconf &= ~(0x3 << 23); +#endif + writel(nfconf, &nand->nfconf); + + /* Initialize & unlock ECC */ + nfcont = readl(&nand->nfcont); + nfcont |= NFCONT_INITMECC; + nfcont &= ~NFCONT_MECCLOCK; + writel(nfcont, &nand->nfcont); +} + +/* + * This function is called immediately after encoding ECC codes. + * This function returns encoded ECC codes. + */ +static int s3c_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, + u_char * ecc_code) +{ + s3c24xx_nand *const nand = s3c24xx_get_base_nand(); + u_long nfcont, nfmecc0; + + /* Lock */ + nfcont = readl(&nand->nfcont); + nfcont |= NFCONT_MECCLOCK; + writel(nfcont, &nand->nfcont); + + /* Return 1-bit ECC */ + nfmecc0 = readl(&nand->nfmecc[0]); + + ecc_code[0] = nfmecc0 & 0xff; + ecc_code[1] = (nfmecc0 >> 8) & 0xff; + ecc_code[2] = (nfmecc0 >> 16) & 0xff; + ecc_code[3] = (nfmecc0 >> 24) & 0xff; + + return 0; +} + +/* + * This function determines whether read data is good or not. + * On SLC, must write ECC codes to controller before reading status bit. + * If status bit is good, return 0. + * If a correctable error occured, correct it and return 1. + * If an uncorrectable error occured, return -1. + */ +static int s3c_nand_correct_data(struct mtd_info *mtd, u_char * dat, + u_char * read_ecc, u_char * calc_ecc) +{ + s3c24xx_nand *const nand = s3c24xx_get_base_nand(); + int ret; + u_long nfeccerr0, nfmeccdata0, nfmeccdata1, err_byte_addr; + u_char err_type, repaired; + + /* SLC: Write ECC to compare */ + nfmeccdata0 = (((u_long) read_ecc[1]) << 16) | read_ecc[0]; + nfmeccdata1 = (((u_long) read_ecc[3]) << 16) | read_ecc[2]; + writel(nfmeccdata0, &nand->nfmeccd[0]); + writel(nfmeccdata1, &nand->nfmeccd[1]); + + /* Read ECC status */ + nfeccerr0 = readl(&nand->nfeccerr[0]); + err_type = nfeccerr0 & 0x3; + + switch (err_type) { + case 0: /* No error */ + ret = 0; + break; + + case 1: + /* + * 1 bit error (Correctable) + * (nfeccerr0 >> 7) & 0x7ff :error byte number + * (nfeccerr0 >> 4) & 0x7 :error bit number + */ + err_byte_addr = (nfeccerr0 >> 7) & 0x7ff; + repaired = dat[err_byte_addr] ^ (1 << ((nfeccerr0 >> 4) & 0x7)); + + printf("S3C24XX NAND: 1 bit error detected at byte %ld. " + "Correcting from 0x%02x to 0x%02x\n", + err_byte_addr, dat[err_byte_addr], repaired); + + dat[err_byte_addr] = repaired; + + ret = 1; + break; + + case 2: /* Multiple error */ + case 3: /* ECC area error */ + printf("S3C24XX NAND: ECC uncorrectable error detected.\n"); + ret = -1; + break; + } + + return ret; +} +#endif /* CONFIG_S3C24XX_NAND_HWECC */ + +/* + * Board-specific NAND initialization. + */ +int board_nand_init(struct nand_chip *nand) +{ + static int chip_n = 0; + s3c24xx_nand *const nand_reg = s3c24xx_get_base_nand(); + u_long nfconf, nfcont; + + if (chip_n == 0) { + /* Extend NAND timings to the maximum */ + nfconf = readl(&nand_reg->nfconf); + nfconf |= 0x7770; + writel(nfconf, &nand_reg->nfconf); + + /* Disable chip selects and soft lock, enable controller */ + nfcont = readl(&nand_reg->nfcont); + nfcont &= ~NFCONT_WP; + nfcont |= NFCONT_NCE1 | NFCONT_NCE0 | NFCONT_ENABLE; + writel(nfcont, &nand_reg->nfcont); + } else if (chip_n >= MAX_CHIPS) { + return -ENODEV; + } + + nand->IO_ADDR_R = (void __iomem *)&nand_reg->nfdata; + nand->IO_ADDR_W = (void __iomem *)&nand_reg->nfdata; + nand->cmd_ctrl = s3c_nand_hwcontrol; + nand->dev_ready = s3c_nand_device_ready; + nand->select_chip = s3c_nand_select_chip; + nand->options = 0; +#ifdef CONFIG_SPL_BUILD + nand->read_buf = nand_read_buf; +#endif + +#ifdef CONFIG_S3C24XX_NAND_HWECC + nand->ecc.hwctl = s3c_nand_enable_hwecc; + nand->ecc.calculate = s3c_nand_calculate_ecc; + nand->ecc.correct = s3c_nand_correct_data; + nand->ecc.mode = NAND_ECC_HW_OOB_FIRST; + nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; + nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES; +#else + nand->ecc.mode = NAND_ECC_SOFT; +#endif /* ! CONFIG_S3C24XX_NAND_HWECC */ + + nand->priv = nand_cs + chip_n++; + + return 0; +}

Dear José Miguel Gonçalves,
NAND Flash driver with HW ECC for the S3C24XX SoCs. Currently it only supports SLC NAND chips.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt
drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/s3c24xx_nand.c | 269 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 drivers/mtd/nand/s3c24xx_nand.c
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 29dc20e..791ec44 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -60,6 +60,7 @@ COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o COBJS-$(CONFIG_NAND_NDFC) += ndfc.o COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o +COBJS-$(CONFIG_NAND_S3C24XX) += s3c24xx_nand.o COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o COBJS-$(CONFIG_NAND_SPEAR) += spr_nand.o COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o diff --git a/drivers/mtd/nand/s3c24xx_nand.c b/drivers/mtd/nand/s3c24xx_nand.c new file mode 100644 index 0000000..eed72d5 --- /dev/null +++ b/drivers/mtd/nand/s3c24xx_nand.c @@ -0,0 +1,269 @@ +/*
- (C) Copyright 2012 INOV - INESC Inovacao
- Jose Goncalves jose.goncalves@inov.pt
- Based on drivers/mtd/nand/s3c64xx.c and U-Boot 1.3.4 from Samsung.
- Supports only SLC NAND Flash chips.
- See file CREDITS for list of people who contributed to this
- project.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- */
+#include <common.h> +#include <nand.h> +#include <asm/io.h> +#include <asm/arch/s3c24xx_cpu.h> +#include <asm/errno.h>
+#define NFCONT_ECC_ENC (1<<18) +#define NFCONT_WP (1<<16) +#define NFCONT_MECCLOCK (1<<7) +#define NFCONT_SECCLOCK (1<<6) +#define NFCONT_INITMECC (1<<5) +#define NFCONT_INITSECC (1<<4) +#define NFCONT_NCE1 (1<<2) +#define NFCONT_NCE0 (1<<1) +#define NFCONT_ENABLE (1<<0)
+#define NFSTAT_RNB (1<<0)
+#define MAX_CHIPS 2 +static int nand_cs[MAX_CHIPS] = { 0, 1 };
+#ifdef CONFIG_SPL_BUILD +#define printf(arg...) do {} while (0) +#endif
+static void s3c_nand_select_chip(struct mtd_info *mtd, int chip) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- u_long nfcont;
- nfcont = readl(&nand->nfcont);
- switch (chip) {
- case -1:
nfcont |= NFCONT_NCE1 | NFCONT_NCE0;
break;
- case 0:
nfcont &= ~NFCONT_NCE0;
break;
- case 1:
nfcont &= ~NFCONT_NCE1;
break;
- default:
return;
- }
- writel(nfcont, &nand->nfcont);
+}
+/*
- Hardware specific access to control-lines function
- */
+static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- struct nand_chip *this = mtd->priv;
- if (ctrl & NAND_CTRL_CHANGE) {
if (ctrl & NAND_CLE)
this->IO_ADDR_W = (void __iomem *)&nand->nfcmmd;
else if (ctrl & NAND_ALE)
this->IO_ADDR_W = (void __iomem *)&nand->nfaddr;
else
this->IO_ADDR_W = (void __iomem *)&nand->nfdata;
Do you need this cast ?
if (ctrl & NAND_NCE)
s3c_nand_select_chip(mtd, *(int *)this->priv);
else
s3c_nand_select_chip(mtd, -1);
- }
- if (cmd != NAND_CMD_NONE)
writeb(cmd, this->IO_ADDR_W);
+}
+/*
- Function for checking device ready pin
- */
+static int s3c_nand_device_ready(struct mtd_info *mtdinfo) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- return readl(&nand->nfstat) & NFSTAT_RNB;
+}
+#ifdef CONFIG_S3C24XX_NAND_HWECC +/*
- This function is called before encoding ECC codes to ready ECC engine.
- */
+static void s3c_nand_enable_hwecc(struct mtd_info *mtd, int mode) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- u_long nfcont, nfconf;
- /* Set 1-bit ECC */
- nfconf = readl(&nand->nfconf);
+#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)
- nfconf &= ~(0x1 << 24);
+#else
- nfconf &= ~(0x3 << 23);
+#endif
Magic
- writel(nfconf, &nand->nfconf);
- /* Initialize & unlock ECC */
- nfcont = readl(&nand->nfcont);
- nfcont |= NFCONT_INITMECC;
- nfcont &= ~NFCONT_MECCLOCK;
- writel(nfcont, &nand->nfcont);
+}
+/*
- This function is called immediately after encoding ECC codes.
- This function returns encoded ECC codes.
- */
+static int s3c_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, + u_char * ecc_code) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- u_long nfcont, nfmecc0;
- /* Lock */
- nfcont = readl(&nand->nfcont);
- nfcont |= NFCONT_MECCLOCK;
- writel(nfcont, &nand->nfcont);
- /* Return 1-bit ECC */
- nfmecc0 = readl(&nand->nfmecc[0]);
- ecc_code[0] = nfmecc0 & 0xff;
- ecc_code[1] = (nfmecc0 >> 8) & 0xff;
- ecc_code[2] = (nfmecc0 >> 16) & 0xff;
- ecc_code[3] = (nfmecc0 >> 24) & 0xff;
- return 0;
+}
+/*
- This function determines whether read data is good or not.
- On SLC, must write ECC codes to controller before reading status bit.
- If status bit is good, return 0.
- If a correctable error occured, correct it and return 1.
- If an uncorrectable error occured, return -1.
- */
+static int s3c_nand_correct_data(struct mtd_info *mtd, u_char * dat,
u_char * read_ecc, u_char * calc_ecc)
+{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- int ret;
- u_long nfeccerr0, nfmeccdata0, nfmeccdata1, err_byte_addr;
- u_char err_type, repaired;
- /* SLC: Write ECC to compare */
- nfmeccdata0 = (((u_long) read_ecc[1]) << 16) | read_ecc[0];
- nfmeccdata1 = (((u_long) read_ecc[3]) << 16) | read_ecc[2];
- writel(nfmeccdata0, &nand->nfmeccd[0]);
- writel(nfmeccdata1, &nand->nfmeccd[1]);
- /* Read ECC status */
- nfeccerr0 = readl(&nand->nfeccerr[0]);
- err_type = nfeccerr0 & 0x3;
- switch (err_type) {
- case 0: /* No error */
ret = 0;
break;
- case 1:
/*
* 1 bit error (Correctable)
* (nfeccerr0 >> 7) & 0x7ff :error byte number
* (nfeccerr0 >> 4) & 0x7 :error bit number
*/
err_byte_addr = (nfeccerr0 >> 7) & 0x7ff;
repaired = dat[err_byte_addr] ^ (1 << ((nfeccerr0 >> 4) & 0x7));
printf("S3C24XX NAND: 1 bit error detected at byte %ld. "
"Correcting from 0x%02x to 0x%02x\n",
err_byte_addr, dat[err_byte_addr], repaired);
dat[err_byte_addr] = repaired;
ret = 1;
break;
- case 2: /* Multiple error */
- case 3: /* ECC area error */
printf("S3C24XX NAND: ECC uncorrectable error detected.\n");
ret = -1;
break;
- }
- return ret;
+} +#endif /* CONFIG_S3C24XX_NAND_HWECC */
+/*
- Board-specific NAND initialization.
- */
+int board_nand_init(struct nand_chip *nand) +{
- static int chip_n = 0;
- s3c24xx_nand *const nand_reg = s3c24xx_get_base_nand();
- u_long nfconf, nfcont;
- if (chip_n == 0) {
/* Extend NAND timings to the maximum */
nfconf = readl(&nand_reg->nfconf);
nfconf |= 0x7770;
Magic
writel(nfconf, &nand_reg->nfconf);
/* Disable chip selects and soft lock, enable controller */
nfcont = readl(&nand_reg->nfcont);
nfcont &= ~NFCONT_WP;
nfcont |= NFCONT_NCE1 | NFCONT_NCE0 | NFCONT_ENABLE;
writel(nfcont, &nand_reg->nfcont);
use clrsetbits_le32()
- } else if (chip_n >= MAX_CHIPS) {
return -ENODEV;
- }
- nand->IO_ADDR_R = (void __iomem *)&nand_reg->nfdata;
- nand->IO_ADDR_W = (void __iomem *)&nand_reg->nfdata;
- nand->cmd_ctrl = s3c_nand_hwcontrol;
- nand->dev_ready = s3c_nand_device_ready;
- nand->select_chip = s3c_nand_select_chip;
- nand->options = 0;
+#ifdef CONFIG_SPL_BUILD
- nand->read_buf = nand_read_buf;
+#endif
+#ifdef CONFIG_S3C24XX_NAND_HWECC
- nand->ecc.hwctl = s3c_nand_enable_hwecc;
- nand->ecc.calculate = s3c_nand_calculate_ecc;
- nand->ecc.correct = s3c_nand_correct_data;
- nand->ecc.mode = NAND_ECC_HW_OOB_FIRST;
- nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
- nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
+#else
- nand->ecc.mode = NAND_ECC_SOFT;
+#endif /* ! CONFIG_S3C24XX_NAND_HWECC */
- nand->priv = nand_cs + chip_n++;
- return 0;
+}

Hi Marek,
On 09/12/2012 10:11 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
+/*
- Hardware specific access to control-lines function
- */
+static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- struct nand_chip *this = mtd->priv;
- if (ctrl & NAND_CTRL_CHANGE) {
if (ctrl & NAND_CLE)
this->IO_ADDR_W = (void __iomem *)&nand->nfcmmd;
else if (ctrl & NAND_ALE)
this->IO_ADDR_W = (void __iomem *)&nand->nfaddr;
else
this->IO_ADDR_W = (void __iomem *)&nand->nfdata;
Do you need this cast ?
Without it gcc gives me a warning:
s3c24xx_nand.c:90:20: warning: assignment discards `volatile' qualifier from pointer target type [enabled by default]
+/*
- Board-specific NAND initialization.
- */
+int board_nand_init(struct nand_chip *nand) +{
- static int chip_n = 0;
- s3c24xx_nand *const nand_reg = s3c24xx_get_base_nand();
- u_long nfconf, nfcont;
- if (chip_n == 0) {
/* Extend NAND timings to the maximum */
nfconf = readl(&nand_reg->nfconf);
nfconf |= 0x7770;
Magic
writel(nfconf, &nand_reg->nfconf);
/* Disable chip selects and soft lock, enable controller */
nfcont = readl(&nand_reg->nfcont);
nfcont &= ~NFCONT_WP;
nfcont |= NFCONT_NCE1 | NFCONT_NCE0 | NFCONT_ENABLE;
writel(nfcont, &nand_reg->nfcont);
use clrsetbits_le32()
I will do that and also define some macros for the magic values.
Regards, José Gonçalves

On 09/12/2012 06:16 PM, José Miguel Gonçalves wrote:
Hi Marek,
On 09/12/2012 10:11 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
+/*
- Hardware specific access to control-lines function
- */
+static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- struct nand_chip *this = mtd->priv;
- if (ctrl & NAND_CTRL_CHANGE) {
if (ctrl & NAND_CLE)
this->IO_ADDR_W = (void __iomem *)&nand->nfcmmd;
else if (ctrl & NAND_ALE)
this->IO_ADDR_W = (void __iomem *)&nand->nfaddr;
else
this->IO_ADDR_W = (void __iomem *)&nand->nfdata;
Do you need this cast ?
Without it gcc gives me a warning:
s3c24xx_nand.c:90:20: warning: assignment discards `volatile' qualifier from pointer target type [enabled by default]
Why do you have volatile in your s3c24xx_nand struct?
-Scott

Hi Scott,
On 09/13/2012 12:20 AM, Scott Wood wrote:
On 09/12/2012 06:16 PM, José Miguel Gonçalves wrote:
Hi Marek,
On 09/12/2012 10:11 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
+/*
- Hardware specific access to control-lines function
- */
+static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- struct nand_chip *this = mtd->priv;
- if (ctrl & NAND_CTRL_CHANGE) {
if (ctrl & NAND_CLE)
this->IO_ADDR_W = (void __iomem *)&nand->nfcmmd;
else if (ctrl & NAND_ALE)
this->IO_ADDR_W = (void __iomem *)&nand->nfaddr;
else
this->IO_ADDR_W = (void __iomem *)&nand->nfdata;
Do you need this cast ?
Without it gcc gives me a warning:
s3c24xx_nand.c:90:20: warning: assignment discards `volatile' qualifier from pointer target type [enabled by default]
Why do you have volatile in your s3c24xx_nand struct?
I use that as a rule to memory mapping of hardware registers. Without it GCC optimization sometimes do bad things, like completely removing sequences of code. For instance, if you need to pause in a loop until some bit of a register is changed (as it's done in the serial driver) and the struct were this register is mapped don't have the volatile attribute, the GCC optimizer removes the loop.
Regards, José Gonçalves

Dear José Miguel Gonçalves,
Hi Scott,
On 09/13/2012 12:20 AM, Scott Wood wrote:
On 09/12/2012 06:16 PM, José Miguel Gonçalves wrote:
Hi Marek,
On 09/12/2012 10:11 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
+/*
- Hardware specific access to control-lines function
- */
+static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- struct nand_chip *this = mtd->priv;
- if (ctrl & NAND_CTRL_CHANGE) {
if (ctrl & NAND_CLE)
this->IO_ADDR_W = (void __iomem *)&nand->nfcmmd;
else if (ctrl & NAND_ALE)
this->IO_ADDR_W = (void __iomem *)&nand->nfaddr;
else
this->IO_ADDR_W = (void __iomem *)&nand->nfdata;
Do you need this cast ?
Without it gcc gives me a warning:
s3c24xx_nand.c:90:20: warning: assignment discards `volatile' qualifier from pointer target type [enabled by default]
Why do you have volatile in your s3c24xx_nand struct?
I use that as a rule to memory mapping of hardware registers. Without it GCC optimization sometimes do bad things, like completely removing sequences of code.
Not true unless your gcc is broken. Use proper accessors (readl()/writel()), they have proper barriers already.
For instance, if you need to pause in a loop until some bit of a register is changed (as it's done in the serial driver) and the struct were this register is mapped don't have the volatile attribute, the GCC optimizer removes the loop.
Yes, see above.
Regards, José Gonçalves
Best regards, Marek Vasut

On 09/13/2012 01:24 AM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
Hi Scott,
On 09/13/2012 12:20 AM, Scott Wood wrote:
On 09/12/2012 06:16 PM, José Miguel Gonçalves wrote:
Hi Marek,
On 09/12/2012 10:11 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
+/*
- Hardware specific access to control-lines function
- */
+static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- struct nand_chip *this = mtd->priv;
- if (ctrl & NAND_CTRL_CHANGE) {
if (ctrl & NAND_CLE)
this->IO_ADDR_W = (void __iomem *)&nand->nfcmmd;
else if (ctrl & NAND_ALE)
this->IO_ADDR_W = (void __iomem *)&nand->nfaddr;
else
this->IO_ADDR_W = (void __iomem *)&nand->nfdata;
Do you need this cast ?
Without it gcc gives me a warning:
s3c24xx_nand.c:90:20: warning: assignment discards `volatile' qualifier from pointer target type [enabled by default]
Why do you have volatile in your s3c24xx_nand struct?
I use that as a rule to memory mapping of hardware registers. Without it GCC optimization sometimes do bad things, like completely removing sequences of code.
Not true unless your gcc is broken. Use proper accessors (readl()/writel()), they have proper barriers already.
For instance, if you need to pause in a loop until some bit of a register is changed (as it's done in the serial driver) and the struct were this register is mapped don't have the volatile attribute, the GCC optimizer removes the loop.
Yes, see above.
When I was debugging U-Boot on the MIN2416 I saw this over-optimization situation in the serial driver so I added the volatile attribute to all structs that map the SoC registers. But, after you pointed to me that the I/O macros have already incorporated the proper barriers, I looked again to the serial driver source and noticed that I forgot to use that macros on register accesses! I will change this and test it tomorrow before resubmitting the patch.
Best regards, José Gonçalves

Dear José Miguel Gonçalves,
On 09/13/2012 01:24 AM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
Hi Scott,
On 09/13/2012 12:20 AM, Scott Wood wrote:
On 09/12/2012 06:16 PM, José Miguel Gonçalves wrote:
Hi Marek,
On 09/12/2012 10:11 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
> + > +/* > + * Hardware specific access to control-lines function > + */ > +static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, > unsigned int > ctrl) +{ > + s3c24xx_nand *const nand = s3c24xx_get_base_nand(); > + struct nand_chip *this = mtd->priv; > + > + if (ctrl & NAND_CTRL_CHANGE) { > + if (ctrl & NAND_CLE) > + this->IO_ADDR_W = (void __iomem *)&nand->nfcmmd; > + else if (ctrl & NAND_ALE) > + this->IO_ADDR_W = (void __iomem *)&nand->nfaddr; > + else > + this->IO_ADDR_W = (void __iomem *)&nand->nfdata;
Do you need this cast ?
Without it gcc gives me a warning:
s3c24xx_nand.c:90:20: warning: assignment discards `volatile' qualifier from pointer target type [enabled by default]
Why do you have volatile in your s3c24xx_nand struct?
I use that as a rule to memory mapping of hardware registers. Without it GCC optimization sometimes do bad things, like completely removing sequences of code.
Not true unless your gcc is broken. Use proper accessors (readl()/writel()), they have proper barriers already.
For instance, if you need to pause in a loop until some bit of a register is changed (as it's done in the serial driver) and the struct were this register is mapped don't have the volatile attribute, the GCC optimizer removes the loop.
Yes, see above.
When I was debugging U-Boot on the MIN2416 I saw this over-optimization situation in the serial driver
I just noticed that all those uart->something in your serial driver are actually register accesses. So that's flat wrong, use writel()/readl() etc accessors. Of course doing it like you do without memory barriers will make it go south.
so I added the volatile attribute to all structs that map the SoC registers. But, after you pointed to me that the I/O macros have already incorporated the proper barriers, I looked again to the serial driver source and noticed that I forgot to use that macros on register accesses! I will change this and test it tomorrow before resubmitting the patch.
WFM, thanks.
Best regards, José Gonçalves
Ccing Gabriel, can you look at those patches ?
Best regards, Marek Vasut

Dear José Miguel Gonçalves,
Hi Marek,
On 09/12/2012 10:11 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
+/*
- Hardware specific access to control-lines function
- */
+static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- struct nand_chip *this = mtd->priv;
- if (ctrl & NAND_CTRL_CHANGE) {
if (ctrl & NAND_CLE)
this->IO_ADDR_W = (void __iomem *)&nand->nfcmmd;
else if (ctrl & NAND_ALE)
this->IO_ADDR_W = (void __iomem *)&nand->nfaddr;
else
this->IO_ADDR_W = (void __iomem *)&nand->nfdata;
Do you need this cast ?
Without it gcc gives me a warning:
s3c24xx_nand.c:90:20: warning: assignment discards `volatile' qualifier from pointer target type [enabled by default]
Not that you need to do the assignment into the structure .... use local variable, no ?
+/*
- Board-specific NAND initialization.
- */
+int board_nand_init(struct nand_chip *nand) +{
- static int chip_n = 0;
- s3c24xx_nand *const nand_reg = s3c24xx_get_base_nand();
- u_long nfconf, nfcont;
- if (chip_n == 0) {
/* Extend NAND timings to the maximum */
nfconf = readl(&nand_reg->nfconf);
nfconf |= 0x7770;
Magic
writel(nfconf, &nand_reg->nfconf);
/* Disable chip selects and soft lock, enable controller */
nfcont = readl(&nand_reg->nfcont);
nfcont &= ~NFCONT_WP;
nfcont |= NFCONT_NCE1 | NFCONT_NCE0 | NFCONT_ENABLE;
writel(nfcont, &nand_reg->nfcont);
use clrsetbits_le32()
I will do that and also define some macros for the magic values.
Regards, José Gonçalves
Best regards, Marek Vasut

On 09/13/2012 12:45 AM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
Hi Marek,
On 09/12/2012 10:11 PM, Marek Vasut wrote:
Dear José Miguel Gonçalves,
+/*
- Hardware specific access to control-lines function
- */
+static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{
- s3c24xx_nand *const nand = s3c24xx_get_base_nand();
- struct nand_chip *this = mtd->priv;
- if (ctrl & NAND_CTRL_CHANGE) {
if (ctrl & NAND_CLE)
this->IO_ADDR_W = (void __iomem *)&nand->nfcmmd;
else if (ctrl & NAND_ALE)
this->IO_ADDR_W = (void __iomem *)&nand->nfaddr;
else
this->IO_ADDR_W = (void __iomem *)&nand->nfdata;
Do you need this cast ?
Without it gcc gives me a warning:
s3c24xx_nand.c:90:20: warning: assignment discards `volatile' qualifier from pointer target type [enabled by default]
Not that you need to do the assignment into the structure .... use local variable, no ?
Understood. I agree, it makes more sense to use a local variable to address the proper NAND controller register. I will update that.
Best regards, José Gonçalves

Samsung's S3C24XX SoCs need this in order to generate a binary image with the SPL and U-Boot concatenated.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile index 058fb53..595b5f6 100644 --- a/Makefile +++ b/Makefile @@ -442,13 +442,14 @@ $(obj)u-boot.sha1: $(obj)u-boot.bin $(obj)u-boot.dis: $(obj)u-boot $(OBJDUMP) -d $< > $@
-$(obj)u-boot.ubl: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin +$(obj)u-boot-ubl.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $(obj)spl/u-boot-spl $(obj)spl/u-boot-spl-pad.bin cat $(obj)spl/u-boot-spl-pad.bin $(obj)u-boot.bin > $(obj)u-boot-ubl.bin + rm $(obj)spl/u-boot-spl-pad.bin + +$(obj)u-boot.ubl: $(obj)u-boot-ubl.bin $(obj)tools/mkimage -n $(UBL_CONFIG) -T ublimage \ -e $(CONFIG_SYS_TEXT_BASE) -d $(obj)u-boot-ubl.bin $(obj)u-boot.ubl - rm $(obj)u-boot-ubl.bin - rm $(obj)spl/u-boot-spl-pad.bin
$(obj)u-boot.ais: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin $(obj)tools/mkimage -s -n $(if $(CONFIG_AIS_CONFIG_FILE),$(CONFIG_AIS_CONFIG_FILE),"/dev/null") \

The MINI2416 board is based on a Samsung's S3C2416 SoC and has 64MB DDR2 SDRAM, 256MB NAND Flash, a LAN9220 Ethernet Controller and a WM8731 Audio CODEC. This U-Boot port was implemented and tested on a unit bought to Boardcon (http://www.armdesigner.com/) but there are some other chinese providers that can supply it with a selectable NAND chip from 128MB to 1GB.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt --- MAINTAINERS | 4 + board/boardcon/mini2416/Makefile | 47 +++++++ board/boardcon/mini2416/config.mk | 4 + board/boardcon/mini2416/mini2416.c | 100 +++++++++++++++ board/boardcon/mini2416/mini2416_spl.c | 213 ++++++++++++++++++++++++++++++++ board/boardcon/mini2416/u-boot-spl.lds | 63 ++++++++++ boards.cfg | 1 + include/configs/mini2416.h | 200 ++++++++++++++++++++++++++++++ 8 files changed, 632 insertions(+) create mode 100644 board/boardcon/mini2416/Makefile create mode 100644 board/boardcon/mini2416/config.mk create mode 100644 board/boardcon/mini2416/mini2416.c create mode 100644 board/boardcon/mini2416/mini2416_spl.c create mode 100644 board/boardcon/mini2416/u-boot-spl.lds create mode 100644 include/configs/mini2416.h
diff --git a/MAINTAINERS b/MAINTAINERS index 4aabcff..593baa0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -655,6 +655,10 @@ Fabio Estevam fabio.estevam@freescale.com mx53ard i.MX53 mx53smd i.MX53
+José Gonçalves jose.goncalves@inov.pt + + mini2416 ARM926EJS (S3C2416 SoC) + Daniel Gorsulowski daniel.gorsulowski@esd.eu
meesc ARM926EJS (AT91SAM9263 SoC) diff --git a/board/boardcon/mini2416/Makefile b/board/boardcon/mini2416/Makefile new file mode 100644 index 0000000..bf92ba1 --- /dev/null +++ b/board/boardcon/mini2416/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2012 INOV - INESC Inovacao +# Jose Goncalves jose.goncalves@inov.pt +# +# 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$(BOARD).o + +ifdef CONFIG_SPL_BUILD +COBJS += mini2416_spl.o +else +COBJS += mini2416.o +endif + +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/boardcon/mini2416/config.mk b/board/boardcon/mini2416/config.mk new file mode 100644 index 0000000..f1230d0 --- /dev/null +++ b/board/boardcon/mini2416/config.mk @@ -0,0 +1,4 @@ +PAD_TO := 0x2000 +ifndef CONFIG_SPL_BUILD +ALL-y += $(obj)u-boot-ubl.bin +endif diff --git a/board/boardcon/mini2416/mini2416.c b/board/boardcon/mini2416/mini2416.c new file mode 100644 index 0000000..f4ed34d --- /dev/null +++ b/board/boardcon/mini2416/mini2416.c @@ -0,0 +1,100 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/s3c24xx_cpu.h> + +DECLARE_GLOBAL_DATA_PTR; + +static void ether_if_init(void) +{ + /* Ethernet chip is on memory bank 1 */ + s3c24xx_smc *const smc = s3c24xx_get_base_smc(S3C24XX_SMC1); + s3c24xx_gpio *const gpio = s3c24xx_get_base_gpio(); + u32 val; + + /* Set bus timings */ + writel(0, &smc->smbidcy); /* Idle Cycle */ + writel(14, &smc->smbwstwr); /* Write Wait State */ + writel(2, &smc->smbwstoen); /* Output Enable Assertion Delay */ + writel(2, &smc->smbwstwen); /* Write Enable Assertion Delay */ + writel(14, &smc->smbwstrd); /* Read Wait State */ + + /* Init SMC control register */ + val = readl(&smc->smbc); + val &= ~((1 << 20) | (1 << 12) | (3 << 4)); + val |= ((1 << 15) | (1 << 7) | (1 << 4) | (1 << 2) | (1 << 0)); + writel(val, &smc->smbc); + + /* Enable CS pin */ + val = readl(&gpio->gpacon); + val |= (1 << 12); + writel(val, &gpio->gpacon); +} + +int board_init(void) +{ + s3c24xx_gpio *const gpio = s3c24xx_get_base_gpio(); + + /* Turn LED on */ + writel((0 << 5), &gpio->gpcdat); + + /* Init interface with Ethernet chip */ + ether_if_init(); + + /* Arch number of MINI2416 Board */ + gd->bd->bi_arch_number = MACH_TYPE_MINI2416; + + /* Address of boot parameters */ + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + + return 0; +} + +int dram_init(void) +{ + gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, + CONFIG_SYS_SDRAM_SIZE); + return 0; +} + +#ifdef CONFIG_DISPLAY_BOARDINFO +int checkboard(void) +{ + printf("\nBoard: MINI2416\n"); + return 0; +} +#endif + +#ifdef CONFIG_CMD_NET +int board_eth_init(bd_t * bis) +{ + int rc = 0; +#ifdef CONFIG_SMC911X + rc = smc911x_initialize(0, CONFIG_SMC911X_BASE); +#endif + return rc; +} +#endif diff --git a/board/boardcon/mini2416/mini2416_spl.c b/board/boardcon/mini2416/mini2416_spl.c new file mode 100644 index 0000000..8b8f26e --- /dev/null +++ b/board/boardcon/mini2416/mini2416_spl.c @@ -0,0 +1,213 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <version.h> +#include <nand.h> +#include <asm/io.h> +#include <asm/arch/s3c24xx_cpu.h> + +/* DRAM Controller macros to use a DDR2 chip */ +#define CFG_BANK_CFG_VAL_DDR2 0x00049253 +#define CFG_BANK_CON1_VAL_DDR2 0x44000040 +#define CFG_BANK_CON2_VAL_DDR2 0x005D0035 +#define INIT_NORMAL 0x0 +#define INIT_PALL 0x1 +#define INIT_EMRS 0x3 +#define INIT_MRS 0x2 + +/* FCLK = 800 MHz, HCLK = 133 MHz, PCLK = 66 MHz */ +#define M_MDIV 400 +#define M_PDIV 3 +#define M_SDIV 1 +#define ARMDIV 0x1 +#define PREDIV 0x2 +#define PCLKDIV 1 +#define HCLKDIV 0x1 + +/* EPLLclk = 96MHz */ +#define E_MDIV 32 +#define E_PDIV 1 +#define E_SDIV 2 + +DECLARE_GLOBAL_DATA_PTR; +static gd_t gdata; + +static inline void asm_delay(ulong loops) +{ + asm volatile ("1:\n" "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0"(loops)); +} + +inline void hang(void) +{ + serial_puts("### ERROR ### Please RESET the board ###\n"); + for (;;) ; +} + +static inline void watchdog_disable(void) +{ + s3c24xx_watchdog *const watchdog = s3c24xx_get_base_watchdog(); + + writel(0, &watchdog->wtcon); +} + +static void pinmux_init(void) +{ + s3c24xx_gpio *const gpio = s3c24xx_get_base_gpio(); + u32 val; + + /* Init LED pin and turn LED off */ + val = readl(&gpio->gpccon); + val &= (0x3 << 10); + val |= (0x1 << 10); + writel(val, &gpio->gpccon); + writel((1 << 5), &gpio->gpcdat); + + /* Init UART pins */ + writel(0x0000AAAA, &gpio->gphcon); + + /* Init NAND interface */ + val = readl(&gpio->gpacon); + val |= (0x3F << 17); + writel(val, &gpio->gpacon); +} + +static void pll_init(void) +{ + s3c2416_sysctl *const sysctl = s3c2416_get_base_sysctl(); + u32 val; + + /* Configure clocks division ratio */ + val = readl(&sysctl->clkdiv0); + val &= ~((0x7 << 9) | (0x3 << 4) | (1 << 2) | (0x3)); + val |= ((ARMDIV << 9) | (PREDIV << 4) | (PCLKDIV << 2) | (HCLKDIV) | + (1 << 3)); + writel(val, &sysctl->clkdiv0); + + /* Set MPLL lock time */ + writel(0x0E10, &sysctl->lockcon0); + + /* Configure MPLL */ + writel((M_MDIV << 14) + (M_PDIV << 5) + M_SDIV, &sysctl->mpllcon); + + /* Set EPLL lock time */ + writel(0x1780, &sysctl->lockcon1); + + /* Configure EPLL */ + writel((E_MDIV << 16) + (E_PDIV << 8) + E_SDIV, &sysctl->epllcon); + + /* MSYSCLK = MPLL and ESYSCLK = EPLL */ + val = readl(&sysctl->clksrc); + val |= 0x50; + writel(val, &sysctl->clksrc); +} + +static void dramctl_init(void) +{ + s3c24xx_dramctl *const dramctl = s3c24xx_get_base_dramctl(); + + /* Step 1: Init BANKCFG & BANKCON1 */ + writel(CFG_BANK_CFG_VAL_DDR2, &dramctl->bankcfg); + writel(CFG_BANK_CON1_VAL_DDR2, &dramctl->bankcon1); + + /* Step 2: Init BANKCON2 */ + writel(CFG_BANK_CON2_VAL_DDR2, &dramctl->bankcon2); + + /* Step 3: Issue a PALL command */ + writel(CFG_BANK_CON1_VAL_DDR2 | INIT_PALL, &dramctl->bankcon1); + + /* Step 4: Issue a EMRS2 command */ + writel(0x80000000, &dramctl->bankcon3); + writel(CFG_BANK_CON1_VAL_DDR2 | INIT_EMRS, &dramctl->bankcon1); + + /* Step 5: Issue a EMRS3 command */ + writel(0xC0000000, &dramctl->bankcon3); + writel(CFG_BANK_CON1_VAL_DDR2 | INIT_EMRS, &dramctl->bankcon1); + + /* Step 6: Issue a EMRS1 command */ + writel(0x44000000, &dramctl->bankcon3); + writel(CFG_BANK_CON1_VAL_DDR2 | INIT_EMRS, &dramctl->bankcon1); + + /* Step 7: Issue a MRS command */ + writel(0x44000130, &dramctl->bankcon3); + writel(CFG_BANK_CON1_VAL_DDR2 | INIT_MRS, &dramctl->bankcon1); + + /* Step 8: Issue a PALL command */ + writel(CFG_BANK_CON1_VAL_DDR2 | INIT_PALL, &dramctl->bankcon1); + + /* Step 9: Write 0xFF into the refresh timer */ + writel(0xFF, &dramctl->refresh); + + /* Step 10: Wait more than 120 clocks */ + asm_delay(256); + + /* Step 11: Issue a MRS command */ + writel(0x44000030, &dramctl->bankcon3); + writel(CFG_BANK_CON1_VAL_DDR2 | INIT_MRS, &dramctl->bankcon1); + + /* Step 12: Issue a EMRS1 command */ + writel(0x47800030, &dramctl->bankcon3); + writel(CFG_BANK_CON1_VAL_DDR2 | INIT_EMRS, &dramctl->bankcon1); + + writel(0x44000030, &dramctl->bankcon3); + writel(CFG_BANK_CON1_VAL_DDR2 | INIT_EMRS, &dramctl->bankcon1); + + /* Step 13: Write 0x87 into the refresh timer */ + writel(0x87, &dramctl->refresh); + + /* Step 14: Normal Mode */ + writel(CFG_BANK_CON1_VAL_DDR2 | INIT_NORMAL, &dramctl->bankcon1); +} + +void board_init_f(ulong bootflag) +{ + watchdog_disable(); + pinmux_init(); + pll_init(); + + /* + * We call relocate_code() with relocation target set to the SPL entry + * point. This will result in relocation getting skipped and only .bss + * initialization is performed before jumping to board_init_r(). + */ + relocate_code(CONFIG_SPL_STACK, &gdata, CONFIG_SPL_TEXT_BASE); +} + +void board_init_r(gd_t * id, ulong dest_addr) +{ + gd = id; + gd->baudrate = CONFIG_BAUDRATE; + serial_init(); + + /* Print U-Boot SPL version string */ + serial_puts("\n\nU-Boot SPL " PLAIN_VERSION); + serial_puts(" (" U_BOOT_DATE " - " U_BOOT_TIME ")\n"); + + dramctl_init(); + nand_init(); + + serial_puts("Loading U-Boot from NAND Flash...\n"); + + nand_boot(); +} diff --git a/board/boardcon/mini2416/u-boot-spl.lds b/board/boardcon/mini2416/u-boot-spl.lds new file mode 100644 index 0000000..d339b0d --- /dev/null +++ b/board/boardcon/mini2416/u-boot-spl.lds @@ -0,0 +1,63 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * 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 + */ + +MEMORY { .iram : ORIGIN = CONFIG_SPL_TEXT_BASE, \ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : + { + CPUDIR/start.o (.text) + *(.text*) + } > .iram + + . = ALIGN(4); + .rodata : + { + *(SORT_BY_ALIGNMENT(.rodata*)) + } > .iram + + . = ALIGN(4); + .data : + { + *(SORT_BY_ALIGNMENT(.data*)) + } > .iram + + . = ALIGN(4); + _end = .; + + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end__ = .; + } >.sram +} diff --git a/boards.cfg b/boards.cfg index 72e7803..bf084a0 100644 --- a/boards.cfg +++ b/boards.cfg @@ -193,6 +193,7 @@ omap730p2_cs0boot arm arm926ejs omap730p2 ti omap omap730p2_cs3boot arm arm926ejs omap730p2 ti omap omap730p2:CS3_BOOT edminiv2 arm arm926ejs - LaCie orion5x dkb arm arm926ejs - Marvell pantheon +mini2416 arm arm926ejs mini2416 boardcon s3c24xx spear300 arm arm926ejs spear300 spear spear spear3xx_evb:spear300 spear300_nand arm arm926ejs spear300 spear spear spear3xx_evb:spear300,nand spear300_usbtty arm arm926ejs spear300 spear spear spear3xx_evb:spear300,usbtty diff --git a/include/configs/mini2416.h b/include/configs/mini2416.h new file mode 100644 index 0000000..dcc6407 --- /dev/null +++ b/include/configs/mini2416.h @@ -0,0 +1,200 @@ +/* + * (C) Copyright 2012 INOV - INESC Inovacao + * Jose Goncalves jose.goncalves@inov.pt + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * SoC Configuration + */ +#define CONFIG_ARM926EJS /* ARM926EJS CPU Core */ +#define CONFIG_S3C24XX /* SAMSUNG S3C24XX Family */ +#define CONFIG_S3C2416 /* SAMSUNG S3C2416 SoC */ +#define CONFIG_SYS_CLK_FREQ 12000000 +#define CONFIG_SYS_HZ 1000 + +/* + * Memory Information + */ +#define CONFIG_SYS_IRAM_BASE 0x00000000 /* Steppingstone base address */ +#define CONFIG_SYS_IRAM_SIZE (8 << 10) /* 8KB of Steppingstone */ +#define CONFIG_SYS_IRAM_END (CONFIG_SYS_IRAM_BASE + CONFIG_SYS_IRAM_SIZE) + +#define CONFIG_SYS_SRAM_BASE 0x00002000 /* SRAM base address */ +#define CONFIG_SYS_SRAM_SIZE (56 << 10) /* 56KB of SRAM */ +#define CONFIG_SYS_SRAM_END (CONFIG_SYS_SRAM_BASE + CONFIG_SYS_SRAM_SIZE) + +#define CONFIG_SYS_SDRAM_BASE 0x30000000 /* DDR2 SDRAM base address */ +#define CONFIG_SYS_SDRAM_SIZE (64 << 20) /* 64MB of DDR2 SDRAM */ +#define CONFIG_SYS_SDRAM_END (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE) + +/* + * Linux Interface + */ +#define MACH_TYPE_MINI2416 3850 +#define CONFIG_MACH_TYPE MACH_TYPE_MINI2416 +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_BOOTDELAY 3 +#define CONFIG_BOOTARGS "console=ttySAC3,115200n8" +#define CONFIG_BOOTCOMMAND "" /* TBD */ + +/* + * SPL + */ +#define CONFIG_SPL +#define CONFIG_SPL_SERIAL_SUPPORT +#define CONFIG_SPL_NAND_SUPPORT +#define CONFIG_SPL_NAND_SIMPLE +#define CONFIG_SPL_NAND_LOAD +#define CONFIG_SPL_TEXT_BASE 0x00000000 /* CONFIG_SYS_IRAM_BASE */ +#define CONFIG_SPL_MAX_SIZE CONFIG_SYS_IRAM_SIZE +#define CONFIG_SPL_BSS_START_ADDR CONFIG_SYS_SRAM_BASE +#define CONFIG_SPL_BSS_MAX_SIZE (CONFIG_SYS_SRAM_SIZE - (8 << 10)) +#define CONFIG_SPL_STACK CONFIG_SYS_SRAM_END /* 8KB for stack */ + +/* + * Monitor Interface + */ +#define CONFIG_SYS_PROMPT "MINI2416 # " +#define CONFIG_SYS_LONGHELP +#define CONFIG_SYS_CBSIZE 1024 +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_MAXARGS 16 +#define CONFIG_CMDLINE_EDITING + +/* + * Command Definition + */ +#define CONFIG_SYS_NO_FLASH /* No NOR Flash */ +#include <config_cmd_default.h> +#define CONFIG_CMD_CACHE +#define CONFIG_CMD_DATE +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_MISC +#define CONFIG_CMD_NAND +#define CONFIG_CMD_PING + +/* + * Miscellaneous Settings + */ +#define CONFIG_SKIP_LOWLEVEL_INIT +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_DISPLAY_BOARDINFO +#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + (1 << 20)) +#define CONFIG_SYS_MONITOR_BASE (CONFIG_SYS_SDRAM_END - (1 << 20)) +#define CONFIG_SYS_MONITOR_LEN (256 << 10) +#define CONFIG_SYS_TEXT_BASE 0x33F00000 /* CONFIG_SYS_MONITOR_BASE */ +#define CONFIG_SYS_MALLOC_LEN (384 << 10) +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SRAM_END - \ + GENERATED_GBL_DATA_SIZE) +#define CONFIG_SYS_ALT_MEMTEST +#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE +#define CONFIG_SYS_MEMTEST_END CONFIG_SYS_MONITOR_BASE + +/* + * NAND Flash + */ +#ifdef CONFIG_CMD_NAND + +#define CONFIG_NAND_S3C24XX +#define CONFIG_S3C24XX_NAND_HWECC +#define CONFIG_SYS_NAND_BASE 0x4E000010 +#define CONFIG_SYS_MAX_NAND_DEVICE 1 + +/* SPL NAND Driver */ +#define CONFIG_SYS_NAND_PAGE_SIZE (2 << 10) +#define CONFIG_SYS_NAND_BLOCK_SIZE (128 << 10) +#define CONFIG_SYS_NAND_PAGE_COUNT (CONFIG_SYS_NAND_BLOCK_SIZE / \ + CONFIG_SYS_NAND_PAGE_SIZE) +#define CONFIG_SYS_NAND_OOBSIZE 64 +#define CONFIG_SYS_NAND_ECCSIZE 512 +#define CONFIG_SYS_NAND_ECCBYTES 4 +#define CONFIG_SYS_NAND_ECCPOS {40, 41, 42, 43, 44, 45, 46, 47, \ + 48, 49, 50, 51, 52, 53, 54, 55} +#define CONFIG_SYS_NAND_BAD_BLOCK_POS 0 +#define CONFIG_SYS_NAND_HW_ECC_OOBFIRST +#define CONFIG_SYS_NAND_5_ADDR_CYCLE +#define CONFIG_SYS_NAND_U_BOOT_DST CONFIG_SYS_TEXT_BASE +#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST +#define CONFIG_SYS_NAND_U_BOOT_OFFS CONFIG_SPL_MAX_SIZE +#define CONFIG_SYS_NAND_U_BOOT_SIZE (CONFIG_SYS_MONITOR_LEN - \ + CONFIG_SPL_MAX_SIZE) + +#endif + +/* + * Serial Driver + */ +#define CONFIG_S3C24XX_SERIAL +#define CONFIG_SERIAL3 +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/* + * Ethernet + */ +#ifdef CONFIG_CMD_NET +#define CONFIG_SMC911X +#define CONFIG_SMC911X_BASE 0x08000000 +#define CONFIG_SMC911X_16_BIT +#define CONFIG_ETHADDR FE:11:22:33:44:55 +#define CONFIG_OVERWRITE_ETHADDR_ONCE +#define CONFIG_IPADDR 192.168.0.10 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_SERVERIP 192.168.0.1 +#define CONFIG_GATEWAYIP 192.168.0.1 +#endif + +/* + * RTC + */ +#ifdef CONFIG_CMD_DATE +#define CONFIG_RTC_S3C24XX +#endif + +/* + * Environment + */ +#ifdef CONFIG_CMD_NAND +#define CONFIG_ENV_IS_IN_NAND +#define CONFIG_ENV_SIZE CONFIG_SYS_NAND_BLOCK_SIZE +#define CONFIG_ENV_OFFSET CONFIG_SYS_MONITOR_LEN +#define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE +#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) +#else +#define CONFIG_ENV_IS_NOWHERE +#endif + +/* + * File System + */ +#ifdef CONFIG_CMD_NAND +#define CONFIG_CMD_MTDPARTS +#define CONFIG_MTD_DEVICE +#define CONFIG_MTD_PARTITIONS +#endif + +#endif /* __CONFIG_H */
participants (3)
-
José Miguel Gonçalves
-
Marek Vasut
-
Scott Wood