Commit 6d53c3b71d32da665dc2742c1e8663741f27d3cd

Authored by Michal Simek
Committed by Greg Kroah-Hartman
1 parent 3240b48d49

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);