2 * Support for Serial I/O using STMicroelectronics' on-chip ASC.
4 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
5 * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
7 * SPDX-License-Identifier: GPL-2.0+
15 DECLARE_GLOBAL_DATA_PTR
;
17 #define BAUDMODE 0x00001000
18 #define RXENABLE 0x00000100
19 #define RUN 0x00000080
20 #define MODE 0x00000001
21 #define MODE_8BIT 0x0001
22 #define STOP_1BIT 0x0008
23 #define PARITYODD 0x0020
26 #define STA_RBF BIT(0)
41 struct sti_asc_serial
{
42 /* address of registers in physical memory */
43 struct sti_asc_uart
*regs
;
46 /* Values for the BAUDRATE Register */
47 #define PCLK (200ul * 1000000ul)
48 #define BAUDRATE_VAL_M0(bps) (PCLK / (16 * (bps)))
49 #define BAUDRATE_VAL_M1(bps) ((bps * (1 << 14)) + (1<<13)) / (PCLK/(1 << 6))
54 * ASCBaudRate = ----------------
58 * baudrate * 16 * 2^16
59 * ASCBaudRate = ------------------------
63 * Mode 1 should be used for baudrates of 19200, and above, as it
64 * has a lower deviation error than Mode 0 for higher frequencies.
65 * Mode 0 should be used for all baudrates below 19200.
68 static int sti_asc_pending(struct udevice
*dev
, bool input
)
70 struct sti_asc_serial
*priv
= dev_get_priv(dev
);
71 struct sti_asc_uart
*const uart
= priv
->regs
;
74 status
= readl(&uart
->status
);
76 return status
& STA_RBF
;
78 return status
& STA_TF
;
81 static int _sti_asc_serial_setbrg(struct sti_asc_uart
*uart
, int baudrate
)
88 t
= BAUDRATE_VAL_M0(9600);
92 t
= BAUDRATE_VAL_M1(19200);
95 t
= BAUDRATE_VAL_M1(38400);
98 t
= BAUDRATE_VAL_M1(57600);
101 debug("ASC: unsupported baud rate: %d, using 115200 instead.\n",
104 t
= BAUDRATE_VAL_M1(115200);
108 /* disable the baudrate generator */
109 val
= readl(&uart
->control
);
110 writel(val
& ~RUN
, &uart
->control
);
112 /* set baud generator reload value */
113 writel(t
, &uart
->baudrate
);
114 /* reset the RX & TX buffers */
115 writel(1, &uart
->txreset
);
116 writel(1, &uart
->rxreset
);
118 /* set baud generator mode */
122 /* finally, write value and enable ASC */
123 writel(val
, &uart
->control
);
128 /* called to adjust baud-rate */
129 static int sti_asc_serial_setbrg(struct udevice
*dev
, int baudrate
)
131 struct sti_asc_serial
*priv
= dev_get_priv(dev
);
132 struct sti_asc_uart
*const uart
= priv
->regs
;
134 return _sti_asc_serial_setbrg(uart
, baudrate
);
137 /* blocking function, that returns next char */
138 static int sti_asc_serial_getc(struct udevice
*dev
)
140 struct sti_asc_serial
*priv
= dev_get_priv(dev
);
141 struct sti_asc_uart
*const uart
= priv
->regs
;
143 /* polling wait: for a char to be read */
144 if (!sti_asc_pending(dev
, true))
147 return readl(&uart
->rxbuf
);
150 /* write write out a single char */
151 static int sti_asc_serial_putc(struct udevice
*dev
, const char c
)
153 struct sti_asc_serial
*priv
= dev_get_priv(dev
);
154 struct sti_asc_uart
*const uart
= priv
->regs
;
156 /* wait till safe to write next char */
157 if (sti_asc_pending(dev
, false))
160 /* finally, write next char */
161 writel(c
, &uart
->txbuf
);
166 /* initialize the ASC */
167 static int sti_asc_serial_probe(struct udevice
*dev
)
169 struct sti_asc_serial
*priv
= dev_get_priv(dev
);
173 base
= devfdt_get_addr(dev
);
174 if (base
== FDT_ADDR_T_NONE
)
177 priv
->regs
= (struct sti_asc_uart
*)base
;
178 sti_asc_serial_setbrg(dev
, gd
->baudrate
);
181 * build up the value to be written to CONTROL
182 * set character length, bit stop number, odd parity
184 val
= RXENABLE
| RUN
| MODE_8BIT
| STOP_1BIT
| PARITYODD
;
185 writel(val
, &priv
->regs
->control
);
190 static const struct dm_serial_ops sti_asc_serial_ops
= {
191 .putc
= sti_asc_serial_putc
,
192 .pending
= sti_asc_pending
,
193 .getc
= sti_asc_serial_getc
,
194 .setbrg
= sti_asc_serial_setbrg
,
197 static const struct udevice_id sti_serial_of_match
[] = {
198 { .compatible
= "st,asc" },
202 U_BOOT_DRIVER(serial_sti_asc
) = {
203 .name
= "serial_sti_asc",
205 .of_match
= sti_serial_of_match
,
206 .ops
= &sti_asc_serial_ops
,
207 .probe
= sti_asc_serial_probe
,
208 .priv_auto_alloc_size
= sizeof(struct sti_asc_serial
),
209 .flags
= DM_FLAG_PRE_RELOC
,