blob: b56123d3affefc45b9055e1110fa9bed94b3cd14 [file] [log] [blame]
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001/*
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02002 * Driver for Atmel AT91 / AT32 Serial ports
Andrew Victor1e6c9c22006-01-10 16:59:27 +00003 * Copyright (C) 2003 Rick Bronson
4 *
5 * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
6 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
7 *
Chip Coldwella6670612008-02-08 04:21:06 -08008 * DMA support added by Chip Coldwell.
9 *
Andrew Victor1e6c9c22006-01-10 16:59:27 +000010 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
Andrew Victor1e6c9c22006-01-10 16:59:27 +000025#include <linux/module.h>
26#include <linux/tty.h>
27#include <linux/ioport.h>
28#include <linux/slab.h>
29#include <linux/init.h>
30#include <linux/serial.h>
Andrew Victorafefc412006-06-19 19:53:19 +010031#include <linux/clk.h>
Andrew Victor1e6c9c22006-01-10 16:59:27 +000032#include <linux/console.h>
33#include <linux/sysrq.h>
34#include <linux/tty_flip.h>
Andrew Victorafefc412006-06-19 19:53:19 +010035#include <linux/platform_device.h>
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +020036#include <linux/of.h>
37#include <linux/of_device.h>
Chip Coldwella6670612008-02-08 04:21:06 -080038#include <linux/dma-mapping.h>
Andrew Victor93a3ddc2007-02-08 11:31:22 +010039#include <linux/atmel_pdc.h>
Guennadi Liakhovetskifa3218d2008-01-29 15:43:13 +010040#include <linux/atmel_serial.h>
Claudio Scordinoe8faff72010-05-03 13:31:28 +010041#include <linux/uaccess.h>
Jean-Christophe PLAGNIOL-VILLARDbcd23602012-10-30 05:12:23 +080042#include <linux/platform_data/atmel.h>
Andrew Victor1e6c9c22006-01-10 16:59:27 +000043
44#include <asm/io.h>
Peter Huewef7512e72010-06-29 19:35:39 +020045#include <asm/ioctls.h>
Andrew Victor1e6c9c22006-01-10 16:59:27 +000046
Haavard Skinnemoenacca9b82006-10-04 16:02:09 +020047#ifdef CONFIG_ARM
Russell Kinga09e64f2008-08-05 16:14:15 +010048#include <mach/cpu.h>
Russell King60e89722011-07-26 10:56:19 +010049#include <asm/gpio.h>
Haavard Skinnemoenacca9b82006-10-04 16:02:09 +020050#endif
Andrew Victor1e6c9c22006-01-10 16:59:27 +000051
Chip Coldwella6670612008-02-08 04:21:06 -080052#define PDC_BUFFER_SIZE 512
53/* Revisit: We should calculate this based on the actual port settings */
54#define PDC_RX_TIMEOUT (3 * 10) /* 3 bytes */
55
Haavard Skinnemoen749c4e62006-10-04 16:02:02 +020056#if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
Andrew Victor1e6c9c22006-01-10 16:59:27 +000057#define SUPPORT_SYSRQ
58#endif
59
60#include <linux/serial_core.h>
61
Claudio Scordinoe8faff72010-05-03 13:31:28 +010062static void atmel_start_rx(struct uart_port *port);
63static void atmel_stop_rx(struct uart_port *port);
64
Haavard Skinnemoen749c4e62006-10-04 16:02:02 +020065#ifdef CONFIG_SERIAL_ATMEL_TTYAT
Andrew Victor1e6c9c22006-01-10 16:59:27 +000066
67/* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we
68 * should coexist with the 8250 driver, such as if we have an external 16C550
69 * UART. */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +020070#define SERIAL_ATMEL_MAJOR 204
Andrew Victor1e6c9c22006-01-10 16:59:27 +000071#define MINOR_START 154
Haavard Skinnemoen7192f922006-10-04 16:02:05 +020072#define ATMEL_DEVICENAME "ttyAT"
Andrew Victor1e6c9c22006-01-10 16:59:27 +000073
74#else
75
76/* Use device name ttyS, major 4, minor 64-68. This is the usual serial port
77 * name, but it is legally reserved for the 8250 driver. */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +020078#define SERIAL_ATMEL_MAJOR TTY_MAJOR
Andrew Victor1e6c9c22006-01-10 16:59:27 +000079#define MINOR_START 64
Haavard Skinnemoen7192f922006-10-04 16:02:05 +020080#define ATMEL_DEVICENAME "ttyS"
Andrew Victor1e6c9c22006-01-10 16:59:27 +000081
82#endif
83
Haavard Skinnemoen7192f922006-10-04 16:02:05 +020084#define ATMEL_ISR_PASS_LIMIT 256
Andrew Victor1e6c9c22006-01-10 16:59:27 +000085
Remy Bohmerb843aa22008-02-08 04:21:01 -080086/* UART registers. CR is write-only, hence no GET macro */
Haavard Skinnemoen544fc722007-02-12 00:52:15 -080087#define UART_PUT_CR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_CR)
88#define UART_GET_MR(port) __raw_readl((port)->membase + ATMEL_US_MR)
89#define UART_PUT_MR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_MR)
90#define UART_PUT_IER(port,v) __raw_writel(v, (port)->membase + ATMEL_US_IER)
91#define UART_PUT_IDR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_IDR)
92#define UART_GET_IMR(port) __raw_readl((port)->membase + ATMEL_US_IMR)
93#define UART_GET_CSR(port) __raw_readl((port)->membase + ATMEL_US_CSR)
94#define UART_GET_CHAR(port) __raw_readl((port)->membase + ATMEL_US_RHR)
95#define UART_PUT_CHAR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_THR)
96#define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR)
97#define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR)
98#define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR)
Claudio Scordinoe8faff72010-05-03 13:31:28 +010099#define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000100
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000101 /* PDC registers */
Haavard Skinnemoen544fc722007-02-12 00:52:15 -0800102#define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
103#define UART_GET_PTSR(port) __raw_readl((port)->membase + ATMEL_PDC_PTSR)
Andrew Victorafefc412006-06-19 19:53:19 +0100104
Haavard Skinnemoen544fc722007-02-12 00:52:15 -0800105#define UART_PUT_RPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
106#define UART_GET_RPR(port) __raw_readl((port)->membase + ATMEL_PDC_RPR)
107#define UART_PUT_RCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
108#define UART_PUT_RNPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
109#define UART_PUT_RNCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000110
Haavard Skinnemoen544fc722007-02-12 00:52:15 -0800111#define UART_PUT_TPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
112#define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
Marc Pignat39d4c922008-04-02 13:04:42 -0700113#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000114
Haavard Skinnemoen71f2e2b2006-10-04 16:02:07 +0200115static int (*atmel_open_hook)(struct uart_port *);
116static void (*atmel_close_hook)(struct uart_port *);
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000117
Chip Coldwella6670612008-02-08 04:21:06 -0800118struct atmel_dma_buffer {
119 unsigned char *buf;
120 dma_addr_t dma_addr;
121 unsigned int dma_size;
122 unsigned int ofs;
123};
124
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800125struct atmel_uart_char {
126 u16 status;
127 u16 ch;
128};
129
130#define ATMEL_SERIAL_RINGSIZE 1024
131
Andrew Victorafefc412006-06-19 19:53:19 +0100132/*
133 * We wrap our port structure around the generic uart_port.
134 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200135struct atmel_uart_port {
Andrew Victorafefc412006-06-19 19:53:19 +0100136 struct uart_port uart; /* uart */
137 struct clk *clk; /* uart clock */
Anti Sullinf05596d2008-09-22 13:57:54 -0700138 int may_wakeup; /* cached value of device_may_wakeup for times we need to disable it */
139 u32 backup_imr; /* IMR saved during suspend */
Haavard Skinnemoen9e6077b2007-07-15 23:40:36 -0700140 int break_active; /* break being received */
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800141
Elen Song64e22eb2013-07-22 16:30:24 +0800142 bool use_pdc_rx; /* enable PDC receiver */
Chip Coldwella6670612008-02-08 04:21:06 -0800143 short pdc_rx_idx; /* current PDC RX buffer */
144 struct atmel_dma_buffer pdc_rx[2]; /* PDC receier */
145
Elen Song64e22eb2013-07-22 16:30:24 +0800146 bool use_pdc_tx; /* enable PDC transmitter */
Chip Coldwella6670612008-02-08 04:21:06 -0800147 struct atmel_dma_buffer pdc_tx; /* PDC transmitter */
148
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800149 struct tasklet_struct tasklet;
150 unsigned int irq_status;
151 unsigned int irq_status_prev;
152
153 struct circ_buf rx_ring;
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100154
155 struct serial_rs485 rs485; /* rs485 settings */
156 unsigned int tx_done_mask;
Elen Songa930e522013-07-22 16:30:25 +0800157 int (*prepare_rx)(struct uart_port *port);
158 int (*prepare_tx)(struct uart_port *port);
159 void (*schedule_rx)(struct uart_port *port);
160 void (*schedule_tx)(struct uart_port *port);
161 void (*release_rx)(struct uart_port *port);
162 void (*release_tx)(struct uart_port *port);
Andrew Victorafefc412006-06-19 19:53:19 +0100163};
164
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200165static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
Pawel Wieczorkiewicz503bded2013-02-20 17:26:20 +0100166static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART);
Andrew Victorafefc412006-06-19 19:53:19 +0100167
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000168#ifdef SUPPORT_SYSRQ
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200169static struct console atmel_console;
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000170#endif
171
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +0200172#if defined(CONFIG_OF)
173static const struct of_device_id atmel_serial_dt_ids[] = {
174 { .compatible = "atmel,at91rm9200-usart" },
175 { .compatible = "atmel,at91sam9260-usart" },
176 { /* sentinel */ }
177};
178
179MODULE_DEVICE_TABLE(of, atmel_serial_dt_ids);
180#endif
181
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800182static inline struct atmel_uart_port *
183to_atmel_uart_port(struct uart_port *uart)
184{
185 return container_of(uart, struct atmel_uart_port, uart);
186}
187
Chip Coldwella6670612008-02-08 04:21:06 -0800188#ifdef CONFIG_SERIAL_ATMEL_PDC
Elen Song64e22eb2013-07-22 16:30:24 +0800189static bool atmel_use_pdc_rx(struct uart_port *port)
Chip Coldwella6670612008-02-08 04:21:06 -0800190{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800191 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Chip Coldwella6670612008-02-08 04:21:06 -0800192
Elen Song64e22eb2013-07-22 16:30:24 +0800193 return atmel_port->use_pdc_rx;
Chip Coldwella6670612008-02-08 04:21:06 -0800194}
195
Elen Song64e22eb2013-07-22 16:30:24 +0800196static bool atmel_use_pdc_tx(struct uart_port *port)
Chip Coldwella6670612008-02-08 04:21:06 -0800197{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800198 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Chip Coldwella6670612008-02-08 04:21:06 -0800199
Elen Song64e22eb2013-07-22 16:30:24 +0800200 return atmel_port->use_pdc_tx;
Chip Coldwella6670612008-02-08 04:21:06 -0800201}
202#else
Elen Song64e22eb2013-07-22 16:30:24 +0800203static bool atmel_use_pdc_rx(struct uart_port *port)
Chip Coldwella6670612008-02-08 04:21:06 -0800204{
205 return false;
206}
207
Elen Song64e22eb2013-07-22 16:30:24 +0800208static bool atmel_use_pdc_tx(struct uart_port *port)
Chip Coldwella6670612008-02-08 04:21:06 -0800209{
210 return false;
211}
212#endif
213
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100214/* Enable or disable the rs485 support */
215void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
216{
217 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
218 unsigned int mode;
Claudio Scordinodbf11152011-12-16 15:08:49 +0100219 unsigned long flags;
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100220
Claudio Scordinodbf11152011-12-16 15:08:49 +0100221 spin_lock_irqsave(&port->lock, flags);
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100222
223 /* Disable interrupts */
224 UART_PUT_IDR(port, atmel_port->tx_done_mask);
225
226 mode = UART_GET_MR(port);
227
228 /* Resetting serial mode to RS232 (0x0) */
229 mode &= ~ATMEL_US_USMODE;
230
231 atmel_port->rs485 = *rs485conf;
232
233 if (rs485conf->flags & SER_RS485_ENABLED) {
234 dev_dbg(port->dev, "Setting UART to RS485\n");
235 atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
Claudio Scordino93f33502011-11-09 15:51:49 +0100236 if ((rs485conf->delay_rts_after_send) > 0)
Claudio Scordino1b633182010-07-20 15:26:47 -0700237 UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100238 mode |= ATMEL_US_USMODE_RS485;
239 } else {
240 dev_dbg(port->dev, "Setting UART to RS232\n");
Elen Song64e22eb2013-07-22 16:30:24 +0800241 if (atmel_use_pdc_tx(port))
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100242 atmel_port->tx_done_mask = ATMEL_US_ENDTX |
243 ATMEL_US_TXBUFE;
244 else
245 atmel_port->tx_done_mask = ATMEL_US_TXRDY;
246 }
247 UART_PUT_MR(port, mode);
248
249 /* Enable interrupts */
250 UART_PUT_IER(port, atmel_port->tx_done_mask);
251
Claudio Scordinodbf11152011-12-16 15:08:49 +0100252 spin_unlock_irqrestore(&port->lock, flags);
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100253
254}
255
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000256/*
257 * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
258 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200259static u_int atmel_tx_empty(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000260{
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200261 return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000262}
263
264/*
265 * Set state of the modem control output lines
266 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200267static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000268{
269 unsigned int control = 0;
Andrew Victorafefc412006-06-19 19:53:19 +0100270 unsigned int mode;
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100271 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000272
Andrew Victorc2f5ccf2006-12-04 09:37:20 +0100273#ifdef CONFIG_ARCH_AT91RM9200
Andrew Victor79da7a62006-11-30 11:58:14 +0100274 if (cpu_is_at91rm9200()) {
Andrew Victorafefc412006-06-19 19:53:19 +0100275 /*
Remy Bohmerb843aa22008-02-08 04:21:01 -0800276 * AT91RM9200 Errata #39: RTS0 is not internally connected
277 * to PA21. We need to drive the pin manually.
Andrew Victorafefc412006-06-19 19:53:19 +0100278 */
Andrew Victor72729912006-09-27 09:44:11 +0100279 if (port->mapbase == AT91RM9200_BASE_US0) {
Andrew Victorafefc412006-06-19 19:53:19 +0100280 if (mctrl & TIOCM_RTS)
Andrew Victor20e65272006-07-05 14:31:13 +0100281 at91_set_gpio_value(AT91_PIN_PA21, 0);
Andrew Victorafefc412006-06-19 19:53:19 +0100282 else
Andrew Victor20e65272006-07-05 14:31:13 +0100283 at91_set_gpio_value(AT91_PIN_PA21, 1);
Andrew Victorafefc412006-06-19 19:53:19 +0100284 }
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000285 }
Haavard Skinnemoenacca9b82006-10-04 16:02:09 +0200286#endif
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000287
288 if (mctrl & TIOCM_RTS)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200289 control |= ATMEL_US_RTSEN;
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000290 else
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200291 control |= ATMEL_US_RTSDIS;
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000292
293 if (mctrl & TIOCM_DTR)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200294 control |= ATMEL_US_DTREN;
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000295 else
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200296 control |= ATMEL_US_DTRDIS;
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000297
Andrew Victorafefc412006-06-19 19:53:19 +0100298 UART_PUT_CR(port, control);
299
300 /* Local loopback mode? */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200301 mode = UART_GET_MR(port) & ~ATMEL_US_CHMODE;
Andrew Victorafefc412006-06-19 19:53:19 +0100302 if (mctrl & TIOCM_LOOP)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200303 mode |= ATMEL_US_CHMODE_LOC_LOOP;
Andrew Victorafefc412006-06-19 19:53:19 +0100304 else
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200305 mode |= ATMEL_US_CHMODE_NORMAL;
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100306
307 /* Resetting serial mode to RS232 (0x0) */
308 mode &= ~ATMEL_US_USMODE;
309
310 if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
311 dev_dbg(port->dev, "Setting UART to RS485\n");
Claudio Scordino93f33502011-11-09 15:51:49 +0100312 if ((atmel_port->rs485.delay_rts_after_send) > 0)
Claudio Scordino1b633182010-07-20 15:26:47 -0700313 UART_PUT_TTGR(port,
314 atmel_port->rs485.delay_rts_after_send);
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100315 mode |= ATMEL_US_USMODE_RS485;
316 } else {
317 dev_dbg(port->dev, "Setting UART to RS232\n");
318 }
Andrew Victorafefc412006-06-19 19:53:19 +0100319 UART_PUT_MR(port, mode);
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000320}
321
322/*
323 * Get state of the modem control input lines
324 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200325static u_int atmel_get_mctrl(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000326{
327 unsigned int status, ret = 0;
328
329 status = UART_GET_CSR(port);
330
331 /*
332 * The control signals are active low.
333 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200334 if (!(status & ATMEL_US_DCD))
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000335 ret |= TIOCM_CD;
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200336 if (!(status & ATMEL_US_CTS))
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000337 ret |= TIOCM_CTS;
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200338 if (!(status & ATMEL_US_DSR))
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000339 ret |= TIOCM_DSR;
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200340 if (!(status & ATMEL_US_RI))
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000341 ret |= TIOCM_RI;
342
343 return ret;
344}
345
346/*
347 * Stop transmitting.
348 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200349static void atmel_stop_tx(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000350{
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100351 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
352
Elen Song64e22eb2013-07-22 16:30:24 +0800353 if (atmel_use_pdc_tx(port)) {
Chip Coldwella6670612008-02-08 04:21:06 -0800354 /* disable PDC transmit */
355 UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100356 }
357 /* Disable interrupts */
358 UART_PUT_IDR(port, atmel_port->tx_done_mask);
359
Bernhard Roth83cac9f2011-08-24 09:48:23 +0200360 if ((atmel_port->rs485.flags & SER_RS485_ENABLED) &&
361 !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX))
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100362 atmel_start_rx(port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000363}
364
365/*
366 * Start transmitting.
367 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200368static void atmel_start_tx(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000369{
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100370 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
371
Elen Song64e22eb2013-07-22 16:30:24 +0800372 if (atmel_use_pdc_tx(port)) {
Chip Coldwella6670612008-02-08 04:21:06 -0800373 if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
374 /* The transmitter is already running. Yes, we
375 really need this.*/
376 return;
377
Bernhard Roth83cac9f2011-08-24 09:48:23 +0200378 if ((atmel_port->rs485.flags & SER_RS485_ENABLED) &&
379 !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX))
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100380 atmel_stop_rx(port);
381
Chip Coldwella6670612008-02-08 04:21:06 -0800382 /* re-enable PDC transmit */
383 UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100384 }
385 /* Enable interrupts */
386 UART_PUT_IER(port, atmel_port->tx_done_mask);
387}
388
389/*
390 * start receiving - port is in process of being opened.
391 */
392static void atmel_start_rx(struct uart_port *port)
393{
394 UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */
395
Siftar, Gabe57c36862012-03-29 15:40:05 +0200396 UART_PUT_CR(port, ATMEL_US_RXEN);
397
Elen Song64e22eb2013-07-22 16:30:24 +0800398 if (atmel_use_pdc_rx(port)) {
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100399 /* enable PDC controller */
400 UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
401 port->read_status_mask);
402 UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
403 } else {
404 UART_PUT_IER(port, ATMEL_US_RXRDY);
405 }
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000406}
407
408/*
409 * Stop receiving - port is in process of being closed.
410 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200411static void atmel_stop_rx(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000412{
Siftar, Gabe57c36862012-03-29 15:40:05 +0200413 UART_PUT_CR(port, ATMEL_US_RXDIS);
414
Elen Song64e22eb2013-07-22 16:30:24 +0800415 if (atmel_use_pdc_rx(port)) {
Chip Coldwella6670612008-02-08 04:21:06 -0800416 /* disable PDC receive */
417 UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100418 UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
419 port->read_status_mask);
420 } else {
Chip Coldwella6670612008-02-08 04:21:06 -0800421 UART_PUT_IDR(port, ATMEL_US_RXRDY);
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100422 }
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000423}
424
425/*
426 * Enable modem status interrupts
427 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200428static void atmel_enable_ms(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000429{
Remy Bohmerb843aa22008-02-08 04:21:01 -0800430 UART_PUT_IER(port, ATMEL_US_RIIC | ATMEL_US_DSRIC
431 | ATMEL_US_DCDIC | ATMEL_US_CTSIC);
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000432}
433
434/*
435 * Control the transmission of a break signal
436 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200437static void atmel_break_ctl(struct uart_port *port, int break_state)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000438{
439 if (break_state != 0)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200440 UART_PUT_CR(port, ATMEL_US_STTBRK); /* start break */
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000441 else
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200442 UART_PUT_CR(port, ATMEL_US_STPBRK); /* stop break */
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000443}
444
445/*
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800446 * Stores the incoming character in the ring buffer
447 */
448static void
449atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
450 unsigned int ch)
451{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800452 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800453 struct circ_buf *ring = &atmel_port->rx_ring;
454 struct atmel_uart_char *c;
455
456 if (!CIRC_SPACE(ring->head, ring->tail, ATMEL_SERIAL_RINGSIZE))
457 /* Buffer overflow, ignore char */
458 return;
459
460 c = &((struct atmel_uart_char *)ring->buf)[ring->head];
461 c->status = status;
462 c->ch = ch;
463
464 /* Make sure the character is stored before we update head. */
465 smp_wmb();
466
467 ring->head = (ring->head + 1) & (ATMEL_SERIAL_RINGSIZE - 1);
468}
469
470/*
Chip Coldwella6670612008-02-08 04:21:06 -0800471 * Deal with parity, framing and overrun errors.
472 */
473static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
474{
475 /* clear error */
476 UART_PUT_CR(port, ATMEL_US_RSTSTA);
477
478 if (status & ATMEL_US_RXBRK) {
479 /* ignore side-effect */
480 status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);
481 port->icount.brk++;
482 }
483 if (status & ATMEL_US_PARE)
484 port->icount.parity++;
485 if (status & ATMEL_US_FRAME)
486 port->icount.frame++;
487 if (status & ATMEL_US_OVRE)
488 port->icount.overrun++;
489}
490
491/*
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000492 * Characters received (called from interrupt handler)
493 */
David Howells7d12e782006-10-05 14:55:46 +0100494static void atmel_rx_chars(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000495{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800496 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800497 unsigned int status, ch;
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000498
Andrew Victorafefc412006-06-19 19:53:19 +0100499 status = UART_GET_CSR(port);
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200500 while (status & ATMEL_US_RXRDY) {
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000501 ch = UART_GET_CHAR(port);
502
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000503 /*
504 * note that the error handling code is
505 * out of the main execution path
506 */
Haavard Skinnemoen9e6077b2007-07-15 23:40:36 -0700507 if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
508 | ATMEL_US_OVRE | ATMEL_US_RXBRK)
509 || atmel_port->break_active)) {
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800510
Remy Bohmerb843aa22008-02-08 04:21:01 -0800511 /* clear error */
512 UART_PUT_CR(port, ATMEL_US_RSTSTA);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800513
Haavard Skinnemoen9e6077b2007-07-15 23:40:36 -0700514 if (status & ATMEL_US_RXBRK
515 && !atmel_port->break_active) {
Haavard Skinnemoen9e6077b2007-07-15 23:40:36 -0700516 atmel_port->break_active = 1;
517 UART_PUT_IER(port, ATMEL_US_RXBRK);
Haavard Skinnemoen9e6077b2007-07-15 23:40:36 -0700518 } else {
519 /*
520 * This is either the end-of-break
521 * condition or we've received at
522 * least one character without RXBRK
523 * being set. In both cases, the next
524 * RXBRK will indicate start-of-break.
525 */
526 UART_PUT_IDR(port, ATMEL_US_RXBRK);
527 status &= ~ATMEL_US_RXBRK;
528 atmel_port->break_active = 0;
Andrew Victorafefc412006-06-19 19:53:19 +0100529 }
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000530 }
531
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800532 atmel_buffer_rx_char(port, status, ch);
Andrew Victorafefc412006-06-19 19:53:19 +0100533 status = UART_GET_CSR(port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000534 }
535
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800536 tasklet_schedule(&atmel_port->tasklet);
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000537}
538
539/*
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800540 * Transmit characters (called from tasklet with TXRDY interrupt
541 * disabled)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000542 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +0200543static void atmel_tx_chars(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000544{
Alan Coxebd2c8f2009-09-19 13:13:28 -0700545 struct circ_buf *xmit = &port->state->xmit;
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100546 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000547
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100548 if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000549 UART_PUT_CHAR(port, port->x_char);
550 port->icount.tx++;
551 port->x_char = 0;
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000552 }
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800553 if (uart_circ_empty(xmit) || uart_tx_stopped(port))
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000554 return;
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000555
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100556 while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000557 UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
558 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
559 port->icount.tx++;
560 if (uart_circ_empty(xmit))
561 break;
562 }
563
564 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
565 uart_write_wakeup(port);
566
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800567 if (!uart_circ_empty(xmit))
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100568 /* Enable interrupts */
569 UART_PUT_IER(port, atmel_port->tx_done_mask);
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000570}
571
572/*
Remy Bohmerb843aa22008-02-08 04:21:01 -0800573 * receive interrupt handler.
574 */
575static void
576atmel_handle_receive(struct uart_port *port, unsigned int pending)
577{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800578 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Remy Bohmerb843aa22008-02-08 04:21:01 -0800579
Elen Song64e22eb2013-07-22 16:30:24 +0800580 if (atmel_use_pdc_rx(port)) {
Chip Coldwella6670612008-02-08 04:21:06 -0800581 /*
582 * PDC receive. Just schedule the tasklet and let it
583 * figure out the details.
584 *
585 * TODO: We're not handling error flags correctly at
586 * the moment.
587 */
588 if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
589 UART_PUT_IDR(port, (ATMEL_US_ENDRX
590 | ATMEL_US_TIMEOUT));
591 tasklet_schedule(&atmel_port->tasklet);
592 }
593
594 if (pending & (ATMEL_US_RXBRK | ATMEL_US_OVRE |
595 ATMEL_US_FRAME | ATMEL_US_PARE))
596 atmel_pdc_rxerr(port, pending);
597 }
598
Remy Bohmerb843aa22008-02-08 04:21:01 -0800599 /* Interrupt receive */
600 if (pending & ATMEL_US_RXRDY)
601 atmel_rx_chars(port);
602 else if (pending & ATMEL_US_RXBRK) {
603 /*
604 * End of break detected. If it came along with a
605 * character, atmel_rx_chars will handle it.
606 */
607 UART_PUT_CR(port, ATMEL_US_RSTSTA);
608 UART_PUT_IDR(port, ATMEL_US_RXBRK);
609 atmel_port->break_active = 0;
610 }
611}
612
613/*
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800614 * transmit interrupt handler. (Transmit is IRQF_NODELAY safe)
Remy Bohmerb843aa22008-02-08 04:21:01 -0800615 */
616static void
617atmel_handle_transmit(struct uart_port *port, unsigned int pending)
618{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800619 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800620
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100621 if (pending & atmel_port->tx_done_mask) {
622 /* Either PDC or interrupt transmission */
623 UART_PUT_IDR(port, atmel_port->tx_done_mask);
624 tasklet_schedule(&atmel_port->tasklet);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800625 }
Remy Bohmerb843aa22008-02-08 04:21:01 -0800626}
627
628/*
629 * status flags interrupt handler.
630 */
631static void
632atmel_handle_status(struct uart_port *port, unsigned int pending,
633 unsigned int status)
634{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800635 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800636
Remy Bohmerb843aa22008-02-08 04:21:01 -0800637 if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800638 | ATMEL_US_CTSIC)) {
639 atmel_port->irq_status = status;
640 tasklet_schedule(&atmel_port->tasklet);
641 }
Remy Bohmerb843aa22008-02-08 04:21:01 -0800642}
643
644/*
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000645 * Interrupt handler
646 */
David Howells7d12e782006-10-05 14:55:46 +0100647static irqreturn_t atmel_interrupt(int irq, void *dev_id)
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000648{
649 struct uart_port *port = dev_id;
650 unsigned int status, pending, pass_counter = 0;
651
Chip Coldwella6670612008-02-08 04:21:06 -0800652 do {
653 status = UART_GET_CSR(port);
654 pending = status & UART_GET_IMR(port);
655 if (!pending)
656 break;
657
Remy Bohmerb843aa22008-02-08 04:21:01 -0800658 atmel_handle_receive(port, pending);
659 atmel_handle_status(port, pending, status);
660 atmel_handle_transmit(port, pending);
Chip Coldwella6670612008-02-08 04:21:06 -0800661 } while (pass_counter++ < ATMEL_ISR_PASS_LIMIT);
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000662
Haavard Skinnemoen0400b692008-02-23 15:23:36 -0800663 return pass_counter ? IRQ_HANDLED : IRQ_NONE;
Andrew Victor1e6c9c22006-01-10 16:59:27 +0000664}
665
Elen Songa930e522013-07-22 16:30:25 +0800666static void atmel_release_tx_pdc(struct uart_port *port)
667{
668 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
669 struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
670
671 dma_unmap_single(port->dev,
672 pdc->dma_addr,
673 pdc->dma_size,
674 DMA_TO_DEVICE);
675}
676
Chip Coldwella6670612008-02-08 04:21:06 -0800677/*
678 * Called from tasklet with ENDTX and TXBUFE interrupts disabled.
679 */
Elen Song64e22eb2013-07-22 16:30:24 +0800680static void atmel_tx_pdc(struct uart_port *port)
Chip Coldwella6670612008-02-08 04:21:06 -0800681{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800682 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Alan Coxebd2c8f2009-09-19 13:13:28 -0700683 struct circ_buf *xmit = &port->state->xmit;
Chip Coldwella6670612008-02-08 04:21:06 -0800684 struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
685 int count;
686
Michael Trimarchiba0657f2008-04-02 13:04:41 -0700687 /* nothing left to transmit? */
688 if (UART_GET_TCR(port))
689 return;
690
Chip Coldwella6670612008-02-08 04:21:06 -0800691 xmit->tail += pdc->ofs;
692 xmit->tail &= UART_XMIT_SIZE - 1;
693
694 port->icount.tx += pdc->ofs;
695 pdc->ofs = 0;
696
Michael Trimarchiba0657f2008-04-02 13:04:41 -0700697 /* more to transmit - setup next transfer */
Chip Coldwella6670612008-02-08 04:21:06 -0800698
Michael Trimarchiba0657f2008-04-02 13:04:41 -0700699 /* disable PDC transmit */
700 UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
701
Itai Levi1f140812009-01-15 13:50:43 -0800702 if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
Chip Coldwella6670612008-02-08 04:21:06 -0800703 dma_sync_single_for_device(port->dev,
704 pdc->dma_addr,
705 pdc->dma_size,
706 DMA_TO_DEVICE);
707
708 count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
709 pdc->ofs = count;
710
711 UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
712 UART_PUT_TCR(port, count);
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100713 /* re-enable PDC transmit */
Chip Coldwella6670612008-02-08 04:21:06 -0800714 UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100715 /* Enable interrupts */
716 UART_PUT_IER(port, atmel_port->tx_done_mask);
717 } else {
Bernhard Roth83cac9f2011-08-24 09:48:23 +0200718 if ((atmel_port->rs485.flags & SER_RS485_ENABLED) &&
719 !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) {
Claudio Scordinoe8faff72010-05-03 13:31:28 +0100720 /* DMA done, stop TX, start RX for RS485 */
721 atmel_start_rx(port);
722 }
Chip Coldwella6670612008-02-08 04:21:06 -0800723 }
724
725 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
726 uart_write_wakeup(port);
727}
728
Elen Songa930e522013-07-22 16:30:25 +0800729static int atmel_prepare_tx_pdc(struct uart_port *port)
730{
731 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
732 struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
733 struct circ_buf *xmit = &port->state->xmit;
734
735 pdc->buf = xmit->buf;
736 pdc->dma_addr = dma_map_single(port->dev,
737 pdc->buf,
738 UART_XMIT_SIZE,
739 DMA_TO_DEVICE);
740 pdc->dma_size = UART_XMIT_SIZE;
741 pdc->ofs = 0;
742
743 return 0;
744}
745
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800746static void atmel_rx_from_ring(struct uart_port *port)
747{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800748 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800749 struct circ_buf *ring = &atmel_port->rx_ring;
750 unsigned int flg;
751 unsigned int status;
752
753 while (ring->head != ring->tail) {
754 struct atmel_uart_char c;
755
756 /* Make sure c is loaded after head. */
757 smp_rmb();
758
759 c = ((struct atmel_uart_char *)ring->buf)[ring->tail];
760
761 ring->tail = (ring->tail + 1) & (ATMEL_SERIAL_RINGSIZE - 1);
762
763 port->icount.rx++;
764 status = c.status;
765 flg = TTY_NORMAL;
766
767 /*
768 * note that the error handling code is
769 * out of the main execution path
770 */
771 if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
772 | ATMEL_US_OVRE | ATMEL_US_RXBRK))) {
773 if (status & ATMEL_US_RXBRK) {
774 /* ignore side-effect */
775 status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);
776
777 port->icount.brk++;
778 if (uart_handle_break(port))
779 continue;
780 }
781 if (status & ATMEL_US_PARE)
782 port->icount.parity++;
783 if (status & ATMEL_US_FRAME)
784 port->icount.frame++;
785 if (status & ATMEL_US_OVRE)
786 port->icount.overrun++;
787
788 status &= port->read_status_mask;
789
790 if (status & ATMEL_US_RXBRK)
791 flg = TTY_BREAK;
792 else if (status & ATMEL_US_PARE)
793 flg = TTY_PARITY;
794 else if (status & ATMEL_US_FRAME)
795 flg = TTY_FRAME;
796 }
797
798
799 if (uart_handle_sysrq_char(port, c.ch))
800 continue;
801
802 uart_insert_char(port, status, ATMEL_US_OVRE, c.ch, flg);
803 }
804
805 /*
806 * Drop the lock here since it might end up calling
807 * uart_start(), which takes the lock.
808 */
809 spin_unlock(&port->lock);
Jiri Slaby2e124b42013-01-03 15:53:06 +0100810 tty_flip_buffer_push(&port->state->port);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800811 spin_lock(&port->lock);
812}
813
Elen Songa930e522013-07-22 16:30:25 +0800814static void atmel_release_rx_pdc(struct uart_port *port)
815{
816 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
817 int i;
818
819 for (i = 0; i < 2; i++) {
820 struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
821
822 dma_unmap_single(port->dev,
823 pdc->dma_addr,
824 pdc->dma_size,
825 DMA_FROM_DEVICE);
826 kfree(pdc->buf);
827 }
828}
829
Elen Song64e22eb2013-07-22 16:30:24 +0800830static void atmel_rx_from_pdc(struct uart_port *port)
Chip Coldwella6670612008-02-08 04:21:06 -0800831{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800832 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100833 struct tty_port *tport = &port->state->port;
Chip Coldwella6670612008-02-08 04:21:06 -0800834 struct atmel_dma_buffer *pdc;
835 int rx_idx = atmel_port->pdc_rx_idx;
836 unsigned int head;
837 unsigned int tail;
838 unsigned int count;
839
840 do {
841 /* Reset the UART timeout early so that we don't miss one */
842 UART_PUT_CR(port, ATMEL_US_STTTO);
843
844 pdc = &atmel_port->pdc_rx[rx_idx];
845 head = UART_GET_RPR(port) - pdc->dma_addr;
846 tail = pdc->ofs;
847
848 /* If the PDC has switched buffers, RPR won't contain
849 * any address within the current buffer. Since head
850 * is unsigned, we just need a one-way comparison to
851 * find out.
852 *
853 * In this case, we just need to consume the entire
854 * buffer and resubmit it for DMA. This will clear the
855 * ENDRX bit as well, so that we can safely re-enable
856 * all interrupts below.
857 */
858 head = min(head, pdc->dma_size);
859
860 if (likely(head != tail)) {
861 dma_sync_single_for_cpu(port->dev, pdc->dma_addr,
862 pdc->dma_size, DMA_FROM_DEVICE);
863
864 /*
865 * head will only wrap around when we recycle
866 * the DMA buffer, and when that happens, we
867 * explicitly set tail to 0. So head will
868 * always be greater than tail.
869 */
870 count = head - tail;
871
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100872 tty_insert_flip_string(tport, pdc->buf + pdc->ofs,
873 count);
Chip Coldwella6670612008-02-08 04:21:06 -0800874
875 dma_sync_single_for_device(port->dev, pdc->dma_addr,
876 pdc->dma_size, DMA_FROM_DEVICE);
877
878 port->icount.rx += count;
879 pdc->ofs = head;
880 }
881
882 /*
883 * If the current buffer is full, we need to check if
884 * the next one contains any additional data.
885 */
886 if (head >= pdc->dma_size) {
887 pdc->ofs = 0;
888 UART_PUT_RNPR(port, pdc->dma_addr);
889 UART_PUT_RNCR(port, pdc->dma_size);
890
891 rx_idx = !rx_idx;
892 atmel_port->pdc_rx_idx = rx_idx;
893 }
894 } while (head >= pdc->dma_size);
895
896 /*
897 * Drop the lock here since it might end up calling
898 * uart_start(), which takes the lock.
899 */
900 spin_unlock(&port->lock);
Jiri Slaby2e124b42013-01-03 15:53:06 +0100901 tty_flip_buffer_push(tport);
Chip Coldwella6670612008-02-08 04:21:06 -0800902 spin_lock(&port->lock);
903
904 UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
905}
906
Elen Songa930e522013-07-22 16:30:25 +0800907static int atmel_prepare_rx_pdc(struct uart_port *port)
908{
909 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
910 int i;
911
912 for (i = 0; i < 2; i++) {
913 struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
914
915 pdc->buf = kmalloc(PDC_BUFFER_SIZE, GFP_KERNEL);
916 if (pdc->buf == NULL) {
917 if (i != 0) {
918 dma_unmap_single(port->dev,
919 atmel_port->pdc_rx[0].dma_addr,
920 PDC_BUFFER_SIZE,
921 DMA_FROM_DEVICE);
922 kfree(atmel_port->pdc_rx[0].buf);
923 }
924 atmel_port->use_pdc_rx = 0;
925 return -ENOMEM;
926 }
927 pdc->dma_addr = dma_map_single(port->dev,
928 pdc->buf,
929 PDC_BUFFER_SIZE,
930 DMA_FROM_DEVICE);
931 pdc->dma_size = PDC_BUFFER_SIZE;
932 pdc->ofs = 0;
933 }
934
935 atmel_port->pdc_rx_idx = 0;
936
937 UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
938 UART_PUT_RCR(port, PDC_BUFFER_SIZE);
939
940 UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
941 UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
942
943 return 0;
944}
945
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800946/*
947 * tasklet handling tty stuff outside the interrupt handler.
948 */
949static void atmel_tasklet_func(unsigned long data)
950{
951 struct uart_port *port = (struct uart_port *)data;
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -0800952 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800953 unsigned int status;
954 unsigned int status_change;
955
956 /* The interrupt handler does not take the lock */
957 spin_lock(&port->lock);
958
Elen Songa930e522013-07-22 16:30:25 +0800959 atmel_port->schedule_tx(port);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800960
961 status = atmel_port->irq_status;
962 status_change = status ^ atmel_port->irq_status_prev;
963
964 if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
965 | ATMEL_US_DCD | ATMEL_US_CTS)) {
966 /* TODO: All reads to CSR will clear these interrupts! */
967 if (status_change & ATMEL_US_RI)
968 port->icount.rng++;
969 if (status_change & ATMEL_US_DSR)
970 port->icount.dsr++;
971 if (status_change & ATMEL_US_DCD)
972 uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
973 if (status_change & ATMEL_US_CTS)
974 uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
975
Alan Coxbdc04e32009-09-19 13:13:31 -0700976 wake_up_interruptible(&port->state->port.delta_msr_wait);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800977
978 atmel_port->irq_status_prev = status;
979 }
980
Elen Songa930e522013-07-22 16:30:25 +0800981 atmel_port->schedule_rx(port);
Remy Bohmer1ecc26b2008-02-08 04:21:05 -0800982
983 spin_unlock(&port->lock);
984}
985
Elen Songa930e522013-07-22 16:30:25 +0800986static void atmel_set_ops(struct uart_port *port)
987{
988 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
989
990 if (atmel_use_pdc_rx(port)) {
991 atmel_port->prepare_rx = &atmel_prepare_rx_pdc;
992 atmel_port->schedule_rx = &atmel_rx_from_pdc;
993 atmel_port->release_rx = &atmel_release_rx_pdc;
994 } else {
995 atmel_port->prepare_rx = NULL;
996 atmel_port->schedule_rx = &atmel_rx_from_ring;
997 atmel_port->release_rx = NULL;
998 }
999
1000 if (atmel_use_pdc_tx(port)) {
1001 atmel_port->prepare_tx = &atmel_prepare_tx_pdc;
1002 atmel_port->schedule_tx = &atmel_tx_pdc;
1003 atmel_port->release_tx = &atmel_release_tx_pdc;
1004 } else {
1005 atmel_port->prepare_tx = NULL;
1006 atmel_port->schedule_tx = &atmel_tx_chars;
1007 atmel_port->release_tx = NULL;
1008 }
1009}
1010
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001011/*
1012 * Perform initialization and enable port for reception
1013 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001014static int atmel_startup(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001015{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -08001016 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Alan Coxebd2c8f2009-09-19 13:13:28 -07001017 struct tty_struct *tty = port->state->port.tty;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001018 int retval;
1019
1020 /*
1021 * Ensure that no interrupts are enabled otherwise when
1022 * request_irq() is called we could get stuck trying to
1023 * handle an unexpected interrupt
1024 */
1025 UART_PUT_IDR(port, -1);
1026
1027 /*
1028 * Allocate the IRQ
1029 */
Remy Bohmerb843aa22008-02-08 04:21:01 -08001030 retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED,
Haavard Skinnemoenae161062008-02-08 04:21:08 -08001031 tty ? tty->name : "atmel_serial", port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001032 if (retval) {
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001033 printk("atmel_serial: atmel_startup - Can't get irq\n");
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001034 return retval;
1035 }
1036
1037 /*
Chip Coldwella6670612008-02-08 04:21:06 -08001038 * Initialize DMA (if necessary)
1039 */
Elen Songa930e522013-07-22 16:30:25 +08001040 if (atmel_port->prepare_rx) {
1041 retval = atmel_port->prepare_rx(port);
1042 if (retval < 0)
1043 atmel_set_ops(port);
Chip Coldwella6670612008-02-08 04:21:06 -08001044 }
1045
Elen Songa930e522013-07-22 16:30:25 +08001046 if (atmel_port->prepare_tx) {
1047 retval = atmel_port->prepare_tx(port);
1048 if (retval < 0)
1049 atmel_set_ops(port);
1050 }
Chip Coldwella6670612008-02-08 04:21:06 -08001051 /*
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001052 * If there is a specific "open" function (to register
1053 * control line interrupts)
1054 */
Haavard Skinnemoen71f2e2b2006-10-04 16:02:07 +02001055 if (atmel_open_hook) {
1056 retval = atmel_open_hook(port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001057 if (retval) {
1058 free_irq(port->irq, port);
1059 return retval;
1060 }
1061 }
1062
Atsushi Nemoto27c0c8e2009-02-18 14:48:28 -08001063 /* Save current CSR for comparison in atmel_tasklet_func() */
1064 atmel_port->irq_status_prev = UART_GET_CSR(port);
1065 atmel_port->irq_status = atmel_port->irq_status_prev;
1066
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001067 /*
1068 * Finally, enable the serial port
1069 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001070 UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
Remy Bohmerb843aa22008-02-08 04:21:01 -08001071 /* enable xmit & rcvr */
1072 UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
Andrew Victorafefc412006-06-19 19:53:19 +01001073
Elen Song64e22eb2013-07-22 16:30:24 +08001074 if (atmel_use_pdc_rx(port)) {
Chip Coldwella6670612008-02-08 04:21:06 -08001075 /* set UART timeout */
1076 UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
1077 UART_PUT_CR(port, ATMEL_US_STTTO);
1078
1079 UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
1080 /* enable PDC controller */
1081 UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
1082 } else {
1083 /* enable receive only */
1084 UART_PUT_IER(port, ATMEL_US_RXRDY);
1085 }
Andrew Victorafefc412006-06-19 19:53:19 +01001086
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001087 return 0;
1088}
1089
1090/*
1091 * Disable the port
1092 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001093static void atmel_shutdown(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001094{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -08001095 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Chip Coldwella6670612008-02-08 04:21:06 -08001096 /*
1097 * Ensure everything is stopped.
1098 */
1099 atmel_stop_rx(port);
1100 atmel_stop_tx(port);
1101
1102 /*
1103 * Shut-down the DMA.
1104 */
Elen Songa930e522013-07-22 16:30:25 +08001105 if (atmel_port->release_rx)
1106 atmel_port->release_rx(port);
1107 if (atmel_port->release_tx)
1108 atmel_port->release_tx(port);
Chip Coldwella6670612008-02-08 04:21:06 -08001109
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001110 /*
1111 * Disable all interrupts, port and break condition.
1112 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001113 UART_PUT_CR(port, ATMEL_US_RSTSTA);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001114 UART_PUT_IDR(port, -1);
1115
1116 /*
1117 * Free the interrupt
1118 */
1119 free_irq(port->irq, port);
1120
1121 /*
1122 * If there is a specific "close" function (to unregister
1123 * control line interrupts)
1124 */
Haavard Skinnemoen71f2e2b2006-10-04 16:02:07 +02001125 if (atmel_close_hook)
1126 atmel_close_hook(port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001127}
1128
1129/*
Haavard Skinnemoen9afd5612008-07-16 21:52:46 +01001130 * Flush any TX data submitted for DMA. Called when the TX circular
1131 * buffer is reset.
1132 */
1133static void atmel_flush_buffer(struct uart_port *port)
1134{
1135 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1136
Elen Song64e22eb2013-07-22 16:30:24 +08001137 if (atmel_use_pdc_tx(port)) {
Haavard Skinnemoen9afd5612008-07-16 21:52:46 +01001138 UART_PUT_TCR(port, 0);
1139 atmel_port->pdc_tx.ofs = 0;
1140 }
1141}
1142
1143/*
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001144 * Power / Clock management.
1145 */
Remy Bohmerb843aa22008-02-08 04:21:01 -08001146static void atmel_serial_pm(struct uart_port *port, unsigned int state,
1147 unsigned int oldstate)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001148{
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -08001149 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Andrew Victorafefc412006-06-19 19:53:19 +01001150
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001151 switch (state) {
Remy Bohmerb843aa22008-02-08 04:21:01 -08001152 case 0:
1153 /*
1154 * Enable the peripheral clock for this serial port.
1155 * This is called on uart_open() or a resume event.
1156 */
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001157 clk_prepare_enable(atmel_port->clk);
Anti Sullinf05596d2008-09-22 13:57:54 -07001158
1159 /* re-enable interrupts if we disabled some on suspend */
1160 UART_PUT_IER(port, atmel_port->backup_imr);
Remy Bohmerb843aa22008-02-08 04:21:01 -08001161 break;
1162 case 3:
Anti Sullinf05596d2008-09-22 13:57:54 -07001163 /* Back up the interrupt mask and disable all interrupts */
1164 atmel_port->backup_imr = UART_GET_IMR(port);
1165 UART_PUT_IDR(port, -1);
1166
Remy Bohmerb843aa22008-02-08 04:21:01 -08001167 /*
1168 * Disable the peripheral clock for this serial port.
1169 * This is called on uart_close() or a suspend event.
1170 */
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001171 clk_disable_unprepare(atmel_port->clk);
Remy Bohmerb843aa22008-02-08 04:21:01 -08001172 break;
1173 default:
1174 printk(KERN_ERR "atmel_serial: unknown pm %d\n", state);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001175 }
1176}
1177
1178/*
1179 * Change the port parameters
1180 */
Remy Bohmerb843aa22008-02-08 04:21:01 -08001181static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
1182 struct ktermios *old)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001183{
1184 unsigned long flags;
1185 unsigned int mode, imr, quot, baud;
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001186 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001187
Andrew Victor03abeac2007-05-03 12:26:24 +01001188 /* Get current mode register */
Remy Bohmerb843aa22008-02-08 04:21:01 -08001189 mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL
Peter Ma8e706c42009-03-31 10:31:02 -07001190 | ATMEL_US_NBSTOP | ATMEL_US_PAR
1191 | ATMEL_US_USMODE);
Andrew Victor03abeac2007-05-03 12:26:24 +01001192
Remy Bohmerb843aa22008-02-08 04:21:01 -08001193 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001194 quot = uart_get_divisor(port, baud);
1195
Remy Bohmerb843aa22008-02-08 04:21:01 -08001196 if (quot > 65535) { /* BRGR is 16-bit, so switch to slower clock */
Andrew Victor03abeac2007-05-03 12:26:24 +01001197 quot /= 8;
1198 mode |= ATMEL_US_USCLKS_MCK_DIV8;
1199 }
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001200
1201 /* byte size */
1202 switch (termios->c_cflag & CSIZE) {
1203 case CS5:
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001204 mode |= ATMEL_US_CHRL_5;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001205 break;
1206 case CS6:
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001207 mode |= ATMEL_US_CHRL_6;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001208 break;
1209 case CS7:
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001210 mode |= ATMEL_US_CHRL_7;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001211 break;
1212 default:
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001213 mode |= ATMEL_US_CHRL_8;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001214 break;
1215 }
1216
1217 /* stop bits */
1218 if (termios->c_cflag & CSTOPB)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001219 mode |= ATMEL_US_NBSTOP_2;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001220
1221 /* parity */
1222 if (termios->c_cflag & PARENB) {
Remy Bohmerb843aa22008-02-08 04:21:01 -08001223 /* Mark or Space parity */
1224 if (termios->c_cflag & CMSPAR) {
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001225 if (termios->c_cflag & PARODD)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001226 mode |= ATMEL_US_PAR_MARK;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001227 else
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001228 mode |= ATMEL_US_PAR_SPACE;
Remy Bohmerb843aa22008-02-08 04:21:01 -08001229 } else if (termios->c_cflag & PARODD)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001230 mode |= ATMEL_US_PAR_ODD;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001231 else
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001232 mode |= ATMEL_US_PAR_EVEN;
Remy Bohmerb843aa22008-02-08 04:21:01 -08001233 } else
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001234 mode |= ATMEL_US_PAR_NONE;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001235
Peter Ma8e706c42009-03-31 10:31:02 -07001236 /* hardware handshake (RTS/CTS) */
1237 if (termios->c_cflag & CRTSCTS)
1238 mode |= ATMEL_US_USMODE_HWHS;
1239 else
1240 mode |= ATMEL_US_USMODE_NORMAL;
1241
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001242 spin_lock_irqsave(&port->lock, flags);
1243
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001244 port->read_status_mask = ATMEL_US_OVRE;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001245 if (termios->c_iflag & INPCK)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001246 port->read_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001247 if (termios->c_iflag & (BRKINT | PARMRK))
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001248 port->read_status_mask |= ATMEL_US_RXBRK;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001249
Elen Song64e22eb2013-07-22 16:30:24 +08001250 if (atmel_use_pdc_rx(port))
Chip Coldwella6670612008-02-08 04:21:06 -08001251 /* need to enable error interrupts */
1252 UART_PUT_IER(port, port->read_status_mask);
1253
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001254 /*
1255 * Characters to ignore
1256 */
1257 port->ignore_status_mask = 0;
1258 if (termios->c_iflag & IGNPAR)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001259 port->ignore_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001260 if (termios->c_iflag & IGNBRK) {
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001261 port->ignore_status_mask |= ATMEL_US_RXBRK;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001262 /*
1263 * If we're ignoring parity and break indicators,
1264 * ignore overruns too (for real raw support).
1265 */
1266 if (termios->c_iflag & IGNPAR)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001267 port->ignore_status_mask |= ATMEL_US_OVRE;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001268 }
Remy Bohmerb843aa22008-02-08 04:21:01 -08001269 /* TODO: Ignore all characters if CREAD is set.*/
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001270
1271 /* update the per-port timeout */
1272 uart_update_timeout(port, termios->c_cflag, baud);
1273
Haavard Skinnemoen0ccad872009-06-16 17:02:03 +01001274 /*
1275 * save/disable interrupts. The tty layer will ensure that the
1276 * transmitter is empty if requested by the caller, so there's
1277 * no need to wait for it here.
1278 */
Remy Bohmerb843aa22008-02-08 04:21:01 -08001279 imr = UART_GET_IMR(port);
1280 UART_PUT_IDR(port, -1);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001281
1282 /* disable receiver and transmitter */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001283 UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001284
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001285 /* Resetting serial mode to RS232 (0x0) */
1286 mode &= ~ATMEL_US_USMODE;
1287
1288 if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
1289 dev_dbg(port->dev, "Setting UART to RS485\n");
Claudio Scordino93f33502011-11-09 15:51:49 +01001290 if ((atmel_port->rs485.delay_rts_after_send) > 0)
Claudio Scordino1b633182010-07-20 15:26:47 -07001291 UART_PUT_TTGR(port,
1292 atmel_port->rs485.delay_rts_after_send);
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001293 mode |= ATMEL_US_USMODE_RS485;
1294 } else {
1295 dev_dbg(port->dev, "Setting UART to RS232\n");
1296 }
1297
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001298 /* set the parity, stop bits and data size */
1299 UART_PUT_MR(port, mode);
1300
1301 /* set the baud rate */
1302 UART_PUT_BRGR(port, quot);
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001303 UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
1304 UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001305
1306 /* restore interrupts */
1307 UART_PUT_IER(port, imr);
1308
1309 /* CTS flow-control and modem-status interrupts */
1310 if (UART_ENABLE_MS(port, termios->c_cflag))
1311 port->ops->enable_ms(port);
1312
1313 spin_unlock_irqrestore(&port->lock, flags);
1314}
1315
Viktar Palstsiuk42bd7a42011-02-09 15:26:13 +01001316static void atmel_set_ldisc(struct uart_port *port, int new)
1317{
Jiri Slabyb54bf3b2011-11-09 21:33:44 +01001318 if (new == N_PPS) {
Viktar Palstsiuk42bd7a42011-02-09 15:26:13 +01001319 port->flags |= UPF_HARDPPS_CD;
1320 atmel_enable_ms(port);
1321 } else {
1322 port->flags &= ~UPF_HARDPPS_CD;
1323 }
1324}
1325
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001326/*
1327 * Return string describing the specified port
1328 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001329static const char *atmel_type(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001330{
Haavard Skinnemoen9ab4f882006-10-04 16:02:06 +02001331 return (port->type == PORT_ATMEL) ? "ATMEL_SERIAL" : NULL;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001332}
1333
1334/*
1335 * Release the memory region(s) being used by 'port'.
1336 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001337static void atmel_release_port(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001338{
Andrew Victorafefc412006-06-19 19:53:19 +01001339 struct platform_device *pdev = to_platform_device(port->dev);
1340 int size = pdev->resource[0].end - pdev->resource[0].start + 1;
1341
1342 release_mem_region(port->mapbase, size);
1343
1344 if (port->flags & UPF_IOREMAP) {
1345 iounmap(port->membase);
1346 port->membase = NULL;
1347 }
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001348}
1349
1350/*
1351 * Request the memory region(s) being used by 'port'.
1352 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001353static int atmel_request_port(struct uart_port *port)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001354{
Andrew Victorafefc412006-06-19 19:53:19 +01001355 struct platform_device *pdev = to_platform_device(port->dev);
1356 int size = pdev->resource[0].end - pdev->resource[0].start + 1;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001357
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001358 if (!request_mem_region(port->mapbase, size, "atmel_serial"))
Andrew Victorafefc412006-06-19 19:53:19 +01001359 return -EBUSY;
1360
1361 if (port->flags & UPF_IOREMAP) {
1362 port->membase = ioremap(port->mapbase, size);
1363 if (port->membase == NULL) {
1364 release_mem_region(port->mapbase, size);
1365 return -ENOMEM;
1366 }
1367 }
1368
1369 return 0;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001370}
1371
1372/*
1373 * Configure/autoconfigure the port.
1374 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001375static void atmel_config_port(struct uart_port *port, int flags)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001376{
1377 if (flags & UART_CONFIG_TYPE) {
Haavard Skinnemoen9ab4f882006-10-04 16:02:06 +02001378 port->type = PORT_ATMEL;
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001379 atmel_request_port(port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001380 }
1381}
1382
1383/*
1384 * Verify the new serial_struct (for TIOCSSERIAL).
1385 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001386static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001387{
1388 int ret = 0;
Haavard Skinnemoen9ab4f882006-10-04 16:02:06 +02001389 if (ser->type != PORT_UNKNOWN && ser->type != PORT_ATMEL)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001390 ret = -EINVAL;
1391 if (port->irq != ser->irq)
1392 ret = -EINVAL;
1393 if (ser->io_type != SERIAL_IO_MEM)
1394 ret = -EINVAL;
1395 if (port->uartclk / 16 != ser->baud_base)
1396 ret = -EINVAL;
1397 if ((void *)port->mapbase != ser->iomem_base)
1398 ret = -EINVAL;
1399 if (port->iobase != ser->port)
1400 ret = -EINVAL;
1401 if (ser->hub6 != 0)
1402 ret = -EINVAL;
1403 return ret;
1404}
1405
Albin Tonnerre8fe2d542009-12-09 12:31:32 -08001406#ifdef CONFIG_CONSOLE_POLL
1407static int atmel_poll_get_char(struct uart_port *port)
1408{
1409 while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
1410 cpu_relax();
1411
1412 return UART_GET_CHAR(port);
1413}
1414
1415static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
1416{
1417 while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
1418 cpu_relax();
1419
1420 UART_PUT_CHAR(port, ch);
1421}
1422#endif
1423
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001424static int
1425atmel_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
1426{
1427 struct serial_rs485 rs485conf;
1428
1429 switch (cmd) {
1430 case TIOCSRS485:
1431 if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,
1432 sizeof(rs485conf)))
1433 return -EFAULT;
1434
1435 atmel_config_rs485(port, &rs485conf);
1436 break;
1437
1438 case TIOCGRS485:
1439 if (copy_to_user((struct serial_rs485 *) arg,
1440 &(to_atmel_uart_port(port)->rs485),
1441 sizeof(rs485conf)))
1442 return -EFAULT;
1443 break;
1444
1445 default:
1446 return -ENOIOCTLCMD;
1447 }
1448 return 0;
1449}
1450
1451
1452
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001453static struct uart_ops atmel_pops = {
1454 .tx_empty = atmel_tx_empty,
1455 .set_mctrl = atmel_set_mctrl,
1456 .get_mctrl = atmel_get_mctrl,
1457 .stop_tx = atmel_stop_tx,
1458 .start_tx = atmel_start_tx,
1459 .stop_rx = atmel_stop_rx,
1460 .enable_ms = atmel_enable_ms,
1461 .break_ctl = atmel_break_ctl,
1462 .startup = atmel_startup,
1463 .shutdown = atmel_shutdown,
Haavard Skinnemoen9afd5612008-07-16 21:52:46 +01001464 .flush_buffer = atmel_flush_buffer,
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001465 .set_termios = atmel_set_termios,
Viktar Palstsiuk42bd7a42011-02-09 15:26:13 +01001466 .set_ldisc = atmel_set_ldisc,
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001467 .type = atmel_type,
1468 .release_port = atmel_release_port,
1469 .request_port = atmel_request_port,
1470 .config_port = atmel_config_port,
1471 .verify_port = atmel_verify_port,
1472 .pm = atmel_serial_pm,
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001473 .ioctl = atmel_ioctl,
Albin Tonnerre8fe2d542009-12-09 12:31:32 -08001474#ifdef CONFIG_CONSOLE_POLL
1475 .poll_get_char = atmel_poll_get_char,
1476 .poll_put_char = atmel_poll_put_char,
1477#endif
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001478};
1479
Bill Pemberton9671f092012-11-19 13:21:50 -05001480static void atmel_of_init_port(struct atmel_uart_port *atmel_port,
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001481 struct device_node *np)
1482{
1483 u32 rs485_delay[2];
1484
1485 /* DMA/PDC usage specification */
1486 if (of_get_property(np, "atmel,use-dma-rx", NULL))
Elen Song64e22eb2013-07-22 16:30:24 +08001487 atmel_port->use_pdc_rx = true;
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001488 else
Elen Song64e22eb2013-07-22 16:30:24 +08001489 atmel_port->use_pdc_rx = false;
1490
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001491 if (of_get_property(np, "atmel,use-dma-tx", NULL))
Elen Song64e22eb2013-07-22 16:30:24 +08001492 atmel_port->use_pdc_tx = true;
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001493 else
Elen Song64e22eb2013-07-22 16:30:24 +08001494 atmel_port->use_pdc_tx = false;
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001495
1496 /* rs485 properties */
1497 if (of_property_read_u32_array(np, "rs485-rts-delay",
1498 rs485_delay, 2) == 0) {
1499 struct serial_rs485 *rs485conf = &atmel_port->rs485;
1500
1501 rs485conf->delay_rts_before_send = rs485_delay[0];
1502 rs485conf->delay_rts_after_send = rs485_delay[1];
1503 rs485conf->flags = 0;
1504
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001505 if (of_get_property(np, "rs485-rx-during-tx", NULL))
1506 rs485conf->flags |= SER_RS485_RX_DURING_TX;
1507
1508 if (of_get_property(np, "linux,rs485-enabled-at-boot-time", NULL))
1509 rs485conf->flags |= SER_RS485_ENABLED;
1510 }
1511}
1512
Andrew Victorafefc412006-06-19 19:53:19 +01001513/*
1514 * Configure the port from the platform device resource info.
1515 */
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001516static int atmel_init_port(struct atmel_uart_port *atmel_port,
Remy Bohmerb843aa22008-02-08 04:21:01 -08001517 struct platform_device *pdev)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001518{
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001519 int ret;
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001520 struct uart_port *port = &atmel_port->uart;
Nicolas Ferre1acfc7e2011-10-12 18:06:57 +02001521 struct atmel_uart_data *pdata = pdev->dev.platform_data;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001522
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001523 if (pdev->dev.of_node) {
1524 atmel_of_init_port(atmel_port, pdev->dev.of_node);
1525 } else {
Elen Song64e22eb2013-07-22 16:30:24 +08001526 atmel_port->use_pdc_rx = pdata->use_dma_rx;
1527 atmel_port->use_pdc_tx = pdata->use_dma_tx;
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001528 atmel_port->rs485 = pdata->rs485;
1529 }
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001530
Elen Songa930e522013-07-22 16:30:25 +08001531 atmel_set_ops(port);
1532
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001533 port->iotype = UPIO_MEM;
1534 port->flags = UPF_BOOT_AUTOCONF;
1535 port->ops = &atmel_pops;
1536 port->fifosize = 1;
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001537 port->dev = &pdev->dev;
Andrew Victorafefc412006-06-19 19:53:19 +01001538 port->mapbase = pdev->resource[0].start;
1539 port->irq = pdev->resource[1].start;
1540
Remy Bohmer1ecc26b2008-02-08 04:21:05 -08001541 tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
1542 (unsigned long)port);
1543
1544 memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
1545
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001546 if (pdata && pdata->regs) {
Haavard Skinnemoen75d35212006-10-04 16:02:08 +02001547 /* Already mapped by setup code */
Nicolas Ferre1acfc7e2011-10-12 18:06:57 +02001548 port->membase = pdata->regs;
Nicolas Ferre588edbf2011-10-12 18:06:58 +02001549 } else {
Andrew Victorafefc412006-06-19 19:53:19 +01001550 port->flags |= UPF_IOREMAP;
1551 port->membase = NULL;
1552 }
1553
Remy Bohmerb843aa22008-02-08 04:21:01 -08001554 /* for console, the clock could already be configured */
1555 if (!atmel_port->clk) {
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001556 atmel_port->clk = clk_get(&pdev->dev, "usart");
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001557 if (IS_ERR(atmel_port->clk)) {
1558 ret = PTR_ERR(atmel_port->clk);
1559 atmel_port->clk = NULL;
1560 return ret;
1561 }
1562 ret = clk_prepare_enable(atmel_port->clk);
1563 if (ret) {
1564 clk_put(atmel_port->clk);
1565 atmel_port->clk = NULL;
1566 return ret;
1567 }
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001568 port->uartclk = clk_get_rate(atmel_port->clk);
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001569 clk_disable_unprepare(atmel_port->clk);
David Brownell06a7f052008-11-06 12:53:40 -08001570 /* only enable clock when USART is in use */
Andrew Victorafefc412006-06-19 19:53:19 +01001571 }
Chip Coldwella6670612008-02-08 04:21:06 -08001572
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001573 /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
1574 if (atmel_port->rs485.flags & SER_RS485_ENABLED)
1575 atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
Elen Song64e22eb2013-07-22 16:30:24 +08001576 else if (atmel_use_pdc_tx(port)) {
Chip Coldwella6670612008-02-08 04:21:06 -08001577 port->fifosize = PDC_BUFFER_SIZE;
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001578 atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE;
1579 } else {
1580 atmel_port->tx_done_mask = ATMEL_US_TXRDY;
1581 }
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001582
1583 return 0;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001584}
1585
Jean-Christophe PLAGNIOL-VILLARD69f6a272012-02-16 00:24:07 +08001586struct platform_device *atmel_default_console_device; /* the serial console device */
1587
Haavard Skinnemoen749c4e62006-10-04 16:02:02 +02001588#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001589static void atmel_console_putchar(struct uart_port *port, int ch)
Russell Kingd3587882006-03-20 20:00:09 +00001590{
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001591 while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
Haavard Skinnemoen829dd812008-02-08 04:21:02 -08001592 cpu_relax();
Russell Kingd3587882006-03-20 20:00:09 +00001593 UART_PUT_CHAR(port, ch);
1594}
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001595
1596/*
1597 * Interrupts are disabled on entering
1598 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001599static void atmel_console_write(struct console *co, const char *s, u_int count)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001600{
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001601 struct uart_port *port = &atmel_ports[co->index].uart;
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001602 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Russell Kingd3587882006-03-20 20:00:09 +00001603 unsigned int status, imr;
Marc Pignat39d4c922008-04-02 13:04:42 -07001604 unsigned int pdc_tx;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001605
1606 /*
Remy Bohmerb843aa22008-02-08 04:21:01 -08001607 * First, save IMR and then disable interrupts
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001608 */
Remy Bohmerb843aa22008-02-08 04:21:01 -08001609 imr = UART_GET_IMR(port);
Claudio Scordinoe8faff72010-05-03 13:31:28 +01001610 UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001611
Marc Pignat39d4c922008-04-02 13:04:42 -07001612 /* Store PDC transmit status and disable it */
1613 pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
1614 UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
1615
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001616 uart_console_write(port, s, count, atmel_console_putchar);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001617
1618 /*
Remy Bohmerb843aa22008-02-08 04:21:01 -08001619 * Finally, wait for transmitter to become empty
1620 * and restore IMR
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001621 */
1622 do {
1623 status = UART_GET_CSR(port);
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001624 } while (!(status & ATMEL_US_TXRDY));
Marc Pignat39d4c922008-04-02 13:04:42 -07001625
1626 /* Restore PDC transmit status */
1627 if (pdc_tx)
1628 UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
1629
Remy Bohmerb843aa22008-02-08 04:21:01 -08001630 /* set interrupts back the way they were */
1631 UART_PUT_IER(port, imr);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001632}
1633
1634/*
Remy Bohmerb843aa22008-02-08 04:21:01 -08001635 * If the port was already initialised (eg, by a boot loader),
1636 * try to determine the current setup.
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001637 */
Remy Bohmerb843aa22008-02-08 04:21:01 -08001638static void __init atmel_console_get_options(struct uart_port *port, int *baud,
1639 int *parity, int *bits)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001640{
1641 unsigned int mr, quot;
1642
Haavard Skinnemoen1c0fd822008-02-08 04:21:03 -08001643 /*
1644 * If the baud rate generator isn't running, the port wasn't
1645 * initialized by the boot loader.
1646 */
Haavard Skinnemoen9c81c5c2008-06-05 22:46:39 -07001647 quot = UART_GET_BRGR(port) & ATMEL_US_CD;
Haavard Skinnemoen1c0fd822008-02-08 04:21:03 -08001648 if (!quot)
1649 return;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001650
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001651 mr = UART_GET_MR(port) & ATMEL_US_CHRL;
1652 if (mr == ATMEL_US_CHRL_8)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001653 *bits = 8;
1654 else
1655 *bits = 7;
1656
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001657 mr = UART_GET_MR(port) & ATMEL_US_PAR;
1658 if (mr == ATMEL_US_PAR_EVEN)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001659 *parity = 'e';
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001660 else if (mr == ATMEL_US_PAR_ODD)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001661 *parity = 'o';
1662
Haavard Skinnemoen4d5e3922006-10-04 16:02:11 +02001663 /*
1664 * The serial core only rounds down when matching this to a
1665 * supported baud rate. Make sure we don't end up slightly
1666 * lower than one of those, as it would make us fall through
1667 * to a much lower baud rate than we really want.
1668 */
Haavard Skinnemoen4d5e3922006-10-04 16:02:11 +02001669 *baud = port->uartclk / (16 * (quot - 1));
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001670}
1671
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001672static int __init atmel_console_setup(struct console *co, char *options)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001673{
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001674 int ret;
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001675 struct uart_port *port = &atmel_ports[co->index].uart;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001676 int baud = 115200;
1677 int bits = 8;
1678 int parity = 'n';
1679 int flow = 'n';
1680
Remy Bohmerb843aa22008-02-08 04:21:01 -08001681 if (port->membase == NULL) {
1682 /* Port not initialized yet - delay setup */
Andrew Victorafefc412006-06-19 19:53:19 +01001683 return -ENODEV;
Remy Bohmerb843aa22008-02-08 04:21:01 -08001684 }
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001685
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001686 ret = clk_prepare_enable(atmel_ports[co->index].clk);
1687 if (ret)
1688 return ret;
David Brownell06a7f052008-11-06 12:53:40 -08001689
Remy Bohmerb843aa22008-02-08 04:21:01 -08001690 UART_PUT_IDR(port, -1);
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001691 UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
1692 UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001693
1694 if (options)
1695 uart_parse_options(options, &baud, &parity, &bits, &flow);
1696 else
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001697 atmel_console_get_options(port, &baud, &parity, &bits);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001698
1699 return uart_set_options(port, co, baud, parity, bits, flow);
1700}
1701
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001702static struct uart_driver atmel_uart;
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001703
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001704static struct console atmel_console = {
1705 .name = ATMEL_DEVICENAME,
1706 .write = atmel_console_write,
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001707 .device = uart_console_device,
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001708 .setup = atmel_console_setup,
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001709 .flags = CON_PRINTBUFFER,
1710 .index = -1,
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001711 .data = &atmel_uart,
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001712};
1713
David Brownell06a7f052008-11-06 12:53:40 -08001714#define ATMEL_CONSOLE_DEVICE (&atmel_console)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001715
Andrew Victorafefc412006-06-19 19:53:19 +01001716/*
1717 * Early console initialization (before VM subsystem initialized).
1718 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001719static int __init atmel_console_init(void)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001720{
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001721 int ret;
Haavard Skinnemoen73e27982006-10-04 16:02:04 +02001722 if (atmel_default_console_device) {
Voss, Nikolaus0d0a3cc2011-08-10 14:02:29 +02001723 struct atmel_uart_data *pdata =
1724 atmel_default_console_device->dev.platform_data;
Linus Torvaldsefb8d212011-10-26 15:11:09 +02001725 int id = pdata->num;
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001726 struct atmel_uart_port *port = &atmel_ports[id];
Voss, Nikolaus0d0a3cc2011-08-10 14:02:29 +02001727
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001728 port->backup_imr = 0;
1729 port->uart.line = id;
1730
1731 add_preferred_console(ATMEL_DEVICENAME, id, NULL);
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001732 ret = atmel_init_port(port, atmel_default_console_device);
1733 if (ret)
1734 return ret;
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001735 register_console(&atmel_console);
Andrew Victorafefc412006-06-19 19:53:19 +01001736 }
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001737
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001738 return 0;
1739}
Remy Bohmerb843aa22008-02-08 04:21:01 -08001740
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001741console_initcall(atmel_console_init);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001742
Andrew Victorafefc412006-06-19 19:53:19 +01001743/*
1744 * Late console initialization.
1745 */
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001746static int __init atmel_late_console_init(void)
Andrew Victorafefc412006-06-19 19:53:19 +01001747{
Remy Bohmerb843aa22008-02-08 04:21:01 -08001748 if (atmel_default_console_device
1749 && !(atmel_console.flags & CON_ENABLED))
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001750 register_console(&atmel_console);
Andrew Victorafefc412006-06-19 19:53:19 +01001751
1752 return 0;
1753}
Remy Bohmerb843aa22008-02-08 04:21:01 -08001754
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001755core_initcall(atmel_late_console_init);
Andrew Victorafefc412006-06-19 19:53:19 +01001756
Haavard Skinnemoendfa7f342008-02-08 04:21:04 -08001757static inline bool atmel_is_console_port(struct uart_port *port)
1758{
1759 return port->cons && port->cons->index == port->line;
1760}
1761
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001762#else
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001763#define ATMEL_CONSOLE_DEVICE NULL
Haavard Skinnemoendfa7f342008-02-08 04:21:04 -08001764
1765static inline bool atmel_is_console_port(struct uart_port *port)
1766{
1767 return false;
1768}
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001769#endif
1770
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001771static struct uart_driver atmel_uart = {
Remy Bohmerb843aa22008-02-08 04:21:01 -08001772 .owner = THIS_MODULE,
1773 .driver_name = "atmel_serial",
1774 .dev_name = ATMEL_DEVICENAME,
1775 .major = SERIAL_ATMEL_MAJOR,
1776 .minor = MINOR_START,
1777 .nr = ATMEL_MAX_UART,
1778 .cons = ATMEL_CONSOLE_DEVICE,
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001779};
1780
Andrew Victorafefc412006-06-19 19:53:19 +01001781#ifdef CONFIG_PM
Haavard Skinnemoenf826caa2008-02-24 14:34:45 +01001782static bool atmel_serial_clk_will_stop(void)
1783{
1784#ifdef CONFIG_ARCH_AT91
1785 return at91_suspend_entering_slow_clock();
1786#else
1787 return false;
1788#endif
1789}
1790
Remy Bohmerb843aa22008-02-08 04:21:01 -08001791static int atmel_serial_suspend(struct platform_device *pdev,
1792 pm_message_t state)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001793{
Andrew Victorafefc412006-06-19 19:53:19 +01001794 struct uart_port *port = platform_get_drvdata(pdev);
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -08001795 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001796
Haavard Skinnemoene1c609e2008-03-14 14:54:13 +01001797 if (atmel_is_console_port(port) && console_suspend_enabled) {
1798 /* Drain the TX shifter */
1799 while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
1800 cpu_relax();
1801 }
1802
Anti Sullinf05596d2008-09-22 13:57:54 -07001803 /* we can not wake up if we're running on slow clock */
1804 atmel_port->may_wakeup = device_may_wakeup(&pdev->dev);
1805 if (atmel_serial_clk_will_stop())
1806 device_set_wakeup_enable(&pdev->dev, 0);
1807
1808 uart_suspend_port(&atmel_uart, port);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001809
1810 return 0;
1811}
1812
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001813static int atmel_serial_resume(struct platform_device *pdev)
Andrew Victorafefc412006-06-19 19:53:19 +01001814{
1815 struct uart_port *port = platform_get_drvdata(pdev);
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -08001816 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Andrew Victorafefc412006-06-19 19:53:19 +01001817
Anti Sullinf05596d2008-09-22 13:57:54 -07001818 uart_resume_port(&atmel_uart, port);
1819 device_set_wakeup_enable(&pdev->dev, atmel_port->may_wakeup);
Andrew Victorafefc412006-06-19 19:53:19 +01001820
1821 return 0;
1822}
1823#else
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001824#define atmel_serial_suspend NULL
1825#define atmel_serial_resume NULL
Andrew Victorafefc412006-06-19 19:53:19 +01001826#endif
1827
Bill Pemberton9671f092012-11-19 13:21:50 -05001828static int atmel_serial_probe(struct platform_device *pdev)
Andrew Victorafefc412006-06-19 19:53:19 +01001829{
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001830 struct atmel_uart_port *port;
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001831 struct device_node *np = pdev->dev.of_node;
Jean-Christophe PLAGNIOL-VILLARDdeba1a02011-06-21 12:17:00 +08001832 struct atmel_uart_data *pdata = pdev->dev.platform_data;
Remy Bohmer1ecc26b2008-02-08 04:21:05 -08001833 void *data;
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001834 int ret = -ENODEV;
Andrew Victorafefc412006-06-19 19:53:19 +01001835
Haavard Skinnemoen9d09daf2009-10-26 16:50:02 -07001836 BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
Remy Bohmer1ecc26b2008-02-08 04:21:05 -08001837
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001838 if (np)
1839 ret = of_alias_get_id(np, "serial");
1840 else
1841 if (pdata)
1842 ret = pdata->num;
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001843
1844 if (ret < 0)
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001845 /* port id not found in platform data nor device-tree aliases:
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001846 * auto-enumerate it */
Pawel Wieczorkiewicz503bded2013-02-20 17:26:20 +01001847 ret = find_first_zero_bit(atmel_ports_in_use, ATMEL_MAX_UART);
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001848
Pawel Wieczorkiewicz503bded2013-02-20 17:26:20 +01001849 if (ret >= ATMEL_MAX_UART) {
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001850 ret = -ENODEV;
1851 goto err;
1852 }
1853
Pawel Wieczorkiewicz503bded2013-02-20 17:26:20 +01001854 if (test_and_set_bit(ret, atmel_ports_in_use)) {
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001855 /* port already in use */
1856 ret = -EBUSY;
1857 goto err;
1858 }
1859
1860 port = &atmel_ports[ret];
Anti Sullinf05596d2008-09-22 13:57:54 -07001861 port->backup_imr = 0;
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001862 port->uart.line = ret;
Anti Sullinf05596d2008-09-22 13:57:54 -07001863
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001864 ret = atmel_init_port(port, pdev);
1865 if (ret)
1866 goto err;
Andrew Victorafefc412006-06-19 19:53:19 +01001867
Elen Song64e22eb2013-07-22 16:30:24 +08001868 if (!atmel_use_pdc_rx(&port->uart)) {
Chip Coldwella6670612008-02-08 04:21:06 -08001869 ret = -ENOMEM;
Haavard Skinnemoen64334712008-02-08 04:21:07 -08001870 data = kmalloc(sizeof(struct atmel_uart_char)
1871 * ATMEL_SERIAL_RINGSIZE, GFP_KERNEL);
Chip Coldwella6670612008-02-08 04:21:06 -08001872 if (!data)
1873 goto err_alloc_ring;
1874 port->rx_ring.buf = data;
1875 }
Remy Bohmer1ecc26b2008-02-08 04:21:05 -08001876
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001877 ret = uart_add_one_port(&atmel_uart, &port->uart);
Haavard Skinnemoendfa7f342008-02-08 04:21:04 -08001878 if (ret)
1879 goto err_add_port;
1880
Albin Tonnerre8da14b52009-07-29 15:04:18 -07001881#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
David Brownell06a7f052008-11-06 12:53:40 -08001882 if (atmel_is_console_port(&port->uart)
1883 && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) {
1884 /*
1885 * The serial core enabled the clock for us, so undo
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001886 * the clk_prepare_enable() in atmel_console_setup()
David Brownell06a7f052008-11-06 12:53:40 -08001887 */
Boris BREZILLON91f8c2d2013-06-19 13:17:30 +02001888 clk_disable_unprepare(port->clk);
David Brownell06a7f052008-11-06 12:53:40 -08001889 }
Albin Tonnerre8da14b52009-07-29 15:04:18 -07001890#endif
David Brownell06a7f052008-11-06 12:53:40 -08001891
Haavard Skinnemoendfa7f342008-02-08 04:21:04 -08001892 device_init_wakeup(&pdev->dev, 1);
1893 platform_set_drvdata(pdev, port);
1894
Claudio Scordino5dfbd1d72011-01-13 15:45:39 -08001895 if (port->rs485.flags & SER_RS485_ENABLED) {
1896 UART_PUT_MR(&port->uart, ATMEL_US_USMODE_NORMAL);
1897 UART_PUT_CR(&port->uart, ATMEL_US_RTSEN);
1898 }
1899
Haavard Skinnemoendfa7f342008-02-08 04:21:04 -08001900 return 0;
1901
1902err_add_port:
Remy Bohmer1ecc26b2008-02-08 04:21:05 -08001903 kfree(port->rx_ring.buf);
1904 port->rx_ring.buf = NULL;
1905err_alloc_ring:
Haavard Skinnemoendfa7f342008-02-08 04:21:04 -08001906 if (!atmel_is_console_port(&port->uart)) {
Haavard Skinnemoendfa7f342008-02-08 04:21:04 -08001907 clk_put(port->clk);
1908 port->clk = NULL;
Andrew Victorafefc412006-06-19 19:53:19 +01001909 }
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001910err:
Andrew Victorafefc412006-06-19 19:53:19 +01001911 return ret;
1912}
1913
Bill Pembertonae8d8a12012-11-19 13:26:18 -05001914static int atmel_serial_remove(struct platform_device *pdev)
Andrew Victorafefc412006-06-19 19:53:19 +01001915{
1916 struct uart_port *port = platform_get_drvdata(pdev);
Haavard Skinnemoenc811ab82008-02-08 04:21:08 -08001917 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
Andrew Victorafefc412006-06-19 19:53:19 +01001918 int ret = 0;
1919
Andrew Victorafefc412006-06-19 19:53:19 +01001920 device_init_wakeup(&pdev->dev, 0);
Andrew Victorafefc412006-06-19 19:53:19 +01001921
Haavard Skinnemoendfa7f342008-02-08 04:21:04 -08001922 ret = uart_remove_one_port(&atmel_uart, port);
1923
Remy Bohmer1ecc26b2008-02-08 04:21:05 -08001924 tasklet_kill(&atmel_port->tasklet);
1925 kfree(atmel_port->rx_ring.buf);
1926
Haavard Skinnemoendfa7f342008-02-08 04:21:04 -08001927 /* "port" is allocated statically, so we shouldn't free it */
1928
Pawel Wieczorkiewicz503bded2013-02-20 17:26:20 +01001929 clear_bit(port->line, atmel_ports_in_use);
Nicolas Ferre4cbf9f42011-10-12 18:06:59 +02001930
Haavard Skinnemoendfa7f342008-02-08 04:21:04 -08001931 clk_put(atmel_port->clk);
Andrew Victorafefc412006-06-19 19:53:19 +01001932
1933 return ret;
1934}
1935
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001936static struct platform_driver atmel_serial_driver = {
1937 .probe = atmel_serial_probe,
Bill Pemberton2d47b712012-11-19 13:21:34 -05001938 .remove = atmel_serial_remove,
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001939 .suspend = atmel_serial_suspend,
1940 .resume = atmel_serial_resume,
Andrew Victorafefc412006-06-19 19:53:19 +01001941 .driver = {
Haavard Skinnemoen1e8ea802006-10-04 16:02:03 +02001942 .name = "atmel_usart",
Andrew Victorafefc412006-06-19 19:53:19 +01001943 .owner = THIS_MODULE,
Nicolas Ferre5fbe46b2011-10-12 18:07:00 +02001944 .of_match_table = of_match_ptr(atmel_serial_dt_ids),
Andrew Victorafefc412006-06-19 19:53:19 +01001945 },
1946};
1947
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001948static int __init atmel_serial_init(void)
Andrew Victorafefc412006-06-19 19:53:19 +01001949{
1950 int ret;
1951
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001952 ret = uart_register_driver(&atmel_uart);
Andrew Victorafefc412006-06-19 19:53:19 +01001953 if (ret)
1954 return ret;
1955
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001956 ret = platform_driver_register(&atmel_serial_driver);
Andrew Victorafefc412006-06-19 19:53:19 +01001957 if (ret)
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001958 uart_unregister_driver(&atmel_uart);
Andrew Victorafefc412006-06-19 19:53:19 +01001959
1960 return ret;
1961}
1962
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001963static void __exit atmel_serial_exit(void)
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001964{
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001965 platform_driver_unregister(&atmel_serial_driver);
1966 uart_unregister_driver(&atmel_uart);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001967}
1968
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001969module_init(atmel_serial_init);
1970module_exit(atmel_serial_exit);
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001971
1972MODULE_AUTHOR("Rick Bronson");
Haavard Skinnemoen7192f922006-10-04 16:02:05 +02001973MODULE_DESCRIPTION("Atmel AT91 / AT32 serial port driver");
Andrew Victor1e6c9c22006-01-10 16:59:27 +00001974MODULE_LICENSE("GPL");
Kay Sieverse169c132008-04-15 14:34:35 -07001975MODULE_ALIAS("platform:atmel_usart");