Merge remote-tracking branch 'remotes/philmd-gitlab/tags/renesas-20201027' into staging
[qemu.git] / hw / char / renesas_sci.c
1 /*
2 * Renesas Serial Communication Interface
3 *
4 * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
5 * (Rev.1.40 R01UH0033EJ0140)
6 *
7 * Copyright (c) 2019 Yoshinori Sato
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms and conditions of the GNU General Public License,
13 * version 2 or later, as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "qemu/osdep.h"
25 #include "qemu/log.h"
26 #include "hw/irq.h"
27 #include "hw/registerfields.h"
28 #include "hw/qdev-properties.h"
29 #include "hw/char/renesas_sci.h"
30 #include "migration/vmstate.h"
31
32 /* SCI register map */
33 REG8(SMR, 0)
34 FIELD(SMR, CKS, 0, 2)
35 FIELD(SMR, MP, 2, 1)
36 FIELD(SMR, STOP, 3, 1)
37 FIELD(SMR, PM, 4, 1)
38 FIELD(SMR, PE, 5, 1)
39 FIELD(SMR, CHR, 6, 1)
40 FIELD(SMR, CM, 7, 1)
41 REG8(BRR, 1)
42 REG8(SCR, 2)
43 FIELD(SCR, CKE, 0, 2)
44 FIELD(SCR, TEIE, 2, 1)
45 FIELD(SCR, MPIE, 3, 1)
46 FIELD(SCR, RE, 4, 1)
47 FIELD(SCR, TE, 5, 1)
48 FIELD(SCR, RIE, 6, 1)
49 FIELD(SCR, TIE, 7, 1)
50 REG8(TDR, 3)
51 REG8(SSR, 4)
52 FIELD(SSR, MPBT, 0, 1)
53 FIELD(SSR, MPB, 1, 1)
54 FIELD(SSR, TEND, 2, 1)
55 FIELD(SSR, ERR, 3, 3)
56 FIELD(SSR, PER, 3, 1)
57 FIELD(SSR, FER, 4, 1)
58 FIELD(SSR, ORER, 5, 1)
59 FIELD(SSR, RDRF, 6, 1)
60 FIELD(SSR, TDRE, 7, 1)
61 REG8(RDR, 5)
62 REG8(SCMR, 6)
63 FIELD(SCMR, SMIF, 0, 1)
64 FIELD(SCMR, SINV, 2, 1)
65 FIELD(SCMR, SDIR, 3, 1)
66 FIELD(SCMR, BCP2, 7, 1)
67 REG8(SEMR, 7)
68 FIELD(SEMR, ACS0, 0, 1)
69 FIELD(SEMR, ABCS, 4, 1)
70
71 static int can_receive(void *opaque)
72 {
73 RSCIState *sci = RSCI(opaque);
74 if (sci->rx_next > qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) {
75 return 0;
76 } else {
77 return FIELD_EX8(sci->scr, SCR, RE);
78 }
79 }
80
81 static void receive(void *opaque, const uint8_t *buf, int size)
82 {
83 RSCIState *sci = RSCI(opaque);
84 sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime;
85 if (FIELD_EX8(sci->ssr, SSR, RDRF) || size > 1) {
86 sci->ssr = FIELD_DP8(sci->ssr, SSR, ORER, 1);
87 if (FIELD_EX8(sci->scr, SCR, RIE)) {
88 qemu_set_irq(sci->irq[ERI], 1);
89 }
90 } else {
91 sci->rdr = buf[0];
92 sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 1);
93 if (FIELD_EX8(sci->scr, SCR, RIE)) {
94 qemu_irq_pulse(sci->irq[RXI]);
95 }
96 }
97 }
98
99 static void send_byte(RSCIState *sci)
100 {
101 if (qemu_chr_fe_backend_connected(&sci->chr)) {
102 qemu_chr_fe_write_all(&sci->chr, &sci->tdr, 1);
103 }
104 timer_mod(&sci->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime);
105 sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 0);
106 sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1);
107 qemu_set_irq(sci->irq[TEI], 0);
108 if (FIELD_EX8(sci->scr, SCR, TIE)) {
109 qemu_irq_pulse(sci->irq[TXI]);
110 }
111 }
112
113 static void txend(void *opaque)
114 {
115 RSCIState *sci = RSCI(opaque);
116 if (!FIELD_EX8(sci->ssr, SSR, TDRE)) {
117 send_byte(sci);
118 } else {
119 sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1);
120 if (FIELD_EX8(sci->scr, SCR, TEIE)) {
121 qemu_set_irq(sci->irq[TEI], 1);
122 }
123 }
124 }
125
126 static void update_trtime(RSCIState *sci)
127 {
128 /* char per bits */
129 sci->trtime = 8 - FIELD_EX8(sci->smr, SMR, CHR);
130 sci->trtime += FIELD_EX8(sci->smr, SMR, PE);
131 sci->trtime += FIELD_EX8(sci->smr, SMR, STOP) + 1;
132 /* x bit transmit time (32 * divrate * brr) / base freq */
133 sci->trtime *= 32 * sci->brr;
134 sci->trtime *= 1 << (2 * FIELD_EX8(sci->smr, SMR, CKS));
135 sci->trtime *= NANOSECONDS_PER_SECOND;
136 sci->trtime /= sci->input_freq;
137 }
138
139 static bool sci_is_tr_enabled(RSCIState *sci)
140 {
141 return FIELD_EX8(sci->scr, SCR, TE) || FIELD_EX8(sci->scr, SCR, RE);
142 }
143
144 static void sci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
145 {
146 RSCIState *sci = RSCI(opaque);
147
148 switch (offset) {
149 case A_SMR:
150 if (!sci_is_tr_enabled(sci)) {
151 sci->smr = val;
152 update_trtime(sci);
153 }
154 break;
155 case A_BRR:
156 if (!sci_is_tr_enabled(sci)) {
157 sci->brr = val;
158 update_trtime(sci);
159 }
160 break;
161 case A_SCR:
162 sci->scr = val;
163 if (FIELD_EX8(sci->scr, SCR, TE)) {
164 sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1);
165 sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1);
166 if (FIELD_EX8(sci->scr, SCR, TIE)) {
167 qemu_irq_pulse(sci->irq[TXI]);
168 }
169 }
170 if (!FIELD_EX8(sci->scr, SCR, TEIE)) {
171 qemu_set_irq(sci->irq[TEI], 0);
172 }
173 if (!FIELD_EX8(sci->scr, SCR, RIE)) {
174 qemu_set_irq(sci->irq[ERI], 0);
175 }
176 break;
177 case A_TDR:
178 sci->tdr = val;
179 if (FIELD_EX8(sci->ssr, SSR, TEND)) {
180 send_byte(sci);
181 } else {
182 sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 0);
183 }
184 break;
185 case A_SSR:
186 sci->ssr = FIELD_DP8(sci->ssr, SSR, MPBT,
187 FIELD_EX8(val, SSR, MPBT));
188 sci->ssr = FIELD_DP8(sci->ssr, SSR, ERR,
189 FIELD_EX8(val, SSR, ERR) & 0x07);
190 if (FIELD_EX8(sci->read_ssr, SSR, ERR) &&
191 FIELD_EX8(sci->ssr, SSR, ERR) == 0) {
192 qemu_set_irq(sci->irq[ERI], 0);
193 }
194 break;
195 case A_RDR:
196 qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: RDR is read only.\n");
197 break;
198 case A_SCMR:
199 sci->scmr = val; break;
200 case A_SEMR: /* SEMR */
201 sci->semr = val; break;
202 default:
203 qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX " "
204 "not implemented\n",
205 offset);
206 }
207 }
208
209 static uint64_t sci_read(void *opaque, hwaddr offset, unsigned size)
210 {
211 RSCIState *sci = RSCI(opaque);
212
213 switch (offset) {
214 case A_SMR:
215 return sci->smr;
216 case A_BRR:
217 return sci->brr;
218 case A_SCR:
219 return sci->scr;
220 case A_TDR:
221 return sci->tdr;
222 case A_SSR:
223 sci->read_ssr = sci->ssr;
224 return sci->ssr;
225 case A_RDR:
226 sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 0);
227 return sci->rdr;
228 case A_SCMR:
229 return sci->scmr;
230 case A_SEMR:
231 return sci->semr;
232 default:
233 qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX
234 " not implemented.\n", offset);
235 }
236 return UINT64_MAX;
237 }
238
239 static const MemoryRegionOps sci_ops = {
240 .write = sci_write,
241 .read = sci_read,
242 .endianness = DEVICE_NATIVE_ENDIAN,
243 .impl.max_access_size = 1,
244 .valid.max_access_size = 1,
245 };
246
247 static void rsci_reset(DeviceState *dev)
248 {
249 RSCIState *sci = RSCI(dev);
250 sci->smr = sci->scr = 0x00;
251 sci->brr = 0xff;
252 sci->tdr = 0xff;
253 sci->rdr = 0x00;
254 sci->ssr = 0x84;
255 sci->scmr = 0x00;
256 sci->semr = 0x00;
257 sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
258 }
259
260 static void sci_event(void *opaque, QEMUChrEvent event)
261 {
262 RSCIState *sci = RSCI(opaque);
263 if (event == CHR_EVENT_BREAK) {
264 sci->ssr = FIELD_DP8(sci->ssr, SSR, FER, 1);
265 if (FIELD_EX8(sci->scr, SCR, RIE)) {
266 qemu_set_irq(sci->irq[ERI], 1);
267 }
268 }
269 }
270
271 static void rsci_realize(DeviceState *dev, Error **errp)
272 {
273 RSCIState *sci = RSCI(dev);
274
275 if (sci->input_freq == 0) {
276 qemu_log_mask(LOG_GUEST_ERROR,
277 "renesas_sci: input-freq property must be set.");
278 return;
279 }
280 qemu_chr_fe_set_handlers(&sci->chr, can_receive, receive,
281 sci_event, NULL, sci, NULL, true);
282 }
283
284 static void rsci_init(Object *obj)
285 {
286 SysBusDevice *d = SYS_BUS_DEVICE(obj);
287 RSCIState *sci = RSCI(obj);
288 int i;
289
290 memory_region_init_io(&sci->memory, OBJECT(sci), &sci_ops,
291 sci, "renesas-sci", 0x8);
292 sysbus_init_mmio(d, &sci->memory);
293
294 for (i = 0; i < SCI_NR_IRQ; i++) {
295 sysbus_init_irq(d, &sci->irq[i]);
296 }
297 timer_init_ns(&sci->timer, QEMU_CLOCK_VIRTUAL, txend, sci);
298 }
299
300 static const VMStateDescription vmstate_rsci = {
301 .name = "renesas-sci",
302 .version_id = 1,
303 .minimum_version_id = 1,
304 .fields = (VMStateField[]) {
305 VMSTATE_INT64(trtime, RSCIState),
306 VMSTATE_INT64(rx_next, RSCIState),
307 VMSTATE_UINT8(smr, RSCIState),
308 VMSTATE_UINT8(brr, RSCIState),
309 VMSTATE_UINT8(scr, RSCIState),
310 VMSTATE_UINT8(tdr, RSCIState),
311 VMSTATE_UINT8(ssr, RSCIState),
312 VMSTATE_UINT8(rdr, RSCIState),
313 VMSTATE_UINT8(scmr, RSCIState),
314 VMSTATE_UINT8(semr, RSCIState),
315 VMSTATE_UINT8(read_ssr, RSCIState),
316 VMSTATE_TIMER(timer, RSCIState),
317 VMSTATE_END_OF_LIST()
318 }
319 };
320
321 static Property rsci_properties[] = {
322 DEFINE_PROP_UINT64("input-freq", RSCIState, input_freq, 0),
323 DEFINE_PROP_CHR("chardev", RSCIState, chr),
324 DEFINE_PROP_END_OF_LIST(),
325 };
326
327 static void rsci_class_init(ObjectClass *klass, void *data)
328 {
329 DeviceClass *dc = DEVICE_CLASS(klass);
330
331 dc->realize = rsci_realize;
332 dc->vmsd = &vmstate_rsci;
333 dc->reset = rsci_reset;
334 device_class_set_props(dc, rsci_properties);
335 }
336
337 static const TypeInfo rsci_info = {
338 .name = TYPE_RENESAS_SCI,
339 .parent = TYPE_SYS_BUS_DEVICE,
340 .instance_size = sizeof(RSCIState),
341 .instance_init = rsci_init,
342 .class_init = rsci_class_init,
343 };
344
345 static void rsci_register_types(void)
346 {
347 type_register_static(&rsci_info);
348 }
349
350 type_init(rsci_register_types)