blob: 53ff6af162733fb10f0b2cc070aad1be619cfb33 [file] [log] [blame]
Feng Tangd843fc62010-07-27 08:20:22 +01001/*
2 * mfd.c: driver for High Speed UART device of Intel Medfield platform
3 *
4 * Refer pxa.c, 8250.c and some other drivers in drivers/serial/
5 *
Feng Tang06c77e22010-07-27 08:20:42 +01006 * (C) Copyright 2010 Intel Corporation
Feng Tangd843fc62010-07-27 08:20:22 +01007 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; version 2
11 * of the License.
12 */
13
Feng Tangd843fc62010-07-27 08:20:22 +010014/* Notes:
Feng Tang06c77e22010-07-27 08:20:42 +010015 * 1. DMA channel allocation: 0/1 channel are assigned to port 0,
16 * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans
17 * are used for RX, odd chans for TX
Feng Tangd843fc62010-07-27 08:20:22 +010018 *
Feng Tang085a4f72011-02-22 15:28:10 +080019 * 2. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always
Feng Tang06c77e22010-07-27 08:20:42 +010020 * asserted, only when the HW is reset the DDCD and DDSR will
21 * be triggered
Feng Tangd843fc62010-07-27 08:20:22 +010022 */
23
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/console.h>
27#include <linux/sysrq.h>
Andrew Morton63d66ca2010-09-30 15:15:28 -070028#include <linux/slab.h>
Feng Tangd843fc62010-07-27 08:20:22 +010029#include <linux/serial_reg.h>
30#include <linux/circ_buf.h>
31#include <linux/delay.h>
32#include <linux/interrupt.h>
33#include <linux/tty.h>
34#include <linux/tty_flip.h>
35#include <linux/serial_core.h>
36#include <linux/serial_mfd.h>
37#include <linux/dma-mapping.h>
38#include <linux/pci.h>
39#include <linux/io.h>
40#include <linux/debugfs.h>
41
Feng Tangd843fc62010-07-27 08:20:22 +010042#define HSU_DMA_BUF_SIZE 2048
43
44#define chan_readl(chan, offset) readl(chan->reg + offset)
45#define chan_writel(chan, offset, val) writel(val, chan->reg + offset)
46
47#define mfd_readl(obj, offset) readl(obj->reg + offset)
48#define mfd_writel(obj, offset, val) writel(val, obj->reg + offset)
49
50struct hsu_dma_buffer {
51 u8 *buf;
52 dma_addr_t dma_addr;
53 u32 dma_size;
54 u32 ofs;
55};
56
57struct hsu_dma_chan {
58 u32 id;
Feng Tang06c77e22010-07-27 08:20:42 +010059 enum dma_data_direction dirt;
Feng Tangd843fc62010-07-27 08:20:22 +010060 struct uart_hsu_port *uport;
Feng Tang669b7a02010-07-27 08:20:32 +010061 void __iomem *reg;
Feng Tangd843fc62010-07-27 08:20:22 +010062};
63
64struct uart_hsu_port {
65 struct uart_port port;
66 unsigned char ier;
67 unsigned char lcr;
68 unsigned char mcr;
69 unsigned int lsr_break_flag;
70 char name[12];
71 int index;
72 struct device *dev;
73
74 struct hsu_dma_chan *txc;
75 struct hsu_dma_chan *rxc;
76 struct hsu_dma_buffer txbuf;
77 struct hsu_dma_buffer rxbuf;
78 int use_dma; /* flag for DMA/PIO */
79 int running;
80 int dma_tx_on;
81};
82
83/* Top level data structure of HSU */
84struct hsu_port {
Feng Tangd843fc62010-07-27 08:20:22 +010085 void __iomem *reg;
86 unsigned long paddr;
87 unsigned long iolen;
88 u32 irq;
89
90 struct uart_hsu_port port[3];
91 struct hsu_dma_chan chans[10];
92
Feng Tangd843fc62010-07-27 08:20:22 +010093 struct dentry *debugfs;
Feng Tangd843fc62010-07-27 08:20:22 +010094};
95
Feng Tangd843fc62010-07-27 08:20:22 +010096static inline unsigned int serial_in(struct uart_hsu_port *up, int offset)
97{
98 unsigned int val;
99
100 if (offset > UART_MSR) {
101 offset <<= 2;
102 val = readl(up->port.membase + offset);
103 } else
104 val = (unsigned int)readb(up->port.membase + offset);
105
106 return val;
107}
108
109static inline void serial_out(struct uart_hsu_port *up, int offset, int value)
110{
111 if (offset > UART_MSR) {
112 offset <<= 2;
113 writel(value, up->port.membase + offset);
114 } else {
115 unsigned char val = value & 0xff;
116 writeb(val, up->port.membase + offset);
117 }
118}
119
120#ifdef CONFIG_DEBUG_FS
121
122#define HSU_REGS_BUFSIZE 1024
123
124static int hsu_show_regs_open(struct inode *inode, struct file *file)
125{
126 file->private_data = inode->i_private;
127 return 0;
128}
129
130static ssize_t port_show_regs(struct file *file, char __user *user_buf,
131 size_t count, loff_t *ppos)
132{
133 struct uart_hsu_port *up = file->private_data;
134 char *buf;
135 u32 len = 0;
136 ssize_t ret;
137
138 buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL);
139 if (!buf)
140 return 0;
141
142 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
143 "MFD HSU port[%d] regs:\n", up->index);
144
145 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
146 "=================================\n");
147 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
148 "IER: \t\t0x%08x\n", serial_in(up, UART_IER));
149 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
150 "IIR: \t\t0x%08x\n", serial_in(up, UART_IIR));
151 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
152 "LCR: \t\t0x%08x\n", serial_in(up, UART_LCR));
153 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
154 "MCR: \t\t0x%08x\n", serial_in(up, UART_MCR));
155 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
156 "LSR: \t\t0x%08x\n", serial_in(up, UART_LSR));
157 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
158 "MSR: \t\t0x%08x\n", serial_in(up, UART_MSR));
159 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
160 "FOR: \t\t0x%08x\n", serial_in(up, UART_FOR));
161 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
162 "PS: \t\t0x%08x\n", serial_in(up, UART_PS));
163 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
164 "MUL: \t\t0x%08x\n", serial_in(up, UART_MUL));
165 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
166 "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
167
Dan Carpentera9589812010-08-12 09:50:09 +0200168 if (len > HSU_REGS_BUFSIZE)
169 len = HSU_REGS_BUFSIZE;
170
Feng Tangd843fc62010-07-27 08:20:22 +0100171 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
172 kfree(buf);
173 return ret;
174}
175
176static ssize_t dma_show_regs(struct file *file, char __user *user_buf,
177 size_t count, loff_t *ppos)
178{
179 struct hsu_dma_chan *chan = file->private_data;
180 char *buf;
181 u32 len = 0;
182 ssize_t ret;
183
184 buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL);
185 if (!buf)
186 return 0;
187
188 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
189 "MFD HSU DMA channel [%d] regs:\n", chan->id);
190
191 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
192 "=================================\n");
193 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
194 "CR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_CR));
195 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
196 "DCR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_DCR));
197 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
198 "BSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_BSR));
199 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
200 "MOTSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_MOTSR));
201 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
202 "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0SAR));
203 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
204 "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0TSR));
205 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
206 "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1SAR));
207 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
208 "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1TSR));
209 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
210 "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2SAR));
211 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
212 "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2TSR));
213 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
214 "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3SAR));
215 len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
216 "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
217
Dan Carpentera9589812010-08-12 09:50:09 +0200218 if (len > HSU_REGS_BUFSIZE)
219 len = HSU_REGS_BUFSIZE;
220
Feng Tangd843fc62010-07-27 08:20:22 +0100221 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
222 kfree(buf);
223 return ret;
224}
225
226static const struct file_operations port_regs_ops = {
227 .owner = THIS_MODULE,
228 .open = hsu_show_regs_open,
229 .read = port_show_regs,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200230 .llseek = default_llseek,
Feng Tangd843fc62010-07-27 08:20:22 +0100231};
232
233static const struct file_operations dma_regs_ops = {
234 .owner = THIS_MODULE,
235 .open = hsu_show_regs_open,
236 .read = dma_show_regs,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200237 .llseek = default_llseek,
Feng Tangd843fc62010-07-27 08:20:22 +0100238};
239
240static int hsu_debugfs_init(struct hsu_port *hsu)
241{
242 int i;
243 char name[32];
244
245 hsu->debugfs = debugfs_create_dir("hsu", NULL);
246 if (!hsu->debugfs)
247 return -ENOMEM;
248
249 for (i = 0; i < 3; i++) {
250 snprintf(name, sizeof(name), "port_%d_regs", i);
251 debugfs_create_file(name, S_IFREG | S_IRUGO,
252 hsu->debugfs, (void *)(&hsu->port[i]), &port_regs_ops);
253 }
254
255 for (i = 0; i < 6; i++) {
256 snprintf(name, sizeof(name), "dma_chan_%d_regs", i);
257 debugfs_create_file(name, S_IFREG | S_IRUGO,
258 hsu->debugfs, (void *)&hsu->chans[i], &dma_regs_ops);
259 }
260
261 return 0;
262}
263
264static void hsu_debugfs_remove(struct hsu_port *hsu)
265{
266 if (hsu->debugfs)
267 debugfs_remove_recursive(hsu->debugfs);
268}
269
270#else
271static inline int hsu_debugfs_init(struct hsu_port *hsu)
272{
273 return 0;
274}
275
276static inline void hsu_debugfs_remove(struct hsu_port *hsu)
277{
278}
279#endif /* CONFIG_DEBUG_FS */
280
281static void serial_hsu_enable_ms(struct uart_port *port)
282{
283 struct uart_hsu_port *up =
284 container_of(port, struct uart_hsu_port, port);
285
286 up->ier |= UART_IER_MSI;
287 serial_out(up, UART_IER, up->ier);
288}
289
290void hsu_dma_tx(struct uart_hsu_port *up)
291{
292 struct circ_buf *xmit = &up->port.state->xmit;
293 struct hsu_dma_buffer *dbuf = &up->txbuf;
294 int count;
295
296 /* test_and_set_bit may be better, but anyway it's in lock protected mode */
297 if (up->dma_tx_on)
298 return;
299
300 /* Update the circ buf info */
301 xmit->tail += dbuf->ofs;
302 xmit->tail &= UART_XMIT_SIZE - 1;
303
304 up->port.icount.tx += dbuf->ofs;
305 dbuf->ofs = 0;
306
307 /* Disable the channel */
308 chan_writel(up->txc, HSU_CH_CR, 0x0);
309
310 if (!uart_circ_empty(xmit) && !uart_tx_stopped(&up->port)) {
311 dma_sync_single_for_device(up->port.dev,
312 dbuf->dma_addr,
313 dbuf->dma_size,
314 DMA_TO_DEVICE);
315
316 count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
317 dbuf->ofs = count;
318
319 /* Reprogram the channel */
320 chan_writel(up->txc, HSU_CH_D0SAR, dbuf->dma_addr + xmit->tail);
321 chan_writel(up->txc, HSU_CH_D0TSR, count);
322
323 /* Reenable the channel */
324 chan_writel(up->txc, HSU_CH_DCR, 0x1
325 | (0x1 << 8)
326 | (0x1 << 16)
327 | (0x1 << 24));
Feng Tangd843fc62010-07-27 08:20:22 +0100328 up->dma_tx_on = 1;
329 chan_writel(up->txc, HSU_CH_CR, 0x1);
330 }
331
332 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
333 uart_write_wakeup(&up->port);
334}
335
336/* The buffer is already cache coherent */
337void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf)
338{
Feng Tangd843fc62010-07-27 08:20:22 +0100339 dbuf->ofs = 0;
340
341 chan_writel(rxc, HSU_CH_BSR, 32);
342 chan_writel(rxc, HSU_CH_MOTSR, 4);
343
344 chan_writel(rxc, HSU_CH_D0SAR, dbuf->dma_addr);
345 chan_writel(rxc, HSU_CH_D0TSR, dbuf->dma_size);
346 chan_writel(rxc, HSU_CH_DCR, 0x1 | (0x1 << 8)
347 | (0x1 << 16)
348 | (0x1 << 24) /* timeout bit, see HSU Errata 1 */
349 );
350 chan_writel(rxc, HSU_CH_CR, 0x3);
351}
352
353/* Protected by spin_lock_irqsave(port->lock) */
354static void serial_hsu_start_tx(struct uart_port *port)
355{
356 struct uart_hsu_port *up =
357 container_of(port, struct uart_hsu_port, port);
358
359 if (up->use_dma) {
360 hsu_dma_tx(up);
361 } else if (!(up->ier & UART_IER_THRI)) {
362 up->ier |= UART_IER_THRI;
363 serial_out(up, UART_IER, up->ier);
364 }
365}
366
367static void serial_hsu_stop_tx(struct uart_port *port)
368{
369 struct uart_hsu_port *up =
370 container_of(port, struct uart_hsu_port, port);
371 struct hsu_dma_chan *txc = up->txc;
372
373 if (up->use_dma)
374 chan_writel(txc, HSU_CH_CR, 0x0);
375 else if (up->ier & UART_IER_THRI) {
376 up->ier &= ~UART_IER_THRI;
377 serial_out(up, UART_IER, up->ier);
378 }
379}
380
381/* This is always called in spinlock protected mode, so
382 * modify timeout timer is safe here */
383void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)
384{
385 struct hsu_dma_buffer *dbuf = &up->rxbuf;
386 struct hsu_dma_chan *chan = up->rxc;
387 struct uart_port *port = &up->port;
388 struct tty_struct *tty = port->state->port.tty;
389 int count;
390
391 if (!tty)
392 return;
393
394 /*
Feng Tang06c77e22010-07-27 08:20:42 +0100395 * First need to know how many is already transferred,
Feng Tangd843fc62010-07-27 08:20:22 +0100396 * then check if its a timeout DMA irq, and return
397 * the trail bytes out, push them up and reenable the
Feng Tang06c77e22010-07-27 08:20:42 +0100398 * channel
Feng Tangd843fc62010-07-27 08:20:22 +0100399 */
400
Feng Tang06c77e22010-07-27 08:20:42 +0100401 /* Timeout IRQ, need wait some time, see Errata 2 */
Feng Tangd843fc62010-07-27 08:20:22 +0100402 if (int_sts & 0xf00)
403 udelay(2);
404
405 /* Stop the channel */
406 chan_writel(chan, HSU_CH_CR, 0x0);
407
Feng Tangd843fc62010-07-27 08:20:22 +0100408 count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
Feng Tang669b7a02010-07-27 08:20:32 +0100409 if (!count) {
Feng Tang06c77e22010-07-27 08:20:42 +0100410 /* Restart the channel before we leave */
Feng Tang669b7a02010-07-27 08:20:32 +0100411 chan_writel(chan, HSU_CH_CR, 0x3);
Feng Tangd843fc62010-07-27 08:20:22 +0100412 return;
Feng Tang669b7a02010-07-27 08:20:32 +0100413 }
Feng Tangd843fc62010-07-27 08:20:22 +0100414
415 dma_sync_single_for_cpu(port->dev, dbuf->dma_addr,
416 dbuf->dma_size, DMA_FROM_DEVICE);
417
418 /*
Feng Tang06c77e22010-07-27 08:20:42 +0100419 * Head will only wrap around when we recycle
Feng Tangd843fc62010-07-27 08:20:22 +0100420 * the DMA buffer, and when that happens, we
421 * explicitly set tail to 0. So head will
422 * always be greater than tail.
423 */
424 tty_insert_flip_string(tty, dbuf->buf, count);
425 port->icount.rx += count;
426
427 dma_sync_single_for_device(up->port.dev, dbuf->dma_addr,
428 dbuf->dma_size, DMA_FROM_DEVICE);
429
430 /* Reprogram the channel */
431 chan_writel(chan, HSU_CH_D0SAR, dbuf->dma_addr);
432 chan_writel(chan, HSU_CH_D0TSR, dbuf->dma_size);
433 chan_writel(chan, HSU_CH_DCR, 0x1
434 | (0x1 << 8)
435 | (0x1 << 16)
436 | (0x1 << 24) /* timeout bit, see HSU Errata 1 */
437 );
Feng Tangd843fc62010-07-27 08:20:22 +0100438 tty_flip_buffer_push(tty);
Feng Tang669b7a02010-07-27 08:20:32 +0100439
440 chan_writel(chan, HSU_CH_CR, 0x3);
Feng Tang669b7a02010-07-27 08:20:32 +0100441
Feng Tangd843fc62010-07-27 08:20:22 +0100442}
443
444static void serial_hsu_stop_rx(struct uart_port *port)
445{
446 struct uart_hsu_port *up =
447 container_of(port, struct uart_hsu_port, port);
448 struct hsu_dma_chan *chan = up->rxc;
449
450 if (up->use_dma)
451 chan_writel(chan, HSU_CH_CR, 0x2);
452 else {
453 up->ier &= ~UART_IER_RLSI;
454 up->port.read_status_mask &= ~UART_LSR_DR;
455 serial_out(up, UART_IER, up->ier);
456 }
457}
458
Feng Tangd843fc62010-07-27 08:20:22 +0100459static inline void receive_chars(struct uart_hsu_port *up, int *status)
460{
461 struct tty_struct *tty = up->port.state->port.tty;
462 unsigned int ch, flag;
463 unsigned int max_count = 256;
464
465 if (!tty)
466 return;
467
468 do {
469 ch = serial_in(up, UART_RX);
470 flag = TTY_NORMAL;
471 up->port.icount.rx++;
472
473 if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
474 UART_LSR_FE | UART_LSR_OE))) {
475
476 dev_warn(up->dev, "We really rush into ERR/BI case"
477 "status = 0x%02x", *status);
478 /* For statistics only */
479 if (*status & UART_LSR_BI) {
480 *status &= ~(UART_LSR_FE | UART_LSR_PE);
481 up->port.icount.brk++;
482 /*
483 * We do the SysRQ and SAK checking
484 * here because otherwise the break
485 * may get masked by ignore_status_mask
486 * or read_status_mask.
487 */
488 if (uart_handle_break(&up->port))
489 goto ignore_char;
490 } else if (*status & UART_LSR_PE)
491 up->port.icount.parity++;
492 else if (*status & UART_LSR_FE)
493 up->port.icount.frame++;
494 if (*status & UART_LSR_OE)
495 up->port.icount.overrun++;
496
497 /* Mask off conditions which should be ignored. */
498 *status &= up->port.read_status_mask;
499
500#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
501 if (up->port.cons &&
502 up->port.cons->index == up->port.line) {
503 /* Recover the break flag from console xmit */
504 *status |= up->lsr_break_flag;
505 up->lsr_break_flag = 0;
506 }
507#endif
508 if (*status & UART_LSR_BI) {
509 flag = TTY_BREAK;
510 } else if (*status & UART_LSR_PE)
511 flag = TTY_PARITY;
512 else if (*status & UART_LSR_FE)
513 flag = TTY_FRAME;
514 }
515
516 if (uart_handle_sysrq_char(&up->port, ch))
517 goto ignore_char;
518
519 uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
520 ignore_char:
521 *status = serial_in(up, UART_LSR);
522 } while ((*status & UART_LSR_DR) && max_count--);
523 tty_flip_buffer_push(tty);
524}
525
526static void transmit_chars(struct uart_hsu_port *up)
527{
528 struct circ_buf *xmit = &up->port.state->xmit;
529 int count;
Feng Tangd843fc62010-07-27 08:20:22 +0100530
531 if (up->port.x_char) {
532 serial_out(up, UART_TX, up->port.x_char);
533 up->port.icount.tx++;
534 up->port.x_char = 0;
535 return;
536 }
537 if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
538 serial_hsu_stop_tx(&up->port);
539 return;
540 }
541
Feng Tang085a4f72011-02-22 15:28:10 +0800542 /* The IRQ is for TX FIFO half-empty */
Feng Tangd843fc62010-07-27 08:20:22 +0100543 count = up->port.fifosize / 2;
Feng Tang085a4f72011-02-22 15:28:10 +0800544
Feng Tangd843fc62010-07-27 08:20:22 +0100545 do {
546 serial_out(up, UART_TX, xmit->buf[xmit->tail]);
547 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
Feng Tangd843fc62010-07-27 08:20:22 +0100548
549 up->port.icount.tx++;
550 if (uart_circ_empty(xmit))
551 break;
552 } while (--count > 0);
553
554 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
555 uart_write_wakeup(&up->port);
556
557 if (uart_circ_empty(xmit))
558 serial_hsu_stop_tx(&up->port);
559}
560
561static inline void check_modem_status(struct uart_hsu_port *up)
562{
563 int status;
564
565 status = serial_in(up, UART_MSR);
566
567 if ((status & UART_MSR_ANY_DELTA) == 0)
568 return;
569
570 if (status & UART_MSR_TERI)
571 up->port.icount.rng++;
572 if (status & UART_MSR_DDSR)
573 up->port.icount.dsr++;
574 /* We may only get DDCD when HW init and reset */
575 if (status & UART_MSR_DDCD)
576 uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
Feng Tang06c77e22010-07-27 08:20:42 +0100577 /* Will start/stop_tx accordingly */
Feng Tangd843fc62010-07-27 08:20:22 +0100578 if (status & UART_MSR_DCTS)
579 uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
580
581 wake_up_interruptible(&up->port.state->port.delta_msr_wait);
582}
583
584/*
585 * This handles the interrupt from one port.
586 */
587static irqreturn_t port_irq(int irq, void *dev_id)
588{
589 struct uart_hsu_port *up = dev_id;
590 unsigned int iir, lsr;
591 unsigned long flags;
592
593 if (unlikely(!up->running))
594 return IRQ_NONE;
595
Feng Tang06c77e22010-07-27 08:20:42 +0100596 spin_lock_irqsave(&up->port.lock, flags);
Feng Tangd843fc62010-07-27 08:20:22 +0100597 if (up->use_dma) {
598 lsr = serial_in(up, UART_LSR);
599 if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE |
600 UART_LSR_FE | UART_LSR_OE)))
601 dev_warn(up->dev,
602 "Got lsr irq while using DMA, lsr = 0x%2x\n",
603 lsr);
604 check_modem_status(up);
Feng Tang06c77e22010-07-27 08:20:42 +0100605 spin_unlock_irqrestore(&up->port.lock, flags);
Feng Tangd843fc62010-07-27 08:20:22 +0100606 return IRQ_HANDLED;
607 }
608
Feng Tangd843fc62010-07-27 08:20:22 +0100609 iir = serial_in(up, UART_IIR);
610 if (iir & UART_IIR_NO_INT) {
611 spin_unlock_irqrestore(&up->port.lock, flags);
612 return IRQ_NONE;
613 }
614
615 lsr = serial_in(up, UART_LSR);
Feng Tangd843fc62010-07-27 08:20:22 +0100616 if (lsr & UART_LSR_DR)
617 receive_chars(up, &lsr);
Feng Tang06c77e22010-07-27 08:20:42 +0100618 check_modem_status(up);
Feng Tangd843fc62010-07-27 08:20:22 +0100619
620 /* lsr will be renewed during the receive_chars */
621 if (lsr & UART_LSR_THRE)
622 transmit_chars(up);
623
624 spin_unlock_irqrestore(&up->port.lock, flags);
625 return IRQ_HANDLED;
626}
627
628static inline void dma_chan_irq(struct hsu_dma_chan *chan)
629{
630 struct uart_hsu_port *up = chan->uport;
631 unsigned long flags;
632 u32 int_sts;
633
634 spin_lock_irqsave(&up->port.lock, flags);
635
636 if (!up->use_dma || !up->running)
637 goto exit;
638
639 /*
640 * No matter what situation, need read clear the IRQ status
641 * There is a bug, see Errata 5, HSD 2900918
642 */
643 int_sts = chan_readl(chan, HSU_CH_SR);
644
645 /* Rx channel */
646 if (chan->dirt == DMA_FROM_DEVICE)
647 hsu_dma_rx(up, int_sts);
648
649 /* Tx channel */
650 if (chan->dirt == DMA_TO_DEVICE) {
Feng Tangd843fc62010-07-27 08:20:22 +0100651 chan_writel(chan, HSU_CH_CR, 0x0);
652 up->dma_tx_on = 0;
653 hsu_dma_tx(up);
654 }
655
656exit:
657 spin_unlock_irqrestore(&up->port.lock, flags);
658 return;
659}
660
661static irqreturn_t dma_irq(int irq, void *dev_id)
662{
663 struct hsu_port *hsu = dev_id;
664 u32 int_sts, i;
665
666 int_sts = mfd_readl(hsu, HSU_GBL_DMAISR);
667
668 /* Currently we only have 6 channels may be used */
669 for (i = 0; i < 6; i++) {
670 if (int_sts & 0x1)
671 dma_chan_irq(&hsu->chans[i]);
672 int_sts >>= 1;
673 }
674
675 return IRQ_HANDLED;
676}
677
678static unsigned int serial_hsu_tx_empty(struct uart_port *port)
679{
680 struct uart_hsu_port *up =
681 container_of(port, struct uart_hsu_port, port);
682 unsigned long flags;
683 unsigned int ret;
684
685 spin_lock_irqsave(&up->port.lock, flags);
686 ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
687 spin_unlock_irqrestore(&up->port.lock, flags);
688
689 return ret;
690}
691
692static unsigned int serial_hsu_get_mctrl(struct uart_port *port)
693{
694 struct uart_hsu_port *up =
695 container_of(port, struct uart_hsu_port, port);
696 unsigned char status;
697 unsigned int ret;
698
699 status = serial_in(up, UART_MSR);
700
701 ret = 0;
702 if (status & UART_MSR_DCD)
703 ret |= TIOCM_CAR;
704 if (status & UART_MSR_RI)
705 ret |= TIOCM_RNG;
706 if (status & UART_MSR_DSR)
707 ret |= TIOCM_DSR;
708 if (status & UART_MSR_CTS)
709 ret |= TIOCM_CTS;
710 return ret;
711}
712
713static void serial_hsu_set_mctrl(struct uart_port *port, unsigned int mctrl)
714{
715 struct uart_hsu_port *up =
716 container_of(port, struct uart_hsu_port, port);
717 unsigned char mcr = 0;
718
719 if (mctrl & TIOCM_RTS)
720 mcr |= UART_MCR_RTS;
721 if (mctrl & TIOCM_DTR)
722 mcr |= UART_MCR_DTR;
723 if (mctrl & TIOCM_OUT1)
724 mcr |= UART_MCR_OUT1;
725 if (mctrl & TIOCM_OUT2)
726 mcr |= UART_MCR_OUT2;
727 if (mctrl & TIOCM_LOOP)
728 mcr |= UART_MCR_LOOP;
729
730 mcr |= up->mcr;
731
732 serial_out(up, UART_MCR, mcr);
733}
734
735static void serial_hsu_break_ctl(struct uart_port *port, int break_state)
736{
737 struct uart_hsu_port *up =
738 container_of(port, struct uart_hsu_port, port);
739 unsigned long flags;
740
741 spin_lock_irqsave(&up->port.lock, flags);
742 if (break_state == -1)
743 up->lcr |= UART_LCR_SBC;
744 else
745 up->lcr &= ~UART_LCR_SBC;
746 serial_out(up, UART_LCR, up->lcr);
747 spin_unlock_irqrestore(&up->port.lock, flags);
748}
749
750/*
751 * What special to do:
752 * 1. chose the 64B fifo mode
Feng Tang085a4f72011-02-22 15:28:10 +0800753 * 2. start dma or pio depends on configuration
754 * 3. we only allocate dma memory when needed
Feng Tangd843fc62010-07-27 08:20:22 +0100755 */
756static int serial_hsu_startup(struct uart_port *port)
757{
758 struct uart_hsu_port *up =
759 container_of(port, struct uart_hsu_port, port);
760 unsigned long flags;
761
762 /*
763 * Clear the FIFO buffers and disable them.
764 * (they will be reenabled in set_termios())
765 */
766 serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
767 serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
768 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
769 serial_out(up, UART_FCR, 0);
770
771 /* Clear the interrupt registers. */
772 (void) serial_in(up, UART_LSR);
773 (void) serial_in(up, UART_RX);
774 (void) serial_in(up, UART_IIR);
775 (void) serial_in(up, UART_MSR);
776
777 /* Now, initialize the UART, default is 8n1 */
778 serial_out(up, UART_LCR, UART_LCR_WLEN8);
779
780 spin_lock_irqsave(&up->port.lock, flags);
781
782 up->port.mctrl |= TIOCM_OUT2;
783 serial_hsu_set_mctrl(&up->port, up->port.mctrl);
784
785 /*
786 * Finally, enable interrupts. Note: Modem status interrupts
787 * are set via set_termios(), which will be occurring imminently
788 * anyway, so we don't enable them here.
789 */
790 if (!up->use_dma)
791 up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE;
792 else
793 up->ier = 0;
794 serial_out(up, UART_IER, up->ier);
795
796 spin_unlock_irqrestore(&up->port.lock, flags);
797
798 /* DMA init */
Feng Tangd843fc62010-07-27 08:20:22 +0100799 if (up->use_dma) {
800 struct hsu_dma_buffer *dbuf;
801 struct circ_buf *xmit = &port->state->xmit;
802
803 up->dma_tx_on = 0;
804
805 /* First allocate the RX buffer */
806 dbuf = &up->rxbuf;
807 dbuf->buf = kzalloc(HSU_DMA_BUF_SIZE, GFP_KERNEL);
808 if (!dbuf->buf) {
809 up->use_dma = 0;
810 goto exit;
811 }
812 dbuf->dma_addr = dma_map_single(port->dev,
813 dbuf->buf,
814 HSU_DMA_BUF_SIZE,
815 DMA_FROM_DEVICE);
816 dbuf->dma_size = HSU_DMA_BUF_SIZE;
817
818 /* Start the RX channel right now */
819 hsu_dma_start_rx_chan(up->rxc, dbuf);
820
821 /* Next init the TX DMA */
822 dbuf = &up->txbuf;
823 dbuf->buf = xmit->buf;
824 dbuf->dma_addr = dma_map_single(port->dev,
825 dbuf->buf,
826 UART_XMIT_SIZE,
827 DMA_TO_DEVICE);
828 dbuf->dma_size = UART_XMIT_SIZE;
829
830 /* This should not be changed all around */
831 chan_writel(up->txc, HSU_CH_BSR, 32);
832 chan_writel(up->txc, HSU_CH_MOTSR, 4);
833 dbuf->ofs = 0;
834 }
835
836exit:
837 /* And clear the interrupt registers again for luck. */
838 (void) serial_in(up, UART_LSR);
839 (void) serial_in(up, UART_RX);
840 (void) serial_in(up, UART_IIR);
841 (void) serial_in(up, UART_MSR);
842
843 up->running = 1;
844 return 0;
845}
846
847static void serial_hsu_shutdown(struct uart_port *port)
848{
849 struct uart_hsu_port *up =
850 container_of(port, struct uart_hsu_port, port);
851 unsigned long flags;
852
853 /* Disable interrupts from this port */
854 up->ier = 0;
855 serial_out(up, UART_IER, 0);
856 up->running = 0;
857
858 spin_lock_irqsave(&up->port.lock, flags);
859 up->port.mctrl &= ~TIOCM_OUT2;
860 serial_hsu_set_mctrl(&up->port, up->port.mctrl);
861 spin_unlock_irqrestore(&up->port.lock, flags);
862
863 /* Disable break condition and FIFOs */
864 serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
865 serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
866 UART_FCR_CLEAR_RCVR |
867 UART_FCR_CLEAR_XMIT);
868 serial_out(up, UART_FCR, 0);
869}
870
871static void
872serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
873 struct ktermios *old)
874{
875 struct uart_hsu_port *up =
876 container_of(port, struct uart_hsu_port, port);
877 struct tty_struct *tty = port->state->port.tty;
878 unsigned char cval, fcr = 0;
879 unsigned long flags;
880 unsigned int baud, quot;
Feng Tanga5880a92010-11-19 11:01:48 +0800881 u32 ps, mul;
Feng Tangd843fc62010-07-27 08:20:22 +0100882
883 switch (termios->c_cflag & CSIZE) {
884 case CS5:
885 cval = UART_LCR_WLEN5;
886 break;
887 case CS6:
888 cval = UART_LCR_WLEN6;
889 break;
890 case CS7:
891 cval = UART_LCR_WLEN7;
892 break;
893 default:
894 case CS8:
895 cval = UART_LCR_WLEN8;
896 break;
897 }
898
899 /* CMSPAR isn't supported by this driver */
900 if (tty)
901 tty->termios->c_cflag &= ~CMSPAR;
902
903 if (termios->c_cflag & CSTOPB)
904 cval |= UART_LCR_STOP;
905 if (termios->c_cflag & PARENB)
906 cval |= UART_LCR_PARITY;
907 if (!(termios->c_cflag & PARODD))
908 cval |= UART_LCR_EPAR;
909
910 /*
Feng Tange5586ec2010-10-14 17:47:35 +0800911 * The base clk is 50Mhz, and the baud rate come from:
912 * baud = 50M * MUL / (DIV * PS * DLAB)
913 *
Feng Tangd843fc62010-07-27 08:20:22 +0100914 * For those basic low baud rate we can get the direct
Feng Tange5586ec2010-10-14 17:47:35 +0800915 * scalar from 2746800, like 115200 = 2746800/24. For those
916 * higher baud rate, we handle them case by case, mainly by
917 * adjusting the MUL/PS registers, and DIV register is kept
918 * as default value 0x3d09 to make things simple
Feng Tangd843fc62010-07-27 08:20:22 +0100919 */
920 baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
Feng Tangd843fc62010-07-27 08:20:22 +0100921
Feng Tange5586ec2010-10-14 17:47:35 +0800922 quot = 1;
Feng Tanga5880a92010-11-19 11:01:48 +0800923 ps = 0x10;
924 mul = 0x3600;
Feng Tangd843fc62010-07-27 08:20:22 +0100925 switch (baud) {
926 case 3500000:
927 mul = 0x3345;
928 ps = 0xC;
Feng Tange5586ec2010-10-14 17:47:35 +0800929 break;
Feng Tange5586ec2010-10-14 17:47:35 +0800930 case 1843200:
Feng Tangd843fc62010-07-27 08:20:22 +0100931 mul = 0x2400;
Feng Tangd843fc62010-07-27 08:20:22 +0100932 break;
Feng Tanga5880a92010-11-19 11:01:48 +0800933 case 3000000:
934 case 2500000:
935 case 2000000:
Feng Tangd843fc62010-07-27 08:20:22 +0100936 case 1500000:
Feng Tange5586ec2010-10-14 17:47:35 +0800937 case 1000000:
Feng Tange5586ec2010-10-14 17:47:35 +0800938 case 500000:
Feng Tanga5880a92010-11-19 11:01:48 +0800939 /* mul/ps/quot = 0x9C4/0x10/0x1 will make a 500000 bps */
940 mul = baud / 500000 * 0x9C4;
Feng Tangd843fc62010-07-27 08:20:22 +0100941 break;
942 default:
Feng Tange5586ec2010-10-14 17:47:35 +0800943 /* Use uart_get_divisor to get quot for other baud rates */
944 quot = 0;
Feng Tangd843fc62010-07-27 08:20:22 +0100945 }
946
Feng Tange5586ec2010-10-14 17:47:35 +0800947 if (!quot)
948 quot = uart_get_divisor(port, baud);
949
Feng Tangd843fc62010-07-27 08:20:22 +0100950 if ((up->port.uartclk / quot) < (2400 * 16))
951 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
952 else if ((up->port.uartclk / quot) < (230400 * 16))
953 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_16B;
954 else
955 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B;
956
957 fcr |= UART_FCR_HSU_64B_FIFO;
Feng Tangd843fc62010-07-27 08:20:22 +0100958
959 /*
960 * Ok, we're now changing the port state. Do it with
961 * interrupts disabled.
962 */
963 spin_lock_irqsave(&up->port.lock, flags);
964
965 /* Update the per-port timeout */
966 uart_update_timeout(port, termios->c_cflag, baud);
967
968 up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
969 if (termios->c_iflag & INPCK)
970 up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
971 if (termios->c_iflag & (BRKINT | PARMRK))
972 up->port.read_status_mask |= UART_LSR_BI;
973
974 /* Characters to ignore */
975 up->port.ignore_status_mask = 0;
976 if (termios->c_iflag & IGNPAR)
977 up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
978 if (termios->c_iflag & IGNBRK) {
979 up->port.ignore_status_mask |= UART_LSR_BI;
980 /*
981 * If we're ignoring parity and break indicators,
982 * ignore overruns too (for real raw support).
983 */
984 if (termios->c_iflag & IGNPAR)
985 up->port.ignore_status_mask |= UART_LSR_OE;
986 }
987
988 /* Ignore all characters if CREAD is not set */
989 if ((termios->c_cflag & CREAD) == 0)
990 up->port.ignore_status_mask |= UART_LSR_DR;
991
992 /*
993 * CTS flow control flag and modem status interrupts, disable
994 * MSI by default
995 */
996 up->ier &= ~UART_IER_MSI;
997 if (UART_ENABLE_MS(&up->port, termios->c_cflag))
998 up->ier |= UART_IER_MSI;
999
1000 serial_out(up, UART_IER, up->ier);
1001
1002 if (termios->c_cflag & CRTSCTS)
1003 up->mcr |= UART_MCR_AFE | UART_MCR_RTS;
1004 else
1005 up->mcr &= ~UART_MCR_AFE;
1006
1007 serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
1008 serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
1009 serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
1010 serial_out(up, UART_LCR, cval); /* reset DLAB */
1011 serial_out(up, UART_MUL, mul); /* set MUL */
1012 serial_out(up, UART_PS, ps); /* set PS */
1013 up->lcr = cval; /* Save LCR */
1014 serial_hsu_set_mctrl(&up->port, up->port.mctrl);
1015 serial_out(up, UART_FCR, fcr);
1016 spin_unlock_irqrestore(&up->port.lock, flags);
1017}
1018
1019static void
1020serial_hsu_pm(struct uart_port *port, unsigned int state,
1021 unsigned int oldstate)
1022{
1023}
1024
1025static void serial_hsu_release_port(struct uart_port *port)
1026{
1027}
1028
1029static int serial_hsu_request_port(struct uart_port *port)
1030{
1031 return 0;
1032}
1033
1034static void serial_hsu_config_port(struct uart_port *port, int flags)
1035{
Feng Tangd843fc62010-07-27 08:20:22 +01001036 struct uart_hsu_port *up =
1037 container_of(port, struct uart_hsu_port, port);
1038 up->port.type = PORT_MFD;
Feng Tangd843fc62010-07-27 08:20:22 +01001039}
1040
1041static int
1042serial_hsu_verify_port(struct uart_port *port, struct serial_struct *ser)
1043{
1044 /* We don't want the core code to modify any port params */
1045 return -EINVAL;
1046}
1047
1048static const char *
1049serial_hsu_type(struct uart_port *port)
1050{
1051 struct uart_hsu_port *up =
1052 container_of(port, struct uart_hsu_port, port);
1053 return up->name;
1054}
1055
1056/* Mainly for uart console use */
1057static struct uart_hsu_port *serial_hsu_ports[3];
1058static struct uart_driver serial_hsu_reg;
1059
1060#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
1061
1062#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
1063
1064/* Wait for transmitter & holding register to empty */
1065static inline void wait_for_xmitr(struct uart_hsu_port *up)
1066{
1067 unsigned int status, tmout = 1000;
1068
1069 /* Wait up to 1ms for the character to be sent. */
1070 do {
1071 status = serial_in(up, UART_LSR);
1072
1073 if (status & UART_LSR_BI)
1074 up->lsr_break_flag = UART_LSR_BI;
1075
1076 if (--tmout == 0)
1077 break;
1078 udelay(1);
1079 } while (!(status & BOTH_EMPTY));
1080
1081 /* Wait up to 1s for flow control if necessary */
1082 if (up->port.flags & UPF_CONS_FLOW) {
1083 tmout = 1000000;
1084 while (--tmout &&
1085 ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
1086 udelay(1);
1087 }
1088}
1089
1090static void serial_hsu_console_putchar(struct uart_port *port, int ch)
1091{
1092 struct uart_hsu_port *up =
1093 container_of(port, struct uart_hsu_port, port);
1094
1095 wait_for_xmitr(up);
1096 serial_out(up, UART_TX, ch);
1097}
1098
1099/*
1100 * Print a string to the serial port trying not to disturb
1101 * any possible real use of the port...
1102 *
1103 * The console_lock must be held when we get here.
1104 */
1105static void
1106serial_hsu_console_write(struct console *co, const char *s, unsigned int count)
1107{
1108 struct uart_hsu_port *up = serial_hsu_ports[co->index];
1109 unsigned long flags;
1110 unsigned int ier;
1111 int locked = 1;
1112
1113 local_irq_save(flags);
1114 if (up->port.sysrq)
1115 locked = 0;
1116 else if (oops_in_progress) {
1117 locked = spin_trylock(&up->port.lock);
1118 } else
1119 spin_lock(&up->port.lock);
1120
1121 /* First save the IER then disable the interrupts */
1122 ier = serial_in(up, UART_IER);
1123 serial_out(up, UART_IER, 0);
1124
1125 uart_console_write(&up->port, s, count, serial_hsu_console_putchar);
1126
1127 /*
1128 * Finally, wait for transmitter to become empty
1129 * and restore the IER
1130 */
1131 wait_for_xmitr(up);
1132 serial_out(up, UART_IER, ier);
1133
1134 if (locked)
1135 spin_unlock(&up->port.lock);
1136 local_irq_restore(flags);
1137}
1138
1139static struct console serial_hsu_console;
1140
1141static int __init
1142serial_hsu_console_setup(struct console *co, char *options)
1143{
1144 struct uart_hsu_port *up;
1145 int baud = 115200;
1146 int bits = 8;
1147 int parity = 'n';
1148 int flow = 'n';
1149 int ret;
1150
1151 if (co->index == -1 || co->index >= serial_hsu_reg.nr)
1152 co->index = 0;
1153 up = serial_hsu_ports[co->index];
1154 if (!up)
1155 return -ENODEV;
1156
1157 if (options)
1158 uart_parse_options(options, &baud, &parity, &bits, &flow);
1159
1160 ret = uart_set_options(&up->port, co, baud, parity, bits, flow);
1161
1162 return ret;
1163}
1164
1165static struct console serial_hsu_console = {
1166 .name = "ttyMFD",
1167 .write = serial_hsu_console_write,
1168 .device = uart_console_device,
1169 .setup = serial_hsu_console_setup,
1170 .flags = CON_PRINTBUFFER,
1171 .index = 2,
1172 .data = &serial_hsu_reg,
1173};
1174#endif
1175
1176struct uart_ops serial_hsu_pops = {
1177 .tx_empty = serial_hsu_tx_empty,
1178 .set_mctrl = serial_hsu_set_mctrl,
1179 .get_mctrl = serial_hsu_get_mctrl,
1180 .stop_tx = serial_hsu_stop_tx,
1181 .start_tx = serial_hsu_start_tx,
1182 .stop_rx = serial_hsu_stop_rx,
1183 .enable_ms = serial_hsu_enable_ms,
1184 .break_ctl = serial_hsu_break_ctl,
1185 .startup = serial_hsu_startup,
1186 .shutdown = serial_hsu_shutdown,
1187 .set_termios = serial_hsu_set_termios,
1188 .pm = serial_hsu_pm,
1189 .type = serial_hsu_type,
1190 .release_port = serial_hsu_release_port,
1191 .request_port = serial_hsu_request_port,
1192 .config_port = serial_hsu_config_port,
1193 .verify_port = serial_hsu_verify_port,
1194};
1195
1196static struct uart_driver serial_hsu_reg = {
1197 .owner = THIS_MODULE,
1198 .driver_name = "MFD serial",
1199 .dev_name = "ttyMFD",
1200 .major = TTY_MAJOR,
1201 .minor = 128,
1202 .nr = 3,
1203};
1204
1205#ifdef CONFIG_PM
1206static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state)
1207{
Feng Tang3c4108c2010-07-27 08:20:52 +01001208 void *priv = pci_get_drvdata(pdev);
Feng Tangd843fc62010-07-27 08:20:22 +01001209 struct uart_hsu_port *up;
1210
Feng Tang3c4108c2010-07-27 08:20:52 +01001211 /* Make sure this is not the internal dma controller */
1212 if (priv && (pdev->device != 0x081E)) {
1213 up = priv;
1214 uart_suspend_port(&serial_hsu_reg, &up->port);
1215 }
Feng Tangd843fc62010-07-27 08:20:22 +01001216
Feng Tang3c4108c2010-07-27 08:20:52 +01001217 pci_save_state(pdev);
1218 pci_set_power_state(pdev, pci_choose_state(pdev, state));
Feng Tangd843fc62010-07-27 08:20:22 +01001219 return 0;
1220}
1221
1222static int serial_hsu_resume(struct pci_dev *pdev)
1223{
Feng Tang3c4108c2010-07-27 08:20:52 +01001224 void *priv = pci_get_drvdata(pdev);
Feng Tangd843fc62010-07-27 08:20:22 +01001225 struct uart_hsu_port *up;
Feng Tang3c4108c2010-07-27 08:20:52 +01001226 int ret;
Feng Tangd843fc62010-07-27 08:20:22 +01001227
Feng Tang3c4108c2010-07-27 08:20:52 +01001228 pci_set_power_state(pdev, PCI_D0);
1229 pci_restore_state(pdev);
1230
1231 ret = pci_enable_device(pdev);
1232 if (ret)
1233 dev_warn(&pdev->dev,
1234 "HSU: can't re-enable device, try to continue\n");
1235
1236 if (priv && (pdev->device != 0x081E)) {
1237 up = priv;
1238 uart_resume_port(&serial_hsu_reg, &up->port);
1239 }
Feng Tangd843fc62010-07-27 08:20:22 +01001240 return 0;
1241}
1242#else
1243#define serial_hsu_suspend NULL
1244#define serial_hsu_resume NULL
1245#endif
1246
1247/* temp global pointer before we settle down on using one or four PCI dev */
1248static struct hsu_port *phsu;
1249
1250static int serial_hsu_probe(struct pci_dev *pdev,
1251 const struct pci_device_id *ent)
1252{
1253 struct uart_hsu_port *uport;
1254 int index, ret;
1255
1256 printk(KERN_INFO "HSU: found PCI Serial controller(ID: %04x:%04x)\n",
1257 pdev->vendor, pdev->device);
1258
1259 switch (pdev->device) {
1260 case 0x081B:
1261 index = 0;
1262 break;
1263 case 0x081C:
1264 index = 1;
1265 break;
1266 case 0x081D:
1267 index = 2;
1268 break;
1269 case 0x081E:
1270 /* internal DMA controller */
1271 index = 3;
1272 break;
1273 default:
1274 dev_err(&pdev->dev, "HSU: out of index!");
1275 return -ENODEV;
1276 }
1277
1278 ret = pci_enable_device(pdev);
1279 if (ret)
1280 return ret;
1281
1282 if (index == 3) {
1283 /* DMA controller */
1284 ret = request_irq(pdev->irq, dma_irq, 0, "hsu_dma", phsu);
1285 if (ret) {
1286 dev_err(&pdev->dev, "can not get IRQ\n");
1287 goto err_disable;
1288 }
1289 pci_set_drvdata(pdev, phsu);
1290 } else {
1291 /* UART port 0~2 */
1292 uport = &phsu->port[index];
1293 uport->port.irq = pdev->irq;
1294 uport->port.dev = &pdev->dev;
1295 uport->dev = &pdev->dev;
1296
1297 ret = request_irq(pdev->irq, port_irq, 0, uport->name, uport);
1298 if (ret) {
1299 dev_err(&pdev->dev, "can not get IRQ\n");
1300 goto err_disable;
1301 }
1302 uart_add_one_port(&serial_hsu_reg, &uport->port);
1303
1304#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
1305 if (index == 2) {
1306 register_console(&serial_hsu_console);
1307 uport->port.cons = &serial_hsu_console;
1308 }
1309#endif
1310 pci_set_drvdata(pdev, uport);
1311 }
1312
1313 return 0;
1314
1315err_disable:
1316 pci_disable_device(pdev);
1317 return ret;
1318}
1319
1320static void hsu_global_init(void)
1321{
1322 struct hsu_port *hsu;
1323 struct uart_hsu_port *uport;
1324 struct hsu_dma_chan *dchan;
1325 int i, ret;
1326
1327 hsu = kzalloc(sizeof(struct hsu_port), GFP_KERNEL);
1328 if (!hsu)
1329 return;
1330
1331 /* Get basic io resource and map it */
1332 hsu->paddr = 0xffa28000;
1333 hsu->iolen = 0x1000;
1334
1335 if (!(request_mem_region(hsu->paddr, hsu->iolen, "HSU global")))
1336 pr_warning("HSU: error in request mem region\n");
1337
1338 hsu->reg = ioremap_nocache((unsigned long)hsu->paddr, hsu->iolen);
1339 if (!hsu->reg) {
1340 pr_err("HSU: error in ioremap\n");
1341 ret = -ENOMEM;
1342 goto err_free_region;
1343 }
1344
1345 /* Initialise the 3 UART ports */
1346 uport = hsu->port;
1347 for (i = 0; i < 3; i++) {
1348 uport->port.type = PORT_MFD;
1349 uport->port.iotype = UPIO_MEM;
1350 uport->port.mapbase = (resource_size_t)hsu->paddr
1351 + HSU_PORT_REG_OFFSET
1352 + i * HSU_PORT_REG_LENGTH;
1353 uport->port.membase = hsu->reg + HSU_PORT_REG_OFFSET
1354 + i * HSU_PORT_REG_LENGTH;
1355
1356 sprintf(uport->name, "hsu_port%d", i);
1357 uport->port.fifosize = 64;
1358 uport->port.ops = &serial_hsu_pops;
1359 uport->port.line = i;
1360 uport->port.flags = UPF_IOREMAP;
Feng Tang06c77e22010-07-27 08:20:42 +01001361 /* set the scalable maxim support rate to 2746800 bps */
Feng Tangd843fc62010-07-27 08:20:22 +01001362 uport->port.uartclk = 115200 * 24 * 16;
1363
1364 uport->running = 0;
1365 uport->txc = &hsu->chans[i * 2];
1366 uport->rxc = &hsu->chans[i * 2 + 1];
1367
1368 serial_hsu_ports[i] = uport;
1369 uport->index = i;
1370 uport++;
1371 }
1372
1373 /* Initialise 6 dma channels */
1374 dchan = hsu->chans;
1375 for (i = 0; i < 6; i++) {
1376 dchan->id = i;
1377 dchan->dirt = (i & 0x1) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
1378 dchan->uport = &hsu->port[i/2];
1379 dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET +
1380 i * HSU_DMA_CHANS_REG_LENGTH;
Feng Tang669b7a02010-07-27 08:20:32 +01001381
Feng Tangd843fc62010-07-27 08:20:22 +01001382 dchan++;
1383 }
1384
1385 phsu = hsu;
Feng Tangd843fc62010-07-27 08:20:22 +01001386 hsu_debugfs_init(hsu);
1387 return;
1388
1389err_free_region:
1390 release_mem_region(hsu->paddr, hsu->iolen);
1391 kfree(hsu);
1392 return;
1393}
1394
1395static void serial_hsu_remove(struct pci_dev *pdev)
1396{
Feng Tange3671ac2010-09-06 13:41:02 +01001397 void *priv = pci_get_drvdata(pdev);
1398 struct uart_hsu_port *up;
Feng Tangd843fc62010-07-27 08:20:22 +01001399
Feng Tange3671ac2010-09-06 13:41:02 +01001400 if (!priv)
Feng Tangd843fc62010-07-27 08:20:22 +01001401 return;
1402
Feng Tange3671ac2010-09-06 13:41:02 +01001403 /* For port 0/1/2, priv is the address of uart_hsu_port */
1404 if (pdev->device != 0x081E) {
1405 up = priv;
1406 uart_remove_one_port(&serial_hsu_reg, &up->port);
1407 }
Feng Tangd843fc62010-07-27 08:20:22 +01001408
1409 pci_set_drvdata(pdev, NULL);
Feng Tange3671ac2010-09-06 13:41:02 +01001410 free_irq(pdev->irq, priv);
Feng Tangd843fc62010-07-27 08:20:22 +01001411 pci_disable_device(pdev);
1412}
1413
1414/* First 3 are UART ports, and the 4th is the DMA */
1415static const struct pci_device_id pci_ids[] __devinitdata = {
1416 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) },
1417 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) },
1418 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) },
1419 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081E) },
1420 {},
1421};
1422
1423static struct pci_driver hsu_pci_driver = {
1424 .name = "HSU serial",
1425 .id_table = pci_ids,
1426 .probe = serial_hsu_probe,
1427 .remove = __devexit_p(serial_hsu_remove),
1428 .suspend = serial_hsu_suspend,
1429 .resume = serial_hsu_resume,
1430};
1431
1432static int __init hsu_pci_init(void)
1433{
1434 int ret;
1435
1436 hsu_global_init();
1437
1438 ret = uart_register_driver(&serial_hsu_reg);
1439 if (ret)
1440 return ret;
1441
1442 return pci_register_driver(&hsu_pci_driver);
1443}
1444
1445static void __exit hsu_pci_exit(void)
1446{
1447 pci_unregister_driver(&hsu_pci_driver);
1448 uart_unregister_driver(&serial_hsu_reg);
1449
1450 hsu_debugfs_remove(phsu);
1451
1452 kfree(phsu);
1453}
1454
1455module_init(hsu_pci_init);
1456module_exit(hsu_pci_exit);
1457
1458MODULE_LICENSE("GPL v2");
1459MODULE_ALIAS("platform:medfield-hsu");