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