blob: 280c02af0eae68a8562cd08d4aca318aadcccd5f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
3 *
Paul Mundtf43dc232011-01-13 15:06:28 +09004 * Copyright (C) 2002 - 2011 Paul Mundt
Markus Brunner3ea6bc32007-08-20 08:59:33 +09005 * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007).
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 *
7 * based off of the old drivers/char/sh-sci.c by:
8 *
9 * Copyright (C) 1999, 2000 Niibe Yutaka
10 * Copyright (C) 2000 Sugioka Toshinobu
11 * Modified to support multiple serial ports. Stuart Menefy (May 2000).
12 * Modified to support SecureEdge. David McCullough (2002)
13 * Modified to support SH7300 SCIF. Takashi Kusuda (Jun 2003).
Magnus Dammd89ddd12007-07-25 11:42:56 +090014 * Removed SH7300 support (Jul 2007).
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 *
16 * This file is subject to the terms and conditions of the GNU General Public
17 * License. See the file "COPYING" in the main directory of this archive
18 * for more details.
19 */
Paul Mundt0b3d4ef2007-03-14 13:22:37 +090020#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
21#define SUPPORT_SYSRQ
22#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
24#undef DEBUG
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/module.h>
27#include <linux/errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/timer.h>
29#include <linux/interrupt.h>
30#include <linux/tty.h>
31#include <linux/tty_flip.h>
32#include <linux/serial.h>
33#include <linux/major.h>
34#include <linux/string.h>
35#include <linux/sysrq.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/ioport.h>
37#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <linux/init.h>
39#include <linux/delay.h>
40#include <linux/console.h>
Paul Mundte108b2c2006-09-27 16:32:13 +090041#include <linux/platform_device.h>
Paul Mundt96de1a82008-02-26 14:52:45 +090042#include <linux/serial_sci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/notifier.h>
Magnus Damm5e50d2d2011-04-19 10:38:25 +000044#include <linux/pm_runtime.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/cpufreq.h>
Paul Mundt85f094e2008-04-25 16:04:20 +090046#include <linux/clk.h>
Paul Mundtfa5da2f2007-03-08 17:27:37 +090047#include <linux/ctype.h>
Paul Mundt7ff731a2008-10-01 15:46:58 +090048#include <linux/err.h>
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +090049#include <linux/dmaengine.h>
50#include <linux/scatterlist.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090051#include <linux/slab.h>
Paul Mundt85f094e2008-04-25 16:04:20 +090052
53#ifdef CONFIG_SUPERH
Paul Mundte108b2c2006-09-27 16:32:13 +090054#include <asm/sh_bios.h>
Paul Mundtb7a76e42006-02-01 03:06:06 -080055#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#include "sh-sci.h"
58
Paul Mundte108b2c2006-09-27 16:32:13 +090059struct sci_port {
60 struct uart_port port;
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
Paul Mundtce6738b2011-01-19 15:24:40 +090062 /* Platform configuration */
63 struct plat_sci_port *cfg;
Paul Mundte108b2c2006-09-27 16:32:13 +090064
Paul Mundte108b2c2006-09-27 16:32:13 +090065 /* Port enable callback */
66 void (*enable)(struct uart_port *port);
67
68 /* Port disable callback */
69 void (*disable)(struct uart_port *port);
70
71 /* Break timer */
72 struct timer_list break_timer;
73 int break_flag;
dmitry pervushin1534a3b2007-04-24 13:41:12 +090074
Magnus Damm501b8252009-01-21 15:14:30 +000075 /* Interface clock */
76 struct clk *iclk;
Paul Mundtc7ed1ab2010-03-10 18:35:14 +090077 /* Function clock */
78 struct clk *fclk;
Paul Mundtedad1f22009-11-25 16:23:35 +090079
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +090080 struct dma_chan *chan_tx;
81 struct dma_chan *chan_rx;
Paul Mundtf43dc232011-01-13 15:06:28 +090082
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +090083#ifdef CONFIG_SERIAL_SH_SCI_DMA
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +090084 struct dma_async_tx_descriptor *desc_tx;
85 struct dma_async_tx_descriptor *desc_rx[2];
86 dma_cookie_t cookie_tx;
87 dma_cookie_t cookie_rx[2];
88 dma_cookie_t active_rx;
89 struct scatterlist sg_tx;
90 unsigned int sg_len_tx;
91 struct scatterlist sg_rx[2];
92 size_t buf_len_rx;
93 struct sh_dmae_slave param_tx;
94 struct sh_dmae_slave param_rx;
95 struct work_struct work_tx;
96 struct work_struct work_rx;
97 struct timer_list rx_timer;
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +000098 unsigned int rx_timeout;
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +090099#endif
Magnus Damme552de22009-01-21 15:13:42 +0000100
Paul Mundtd535a232011-01-19 17:19:35 +0900101 struct notifier_block freq_transition;
Paul Mundte108b2c2006-09-27 16:32:13 +0900102};
103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104/* Function prototypes */
Paul Mundtd535a232011-01-19 17:19:35 +0900105static void sci_start_tx(struct uart_port *port);
Russell Kingb129a8c2005-08-31 10:12:14 +0100106static void sci_stop_tx(struct uart_port *port);
Paul Mundtd535a232011-01-19 17:19:35 +0900107static void sci_start_rx(struct uart_port *port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Paul Mundte108b2c2006-09-27 16:32:13 +0900109#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
110
111static struct sci_port sci_ports[SCI_NPORTS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112static struct uart_driver sci_uart_driver;
113
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900114static inline struct sci_port *
115to_sci_port(struct uart_port *uart)
116{
117 return container_of(uart, struct sci_port, port);
118}
119
Paul Mundt07d2a1a2008-12-11 19:06:43 +0900120#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
Paul Mundt1f6fd5c2008-12-17 14:53:24 +0900121
122#ifdef CONFIG_CONSOLE_POLL
Paul Mundt07d2a1a2008-12-11 19:06:43 +0900123static int sci_poll_get_char(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 unsigned short status;
126 int c;
127
Paul Mundte108b2c2006-09-27 16:32:13 +0900128 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 status = sci_in(port, SCxSR);
130 if (status & SCxSR_ERRORS(port)) {
Paul Mundt94c8b6d2011-01-20 23:26:18 +0900131 sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 continue;
133 }
Jason Wessel3f255eb2010-05-20 21:04:23 -0500134 break;
135 } while (1);
136
137 if (!(status & SCxSR_RDxF(port)))
138 return NO_POLL_CHAR;
Paul Mundt07d2a1a2008-12-11 19:06:43 +0900139
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 c = sci_in(port, SCxRDR);
Paul Mundt07d2a1a2008-12-11 19:06:43 +0900141
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900142 /* Dummy read */
143 sci_in(port, SCxSR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
146 return c;
147}
Paul Mundt1f6fd5c2008-12-17 14:53:24 +0900148#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
Paul Mundt07d2a1a2008-12-11 19:06:43 +0900150static void sci_poll_put_char(struct uart_port *port, unsigned char c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 unsigned short status;
153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 do {
155 status = sci_in(port, SCxSR);
156 } while (!(status & SCxSR_TDxE(port)));
157
Paul Mundt272966c2008-11-13 17:46:06 +0900158 sci_out(port, SCxTDR, c);
SUGIOKA Toshinobudd0a3e72009-06-01 03:53:41 +0000159 sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160}
Paul Mundt07d2a1a2008-12-11 19:06:43 +0900161#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
Paul Mundtab7cfb52011-06-01 14:47:42 +0900163#if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
Paul Mundtd5701642008-12-16 20:07:27 +0900164static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
Paul Mundte108b2c2006-09-27 16:32:13 +0900165{
Paul Mundtd5701642008-12-16 20:07:27 +0900166 if (port->mapbase == 0xA4400000) {
167 __raw_writew(__raw_readw(PACR) & 0xffc0, PACR);
168 __raw_writew(__raw_readw(PBCR) & 0x0fff, PBCR);
169 } else if (port->mapbase == 0xA4410000)
170 __raw_writew(__raw_readw(PBCR) & 0xf003, PBCR);
Nobuhiro Iwamatsu9465a542007-03-27 18:13:51 +0900171}
Yoshihiro Shimoda31a49c42007-12-26 11:45:06 +0900172#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || defined(CONFIG_CPU_SUBTYPE_SH7721)
Paul Mundtd5701642008-12-16 20:07:27 +0900173static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
Markus Brunner3ea6bc32007-08-20 08:59:33 +0900174{
Markus Brunner3ea6bc32007-08-20 08:59:33 +0900175 unsigned short data;
176
177 if (cflag & CRTSCTS) {
178 /* enable RTS/CTS */
179 if (port->mapbase == 0xa4430000) { /* SCIF0 */
180 /* Clear PTCR bit 9-2; enable all scif pins but sck */
Paul Mundtd5701642008-12-16 20:07:27 +0900181 data = __raw_readw(PORT_PTCR);
182 __raw_writew((data & 0xfc03), PORT_PTCR);
Markus Brunner3ea6bc32007-08-20 08:59:33 +0900183 } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
184 /* Clear PVCR bit 9-2 */
Paul Mundtd5701642008-12-16 20:07:27 +0900185 data = __raw_readw(PORT_PVCR);
186 __raw_writew((data & 0xfc03), PORT_PVCR);
Markus Brunner3ea6bc32007-08-20 08:59:33 +0900187 }
Markus Brunner3ea6bc32007-08-20 08:59:33 +0900188 } else {
189 if (port->mapbase == 0xa4430000) { /* SCIF0 */
190 /* Clear PTCR bit 5-2; enable only tx and rx */
Paul Mundtd5701642008-12-16 20:07:27 +0900191 data = __raw_readw(PORT_PTCR);
192 __raw_writew((data & 0xffc3), PORT_PTCR);
Markus Brunner3ea6bc32007-08-20 08:59:33 +0900193 } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
194 /* Clear PVCR bit 5-2 */
Paul Mundtd5701642008-12-16 20:07:27 +0900195 data = __raw_readw(PORT_PVCR);
196 __raw_writew((data & 0xffc3), PORT_PVCR);
Markus Brunner3ea6bc32007-08-20 08:59:33 +0900197 }
198 }
Markus Brunner3ea6bc32007-08-20 08:59:33 +0900199}
Paul Mundtb7a76e42006-02-01 03:06:06 -0800200#elif defined(CONFIG_CPU_SH3)
Paul Mundte108b2c2006-09-27 16:32:13 +0900201/* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
Paul Mundtd5701642008-12-16 20:07:27 +0900202static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203{
Paul Mundtb7a76e42006-02-01 03:06:06 -0800204 unsigned short data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Paul Mundtb7a76e42006-02-01 03:06:06 -0800206 /* We need to set SCPCR to enable RTS/CTS */
Paul Mundtd5701642008-12-16 20:07:27 +0900207 data = __raw_readw(SCPCR);
Paul Mundtb7a76e42006-02-01 03:06:06 -0800208 /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
Paul Mundtd5701642008-12-16 20:07:27 +0900209 __raw_writew(data & 0x0fcf, SCPCR);
Paul Mundtb7a76e42006-02-01 03:06:06 -0800210
Paul Mundtd5701642008-12-16 20:07:27 +0900211 if (!(cflag & CRTSCTS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 /* We need to set SCPCR to enable RTS/CTS */
Paul Mundtd5701642008-12-16 20:07:27 +0900213 data = __raw_readw(SCPCR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 /* Clear out SCP7MD1,0, SCP4MD1,0,
215 Set SCP6MD1,0 = {01} (output) */
Paul Mundtd5701642008-12-16 20:07:27 +0900216 __raw_writew((data & 0x0fcf) | 0x1000, SCPCR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Paul Mundt32b53072009-12-24 14:52:43 +0900218 data = __raw_readb(SCPDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 /* Set /RTS2 (bit6) = 0 */
Paul Mundt32b53072009-12-24 14:52:43 +0900220 __raw_writeb(data & 0xbf, SCPDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222}
Paul Mundt41504c32006-12-11 20:28:03 +0900223#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
Paul Mundtd5701642008-12-16 20:07:27 +0900224static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
Paul Mundt41504c32006-12-11 20:28:03 +0900225{
Magnus Damm346b7462008-04-23 21:25:29 +0900226 unsigned short data;
Paul Mundt41504c32006-12-11 20:28:03 +0900227
Magnus Damm346b7462008-04-23 21:25:29 +0900228 if (port->mapbase == 0xffe00000) {
Paul Mundtd5701642008-12-16 20:07:27 +0900229 data = __raw_readw(PSCR);
Magnus Damm346b7462008-04-23 21:25:29 +0900230 data &= ~0x03cf;
Paul Mundtd5701642008-12-16 20:07:27 +0900231 if (!(cflag & CRTSCTS))
Magnus Damm346b7462008-04-23 21:25:29 +0900232 data |= 0x0340;
Paul Mundt41504c32006-12-11 20:28:03 +0900233
Paul Mundtd5701642008-12-16 20:07:27 +0900234 __raw_writew(data, PSCR);
Paul Mundt41504c32006-12-11 20:28:03 +0900235 }
Paul Mundt41504c32006-12-11 20:28:03 +0900236}
Yoshihiro Shimodac01f0f12009-08-21 16:30:28 +0900237#elif defined(CONFIG_CPU_SUBTYPE_SH7757) || \
238 defined(CONFIG_CPU_SUBTYPE_SH7763) || \
Yoshihiro Shimoda7d740a02008-01-07 14:40:07 +0900239 defined(CONFIG_CPU_SUBTYPE_SH7780) || \
Paul Mundt2b1bd1a2007-06-20 18:27:10 +0900240 defined(CONFIG_CPU_SUBTYPE_SH7785) || \
Kuninori Morimoto55ba99e2009-03-03 15:40:25 +0900241 defined(CONFIG_CPU_SUBTYPE_SH7786) || \
Paul Mundt2b1bd1a2007-06-20 18:27:10 +0900242 defined(CONFIG_CPU_SUBTYPE_SHX3)
Paul Mundtd5701642008-12-16 20:07:27 +0900243static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
244{
245 if (!(cflag & CRTSCTS))
246 __raw_writew(0x0080, SCSPTR0); /* Set RTS = 1 */
247}
Paul Mundtb0c50ad2008-12-22 03:40:10 +0900248#elif defined(CONFIG_CPU_SH4) && !defined(CONFIG_CPU_SH4A)
Paul Mundtd5701642008-12-16 20:07:27 +0900249static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
250{
251 if (!(cflag & CRTSCTS))
252 __raw_writew(0x0080, SCSPTR2); /* Set RTS = 1 */
253}
Paul Mundtb7a76e42006-02-01 03:06:06 -0800254#else
Paul Mundtd5701642008-12-16 20:07:27 +0900255static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
256{
257 /* Nothing to do */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258}
Paul Mundte108b2c2006-09-27 16:32:13 +0900259#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260
Paul Mundt32351a22007-03-12 14:38:59 +0900261#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
262 defined(CONFIG_CPU_SUBTYPE_SH7780) || \
Kuninori Morimoto55ba99e2009-03-03 15:40:25 +0900263 defined(CONFIG_CPU_SUBTYPE_SH7785) || \
264 defined(CONFIG_CPU_SUBTYPE_SH7786)
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900265static int scif_txfill(struct uart_port *port)
Paul Mundte108b2c2006-09-27 16:32:13 +0900266{
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900267 return sci_in(port, SCTFDR) & 0xff;
Paul Mundte108b2c2006-09-27 16:32:13 +0900268}
269
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900270static int scif_txroom(struct uart_port *port)
271{
272 return SCIF_TXROOM_MAX - scif_txfill(port);
273}
274
275static int scif_rxfill(struct uart_port *port)
Paul Mundte108b2c2006-09-27 16:32:13 +0900276{
Yutaro Ebiharacae167d2008-03-11 13:58:50 +0900277 return sci_in(port, SCRFDR) & 0xff;
Paul Mundte108b2c2006-09-27 16:32:13 +0900278}
Nobuhiro Iwamatsuc63847a2008-06-06 17:04:08 +0900279#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900280static int scif_txfill(struct uart_port *port)
Nobuhiro Iwamatsuc63847a2008-06-06 17:04:08 +0900281{
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900282 if (port->mapbase == 0xffe00000 ||
283 port->mapbase == 0xffe08000)
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900284 /* SCIF0/1*/
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900285 return sci_in(port, SCTFDR) & 0xff;
286 else
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900287 /* SCIF2 */
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900288 return sci_in(port, SCFDR) >> 8;
Nobuhiro Iwamatsuc63847a2008-06-06 17:04:08 +0900289}
290
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900291static int scif_txroom(struct uart_port *port)
292{
293 if (port->mapbase == 0xffe00000 ||
294 port->mapbase == 0xffe08000)
295 /* SCIF0/1*/
296 return SCIF_TXROOM_MAX - scif_txfill(port);
297 else
298 /* SCIF2 */
299 return SCIF2_TXROOM_MAX - scif_txfill(port);
300}
301
302static int scif_rxfill(struct uart_port *port)
Nobuhiro Iwamatsuc63847a2008-06-06 17:04:08 +0900303{
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900304 if ((port->mapbase == 0xffe00000) ||
305 (port->mapbase == 0xffe08000)) {
306 /* SCIF0/1*/
Nobuhiro Iwamatsuc63847a2008-06-06 17:04:08 +0900307 return sci_in(port, SCRFDR) & 0xff;
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900308 } else {
309 /* SCIF2 */
Nobuhiro Iwamatsuc63847a2008-06-06 17:04:08 +0900310 return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900311 }
Nobuhiro Iwamatsuc63847a2008-06-06 17:04:08 +0900312}
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +0000313#elif defined(CONFIG_ARCH_SH7372)
314static int scif_txfill(struct uart_port *port)
Paul Mundte108b2c2006-09-27 16:32:13 +0900315{
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +0000316 if (port->type == PORT_SCIFA)
317 return sci_in(port, SCFDR) >> 8;
318 else
319 return sci_in(port, SCTFDR);
Paul Mundte108b2c2006-09-27 16:32:13 +0900320}
321
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +0000322static int scif_txroom(struct uart_port *port)
323{
324 return port->fifosize - scif_txfill(port);
325}
326
327static int scif_rxfill(struct uart_port *port)
328{
329 if (port->type == PORT_SCIFA)
330 return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
331 else
332 return sci_in(port, SCRFDR);
333}
Paul Mundte108b2c2006-09-27 16:32:13 +0900334#else
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900335static int scif_txfill(struct uart_port *port)
Paul Mundte108b2c2006-09-27 16:32:13 +0900336{
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900337 return sci_in(port, SCFDR) >> 8;
Paul Mundte108b2c2006-09-27 16:32:13 +0900338}
339
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900340static int scif_txroom(struct uart_port *port)
341{
342 return SCIF_TXROOM_MAX - scif_txfill(port);
343}
344
345static int scif_rxfill(struct uart_port *port)
Paul Mundte108b2c2006-09-27 16:32:13 +0900346{
347 return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
348}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900351static int sci_txfill(struct uart_port *port)
Paul Mundte108b2c2006-09-27 16:32:13 +0900352{
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900353 return !(sci_in(port, SCxSR) & SCI_TDRE);
Paul Mundte108b2c2006-09-27 16:32:13 +0900354}
355
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900356static int sci_txroom(struct uart_port *port)
357{
358 return !sci_txfill(port);
359}
360
361static int sci_rxfill(struct uart_port *port)
Paul Mundte108b2c2006-09-27 16:32:13 +0900362{
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900363 return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
Paul Mundte108b2c2006-09-27 16:32:13 +0900364}
365
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366/* ********************************************************************** *
367 * the interrupt related routines *
368 * ********************************************************************** */
369
370static void sci_transmit_chars(struct uart_port *port)
371{
Alan Coxebd2c8f2009-09-19 13:13:28 -0700372 struct circ_buf *xmit = &port->state->xmit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 unsigned int stopped = uart_tx_stopped(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 unsigned short status;
375 unsigned short ctrl;
Paul Mundte108b2c2006-09-27 16:32:13 +0900376 int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
378 status = sci_in(port, SCxSR);
379 if (!(status & SCxSR_TDxE(port))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 ctrl = sci_in(port, SCSCR);
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900381 if (uart_circ_empty(xmit))
Paul Mundt8e698612009-06-24 19:44:32 +0900382 ctrl &= ~SCSCR_TIE;
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900383 else
Paul Mundt8e698612009-06-24 19:44:32 +0900384 ctrl |= SCSCR_TIE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 sci_out(port, SCSCR, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 return;
387 }
388
Yoshihiro Shimoda1a22f082008-11-11 12:19:05 +0900389 if (port->type == PORT_SCI)
Paul Mundte108b2c2006-09-27 16:32:13 +0900390 count = sci_txroom(port);
Yoshihiro Shimoda1a22f082008-11-11 12:19:05 +0900391 else
392 count = scif_txroom(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
394 do {
395 unsigned char c;
396
397 if (port->x_char) {
398 c = port->x_char;
399 port->x_char = 0;
400 } else if (!uart_circ_empty(xmit) && !stopped) {
401 c = xmit->buf[xmit->tail];
402 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
403 } else {
404 break;
405 }
406
407 sci_out(port, SCxTDR, c);
408
409 port->icount.tx++;
410 } while (--count > 0);
411
412 sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
413
414 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
415 uart_write_wakeup(port);
416 if (uart_circ_empty(xmit)) {
Russell Kingb129a8c2005-08-31 10:12:14 +0100417 sci_stop_tx(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 ctrl = sci_in(port, SCSCR);
420
Yoshihiro Shimoda1a22f082008-11-11 12:19:05 +0900421 if (port->type != PORT_SCI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 sci_in(port, SCxSR); /* Dummy read */
423 sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
424 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
Paul Mundt8e698612009-06-24 19:44:32 +0900426 ctrl |= SCSCR_TIE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 sci_out(port, SCSCR, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 }
429}
430
431/* On SH3, SCIF may read end-of-break as a space->mark char */
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900432#define STEPFN(c) ({int __c = (c); (((__c-1)|(__c)) == -1); })
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Paul Mundt94c8b6d2011-01-20 23:26:18 +0900434static void sci_receive_chars(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435{
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900436 struct sci_port *sci_port = to_sci_port(port);
Alan Coxebd2c8f2009-09-19 13:13:28 -0700437 struct tty_struct *tty = port->state->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 int i, count, copied = 0;
439 unsigned short status;
Alan Cox33f0f882006-01-09 20:54:13 -0800440 unsigned char flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
442 status = sci_in(port, SCxSR);
443 if (!(status & SCxSR_RDxF(port)))
444 return;
445
446 while (1) {
Yoshihiro Shimoda1a22f082008-11-11 12:19:05 +0900447 if (port->type == PORT_SCI)
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900448 count = sci_rxfill(port);
Yoshihiro Shimoda1a22f082008-11-11 12:19:05 +0900449 else
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900450 count = scif_rxfill(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
452 /* Don't copy more bytes than there is room for in the buffer */
Alan Cox33f0f882006-01-09 20:54:13 -0800453 count = tty_buffer_request_room(tty, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
455 /* If for any reason we can't copy more data, we're done! */
456 if (count == 0)
457 break;
458
459 if (port->type == PORT_SCI) {
460 char c = sci_in(port, SCxRDR);
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900461 if (uart_handle_sysrq_char(port, c) ||
462 sci_port->break_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 count = 0;
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900464 else
Paul Mundte108b2c2006-09-27 16:32:13 +0900465 tty_insert_flip_char(tty, c, TTY_NORMAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 } else {
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900467 for (i = 0; i < count; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 char c = sci_in(port, SCxRDR);
469 status = sci_in(port, SCxSR);
470#if defined(CONFIG_CPU_SH3)
471 /* Skip "chars" during break */
Paul Mundte108b2c2006-09-27 16:32:13 +0900472 if (sci_port->break_flag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 if ((c == 0) &&
474 (status & SCxSR_FER(port))) {
475 count--; i--;
476 continue;
477 }
Paul Mundte108b2c2006-09-27 16:32:13 +0900478
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 /* Nonzero => end-of-break */
Paul Mundt762c69e2008-12-16 18:55:26 +0900480 dev_dbg(port->dev, "debounce<%02x>\n", c);
Paul Mundte108b2c2006-09-27 16:32:13 +0900481 sci_port->break_flag = 0;
482
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 if (STEPFN(c)) {
484 count--; i--;
485 continue;
486 }
487 }
488#endif /* CONFIG_CPU_SH3 */
David Howells7d12e782006-10-05 14:55:46 +0100489 if (uart_handle_sysrq_char(port, c)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 count--; i--;
491 continue;
492 }
493
494 /* Store data and status */
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900495 if (status & SCxSR_FER(port)) {
Alan Cox33f0f882006-01-09 20:54:13 -0800496 flag = TTY_FRAME;
Paul Mundt762c69e2008-12-16 18:55:26 +0900497 dev_notice(port->dev, "frame error\n");
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900498 } else if (status & SCxSR_PER(port)) {
Alan Cox33f0f882006-01-09 20:54:13 -0800499 flag = TTY_PARITY;
Paul Mundt762c69e2008-12-16 18:55:26 +0900500 dev_notice(port->dev, "parity error\n");
Alan Cox33f0f882006-01-09 20:54:13 -0800501 } else
502 flag = TTY_NORMAL;
Paul Mundt762c69e2008-12-16 18:55:26 +0900503
Alan Cox33f0f882006-01-09 20:54:13 -0800504 tty_insert_flip_char(tty, c, flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 }
506 }
507
508 sci_in(port, SCxSR); /* dummy read */
509 sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
510
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 copied += count;
512 port->icount.rx += count;
513 }
514
515 if (copied) {
516 /* Tell the rest of the system the news. New characters! */
517 tty_flip_buffer_push(tty);
518 } else {
519 sci_in(port, SCxSR); /* dummy read */
520 sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
521 }
522}
523
524#define SCI_BREAK_JIFFIES (HZ/20)
Paul Mundt94c8b6d2011-01-20 23:26:18 +0900525
526/*
527 * The sci generates interrupts during the break,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 * 1 per millisecond or so during the break period, for 9600 baud.
529 * So dont bother disabling interrupts.
530 * But dont want more than 1 break event.
531 * Use a kernel timer to periodically poll the rx line until
532 * the break is finished.
533 */
Paul Mundt94c8b6d2011-01-20 23:26:18 +0900534static inline void sci_schedule_break_timer(struct sci_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535{
Paul Mundtbc9b3f52011-01-20 23:30:19 +0900536 mod_timer(&port->break_timer, jiffies + SCI_BREAK_JIFFIES);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537}
Paul Mundt94c8b6d2011-01-20 23:26:18 +0900538
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539/* Ensure that two consecutive samples find the break over. */
540static void sci_break_timer(unsigned long data)
541{
Paul Mundte108b2c2006-09-27 16:32:13 +0900542 struct sci_port *port = (struct sci_port *)data;
543
Magnus Damm5e50d2d2011-04-19 10:38:25 +0000544 if (port->enable)
545 port->enable(&port->port);
546
Paul Mundte108b2c2006-09-27 16:32:13 +0900547 if (sci_rxd_in(&port->port) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 port->break_flag = 1;
Paul Mundte108b2c2006-09-27 16:32:13 +0900549 sci_schedule_break_timer(port);
550 } else if (port->break_flag == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 /* break is over. */
552 port->break_flag = 2;
Paul Mundte108b2c2006-09-27 16:32:13 +0900553 sci_schedule_break_timer(port);
554 } else
555 port->break_flag = 0;
Magnus Damm5e50d2d2011-04-19 10:38:25 +0000556
557 if (port->disable)
558 port->disable(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559}
560
Paul Mundt94c8b6d2011-01-20 23:26:18 +0900561static int sci_handle_errors(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562{
563 int copied = 0;
564 unsigned short status = sci_in(port, SCxSR);
Alan Coxebd2c8f2009-09-19 13:13:28 -0700565 struct tty_struct *tty = port->state->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
Paul Mundte108b2c2006-09-27 16:32:13 +0900567 if (status & SCxSR_ORER(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 /* overrun error */
Paul Mundte108b2c2006-09-27 16:32:13 +0900569 if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
Alan Cox33f0f882006-01-09 20:54:13 -0800570 copied++;
Paul Mundt762c69e2008-12-16 18:55:26 +0900571
572 dev_notice(port->dev, "overrun error");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 }
574
Paul Mundte108b2c2006-09-27 16:32:13 +0900575 if (status & SCxSR_FER(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 if (sci_rxd_in(port) == 0) {
577 /* Notify of BREAK */
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900578 struct sci_port *sci_port = to_sci_port(port);
Paul Mundte108b2c2006-09-27 16:32:13 +0900579
580 if (!sci_port->break_flag) {
581 sci_port->break_flag = 1;
582 sci_schedule_break_timer(sci_port);
583
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 /* Do sysrq handling. */
Paul Mundte108b2c2006-09-27 16:32:13 +0900585 if (uart_handle_break(port))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 return 0;
Paul Mundt762c69e2008-12-16 18:55:26 +0900587
588 dev_dbg(port->dev, "BREAK detected\n");
589
Paul Mundte108b2c2006-09-27 16:32:13 +0900590 if (tty_insert_flip_char(tty, 0, TTY_BREAK))
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900591 copied++;
592 }
593
Paul Mundte108b2c2006-09-27 16:32:13 +0900594 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 /* frame error */
Paul Mundte108b2c2006-09-27 16:32:13 +0900596 if (tty_insert_flip_char(tty, 0, TTY_FRAME))
Alan Cox33f0f882006-01-09 20:54:13 -0800597 copied++;
Paul Mundt762c69e2008-12-16 18:55:26 +0900598
599 dev_notice(port->dev, "frame error\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 }
601 }
602
Paul Mundte108b2c2006-09-27 16:32:13 +0900603 if (status & SCxSR_PER(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 /* parity error */
Paul Mundte108b2c2006-09-27 16:32:13 +0900605 if (tty_insert_flip_char(tty, 0, TTY_PARITY))
606 copied++;
Paul Mundt762c69e2008-12-16 18:55:26 +0900607
608 dev_notice(port->dev, "parity error");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 }
610
Alan Cox33f0f882006-01-09 20:54:13 -0800611 if (copied)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
614 return copied;
615}
616
Paul Mundt94c8b6d2011-01-20 23:26:18 +0900617static int sci_handle_fifo_overrun(struct uart_port *port)
Paul Mundtd830fa42008-12-16 19:29:38 +0900618{
Alan Coxebd2c8f2009-09-19 13:13:28 -0700619 struct tty_struct *tty = port->state->port.tty;
Paul Mundtd830fa42008-12-16 19:29:38 +0900620 int copied = 0;
621
622 if (port->type != PORT_SCIF)
623 return 0;
624
625 if ((sci_in(port, SCLSR) & SCIF_ORER) != 0) {
626 sci_out(port, SCLSR, 0);
627
628 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
629 tty_flip_buffer_push(tty);
630
631 dev_notice(port->dev, "overrun error\n");
632 copied++;
633 }
634
635 return copied;
636}
637
Paul Mundt94c8b6d2011-01-20 23:26:18 +0900638static int sci_handle_breaks(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639{
640 int copied = 0;
641 unsigned short status = sci_in(port, SCxSR);
Alan Coxebd2c8f2009-09-19 13:13:28 -0700642 struct tty_struct *tty = port->state->port.tty;
Magnus Damma5660ad2009-01-21 15:14:38 +0000643 struct sci_port *s = to_sci_port(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Paul Mundt0b3d4ef2007-03-14 13:22:37 +0900645 if (uart_handle_break(port))
646 return 0;
647
Paul Mundtb7a76e42006-02-01 03:06:06 -0800648 if (!s->break_flag && status & SCxSR_BRK(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649#if defined(CONFIG_CPU_SH3)
650 /* Debounce break */
651 s->break_flag = 1;
652#endif
653 /* Notify of BREAK */
Paul Mundte108b2c2006-09-27 16:32:13 +0900654 if (tty_insert_flip_char(tty, 0, TTY_BREAK))
Alan Cox33f0f882006-01-09 20:54:13 -0800655 copied++;
Paul Mundt762c69e2008-12-16 18:55:26 +0900656
657 dev_dbg(port->dev, "BREAK detected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 }
659
Alan Cox33f0f882006-01-09 20:54:13 -0800660 if (copied)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 tty_flip_buffer_push(tty);
Paul Mundte108b2c2006-09-27 16:32:13 +0900662
Paul Mundtd830fa42008-12-16 19:29:38 +0900663 copied += sci_handle_fifo_overrun(port);
664
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 return copied;
666}
667
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900668static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669{
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900670#ifdef CONFIG_SERIAL_SH_SCI_DMA
671 struct uart_port *port = ptr;
672 struct sci_port *s = to_sci_port(port);
673
674 if (s->chan_rx) {
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900675 u16 scr = sci_in(port, SCSCR);
676 u16 ssr = sci_in(port, SCxSR);
677
678 /* Disable future Rx interrupts */
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +0000679 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +0000680 disable_irq_nosync(irq);
681 scr |= 0x4000;
682 } else {
Paul Mundtf43dc232011-01-13 15:06:28 +0900683 scr &= ~SCSCR_RIE;
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +0000684 }
685 sci_out(port, SCSCR, scr);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900686 /* Clear current interrupt */
687 sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +0000688 dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n",
689 jiffies, s->rx_timeout);
690 mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900691
692 return IRQ_HANDLED;
693 }
694#endif
695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 /* I think sci_receive_chars has to be called irrespective
697 * of whether the I_IXOFF is set, otherwise, how is the interrupt
698 * to be disabled?
699 */
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900700 sci_receive_chars(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
702 return IRQ_HANDLED;
703}
704
David Howells7d12e782006-10-05 14:55:46 +0100705static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
707 struct uart_port *port = ptr;
Stuart Menefyfd78a762009-07-29 23:01:24 +0900708 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Stuart Menefyfd78a762009-07-29 23:01:24 +0900710 spin_lock_irqsave(&port->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 sci_transmit_chars(port);
Stuart Menefyfd78a762009-07-29 23:01:24 +0900712 spin_unlock_irqrestore(&port->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
714 return IRQ_HANDLED;
715}
716
David Howells7d12e782006-10-05 14:55:46 +0100717static irqreturn_t sci_er_interrupt(int irq, void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718{
719 struct uart_port *port = ptr;
720
721 /* Handle errors */
722 if (port->type == PORT_SCI) {
723 if (sci_handle_errors(port)) {
724 /* discard character in rx buffer */
725 sci_in(port, SCxSR);
726 sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
727 }
728 } else {
Paul Mundtd830fa42008-12-16 19:29:38 +0900729 sci_handle_fifo_overrun(port);
David Howells7d12e782006-10-05 14:55:46 +0100730 sci_rx_interrupt(irq, ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 }
732
733 sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
734
735 /* Kick the transmission */
David Howells7d12e782006-10-05 14:55:46 +0100736 sci_tx_interrupt(irq, ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
738 return IRQ_HANDLED;
739}
740
David Howells7d12e782006-10-05 14:55:46 +0100741static irqreturn_t sci_br_interrupt(int irq, void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742{
743 struct uart_port *port = ptr;
744
745 /* Handle BREAKs */
746 sci_handle_breaks(port);
747 sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
748
749 return IRQ_HANDLED;
750}
751
Paul Mundtf43dc232011-01-13 15:06:28 +0900752static inline unsigned long port_rx_irq_mask(struct uart_port *port)
753{
754 /*
755 * Not all ports (such as SCIFA) will support REIE. Rather than
756 * special-casing the port type, we check the port initialization
757 * IRQ enable mask to see whether the IRQ is desired at all. If
758 * it's unset, it's logically inferred that there's no point in
759 * testing for it.
760 */
Paul Mundtce6738b2011-01-19 15:24:40 +0900761 return SCSCR_RIE | (to_sci_port(port)->cfg->scscr & SCSCR_REIE);
Paul Mundtf43dc232011-01-13 15:06:28 +0900762}
763
David Howells7d12e782006-10-05 14:55:46 +0100764static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765{
Magnus Damm44e18e92009-07-03 08:39:34 +0000766 unsigned short ssr_status, scr_status, err_enabled;
Michael Trimarchia8884e32008-10-31 16:10:23 +0900767 struct uart_port *port = ptr;
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900768 struct sci_port *s = to_sci_port(port);
Michael Trimarchia8884e32008-10-31 16:10:23 +0900769 irqreturn_t ret = IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770
Michael Trimarchie7c98dc2008-11-13 18:18:35 +0900771 ssr_status = sci_in(port, SCxSR);
772 scr_status = sci_in(port, SCSCR);
Paul Mundtf43dc232011-01-13 15:06:28 +0900773 err_enabled = scr_status & port_rx_irq_mask(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
775 /* Tx Interrupt */
Paul Mundtf43dc232011-01-13 15:06:28 +0900776 if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCSCR_TIE) &&
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900777 !s->chan_tx)
Michael Trimarchia8884e32008-10-31 16:10:23 +0900778 ret = sci_tx_interrupt(irq, ptr);
Paul Mundtf43dc232011-01-13 15:06:28 +0900779
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900780 /*
781 * Rx Interrupt: if we're using DMA, the DMA controller clears RDF /
782 * DR flags
783 */
784 if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) &&
Paul Mundtf43dc232011-01-13 15:06:28 +0900785 (scr_status & SCSCR_RIE))
Michael Trimarchia8884e32008-10-31 16:10:23 +0900786 ret = sci_rx_interrupt(irq, ptr);
Paul Mundtf43dc232011-01-13 15:06:28 +0900787
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 /* Error Interrupt */
SUGIOKA Toshinobudd4da3a2009-07-07 05:32:07 +0000789 if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled)
Michael Trimarchia8884e32008-10-31 16:10:23 +0900790 ret = sci_er_interrupt(irq, ptr);
Paul Mundtf43dc232011-01-13 15:06:28 +0900791
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 /* Break Interrupt */
SUGIOKA Toshinobudd4da3a2009-07-07 05:32:07 +0000793 if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
Michael Trimarchia8884e32008-10-31 16:10:23 +0900794 ret = sci_br_interrupt(irq, ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795
Michael Trimarchia8884e32008-10-31 16:10:23 +0900796 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797}
798
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799/*
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300800 * Here we define a transition notifier so that we can update all of our
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 * ports' baud rate when the peripheral clock changes.
802 */
Paul Mundte108b2c2006-09-27 16:32:13 +0900803static int sci_notifier(struct notifier_block *self,
804 unsigned long phase, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805{
Magnus Damme552de22009-01-21 15:13:42 +0000806 struct sci_port *sci_port;
807 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
Paul Mundtd535a232011-01-19 17:19:35 +0900809 sci_port = container_of(self, struct sci_port, freq_transition);
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 if ((phase == CPUFREQ_POSTCHANGE) ||
Magnus Damme552de22009-01-21 15:13:42 +0000812 (phase == CPUFREQ_RESUMECHANGE)) {
Paul Mundtd535a232011-01-19 17:19:35 +0900813 struct uart_port *port = &sci_port->port;
Paul Mundt073e84c2011-01-19 17:30:53 +0900814
Paul Mundtd535a232011-01-19 17:19:35 +0900815 spin_lock_irqsave(&port->lock, flags);
816 port->uartclk = clk_get_rate(sci_port->iclk);
817 spin_unlock_irqrestore(&port->lock, flags);
Magnus Damme552de22009-01-21 15:13:42 +0000818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 return NOTIFY_OK;
821}
Magnus Damm501b8252009-01-21 15:14:30 +0000822
823static void sci_clk_enable(struct uart_port *port)
824{
825 struct sci_port *sci_port = to_sci_port(port);
826
Magnus Damm5e50d2d2011-04-19 10:38:25 +0000827 pm_runtime_get_sync(port->dev);
828
Paul Mundtc7ed1ab2010-03-10 18:35:14 +0900829 clk_enable(sci_port->iclk);
830 sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
831 clk_enable(sci_port->fclk);
Magnus Damm501b8252009-01-21 15:14:30 +0000832}
833
834static void sci_clk_disable(struct uart_port *port)
835{
836 struct sci_port *sci_port = to_sci_port(port);
837
Paul Mundtc7ed1ab2010-03-10 18:35:14 +0900838 clk_disable(sci_port->fclk);
839 clk_disable(sci_port->iclk);
Magnus Damm5e50d2d2011-04-19 10:38:25 +0000840
841 pm_runtime_put_sync(port->dev);
Magnus Damm501b8252009-01-21 15:14:30 +0000842}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843
844static int sci_request_irq(struct sci_port *port)
845{
846 int i;
David Howells7d12e782006-10-05 14:55:46 +0100847 irqreturn_t (*handlers[4])(int irq, void *ptr) = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt,
849 sci_br_interrupt,
850 };
851 const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full",
852 "SCI Transmit Data Empty", "SCI Break" };
853
Paul Mundtce6738b2011-01-19 15:24:40 +0900854 if (port->cfg->irqs[0] == port->cfg->irqs[1]) {
855 if (unlikely(!port->cfg->irqs[0]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 return -ENODEV;
Paul Mundte108b2c2006-09-27 16:32:13 +0900857
Paul Mundtce6738b2011-01-19 15:24:40 +0900858 if (request_irq(port->cfg->irqs[0], sci_mpxed_interrupt,
Paul Mundt35f3c512006-10-06 15:31:16 +0900859 IRQF_DISABLED, "sci", port)) {
Paul Mundt762c69e2008-12-16 18:55:26 +0900860 dev_err(port->port.dev, "Can't allocate IRQ\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 return -ENODEV;
862 }
863 } else {
864 for (i = 0; i < ARRAY_SIZE(handlers); i++) {
Paul Mundtce6738b2011-01-19 15:24:40 +0900865 if (unlikely(!port->cfg->irqs[i]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 continue;
Paul Mundt762c69e2008-12-16 18:55:26 +0900867
Paul Mundtce6738b2011-01-19 15:24:40 +0900868 if (request_irq(port->cfg->irqs[i], handlers[i],
Paul Mundt35f3c512006-10-06 15:31:16 +0900869 IRQF_DISABLED, desc[i], port)) {
Paul Mundt762c69e2008-12-16 18:55:26 +0900870 dev_err(port->port.dev, "Can't allocate IRQ\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 return -ENODEV;
872 }
873 }
874 }
875
876 return 0;
877}
878
879static void sci_free_irq(struct sci_port *port)
880{
881 int i;
882
Paul Mundtce6738b2011-01-19 15:24:40 +0900883 if (port->cfg->irqs[0] == port->cfg->irqs[1])
884 free_irq(port->cfg->irqs[0], port);
Paul Mundt762c69e2008-12-16 18:55:26 +0900885 else {
Paul Mundtce6738b2011-01-19 15:24:40 +0900886 for (i = 0; i < ARRAY_SIZE(port->cfg->irqs); i++) {
887 if (!port->cfg->irqs[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 continue;
889
Paul Mundtce6738b2011-01-19 15:24:40 +0900890 free_irq(port->cfg->irqs[i], port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 }
892 }
893}
894
895static unsigned int sci_tx_empty(struct uart_port *port)
896{
Guennadi Liakhovetskib1516802009-12-01 09:54:46 +0000897 unsigned short status = sci_in(port, SCxSR);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900898 unsigned short in_tx_fifo = scif_txfill(port);
899
900 return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901}
902
903static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
904{
905 /* This routine is used for seting signals of: DTR, DCD, CTS/RTS */
906 /* We use SCIF's hardware for CTS/RTS, so don't need any for that. */
907 /* If you have signals for DTR and DCD, please implement here. */
908}
909
910static unsigned int sci_get_mctrl(struct uart_port *port)
911{
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900912 /* This routine is used for getting signals of: DTR, DCD, DSR, RI,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 and CTS/RTS */
914
915 return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR;
916}
917
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900918#ifdef CONFIG_SERIAL_SH_SCI_DMA
919static void sci_dma_tx_complete(void *arg)
920{
921 struct sci_port *s = arg;
922 struct uart_port *port = &s->port;
923 struct circ_buf *xmit = &port->state->xmit;
924 unsigned long flags;
925
926 dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
927
928 spin_lock_irqsave(&port->lock, flags);
929
Magnus Dammf354a382010-03-19 04:47:01 +0000930 xmit->tail += sg_dma_len(&s->sg_tx);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900931 xmit->tail &= UART_XMIT_SIZE - 1;
932
Magnus Dammf354a382010-03-19 04:47:01 +0000933 port->icount.tx += sg_dma_len(&s->sg_tx);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900934
935 async_tx_ack(s->desc_tx);
936 s->cookie_tx = -EINVAL;
937 s->desc_tx = NULL;
938
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900939 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
940 uart_write_wakeup(port);
941
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +0000942 if (!uart_circ_empty(xmit)) {
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900943 schedule_work(&s->work_tx);
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +0000944 } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +0000945 u16 ctrl = sci_in(port, SCSCR);
Paul Mundtf43dc232011-01-13 15:06:28 +0900946 sci_out(port, SCSCR, ctrl & ~SCSCR_TIE);
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +0000947 }
948
949 spin_unlock_irqrestore(&port->lock, flags);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900950}
951
952/* Locking: called with port lock held */
953static int sci_dma_rx_push(struct sci_port *s, struct tty_struct *tty,
954 size_t count)
955{
956 struct uart_port *port = &s->port;
957 int i, active, room;
958
959 room = tty_buffer_request_room(tty, count);
960
961 if (s->active_rx == s->cookie_rx[0]) {
962 active = 0;
963 } else if (s->active_rx == s->cookie_rx[1]) {
964 active = 1;
965 } else {
966 dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
967 return 0;
968 }
969
970 if (room < count)
971 dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
972 count - room);
973 if (!room)
974 return room;
975
976 for (i = 0; i < room; i++)
977 tty_insert_flip_char(tty, ((u8 *)sg_virt(&s->sg_rx[active]))[i],
978 TTY_NORMAL);
979
980 port->icount.rx += room;
981
982 return room;
983}
984
985static void sci_dma_rx_complete(void *arg)
986{
987 struct sci_port *s = arg;
988 struct uart_port *port = &s->port;
989 struct tty_struct *tty = port->state->port.tty;
990 unsigned long flags;
991 int count;
992
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +0000993 dev_dbg(port->dev, "%s(%d) active #%d\n", __func__, port->line, s->active_rx);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +0900994
995 spin_lock_irqsave(&port->lock, flags);
996
997 count = sci_dma_rx_push(s, tty, s->buf_len_rx);
998
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +0000999 mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001000
1001 spin_unlock_irqrestore(&port->lock, flags);
1002
1003 if (count)
1004 tty_flip_buffer_push(tty);
1005
1006 schedule_work(&s->work_rx);
1007}
1008
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001009static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
1010{
1011 struct dma_chan *chan = s->chan_rx;
1012 struct uart_port *port = &s->port;
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001013
1014 s->chan_rx = NULL;
1015 s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
1016 dma_release_channel(chan);
Guennadi Liakhovetski85b8e3f2010-05-21 15:22:40 +00001017 if (sg_dma_address(&s->sg_rx[0]))
1018 dma_free_coherent(port->dev, s->buf_len_rx * 2,
1019 sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0]));
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001020 if (enable_pio)
1021 sci_start_rx(port);
1022}
1023
1024static void sci_tx_dma_release(struct sci_port *s, bool enable_pio)
1025{
1026 struct dma_chan *chan = s->chan_tx;
1027 struct uart_port *port = &s->port;
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001028
1029 s->chan_tx = NULL;
1030 s->cookie_tx = -EINVAL;
1031 dma_release_channel(chan);
1032 if (enable_pio)
1033 sci_start_tx(port);
1034}
1035
1036static void sci_submit_rx(struct sci_port *s)
1037{
1038 struct dma_chan *chan = s->chan_rx;
1039 int i;
1040
1041 for (i = 0; i < 2; i++) {
1042 struct scatterlist *sg = &s->sg_rx[i];
1043 struct dma_async_tx_descriptor *desc;
1044
1045 desc = chan->device->device_prep_slave_sg(chan,
1046 sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT);
1047
1048 if (desc) {
1049 s->desc_rx[i] = desc;
1050 desc->callback = sci_dma_rx_complete;
1051 desc->callback_param = s;
1052 s->cookie_rx[i] = desc->tx_submit(desc);
1053 }
1054
1055 if (!desc || s->cookie_rx[i] < 0) {
1056 if (i) {
1057 async_tx_ack(s->desc_rx[0]);
1058 s->cookie_rx[0] = -EINVAL;
1059 }
1060 if (desc) {
1061 async_tx_ack(desc);
1062 s->cookie_rx[i] = -EINVAL;
1063 }
1064 dev_warn(s->port.dev,
1065 "failed to re-start DMA, using PIO\n");
1066 sci_rx_dma_release(s, true);
1067 return;
1068 }
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001069 dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__,
1070 s->cookie_rx[i], i);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001071 }
1072
1073 s->active_rx = s->cookie_rx[0];
1074
1075 dma_async_issue_pending(chan);
1076}
1077
1078static void work_fn_rx(struct work_struct *work)
1079{
1080 struct sci_port *s = container_of(work, struct sci_port, work_rx);
1081 struct uart_port *port = &s->port;
1082 struct dma_async_tx_descriptor *desc;
1083 int new;
1084
1085 if (s->active_rx == s->cookie_rx[0]) {
1086 new = 0;
1087 } else if (s->active_rx == s->cookie_rx[1]) {
1088 new = 1;
1089 } else {
1090 dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
1091 return;
1092 }
1093 desc = s->desc_rx[new];
1094
1095 if (dma_async_is_tx_complete(s->chan_rx, s->active_rx, NULL, NULL) !=
1096 DMA_SUCCESS) {
1097 /* Handle incomplete DMA receive */
1098 struct tty_struct *tty = port->state->port.tty;
1099 struct dma_chan *chan = s->chan_rx;
1100 struct sh_desc *sh_desc = container_of(desc, struct sh_desc,
1101 async_tx);
1102 unsigned long flags;
1103 int count;
1104
Linus Walleij05827632010-05-17 16:30:42 -07001105 chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001106 dev_dbg(port->dev, "Read %u bytes with cookie %d\n",
1107 sh_desc->partial, sh_desc->cookie);
1108
1109 spin_lock_irqsave(&port->lock, flags);
1110 count = sci_dma_rx_push(s, tty, sh_desc->partial);
1111 spin_unlock_irqrestore(&port->lock, flags);
1112
1113 if (count)
1114 tty_flip_buffer_push(tty);
1115
1116 sci_submit_rx(s);
1117
1118 return;
1119 }
1120
1121 s->cookie_rx[new] = desc->tx_submit(desc);
1122 if (s->cookie_rx[new] < 0) {
1123 dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n");
1124 sci_rx_dma_release(s, true);
1125 return;
1126 }
1127
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001128 s->active_rx = s->cookie_rx[!new];
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001129
1130 dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n", __func__,
1131 s->cookie_rx[new], new, s->active_rx);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001132}
1133
1134static void work_fn_tx(struct work_struct *work)
1135{
1136 struct sci_port *s = container_of(work, struct sci_port, work_tx);
1137 struct dma_async_tx_descriptor *desc;
1138 struct dma_chan *chan = s->chan_tx;
1139 struct uart_port *port = &s->port;
1140 struct circ_buf *xmit = &port->state->xmit;
1141 struct scatterlist *sg = &s->sg_tx;
1142
1143 /*
1144 * DMA is idle now.
1145 * Port xmit buffer is already mapped, and it is one page... Just adjust
1146 * offsets and lengths. Since it is a circular buffer, we have to
1147 * transmit till the end, and then the rest. Take the port lock to get a
1148 * consistent xmit buffer state.
1149 */
1150 spin_lock_irq(&port->lock);
1151 sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
Magnus Dammf354a382010-03-19 04:47:01 +00001152 sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001153 sg->offset;
Magnus Dammf354a382010-03-19 04:47:01 +00001154 sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001155 CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001156 spin_unlock_irq(&port->lock);
1157
Magnus Dammf354a382010-03-19 04:47:01 +00001158 BUG_ON(!sg_dma_len(sg));
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001159
1160 desc = chan->device->device_prep_slave_sg(chan,
1161 sg, s->sg_len_tx, DMA_TO_DEVICE,
1162 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
1163 if (!desc) {
1164 /* switch to PIO */
1165 sci_tx_dma_release(s, true);
1166 return;
1167 }
1168
1169 dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
1170
1171 spin_lock_irq(&port->lock);
1172 s->desc_tx = desc;
1173 desc->callback = sci_dma_tx_complete;
1174 desc->callback_param = s;
1175 spin_unlock_irq(&port->lock);
1176 s->cookie_tx = desc->tx_submit(desc);
1177 if (s->cookie_tx < 0) {
1178 dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n");
1179 /* switch to PIO */
1180 sci_tx_dma_release(s, true);
1181 return;
1182 }
1183
1184 dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", __func__,
1185 xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
1186
1187 dma_async_issue_pending(chan);
1188}
1189#endif
1190
Russell Kingb129a8c2005-08-31 10:12:14 +01001191static void sci_start_tx(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192{
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001193 struct sci_port *s = to_sci_port(port);
Paul Mundte108b2c2006-09-27 16:32:13 +09001194 unsigned short ctrl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001196#ifdef CONFIG_SERIAL_SH_SCI_DMA
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +00001197 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001198 u16 new, scr = sci_in(port, SCSCR);
1199 if (s->chan_tx)
1200 new = scr | 0x8000;
1201 else
1202 new = scr & ~0x8000;
1203 if (new != scr)
1204 sci_out(port, SCSCR, new);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001205 }
Paul Mundtf43dc232011-01-13 15:06:28 +09001206
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001207 if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
1208 s->cookie_tx < 0)
1209 schedule_work(&s->work_tx);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001210#endif
Paul Mundtf43dc232011-01-13 15:06:28 +09001211
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +00001212 if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001213 /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
1214 ctrl = sci_in(port, SCSCR);
Paul Mundtf43dc232011-01-13 15:06:28 +09001215 sci_out(port, SCSCR, ctrl | SCSCR_TIE);
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217}
1218
Russell Kingb129a8c2005-08-31 10:12:14 +01001219static void sci_stop_tx(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 unsigned short ctrl;
1222
1223 /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 ctrl = sci_in(port, SCSCR);
Paul Mundtf43dc232011-01-13 15:06:28 +09001225
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +00001226 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001227 ctrl &= ~0x8000;
Paul Mundtf43dc232011-01-13 15:06:28 +09001228
Paul Mundt8e698612009-06-24 19:44:32 +09001229 ctrl &= ~SCSCR_TIE;
Paul Mundtf43dc232011-01-13 15:06:28 +09001230
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 sci_out(port, SCSCR, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232}
1233
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001234static void sci_start_rx(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 unsigned short ctrl;
1237
Paul Mundtf43dc232011-01-13 15:06:28 +09001238 ctrl = sci_in(port, SCSCR) | port_rx_irq_mask(port);
1239
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +00001240 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001241 ctrl &= ~0x4000;
Paul Mundtf43dc232011-01-13 15:06:28 +09001242
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 sci_out(port, SCSCR, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244}
1245
1246static void sci_stop_rx(struct uart_port *port)
1247{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 unsigned short ctrl;
1249
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 ctrl = sci_in(port, SCSCR);
Paul Mundtf43dc232011-01-13 15:06:28 +09001251
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +00001252 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001253 ctrl &= ~0x4000;
Paul Mundtf43dc232011-01-13 15:06:28 +09001254
1255 ctrl &= ~port_rx_irq_mask(port);
1256
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 sci_out(port, SCSCR, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258}
1259
1260static void sci_enable_ms(struct uart_port *port)
1261{
1262 /* Nothing here yet .. */
1263}
1264
1265static void sci_break_ctl(struct uart_port *port, int break_state)
1266{
1267 /* Nothing here yet .. */
1268}
1269
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001270#ifdef CONFIG_SERIAL_SH_SCI_DMA
1271static bool filter(struct dma_chan *chan, void *slave)
1272{
1273 struct sh_dmae_slave *param = slave;
1274
1275 dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__,
1276 param->slave_id);
1277
1278 if (param->dma_dev == chan->device->dev) {
1279 chan->private = param;
1280 return true;
1281 } else {
1282 return false;
1283 }
1284}
1285
1286static void rx_timer_fn(unsigned long arg)
1287{
1288 struct sci_port *s = (struct sci_port *)arg;
1289 struct uart_port *port = &s->port;
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001290 u16 scr = sci_in(port, SCSCR);
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001291
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +00001292 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001293 scr &= ~0x4000;
Paul Mundtce6738b2011-01-19 15:24:40 +09001294 enable_irq(s->cfg->irqs[1]);
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001295 }
Paul Mundtf43dc232011-01-13 15:06:28 +09001296 sci_out(port, SCSCR, scr | SCSCR_RIE);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001297 dev_dbg(port->dev, "DMA Rx timed out\n");
1298 schedule_work(&s->work_rx);
1299}
1300
1301static void sci_request_dma(struct uart_port *port)
1302{
1303 struct sci_port *s = to_sci_port(port);
1304 struct sh_dmae_slave *param;
1305 struct dma_chan *chan;
1306 dma_cap_mask_t mask;
1307 int nent;
1308
1309 dev_dbg(port->dev, "%s: port %d DMA %p\n", __func__,
Paul Mundtce6738b2011-01-19 15:24:40 +09001310 port->line, s->cfg->dma_dev);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001311
Paul Mundtce6738b2011-01-19 15:24:40 +09001312 if (!s->cfg->dma_dev)
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001313 return;
1314
1315 dma_cap_zero(mask);
1316 dma_cap_set(DMA_SLAVE, mask);
1317
1318 param = &s->param_tx;
1319
1320 /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
Paul Mundtce6738b2011-01-19 15:24:40 +09001321 param->slave_id = s->cfg->dma_slave_tx;
1322 param->dma_dev = s->cfg->dma_dev;
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001323
1324 s->cookie_tx = -EINVAL;
1325 chan = dma_request_channel(mask, filter, param);
1326 dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
1327 if (chan) {
1328 s->chan_tx = chan;
1329 sg_init_table(&s->sg_tx, 1);
1330 /* UART circular tx buffer is an aligned page. */
1331 BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
1332 sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf),
1333 UART_XMIT_SIZE, (int)port->state->xmit.buf & ~PAGE_MASK);
1334 nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE);
1335 if (!nent)
1336 sci_tx_dma_release(s, false);
1337 else
1338 dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
1339 sg_dma_len(&s->sg_tx),
1340 port->state->xmit.buf, sg_dma_address(&s->sg_tx));
1341
1342 s->sg_len_tx = nent;
1343
1344 INIT_WORK(&s->work_tx, work_fn_tx);
1345 }
1346
1347 param = &s->param_rx;
1348
1349 /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
Paul Mundtce6738b2011-01-19 15:24:40 +09001350 param->slave_id = s->cfg->dma_slave_rx;
1351 param->dma_dev = s->cfg->dma_dev;
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001352
1353 chan = dma_request_channel(mask, filter, param);
1354 dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
1355 if (chan) {
1356 dma_addr_t dma[2];
1357 void *buf[2];
1358 int i;
1359
1360 s->chan_rx = chan;
1361
1362 s->buf_len_rx = 2 * max(16, (int)port->fifosize);
1363 buf[0] = dma_alloc_coherent(port->dev, s->buf_len_rx * 2,
1364 &dma[0], GFP_KERNEL);
1365
1366 if (!buf[0]) {
1367 dev_warn(port->dev,
1368 "failed to allocate dma buffer, using PIO\n");
1369 sci_rx_dma_release(s, true);
1370 return;
1371 }
1372
1373 buf[1] = buf[0] + s->buf_len_rx;
1374 dma[1] = dma[0] + s->buf_len_rx;
1375
1376 for (i = 0; i < 2; i++) {
1377 struct scatterlist *sg = &s->sg_rx[i];
1378
1379 sg_init_table(sg, 1);
1380 sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx,
1381 (int)buf[i] & ~PAGE_MASK);
Magnus Dammf354a382010-03-19 04:47:01 +00001382 sg_dma_address(sg) = dma[i];
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001383 }
1384
1385 INIT_WORK(&s->work_rx, work_fn_rx);
1386 setup_timer(&s->rx_timer, rx_timer_fn, (unsigned long)s);
1387
1388 sci_submit_rx(s);
1389 }
1390}
1391
1392static void sci_free_dma(struct uart_port *port)
1393{
1394 struct sci_port *s = to_sci_port(port);
1395
Paul Mundtce6738b2011-01-19 15:24:40 +09001396 if (!s->cfg->dma_dev)
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001397 return;
1398
1399 if (s->chan_tx)
1400 sci_tx_dma_release(s, false);
1401 if (s->chan_rx)
1402 sci_rx_dma_release(s, false);
1403}
Paul Mundt27bd1072011-01-19 15:37:31 +09001404#else
1405static inline void sci_request_dma(struct uart_port *port)
1406{
1407}
1408
1409static inline void sci_free_dma(struct uart_port *port)
1410{
1411}
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001412#endif
1413
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414static int sci_startup(struct uart_port *port)
1415{
Magnus Damma5660ad2009-01-21 15:14:38 +00001416 struct sci_port *s = to_sci_port(port);
Paul Mundt073e84c2011-01-19 17:30:53 +09001417 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001419 dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
1420
Paul Mundte108b2c2006-09-27 16:32:13 +09001421 if (s->enable)
1422 s->enable(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Paul Mundt073e84c2011-01-19 17:30:53 +09001424 ret = sci_request_irq(s);
1425 if (unlikely(ret < 0))
1426 return ret;
1427
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001428 sci_request_dma(port);
Paul Mundt073e84c2011-01-19 17:30:53 +09001429
Yoshinori Satod6569012005-10-14 15:59:12 -07001430 sci_start_tx(port);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001431 sci_start_rx(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
1433 return 0;
1434}
1435
1436static void sci_shutdown(struct uart_port *port)
1437{
Magnus Damma5660ad2009-01-21 15:14:38 +00001438 struct sci_port *s = to_sci_port(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001440 dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
1441
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 sci_stop_rx(port);
Russell Kingb129a8c2005-08-31 10:12:14 +01001443 sci_stop_tx(port);
Paul Mundt073e84c2011-01-19 17:30:53 +09001444
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001445 sci_free_dma(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 sci_free_irq(s);
1447
Paul Mundte108b2c2006-09-27 16:32:13 +09001448 if (s->disable)
1449 s->disable(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450}
1451
Paul Mundt26c92f32009-06-24 18:23:52 +09001452static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
1453 unsigned long freq)
1454{
1455 switch (algo_id) {
1456 case SCBRR_ALGO_1:
1457 return ((freq + 16 * bps) / (16 * bps) - 1);
1458 case SCBRR_ALGO_2:
1459 return ((freq + 16 * bps) / (32 * bps) - 1);
1460 case SCBRR_ALGO_3:
1461 return (((freq * 2) + 16 * bps) / (16 * bps) - 1);
1462 case SCBRR_ALGO_4:
1463 return (((freq * 2) + 16 * bps) / (32 * bps) - 1);
1464 case SCBRR_ALGO_5:
1465 return (((freq * 1000 / 32) / bps) - 1);
1466 }
1467
1468 /* Warn, but use a safe default */
1469 WARN_ON(1);
Paul Mundte8183a62011-01-19 17:51:37 +09001470
Paul Mundt26c92f32009-06-24 18:23:52 +09001471 return ((freq + 16 * bps) / (32 * bps) - 1);
1472}
1473
Alan Cox606d0992006-12-08 02:38:45 -08001474static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
1475 struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476{
Paul Mundt00b9de92009-06-24 17:53:33 +09001477 struct sci_port *s = to_sci_port(port);
Magnus Damm154280f2009-12-22 03:37:28 +00001478 unsigned int status, baud, smr_val, max_baud;
Paul Mundta2159b52008-10-02 19:09:13 +09001479 int t = -1;
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001480 u16 scfcr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
Magnus Damm154280f2009-12-22 03:37:28 +00001482 /*
1483 * earlyprintk comes here early on with port->uartclk set to zero.
1484 * the clock framework is not up and running at this point so here
1485 * we assume that 115200 is the maximum baud rate. please note that
1486 * the baud rate is not programmed during earlyprintk - it is assumed
1487 * that the previous boot loader has enabled required clocks and
1488 * setup the baud rate generator hardware for us already.
1489 */
1490 max_baud = port->uartclk ? port->uartclk / 16 : 115200;
1491
1492 baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
1493 if (likely(baud && port->uartclk))
Paul Mundtce6738b2011-01-19 15:24:40 +09001494 t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
Alexandre Courbot36003382011-03-03 08:04:42 +00001496 if (s->enable)
1497 s->enable(port);
1498
Paul Mundte108b2c2006-09-27 16:32:13 +09001499 do {
1500 status = sci_in(port, SCxSR);
1501 } while (!(status & SCxSR_TEND(port)));
1502
1503 sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
1504
Yoshihiro Shimoda1a22f082008-11-11 12:19:05 +09001505 if (port->type != PORT_SCI)
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001506 sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST);
Paul Mundte108b2c2006-09-27 16:32:13 +09001507
1508 smr_val = sci_in(port, SCSMR) & 3;
Paul Mundte8183a62011-01-19 17:51:37 +09001509
Paul Mundte108b2c2006-09-27 16:32:13 +09001510 if ((termios->c_cflag & CSIZE) == CS7)
1511 smr_val |= 0x40;
1512 if (termios->c_cflag & PARENB)
1513 smr_val |= 0x20;
1514 if (termios->c_cflag & PARODD)
1515 smr_val |= 0x30;
1516 if (termios->c_cflag & CSTOPB)
1517 smr_val |= 0x08;
1518
1519 uart_update_timeout(port, termios->c_cflag, baud);
1520
1521 sci_out(port, SCSMR, smr_val);
1522
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001523 dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
Paul Mundtce6738b2011-01-19 15:24:40 +09001524 s->cfg->scscr);
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001525
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 if (t > 0) {
Michael Trimarchie7c98dc2008-11-13 18:18:35 +09001527 if (t >= 256) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1);
1529 t >>= 2;
Michael Trimarchie7c98dc2008-11-13 18:18:35 +09001530 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 sci_out(port, SCSMR, sci_in(port, SCSMR) & ~3);
Michael Trimarchie7c98dc2008-11-13 18:18:35 +09001532
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 sci_out(port, SCBRR, t);
1534 udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
1535 }
1536
Paul Mundtd5701642008-12-16 20:07:27 +09001537 sci_init_pins(port, termios->c_cflag);
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001538 sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0));
Paul Mundtb7a76e42006-02-01 03:06:06 -08001539
Paul Mundtce6738b2011-01-19 15:24:40 +09001540 sci_out(port, SCSCR, s->cfg->scscr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541
Guennadi Liakhovetski3089f382010-03-19 13:53:04 +00001542#ifdef CONFIG_SERIAL_SH_SCI_DMA
1543 /*
1544 * Calculate delay for 1.5 DMA buffers: see
1545 * drivers/serial/serial_core.c::uart_update_timeout(). With 10 bits
1546 * (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function
1547 * calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)."
1548 * Then below we calculate 3 jiffies (12ms) for 1.5 DMA buffers (3 FIFO
1549 * sizes), but it has been found out experimentally, that this is not
1550 * enough: the driver too often needlessly runs on a DMA timeout. 20ms
1551 * as a minimum seem to work perfectly.
1552 */
1553 if (s->chan_rx) {
1554 s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
1555 port->fifosize / 2;
1556 dev_dbg(port->dev,
1557 "DMA Rx t-out %ums, tty t-out %u jiffies\n",
1558 s->rx_timeout * 1000 / HZ, port->timeout);
1559 if (s->rx_timeout < msecs_to_jiffies(20))
1560 s->rx_timeout = msecs_to_jiffies(20);
1561 }
1562#endif
1563
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 if ((termios->c_cflag & CREAD) != 0)
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001565 sci_start_rx(port);
Alexandre Courbot36003382011-03-03 08:04:42 +00001566
1567 if (s->disable)
1568 s->disable(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569}
1570
1571static const char *sci_type(struct uart_port *port)
1572{
1573 switch (port->type) {
Michael Trimarchie7c98dc2008-11-13 18:18:35 +09001574 case PORT_IRDA:
1575 return "irda";
1576 case PORT_SCI:
1577 return "sci";
1578 case PORT_SCIF:
1579 return "scif";
1580 case PORT_SCIFA:
1581 return "scifa";
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +00001582 case PORT_SCIFB:
1583 return "scifb";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 }
1585
Paul Mundtfa439722008-09-04 18:53:58 +09001586 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587}
1588
Paul Mundte2651642011-01-20 21:24:03 +09001589static inline unsigned long sci_port_size(struct uart_port *port)
1590{
1591 /*
1592 * Pick an arbitrary size that encapsulates all of the base
1593 * registers by default. This can be optimized later, or derived
1594 * from platform resource data at such a time that ports begin to
1595 * behave more erratically.
1596 */
1597 return 64;
1598}
1599
Paul Mundtf6e94952011-01-21 15:25:36 +09001600static int sci_remap_port(struct uart_port *port)
1601{
1602 unsigned long size = sci_port_size(port);
1603
1604 /*
1605 * Nothing to do if there's already an established membase.
1606 */
1607 if (port->membase)
1608 return 0;
1609
1610 if (port->flags & UPF_IOREMAP) {
1611 port->membase = ioremap_nocache(port->mapbase, size);
1612 if (unlikely(!port->membase)) {
1613 dev_err(port->dev, "can't remap port#%d\n", port->line);
1614 return -ENXIO;
1615 }
1616 } else {
1617 /*
1618 * For the simple (and majority of) cases where we don't
1619 * need to do any remapping, just cast the cookie
1620 * directly.
1621 */
1622 port->membase = (void __iomem *)port->mapbase;
1623 }
1624
1625 return 0;
1626}
1627
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628static void sci_release_port(struct uart_port *port)
1629{
Paul Mundte2651642011-01-20 21:24:03 +09001630 if (port->flags & UPF_IOREMAP) {
1631 iounmap(port->membase);
1632 port->membase = NULL;
1633 }
1634
1635 release_mem_region(port->mapbase, sci_port_size(port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636}
1637
1638static int sci_request_port(struct uart_port *port)
1639{
Paul Mundte2651642011-01-20 21:24:03 +09001640 unsigned long size = sci_port_size(port);
1641 struct resource *res;
Paul Mundtf6e94952011-01-21 15:25:36 +09001642 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
Paul Mundt10205202011-01-21 16:00:31 +09001644 res = request_mem_region(port->mapbase, size, dev_name(port->dev));
Paul Mundte2651642011-01-20 21:24:03 +09001645 if (unlikely(res == NULL))
1646 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647
Paul Mundtf6e94952011-01-21 15:25:36 +09001648 ret = sci_remap_port(port);
1649 if (unlikely(ret != 0)) {
1650 release_resource(res);
1651 return ret;
Paul Mundt7ff731a2008-10-01 15:46:58 +09001652 }
Paul Mundte2651642011-01-20 21:24:03 +09001653
1654 return 0;
1655}
1656
1657static void sci_config_port(struct uart_port *port, int flags)
1658{
1659 if (flags & UART_CONFIG_TYPE) {
1660 struct sci_port *sport = to_sci_port(port);
1661
1662 port->type = sport->cfg->type;
1663 sci_request_port(port);
1664 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665}
1666
1667static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
1668{
Magnus Damma5660ad2009-01-21 15:14:38 +00001669 struct sci_port *s = to_sci_port(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670
Paul Mundtce6738b2011-01-19 15:24:40 +09001671 if (ser->irq != s->cfg->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 return -EINVAL;
1673 if (ser->baud_base < 2400)
1674 /* No paper tape reader for Mitch.. */
1675 return -EINVAL;
1676
1677 return 0;
1678}
1679
1680static struct uart_ops sci_uart_ops = {
1681 .tx_empty = sci_tx_empty,
1682 .set_mctrl = sci_set_mctrl,
1683 .get_mctrl = sci_get_mctrl,
1684 .start_tx = sci_start_tx,
1685 .stop_tx = sci_stop_tx,
1686 .stop_rx = sci_stop_rx,
1687 .enable_ms = sci_enable_ms,
1688 .break_ctl = sci_break_ctl,
1689 .startup = sci_startup,
1690 .shutdown = sci_shutdown,
1691 .set_termios = sci_set_termios,
1692 .type = sci_type,
1693 .release_port = sci_release_port,
1694 .request_port = sci_request_port,
1695 .config_port = sci_config_port,
1696 .verify_port = sci_verify_port,
Paul Mundt07d2a1a2008-12-11 19:06:43 +09001697#ifdef CONFIG_CONSOLE_POLL
1698 .poll_get_char = sci_poll_get_char,
1699 .poll_put_char = sci_poll_put_char,
1700#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701};
1702
Paul Mundtc7ed1ab2010-03-10 18:35:14 +09001703static int __devinit sci_init_single(struct platform_device *dev,
1704 struct sci_port *sci_port,
1705 unsigned int index,
1706 struct plat_sci_port *p)
Paul Mundte108b2c2006-09-27 16:32:13 +09001707{
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001708 struct uart_port *port = &sci_port->port;
Paul Mundte108b2c2006-09-27 16:32:13 +09001709
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001710 port->ops = &sci_uart_ops;
1711 port->iotype = UPIO_MEM;
1712 port->line = index;
Markus Pietrek75136d42010-01-15 08:33:20 +09001713
1714 switch (p->type) {
Guennadi Liakhovetskid1d4b102010-05-23 16:39:09 +00001715 case PORT_SCIFB:
1716 port->fifosize = 256;
1717 break;
Markus Pietrek75136d42010-01-15 08:33:20 +09001718 case PORT_SCIFA:
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001719 port->fifosize = 64;
Markus Pietrek75136d42010-01-15 08:33:20 +09001720 break;
1721 case PORT_SCIF:
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001722 port->fifosize = 16;
Markus Pietrek75136d42010-01-15 08:33:20 +09001723 break;
1724 default:
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001725 port->fifosize = 1;
Markus Pietrek75136d42010-01-15 08:33:20 +09001726 break;
1727 }
Magnus Damm7b6fd3b2009-12-14 10:24:42 +00001728
1729 if (dev) {
Paul Mundtc7ed1ab2010-03-10 18:35:14 +09001730 sci_port->iclk = clk_get(&dev->dev, "sci_ick");
1731 if (IS_ERR(sci_port->iclk)) {
1732 sci_port->iclk = clk_get(&dev->dev, "peripheral_clk");
1733 if (IS_ERR(sci_port->iclk)) {
1734 dev_err(&dev->dev, "can't get iclk\n");
1735 return PTR_ERR(sci_port->iclk);
1736 }
1737 }
1738
1739 /*
1740 * The function clock is optional, ignore it if we can't
1741 * find it.
1742 */
1743 sci_port->fclk = clk_get(&dev->dev, "sci_fck");
1744 if (IS_ERR(sci_port->fclk))
1745 sci_port->fclk = NULL;
1746
Magnus Damm7b6fd3b2009-12-14 10:24:42 +00001747 sci_port->enable = sci_clk_enable;
1748 sci_port->disable = sci_clk_disable;
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001749 port->dev = &dev->dev;
Magnus Damm5e50d2d2011-04-19 10:38:25 +00001750
1751 pm_runtime_enable(&dev->dev);
Magnus Damm7b6fd3b2009-12-14 10:24:42 +00001752 }
Paul Mundte108b2c2006-09-27 16:32:13 +09001753
Magnus Damm7ed7e072009-01-21 15:14:14 +00001754 sci_port->break_timer.data = (unsigned long)sci_port;
1755 sci_port->break_timer.function = sci_break_timer;
1756 init_timer(&sci_port->break_timer);
Paul Mundte108b2c2006-09-27 16:32:13 +09001757
Paul Mundtce6738b2011-01-19 15:24:40 +09001758 sci_port->cfg = p;
Magnus Damm7ed7e072009-01-21 15:14:14 +00001759
Paul Mundtce6738b2011-01-19 15:24:40 +09001760 port->mapbase = p->mapbase;
1761 port->type = p->type;
Paul Mundtf43dc232011-01-13 15:06:28 +09001762 port->flags = p->flags;
Paul Mundtce6738b2011-01-19 15:24:40 +09001763
1764 /*
1765 * The UART port needs an IRQ value, so we peg this to the TX IRQ
1766 * for the multi-IRQ ports, which is where we are primarily
1767 * concerned with the shutdown path synchronization.
1768 *
1769 * For the muxed case there's nothing more to do.
1770 */
Magnus Damm54aa89e2011-04-21 13:08:46 +00001771 port->irq = p->irqs[SCIx_RXI_IRQ];
Guennadi Liakhovetski73a19e4c2010-03-02 11:39:15 +09001772
Paul Mundtce6738b2011-01-19 15:24:40 +09001773 if (p->dma_dev)
1774 dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n",
1775 p->dma_dev, p->dma_slave_tx, p->dma_slave_rx);
Magnus Damm7ed7e072009-01-21 15:14:14 +00001776
Paul Mundtc7ed1ab2010-03-10 18:35:14 +09001777 return 0;
Paul Mundte108b2c2006-09-27 16:32:13 +09001778}
1779
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
Magnus Dammdc8e6f52009-01-21 15:14:06 +00001781static void serial_console_putchar(struct uart_port *port, int ch)
1782{
1783 sci_poll_put_char(port, ch);
1784}
1785
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786/*
1787 * Print a string to the serial port trying not to disturb
1788 * any possible real use of the port...
1789 */
1790static void serial_console_write(struct console *co, const char *s,
1791 unsigned count)
1792{
Paul Mundt906b17d2011-01-21 16:19:53 +09001793 struct sci_port *sci_port = &sci_ports[co->index];
1794 struct uart_port *port = &sci_port->port;
Magnus Damm973e5d52009-02-24 15:57:12 +09001795 unsigned short bits;
Paul Mundt07d2a1a2008-12-11 19:06:43 +09001796
Magnus Damm501b8252009-01-21 15:14:30 +00001797 if (sci_port->enable)
1798 sci_port->enable(port);
1799
1800 uart_console_write(port, s, count, serial_console_putchar);
Magnus Damm973e5d52009-02-24 15:57:12 +09001801
1802 /* wait until fifo is empty and last bit has been transmitted */
1803 bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
1804 while ((sci_in(port, SCxSR) & bits) != bits)
1805 cpu_relax();
Magnus Damm501b8252009-01-21 15:14:30 +00001806
Magnus Damm345e5a72009-11-05 14:34:57 +00001807 if (sci_port->disable)
Magnus Damm501b8252009-01-21 15:14:30 +00001808 sci_port->disable(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809}
1810
Magnus Damm7b6fd3b2009-12-14 10:24:42 +00001811static int __devinit serial_console_setup(struct console *co, char *options)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812{
Magnus Dammdc8e6f52009-01-21 15:14:06 +00001813 struct sci_port *sci_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 struct uart_port *port;
1815 int baud = 115200;
1816 int bits = 8;
1817 int parity = 'n';
1818 int flow = 'n';
1819 int ret;
1820
Paul Mundte108b2c2006-09-27 16:32:13 +09001821 /*
Paul Mundt906b17d2011-01-21 16:19:53 +09001822 * Refuse to handle any bogus ports.
Paul Mundte108b2c2006-09-27 16:32:13 +09001823 */
Paul Mundt906b17d2011-01-21 16:19:53 +09001824 if (co->index < 0 || co->index >= SCI_NPORTS)
Paul Mundte108b2c2006-09-27 16:32:13 +09001825 return -ENODEV;
Paul Mundte108b2c2006-09-27 16:32:13 +09001826
Paul Mundt906b17d2011-01-21 16:19:53 +09001827 sci_port = &sci_ports[co->index];
1828 port = &sci_port->port;
1829
Alexandre Courbotb2267a62011-02-09 03:18:46 +00001830 /*
1831 * Refuse to handle uninitialized ports.
1832 */
1833 if (!port->ops)
1834 return -ENODEV;
1835
Paul Mundtf6e94952011-01-21 15:25:36 +09001836 ret = sci_remap_port(port);
1837 if (unlikely(ret != 0))
1838 return ret;
Paul Mundte108b2c2006-09-27 16:32:13 +09001839
Magnus Dammdc8e6f52009-01-21 15:14:06 +00001840 if (sci_port->enable)
1841 sci_port->enable(port);
Paul Mundte108b2c2006-09-27 16:32:13 +09001842
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 if (options)
1844 uart_parse_options(options, &baud, &parity, &bits, &flow);
1845
Magnus Damm501b8252009-01-21 15:14:30 +00001846 /* TODO: disable clock */
Paul Mundtab7cfb52011-06-01 14:47:42 +09001847 return uart_set_options(port, co, baud, parity, bits, flow);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848}
1849
1850static struct console serial_console = {
1851 .name = "ttySC",
Paul Mundt906b17d2011-01-21 16:19:53 +09001852 .device = uart_console_device,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 .write = serial_console_write,
1854 .setup = serial_console_setup,
Paul Mundtfa5da2f2007-03-08 17:27:37 +09001855 .flags = CON_PRINTBUFFER,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 .index = -1,
Paul Mundt906b17d2011-01-21 16:19:53 +09001857 .data = &sci_uart_driver,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858};
1859
Magnus Damm7b6fd3b2009-12-14 10:24:42 +00001860static struct console early_serial_console = {
1861 .name = "early_ttySC",
1862 .write = serial_console_write,
1863 .flags = CON_PRINTBUFFER,
Paul Mundt906b17d2011-01-21 16:19:53 +09001864 .index = -1,
Magnus Damm7b6fd3b2009-12-14 10:24:42 +00001865};
Paul Mundtecdf8a42011-01-21 00:05:48 +09001866
Magnus Damm7b6fd3b2009-12-14 10:24:42 +00001867static char early_serial_buf[32];
1868
Paul Mundtecdf8a42011-01-21 00:05:48 +09001869static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
1870{
1871 struct plat_sci_port *cfg = pdev->dev.platform_data;
1872
1873 if (early_serial_console.data)
1874 return -EEXIST;
1875
1876 early_serial_console.index = pdev->id;
Paul Mundtecdf8a42011-01-21 00:05:48 +09001877
Paul Mundt906b17d2011-01-21 16:19:53 +09001878 sci_init_single(NULL, &sci_ports[pdev->id], pdev->id, cfg);
Paul Mundtecdf8a42011-01-21 00:05:48 +09001879
1880 serial_console_setup(&early_serial_console, early_serial_buf);
1881
1882 if (!strstr(early_serial_buf, "keep"))
1883 early_serial_console.flags |= CON_BOOT;
1884
1885 register_console(&early_serial_console);
1886 return 0;
1887}
Nobuhiro Iwamatsu6a8c9792011-03-24 02:20:56 +00001888
1889#define SCI_CONSOLE (&serial_console)
1890
Paul Mundtecdf8a42011-01-21 00:05:48 +09001891#else
1892static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
1893{
1894 return -EINVAL;
1895}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
Nobuhiro Iwamatsu6a8c9792011-03-24 02:20:56 +00001897#define SCI_CONSOLE NULL
1898
1899#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900
1901static char banner[] __initdata =
1902 KERN_INFO "SuperH SCI(F) driver initialized\n";
1903
1904static struct uart_driver sci_uart_driver = {
1905 .owner = THIS_MODULE,
1906 .driver_name = "sci",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 .dev_name = "ttySC",
1908 .major = SCI_MAJOR,
1909 .minor = SCI_MINOR_START,
Paul Mundte108b2c2006-09-27 16:32:13 +09001910 .nr = SCI_NPORTS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 .cons = SCI_CONSOLE,
1912};
1913
Paul Mundt54507f62009-05-08 23:48:33 +09001914static int sci_remove(struct platform_device *dev)
Magnus Damme552de22009-01-21 15:13:42 +00001915{
Paul Mundtd535a232011-01-19 17:19:35 +09001916 struct sci_port *port = platform_get_drvdata(dev);
Magnus Damme552de22009-01-21 15:13:42 +00001917
Paul Mundtd535a232011-01-19 17:19:35 +09001918 cpufreq_unregister_notifier(&port->freq_transition,
1919 CPUFREQ_TRANSITION_NOTIFIER);
Magnus Damme552de22009-01-21 15:13:42 +00001920
Paul Mundtd535a232011-01-19 17:19:35 +09001921 uart_remove_one_port(&sci_uart_driver, &port->port);
Magnus Damme552de22009-01-21 15:13:42 +00001922
Paul Mundtd535a232011-01-19 17:19:35 +09001923 clk_put(port->iclk);
1924 clk_put(port->fclk);
1925
Magnus Damm5e50d2d2011-04-19 10:38:25 +00001926 pm_runtime_disable(&dev->dev);
Magnus Damme552de22009-01-21 15:13:42 +00001927 return 0;
1928}
1929
Magnus Damm0ee70712009-01-21 15:13:50 +00001930static int __devinit sci_probe_single(struct platform_device *dev,
1931 unsigned int index,
1932 struct plat_sci_port *p,
1933 struct sci_port *sciport)
1934{
Magnus Damm0ee70712009-01-21 15:13:50 +00001935 int ret;
1936
1937 /* Sanity check */
1938 if (unlikely(index >= SCI_NPORTS)) {
1939 dev_notice(&dev->dev, "Attempting to register port "
1940 "%d when only %d are available.\n",
1941 index+1, SCI_NPORTS);
1942 dev_notice(&dev->dev, "Consider bumping "
1943 "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
1944 return 0;
1945 }
1946
Paul Mundtc7ed1ab2010-03-10 18:35:14 +09001947 ret = sci_init_single(dev, sciport, index, p);
1948 if (ret)
1949 return ret;
Magnus Damm0ee70712009-01-21 15:13:50 +00001950
Paul Mundtd535a232011-01-19 17:19:35 +09001951 return uart_add_one_port(&sci_uart_driver, &sciport->port);
Magnus Damm0ee70712009-01-21 15:13:50 +00001952}
1953
Paul Mundte108b2c2006-09-27 16:32:13 +09001954static int __devinit sci_probe(struct platform_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955{
Paul Mundte108b2c2006-09-27 16:32:13 +09001956 struct plat_sci_port *p = dev->dev.platform_data;
Paul Mundtd535a232011-01-19 17:19:35 +09001957 struct sci_port *sp = &sci_ports[dev->id];
Paul Mundtecdf8a42011-01-21 00:05:48 +09001958 int ret;
Magnus Damme552de22009-01-21 15:13:42 +00001959
Paul Mundtecdf8a42011-01-21 00:05:48 +09001960 /*
1961 * If we've come here via earlyprintk initialization, head off to
1962 * the special early probe. We don't have sufficient device state
1963 * to make it beyond this yet.
1964 */
1965 if (is_early_platform_device(dev))
1966 return sci_probe_earlyprintk(dev);
Magnus Damm7b6fd3b2009-12-14 10:24:42 +00001967
Paul Mundtd535a232011-01-19 17:19:35 +09001968 platform_set_drvdata(dev, sp);
Magnus Damme552de22009-01-21 15:13:42 +00001969
Paul Mundt906b17d2011-01-21 16:19:53 +09001970 ret = sci_probe_single(dev, dev->id, p, sp);
Paul Mundtd535a232011-01-19 17:19:35 +09001971 if (ret)
1972 goto err_unreg;
Magnus Damme552de22009-01-21 15:13:42 +00001973
Paul Mundtd535a232011-01-19 17:19:35 +09001974 sp->freq_transition.notifier_call = sci_notifier;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975
Paul Mundtd535a232011-01-19 17:19:35 +09001976 ret = cpufreq_register_notifier(&sp->freq_transition,
1977 CPUFREQ_TRANSITION_NOTIFIER);
1978 if (unlikely(ret < 0))
1979 goto err_unreg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980
1981#ifdef CONFIG_SH_STANDARD_BIOS
1982 sh_bios_gdb_detach();
1983#endif
1984
Paul Mundte108b2c2006-09-27 16:32:13 +09001985 return 0;
Paul Mundt7ff731a2008-10-01 15:46:58 +09001986
1987err_unreg:
Magnus Damme552de22009-01-21 15:13:42 +00001988 sci_remove(dev);
Paul Mundt7ff731a2008-10-01 15:46:58 +09001989 return ret;
Paul Mundte108b2c2006-09-27 16:32:13 +09001990}
1991
Paul Mundt6daa79b2009-06-15 07:07:38 +09001992static int sci_suspend(struct device *dev)
Paul Mundte108b2c2006-09-27 16:32:13 +09001993{
Paul Mundtd535a232011-01-19 17:19:35 +09001994 struct sci_port *sport = dev_get_drvdata(dev);
Paul Mundte108b2c2006-09-27 16:32:13 +09001995
Paul Mundtd535a232011-01-19 17:19:35 +09001996 if (sport)
1997 uart_suspend_port(&sci_uart_driver, &sport->port);
Paul Mundte108b2c2006-09-27 16:32:13 +09001998
1999 return 0;
2000}
2001
Paul Mundt6daa79b2009-06-15 07:07:38 +09002002static int sci_resume(struct device *dev)
Paul Mundte108b2c2006-09-27 16:32:13 +09002003{
Paul Mundtd535a232011-01-19 17:19:35 +09002004 struct sci_port *sport = dev_get_drvdata(dev);
Paul Mundte108b2c2006-09-27 16:32:13 +09002005
Paul Mundtd535a232011-01-19 17:19:35 +09002006 if (sport)
2007 uart_resume_port(&sci_uart_driver, &sport->port);
Paul Mundte108b2c2006-09-27 16:32:13 +09002008
2009 return 0;
2010}
2011
Alexey Dobriyan47145212009-12-14 18:00:08 -08002012static const struct dev_pm_ops sci_dev_pm_ops = {
Paul Mundt6daa79b2009-06-15 07:07:38 +09002013 .suspend = sci_suspend,
2014 .resume = sci_resume,
2015};
2016
Paul Mundte108b2c2006-09-27 16:32:13 +09002017static struct platform_driver sci_driver = {
2018 .probe = sci_probe,
Uwe Kleine-Königb9e39c82009-11-24 22:07:32 +01002019 .remove = sci_remove,
Paul Mundte108b2c2006-09-27 16:32:13 +09002020 .driver = {
2021 .name = "sh-sci",
2022 .owner = THIS_MODULE,
Paul Mundt6daa79b2009-06-15 07:07:38 +09002023 .pm = &sci_dev_pm_ops,
Paul Mundte108b2c2006-09-27 16:32:13 +09002024 },
2025};
2026
2027static int __init sci_init(void)
2028{
2029 int ret;
2030
2031 printk(banner);
2032
Paul Mundte108b2c2006-09-27 16:32:13 +09002033 ret = uart_register_driver(&sci_uart_driver);
2034 if (likely(ret == 0)) {
2035 ret = platform_driver_register(&sci_driver);
2036 if (unlikely(ret))
2037 uart_unregister_driver(&sci_uart_driver);
2038 }
2039
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 return ret;
2041}
2042
2043static void __exit sci_exit(void)
2044{
Paul Mundte108b2c2006-09-27 16:32:13 +09002045 platform_driver_unregister(&sci_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 uart_unregister_driver(&sci_uart_driver);
2047}
2048
Magnus Damm7b6fd3b2009-12-14 10:24:42 +00002049#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
2050early_platform_init_buffer("earlyprintk", &sci_driver,
2051 early_serial_buf, ARRAY_SIZE(early_serial_buf));
2052#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053module_init(sci_init);
2054module_exit(sci_exit);
2055
Paul Mundte108b2c2006-09-27 16:32:13 +09002056MODULE_LICENSE("GPL");
Kay Sieverse169c132008-04-15 14:34:35 -07002057MODULE_ALIAS("platform:sh-sci");