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>
This commit is contained in:
		
							parent
							
								
									c8bc166124
								
							
						
					
					
						commit
						d0c47b3ef7
					
				|  | @ -1,5 +1,5 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (C) 2012-2014 Panasonic Corporation |  * Copyright (C) 2012-2015 Panasonic Corporation | ||||||
|  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com> |  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com> | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier:	GPL-2.0+ |  * SPDX-License-Identifier:	GPL-2.0+ | ||||||
|  | @ -13,31 +13,25 @@ | ||||||
| #include <serial.h> | #include <serial.h> | ||||||
| #include <fdtdec.h> | #include <fdtdec.h> | ||||||
| 
 | 
 | ||||||
| #define UART_REG(x)					\ |  | ||||||
| 	u8 x;						\ |  | ||||||
| 	u8 postpad_##x[3]; |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * Note: Register map is slightly different from that of 16550. |  * Note: Register map is slightly different from that of 16550. | ||||||
|  */ |  */ | ||||||
| struct uniphier_serial { | struct uniphier_serial { | ||||||
| 	UART_REG(rbr);		/* 0x00 */ | 	u32 rx;			/* In:  Receive buffer */ | ||||||
| 	UART_REG(ier);		/* 0x04 */ | #define tx rx			/* Out: Transmit buffer */ | ||||||
| 	UART_REG(iir);		/* 0x08 */ | 	u32 ier;		/* Interrupt Enable Register */ | ||||||
| 	UART_REG(fcr);		/* 0x0c */ | 	u32 iir;		/* In: Interrupt ID Register */ | ||||||
| 	u8 mcr;			/* 0x10 */ | 	u32 char_fcr;		/* Charactor / FIFO Control Register */ | ||||||
| 	u8 lcr; | 	u32 lcr_mcr;		/* Line/Modem Control Register */ | ||||||
| 	u16 __postpad; | #define LCR_SHIFT	8 | ||||||
| 	UART_REG(lsr);		/* 0x14 */ | #define LCR_MASK	(0xff << (LCR_SHIFT)) | ||||||
| 	UART_REG(msr);		/* 0x18 */ | 	u32 lsr;		/* In: Line Status Register */ | ||||||
| 	u32 __none1; | 	u32 msr;		/* In: Modem Status Register */ | ||||||
| 	u32 __none2; | 	u32 __rsv0; | ||||||
| 	u16 dlr; | 	u32 __rsv1; | ||||||
| 	u16 __postpad2; | 	u32 dlr;		/* Divisor Latch Register */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define thr rbr |  | ||||||
| 
 |  | ||||||
| struct uniphier_serial_private_data { | struct uniphier_serial_private_data { | ||||||
| 	struct uniphier_serial __iomem *membase; | 	struct uniphier_serial __iomem *membase; | ||||||
| }; | }; | ||||||
|  | @ -51,12 +45,16 @@ static int uniphier_serial_setbrg(struct udevice *dev, int baudrate) | ||||||
| 	struct uniphier_serial __iomem *port = uniphier_serial_port(dev); | 	struct uniphier_serial __iomem *port = uniphier_serial_port(dev); | ||||||
| 	const unsigned int mode_x_div = 16; | 	const unsigned int mode_x_div = 16; | ||||||
| 	unsigned int divisor; | 	unsigned int divisor; | ||||||
|  | 	u32 tmp; | ||||||
| 
 | 
 | ||||||
| 	writeb(UART_LCR_WLEN8, &port->lcr); | 	tmp = readl(&port->lcr_mcr); | ||||||
|  | 	tmp &= ~LCR_MASK; | ||||||
|  | 	tmp |= UART_LCR_WLEN8 << LCR_SHIFT; | ||||||
|  | 	writel(tmp, &port->lcr_mcr); | ||||||
| 
 | 
 | ||||||
| 	divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate); | 	divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate); | ||||||
| 
 | 
 | ||||||
| 	writew(divisor, &port->dlr); | 	writel(divisor, &port->dlr); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -65,20 +63,20 @@ static int uniphier_serial_getc(struct udevice *dev) | ||||||
| { | { | ||||||
| 	struct uniphier_serial __iomem *port = uniphier_serial_port(dev); | 	struct uniphier_serial __iomem *port = uniphier_serial_port(dev); | ||||||
| 
 | 
 | ||||||
| 	if (!(readb(&port->lsr) & UART_LSR_DR)) | 	if (!(readl(&port->lsr) & UART_LSR_DR)) | ||||||
| 		return -EAGAIN; | 		return -EAGAIN; | ||||||
| 
 | 
 | ||||||
| 	return readb(&port->rbr); | 	return readl(&port->rx); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int uniphier_serial_putc(struct udevice *dev, const char c) | static int uniphier_serial_putc(struct udevice *dev, const char c) | ||||||
| { | { | ||||||
| 	struct uniphier_serial __iomem *port = uniphier_serial_port(dev); | 	struct uniphier_serial __iomem *port = uniphier_serial_port(dev); | ||||||
| 
 | 
 | ||||||
| 	if (!(readb(&port->lsr) & UART_LSR_THRE)) | 	if (!(readl(&port->lsr) & UART_LSR_THRE)) | ||||||
| 		return -EAGAIN; | 		return -EAGAIN; | ||||||
| 
 | 
 | ||||||
| 	writeb(c, &port->thr); | 	writel(c, &port->tx); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -88,9 +86,9 @@ static int uniphier_serial_pending(struct udevice *dev, bool input) | ||||||
| 	struct uniphier_serial __iomem *port = uniphier_serial_port(dev); | 	struct uniphier_serial __iomem *port = uniphier_serial_port(dev); | ||||||
| 
 | 
 | ||||||
| 	if (input) | 	if (input) | ||||||
| 		return readb(&port->lsr) & UART_LSR_DR; | 		return readl(&port->lsr) & UART_LSR_DR; | ||||||
| 	else | 	else | ||||||
| 		return !(readb(&port->lsr) & UART_LSR_THRE); | 		return !(readl(&port->lsr) & UART_LSR_THRE); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int uniphier_serial_probe(struct udevice *dev) | static int uniphier_serial_probe(struct udevice *dev) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue