Blame view

drivers/serial/atmel_serial.c 44.4 KB
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1
  /*
c2f5ccfbd   Andrew Victor   [ARM] 3973/1: AT9...
2
   *  linux/drivers/char/atmel_serial.c
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
3
   *
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
4
   *  Driver for Atmel AT91 / AT32 Serial ports
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
5
6
7
8
9
   *  Copyright (C) 2003 Rick Bronson
   *
   *  Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
   *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
   *
a66706158   Chip Coldwell   atmel_serial: add...
10
11
   *  DMA support added by Chip Coldwell.
   *
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   *
   */
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
27
28
29
30
31
32
  #include <linux/module.h>
  #include <linux/tty.h>
  #include <linux/ioport.h>
  #include <linux/slab.h>
  #include <linux/init.h>
  #include <linux/serial.h>
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
33
  #include <linux/clk.h>
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
34
35
36
  #include <linux/console.h>
  #include <linux/sysrq.h>
  #include <linux/tty_flip.h>
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
37
  #include <linux/platform_device.h>
a66706158   Chip Coldwell   atmel_serial: add...
38
  #include <linux/dma-mapping.h>
93a3ddc20   Andrew Victor   [ARM] 4151/1: AT9...
39
  #include <linux/atmel_pdc.h>
fa3218d85   Guennadi Liakhovetski   [ARM] 4660/3: at9...
40
  #include <linux/atmel_serial.h>
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
41
  #include <linux/uaccess.h>
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
42
43
  
  #include <asm/io.h>
f7512e7c4   Peter Huewe   serial: fix rs485...
44
  #include <asm/ioctls.h>
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
45

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
46
  #include <asm/mach/serial_at91.h>
a09e64fbc   Russell King   [ARM] Move includ...
47
  #include <mach/board.h>
93a3ddc20   Andrew Victor   [ARM] 4151/1: AT9...
48

acca9b83a   Haavard Skinnemoen   [PATCH] atmel_ser...
49
  #ifdef CONFIG_ARM
a09e64fbc   Russell King   [ARM] Move includ...
50
51
  #include <mach/cpu.h>
  #include <mach/gpio.h>
acca9b83a   Haavard Skinnemoen   [PATCH] atmel_ser...
52
  #endif
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
53

a66706158   Chip Coldwell   atmel_serial: add...
54
55
56
  #define PDC_BUFFER_SIZE		512
  /* Revisit: We should calculate this based on the actual port settings */
  #define PDC_RX_TIMEOUT		(3 * 10)		/* 3 bytes */
749c4e603   Haavard Skinnemoen   [PATCH] at91_seri...
57
  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
58
59
60
61
  #define SUPPORT_SYSRQ
  #endif
  
  #include <linux/serial_core.h>
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
62
63
  static void atmel_start_rx(struct uart_port *port);
  static void atmel_stop_rx(struct uart_port *port);
749c4e603   Haavard Skinnemoen   [PATCH] at91_seri...
64
  #ifdef CONFIG_SERIAL_ATMEL_TTYAT
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
65
66
67
68
  
  /* Use device name ttyAT, major 204 and minor 154-169.  This is necessary if we
   * should coexist with the 8250 driver, such as if we have an external 16C550
   * UART. */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
69
  #define SERIAL_ATMEL_MAJOR	204
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
70
  #define MINOR_START		154
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
71
  #define ATMEL_DEVICENAME	"ttyAT"
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
72
73
74
75
76
  
  #else
  
  /* Use device name ttyS, major 4, minor 64-68.  This is the usual serial port
   * name, but it is legally reserved for the 8250 driver. */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
77
  #define SERIAL_ATMEL_MAJOR	TTY_MAJOR
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
78
  #define MINOR_START		64
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
79
  #define ATMEL_DEVICENAME	"ttyS"
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
80
81
  
  #endif
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
82
  #define ATMEL_ISR_PASS_LIMIT	256
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
83

b843aa216   Remy Bohmer   atmel_serial: cle...
84
  /* UART registers. CR is write-only, hence no GET macro */
544fc7283   Haavard Skinnemoen   [PATCH] atmel_ser...
85
86
87
88
89
90
91
92
93
94
95
96
  #define UART_PUT_CR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_CR)
  #define UART_GET_MR(port)	__raw_readl((port)->membase + ATMEL_US_MR)
  #define UART_PUT_MR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_MR)
  #define UART_PUT_IER(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IER)
  #define UART_PUT_IDR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IDR)
  #define UART_GET_IMR(port)	__raw_readl((port)->membase + ATMEL_US_IMR)
  #define UART_GET_CSR(port)	__raw_readl((port)->membase + ATMEL_US_CSR)
  #define UART_GET_CHAR(port)	__raw_readl((port)->membase + ATMEL_US_RHR)
  #define UART_PUT_CHAR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_THR)
  #define UART_GET_BRGR(port)	__raw_readl((port)->membase + ATMEL_US_BRGR)
  #define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
  #define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
97
  #define UART_PUT_TTGR(port, v)	__raw_writel(v, (port)->membase + ATMEL_US_TTGR)
544fc7283   Haavard Skinnemoen   [PATCH] atmel_ser...
98

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
99
   /* PDC registers */
544fc7283   Haavard Skinnemoen   [PATCH] atmel_ser...
100
101
102
103
104
105
106
107
108
109
110
  #define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
  #define UART_GET_PTSR(port)	__raw_readl((port)->membase + ATMEL_PDC_PTSR)
  
  #define UART_PUT_RPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
  #define UART_GET_RPR(port)	__raw_readl((port)->membase + ATMEL_PDC_RPR)
  #define UART_PUT_RCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
  #define UART_PUT_RNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
  #define UART_PUT_RNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
  
  #define UART_PUT_TPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
  #define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
39d4c922b   Marc Pignat   atmel_serial: fix...
111
  #define UART_GET_TCR(port)	__raw_readl((port)->membase + ATMEL_PDC_TCR)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
112

71f2e2b87   Haavard Skinnemoen   [PATCH] atmel_ser...
113
114
  static int (*atmel_open_hook)(struct uart_port *);
  static void (*atmel_close_hook)(struct uart_port *);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
115

a66706158   Chip Coldwell   atmel_serial: add...
116
117
118
119
120
121
  struct atmel_dma_buffer {
  	unsigned char	*buf;
  	dma_addr_t	dma_addr;
  	unsigned int	dma_size;
  	unsigned int	ofs;
  };
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
122
123
124
125
126
127
  struct atmel_uart_char {
  	u16		status;
  	u16		ch;
  };
  
  #define ATMEL_SERIAL_RINGSIZE 1024
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
128
129
130
  /*
   * We wrap our port structure around the generic uart_port.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
131
  struct atmel_uart_port {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
132
133
  	struct uart_port	uart;		/* uart */
  	struct clk		*clk;		/* uart clock */
f05596dbc   Anti Sullin   atmel_serial: upd...
134
135
  	int			may_wakeup;	/* cached value of device_may_wakeup for times we need to disable it */
  	u32			backup_imr;	/* IMR saved during suspend */
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
136
  	int			break_active;	/* break being received */
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
137

a66706158   Chip Coldwell   atmel_serial: add...
138
139
140
141
142
143
  	short			use_dma_rx;	/* enable PDC receiver */
  	short			pdc_rx_idx;	/* current PDC RX buffer */
  	struct atmel_dma_buffer	pdc_rx[2];	/* PDC receier */
  
  	short			use_dma_tx;	/* enable PDC transmitter */
  	struct atmel_dma_buffer	pdc_tx;		/* PDC transmitter */
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
144
145
146
147
148
  	struct tasklet_struct	tasklet;
  	unsigned int		irq_status;
  	unsigned int		irq_status_prev;
  
  	struct circ_buf		rx_ring;
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
149
150
151
  
  	struct serial_rs485	rs485;		/* rs485 settings */
  	unsigned int		tx_done_mask;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
152
  };
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
153
  static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
154

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
155
  #ifdef SUPPORT_SYSRQ
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
156
  static struct console atmel_console;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
157
  #endif
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
158
159
160
161
162
  static inline struct atmel_uart_port *
  to_atmel_uart_port(struct uart_port *uart)
  {
  	return container_of(uart, struct atmel_uart_port, uart);
  }
