17f368553SMasahiro Yamada /* 27f368553SMasahiro Yamada * Copyright (C) 2012-2014 Panasonic Corporation 37f368553SMasahiro Yamada * Author: Masahiro Yamada <yamada.m@jp.panasonic.com> 47f368553SMasahiro Yamada * 57f368553SMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+ 67f368553SMasahiro Yamada */ 77f368553SMasahiro Yamada 87f368553SMasahiro Yamada #include <common.h> 9d064cbffSMasahiro Yamada #include <asm/io.h> 10d064cbffSMasahiro Yamada #include <asm/errno.h> 11d064cbffSMasahiro Yamada #include <dm/device.h> 12d064cbffSMasahiro Yamada #include <dm/platform_data/serial-uniphier.h> 137f368553SMasahiro Yamada #include <serial.h> 147f368553SMasahiro Yamada 157f368553SMasahiro Yamada #define UART_REG(x) \ 167f368553SMasahiro Yamada u8 x; \ 177f368553SMasahiro Yamada u8 postpad_##x[3]; 187f368553SMasahiro Yamada 197f368553SMasahiro Yamada /* 207f368553SMasahiro Yamada * Note: Register map is slightly different from that of 16550. 217f368553SMasahiro Yamada */ 227f368553SMasahiro Yamada struct uniphier_serial { 237f368553SMasahiro Yamada UART_REG(rbr); /* 0x00 */ 247f368553SMasahiro Yamada UART_REG(ier); /* 0x04 */ 257f368553SMasahiro Yamada UART_REG(iir); /* 0x08 */ 267f368553SMasahiro Yamada UART_REG(fcr); /* 0x0c */ 277f368553SMasahiro Yamada u8 mcr; /* 0x10 */ 287f368553SMasahiro Yamada u8 lcr; 297f368553SMasahiro Yamada u16 __postpad; 307f368553SMasahiro Yamada UART_REG(lsr); /* 0x14 */ 317f368553SMasahiro Yamada UART_REG(msr); /* 0x18 */ 327f368553SMasahiro Yamada u32 __none1; 337f368553SMasahiro Yamada u32 __none2; 347f368553SMasahiro Yamada u16 dlr; 357f368553SMasahiro Yamada u16 __postpad2; 367f368553SMasahiro Yamada }; 377f368553SMasahiro Yamada 387f368553SMasahiro Yamada #define thr rbr 397f368553SMasahiro Yamada 407f368553SMasahiro Yamada /* 417f368553SMasahiro Yamada * These are the definitions for the Line Control Register 427f368553SMasahiro Yamada */ 437f368553SMasahiro Yamada #define UART_LCR_WLS_8 0x03 /* 8 bit character length */ 447f368553SMasahiro Yamada 457f368553SMasahiro Yamada /* 467f368553SMasahiro Yamada * These are the definitions for the Line Status Register 477f368553SMasahiro Yamada */ 487f368553SMasahiro Yamada #define UART_LSR_DR 0x01 /* Data ready */ 497f368553SMasahiro Yamada #define UART_LSR_THRE 0x20 /* Xmit holding register empty */ 507f368553SMasahiro Yamada 51d064cbffSMasahiro Yamada struct uniphier_serial_private_data { 52d064cbffSMasahiro Yamada struct uniphier_serial __iomem *membase; 53d064cbffSMasahiro Yamada }; 547f368553SMasahiro Yamada 55d064cbffSMasahiro Yamada #define uniphier_serial_port(dev) \ 56d064cbffSMasahiro Yamada ((struct uniphier_serial_private_data *)dev_get_priv(dev))->membase 57d064cbffSMasahiro Yamada 58d064cbffSMasahiro Yamada int uniphier_serial_setbrg(struct udevice *dev, int baudrate) 597f368553SMasahiro Yamada { 60d064cbffSMasahiro Yamada struct uniphier_serial_platform_data *plat = dev_get_platdata(dev); 61d064cbffSMasahiro Yamada struct uniphier_serial __iomem *port = uniphier_serial_port(dev); 627f368553SMasahiro Yamada const unsigned int mode_x_div = 16; 637f368553SMasahiro Yamada unsigned int divisor; 647f368553SMasahiro Yamada 657f368553SMasahiro Yamada writeb(UART_LCR_WLS_8, &port->lcr); 667f368553SMasahiro Yamada 67d064cbffSMasahiro Yamada divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate); 687f368553SMasahiro Yamada 697f368553SMasahiro Yamada writew(divisor, &port->dlr); 70d064cbffSMasahiro Yamada 71d064cbffSMasahiro Yamada return 0; 727f368553SMasahiro Yamada } 737f368553SMasahiro Yamada 74d064cbffSMasahiro Yamada static int uniphier_serial_getc(struct udevice *dev) 757f368553SMasahiro Yamada { 76d064cbffSMasahiro Yamada struct uniphier_serial __iomem *port = uniphier_serial_port(dev); 777f368553SMasahiro Yamada 78d064cbffSMasahiro Yamada if (!(readb(&port->lsr) & UART_LSR_DR)) 79d064cbffSMasahiro Yamada return -EAGAIN; 807f368553SMasahiro Yamada 817f368553SMasahiro Yamada return readb(&port->rbr); 827f368553SMasahiro Yamada } 837f368553SMasahiro Yamada 84d064cbffSMasahiro Yamada static int uniphier_serial_putc(struct udevice *dev, const char c) 857f368553SMasahiro Yamada { 86d064cbffSMasahiro Yamada struct uniphier_serial __iomem *port = uniphier_serial_port(dev); 877f368553SMasahiro Yamada 88d064cbffSMasahiro Yamada if (!(readb(&port->lsr) & UART_LSR_THRE)) 89d064cbffSMasahiro Yamada return -EAGAIN; 907f368553SMasahiro Yamada 917f368553SMasahiro Yamada writeb(c, &port->thr); 92d064cbffSMasahiro Yamada 93d064cbffSMasahiro Yamada return 0; 947f368553SMasahiro Yamada } 957f368553SMasahiro Yamada 96*bb72148bSMasahiro Yamada static int uniphier_serial_pending(struct udevice *dev, bool input) 97*bb72148bSMasahiro Yamada { 98*bb72148bSMasahiro Yamada struct uniphier_serial __iomem *port = uniphier_serial_port(dev); 99*bb72148bSMasahiro Yamada 100*bb72148bSMasahiro Yamada if (input) 101*bb72148bSMasahiro Yamada return readb(&port->lsr) & UART_LSR_DR; 102*bb72148bSMasahiro Yamada else 103*bb72148bSMasahiro Yamada return !(readb(&port->lsr) & UART_LSR_THRE); 104*bb72148bSMasahiro Yamada } 105*bb72148bSMasahiro Yamada 106d064cbffSMasahiro Yamada int uniphier_serial_probe(struct udevice *dev) 107d064cbffSMasahiro Yamada { 108d064cbffSMasahiro Yamada struct uniphier_serial_private_data *priv = dev_get_priv(dev); 109d064cbffSMasahiro Yamada struct uniphier_serial_platform_data *plat = dev_get_platdata(dev); 110d064cbffSMasahiro Yamada 111d064cbffSMasahiro Yamada priv->membase = map_sysmem(plat->base, sizeof(struct uniphier_serial)); 112d064cbffSMasahiro Yamada 113d064cbffSMasahiro Yamada if (!priv->membase) 114d064cbffSMasahiro Yamada return -ENOMEM; 115d064cbffSMasahiro Yamada 116d064cbffSMasahiro Yamada return 0; 117d064cbffSMasahiro Yamada } 118d064cbffSMasahiro Yamada 119d064cbffSMasahiro Yamada int uniphier_serial_remove(struct udevice *dev) 120d064cbffSMasahiro Yamada { 121d064cbffSMasahiro Yamada unmap_sysmem(uniphier_serial_port(dev)); 122d064cbffSMasahiro Yamada 123d064cbffSMasahiro Yamada return 0; 124d064cbffSMasahiro Yamada } 125d064cbffSMasahiro Yamada 126d064cbffSMasahiro Yamada #ifdef CONFIG_OF_CONTROL 127d064cbffSMasahiro Yamada static const struct udevice_id uniphier_uart_of_match = { 128d064cbffSMasahiro Yamada { .compatible = "panasonic,uniphier-uart"}, 129d064cbffSMasahiro Yamada {}, 1307f368553SMasahiro Yamada }; 1317f368553SMasahiro Yamada 132d064cbffSMasahiro Yamada static int uniphier_serial_ofdata_to_platdata(struct udevice *dev) 1337f368553SMasahiro Yamada { 134d064cbffSMasahiro Yamada /* 135d064cbffSMasahiro Yamada * TODO: Masahiro Yamada (yamada.m@jp.panasonic.com) 136d064cbffSMasahiro Yamada * 137d064cbffSMasahiro Yamada * Implement conversion code from DTB to platform data 138d064cbffSMasahiro Yamada * when supporting CONFIG_OF_CONTROL on UniPhir platform. 139d064cbffSMasahiro Yamada */ 1407f368553SMasahiro Yamada } 141d064cbffSMasahiro Yamada #endif 1427f368553SMasahiro Yamada 143d064cbffSMasahiro Yamada static const struct dm_serial_ops uniphier_serial_ops = { 144d064cbffSMasahiro Yamada .setbrg = uniphier_serial_setbrg, 145d064cbffSMasahiro Yamada .getc = uniphier_serial_getc, 146d064cbffSMasahiro Yamada .putc = uniphier_serial_putc, 147*bb72148bSMasahiro Yamada .pending = uniphier_serial_pending, 148d064cbffSMasahiro Yamada }; 149d064cbffSMasahiro Yamada 150d064cbffSMasahiro Yamada U_BOOT_DRIVER(uniphier_serial) = { 151d064cbffSMasahiro Yamada .name = DRIVER_NAME, 152d064cbffSMasahiro Yamada .id = UCLASS_SERIAL, 153d064cbffSMasahiro Yamada .of_match = of_match_ptr(uniphier_uart_of_match), 154d064cbffSMasahiro Yamada .ofdata_to_platdata = of_match_ptr(uniphier_serial_ofdata_to_platdata), 155d064cbffSMasahiro Yamada .probe = uniphier_serial_probe, 156d064cbffSMasahiro Yamada .remove = uniphier_serial_remove, 157d064cbffSMasahiro Yamada .priv_auto_alloc_size = sizeof(struct uniphier_serial_private_data), 158d064cbffSMasahiro Yamada .platdata_auto_alloc_size = 159d064cbffSMasahiro Yamada sizeof(struct uniphier_serial_platform_data), 160d064cbffSMasahiro Yamada .ops = &uniphier_serial_ops, 161d064cbffSMasahiro Yamada .flags = DM_FLAG_PRE_RELOC, 162d064cbffSMasahiro Yamada }; 163