summaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorJuergen Beisert <j.beisert@pengutronix.de>2009-06-23 15:46:15 +0200
committerJuergen Beisert <j.beisert@pengutronix.de>2009-07-01 14:36:40 +0200
commit5139e618b8d732bfbea69d9a9bdf83832de30472 (patch)
tree530f01f7b25071d0d8ab1a300060e6f9e15aae1b /drivers/serial
parent5d56a46c0aaaadb7eebc23ef7577a637610926f7 (diff)
downloadbarebox-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 'drivers/serial')
-rw-r--r--drivers/serial/Kconfig15
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial_s3c24x0.c165
3 files changed, 181 insertions, 0 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index f6905b2afd..6acce19630 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -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
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index fc1e891739..3bc965c6e3 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -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
diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c24x0.c
new file mode 100644
index 0000000000..43a4cd2d47
--- /dev/null
+++ b/drivers/serial/serial_s3c24x0.c
@@ -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);