diff options
author | Juergen Beisert <j.beisert@pengutronix.de> | 2009-06-23 15:46:15 +0200 |
---|---|---|
committer | Juergen Beisert <j.beisert@pengutronix.de> | 2009-07-01 14:36:40 +0200 |
commit | 5139e618b8d732bfbea69d9a9bdf83832de30472 (patch) | |
tree | 530f01f7b25071d0d8ab1a300060e6f9e15aae1b /arch/arm/mach-s3c24xx/generic.c | |
parent | 5d56a46c0aaaadb7eebc23ef7577a637610926f7 (diff) | |
download | barebox-5139e618b8d732bfbea69d9a9bdf83832de30472.tar.gz barebox-5139e618b8d732bfbea69d9a9bdf83832de30472.tar.xz |
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>
Diffstat (limited to 'arch/arm/mach-s3c24xx/generic.c')
-rw-r--r-- | arch/arm/mach-s3c24xx/generic.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/arch/arm/mach-s3c24xx/generic.c b/arch/arm/mach-s3c24xx/generic.c new file mode 100644 index 0000000000..864977d7b8 --- /dev/null +++ b/arch/arm/mach-s3c24xx/generic.c @@ -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 +*/ |