Blame view

drivers/serial/atmel_serial.c 25.8 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
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   *  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.
   *
   * 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...
25
26
27
28
29
30
  #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...
31
  #include <linux/clk.h>
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
32
33
34
  #include <linux/console.h>
  #include <linux/sysrq.h>
  #include <linux/tty_flip.h>
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
35
  #include <linux/platform_device.h>
93a3ddc20   Andrew Victor   [ARM] 4151/1: AT9...
36
  #include <linux/atmel_pdc.h>
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
37
38
  
  #include <asm/io.h>
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
39
  #include <asm/mach/serial_at91.h>
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
40
  #include <asm/arch/board.h>
93a3ddc20   Andrew Victor   [ARM] 4151/1: AT9...
41

acca9b83a   Haavard Skinnemoen   [PATCH] atmel_ser...
42
  #ifdef CONFIG_ARM
c2f5ccfbd   Andrew Victor   [ARM] 3973/1: AT9...
43
  #include <asm/arch/cpu.h>
20e652761   Andrew Victor   [ARM] 3710/1: AT9...
44
  #include <asm/arch/gpio.h>
acca9b83a   Haavard Skinnemoen   [PATCH] atmel_ser...
45
  #endif
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
46

5b34821a6   Haavard Skinnemoen   [PATCH] at91_seri...
47
  #include "atmel_serial.h"
749c4e603   Haavard Skinnemoen   [PATCH] at91_seri...
48
  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
49
50
51
52
  #define SUPPORT_SYSRQ
  #endif
  
  #include <linux/serial_core.h>
749c4e603   Haavard Skinnemoen   [PATCH] at91_seri...
53
  #ifdef CONFIG_SERIAL_ATMEL_TTYAT
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
54
55
56
57
  
  /* 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...
58
  #define SERIAL_ATMEL_MAJOR	204
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
59
  #define MINOR_START		154
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
60
  #define ATMEL_DEVICENAME	"ttyAT"
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
61
62
63
64
65
  
  #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...
66
  #define SERIAL_ATMEL_MAJOR	TTY_MAJOR
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
67
  #define MINOR_START		64
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
68
  #define ATMEL_DEVICENAME	"ttyS"
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
69
70
  
  #endif
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
71
  #define ATMEL_ISR_PASS_LIMIT	256
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
72

544fc7283   Haavard Skinnemoen   [PATCH] atmel_ser...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  #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)
  
  // #define UART_GET_CR(port)	__raw_readl((port)->membase + ATMEL_US_CR)		// is write-only
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
87
88
  
   /* PDC registers */
544fc7283   Haavard Skinnemoen   [PATCH] atmel_ser...
89
90
91
92
93
94
95
96
97
98
99
100
101
  #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)
  //#define UART_PUT_TNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TNPR)
  //#define UART_PUT_TNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TNCR)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
102

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

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
106
107
108
  /*
   * We wrap our port structure around the generic uart_port.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
109
  struct atmel_uart_port {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
110
111
112
  	struct uart_port	uart;		/* uart */
  	struct clk		*clk;		/* uart clock */
  	unsigned short		suspended;	/* is port suspended? */
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
113
  	int			break_active;	/* break being received */
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
114
  };
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
115
  static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
116

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
117
  #ifdef SUPPORT_SYSRQ
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
118
  static struct console atmel_console;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
119
120
121
122
123
  #endif
  
  /*
   * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
124
  static u_int atmel_tx_empty(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
125
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
126
  	return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
127
128
129
130
131
  }
  
  /*
   * Set state of the modem control output lines
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
132
  static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
133
134
  {
  	unsigned int control = 0;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
135
  	unsigned int mode;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
136

c2f5ccfbd   Andrew Victor   [ARM] 3973/1: AT9...
137
  #ifdef CONFIG_ARCH_AT91RM9200
79da7a610   Andrew Victor   [ARM] 3947/1: AT9...
138
  	if (cpu_is_at91rm9200()) {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
139
140
141
142
  		/*
  		 * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21.
  		 *  We need to drive the pin manually.
  		 */
