Home | History | Annotate | Download | only in serial
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Support for Serial I/O using STMicroelectronics' on-chip ASC.
      4  *
      5  * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
      6  * Author(s): Patrice Chotard, <patrice.chotard (at) st.com> for STMicroelectronics.
      7  */
      8 
      9 #include <common.h>
     10 #include <dm.h>
     11 #include <serial.h>
     12 #include <asm/io.h>
     13 
     14 DECLARE_GLOBAL_DATA_PTR;
     15 
     16 #define BAUDMODE	0x00001000
     17 #define RXENABLE	0x00000100
     18 #define RUN		0x00000080
     19 #define MODE		0x00000001
     20 #define MODE_8BIT	0x0001
     21 #define STOP_1BIT	0x0008
     22 #define PARITYODD	0x0020
     23 
     24 #define STA_TF		BIT(9)
     25 #define STA_RBF		BIT(0)
     26 
     27 struct sti_asc_uart {
     28 	u32 baudrate;
     29 	u32 txbuf;
     30 	u32 rxbuf;
     31 	u32 control;
     32 	u32 inten;
     33 	u32 status;
     34 	u32 guardtime;
     35 	u32 timeout;
     36 	u32 txreset;
     37 	u32 rxreset;
     38 };
     39 
     40 struct sti_asc_serial {
     41 	/* address of registers in physical memory */
     42 	struct sti_asc_uart *regs;
     43 };
     44 
     45 /* Values for the BAUDRATE Register */
     46 #define PCLK			(200ul * 1000000ul)
     47 #define BAUDRATE_VAL_M0(bps)	(PCLK / (16 * (bps)))
     48 #define BAUDRATE_VAL_M1(bps)	((bps * (1 << 14)) + (1<<13)) / (PCLK/(1 << 6))
     49 
     50 /*
     51  * MODE 0
     52  *                       ICCLK
     53  * ASCBaudRate =   ----------------
     54  *                   baudrate * 16
     55  *
     56  * MODE 1
     57  *                   baudrate * 16 * 2^16
     58  * ASCBaudRate =   ------------------------
     59  *                          ICCLK
     60  *
     61  * NOTE:
     62  * Mode 1 should be used for baudrates of 19200, and above, as it
     63  * has a lower deviation error than Mode 0 for higher frequencies.
     64  * Mode 0 should be used for all baudrates below 19200.
     65  */
     66 
     67 static int sti_asc_pending(struct udevice *dev, bool input)
     68 {
     69 	struct sti_asc_serial *priv = dev_get_priv(dev);
     70 	struct sti_asc_uart *const uart = priv->regs;
     71 	unsigned long status;
     72 
     73 	status = readl(&uart->status);
     74 	if (input)
     75 		return status & STA_RBF;
     76 	else
     77 		return status & STA_TF;
     78 }
     79 
     80 static int _sti_asc_serial_setbrg(struct sti_asc_uart *uart, int baudrate)
     81 {
     82 	unsigned long val;
     83 	int t, mode = 1;
     84 
     85 	switch (baudrate) {
     86 	case 9600:
     87 		t = BAUDRATE_VAL_M0(9600);
     88 		mode = 0;
     89 		break;
     90 	case 19200:
     91 		t = BAUDRATE_VAL_M1(19200);
     92 		break;
     93 	case 38400:
     94 		t = BAUDRATE_VAL_M1(38400);
     95 		break;
     96 	case 57600:
     97 		t = BAUDRATE_VAL_M1(57600);
     98 		break;
     99 	default:
    100 		debug("ASC: unsupported baud rate: %d, using 115200 instead.\n",
    101 		      baudrate);
    102 	case 115200:
    103 		t = BAUDRATE_VAL_M1(115200);
    104 		break;
    105 	}
    106 
    107 	/* disable the baudrate generator */
    108 	val = readl(&uart->control);
    109 	writel(val & ~RUN, &uart->control);
    110 
    111 	/* set baud generator reload value */
    112 	writel(t, &uart->baudrate);
    113 	/* reset the RX & TX buffers */
    114 	writel(1, &uart->txreset);
    115 	writel(1, &uart->rxreset);
    116 
    117 	/* set baud generator mode */
    118 	if (mode)
    119 		val |= BAUDMODE;
    120 
    121 	/* finally, write value and enable ASC */
    122 	writel(val, &uart->control);
    123 
    124 	return 0;
    125 }
    126 
    127 /* called to adjust baud-rate */
    128 static int sti_asc_serial_setbrg(struct udevice *dev, int baudrate)
    129 {
    130 	struct sti_asc_serial *priv = dev_get_priv(dev);
    131 	struct sti_asc_uart *const uart = priv->regs;
    132 
    133 	return _sti_asc_serial_setbrg(uart, baudrate);
    134 }
    135 
    136 /* blocking function, that returns next char */
    137 static int sti_asc_serial_getc(struct udevice *dev)
    138 {
    139 	struct sti_asc_serial *priv = dev_get_priv(dev);
    140 	struct sti_asc_uart *const uart = priv->regs;
    141 
    142 	/* polling wait: for a char to be read */
    143 	if (!sti_asc_pending(dev, true))
    144 		return -EAGAIN;
    145 
    146 	return readl(&uart->rxbuf);
    147 }
    148 
    149 /* write write out a single char */
    150 static int sti_asc_serial_putc(struct udevice *dev, const char c)
    151 {
    152 	struct sti_asc_serial *priv = dev_get_priv(dev);
    153 	struct sti_asc_uart *const uart = priv->regs;
    154 
    155 	/* wait till safe to write next char */
    156 	if (sti_asc_pending(dev, false))
    157 		return -EAGAIN;
    158 
    159 	/* finally, write next char */
    160 	writel(c, &uart->txbuf);
    161 
    162 	return 0;
    163 }
    164 
    165 /* initialize the ASC */
    166 static int sti_asc_serial_probe(struct udevice *dev)
    167 {
    168 	struct sti_asc_serial *priv = dev_get_priv(dev);
    169 	unsigned long val;
    170 	fdt_addr_t base;
    171 
    172 	base = devfdt_get_addr(dev);
    173 	if (base == FDT_ADDR_T_NONE)
    174 		return -EINVAL;
    175 
    176 	priv->regs = (struct sti_asc_uart *)base;
    177 	sti_asc_serial_setbrg(dev, gd->baudrate);
    178 
    179 	/*
    180 	 * build up the value to be written to CONTROL
    181 	 * set character length, bit stop number, odd parity
    182 	 */
    183 	val = RXENABLE | RUN | MODE_8BIT | STOP_1BIT | PARITYODD;
    184 	writel(val, &priv->regs->control);
    185 
    186 	return 0;
    187 }
    188 
    189 static const struct dm_serial_ops sti_asc_serial_ops = {
    190 	.putc = sti_asc_serial_putc,
    191 	.pending = sti_asc_pending,
    192 	.getc = sti_asc_serial_getc,
    193 	.setbrg = sti_asc_serial_setbrg,
    194 };
    195 
    196 static const struct udevice_id sti_serial_of_match[] = {
    197 	{ .compatible = "st,asc" },
    198 	{ }
    199 };
    200 
    201 U_BOOT_DRIVER(serial_sti_asc) = {
    202 	.name = "serial_sti_asc",
    203 	.id = UCLASS_SERIAL,
    204 	.of_match = sti_serial_of_match,
    205 	.ops = &sti_asc_serial_ops,
    206 	.probe = sti_asc_serial_probe,
    207 	.priv_auto_alloc_size = sizeof(struct sti_asc_serial),
    208 	.flags = DM_FLAG_PRE_RELOC,
    209 };
    210 
    211