a66706158   Chip Coldwell   atmel_serial: add...
163
164
165
  #ifdef CONFIG_SERIAL_ATMEL_PDC
  static bool atmel_use_dma_rx(struct uart_port *port)
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
166
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
a66706158   Chip Coldwell   atmel_serial: add...
167
168
169
170
171
172
  
  	return atmel_port->use_dma_rx;
  }
  
  static bool atmel_use_dma_tx(struct uart_port *port)
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
173
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
a66706158   Chip Coldwell   atmel_serial: add...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  
  	return atmel_port->use_dma_tx;
  }
  #else
  static bool atmel_use_dma_rx(struct uart_port *port)
  {
  	return false;
  }
  
  static bool atmel_use_dma_tx(struct uart_port *port)
  {
  	return false;
  }
  #endif
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  /* Enable or disable the rs485 support */
  void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
  {
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
  	unsigned int mode;
  
  	spin_lock(&port->lock);
  
  	/* Disable interrupts */
  	UART_PUT_IDR(port, atmel_port->tx_done_mask);
  
  	mode = UART_GET_MR(port);
  
  	/* Resetting serial mode to RS232 (0x0) */
  	mode &= ~ATMEL_US_USMODE;
  
  	atmel_port->rs485 = *rs485conf;
  
  	if (rs485conf->flags & SER_RS485_ENABLED) {
  		dev_dbg(port->dev, "Setting UART to RS485
  ");
  		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
1b6331848   Claudio Scordino   serial: general f...
210
211
  		if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
  			UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  		mode |= ATMEL_US_USMODE_RS485;
  	} else {
  		dev_dbg(port->dev, "Setting UART to RS232
  ");
  		if (atmel_use_dma_tx(port))
  			atmel_port->tx_done_mask = ATMEL_US_ENDTX |
  				ATMEL_US_TXBUFE;
  		else
  			atmel_port->tx_done_mask = ATMEL_US_TXRDY;
  	}
  	UART_PUT_MR(port, mode);
  
  	/* Enable interrupts */
  	UART_PUT_IER(port, atmel_port->tx_done_mask);
  
  	spin_unlock(&port->lock);
  
  }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
230
231
232
  /*
   * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
233
  static u_int atmel_tx_empty(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
234
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
235
  	return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
236
237
238
239
240
  }
  
  /*
   * Set state of the modem control output lines
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
241
  static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
242
243
  {
  	unsigned int control = 0;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
244
  	unsigned int mode;
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
245
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
246

c2f5ccfbd   Andrew Victor   [ARM] 3973/1: AT9...
247
  #ifdef CONFIG_ARCH_AT91RM9200
79da7a610   Andrew Victor   [ARM] 3947/1: AT9...
248
  	if (cpu_is_at91rm9200()) {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
249
  		/*
b843aa216   Remy Bohmer   atmel_serial: cle...
250
251
  		 * AT91RM9200 Errata #39: RTS0 is not internally connected
  		 * to PA21. We need to drive the pin manually.
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
252
  		 */
72729910c   Andrew Victor   [ARM] 3865/1: AT9...
253
  		if (port->mapbase == AT91RM9200_BASE_US0) {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
254
  			if (mctrl & TIOCM_RTS)
20e652761   Andrew Victor   [ARM] 3710/1: AT9...
255
  				at91_set_gpio_value(AT91_PIN_PA21, 0);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
256
  			else
20e652761   Andrew Victor   [ARM] 3710/1: AT9...
257
  				at91_set_gpio_value(AT91_PIN_PA21, 1);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
258
  		}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
259
  	}
acca9b83a   Haavard Skinnemoen   [PATCH] atmel_ser...
260
  #endif
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
261
262
  
  	if (mctrl & TIOCM_RTS)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
263
  		control |= ATMEL_US_RTSEN;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
264
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
265
  		control |= ATMEL_US_RTSDIS;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
266
267
  
  	if (mctrl & TIOCM_DTR)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
268
  		control |= ATMEL_US_DTREN;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
269
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
270
  		control |= ATMEL_US_DTRDIS;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
271

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
272
273
274
  	UART_PUT_CR(port, control);
  
  	/* Local loopback mode? */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
275
  	mode = UART_GET_MR(port) & ~ATMEL_US_CHMODE;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
276
  	if (mctrl & TIOCM_LOOP)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
277
  		mode |= ATMEL_US_CHMODE_LOC_LOOP;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
278
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
279
  		mode |= ATMEL_US_CHMODE_NORMAL;
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
280
281
282
283
284
285
286
  
  	/* Resetting serial mode to RS232 (0x0) */
  	mode &= ~ATMEL_US_USMODE;
  
  	if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
  		dev_dbg(port->dev, "Setting UART to RS485
  ");
1b6331848   Claudio Scordino   serial: general f...
287
288
289
  		if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
  			UART_PUT_TTGR(port,
  					atmel_port->rs485.delay_rts_after_send);
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
290
291
292
293
294
  		mode |= ATMEL_US_USMODE_RS485;
  	} else {
  		dev_dbg(port->dev, "Setting UART to RS232
  ");
  	}
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
295
  	UART_PUT_MR(port, mode);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
296
297
298
299
300
  }
  
  /*
   * Get state of the modem control input lines
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
301
  static u_int atmel_get_mctrl(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
302
303
304
305
306
307
308
309
  {
  	unsigned int status, ret = 0;
  
  	status = UART_GET_CSR(port);
  
  	/*
  	 * The control signals are active low.
  	 */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
310
  	if (!(status & ATMEL_US_DCD))
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
311
  		ret |= TIOCM_CD;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
312
  	if (!(status & ATMEL_US_CTS))
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
313
  		ret |= TIOCM_CTS;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
314
  	if (!(status & ATMEL_US_DSR))
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
315
  		ret |= TIOCM_DSR;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
316
  	if (!(status & ATMEL_US_RI))
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
317
318
319
320
321
322
323
324
  		ret |= TIOCM_RI;
  
  	return ret;
  }
  
  /*
   * Stop transmitting.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
325
  static void atmel_stop_tx(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
326
  {
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
327
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
a66706158   Chip Coldwell   atmel_serial: add...
328
329
330
  	if (atmel_use_dma_tx(port)) {
  		/* disable PDC transmit */
  		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
331
332
333
334
335
336
  	}
  	/* Disable interrupts */
  	UART_PUT_IDR(port, atmel_port->tx_done_mask);
  
  	if (atmel_port->rs485.flags & SER_RS485_ENABLED)
  		atmel_start_rx(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
337
338
339
340
341
  }
  
  /*
   * Start transmitting.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
342
  static void atmel_start_tx(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
343
  {
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
344
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
a66706158   Chip Coldwell   atmel_serial: add...
345
346
347
348
349
  	if (atmel_use_dma_tx(port)) {
  		if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
  			/* The transmitter is already running.  Yes, we
  			   really need this.*/
  			return;
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
350
351
  		if (atmel_port->rs485.flags & SER_RS485_ENABLED)
  			atmel_stop_rx(port);
a66706158   Chip Coldwell   atmel_serial: add...
352
353
  		/* re-enable PDC transmit */
  		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
  	}
  	/* Enable interrupts */
  	UART_PUT_IER(port, atmel_port->tx_done_mask);
  }
  
  /*
   * start receiving - port is in process of being opened.
   */
  static void atmel_start_rx(struct uart_port *port)
  {
  	UART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */
  
  	if (atmel_use_dma_rx(port)) {
  		/* enable PDC controller */
  		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
  			port->read_status_mask);
  		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
  	} else {
  		UART_PUT_IER(port, ATMEL_US_RXRDY);
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
374
375
376
377
378
  }
  
  /*
   * Stop receiving - port is in process of being closed.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
379
  static void atmel_stop_rx(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
380
  {
a66706158   Chip Coldwell   atmel_serial: add...
381
382
383
  	if (atmel_use_dma_rx(port)) {
  		/* disable PDC receive */
  		UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
384
385
386
  		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
  			port->read_status_mask);
  	} else {
a66706158   Chip Coldwell   atmel_serial: add...
387
  		UART_PUT_IDR(port, ATMEL_US_RXRDY);
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
388
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
389
390
391
392
393
  }
  
  /*
   * Enable modem status interrupts
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
394
  static void atmel_enable_ms(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
395
  {
b843aa216   Remy Bohmer   atmel_serial: cle...
396
397
  	UART_PUT_IER(port, ATMEL_US_RIIC | ATMEL_US_DSRIC
  			| ATMEL_US_DCDIC | ATMEL_US_CTSIC);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
398
399
400
401
402
  }
  
  /*
   * Control the transmission of a break signal
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
403
  static void atmel_break_ctl(struct uart_port *port, int break_state)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
404
405
  {
  	if (break_state != 0)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
406
  		UART_PUT_CR(port, ATMEL_US_STTBRK);	/* start break */
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
407
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
408
  		UART_PUT_CR(port, ATMEL_US_STPBRK);	/* stop break */
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
409
410
411
  }
  
  /*
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
412
413
414
415
416
417
   * Stores the incoming character in the ring buffer
   */
  static void
  atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
  		     unsigned int ch)
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
418
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
  	struct circ_buf *ring = &atmel_port->rx_ring;
  	struct atmel_uart_char *c;
  
  	if (!CIRC_SPACE(ring->head, ring->tail, ATMEL_SERIAL_RINGSIZE))
  		/* Buffer overflow, ignore char */
  		return;
  
  	c = &((struct atmel_uart_char *)ring->buf)[ring->head];
  	c->status	= status;
  	c->ch		= ch;
  
  	/* Make sure the character is stored before we update head. */
  	smp_wmb();
  
  	ring->head = (ring->head + 1) & (ATMEL_SERIAL_RINGSIZE - 1);
  }
  
  /*
a66706158   Chip Coldwell   atmel_serial: add...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
   * Deal with parity, framing and overrun errors.
   */
  static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
  {
  	/* clear error */
  	UART_PUT_CR(port, ATMEL_US_RSTSTA);
  
  	if (status & ATMEL_US_RXBRK) {
  		/* ignore side-effect */
  		status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);
  		port->icount.brk++;
  	}
  	if (status & ATMEL_US_PARE)
  		port->icount.parity++;
  	if (status & ATMEL_US_FRAME)
  		port->icount.frame++;
  	if (status & ATMEL_US_OVRE)
  		port->icount.overrun++;
  }
  
  /*
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
458
459
   * Characters received (called from interrupt handler)
   */
