diff options
author | Michal Simek <michal.simek@xilinx.com> | 2013-02-11 13:04:34 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-13 11:38:45 -0500 |
commit | 6d53c3b71d32da665dc2742c1e8663741f27d3cd (patch) | |
tree | 66936c3b7c8145e6c48bc768afa3efa898345b41 /drivers/tty | |
parent | 3240b48d492b368339a8a5cb3a4dc5b35432ef43 (diff) |
tty: serial: uartlite: Support uartlite on big and little endian systems
Use big and little endian accessors function to reflect system configuration.
Detection is done via control register in ulite_request_port.
Tested on Microblaze LE, BE, PPC440 and Arm zynq.
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/uartlite.c | 101 |
1 files changed, 79 insertions, 22 deletions
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index f3b09ee767ff..5f90ef24d475 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c | |||
@@ -34,7 +34,7 @@ | |||
34 | * Register definitions | 34 | * Register definitions |
35 | * | 35 | * |
36 | * For register details see datasheet: | 36 | * For register details see datasheet: |
37 | * http://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf | 37 | * http://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf |
38 | */ | 38 | */ |
39 | 39 | ||
40 | #define ULITE_RX 0x00 | 40 | #define ULITE_RX 0x00 |
@@ -57,6 +57,54 @@ | |||
57 | #define ULITE_CONTROL_RST_RX 0x02 | 57 | #define ULITE_CONTROL_RST_RX 0x02 |
58 | #define ULITE_CONTROL_IE 0x10 | 58 | #define ULITE_CONTROL_IE 0x10 |
59 | 59 | ||
60 | struct uartlite_reg_ops { | ||
61 | u32 (*in)(void __iomem *addr); | ||
62 | void (*out)(u32 val, void __iomem *addr); | ||
63 | }; | ||
64 | |||
65 | static u32 uartlite_inbe32(void __iomem *addr) | ||
66 | { | ||
67 | return ioread32be(addr); | ||
68 | } | ||
69 | |||
70 | static void uartlite_outbe32(u32 val, void __iomem *addr) | ||
71 | { | ||
72 | iowrite32be(val, addr); | ||
73 | } | ||
74 | |||
75 | static struct uartlite_reg_ops uartlite_be = { | ||
76 | .in = uartlite_inbe32, | ||
77 | .out = uartlite_outbe32, | ||
78 | }; | ||
79 | |||
80 | static u32 uartlite_inle32(void __iomem *addr) | ||
81 | { | ||
82 | return ioread32(addr); | ||
83 | } | ||
84 | |||
85 | static void uartlite_outle32(u32 val, void __iomem *addr) | ||
86 | { | ||
87 | iowrite32(val, addr); | ||
88 | } | ||
89 | |||
90 | static struct uartlite_reg_ops uartlite_le = { | ||
91 | .in = uartlite_inle32, | ||
92 | .out = uartlite_outle32, | ||
93 | }; | ||
94 | |||
95 | static inline u32 uart_in32(u32 offset, struct uart_port *port) | ||
96 | { | ||
97 | struct uartlite_reg_ops *reg_ops = port->private_data; | ||
98 | |||
99 | return reg_ops->in(port->membase + offset); | ||
100 | } | ||
101 | |||
102 | static inline void uart_out32(u32 val, u32 offset, struct uart_port *port) | ||
103 | { | ||
104 | struct uartlite_reg_ops *reg_ops = port->private_data; | ||
105 | |||
106 | reg_ops->out(val, port->membase + offset); | ||
107 | } | ||
60 | 108 | ||
61 | static struct uart_port ulite_ports[ULITE_NR_UARTS]; | 109 | static struct uart_port ulite_ports[ULITE_NR_UARTS]; |
62 | 110 | ||
@@ -77,7 +125,7 @@ static int ulite_receive(struct uart_port *port, int stat) | |||
77 | /* stats */ | 125 | /* stats */ |
78 | if (stat & ULITE_STATUS_RXVALID) { | 126 | if (stat & ULITE_STATUS_RXVALID) { |
79 | port->icount.rx++; | 127 | port->icount.rx++; |
80 | ch = ioread32be(port->membase + ULITE_RX); | 128 | ch = uart_in32(ULITE_RX, port); |
81 | 129 | ||
82 | if (stat & ULITE_STATUS_PARITY) | 130 | if (stat & ULITE_STATUS_PARITY) |
83 | port->icount.parity++; | 131 | port->icount.parity++; |
@@ -122,7 +170,7 @@ static int ulite_transmit(struct uart_port *port, int stat) | |||
122 | return 0; | 170 | return 0; |
123 | 171 | ||
124 | if (port->x_char) { | 172 | if (port->x_char) { |
125 | iowrite32be(port->x_char, port->membase + ULITE_TX); | 173 | uart_out32(port->x_char, ULITE_TX, port); |
126 | port->x_char = 0; | 174 | port->x_char = 0; |
127 | port->icount.tx++; | 175 | port->icount.tx++; |
128 | return 1; | 176 | return 1; |
@@ -131,7 +179,7 @@ static int ulite_transmit(struct uart_port *port, int stat) | |||
131 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) | 179 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) |
132 | return 0; | 180 | return 0; |
133 | 181 | ||
134 | iowrite32be(xmit->buf[xmit->tail], port->membase + ULITE_TX); | 182 | uart_out32(xmit->buf[xmit->tail], ULITE_TX, port); |
135 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); | 183 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); |
136 | port->icount.tx++; | 184 | port->icount.tx++; |
137 | 185 | ||
@@ -148,7 +196,7 @@ static irqreturn_t ulite_isr(int irq, void *dev_id) | |||
148 | int busy, n = 0; | 196 | int busy, n = 0; |
149 | 197 | ||
150 | do { | 198 | do { |
151 | int stat = ioread32be(port->membase + ULITE_STATUS); | 199 | int stat = uart_in32(ULITE_STATUS, port); |
152 | busy = ulite_receive(port, stat); | 200 | busy = ulite_receive(port, stat); |
153 | busy |= ulite_transmit(port, stat); | 201 | busy |= ulite_transmit(port, stat); |
154 | n++; | 202 | n++; |
@@ -169,7 +217,7 @@ static unsigned int ulite_tx_empty(struct uart_port *port) | |||
169 | unsigned int ret; | 217 | unsigned int ret; |
170 | 218 | ||
171 | spin_lock_irqsave(&port->lock, flags); | 219 | spin_lock_irqsave(&port->lock, flags); |
172 | ret = ioread32be(port->membase + ULITE_STATUS); | 220 | ret = uart_in32(ULITE_STATUS, port); |
173 | spin_unlock_irqrestore(&port->lock, flags); | 221 | spin_unlock_irqrestore(&port->lock, flags); |
174 | 222 | ||
175 | return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0; | 223 | return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0; |
@@ -192,7 +240,7 @@ static void ulite_stop_tx(struct uart_port *port) | |||
192 | 240 | ||
193 | static void ulite_start_tx(struct uart_port *port) | 241 | static void ulite_start_tx(struct uart_port *port) |
194 | { | 242 | { |
195 | ulite_transmit(port, ioread32be(port->membase + ULITE_STATUS)); | 243 | ulite_transmit(port, uart_in32(ULITE_STATUS, port)); |
196 | } | 244 | } |
197 | 245 | ||
198 | static void ulite_stop_rx(struct uart_port *port) | 246 | static void ulite_stop_rx(struct uart_port *port) |
@@ -220,17 +268,17 @@ static int ulite_startup(struct uart_port *port) | |||
220 | if (ret) | 268 | if (ret) |
221 | return ret; | 269 | return ret; |
222 | 270 | ||
223 | iowrite32be(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX, | 271 | uart_out32(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX, |
224 | port->membase + ULITE_CONTROL); | 272 | ULITE_CONTROL, port); |
225 | iowrite32be(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL); | 273 | uart_out32(ULITE_CONTROL_IE, ULITE_CONTROL, port); |
226 | 274 | ||
227 | return 0; | 275 | return 0; |
228 | } | 276 | } |
229 | 277 | ||
230 | static void ulite_shutdown(struct uart_port *port) | 278 | static void ulite_shutdown(struct uart_port *port) |
231 | { | 279 | { |
232 | iowrite32be(0, port->membase + ULITE_CONTROL); | 280 | uart_out32(0, ULITE_CONTROL, port); |
233 | ioread32be(port->membase + ULITE_CONTROL); /* dummy */ | 281 | uart_in32(ULITE_CONTROL, port); /* dummy */ |
234 | free_irq(port->irq, port); | 282 | free_irq(port->irq, port); |
235 | } | 283 | } |
236 | 284 | ||
@@ -281,6 +329,8 @@ static void ulite_release_port(struct uart_port *port) | |||
281 | 329 | ||
282 | static int ulite_request_port(struct uart_port *port) | 330 | static int ulite_request_port(struct uart_port *port) |
283 | { | 331 | { |
332 | int ret; | ||
333 | |||
284 | pr_debug("ulite console: port=%p; port->mapbase=%llx\n", | 334 | pr_debug("ulite console: port=%p; port->mapbase=%llx\n", |
285 | port, (unsigned long long) port->mapbase); | 335 | port, (unsigned long long) port->mapbase); |
286 | 336 | ||
@@ -296,6 +346,14 @@ static int ulite_request_port(struct uart_port *port) | |||
296 | return -EBUSY; | 346 | return -EBUSY; |
297 | } | 347 | } |
298 | 348 | ||
349 | port->private_data = &uartlite_be; | ||
350 | ret = uart_in32(ULITE_CONTROL, port); | ||
351 | uart_out32(ULITE_CONTROL_RST_TX, ULITE_CONTROL, port); | ||
352 | ret = uart_in32(ULITE_STATUS, port); | ||
353 | /* Endianess detection */ | ||
354 | if ((ret & ULITE_STATUS_TXEMPTY) != ULITE_STATUS_TXEMPTY) | ||
355 | port->private_data = &uartlite_le; | ||
356 | |||
299 | return 0; | 357 | return 0; |
300 | } | 358 | } |
301 | 359 | ||
@@ -314,20 +372,19 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
314 | #ifdef CONFIG_CONSOLE_POLL | 372 | #ifdef CONFIG_CONSOLE_POLL |
315 | static int ulite_get_poll_char(struct uart_port *port) | 373 | static int ulite_get_poll_char(struct uart_port *port) |
316 | { | 374 | { |
317 | if (!(ioread32be(port->membase + ULITE_STATUS) | 375 | if (!(uart_in32(ULITE_STATUS, port) & ULITE_STATUS_RXVALID)) |
318 | & ULITE_STATUS_RXVALID)) | ||
319 | return NO_POLL_CHAR; | 376 | return NO_POLL_CHAR; |
320 | 377 | ||
321 | return ioread32be(port->membase + ULITE_RX); | 378 | return uart_in32(ULITE_RX, port); |
322 | } | 379 | } |
323 | 380 | ||
324 | static void ulite_put_poll_char(struct uart_port *port, unsigned char ch) | 381 | static void ulite_put_poll_char(struct uart_port *port, unsigned char ch) |
325 | { | 382 | { |
326 | while (ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL) | 383 | while (uart_in32(ULITE_STATUS, port) & ULITE_STATUS_TXFULL) |
327 | cpu_relax(); | 384 | cpu_relax(); |
328 | 385 | ||
329 | /* write char to device */ | 386 | /* write char to device */ |
330 | iowrite32be(ch, port->membase + ULITE_TX); | 387 | uart_out32(ch, ULITE_TX, port); |
331 | } | 388 | } |
332 | #endif | 389 | #endif |
333 | 390 | ||
@@ -366,7 +423,7 @@ static void ulite_console_wait_tx(struct uart_port *port) | |||
366 | 423 | ||
367 | /* Spin waiting for TX fifo to have space available */ | 424 | /* Spin waiting for TX fifo to have space available */ |
368 | for (i = 0; i < 100000; i++) { | 425 | for (i = 0; i < 100000; i++) { |
369 | val = ioread32be(port->membase + ULITE_STATUS); | 426 | val = uart_in32(ULITE_STATUS, port); |
370 | if ((val & ULITE_STATUS_TXFULL) == 0) | 427 | if ((val & ULITE_STATUS_TXFULL) == 0) |
371 | break; | 428 | break; |
372 | cpu_relax(); | 429 | cpu_relax(); |
@@ -376,7 +433,7 @@ static void ulite_console_wait_tx(struct uart_port *port) | |||
376 | static void ulite_console_putchar(struct uart_port *port, int ch) | 433 | static void ulite_console_putchar(struct uart_port *port, int ch) |
377 | { | 434 | { |
378 | ulite_console_wait_tx(port); | 435 | ulite_console_wait_tx(port); |
379 | iowrite32be(ch, port->membase + ULITE_TX); | 436 | uart_out32(ch, ULITE_TX, port); |
380 | } | 437 | } |
381 | 438 | ||
382 | static void ulite_console_write(struct console *co, const char *s, | 439 | static void ulite_console_write(struct console *co, const char *s, |
@@ -393,8 +450,8 @@ static void ulite_console_write(struct console *co, const char *s, | |||
393 | spin_lock_irqsave(&port->lock, flags); | 450 | spin_lock_irqsave(&port->lock, flags); |
394 | 451 | ||
395 | /* save and disable interrupt */ | 452 | /* save and disable interrupt */ |
396 | ier = ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_IE; | 453 | ier = uart_in32(ULITE_STATUS, port) & ULITE_STATUS_IE; |
397 | iowrite32be(0, port->membase + ULITE_CONTROL); | 454 | uart_out32(0, ULITE_CONTROL, port); |
398 | 455 | ||
399 | uart_console_write(port, s, count, ulite_console_putchar); | 456 | uart_console_write(port, s, count, ulite_console_putchar); |
400 | 457 | ||
@@ -402,7 +459,7 @@ static void ulite_console_write(struct console *co, const char *s, | |||
402 | 459 | ||
403 | /* restore interrupt state */ | 460 | /* restore interrupt state */ |
404 | if (ier) | 461 | if (ier) |
405 | iowrite32be(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL); | 462 | uart_out32(ULITE_CONTROL_IE, ULITE_CONTROL, port); |
406 | 463 | ||
407 | if (locked) | 464 | if (locked) |
408 | spin_unlock_irqrestore(&port->lock, flags); | 465 | spin_unlock_irqrestore(&port->lock, flags); |