72729910c   Andrew Victor   [ARM] 3865/1: AT9...
143
  		if (port->mapbase == AT91RM9200_BASE_US0) {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
144
  			if (mctrl & TIOCM_RTS)
20e652761   Andrew Victor   [ARM] 3710/1: AT9...
145
  				at91_set_gpio_value(AT91_PIN_PA21, 0);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
146
  			else
20e652761   Andrew Victor   [ARM] 3710/1: AT9...
147
  				at91_set_gpio_value(AT91_PIN_PA21, 1);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
148
  		}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
149
  	}
acca9b83a   Haavard Skinnemoen   [PATCH] atmel_ser...
150
  #endif
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
151
152
  
  	if (mctrl & TIOCM_RTS)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
153
  		control |= ATMEL_US_RTSEN;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
154
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
155
  		control |= ATMEL_US_RTSDIS;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
156
157
  
  	if (mctrl & TIOCM_DTR)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
158
  		control |= ATMEL_US_DTREN;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
159
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
160
  		control |= ATMEL_US_DTRDIS;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
161

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
162
163
164
  	UART_PUT_CR(port, control);
  
  	/* Local loopback mode? */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
165
  	mode = UART_GET_MR(port) & ~ATMEL_US_CHMODE;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
166
  	if (mctrl & TIOCM_LOOP)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
167
  		mode |= ATMEL_US_CHMODE_LOC_LOOP;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
168
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
169
  		mode |= ATMEL_US_CHMODE_NORMAL;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
170
  	UART_PUT_MR(port, mode);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
171
172
173
174
175
  }
  
  /*
   * Get state of the modem control input lines
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
176
  static u_int atmel_get_mctrl(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
177
178
179
180
181
182
183
184
  {
  	unsigned int status, ret = 0;
  
  	status = UART_GET_CSR(port);
  
  	/*
  	 * The control signals are active low.
  	 */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
185
  	if (!(status & ATMEL_US_DCD))
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
186
  		ret |= TIOCM_CD;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
187
  	if (!(status & ATMEL_US_CTS))
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
188
  		ret |= TIOCM_CTS;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
189
  	if (!(status & ATMEL_US_DSR))
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
190
  		ret |= TIOCM_DSR;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
191
  	if (!(status & ATMEL_US_RI))
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
192
193
194
195
196
197
198
199
  		ret |= TIOCM_RI;
  
  	return ret;
  }
  
  /*
   * Stop transmitting.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
200
  static void atmel_stop_tx(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
201
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
202
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
203

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
204
  	UART_PUT_IDR(port, ATMEL_US_TXRDY);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
205
206
207
208
209
  }
  
  /*
   * Start transmitting.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
210
  static void atmel_start_tx(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
211
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
212
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
213

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
214
  	UART_PUT_IER(port, ATMEL_US_TXRDY);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
215
216
217
218
219
  }
  
  /*
   * Stop receiving - port is in process of being closed.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
220
  static void atmel_stop_rx(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
221
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
222
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
223

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
224
  	UART_PUT_IDR(port, ATMEL_US_RXRDY);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
225
226
227
228
229
  }
  
  /*
   * Enable modem status interrupts
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
230
  static void atmel_enable_ms(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
231
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
232
  	UART_PUT_IER(port, ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC | ATMEL_US_CTSIC);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
233
234
235
236
237
  }
  
  /*
   * Control the transmission of a break signal
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
238
  static void atmel_break_ctl(struct uart_port *port, int break_state)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
239
240
  {
  	if (break_state != 0)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
241
  		UART_PUT_CR(port, ATMEL_US_STTBRK);	/* start break */
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
242
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
243
  		UART_PUT_CR(port, ATMEL_US_STPBRK);	/* stop break */
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
244
245
246
247
248
  }
  
  /*
   * Characters received (called from interrupt handler)
   */