7d12e780e   David Howells   IRQ: Maintain reg...
460
  static void atmel_rx_chars(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
461
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
462
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
463
  	unsigned int status, ch;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
464

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
465
  	status = UART_GET_CSR(port);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
466
  	while (status & ATMEL_US_RXRDY) {
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
467
  		ch = UART_GET_CHAR(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
468
469
470
471
  		/*
  		 * note that the error handling code is
  		 * out of the main execution path
  		 */
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
472
473
474
  		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
  				       | ATMEL_US_OVRE | ATMEL_US_RXBRK)
  			     || atmel_port->break_active)) {
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
475

b843aa216   Remy Bohmer   atmel_serial: cle...
476
477
  			/* clear error */
  			UART_PUT_CR(port, ATMEL_US_RSTSTA);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
478

9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
479
480
  			if (status & ATMEL_US_RXBRK
  			    && !atmel_port->break_active) {
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
481
482
  				atmel_port->break_active = 1;
  				UART_PUT_IER(port, ATMEL_US_RXBRK);
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
483
484
485
486
487
488
489
490
491
492
493
  			} else {
  				/*
  				 * This is either the end-of-break
  				 * condition or we've received at
  				 * least one character without RXBRK
  				 * being set. In both cases, the next
  				 * RXBRK will indicate start-of-break.
  				 */
  				UART_PUT_IDR(port, ATMEL_US_RXBRK);
  				status &= ~ATMEL_US_RXBRK;
  				atmel_port->break_active = 0;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
494
  			}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
495
  		}
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
496
  		atmel_buffer_rx_char(port, status, ch);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
497
  		status = UART_GET_CSR(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
498
  	}
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
499
  	tasklet_schedule(&atmel_port->tasklet);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
500
501
502
  }
  
  /*
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
503
504
   * Transmit characters (called from tasklet with TXRDY interrupt
   * disabled)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
505
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
506
  static void atmel_tx_chars(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
507
  {
ebd2c8f6d   Alan Cox   serial: kill off ...
508
  	struct circ_buf *xmit = &port->state->xmit;
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
509
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
510

e8faff733   Claudio Scordino   ARM: 6092/1: atme...
511
  	if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
512
513
514
  		UART_PUT_CHAR(port, port->x_char);
  		port->icount.tx++;
  		port->x_char = 0;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
515
  	}
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
516
  	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
517
  		return;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
518

e8faff733   Claudio Scordino   ARM: 6092/1: atme...
519
  	while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
520
521
522
523
524
525
526
527
528
  		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
  		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  		port->icount.tx++;
  		if (uart_circ_empty(xmit))
  			break;
  	}
  
  	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  		uart_write_wakeup(port);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
529
  	if (!uart_circ_empty(xmit))
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
530
531
  		/* Enable interrupts */
  		UART_PUT_IER(port, atmel_port->tx_done_mask);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
532
533
534
  }
  
  /*
b843aa216   Remy Bohmer   atmel_serial: cle...
535
536
537
538
539
   * receive interrupt handler.
   */
  static void
  atmel_handle_receive(struct uart_port *port, unsigned int pending)
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
540
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
b843aa216   Remy Bohmer   atmel_serial: cle...
541

a66706158   Chip Coldwell   atmel_serial: add...
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
  	if (atmel_use_dma_rx(port)) {
  		/*
  		 * PDC receive. Just schedule the tasklet and let it
  		 * figure out the details.
  		 *
  		 * TODO: We're not handling error flags correctly at
  		 * the moment.
  		 */
  		if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
  			UART_PUT_IDR(port, (ATMEL_US_ENDRX
  						| ATMEL_US_TIMEOUT));
  			tasklet_schedule(&atmel_port->tasklet);
  		}
  
  		if (pending & (ATMEL_US_RXBRK | ATMEL_US_OVRE |
  				ATMEL_US_FRAME | ATMEL_US_PARE))
  			atmel_pdc_rxerr(port, pending);
  	}
b843aa216   Remy Bohmer   atmel_serial: cle...
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  	/* Interrupt receive */
  	if (pending & ATMEL_US_RXRDY)
  		atmel_rx_chars(port);
  	else if (pending & ATMEL_US_RXBRK) {
  		/*
  		 * End of break detected. If it came along with a
  		 * character, atmel_rx_chars will handle it.
  		 */
  		UART_PUT_CR(port, ATMEL_US_RSTSTA);
  		UART_PUT_IDR(port, ATMEL_US_RXBRK);
  		atmel_port->break_active = 0;
  	}
  }
  
  /*
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
575
   * transmit interrupt handler. (Transmit is IRQF_NODELAY safe)
b843aa216   Remy Bohmer   atmel_serial: cle...
576
577
578
579
   */
  static void
  atmel_handle_transmit(struct uart_port *port, unsigned int pending)
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
580
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
581

e8faff733   Claudio Scordino   ARM: 6092/1: atme...
582
583
584
585
  	if (pending & atmel_port->tx_done_mask) {
  		/* Either PDC or interrupt transmission */
  		UART_PUT_IDR(port, atmel_port->tx_done_mask);
  		tasklet_schedule(&atmel_port->tasklet);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
586
  	}
b843aa216   Remy Bohmer   atmel_serial: cle...
587
588
589
590
591
592
593
594
595
  }
  
  /*
   * status flags interrupt handler.
   */
  static void
  atmel_handle_status(struct uart_port *port, unsigned int pending,
  		    unsigned int status)
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
596
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
597

b843aa216   Remy Bohmer   atmel_serial: cle...
598
  	if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
599
600
601
602
  				| ATMEL_US_CTSIC)) {
  		atmel_port->irq_status = status;
  		tasklet_schedule(&atmel_port->tasklet);
  	}
b843aa216   Remy Bohmer   atmel_serial: cle...
603
604
605
  }
  
  /*
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
606
607
   * Interrupt handler
   */
7d12e780e   David Howells   IRQ: Maintain reg...
608
  static irqreturn_t atmel_interrupt(int irq, void *dev_id)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
609
610
611
  {
  	struct uart_port *port = dev_id;
  	unsigned int status, pending, pass_counter = 0;
a66706158   Chip Coldwell   atmel_serial: add...
612
613
614
615
616
  	do {
  		status = UART_GET_CSR(port);
  		pending = status & UART_GET_IMR(port);
  		if (!pending)
  			break;
b843aa216   Remy Bohmer   atmel_serial: cle...
617
618
619
  		atmel_handle_receive(port, pending);
  		atmel_handle_status(port, pending, status);
  		atmel_handle_transmit(port, pending);
a66706158   Chip Coldwell   atmel_serial: add...
620
  	} while (pass_counter++ < ATMEL_ISR_PASS_LIMIT);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
621

0400b697e   Haavard Skinnemoen   atmel_serial: fix...
622
  	return pass_counter ? IRQ_HANDLED : IRQ_NONE;
a66706158   Chip Coldwell   atmel_serial: add...
623
  }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
624

a66706158   Chip Coldwell   atmel_serial: add...
625
626
627
628
629
  /*
   * Called from tasklet with ENDTX and TXBUFE interrupts disabled.
   */
  static void atmel_tx_dma(struct uart_port *port)
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
630
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
ebd2c8f6d   Alan Cox   serial: kill off ...
631
  	struct circ_buf *xmit = &port->state->xmit;
a66706158   Chip Coldwell   atmel_serial: add...
632
633
  	struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
  	int count;
ba0657ff0   Michael Trimarchi   atmel_serial: avo...
634
635
636
  	/* nothing left to transmit? */
  	if (UART_GET_TCR(port))
  		return;
a66706158   Chip Coldwell   atmel_serial: add...
637
638
639
640
641
  	xmit->tail += pdc->ofs;
  	xmit->tail &= UART_XMIT_SIZE - 1;
  
  	port->icount.tx += pdc->ofs;
  	pdc->ofs = 0;
ba0657ff0   Michael Trimarchi   atmel_serial: avo...
642
  	/* more to transmit - setup next transfer */
a66706158   Chip Coldwell   atmel_serial: add...
643

ba0657ff0   Michael Trimarchi   atmel_serial: avo...
644
645
  	/* disable PDC transmit */
  	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
1f14081d8   Itai Levi   atmel_serial: fix...
646
  	if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
a66706158   Chip Coldwell   atmel_serial: add...
647
648
649
650
651
652
653
654
655
656
  		dma_sync_single_for_device(port->dev,
  					   pdc->dma_addr,
  					   pdc->dma_size,
  					   DMA_TO_DEVICE);
  
  		count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
  		pdc->ofs = count;
  
  		UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
  		UART_PUT_TCR(port, count);
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
657
  		/* re-enable PDC transmit */
a66706158   Chip Coldwell   atmel_serial: add...
658
  		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
659
660
661
662
663
664
665
  		/* Enable interrupts */
  		UART_PUT_IER(port, atmel_port->tx_done_mask);
  	} else {
  		if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
  			/* DMA done, stop TX, start RX for RS485 */
  			atmel_start_rx(port);
  		}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
666
  	}
a66706158   Chip Coldwell   atmel_serial: add...
667
668
669
  
  	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  		uart_write_wakeup(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
670
  }
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
671
672
  static void atmel_rx_from_ring(struct uart_port *port)
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
673
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
  	struct circ_buf *ring = &atmel_port->rx_ring;
  	unsigned int flg;
  	unsigned int status;
  
  	while (ring->head != ring->tail) {
  		struct atmel_uart_char c;
  
  		/* Make sure c is loaded after head. */
  		smp_rmb();
  
  		c = ((struct atmel_uart_char *)ring->buf)[ring->tail];
  
  		ring->tail = (ring->tail + 1) & (ATMEL_SERIAL_RINGSIZE - 1);
  
  		port->icount.rx++;
  		status = c.status;
  		flg = TTY_NORMAL;
  
  		/*
  		 * note that the error handling code is
  		 * out of the main execution path
  		 */
  		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
  				       | ATMEL_US_OVRE | ATMEL_US_RXBRK))) {
  			if (status & ATMEL_US_RXBRK) {
  				/* ignore side-effect */
  				status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);
  
  				port->icount.brk++;
  				if (uart_handle_break(port))
  					continue;
  			}
  			if (status & ATMEL_US_PARE)
  				port->icount.parity++;
  			if (status & ATMEL_US_FRAME)
  				port->icount.frame++;
  			if (status & ATMEL_US_OVRE)
  				port->icount.overrun++;
  
  			status &= port->read_status_mask;
  
  			if (status & ATMEL_US_RXBRK)
  				flg = TTY_BREAK;
  			else if (status & ATMEL_US_PARE)
  				flg = TTY_PARITY;
  			else if (status & ATMEL_US_FRAME)
  				flg = TTY_FRAME;
  		}
  
  
  		if (uart_handle_sysrq_char(port, c.ch))
  			continue;
  
  		uart_insert_char(port, status, ATMEL_US_OVRE, c.ch, flg);
  	}
  
  	/*
  	 * Drop the lock here since it might end up calling
  	 * uart_start(), which takes the lock.
  	 */
  	spin_unlock(&port->lock);
ebd2c8f6d   Alan Cox   serial: kill off ...
735
  	tty_flip_buffer_push(port->state->port.tty);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
736
737
  	spin_lock(&port->lock);
  }
a66706158   Chip Coldwell   atmel_serial: add...
738
739
  static void atmel_rx_from_dma(struct uart_port *port)
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
740
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
ebd2c8f6d   Alan Cox   serial: kill off ...
741
  	struct tty_struct *tty = port->state->port.tty;
a66706158   Chip Coldwell   atmel_serial: add...
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
  	struct atmel_dma_buffer *pdc;
  	int rx_idx = atmel_port->pdc_rx_idx;
  	unsigned int head;
  	unsigned int tail;
  	unsigned int count;
  
  	do {
  		/* Reset the UART timeout early so that we don't miss one */
  		UART_PUT_CR(port, ATMEL_US_STTTO);
  
  		pdc = &atmel_port->pdc_rx[rx_idx];
  		head = UART_GET_RPR(port) - pdc->dma_addr;
  		tail = pdc->ofs;
  
  		/* If the PDC has switched buffers, RPR won't contain
  		 * any address within the current buffer. Since head
  		 * is unsigned, we just need a one-way comparison to
  		 * find out.
  		 *
  		 * In this case, we just need to consume the entire
  		 * buffer and resubmit it for DMA. This will clear the
  		 * ENDRX bit as well, so that we can safely re-enable
  		 * all interrupts below.
  		 */
  		head = min(head, pdc->dma_size);
  
  		if (likely(head != tail)) {
  			dma_sync_single_for_cpu(port->dev, pdc->dma_addr,
  					pdc->dma_size, DMA_FROM_DEVICE);
  
  			/*
  			 * head will only wrap around when we recycle
  			 * the DMA buffer, and when that happens, we
  			 * explicitly set tail to 0. So head will
  			 * always be greater than tail.
  			 */
  			count = head - tail;
  
  			tty_insert_flip_string(tty, pdc->buf + pdc->ofs, count);
  
  			dma_sync_single_for_device(port->dev, pdc->dma_addr,
  					pdc->dma_size, DMA_FROM_DEVICE);
  
  			port->icount.rx += count;
  			pdc->ofs = head;
  		}
  
  		/*
  		 * If the current buffer is full, we need to check if
  		 * the next one contains any additional data.
  		 */
  		if (head >= pdc->dma_size) {
  			pdc->ofs = 0;
  			UART_PUT_RNPR(port, pdc->dma_addr);
  			UART_PUT_RNCR(port, pdc->dma_size);
  
  			rx_idx = !rx_idx;
  			atmel_port->pdc_rx_idx = rx_idx;
  		}
  	} while (head >= pdc->dma_size);
  
  	/*
  	 * Drop the lock here since it might end up calling
  	 * uart_start(), which takes the lock.
  	 */
  	spin_unlock(&port->lock);
  	tty_flip_buffer_push(tty);
  	spin_lock(&port->lock);
  
  	UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
  }
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
813
814
815
816
817
818
  /*
   * tasklet handling tty stuff outside the interrupt handler.
   */
  static void atmel_tasklet_func(unsigned long data)
  {
  	struct uart_port *port = (struct uart_port *)data;
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
819
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
820
821
822
823
824
  	unsigned int status;
  	unsigned int status_change;
  
  	/* The interrupt handler does not take the lock */
  	spin_lock(&port->lock);
a66706158   Chip Coldwell   atmel_serial: add...
825
826
827
828
  	if (atmel_use_dma_tx(port))
  		atmel_tx_dma(port);
  	else
  		atmel_tx_chars(port);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
  
  	status = atmel_port->irq_status;
  	status_change = status ^ atmel_port->irq_status_prev;
  
  	if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
  				| ATMEL_US_DCD | ATMEL_US_CTS)) {
  		/* TODO: All reads to CSR will clear these interrupts! */
  		if (status_change & ATMEL_US_RI)
  			port->icount.rng++;
  		if (status_change & ATMEL_US_DSR)
  			port->icount.dsr++;
  		if (status_change & ATMEL_US_DCD)
  			uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
  		if (status_change & ATMEL_US_CTS)
  			uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
bdc04e317   Alan Cox   serial: move delt...
844
  		wake_up_interruptible(&port->state->port.delta_msr_wait);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
845
846
847
  
  		atmel_port->irq_status_prev = status;
  	}
a66706158   Chip Coldwell   atmel_serial: add...
848
849
850
851
  	if (atmel_use_dma_rx(port))
  		atmel_rx_from_dma(port);
  	else
  		atmel_rx_from_ring(port);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
852
853
854
  
  	spin_unlock(&port->lock);
  }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
855
856
857
  /*
   * Perform initialization and enable port for reception
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
858
  static int atmel_startup(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
859
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
860
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
ebd2c8f6d   Alan Cox   serial: kill off ...
861
  	struct tty_struct *tty = port->state->port.tty;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
862
863
864
865
866
867
868
869
870
871
872
873
  	int retval;
  
  	/*
  	 * Ensure that no interrupts are enabled otherwise when
  	 * request_irq() is called we could get stuck trying to
  	 * handle an unexpected interrupt
  	 */
  	UART_PUT_IDR(port, -1);
  
  	/*
  	 * Allocate the IRQ
  	 */
b843aa216   Remy Bohmer   atmel_serial: cle...
874
  	retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED,
ae1610687   Haavard Skinnemoen   atmel_serial: sho...
875
  			tty ? tty->name : "atmel_serial", port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
