aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/serial/Kconfig15
-rw-r--r--drivers/serial/Makefile2
-rw-r--r--drivers/serial/s3c24a0.c118
-rw-r--r--drivers/serial/s3c6400.c151
-rw-r--r--drivers/serial/samsung.c55
-rw-r--r--drivers/serial/samsung.h3
6 files changed, 320 insertions, 24 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 579d63a81aa..e4ae499e587 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -447,7 +447,7 @@ config SERIAL_CLPS711X_CONSOLE
447 447
448config SERIAL_SAMSUNG 448config SERIAL_SAMSUNG
449 tristate "Samsung SoC serial support" 449 tristate "Samsung SoC serial support"
450 depends on ARM && PLAT_S3C24XX 450 depends on ARM && PLAT_S3C
451 select SERIAL_CORE 451 select SERIAL_CORE
452 help 452 help
453 Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, 453 Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
@@ -508,7 +508,20 @@ config SERIAL_S3C2440
508 help 508 help
509 Serial port support for the Samsung S3C2440 and S3C2442 SoC 509 Serial port support for the Samsung S3C2440 and S3C2442 SoC
510 510
511config SERIAL_S3C24A0
512 tristate "Samsung S3C24A0 Serial port support"
513 depends on SERIAL_SAMSUNG && CPU_S3C24A0
514 default y if CPU_S3C24A0
515 help
516 Serial port support for the Samsung S3C24A0 SoC
511 517
518config SERIAL_S3C6400
519 tristate "Samsung S3C6400/S3C6410 Serial port support"
520 depends on SERIAL_SAMSUNG && (CPU_S3C600 || CPU_S3C6410)
521 default y
522 help
523 Serial port support for the Samsung S3C6400 and S3C6410
524 SoCs
512 525
513config SERIAL_DZ 526config SERIAL_DZ
514 bool "DECstation DZ serial driver" 527 bool "DECstation DZ serial driver"
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 0c17c8ddb19..dfe775ac45b 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -41,6 +41,8 @@ obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o
41obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o 41obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
42obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o 42obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
43obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o 43obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
44obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
45obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
44obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o 46obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
45obj-$(CONFIG_SERIAL_MUX) += mux.o 47obj-$(CONFIG_SERIAL_MUX) += mux.o
46obj-$(CONFIG_SERIAL_68328) += 68328serial.o 48obj-$(CONFIG_SERIAL_68328) += 68328serial.o
diff --git a/drivers/serial/s3c24a0.c b/drivers/serial/s3c24a0.c
new file mode 100644
index 00000000000..ebf2fd3c8f7
--- /dev/null
+++ b/drivers/serial/s3c24a0.c
@@ -0,0 +1,118 @@
1/* linux/drivers/serial/s3c24a0.c
2 *
3 * Driver for Samsung S3C24A0 SoC onboard UARTs.
4 *
5 * Based on drivers/serial/s3c2410.c
6 *
7 * Author: Sandeep Patil <sandeep.patil@azingo.com>
8 *
9 * Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics
10 * http://armlinux.simtec.co.uk/
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15*/
16
17#include <linux/module.h>
18#include <linux/ioport.h>
19#include <linux/platform_device.h>
20#include <linux/init.h>
21#include <linux/serial_core.h>
22#include <linux/serial.h>
23#include <linux/io.h>
24#include <linux/irq.h>
25
26#include <mach/hardware.h>
27
28#include <plat/regs-serial.h>
29#include <mach/regs-gpio.h>
30
31#include "samsung.h"
32
33static int s3c24a0_serial_setsource(struct uart_port *port,
34 struct s3c24xx_uart_clksrc *clk)
35{
36 unsigned long ucon = rd_regl(port, S3C2410_UCON);
37
38 if (strcmp(clk->name, "uclk") == 0)
39 ucon |= S3C2410_UCON_UCLK;
40 else
41 ucon &= ~S3C2410_UCON_UCLK;
42
43 wr_regl(port, S3C2410_UCON, ucon);
44 return 0;
45}
46
47static int s3c24a0_serial_getsource(struct uart_port *port,
48 struct s3c24xx_uart_clksrc *clk)
49{
50 unsigned long ucon = rd_regl(port, S3C2410_UCON);
51
52 clk->divisor = 1;
53 clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk";
54
55 return 0;
56}
57
58static int s3c24a0_serial_resetport(struct uart_port *port,
59 struct s3c2410_uartcfg *cfg)
60{
61 dbg("s3c24a0_serial_resetport: port=%p (%08lx), cfg=%p\n",
62 port, port->mapbase, cfg);
63
64 wr_regl(port, S3C2410_UCON, cfg->ucon);
65 wr_regl(port, S3C2410_ULCON, cfg->ulcon);
66
67 /* reset both fifos */
68
69 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
70 wr_regl(port, S3C2410_UFCON, cfg->ufcon);
71
72 return 0;
73}
74
75static struct s3c24xx_uart_info s3c24a0_uart_inf = {
76 .name = "Samsung S3C24A0 UART",
77 .type = PORT_S3C2410,
78 .fifosize = 16,
79 .rx_fifomask = S3C24A0_UFSTAT_RXMASK,
80 .rx_fifoshift = S3C24A0_UFSTAT_RXSHIFT,
81 .rx_fifofull = S3C24A0_UFSTAT_RXFULL,
82 .tx_fifofull = S3C24A0_UFSTAT_TXFULL,
83 .tx_fifomask = S3C24A0_UFSTAT_TXMASK,
84 .tx_fifoshift = S3C24A0_UFSTAT_TXSHIFT,
85 .get_clksrc = s3c24a0_serial_getsource,
86 .set_clksrc = s3c24a0_serial_setsource,
87 .reset_port = s3c24a0_serial_resetport,
88};
89
90static int s3c24a0_serial_probe(struct platform_device *dev)
91{
92 return s3c24xx_serial_probe(dev, &s3c24a0_uart_inf);
93}
94
95static struct platform_driver s3c24a0_serial_drv = {
96 .probe = s3c24a0_serial_probe,
97 .remove = s3c24xx_serial_remove,
98 .driver = {
99 .name = "s3c24a0-uart",
100 .owner = THIS_MODULE,
101 },
102};
103
104s3c24xx_console_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf);
105
106static int __init s3c24a0_serial_init(void)
107{
108 return s3c24xx_serial_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf);
109}
110
111static void __exit s3c24a0_serial_exit(void)
112{
113 platform_driver_unregister(&s3c24a0_serial_drv);
114}
115
116module_init(s3c24a0_serial_init);
117module_exit(s3c24a0_serial_exit);
118
diff --git a/drivers/serial/s3c6400.c b/drivers/serial/s3c6400.c
new file mode 100644
index 00000000000..06936d13393
--- /dev/null
+++ b/drivers/serial/s3c6400.c
@@ -0,0 +1,151 @@
1/* linux/drivers/serial/s3c6400.c
2 *
3 * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs.
4 *
5 * Copyright 2008 Openmoko, Inc.
6 * Copyright 2008 Simtec Electronics
7 * Ben Dooks <ben@simtec.co.uk>
8 * http://armlinux.simtec.co.uk/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/module.h>
16#include <linux/ioport.h>
17#include <linux/io.h>
18#include <linux/platform_device.h>
19#include <linux/init.h>
20#include <linux/serial_core.h>
21#include <linux/serial.h>
22
23#include <asm/irq.h>
24#include <mach/hardware.h>
25
26#include <plat/regs-serial.h>
27
28#include "samsung.h"
29
30static int s3c6400_serial_setsource(struct uart_port *port,
31 struct s3c24xx_uart_clksrc *clk)
32{
33 unsigned long ucon = rd_regl(port, S3C2410_UCON);
34
35 if (strcmp(clk->name, "uclk0") == 0) {
36 ucon &= ~S3C6400_UCON_CLKMASK;
37 ucon |= S3C6400_UCON_UCLK0;
38 } else if (strcmp(clk->name, "uclk1") == 0)
39 ucon |= S3C6400_UCON_UCLK1;
40 else if (strcmp(clk->name, "pclk") == 0) {
41 /* See notes about transitioning from UCLK to PCLK */
42 ucon &= ~S3C6400_UCON_UCLK0;
43 } else {
44 printk(KERN_ERR "unknown clock source %s\n", clk->name);
45 return -EINVAL;
46 }
47
48 wr_regl(port, S3C2410_UCON, ucon);
49 return 0;
50}
51
52
53static int s3c6400_serial_getsource(struct uart_port *port,
54 struct s3c24xx_uart_clksrc *clk)
55{
56 u32 ucon = rd_regl(port, S3C2410_UCON);
57
58 clk->divisor = 1;
59
60 switch (ucon & S3C6400_UCON_CLKMASK) {
61 case S3C6400_UCON_UCLK0:
62 clk->name = "uclk0";
63 break;
64
65 case S3C6400_UCON_UCLK1:
66 clk->name = "uclk1";
67 break;
68
69 case S3C6400_UCON_PCLK:
70 case S3C6400_UCON_PCLK2:
71 clk->name = "pclk";
72 break;
73 }
74
75 return 0;
76}
77
78static int s3c6400_serial_resetport(struct uart_port *port,
79 struct s3c2410_uartcfg *cfg)
80{
81 unsigned long ucon = rd_regl(port, S3C2410_UCON);
82
83 dbg("s3c6400_serial_resetport: port=%p (%08lx), cfg=%p\n",
84 port, port->mapbase, cfg);
85
86 /* ensure we don't change the clock settings... */
87
88 ucon &= S3C6400_UCON_CLKMASK;
89
90 wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
91 wr_regl(port, S3C2410_ULCON, cfg->ulcon);
92
93 /* reset both fifos */
94
95 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
96 wr_regl(port, S3C2410_UFCON, cfg->ufcon);
97
98 return 0;
99}
100
101static struct s3c24xx_uart_info s3c6400_uart_inf = {
102 .name = "Samsung S3C6400 UART",
103 .type = PORT_S3C6400,
104 .fifosize = 64,
105 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
106 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
107 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
108 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
109 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
110 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
111 .get_clksrc = s3c6400_serial_getsource,
112 .set_clksrc = s3c6400_serial_setsource,
113 .reset_port = s3c6400_serial_resetport,
114};
115
116/* device management */
117
118static int s3c6400_serial_probe(struct platform_device *dev)
119{
120 dbg("s3c6400_serial_probe: dev=%p\n", dev);
121 return s3c24xx_serial_probe(dev, &s3c6400_uart_inf);
122}
123
124static struct platform_driver s3c6400_serial_drv = {
125 .probe = s3c6400_serial_probe,
126 .remove = s3c24xx_serial_remove,
127 .driver = {
128 .name = "s3c6400-uart",
129 .owner = THIS_MODULE,
130 },
131};
132
133s3c24xx_console_init(&s3c6400_serial_drv, &s3c6400_uart_inf);
134
135static int __init s3c6400_serial_init(void)
136{
137 return s3c24xx_serial_init(&s3c6400_serial_drv, &s3c6400_uart_inf);
138}
139
140static void __exit s3c6400_serial_exit(void)
141{
142 platform_driver_unregister(&s3c6400_serial_drv);
143}
144
145module_init(s3c6400_serial_init);
146module_exit(s3c6400_serial_exit);
147
148MODULE_DESCRIPTION("Samsung S3C6400,S3C6410 SoC Serial port driver");
149MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
150MODULE_LICENSE("GPL v2");
151MODULE_ALIAS("platform:s3c6400-uart");
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c
index ebeda832c8a..ba2e8685f9f 100644
--- a/drivers/serial/samsung.c
+++ b/drivers/serial/samsung.c
@@ -47,9 +47,9 @@
47#include <asm/irq.h> 47#include <asm/irq.h>
48 48
49#include <mach/hardware.h> 49#include <mach/hardware.h>
50#include <mach/map.h>
50 51
51#include <plat/regs-serial.h> 52#include <plat/regs-serial.h>
52#include <mach/regs-gpio.h>
53 53
54#include "samsung.h" 54#include "samsung.h"
55 55
@@ -61,17 +61,12 @@
61 61
62/* we can support 3 uarts, but not always use them */ 62/* we can support 3 uarts, but not always use them */
63 63
64#ifdef CONFIG_CPU_S3C2400 64#if defined(CONFIG_CPU_S3C2400) || defined(CONFIG_CPU_S3C24A0)
65#define NR_PORTS (2) 65#define NR_PORTS (2)
66#else 66#else
67#define NR_PORTS (3) 67#define NR_PORTS (3)
68#endif 68#endif
69 69
70/* port irq numbers */
71
72#define TX_IRQ(port) ((port)->irq + 1)
73#define RX_IRQ(port) ((port)->irq)
74
75/* macros to change one thing to another */ 70/* macros to change one thing to another */
76 71
77#define tx_enabled(port) ((port)->unused[0]) 72#define tx_enabled(port) ((port)->unused[0])
@@ -137,8 +132,10 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port)
137 132
138static void s3c24xx_serial_stop_tx(struct uart_port *port) 133static void s3c24xx_serial_stop_tx(struct uart_port *port)
139{ 134{
135 struct s3c24xx_uart_port *ourport = to_ourport(port);
136
140 if (tx_enabled(port)) { 137 if (tx_enabled(port)) {
141 disable_irq(TX_IRQ(port)); 138 disable_irq(ourport->tx_irq);
142 tx_enabled(port) = 0; 139 tx_enabled(port) = 0;
143 if (port->flags & UPF_CONS_FLOW) 140 if (port->flags & UPF_CONS_FLOW)
144 s3c24xx_serial_rx_enable(port); 141 s3c24xx_serial_rx_enable(port);
@@ -147,11 +144,13 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
147 144
148static void s3c24xx_serial_start_tx(struct uart_port *port) 145static void s3c24xx_serial_start_tx(struct uart_port *port)
149{ 146{
147 struct s3c24xx_uart_port *ourport = to_ourport(port);
148
150 if (!tx_enabled(port)) { 149 if (!tx_enabled(port)) {
151 if (port->flags & UPF_CONS_FLOW) 150 if (port->flags & UPF_CONS_FLOW)
152 s3c24xx_serial_rx_disable(port); 151 s3c24xx_serial_rx_disable(port);
153 152
154 enable_irq(TX_IRQ(port)); 153 enable_irq(ourport->tx_irq);
155 tx_enabled(port) = 1; 154 tx_enabled(port) = 1;
156 } 155 }
157} 156}
@@ -159,9 +158,11 @@ static void s3c24xx_serial_start_tx(struct uart_port *port)
159 158
160static void s3c24xx_serial_stop_rx(struct uart_port *port) 159static void s3c24xx_serial_stop_rx(struct uart_port *port)
161{ 160{
161 struct s3c24xx_uart_port *ourport = to_ourport(port);
162
162 if (rx_enabled(port)) { 163 if (rx_enabled(port)) {
163 dbg("s3c24xx_serial_stop_rx: port=%p\n", port); 164 dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
164 disable_irq(RX_IRQ(port)); 165 disable_irq(ourport->rx_irq);
165 rx_enabled(port) = 0; 166 rx_enabled(port) = 0;
166 } 167 }
167} 168}
@@ -385,13 +386,13 @@ static void s3c24xx_serial_shutdown(struct uart_port *port)
385 struct s3c24xx_uart_port *ourport = to_ourport(port); 386 struct s3c24xx_uart_port *ourport = to_ourport(port);
386 387
387 if (ourport->tx_claimed) { 388 if (ourport->tx_claimed) {
388 free_irq(TX_IRQ(port), ourport); 389 free_irq(ourport->tx_irq, ourport);
389 tx_enabled(port) = 0; 390 tx_enabled(port) = 0;
390 ourport->tx_claimed = 0; 391 ourport->tx_claimed = 0;
391 } 392 }
392 393
393 if (ourport->rx_claimed) { 394 if (ourport->rx_claimed) {
394 free_irq(RX_IRQ(port), ourport); 395 free_irq(ourport->rx_irq, ourport);
395 ourport->rx_claimed = 0; 396 ourport->rx_claimed = 0;
396 rx_enabled(port) = 0; 397 rx_enabled(port) = 0;
397 } 398 }
@@ -408,12 +409,11 @@ static int s3c24xx_serial_startup(struct uart_port *port)
408 409
409 rx_enabled(port) = 1; 410 rx_enabled(port) = 1;
410 411
411 ret = request_irq(RX_IRQ(port), 412 ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
412 s3c24xx_serial_rx_chars, 0,
413 s3c24xx_serial_portname(port), ourport); 413 s3c24xx_serial_portname(port), ourport);
414 414
415 if (ret != 0) { 415 if (ret != 0) {
416 printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port)); 416 printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);
417 return ret; 417 return ret;
418 } 418 }
419 419
@@ -423,12 +423,11 @@ static int s3c24xx_serial_startup(struct uart_port *port)
423 423
424 tx_enabled(port) = 1; 424 tx_enabled(port) = 1;
425 425
426 ret = request_irq(TX_IRQ(port), 426 ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,
427 s3c24xx_serial_tx_chars, 0,
428 s3c24xx_serial_portname(port), ourport); 427 s3c24xx_serial_portname(port), ourport);
429 428
430 if (ret) { 429 if (ret) {
431 printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port)); 430 printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq);
432 goto err; 431 goto err;
433 } 432 }
434 433
@@ -756,6 +755,8 @@ static const char *s3c24xx_serial_type(struct uart_port *port)
756 return "S3C2440"; 755 return "S3C2440";
757 case PORT_S3C2412: 756 case PORT_S3C2412:
758 return "S3C2412"; 757 return "S3C2412";
758 case PORT_S3C6400:
759 return "S3C6400/10";
759 default: 760 default:
760 return NULL; 761 return NULL;
761 } 762 }
@@ -1034,18 +1035,26 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
1034 1035
1035 dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); 1036 dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
1036 1037
1037 port->mapbase = res->start; 1038 port->mapbase = res->start;
1038 port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART); 1039 port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000);
1039 ret = platform_get_irq(platdev, 0); 1040 ret = platform_get_irq(platdev, 0);
1040 if (ret < 0) 1041 if (ret < 0)
1041 port->irq = 0; 1042 port->irq = 0;
1042 else 1043 else {
1043 port->irq = ret; 1044 port->irq = ret;
1045 ourport->rx_irq = ret;
1046 ourport->tx_irq = ret + 1;
1047 }
1048
1049 ret = platform_get_irq(platdev, 1);
1050 if (ret > 0)
1051 ourport->tx_irq = ret;
1044 1052
1045 ourport->clk = clk_get(&platdev->dev, "uart"); 1053 ourport->clk = clk_get(&platdev->dev, "uart");
1046 1054
1047 dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n", 1055 dbg("port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n",
1048 port->mapbase, port->membase, port->irq, port->uartclk); 1056 port->mapbase, port->membase, port->irq,
1057 ourport->rx_irq, ourport->tx_irq, port->uartclk);
1049 1058
1050 /* reset the fifos (and setup the uart) */ 1059 /* reset the fifos (and setup the uart) */
1051 s3c24xx_serial_resetport(port, cfg); 1060 s3c24xx_serial_resetport(port, cfg);
diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h
index be263423205..571d6b90d20 100644
--- a/drivers/serial/samsung.h
+++ b/drivers/serial/samsung.h
@@ -36,6 +36,9 @@ struct s3c24xx_uart_port {
36 unsigned int pm_level; 36 unsigned int pm_level;
37 unsigned long baudclk_rate; 37 unsigned long baudclk_rate;
38 38
39 unsigned int rx_irq;
40 unsigned int tx_irq;
41
39 struct s3c24xx_uart_info *info; 42 struct s3c24xx_uart_info *info;
40 struct s3c24xx_uart_clksrc *clksrc; 43 struct s3c24xx_uart_clksrc *clksrc;
41 struct clk *clk; 44 struct clk *clk;