summaryrefslogtreecommitdiff
path: root/cpu/arm920t/s3c24x0
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/arm920t/s3c24x0')
-rw-r--r--cpu/arm920t/s3c24x0/Makefile2
-rw-r--r--cpu/arm920t/s3c24x0/interrupts.c9
-rw-r--r--cpu/arm920t/s3c24x0/nand.c179
-rw-r--r--cpu/arm920t/s3c24x0/serial.c164
4 files changed, 332 insertions, 22 deletions
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/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) */
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 <laforge@openmoko.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if 0
+#define DEBUGN printf
+#else
+#define DEBUGN(x, args ...) {}
+#endif
+
+#if defined(CONFIG_CMD_NAND)
+#if !defined(CFG_NAND_LEGACY)
+
+#include <nand.h>
+#include <s3c2410.h>
+
+#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
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 <serial.h>
+
+/* 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) */