Skip to content

Commit

Permalink
[ARM] S3C6400: serial support for S3C6400 and S3C6410 SoCs
Browse files Browse the repository at this point in the history
Add support to the Samsung serial driver for the S3C6400
and S3C6410 serial ports.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
  • Loading branch information
Ben Dooks committed Dec 15, 2008
1 parent cf18acf commit b690ace
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 4 deletions.
2 changes: 2 additions & 0 deletions arch/arm/mach-s3c2410/include/mach/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,6 @@
#define S3C24XX_PA_SDI S3C2410_PA_SDI
#define S3C24XX_PA_NAND S3C2410_PA_NAND

#define S3C_PA_UART S3C24XX_PA_UART

#endif /* __ASM_ARCH_MAP_H */
2 changes: 2 additions & 0 deletions arch/arm/mach-s3c24a0/include/mach/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,6 @@
#define S3C24XX_PA_SDI S3C24A0_PA_SDI
#define S3C24XX_PA_NAND S3C24A0_PA_NAND

#define S3C_PA_UART S3C24A0_PA_UART

#endif /* __ASM_ARCH_24A0_MAP_H */
6 changes: 6 additions & 0 deletions arch/arm/plat-s3c/include/plat/regs-serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@
#define S3C2440_UCON_FCLK (3<<10)
#define S3C2443_UCON_EPLL (3<<10)

#define S3C6400_UCON_CLKMASK (3<<10)
#define S3C6400_UCON_PCLK (0<<10)
#define S3C6400_UCON_PCLK2 (2<<10)
#define S3C6400_UCON_UCLK0 (1<<10)
#define S3C6400_UCON_UCLK1 (3<<10)

#define S3C2440_UCON2_FCLK_EN (1<<15)
#define S3C2440_UCON0_DIVMASK (15 << 12)
#define S3C2440_UCON1_DIVMASK (15 << 12)
Expand Down
10 changes: 9 additions & 1 deletion drivers/serial/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ config SERIAL_CLPS711X_CONSOLE

config SERIAL_SAMSUNG
tristate "Samsung SoC serial support"
depends on ARM && PLAT_S3C24XX
depends on ARM && PLAT_S3C
select SERIAL_CORE
help
Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
Expand Down Expand Up @@ -515,6 +515,14 @@ config SERIAL_S3C24A0
help
Serial port support for the Samsung S3C24A0 SoC

config SERIAL_S3C6400
tristate "Samsung S3C6400/S3C6410 Serial port support"
depends on SERIAL_SAMSUNG && (CPU_S3C600 || CPU_S3C6410)
default y
help
Serial port support for the Samsung S3C6400 and S3C6410
SoCs

config SERIAL_DZ
bool "DECstation DZ serial driver"
depends on MACH_DECSTATION && 32BIT
Expand Down
1 change: 1 addition & 0 deletions drivers/serial/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
obj-$(CONFIG_SERIAL_MUX) += mux.o
obj-$(CONFIG_SERIAL_68328) += 68328serial.o
Expand Down
151 changes: 151 additions & 0 deletions drivers/serial/s3c6400.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/* linux/drivers/serial/s3c6400.c
*
* Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs.
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/serial.h>

#include <asm/irq.h>
#include <mach/hardware.h>

#include <plat/regs-serial.h>

#include "samsung.h"

static int s3c6400_serial_setsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);

if (strcmp(clk->name, "uclk0") == 0) {
ucon &= ~S3C6400_UCON_CLKMASK;
ucon |= S3C6400_UCON_UCLK0;
} else if (strcmp(clk->name, "uclk1") == 0)
ucon |= S3C6400_UCON_UCLK1;
else if (strcmp(clk->name, "pclk") == 0) {
/* See notes about transitioning from UCLK to PCLK */
ucon &= ~S3C6400_UCON_UCLK0;
} else {
printk(KERN_ERR "unknown clock source %s\n", clk->name);
return -EINVAL;
}

