Commit d0c47b3ef7c582ec984edeba08984b0acc2ffcba

Authored by Masahiro Yamada
1 parent c8bc166124

serial: UniPhier: use 32 bit register access

For PH1-Pro4, the 8 bit write access to LCR register (offset = 0x11)
is not working correctly.  As a side effect, it also modifies MCR
register (offset = 0x10) and results in unexpected behavior.

Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>

Showing 1 changed file with 26 additions and 28 deletions Side-by-side Diff

drivers/serial/serial_uniphier.c
1 1 /*
2   - * Copyright (C) 2012-2014 Panasonic Corporation
  2 + * Copyright (C) 2012-2015 Panasonic Corporation
3 3 * Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
4 4 *
5 5 * SPDX-License-Identifier: GPL-2.0+
6 6  
7 7  
... ... @@ -13,31 +13,25 @@
13 13 #include <serial.h>
14 14 #include <fdtdec.h>
15 15  
16   -#define UART_REG(x) \
17   - u8 x; \
18   - u8 postpad_##x[3];
19   -
20 16 /*
21 17 * Note: Register map is slightly different from that of 16550.
22 18 */
23 19 struct uniphier_serial {
24   - UART_REG(rbr); /* 0x00 */
25   - UART_REG(ier); /* 0x04 */
26   - UART_REG(iir); /* 0x08 */
27   - UART_REG(fcr); /* 0x0c */
28   - u8 mcr; /* 0x10 */
29   - u8 lcr;
30   - u16 __postpad;
31   - UART_REG(lsr); /* 0x14 */
32   - UART_REG(msr); /* 0x18 */
33   - u32 __none1;
34   - u32 __none2;
35   - u16 dlr;
36   - u16 __postpad2;
  20 + u32 rx; /* In: Receive buffer */
  21 +#define tx rx /* Out: Transmit buffer */
  22 + u32 ier; /* Interrupt Enable Register */
  23 + u32 iir; /* In: Interrupt ID Register */
  24 + u32 char_fcr; /* Charactor / FIFO Control Register */
  25 + u32 lcr_mcr; /* Line/Modem Control Register */
  26 +#define LCR_SHIFT 8
  27 +#define LCR_MASK (0xff << (LCR_SHIFT))
  28 + u32 lsr; /* In: Line Status Register */
  29 + u32 msr; /* In: Modem Status Register */
  30 + u32 __rsv0;
  31 + u32 __rsv1;
  32 + u32 dlr; /* Divisor Latch Register */
37 33 };
38 34  
39   -#define thr rbr
40   -
41 35 struct uniphier_serial_private_data {
42 36 struct uniphier_serial __iomem *membase;
43 37 };
44 38  
45 39  
... ... @@ -51,12 +45,16 @@
51 45 struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
52 46 const unsigned int mode_x_div = 16;
53 47 unsigned int divisor;
  48 + u32 tmp;
54 49  
55   - writeb(UART_LCR_WLEN8, &port->lcr);
  50 + tmp = readl(&port->lcr_mcr);
  51 + tmp &= ~LCR_MASK;
  52 + tmp |= UART_LCR_WLEN8 << LCR_SHIFT;
  53 + writel(tmp, &port->lcr_mcr);
56 54  
57 55 divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate);
58 56  
59   - writew(divisor, &port->dlr);
  57 + writel(divisor, &port->dlr);
60 58  
61 59 return 0;
62 60 }
63 61  
64 62  
65 63  
... ... @@ -65,20 +63,20 @@
65 63 {
66 64 struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
67 65  
68   - if (!(readb(&port->lsr) & UART_LSR_DR))
  66 + if (!(readl(&port->lsr) & UART_LSR_DR))
69 67 return -EAGAIN;
70 68  
71   - return readb(&port->rbr);
  69 + return readl(&port->rx);
72 70 }
73 71  
74 72 static int uniphier_serial_putc(struct udevice *dev, const char c)
75 73 {
76 74 struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
77 75  
78   - if (!(readb(&port->lsr) & UART_LSR_THRE))
  76 + if (!(readl(&port->lsr) & UART_LSR_THRE))
79 77 return -EAGAIN;
80 78  
81   - writeb(c, &port->thr);
  79 + writel(c, &port->tx);
82 80  
83 81 return 0;
84 82 }
85 83  
... ... @@ -88,9 +86,9 @@
88 86 struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
89 87  
90 88 if (input)
91   - return readb(&port->lsr) & UART_LSR_DR;
  89 + return readl(&port->lsr) & UART_LSR_DR;
92 90 else
93   - return !(readb(&port->lsr) & UART_LSR_THRE);
  91 + return !(readl(&port->lsr) & UART_LSR_THRE);
94 92 }
95 93  
96 94 static int uniphier_serial_probe(struct udevice *dev)