Add basic architecture support for Samsung's S3C2410 and S3C2440 CPU.
It includes a - driver for the internal UART - driver for the internal NAND controller - support to boot from NAND - PLL handling - SDRAM initialisation Signed-off-by: Juergen Beisert <j.beisert@pengutronix.de>
This commit is contained in:
parent
5d56a46c0a
commit
5139e618b8
|
@ -213,6 +213,7 @@ endchoice
|
|||
source arch/arm/mach-imx/Kconfig
|
||||
source arch/arm/mach-netx/Kconfig
|
||||
source arch/arm/mach-omap/Kconfig
|
||||
source arch/arm/mach-s3c24xx/Kconfig
|
||||
|
||||
menu "Arm specific settings "
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ machine-$(CONFIG_ARCH_NETX) := netx
|
|||
machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200
|
||||
machine-$(CONFIG_ARCH_OMAP) := omap
|
||||
machine-$(CONFIG_ARCH_AT91SAM9) := at91sam9
|
||||
machine-$(CONFIG_ARCH_S3C24xx) := s3c24xx
|
||||
board-$(CONFIG_MACH_MX1ADS) := mx1ads
|
||||
board-$(CONFIG_MACH_ECO920) := eco920
|
||||
board-$(CONFIG_MACH_SCB9328) := scb9328
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
config ARCH_S3C24xx
|
||||
bool
|
||||
select ARM920T
|
||||
|
||||
config CPU_S3C2410
|
||||
select ARCH_S3C24xx
|
||||
bool
|
||||
|
||||
config CPU_S3C2440
|
||||
select ARCH_S3C24xx
|
||||
bool
|
||||
|
||||
if ARCH_S3C24xx
|
||||
|
||||
menu "Board specific settings "
|
||||
endmenu
|
||||
|
||||
menu "S3C24X0 Features "
|
||||
|
||||
config S3C24XX_LOW_LEVEL_INIT
|
||||
bool
|
||||
|
||||
config S3C24XX_PLL_INIT
|
||||
bool
|
||||
prompt "Reconfigure PLL"
|
||||
select S3C24XX_LOW_LEVEL_INIT
|
||||
help
|
||||
This adds generic code to reconfigure the internal PLL very early
|
||||
after reset.
|
||||
|
||||
config S3C24XX_SDRAM_INIT
|
||||
bool
|
||||
prompt "Initialize SDRAM"
|
||||
select S3C24XX_LOW_LEVEL_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
|
||||
bool
|
||||
prompt "Booting from NAND"
|
||||
select NAND_S3C24X0
|
||||
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.
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
|
@ -0,0 +1,2 @@
|
|||
obj-y += generic.o
|
||||
obj-$(CONFIG_S3C24XX_LOW_LEVEL_INIT) += lowlevel-init.o
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* 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 and timer handling for S3C24xx CPUs
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <clock.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/s3c24x0-iomap.h>
|
||||
|
||||
/**
|
||||
* Calculate the current M-PLL clock.
|
||||
* @return Current frequency in Hz
|
||||
*/
|
||||
uint32_t s3c24xx_get_mpllclk(void)
|
||||
{
|
||||
uint32_t m, p, s, reg_val;
|
||||
|
||||
reg_val = readl(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 s3c24xx_get_upllclk(void)
|
||||
{
|
||||
uint32_t m, p, s, reg_val;
|
||||
|
||||
reg_val = readl(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 s3c24xx_get_fclk(void)
|
||||
{
|
||||
return s3c24xx_get_mpllclk();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the HCLK frequency used for the AHB bus (CPU to main peripheral)
|
||||
* @return Current frequency in Hz
|
||||
*/
|
||||
uint32_t s3c24xx_get_hclk(void)
|
||||
{
|
||||
uint32_t f_clk;
|
||||
|
||||
f_clk = s3c24xx_get_fclk();
|
||||
#ifdef CONFIG_CPU_S3C2410
|
||||
if (readl(CLKDIVN) & 0x02)
|
||||
return f_clk >> 1;
|
||||
#endif
|
||||
#ifdef CONFIG_CPU_S3C2440
|
||||
switch(readl(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 s3c24xx_get_pclk(void)
|
||||
{
|
||||
uint32_t p_clk;
|
||||
|
||||
p_clk = s3c24xx_get_hclk();
|
||||
if (readl(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 s3c24xx_get_uclk(void)
|
||||
{
|
||||
return s3c24xx_get_upllclk();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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", s3c24xx_get_mpllclk() / 1000);
|
||||
printf("upll: %7d kHz\n", s3c24xx_get_upllclk() / 1000);
|
||||
printf("fclk: %7d kHz\n", s3c24xx_get_fclk() / 1000);
|
||||
printf("hclk: %7d kHz\n", s3c24xx_get_hclk() / 1000);
|
||||
printf("pclk: %7d kHz\n", s3c24xx_get_pclk() / 1000);
|
||||
printf("SDRAM1: CL%d@%dMHz\n", ((readl(BANKCON6) & 0xc) >> 2) + 2, s3c24xx_get_hclk() / 1000000);
|
||||
if (!(readl(MISCCR) & (1 << 18)))
|
||||
printf("SDRAM2: CL%d@%dMHz\n", ((readl(BANKCON7) & 0xc) >> 2) + 2, s3c24xx_get_hclk() / 1000000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(s3c24xx_dump_clocks);
|
||||
|
||||
static uint64_t s3c24xx_clocksource_read(void)
|
||||
{
|
||||
/* note: its a down counter */
|
||||
return 0xFFFF - readw(TCNTO4);
|
||||
}
|
||||
|
||||
static struct clocksource cs = {
|
||||
.read = s3c24xx_clocksource_read,
|
||||
.mask = 0x0000ffff,
|
||||
.shift = 10,
|
||||
};
|
||||
|
||||
static int clocksource_init (void)
|
||||
{
|
||||
uint32_t p_clk = s3c24xx_get_pclk();
|
||||
|
||||
writel(0x00000000, TCON); /* stop all timers */
|
||||
writel(0x00ffffff, TCFG0); /* PCLK / (255 + 1) for timer 4 */
|
||||
writel(0x00030000, TCFG1); /* /16 */
|
||||
|
||||
writew(0xffff, TCNTB4); /* reload value is TOP */
|
||||
|
||||
writel(0x00600000, TCON); /* force a first reload */
|
||||
writel(0x00400000, TCON);
|
||||
writel(0x00500000, TCON); /* enable timer 4 with auto reload */
|
||||
|
||||
cs.mult = clocksource_hz2mult(p_clk / ((255 + 1) * 16), cs.shift);
|
||||
init_clock(&cs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
core_initcall(clocksource_init);
|
||||
|
||||
void reset_cpu(ulong addr)
|
||||
{
|
||||
/* Disable watchdog */
|
||||
writew(0x0000, WTCON);
|
||||
|
||||
/* Initialize watchdog timer count register */
|
||||
writew(0x0001, WTCNT);
|
||||
|
||||
/* Enable watchdog timer; assert reset at timer timeout */
|
||||
writew(0x0021, WTCON);
|
||||
|
||||
/* loop forever and wait for reset to happen */
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
EXPORT_SYMBOL(reset_cpu);
|
||||
|
||||
/**
|
||||
|
||||
@page dev_s3c24xx_arch Samsung's S3C24xx Platforms in U-Boot-v2
|
||||
|
||||
@section s3c24xx_boards Boards using S3C24xx Processors
|
||||
|
||||
@li @subpage board/a9m2410/a9m2410.c
|
||||
@li @subpage board/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 U-Boot-v2 Map
|
||||
|
||||
The location of the U-Boot-v2 itself depends on the available amount of
|
||||
installed SDRAM memory:
|
||||
|
||||
- 0x30fc.0000 Start of U-Boot-v2 when 16MiB SDRAM is available
|
||||
- 0x31fc.0000 Start of U-Boot-v2 when 32MiB SDRAM is available
|
||||
- 0x33fc.0000 Start of U-Boot-v2 when 64MiB SDRAM is available
|
||||
|
||||
Adjust the 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
|
||||
U-Boot-v2 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
|
||||
*/
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* (C) Copyright 2009
|
||||
* Juergen Beisert <kernel@pengutronix.de>
|
||||
*
|
||||
* 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 <asm/arch/s3c24x0-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, =S3C24X0_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, #S3C24X0_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, #S3C24X0_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. U-Boot-v2 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, #S3C24X0_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 U-Boot-v2 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 U-Boot-v2 should have no bit error.
|
||||
|
||||
Due to the fact the code to load the whole U-Boot-v2 from NAND must fit into
|
||||
the first 4kiB of the U-Boot-v2 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.
|
||||
|
||||
*/
|
|
@ -38,6 +38,13 @@ config NAND_ATMEL
|
|||
prompt "Atmel (AT91SAM9xxx) NAND driver"
|
||||
depends on ARCH_AT91SAM9
|
||||
|
||||
config NAND_S3C24X0
|
||||
bool
|
||||
prompt "Samsung S3C24X0 NAND driver"
|
||||
depends on ARCH_S3C24xx
|
||||
help
|
||||
Add support for processor's NAND device controller.
|
||||
|
||||
config MTD_NAND_VERIFY_WRITE
|
||||
bool "Verify NAND page writes"
|
||||
help
|
||||
|
|
|
@ -8,4 +8,5 @@ obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o
|
|||
obj-$(CONFIG_NAND_IMX) += nand_imx.o
|
||||
obj-$(CONFIG_NAND_OMAP_GPMC) += nand_omap_gpmc.o
|
||||
obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o
|
||||
obj-$(CONFIG_NAND_S3C24X0) += nand_s3c2410.o
|
||||
#obj-$(CONFIG_NAND) += nand_util.o
|
||||
|
|
|
@ -0,0 +1,528 @@
|
|||
/* 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@simtec.co.uk>
|
||||
*
|
||||
* 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 <asm/arch/s3c24xx-generic.h>
|
||||
#include <asm/arch/s3c24x0-iomap.h>
|
||||
#include <asm/arch/s3c24x0-nand.h>
|
||||
#include <asm/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 NFECC 0x1C
|
||||
#define NFSTAT 0x20
|
||||
|
||||
/* S3C2440 specific bits */
|
||||
#define NFSTAT_BUSY (1)
|
||||
#define NFCONT_nFCE (1 << 1)
|
||||
#define NFCONF_INITECC (1 << 12)
|
||||
#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;
|
||||
|
||||
unsigned long base;
|
||||
};
|
||||
|
||||
/**
|
||||
* oob placement block for use with hardware ecc generation
|
||||
*/
|
||||
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(unsigned long 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(unsigned long 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(unsigned long 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(unsigned long 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(unsigned long 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(unsigned long host)
|
||||
{
|
||||
#ifdef CONFIG_CPU_S3C2410
|
||||
writew(NFCONF_nFCE, host + NFCONF);
|
||||
#endif
|
||||
#ifdef CONFIG_CPU_S3C2440
|
||||
writew(NFCONT_nFCE, host + NFCONT);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Check the ECC and try to repair the data if possible
|
||||
* @param[in] mtd_info FIXME
|
||||
* @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: Alsways 512 byte of data
|
||||
*/
|
||||
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
|
||||
/* && info->platform->ignore_unset_ecc */)
|
||||
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;
|
||||
|
||||
writel(readl(host->base + NFCONF) | NFCONF_INITECC , host->base + NFCONF);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ecc_code[0] = readb(host->base + NFECC);
|
||||
ecc_code[1] = readb(host->base + NFECC + 1);
|
||||
ecc_code[2] = readb(host->base + NFECC + 2);
|
||||
|
||||
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 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->map_base;
|
||||
|
||||
/* structures must be linked */
|
||||
chip = &host->nand;
|
||||
mtd = &host->mtd;
|
||||
mtd->priv = chip;
|
||||
|
||||
/* init the default settings */
|
||||
#if 0
|
||||
/* TODO: Will follow later */
|
||||
init_nand_chip_bw8(chip);
|
||||
#endif
|
||||
/* 50 us command delay time */
|
||||
chip->chip_delay = 50;
|
||||
chip->priv = host;
|
||||
|
||||
chip->IO_ADDR_R = chip->IO_ADDR_W = (void*)(dev->map_base + NFDATA);
|
||||
|
||||
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;
|
||||
chip->ecc.calculate = s3c2410_nand_calculate_ecc;
|
||||
|
||||
/* our hardware capabilities */
|
||||
chip->ecc.mode = NAND_ECC_HW;
|
||||
chip->ecc.size = 512;
|
||||
chip->ecc.bytes = 3;
|
||||
chip->ecc.layout = &nand_hw_eccoob;
|
||||
|
||||
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);
|
||||
|
||||
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(unsigned long host)
|
||||
{
|
||||
while (!(readw(host + NFSTAT) & NFSTAT_BUSY))
|
||||
;
|
||||
}
|
||||
|
||||
static void __nand_boot_init nfc_addr(unsigned long host, uint32_t offs)
|
||||
{
|
||||
send_addr(host, offs & 0xff);
|
||||
send_addr(host, (offs >> 9) & 0xff);
|
||||
send_addr(host, (offs >> 17) & 0xff);
|
||||
send_addr(host, (offs >> 25) & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a sequential count of blocks 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
|
||||
* @param[in] pagesize Size of each page in the NAND
|
||||
*
|
||||
* This function must be located in the first 4kiB of the U-Boot-v2 image
|
||||
* (guess why). When this routine is running the SDRAM is up and running
|
||||
* and it runs from the correct address (physical=linked address).
|
||||
* TODO Could we access the platform data from the boardfile?
|
||||
* Due to it makes no sense this function does not return in case of failure.
|
||||
*/
|
||||
void __nand_boot_init s3c24x0_nand_load_image(void *dest, int size, int page, int pagesize)
|
||||
{
|
||||
unsigned long host = S3C24X0_NAND_BASE;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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);
|
||||
wait_for_completion(host);
|
||||
/* copy one page (do *not* use readsb() here!)*/
|
||||
for (i = 0; i < pagesize; i++)
|
||||
writeb(readb(host + NFDATA), (unsigned long)(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(cmd_tbl_t *cmdtp, int argc, char *argv[])
|
||||
{
|
||||
void *dest;
|
||||
int size, pagesize;
|
||||
|
||||
if (argc < 3) {
|
||||
u_boot_cmd_usage(cmdtp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dest = (void *)strtoul_suffix(argv[1], NULL, 0);
|
||||
size = strtoul_suffix(argv[2], NULL, 0);
|
||||
pagesize = strtoul_suffix(argv[3], NULL, 0);
|
||||
|
||||
s3c24x0_nand_load_image(dest, size, 0, pagesize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const __maybe_unused char cmd_nand_boot_test_help[] =
|
||||
"Usage: nand_boot_test <dest> <size> <pagesize>\n";
|
||||
|
||||
U_BOOT_CMD_START(nand_boot_test)
|
||||
.maxargs = CONFIG_MAXARGS,
|
||||
.cmd = do_nand_boot_test,
|
||||
.usage = "load an image from NAND",
|
||||
U_BOOT_CMD_HELP(cmd_nand_boot_test_help)
|
||||
U_BOOT_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);
|
|
@ -42,4 +42,19 @@ config DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS
|
|||
depends on ARCH_OMAP
|
||||
help
|
||||
Say Y here if you are using OMAP extensions to NS16550
|
||||
|
||||
config DRIVER_SERIAL_S3C24X0
|
||||
bool "Samsung S3C24X0 serial driver"
|
||||
depends on ARCH_S3C24xx
|
||||
default y
|
||||
help
|
||||
Say Y here if you want to use the CONS on a S3C24X0 CPU
|
||||
|
||||
config DRIVER_SERIAL_S3C24X0_AUTOSYNC
|
||||
bool "Enable auto flow"
|
||||
depends on DRIVER_SERIAL_S3C24X0
|
||||
help
|
||||
Say Y here if you want to use the auto flow feature of this
|
||||
UART. RTS and CTS will be handled by the hardware when enabled.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -12,3 +12,4 @@ obj-$(CONFIG_DRIVER_SERIAL_LINUX_COMSOLE) += linux_console.o
|
|||
obj-$(CONFIG_DRIVER_SERIAL_MPC5XXX) += serial_mpc5xxx.o
|
||||
obj-$(CONFIG_DRIVER_SERIAL_BLACKFIN) += serial_blackfin.o
|
||||
obj-$(CONFIG_DRIVER_SERIAL_NS16550) += serial_ns16550.o
|
||||
obj-$(CONFIG_DRIVER_SERIAL_S3C24X0) += serial_s3c24x0.o
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* (c) 2009 Juergen Beisert <j.beisert@saschahauer.de>
|
||||
*
|
||||
* Based on code from:
|
||||
* (c) 2004 Sascha Hauer <sascha@saschahauer.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <driver.h>
|
||||
#include <init.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/s3c24xx-generic.h>
|
||||
#include <asm/arch/s3c24x0-iomap.h>
|
||||
|
||||
/* Note: Offsets are for little endian access */
|
||||
#define ULCON 0x00 /* line control */
|
||||
#define UCON 0x04 /* UART control */
|
||||
#define UFCON 0x08 /* FIFO control */
|
||||
#define UMCON 0x0c /* modem control */
|
||||
#define UTRSTAT 0x10 /* Rx/Tx status */
|
||||
#define UERSTAT 0x14 /* error status */
|
||||
#define UFSTAT 0x18 /* FIFO status */
|
||||
#define UMSTAT 0x1c /* modem status */
|
||||
#define UTXH 0x20 /* transmitt */
|
||||
#define URXH 0x24 /* receive */
|
||||
#define UBRDIV 0x28 /* baudrate generator */
|
||||
|
||||
static int s3c24x0_serial_setbaudrate(struct console_device *cdev, int baudrate)
|
||||
{
|
||||
struct device_d *dev = cdev->dev;
|
||||
unsigned val;
|
||||
|
||||
/* value is calculated so : PCLK / (16 * baudrate) -1 */
|
||||
val = s3c24xx_get_pclk() / (16 * baudrate) - 1;
|
||||
writew(val, dev->map_base + UBRDIV);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c24x0_serial_init_port(struct console_device *cdev)
|
||||
{
|
||||
struct device_d *dev = cdev->dev;
|
||||
|
||||
/* FIFO enable, Tx/Rx FIFO clear */
|
||||
writeb(0x07, dev->map_base + UFCON);
|
||||
writeb(0x00, dev->map_base + UMCON);
|
||||
|
||||
/* Normal,No parity,1 stop,8 bit */
|
||||
writeb(0x03, dev->map_base + ULCON);
|
||||
/*
|
||||
* tx=level,rx=edge,disable timeout int.,enable rx error int.,
|
||||
* normal,interrupt or polling
|
||||
*/
|
||||
writew(0x0245, dev->map_base + UCON);
|
||||
|
||||
#ifdef CONFIG_DRIVER_SERIAL_S3C24X0_AUTOSYNC
|
||||
writeb(0x01, dev->map_base + UMCON); /* RTS up */
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void s3c24x0_serial_putc(struct console_device *cdev, char c)
|
||||
{
|
||||
struct device_d *dev = cdev->dev;
|
||||
|
||||
/* Wait for Tx FIFO not full */
|
||||
while (!(readb(dev->map_base + UTRSTAT) & 0x2))
|
||||
;
|
||||
|
||||
writeb(c, dev->map_base + UTXH);
|
||||
}
|
||||
|
||||
static int s3c24x0_serial_tstc(struct console_device *cdev)
|
||||
{
|
||||
struct device_d *dev = cdev->dev;
|
||||
|
||||
/* If receive fifo is empty, return false */
|
||||
if (readb(dev->map_base + UTRSTAT) & 0x1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c24x0_serial_getc(struct console_device *cdev)
|
||||
{
|
||||
struct device_d *dev = cdev->dev;
|
||||
|
||||
/* wait for a character */
|
||||
while (!(readb(dev->map_base + UTRSTAT) & 0x1))
|
||||
;
|
||||
|
||||
return readb(dev->map_base + URXH);
|
||||
}
|
||||
|
||||
static void s3c24x0_serial_flush(struct console_device *cdev)
|
||||
{
|
||||
struct device_d *dev = cdev->dev;
|
||||
|
||||
while (!readb(dev->map_base + UTRSTAT) & 0x4)
|
||||
;
|
||||
}
|
||||
|
||||
static int s3c24x0_serial_probe(struct device_d *dev)
|
||||
{
|
||||
struct console_device *cdev;
|
||||
|
||||
cdev = malloc(sizeof(struct console_device));
|
||||
|
||||
dev->type_data = cdev;
|
||||
cdev->dev = dev;
|
||||
cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
|
||||
cdev->tstc = s3c24x0_serial_tstc;
|
||||
cdev->putc = s3c24x0_serial_putc;
|
||||
cdev->getc = s3c24x0_serial_getc;
|
||||
cdev->flush = s3c24x0_serial_flush;
|
||||
cdev->setbrg = s3c24x0_serial_setbaudrate;
|
||||
|
||||
s3c24x0_serial_init_port(cdev);
|
||||
|
||||
/* Enable UART */
|
||||
console_register(cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void s3c24x0_serial_remove(struct device_d *dev)
|
||||
{
|
||||
struct console_device *cdev = dev->type_data;
|
||||
|
||||
s3c24x0_serial_flush(cdev);
|
||||
free(cdev);
|
||||
dev->type_data = NULL;
|
||||
}
|
||||
|
||||
static struct driver_d s3c24x0_serial_driver = {
|
||||
.name = "s3c24x0_serial",
|
||||
.probe = s3c24x0_serial_probe,
|
||||
.remove = s3c24x0_serial_remove,
|
||||
.type = DEVICE_TYPE_CONSOLE,
|
||||
};
|
||||
|
||||
static int s3c24x0_serial_init(void)
|
||||
{
|
||||
register_driver(&s3c24x0_serial_driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
console_initcall(s3c24x0_serial_init);
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* 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 S3C24X0_SDRAM_BASE 0x30000000
|
||||
#define S3C24X0_SDRAM_END 0x40000000
|
||||
#define S3C24X0_MEMCTL_BASE 0x48000000
|
||||
#define S3C2410_USB_HOST_BASE 0x49000000
|
||||
#define S3C2410_INTERRUPT_BASE 0x4A000000
|
||||
#define S3C2410_DMA_BASE 0x4B000000
|
||||
#define S3C24X0_CLOCK_POWER_BASE 0x4C000000
|
||||
#define S3C2410_LCD_BASE 0x4D000000
|
||||
#define S3C24X0_NAND_BASE 0x4E000000
|
||||
#define S3C24X0_UART_BASE 0x50000000
|
||||
#define S3C24X0_TIMER_BASE 0x51000000
|
||||
#define S3C2410_USB_DEVICE_BASE 0x52000140
|
||||
#define S3C24X0_WATCHDOG_BASE 0x53000000
|
||||
#define S3C2410_I2C_BASE 0x54000000
|
||||
#define S3C2410_I2S_BASE 0x55000000
|
||||
#define S3C24X0_GPIO_BASE 0x56000000
|
||||
#define S3C2410_RTC_BASE 0x57000000
|
||||
#define S3C2410_ADC_BASE 0x58000000
|
||||
#define S3C2410_SPI_BASE 0x59000000
|
||||
#define S3C2410_SDI_BASE 0x5A000000
|
||||
|
||||
/* Clock control (direct access) */
|
||||
|
||||
#define LOCKTIME (S3C24X0_CLOCK_POWER_BASE)
|
||||
#define MPLLCON (S3C24X0_CLOCK_POWER_BASE + 0x4)
|
||||
#define UPLLCON (S3C24X0_CLOCK_POWER_BASE + 0x8)
|
||||
#define CLKCON (S3C24X0_CLOCK_POWER_BASE + 0xc)
|
||||
#define CLKSLOW (S3C24X0_CLOCK_POWER_BASE + 0x10)
|
||||
#define CLKDIVN (S3C24X0_CLOCK_POWER_BASE + 0x14)
|
||||
|
||||
/* Timer (direct access) */
|
||||
#define TCFG0 (S3C24X0_TIMER_BASE + 0x00)
|
||||
#define TCFG1 (S3C24X0_TIMER_BASE + 0x04)
|
||||
#define TCON (S3C24X0_TIMER_BASE + 0x08)
|
||||
#define TCNTB0 (S3C24X0_TIMER_BASE + 0x0c)
|
||||
#define TCMPB0 (S3C24X0_TIMER_BASE + 0x10)
|
||||
#define TCNTO0 (S3C24X0_TIMER_BASE + 0x14)
|
||||
#define TCNTB1 (S3C24X0_TIMER_BASE + 0x18)
|
||||
#define TCMPB1 (S3C24X0_TIMER_BASE + 0x1c)
|
||||
#define TCNTO1 (S3C24X0_TIMER_BASE + 0x20)
|
||||
#define TCNTB2 (S3C24X0_TIMER_BASE + 0x24)
|
||||
#define TCMPB2 (S3C24X0_TIMER_BASE + 0x28)
|
||||
#define TCNTO2 (S3C24X0_TIMER_BASE + 0x2c)
|
||||
#define TCNTB3 (S3C24X0_TIMER_BASE + 0x30)
|
||||
#define TCMPB3 (S3C24X0_TIMER_BASE + 0x34)
|
||||
#define TCNTO3 (S3C24X0_TIMER_BASE + 0x38)
|
||||
#define TCNTB4 (S3C24X0_TIMER_BASE + 0x3c)
|
||||
#define TCNTO4 (S3C24X0_TIMER_BASE + 0x40)
|
||||
|
||||
/* Watchdog (direct access) */
|
||||
#define WTCON (S3C24X0_WATCHDOG_BASE)
|
||||
#define WTDAT (S3C24X0_WATCHDOG_BASE + 0x04)
|
||||
#define WTCNT (S3C24X0_WATCHDOG_BASE + 0x08)
|
||||
|
||||
/*
|
||||
* 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
|
||||
#endif
|
||||
#define NFC_RAM_SIZE 4096
|
||||
|
||||
/* internal UARTs (driver based) */
|
||||
#define UART1_BASE (S3C24X0_UART_BASE)
|
||||
#define UART1_SIZE 0x4000
|
||||
#define UART2_BASE (S3C24X0_UART_BASE + 0x4000)
|
||||
#define UART3_SIZE 0x4000
|
||||
#define UART3_BASE (S3C24X0_UART_BASE + 0x8000)
|
||||
#define UART3_SIZE 0x4000
|
||||
|
||||
/* CS configuration (direct access) */
|
||||
#define BWSCON (S3C24X0_MEMCTL_BASE)
|
||||
#define BANKCON0 (S3C24X0_MEMCTL_BASE + 0x04)
|
||||
#define BANKCON1 (S3C24X0_MEMCTL_BASE + 0x08)
|
||||
#define BANKCON2 (S3C24X0_MEMCTL_BASE + 0x0c)
|
||||
#define BANKCON3 (S3C24X0_MEMCTL_BASE + 0x10)
|
||||
#define BANKCON4 (S3C24X0_MEMCTL_BASE + 0x14)
|
||||
#define BANKCON5 (S3C24X0_MEMCTL_BASE + 0x18)
|
||||
#define BANKCON6 (S3C24X0_MEMCTL_BASE + 0x1c)
|
||||
#define BANKCON7 (S3C24X0_MEMCTL_BASE + 0x20)
|
||||
#define REFRESH (S3C24X0_MEMCTL_BASE + 0x24)
|
||||
#define BANKSIZE (S3C24X0_MEMCTL_BASE + 0x28)
|
||||
#define MRSRB6 (S3C24X0_MEMCTL_BASE + 0x2c)
|
||||
#define MRSRB7 (S3C24X0_MEMCTL_BASE + 0x30)
|
||||
|
||||
/* GPIO registers (direct access) */
|
||||
#define GPACON (S3C24X0_GPIO_BASE)
|
||||
#define GPADAT (S3C24X0_GPIO_BASE + 0x04)
|
||||
|
||||
#define GPBCON (S3C24X0_GPIO_BASE + 0x10)
|
||||
#define GPBDAT (S3C24X0_GPIO_BASE + 0x14)
|
||||
#define GPBUP (S3C24X0_GPIO_BASE + 0x18)
|
||||
|
||||
#define GPCCON (S3C24X0_GPIO_BASE + 0x20)
|
||||
#define GPCDAT (S3C24X0_GPIO_BASE + 0x24)
|
||||
#define GPCUP (S3C24X0_GPIO_BASE + 0x28)
|
||||
|
||||
#define GPDCON (S3C24X0_GPIO_BASE + 0x30)
|
||||
#define GPDDAT (S3C24X0_GPIO_BASE + 0x34)
|
||||
#define GPDUP (S3C24X0_GPIO_BASE + 0x38)
|
||||
|
||||
#define GPECON (S3C24X0_GPIO_BASE + 0x40)
|
||||
#define GPEDAT (S3C24X0_GPIO_BASE + 0x44)
|
||||
#define GPEUP (S3C24X0_GPIO_BASE + 0x48)
|
||||
|
||||
#define GPFCON (S3C24X0_GPIO_BASE + 0x50)
|
||||
#define GPFDAT (S3C24X0_GPIO_BASE + 0x54)
|
||||
#define GPFUP (S3C24X0_GPIO_BASE + 0x58)
|
||||
|
||||
#define GPGCON (S3C24X0_GPIO_BASE + 0x60)
|
||||
#define GPGDAT (S3C24X0_GPIO_BASE + 0x64)
|
||||
#define GPGUP (S3C24X0_GPIO_BASE + 0x68)
|
||||
|
||||
#define GPHCON (S3C24X0_GPIO_BASE + 0x70)
|
||||
#define GPHDAT (S3C24X0_GPIO_BASE + 0x74)
|
||||
#define GPHUP (S3C24X0_GPIO_BASE + 0x78)
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2440
|
||||
# define GPJCON (S3C24X0_GPIO_BASE + 0xd0)
|
||||
# define GPJDAT (S3C24X0_GPIO_BASE + 0xd4)
|
||||
# define GPJUP (S3C24X0_GPIO_BASE + 0xd8)
|
||||
#endif
|
||||
|
||||
#define MISCCR (S3C24X0_GPIO_BASE + 0x80)
|
||||
#define DCLKCON (S3C24X0_GPIO_BASE + 0x84)
|
||||
#define EXTINT0 (S3C24X0_GPIO_BASE + 0x88)
|
||||
#define EXTINT1 (S3C24X0_GPIO_BASE + 0x8c)
|
||||
#define EXTINT2 (S3C24X0_GPIO_BASE + 0x90)
|
||||
#define EINTFLT0 (S3C24X0_GPIO_BASE + 0x94)
|
||||
#define EINTFLT1 (S3C24X0_GPIO_BASE + 0x98)
|
||||
#define EINTFLT2 (S3C24X0_GPIO_BASE + 0x9c)
|
||||
#define EINTFLT3 (S3C24X0_GPIO_BASE + 0xa0)
|
||||
#define EINTMASK (S3C24X0_GPIO_BASE + 0xa4)
|
||||
#define EINTPEND (S3C24X0_GPIO_BASE + 0xa8)
|
||||
#define GSTATUS0 (S3C24X0_GPIO_BASE + 0xac)
|
||||
#define GSTATUS1 (S3C24X0_GPIO_BASE + 0xb0)
|
||||
#define GSTATUS2 (S3C24X0_GPIO_BASE + 0xb4)
|
||||
#define GSTATUS3 (S3C24X0_GPIO_BASE + 0xb8)
|
||||
#define GSTATUS4 (S3C24X0_GPIO_BASE + 0xbc)
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2440
|
||||
# define DSC0 (S3C24X0_GPIO_BASE + 0xc4)
|
||||
# define DSC1 (S3C24X0_GPIO_BASE + 0xc8)
|
||||
#endif
|
||||
|
||||
/* external IO space */
|
||||
#define CS0_BASE 0x00000000
|
||||
#define CS1_BASE 0x08000000
|
||||
#define CS2_BASE 0x10000000
|
||||
#define CS3_BASE 0x18000000
|
||||
#define CS4_BASE 0x20000000
|
||||
#define CS5_BASE 0x28000000
|
||||
#define CS6_BASE 0x30000000
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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, 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) */
|
||||
};
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Basic declaration to use the s3c24x0 NAND driver
|
||||
*/
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* (C) Copyright 2009
|
||||
* Juergen Beisert, Pengutronix
|
||||
*
|
||||
* (C) Copyright 2001-2004
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* David Mueller, ELSOFT AG, d.mueller@elsoft.ch
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
uint32_t s3c24xx_get_mpllclk(void);
|
||||
uint32_t s3c24xx_get_upllclk(void);
|
||||
uint32_t s3c24xx_get_fclk(void);
|
||||
uint32_t s3c24xx_get_hclk(void);
|
||||
uint32_t s3c24xx_get_pclk(void);
|
||||
uint32_t s3c24xx_get_uclk(void);
|
Loading…
Reference in New Issue