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 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 int uniphier_serial_probe(struct udevice
*dev
)
98 struct uniphier_serial_private_data
*priv
= dev_get_priv(dev
);
99 struct uniphier_serial_platform_data
*plat
= dev_get_platdata(dev
);
101 priv
->membase
= map_sysmem(plat
->base
, sizeof(struct uniphier_serial
));
109 int uniphier_serial_remove(struct udevice
*dev
)
111 unmap_sysmem(uniphier_serial_port(dev
));
116 #ifdef CONFIG_OF_CONTROL
117 static const struct udevice_id uniphier_uart_of_match
= {
118 { .compatible
= "panasonic,uniphier-uart"},
122 static int uniphier_serial_ofdata_to_platdata(struct udevice
*dev
)
125 * TODO: Masahiro Yamada (yamada.m@jp.panasonic.com)
127 * Implement conversion code from DTB to platform data
128 * when supporting CONFIG_OF_CONTROL on UniPhir platform.
133 static const struct dm_serial_ops uniphier_serial_ops
= {
134 .setbrg
= uniphier_serial_setbrg
,
135 .getc
= uniphier_serial_getc
,
136 .putc
= uniphier_serial_putc
,
139 U_BOOT_DRIVER(uniphier_serial
) = {
142 .of_match
= of_match_ptr(uniphier_uart_of_match
),
143 .ofdata_to_platdata
= of_match_ptr(uniphier_serial_ofdata_to_platdata
),
144 .probe
= uniphier_serial_probe
,
145 .remove
= uniphier_serial_remove
,
146 .priv_auto_alloc_size
= sizeof(struct uniphier_serial_private_data
),
147 .platdata_auto_alloc_size
=
148 sizeof(struct uniphier_serial_platform_data
),
149 .ops
= &uniphier_serial_ops
,
150 .flags
= DM_FLAG_PRE_RELOC
,