Commit 6d53c3b71d32da665dc2742c1e8663741f27d3cd
Committed by
Greg Kroah-Hartman
1 parent
3240b48d49
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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>
Showing 1 changed file with 79 additions and 22 deletions Side-by-side Diff
drivers/tty/serial/uartlite.c
... | ... | @@ -34,7 +34,7 @@ |
34 | 34 | * Register definitions |
35 | 35 | * |
36 | 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 | 40 | #define ULITE_RX 0x00 |
41 | 41 | |
... | ... | @@ -57,7 +57,55 @@ |
57 | 57 | #define ULITE_CONTROL_RST_RX 0x02 |
58 | 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 | +}; | |
60 | 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 | +} | |
108 | + | |
61 | 109 | static struct uart_port ulite_ports[ULITE_NR_UARTS]; |
62 | 110 | |
63 | 111 | /* --------------------------------------------------------------------- |
... | ... | @@ -77,7 +125,7 @@ |
77 | 125 | /* stats */ |
78 | 126 | if (stat & ULITE_STATUS_RXVALID) { |
79 | 127 | port->icount.rx++; |
80 | - ch = ioread32be(port->membase + ULITE_RX); | |
128 | + ch = uart_in32(ULITE_RX, port); | |
81 | 129 | |
82 | 130 | if (stat & ULITE_STATUS_PARITY) |
83 | 131 | port->icount.parity++; |
... | ... | @@ -122,7 +170,7 @@ |
122 | 170 | return 0; |
123 | 171 | |
124 | 172 | if (port->x_char) { |
125 | - iowrite32be(port->x_char, port->membase + ULITE_TX); | |
173 | + uart_out32(port->x_char, ULITE_TX, port); | |
126 | 174 | port->x_char = 0; |
127 | 175 | port->icount.tx++; |
128 | 176 | return 1; |
... | ... | @@ -131,7 +179,7 @@ |
131 | 179 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) |
132 | 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 | 183 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); |
136 | 184 | port->icount.tx++; |
137 | 185 | |
... | ... | @@ -148,7 +196,7 @@ |
148 | 196 | int busy, n = 0; |
149 | 197 | |
150 | 198 | do { |
151 | - int stat = ioread32be(port->membase + ULITE_STATUS); | |
199 | + int stat = uart_in32(ULITE_STATUS, port); | |
152 | 200 | busy = ulite_receive(port, stat); |
153 | 201 | busy |= ulite_transmit(port, stat); |
154 | 202 | n++; |
... | ... | @@ -169,7 +217,7 @@ |
169 | 217 | unsigned int ret; |
170 | 218 | |
171 | 219 | spin_lock_irqsave(&port->lock, flags); |
172 | - ret = ioread32be(port->membase + ULITE_STATUS); | |
220 | + ret = uart_in32(ULITE_STATUS, port); | |
173 | 221 | spin_unlock_irqrestore(&port->lock, flags); |
174 | 222 | |
175 | 223 | return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0; |
... | ... | @@ -192,7 +240,7 @@ |
192 | 240 | |
193 | 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 | 246 | static void ulite_stop_rx(struct uart_port *port) |
199 | 247 | |
... | ... | @@ -220,17 +268,17 @@ |
220 | 268 | if (ret) |
221 | 269 | return ret; |
222 | 270 | |
223 | - iowrite32be(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX, | |
224 | - port->membase + ULITE_CONTROL); | |
225 | - iowrite32be(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL); | |
271 | + uart_out32(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX, | |
272 | + ULITE_CONTROL, port); | |
273 | + uart_out32(ULITE_CONTROL_IE, ULITE_CONTROL, port); | |
226 | 274 | |
227 | 275 | return 0; |
228 | 276 | } |
229 | 277 | |
230 | 278 | static void ulite_shutdown(struct uart_port *port) |
231 | 279 | { |
232 | - iowrite32be(0, port->membase + ULITE_CONTROL); | |
233 | - ioread32be(port->membase + ULITE_CONTROL); /* dummy */ | |
280 | + uart_out32(0, ULITE_CONTROL, port); | |
281 | + uart_in32(ULITE_CONTROL, port); /* dummy */ | |
234 | 282 | free_irq(port->irq, port); |
235 | 283 | } |
236 | 284 | |
... | ... | @@ -281,6 +329,8 @@ |
281 | 329 | |
282 | 330 | static int ulite_request_port(struct uart_port *port) |
283 | 331 | { |
332 | + int ret; | |
333 | + | |
284 | 334 | pr_debug("ulite console: port=%p; port->mapbase=%llx\n", |
285 | 335 | port, (unsigned long long) port->mapbase); |
286 | 336 | |
... | ... | @@ -296,6 +346,14 @@ |
296 | 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 | 357 | return 0; |
300 | 358 | } |
301 | 359 | |
302 | 360 | |
303 | 361 | |
304 | 362 | |
... | ... | @@ -314,20 +372,19 @@ |
314 | 372 | #ifdef CONFIG_CONSOLE_POLL |
315 | 373 | static int ulite_get_poll_char(struct uart_port *port) |
316 | 374 | { |
317 | - if (!(ioread32be(port->membase + ULITE_STATUS) | |
318 | - & ULITE_STATUS_RXVALID)) | |
375 | + if (!(uart_in32(ULITE_STATUS, port) & ULITE_STATUS_RXVALID)) | |
319 | 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 | 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 | 384 | cpu_relax(); |
328 | 385 | |
329 | 386 | /* write char to device */ |
330 | - iowrite32be(ch, port->membase + ULITE_TX); | |
387 | + uart_out32(ch, ULITE_TX, port); | |
331 | 388 | } |
332 | 389 | #endif |
333 | 390 | |
... | ... | @@ -366,7 +423,7 @@ |
366 | 423 | |
367 | 424 | /* Spin waiting for TX fifo to have space available */ |
368 | 425 | for (i = 0; i < 100000; i++) { |
369 | - val = ioread32be(port->membase + ULITE_STATUS); | |
426 | + val = uart_in32(ULITE_STATUS, port); | |
370 | 427 | if ((val & ULITE_STATUS_TXFULL) == 0) |
371 | 428 | break; |
372 | 429 | cpu_relax(); |
... | ... | @@ -376,7 +433,7 @@ |
376 | 433 | static void ulite_console_putchar(struct uart_port *port, int ch) |
377 | 434 | { |
378 | 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 | 439 | static void ulite_console_write(struct console *co, const char *s, |
... | ... | @@ -393,8 +450,8 @@ |
393 | 450 | spin_lock_irqsave(&port->lock, flags); |
394 | 451 | |
395 | 452 | /* save and disable interrupt */ |
396 | - ier = ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_IE; | |
397 | - iowrite32be(0, port->membase + ULITE_CONTROL); | |
453 | + ier = uart_in32(ULITE_STATUS, port) & ULITE_STATUS_IE; | |
454 | + uart_out32(0, ULITE_CONTROL, port); | |
398 | 455 | |
399 | 456 | uart_console_write(port, s, count, ulite_console_putchar); |
400 | 457 | |
... | ... | @@ -402,7 +459,7 @@ |
402 | 459 | |
403 | 460 | /* restore interrupt state */ |
404 | 461 | if (ier) |
405 | - iowrite32be(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL); | |
462 | + uart_out32(ULITE_CONTROL_IE, ULITE_CONTROL, port); | |
406 | 463 | |
407 | 464 | if (locked) |
408 | 465 | spin_unlock_irqrestore(&port->lock, flags); |