From be19bd5cd0f454b63298844a0b5377e029b2caad Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 19 Dec 2007 14:19:38 +0100 Subject: ARM: arm920/s3c24xx: IRQ demulitplexer callback This patch adds a IRQ demultiplexer callback to the arm920 cpu core code, plus a stub implementation of it for the S3C2410. The purpose is to allow arm920t implementations such as the s3c24x0 to implement interrupt handlers in u-boot without having to touch core arm920t code. Signed-off-by: Harald Welte --- cpu/arm920t/interrupts.c | 7 ++++++- cpu/arm920t/s3c24x0/interrupts.c | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'cpu/arm920t') diff --git a/cpu/arm920t/interrupts.c b/cpu/arm920t/interrupts.c index a43a3ed..0a6d94f 100644 --- a/cpu/arm920t/interrupts.c +++ b/cpu/arm920t/interrupts.c @@ -161,11 +161,16 @@ void do_fiq (struct pt_regs *pt_regs) void do_irq (struct pt_regs *pt_regs) { -#if defined (CONFIG_USE_IRQ) && defined (CONFIG_ARCH_INTEGRATOR) +#if defined (CONFIG_USE_IRQ) +#if defined (ARM920_IRQ_CALLBACK) + ARM920_IRQ_CALLBACK(); + return; +#elif defined (CONFIG_ARCH_INTEGRATOR) /* ASSUMED to be a timer interrupt */ /* Just clear it - count handled in */ /* integratorap.c */ *(volatile ulong *)(CFG_TIMERBASE + 0x0C) = 0; +#endif /* ARCH_INTEGRATOR */ #else printf ("interrupt request\n"); show_regs (pt_regs); diff --git a/cpu/arm920t/s3c24x0/interrupts.c b/cpu/arm920t/s3c24x0/interrupts.c index 1b36412..7ad9fcb 100644 --- a/cpu/arm920t/s3c24x0/interrupts.c +++ b/cpu/arm920t/s3c24x0/interrupts.c @@ -216,4 +216,13 @@ void reset_cpu (ulong ignored) /*NOTREACHED*/ } +#ifdef CONFIG_USE_IRQ +void s3c2410_irq(void) +{ + S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT(); + u_int32_t intpnd = irq->INTPND; + +} +#endif /* USE_IRQ */ + #endif /* defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) */ -- cgit v1.1 From a25f72f1f73a11de68251fb88c89991e202e68fa Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 19 Dec 2007 14:16:57 +0100 Subject: ARM: arm920t: Allow use of 'gd' pointer from IRQ This patch allows us to use the 'gd' pointer (and thus environment and everything else associated with it) from interrupt context on arm920t. Signed-off-by: Harald Welte --- cpu/arm920t/start.S | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'cpu/arm920t') diff --git a/cpu/arm920t/start.S b/cpu/arm920t/start.S index aefcdd1..ae86002 100644 --- a/cpu/arm920t/start.S +++ b/cpu/arm920t/start.S @@ -329,12 +329,12 @@ cpu_init_crit: .macro irq_save_user_regs sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0-r12 - add r8, sp, #S_PC - stmdb r8, {sp, lr}^ @ Calling SP, LR - str lr, [r8, #0] @ Save calling PC + add r7, sp, #S_PC + stmdb r7, {sp, lr}^ @ Calling SP, LR + str lr, [r7, #0] @ Save calling PC mrs r6, spsr - str r6, [r8, #4] @ Save CPSR - str r0, [r8, #8] @ Save OLD_R0 + str r6, [r7, #4] @ Save CPSR + str r0, [r7, #8] @ Save OLD_R0 mov r0, sp .endm -- cgit v1.1 From a7c185ed3d9f8ebd85cfc286e1ffee72e4803163 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 19 Dec 2007 14:24:40 +0100 Subject: ARM: s3c24xx: Multiple serial port support This patch adds support for CONFIG_SERIAL_MULTI on s3c24x0 CPU's Signed-off-by: Harald Welte --- cpu/arm920t/s3c24x0/serial.c | 164 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 143 insertions(+), 21 deletions(-) (limited to 'cpu/arm920t') diff --git a/cpu/arm920t/s3c24x0/serial.c b/cpu/arm920t/s3c24x0/serial.c index 36851ad..6e853b8 100644 --- a/cpu/arm920t/s3c24x0/serial.c +++ b/cpu/arm920t/s3c24x0/serial.c @@ -48,18 +48,74 @@ DECLARE_GLOBAL_DATA_PTR; #error "Bad: you didn't configure serial ..." #endif -void serial_setbrg (void) +#if defined(CONFIG_SERIAL_MULTI) +#include + +/* Multi serial device functions */ +#define DECLARE_S3C_SERIAL_FUNCTIONS(port) \ + int s3serial##port##_init (void) {\ + return serial_init_dev(port);}\ + void s3serial##port##_setbrg (void) {\ + serial_setbrg_dev(port);}\ + int s3serial##port##_getc (void) {\ + return serial_getc_dev(port);}\ + int s3serial##port##_tstc (void) {\ + return serial_tstc_dev(port);}\ + void s3serial##port##_putc (const char c) {\ + serial_putc_dev(port, c);}\ + void s3serial##port##_puts (const char *s) {\ + serial_puts_dev(port, s);} + +#define INIT_S3C_SERIAL_STRUCTURE(port,name,bus) {\ + name,\ + bus,\ + s3serial##port##_init,\ + s3serial##port##_setbrg,\ + s3serial##port##_getc,\ + s3serial##port##_tstc,\ + s3serial##port##_putc,\ + s3serial##port##_puts, } + +#endif /* CONFIG_SERIAL_MULTI */ + +void _serial_setbrg(const int dev_index) { - S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR); - int i; + S3C24X0_UART * const uart = S3C24X0_GetBase_UART(dev_index); unsigned int reg = 0; + int i; /* value is calculated so : (int)(PCLK/16./baudrate) -1 */ reg = get_PCLK() / (16 * gd->baudrate) - 1; + uart->UBRDIV = reg; + for (i = 0; i < 100; i++); +} +#if defined(CONFIG_SERIAL_MULTI) +static inline void +serial_setbrg_dev(unsigned int dev_index) +{ + _serial_setbrg(dev_index); +} +#else +void serial_setbrg(void) +{ + _serial_setbrg(UART_NR); +} +#endif + + +/* Initialise the serial port. The settings are always 8 data bits, no parity, + * 1 stop bit, no start bits. + */ +static int serial_init_dev(const int dev_index) +{ + S3C24X0_UART * const uart = S3C24X0_GetBase_UART(dev_index); + int i; + /* FIFO enable, Tx/Rx FIFO clear */ uart->UFCON = 0x07; uart->UMCON = 0x0; + /* Normal,No parity,1 stop,8 bit */ uart->ULCON = 0x3; /* @@ -67,40 +123,57 @@ void serial_setbrg (void) * normal,interrupt or polling */ uart->UCON = 0x245; - uart->UBRDIV = reg; #ifdef CONFIG_HWFLOW uart->UMCON = 0x1; /* RTS up */ #endif - for (i = 0; i < 100; i++); + + /* FIXME: This is sooooooooooooooooooo ugly */ +#if defined(CONFIG_ARCH_GTA02_v1) || defined(CONFIG_ARCH_GTA02_v2) + /* we need auto hw flow control on the gsm and gps port */ + if (dev_index == 0 || dev_index == 1) + uart->UMCON = 0x10; +#endif + _serial_setbrg(dev_index); + + return (0); } -/* - * Initialise the serial port with the given baudrate. The settings - * are always 8 data bits, no parity, 1 stop bit, no start bits. - * +#if !defined(CONFIG_SERIAL_MULTI) +/* Initialise the serial port. The settings are always 8 data bits, no parity, + * 1 stop bit, no start bits. */ int serial_init (void) { - serial_setbrg (); - - return (0); + return serial_init_dev(UART_NR); } +#endif /* * Read a single byte from the serial port. Returns 1 on success, 0 * otherwise. When the function is succesfull, the character read is * written into its argument c. */ -int serial_getc (void) +int _serial_getc (const int dev_index) { - S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR); + S3C24X0_UART * const uart = S3C24X0_GetBase_UART(dev_index); /* wait for character to arrive */ while (!(uart->UTRSTAT & 0x1)); return uart->URXH & 0xff; } +#if defined(CONFIG_SERIAL_MULTI) +static inline int serial_getc_dev(unsigned int dev_index) +{ + return _serial_getc(dev_index); +} +#else +int serial_getc (void) +{ + return _serial_getc(UART_NR); +} +#endif #ifdef CONFIG_HWFLOW static int hwflow = 0; /* turned off by default */ @@ -138,9 +211,9 @@ void enable_putc(void) /* * Output a single byte to the serial port. */ -void serial_putc (const char c) +void _serial_putc (const char c, const int dev_index) { - S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR); + S3C24X0_UART * const uart = S3C24X0_GetBase_UART(dev_index); #ifdef CONFIG_MODEM_SUPPORT if (be_quiet) return; @@ -161,23 +234,72 @@ void serial_putc (const char c) if (c == '\n') serial_putc ('\r'); } +#if defined(CONFIG_SERIAL_MULTI) +static inline void serial_putc_dev(unsigned int dev_index, const char c) +{ + _serial_putc(c, dev_index); +} +#else +void serial_putc(const char c) +{ + _serial_putc(c, UART_NR); +} +#endif + /* * Test whether a character is in the RX buffer */ -int serial_tstc (void) +int _serial_tstc(const int dev_index) { - S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR); + S3C24X0_UART * const uart = S3C24X0_GetBase_UART(dev_index); return uart->UTRSTAT & 0x1; } +#if defined(CONFIG_SERIAL_MULTI) +static inline int +serial_tstc_dev(unsigned int dev_index) +{ + return _serial_tstc(dev_index); +} +#else +int serial_tstc(void) +{ + return _serial_tstc(UART_NR); +} +#endif -void -serial_puts (const char *s) +void _serial_puts(const char *s, const int dev_index) { while (*s) { - serial_putc (*s++); + _serial_putc (*s++, dev_index); } } +#if defined(CONFIG_SERIAL_MULTI) +static inline void +serial_puts_dev(int dev_index, const char *s) +{ + _serial_puts(s, dev_index); +} +#else +void +serial_puts (const char *s) +{ + _serial_puts(s, UART_NR); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +DECLARE_S3C_SERIAL_FUNCTIONS(0); +struct serial_device s3c24xx_serial0_device = + INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0", "S3UART1"); +DECLARE_S3C_SERIAL_FUNCTIONS(1); +struct serial_device s3c24xx_serial1_device = + INIT_S3C_SERIAL_STRUCTURE(1, "s3ser1", "S3UART2"); +DECLARE_S3C_SERIAL_FUNCTIONS(2); +struct serial_device s3c24xx_serial2_device = + INIT_S3C_SERIAL_STRUCTURE(2, "s3ser2", "S3UART3"); + +#endif /* CONFIG_SERIAL_MULTI */ #endif /* defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) */ -- cgit v1.1 From 16158778b5f52f201e95ded2d2d9084b0ed5670d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 19 Dec 2007 15:10:52 +0100 Subject: ARM: S3C24x0 SoC NAND controller support This patch adds NAND support to the S3C24x0 SoC code in u-boot Signed-off-by: Harald Welte --- cpu/arm920t/s3c24x0/Makefile | 2 +- cpu/arm920t/s3c24x0/nand.c | 179 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 cpu/arm920t/s3c24x0/nand.c (limited to 'cpu/arm920t') diff --git a/cpu/arm920t/s3c24x0/Makefile b/cpu/arm920t/s3c24x0/Makefile index 1ed9bf3..6764920 100644 --- a/cpu/arm920t/s3c24x0/Makefile +++ b/cpu/arm920t/s3c24x0/Makefile @@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).a COBJS = i2c.o interrupts.o serial.o speed.o \ - usb.o usb_ohci.o + usb.o usb_ohci.o nand.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/arm920t/s3c24x0/nand.c b/cpu/arm920t/s3c24x0/nand.c new file mode 100644 index 0000000..e1bf128 --- /dev/null +++ b/cpu/arm920t/s3c24x0/nand.c @@ -0,0 +1,179 @@ +/* + * (C) Copyright 2006 OpenMoko, Inc. + * Author: Harald Welte + * + * 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 + +#if 0 +#define DEBUGN printf +#else +#define DEBUGN(x, args ...) {} +#endif + +#if defined(CONFIG_CMD_NAND) +#if !defined(CFG_NAND_LEGACY) + +#include +#include + +#define __REGb(x) (*(volatile unsigned char *)(x)) +#define __REGi(x) (*(volatile unsigned int *)(x)) + +#define NF_BASE 0x4e000000 +#define NFCONF __REGi(NF_BASE + 0x0) +#define NFCMD __REGb(NF_BASE + 0x4) +#define NFADDR __REGb(NF_BASE + 0x8) +#define NFDATA __REGb(NF_BASE + 0xc) +#define NFSTAT __REGb(NF_BASE + 0x10) +#define NFECC0 __REGb(NF_BASE + 0x14) +#define NFECC1 __REGb(NF_BASE + 0x15) +#define NFECC2 __REGb(NF_BASE + 0x16) + +#define S3C2410_NFCONF_EN (1<<15) +#define S3C2410_NFCONF_512BYTE (1<<14) +#define S3C2410_NFCONF_4STEP (1<<13) +#define S3C2410_NFCONF_INITECC (1<<12) +#define S3C2410_NFCONF_nFCE (1<<11) +#define S3C2410_NFCONF_TACLS(x) ((x)<<8) +#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4) +#define S3C2410_NFCONF_TWRPH1(x) ((x)<<0) + +static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip *chip = mtd->priv; + + DEBUGN("hwcontrol(): 0x%02x: ", cmd); + + switch (cmd) { + case NAND_CTL_SETNCE: + NFCONF &= ~S3C2410_NFCONF_nFCE; + DEBUGN("NFCONF=0x%08x\n", NFCONF); + break; + case NAND_CTL_CLRNCE: + NFCONF |= S3C2410_NFCONF_nFCE; + DEBUGN("NFCONF=0x%08x\n", NFCONF); + break; + case NAND_CTL_SETALE: + chip->IO_ADDR_W = NF_BASE + 0x8; + DEBUGN("SETALE\n"); + break; + case NAND_CTL_SETCLE: + chip->IO_ADDR_W = NF_BASE + 0x4; + DEBUGN("SETCLE\n"); + break; + default: + chip->IO_ADDR_W = NF_BASE + 0xc; + break; + } + return; +} + +static int s3c2410_dev_ready(struct mtd_info *mtd) +{ + DEBUGN("dev_ready\n"); + return (NFSTAT & 0x01); +} + +#ifdef CONFIG_S3C2410_NAND_HWECC +void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode) +{ + DEBUGN("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd ,mode); + NFCONF |= S3C2410_NFCONF_INITECC; +} + +static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, + u_char *ecc_code) +{ + ecc_code[0] = NFECC0; + ecc_code[1] = NFECC1; + ecc_code[2] = NFECC2; + DEBUGN("s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n", + mtd , ecc_code[0], ecc_code[1], ecc_code[2]); + + return 0; +} + +static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, + u_char *read_ecc, u_char *calc_ecc) +{ + if (read_ecc[0] == calc_ecc[0] && + read_ecc[1] == calc_ecc[1] && + read_ecc[2] == calc_ecc[2]) + return 0; + + printf("s3c2410_nand_correct_data: not implemented\n"); + return -1; +} +#endif + +int board_nand_init(struct nand_chip *nand) +{ + u_int32_t cfg; + u_int8_t tacls, twrph0, twrph1; + S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); + + DEBUGN("board_nand_init()\n"); + + clk_power->CLKCON |= (1 << 4); + + /* initialize hardware */ + twrph0 = 3; twrph1 = 0; tacls = 0; + + cfg = S3C2410_NFCONF_EN; + cfg |= S3C2410_NFCONF_TACLS(tacls - 1); + cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1); + cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1); + + NFCONF = cfg; + + /* initialize nand_chip data structure */ + nand->IO_ADDR_R = nand->IO_ADDR_W = 0x4e00000c; + + /* read_buf and write_buf are default */ + /* read_byte and write_byte are default */ + + /* hwcontrol always must be implemented */ + nand->hwcontrol = s3c2410_hwcontrol; + + nand->dev_ready = s3c2410_dev_ready; + +#ifdef CONFIG_S3C2410_NAND_HWECC + nand->enable_hwecc = s3c2410_nand_enable_hwecc; + nand->calculate_ecc = s3c2410_nand_calculate_ecc; + nand->correct_data = s3c2410_nand_correct_data; + nand->eccmode = NAND_ECC_HW3_512; +#else + nand->eccmode = NAND_ECC_SOFT; +#endif + +#ifdef CONFIG_S3C2410_NAND_BBT + nand->options = NAND_USE_FLASH_BBT; +#else + nand->options = 0; +#endif + + DEBUGN("end of nand_init\n"); + + return 0; +} + +#else + #error "U-Boot legacy NAND support not available for S3C2410" +#endif +#endif -- cgit v1.1