876
  	if (retval) {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
877
878
  		printk("atmel_serial: atmel_startup - Can't get irq
  ");
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
879
880
881
882
  		return retval;
  	}
  
  	/*
a66706158   Chip Coldwell   atmel_serial: add...
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
  	 * Initialize DMA (if necessary)
  	 */
  	if (atmel_use_dma_rx(port)) {
  		int i;
  
  		for (i = 0; i < 2; i++) {
  			struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
  
  			pdc->buf = kmalloc(PDC_BUFFER_SIZE, GFP_KERNEL);
  			if (pdc->buf == NULL) {
  				if (i != 0) {
  					dma_unmap_single(port->dev,
  						atmel_port->pdc_rx[0].dma_addr,
  						PDC_BUFFER_SIZE,
  						DMA_FROM_DEVICE);
  					kfree(atmel_port->pdc_rx[0].buf);
  				}
  				free_irq(port->irq, port);
  				return -ENOMEM;
  			}
  			pdc->dma_addr = dma_map_single(port->dev,
  						       pdc->buf,
  						       PDC_BUFFER_SIZE,
  						       DMA_FROM_DEVICE);
  			pdc->dma_size = PDC_BUFFER_SIZE;
  			pdc->ofs = 0;
  		}
  
  		atmel_port->pdc_rx_idx = 0;
  
  		UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
  		UART_PUT_RCR(port, PDC_BUFFER_SIZE);
  
  		UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
  		UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
  	}
  	if (atmel_use_dma_tx(port)) {
  		struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
ebd2c8f6d   Alan Cox   serial: kill off ...
921
  		struct circ_buf *xmit = &port->state->xmit;
a66706158   Chip Coldwell   atmel_serial: add...
922
923
924
925
926
927
928
929
930
931
932
  
  		pdc->buf = xmit->buf;
  		pdc->dma_addr = dma_map_single(port->dev,
  					       pdc->buf,
  					       UART_XMIT_SIZE,
  					       DMA_TO_DEVICE);
  		pdc->dma_size = UART_XMIT_SIZE;
  		pdc->ofs = 0;
  	}
  
  	/*
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
933
934
935
  	 * If there is a specific "open" function (to register
  	 * control line interrupts)
  	 */
71f2e2b87   Haavard Skinnemoen   [PATCH] atmel_ser...
936
937
  	if (atmel_open_hook) {
  		retval = atmel_open_hook(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
938
939
940
941
942
  		if (retval) {
  			free_irq(port->irq, port);
  			return retval;
  		}
  	}
27c0c8e51   Atsushi Nemoto   atmel_serial migh...
943
944
945
  	/* Save current CSR for comparison in atmel_tasklet_func() */
  	atmel_port->irq_status_prev = UART_GET_CSR(port);
  	atmel_port->irq_status = atmel_port->irq_status_prev;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
946
947
948
  	/*
  	 * Finally, enable the serial port
  	 */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
949
  	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
b843aa216   Remy Bohmer   atmel_serial: cle...
950
951
  	/* enable xmit & rcvr */
  	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
952

a66706158   Chip Coldwell   atmel_serial: add...
953
954
955
956
957
958
959
960
961
962
963
964
  	if (atmel_use_dma_rx(port)) {
  		/* set UART timeout */
  		UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
  		UART_PUT_CR(port, ATMEL_US_STTTO);
  
  		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
  		/* enable PDC controller */
  		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
  	} else {
  		/* enable receive only */
  		UART_PUT_IER(port, ATMEL_US_RXRDY);
  	}
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
965

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
966
967
968
969
970
971
  	return 0;
  }
  
  /*
   * Disable the port
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
972
  static void atmel_shutdown(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
973
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
974
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
a66706158   Chip Coldwell   atmel_serial: add...
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
  	/*
  	 * Ensure everything is stopped.
  	 */
  	atmel_stop_rx(port);
  	atmel_stop_tx(port);
  
  	/*
  	 * Shut-down the DMA.
  	 */
  	if (atmel_use_dma_rx(port)) {
  		int i;
  
  		for (i = 0; i < 2; i++) {
  			struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
  
  			dma_unmap_single(port->dev,
  					 pdc->dma_addr,
  					 pdc->dma_size,
  					 DMA_FROM_DEVICE);
  			kfree(pdc->buf);
  		}
  	}
  	if (atmel_use_dma_tx(port)) {
  		struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
  
  		dma_unmap_single(port->dev,
  				 pdc->dma_addr,
  				 pdc->dma_size,
  				 DMA_TO_DEVICE);
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1005
1006
1007
  	/*
  	 * Disable all interrupts, port and break condition.
  	 */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1008
  	UART_PUT_CR(port, ATMEL_US_RSTSTA);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
  	UART_PUT_IDR(port, -1);
  
  	/*
  	 * Free the interrupt
  	 */
  	free_irq(port->irq, port);
  
  	/*
  	 * If there is a specific "close" function (to unregister
  	 * control line interrupts)
  	 */
71f2e2b87   Haavard Skinnemoen   [PATCH] atmel_ser...
1020
1021
  	if (atmel_close_hook)
  		atmel_close_hook(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1022
1023
1024
  }
  
  /*
9afd561ac   Haavard Skinnemoen   Subject: [PATCH 2...
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
   * Flush any TX data submitted for DMA. Called when the TX circular
   * buffer is reset.
   */
  static void atmel_flush_buffer(struct uart_port *port)
  {
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
  
  	if (atmel_use_dma_tx(port)) {
  		UART_PUT_TCR(port, 0);
  		atmel_port->pdc_tx.ofs = 0;
  	}
  }
  
  /*
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1039
1040
   * Power / Clock management.
   */
b843aa216   Remy Bohmer   atmel_serial: cle...
1041
1042
  static void atmel_serial_pm(struct uart_port *port, unsigned int state,
  			    unsigned int oldstate)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1043
  {
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
1044
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1045

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1046
  	switch (state) {
b843aa216   Remy Bohmer   atmel_serial: cle...
1047
1048
1049
1050
1051
1052
  	case 0:
  		/*
  		 * Enable the peripheral clock for this serial port.
  		 * This is called on uart_open() or a resume event.
  		 */
  		clk_enable(atmel_port->clk);
f05596dbc   Anti Sullin   atmel_serial: upd...
1053
1054
1055
  
  		/* re-enable interrupts if we disabled some on suspend */
  		UART_PUT_IER(port, atmel_port->backup_imr);
b843aa216   Remy Bohmer   atmel_serial: cle...
1056
1057
  		break;
  	case 3:
f05596dbc   Anti Sullin   atmel_serial: upd...
1058
1059
1060
  		/* Back up the interrupt mask and disable all interrupts */
  		atmel_port->backup_imr = UART_GET_IMR(port);
  		UART_PUT_IDR(port, -1);
b843aa216   Remy Bohmer   atmel_serial: cle...
1061
1062
1063
1064
1065
1066
1067
1068
1069
  		/*
  		 * Disable the peripheral clock for this serial port.
  		 * This is called on uart_close() or a suspend event.
  		 */
  		clk_disable(atmel_port->clk);
  		break;
  	default:
  		printk(KERN_ERR "atmel_serial: unknown pm %d
  ", state);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1070
1071
1072
1073
1074
1075
  	}
  }
  
  /*
   * Change the port parameters
   */
b843aa216   Remy Bohmer   atmel_serial: cle...
1076
1077
  static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
  			      struct ktermios *old)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1078
1079
1080
  {
  	unsigned long flags;
  	unsigned int mode, imr, quot, baud;
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
1081
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1082

03abeac0a   Andrew Victor   [ARM] 4357/1: AT9...
1083
  	/* Get current mode register */
b843aa216   Remy Bohmer   atmel_serial: cle...
1084
  	mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL
8e706c4d0   Peter Ma   avr32: add hardwa...
1085
1086
  					| ATMEL_US_NBSTOP | ATMEL_US_PAR
  					| ATMEL_US_USMODE);
03abeac0a   Andrew Victor   [ARM] 4357/1: AT9...
1087

b843aa216   Remy Bohmer   atmel_serial: cle...
1088
  	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1089
  	quot = uart_get_divisor(port, baud);
b843aa216   Remy Bohmer   atmel_serial: cle...
1090
  	if (quot > 65535) {	/* BRGR is 16-bit, so switch to slower clock */
03abeac0a   Andrew Victor   [ARM] 4357/1: AT9...
1091
1092
1093
  		quot /= 8;
  		mode |= ATMEL_US_USCLKS_MCK_DIV8;
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1094
1095
1096
1097
  
  	/* byte size */
  	switch (termios->c_cflag & CSIZE) {
  	case CS5:
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1098
  		mode |= ATMEL_US_CHRL_5;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1099
1100
  		break;
  	case CS6:
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1101
  		mode |= ATMEL_US_CHRL_6;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1102
1103
  		break;
  	case CS7:
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1104
  		mode |= ATMEL_US_CHRL_7;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1105
1106
  		break;
  	default:
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1107
  		mode |= ATMEL_US_CHRL_8;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1108
1109
1110
1111
1112
  		break;
  	}
  
  	/* stop bits */
  	if (termios->c_cflag & CSTOPB)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1113
  		mode |= ATMEL_US_NBSTOP_2;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1114
1115
1116
  
  	/* parity */
  	if (termios->c_cflag & PARENB) {
b843aa216   Remy Bohmer   atmel_serial: cle...
1117
1118
  		/* Mark or Space parity */
  		if (termios->c_cflag & CMSPAR) {
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1119
  			if (termios->c_cflag & PARODD)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1120
  				mode |= ATMEL_US_PAR_MARK;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1121
  			else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1122
  				mode |= ATMEL_US_PAR_SPACE;
b843aa216   Remy Bohmer   atmel_serial: cle...
1123
  		} else if (termios->c_cflag & PARODD)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1124
  			mode |= ATMEL_US_PAR_ODD;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1125
  		else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1126
  			mode |= ATMEL_US_PAR_EVEN;
b843aa216   Remy Bohmer   atmel_serial: cle...
1127
  	} else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1128
  		mode |= ATMEL_US_PAR_NONE;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1129

8e706c4d0   Peter Ma   avr32: add hardwa...
1130
1131
1132
1133
1134
  	/* hardware handshake (RTS/CTS) */
  	if (termios->c_cflag & CRTSCTS)
  		mode |= ATMEL_US_USMODE_HWHS;
  	else
  		mode |= ATMEL_US_USMODE_NORMAL;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1135
  	spin_lock_irqsave(&port->lock, flags);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1136
  	port->read_status_mask = ATMEL_US_OVRE;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1137
  	if (termios->c_iflag & INPCK)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1138
  		port->read_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1139
  	if (termios->c_iflag & (BRKINT | PARMRK))
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1140
  		port->read_status_mask |= ATMEL_US_RXBRK;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1141

a66706158   Chip Coldwell   atmel_serial: add...
1142
1143
1144
  	if (atmel_use_dma_rx(port))
  		/* need to enable error interrupts */
  		UART_PUT_IER(port, port->read_status_mask);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1145
1146
1147
1148
1149
  	/*
  	 * Characters to ignore
  	 */
  	port->ignore_status_mask = 0;
  	if (termios->c_iflag & IGNPAR)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1150
  		port->ignore_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1151
  	if (termios->c_iflag & IGNBRK) {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1152
  		port->ignore_status_mask |= ATMEL_US_RXBRK;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1153
1154
1155
1156
1157
  		/*
  		 * If we're ignoring parity and break indicators,
  		 * ignore overruns too (for real raw support).
  		 */
  		if (termios->c_iflag & IGNPAR)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1158
  			port->ignore_status_mask |= ATMEL_US_OVRE;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1159
  	}
b843aa216   Remy Bohmer   atmel_serial: cle...
1160
  	/* TODO: Ignore all characters if CREAD is set.*/
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1161
1162
1163
  
  	/* update the per-port timeout */
  	uart_update_timeout(port, termios->c_cflag, baud);
0ccad8701   Haavard Skinnemoen   atmel_serial: fix...
1164
1165
1166
1167
1168
  	/*
  	 * save/disable interrupts. The tty layer will ensure that the
  	 * transmitter is empty if requested by the caller, so there's
  	 * no need to wait for it here.
  	 */
b843aa216   Remy Bohmer   atmel_serial: cle...
1169
1170
  	imr = UART_GET_IMR(port);
  	UART_PUT_IDR(port, -1);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1171
1172
  
  	/* disable receiver and transmitter */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1173
  	UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1174

e8faff733   Claudio Scordino   ARM: 6092/1: atme...
1175
1176
1177
1178
1179
1180
  	/* Resetting serial mode to RS232 (0x0) */
  	mode &= ~ATMEL_US_USMODE;
  
  	if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
  		dev_dbg(port->dev, "Setting UART to RS485
  ");
1b6331848   Claudio Scordino   serial: general f...
1181
1182
1183
  		if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
  			UART_PUT_TTGR(port,
  					atmel_port->rs485.delay_rts_after_send);
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
1184
1185
1186
1187
1188
  		mode |= ATMEL_US_USMODE_RS485;
  	} else {
  		dev_dbg(port->dev, "Setting UART to RS232
  ");
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1189
1190
1191
1192
1193
  	/* set the parity, stop bits and data size */
  	UART_PUT_MR(port, mode);
  
  	/* set the baud rate */
  	UART_PUT_BRGR(port, quot);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1194
1195
  	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
  	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
  
  	/* restore interrupts */
  	UART_PUT_IER(port, imr);
  
  	/* CTS flow-control and modem-status interrupts */
  	if (UART_ENABLE_MS(port, termios->c_cflag))
  		port->ops->enable_ms(port);
  
  	spin_unlock_irqrestore(&port->lock, flags);
  }
  
  /*
   * Return string describing the specified port
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1210
  static const char *atmel_type(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1211
  {
9ab4f88b7   Haavard Skinnemoen   [PATCH] serial: R...
1212
  	return (port->type == PORT_ATMEL) ? "ATMEL_SERIAL" : NULL;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1213
1214
1215
1216
1217
  }
  
  /*
   * Release the memory region(s) being used by 'port'.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1218
  static void atmel_release_port(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1219
  {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1220
1221
1222
1223
1224
1225
1226
1227
1228
  	struct platform_device *pdev = to_platform_device(port->dev);
  	int size = pdev->resource[0].end - pdev->resource[0].start + 1;
  
  	release_mem_region(port->mapbase, size);
  
  	if (port->flags & UPF_IOREMAP) {
  		iounmap(port->membase);
  		port->membase = NULL;
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1229
1230
1231
1232
1233
  }
  
  /*
   * Request the memory region(s) being used by 'port'.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1234
  static int atmel_request_port(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1235
  {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1236
1237
  	struct platform_device *pdev = to_platform_device(port->dev);
  	int size = pdev->resource[0].end - pdev->resource[0].start + 1;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1238
  	if (!request_mem_region(port->mapbase, size, "atmel_serial"))
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1239
1240
1241
1242
1243
1244
1245
1246
1247
  		return -EBUSY;
  
  	if (port->flags & UPF_IOREMAP) {
  		port->membase = ioremap(port->mapbase, size);
  		if (port->membase == NULL) {
  			release_mem_region(port->mapbase, size);
  			return -ENOMEM;
  		}
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1248

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1249
  	return 0;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1250
1251
1252
1253
1254
  }
  
  /*
   * Configure/autoconfigure the port.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1255
  static void atmel_config_port(struct uart_port *port, int flags)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1256
1257
  {
  	if (flags & UART_CONFIG_TYPE) {
9ab4f88b7   Haavard Skinnemoen   [PATCH] serial: R...
1258
  		port->type = PORT_ATMEL;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1259
  		atmel_request_port(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1260
1261
1262
1263
1264
1265
  	}
  }
  
  /*
   * Verify the new serial_struct (for TIOCSSERIAL).
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1266
  static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1267
1268
  {
  	int ret = 0;
9ab4f88b7   Haavard Skinnemoen   [PATCH] serial: R...
1269
  	if (ser->type != PORT_UNKNOWN && ser->type != PORT_ATMEL)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
  		ret = -EINVAL;
  	if (port->irq != ser->irq)
  		ret = -EINVAL;
  	if (ser->io_type != SERIAL_IO_MEM)
  		ret = -EINVAL;
  	if (port->uartclk / 16 != ser->baud_base)
  		ret = -EINVAL;
  	if ((void *)port->mapbase != ser->iomem_base)
  		ret = -EINVAL;
  	if (port->iobase != ser->port)
  		ret = -EINVAL;
  	if (ser->hub6 != 0)
  		ret = -EINVAL;
  	return ret;
  }
8fe2d5414   Albin Tonnerre   serial: atmel_ser...
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
  #ifdef CONFIG_CONSOLE_POLL
  static int atmel_poll_get_char(struct uart_port *port)
  {
  	while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
  		cpu_relax();
  
  	return UART_GET_CHAR(port);
  }
  
  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
  {
  	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
  		cpu_relax();
  
  	UART_PUT_CHAR(port, ch);
  }
  #endif
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
  static int
  atmel_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
  {
  	struct serial_rs485 rs485conf;
  
  	switch (cmd) {
  	case TIOCSRS485:
  		if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,
  					sizeof(rs485conf)))
  			return -EFAULT;
  
  		atmel_config_rs485(port, &rs485conf);
  		break;
  
  	case TIOCGRS485:
  		if (copy_to_user((struct serial_rs485 *) arg,
  					&(to_atmel_uart_port(port)->rs485),
  					sizeof(rs485conf)))
  			return -EFAULT;
  		break;
  
  	default:
  		return -ENOIOCTLCMD;
  	}
  	return 0;
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
  static struct uart_ops atmel_pops = {
  	.tx_empty	= atmel_tx_empty,
  	.set_mctrl	= atmel_set_mctrl,
  	.get_mctrl	= atmel_get_mctrl,
  	.stop_tx	= atmel_stop_tx,
  	.start_tx	= atmel_start_tx,
  	.stop_rx	= atmel_stop_rx,
  	.enable_ms	= atmel_enable_ms,
  	.break_ctl	= atmel_break_ctl,
  	.startup	= atmel_startup,
  	.shutdown	= atmel_shutdown,
9afd561ac   Haavard Skinnemoen   Subject: [PATCH 2...
1339
  	.flush_buffer	= atmel_flush_buffer,
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1340
1341
1342
1343
1344
1345
1346
  	.set_termios	= atmel_set_termios,
  	.type		= atmel_type,
  	.release_port	= atmel_release_port,
  	.request_port	= atmel_request_port,
  	.config_port	= atmel_config_port,
  	.verify_port	= atmel_verify_port,
  	.pm		= atmel_serial_pm,
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
1347
  	.ioctl		= atmel_ioctl,
8fe2d5414   Albin Tonnerre   serial: atmel_ser...
1348
1349
1350
1351
  #ifdef CONFIG_CONSOLE_POLL
  	.poll_get_char	= atmel_poll_get_char,
  	.poll_put_char	= atmel_poll_put_char,
  #endif
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1352
  };
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1353
1354
1355
  /*
   * Configure the port from the platform device resource info.
   */
b843aa216   Remy Bohmer   atmel_serial: cle...
1356
1357
  static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
  				      struct platform_device *pdev)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1358
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1359
  	struct uart_port *port = &atmel_port->uart;
73e2798b0   Haavard Skinnemoen   [PATCH] at91_seri...
1360
  	struct atmel_uart_data *data = pdev->dev.platform_data;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1361

e8faff733   Claudio Scordino   ARM: 6092/1: atme...
1362
1363
1364
1365
1366
1367
  	port->iotype		= UPIO_MEM;
  	port->flags		= UPF_BOOT_AUTOCONF;
  	port->ops		= &atmel_pops;
  	port->fifosize		= 1;
  	port->line		= pdev->id;
  	port->dev		= &pdev->dev;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1368
1369
  	port->mapbase	= pdev->resource[0].start;
  	port->irq	= pdev->resource[1].start;
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
1370
1371
1372
1373
  	tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
  			(unsigned long)port);
  
  	memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
75d352137   Haavard Skinnemoen   [PATCH] atmel_ser...
1374
1375
1376
  	if (data->regs)
  		/* Already mapped by setup code */
  		port->membase = data->regs;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1377
1378
1379
1380
  	else {
  		port->flags	|= UPF_IOREMAP;
  		port->membase	= NULL;
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1381

b843aa216   Remy Bohmer   atmel_serial: cle...
1382
1383
  	/* for console, the clock could already be configured */
  	if (!atmel_port->clk) {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1384
1385
1386
  		atmel_port->clk = clk_get(&pdev->dev, "usart");
  		clk_enable(atmel_port->clk);
  		port->uartclk = clk_get_rate(atmel_port->clk);
06a7f0587   David Brownell   atmel_serial: kee...
1387
1388
  		clk_disable(atmel_port->clk);
  		/* only enable clock when USART is in use */
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1389
  	}
a66706158   Chip Coldwell   atmel_serial: add...
1390
1391
1392
  
  	atmel_port->use_dma_rx = data->use_dma_rx;
  	atmel_port->use_dma_tx = data->use_dma_tx;
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
1393
1394
1395
1396
1397
  	atmel_port->rs485	= data->rs485;
  	/* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
  	if (atmel_port->rs485.flags & SER_RS485_ENABLED)
  		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
  	else if (atmel_use_dma_tx(port)) {
a66706158   Chip Coldwell   atmel_serial: add...
1398
  		port->fifosize = PDC_BUFFER_SIZE;
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
1399
1400
1401
1402
  		atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE;
  	} else {
  		atmel_port->tx_done_mask = ATMEL_US_TXRDY;
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1403
  }
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1404
1405
1406
  /*
   * Register board-specific modem-control line handlers.
   */
71f2e2b87   Haavard Skinnemoen   [PATCH] atmel_ser...
1407
  void __init atmel_register_uart_fns(struct atmel_port_fns *fns)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1408
1409
  {
  	if (fns->enable_ms)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1410
  		atmel_pops.enable_ms = fns->enable_ms;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1411
  	if (fns->get_mctrl)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1412
  		atmel_pops.get_mctrl = fns->get_mctrl;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1413
  	if (fns->set_mctrl)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1414
  		atmel_pops.set_mctrl = fns->set_mctrl;
71f2e2b87   Haavard Skinnemoen   [PATCH] atmel_ser...
1415
1416
  	atmel_open_hook		= fns->open;
  	atmel_close_hook	= fns->close;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1417
1418
  	atmel_pops.pm		= fns->pm;
  	atmel_pops.set_wake	= fns->set_wake;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1419
  }
749c4e603   Haavard Skinnemoen   [PATCH] at91_seri...
1420
  #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1421
  static void atmel_console_putchar(struct uart_port *port, int ch)
d358788f3   Russell King   [SERIAL] kernel c...
1422
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1423
  	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
829dd8112   Haavard Skinnemoen   atmel_serial: use...
1424
  		cpu_relax();
d358788f3   Russell King   [SERIAL] kernel c...
1425
1426
  	UART_PUT_CHAR(port, ch);
  }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1427
1428
1429
1430
  
  /*
   * Interrupts are disabled on entering
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1431
  static void atmel_console_write(struct console *co, const char *s, u_int count)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1432
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1433
  	struct uart_port *port = &atmel_ports[co->index].uart;
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
1434
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
d358788f3   Russell King   [SERIAL] kernel c...
1435
  	unsigned int status, imr;
39d4c922b   Marc Pignat   atmel_serial: fix...
1436
  	unsigned int pdc_tx;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1437
1438
  
  	/*
b843aa216   Remy Bohmer   atmel_serial: cle...
1439
  	 * First, save IMR and then disable interrupts
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1440
  	 */
b843aa216   Remy Bohmer   atmel_serial: cle...
1441
  	imr = UART_GET_IMR(port);
e8faff733   Claudio Scordino   ARM: 6092/1: atme...
1442
  	UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1443

39d4c922b   Marc Pignat   atmel_serial: fix...
1444
1445
1446
  	/* Store PDC transmit status and disable it */
  	pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
  	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1447
  	uart_console_write(port, s, count, atmel_console_putchar);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1448
1449
  
  	/*
b843aa216   Remy Bohmer   atmel_serial: cle...
1450
1451
  	 * Finally, wait for transmitter to become empty
  	 * and restore IMR
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1452
1453
1454
  	 */
  	do {
  		status = UART_GET_CSR(port);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1455
  	} while (!(status & ATMEL_US_TXRDY));
39d4c922b   Marc Pignat   atmel_serial: fix...
1456
1457
1458
1459
  
  	/* Restore PDC transmit status */
  	if (pdc_tx)
  		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
b843aa216   Remy Bohmer   atmel_serial: cle...
1460
1461
  	/* set interrupts back the way they were */
  	UART_PUT_IER(port, imr);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1462
1463
1464
  }
  
  /*
b843aa216   Remy Bohmer   atmel_serial: cle...
1465
1466
   * If the port was already initialised (eg, by a boot loader),
   * try to determine the current setup.
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1467
   */
b843aa216   Remy Bohmer   atmel_serial: cle...
1468
1469
  static void __init atmel_console_get_options(struct uart_port *port, int *baud,
  					     int *parity, int *bits)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1470
1471
  {
  	unsigned int mr, quot;
1c0fd82f9   Haavard Skinnemoen   atmel_serial: use...
1472
1473
1474
1475
  	/*
  	 * If the baud rate generator isn't running, the port wasn't
  	 * initialized by the boot loader.
  	 */
9c81c5c95   Haavard Skinnemoen   atmel_serial: fil...
1476
  	quot = UART_GET_BRGR(port) & ATMEL_US_CD;
1c0fd82f9   Haavard Skinnemoen   atmel_serial: use...
1477
1478
  	if (!quot)
  		return;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1479

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1480
1481
  	mr = UART_GET_MR(port) & ATMEL_US_CHRL;
  	if (mr == ATMEL_US_CHRL_8)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1482
1483
1484
  		*bits = 8;
  	else
  		*bits = 7;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1485
1486
  	mr = UART_GET_MR(port) & ATMEL_US_PAR;
  	if (mr == ATMEL_US_PAR_EVEN)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1487
  		*parity = 'e';
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1488
  	else if (mr == ATMEL_US_PAR_ODD)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1489
  		*parity = 'o';
4d5e392c3   Haavard Skinnemoen   [PATCH] atmel_ser...
1490
1491
1492
1493
1494
1495
  	/*
  	 * The serial core only rounds down when matching this to a
  	 * supported baud rate. Make sure we don't end up slightly
  	 * lower than one of those, as it would make us fall through
  	 * to a much lower baud rate than we really want.
  	 */
4d5e392c3   Haavard Skinnemoen   [PATCH] atmel_ser...
1496
  	*baud = port->uartclk / (16 * (quot - 1));
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1497
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1498
  static int __init atmel_console_setup(struct console *co, char *options)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1499
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1500
  	struct uart_port *port = &atmel_ports[co->index].uart;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1501
1502
1503
1504
  	int baud = 115200;
  	int bits = 8;
  	int parity = 'n';
  	int flow = 'n';
b843aa216   Remy Bohmer   atmel_serial: cle...
1505
1506
  	if (port->membase == NULL) {
  		/* Port not initialized yet - delay setup */
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1507
  		return -ENODEV;
b843aa216   Remy Bohmer   atmel_serial: cle...
1508
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1509

06a7f0587   David Brownell   atmel_serial: kee...
1510
  	clk_enable(atmel_ports[co->index].clk);
b843aa216   Remy Bohmer   atmel_serial: cle...
1511
  	UART_PUT_IDR(port, -1);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1512
1513
  	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
  	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1514
1515
1516
1517
  
  	if (options)
  		uart_parse_options(options, &baud, &parity, &bits, &flow);
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1518
  		atmel_console_get_options(port, &baud, &parity, &bits);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1519
1520
1521
  
  	return uart_set_options(port, co, baud, parity, bits, flow);
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1522
  static struct uart_driver atmel_uart;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1523

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1524
1525
1526
  static struct console atmel_console = {
  	.name		= ATMEL_DEVICENAME,
  	.write		= atmel_console_write,
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1527
  	.device		= uart_console_device,
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1528
  	.setup		= atmel_console_setup,
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1529
1530
  	.flags		= CON_PRINTBUFFER,
  	.index		= -1,
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1531
  	.data		= &atmel_uart,
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1532
  };
06a7f0587   David Brownell   atmel_serial: kee...
1533
  #define ATMEL_CONSOLE_DEVICE	(&atmel_console)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1534

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1535
1536
1537
  /*
   * Early console initialization (before VM subsystem initialized).
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1538
  static int __init atmel_console_init(void)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1539
  {
73e2798b0   Haavard Skinnemoen   [PATCH] at91_seri...
1540
  	if (atmel_default_console_device) {
b843aa216   Remy Bohmer   atmel_serial: cle...
1541
1542
1543
1544
  		add_preferred_console(ATMEL_DEVICENAME,
  				      atmel_default_console_device->id, NULL);
  		atmel_init_port(&atmel_ports[atmel_default_console_device->id],
  				atmel_default_console_device);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1545
  		register_console(&atmel_console);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1546
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1547

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1548
1549
  	return 0;
  }
b843aa216   Remy Bohmer   atmel_serial: cle...
1550

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1551
  console_initcall(atmel_console_init);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1552

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1553
1554
1555
  /*
   * Late console initialization.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1556
  static int __init atmel_late_console_init(void)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1557
  {
b843aa216   Remy Bohmer   atmel_serial: cle...
1558
1559
  	if (atmel_default_console_device
  	    && !(atmel_console.flags & CON_ENABLED))
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1560
  		register_console(&atmel_console);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1561
1562
1563
  
  	return 0;
  }
b843aa216   Remy Bohmer   atmel_serial: cle...
1564

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1565
  core_initcall(atmel_late_console_init);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1566

dfa7f343e   Haavard Skinnemoen   atmel_serial: fix...
1567
1568
1569
1570
  static inline bool atmel_is_console_port(struct uart_port *port)
  {
  	return port->cons && port->cons->index == port->line;
  }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1571
  #else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1572
  #define ATMEL_CONSOLE_DEVICE	NULL
dfa7f343e   Haavard Skinnemoen   atmel_serial: fix...
1573
1574
1575
1576
1577
  
  static inline bool atmel_is_console_port(struct uart_port *port)
  {
  	return false;
  }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1578
  #endif
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1579
  static struct uart_driver atmel_uart = {
b843aa216   Remy Bohmer   atmel_serial: cle...
1580
1581
1582
1583
1584
1585
1586
  	.owner		= THIS_MODULE,
  	.driver_name	= "atmel_serial",
  	.dev_name	= ATMEL_DEVICENAME,
  	.major		= SERIAL_ATMEL_MAJOR,
  	.minor		= MINOR_START,
  	.nr		= ATMEL_MAX_UART,
  	.cons		= ATMEL_CONSOLE_DEVICE,
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1587
  };
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1588
  #ifdef CONFIG_PM
f826caa44   Haavard Skinnemoen   atmel_serial: Fix...
1589
1590
1591
1592
1593
1594
1595
1596
  static bool atmel_serial_clk_will_stop(void)
  {
  #ifdef CONFIG_ARCH_AT91
  	return at91_suspend_entering_slow_clock();
  #else
  	return false;
  #endif
  }
b843aa216   Remy Bohmer   atmel_serial: cle...
1597
1598
  static int atmel_serial_suspend(struct platform_device *pdev,
  				pm_message_t state)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1599
  {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1600
  	struct uart_port *port = platform_get_drvdata(pdev);
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
1601
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1602

e1c609efb   Haavard Skinnemoen   atmel_serial: Dra...
1603
1604
1605
1606
1607
  	if (atmel_is_console_port(port) && console_suspend_enabled) {
  		/* Drain the TX shifter */
  		while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
  			cpu_relax();
  	}
f05596dbc   Anti Sullin   atmel_serial: upd...
1608
1609
1610
1611
1612
1613
  	/* we can not wake up if we're running on slow clock */
  	atmel_port->may_wakeup = device_may_wakeup(&pdev->dev);
  	if (atmel_serial_clk_will_stop())
  		device_set_wakeup_enable(&pdev->dev, 0);
  
  	uart_suspend_port(&atmel_uart, port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1614

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1615
1616
  	return 0;
  }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1617

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1618
  static int atmel_serial_resume(struct platform_device *pdev)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1619
1620
  {
  	struct uart_port *port = platform_get_drvdata(pdev);
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
1621
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1622

f05596dbc   Anti Sullin   atmel_serial: upd...
1623
1624
  	uart_resume_port(&atmel_uart, port);
  	device_set_wakeup_enable(&pdev->dev, atmel_port->may_wakeup);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1625
1626
1627
  
  	return 0;
  }
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1628
  #else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1629
1630
  #define atmel_serial_suspend NULL
  #define atmel_serial_resume NULL
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1631
  #endif
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1632

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1633
  static int __devinit atmel_serial_probe(struct platform_device *pdev)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1634
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1635
  	struct atmel_uart_port *port;
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
1636
  	void *data;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1637
  	int ret;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1638

9d09daf8e   Haavard Skinnemoen   atmel_serial: fix...
1639
  	BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
1640

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1641
  	port = &atmel_ports[pdev->id];
f05596dbc   Anti Sullin   atmel_serial: upd...
1642
  	port->backup_imr = 0;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1643
  	atmel_init_port(port, pdev);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1644

a66706158   Chip Coldwell   atmel_serial: add...
1645
1646
  	if (!atmel_use_dma_rx(&port->uart)) {
  		ret = -ENOMEM;
6433471d3   Haavard Skinnemoen   atmel_serial: fix...
1647
1648
  		data = kmalloc(sizeof(struct atmel_uart_char)
  				* ATMEL_SERIAL_RINGSIZE, GFP_KERNEL);
a66706158   Chip Coldwell   atmel_serial: add...
1649
1650
1651
1652
  		if (!data)
  			goto err_alloc_ring;
  		port->rx_ring.buf = data;
  	}
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
1653

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1654
  	ret = uart_add_one_port(&atmel_uart, &port->uart);
dfa7f343e   Haavard Skinnemoen   atmel_serial: fix...
1655
1656
  	if (ret)
  		goto err_add_port;
8da14b5fc   Albin Tonnerre   drivers/serial/at...
1657
  #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
06a7f0587   David Brownell   atmel_serial: kee...
1658
1659
1660
1661
1662
1663
1664
1665
  	if (atmel_is_console_port(&port->uart)
  			&& ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) {
  		/*
  		 * The serial core enabled the clock for us, so undo
  		 * the clk_enable() in atmel_console_setup()
  		 */
  		clk_disable(port->clk);
  	}
8da14b5fc   Albin Tonnerre   drivers/serial/at...
1666
  #endif
06a7f0587   David Brownell   atmel_serial: kee...
1667

dfa7f343e   Haavard Skinnemoen   atmel_serial: fix...
1668
1669
1670
1671
1672
1673
  	device_init_wakeup(&pdev->dev, 1);
  	platform_set_drvdata(pdev, port);
  
  	return 0;
  
  err_add_port:
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
1674
1675
1676
  	kfree(port->rx_ring.buf);
  	port->rx_ring.buf = NULL;
  err_alloc_ring:
dfa7f343e   Haavard Skinnemoen   atmel_serial: fix...
1677
  	if (!atmel_is_console_port(&port->uart)) {
dfa7f343e   Haavard Skinnemoen   atmel_serial: fix...
1678
1679
  		clk_put(port->clk);
  		port->clk = NULL;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1680
1681
1682
1683
  	}
  
  	return ret;
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1684
  static int __devexit atmel_serial_remove(struct platform_device *pdev)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1685
1686
  {
  	struct uart_port *port = platform_get_drvdata(pdev);
c811ab8c2   Haavard Skinnemoen   atmel_serial: use...
1687
  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1688
  	int ret = 0;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1689
1690
  	device_init_wakeup(&pdev->dev, 0);
  	platform_set_drvdata(pdev, NULL);
dfa7f343e   Haavard Skinnemoen   atmel_serial: fix...
1691
  	ret = uart_remove_one_port(&atmel_uart, port);
1ecc26bd2   Remy Bohmer   atmel_serial: spl...
1692
1693
  	tasklet_kill(&atmel_port->tasklet);
  	kfree(atmel_port->rx_ring.buf);
dfa7f343e   Haavard Skinnemoen   atmel_serial: fix...
1694
  	/* "port" is allocated statically, so we shouldn't free it */
dfa7f343e   Haavard Skinnemoen   atmel_serial: fix...
1695
  	clk_put(atmel_port->clk);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1696
1697
1698
  
  	return ret;
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1699
1700
1701
1702
1703
  static struct platform_driver atmel_serial_driver = {
  	.probe		= atmel_serial_probe,
  	.remove		= __devexit_p(atmel_serial_remove),
  	.suspend	= atmel_serial_suspend,
  	.resume		= atmel_serial_resume,
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1704
  	.driver		= {
1e8ea8021   Haavard Skinnemoen   [PATCH] at91_seri...
1705
  		.name	= "atmel_usart",
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1706
1707
1708
  		.owner	= THIS_MODULE,
  	},
  };
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1709
  static int __init atmel_serial_init(void)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1710
1711
  {
  	int ret;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1712
  	ret = uart_register_driver(&atmel_uart);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1713
1714
  	if (ret)
  		return ret;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1715
  	ret = platform_driver_register(&atmel_serial_driver);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1716
  	if (ret)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1717
  		uart_unregister_driver(&atmel_uart);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1718
1719
1720
  
  	return ret;
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1721
  static void __exit atmel_serial_exit(void)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
1722
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1723
1724
  	platform_driver_unregister(&atmel_serial_driver);
  	uart_unregister_driver(&atmel_uart);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1725
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1726
1727
  module_init(atmel_serial_init);
  module_exit(atmel_serial_exit);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1728
1729
  
  MODULE_AUTHOR("Rick Bronson");
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
1730
  MODULE_DESCRIPTION("Atmel AT91 / AT32 serial port driver");
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
1731
  MODULE_LICENSE("GPL");
e169c1396   Kay Sievers   serial: fix platf...
1732
  MODULE_ALIAS("platform:atmel_usart");