7d12e780e   David Howells   IRQ: Maintain reg...
249
  static void atmel_rx_chars(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
250
  {
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
251
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
252
253
  	struct tty_struct *tty = port->info->tty;
  	unsigned int status, ch, flg;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
254
  	status = UART_GET_CSR(port);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
255
  	while (status & ATMEL_US_RXRDY) {
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
256
  		ch = UART_GET_CHAR(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
257
258
259
260
261
262
263
264
  		port->icount.rx++;
  
  		flg = TTY_NORMAL;
  
  		/*
  		 * note that the error handling code is
  		 * out of the main execution path
  		 */
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
265
266
267
  		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
  				       | ATMEL_US_OVRE | ATMEL_US_RXBRK)
  			     || atmel_port->break_active)) {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
268
  			UART_PUT_CR(port, ATMEL_US_RSTSTA);	/* clear error */
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
269
270
  			if (status & ATMEL_US_RXBRK
  			    && !atmel_port->break_active) {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
271
  				status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);	/* ignore side-effect */
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
272
  				port->icount.brk++;
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
273
274
  				atmel_port->break_active = 1;
  				UART_PUT_IER(port, ATMEL_US_RXBRK);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
275
276
  				if (uart_handle_break(port))
  					goto ignore_char;
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
277
278
279
280
281
282
283
284
285
286
287
  			} 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...
288
  			}
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
289
  			if (status & ATMEL_US_PARE)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
290
  				port->icount.parity++;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
291
  			if (status & ATMEL_US_FRAME)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
292
  				port->icount.frame++;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
293
  			if (status & ATMEL_US_OVRE)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
294
  				port->icount.overrun++;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
295
  			status &= port->read_status_mask;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
296
  			if (status & ATMEL_US_RXBRK)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
297
  				flg = TTY_BREAK;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
298
  			else if (status & ATMEL_US_PARE)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
299
  				flg = TTY_PARITY;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
300
  			else if (status & ATMEL_US_FRAME)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
301
  				flg = TTY_FRAME;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
302
  		}
7d12e780e   David Howells   IRQ: Maintain reg...
303
  		if (uart_handle_sysrq_char(port, ch))
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
304
  			goto ignore_char;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
305
  		uart_insert_char(port, status, ATMEL_US_OVRE, ch, flg);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
306
307
  
  	ignore_char:
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
308
  		status = UART_GET_CSR(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
309
310
311
312
313
314
315
316
  	}
  
  	tty_flip_buffer_push(tty);
  }
  
  /*
   * Transmit characters (called from interrupt handler)
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
317
  static void atmel_tx_chars(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
318
319
320
321
322
323
324
325
326
327
  {
  	struct circ_buf *xmit = &port->info->xmit;
  
  	if (port->x_char) {
  		UART_PUT_CHAR(port, port->x_char);
  		port->icount.tx++;
  		port->x_char = 0;
  		return;
  	}
  	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
328
  		atmel_stop_tx(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
329
330
  		return;
  	}
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
331
  	while (UART_GET_CSR(port) & ATMEL_US_TXRDY) {
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
332
333
334
335
336
337
338
339
340
341
342
  		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);
  
  	if (uart_circ_empty(xmit))
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
343
  		atmel_stop_tx(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
344
345
346
347
348
  }
  
  /*
   * Interrupt handler
   */
7d12e780e   David Howells   IRQ: Maintain reg...
349
  static irqreturn_t atmel_interrupt(int irq, void *dev_id)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
350
351
  {
  	struct uart_port *port = dev_id;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
352
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
353
354
355
  	unsigned int status, pending, pass_counter = 0;
  
  	status = UART_GET_CSR(port);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
356
357
358
  	pending = status & UART_GET_IMR(port);
  	while (pending) {
  		/* Interrupt receive */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
359
  		if (pending & ATMEL_US_RXRDY)
7d12e780e   David Howells   IRQ: Maintain reg...
360
  			atmel_rx_chars(port);
9e6077bd8   Haavard Skinnemoen   atmel_serial: fix...
361
362
363
364
365
366
367
368
369
370
  		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;
  		}
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
371
372
  
  		// TODO: All reads to CSR will clear these interrupts!
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
373
374
375
376
377
378
379
  		if (pending & ATMEL_US_RIIC) port->icount.rng++;
  		if (pending & ATMEL_US_DSRIC) port->icount.dsr++;
  		if (pending & ATMEL_US_DCDIC)
  			uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
  		if (pending & ATMEL_US_CTSIC)
  			uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
  		if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC | ATMEL_US_CTSIC))
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
380
381
382
  			wake_up_interruptible(&port->info->delta_msr_wait);
  
  		/* Interrupt transmit */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
383
384
  		if (pending & ATMEL_US_TXRDY)
  			atmel_tx_chars(port);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
385

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
386
  		if (pass_counter++ > ATMEL_ISR_PASS_LIMIT)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
387
  			break;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
388

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
389
390
  		status = UART_GET_CSR(port);
  		pending = status & UART_GET_IMR(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
391
392
393
394
395
396
397
  	}
  	return IRQ_HANDLED;
  }
  
  /*
   * Perform initialization and enable port for reception
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
398
  static int atmel_startup(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
399
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
400
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
401
402
403
404
405
406
407
408
409
410
411
412
  	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
  	 */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
413
  	retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED, "atmel_serial", port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
414
  	if (retval) {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
415
416
  		printk("atmel_serial: atmel_startup - Can't get irq
  ");
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
417
418
419
420
421
422
423
  		return retval;
  	}
  
  	/*
  	 * If there is a specific "open" function (to register
  	 * control line interrupts)
  	 */
71f2e2b87   Haavard Skinnemoen   [PATCH] atmel_ser...
424
425
  	if (atmel_open_hook) {
  		retval = atmel_open_hook(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
426
427
428
429
430
  		if (retval) {
  			free_irq(port->irq, port);
  			return retval;
  		}
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
431
432
433
  	/*
  	 * Finally, enable the serial port
  	 */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
434
435
  	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
  	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);		/* enable xmit & rcvr */
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
436

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
437
  	UART_PUT_IER(port, ATMEL_US_RXRDY);		/* enable receive only */
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
438

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
439
440
441
442
443
444
  	return 0;
  }
  
  /*
   * Disable the port
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
445
  static void atmel_shutdown(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
446
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
447
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
448

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
449
450
451
  	/*
  	 * Disable all interrupts, port and break condition.
  	 */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
452
  	UART_PUT_CR(port, ATMEL_US_RSTSTA);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
453
454
455
456
457
458
459
460
461
462
463
  	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...
464
465
  	if (atmel_close_hook)
  		atmel_close_hook(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
466
467
468
469
470
  }
  
  /*
   * Power / Clock management.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
471
  static void atmel_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
472
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
473
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
474

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
475
476
477
478
479
480
  	switch (state) {
  		case 0:
  			/*
  			 * Enable the peripheral clock for this serial port.
  			 * This is called on uart_open() or a resume event.
  			 */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
481
  			clk_enable(atmel_port->clk);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
482
483
484
485
486
487
  			break;
  		case 3:
  			/*
  			 * Disable the peripheral clock for this serial port.
  			 * This is called on uart_close() or a suspend event.
  			 */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
488
  			clk_disable(atmel_port->clk);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
489
490
  			break;
  		default:
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
491
492
  			printk(KERN_ERR "atmel_serial: unknown pm %d
  ", state);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
493
494
495
496
497
498
  	}
  }
  
  /*
   * Change the port parameters
   */
606d099cd   Alan Cox   [PATCH] tty: swit...
499
  static void atmel_set_termios(struct uart_port *port, struct ktermios * termios, struct ktermios * old)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