wr_regl(port, S3C2410_UCON, ucon);
return 0;
}


static int s3c6400_serial_getsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
u32 ucon = rd_regl(port, S3C2410_UCON);

clk->divisor = 1;

switch (ucon & S3C6400_UCON_CLKMASK) {
case S3C6400_UCON_UCLK0:
clk->name = "uclk0";
break;

case S3C6400_UCON_UCLK1:
clk->name = "uclk1";
break;

case S3C6400_UCON_PCLK:
case S3C6400_UCON_PCLK2:
clk->name = "pclk";
break;
}

return 0;
}

static int s3c6400_serial_resetport(struct uart_port *port,
struct s3c2410_uartcfg *cfg)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);

dbg("s3c6400_serial_resetport: port=%p (%08lx), cfg=%p\n",
port, port->mapbase, cfg);

/* ensure we don't change the clock settings... */

ucon &= S3C6400_UCON_CLKMASK;

wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
wr_regl(port, S3C2410_ULCON, cfg->ulcon);

/* reset both fifos */

wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
wr_regl(port, S3C2410_UFCON, cfg->ufcon);

return 0;
}

static struct s3c24xx_uart_info s3c6400_uart_inf = {
.name = "Samsung S3C6400 UART",
.type = PORT_S3C6400,
.fifosize = 64,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
.rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
.rx_fifofull = S3C2440_UFSTAT_RXFULL,
.tx_fifofull = S3C2440_UFSTAT_TXFULL,
.tx_fifomask = S3C2440_UFSTAT_TXMASK,
.tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
.get_clksrc = s3c6400_serial_getsource,
.set_clksrc = s3c6400_serial_setsource,
.reset_port = s3c6400_serial_resetport,
};

/* device management */

static int s3c6400_serial_probe(struct platform_device *dev)
{
dbg("s3c6400_serial_probe: dev=%p\n", dev);
return s3c24xx_serial_probe(dev, &s3c6400_uart_inf);
}

static struct platform_driver s3c6400_serial_drv = {
.probe = s3c6400_serial_probe,
.remove = s3c24xx_serial_remove,
.driver = {
.name = "s3c6400-uart",
.owner = THIS_MODULE,
},
};

s3c24xx_console_init(&s3c6400_serial_drv, &s3c6400_uart_inf);

static int __init s3c6400_serial_init(void)
{
return s3c24xx_serial_init(&s3c6400_serial_drv, &s3c6400_uart_inf);
}

static void __exit s3c6400_serial_exit(void)
{
platform_driver_unregister(&s3c6400_serial_drv);
}

module_init(s3c6400_serial_init);
module_exit(s3c6400_serial_exit);

MODULE_DESCRIPTION("Samsung S3C6400,S3C6410 SoC Serial port driver");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:s3c6400-uart");
8 changes: 5 additions & 3 deletions drivers/serial/samsung.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@
#include <asm/irq.h>

#include <mach/hardware.h>
#include <mach/map.h>

#include <plat/regs-serial.h>
#include <mach/regs-gpio.h>

#include "samsung.h"

Expand Down Expand Up @@ -756,6 +756,8 @@ static const char *s3c24xx_serial_type(struct uart_port *port)
return "S3C2440";
case PORT_S3C2412:
return "S3C2412";
case PORT_S3C6400:
return "S3C6400/10";
default:
return NULL;
}
Expand Down Expand Up @@ -1034,8 +1036,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,

dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);

port->mapbase = res->start;
port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
port->mapbase = res->start;
port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000);
ret = platform_get_irq(platdev, 0);
if (ret < 0)
port->irq = 0;
Expand Down
2 changes: 2 additions & 0 deletions include/linux/serial_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@
/* SH-SCI */
#define PORT_SCIFA 83

#define PORT_S3C6400 84

#ifdef __KERNEL__

#include <linux/compiler.h>
Expand Down

0 comments on commit b690ace

Please sign in to comment.