Signed-off-by: Alexey Galakhov <agalakhov@xxxxxxxxx> --- arch/arm/boards/a9m2410/a9m2410.c | 12 +- arch/arm/boards/a9m2410/config.h | 2 +- arch/arm/boards/a9m2410/lowlevel_init.S | 2 +- arch/arm/boards/a9m2440/a9m2410dev.c | 2 +- arch/arm/boards/a9m2440/a9m2440.c | 12 +- arch/arm/boards/a9m2440/config.h | 2 +- arch/arm/boards/a9m2440/lowlevel_init.S | 4 +- arch/arm/boards/mini2440/config.h | 2 +- arch/arm/boards/mini2440/lowlevel_init.S | 2 +- arch/arm/boards/mini2440/mini2440.c | 12 +- arch/arm/configs/a9m2410_defconfig | 2 +- arch/arm/configs/a9m2440_defconfig | 4 +- arch/arm/configs/mini2440_defconfig | 2 +- arch/arm/mach-samsung/Kconfig | 30 +- arch/arm/mach-samsung/Makefile | 5 +- arch/arm/mach-samsung/clocks-s3c24x0.c | 157 +++++ arch/arm/mach-samsung/generic.c | 112 ---- arch/arm/mach-samsung/gpio-s3c24x0.c | 2 +- .../arm/mach-samsung/include/mach/clocks-s3c24x0.h | 24 + arch/arm/mach-samsung/include/mach/gpio-s3c24x0.h | 77 +++ arch/arm/mach-samsung/include/mach/iomap-s3c24x0.h | 69 ++ arch/arm/mach-samsung/include/mach/s3c-clocks.h | 22 +- arch/arm/mach-samsung/include/mach/s3c-generic.h | 4 +- arch/arm/mach-samsung/include/mach/s3c-iomap.h | 53 +- arch/arm/mach-samsung/include/mach/s3c-nand.h | 54 ++ arch/arm/mach-samsung/include/mach/s3c24xx-gpio.h | 77 --- arch/arm/mach-samsung/include/mach/s3c24xx-nand.h | 54 -- arch/arm/mach-samsung/lowlevel-init.S | 317 ---------- arch/arm/mach-samsung/lowlevel-s3c24x0.S | 317 ++++++++++ arch/arm/mach-samsung/mem-s3c24x0.c | 143 +++++ arch/arm/mach-samsung/s3c24xx-clocks.c | 157 ----- drivers/mtd/nand/Kconfig | 4 +- drivers/mtd/nand/Makefile | 2 +- drivers/mtd/nand/nand_s3c.c | 665 ++++++++++++++++++++ drivers/mtd/nand/nand_s3c24xx.c | 665 -------------------- drivers/serial/Kconfig | 2 +- 36 files changed, 1576 insertions(+), 1496 deletions(-) create mode 100644 arch/arm/mach-samsung/clocks-s3c24x0.c create mode 100644 arch/arm/mach-samsung/include/mach/clocks-s3c24x0.h create mode 100644 arch/arm/mach-samsung/include/mach/gpio-s3c24x0.h create mode 100644 arch/arm/mach-samsung/include/mach/iomap-s3c24x0.h create mode 100644 arch/arm/mach-samsung/include/mach/s3c-nand.h delete mode 100644 arch/arm/mach-samsung/include/mach/s3c24xx-gpio.h delete mode 100644 arch/arm/mach-samsung/include/mach/s3c24xx-nand.h delete mode 100644 arch/arm/mach-samsung/lowlevel-init.S create mode 100644 arch/arm/mach-samsung/lowlevel-s3c24x0.S create mode 100644 arch/arm/mach-samsung/mem-s3c24x0.c delete mode 100644 arch/arm/mach-samsung/s3c24xx-clocks.c create mode 100644 drivers/mtd/nand/nand_s3c.c delete mode 100644 drivers/mtd/nand/nand_s3c24xx.c diff --git a/arch/arm/boards/a9m2410/a9m2410.c b/arch/arm/boards/a9m2410/a9m2410.c index adeaacc..19bf66a 100644 --- a/arch/arm/boards/a9m2410/a9m2410.c +++ b/arch/arm/boards/a9m2410/a9m2410.c @@ -33,13 +33,13 @@ #include <nand.h> #include <io.h> #include <mach/s3c-iomap.h> -#include <mach/s3c24xx-nand.h> +#include <mach/s3c-nand.h> #include <mach/s3c-generic.h> #include <mach/s3c-busctl.h> -#include <mach/s3c24xx-gpio.h> +#include <mach/gpio-s3c24x0.h> // {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0}, -static struct s3c24x0_nand_platform_data nand_info = { +static struct s3c_nand_platform_data nand_info = { .nand_timing = CALC_NFCONF_TIMING(A9M2410_TACLS, A9M2410_TWRPH0, A9M2410_TWRPH1) }; @@ -51,7 +51,7 @@ static int a9m2410_mem_init(void) * Note: On this card the second SDRAM page is not used */ s3c24xx_disable_second_sdram_bank(); - size = s3c24xx_get_memory_size(); + size = s3c_get_memory_size(); /* ---------- configure the GPIOs ------------- */ writel(0x007FFFFF, S3C_GPACON); @@ -136,10 +136,10 @@ static int a9m2410_devices_init(void) device_initcall(a9m2410_devices_init); -#ifdef CONFIG_S3C24XX_NAND_BOOT +#ifdef CONFIG_S3C_NAND_BOOT void __bare_init nand_boot(void) { - s3c24x0_nand_load_image((void *)TEXT_BASE, 256 * 1024, 0); + s3c_nand_load_image((void *)TEXT_BASE, 256 * 1024, 0); } #endif diff --git a/arch/arm/boards/a9m2410/config.h b/arch/arm/boards/a9m2410/config.h index 87b05fc..4b8a9a2 100644 --- a/arch/arm/boards/a9m2410/config.h +++ b/arch/arm/boards/a9m2410/config.h @@ -115,7 +115,7 @@ #define A9M2410_TWRPH1 1 /* needed in the generic NAND boot code only */ -#ifdef CONFIG_S3C24XX_NAND_BOOT +#ifdef CONFIG_S3C_NAND_BOOT # define BOARD_DEFAULT_NAND_TIMING CALC_NFCONF_TIMING(A9M2410_TACLS, A9M2410_TWRPH0, A9M2410_TWRPH1) #endif diff --git a/arch/arm/boards/a9m2410/lowlevel_init.S b/arch/arm/boards/a9m2410/lowlevel_init.S index a106d53..0463b26 100644 --- a/arch/arm/boards/a9m2410/lowlevel_init.S +++ b/arch/arm/boards/a9m2410/lowlevel_init.S @@ -28,7 +28,7 @@ board_init_lowlevel: bl s3c24x0_sdram_init -#ifdef CONFIG_S3C24XX_NAND_BOOT +#ifdef CONFIG_S3C_NAND_BOOT mov lr, r10 /* restore the link register */ /* up to here we are running from the internal SRAM area */ b s3c24x0_nand_boot /* does return directly to our caller into SDRAM */ diff --git a/arch/arm/boards/a9m2440/a9m2410dev.c b/arch/arm/boards/a9m2440/a9m2410dev.c index bedb0f7..f23fc5d 100644 --- a/arch/arm/boards/a9m2440/a9m2410dev.c +++ b/arch/arm/boards/a9m2440/a9m2410dev.c @@ -30,7 +30,7 @@ #include <io.h> #include <mach/s3c-iomap.h> #include <mach/s3c-busctl.h> -#include <mach/s3c24xx-gpio.h> +#include <mach/gpio-s3c24x0.h> /** * Initialize the CPU to be able to work with the a9m2410dev evaluation board diff --git a/arch/arm/boards/a9m2440/a9m2440.c b/arch/arm/boards/a9m2440/a9m2440.c index 6c6ccdb..94618ae 100644 --- a/arch/arm/boards/a9m2440/a9m2440.c +++ b/arch/arm/boards/a9m2440/a9m2440.c @@ -33,14 +33,14 @@ #include <nand.h> #include <io.h> #include <mach/s3c-iomap.h> -#include <mach/s3c24xx-nand.h> +#include <mach/s3c-nand.h> #include <mach/s3c-generic.h> #include <mach/s3c-busctl.h> -#include <mach/s3c24xx-gpio.h> +#include <mach/gpio-s3c24x0.h> #include "baseboards.h" -static struct s3c24x0_nand_platform_data nand_info = { +static struct s3c_nand_platform_data nand_info = { .nand_timing = CALC_NFCONF_TIMING(A9M2440_TACLS, A9M2440_TWRPH0, A9M2440_TWRPH1) }; @@ -99,7 +99,7 @@ static int a9m2440_mem_init(void) break; } - arm_add_mem_device("ram0", S3C_SDRAM_BASE, s3c24xx_get_memory_size()); + arm_add_mem_device("ram0", S3C_SDRAM_BASE, s3c_get_memory_size()); return 0; } @@ -155,10 +155,10 @@ static int a9m2440_devices_init(void) device_initcall(a9m2440_devices_init); -#ifdef CONFIG_S3C24XX_NAND_BOOT +#ifdef CONFIG_S3C_NAND_BOOT void __bare_init nand_boot(void) { - s3c24x0_nand_load_image((void *)TEXT_BASE, 256 * 1024, 0); + s3c_nand_load_image((void *)TEXT_BASE, 256 * 1024, 0); } #endif diff --git a/arch/arm/boards/a9m2440/config.h b/arch/arm/boards/a9m2440/config.h index 43cb6ab..09ad949 100644 --- a/arch/arm/boards/a9m2440/config.h +++ b/arch/arm/boards/a9m2440/config.h @@ -66,7 +66,7 @@ #define A9M2440_TWRPH1 1 /* needed in the generic NAND boot code only */ -#ifdef CONFIG_S3C24XX_NAND_BOOT +#ifdef CONFIG_S3C_NAND_BOOT # define BOARD_DEFAULT_NAND_TIMING CALC_NFCONF_TIMING(A9M2440_TACLS, A9M2440_TWRPH0, A9M2440_TWRPH1) #endif diff --git a/arch/arm/boards/a9m2440/lowlevel_init.S b/arch/arm/boards/a9m2440/lowlevel_init.S index e915a16..f6522f4 100644 --- a/arch/arm/boards/a9m2440/lowlevel_init.S +++ b/arch/arm/boards/a9m2440/lowlevel_init.S @@ -4,7 +4,7 @@ #include <config.h> #include <mach/s3c-iomap.h> -#include <mach/s3c24xx-gpio.h> +#include <mach/gpio-s3c24x0.h> .section ".text_bare_init.board_init_lowlevel","ax" @@ -232,7 +232,7 @@ board_init_lowlevel: bl sdram_init -#ifdef CONFIG_S3C24XX_NAND_BOOT +#ifdef CONFIG_S3C_NAND_BOOT mov lr, r10 /* restore the link register */ /* up to here we are running from the internal SRAM area */ b s3c24x0_nand_boot /* does return directly to our caller into SDRAM */ diff --git a/arch/arm/boards/mini2440/config.h b/arch/arm/boards/mini2440/config.h index 8d36193..674d974 100644 --- a/arch/arm/boards/mini2440/config.h +++ b/arch/arm/boards/mini2440/config.h @@ -66,7 +66,7 @@ #define MINI2440_TWRPH1 1 /* needed in the generic NAND boot code only */ -#ifdef CONFIG_S3C24XX_NAND_BOOT +#ifdef CONFIG_S3C_NAND_BOOT # define BOARD_DEFAULT_NAND_TIMING \ CALC_NFCONF_TIMING(MINI2440_TACLS, MINI2440_TWRPH0, MINI2440_TWRPH1) #endif diff --git a/arch/arm/boards/mini2440/lowlevel_init.S b/arch/arm/boards/mini2440/lowlevel_init.S index 1c8860a..827cf00 100644 --- a/arch/arm/boards/mini2440/lowlevel_init.S +++ b/arch/arm/boards/mini2440/lowlevel_init.S @@ -30,7 +30,7 @@ board_init_lowlevel: bl s3c24x0_sdram_init -#ifdef CONFIG_S3C24XX_NAND_BOOT +#ifdef CONFIG_S3C_NAND_BOOT mov lr, r10 /* restore the link register */ /* up to here we are running from the internal SRAM area */ b s3c24x0_nand_boot /* does return directly to our caller into SDRAM */ diff --git a/arch/arm/boards/mini2440/mini2440.c b/arch/arm/boards/mini2440/mini2440.c index 97e56db..1bc60b0 100644 --- a/arch/arm/boards/mini2440/mini2440.c +++ b/arch/arm/boards/mini2440/mini2440.c @@ -39,14 +39,14 @@ #include <io.h> #include <mach/gpio.h> #include <mach/s3c-iomap.h> -#include <mach/s3c24xx-nand.h> +#include <mach/s3c-nand.h> #include <mach/s3c-generic.h> #include <mach/s3c-mci.h> #include <mach/s3c24xx-fb.h> #include <mach/s3c-busctl.h> -#include <mach/s3c24xx-gpio.h> +#include <mach/gpio-s3c24x0.h> -static struct s3c24x0_nand_platform_data nand_info = { +static struct s3c_nand_platform_data nand_info = { .nand_timing = CALC_NFCONF_TIMING(MINI2440_TACLS, MINI2440_TWRPH0, MINI2440_TWRPH1), .flash_bbt = 1, /* same as the kernel */ @@ -268,7 +268,7 @@ static const unsigned pin_usage[] = { static int mini2440_mem_init(void) { - arm_add_mem_device("ram0", S3C_SDRAM_BASE, s3c24xx_get_memory_size()); + arm_add_mem_device("ram0", S3C_SDRAM_BASE, s3c_get_memory_size()); return 0; } @@ -326,10 +326,10 @@ static int mini2440_devices_init(void) device_initcall(mini2440_devices_init); -#ifdef CONFIG_S3C24XX_NAND_BOOT +#ifdef CONFIG_S3C_NAND_BOOT void __bare_init nand_boot(void) { - s3c24x0_nand_load_image((void *)TEXT_BASE, 256 * 1024, 0); + s3c_nand_load_image((void *)TEXT_BASE, 256 * 1024, 0); } #endif diff --git a/arch/arm/configs/a9m2410_defconfig b/arch/arm/configs/a9m2410_defconfig index 57e73c7..1955023 100644 --- a/arch/arm/configs/a9m2410_defconfig +++ b/arch/arm/configs/a9m2410_defconfig @@ -1,5 +1,5 @@ CONFIG_ARCH_S3C24xx=y -CONFIG_S3C24XX_NAND_BOOT=y +CONFIG_S3C_NAND_BOOT=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_BROKEN=y CONFIG_EXPERIMENTAL=y diff --git a/arch/arm/configs/a9m2440_defconfig b/arch/arm/configs/a9m2440_defconfig index ae7f523..ebdf64f 100644 --- a/arch/arm/configs/a9m2440_defconfig +++ b/arch/arm/configs/a9m2440_defconfig @@ -1,7 +1,7 @@ CONFIG_ARCH_S3C24xx=y CONFIG_MACH_A9M2440=y -CONFIG_S3C24XX_SDRAM_INIT=y -CONFIG_S3C24XX_NAND_BOOT=y +CONFIG_S3C_SDRAM_INIT=y +CONFIG_S3C_NAND_BOOT=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_BROKEN=y CONFIG_EXPERIMENTAL=y diff --git a/arch/arm/configs/mini2440_defconfig b/arch/arm/configs/mini2440_defconfig index 9b35dd5..efe76e4 100644 --- a/arch/arm/configs/mini2440_defconfig +++ b/arch/arm/configs/mini2440_defconfig @@ -1,7 +1,7 @@ CONFIG_ARCH_S3C24xx=y CONFIG_MACH_MINI2440=y CONFIG_MINI2440_VIDEO_N35=y -CONFIG_S3C24XX_NAND_BOOT=y +CONFIG_S3C_NAND_BOOT=y CONFIG_AEABI=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_TEXT_BASE=0x33e00000 diff --git a/arch/arm/mach-samsung/Kconfig b/arch/arm/mach-samsung/Kconfig index bc283dc..4d5f7c5 100644 --- a/arch/arm/mach-samsung/Kconfig +++ b/arch/arm/mach-samsung/Kconfig @@ -30,8 +30,8 @@ config MACH_A9M2410 bool "Digi A9M2410" select CPU_S3C2410 select MACH_HAS_LOWLEVEL_INIT - select S3C24XX_PLL_INIT - select S3C24XX_SDRAM_INIT + select S3C_PLL_INIT + select S3C_SDRAM_INIT help Say Y here if you are using Digi's Connect Core 9M equipped with a Samsung S3C2410 Processor @@ -40,7 +40,7 @@ config MACH_A9M2440 bool "Digi A9M2440" select CPU_S3C2440 select MACH_HAS_LOWLEVEL_INIT - select S3C24XX_PLL_INIT + select S3C_PLL_INIT help Say Y here if you are using Digi's Connect Core 9M equipped with a Samsung S3C2440 Processor @@ -50,8 +50,8 @@ config MACH_MINI2440 select CPU_S3C2440 select MACH_HAS_LOWLEVEL_INIT select MACH_DO_LOWLEVEL_INIT - select S3C24XX_PLL_INIT - select S3C24XX_SDRAM_INIT + select S3C_PLL_INIT + select S3C_SDRAM_INIT select HAS_DM9000 help Say Y here if you are using Mini 2440 dev board equipped @@ -78,34 +78,36 @@ source arch/arm/boards/mini2440/Kconfig endmenu -menu "S3C24X0 Features " +endif + +menu "S3C Features " -config S3C24XX_LOW_LEVEL_INIT +config S3C_LOWLEVEL_INIT bool -config S3C24XX_PLL_INIT +config S3C_PLL_INIT bool prompt "Reconfigure PLL" - select S3C24XX_LOW_LEVEL_INIT + select S3C_LOWLEVEL_INIT help This adds generic code to reconfigure the internal PLL very early after reset. -config S3C24XX_SDRAM_INIT +config S3C_SDRAM_INIT bool prompt "Initialize SDRAM" - select S3C24XX_LOW_LEVEL_INIT + select S3C_LOWLEVEL_INIT help This adds generic code to configure the SDRAM controller after reset. The initialisation will be skipped if the code is already running from SDRAM. -config S3C24XX_NAND_BOOT +config S3C_NAND_BOOT bool prompt "Booting from NAND" select MTD select NAND - select NAND_S3C24XX + select NAND_S3C help Add generic support to boot from NAND flash. Image loading will be skipped if the code is running from NOR or already from SDRAM. @@ -113,5 +115,3 @@ config S3C24XX_NAND_BOOT endmenu endif - -endif diff --git a/arch/arm/mach-samsung/Makefile b/arch/arm/mach-samsung/Makefile index 2ba5c3f..8f032fb 100644 --- a/arch/arm/mach-samsung/Makefile +++ b/arch/arm/mach-samsung/Makefile @@ -1,3 +1,4 @@ obj-y += s3c-timer.o generic.o -obj-$(CONFIG_ARCH_S3C24xx) += gpio-s3c24x0.o s3c24xx-clocks.o -obj-$(CONFIG_S3C24XX_LOW_LEVEL_INIT) += lowlevel-init.o +obj-lowlevel-$(CONFIG_ARCH_S3C24xx) += lowlevel-s3c24x0.o +obj-$(CONFIG_ARCH_S3C24xx) += gpio-s3c24x0.o clocks-s3c24x0.o mem-s3c24x0.o +obj-$(CONFIG_S3C_LOWLEVEL_INIT) += $(obj-lowlevel-y) diff --git a/arch/arm/mach-samsung/clocks-s3c24x0.c b/arch/arm/mach-samsung/clocks-s3c24x0.c new file mode 100644 index 0000000..38d8b75 --- /dev/null +++ b/arch/arm/mach-samsung/clocks-s3c24x0.c @@ -0,0 +1,157 @@ +/* + * 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. + */ + +#include <config.h> +#include <common.h> +#include <init.h> +#include <clock.h> +#include <io.h> +#include <mach/s3c-iomap.h> +#include <mach/s3c-generic.h> +#include <mach/s3c-clocks.h> +#include <mach/s3c-busctl.h> + +/** + * Calculate the current M-PLL clock. + * @return Current frequency in Hz + */ +uint32_t s3c_get_mpllclk(void) +{ + uint32_t m, p, s, reg_val; + + reg_val = readl(S3C_MPLLCON); + m = ((reg_val & 0xFF000) >> 12) + 8; + p = ((reg_val & 0x003F0) >> 4) + 2; + s = reg_val & 0x3; +#ifdef CONFIG_CPU_S3C2410 + return (S3C24XX_CLOCK_REFERENCE * m) / (p << s); +#endif +#ifdef CONFIG_CPU_S3C2440 + return 2 * m * (S3C24XX_CLOCK_REFERENCE / (p << s)); +#endif +} + +/** + * Calculate the current U-PLL clock + * @return Current frequency in Hz + */ +uint32_t s3c_get_upllclk(void) +{ + uint32_t m, p, s, reg_val; + + reg_val = readl(S3C_UPLLCON); + m = ((reg_val & 0xFF000) >> 12) + 8; + p = ((reg_val & 0x003F0) >> 4) + 2; + s = reg_val & 0x3; + + return (S3C24XX_CLOCK_REFERENCE * m) / (p << s); +} + +/** + * Calculate the FCLK frequency used for the ARM CPU core + * @return Current frequency in Hz + */ +uint32_t s3c_get_fclk(void) +{ + return s3c_get_mpllclk(); +} + +/** + * Calculate the HCLK frequency used for the AHB bus (CPU to main peripheral) + * @return Current frequency in Hz + */ +uint32_t s3c_get_hclk(void) +{ + uint32_t f_clk; + + f_clk = s3c_get_fclk(); +#ifdef CONFIG_CPU_S3C2410 + if (readl(S3C_CLKDIVN) & 0x02) + return f_clk >> 1; +#endif +#ifdef CONFIG_CPU_S3C2440 + switch(readl(S3C_CLKDIVN) & 0x06) { + case 2: + return f_clk >> 1; + case 4: + return f_clk >> 2; /* TODO consider CAMDIVN */ + case 6: + return f_clk / 3; /* TODO consider CAMDIVN */ + } +#endif + return f_clk; +} + +/** + * Calculate the PCLK frequency used for the slower peripherals + * @return Current frequency in Hz + */ +uint32_t s3c_get_pclk(void) +{ + uint32_t p_clk; + + p_clk = s3c_get_hclk(); + if (readl(S3C_CLKDIVN) & 0x01) + return p_clk >> 1; + return p_clk; +} + +/** + * Calculate the UCLK frequency used by the USB host device + * @return Current frequency in Hz + */ +uint32_t s3c24_get_uclk(void) +{ + return s3c_get_upllclk(); +} + +/** + * Return correct UART frequency based on the UCON register + */ +unsigned s3c_get_uart_clk(unsigned src) +{ + switch (src & 3) { + case 0: + case 2: + return s3c_get_pclk(); + case 1: + return 0; /* TODO UEXTCLK */ + case 3: + return 0; /* TODO FCLK/n */ + } + return 0; /* not reached, to make compiler happy */ +} + +/** + * Show the user the current clock settings + */ +int s3c24xx_dump_clocks(void) +{ + printf("refclk: %7d kHz\n", S3C24XX_CLOCK_REFERENCE / 1000); + printf("mpll: %7d kHz\n", s3c_get_mpllclk() / 1000); + printf("upll: %7d kHz\n", s3c_get_upllclk() / 1000); + printf("fclk: %7d kHz\n", s3c_get_fclk() / 1000); + printf("hclk: %7d kHz\n", s3c_get_hclk() / 1000); + printf("pclk: %7d kHz\n", s3c_get_pclk() / 1000); + printf("SDRAM1: CL%d@%dMHz\n", ((readl(S3C_BANKCON6) & 0xc) >> 2) + 2, + s3c_get_hclk() / 1000000); + if ((readl(S3C_BANKCON7) & (0x3 << 15)) == (0x3 << 15)) + printf("SDRAM2: CL%d@%dMHz\n", + ((readl(S3C_BANKCON7) & 0xc) >> 2) + 2, + s3c_get_hclk() / 1000000); + return 0; +} + +late_initcall(s3c24xx_dump_clocks); diff --git a/arch/arm/mach-samsung/generic.c b/arch/arm/mach-samsung/generic.c index 7706be2..f919e24 100644 --- a/arch/arm/mach-samsung/generic.c +++ b/arch/arm/mach-samsung/generic.c @@ -25,65 +25,10 @@ #include <config.h> #include <common.h> #include <init.h> -#include <clock.h> #include <io.h> -#include <sizes.h> #include <mach/s3c-iomap.h> #include <mach/s3c-generic.h> -#include <mach/s3c-busctl.h> -#include <mach/s3c24xx-gpio.h> -/** - * Calculate the amount of connected and available memory - * @return Memory size in bytes - */ -uint32_t s3c24xx_get_memory_size(void) -{ - uint32_t reg, size; - - /* - * detect the current memory size - */ - reg = readl(S3C_BANKSIZE); - - switch (reg & 0x7) { - case 0: - size = SZ_32M; - break; - case 1: - size = SZ_64M; - break; - case 2: - size = SZ_128M; - break; - case 4: - size = SZ_2M; - break; - case 5: - size = SZ_4M; - break; - case 6: - size = SZ_8M; - break; - default: - size = SZ_16M; - break; - } - - /* - * Is bank7 also configured for SDRAM usage? - */ - if ((readl(S3C_BANKCON7) & (0x3 << 15)) == (0x3 << 15)) - size <<= 1; /* also count this bank */ - - return size; -} - -void s3c24xx_disable_second_sdram_bank(void) -{ - writel(readl(S3C_BANKCON7) & ~(0x3 << 15), S3C_BANKCON7); - writel(readl(S3C_MISCCR) | (1 << 18), S3C_MISCCR); /* disable its clock */ -} #define S3C_WTCON (S3C_WATCHDOG_BASE) #define S3C_WTDAT (S3C_WATCHDOG_BASE + 0x04) @@ -105,60 +50,3 @@ void __noreturn reset_cpu(unsigned long addr) ; } EXPORT_SYMBOL(reset_cpu); - -/** - -@page dev_s3c24xx_arch Samsung's S3C24xx Platforms in barebox - -@section s3c24xx_boards Boards using S3C24xx Processors - -@li @subpage arch/arm/boards/a9m2410/a9m2410.c -@li @subpage arch/arm/boards/a9m2440/a9m2440.c - -@section s3c24xx_arch Documentation for S3C24xx Architectures Files - -@li @subpage arch/arm/mach-s3c24xx/generic.c - -@section s3c24xx_mem_map SDRAM Memory Map - -SDRAM starts at address 0x3000.0000 up to the available amount of connected -SDRAM memory. Physically this CPU can handle up to 256MiB (two areas with -up to 128MiB each). - -@subsection s3c24xx_mem_generic_map Generic Map -- 0x0000.0000 Start of the internal SRAM when booting from NAND flash memory or CS signal to a NOR flash memory. -- 0x0800.0000 Start of I/O space. -- 0x3000.0000 Start of SDRAM area. - - 0x3000.0100 Start of the TAG list area. - - 0x3000.8000 Start of the linux kernel (physical address). -- 0x4000.0000 Start of internal SRAM, when booting from NOR flash memory -- 0x4800.0000 Start of the internal I/O area - -@section s3c24xx_asm_arm include/asm-arm/arch-s3c24xx directory guidelines -All S3C24xx common headers are located here. - -@note Do not add board specific header files/information here. -*/ - -/** @page dev_s3c24xx_mach Samsung's S3C24xx based platforms - -@par barebox Map - -The location of the @a barebox itself depends on the available amount of -installed SDRAM memory: - -- 0x30fc.0000 Start of @a barebox when 16MiB SDRAM is available -- 0x31fc.0000 Start of @a barebox when 32MiB SDRAM is available -- 0x33fc.0000 Start of @a barebox when 64MiB SDRAM is available - -Adjust the @p CONFIG_TEXT_BASE/CONFIG_ARCH_TEXT_BASE symbol in accordance to -the available memory. - -@note The RAM based filesystem and the stack resides always below the -@a barebox start address. - -@li @subpage dev_s3c24xx_wd_handling -@li @subpage dev_s3c24xx_pll_handling -@li @subpage dev_s3c24xx_sdram_handling -@li @subpage dev_s3c24xx_nandboot_handling -*/ diff --git a/arch/arm/mach-samsung/gpio-s3c24x0.c b/arch/arm/mach-samsung/gpio-s3c24x0.c index 4f1c5cc..baeaf4f 100644 --- a/arch/arm/mach-samsung/gpio-s3c24x0.c +++ b/arch/arm/mach-samsung/gpio-s3c24x0.c @@ -20,7 +20,7 @@ #include <io.h> #include <mach/s3c-iomap.h> #include <mach/gpio.h> -#include <mach/s3c24xx-gpio.h> +#include <mach/gpio-s3c24x0.h> static const unsigned char group_offset[] = { diff --git a/arch/arm/mach-samsung/include/mach/clocks-s3c24x0.h b/arch/arm/mach-samsung/include/mach/clocks-s3c24x0.h new file mode 100644 index 0000000..839dfe3 --- /dev/null +++ b/arch/arm/mach-samsung/include/mach/clocks-s3c24x0.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2011 Juergen Beisert, Pengutronix + * + * 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. + */ + +# define S3C_LOCKTIME (S3C_CLOCK_POWER_BASE) +# define S3C_MPLLCON (S3C_CLOCK_POWER_BASE + 0x4) +# define S3C_UPLLCON (S3C_CLOCK_POWER_BASE + 0x8) +# define S3C_CLKCON (S3C_CLOCK_POWER_BASE + 0xc) +# define S3C_CLKSLOW (S3C_CLOCK_POWER_BASE + 0x10) +# define S3C_CLKDIVN (S3C_CLOCK_POWER_BASE + 0x14) + +# define S3C_MPLLCON_GET_MDIV(x) ((((x) >> 12) & 0xff) + 8) +# define S3C_MPLLCON_GET_PDIV(x) ((((x) >> 4) & 0x3f) + 2) +# define S3C_MPLLCON_GET_SDIV(x) ((x) & 0x3) diff --git a/arch/arm/mach-samsung/include/mach/gpio-s3c24x0.h b/arch/arm/mach-samsung/include/mach/gpio-s3c24x0.h new file mode 100644 index 0000000..ffb57fb --- /dev/null +++ b/arch/arm/mach-samsung/include/mach/gpio-s3c24x0.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2011 Juergen Beisert, Pengutronix + * + * 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. + */ + +#ifndef __MACH_GPIO_S3C24X0_H +# define __MACH_GPIO_S3C24X0_H + +#define S3C_GPACON (S3C_GPIO_BASE) +#define S3C_GPADAT (S3C_GPIO_BASE + 0x04) + +#define S3C_GPBCON (S3C_GPIO_BASE + 0x10) +#define S3C_GPBDAT (S3C_GPIO_BASE + 0x14) +#define S3C_GPBUP (S3C_GPIO_BASE + 0x18) + +#define S3C_GPCCON (S3C_GPIO_BASE + 0x20) +#define S3C_GPCDAT (S3C_GPIO_BASE + 0x24) +#define S3C_GPCUP (S3C_GPIO_BASE + 0x28) + +#define S3C_GPDCON (S3C_GPIO_BASE + 0x30) +#define S3C_GPDDAT (S3C_GPIO_BASE + 0x34) +#define S3C_GPDUP (S3C_GPIO_BASE + 0x38) + +#define S3C_GPECON (S3C_GPIO_BASE + 0x40) +#define S3C_GPEDAT (S3C_GPIO_BASE + 0x44) +#define S3C_GPEUP (S3C_GPIO_BASE + 0x48) + +#define S3C_GPFCON (S3C_GPIO_BASE + 0x50) +#define S3C_GPFDAT (S3C_GPIO_BASE + 0x54) +#define S3C_GPFUP (S3C_GPIO_BASE + 0x58) + +#define S3C_GPGCON (S3C_GPIO_BASE + 0x60) +#define S3C_GPGDAT (S3C_GPIO_BASE + 0x64) +#define S3C_GPGUP (S3C_GPIO_BASE + 0x68) + +#define S3C_GPHCON (S3C_GPIO_BASE + 0x70) +#define S3C_GPHDAT (S3C_GPIO_BASE + 0x74) +#define S3C_GPHUP (S3C_GPIO_BASE + 0x78) + +#ifdef CONFIG_CPU_S3C2440 +# define S3C_GPJCON (S3C_GPIO_BASE + 0xd0) +# define S3C_GPJDAT (S3C_GPIO_BASE + 0xd4) +# define S3C_GPJUP (S3C_GPIO_BASE + 0xd8) +#endif + +#define S3C_MISCCR (S3C_GPIO_BASE + 0x80) +#define S3C_DCLKCON (S3C_GPIO_BASE + 0x84) +#define S3C_EXTINT0 (S3C_GPIO_BASE + 0x88) +#define S3C_EXTINT1 (S3C_GPIO_BASE + 0x8c) +#define S3C_EXTINT2 (S3C_GPIO_BASE + 0x90) +#define S3C_EINTFLT0 (S3C_GPIO_BASE + 0x94) +#define S3C_EINTFLT1 (S3C_GPIO_BASE + 0x98) +#define S3C_EINTFLT2 (S3C_GPIO_BASE + 0x9c) +#define S3C_EINTFLT3 (S3C_GPIO_BASE + 0xa0) +#define S3C_EINTMASK (S3C_GPIO_BASE + 0xa4) +#define S3C_EINTPEND (S3C_GPIO_BASE + 0xa8) +#define S3C_GSTATUS0 (S3C_GPIO_BASE + 0xac) +#define S3C_GSTATUS1 (S3C_GPIO_BASE + 0xb0) +#define S3C_GSTATUS2 (S3C_GPIO_BASE + 0xb4) +#define S3C_GSTATUS3 (S3C_GPIO_BASE + 0xb8) +#define S3C_GSTATUS4 (S3C_GPIO_BASE + 0xbc) + +#ifdef CONFIG_CPU_S3C2440 +# define S3C_DSC0 (S3C_GPIO_BASE + 0xc4) +# define S3C_DSC1 (S3C_GPIO_BASE + 0xc8) +#endif + +#endif /* __MACH_GPIO_S3C24X0_H */ diff --git a/arch/arm/mach-samsung/include/mach/iomap-s3c24x0.h b/arch/arm/mach-samsung/include/mach/iomap-s3c24x0.h new file mode 100644 index 0000000..60d44e3 --- /dev/null +++ b/arch/arm/mach-samsung/include/mach/iomap-s3c24x0.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2009 Juergen Beisert, Pengutronix + * + * 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 + * + */ + +/* S3C2410 device base addresses */ +#define S3C_MEMCTL_BASE 0x48000000 +#define S3C2410_USB_HOST_BASE 0x49000000 +#define S3C2410_INTERRUPT_BASE 0x4A000000 +#define S3C2410_DMA_BASE 0x4B000000 +#define S3C_CLOCK_POWER_BASE 0x4C000000 +#define S3C2410_LCD_BASE 0x4D000000 +#define S3C24X0_NAND_BASE 0x4E000000 +#define S3C_UART_BASE 0x50000000 +#define S3C_TIMER_BASE 0x51000000 +#define S3C2410_USB_DEVICE_BASE 0x52000140 +#define S3C_WATCHDOG_BASE 0x53000000 +#define S3C2410_I2C_BASE 0x54000000 +#define S3C2410_I2S_BASE 0x55000000 +#define S3C_GPIO_BASE 0x56000000 +#define S3C2410_RTC_BASE 0x57000000 +#define S3C2410_ADC_BASE 0x58000000 +#define S3C2410_SPI_BASE 0x59000000 +#define S3C2410_SDI_BASE 0x5A000000 + +/* external IO space */ +#define S3C_CS0_BASE 0x00000000 +#define S3C_CS1_BASE 0x08000000 +#define S3C_CS2_BASE 0x10000000 +#define S3C_CS3_BASE 0x18000000 +#define S3C_CS4_BASE 0x20000000 +#define S3C_CS5_BASE 0x28000000 +#define S3C_CS6_BASE 0x30000000 + +#define S3C_SDRAM_BASE S3C_CS6_BASE +#define S3C_SDRAM_END (S3C_SDRAM_BASE + 0x10000000) + +/* + * if we are booting from NAND, its internal SRAM occures at + * a different address than without this feature + */ +#ifdef CONFIG_S3C_NAND_BOOT +# define NFC_RAM_AREA 0x00000000 +#else +# define NFC_RAM_AREA 0x40000000 +#endif +#define NFC_RAM_SIZE 4096 + +#define S3C_UART1_BASE (S3C_UART_BASE) +#define S3C_UART1_SIZE 0x4000 +#define S3C_UART2_BASE (S3C_UART_BASE + 0x4000) +#define S3C_UART2_SIZE 0x4000 +#define S3C_UART3_BASE (S3C_UART_BASE + 0x8000) +#define S3C_UART3_SIZE 0x4000 diff --git a/arch/arm/mach-samsung/include/mach/s3c-clocks.h b/arch/arm/mach-samsung/include/mach/s3c-clocks.h index 44b2a6c..f4ca8fa 100644 --- a/arch/arm/mach-samsung/include/mach/s3c-clocks.h +++ b/arch/arm/mach-samsung/include/mach/s3c-clocks.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Juergen Beisert, Pengutronix + * 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 @@ -10,22 +11,19 @@ * 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 __MACH_S3C_CLOCKS_H -# define __MACH_S3C_CLOCKS_H +#define __MACH_S3C_CLOCKS_H #ifdef CONFIG_ARCH_S3C24xx -# define S3C_LOCKTIME (S3C_CLOCK_POWER_BASE) -# define S3C_MPLLCON (S3C_CLOCK_POWER_BASE + 0x4) -# define S3C_UPLLCON (S3C_CLOCK_POWER_BASE + 0x8) -# define S3C_CLKCON (S3C_CLOCK_POWER_BASE + 0xc) -# define S3C_CLKSLOW (S3C_CLOCK_POWER_BASE + 0x10) -# define S3C_CLKDIVN (S3C_CLOCK_POWER_BASE + 0x14) - -# define S3C_MPLLCON_GET_MDIV(x) ((((x) >> 12) & 0xff) + 8) -# define S3C_MPLLCON_GET_PDIV(x) ((((x) >> 4) & 0x3f) + 2) -# define S3C_MPLLCON_GET_SDIV(x) ((x) & 0x3) +# include <mach/clocks-s3c24x0.h> #endif #endif /* __MACH_S3C_CLOCKS_H */ diff --git a/arch/arm/mach-samsung/include/mach/s3c-generic.h b/arch/arm/mach-samsung/include/mach/s3c-generic.h index 5d3808e..62d2c93 100644 --- a/arch/arm/mach-samsung/include/mach/s3c-generic.h +++ b/arch/arm/mach-samsung/include/mach/s3c-generic.h @@ -33,6 +33,8 @@ uint32_t s3c_get_uclk(void); unsigned s3c_get_uart_clk(unsigned src); -uint32_t s3c24xx_get_memory_size(void); +uint32_t s3c_get_memory_size(void); +#ifdef CONFIG_ARCH_S3C24xx void s3c24xx_disable_second_sdram_bank(void); +#endif diff --git a/arch/arm/mach-samsung/include/mach/s3c-iomap.h b/arch/arm/mach-samsung/include/mach/s3c-iomap.h index 9e867f8..b1305da 100644 --- a/arch/arm/mach-samsung/include/mach/s3c-iomap.h +++ b/arch/arm/mach-samsung/include/mach/s3c-iomap.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2009 Juergen Beisert, Pengutronix + * 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 @@ -18,52 +19,6 @@ * */ -/* S3C2410 device base addresses */ -#define S3C_MEMCTL_BASE 0x48000000 -#define S3C2410_USB_HOST_BASE 0x49000000 -#define S3C2410_INTERRUPT_BASE 0x4A000000 -#define S3C2410_DMA_BASE 0x4B000000 -#define S3C_CLOCK_POWER_BASE 0x4C000000 -#define S3C2410_LCD_BASE 0x4D000000 -#define S3C24X0_NAND_BASE 0x4E000000 -#define S3C_UART_BASE 0x50000000 -#define S3C_TIMER_BASE 0x51000000 -#define S3C2410_USB_DEVICE_BASE 0x52000140 -#define S3C_WATCHDOG_BASE 0x53000000 -#define S3C2410_I2C_BASE 0x54000000 -#define S3C2410_I2S_BASE 0x55000000 -#define S3C_GPIO_BASE 0x56000000 -#define S3C2410_RTC_BASE 0x57000000 -#define S3C2410_ADC_BASE 0x58000000 -#define S3C2410_SPI_BASE 0x59000000 -#define S3C2410_SDI_BASE 0x5A000000 - -/* external IO space */ -#define S3C_CS0_BASE 0x00000000 -#define S3C_CS1_BASE 0x08000000 -#define S3C_CS2_BASE 0x10000000 -#define S3C_CS3_BASE 0x18000000 -#define S3C_CS4_BASE 0x20000000 -#define S3C_CS5_BASE 0x28000000 -#define S3C_CS6_BASE 0x30000000 - -#define S3C_SDRAM_BASE S3C_CS6_BASE -#define S3C_SDRAM_END (S3C_SDRAM_BASE + 0x10000000) - -/* - * if we are booting from NAND, its internal SRAM occures at - * a different address than without this feature - */ -#ifdef CONFIG_S3C24XX_NAND_BOOT -# define NFC_RAM_AREA 0x00000000 -#else -# define NFC_RAM_AREA 0x40000000 +#ifdef CONFIG_ARCH_S3C24xx +# include <mach/iomap-s3c24x0.h> #endif -#define NFC_RAM_SIZE 4096 - -#define S3C_UART1_BASE (S3C_UART_BASE) -#define S3C_UART1_SIZE 0x4000 -#define S3C_UART2_BASE (S3C_UART_BASE + 0x4000) -#define S3C_UART2_SIZE 0x4000 -#define S3C_UART3_BASE (S3C_UART_BASE + 0x8000) -#define S3C_UART3_SIZE 0x4000 diff --git a/arch/arm/mach-samsung/include/mach/s3c-nand.h b/arch/arm/mach-samsung/include/mach/s3c-nand.h new file mode 100644 index 0000000..51d0387 --- /dev/null +++ b/arch/arm/mach-samsung/include/mach/s3c-nand.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 Juergen Beisert, Pengutronix + * + * 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 + * + */ + +#ifdef CONFIG_S3C_NAND_BOOT +extern void s3c_nand_load_image(void*, int, int); +#endif + +/** + * Locate the timing bits for the NFCONF register + * @param setup is the TACLS clock count + * @param access is the TWRPH0 clock count + * @param hold is the TWRPH1 clock count + * + * @note A clock count of 0 means always 1 HCLK clock. + * @note Clock count settings depend on the NAND flash requirements and the current HCLK speed + */ +#ifdef CONFIG_CPU_S3C2410 +# define CALC_NFCONF_TIMING(setup, access, hold) \ + ((setup << 8) + (access << 4) + (hold << 0)) +#endif +#ifdef CONFIG_CPU_S3C2440 +# define CALC_NFCONF_TIMING(setup, access, hold) \ + ((setup << 12) + (access << 8) + (hold << 4)) +#endif + +/** + * Define platform specific data for the NAND controller and its device + */ +struct s3c_nand_platform_data { + uint32_t nand_timing; /**< value for the NFCONF register (timing bits only) */ + char flash_bbt; /**< force a flash based BBT */ +}; + +/** + * @file + * @brief Basic declaration to use the s3c24x0 NAND driver + */ diff --git a/arch/arm/mach-samsung/include/mach/s3c24xx-gpio.h b/arch/arm/mach-samsung/include/mach/s3c24xx-gpio.h deleted file mode 100644 index c835974..0000000 --- a/arch/arm/mach-samsung/include/mach/s3c24xx-gpio.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2011 Juergen Beisert, Pengutronix - * - * 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. - */ - -#ifndef __MACH_S3C24XX_GPIO_H -# define __MACH_S3C24XX_GPIO_H - -#define S3C_GPACON (S3C_GPIO_BASE) -#define S3C_GPADAT (S3C_GPIO_BASE + 0x04) - -#define S3C_GPBCON (S3C_GPIO_BASE + 0x10) -#define S3C_GPBDAT (S3C_GPIO_BASE + 0x14) -#define S3C_GPBUP (S3C_GPIO_BASE + 0x18) - -#define S3C_GPCCON (S3C_GPIO_BASE + 0x20) -#define S3C_GPCDAT (S3C_GPIO_BASE + 0x24) -#define S3C_GPCUP (S3C_GPIO_BASE + 0x28) - -#define S3C_GPDCON (S3C_GPIO_BASE + 0x30) -#define S3C_GPDDAT (S3C_GPIO_BASE + 0x34) -#define S3C_GPDUP (S3C_GPIO_BASE + 0x38) - -#define S3C_GPECON (S3C_GPIO_BASE + 0x40) -#define S3C_GPEDAT (S3C_GPIO_BASE + 0x44) -#define S3C_GPEUP (S3C_GPIO_BASE + 0x48) - -#define S3C_GPFCON (S3C_GPIO_BASE + 0x50) -#define S3C_GPFDAT (S3C_GPIO_BASE + 0x54) -#define S3C_GPFUP (S3C_GPIO_BASE + 0x58) - -#define S3C_GPGCON (S3C_GPIO_BASE + 0x60) -#define S3C_GPGDAT (S3C_GPIO_BASE + 0x64) -#define S3C_GPGUP (S3C_GPIO_BASE + 0x68) - -#define S3C_GPHCON (S3C_GPIO_BASE + 0x70) -#define S3C_GPHDAT (S3C_GPIO_BASE + 0x74) -#define S3C_GPHUP (S3C_GPIO_BASE + 0x78) - -#ifdef CONFIG_CPU_S3C2440 -# define S3C_GPJCON (S3C_GPIO_BASE + 0xd0) -# define S3C_GPJDAT (S3C_GPIO_BASE + 0xd4) -# define S3C_GPJUP (S3C_GPIO_BASE + 0xd8) -#endif - -#define S3C_MISCCR (S3C_GPIO_BASE + 0x80) -#define S3C_DCLKCON (S3C_GPIO_BASE + 0x84) -#define S3C_EXTINT0 (S3C_GPIO_BASE + 0x88) -#define S3C_EXTINT1 (S3C_GPIO_BASE + 0x8c) -#define S3C_EXTINT2 (S3C_GPIO_BASE + 0x90) -#define S3C_EINTFLT0 (S3C_GPIO_BASE + 0x94) -#define S3C_EINTFLT1 (S3C_GPIO_BASE + 0x98) -#define S3C_EINTFLT2 (S3C_GPIO_BASE + 0x9c) -#define S3C_EINTFLT3 (S3C_GPIO_BASE + 0xa0) -#define S3C_EINTMASK (S3C_GPIO_BASE + 0xa4) -#define S3C_EINTPEND (S3C_GPIO_BASE + 0xa8) -#define S3C_GSTATUS0 (S3C_GPIO_BASE + 0xac) -#define S3C_GSTATUS1 (S3C_GPIO_BASE + 0xb0) -#define S3C_GSTATUS2 (S3C_GPIO_BASE + 0xb4) -#define S3C_GSTATUS3 (S3C_GPIO_BASE + 0xb8) -#define S3C_GSTATUS4 (S3C_GPIO_BASE + 0xbc) - -#ifdef CONFIG_CPU_S3C2440 -# define S3C_DSC0 (S3C_GPIO_BASE + 0xc4) -# define S3C_DSC1 (S3C_GPIO_BASE + 0xc8) -#endif - -#endif /* __MACH_S3C24XX_GPIO_H */ diff --git a/arch/arm/mach-samsung/include/mach/s3c24xx-nand.h b/arch/arm/mach-samsung/include/mach/s3c24xx-nand.h deleted file mode 100644 index 7610b4e..0000000 --- a/arch/arm/mach-samsung/include/mach/s3c24xx-nand.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2009 Juergen Beisert, Pengutronix - * - * 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 - * - */ - -#ifdef CONFIG_S3C24XX_NAND_BOOT -extern void s3c24x0_nand_load_image(void*, int, int); -#endif - -/** - * Locate the timing bits for the NFCONF register - * @param setup is the TACLS clock count - * @param access is the TWRPH0 clock count - * @param hold is the TWRPH1 clock count - * - * @note A clock count of 0 means always 1 HCLK clock. - * @note Clock count settings depend on the NAND flash requirements and the current HCLK speed - */ -#ifdef CONFIG_CPU_S3C2410 -# define CALC_NFCONF_TIMING(setup, access, hold) \ - ((setup << 8) + (access << 4) + (hold << 0)) -#endif -#ifdef CONFIG_CPU_S3C2440 -# define CALC_NFCONF_TIMING(setup, access, hold) \ - ((setup << 12) + (access << 8) + (hold << 4)) -#endif - -/** - * Define platform specific data for the NAND controller and its device - */ -struct s3c24x0_nand_platform_data { - uint32_t nand_timing; /**< value for the NFCONF register (timing bits only) */ - char flash_bbt; /**< force a flash based BBT */ -}; - -/** - * @file - * @brief Basic declaration to use the s3c24x0 NAND driver - */ diff --git a/arch/arm/mach-samsung/lowlevel-init.S b/arch/arm/mach-samsung/lowlevel-init.S deleted file mode 100644 index 31c6196..0000000 --- a/arch/arm/mach-samsung/lowlevel-init.S +++ /dev/null @@ -1,317 +0,0 @@ -/* - * (C) Copyright 2009 - * Juergen Beisert <kernel@xxxxxxxxxxxxxx> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <config.h> -#include <mach/s3c-iomap.h> - - .section ".text_bare_init.s3c24x0_disable_wd","ax" - -/* - * Disable the watchdog, else it continues to bark - */ -.globl s3c24x0_disable_wd -s3c24x0_disable_wd: - - ldr r0, =S3C_WATCHDOG_BASE - mov r1, #0x0 - str r1, [r0] - mov pc, lr - -/** -@page dev_s3c24xx_wd_handling Watchdog handling - -The watchdog must be disabled very early, because if it resets the system -it is still active and will continue to reset the system. So, call this -routine very early in your board_init_lowlevel routine. -*/ - -/* - * S3C2410 PLL configuration - * ------------------------- - * - * Basic frequency calculation - * - * m * REFclk s = SDIV - * PLLclk = ------------ p = PDIV + 2 - * p * 2^s m = MDIV + 8 - * - * After reset the PLL of the s3c2410 processor uses: - * - * MPLL UPLL - * MDIV 0x5c 0x28 - * PDIV 0x08 0x08 - * SDIV 0x0 0x0 - * - * 100 * 12MHz 1200MHz - * MPLLclk = ------------- = -------- = 120MHz - * 10 * 2^0 10 - * - * 48 * 12MHz 576MHz - * UPLLclk = ------------- = -------- = 57,6MHz - * 10 * 2^0 10 - * - * Note: Do not use "r10" here in this code - */ - -#ifdef CONFIG_S3C24XX_PLL_INIT - - .section ".text_bare_init.s3c24x0_pll_init","ax" - -.globl s3c24x0_pll_init -s3c24x0_pll_init: - - mov r0, #S3C_CLOCK_POWER_BASE - - /* configure internal clock ratio */ - mov r1, #BOARD_SPECIFIC_CLKDIVN - str r1, [r0, #20] - - /* enable all devices on this chip */ - mov r1, #0xFFFFFFF0 - str r1, [r0, #12] - - /* ??????? */ -#ifdef CONFIG_CPU_S3C2440 - mov r1, #0xFFFFFFFF -#endif -#ifdef CONFIG_CPU_S3C2410 - mov r1, #0x00FFFFFF -#endif - str r1, [r0, #0] - -#ifdef CONFIG_CPU_S3C2440 - /* - * Most of the time HDIVN is not 0, so we must use the - * asynchronous bus mode (refer datasheet "Clock and Power Management") - */ - mrc p15, 0, r1, c1, c0, 0 - orr r1, r1, #0xc0000000 - mcr p15, 0, r1, c1, c0, 0 -#endif - - /* configure UPLL */ - ldr r1, =BOARD_SPECIFIC_UPLL - str r1, [r0, #8] - - nop - nop - nop - nop - nop - nop - nop - nop - - /* configure MPLL */ - ldr r1, =BOARD_SPECIFIC_MPLL - str r1, [r0, #4] - - nop - nop - nop - nop - nop - nop - nop - nop - - mov pc, lr - -#endif - -/** -@page dev_s3c24xx_pll_handling PLL clock handling - -To control the speed of your machine the PLLs must be reconfigured after reset. - -For example the S3C2410 CPU wakes up after reset at 120MHz main PLL speed, -shared with all other system on chip components. Most of the time this -configuration is to slow for the CPU and to fast for the other components. - -PLL reprogramming can be done in the machine specific manner very early when -the CONFIG_S3C24XX_PLL_INIT and CONFIG_MACH_HAS_LOWLEVEL_INIT symbols are -defined. The board must provide a board_init_lowlevel() assembler function in -this case and calling the s3c24x0_pll_init() assembler function. - -If the s3c24x0_pll_init() is called a few further symbols must be defined to -setup the correct values for the machine. - -Define in the machine specific config.h the following symbols: - -- S3C24XX_CLOCK_REFERENCE with the frequency in Hz of your reference crystal. -- BOARD_SPECIFIC_CLKDIVN with the value for the main clock ratio register (CLKDIVN) -- BOARD_SPECIFIC_MPLL with the value for the main PLL setup register -- BOARD_SPECIFIC_UPLL with the value for the USB PLL setup register - -@note Valid values for the PLL settings can be found in the CPU manual. - -@par Background: PLL frequency calculation for the S3C2410 CPU (both PLLs) and S3C2440 (UPLL only) - -@f[ - f_{PLL} = \frac{m * f_{Ref}}{p * 2^s} -@f] - -With m = MDIV + 8, p = PDIV + 2 and s = SDIV. - -@par Background: PLL frequency calculation for the S3C2440 CPU (MPLL only) - -@f[ - f_{PLL} = \frac{2 * m * f_{Ref}}{p * 2^s} -@f] - -With m = MDIV + 8, p = PDIV + 2 and s = SDIV. - -@note This routine can be used for the S3C2410 and the S3C2440 CPU. - -*/ - -/* ----------------------------------------------------------------------- */ - -#ifdef CONFIG_S3C24XX_SDRAM_INIT - - .section ".text_bare_init.s3c24x0_sdram_init","ax" - - .globl s3c24x0_sdram_init -s3c24x0_sdram_init: - - adr r0, SDRAMDATA /* get the current relative address of the table */ - mov r1, #S3C_MEMCTL_BASE - mov r2, #6 /* we *know* it contains 6 entries */ - - ldr r3, [r0], #4 /* write BSWCON first */ - str r3, [r1], #0x1c /* post add register offset for bank6 */ -/* - * Initializing the SDRAM controller is very simple: - * Just write some useful values into the SDRAM controller. - */ -0: ldr r3, [r0], #4 - str r3, [r1], #4 - subs r2, r2, #1 - bne 0b - - mov pc, lr - -SDRAMDATA: - .word BOARD_SPECIFIC_BWSCON - .word BOARD_SPECIFIC_BANKCON6 - .word BOARD_SPECIFIC_BANKCON7 - .word BOARD_SPECIFIC_REFRESH - .word BOARD_SPECIFIC_BANKSIZE - .word BOARD_SPECIFIC_MRSRB6 - .word BOARD_SPECIFIC_MRSRB7 - -#endif - -/** -@page dev_s3c24xx_sdram_handling SDRAM controller initialisation - -The SDRAM controller is very simple and its initialisation requires only a -few steps. barebox provides a generic routine to do this step. - -Enable CONFIG_S3C24XX_SDRAM_INIT and CONFIG_MACH_HAS_LOWLEVEL_INIT to be able -to call the generic s3c24x0_sdram_init() assembler function from within the -machine specific board_init_lowlevel() assembler function. - -To use the s3c24x0_sdram_init() assembler function a few symbols must be -defined to setup correct values for the machine. - -Define in the machine specific config.h the following list of symbols: - -- BOARD_SPECIFIC_BWSCON with the values for SDRAM banks 6 and 7 -- BOARD_SPECIFIC_BANKCON6 with the value for the BANKCON6 register -- BOARD_SPECIFIC_BANKCON7 with the value for the BANKCON7 register -- BOARD_SPECIFIC_REFRESH with the value for the REFRESH register -- BOARD_SPECIFIC_BANKSIZE with the value for the BANKSIZE register -- BOARD_SPECIFIC_MRSRB6 with the value for the MRSRB6 register -- BOARD_SPECIFIC_MRSRB7 with the value for the MRSRB7 register -*/ - -/* ----------------------------------------------------------------------- */ - -#ifdef CONFIG_S3C24XX_NAND_BOOT - - .section ".text_bare_init.s3c24x0_nand_boot","ax" - - .globl s3c24x0_nand_boot -s3c24x0_nand_boot: -/* - * In the case of NOR boot we are running from the same address space. - * Detect this case to handle it correctly. - */ - mov r1, #S3C_MEMCTL_BASE - ldr r3, [r1] - and r3, r3, #0x6 - cmp r3, #0x0 /* check for NAND case */ - beq 2f - mov pc, lr /* NOR case: nothing to do here */ - -2: ldr sp, =TEXT_BASE /* Setup a temporary stack in SDRAM */ -/* - * We still run at a location we are not linked to. But lets still running - * from the internal SRAM, this may speed up the boot - */ - push {lr} - bl nand_boot - pop {lr} -/* - * Adjust the return address to the correct address in SDRAM - */ - ldr r1, =TEXT_BASE - add lr, lr, r1 - - mov pc, lr - -#endif - -/** -@page dev_s3c24xx_nandboot_handling Booting from NAND - -To be able to boot from NAND memory only, enable the S3C24x0 NAND driver. Also -enable CONFIG_S3C24XX_NAND_BOOT and CONFIG_MACH_HAS_LOWLEVEL_INIT to be -able to call the s3c24x0_nand_boot() assembler routine from within the -machine specific board_init_lowlevel() assembler function. - -@note This routine assumes an already working SDRAM controller and -an initialized stack pointer. - -@note Basicly this routine runs from inside the internal SRAM. After load of -the whole barebox image from the NAND flash memory into the SDRAM it adjusts -the link register to the final SDRAM adress and returns. - -@note In the NAND boot mode, ECC is not checked. So, the first x KBytes used -by barebox should have no bit error. - -Due to the fact the code to load the whole barebox from NAND must fit into -the first 4kiB of the barebox image, the shrinked NAND driver is very -minimalistic. Setup the NAND access timing is done in a safe manner, what -means: Slowest possible values are used. If you want to increase the speed you -should define the BOARD_DEFAULT_NAND_TIMING to a valid setting into the -NFCONF register and add it to your board specific config.h. Refer S3C24x0's -datasheet for further details. The macro #CALC_NFCONF_TIMING could help to -calculate the register setting in a hardware independent manner. - -@note The regular NAND driver uses a platform data structure to define the -NAND access timings. - -@note Its still possible to boot this image from NOR memory. If this routine -detects it is running from NOR instead of the internal SRAM it skips any -loading and returns immediately. - -*/ diff --git a/arch/arm/mach-samsung/lowlevel-s3c24x0.S b/arch/arm/mach-samsung/lowlevel-s3c24x0.S new file mode 100644 index 0000000..e9471a5 --- /dev/null +++ b/arch/arm/mach-samsung/lowlevel-s3c24x0.S @@ -0,0 +1,317 @@ +/* + * (C) Copyright 2009 + * Juergen Beisert <kernel@xxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <mach/s3c-iomap.h> + + .section ".text_bare_init.s3c24x0_disable_wd","ax" + +/* + * Disable the watchdog, else it continues to bark + */ +.globl s3c24x0_disable_wd +s3c24x0_disable_wd: + + ldr r0, =S3C_WATCHDOG_BASE + mov r1, #0x0 + str r1, [r0] + mov pc, lr + +/** +@page dev_s3c24xx_wd_handling Watchdog handling + +The watchdog must be disabled very early, because if it resets the system +it is still active and will continue to reset the system. So, call this +routine very early in your board_init_lowlevel routine. +*/ + +/* + * S3C2410 PLL configuration + * ------------------------- + * + * Basic frequency calculation + * + * m * REFclk s = SDIV + * PLLclk = ------------ p = PDIV + 2 + * p * 2^s m = MDIV + 8 + * + * After reset the PLL of the s3c2410 processor uses: + * + * MPLL UPLL + * MDIV 0x5c 0x28 + * PDIV 0x08 0x08 + * SDIV 0x0 0x0 + * + * 100 * 12MHz 1200MHz + * MPLLclk = ------------- = -------- = 120MHz + * 10 * 2^0 10 + * + * 48 * 12MHz 576MHz + * UPLLclk = ------------- = -------- = 57,6MHz + * 10 * 2^0 10 + * + * Note: Do not use "r10" here in this code + */ + +#ifdef CONFIG_S3C_PLL_INIT + + .section ".text_bare_init.s3c24x0_pll_init","ax" + +.globl s3c24x0_pll_init +s3c24x0_pll_init: + + mov r0, #S3C_CLOCK_POWER_BASE + + /* configure internal clock ratio */ + mov r1, #BOARD_SPECIFIC_CLKDIVN + str r1, [r0, #20] + + /* enable all devices on this chip */ + mov r1, #0xFFFFFFF0 + str r1, [r0, #12] + + /* ??????? */ +#ifdef CONFIG_CPU_S3C2440 + mov r1, #0xFFFFFFFF +#endif +#ifdef CONFIG_CPU_S3C2410 + mov r1, #0x00FFFFFF +#endif + str r1, [r0, #0] + +#ifdef CONFIG_CPU_S3C2440 + /* + * Most of the time HDIVN is not 0, so we must use the + * asynchronous bus mode (refer datasheet "Clock and Power Management") + */ + mrc p15, 0, r1, c1, c0, 0 + orr r1, r1, #0xc0000000 + mcr p15, 0, r1, c1, c0, 0 +#endif + + /* configure UPLL */ + ldr r1, =BOARD_SPECIFIC_UPLL + str r1, [r0, #8] + + nop + nop + nop + nop + nop + nop + nop + nop + + /* configure MPLL */ + ldr r1, =BOARD_SPECIFIC_MPLL + str r1, [r0, #4] + + nop + nop + nop + nop + nop + nop + nop + nop + + mov pc, lr + +#endif + +/** +@page dev_s3c24xx_pll_handling PLL clock handling + +To control the speed of your machine the PLLs must be reconfigured after reset. + +For example the S3C2410 CPU wakes up after reset at 120MHz main PLL speed, +shared with all other system on chip components. Most of the time this +configuration is to slow for the CPU and to fast for the other components. + +PLL reprogramming can be done in the machine specific manner very early when +the CONFIG_S3C_PLL_INIT and CONFIG_MACH_HAS_LOWLEVEL_INIT symbols are +defined. The board must provide a board_init_lowlevel() assembler function in +this case and calling the s3c24x0_pll_init() assembler function. + +If the s3c24x0_pll_init() is called a few further symbols must be defined to +setup the correct values for the machine. + +Define in the machine specific config.h the following symbols: + +- S3C24XX_CLOCK_REFERENCE with the frequency in Hz of your reference crystal. +- BOARD_SPECIFIC_CLKDIVN with the value for the main clock ratio register (CLKDIVN) +- BOARD_SPECIFIC_MPLL with the value for the main PLL setup register +- BOARD_SPECIFIC_UPLL with the value for the USB PLL setup register + +@note Valid values for the PLL settings can be found in the CPU manual. + +@par Background: PLL frequency calculation for the S3C2410 CPU (both PLLs) and S3C2440 (UPLL only) + +@f[ + f_{PLL} = \frac{m * f_{Ref}}{p * 2^s} +@f] + +With m = MDIV + 8, p = PDIV + 2 and s = SDIV. + +@par Background: PLL frequency calculation for the S3C2440 CPU (MPLL only) + +@f[ + f_{PLL} = \frac{2 * m * f_{Ref}}{p * 2^s} +@f] + +With m = MDIV + 8, p = PDIV + 2 and s = SDIV. + +@note This routine can be used for the S3C2410 and the S3C2440 CPU. + +*/ + +/* ----------------------------------------------------------------------- */ + +#ifdef CONFIG_S3C_SDRAM_INIT + + .section ".text_bare_init.s3c24x0_sdram_init","ax" + + .globl s3c24x0_sdram_init +s3c24x0_sdram_init: + + adr r0, SDRAMDATA /* get the current relative address of the table */ + mov r1, #S3C_MEMCTL_BASE + mov r2, #6 /* we *know* it contains 6 entries */ + + ldr r3, [r0], #4 /* write BSWCON first */ + str r3, [r1], #0x1c /* post add register offset for bank6 */ +/* + * Initializing the SDRAM controller is very simple: + * Just write some useful values into the SDRAM controller. + */ +0: ldr r3, [r0], #4 + str r3, [r1], #4 + subs r2, r2, #1 + bne 0b + + mov pc, lr + +SDRAMDATA: + .word BOARD_SPECIFIC_BWSCON + .word BOARD_SPECIFIC_BANKCON6 + .word BOARD_SPECIFIC_BANKCON7 + .word BOARD_SPECIFIC_REFRESH + .word BOARD_SPECIFIC_BANKSIZE + .word BOARD_SPECIFIC_MRSRB6 + .word BOARD_SPECIFIC_MRSRB7 + +#endif + +/** +@page dev_s3c24xx_sdram_handling SDRAM controller initialisation + +The SDRAM controller is very simple and its initialisation requires only a +few steps. barebox provides a generic routine to do this step. + +Enable CONFIG_S3C_SDRAM_INIT and CONFIG_MACH_HAS_LOWLEVEL_INIT to be able +to call the generic s3c24x0_sdram_init() assembler function from within the +machine specific board_init_lowlevel() assembler function. + +To use the s3c24x0_sdram_init() assembler function a few symbols must be +defined to setup correct values for the machine. + +Define in the machine specific config.h the following list of symbols: + +- BOARD_SPECIFIC_BWSCON with the values for SDRAM banks 6 and 7 +- BOARD_SPECIFIC_BANKCON6 with the value for the BANKCON6 register +- BOARD_SPECIFIC_BANKCON7 with the value for the BANKCON7 register +- BOARD_SPECIFIC_REFRESH with the value for the REFRESH register +- BOARD_SPECIFIC_BANKSIZE with the value for the BANKSIZE register +- BOARD_SPECIFIC_MRSRB6 with the value for the MRSRB6 register +- BOARD_SPECIFIC_MRSRB7 with the value for the MRSRB7 register +*/ + +/* ----------------------------------------------------------------------- */ + +#ifdef CONFIG_S3C_NAND_BOOT + + .section ".text_bare_init.s3c24x0_nand_boot","ax" + + .globl s3c24x0_nand_boot +s3c24x0_nand_boot: +/* + * In the case of NOR boot we are running from the same address space. + * Detect this case to handle it correctly. + */ + mov r1, #S3C_MEMCTL_BASE + ldr r3, [r1] + and r3, r3, #0x6 + cmp r3, #0x0 /* check for NAND case */ + beq 2f + mov pc, lr /* NOR case: nothing to do here */ + +2: ldr sp, =TEXT_BASE /* Setup a temporary stack in SDRAM */ +/* + * We still run at a location we are not linked to. But lets still running + * from the internal SRAM, this may speed up the boot + */ + push {lr} + bl nand_boot + pop {lr} +/* + * Adjust the return address to the correct address in SDRAM + */ + ldr r1, =TEXT_BASE + add lr, lr, r1 + + mov pc, lr + +#endif + +/** +@page dev_s3c24xx_nandboot_handling Booting from NAND + +To be able to boot from NAND memory only, enable the S3C24x0 NAND driver. Also +enable CONFIG_S3C_NAND_BOOT and CONFIG_MACH_HAS_LOWLEVEL_INIT to be +able to call the s3c24x0_nand_boot() assembler routine from within the +machine specific board_init_lowlevel() assembler function. + +@note This routine assumes an already working SDRAM controller and +an initialized stack pointer. + +@note Basicly this routine runs from inside the internal SRAM. After load of +the whole barebox image from the NAND flash memory into the SDRAM it adjusts +the link register to the final SDRAM adress and returns. + +@note In the NAND boot mode, ECC is not checked. So, the first x KBytes used +by barebox should have no bit error. + +Due to the fact the code to load the whole barebox from NAND must fit into +the first 4kiB of the barebox image, the shrinked NAND driver is very +minimalistic. Setup the NAND access timing is done in a safe manner, what +means: Slowest possible values are used. If you want to increase the speed you +should define the BOARD_DEFAULT_NAND_TIMING to a valid setting into the +NFCONF register and add it to your board specific config.h. Refer S3C24x0's +datasheet for further details. The macro #CALC_NFCONF_TIMING could help to +calculate the register setting in a hardware independent manner. + +@note The regular NAND driver uses a platform data structure to define the +NAND access timings. + +@note Its still possible to boot this image from NOR memory. If this routine +detects it is running from NOR instead of the internal SRAM it skips any +loading and returns immediately. + +*/ diff --git a/arch/arm/mach-samsung/mem-s3c24x0.c b/arch/arm/mach-samsung/mem-s3c24x0.c new file mode 100644 index 0000000..6944504 --- /dev/null +++ b/arch/arm/mach-samsung/mem-s3c24x0.c @@ -0,0 +1,143 @@ +/* + * 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 + */ +/** + * @file + * @brief Basic clock, sdram and timer handling for S3C24xx CPUs + */ + +#include <config.h> +#include <common.h> +#include <init.h> +#include <clock.h> +#include <io.h> +#include <sizes.h> +#include <mach/s3c-iomap.h> +#include <mach/s3c-generic.h> +#include <mach/s3c-busctl.h> +#include <mach/gpio-s3c24x0.h> + +/** + * Calculate the amount of connected and available memory + * @return Memory size in bytes + */ +uint32_t s3c_get_memory_size(void) +{ + uint32_t reg, size; + + /* + * detect the current memory size + */ + reg = readl(S3C_BANKSIZE); + + switch (reg & 0x7) { + case 0: + size = SZ_32M; + break; + case 1: + size = SZ_64M; + break; + case 2: + size = SZ_128M; + break; + case 4: + size = SZ_2M; + break; + case 5: + size = SZ_4M; + break; + case 6: + size = SZ_8M; + break; + default: + size = SZ_16M; + break; + } + + /* + * Is bank7 also configured for SDRAM usage? + */ + if ((readl(S3C_BANKCON7) & (0x3 << 15)) == (0x3 << 15)) + size <<= 1; /* also count this bank */ + + return size; +} + +void s3c24xx_disable_second_sdram_bank(void) +{ + writel(readl(S3C_BANKCON7) & ~(0x3 << 15), S3C_BANKCON7); + writel(readl(S3C_MISCCR) | (1 << 18), S3C_MISCCR); /* disable its clock */ +} + +/** + +@page dev_s3c24xx_arch Samsung's S3C24xx Platforms in barebox + +@section s3c24xx_boards Boards using S3C24xx Processors + +@li @subpage arch/arm/boards/a9m2410/a9m2410.c +@li @subpage arch/arm/boards/a9m2440/a9m2440.c + +@section s3c24xx_arch Documentation for S3C24xx Architectures Files + +@li @subpage arch/arm/mach-s3c24xx/generic.c + +@section s3c24xx_mem_map SDRAM Memory Map + +SDRAM starts at address 0x3000.0000 up to the available amount of connected +SDRAM memory. Physically this CPU can handle up to 256MiB (two areas with +up to 128MiB each). + +@subsection s3c24xx_mem_generic_map Generic Map +- 0x0000.0000 Start of the internal SRAM when booting from NAND flash memory or CS signal to a NOR flash memory. +- 0x0800.0000 Start of I/O space. +- 0x3000.0000 Start of SDRAM area. + - 0x3000.0100 Start of the TAG list area. + - 0x3000.8000 Start of the linux kernel (physical address). +- 0x4000.0000 Start of internal SRAM, when booting from NOR flash memory +- 0x4800.0000 Start of the internal I/O area + +@section s3c24xx_asm_arm include/asm-arm/arch-s3c24xx directory guidelines +All S3C24xx common headers are located here. + +@note Do not add board specific header files/information here. +*/ + +/** @page dev_s3c24xx_mach Samsung's S3C24xx based platforms + +@par barebox Map + +The location of the @a barebox itself depends on the available amount of +installed SDRAM memory: + +- 0x30fc.0000 Start of @a barebox when 16MiB SDRAM is available +- 0x31fc.0000 Start of @a barebox when 32MiB SDRAM is available +- 0x33fc.0000 Start of @a barebox when 64MiB SDRAM is available + +Adjust the @p CONFIG_TEXT_BASE/CONFIG_ARCH_TEXT_BASE symbol in accordance to +the available memory. + +@note The RAM based filesystem and the stack resides always below the +@a barebox start address. + +@li @subpage dev_s3c24xx_wd_handling +@li @subpage dev_s3c24xx_pll_handling +@li @subpage dev_s3c24xx_sdram_handling +@li @subpage dev_s3c24xx_nandboot_handling +*/ diff --git a/arch/arm/mach-samsung/s3c24xx-clocks.c b/arch/arm/mach-samsung/s3c24xx-clocks.c deleted file mode 100644 index 38d8b75..0000000 --- a/arch/arm/mach-samsung/s3c24xx-clocks.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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. - */ - -#include <config.h> -#include <common.h> -#include <init.h> -#include <clock.h> -#include <io.h> -#include <mach/s3c-iomap.h> -#include <mach/s3c-generic.h> -#include <mach/s3c-clocks.h> -#include <mach/s3c-busctl.h> - -/** - * Calculate the current M-PLL clock. - * @return Current frequency in Hz - */ -uint32_t s3c_get_mpllclk(void) -{ - uint32_t m, p, s, reg_val; - - reg_val = readl(S3C_MPLLCON); - m = ((reg_val & 0xFF000) >> 12) + 8; - p = ((reg_val & 0x003F0) >> 4) + 2; - s = reg_val & 0x3; -#ifdef CONFIG_CPU_S3C2410 - return (S3C24XX_CLOCK_REFERENCE * m) / (p << s); -#endif -#ifdef CONFIG_CPU_S3C2440 - return 2 * m * (S3C24XX_CLOCK_REFERENCE / (p << s)); -#endif -} - -/** - * Calculate the current U-PLL clock - * @return Current frequency in Hz - */ -uint32_t s3c_get_upllclk(void) -{ - uint32_t m, p, s, reg_val; - - reg_val = readl(S3C_UPLLCON); - m = ((reg_val & 0xFF000) >> 12) + 8; - p = ((reg_val & 0x003F0) >> 4) + 2; - s = reg_val & 0x3; - - return (S3C24XX_CLOCK_REFERENCE * m) / (p << s); -} - -/** - * Calculate the FCLK frequency used for the ARM CPU core - * @return Current frequency in Hz - */ -uint32_t s3c_get_fclk(void) -{ - return s3c_get_mpllclk(); -} - -/** - * Calculate the HCLK frequency used for the AHB bus (CPU to main peripheral) - * @return Current frequency in Hz - */ -uint32_t s3c_get_hclk(void) -{ - uint32_t f_clk; - - f_clk = s3c_get_fclk(); -#ifdef CONFIG_CPU_S3C2410 - if (readl(S3C_CLKDIVN) & 0x02) - return f_clk >> 1; -#endif -#ifdef CONFIG_CPU_S3C2440 - switch(readl(S3C_CLKDIVN) & 0x06) { - case 2: - return f_clk >> 1; - case 4: - return f_clk >> 2; /* TODO consider CAMDIVN */ - case 6: - return f_clk / 3; /* TODO consider CAMDIVN */ - } -#endif - return f_clk; -} - -/** - * Calculate the PCLK frequency used for the slower peripherals - * @return Current frequency in Hz - */ -uint32_t s3c_get_pclk(void) -{ - uint32_t p_clk; - - p_clk = s3c_get_hclk(); - if (readl(S3C_CLKDIVN) & 0x01) - return p_clk >> 1; - return p_clk; -} - -/** - * Calculate the UCLK frequency used by the USB host device - * @return Current frequency in Hz - */ -uint32_t s3c24_get_uclk(void) -{ - return s3c_get_upllclk(); -} - -/** - * Return correct UART frequency based on the UCON register - */ -unsigned s3c_get_uart_clk(unsigned src) -{ - switch (src & 3) { - case 0: - case 2: - return s3c_get_pclk(); - case 1: - return 0; /* TODO UEXTCLK */ - case 3: - return 0; /* TODO FCLK/n */ - } - return 0; /* not reached, to make compiler happy */ -} - -/** - * Show the user the current clock settings - */ -int s3c24xx_dump_clocks(void) -{ - printf("refclk: %7d kHz\n", S3C24XX_CLOCK_REFERENCE / 1000); - printf("mpll: %7d kHz\n", s3c_get_mpllclk() / 1000); - printf("upll: %7d kHz\n", s3c_get_upllclk() / 1000); - printf("fclk: %7d kHz\n", s3c_get_fclk() / 1000); - printf("hclk: %7d kHz\n", s3c_get_hclk() / 1000); - printf("pclk: %7d kHz\n", s3c_get_pclk() / 1000); - printf("SDRAM1: CL%d@%dMHz\n", ((readl(S3C_BANKCON6) & 0xc) >> 2) + 2, - s3c_get_hclk() / 1000000); - if ((readl(S3C_BANKCON7) & (0x3 << 15)) == (0x3 << 15)) - printf("SDRAM2: CL%d@%dMHz\n", - ((readl(S3C_BANKCON7) & 0xc) >> 2) + 2, - s3c_get_hclk() / 1000000); - return 0; -} - -late_initcall(s3c24xx_dump_clocks); diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 926a64b..f49417d 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -65,9 +65,9 @@ config NAND_ATMEL prompt "Atmel (AT91SAM9xxx) NAND driver" depends on ARCH_AT91 -config NAND_S3C24XX +config NAND_S3C bool - prompt "Samsung S3C24XX NAND driver" + prompt "Samsung S3C NAND driver" depends on ARCH_S3C24xx help Add support for processor's NAND device controller. diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 5c6d8b3..3e211d5 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -14,4 +14,4 @@ obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o obj-$(CONFIG_NAND_IMX) += nand_imx.o obj-$(CONFIG_NAND_OMAP_GPMC) += nand_omap_gpmc.o nand_omap_bch_decoder.o obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o -obj-$(CONFIG_NAND_S3C24XX) += nand_s3c24xx.o +obj-$(CONFIG_NAND_S3C) += nand_s3c.o diff --git a/drivers/mtd/nand/nand_s3c.c b/drivers/mtd/nand/nand_s3c.c new file mode 100644 index 0000000..9b76f98 --- /dev/null +++ b/drivers/mtd/nand/nand_s3c.c @@ -0,0 +1,665 @@ +/* linux/drivers/mtd/nand/s3c2410.c + * + * Copyright (C) 2009 Juergen Beisert, Pengutronix + * + * Copyright © 2004-2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@xxxxxxxxxxxx> + * + * Samsung S3C2410 NAND driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <config.h> +#include <common.h> +#include <driver.h> +#include <malloc.h> +#include <init.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <mach/s3c-generic.h> +#include <mach/s3c-iomap.h> +#include <mach/s3c-nand.h> +#include <io.h> +#include <asm-generic/errno.h> + +#ifdef CONFIG_S3C_NAND_BOOT +# define __nand_boot_init __bare_init +# ifndef BOARD_DEFAULT_NAND_TIMING +# define BOARD_DEFAULT_NAND_TIMING 0x0737 +# endif +#else +# define __nand_boot_init +#endif + +/** + * Define this symbol for testing purpose. It will add a command to read an + * image from the NAND like it the boot strap code will do. + */ +#define CONFIG_NAND_S3C_BOOT_DEBUG + +/* NAND controller's register */ + +#define NFCONF 0x00 + +#ifdef CONFIG_CPU_S3C2410 + +#define NFCMD 0x04 +#define NFADDR 0x08 +#define NFDATA 0x0c +#define NFSTAT 0x10 +#define NFECC 0x14 + +/* S3C2410 specific bits */ +#define NFSTAT_BUSY (1) +#define NFCONF_nFCE (1 << 11) +#define NFCONF_INITECC (1 << 12) +#define NFCONF_EN (1 << 15) + +#endif /* CONFIG_CPU_S3C2410 */ + +#ifdef CONFIG_CPU_S3C2440 + +#define NFCONT 0x04 +#define NFCMD 0x08 +#define NFADDR 0x0C +#define NFDATA 0x10 +#define NFSTAT 0x20 +#define NFECC 0x2C + +/* S3C2440 specific bits */ +#define NFSTAT_BUSY (1) +#define NFCONT_nFCE (1 << 1) +#define NFCONT_INITECC (1 << 4) +#define NFCONT_EN (1) + +#endif /* CONFIG_CPU_S3C2440 */ + + +struct s3c24x0_nand_host { + struct mtd_info mtd; + struct nand_chip nand; + struct mtd_partition *parts; + struct device_d *dev; + + void __iomem *base; +}; + +/** + * oob placement block for use with hardware ecc generation on small page + */ +static struct nand_ecclayout nand_hw_eccoob = { + .eccbytes = 3, + .eccpos = { 0, 1, 2}, + .oobfree = { + { + .offset = 8, + .length = 8 + } + } +}; + +/* - Functions shared between the boot strap code and the regular driver - */ + +/** + * Issue the specified command to the NAND device + * @param[in] host Base address of the NAND controller + * @param[in] cmd Command for NAND flash + */ +static void __nand_boot_init send_cmd(void __iomem *host, uint8_t cmd) +{ + writeb(cmd, host + NFCMD); +} + +/** + * Issue the specified address to the NAND device + * @param[in] host Base address of the NAND controller + * @param[in] addr Address for the NAND flash + */ +static void __nand_boot_init send_addr(void __iomem *host, uint8_t addr) +{ + writeb(addr, host + NFADDR); +} + +/** + * Enable the NAND flash access + * @param[in] host Base address of the NAND controller + */ +static void __nand_boot_init enable_cs(void __iomem *host) +{ +#ifdef CONFIG_CPU_S3C2410 + writew(readw(host + NFCONF) & ~NFCONF_nFCE, host + NFCONF); +#endif +#ifdef CONFIG_CPU_S3C2440 + writew(readw(host + NFCONT) & ~NFCONT_nFCE, host + NFCONT); +#endif +} + +/** + * Disable the NAND flash access + * @param[in] host Base address of the NAND controller + */ +static void __nand_boot_init disable_cs(void __iomem *host) +{ +#ifdef CONFIG_CPU_S3C2410 + writew(readw(host + NFCONF) | NFCONF_nFCE, host + NFCONF); +#endif +#ifdef CONFIG_CPU_S3C2440 + writew(readw(host + NFCONT) | NFCONT_nFCE, host + NFCONT); +#endif +} + +/** + * Enable the NAND flash controller + * @param[in] host Base address of the NAND controller + * @param[in] timing Timing to access the NAND memory + */ +static void __nand_boot_init enable_nand_controller(void __iomem *host, uint32_t timing) +{ +#ifdef CONFIG_CPU_S3C2410 + writew(timing + NFCONF_EN + NFCONF_nFCE, host + NFCONF); +#endif +#ifdef CONFIG_CPU_S3C2440 + writew(NFCONT_EN + NFCONT_nFCE, host + NFCONT); + writew(timing, host + NFCONF); +#endif +} + +/** + * Diable the NAND flash controller + * @param[in] host Base address of the NAND controller + */ +static void __nand_boot_init disable_nand_controller(void __iomem *host) +{ +#ifdef CONFIG_CPU_S3C2410 + writew(NFCONF_nFCE, host + NFCONF); +#endif +#ifdef CONFIG_CPU_S3C2440 + writew(NFCONT_nFCE, host + NFCONT); +#endif +} + +/* ----------------------------------------------------------------------- */ + +#ifdef CONFIG_CPU_S3C2440 +/** + * Read one block of data from the NAND port + * @param[in] mtd Instance data + * @param[out] buf buffer to write data to + * @param[in] len byte count + * + * This is a special block read variant for the S3C2440 CPU. + */ +static void s3c2440_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + struct s3c24x0_nand_host *host = nand_chip->priv; + + readsl(host->base + NFDATA, buf, len >> 2); + + /* cleanup any fractional read */ + if (len & 3) { + buf += len & ~3; + + for (; len & 3; len--) + *buf++ = readb(host->base + NFDATA); + } +} + +/** + * Write one block of data to the NAND port + * @param[in] mtd Instance data + * @param[out] buf buffer to read data from + * @param[in] len byte count + * + * This is a special block write variant for the S3C2440 CPU. + */ +static void s3c2440_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, + int len) +{ + struct nand_chip *nand_chip = mtd->priv; + struct s3c24x0_nand_host *host = nand_chip->priv; + + writesl(host->base + NFDATA, buf, len >> 2); + + /* cleanup any fractional write */ + if (len & 3) { + buf += len & ~3; + + for (; len & 3; len--, buf++) + writeb(*buf, host->base + NFDATA); + } +} +#endif + +/** + * Check the ECC and try to repair the data if possible + * @param[in] mtd_info Not used + * @param[inout] dat Pointer to the data buffer that might contain a bit error + * @param[in] read_ecc ECC data from the OOB space + * @param[in] calc_ecc ECC data calculated from the data + * @return 0 no error, 1 repaired error, -1 no way... + * + * @note: This routine works always on a 24 bit ECC + */ +static int s3c2410_nand_correct_data(struct mtd_info *mtd, uint8_t *dat, + uint8_t *read_ecc, uint8_t *calc_ecc) +{ + unsigned int diff0, diff1, diff2; + unsigned int bit, byte; + + diff0 = read_ecc[0] ^ calc_ecc[0]; + diff1 = read_ecc[1] ^ calc_ecc[1]; + diff2 = read_ecc[2] ^ calc_ecc[2]; + + if (diff0 == 0 && diff1 == 0 && diff2 == 0) + return 0; /* ECC is ok */ + + /* sometimes people do not think about using the ECC, so check + * to see if we have an 0xff,0xff,0xff read ECC and then ignore + * the error, on the assumption that this is an un-eccd page. + */ + if (read_ecc[0] == 0xff && read_ecc[1] == 0xff && read_ecc[2] == 0xff) + return 0; + + /* Can we correct this ECC (ie, one row and column change). + * Note, this is similar to the 256 error code on smartmedia */ + + if (((diff0 ^ (diff0 >> 1)) & 0x55) == 0x55 && + ((diff1 ^ (diff1 >> 1)) & 0x55) == 0x55 && + ((diff2 ^ (diff2 >> 1)) & 0x55) == 0x55) { + /* calculate the bit position of the error */ + + bit = ((diff2 >> 3) & 1) | + ((diff2 >> 4) & 2) | + ((diff2 >> 5) & 4); + + /* calculate the byte position of the error */ + + byte = ((diff2 << 7) & 0x100) | + ((diff1 << 0) & 0x80) | + ((diff1 << 1) & 0x40) | + ((diff1 << 2) & 0x20) | + ((diff1 << 3) & 0x10) | + ((diff0 >> 4) & 0x08) | + ((diff0 >> 3) & 0x04) | + ((diff0 >> 2) & 0x02) | + ((diff0 >> 1) & 0x01); + + dat[byte] ^= (1 << bit); + return 1; + } + + /* if there is only one bit difference in the ECC, then + * one of only a row or column parity has changed, which + * means the error is most probably in the ECC itself */ + + diff0 |= (diff1 << 8); + diff0 |= (diff2 << 16); + + if ((diff0 & ~(1<<fls(diff0))) == 0) + return 1; + + return -1; +} + +static void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode) +{ + struct nand_chip *nand_chip = mtd->priv; + struct s3c24x0_nand_host *host = nand_chip->priv; + +#ifdef CONFIG_CPU_S3C2410 + writel(readl(host->base + NFCONF) | NFCONF_INITECC , host->base + NFCONF); +#endif +#ifdef CONFIG_CPU_S3C2440 + writel(readl(host->base + NFCONT) | NFCONT_INITECC , host->base + NFCONT); +#endif +} + +static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code) +{ + struct nand_chip *nand_chip = mtd->priv; + struct s3c24x0_nand_host *host = nand_chip->priv; + +#ifdef CONFIG_CPU_S3C2410 + ecc_code[0] = readb(host->base + NFECC); + ecc_code[1] = readb(host->base + NFECC + 1); + ecc_code[2] = readb(host->base + NFECC + 2); +#endif +#ifdef CONFIG_CPU_S3C2440 + unsigned long ecc = readl(host->base + NFECC); + + ecc_code[0] = ecc; + ecc_code[1] = ecc >> 8; + ecc_code[2] = ecc >> 16; +#endif + return 0; +} + +static void s3c24x0_nand_select_chip(struct mtd_info *mtd, int chip) +{ + struct nand_chip *nand_chip = mtd->priv; + struct s3c24x0_nand_host *host = nand_chip->priv; + + if (chip == -1) + disable_cs(host->base); + else + enable_cs(host->base); +} + +static int s3c24x0_nand_devready(struct mtd_info *mtd) +{ + struct nand_chip *nand_chip = mtd->priv; + struct s3c24x0_nand_host *host = nand_chip->priv; + + return readw(host->base + NFSTAT) & NFSTAT_BUSY; +} + +static void s3c24x0_nand_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + struct nand_chip *nand_chip = mtd->priv; + struct s3c24x0_nand_host *host = nand_chip->priv; + + if (cmd == NAND_CMD_NONE) + return; + /* + * If the CLE should be active, this call is a NAND command + */ + if (ctrl & NAND_CLE) + send_cmd(host->base, cmd); + /* + * If the ALE should be active, this call is a NAND address + */ + if (ctrl & NAND_ALE) + send_addr(host->base, cmd); +} + +static int s3c24x0_nand_inithw(struct s3c24x0_nand_host *host) +{ + struct s3c_nand_platform_data *pdata = host->dev->platform_data; + uint32_t tmp; + + /* reset the NAND controller */ + disable_nand_controller(host->base); + + if (pdata != NULL) + tmp = pdata->nand_timing; + else + /* else slowest possible timing */ + tmp = CALC_NFCONF_TIMING(4, 8, 8); + + /* reenable the NAND controller */ + enable_nand_controller(host->base, tmp); + + return 0; +} + +static int s3c24x0_nand_probe(struct device_d *dev) +{ + struct nand_chip *chip; + struct s3c_nand_platform_data *pdata = dev->platform_data; + struct mtd_info *mtd; + struct s3c24x0_nand_host *host; + int ret; + + /* Allocate memory for MTD device structure and private data */ + host = kzalloc(sizeof(struct s3c24x0_nand_host), GFP_KERNEL); + if (!host) + return -ENOMEM; + + host->dev = dev; + host->base = dev_request_mem_region(dev, 0); + + /* structures must be linked */ + chip = &host->nand; + mtd = &host->mtd; + mtd->priv = chip; + + /* init the default settings */ + + /* 50 us command delay time */ + chip->chip_delay = 50; + chip->priv = host; + + chip->IO_ADDR_R = chip->IO_ADDR_W = host->base + NFDATA; + +#ifdef CONFIG_CPU_S3C2440 + chip->read_buf = s3c2440_nand_read_buf; + chip->write_buf = s3c2440_nand_write_buf; +#endif + chip->cmd_ctrl = s3c24x0_nand_hwcontrol; + chip->dev_ready = s3c24x0_nand_devready; + chip->select_chip = s3c24x0_nand_select_chip; + + /* we are using the hardware ECC feature of this device */ + chip->ecc.calculate = s3c2410_nand_calculate_ecc; + chip->ecc.correct = s3c2410_nand_correct_data; + chip->ecc.hwctl = s3c2410_nand_enable_hwecc; + + /* + * Setup ECC handling in accordance to the kernel + * - 1 times 512 bytes with 24 bit ECC for small page + * - 8 times 256 bytes with 24 bit ECC each for large page + */ + chip->ecc.mode = NAND_ECC_HW; + chip->ecc.bytes = 3; /* always 24 bit ECC per turn */ +#ifdef CONFIG_CPU_S3C2440 + if (readl(host->base) & 0x8) { + /* large page (2048 bytes per page) */ + chip->ecc.size = 256; + } else +#endif + { + /* small page (512 bytes per page) */ + chip->ecc.size = 512; + chip->ecc.layout = &nand_hw_eccoob; + } + + if (pdata->flash_bbt) { + /* use a flash based bbt */ + chip->options |= NAND_USE_FLASH_BBT; + } + + ret = s3c24x0_nand_inithw(host); + if (ret != 0) + goto on_error; + + /* Scan to find existence of the device */ + ret = nand_scan(mtd, 1); + if (ret != 0) { + ret = -ENXIO; + goto on_error; + } + + return add_mtd_device(mtd, "nand"); + +on_error: + free(host); + return ret; +} + +static struct driver_d s3c24x0_nand_driver = { + .name = "s3c24x0_nand", + .probe = s3c24x0_nand_probe, +}; + +#ifdef CONFIG_S3C_NAND_BOOT + +static void __nand_boot_init wait_for_completion(void __iomem *host) +{ + while (!(readw(host + NFSTAT) & NFSTAT_BUSY)) + ; +} + +/** + * Convert a page offset into a page address for the NAND + * @param host Where to write the address to + * @param offs Page's offset in the NAND + * @param ps Page size (512 or 2048) + * @param c Address cycle count (3, 4 or 5) + * + * Uses the offset of the page to generate an page address into the NAND. This + * differs when using a 512 byte or 2048 bytes per page NAND. + * The collumn part of the page address to be generated is always forced to '0'. + */ +static void __nand_boot_init nfc_addr(void __iomem *host, uint32_t offs, + int ps, int c) +{ + send_addr(host, 0); /* collumn part 1 */ + + if (ps == 512) { + send_addr(host, offs >> 9); + send_addr(host, offs >> 17); + if (c > 3) + send_addr(host, offs >> 25); + } else { + send_addr(host, 0); /* collumn part 2 */ + send_addr(host, offs >> 11); + send_addr(host, offs >> 19); + if (c > 4) + send_addr(host, offs >> 27); + send_cmd(host, NAND_CMD_READSTART); + } +} + +/** + * Load a sequential count of pages from the NAND into memory + * @param[out] dest Pointer to target area (in SDRAM) + * @param[in] size Bytes to read from NAND device + * @param[in] page Start page to read from + * + * This function must be located in the first 4kiB of the barebox image + * (guess why). + */ +void __nand_boot_init s3c_nand_load_image(void *dest, int size, int page) +{ + void __iomem *host = (void __iomem *)S3C24X0_NAND_BASE; + unsigned pagesize; + int i, cycle; + + /* + * Reenable the NFC and use the default (but slow) access + * timing or the board specific setting if provided. + */ + enable_nand_controller(host, BOARD_DEFAULT_NAND_TIMING); + + /* use the current NAND hardware configuration */ + switch (readl(S3C24X0_NAND_BASE) & 0xf) { + case 0x6: /* 8 bit, 4 addr cycles, 512 bpp, normal NAND */ + pagesize = 512; + cycle = 4; + break; + case 0xc: /* 8 bit, 4 addr cycles, 2048 bpp, advanced NAND */ + pagesize = 2048; + cycle = 4; + break; + case 0xe: /* 8 bit, 5 addr cycles, 2048 bpp, advanced NAND */ + pagesize = 2048; + cycle = 5; + break; + default: + /* we cannot output an error message here :-( */ + disable_nand_controller(host); + return; + } + + enable_cs(host); + + /* Reset the NAND device */ + send_cmd(host, NAND_CMD_RESET); + wait_for_completion(host); + disable_cs(host); + + do { + enable_cs(host); + send_cmd(host, NAND_CMD_READ0); + nfc_addr(host, page * pagesize, pagesize, cycle); + wait_for_completion(host); + /* copy one page (do *not* use readsb() here!)*/ + for (i = 0; i < pagesize; i++) + writeb(readb(host + NFDATA), (void __iomem *)(dest + i)); + disable_cs(host); + + page++; + dest += pagesize; + size -= pagesize; + } while (size >= 0); + + /* disable the controller again */ + disable_nand_controller(host); +} + +#ifdef CONFIG_NAND_S3C_BOOT_DEBUG +#include <command.h> + +static int do_nand_boot_test(int argc, char *argv[]) +{ + void *dest; + int size; + + if (argc < 3) + return COMMAND_ERROR_USAGE; + + dest = (void *)strtoul_suffix(argv[1], NULL, 0); + size = strtoul_suffix(argv[2], NULL, 0); + + s3c_nand_load_image(dest, size, 0); + + /* re-enable the controller again, as this was a test only */ + enable_nand_controller((void *)S3C24X0_NAND_BASE, + BOARD_DEFAULT_NAND_TIMING); + + return 0; +} + +static const __maybe_unused char cmd_nand_boot_test_help[] = +"Usage: nand_boot_test <dest> <size>\n"; + +BAREBOX_CMD_START(nand_boot_test) + .cmd = do_nand_boot_test, + .usage = "load an image from NAND", + BAREBOX_CMD_HELP(cmd_nand_boot_test_help) +BAREBOX_CMD_END +#endif + +#endif /* CONFIG_S3C_NAND_BOOT */ + +/* + * Main initialization routine + * @return 0 if successful; non-zero otherwise + */ +static int __init s3c24x0_nand_init(void) +{ + return register_driver(&s3c24x0_nand_driver); +} + +device_initcall(s3c24x0_nand_init); + +/** + * @file + * @brief Support for various kinds of NAND devices + * + * ECC handling in this driver (in accordance to the current 2.6.38 kernel): + * - for small page NANDs it generates 3 ECC bytes out of 512 data bytes + * - for large page NANDs it generates 24 ECC bytes out of 2048 data bytes + * + * As small page NANDs are using 48 bits ECC per default, this driver uses a + * local OOB layout description, to shrink it down to 24 bits. This is a bad + * idea, but we cannot change it here, as the kernel is using this layout. + * + * For large page NANDs this driver uses the default layout, as the kernel does. + */ diff --git a/drivers/mtd/nand/nand_s3c24xx.c b/drivers/mtd/nand/nand_s3c24xx.c deleted file mode 100644 index dbf2e14..0000000 --- a/drivers/mtd/nand/nand_s3c24xx.c +++ /dev/null @@ -1,665 +0,0 @@ -/* linux/drivers/mtd/nand/s3c2410.c - * - * Copyright (C) 2009 Juergen Beisert, Pengutronix - * - * Copyright © 2004-2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks <ben@xxxxxxxxxxxx> - * - * Samsung S3C2410 NAND driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include <config.h> -#include <common.h> -#include <driver.h> -#include <malloc.h> -#include <init.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/nand.h> -#include <mach/s3c-generic.h> -#include <mach/s3c-iomap.h> -#include <mach/s3c24xx-nand.h> -#include <io.h> -#include <asm-generic/errno.h> - -#ifdef CONFIG_S3C24XX_NAND_BOOT -# define __nand_boot_init __bare_init -# ifndef BOARD_DEFAULT_NAND_TIMING -# define BOARD_DEFAULT_NAND_TIMING 0x0737 -# endif -#else -# define __nand_boot_init -#endif - -/** - * Define this symbol for testing purpose. It will add a command to read an - * image from the NAND like it the boot strap code will do. - */ -#define CONFIG_NAND_S3C24XX_BOOT_DEBUG - -/* NAND controller's register */ - -#define NFCONF 0x00 - -#ifdef CONFIG_CPU_S3C2410 - -#define NFCMD 0x04 -#define NFADDR 0x08 -#define NFDATA 0x0c -#define NFSTAT 0x10 -#define NFECC 0x14 - -/* S3C2410 specific bits */ -#define NFSTAT_BUSY (1) -#define NFCONF_nFCE (1 << 11) -#define NFCONF_INITECC (1 << 12) -#define NFCONF_EN (1 << 15) - -#endif /* CONFIG_CPU_S3C2410 */ - -#ifdef CONFIG_CPU_S3C2440 - -#define NFCONT 0x04 -#define NFCMD 0x08 -#define NFADDR 0x0C -#define NFDATA 0x10 -#define NFSTAT 0x20 -#define NFECC 0x2C - -/* S3C2440 specific bits */ -#define NFSTAT_BUSY (1) -#define NFCONT_nFCE (1 << 1) -#define NFCONT_INITECC (1 << 4) -#define NFCONT_EN (1) - -#endif /* CONFIG_CPU_S3C2440 */ - - -struct s3c24x0_nand_host { - struct mtd_info mtd; - struct nand_chip nand; - struct mtd_partition *parts; - struct device_d *dev; - - void __iomem *base; -}; - -/** - * oob placement block for use with hardware ecc generation on small page - */ -static struct nand_ecclayout nand_hw_eccoob = { - .eccbytes = 3, - .eccpos = { 0, 1, 2}, - .oobfree = { - { - .offset = 8, - .length = 8 - } - } -}; - -/* - Functions shared between the boot strap code and the regular driver - */ - -/** - * Issue the specified command to the NAND device - * @param[in] host Base address of the NAND controller - * @param[in] cmd Command for NAND flash - */ -static void __nand_boot_init send_cmd(void __iomem *host, uint8_t cmd) -{ - writeb(cmd, host + NFCMD); -} - -/** - * Issue the specified address to the NAND device - * @param[in] host Base address of the NAND controller - * @param[in] addr Address for the NAND flash - */ -static void __nand_boot_init send_addr(void __iomem *host, uint8_t addr) -{ - writeb(addr, host + NFADDR); -} - -/** - * Enable the NAND flash access - * @param[in] host Base address of the NAND controller - */ -static void __nand_boot_init enable_cs(void __iomem *host) -{ -#ifdef CONFIG_CPU_S3C2410 - writew(readw(host + NFCONF) & ~NFCONF_nFCE, host + NFCONF); -#endif -#ifdef CONFIG_CPU_S3C2440 - writew(readw(host + NFCONT) & ~NFCONT_nFCE, host + NFCONT); -#endif -} - -/** - * Disable the NAND flash access - * @param[in] host Base address of the NAND controller - */ -static void __nand_boot_init disable_cs(void __iomem *host) -{ -#ifdef CONFIG_CPU_S3C2410 - writew(readw(host + NFCONF) | NFCONF_nFCE, host + NFCONF); -#endif -#ifdef CONFIG_CPU_S3C2440 - writew(readw(host + NFCONT) | NFCONT_nFCE, host + NFCONT); -#endif -} - -/** - * Enable the NAND flash controller - * @param[in] host Base address of the NAND controller - * @param[in] timing Timing to access the NAND memory - */ -static void __nand_boot_init enable_nand_controller(void __iomem *host, uint32_t timing) -{ -#ifdef CONFIG_CPU_S3C2410 - writew(timing + NFCONF_EN + NFCONF_nFCE, host + NFCONF); -#endif -#ifdef CONFIG_CPU_S3C2440 - writew(NFCONT_EN + NFCONT_nFCE, host + NFCONT); - writew(timing, host + NFCONF); -#endif -} - -/** - * Diable the NAND flash controller - * @param[in] host Base address of the NAND controller - */ -static void __nand_boot_init disable_nand_controller(void __iomem *host) -{ -#ifdef CONFIG_CPU_S3C2410 - writew(NFCONF_nFCE, host + NFCONF); -#endif -#ifdef CONFIG_CPU_S3C2440 - writew(NFCONT_nFCE, host + NFCONT); -#endif -} - -/* ----------------------------------------------------------------------- */ - -#ifdef CONFIG_CPU_S3C2440 -/** - * Read one block of data from the NAND port - * @param[in] mtd Instance data - * @param[out] buf buffer to write data to - * @param[in] len byte count - * - * This is a special block read variant for the S3C2440 CPU. - */ -static void s3c2440_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) -{ - struct nand_chip *nand_chip = mtd->priv; - struct s3c24x0_nand_host *host = nand_chip->priv; - - readsl(host->base + NFDATA, buf, len >> 2); - - /* cleanup any fractional read */ - if (len & 3) { - buf += len & ~3; - - for (; len & 3; len--) - *buf++ = readb(host->base + NFDATA); - } -} - -/** - * Write one block of data to the NAND port - * @param[in] mtd Instance data - * @param[out] buf buffer to read data from - * @param[in] len byte count - * - * This is a special block write variant for the S3C2440 CPU. - */ -static void s3c2440_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, - int len) -{ - struct nand_chip *nand_chip = mtd->priv; - struct s3c24x0_nand_host *host = nand_chip->priv; - - writesl(host->base + NFDATA, buf, len >> 2); - - /* cleanup any fractional write */ - if (len & 3) { - buf += len & ~3; - - for (; len & 3; len--, buf++) - writeb(*buf, host->base + NFDATA); - } -} -#endif - -/** - * Check the ECC and try to repair the data if possible - * @param[in] mtd_info Not used - * @param[inout] dat Pointer to the data buffer that might contain a bit error - * @param[in] read_ecc ECC data from the OOB space - * @param[in] calc_ecc ECC data calculated from the data - * @return 0 no error, 1 repaired error, -1 no way... - * - * @note: This routine works always on a 24 bit ECC - */ -static int s3c2410_nand_correct_data(struct mtd_info *mtd, uint8_t *dat, - uint8_t *read_ecc, uint8_t *calc_ecc) -{ - unsigned int diff0, diff1, diff2; - unsigned int bit, byte; - - diff0 = read_ecc[0] ^ calc_ecc[0]; - diff1 = read_ecc[1] ^ calc_ecc[1]; - diff2 = read_ecc[2] ^ calc_ecc[2]; - - if (diff0 == 0 && diff1 == 0 && diff2 == 0) - return 0; /* ECC is ok */ - - /* sometimes people do not think about using the ECC, so check - * to see if we have an 0xff,0xff,0xff read ECC and then ignore - * the error, on the assumption that this is an un-eccd page. - */ - if (read_ecc[0] == 0xff && read_ecc[1] == 0xff && read_ecc[2] == 0xff) - return 0; - - /* Can we correct this ECC (ie, one row and column change). - * Note, this is similar to the 256 error code on smartmedia */ - - if (((diff0 ^ (diff0 >> 1)) & 0x55) == 0x55 && - ((diff1 ^ (diff1 >> 1)) & 0x55) == 0x55 && - ((diff2 ^ (diff2 >> 1)) & 0x55) == 0x55) { - /* calculate the bit position of the error */ - - bit = ((diff2 >> 3) & 1) | - ((diff2 >> 4) & 2) | - ((diff2 >> 5) & 4); - - /* calculate the byte position of the error */ - - byte = ((diff2 << 7) & 0x100) | - ((diff1 << 0) & 0x80) | - ((diff1 << 1) & 0x40) | - ((diff1 << 2) & 0x20) | - ((diff1 << 3) & 0x10) | - ((diff0 >> 4) & 0x08) | - ((diff0 >> 3) & 0x04) | - ((diff0 >> 2) & 0x02) | - ((diff0 >> 1) & 0x01); - - dat[byte] ^= (1 << bit); - return 1; - } - - /* if there is only one bit difference in the ECC, then - * one of only a row or column parity has changed, which - * means the error is most probably in the ECC itself */ - - diff0 |= (diff1 << 8); - diff0 |= (diff2 << 16); - - if ((diff0 & ~(1<<fls(diff0))) == 0) - return 1; - - return -1; -} - -static void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode) -{ - struct nand_chip *nand_chip = mtd->priv; - struct s3c24x0_nand_host *host = nand_chip->priv; - -#ifdef CONFIG_CPU_S3C2410 - writel(readl(host->base + NFCONF) | NFCONF_INITECC , host->base + NFCONF); -#endif -#ifdef CONFIG_CPU_S3C2440 - writel(readl(host->base + NFCONT) | NFCONT_INITECC , host->base + NFCONT); -#endif -} - -static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code) -{ - struct nand_chip *nand_chip = mtd->priv; - struct s3c24x0_nand_host *host = nand_chip->priv; - -#ifdef CONFIG_CPU_S3C2410 - ecc_code[0] = readb(host->base + NFECC); - ecc_code[1] = readb(host->base + NFECC + 1); - ecc_code[2] = readb(host->base + NFECC + 2); -#endif -#ifdef CONFIG_CPU_S3C2440 - unsigned long ecc = readl(host->base + NFECC); - - ecc_code[0] = ecc; - ecc_code[1] = ecc >> 8; - ecc_code[2] = ecc >> 16; -#endif - return 0; -} - -static void s3c24x0_nand_select_chip(struct mtd_info *mtd, int chip) -{ - struct nand_chip *nand_chip = mtd->priv; - struct s3c24x0_nand_host *host = nand_chip->priv; - - if (chip == -1) - disable_cs(host->base); - else - enable_cs(host->base); -} - -static int s3c24x0_nand_devready(struct mtd_info *mtd) -{ - struct nand_chip *nand_chip = mtd->priv; - struct s3c24x0_nand_host *host = nand_chip->priv; - - return readw(host->base + NFSTAT) & NFSTAT_BUSY; -} - -static void s3c24x0_nand_hwcontrol(struct mtd_info *mtd, int cmd, - unsigned int ctrl) -{ - struct nand_chip *nand_chip = mtd->priv; - struct s3c24x0_nand_host *host = nand_chip->priv; - - if (cmd == NAND_CMD_NONE) - return; - /* - * If the CLE should be active, this call is a NAND command - */ - if (ctrl & NAND_CLE) - send_cmd(host->base, cmd); - /* - * If the ALE should be active, this call is a NAND address - */ - if (ctrl & NAND_ALE) - send_addr(host->base, cmd); -} - -static int s3c24x0_nand_inithw(struct s3c24x0_nand_host *host) -{ - struct s3c24x0_nand_platform_data *pdata = host->dev->platform_data; - uint32_t tmp; - - /* reset the NAND controller */ - disable_nand_controller(host->base); - - if (pdata != NULL) - tmp = pdata->nand_timing; - else - /* else slowest possible timing */ - tmp = CALC_NFCONF_TIMING(4, 8, 8); - - /* reenable the NAND controller */ - enable_nand_controller(host->base, tmp); - - return 0; -} - -static int s3c24x0_nand_probe(struct device_d *dev) -{ - struct nand_chip *chip; - struct s3c24x0_nand_platform_data *pdata = dev->platform_data; - struct mtd_info *mtd; - struct s3c24x0_nand_host *host; - int ret; - - /* Allocate memory for MTD device structure and private data */ - host = kzalloc(sizeof(struct s3c24x0_nand_host), GFP_KERNEL); - if (!host) - return -ENOMEM; - - host->dev = dev; - host->base = dev_request_mem_region(dev, 0); - - /* structures must be linked */ - chip = &host->nand; - mtd = &host->mtd; - mtd->priv = chip; - - /* init the default settings */ - - /* 50 us command delay time */ - chip->chip_delay = 50; - chip->priv = host; - - chip->IO_ADDR_R = chip->IO_ADDR_W = host->base + NFDATA; - -#ifdef CONFIG_CPU_S3C2440 - chip->read_buf = s3c2440_nand_read_buf; - chip->write_buf = s3c2440_nand_write_buf; -#endif - chip->cmd_ctrl = s3c24x0_nand_hwcontrol; - chip->dev_ready = s3c24x0_nand_devready; - chip->select_chip = s3c24x0_nand_select_chip; - - /* we are using the hardware ECC feature of this device */ - chip->ecc.calculate = s3c2410_nand_calculate_ecc; - chip->ecc.correct = s3c2410_nand_correct_data; - chip->ecc.hwctl = s3c2410_nand_enable_hwecc; - - /* - * Setup ECC handling in accordance to the kernel - * - 1 times 512 bytes with 24 bit ECC for small page - * - 8 times 256 bytes with 24 bit ECC each for large page - */ - chip->ecc.mode = NAND_ECC_HW; - chip->ecc.bytes = 3; /* always 24 bit ECC per turn */ -#ifdef CONFIG_CPU_S3C2440 - if (readl(host->base) & 0x8) { - /* large page (2048 bytes per page) */ - chip->ecc.size = 256; - } else -#endif - { - /* small page (512 bytes per page) */ - chip->ecc.size = 512; - chip->ecc.layout = &nand_hw_eccoob; - } - - if (pdata->flash_bbt) { - /* use a flash based bbt */ - chip->options |= NAND_USE_FLASH_BBT; - } - - ret = s3c24x0_nand_inithw(host); - if (ret != 0) - goto on_error; - - /* Scan to find existence of the device */ - ret = nand_scan(mtd, 1); - if (ret != 0) { - ret = -ENXIO; - goto on_error; - } - - return add_mtd_device(mtd, "nand"); - -on_error: - free(host); - return ret; -} - -static struct driver_d s3c24x0_nand_driver = { - .name = "s3c24x0_nand", - .probe = s3c24x0_nand_probe, -}; - -#ifdef CONFIG_S3C24XX_NAND_BOOT - -static void __nand_boot_init wait_for_completion(void __iomem *host) -{ - while (!(readw(host + NFSTAT) & NFSTAT_BUSY)) - ; -} - -/** - * Convert a page offset into a page address for the NAND - * @param host Where to write the address to - * @param offs Page's offset in the NAND - * @param ps Page size (512 or 2048) - * @param c Address cycle count (3, 4 or 5) - * - * Uses the offset of the page to generate an page address into the NAND. This - * differs when using a 512 byte or 2048 bytes per page NAND. - * The collumn part of the page address to be generated is always forced to '0'. - */ -static void __nand_boot_init nfc_addr(void __iomem *host, uint32_t offs, - int ps, int c) -{ - send_addr(host, 0); /* collumn part 1 */ - - if (ps == 512) { - send_addr(host, offs >> 9); - send_addr(host, offs >> 17); - if (c > 3) - send_addr(host, offs >> 25); - } else { - send_addr(host, 0); /* collumn part 2 */ - send_addr(host, offs >> 11); - send_addr(host, offs >> 19); - if (c > 4) - send_addr(host, offs >> 27); - send_cmd(host, NAND_CMD_READSTART); - } -} - -/** - * Load a sequential count of pages from the NAND into memory - * @param[out] dest Pointer to target area (in SDRAM) - * @param[in] size Bytes to read from NAND device - * @param[in] page Start page to read from - * - * This function must be located in the first 4kiB of the barebox image - * (guess why). - */ -void __nand_boot_init s3c24x0_nand_load_image(void *dest, int size, int page) -{ - void __iomem *host = (void __iomem *)S3C24X0_NAND_BASE; - unsigned pagesize; - int i, cycle; - - /* - * Reenable the NFC and use the default (but slow) access - * timing or the board specific setting if provided. - */ - enable_nand_controller(host, BOARD_DEFAULT_NAND_TIMING); - - /* use the current NAND hardware configuration */ - switch (readl(S3C24X0_NAND_BASE) & 0xf) { - case 0x6: /* 8 bit, 4 addr cycles, 512 bpp, normal NAND */ - pagesize = 512; - cycle = 4; - break; - case 0xc: /* 8 bit, 4 addr cycles, 2048 bpp, advanced NAND */ - pagesize = 2048; - cycle = 4; - break; - case 0xe: /* 8 bit, 5 addr cycles, 2048 bpp, advanced NAND */ - pagesize = 2048; - cycle = 5; - break; - default: - /* we cannot output an error message here :-( */ - disable_nand_controller(host); - return; - } - - enable_cs(host); - - /* Reset the NAND device */ - send_cmd(host, NAND_CMD_RESET); - wait_for_completion(host); - disable_cs(host); - - do { - enable_cs(host); - send_cmd(host, NAND_CMD_READ0); - nfc_addr(host, page * pagesize, pagesize, cycle); - wait_for_completion(host); - /* copy one page (do *not* use readsb() here!)*/ - for (i = 0; i < pagesize; i++) - writeb(readb(host + NFDATA), (void __iomem *)(dest + i)); - disable_cs(host); - - page++; - dest += pagesize; - size -= pagesize; - } while (size >= 0); - - /* disable the controller again */ - disable_nand_controller(host); -} - -#ifdef CONFIG_NAND_S3C24XX_BOOT_DEBUG -#include <command.h> - -static int do_nand_boot_test(int argc, char *argv[]) -{ - void *dest; - int size; - - if (argc < 3) - return COMMAND_ERROR_USAGE; - - dest = (void *)strtoul_suffix(argv[1], NULL, 0); - size = strtoul_suffix(argv[2], NULL, 0); - - s3c24x0_nand_load_image(dest, size, 0); - - /* re-enable the controller again, as this was a test only */ - enable_nand_controller((void *)S3C24X0_NAND_BASE, - BOARD_DEFAULT_NAND_TIMING); - - return 0; -} - -static const __maybe_unused char cmd_nand_boot_test_help[] = -"Usage: nand_boot_test <dest> <size>\n"; - -BAREBOX_CMD_START(nand_boot_test) - .cmd = do_nand_boot_test, - .usage = "load an image from NAND", - BAREBOX_CMD_HELP(cmd_nand_boot_test_help) -BAREBOX_CMD_END -#endif - -#endif /* CONFIG_S3C24XX_NAND_BOOT */ - -/* - * Main initialization routine - * @return 0 if successful; non-zero otherwise - */ -static int __init s3c24x0_nand_init(void) -{ - return register_driver(&s3c24x0_nand_driver); -} - -device_initcall(s3c24x0_nand_init); - -/** - * @file - * @brief Support for various kinds of NAND devices - * - * ECC handling in this driver (in accordance to the current 2.6.38 kernel): - * - for small page NANDs it generates 3 ECC bytes out of 512 data bytes - * - for large page NANDs it generates 24 ECC bytes out of 2048 data bytes - * - * As small page NANDs are using 48 bits ECC per default, this driver uses a - * local OOB layout description, to shrink it down to 24 bits. This is a bad - * idea, but we cannot change it here, as the kernel is using this layout. - * - * For large page NANDs this driver uses the default layout, as the kernel does. - */ diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 186b596..a9383da 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -80,7 +80,7 @@ config DRIVER_SERIAL_PL010 config DRIVER_SERIAL_S3C bool "Samsung S3C serial driver" - depends on ARCH_S3C24xx + depends on ARCH_SAMSUNG default y help Say Y here if you want to use the CONS on a Samsung S3C CPU -- 1.7.10 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox