Diff markup
1 /* 1 /*
2 * linux/drivers/serial/s3c2410.c 2 * linux/drivers/serial/s3c2410.c
3 * 3 *
4 * Driver for onboard UARTs on the Samsung S3C 4 * Driver for onboard UARTs on the Samsung S3C24XX
5 * 5 *
6 * Based on drivers/char/serial.c and drivers/ 6 * Based on drivers/char/serial.c and drivers/char/21285.c
7 * 7 *
8 * Ben Dooks, (c) 2003-2005 Simtec Electronics 8 * Ben Dooks, (c) 2003-2005 Simtec Electronics
9 * http://www.simtec.co.uk/products/SWLIN 9 * http://www.simtec.co.uk/products/SWLINUX/
10 * 10 *
11 * Changelog: 11 * Changelog:
12 * 12 *
13 * 22-Jul-2004 BJD Finished off device rewri 13 * 22-Jul-2004 BJD Finished off device rewrite
14 * 14 *
15 * 21-Jul-2004 BJD Thanks to <herbet@13thflo 15 * 21-Jul-2004 BJD Thanks to <herbet@13thfloor.at> for pointing out
16 * problems with baud rate a 16 * problems with baud rate and loss of IR settings. Update
17 * to add configuration via 17 * to add configuration via platform_device structure
18 * 18 *
19 * 28-Sep-2004 BJD Re-write for the followin 19 * 28-Sep-2004 BJD Re-write for the following items
20 * - S3C2410 and S3C2440 ser 20 * - S3C2410 and S3C2440 serial support
21 * - Power Management suppor 21 * - Power Management support
22 * - Fix console via IrDA de 22 * - Fix console via IrDA devices
23 * - SysReq (Herbert Pötzl) 23 * - SysReq (Herbert Pötzl)
24 * - Break character handlin 24 * - Break character handling (Herbert Pötzl)
25 * - spin-lock initialisatio 25 * - spin-lock initialisation (Dimitry Andric)
26 * - added clock control 26 * - added clock control
27 * - updated init code to us 27 * - updated init code to use platform_device info
28 * 28 *
29 * 06-Mar-2005 BJD Add s3c2440 fclk clock so 29 * 06-Mar-2005 BJD Add s3c2440 fclk clock source
30 * 30 *
31 * 09-Mar-2005 BJD Add s3c2400 support 31 * 09-Mar-2005 BJD Add s3c2400 support
32 * 32 *
33 * 10-Mar-2005 LCVR Changed S3C2410_VA_UART t 33 * 10-Mar-2005 LCVR Changed S3C2410_VA_UART to S3C24XX_VA_UART
34 */ 34 */
35 35
36 /* Note on 2440 fclk clock source handling 36 /* Note on 2440 fclk clock source handling
37 * 37 *
38 * Whilst it is possible to use the fclk as cl 38 * Whilst it is possible to use the fclk as clock source, the method
39 * of properly switching too/from this is curr 39 * of properly switching too/from this is currently un-implemented, so
40 * whichever way is configured at startup is t 40 * whichever way is configured at startup is the one that will be used.
41 */ 41 */
42 42
43 /* Hote on 2410 error handling 43 /* Hote on 2410 error handling
44 * 44 *
45 * The s3c2410 manual has a love/hate affair w 45 * The s3c2410 manual has a love/hate affair with the contents of the
46 * UERSTAT register in the UART blocks, and ke 46 * UERSTAT register in the UART blocks, and keeps marking some of the
47 * error bits as reserved. Having checked with 47 * error bits as reserved. Having checked with the s3c2410x01,
48 * it copes with BREAKs properly, so I am happ 48 * it copes with BREAKs properly, so I am happy to ignore the RESERVED
49 * feature from the latter versions of the man 49 * feature from the latter versions of the manual.
50 * 50 *
51 * If it becomes aparrent that latter versions 51 * If it becomes aparrent that latter versions of the 2410 remove these
52 * bits, then action will have to be taken to 52 * bits, then action will have to be taken to differentiate the versions
53 * and change the policy on BREAK 53 * and change the policy on BREAK
54 * 54 *
55 * BJD, 04-Nov-2004 55 * BJD, 04-Nov-2004
56 */ 56 */
57 57
58 58
59 #if defined(CONFIG_SERIAL_S3C2410_CONSOLE) && 59 #if defined(CONFIG_SERIAL_S3C2410_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
60 #define SUPPORT_SYSRQ 60 #define SUPPORT_SYSRQ
61 #endif 61 #endif
62 62
63 #include <linux/module.h> 63 #include <linux/module.h>
64 #include <linux/ioport.h> 64 #include <linux/ioport.h>
65 #include <linux/platform_device.h> 65 #include <linux/platform_device.h>
66 #include <linux/init.h> 66 #include <linux/init.h>
67 #include <linux/sysrq.h> 67 #include <linux/sysrq.h>
68 #include <linux/console.h> 68 #include <linux/console.h>
69 #include <linux/tty.h> 69 #include <linux/tty.h>
70 #include <linux/tty_flip.h> 70 #include <linux/tty_flip.h>
71 #include <linux/serial_core.h> 71 #include <linux/serial_core.h>
72 #include <linux/serial.h> 72 #include <linux/serial.h>
73 #include <linux/delay.h> 73 #include <linux/delay.h>
74 #include <linux/clk.h> 74 #include <linux/clk.h>
75 75
76 #include <asm/io.h> 76 #include <asm/io.h>
77 #include <asm/irq.h> 77 #include <asm/irq.h>
78 78
79 #include <asm/hardware.h> 79 #include <asm/hardware.h>
80 80
81 #include <asm/plat-s3c/regs-serial.h> 81 #include <asm/plat-s3c/regs-serial.h>
82 #include <asm/arch/regs-gpio.h> 82 #include <asm/arch/regs-gpio.h>
83 83
84 /* structures */ 84 /* structures */
85 85
86 struct s3c24xx_uart_info { 86 struct s3c24xx_uart_info {
87 char *name; 87 char *name;
88 unsigned int type; 88 unsigned int type;
89 unsigned int fifosize; 89 unsigned int fifosize;
90 unsigned long rx_fifomask; 90 unsigned long rx_fifomask;
91 unsigned long rx_fifoshift; 91 unsigned long rx_fifoshift;
92 unsigned long rx_fifofull; 92 unsigned long rx_fifofull;
93 unsigned long tx_fifomask; 93 unsigned long tx_fifomask;
94 unsigned long tx_fifoshift; 94 unsigned long tx_fifoshift;
95 unsigned long tx_fifofull; 95 unsigned long tx_fifofull;
96 96
97 /* clock source control */ 97 /* clock source control */
98 98
99 int (*get_clksrc)(struct uart_port *, 99 int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
100 int (*set_clksrc)(struct uart_port *, 100 int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
101 101
102 /* uart controls */ 102 /* uart controls */
103 int (*reset_port)(struct uart_port *, 103 int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *);
104 }; 104 };
105 105
106 struct s3c24xx_uart_port { 106 struct s3c24xx_uart_port {
107 unsigned char rx_cla 107 unsigned char rx_claimed;
108 unsigned char tx_cla 108 unsigned char tx_claimed;
109 109
110 struct s3c24xx_uart_info *info; 110 struct s3c24xx_uart_info *info;
111 struct s3c24xx_uart_clksrc *clksr 111 struct s3c24xx_uart_clksrc *clksrc;
112 struct clk *clk; 112 struct clk *clk;
113 struct clk *baudc 113 struct clk *baudclk;
114 struct uart_port port; 114 struct uart_port port;
115 }; 115 };
116 116
117 117
118 /* configuration defines */ 118 /* configuration defines */
119 119
120 #if 0 120 #if 0
121 #if 1 121 #if 1
122 /* send debug to the low-level output routines 122 /* send debug to the low-level output routines */
123 123
124 extern void printascii(const char *); 124 extern void printascii(const char *);
125 125
126 static void 126 static void
127 s3c24xx_serial_dbg(const char *fmt, ...) 127 s3c24xx_serial_dbg(const char *fmt, ...)
128 { 128 {
129 va_list va; 129 va_list va;
130 char buff[256]; 130 char buff[256];
131 131
132 va_start(va, fmt); 132 va_start(va, fmt);
133 vsprintf(buff, fmt, va); 133 vsprintf(buff, fmt, va);
134 va_end(va); 134 va_end(va);
135 135
136 printascii(buff); 136 printascii(buff);
137 } 137 }
138 138
139 #define dbg(x...) s3c24xx_serial_dbg(x) 139 #define dbg(x...) s3c24xx_serial_dbg(x)
140 140
141 #else 141 #else
142 #define dbg(x...) printk(KERN_DEBUG "s3c24xx: 142 #define dbg(x...) printk(KERN_DEBUG "s3c24xx: ");
143 #endif 143 #endif
144 #else /* no debug */ 144 #else /* no debug */
145 #define dbg(x...) do {} while(0) 145 #define dbg(x...) do {} while(0)
146 #endif 146 #endif
147 147
148 /* UART name and device definitions */ 148 /* UART name and device definitions */
149 149
150 #define S3C24XX_SERIAL_NAME "ttySAC" 150 #define S3C24XX_SERIAL_NAME "ttySAC"
151 #define S3C24XX_SERIAL_MAJOR 204 151 #define S3C24XX_SERIAL_MAJOR 204
152 #define S3C24XX_SERIAL_MINOR 64 152 #define S3C24XX_SERIAL_MINOR 64
153 153
154 154
155 /* conversion functions */ 155 /* conversion functions */
156 156
157 #define s3c24xx_dev_to_port(__dev) (struct uar 157 #define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev)
158 #define s3c24xx_dev_to_cfg(__dev) (struct s3c2 158 #define s3c24xx_dev_to_cfg(__dev) (struct s3c2410_uartcfg *)((__dev)->platform_data)
159 159
160 /* we can support 3 uarts, but not always use 160 /* we can support 3 uarts, but not always use them */
161 161
162 #ifdef CONFIG_CPU_S3C2400 162 #ifdef CONFIG_CPU_S3C2400
163 #define NR_PORTS (2) 163 #define NR_PORTS (2)
164 #else 164 #else
165 #define NR_PORTS (3) 165 #define NR_PORTS (3)
166 #endif 166 #endif
167 167
168 /* port irq numbers */ 168 /* port irq numbers */
169 169
170 #define TX_IRQ(port) ((port)->irq + 1) 170 #define TX_IRQ(port) ((port)->irq + 1)
171 #define RX_IRQ(port) ((port)->irq) 171 #define RX_IRQ(port) ((port)->irq)
172 172
173 /* register access controls */ 173 /* register access controls */
174 174
175 #define portaddr(port, reg) ((port)->membase + 175 #define portaddr(port, reg) ((port)->membase + (reg))
176 176
177 #define rd_regb(port, reg) (__raw_readb(portad 177 #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
178 #define rd_regl(port, reg) (__raw_readl(portad 178 #define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
179 179
180 #define wr_regb(port, reg, val) \ 180 #define wr_regb(port, reg, val) \
181 do { __raw_writeb(val, portaddr(port, reg)); 181 do { __raw_writeb(val, portaddr(port, reg)); } while(0)
182 182
183 #define wr_regl(port, reg, val) \ 183 #define wr_regl(port, reg, val) \
184 do { __raw_writel(val, portaddr(port, reg)); 184 do { __raw_writel(val, portaddr(port, reg)); } while(0)
185 185
186 /* macros to change one thing to another */ 186 /* macros to change one thing to another */
187 187
188 #define tx_enabled(port) ((port)->unused[0]) 188 #define tx_enabled(port) ((port)->unused[0])
189 #define rx_enabled(port) ((port)->unused[1]) 189 #define rx_enabled(port) ((port)->unused[1])
190 190
191 /* flag to ignore all characters comming in */ 191 /* flag to ignore all characters comming in */
192 #define RXSTAT_DUMMY_READ (0x10000000) 192 #define RXSTAT_DUMMY_READ (0x10000000)
193 193
194 static inline struct s3c24xx_uart_port *to_our 194 static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
195 { 195 {
196 return container_of(port, struct s3c24 196 return container_of(port, struct s3c24xx_uart_port, port);
197 } 197 }
198 198
199 /* translate a port to the device name */ 199 /* translate a port to the device name */
200 200
201 static inline const char *s3c24xx_serial_portn 201 static inline const char *s3c24xx_serial_portname(struct uart_port *port)
202 { 202 {
203 return to_platform_device(port->dev)-> 203 return to_platform_device(port->dev)->name;
204 } 204 }
205 205
206 static int s3c24xx_serial_txempty_nofifo(struc 206 static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
207 { 207 {
208 return (rd_regl(port, S3C2410_UTRSTAT) 208 return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE);
209 } 209 }
210 210
211 static void s3c24xx_serial_rx_enable(struct ua 211 static void s3c24xx_serial_rx_enable(struct uart_port *port)
212 { 212 {
213 unsigned long flags; 213 unsigned long flags;
214 unsigned int ucon, ufcon; 214 unsigned int ucon, ufcon;
215 int count = 10000; 215 int count = 10000;
216 216
217 spin_lock_irqsave(&port->lock, flags); 217 spin_lock_irqsave(&port->lock, flags);
218 218
219 while (--count && !s3c24xx_serial_txem 219 while (--count && !s3c24xx_serial_txempty_nofifo(port))
220 udelay(100); 220 udelay(100);
221 221
222 ufcon = rd_regl(port, S3C2410_UFCON); 222 ufcon = rd_regl(port, S3C2410_UFCON);
223 ufcon |= S3C2410_UFCON_RESETRX; 223 ufcon |= S3C2410_UFCON_RESETRX;
224 wr_regl(port, S3C2410_UFCON, ufcon); 224 wr_regl(port, S3C2410_UFCON, ufcon);
225 225
226 ucon = rd_regl(port, S3C2410_UCON); 226 ucon = rd_regl(port, S3C2410_UCON);
227 ucon |= S3C2410_UCON_RXIRQMODE; 227 ucon |= S3C2410_UCON_RXIRQMODE;
228 wr_regl(port, S3C2410_UCON, ucon); 228 wr_regl(port, S3C2410_UCON, ucon);
229 229
230 rx_enabled(port) = 1; 230 rx_enabled(port) = 1;
231 spin_unlock_irqrestore(&port->lock, fl 231 spin_unlock_irqrestore(&port->lock, flags);
232 } 232 }
233 233
234 static void s3c24xx_serial_rx_disable(struct u 234 static void s3c24xx_serial_rx_disable(struct uart_port *port)
235 { 235 {
236 unsigned long flags; 236 unsigned long flags;
237 unsigned int ucon; 237 unsigned int ucon;
238 238
239 spin_lock_irqsave(&port->lock, flags); 239 spin_lock_irqsave(&port->lock, flags);
240 240
241 ucon = rd_regl(port, S3C2410_UCON); 241 ucon = rd_regl(port, S3C2410_UCON);
242 ucon &= ~S3C2410_UCON_RXIRQMODE; 242 ucon &= ~S3C2410_UCON_RXIRQMODE;
243 wr_regl(port, S3C2410_UCON, ucon); 243 wr_regl(port, S3C2410_UCON, ucon);
244 244
245 rx_enabled(port) = 0; 245 rx_enabled(port) = 0;
246 spin_unlock_irqrestore(&port->lock, fl 246 spin_unlock_irqrestore(&port->lock, flags);
247 } 247 }
248 248
249 static void s3c24xx_serial_stop_tx(struct uart 249 static void s3c24xx_serial_stop_tx(struct uart_port *port)
250 { 250 {
251 if (tx_enabled(port)) { 251 if (tx_enabled(port)) {
252 disable_irq(TX_IRQ(port)); 252 disable_irq(TX_IRQ(port));
253 tx_enabled(port) = 0; 253 tx_enabled(port) = 0;
254 if (port->flags & UPF_CONS_FLO 254 if (port->flags & UPF_CONS_FLOW)
255 s3c24xx_serial_rx_enab 255 s3c24xx_serial_rx_enable(port);
256 } 256 }
257 } 257 }
258 258
259 static void s3c24xx_serial_start_tx(struct uar 259 static void s3c24xx_serial_start_tx(struct uart_port *port)
260 { 260 {
261 if (!tx_enabled(port)) { 261 if (!tx_enabled(port)) {
262 if (port->flags & UPF_CONS_FLO 262 if (port->flags & UPF_CONS_FLOW)
263 s3c24xx_serial_rx_disa 263 s3c24xx_serial_rx_disable(port);
264 264
265 enable_irq(TX_IRQ(port)); 265 enable_irq(TX_IRQ(port));
266 tx_enabled(port) = 1; 266 tx_enabled(port) = 1;
267 } 267 }
268 } 268 }
269 269
270 270
271 static void s3c24xx_serial_stop_rx(struct uart 271 static void s3c24xx_serial_stop_rx(struct uart_port *port)
272 { 272 {
273 if (rx_enabled(port)) { 273 if (rx_enabled(port)) {
274 dbg("s3c24xx_serial_stop_rx: p 274 dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
275 disable_irq(RX_IRQ(port)); 275 disable_irq(RX_IRQ(port));
276 rx_enabled(port) = 0; 276 rx_enabled(port) = 0;
277 } 277 }
278 } 278 }
279 279
280 static void s3c24xx_serial_enable_ms(struct ua 280 static void s3c24xx_serial_enable_ms(struct uart_port *port)
281 { 281 {
282 } 282 }
283 283
284 static inline struct s3c24xx_uart_info *s3c24x 284 static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port)
285 { 285 {
286 return to_ourport(port)->info; 286 return to_ourport(port)->info;
287 } 287 }
288 288
289 static inline struct s3c2410_uartcfg *s3c24xx_ 289 static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port)
290 { 290 {
291 if (port->dev == NULL) 291 if (port->dev == NULL)
292 return NULL; 292 return NULL;
293 293
294 return (struct s3c2410_uartcfg *)port- 294 return (struct s3c2410_uartcfg *)port->dev->platform_data;
295 } 295 }
296 296
297 static int s3c24xx_serial_rx_fifocnt(struct s3 297 static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
298 unsigned 298 unsigned long ufstat)
299 { 299 {
300 struct s3c24xx_uart_info *info = ourpo 300 struct s3c24xx_uart_info *info = ourport->info;
301 301
302 if (ufstat & info->rx_fifofull) 302 if (ufstat & info->rx_fifofull)
303 return info->fifosize; 303 return info->fifosize;
304 304
305 return (ufstat & info->rx_fifomask) >> 305 return (ufstat & info->rx_fifomask) >> info->rx_fifoshift;
306 } 306 }
307 307
308 308
309 /* ? - where has parity gone?? */ 309 /* ? - where has parity gone?? */
310 #define S3C2410_UERSTAT_PARITY (0x1000) 310 #define S3C2410_UERSTAT_PARITY (0x1000)
311 311
312 static irqreturn_t 312 static irqreturn_t
313 s3c24xx_serial_rx_chars(int irq, void *dev_id) 313 s3c24xx_serial_rx_chars(int irq, void *dev_id)
314 { 314 {
315 struct s3c24xx_uart_port *ourport = de 315 struct s3c24xx_uart_port *ourport = dev_id;
316 struct uart_port *port = &ourport->por 316 struct uart_port *port = &ourport->port;
317 struct tty_struct *tty = port->info->t 317 struct tty_struct *tty = port->info->tty;
318 unsigned int ufcon, ch, flag, ufstat, 318 unsigned int ufcon, ch, flag, ufstat, uerstat;
319 int max_count = 64; 319 int max_count = 64;
320 320
321 while (max_count-- > 0) { 321 while (max_count-- > 0) {
322 ufcon = rd_regl(port, S3C2410_ 322 ufcon = rd_regl(port, S3C2410_UFCON);
323 ufstat = rd_regl(port, S3C2410 323 ufstat = rd_regl(port, S3C2410_UFSTAT);
324 324
325 if (s3c24xx_serial_rx_fifocnt( 325 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
326 break; 326 break;
327 327
328 uerstat = rd_regl(port, S3C241 328 uerstat = rd_regl(port, S3C2410_UERSTAT);
329 ch = rd_regb(port, S3C2410_URX 329 ch = rd_regb(port, S3C2410_URXH);
330 330
331 if (port->flags & UPF_CONS_FLO 331 if (port->flags & UPF_CONS_FLOW) {
332 int txe = s3c24xx_seri 332 int txe = s3c24xx_serial_txempty_nofifo(port);
333 333
334 if (rx_enabled(port)) 334 if (rx_enabled(port)) {
335 if (!txe) { 335 if (!txe) {
336 rx_ena 336 rx_enabled(port) = 0;
337 contin 337 continue;
338 } 338 }
339 } else { 339 } else {
340 if (txe) { 340 if (txe) {
341 ufcon 341 ufcon |= S3C2410_UFCON_RESETRX;
342 wr_reg 342 wr_regl(port, S3C2410_UFCON, ufcon);
343 rx_ena 343 rx_enabled(port) = 1;
344 goto o 344 goto out;
345 } 345 }
346 continue; 346 continue;
347 } 347 }
348 } 348 }
349 349
350 /* insert the character into t 350 /* insert the character into the buffer */
351 351
352 flag = TTY_NORMAL; 352 flag = TTY_NORMAL;
353 port->icount.rx++; 353 port->icount.rx++;
354 354
355 if (unlikely(uerstat & S3C2410 355 if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
356 dbg("rxerr: port ch=0x 356 dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
357 ch, uerstat); 357 ch, uerstat);
358 358
359 /* check for break */ 359 /* check for break */
360 if (uerstat & S3C2410_ 360 if (uerstat & S3C2410_UERSTAT_BREAK) {
361 dbg("break!\n" 361 dbg("break!\n");
362 port->icount.b 362 port->icount.brk++;
363 if (uart_handl 363 if (uart_handle_break(port))
364 goto ignor 364 goto ignore_char;
365 } 365 }
366 366
367 if (uerstat & S3C2410_ 367 if (uerstat & S3C2410_UERSTAT_FRAME)
368 port->icount.f 368 port->icount.frame++;
369 if (uerstat & S3C2410_ 369 if (uerstat & S3C2410_UERSTAT_OVERRUN)
370 port->icount.o 370 port->icount.overrun++;
371 371
372 uerstat &= port->read_ 372 uerstat &= port->read_status_mask;
373 373
374 if (uerstat & S3C2410_ 374 if (uerstat & S3C2410_UERSTAT_BREAK)
375 flag = TTY_BRE 375 flag = TTY_BREAK;
376 else if (uerstat & S3C 376 else if (uerstat & S3C2410_UERSTAT_PARITY)
377 flag = TTY_PAR 377 flag = TTY_PARITY;
378 else if (uerstat & ( S 378 else if (uerstat & ( S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_OVERRUN))
379 flag = TTY_FRA 379 flag = TTY_FRAME;
380 } 380 }
381 381
382 if (uart_handle_sysrq_char(por 382 if (uart_handle_sysrq_char(port, ch))
383 goto ignore_char; 383 goto ignore_char;
384 384
385 uart_insert_char(port, uerstat 385 uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag);
386 386
387 ignore_char: 387 ignore_char:
388 continue; 388 continue;
389 } 389 }
390 tty_flip_buffer_push(tty); 390 tty_flip_buffer_push(tty);
391 391
392 out: 392 out:
393 return IRQ_HANDLED; 393 return IRQ_HANDLED;
394 } 394 }
395 395
396 static irqreturn_t s3c24xx_serial_tx_chars(int 396 static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
397 { 397 {
398 struct s3c24xx_uart_port *ourport = id 398 struct s3c24xx_uart_port *ourport = id;
399 struct uart_port *port = &ourport->por 399 struct uart_port *port = &ourport->port;
400 struct circ_buf *xmit = &port->info->x 400 struct circ_buf *xmit = &port->info->xmit;
401 int count = 256; 401 int count = 256;
402 402
403 if (port->x_char) { 403 if (port->x_char) {
404 wr_regb(port, S3C2410_UTXH, po 404 wr_regb(port, S3C2410_UTXH, port->x_char);
405 port->icount.tx++; 405 port->icount.tx++;
406 port->x_char = 0; 406 port->x_char = 0;
407 goto out; 407 goto out;
408 } 408 }
409 409
410 /* if there isnt anything more to tran 410 /* if there isnt anything more to transmit, or the uart is now
411 * stopped, disable the uart and exit 411 * stopped, disable the uart and exit
412 */ 412 */
413 413
414 if (uart_circ_empty(xmit) || uart_tx_s 414 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
415 s3c24xx_serial_stop_tx(port); 415 s3c24xx_serial_stop_tx(port);
416 goto out; 416 goto out;
417 } 417 }
418 418
419 /* try and drain the buffer... */ 419 /* try and drain the buffer... */
420 420
421 while (!uart_circ_empty(xmit) && count 421 while (!uart_circ_empty(xmit) && count-- > 0) {
422 if (rd_regl(port, S3C2410_UFST 422 if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
423 break; 423 break;
424 424
425 wr_regb(port, S3C2410_UTXH, xm 425 wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
426 xmit->tail = (xmit->tail + 1) 426 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
427 port->icount.tx++; 427 port->icount.tx++;
428 } 428 }
429 429
430 if (uart_circ_chars_pending(xmit) < WA 430 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
431 uart_write_wakeup(port); 431 uart_write_wakeup(port);
432 432
433 if (uart_circ_empty(xmit)) 433 if (uart_circ_empty(xmit))
434 s3c24xx_serial_stop_tx(port); 434 s3c24xx_serial_stop_tx(port);
435 435
436 out: 436 out:
437 return IRQ_HANDLED; 437 return IRQ_HANDLED;
438 } 438 }
439 439
440 static unsigned int s3c24xx_serial_tx_empty(st 440 static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
441 { 441 {
442 struct s3c24xx_uart_info *info = s3c24 442 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
443 unsigned long ufstat = rd_regl(port, S 443 unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT);
444 unsigned long ufcon = rd_regl(port, S3 444 unsigned long ufcon = rd_regl(port, S3C2410_UFCON);
445 445
446 if (ufcon & S3C2410_UFCON_FIFOMODE) { 446 if (ufcon & S3C2410_UFCON_FIFOMODE) {
447 if ((ufstat & info->tx_fifomas 447 if ((ufstat & info->tx_fifomask) != 0 ||
448 (ufstat & info->tx_fifoful 448 (ufstat & info->tx_fifofull))
449 return 0; 449 return 0;
450 450
451 return 1; 451 return 1;
452 } 452 }
453 453
454 return s3c24xx_serial_txempty_nofifo(p 454 return s3c24xx_serial_txempty_nofifo(port);
455 } 455 }
456 456
457 /* no modem control lines */ 457 /* no modem control lines */
458 static unsigned int s3c24xx_serial_get_mctrl(s 458 static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
459 { 459 {
460 unsigned int umstat = rd_regb(port,S3C 460 unsigned int umstat = rd_regb(port,S3C2410_UMSTAT);
461 461
462 if (umstat & S3C2410_UMSTAT_CTS) 462 if (umstat & S3C2410_UMSTAT_CTS)
463 return TIOCM_CAR | TIOCM_DSR | 463 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
464 else 464 else
465 return TIOCM_CAR | TIOCM_DSR; 465 return TIOCM_CAR | TIOCM_DSR;
466 } 466 }
467 467
468 static void s3c24xx_serial_set_mctrl(struct ua 468 static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
469 { 469 {
470 /* todo - possibly remove AFC and do m 470 /* todo - possibly remove AFC and do manual CTS */
471 } 471 }
472 472
473 static void s3c24xx_serial_break_ctl(struct ua 473 static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
474 { 474 {
475 unsigned long flags; 475 unsigned long flags;
476 unsigned int ucon; 476 unsigned int ucon;
477 477
478 spin_lock_irqsave(&port->lock, flags); 478 spin_lock_irqsave(&port->lock, flags);
479 479
480 ucon = rd_regl(port, S3C2410_UCON); 480 ucon = rd_regl(port, S3C2410_UCON);
481 481
482 if (break_state) 482 if (break_state)
483 ucon |= S3C2410_UCON_SBREAK; 483 ucon |= S3C2410_UCON_SBREAK;
484 else 484 else
485 ucon &= ~S3C2410_UCON_SBREAK; 485 ucon &= ~S3C2410_UCON_SBREAK;
486 486
487 wr_regl(port, S3C2410_UCON, ucon); 487 wr_regl(port, S3C2410_UCON, ucon);
488 488
489 spin_unlock_irqrestore(&port->lock, fl 489 spin_unlock_irqrestore(&port->lock, flags);
490 } 490 }
491 491
492 static void s3c24xx_serial_shutdown(struct uar 492 static void s3c24xx_serial_shutdown(struct uart_port *port)
493 { 493 {
494 struct s3c24xx_uart_port *ourport = to 494 struct s3c24xx_uart_port *ourport = to_ourport(port);
495 495
496 if (ourport->tx_claimed) { 496 if (ourport->tx_claimed) {
497 free_irq(TX_IRQ(port), ourport 497 free_irq(TX_IRQ(port), ourport);
498 tx_enabled(port) = 0; 498 tx_enabled(port) = 0;
499 ourport->tx_claimed = 0; 499 ourport->tx_claimed = 0;
500 } 500 }
501 501
502 if (ourport->rx_claimed) { 502 if (ourport->rx_claimed) {
503 free_irq(RX_IRQ(port), ourport 503 free_irq(RX_IRQ(port), ourport);
504 ourport->rx_claimed = 0; 504 ourport->rx_claimed = 0;
505 rx_enabled(port) = 0; 505 rx_enabled(port) = 0;
506 } 506 }
507 } 507 }
508 508
509 509
510 static int s3c24xx_serial_startup(struct uart_ 510 static int s3c24xx_serial_startup(struct uart_port *port)
511 { 511 {
512 struct s3c24xx_uart_port *ourport = to 512 struct s3c24xx_uart_port *ourport = to_ourport(port);
513 int ret; 513 int ret;
514 514
515 dbg("s3c24xx_serial_startup: port=%p ( 515 dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
516 port->mapbase, port->membase); 516 port->mapbase, port->membase);
517 517
518 rx_enabled(port) = 1; 518 rx_enabled(port) = 1;
519 519
520 ret = request_irq(RX_IRQ(port), 520 ret = request_irq(RX_IRQ(port),
521 s3c24xx_serial_rx_ch 521 s3c24xx_serial_rx_chars, 0,
522 s3c24xx_serial_portn 522 s3c24xx_serial_portname(port), ourport);
523 523
524 if (ret != 0) { 524 if (ret != 0) {
525 printk(KERN_ERR "cannot get ir 525 printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port));
526 return ret; 526 return ret;
527 } 527 }
528 528
529 ourport->rx_claimed = 1; 529 ourport->rx_claimed = 1;
530 530
531 dbg("requesting tx irq...\n"); 531 dbg("requesting tx irq...\n");
532 532
533 tx_enabled(port) = 1; 533 tx_enabled(port) = 1;
534 534
535 ret = request_irq(TX_IRQ(port), 535 ret = request_irq(TX_IRQ(port),
536 s3c24xx_serial_tx_ch 536 s3c24xx_serial_tx_chars, 0,
537 s3c24xx_serial_portn 537 s3c24xx_serial_portname(port), ourport);
538 538
539 if (ret) { 539 if (ret) {
540 printk(KERN_ERR "cannot get ir 540 printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port));
541 goto err; 541 goto err;
542 } 542 }
543 543
544 ourport->tx_claimed = 1; 544 ourport->tx_claimed = 1;
545 545
546 dbg("s3c24xx_serial_startup ok\n"); 546 dbg("s3c24xx_serial_startup ok\n");
547 547
548 /* the port reset code should have don 548 /* the port reset code should have done the correct
549 * register setup for the port control 549 * register setup for the port controls */
550 550
551 return ret; 551 return ret;
552 552
553 err: 553 err:
554 s3c24xx_serial_shutdown(port); 554 s3c24xx_serial_shutdown(port);
555 return ret; 555 return ret;
556 } 556 }
557 557
558 /* power power management control */ 558 /* power power management control */
559 559
560 static void s3c24xx_serial_pm(struct uart_port 560 static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
561 unsigned int old 561 unsigned int old)
562 { 562 {
563 struct s3c24xx_uart_port *ourport = to 563 struct s3c24xx_uart_port *ourport = to_ourport(port);
564 564
565 switch (level) { 565 switch (level) {
566 case 3: 566 case 3:
567 if (!IS_ERR(ourport->baudclk) 567 if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
568 clk_disable(ourport->b 568 clk_disable(ourport->baudclk);
569 569
570 clk_disable(ourport->clk); 570 clk_disable(ourport->clk);
571 break; 571 break;
572 572
573 case 0: 573 case 0:
574 clk_enable(ourport->clk); 574 clk_enable(ourport->clk);
575 575
576 if (!IS_ERR(ourport->baudclk) 576 if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
577 clk_enable(ourport->ba 577 clk_enable(ourport->baudclk);
578 578
579 break; 579 break;
580 default: 580 default:
581 printk(KERN_ERR "s3c24xx_seria 581 printk(KERN_ERR "s3c24xx_serial: unknown pm %d\n", level);
582 } 582 }
583 } 583 }
584 584
585 /* baud rate calculation 585 /* baud rate calculation
586 * 586 *
587 * The UARTs on the S3C2410/S3C2440 can take t 587 * The UARTs on the S3C2410/S3C2440 can take their clocks from a number
588 * of different sources, including the periphe 588 * of different sources, including the peripheral clock ("pclk") and an
589 * external clock ("uclk"). The S3C2440 also a 589 * external clock ("uclk"). The S3C2440 also adds the core clock ("fclk")
590 * with a programmable extra divisor. 590 * with a programmable extra divisor.
591 * 591 *
592 * The following code goes through the clock s 592 * The following code goes through the clock sources, and calculates the
593 * baud clocks (and the resultant actual baud 593 * baud clocks (and the resultant actual baud rates) and then tries to
594 * pick the closest one and select that. 594 * pick the closest one and select that.
595 * 595 *
596 */ 596 */
597 597
598 598
599 #define MAX_CLKS (8) 599 #define MAX_CLKS (8)
600 600
601 static struct s3c24xx_uart_clksrc tmp_clksrc = 601 static struct s3c24xx_uart_clksrc tmp_clksrc = {
602 .name = "pclk", 602 .name = "pclk",
603 .min_baud = 0, 603 .min_baud = 0,
604 .max_baud = 0, 604 .max_baud = 0,
605 .divisor = 1, 605 .divisor = 1,
606 }; 606 };
607 607
608 static inline int 608 static inline int
609 s3c24xx_serial_getsource(struct uart_port *por 609 s3c24xx_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c)
610 { 610 {
611 struct s3c24xx_uart_info *info = s3c24 611 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
612 612
613 return (info->get_clksrc)(port, c); 613 return (info->get_clksrc)(port, c);
614 } 614 }
615 615
616 static inline int 616 static inline int
617 s3c24xx_serial_setsource(struct uart_port *por 617 s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c)
618 { 618 {
619 struct s3c24xx_uart_info *info = s3c24 619 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
620 620
621 return (info->set_clksrc)(port, c); 621 return (info->set_clksrc)(port, c);
622 } 622 }
623 623
624 struct baud_calc { 624 struct baud_calc {
625 struct s3c24xx_uart_clksrc *clksr 625 struct s3c24xx_uart_clksrc *clksrc;
626 unsigned int calc; 626 unsigned int calc;
627 unsigned int quot; 627 unsigned int quot;
628 struct clk *src; 628 struct clk *src;
629 }; 629 };
630 630
631 static int s3c24xx_serial_calcbaud(struct baud 631 static int s3c24xx_serial_calcbaud(struct baud_calc *calc,
632 struct uart 632 struct uart_port *port,
633 struct s3c2 633 struct s3c24xx_uart_clksrc *clksrc,
634 unsigned in 634 unsigned int baud)
635 { 635 {
636 unsigned long rate; 636 unsigned long rate;
637 637
638 calc->src = clk_get(port->dev, clksrc- 638 calc->src = clk_get(port->dev, clksrc->name);
639 if (calc->src == NULL || IS_ERR(calc-> 639 if (calc->src == NULL || IS_ERR(calc->src))
640 return 0; 640 return 0;
641 641
642 rate = clk_get_rate(calc->src); 642 rate = clk_get_rate(calc->src);
643 rate /= clksrc->divisor; 643 rate /= clksrc->divisor;
644 644
645 calc->clksrc = clksrc; 645 calc->clksrc = clksrc;
646 calc->quot = (rate + (8 * baud)) / (16 646 calc->quot = (rate + (8 * baud)) / (16 * baud);
647 calc->calc = (rate / (calc->quot * 16) 647 calc->calc = (rate / (calc->quot * 16));
648 648
649 calc->quot--; 649 calc->quot--;
650 return 1; 650 return 1;
651 } 651 }
652 652
653 static unsigned int s3c24xx_serial_getclk(stru 653 static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
654 stru 654 struct s3c24xx_uart_clksrc **clksrc,
655 stru 655 struct clk **clk,
656 unsi 656 unsigned int baud)
657 { 657 {
658 struct s3c2410_uartcfg *cfg = s3c24xx_ 658 struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
659 struct s3c24xx_uart_clksrc *clkp; 659 struct s3c24xx_uart_clksrc *clkp;
660 struct baud_calc res[MAX_CLKS]; 660 struct baud_calc res[MAX_CLKS];
661 struct baud_calc *resptr, *best, *sptr 661 struct baud_calc *resptr, *best, *sptr;
662 int i; 662 int i;
663 663
664 clkp = cfg->clocks; 664 clkp = cfg->clocks;
665 best = NULL; 665 best = NULL;
666 666
667 if (cfg->clocks_size < 2) { 667 if (cfg->clocks_size < 2) {
668 if (cfg->clocks_size == 0) 668 if (cfg->clocks_size == 0)
669 clkp = &tmp_clksrc; 669 clkp = &tmp_clksrc;
670 670
671 /* check to see if we're sourc 671 /* check to see if we're sourcing fclk, and if so we're
672 * going to have to update the 672 * going to have to update the clock source
673 */ 673 */
674 674
675 if (strcmp(clkp->name, "fclk") 675 if (strcmp(clkp->name, "fclk") == 0) {
676 struct s3c24xx_uart_cl 676 struct s3c24xx_uart_clksrc src;
677 677
678 s3c24xx_serial_getsour 678 s3c24xx_serial_getsource(port, &src);
679 679
680 /* check that the port 680 /* check that the port already using fclk, and if
681 * not, then re-select 681 * not, then re-select fclk
682 */ 682 */
683 683
684 if (strcmp(src.name, c 684 if (strcmp(src.name, clkp->name) == 0) {
685 s3c24xx_serial 685 s3c24xx_serial_setsource(port, clkp);
686 s3c24xx_serial 686 s3c24xx_serial_getsource(port, &src);
687 } 687 }
688 688
689 clkp->divisor = src.di 689 clkp->divisor = src.divisor;
690 } 690 }
691 691
692 s3c24xx_serial_calcbaud(res, p 692 s3c24xx_serial_calcbaud(res, port, clkp, baud);
693 best = res; 693 best = res;
694 resptr = best + 1; 694 resptr = best + 1;
695 } else { 695 } else {
696 resptr = res; 696 resptr = res;
697 697
698 for (i = 0; i < cfg->clocks_si 698 for (i = 0; i < cfg->clocks_size; i++, clkp++) {
699 if (s3c24xx_serial_cal 699 if (s3c24xx_serial_calcbaud(resptr, port, clkp, baud))
700 resptr++; 700 resptr++;
701 } 701 }
702 } 702 }
703 703
704 /* ok, we now need to select the best 704 /* ok, we now need to select the best clock we found */
705 705
706 if (!best) { 706 if (!best) {
707 unsigned int deviation = (1<<3 707 unsigned int deviation = (1<<30)|((1<<30)-1);
708 int calc_deviation; 708 int calc_deviation;
709 709
710 for (sptr = res; sptr < resptr 710 for (sptr = res; sptr < resptr; sptr++) {
711 printk(KERN_DEBUG 711 printk(KERN_DEBUG
712 "found clk %p ( 712 "found clk %p (%s) quot %d, calc %d\n",
713 sptr->clksrc, s 713 sptr->clksrc, sptr->clksrc->name,
714 sptr->quot, spt 714 sptr->quot, sptr->calc);
715 715
716 calc_deviation = baud 716 calc_deviation = baud - sptr->calc;
717 if (calc_deviation < 0 717 if (calc_deviation < 0)
718 calc_deviation 718 calc_deviation = -calc_deviation;
719 719
720 if (calc_deviation < d 720 if (calc_deviation < deviation) {
721 best = sptr; 721 best = sptr;
722 deviation = ca 722 deviation = calc_deviation;
723 } 723 }
724 } 724 }
725 725
726 printk(KERN_DEBUG "best %p (de 726 printk(KERN_DEBUG "best %p (deviation %d)\n", best, deviation);
727 } 727 }
728 728
729 printk(KERN_DEBUG "selected clock %p ( 729 printk(KERN_DEBUG "selected clock %p (%s) quot %d, calc %d\n",
730 best->clksrc, best->clksrc->nam 730 best->clksrc, best->clksrc->name, best->quot, best->calc);
731 731
732 /* store results to pass back */ 732 /* store results to pass back */
733 733
734 *clksrc = best->clksrc; 734 *clksrc = best->clksrc;
735 *clk = best->src; 735 *clk = best->src;
736 736
737 return best->quot; 737 return best->quot;
738 } 738 }
739 739
740 static void s3c24xx_serial_set_termios(struct 740 static void s3c24xx_serial_set_termios(struct uart_port *port,
741 struct 741 struct ktermios *termios,
742 struct 742 struct ktermios *old)
743 { 743 {
744 struct s3c2410_uartcfg *cfg = s3c24xx_ 744 struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
745 struct s3c24xx_uart_port *ourport = to 745 struct s3c24xx_uart_port *ourport = to_ourport(port);
746 struct s3c24xx_uart_clksrc *clksrc = N 746 struct s3c24xx_uart_clksrc *clksrc = NULL;
747 struct clk *clk = NULL; 747 struct clk *clk = NULL;
748 unsigned long flags; 748 unsigned long flags;
749 unsigned int baud, quot; 749 unsigned int baud, quot;
750 unsigned int ulcon; 750 unsigned int ulcon;
751 unsigned int umcon; 751 unsigned int umcon;
752 752
753 /* 753 /*
754 * We don't support modem control line 754 * We don't support modem control lines.
755 */ 755 */
756 termios->c_cflag &= ~(HUPCL | CMSPAR); 756 termios->c_cflag &= ~(HUPCL | CMSPAR);
757 termios->c_cflag |= CLOCAL; 757 termios->c_cflag |= CLOCAL;
758 758
759 /* 759 /*
760 * Ask the core to calculate the divis 760 * Ask the core to calculate the divisor for us.
761 */ 761 */
762 762
763 baud = uart_get_baud_rate(port, termio 763 baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
764 764
765 if (baud == 38400 && (port->flags & UP 765 if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
766 quot = port->custom_divisor; 766 quot = port->custom_divisor;
767 else 767 else
768 quot = s3c24xx_serial_getclk(p 768 quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud);
769 769
770 /* check to see if we need to change 770 /* check to see if we need to change clock source */
771 771
772 if (ourport->clksrc != clksrc || ourpo 772 if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
773 s3c24xx_serial_setsource(port, 773 s3c24xx_serial_setsource(port, clksrc);
774 774
775 if (ourport->baudclk != NULL & 775 if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
776 clk_disable(ourport->b 776 clk_disable(ourport->baudclk);
777 ourport->baudclk = NU 777 ourport->baudclk = NULL;
778 } 778 }
779 779
780 clk_enable(clk); 780 clk_enable(clk);
781 781
782 ourport->clksrc = clksrc; 782 ourport->clksrc = clksrc;
783 ourport->baudclk = clk; 783 ourport->baudclk = clk;
784 } 784 }
785 785
786 switch (termios->c_cflag & CSIZE) { 786 switch (termios->c_cflag & CSIZE) {
787 case CS5: 787 case CS5:
788 dbg("config: 5bits/char\n"); 788 dbg("config: 5bits/char\n");
789 ulcon = S3C2410_LCON_CS5; 789 ulcon = S3C2410_LCON_CS5;
790 break; 790 break;
791 case CS6: 791 case CS6:
792 dbg("config: 6bits/char\n"); 792 dbg("config: 6bits/char\n");
793 ulcon = S3C2410_LCON_CS6; 793 ulcon = S3C2410_LCON_CS6;
794 break; 794 break;
795 case CS7: 795 case CS7:
796 dbg("config: 7bits/char\n"); 796 dbg("config: 7bits/char\n");
797 ulcon = S3C2410_LCON_CS7; 797 ulcon = S3C2410_LCON_CS7;
798 break; 798 break;
799 case CS8: 799 case CS8:
800 default: 800 default:
801 dbg("config: 8bits/char\n"); 801 dbg("config: 8bits/char\n");
802 ulcon = S3C2410_LCON_CS8; 802 ulcon = S3C2410_LCON_CS8;
803 break; 803 break;
804 } 804 }
805 805
806 /* preserve original lcon IR settings 806 /* preserve original lcon IR settings */
807 ulcon |= (cfg->ulcon & S3C2410_LCON_IR 807 ulcon |= (cfg->ulcon & S3C2410_LCON_IRM);
808 808
809 if (termios->c_cflag & CSTOPB) 809 if (termios->c_cflag & CSTOPB)
810 ulcon |= S3C2410_LCON_STOPB; 810 ulcon |= S3C2410_LCON_STOPB;
811 811
812 umcon = (termios->c_cflag & CRTSCTS) ? 812 umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0;
813 813
814 if (termios->c_cflag & PARENB) { 814 if (termios->c_cflag & PARENB) {
815 if (termios->c_cflag & PARODD) 815 if (termios->c_cflag & PARODD)
816 ulcon |= S3C2410_LCON_ 816 ulcon |= S3C2410_LCON_PODD;
817 else 817 else
818 ulcon |= S3C2410_LCON_ 818 ulcon |= S3C2410_LCON_PEVEN;
819 } else { 819 } else {
820 ulcon |= S3C2410_LCON_PNONE; 820 ulcon |= S3C2410_LCON_PNONE;
821 } 821 }
822 822
823 spin_lock_irqsave(&port->lock, flags); 823 spin_lock_irqsave(&port->lock, flags);
824 824
825 dbg("setting ulcon to %08x, brddiv to 825 dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot);
826 826
827 wr_regl(port, S3C2410_ULCON, ulcon); 827 wr_regl(port, S3C2410_ULCON, ulcon);
828 wr_regl(port, S3C2410_UBRDIV, quot); 828 wr_regl(port, S3C2410_UBRDIV, quot);
829 wr_regl(port, S3C2410_UMCON, umcon); 829 wr_regl(port, S3C2410_UMCON, umcon);
830 830
831 dbg("uart: ulcon = 0x%08x, ucon = 0x%0 831 dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
832 rd_regl(port, S3C2410_ULCON), 832 rd_regl(port, S3C2410_ULCON),
833 rd_regl(port, S3C2410_UCON), 833 rd_regl(port, S3C2410_UCON),
834 rd_regl(port, S3C2410_UFCON)); 834 rd_regl(port, S3C2410_UFCON));
835 835
836 /* 836 /*
837 * Update the per-port timeout. 837 * Update the per-port timeout.
838 */ 838 */
839 uart_update_timeout(port, termios->c_c 839 uart_update_timeout(port, termios->c_cflag, baud);
840 840
841 /* 841 /*
842 * Which character status flags are we 842 * Which character status flags are we interested in?
843 */ 843 */
844 port->read_status_mask = S3C2410_UERST 844 port->read_status_mask = S3C2410_UERSTAT_OVERRUN;
845 if (termios->c_iflag & INPCK) 845 if (termios->c_iflag & INPCK)
846 port->read_status_mask |= S3C2 846 port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY;
847 847
848 /* 848 /*
849 * Which character status flags should 849 * Which character status flags should we ignore?
850 */ 850 */
851 port->ignore_status_mask = 0; 851 port->ignore_status_mask = 0;
852 if (termios->c_iflag & IGNPAR) 852 if (termios->c_iflag & IGNPAR)
853 port->ignore_status_mask |= S3 853 port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN;
854 if (termios->c_iflag & IGNBRK && termi 854 if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
855 port->ignore_status_mask |= S3 855 port->ignore_status_mask |= S3C2410_UERSTAT_FRAME;
856 856
857 /* 857 /*
858 * Ignore all characters if CREAD is n 858 * Ignore all characters if CREAD is not set.
859 */ 859 */
860 if ((termios->c_cflag & CREAD) == 0) 860 if ((termios->c_cflag & CREAD) == 0)
861 port->ignore_status_mask |= RX 861 port->ignore_status_mask |= RXSTAT_DUMMY_READ;
862 862
863 spin_unlock_irqrestore(&port->lock, fl 863 spin_unlock_irqrestore(&port->lock, flags);
864 } 864 }
865 865
866 static const char *s3c24xx_serial_type(struct 866 static const char *s3c24xx_serial_type(struct uart_port *port)
867 { 867 {
868 switch (port->type) { 868 switch (port->type) {
869 case PORT_S3C2410: 869 case PORT_S3C2410:
870 return "S3C2410"; 870 return "S3C2410";
871 case PORT_S3C2440: 871 case PORT_S3C2440:
872 return "S3C2440"; 872 return "S3C2440";
873 case PORT_S3C2412: 873 case PORT_S3C2412:
874 return "S3C2412"; 874 return "S3C2412";
875 default: 875 default:
876 return NULL; 876 return NULL;
877 } 877 }
878 } 878 }
879 879
880 #define MAP_SIZE (0x100) 880 #define MAP_SIZE (0x100)
881 881
882 static void s3c24xx_serial_release_port(struct 882 static void s3c24xx_serial_release_port(struct uart_port *port)
883 { 883 {
884 release_mem_region(port->mapbase, MAP_ 884 release_mem_region(port->mapbase, MAP_SIZE);
885 } 885 }
886 886
887 static int s3c24xx_serial_request_port(struct 887 static int s3c24xx_serial_request_port(struct uart_port *port)
888 { 888 {
889 const char *name = s3c24xx_serial_port 889 const char *name = s3c24xx_serial_portname(port);
890 return request_mem_region(port->mapbas 890 return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY;
891 } 891 }
892 892
893 static void s3c24xx_serial_config_port(struct 893 static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
894 { 894 {
895 struct s3c24xx_uart_info *info = s3c24 895 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
896 896
897 if (flags & UART_CONFIG_TYPE && 897 if (flags & UART_CONFIG_TYPE &&
898 s3c24xx_serial_request_port(port) 898 s3c24xx_serial_request_port(port) == 0)
899 port->type = info->type; 899 port->type = info->type;
900 } 900 }
901 901
902 /* 902 /*
903 * verify the new serial_struct (for TIOCSSERI 903 * verify the new serial_struct (for TIOCSSERIAL).
904 */ 904 */
905 static int 905 static int
906 s3c24xx_serial_verify_port(struct uart_port *p 906 s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
907 { 907 {
908 struct s3c24xx_uart_info *info = s3c24 908 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
909 909
910 if (ser->type != PORT_UNKNOWN && ser-> 910 if (ser->type != PORT_UNKNOWN && ser->type != info->type)
911 return -EINVAL; 911 return -EINVAL;
912 912
913 return 0; 913 return 0;
914 } 914 }
915 915
916 916
917 #ifdef CONFIG_SERIAL_S3C2410_CONSOLE 917 #ifdef CONFIG_SERIAL_S3C2410_CONSOLE
918 918
919 static struct console s3c24xx_serial_console; 919 static struct console s3c24xx_serial_console;
920 920
921 #define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial 921 #define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
922 #else 922 #else
923 #define S3C24XX_SERIAL_CONSOLE NULL 923 #define S3C24XX_SERIAL_CONSOLE NULL
924 #endif 924 #endif
925 925
926 static struct uart_ops s3c24xx_serial_ops = { 926 static struct uart_ops s3c24xx_serial_ops = {
927 .pm = s3c24xx_serial_pm, 927 .pm = s3c24xx_serial_pm,
928 .tx_empty = s3c24xx_serial_tx_em 928 .tx_empty = s3c24xx_serial_tx_empty,
929 .get_mctrl = s3c24xx_serial_get_m 929 .get_mctrl = s3c24xx_serial_get_mctrl,
930 .set_mctrl = s3c24xx_serial_set_m 930 .set_mctrl = s3c24xx_serial_set_mctrl,
931 .stop_tx = s3c24xx_serial_stop_ 931 .stop_tx = s3c24xx_serial_stop_tx,
932 .start_tx = s3c24xx_serial_start 932 .start_tx = s3c24xx_serial_start_tx,
933 .stop_rx = s3c24xx_serial_stop_ 933 .stop_rx = s3c24xx_serial_stop_rx,
934 .enable_ms = s3c24xx_serial_enabl 934 .enable_ms = s3c24xx_serial_enable_ms,
935 .break_ctl = s3c24xx_serial_break 935 .break_ctl = s3c24xx_serial_break_ctl,
936 .startup = s3c24xx_serial_start 936 .startup = s3c24xx_serial_startup,
937 .shutdown = s3c24xx_serial_shutd 937 .shutdown = s3c24xx_serial_shutdown,
938 .set_termios = s3c24xx_serial_set_t 938 .set_termios = s3c24xx_serial_set_termios,
939 .type = s3c24xx_serial_type, 939 .type = s3c24xx_serial_type,
940 .release_port = s3c24xx_serial_relea 940 .release_port = s3c24xx_serial_release_port,
941 .request_port = s3c24xx_serial_reque 941 .request_port = s3c24xx_serial_request_port,
942 .config_port = s3c24xx_serial_confi 942 .config_port = s3c24xx_serial_config_port,
943 .verify_port = s3c24xx_serial_verif 943 .verify_port = s3c24xx_serial_verify_port,
944 }; 944 };
945 945
946 946
947 static struct uart_driver s3c24xx_uart_drv = { 947 static struct uart_driver s3c24xx_uart_drv = {
948 .owner = THIS_MODULE, 948 .owner = THIS_MODULE,
949 .dev_name = "s3c2410_serial", 949 .dev_name = "s3c2410_serial",
950 .nr = 3, 950 .nr = 3,
951 .cons = S3C24XX_SERIAL_CONSO 951 .cons = S3C24XX_SERIAL_CONSOLE,
952 .driver_name = S3C24XX_SERIAL_NAME, 952 .driver_name = S3C24XX_SERIAL_NAME,
953 .major = S3C24XX_SERIAL_MAJOR 953 .major = S3C24XX_SERIAL_MAJOR,
954 .minor = S3C24XX_SERIAL_MINOR 954 .minor = S3C24XX_SERIAL_MINOR,
955 }; 955 };
956 956
957 static struct s3c24xx_uart_port s3c24xx_serial 957 static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
958 [0] = { 958 [0] = {
959 .port = { 959 .port = {
960 .lock = __SP 960 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
961 .iotype = UPIO 961 .iotype = UPIO_MEM,
962 .irq = IRQ_ 962 .irq = IRQ_S3CUART_RX0,
963 .uartclk = 0, 963 .uartclk = 0,
964 .fifosize = 16, 964 .fifosize = 16,
965 .ops = &s3c 965 .ops = &s3c24xx_serial_ops,
966 .flags = UPF_ 966 .flags = UPF_BOOT_AUTOCONF,
967 .line = 0, 967 .line = 0,
968 } 968 }
969 }, 969 },
970 [1] = { 970 [1] = {
971 .port = { 971 .port = {
972 .lock = __SP 972 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),
973 .iotype = UPIO 973 .iotype = UPIO_MEM,
974 .irq = IRQ_ 974 .irq = IRQ_S3CUART_RX1,
975 .uartclk = 0, 975 .uartclk = 0,
976 .fifosize = 16, 976 .fifosize = 16,
977 .ops = &s3c 977 .ops = &s3c24xx_serial_ops,
978 .flags = UPF_ 978 .flags = UPF_BOOT_AUTOCONF,
979 .line = 1, 979 .line = 1,
980 } 980 }
981 }, 981 },
982 #if NR_PORTS > 2 982 #if NR_PORTS > 2
983 983
984 [2] = { 984 [2] = {
985 .port = { 985 .port = {
986 .lock = __SP 986 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),
987 .iotype = UPIO 987 .iotype = UPIO_MEM,
988 .irq = IRQ_ 988 .irq = IRQ_S3CUART_RX2,
989 .uartclk = 0, 989 .uartclk = 0,
990 .fifosize = 16, 990 .fifosize = 16,
991 .ops = &s3c 991 .ops = &s3c24xx_serial_ops,
992 .flags = UPF_ 992 .flags = UPF_BOOT_AUTOCONF,
993 .line = 2, 993 .line = 2,
994 } 994 }
995 } 995 }
996 #endif 996 #endif
997 }; 997 };
998 998
999 /* s3c24xx_serial_resetport 999 /* s3c24xx_serial_resetport
1000 * 1000 *
1001 * wrapper to call the specific reset for thi 1001 * wrapper to call the specific reset for this port (reset the fifos
1002 * and the settings) 1002 * and the settings)
1003 */ 1003 */
1004 1004
1005 static inline int s3c24xx_serial_resetport(st 1005 static inline int s3c24xx_serial_resetport(struct uart_port * port,
1006 st 1006 struct s3c2410_uartcfg *cfg)
1007 { 1007 {
1008 struct s3c24xx_uart_info *info = s3c2 1008 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1009 1009
1010 return (info->reset_port)(port, cfg); 1010 return (info->reset_port)(port, cfg);
1011 } 1011 }
1012 1012
1013 /* s3c24xx_serial_init_port 1013 /* s3c24xx_serial_init_port
1014 * 1014 *
1015 * initialise a single serial port from the p 1015 * initialise a single serial port from the platform device given
1016 */ 1016 */
1017 1017
1018 static int s3c24xx_serial_init_port(struct s3 1018 static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
1019 struct s3 1019 struct s3c24xx_uart_info *info,
1020 struct pl 1020 struct platform_device *platdev)
1021 { 1021 {
1022 struct uart_port *port = &ourport->po 1022 struct uart_port *port = &ourport->port;
1023 struct s3c2410_uartcfg *cfg; 1023 struct s3c2410_uartcfg *cfg;
1024 struct resource *res; 1024 struct resource *res;
1025 1025
1026 dbg("s3c24xx_serial_init_port: port=% 1026 dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);
1027 1027
1028 if (platdev == NULL) 1028 if (platdev == NULL)
1029 return -ENODEV; 1029 return -ENODEV;
1030 1030
1031 cfg = s3c24xx_dev_to_cfg(&platdev->de 1031 cfg = s3c24xx_dev_to_cfg(&platdev->dev);
1032 1032
1033 if (port->mapbase != 0) 1033 if (port->mapbase != 0)
1034 return 0; 1034 return 0;
1035 1035
1036 if (cfg->hwport > 3) 1036 if (cfg->hwport > 3)
1037 return -EINVAL; 1037 return -EINVAL;
1038 1038
1039 /* setup info for port */ 1039 /* setup info for port */
1040 port->dev = &platdev->dev; 1040 port->dev = &platdev->dev;
1041 ourport->info = info; 1041 ourport->info = info;
1042 1042
1043 /* copy the info in from provided str 1043 /* copy the info in from provided structure */
1044 ourport->port.fifosize = info->fifosi 1044 ourport->port.fifosize = info->fifosize;
1045 1045
1046 dbg("s3c24xx_serial_init_port: %p (hw 1046 dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport);
1047 1047
1048 port->uartclk = 1; 1048 port->uartclk = 1;
1049 1049
1050 if (cfg->uart_flags & UPF_CONS_FLOW) 1050 if (cfg->uart_flags & UPF_CONS_FLOW) {
1051 dbg("s3c24xx_serial_init_port 1051 dbg("s3c24xx_serial_init_port: enabling flow control\n");
1052 port->flags |= UPF_CONS_FLOW; 1052 port->flags |= UPF_CONS_FLOW;
1053 } 1053 }
1054 1054
1055 /* sort our the physical and virtual 1055 /* sort our the physical and virtual addresses for each UART */
1056 1056
1057 res = platform_get_resource(platdev, 1057 res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
1058 if (res == NULL) { 1058 if (res == NULL) {
1059 printk(KERN_ERR "failed to fi 1059 printk(KERN_ERR "failed to find memory resource for uart\n");
1060 return -EINVAL; 1060 return -EINVAL;
1061 } 1061 }
1062 1062
1063 dbg("resource %p (%lx..%lx)\n", res, 1063 dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
1064 1064
1065 port->mapbase = res->start; 1065 port->mapbase = res->start;
1066 port->membase = S3C24XX_VA_UART + ( 1066 port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
1067 port->irq = platform_get_irq(pl 1067 port->irq = platform_get_irq(platdev, 0);
1068 if (port->irq < 0) 1068 if (port->irq < 0)
1069 port->irq = 0; 1069 port->irq = 0;
1070 1070
1071 ourport->clk = clk_get(&platdev->d 1071 ourport->clk = clk_get(&platdev->dev, "uart");
1072 1072
1073 dbg("port: map=%08x, mem=%08x, irq=%d 1073 dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n",
1074 port->mapbase, port->membase, por 1074 port->mapbase, port->membase, port->irq, port->uartclk);
1075 1075
1076 /* reset the fifos (and setup the uar 1076 /* reset the fifos (and setup the uart) */
1077 s3c24xx_serial_resetport(port, cfg); 1077 s3c24xx_serial_resetport(port, cfg);
1078 return 0; 1078 return 0;
1079 } 1079 }
1080 1080
1081 /* Device driver serial port probe */ 1081 /* Device driver serial port probe */
1082 1082
1083 static int probe_index = 0; 1083 static int probe_index = 0;
1084 1084
1085 static int s3c24xx_serial_probe(struct platfo 1085 static int s3c24xx_serial_probe(struct platform_device *dev,
1086 struct s3c24x 1086 struct s3c24xx_uart_info *info)
1087 { 1087 {
1088 struct s3c24xx_uart_port *ourport; 1088 struct s3c24xx_uart_port *ourport;
1089 int ret; 1089 int ret;
1090 1090
1091 dbg("s3c24xx_serial_probe(%p, %p) %d\ 1091 dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, probe_index);
1092 1092
1093 ourport = &s3c24xx_serial_ports[probe 1093 ourport = &s3c24xx_serial_ports[probe_index];
1094 probe_index++; 1094 probe_index++;
1095 1095
1096 dbg("%s: initialising port %p...\n", 1096 dbg("%s: initialising port %p...\n", __FUNCTION__, ourport);
1097 1097
1098 ret = s3c24xx_serial_init_port(ourpor 1098 ret = s3c24xx_serial_init_port(ourport, info, dev);
1099 if (ret < 0) 1099 if (ret < 0)
1100 goto probe_err; 1100 goto probe_err;
1101 1101
1102 dbg("%s: adding port\n", __FUNCTION__ 1102 dbg("%s: adding port\n", __FUNCTION__);
1103 uart_add_one_port(&s3c24xx_uart_drv, 1103 uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
1104 platform_set_drvdata(dev, &ourport->p 1104 platform_set_drvdata(dev, &ourport->port);
1105 1105
1106 return 0; 1106 return 0;
1107 1107
1108 probe_err: 1108 probe_err:
1109 return ret; 1109 return ret;
1110 } 1110 }
1111 1111
1112 static int s3c24xx_serial_remove(struct platf 1112 static int s3c24xx_serial_remove(struct platform_device *dev)
1113 { 1113 {
1114 struct uart_port *port = s3c24xx_dev_ 1114 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
1115 1115
1116 if (port) 1116 if (port)
1117 uart_remove_one_port(&s3c24xx 1117 uart_remove_one_port(&s3c24xx_uart_drv, port);
1118 1118
1119 return 0; 1119 return 0;
1120 } 1120 }
1121 1121
1122 /* UART power management code */ 1122 /* UART power management code */
1123 1123
1124 #ifdef CONFIG_PM 1124 #ifdef CONFIG_PM
1125 1125
1126 static int s3c24xx_serial_suspend(struct plat 1126 static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state)
1127 { 1127 {
1128 struct uart_port *port = s3c24xx_dev_ 1128 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
1129 1129
1130 if (port) 1130 if (port)
1131 uart_suspend_port(&s3c24xx_ua 1131 uart_suspend_port(&s3c24xx_uart_drv, port);
1132 1132
1133 return 0; 1133 return 0;
1134 } 1134 }
1135 1135
1136 static int s3c24xx_serial_resume(struct platf 1136 static int s3c24xx_serial_resume(struct platform_device *dev)
1137 { 1137 {
1138 struct uart_port *port = s3c24xx_dev_ 1138 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
1139 struct s3c24xx_uart_port *ourport = t 1139 struct s3c24xx_uart_port *ourport = to_ourport(port);
1140 1140
1141 if (port) { 1141 if (port) {
1142 clk_enable(ourport->clk); 1142 clk_enable(ourport->clk);
1143 s3c24xx_serial_resetport(port 1143 s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
1144 clk_disable(ourport->clk); 1144 clk_disable(ourport->clk);
1145 1145
1146 uart_resume_port(&s3c24xx_uar 1146 uart_resume_port(&s3c24xx_uart_drv, port);
1147 } 1147 }
1148 1148
1149 return 0; 1149 return 0;
1150 } 1150 }
1151 1151
1152 #else 1152 #else
1153 #define s3c24xx_serial_suspend NULL 1153 #define s3c24xx_serial_suspend NULL
1154 #define s3c24xx_serial_resume NULL 1154 #define s3c24xx_serial_resume NULL
1155 #endif 1155 #endif
1156 1156
1157 static int s3c24xx_serial_init(struct platfor 1157 static int s3c24xx_serial_init(struct platform_driver *drv,
1158 struct s3c24xx 1158 struct s3c24xx_uart_info *info)
1159 { 1159 {
1160 dbg("s3c24xx_serial_init(%p,%p)\n", d 1160 dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
1161 return platform_driver_register(drv); 1161 return platform_driver_register(drv);
1162 } 1162 }
1163 1163
1164 1164
1165 /* now comes the code to initialise either th 1165 /* now comes the code to initialise either the s3c2410 or s3c2440 serial
1166 * port information 1166 * port information
1167 */ 1167 */
1168 1168
1169 /* cpu specific variations on the serial port 1169 /* cpu specific variations on the serial port support */
1170 1170
1171 #ifdef CONFIG_CPU_S3C2400 1171 #ifdef CONFIG_CPU_S3C2400
1172 1172
1173 static int s3c2400_serial_getsource(struct ua 1173 static int s3c2400_serial_getsource(struct uart_port *port,
1174 struct s3 1174 struct s3c24xx_uart_clksrc *clk)
1175 { 1175 {
1176 clk->divisor = 1; 1176 clk->divisor = 1;
1177 clk->name = "pclk"; 1177 clk->name = "pclk";
1178 1178
1179 return 0; 1179 return 0;
1180 } 1180 }
1181 1181
1182 static int s3c2400_serial_setsource(struct ua 1182 static int s3c2400_serial_setsource(struct uart_port *port,
1183 struct s3 1183 struct s3c24xx_uart_clksrc *clk)
1184 { 1184 {
1185 return 0; 1185 return 0;
1186 } 1186 }
1187 1187
1188 static int s3c2400_serial_resetport(struct ua 1188 static int s3c2400_serial_resetport(struct uart_port *port,
1189 struct s3 1189 struct s3c2410_uartcfg *cfg)
1190 { 1190 {
1191 dbg("s3c2400_serial_resetport: port=% 1191 dbg("s3c2400_serial_resetport: port=%p (%08lx), cfg=%p\n",
1192 port, port->mapbase, cfg); 1192 port, port->mapbase, cfg);
1193 1193
1194 wr_regl(port, S3C2410_UCON, cfg->uco 1194 wr_regl(port, S3C2410_UCON, cfg->ucon);
1195 wr_regl(port, S3C2410_ULCON, cfg->ulc 1195 wr_regl(port, S3C2410_ULCON, cfg->ulcon);
1196 1196
1197 /* reset both fifos */ 1197 /* reset both fifos */
1198 1198
1199 wr_regl(port, S3C2410_UFCON, cfg->ufc 1199 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
1200 wr_regl(port, S3C2410_UFCON, cfg->ufc 1200 wr_regl(port, S3C2410_UFCON, cfg->ufcon);
1201 1201
1202 return 0; 1202 return 0;
1203 } 1203 }
1204 1204
1205 static struct s3c24xx_uart_info s3c2400_uart_ 1205 static struct s3c24xx_uart_info s3c2400_uart_inf = {
1206 .name = "Samsung S3C2400 UA 1206 .name = "Samsung S3C2400 UART",
1207 .type = PORT_S3C2400, 1207 .type = PORT_S3C2400,
1208 .fifosize = 16, 1208 .fifosize = 16,
1209 .rx_fifomask = S3C2410_UFSTAT_RXMA 1209 .rx_fifomask = S3C2410_UFSTAT_RXMASK,
1210 .rx_fifoshift = S3C2410_UFSTAT_RXSH 1210 .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
1211 .rx_fifofull = S3C2410_UFSTAT_RXFU 1211 .rx_fifofull = S3C2410_UFSTAT_RXFULL,
1212 .tx_fifofull = S3C2410_UFSTAT_TXFU 1212 .tx_fifofull = S3C2410_UFSTAT_TXFULL,
1213 .tx_fifomask = S3C2410_UFSTAT_TXMA 1213 .tx_fifomask = S3C2410_UFSTAT_TXMASK,
1214 .tx_fifoshift = S3C2410_UFSTAT_TXSH 1214 .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
1215 .get_clksrc = s3c2400_serial_gets 1215 .get_clksrc = s3c2400_serial_getsource,
1216 .set_clksrc = s3c2400_serial_sets 1216 .set_clksrc = s3c2400_serial_setsource,
1217 .reset_port = s3c2400_serial_rese 1217 .reset_port = s3c2400_serial_resetport,
1218 }; 1218 };
1219 1219
1220 static int s3c2400_serial_probe(struct platfo 1220 static int s3c2400_serial_probe(struct platform_device *dev)
1221 { 1221 {
1222 return s3c24xx_serial_probe(dev, &s3c 1222 return s3c24xx_serial_probe(dev, &s3c2400_uart_inf);
1223 } 1223 }
1224 1224
1225 static struct platform_driver s3c2400_serial_ 1225 static struct platform_driver s3c2400_serial_drv = {
1226 .probe = s3c2400_serial_prob 1226 .probe = s3c2400_serial_probe,
1227 .remove = s3c24xx_serial_remo 1227 .remove = s3c24xx_serial_remove,
1228 .suspend = s3c24xx_serial_susp 1228 .suspend = s3c24xx_serial_suspend,
1229 .resume = s3c24xx_serial_resu 1229 .resume = s3c24xx_serial_resume,
1230 .driver = { 1230 .driver = {
1231 .name = "s3c2400-uart", 1231 .name = "s3c2400-uart",
1232 .owner = THIS_MODULE, 1232 .owner = THIS_MODULE,
1233 }, 1233 },
1234 }; 1234 };
1235 1235
1236 static inline int s3c2400_serial_init(void) 1236 static inline int s3c2400_serial_init(void)
1237 { 1237 {
1238 return s3c24xx_serial_init(&s3c2400_s 1238 return s3c24xx_serial_init(&s3c2400_serial_drv, &s3c2400_uart_inf);
1239 } 1239 }
1240 1240
1241 static inline void s3c2400_serial_exit(void) 1241 static inline void s3c2400_serial_exit(void)
1242 { 1242 {
1243 platform_driver_unregister(&s3c2400_s 1243 platform_driver_unregister(&s3c2400_serial_drv);
1244 } 1244 }
1245 1245
1246 #define s3c2400_uart_inf_at &s3c2400_uart_inf 1246 #define s3c2400_uart_inf_at &s3c2400_uart_inf
1247 #else 1247 #else
1248 1248
1249 static inline int s3c2400_serial_init(void) 1249 static inline int s3c2400_serial_init(void)
1250 { 1250 {
1251 return 0; 1251 return 0;
1252 } 1252 }
1253 1253
1254 static inline void s3c2400_serial_exit(void) 1254 static inline void s3c2400_serial_exit(void)
1255 { 1255 {
1256 } 1256 }
1257 1257
1258 #define s3c2400_uart_inf_at NULL 1258 #define s3c2400_uart_inf_at NULL
1259 1259
1260 #endif /* CONFIG_CPU_S3C2400 */ 1260 #endif /* CONFIG_CPU_S3C2400 */
1261 1261
1262 /* S3C2410 support */ 1262 /* S3C2410 support */
1263 1263
1264 #ifdef CONFIG_CPU_S3C2410 1264 #ifdef CONFIG_CPU_S3C2410
1265 1265
1266 static int s3c2410_serial_setsource(struct ua 1266 static int s3c2410_serial_setsource(struct uart_port *port,
1267 struct s3 1267 struct s3c24xx_uart_clksrc *clk)
1268 { 1268 {
1269 unsigned long ucon = rd_regl(port, S3 1269 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1270 1270
1271 if (strcmp(clk->name, "uclk") == 0) 1271 if (strcmp(clk->name, "uclk") == 0)
1272 ucon |= S3C2410_UCON_UCLK; 1272 ucon |= S3C2410_UCON_UCLK;
1273 else 1273 else
1274 ucon &= ~S3C2410_UCON_UCLK; 1274 ucon &= ~S3C2410_UCON_UCLK;
1275 1275
1276 wr_regl(port, S3C2410_UCON, ucon); 1276 wr_regl(port, S3C2410_UCON, ucon);
1277 return 0; 1277 return 0;
1278 } 1278 }
1279 1279
1280 static int s3c2410_serial_getsource(struct ua 1280 static int s3c2410_serial_getsource(struct uart_port *port,
1281 struct s3 1281 struct s3c24xx_uart_clksrc *clk)
1282 { 1282 {
1283 unsigned long ucon = rd_regl(port, S3 1283 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1284 1284
1285 clk->divisor = 1; 1285 clk->divisor = 1;
1286 clk->name = (ucon & S3C2410_UCON_UCLK 1286 clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk";
1287 1287
1288 return 0; 1288 return 0;
1289 } 1289 }
1290 1290
1291 static int s3c2410_serial_resetport(struct ua 1291 static int s3c2410_serial_resetport(struct uart_port *port,
1292 struct s3 1292 struct s3c2410_uartcfg *cfg)
1293 { 1293 {
1294 dbg("s3c2410_serial_resetport: port=% 1294 dbg("s3c2410_serial_resetport: port=%p (%08lx), cfg=%p\n",
1295 port, port->mapbase, cfg); 1295 port, port->mapbase, cfg);
1296 1296
1297 wr_regl(port, S3C2410_UCON, cfg->uco 1297 wr_regl(port, S3C2410_UCON, cfg->ucon);
1298 wr_regl(port, S3C2410_ULCON, cfg->ulc 1298 wr_regl(port, S3C2410_ULCON, cfg->ulcon);
1299 1299
1300 /* reset both fifos */ 1300 /* reset both fifos */
1301 1301
1302 wr_regl(port, S3C2410_UFCON, cfg->ufc 1302 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
1303 wr_regl(port, S3C2410_UFCON, cfg->ufc 1303 wr_regl(port, S3C2410_UFCON, cfg->ufcon);
1304 1304
1305 return 0; 1305 return 0;
1306 } 1306 }
1307 1307
1308 static struct s3c24xx_uart_info s3c2410_uart_ 1308 static struct s3c24xx_uart_info s3c2410_uart_inf = {
1309 .name = "Samsung S3C2410 UA 1309 .name = "Samsung S3C2410 UART",
1310 .type = PORT_S3C2410, 1310 .type = PORT_S3C2410,
1311 .fifosize = 16, 1311 .fifosize = 16,
1312 .rx_fifomask = S3C2410_UFSTAT_RXMA 1312 .rx_fifomask = S3C2410_UFSTAT_RXMASK,
1313 .rx_fifoshift = S3C2410_UFSTAT_RXSH 1313 .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
1314 .rx_fifofull = S3C2410_UFSTAT_RXFU 1314 .rx_fifofull = S3C2410_UFSTAT_RXFULL,
1315 .tx_fifofull = S3C2410_UFSTAT_TXFU 1315 .tx_fifofull = S3C2410_UFSTAT_TXFULL,
1316 .tx_fifomask = S3C2410_UFSTAT_TXMA 1316 .tx_fifomask = S3C2410_UFSTAT_TXMASK,
1317 .tx_fifoshift = S3C2410_UFSTAT_TXSH 1317 .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
1318 .get_clksrc = s3c2410_serial_gets 1318 .get_clksrc = s3c2410_serial_getsource,
1319 .set_clksrc = s3c2410_serial_sets 1319 .set_clksrc = s3c2410_serial_setsource,
1320 .reset_port = s3c2410_serial_rese 1320 .reset_port = s3c2410_serial_resetport,
1321 }; 1321 };
1322 1322
1323 /* device management */ 1323 /* device management */
1324 1324
1325 static int s3c2410_serial_probe(struct platfo 1325 static int s3c2410_serial_probe(struct platform_device *dev)
1326 { 1326 {
1327 return s3c24xx_serial_probe(dev, &s3c 1327 return s3c24xx_serial_probe(dev, &s3c2410_uart_inf);
1328 } 1328 }
1329 1329
1330 static struct platform_driver s3c2410_serial_ 1330 static struct platform_driver s3c2410_serial_drv = {
1331 .probe = s3c2410_serial_prob 1331 .probe = s3c2410_serial_probe,
1332 .remove = s3c24xx_serial_remo 1332 .remove = s3c24xx_serial_remove,
1333 .suspend = s3c24xx_serial_susp 1333 .suspend = s3c24xx_serial_suspend,
1334 .resume = s3c24xx_serial_resu 1334 .resume = s3c24xx_serial_resume,
1335 .driver = { 1335 .driver = {
1336 .name = "s3c2410-uart", 1336 .name = "s3c2410-uart",
1337 .owner = THIS_MODULE, 1337 .owner = THIS_MODULE,
1338 }, 1338 },
1339 }; 1339 };
1340 1340
1341 static inline int s3c2410_serial_init(void) 1341 static inline int s3c2410_serial_init(void)
1342 { 1342 {
1343 return s3c24xx_serial_init(&s3c2410_s 1343 return s3c24xx_serial_init(&s3c2410_serial_drv, &s3c2410_uart_inf);
1344 } 1344 }
1345 1345
1346 static inline void s3c2410_serial_exit(void) 1346 static inline void s3c2410_serial_exit(void)
1347 { 1347 {
1348 platform_driver_unregister(&s3c2410_s 1348 platform_driver_unregister(&s3c2410_serial_drv);
1349 } 1349 }
1350 1350
1351 #define s3c2410_uart_inf_at &s3c2410_uart_inf 1351 #define s3c2410_uart_inf_at &s3c2410_uart_inf
1352 #else 1352 #else
1353 1353
1354 static inline int s3c2410_serial_init(void) 1354 static inline int s3c2410_serial_init(void)
1355 { 1355 {
1356 return 0; 1356 return 0;
1357 } 1357 }
1358 1358
1359 static inline void s3c2410_serial_exit(void) 1359 static inline void s3c2410_serial_exit(void)
1360 { 1360 {
1361 } 1361 }
1362 1362
1363 #define s3c2410_uart_inf_at NULL 1363 #define s3c2410_uart_inf_at NULL
1364 1364
1365 #endif /* CONFIG_CPU_S3C2410 */ 1365 #endif /* CONFIG_CPU_S3C2410 */
1366 1366
1367 #if defined(CONFIG_CPU_S3C2440) || defined(CO 1367 #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
1368 1368
1369 static int s3c2440_serial_setsource(struct ua 1369 static int s3c2440_serial_setsource(struct uart_port *port,
1370 struct s 1370 struct s3c24xx_uart_clksrc *clk)
1371 { 1371 {
1372 unsigned long ucon = rd_regl(port, S3 1372 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1373 1373
1374 // todo - proper fclk<>nonfclk switch 1374 // todo - proper fclk<>nonfclk switch //
1375 1375
1376 ucon &= ~S3C2440_UCON_CLKMASK; 1376 ucon &= ~S3C2440_UCON_CLKMASK;
1377 1377
1378 if (strcmp(clk->name, "uclk") == 0) 1378 if (strcmp(clk->name, "uclk") == 0)
1379 ucon |= S3C2440_UCON_UCLK; 1379 ucon |= S3C2440_UCON_UCLK;
1380 else if (strcmp(clk->name, "pclk") == 1380 else if (strcmp(clk->name, "pclk") == 0)
1381 ucon |= S3C2440_UCON_PCLK; 1381 ucon |= S3C2440_UCON_PCLK;
1382 else if (strcmp(clk->name, "fclk") == 1382 else if (strcmp(clk->name, "fclk") == 0)
1383 ucon |= S3C2440_UCON_FCLK; 1383 ucon |= S3C2440_UCON_FCLK;
1384 else { 1384 else {
1385 printk(KERN_ERR "unknown cloc 1385 printk(KERN_ERR "unknown clock source %s\n", clk->name);
1386 return -EINVAL; 1386 return -EINVAL;
1387 } 1387 }
1388 1388
1389 wr_regl(port, S3C2410_UCON, ucon); 1389 wr_regl(port, S3C2410_UCON, ucon);
1390 return 0; 1390 return 0;
1391 } 1391 }
1392 1392
1393 1393
1394 static int s3c2440_serial_getsource(struct ua 1394 static int s3c2440_serial_getsource(struct uart_port *port,
1395 struct s3 1395 struct s3c24xx_uart_clksrc *clk)
1396 { 1396 {
1397 unsigned long ucon = rd_regl(port, S3 1397 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1398 unsigned long ucon0, ucon1, ucon2; 1398 unsigned long ucon0, ucon1, ucon2;
1399 1399
1400 switch (ucon & S3C2440_UCON_CLKMASK) 1400 switch (ucon & S3C2440_UCON_CLKMASK) {
1401 case S3C2440_UCON_UCLK: 1401 case S3C2440_UCON_UCLK:
1402 clk->divisor = 1; 1402 clk->divisor = 1;
1403 clk->name = "uclk"; 1403 clk->name = "uclk";
1404 break; 1404 break;
1405 1405
1406 case S3C2440_UCON_PCLK: 1406 case S3C2440_UCON_PCLK:
1407 case S3C2440_UCON_PCLK2: 1407 case S3C2440_UCON_PCLK2:
1408 clk->divisor = 1; 1408 clk->divisor = 1;
1409 clk->name = "pclk"; 1409 clk->name = "pclk";
1410 break; 1410 break;
1411 1411
1412 case S3C2440_UCON_FCLK: 1412 case S3C2440_UCON_FCLK:
1413 /* the fun of calculating the 1413 /* the fun of calculating the uart divisors on
1414 * the s3c2440 */ 1414 * the s3c2440 */
1415 1415
1416 ucon0 = __raw_readl(S3C24XX_V 1416 ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
1417 ucon1 = __raw_readl(S3C24XX_V 1417 ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
1418 ucon2 = __raw_readl(S3C24XX_V 1418 ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
1419 1419
1420 printk("ucons: %08lx, %08lx, 1420 printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2);
1421 1421
1422 ucon0 &= S3C2440_UCON0_DIVMAS 1422 ucon0 &= S3C2440_UCON0_DIVMASK;
1423 ucon1 &= S3C2440_UCON1_DIVMAS 1423 ucon1 &= S3C2440_UCON1_DIVMASK;
1424 ucon2 &= S3C2440_UCON2_DIVMAS 1424 ucon2 &= S3C2440_UCON2_DIVMASK;
1425 1425
1426 if (ucon0 != 0) { 1426 if (ucon0 != 0) {
1427 clk->divisor = ucon0 1427 clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT;
1428 clk->divisor += 6; 1428 clk->divisor += 6;
1429 } else if (ucon1 != 0) { 1429 } else if (ucon1 != 0) {
1430 clk->divisor = ucon1 1430 clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT;
1431 clk->divisor += 21; 1431 clk->divisor += 21;
1432 } else if (ucon2 != 0) { 1432 } else if (ucon2 != 0) {
1433 clk->divisor = ucon2 1433 clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT;
1434 clk->divisor += 36; 1434 clk->divisor += 36;
1435 } else { 1435 } else {
1436 /* manual calims 44, 1436 /* manual calims 44, seems to be 9 */
1437 clk->divisor = 9; 1437 clk->divisor = 9;
1438 } 1438 }
1439 1439
1440 clk->name = "fclk"; 1440 clk->name = "fclk";
1441 break; 1441 break;
1442 } 1442 }
1443 1443
1444 return 0; 1444 return 0;
1445 } 1445 }
1446 1446
1447 static int s3c2440_serial_resetport(struct ua 1447 static int s3c2440_serial_resetport(struct uart_port *port,
1448 struct s3 1448 struct s3c2410_uartcfg *cfg)
1449 { 1449 {
1450 unsigned long ucon = rd_regl(port, S3 1450 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1451 1451
1452 dbg("s3c2440_serial_resetport: port=% 1452 dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n",
1453 port, port->mapbase, cfg); 1453 port, port->mapbase, cfg);
1454 1454
1455 /* ensure we don't change the clock s 1455 /* ensure we don't change the clock settings... */
1456 1456
1457 ucon &= (S3C2440_UCON0_DIVMASK | (3<< 1457 ucon &= (S3C2440_UCON0_DIVMASK | (3<<10));
1458 1458
1459 wr_regl(port, S3C2410_UCON, ucon | c 1459 wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
1460 wr_regl(port, S3C2410_ULCON, cfg->ulc 1460 wr_regl(port, S3C2410_ULCON, cfg->ulcon);
1461 1461
1462 /* reset both fifos */ 1462 /* reset both fifos */
1463 1463
1464 wr_regl(port, S3C2410_UFCON, cfg->ufc 1464 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
1465 wr_regl(port, S3C2410_UFCON, cfg->ufc 1465 wr_regl(port, S3C2410_UFCON, cfg->ufcon);
1466 1466
1467 return 0; 1467 return 0;
1468 } 1468 }
1469 1469
1470 static struct s3c24xx_uart_info s3c2440_uart_ 1470 static struct s3c24xx_uart_info s3c2440_uart_inf = {
1471 .name = "Samsung S3C2440 UA 1471 .name = "Samsung S3C2440 UART",
1472 .type = PORT_S3C2440, 1472 .type = PORT_S3C2440,
1473 .fifosize = 64, 1473 .fifosize = 64,
1474 .rx_fifomask = S3C2440_UFSTAT_RXMA 1474 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
1475 .rx_fifoshift = S3C2440_UFSTAT_RXSH 1475 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
1476 .rx_fifofull = S3C2440_UFSTAT_RXFU 1476 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
1477 .tx_fifofull = S3C2440_UFSTAT_TXFU 1477 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
1478 .tx_fifomask = S3C2440_UFSTAT_TXMA 1478 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
1479 .tx_fifoshift = S3C2440_UFSTAT_TXSH 1479 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
1480 .get_clksrc = s3c2440_serial_gets 1480 .get_clksrc = s3c2440_serial_getsource,
1481 .set_clksrc = s3c2440_serial_sets 1481 .set_clksrc = s3c2440_serial_setsource,
1482 .reset_port = s3c2440_serial_rese 1482 .reset_port = s3c2440_serial_resetport,
1483 }; 1483 };
1484 1484
1485 /* device management */ 1485 /* device management */
1486 1486
1487 static int s3c2440_serial_probe(struct platfo 1487 static int s3c2440_serial_probe(struct platform_device *dev)
1488 { 1488 {
1489 dbg("s3c2440_serial_probe: dev=%p\n", 1489 dbg("s3c2440_serial_probe: dev=%p\n", dev);
1490 return s3c24xx_serial_probe(dev, &s3c 1490 return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
1491 } 1491 }
1492 1492
1493 static struct platform_driver s3c2440_serial_ 1493 static struct platform_driver s3c2440_serial_drv = {
1494 .probe = s3c2440_serial_prob 1494 .probe = s3c2440_serial_probe,
1495 .remove = s3c24xx_serial_remo 1495 .remove = s3c24xx_serial_remove,
1496 .suspend = s3c24xx_serial_susp 1496 .suspend = s3c24xx_serial_suspend,
1497 .resume = s3c24xx_serial_resu 1497 .resume = s3c24xx_serial_resume,
1498 .driver = { 1498 .driver = {
1499 .name = "s3c2440-uart", 1499 .name = "s3c2440-uart",
1500 .owner = THIS_MODULE, 1500 .owner = THIS_MODULE,
1501 }, 1501 },
1502 }; 1502 };
1503 1503
1504 1504
1505 static inline int s3c2440_serial_init(void) 1505 static inline int s3c2440_serial_init(void)
1506 { 1506 {
1507 return s3c24xx_serial_init(&s3c2440_s 1507 return s3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf);
1508 } 1508 }
1509 1509
1510 static inline void s3c2440_serial_exit(void) 1510 static inline void s3c2440_serial_exit(void)
1511 { 1511 {
1512 platform_driver_unregister(&s3c2440_s 1512 platform_driver_unregister(&s3c2440_serial_drv);
1513 } 1513 }
1514 1514
1515 #define s3c2440_uart_inf_at &s3c2440_uart_inf 1515 #define s3c2440_uart_inf_at &s3c2440_uart_inf
1516 #else 1516 #else
1517 1517
1518 static inline int s3c2440_serial_init(void) 1518 static inline int s3c2440_serial_init(void)
1519 { 1519 {
1520 return 0; 1520 return 0;
1521 } 1521 }
1522 1522
1523 static inline void s3c2440_serial_exit(void) 1523 static inline void s3c2440_serial_exit(void)
1524 { 1524 {
1525 } 1525 }
1526 1526
1527 #define s3c2440_uart_inf_at NULL 1527 #define s3c2440_uart_inf_at NULL
1528 #endif /* CONFIG_CPU_S3C2440 */ 1528 #endif /* CONFIG_CPU_S3C2440 */
1529 1529
1530 #if defined(CONFIG_CPU_S3C2412) 1530 #if defined(CONFIG_CPU_S3C2412)
1531 1531
1532 static int s3c2412_serial_setsource(struct ua 1532 static int s3c2412_serial_setsource(struct uart_port *port,
1533 struct s 1533 struct s3c24xx_uart_clksrc *clk)
1534 { 1534 {
1535 unsigned long ucon = rd_regl(port, S3 1535 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1536 1536
1537 ucon &= ~S3C2412_UCON_CLKMASK; 1537 ucon &= ~S3C2412_UCON_CLKMASK;
1538 1538
1539 if (strcmp(clk->name, "uclk") == 0) 1539 if (strcmp(clk->name, "uclk") == 0)
1540 ucon |= S3C2440_UCON_UCLK; 1540 ucon |= S3C2440_UCON_UCLK;
1541 else if (strcmp(clk->name, "pclk") == 1541 else if (strcmp(clk->name, "pclk") == 0)
1542 ucon |= S3C2440_UCON_PCLK; 1542 ucon |= S3C2440_UCON_PCLK;
1543 else if (strcmp(clk->name, "usysclk") 1543 else if (strcmp(clk->name, "usysclk") == 0)
1544 ucon |= S3C2412_UCON_USYSCLK; 1544 ucon |= S3C2412_UCON_USYSCLK;
1545 else { 1545 else {
1546 printk(KERN_ERR "unknown cloc 1546 printk(KERN_ERR "unknown clock source %s\n", clk->name);
1547 return -EINVAL; 1547 return -EINVAL;
1548 } 1548 }
1549 1549
1550 wr_regl(port, S3C2410_UCON, ucon); 1550 wr_regl(port, S3C2410_UCON, ucon);
1551 return 0; 1551 return 0;
1552 } 1552 }
1553 1553
1554 1554
1555 static int s3c2412_serial_getsource(struct ua 1555 static int s3c2412_serial_getsource(struct uart_port *port,
1556 struct s3 1556 struct s3c24xx_uart_clksrc *clk)
1557 { 1557 {
1558 unsigned long ucon = rd_regl(port, S3 1558 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1559 1559
1560 switch (ucon & S3C2412_UCON_CLKMASK) 1560 switch (ucon & S3C2412_UCON_CLKMASK) {
1561 case S3C2412_UCON_UCLK: 1561 case S3C2412_UCON_UCLK:
1562 clk->divisor = 1; 1562 clk->divisor = 1;
1563 clk->name = "uclk"; 1563 clk->name = "uclk";
1564 break; 1564 break;
1565 1565
1566 case S3C2412_UCON_PCLK: 1566 case S3C2412_UCON_PCLK:
1567 case S3C2412_UCON_PCLK2: 1567 case S3C2412_UCON_PCLK2:
1568 clk->divisor = 1; 1568 clk->divisor = 1;
1569 clk->name = "pclk"; 1569 clk->name = "pclk";
1570 break; 1570 break;
1571 1571
1572 case S3C2412_UCON_USYSCLK: 1572 case S3C2412_UCON_USYSCLK:
1573 clk->divisor = 1; 1573 clk->divisor = 1;
1574 clk->name = "usysclk"; 1574 clk->name = "usysclk";
1575 break; 1575 break;
1576 } 1576 }
1577 1577
1578 return 0; 1578 return 0;
1579 } 1579 }
1580 1580
1581 static int s3c2412_serial_resetport(struct ua 1581 static int s3c2412_serial_resetport(struct uart_port *port,
1582 struct s3 1582 struct s3c2410_uartcfg *cfg)
1583 { 1583 {
1584 unsigned long ucon = rd_regl(port, S3 1584 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1585 1585
1586 dbg("%s: port=%p (%08lx), cfg=%p\n", 1586 dbg("%s: port=%p (%08lx), cfg=%p\n",
1587 __FUNCTION__, port, port->mapbase 1587 __FUNCTION__, port, port->mapbase, cfg);
1588 1588
1589 /* ensure we don't change the clock s 1589 /* ensure we don't change the clock settings... */
1590 1590
1591 ucon &= S3C2412_UCON_CLKMASK; 1591 ucon &= S3C2412_UCON_CLKMASK;
1592 1592
1593 wr_regl(port, S3C2410_UCON, ucon | c 1593 wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
1594 wr_regl(port, S3C2410_ULCON, cfg->ulc 1594 wr_regl(port, S3C2410_ULCON, cfg->ulcon);
1595 1595
1596 /* reset both fifos */ 1596 /* reset both fifos */
1597 1597
1598 wr_regl(port, S3C2410_UFCON, cfg->ufc 1598 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
1599 wr_regl(port, S3C2410_UFCON, cfg->ufc 1599 wr_regl(port, S3C2410_UFCON, cfg->ufcon);
1600 1600
1601 return 0; 1601 return 0;
1602 } 1602 }
1603 1603
1604 static struct s3c24xx_uart_info s3c2412_uart_ 1604 static struct s3c24xx_uart_info s3c2412_uart_inf = {
1605 .name = "Samsung S3C2412 UA 1605 .name = "Samsung S3C2412 UART",
1606 .type = PORT_S3C2412, 1606 .type = PORT_S3C2412,
1607 .fifosize = 64, 1607 .fifosize = 64,
1608 .rx_fifomask = S3C2440_UFSTAT_RXMA 1608 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
1609 .rx_fifoshift = S3C2440_UFSTAT_RXSH 1609 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
1610 .rx_fifofull = S3C2440_UFSTAT_RXFU 1610 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
1611 .tx_fifofull = S3C2440_UFSTAT_TXFU 1611 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
1612 .tx_fifomask = S3C2440_UFSTAT_TXMA 1612 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
1613 .tx_fifoshift = S3C2440_UFSTAT_TXSH 1613 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
1614 .get_clksrc = s3c2412_serial_gets 1614 .get_clksrc = s3c2412_serial_getsource,
1615 .set_clksrc = s3c2412_serial_sets 1615 .set_clksrc = s3c2412_serial_setsource,
1616 .reset_port = s3c2412_serial_rese 1616 .reset_port = s3c2412_serial_resetport,
1617 }; 1617 };
1618 1618
1619 /* device management */ 1619 /* device management */
1620 1620
1621 static int s3c2412_serial_probe(struct platfo 1621 static int s3c2412_serial_probe(struct platform_device *dev)
1622 { 1622 {
1623 dbg("s3c2440_serial_probe: dev=%p\n", 1623 dbg("s3c2440_serial_probe: dev=%p\n", dev);
1624 return s3c24xx_serial_probe(dev, &s3c 1624 return s3c24xx_serial_probe(dev, &s3c2412_uart_inf);
1625 } 1625 }
1626 1626
1627 static struct platform_driver s3c2412_serial_ 1627 static struct platform_driver s3c2412_serial_drv = {
1628 .probe = s3c2412_serial_prob 1628 .probe = s3c2412_serial_probe,
1629 .remove = s3c24xx_serial_remo 1629 .remove = s3c24xx_serial_remove,
1630 .suspend = s3c24xx_serial_susp 1630 .suspend = s3c24xx_serial_suspend,
1631 .resume = s3c24xx_serial_resu 1631 .resume = s3c24xx_serial_resume,
1632 .driver = { 1632 .driver = {
1633 .name = "s3c2412-uart", 1633 .name = "s3c2412-uart",
1634 .owner = THIS_MODULE, 1634 .owner = THIS_MODULE,
1635 }, 1635 },
1636 }; 1636 };
1637 1637
1638 1638
1639 static inline int s3c2412_serial_init(void) 1639 static inline int s3c2412_serial_init(void)
1640 { 1640 {
1641 return s3c24xx_serial_init(&s3c2412_s 1641 return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf);
1642 } 1642 }
1643 1643
1644 static inline void s3c2412_serial_exit(void) 1644 static inline void s3c2412_serial_exit(void)
1645 { 1645 {
1646 platform_driver_unregister(&s3c2412_s 1646 platform_driver_unregister(&s3c2412_serial_drv);
1647 } 1647 }
1648 1648
1649 #define s3c2412_uart_inf_at &s3c2412_uart_inf 1649 #define s3c2412_uart_inf_at &s3c2412_uart_inf
1650 #else 1650 #else
1651 1651
1652 static inline int s3c2412_serial_init(void) 1652 static inline int s3c2412_serial_init(void)
1653 { 1653 {
1654 return 0; 1654 return 0;
1655 } 1655 }
1656 1656
1657 static inline void s3c2412_serial_exit(void) 1657 static inline void s3c2412_serial_exit(void)
1658 { 1658 {
1659 } 1659 }
1660 1660
1661 #define s3c2412_uart_inf_at NULL 1661 #define s3c2412_uart_inf_at NULL
1662 #endif /* CONFIG_CPU_S3C2440 */ 1662 #endif /* CONFIG_CPU_S3C2440 */
1663 1663
1664 1664
1665 /* module initialisation code */ 1665 /* module initialisation code */
1666 1666
1667 static int __init s3c24xx_serial_modinit(void 1667 static int __init s3c24xx_serial_modinit(void)
1668 { 1668 {
1669 int ret; 1669 int ret;
1670 1670
1671 ret = uart_register_driver(&s3c24xx_u 1671 ret = uart_register_driver(&s3c24xx_uart_drv);
1672 if (ret < 0) { 1672 if (ret < 0) {
1673 printk(KERN_ERR "failed to re 1673 printk(KERN_ERR "failed to register UART driver\n");
1674 return -1; 1674 return -1;
1675 } 1675 }
1676 1676
1677 s3c2400_serial_init(); 1677 s3c2400_serial_init();
1678 s3c2410_serial_init(); 1678 s3c2410_serial_init();
1679 s3c2412_serial_init(); 1679 s3c2412_serial_init();
1680 s3c2440_serial_init(); 1680 s3c2440_serial_init();
1681 1681
1682 return 0; 1682 return 0;
1683 } 1683 }
1684 1684
1685 static void __exit s3c24xx_serial_modexit(voi 1685 static void __exit s3c24xx_serial_modexit(void)
1686 { 1686 {
1687 s3c2400_serial_exit(); 1687 s3c2400_serial_exit();
1688 s3c2410_serial_exit(); 1688 s3c2410_serial_exit();
1689 s3c2412_serial_exit(); 1689 s3c2412_serial_exit();
1690 s3c2440_serial_exit(); 1690 s3c2440_serial_exit();
1691 1691
1692 uart_unregister_driver(&s3c24xx_uart_ 1692 uart_unregister_driver(&s3c24xx_uart_drv);
1693 } 1693 }
1694 1694
1695 1695
1696 module_init(s3c24xx_serial_modinit); 1696 module_init(s3c24xx_serial_modinit);
1697 module_exit(s3c24xx_serial_modexit); 1697 module_exit(s3c24xx_serial_modexit);
1698 1698
1699 /* Console code */ 1699 /* Console code */
1700 1700
1701 #ifdef CONFIG_SERIAL_S3C2410_CONSOLE 1701 #ifdef CONFIG_SERIAL_S3C2410_CONSOLE
1702 1702
1703 static struct uart_port *cons_uart; 1703 static struct uart_port *cons_uart;
1704 1704
1705 static int 1705 static int
1706 s3c24xx_serial_console_txrdy(struct uart_port 1706 s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
1707 { 1707 {
1708 struct s3c24xx_uart_info *info = s3c2 1708 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1709 unsigned long ufstat, utrstat; 1709 unsigned long ufstat, utrstat;
1710 1710
1711 if (ufcon & S3C2410_UFCON_FIFOMODE) { 1711 if (ufcon & S3C2410_UFCON_FIFOMODE) {
1712 /* fifo mode - check ammount 1712 /* fifo mode - check ammount of data in fifo registers... */
1713 1713
1714 ufstat = rd_regl(port, S3C241 1714 ufstat = rd_regl(port, S3C2410_UFSTAT);
1715 return (ufstat & info->tx_fif 1715 return (ufstat & info->tx_fifofull) ? 0 : 1;
1716 } 1716 }
1717 1717
1718 /* in non-fifo mode, we go and use th 1718 /* in non-fifo mode, we go and use the tx buffer empty */
1719 1719
1720 utrstat = rd_regl(port, S3C2410_UTRST 1720 utrstat = rd_regl(port, S3C2410_UTRSTAT);
1721 return (utrstat & S3C2410_UTRSTAT_TXE 1721 return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
1722 } 1722 }
1723 1723
1724 static void 1724 static void
1725 s3c24xx_serial_console_putchar(struct uart_po 1725 s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
1726 { 1726 {
1727 unsigned int ufcon = rd_regl(cons_uar 1727 unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
1728 while (!s3c24xx_serial_console_txrdy( 1728 while (!s3c24xx_serial_console_txrdy(port, ufcon))
1729 barrier(); 1729 barrier();
1730 wr_regb(cons_uart, S3C2410_UTXH, ch); 1730 wr_regb(cons_uart, S3C2410_UTXH, ch);
1731 } 1731 }
1732 1732
1733 static void 1733 static void
1734 s3c24xx_serial_console_write(struct console * 1734 s3c24xx_serial_console_write(struct console *co, const char *s,
1735 unsigned int cou 1735 unsigned int count)
1736 { 1736 {
1737 uart_console_write(cons_uart, s, coun 1737 uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
1738 } 1738 }
1739 1739
1740 static void __init 1740 static void __init
1741 s3c24xx_serial_get_options(struct uart_port * 1741 s3c24xx_serial_get_options(struct uart_port *port, int *baud,
1742 int *parity, int * 1742 int *parity, int *bits)
1743 { 1743 {
1744 struct s3c24xx_uart_clksrc clksrc; 1744 struct s3c24xx_uart_clksrc clksrc;
1745 struct clk *clk; 1745 struct clk *clk;
1746 unsigned int ulcon; 1746 unsigned int ulcon;
1747 unsigned int ucon; 1747 unsigned int ucon;
1748 unsigned int ubrdiv; 1748 unsigned int ubrdiv;
1749 unsigned long rate; 1749 unsigned long rate;
1750 1750
1751 ulcon = rd_regl(port, S3C2410_ULCON) 1751 ulcon = rd_regl(port, S3C2410_ULCON);
1752 ucon = rd_regl(port, S3C2410_UCON); 1752 ucon = rd_regl(port, S3C2410_UCON);
1753 ubrdiv = rd_regl(port, S3C2410_UBRDIV 1753 ubrdiv = rd_regl(port, S3C2410_UBRDIV);
1754 1754
1755 dbg("s3c24xx_serial_get_options: port 1755 dbg("s3c24xx_serial_get_options: port=%p\n"
1756 "registers: ulcon=%08x, ucon=%08x 1756 "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
1757 port, ulcon, ucon, ubrdiv); 1757 port, ulcon, ucon, ubrdiv);
1758 1758
1759 if ((ucon & 0xf) != 0) { 1759 if ((ucon & 0xf) != 0) {
1760 /* consider the serial port c 1760 /* consider the serial port configured if the tx/rx mode set */
1761 1761
1762 switch (ulcon & S3C2410_LCON_ 1762 switch (ulcon & S3C2410_LCON_CSMASK) {
1763 case S3C2410_LCON_CS5: 1763 case S3C2410_LCON_CS5:
1764 *bits = 5; 1764 *bits = 5;
1765 break; 1765 break;
1766 case S3C2410_LCON_CS6: 1766 case S3C2410_LCON_CS6:
1767 *bits = 6; 1767 *bits = 6;
1768 break; 1768 break;
1769 case S3C2410_LCON_CS7: 1769 case S3C2410_LCON_CS7:
1770 *bits = 7; 1770 *bits = 7;
1771 break; 1771 break;
1772 default: 1772 default:
1773 case S3C2410_LCON_CS8: 1773 case S3C2410_LCON_CS8:
1774 *bits = 8; 1774 *bits = 8;
1775 break; 1775 break;
1776 } 1776 }
1777 1777
1778 switch (ulcon & S3C2410_LCON_ 1778 switch (ulcon & S3C2410_LCON_PMASK) {
1779 case S3C2410_LCON_PEVEN: 1779 case S3C2410_LCON_PEVEN:
1780 *parity = 'e'; 1780 *parity = 'e';
1781 break; 1781 break;
1782 1782
1783 case S3C2410_LCON_PODD: 1783 case S3C2410_LCON_PODD:
1784 *parity = 'o'; 1784 *parity = 'o';
1785 break; 1785 break;
1786 1786
1787 case S3C2410_LCON_PNONE: 1787 case S3C2410_LCON_PNONE:
1788 default: 1788 default:
1789 *parity = 'n'; 1789 *parity = 'n';
1790 } 1790 }
1791 1791
1792 /* now calculate the baud rat 1792 /* now calculate the baud rate */
1793 1793
1794 s3c24xx_serial_getsource(port 1794 s3c24xx_serial_getsource(port, &clksrc);
1795 1795
1796 clk = clk_get(port->dev, clks 1796 clk = clk_get(port->dev, clksrc.name);
1797 if (!IS_ERR(clk) && clk != NU 1797 if (!IS_ERR(clk) && clk != NULL)
1798 rate = clk_get_rate(c 1798 rate = clk_get_rate(clk) / clksrc.divisor;
1799 else 1799 else
1800 rate = 1; 1800 rate = 1;
1801 1801
1802 1802
1803 *baud = rate / ( 16 * (ubrdiv 1803 *baud = rate / ( 16 * (ubrdiv + 1));
1804 dbg("calculated baud %d\n", * 1804 dbg("calculated baud %d\n", *baud);
1805 } 1805 }
1806 1806
1807 } 1807 }
1808 1808
1809 /* s3c24xx_serial_init_ports 1809 /* s3c24xx_serial_init_ports
1810 * 1810 *
1811 * initialise the serial ports from the machi 1811 * initialise the serial ports from the machine provided initialisation
1812 * data. 1812 * data.
1813 */ 1813 */
1814 1814
1815 static int s3c24xx_serial_init_ports(struct s 1815 static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info)
1816 { 1816 {
1817 struct s3c24xx_uart_port *ptr = s3c24 1817 struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports;
1818 struct platform_device **platdev_ptr; 1818 struct platform_device **platdev_ptr;
1819 int i; 1819 int i;
1820 1820
1821 dbg("s3c24xx_serial_init_ports: initi 1821 dbg("s3c24xx_serial_init_ports: initialising ports...\n");
1822 1822
1823 platdev_ptr = s3c24xx_uart_devs; 1823 platdev_ptr = s3c24xx_uart_devs;
1824 1824
1825 for (i = 0; i < NR_PORTS; i++, ptr++, 1825 for (i = 0; i < NR_PORTS; i++, ptr++, platdev_ptr++) {
1826 s3c24xx_serial_init_port(ptr, 1826 s3c24xx_serial_init_port(ptr, info, *platdev_ptr);
1827 } 1827 }
1828 1828
1829 return 0; 1829 return 0;
1830 } 1830 }
1831 1831
1832 static int __init 1832 static int __init
1833 s3c24xx_serial_console_setup(struct console * 1833 s3c24xx_serial_console_setup(struct console *co, char *options)
1834 { 1834 {
1835 struct uart_port *port; 1835 struct uart_port *port;
1836 int baud = 9600; 1836 int baud = 9600;
1837 int bits = 8; 1837 int bits = 8;
1838 int parity = 'n'; 1838 int parity = 'n';
1839 int flow = 'n'; 1839 int flow = 'n';
1840 1840
1841 dbg("s3c24xx_serial_console_setup: co 1841 dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n",
1842 co, co->index, options); 1842 co, co->index, options);
1843 1843
1844 /* is this a valid port */ 1844 /* is this a valid port */
1845 1845
1846 if (co->index == -1 || co->index >= N 1846 if (co->index == -1 || co->index >= NR_PORTS)
1847 co->index = 0; 1847 co->index = 0;
1848 1848
1849 port = &s3c24xx_serial_ports[co->inde 1849 port = &s3c24xx_serial_ports[co->index].port;
1850 1850
1851 /* is the port configured? */ 1851 /* is the port configured? */
1852 1852
1853 if (port->mapbase == 0x0) { 1853 if (port->mapbase == 0x0) {
1854 co->index = 0; 1854 co->index = 0;
1855 port = &s3c24xx_serial_ports[ 1855 port = &s3c24xx_serial_ports[co->index].port;
1856 } 1856 }
1857 1857
1858 cons_uart = port; 1858 cons_uart = port;
1859 1859
1860 dbg("s3c24xx_serial_console_setup: po 1860 dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index);
1861 1861
1862 /* 1862 /*
1863 * Check whether an invalid uart numb 1863 * Check whether an invalid uart number has been specified, and
1864 * if so, search for the first availa 1864 * if so, search for the first available port that does have
1865 * console support. 1865 * console support.
1866 */ 1866 */
1867 if (options) 1867 if (options)
1868 uart_parse_options(options, & 1868 uart_parse_options(options, &baud, &parity, &bits, &flow);
1869 else 1869 else
1870 s3c24xx_serial_get_options(po 1870 s3c24xx_serial_get_options(port, &baud, &parity, &bits);
1871 1871
1872 dbg("s3c24xx_serial_console_setup: ba 1872 dbg("s3c24xx_serial_console_setup: baud %d\n", baud);
1873 1873
1874 return uart_set_options(port, co, bau 1874 return uart_set_options(port, co, baud, parity, bits, flow);
1875 } 1875 }
1876 1876
1877 /* s3c24xx_serial_initconsole 1877 /* s3c24xx_serial_initconsole
1878 * 1878 *
1879 * initialise the console from one of the uar 1879 * initialise the console from one of the uart drivers
1880 */ 1880 */
1881 1881
1882 static struct console s3c24xx_serial_console 1882 static struct console s3c24xx_serial_console =
1883 { 1883 {
1884 .name = S3C24XX_SERIAL_NAME 1884 .name = S3C24XX_SERIAL_NAME,
1885 .device = uart_console_device 1885 .device = uart_console_device,
1886 .flags = CON_PRINTBUFFER, 1886 .flags = CON_PRINTBUFFER,
1887 .index = -1, 1887 .index = -1,
1888 .write = s3c24xx_serial_cons 1888 .write = s3c24xx_serial_console_write,
1889 .setup = s3c24xx_serial_cons 1889 .setup = s3c24xx_serial_console_setup
1890 }; 1890 };
1891 1891
1892 static int s3c24xx_serial_initconsole(void) 1892 static int s3c24xx_serial_initconsole(void)
1893 { 1893 {
1894 struct s3c24xx_uart_info *info; 1894 struct s3c24xx_uart_info *info;
1895 struct platform_device *dev = s3c24xx 1895 struct platform_device *dev = s3c24xx_uart_devs[0];
1896 1896
1897 dbg("s3c24xx_serial_initconsole\n"); 1897 dbg("s3c24xx_serial_initconsole\n");
1898 1898
1899 /* select driver based on the cpu */ 1899 /* select driver based on the cpu */
1900 1900
1901 if (dev == NULL) { 1901 if (dev == NULL) {
1902 printk(KERN_ERR "s3c24xx: no 1902 printk(KERN_ERR "s3c24xx: no devices for console init\n");
1903 return 0; 1903 return 0;
1904 } 1904 }
1905 1905
1906 if (strcmp(dev->name, "s3c2400-uart") 1906 if (strcmp(dev->name, "s3c2400-uart") == 0) {
1907 info = s3c2400_uart_inf_at; 1907 info = s3c2400_uart_inf_at;
1908 } else if (strcmp(dev->name, "s3c2410 1908 } else if (strcmp(dev->name, "s3c2410-uart") == 0) {
1909 info = s3c2410_uart_inf_at; 1909 info = s3c2410_uart_inf_at;
1910 } else if (strcmp(dev->name, "s3c2440 1910 } else if (strcmp(dev->name, "s3c2440-uart") == 0) {
1911 info = s3c2440_uart_inf_at; 1911 info = s3c2440_uart_inf_at;
1912 } else if (strcmp(dev->name, "s3c2412 1912 } else if (strcmp(dev->name, "s3c2412-uart") == 0) {
1913 info = s3c2412_uart_inf_at; 1913 info = s3c2412_uart_inf_at;
1914 } else { 1914 } else {
1915 printk(KERN_ERR "s3c24xx: no 1915 printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
1916 return 0; 1916 return 0;
1917 } 1917 }
1918 1918
1919 if (info == NULL) { 1919 if (info == NULL) {
1920 printk(KERN_ERR "s3c24xx: no 1920 printk(KERN_ERR "s3c24xx: no driver for console\n");
1921 return 0; 1921 return 0;
1922 } 1922 }
1923 1923
1924 s3c24xx_serial_console.data = &s3c24x 1924 s3c24xx_serial_console.data = &s3c24xx_uart_drv;
1925 s3c24xx_serial_init_ports(info); 1925 s3c24xx_serial_init_ports(info);
1926 1926
1927 register_console(&s3c24xx_serial_cons 1927 register_console(&s3c24xx_serial_console);
1928 return 0; 1928 return 0;
1929 } 1929 }
1930 1930
1931 console_initcall(s3c24xx_serial_initconsole); 1931 console_initcall(s3c24xx_serial_initconsole);
1932 1932
1933 #endif /* CONFIG_SERIAL_S3C2410_CONSOLE */ 1933 #endif /* CONFIG_SERIAL_S3C2410_CONSOLE */
1934 1934
1935 MODULE_LICENSE("GPL"); 1935 MODULE_LICENSE("GPL");
1936 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>") 1936 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1937 MODULE_DESCRIPTION("Samsung S3C2410/S3C2440/S 1937 MODULE_DESCRIPTION("Samsung S3C2410/S3C2440/S3C2412 Serial port driver");
1938 MODULE_ALIAS("platform:s3c2400-uart"); 1938 MODULE_ALIAS("platform:s3c2400-uart");
1939 MODULE_ALIAS("platform:s3c2410-uart"); 1939 MODULE_ALIAS("platform:s3c2410-uart");
1940 MODULE_ALIAS("platform:s3c2412-uart"); 1940 MODULE_ALIAS("platform:s3c2412-uart");
1941 MODULE_ALIAS("platform:s3c2440-uart"); 1941 MODULE_ALIAS("platform:s3c2440-uart");
1942 1942
|
This page was automatically generated by the
LXR engine.
|