500
501
502
  {
  	unsigned long flags;
  	unsigned int mode, imr, quot, baud;
03abeac0a   Andrew Victor   [ARM] 4357/1: AT9...
503
504
  	/* Get current mode register */
  	mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
505
506
  	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
  	quot = uart_get_divisor(port, baud);
03abeac0a   Andrew Victor   [ARM] 4357/1: AT9...
507
508
509
510
  	if (quot > 65535) {		/* BRGR is 16-bit, so switch to slower clock */
  		quot /= 8;
  		mode |= ATMEL_US_USCLKS_MCK_DIV8;
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
511
512
513
514
  
  	/* byte size */
  	switch (termios->c_cflag & CSIZE) {
  	case CS5:
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
515
  		mode |= ATMEL_US_CHRL_5;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
516
517
  		break;
  	case CS6:
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
518
  		mode |= ATMEL_US_CHRL_6;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
519
520
  		break;
  	case CS7:
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
521
  		mode |= ATMEL_US_CHRL_7;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
522
523
  		break;
  	default:
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
524
  		mode |= ATMEL_US_CHRL_8;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
525
526
527
528
529
  		break;
  	}
  
  	/* stop bits */
  	if (termios->c_cflag & CSTOPB)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
530
  		mode |= ATMEL_US_NBSTOP_2;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
531
532
533
534
535
  
  	/* parity */
  	if (termios->c_cflag & PARENB) {
  		if (termios->c_cflag & CMSPAR) {			/* Mark or Space parity */
  			if (termios->c_cflag & PARODD)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
536
  				mode |= ATMEL_US_PAR_MARK;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
537
  			else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
538
  				mode |= ATMEL_US_PAR_SPACE;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
539
540
  		}
  		else if (termios->c_cflag & PARODD)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
541
  			mode |= ATMEL_US_PAR_ODD;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
542
  		else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
543
  			mode |= ATMEL_US_PAR_EVEN;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
544
545
  	}
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
546
  		mode |= ATMEL_US_PAR_NONE;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
547
548
  
  	spin_lock_irqsave(&port->lock, flags);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
549
  	port->read_status_mask = ATMEL_US_OVRE;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
550
  	if (termios->c_iflag & INPCK)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
551
  		port->read_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
552
  	if (termios->c_iflag & (BRKINT | PARMRK))
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
553
  		port->read_status_mask |= ATMEL_US_RXBRK;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
554
555
556
557
558
559
  
  	/*
  	 * Characters to ignore
  	 */
  	port->ignore_status_mask = 0;
  	if (termios->c_iflag & IGNPAR)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
560
  		port->ignore_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
561
  	if (termios->c_iflag & IGNBRK) {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
562
  		port->ignore_status_mask |= ATMEL_US_RXBRK;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
563
564
565
566
567
  		/*
  		 * 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...
568
  			port->ignore_status_mask |= ATMEL_US_OVRE;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
569
570
571
572
573
574
575
576
577
578
  	}
  
  	// TODO: Ignore all characters if CREAD is set.
  
  	/* update the per-port timeout */
  	uart_update_timeout(port, termios->c_cflag, baud);
  
  	/* disable interrupts and drain transmitter */
  	imr = UART_GET_IMR(port);	/* get interrupt mask */
  	UART_PUT_IDR(port, -1);		/* disable all interrupts */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
579
  	while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY)) { barrier(); }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
580
581
  
  	/* disable receiver and transmitter */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
582
  	UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
583
584
585
586
587
588
  
  	/* 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...
589
590
  	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...
591
592
593
594
595
596
597
598
599
600
601
602
603
604
  
  	/* 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...
605
  static const char *atmel_type(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
606
  {
9ab4f88b7   Haavard Skinnemoen   [PATCH] serial: R...
607
  	return (port->type == PORT_ATMEL) ? "ATMEL_SERIAL" : NULL;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
608
609
610
611
612
  }
  
  /*
   * Release the memory region(s) being used by 'port'.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
613
  static void atmel_release_port(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
614
  {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
615
616
617
618
619
620
621
622
623
  	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...
624
625
626
627
628
  }
  
  /*
   * Request the memory region(s) being used by 'port'.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
629
  static int atmel_request_port(struct uart_port *port)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
630
  {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
631
632
  	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...
633
  	if (!request_mem_region(port->mapbase, size, "atmel_serial"))
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
634
635
636
637
638
639
640
641
642
  		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...
643

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
644
  	return 0;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
645
646
647
648
649
  }
  
  /*
   * Configure/autoconfigure the port.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
650
  static void atmel_config_port(struct uart_port *port, int flags)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
651
652
  {
  	if (flags & UART_CONFIG_TYPE) {
9ab4f88b7   Haavard Skinnemoen   [PATCH] serial: R...
653
  		port->type = PORT_ATMEL;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
654
  		atmel_request_port(port);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
655
656
657
658
659
660
  	}
  }
  
  /*
   * Verify the new serial_struct (for TIOCSSERIAL).
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
661
  static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
662
663
  {
  	int ret = 0;
9ab4f88b7   Haavard Skinnemoen   [PATCH] serial: R...
664
  	if (ser->type != PORT_UNKNOWN && ser->type != PORT_ATMEL)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
  		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;
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
  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,
  	.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,
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
698
  };
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
699
700
701
  /*
   * Configure the port from the platform device resource info.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
702
  static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, struct platform_device *pdev)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
703
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
704
  	struct uart_port *port = &atmel_port->uart;
73e2798b0   Haavard Skinnemoen   [PATCH] at91_seri...
705
  	struct atmel_uart_data *data = pdev->dev.platform_data;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
706
707
  
  	port->iotype	= UPIO_MEM;
a14d52730   Andrew Victor   [ARM] 4086/1: AT9...
708
  	port->flags	= UPF_BOOT_AUTOCONF;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
709
  	port->ops	= &atmel_pops;
a14d52730   Andrew Victor   [ARM] 4086/1: AT9...
710
  	port->fifosize	= 1;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
711
712
713
714
715
  	port->line	= pdev->id;
  	port->dev	= &pdev->dev;
  
  	port->mapbase	= pdev->resource[0].start;
  	port->irq	= pdev->resource[1].start;
75d352137   Haavard Skinnemoen   [PATCH] atmel_ser...
716
717
718
  	if (data->regs)
  		/* Already mapped by setup code */
  		port->membase = data->regs;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
719
720
721
722
  	else {
  		port->flags	|= UPF_IOREMAP;
  		port->membase	= NULL;
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
723

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
724
725
726
727
  	if (!atmel_port->clk) {		/* for console, the clock could already be configured */
  		atmel_port->clk = clk_get(&pdev->dev, "usart");
  		clk_enable(atmel_port->clk);
  		port->uartclk = clk_get_rate(atmel_port->clk);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
728
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
729
  }
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
730
731
732
  /*
   * Register board-specific modem-control line handlers.
   */
71f2e2b87   Haavard Skinnemoen   [PATCH] atmel_ser...
733
  void __init atmel_register_uart_fns(struct atmel_port_fns *fns)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
734
735
  {
  	if (fns->enable_ms)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
736
  		atmel_pops.enable_ms = fns->enable_ms;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
737
  	if (fns->get_mctrl)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
738
  		atmel_pops.get_mctrl = fns->get_mctrl;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
739
  	if (fns->set_mctrl)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
740
  		atmel_pops.set_mctrl = fns->set_mctrl;
71f2e2b87   Haavard Skinnemoen   [PATCH] atmel_ser...
741
742
  	atmel_open_hook		= fns->open;
  	atmel_close_hook	= fns->close;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
743
744
  	atmel_pops.pm		= fns->pm;
  	atmel_pops.set_wake	= fns->set_wake;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
745
  }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
746

749c4e603   Haavard Skinnemoen   [PATCH] at91_seri...
747
  #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
748
  static void atmel_console_putchar(struct uart_port *port, int ch)
d358788f3   Russell King   [SERIAL] kernel c...
749
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
750
  	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
d358788f3   Russell King   [SERIAL] kernel c...
751
752
753
  		barrier();
  	UART_PUT_CHAR(port, ch);
  }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
754
755
756
757
  
  /*
   * Interrupts are disabled on entering
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
758
  static void atmel_console_write(struct console *co, const char *s, u_int count)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
759
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
760
  	struct uart_port *port = &atmel_ports[co->index].uart;
d358788f3   Russell King   [SERIAL] kernel c...
761
  	unsigned int status, imr;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
762
763
764
765
766
  
  	/*
  	 *	First, save IMR and then disable interrupts
  	 */
  	imr = UART_GET_IMR(port);	/* get interrupt mask */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
767
  	UART_PUT_IDR(port, ATMEL_US_RXRDY | ATMEL_US_TXRDY);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
768

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
769
  	uart_console_write(port, s, count, atmel_console_putchar);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
770
771
772
773
774
775
776
  
  	/*
  	 *	Finally, wait for transmitter to become empty
  	 *	and restore IMR
  	 */
  	do {
  		status = UART_GET_CSR(port);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
777
  	} while (!(status & ATMEL_US_TXRDY));
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
778
779
780
781
782
783
784
  	UART_PUT_IER(port, imr);	/* set interrupts back the way they were */
  }
  
  /*
   * If the port was already initialised (eg, by a boot loader), try to determine
   * the current setup.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
785
  static void __init atmel_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
786
787
788
789
790
791
  {
  	unsigned int mr, quot;
  
  // TODO: CR is a write-only register
  //	unsigned int cr;
  //
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
792
793
  //	cr = UART_GET_CR(port) & (ATMEL_US_RXEN | ATMEL_US_TXEN);
  //	if (cr == (ATMEL_US_RXEN | ATMEL_US_TXEN)) {
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
794
795
  //		/* ok, the port was enabled */
  //	}
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
796
797
  	mr = UART_GET_MR(port) & ATMEL_US_CHRL;
  	if (mr == ATMEL_US_CHRL_8)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
798
799
800
  		*bits = 8;
  	else
  		*bits = 7;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
801
802
  	mr = UART_GET_MR(port) & ATMEL_US_PAR;
  	if (mr == ATMEL_US_PAR_EVEN)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
803
  		*parity = 'e';
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
804
  	else if (mr == ATMEL_US_PAR_ODD)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
805
  		*parity = 'o';
4d5e392c3   Haavard Skinnemoen   [PATCH] atmel_ser...
806
807
808
809
810
811
  	/*
  	 * 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.
  	 */
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
812
  	quot = UART_GET_BRGR(port);
4d5e392c3   Haavard Skinnemoen   [PATCH] atmel_ser...
813
  	*baud = port->uartclk / (16 * (quot - 1));
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
814
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
815
  static int __init atmel_console_setup(struct console *co, char *options)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
816
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
817
  	struct uart_port *port = &atmel_ports[co->index].uart;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
818
819
820
821
  	int baud = 115200;
  	int bits = 8;
  	int parity = 'n';
  	int flow = 'n';
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
822
823
  	if (port->membase == 0)		/* Port not initialized yet - delay setup */
  		return -ENODEV;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
824

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
825
  	UART_PUT_IDR(port, -1);				/* disable interrupts */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
826
827
  	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...
828
829
830
831
  
  	if (options)
  		uart_parse_options(options, &baud, &parity, &bits, &flow);
  	else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
832
  		atmel_console_get_options(port, &baud, &parity, &bits);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
833
834
835
  
  	return uart_set_options(port, co, baud, parity, bits, flow);
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
836
  static struct uart_driver atmel_uart;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
837

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
838
839
840
  static struct console atmel_console = {
  	.name		= ATMEL_DEVICENAME,
  	.write		= atmel_console_write,
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
841
  	.device		= uart_console_device,
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
842
  	.setup		= atmel_console_setup,
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
843
844
  	.flags		= CON_PRINTBUFFER,
  	.index		= -1,
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
845
  	.data		= &atmel_uart,
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
846
  };
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
847
  #define ATMEL_CONSOLE_DEVICE	&atmel_console
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
848

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
849
850
851
  /*
   * Early console initialization (before VM subsystem initialized).
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
852
  static int __init atmel_console_init(void)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
853
  {
73e2798b0   Haavard Skinnemoen   [PATCH] at91_seri...
854
  	if (atmel_default_console_device) {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
855
856
857
  		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);
  		register_console(&atmel_console);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
858
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
859

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
860
861
  	return 0;
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
862
  console_initcall(atmel_console_init);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
863

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
864
865
866
  /*
   * Late console initialization.
   */
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
867
  static int __init atmel_late_console_init(void)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
868
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
869
870
  	if (atmel_default_console_device && !(atmel_console.flags & CON_ENABLED))
  		register_console(&atmel_console);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
871
872
873
  
  	return 0;
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
874
  core_initcall(atmel_late_console_init);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
875

1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
876
  #else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
