2 * Copyright (C) 2012-2014 Panasonic Corporation
3 * Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
5 * SPDX-License-Identifier: GPL-2.0+
10 #include <asm/errno.h>
11 #include <dm/device.h>
12 #include <dm/platform_data/serial-uniphier.h>
20 * Note: Register map is slightly different from that of 16550.
22 struct uniphier_serial
{
23 UART_REG(rbr
); /* 0x00 */
24 UART_REG(ier
); /* 0x04 */
25 UART_REG(iir
); /* 0x08 */
26 UART_REG(fcr
); /* 0x0c */
30 UART_REG(lsr
); /* 0x14 */
31 UART_REG(msr
); /* 0x18 */
41 * These are the definitions for the Line Control Register
43 #define UART_LCR_WLS_8 0x03 /* 8 bit character length */
46 * These are the definitions for the Line Status Register
48 #define UART_LSR_DR 0x01 /* Data ready */
49 #define UART_LSR_THRE 0x20 /* Xmit holding register empty */
51 struct uniphier_serial_private_data
{
52 struct uniphier_serial __iomem
*membase
;
55 #define uniphier_serial_port(dev) \
56 ((struct uniphier_serial_private_data *)dev_get_priv(dev))->membase
58 static int uniphier_serial_setbrg(struct udevice
*dev
, int baudrate
)
60 struct uniphier_serial_platform_data
*plat
= dev_get_platdata(dev
);
61 struct uniphier_serial __iomem
*port
= uniphier_serial_port(dev
);
62 const unsigned int mode_x_div
= 16;
65 writeb(UART_LCR_WLS_8
, &port
->lcr
);
67 divisor
= DIV_ROUND_CLOSEST(plat
->uartclk
, mode_x_div
* baudrate
);
69 writew(divisor
, &port
->dlr
);
74 static int uniphier_serial_getc(struct udevice
*dev
)
76 struct uniphier_serial __iomem
*port
= uniphier_serial_port(dev
);
78 if (!(readb(&port
->lsr
) & UART_LSR_DR
))
81 return readb(&port
->rbr
);
84 static int uniphier_serial_putc(struct udevice
*dev
, const char c
)
86 struct uniphier_serial __iomem
*port
= uniphier_serial_port(dev
);
88 if (!(readb(&port
->lsr
) & UART_LSR_THRE
))
91 writeb(c
, &port
->thr
);
96 static int uniphier_serial_pending(struct udevice
*dev
, bool input
)
98 struct uniphier_serial __iomem
*port
= uniphier_serial_port(dev
);
101 return readb(&port
->lsr
) & UART_LSR_DR
;
103 return !(readb(&port
->lsr
) & UART_LSR_THRE
);
106 static int uniphier_serial_probe(struct udevice
*dev
)
108 struct uniphier_serial_private_data
*priv
= dev_get_priv(dev
);
109 struct uniphier_serial_platform_data
*plat
= dev_get_platdata(dev
);
111 priv
->membase
= map_sysmem(plat
->base
, sizeof(struct uniphier_serial
));
119 static int uniphier_serial_remove(struct udevice
*dev
)
121 unmap_sysmem(uniphier_serial_port(dev
));
126 #ifdef CONFIG_OF_CONTROL
127 static const struct udevice_id uniphier_uart_of_match
= {
128 { .compatible
= "panasonic,uniphier-uart"},
132 static int uniphier_serial_ofdata_to_platdata(struct udevice
*dev
)
135 * TODO: Masahiro Yamada (yamada.m@jp.panasonic.com)
137 * Implement conversion code from DTB to platform data
138 * when supporting CONFIG_OF_CONTROL on UniPhir platform.
143 static const struct dm_serial_ops uniphier_serial_ops
= {
144 .setbrg
= uniphier_serial_setbrg
,
145 .getc
= uniphier_serial_getc
,
146 .putc
= uniphier_serial_putc
,
147 .pending
= uniphier_serial_pending
,
150 U_BOOT_DRIVER(uniphier_serial
) = {
153 .of_match
= of_match_ptr(uniphier_uart_of_match
),
154 .ofdata_to_platdata
= of_match_ptr(uniphier_serial_ofdata_to_platdata
),
155 .probe
= uniphier_serial_probe
,
156 .remove
= uniphier_serial_remove
,
157 .priv_auto_alloc_size
= sizeof(struct uniphier_serial_private_data
),
158 .platdata_auto_alloc_size
=
159 sizeof(struct uniphier_serial_platform_data
),
160 .ops
= &uniphier_serial_ops
,
161 .flags
= DM_FLAG_PRE_RELOC
,