diff options
Diffstat (limited to 'drivers/serial/amba-pl010.c')
-rw-r--r-- | drivers/serial/amba-pl010.c | 270 |
1 files changed, 116 insertions, 154 deletions
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index e04d5e82d9ae..1631414000a2 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
@@ -51,8 +51,6 @@ | |||
51 | #include <linux/amba/serial.h> | 51 | #include <linux/amba/serial.h> |
52 | 52 | ||
53 | #include <asm/io.h> | 53 | #include <asm/io.h> |
54 | #include <asm/irq.h> | ||
55 | #include <asm/hardware.h> | ||
56 | 54 | ||
57 | #define UART_NR 2 | 55 | #define UART_NR 2 |
58 | 56 | ||
@@ -62,47 +60,19 @@ | |||
62 | 60 | ||
63 | #define AMBA_ISR_PASS_LIMIT 256 | 61 | #define AMBA_ISR_PASS_LIMIT 256 |
64 | 62 | ||
65 | /* | ||
66 | * Access macros for the AMBA UARTs | ||
67 | */ | ||
68 | #define UART_GET_INT_STATUS(p) readb((p)->membase + UART010_IIR) | ||
69 | #define UART_PUT_ICR(p, c) writel((c), (p)->membase + UART010_ICR) | ||
70 | #define UART_GET_FR(p) readb((p)->membase + UART01x_FR) | ||
71 | #define UART_GET_CHAR(p) readb((p)->membase + UART01x_DR) | ||
72 | #define UART_PUT_CHAR(p, c) writel((c), (p)->membase + UART01x_DR) | ||
73 | #define UART_GET_RSR(p) readb((p)->membase + UART01x_RSR) | ||
74 | #define UART_GET_CR(p) readb((p)->membase + UART010_CR) | ||
75 | #define UART_PUT_CR(p,c) writel((c), (p)->membase + UART010_CR) | ||
76 | #define UART_GET_LCRL(p) readb((p)->membase + UART010_LCRL) | ||
77 | #define UART_PUT_LCRL(p,c) writel((c), (p)->membase + UART010_LCRL) | ||
78 | #define UART_GET_LCRM(p) readb((p)->membase + UART010_LCRM) | ||
79 | #define UART_PUT_LCRM(p,c) writel((c), (p)->membase + UART010_LCRM) | ||
80 | #define UART_GET_LCRH(p) readb((p)->membase + UART010_LCRH) | ||
81 | #define UART_PUT_LCRH(p,c) writel((c), (p)->membase + UART010_LCRH) | ||
82 | #define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0) | 63 | #define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0) |
83 | #define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0) | 64 | #define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0) |
84 | #define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART01x_FR_TMSK) == 0) | ||
85 | 65 | ||
86 | #define UART_DUMMY_RSR_RX /*256*/0 | 66 | #define UART_DUMMY_RSR_RX 256 |
87 | #define UART_PORT_SIZE 64 | 67 | #define UART_PORT_SIZE 64 |
88 | 68 | ||
89 | /* | 69 | /* |
90 | * On the Integrator platform, the port RTS and DTR are provided by | ||
91 | * bits in the following SC_CTRLS register bits: | ||
92 | * RTS DTR | ||
93 | * UART0 7 6 | ||
94 | * UART1 5 4 | ||
95 | */ | ||
96 | #define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) | ||
97 | #define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) | ||
98 | |||
99 | /* | ||
100 | * We wrap our port structure around the generic uart_port. | 70 | * We wrap our port structure around the generic uart_port. |
101 | */ | 71 | */ |
102 | struct uart_amba_port { | 72 | struct uart_amba_port { |
103 | struct uart_port port; | 73 | struct uart_port port; |
104 | unsigned int dtr_mask; | 74 | struct amba_device *dev; |
105 | unsigned int rts_mask; | 75 | struct amba_pl010_data *data; |
106 | unsigned int old_status; | 76 | unsigned int old_status; |
107 | }; | 77 | }; |
108 | 78 | ||
@@ -110,36 +80,36 @@ static void pl010_stop_tx(struct uart_port *port) | |||
110 | { | 80 | { |
111 | unsigned int cr; | 81 | unsigned int cr; |
112 | 82 | ||
113 | cr = UART_GET_CR(port); | 83 | cr = readb(port->membase + UART010_CR); |
114 | cr &= ~UART010_CR_TIE; | 84 | cr &= ~UART010_CR_TIE; |
115 | UART_PUT_CR(port, cr); | 85 | writel(cr, port->membase + UART010_CR); |
116 | } | 86 | } |
117 | 87 | ||
118 | static void pl010_start_tx(struct uart_port *port) | 88 | static void pl010_start_tx(struct uart_port *port) |
119 | { | 89 | { |
120 | unsigned int cr; | 90 | unsigned int cr; |
121 | 91 | ||
122 | cr = UART_GET_CR(port); | 92 | cr = readb(port->membase + UART010_CR); |
123 | cr |= UART010_CR_TIE; | 93 | cr |= UART010_CR_TIE; |
124 | UART_PUT_CR(port, cr); | 94 | writel(cr, port->membase + UART010_CR); |
125 | } | 95 | } |
126 | 96 | ||
127 | static void pl010_stop_rx(struct uart_port *port) | 97 | static void pl010_stop_rx(struct uart_port *port) |
128 | { | 98 | { |
129 | unsigned int cr; | 99 | unsigned int cr; |
130 | 100 | ||
131 | cr = UART_GET_CR(port); | 101 | cr = readb(port->membase + UART010_CR); |
132 | cr &= ~(UART010_CR_RIE | UART010_CR_RTIE); | 102 | cr &= ~(UART010_CR_RIE | UART010_CR_RTIE); |
133 | UART_PUT_CR(port, cr); | 103 | writel(cr, port->membase + UART010_CR); |
134 | } | 104 | } |
135 | 105 | ||
136 | static void pl010_enable_ms(struct uart_port *port) | 106 | static void pl010_enable_ms(struct uart_port *port) |
137 | { | 107 | { |
138 | unsigned int cr; | 108 | unsigned int cr; |
139 | 109 | ||
140 | cr = UART_GET_CR(port); | 110 | cr = readb(port->membase + UART010_CR); |
141 | cr |= UART010_CR_MSIE; | 111 | cr |= UART010_CR_MSIE; |
142 | UART_PUT_CR(port, cr); | 112 | writel(cr, port->membase + UART010_CR); |
143 | } | 113 | } |
144 | 114 | ||
145 | static void | 115 | static void |
@@ -152,9 +122,9 @@ pl010_rx_chars(struct uart_port *port) | |||
152 | struct tty_struct *tty = port->info->tty; | 122 | struct tty_struct *tty = port->info->tty; |
153 | unsigned int status, ch, flag, rsr, max_count = 256; | 123 | unsigned int status, ch, flag, rsr, max_count = 256; |
154 | 124 | ||
155 | status = UART_GET_FR(port); | 125 | status = readb(port->membase + UART01x_FR); |
156 | while (UART_RX_DATA(status) && max_count--) { | 126 | while (UART_RX_DATA(status) && max_count--) { |
157 | ch = UART_GET_CHAR(port); | 127 | ch = readb(port->membase + UART01x_DR); |
158 | flag = TTY_NORMAL; | 128 | flag = TTY_NORMAL; |
159 | 129 | ||
160 | port->icount.rx++; | 130 | port->icount.rx++; |
@@ -163,7 +133,7 @@ pl010_rx_chars(struct uart_port *port) | |||
163 | * Note that the error handling code is | 133 | * Note that the error handling code is |
164 | * out of the main execution path | 134 | * out of the main execution path |
165 | */ | 135 | */ |
166 | rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX; | 136 | rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX; |
167 | if (unlikely(rsr & UART01x_RSR_ANY)) { | 137 | if (unlikely(rsr & UART01x_RSR_ANY)) { |
168 | if (rsr & UART01x_RSR_BE) { | 138 | if (rsr & UART01x_RSR_BE) { |
169 | rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); | 139 | rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); |
@@ -193,7 +163,7 @@ pl010_rx_chars(struct uart_port *port) | |||
193 | uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); | 163 | uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); |
194 | 164 | ||
195 | ignore_char: | 165 | ignore_char: |
196 | status = UART_GET_FR(port); | 166 | status = readb(port->membase + UART01x_FR); |
197 | } | 167 | } |
198 | tty_flip_buffer_push(tty); | 168 | tty_flip_buffer_push(tty); |
199 | return; | 169 | return; |
@@ -205,7 +175,7 @@ static void pl010_tx_chars(struct uart_port *port) | |||
205 | int count; | 175 | int count; |
206 | 176 | ||
207 | if (port->x_char) { | 177 | if (port->x_char) { |
208 | UART_PUT_CHAR(port, port->x_char); | 178 | writel(port->x_char, port->membase + UART01x_DR); |
209 | port->icount.tx++; | 179 | port->icount.tx++; |
210 | port->x_char = 0; | 180 | port->x_char = 0; |
211 | return; | 181 | return; |
@@ -217,7 +187,7 @@ static void pl010_tx_chars(struct uart_port *port) | |||
217 | 187 | ||
218 | count = port->fifosize >> 1; | 188 | count = port->fifosize >> 1; |
219 | do { | 189 | do { |
220 | UART_PUT_CHAR(port, xmit->buf[xmit->tail]); | 190 | writel(xmit->buf[xmit->tail], port->membase + UART01x_DR); |
221 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 191 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
222 | port->icount.tx++; | 192 | port->icount.tx++; |
223 | if (uart_circ_empty(xmit)) | 193 | if (uart_circ_empty(xmit)) |
@@ -236,9 +206,9 @@ static void pl010_modem_status(struct uart_port *port) | |||
236 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 206 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
237 | unsigned int status, delta; | 207 | unsigned int status, delta; |
238 | 208 | ||
239 | UART_PUT_ICR(&uap->port, 0); | 209 | writel(0, uap->port.membase + UART010_ICR); |
240 | 210 | ||
241 | status = UART_GET_FR(&uap->port) & UART01x_FR_MODEM_ANY; | 211 | status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; |
242 | 212 | ||
243 | delta = status ^ uap->old_status; | 213 | delta = status ^ uap->old_status; |
244 | uap->old_status = status; | 214 | uap->old_status = status; |
@@ -266,7 +236,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) | |||
266 | 236 | ||
267 | spin_lock(&port->lock); | 237 | spin_lock(&port->lock); |
268 | 238 | ||
269 | status = UART_GET_INT_STATUS(port); | 239 | status = readb(port->membase + UART010_IIR); |
270 | if (status) { | 240 | if (status) { |
271 | do { | 241 | do { |
272 | if (status & (UART010_IIR_RTIS | UART010_IIR_RIS)) | 242 | if (status & (UART010_IIR_RTIS | UART010_IIR_RIS)) |
@@ -283,7 +253,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) | |||
283 | if (pass_counter-- == 0) | 253 | if (pass_counter-- == 0) |
284 | break; | 254 | break; |
285 | 255 | ||
286 | status = UART_GET_INT_STATUS(port); | 256 | status = readb(port->membase + UART010_IIR); |
287 | } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS | | 257 | } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS | |
288 | UART010_IIR_TIS)); | 258 | UART010_IIR_TIS)); |
289 | handled = 1; | 259 | handled = 1; |
@@ -296,7 +266,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) | |||
296 | 266 | ||
297 | static unsigned int pl010_tx_empty(struct uart_port *port) | 267 | static unsigned int pl010_tx_empty(struct uart_port *port) |
298 | { | 268 | { |
299 | return UART_GET_FR(port) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; | 269 | return readb(port->membase + UART01x_FR) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; |
300 | } | 270 | } |
301 | 271 | ||
302 | static unsigned int pl010_get_mctrl(struct uart_port *port) | 272 | static unsigned int pl010_get_mctrl(struct uart_port *port) |
@@ -304,7 +274,7 @@ static unsigned int pl010_get_mctrl(struct uart_port *port) | |||
304 | unsigned int result = 0; | 274 | unsigned int result = 0; |
305 | unsigned int status; | 275 | unsigned int status; |
306 | 276 | ||
307 | status = UART_GET_FR(port); | 277 | status = readb(port->membase + UART01x_FR); |
308 | if (status & UART01x_FR_DCD) | 278 | if (status & UART01x_FR_DCD) |
309 | result |= TIOCM_CAR; | 279 | result |= TIOCM_CAR; |
310 | if (status & UART01x_FR_DSR) | 280 | if (status & UART01x_FR_DSR) |
@@ -318,20 +288,9 @@ static unsigned int pl010_get_mctrl(struct uart_port *port) | |||
318 | static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl) | 288 | static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl) |
319 | { | 289 | { |
320 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 290 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
321 | unsigned int ctrls = 0, ctrlc = 0; | ||
322 | |||
323 | if (mctrl & TIOCM_RTS) | ||
324 | ctrlc |= uap->rts_mask; | ||
325 | else | ||
326 | ctrls |= uap->rts_mask; | ||
327 | |||
328 | if (mctrl & TIOCM_DTR) | ||
329 | ctrlc |= uap->dtr_mask; | ||
330 | else | ||
331 | ctrls |= uap->dtr_mask; | ||
332 | 291 | ||
333 | __raw_writel(ctrls, SC_CTRLS); | 292 | if (uap->data) |
334 | __raw_writel(ctrlc, SC_CTRLC); | 293 | uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl); |
335 | } | 294 | } |
336 | 295 | ||
337 | static void pl010_break_ctl(struct uart_port *port, int break_state) | 296 | static void pl010_break_ctl(struct uart_port *port, int break_state) |
@@ -340,12 +299,12 @@ static void pl010_break_ctl(struct uart_port *port, int break_state) | |||
340 | unsigned int lcr_h; | 299 | unsigned int lcr_h; |
341 | 300 | ||
342 | spin_lock_irqsave(&port->lock, flags); | 301 | spin_lock_irqsave(&port->lock, flags); |
343 | lcr_h = UART_GET_LCRH(port); | 302 | lcr_h = readb(port->membase + UART010_LCRH); |
344 | if (break_state == -1) | 303 | if (break_state == -1) |
345 | lcr_h |= UART01x_LCRH_BRK; | 304 | lcr_h |= UART01x_LCRH_BRK; |
346 | else | 305 | else |
347 | lcr_h &= ~UART01x_LCRH_BRK; | 306 | lcr_h &= ~UART01x_LCRH_BRK; |
348 | UART_PUT_LCRH(port, lcr_h); | 307 | writel(lcr_h, port->membase + UART010_LCRH); |
349 | spin_unlock_irqrestore(&port->lock, flags); | 308 | spin_unlock_irqrestore(&port->lock, flags); |
350 | } | 309 | } |
351 | 310 | ||
@@ -364,13 +323,13 @@ static int pl010_startup(struct uart_port *port) | |||
364 | /* | 323 | /* |
365 | * initialise the old status of the modem signals | 324 | * initialise the old status of the modem signals |
366 | */ | 325 | */ |
367 | uap->old_status = UART_GET_FR(port) & UART01x_FR_MODEM_ANY; | 326 | uap->old_status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY; |
368 | 327 | ||
369 | /* | 328 | /* |
370 | * Finally, enable interrupts | 329 | * Finally, enable interrupts |
371 | */ | 330 | */ |
372 | UART_PUT_CR(port, UART01x_CR_UARTEN | UART010_CR_RIE | | 331 | writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE, |
373 | UART010_CR_RTIE); | 332 | port->membase + UART010_CR); |
374 | 333 | ||
375 | return 0; | 334 | return 0; |
376 | } | 335 | } |
@@ -385,11 +344,12 @@ static void pl010_shutdown(struct uart_port *port) | |||
385 | /* | 344 | /* |
386 | * disable all interrupts, disable the port | 345 | * disable all interrupts, disable the port |
387 | */ | 346 | */ |
388 | UART_PUT_CR(port, 0); | 347 | writel(0, port->membase + UART010_CR); |
389 | 348 | ||
390 | /* disable break condition and fifos */ | 349 | /* disable break condition and fifos */ |
391 | UART_PUT_LCRH(port, UART_GET_LCRH(port) & | 350 | writel(readb(port->membase + UART010_LCRH) & |
392 | ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN)); | 351 | ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN), |
352 | port->membase + UART010_LCRH); | ||
393 | } | 353 | } |
394 | 354 | ||
395 | static void | 355 | static void |
@@ -466,25 +426,25 @@ pl010_set_termios(struct uart_port *port, struct termios *termios, | |||
466 | port->ignore_status_mask |= UART_DUMMY_RSR_RX; | 426 | port->ignore_status_mask |= UART_DUMMY_RSR_RX; |
467 | 427 | ||
468 | /* first, disable everything */ | 428 | /* first, disable everything */ |
469 | old_cr = UART_GET_CR(port) & ~UART010_CR_MSIE; | 429 | old_cr = readb(port->membase + UART010_CR) & ~UART010_CR_MSIE; |
470 | 430 | ||
471 | if (UART_ENABLE_MS(port, termios->c_cflag)) | 431 | if (UART_ENABLE_MS(port, termios->c_cflag)) |
472 | old_cr |= UART010_CR_MSIE; | 432 | old_cr |= UART010_CR_MSIE; |
473 | 433 | ||
474 | UART_PUT_CR(port, 0); | 434 | writel(0, port->membase + UART010_CR); |
475 | 435 | ||
476 | /* Set baud rate */ | 436 | /* Set baud rate */ |
477 | quot -= 1; | 437 | quot -= 1; |
478 | UART_PUT_LCRM(port, ((quot & 0xf00) >> 8)); | 438 | writel((quot & 0xf00) >> 8, port->membase + UART010_LCRM); |
479 | UART_PUT_LCRL(port, (quot & 0xff)); | 439 | writel(quot & 0xff, port->membase + UART010_LCRL); |
480 | 440 | ||
481 | /* | 441 | /* |
482 | * ----------v----------v----------v----------v----- | 442 | * ----------v----------v----------v----------v----- |
483 | * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L | 443 | * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L |
484 | * ----------^----------^----------^----------^----- | 444 | * ----------^----------^----------^----------^----- |
485 | */ | 445 | */ |
486 | UART_PUT_LCRH(port, lcr_h); | 446 | writel(lcr_h, port->membase + UART010_LCRH); |
487 | UART_PUT_CR(port, old_cr); | 447 | writel(old_cr, port->membase + UART010_CR); |
488 | 448 | ||
489 | spin_unlock_irqrestore(&port->lock, flags); | 449 | spin_unlock_irqrestore(&port->lock, flags); |
490 | } | 450 | } |
@@ -556,59 +516,32 @@ static struct uart_ops amba_pl010_pops = { | |||
556 | .verify_port = pl010_verify_port, | 516 | .verify_port = pl010_verify_port, |
557 | }; | 517 | }; |
558 | 518 | ||
559 | static struct uart_amba_port amba_ports[UART_NR] = { | 519 | static struct uart_amba_port *amba_ports[UART_NR]; |
560 | { | ||
561 | .port = { | ||
562 | .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), | ||
563 | .mapbase = INTEGRATOR_UART0_BASE, | ||
564 | .iotype = UPIO_MEM, | ||
565 | .irq = IRQ_UARTINT0, | ||
566 | .uartclk = 14745600, | ||
567 | .fifosize = 16, | ||
568 | .ops = &amba_pl010_pops, | ||
569 | .flags = UPF_BOOT_AUTOCONF, | ||
570 | .line = 0, | ||
571 | }, | ||
572 | .dtr_mask = 1 << 5, | ||
573 | .rts_mask = 1 << 4, | ||
574 | }, | ||
575 | { | ||
576 | .port = { | ||
577 | .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), | ||
578 | .mapbase = INTEGRATOR_UART1_BASE, | ||
579 | .iotype = UPIO_MEM, | ||
580 | .irq = IRQ_UARTINT1, | ||
581 | .uartclk = 14745600, | ||
582 | .fifosize = 16, | ||
583 | .ops = &amba_pl010_pops, | ||
584 | .flags = UPF_BOOT_AUTOCONF, | ||
585 | .line = 1, | ||
586 | }, | ||
587 | .dtr_mask = 1 << 7, | ||
588 | .rts_mask = 1 << 6, | ||
589 | } | ||
590 | }; | ||
591 | 520 | ||
592 | #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE | 521 | #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE |
593 | 522 | ||
594 | static void pl010_console_putchar(struct uart_port *port, int ch) | 523 | static void pl010_console_putchar(struct uart_port *port, int ch) |
595 | { | 524 | { |
596 | while (!UART_TX_READY(UART_GET_FR(port))) | 525 | unsigned int status; |
526 | |||
527 | do { | ||
528 | status = readb(port->membase + UART01x_FR); | ||
597 | barrier(); | 529 | barrier(); |
598 | UART_PUT_CHAR(port, ch); | 530 | } while (!UART_TX_READY(status)); |
531 | writel(ch, port->membase + UART01x_DR); | ||
599 | } | 532 | } |
600 | 533 | ||
601 | static void | 534 | static void |
602 | pl010_console_write(struct console *co, const char *s, unsigned int count) | 535 | pl010_console_write(struct console *co, const char *s, unsigned int count) |
603 | { | 536 | { |
604 | struct uart_port *port = &amba_ports[co->index].port; | 537 | struct uart_port *port = &amba_ports[co->index]->port; |
605 | unsigned int status, old_cr; | 538 | unsigned int status, old_cr; |
606 | 539 | ||
607 | /* | 540 | /* |
608 | * First save the CR then disable the interrupts | 541 | * First save the CR then disable the interrupts |
609 | */ | 542 | */ |
610 | old_cr = UART_GET_CR(port); | 543 | old_cr = readb(port->membase + UART010_CR); |
611 | UART_PUT_CR(port, UART01x_CR_UARTEN); | 544 | writel(UART01x_CR_UARTEN, port->membase + UART010_CR); |
612 | 545 | ||
613 | uart_console_write(port, s, count, pl010_console_putchar); | 546 | uart_console_write(port, s, count, pl010_console_putchar); |
614 | 547 | ||
@@ -617,18 +550,19 @@ pl010_console_write(struct console *co, const char *s, unsigned int count) | |||
617 | * and restore the TCR | 550 | * and restore the TCR |
618 | */ | 551 | */ |
619 | do { | 552 | do { |
620 | status = UART_GET_FR(port); | 553 | status = readb(port->membase + UART01x_FR); |
554 | barrier(); | ||
621 | } while (status & UART01x_FR_BUSY); | 555 | } while (status & UART01x_FR_BUSY); |
622 | UART_PUT_CR(port, old_cr); | 556 | writel(old_cr, port->membase + UART010_CR); |
623 | } | 557 | } |
624 | 558 | ||
625 | static void __init | 559 | static void __init |
626 | pl010_console_get_options(struct uart_port *port, int *baud, | 560 | pl010_console_get_options(struct uart_port *port, int *baud, |
627 | int *parity, int *bits) | 561 | int *parity, int *bits) |
628 | { | 562 | { |
629 | if (UART_GET_CR(port) & UART01x_CR_UARTEN) { | 563 | if (readb(port->membase + UART010_CR) & UART01x_CR_UARTEN) { |
630 | unsigned int lcr_h, quot; | 564 | unsigned int lcr_h, quot; |
631 | lcr_h = UART_GET_LCRH(port); | 565 | lcr_h = readb(port->membase + UART010_LCRH); |
632 | 566 | ||
633 | *parity = 'n'; | 567 | *parity = 'n'; |
634 | if (lcr_h & UART01x_LCRH_PEN) { | 568 | if (lcr_h & UART01x_LCRH_PEN) { |
@@ -643,7 +577,7 @@ pl010_console_get_options(struct uart_port *port, int *baud, | |||
643 | else | 577 | else |
644 | *bits = 8; | 578 | *bits = 8; |
645 | 579 | ||
646 | quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8; | 580 | quot = readb(port->membase + UART010_LCRL) | readb(port->membase + UART010_LCRM) << 8; |
647 | *baud = port->uartclk / (16 * (quot + 1)); | 581 | *baud = port->uartclk / (16 * (quot + 1)); |
648 | } | 582 | } |
649 | } | 583 | } |
@@ -663,7 +597,7 @@ static int __init pl010_console_setup(struct console *co, char *options) | |||
663 | */ | 597 | */ |
664 | if (co->index >= UART_NR) | 598 | if (co->index >= UART_NR) |
665 | co->index = 0; | 599 | co->index = 0; |
666 | port = &amba_ports[co->index].port; | 600 | port = &amba_ports[co->index]->port; |
667 | 601 | ||
668 | if (options) | 602 | if (options) |
669 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 603 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
@@ -684,24 +618,6 @@ static struct console amba_console = { | |||
684 | .data = &amba_reg, | 618 | .data = &amba_reg, |
685 | }; | 619 | }; |
686 | 620 | ||
687 | static int __init amba_console_init(void) | ||
688 | { | ||
689 | /* | ||
690 | * All port initializations are done statically | ||
691 | */ | ||
692 | register_console(&amba_console); | ||
693 | return 0; | ||
694 | } | ||
695 | console_initcall(amba_console_init); | ||
696 | |||
697 | static int __init amba_late_console_init(void) | ||
698 | { | ||
699 | if (!(amba_console.flags & CON_ENABLED)) | ||
700 | register_console(&amba_console); | ||
701 | return 0; | ||
702 | } | ||
703 | late_initcall(amba_late_console_init); | ||
704 | |||
705 | #define AMBA_CONSOLE &amba_console | 621 | #define AMBA_CONSOLE &amba_console |
706 | #else | 622 | #else |
707 | #define AMBA_CONSOLE NULL | 623 | #define AMBA_CONSOLE NULL |
@@ -719,30 +635,76 @@ static struct uart_driver amba_reg = { | |||
719 | 635 | ||
720 | static int pl010_probe(struct amba_device *dev, void *id) | 636 | static int pl010_probe(struct amba_device *dev, void *id) |
721 | { | 637 | { |
722 | int i; | 638 | struct uart_amba_port *port; |
639 | void __iomem *base; | ||
640 | int i, ret; | ||
723 | 641 | ||
724 | for (i = 0; i < UART_NR; i++) { | 642 | for (i = 0; i < ARRAY_SIZE(amba_ports); i++) |
725 | if (amba_ports[i].port.mapbase != dev->res.start) | 643 | if (amba_ports[i] == NULL) |
726 | continue; | 644 | break; |
727 | 645 | ||
728 | amba_ports[i].port.dev = &dev->dev; | 646 | if (i == ARRAY_SIZE(amba_ports)) { |
729 | uart_add_one_port(&amba_reg, &amba_ports[i].port); | 647 | ret = -EBUSY; |
730 | amba_set_drvdata(dev, &amba_ports[i]); | 648 | goto out; |
731 | break; | ||
732 | } | 649 | } |
733 | 650 | ||
734 | return 0; | 651 | port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL); |
652 | if (!port) { | ||
653 | ret = -ENOMEM; | ||
654 | goto out; | ||
655 | } | ||
656 | |||
657 | base = ioremap(dev->res.start, PAGE_SIZE); | ||
658 | if (!base) { | ||
659 | ret = -ENOMEM; | ||
660 | goto free; | ||
661 | } | ||
662 | |||
663 | port->port.dev = &dev->dev; | ||
664 | port->port.mapbase = dev->res.start; | ||
665 | port->port.membase = base; | ||
666 | port->port.iotype = UPIO_MEM; | ||
667 | port->port.irq = dev->irq[0]; | ||
668 | port->port.uartclk = 14745600; | ||
669 | port->port.fifosize = 16; | ||
670 | port->port.ops = &amba_pl010_pops; | ||
671 | port->port.flags = UPF_BOOT_AUTOCONF; | ||
672 | port->port.line = i; | ||
673 | port->dev = dev; | ||
674 | port->data = dev->dev.platform_data; | ||
675 | |||
676 | amba_ports[i] = port; | ||
677 | |||
678 | amba_set_drvdata(dev, port); | ||
679 | ret = uart_add_one_port(&amba_reg, &port->port); | ||
680 | if (ret) { | ||
681 | amba_set_drvdata(dev, NULL); | ||
682 | amba_ports[i] = NULL; | ||
683 | iounmap(base); | ||
684 | free: | ||
685 | kfree(port); | ||
686 | } | ||
687 | |||
688 | out: | ||
689 | return ret; | ||
735 | } | 690 | } |
736 | 691 | ||
737 | static int pl010_remove(struct amba_device *dev) | 692 | static int pl010_remove(struct amba_device *dev) |
738 | { | 693 | { |
739 | struct uart_amba_port *uap = amba_get_drvdata(dev); | 694 | struct uart_amba_port *port = amba_get_drvdata(dev); |
740 | 695 | int i; | |
741 | if (uap) | ||
742 | uart_remove_one_port(&amba_reg, &uap->port); | ||
743 | 696 | ||
744 | amba_set_drvdata(dev, NULL); | 697 | amba_set_drvdata(dev, NULL); |
745 | 698 | ||
699 | uart_remove_one_port(&amba_reg, &port->port); | ||
700 | |||
701 | for (i = 0; i < ARRAY_SIZE(amba_ports); i++) | ||
702 | if (amba_ports[i] == port) | ||
703 | amba_ports[i] = NULL; | ||
704 | |||
705 | iounmap(port->port.membase); | ||
706 | kfree(port); | ||
707 | |||
746 | return 0; | 708 | return 0; |
747 | } | 709 | } |
748 | 710 | ||