877
  #define ATMEL_CONSOLE_DEVICE	NULL
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
878
  #endif
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
879
  static struct uart_driver atmel_uart = {
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
880
  	.owner			= THIS_MODULE,
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
881
882
883
  	.driver_name		= "atmel_serial",
  	.dev_name		= ATMEL_DEVICENAME,
  	.major			= SERIAL_ATMEL_MAJOR,
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
884
  	.minor			= MINOR_START,
73e2798b0   Haavard Skinnemoen   [PATCH] at91_seri...
885
  	.nr			= ATMEL_MAX_UART,
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
886
  	.cons			= ATMEL_CONSOLE_DEVICE,
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
887
  };
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
888
  #ifdef CONFIG_PM
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
889
  static int atmel_serial_suspend(struct platform_device *pdev, pm_message_t state)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
890
  {
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
891
  	struct uart_port *port = platform_get_drvdata(pdev);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
892
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
893
894
895
896
  
  	if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock())
  		enable_irq_wake(port->irq);
  	else {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
897
898
  		uart_suspend_port(&atmel_uart, port);
  		atmel_port->suspended = 1;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
899
  	}
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
900

afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
901
902
  	return 0;
  }
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
903

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
904
  static int atmel_serial_resume(struct platform_device *pdev)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
905
906
  {
  	struct uart_port *port = platform_get_drvdata(pdev);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
907
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
908

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
909
910
911
  	if (atmel_port->suspended) {
  		uart_resume_port(&atmel_uart, port);
  		atmel_port->suspended = 0;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
912
  	}
9b9381669   Andrew Victor   [ARM] 4088/1: AT9...
913
914
  	else
  		disable_irq_wake(port->irq);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
915
916
917
  
  	return 0;
  }
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
918
  #else
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
919
920
  #define atmel_serial_suspend NULL
  #define atmel_serial_resume NULL
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
921
  #endif
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
922

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
923
  static int __devinit atmel_serial_probe(struct platform_device *pdev)
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
924
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
925
  	struct atmel_uart_port *port;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
926
  	int ret;
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
927

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
928
929
  	port = &atmel_ports[pdev->id];
  	atmel_init_port(port, pdev);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
930

7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
931
  	ret = uart_add_one_port(&atmel_uart, &port->uart);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
932
933
934
935
936
937
938
  	if (!ret) {
  		device_init_wakeup(&pdev->dev, 1);
  		platform_set_drvdata(pdev, port);
  	}
  
  	return ret;
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
939
  static int __devexit atmel_serial_remove(struct platform_device *pdev)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
940
941
  {
  	struct uart_port *port = platform_get_drvdata(pdev);
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
942
  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
943
  	int ret = 0;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
944
945
  	clk_disable(atmel_port->clk);
  	clk_put(atmel_port->clk);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
946
947
948
949
950
  
  	device_init_wakeup(&pdev->dev, 0);
  	platform_set_drvdata(pdev, NULL);
  
  	if (port) {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
951
  		ret = uart_remove_one_port(&atmel_uart, port);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
952
953
954
955
956
  		kfree(port);
  	}
  
  	return ret;
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
957
958
959
960
961
  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...
962
  	.driver		= {
1e8ea8021   Haavard Skinnemoen   [PATCH] at91_seri...
963
  		.name	= "atmel_usart",
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
964
965
966
  		.owner	= THIS_MODULE,
  	},
  };
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
967
  static int __init atmel_serial_init(void)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
968
969
  {
  	int ret;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
970
  	ret = uart_register_driver(&atmel_uart);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
971
972
  	if (ret)
  		return ret;
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
973
  	ret = platform_driver_register(&atmel_serial_driver);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
974
  	if (ret)
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
975
  		uart_unregister_driver(&atmel_uart);
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
976
977
978
  
  	return ret;
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
979
  static void __exit atmel_serial_exit(void)
afefc4158   Andrew Victor   [ARM] 3592/1: AT9...
980
  {
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
981
982
  	platform_driver_unregister(&atmel_serial_driver);
  	uart_unregister_driver(&atmel_uart);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
983
  }
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
984
985
  module_init(atmel_serial_init);
  module_exit(atmel_serial_exit);
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
986
987
  
  MODULE_AUTHOR("Rick Bronson");
7192f92c7   Haavard Skinnemoen   [PATCH] at91_seri...
988
  MODULE_DESCRIPTION("Atmel AT91 / AT32 serial port driver");
1e6c9c287   Andrew Victor   [ARM] 3242/2: AT9...
989
  MODULE_LICENSE("GPL");