1
2
3
4
5
6
7
8#include "qemu/osdep.h"
9#include "hw/sysbus.h"
10#include "chardev/char.h"
11#include "chardev/char-fe.h"
12#include "migration/vmstate.h"
13#include "hw/qdev-properties.h"
14#include "hw/register.h"
15#include "hw/irq.h"
16#include "qemu/fifo.h"
17#include "hw/remote-port-proto.h"
18#include "hw/remote-port-device.h"
19#include "hw/stream.h"
20#include "qemu/log.h"
21#include "hw/fdt_generic_util.h"
22
23REG32(SBI_MODE, 0x0)
24 FIELD(SBI_MODE, JTAG, 1, 1)
25 FIELD(SBI_MODE, SELECT, 0, 1)
26REG32(SBI_CTRL, 0x4)
27 FIELD(SBI_CTRL, APB_ERR_RES, 5, 1)
28 FIELD(SBI_CTRL, INTERFACE, 2, 3)
29 FIELD(SBI_CTRL, SOFT_RST, 1, 1)
30 FIELD(SBI_CTRL, ENABLE, 0, 1)
31REG32(SMAP_CTRL, 0x8)
32 FIELD(SMAP_CTRL, BURST_SIZE, 1, 2)
33 FIELD(SMAP_CTRL, MODE, 0, 1)
34REG32(SBI_IRQ_STATUS, 0x300)
35 FIELD(SBI_IRQ_STATUS, DATA_RDY, 2, 1)
36 FIELD(SBI_IRQ_STATUS, SMAP_ABORT, 1, 1)
37 FIELD(SBI_IRQ_STATUS, INV_APB, 0, 1)
38REG32(SBI_IRQ_MASK, 0x304)
39 FIELD(SBI_IRQ_MASK, DATA_RDY, 2, 1)
40 FIELD(SBI_IRQ_MASK, SMAP_ABORT, 1, 1)
41 FIELD(SBI_IRQ_MASK, INV_APB, 0, 1)
42REG32(SBI_IRQ_ENABLE, 0x308)
43 FIELD(SBI_IRQ_ENABLE, DATA_RDY, 2, 1)
44 FIELD(SBI_IRQ_ENABLE, SMAP_ABORT, 1, 1)
45 FIELD(SBI_IRQ_ENABLE, INV_APB, 0, 1)
46REG32(SBI_IRQ_DISABLE, 0x30c)
47 FIELD(SBI_IRQ_DISABLE, DATA_RDY, 2, 1)
48 FIELD(SBI_IRQ_DISABLE, SMAP_ABORT, 1, 1)
49 FIELD(SBI_IRQ_DISABLE, INV_APB, 0, 1)
50REG32(SBI_IRQ_TRIGGER, 0x310)
51 FIELD(SBI_IRQ_TRIGGER, DATA_RDY, 2, 1)
52 FIELD(SBI_IRQ_TRIGGER, SMAP_ABORT, 1, 1)
53 FIELD(SBI_IRQ_TRIGGER, INV_APB, 0, 1)
54REG32(SBI_RAM, 0x500)
55 FIELD(SBI_RAM, EMASA, 6, 1)
56 FIELD(SBI_RAM, EMAB, 3, 3)
57 FIELD(SBI_RAM, EMAA, 0, 3)
58REG32(SBI_ECO, 0x1000)
59
60#define R_MAX (R_SBI_ECO + 1)
61
62#define SMAP_INTERFACE 0
63#define JTAG_INTERFACE 1
64#define AXI_SLAVE_INTERFACE 2
65
66#define SBI_DATA_LOADING_MODE 0
67#define SBI_READ_BACK_MODE 1
68
69#define SMAP_NORMAL_MODE 0
70#define SMAP_BURST_MODE 1
71
72#define SMAP_CS_B 1
73#define SMAP_RDWR_B 0
74
75#define TYPE_SBI "pmc.slave-boot"
76
77#define SBI(obj) \
78 OBJECT_CHECK(SlaveBootInt, (obj), TYPE_SBI)
79
80#ifndef SBI_ERR_DEBUG
81#define SBI_ERR_DEBUG 0
82#endif
83
84#define DPRINT(args, ...) \
85 do { \
86 if (SBI_ERR_DEBUG) { \
87 fprintf(stderr, args, ## __VA_ARGS__); \
88 } \
89 } while (0)
90
91#define IF_BURST(pnum) \
92 (ARRAY_FIELD_EX32(s->regs, SMAP_CTRL, MODE) == SMAP_BURST_MODE && \
93 ARRAY_FIELD_EX32(s->regs, SBI_CTRL, INTERFACE) == SMAP_INTERFACE && \
94 (pnum >= (1 << ARRAY_FIELD_EX32(s->regs, SMAP_CTRL, BURST_SIZE)) * 1024))
95
96#define IF_NON_BURST(pnum) \
97 ((ARRAY_FIELD_EX32(s->regs, SMAP_CTRL, MODE) == SMAP_NORMAL_MODE) && \
98 (pnum >= 4))
99
100#define SMAP_BURST_SIZE(s) \
101 ((1 << ARRAY_FIELD_EX32(s->regs, SMAP_CTRL, BURST_SIZE)) * 1024)
102
103typedef struct SlaveBootInt {
104 SysBusDevice parent_obj;
105
106 StreamSlave *tx_dev;
107 Fifo fifo;
108 qemu_irq irq;
109 StreamCanPushNotifyFn notify;
110 void *notify_opaque;
111 MemoryRegion iomem;
112 uint32_t regs[R_MAX];
113 RegisterInfo regs_info[R_MAX];
114 int BusWidthDetectCounter;
115
116
117 uint8_t cs;
118 uint8_t busy_line;
119 uint8_t rdwr;
120
121 CharBackend chr;
122 qemu_irq smap_busy;
123} SlaveBootInt;
124
125static int sbi_can_receive_from_dma(SlaveBootInt *s)
126{
127 if (!ARRAY_FIELD_EX32(s->regs, SBI_MODE, SELECT)) {
128 return 1;
129 }
130
131 if (IF_BURST(fifo_num_free(&s->fifo))) {
132 return 0;
133 }
134
135 if (IF_NON_BURST(fifo_num_free(&s->fifo))) {
136 return 0;
137 }
138
139 return 1;
140}
141
142static void sbi_update_irq(SlaveBootInt *s)
143{
144 bool pending;
145
146 if (IF_BURST(s->fifo.num)) {
147 ARRAY_FIELD_DP32(s->regs, SBI_IRQ_STATUS, DATA_RDY, 1);
148 }
149
150 if (IF_NON_BURST(s->fifo.num)) {
151 ARRAY_FIELD_DP32(s->regs, SBI_IRQ_STATUS, DATA_RDY, 1);
152 }
153 pending = !!(s->regs[R_SBI_IRQ_STATUS] & ~s->regs[R_SBI_IRQ_MASK]);
154 qemu_set_irq(s->irq, pending);
155}
156
157static void ss_update_busy_line(SlaveBootInt *s)
158{
159 uint32_t num = fifo_num_free(&s->fifo);
160
161 if (!ARRAY_FIELD_EX32(s->regs, SBI_CTRL, ENABLE)) {
162 s->busy_line = 1;
163 goto update_busy;
164 }
165
166 if (ARRAY_FIELD_EX32(s->regs, SMAP_CTRL, MODE) == SMAP_BURST_MODE) {
167 if (ARRAY_FIELD_EX32(s->regs, SBI_MODE, SELECT)
168 == SBI_DATA_LOADING_MODE) {
169 s->busy_line = (num >= SMAP_BURST_SIZE(s)) ? 0 : 1;
170 } else {
171
172 s->busy_line = (s->fifo.num >= SMAP_BURST_SIZE(s)) ?
173 0 : 1;
174 if (s->notify) {
175 s->notify(s->notify_opaque);
176 }
177 }
178 } else {
179
180
181
182 if (ARRAY_FIELD_EX32(s->regs, SBI_MODE, SELECT)
183 == SBI_DATA_LOADING_MODE) {
184 s->busy_line = num >= 4 ? 0 : 1;
185 } else {
186 s->busy_line = s->fifo.num >= 4 ? 0 : 1;
187 if (s->notify) {
188 s->notify(s->notify_opaque);
189 }
190 }
191 }
192update_busy:
193
194 qemu_set_irq(s->smap_busy, s->busy_line);
195}
196
197static void ss_stream_out(SlaveBootInt *s);
198static void smap_data_rdwr(SlaveBootInt *s)
199{
200 if (!s->cs) {
201 if (!s->rdwr) {
202 qemu_chr_fe_accept_input(&s->chr);
203 } else {
204 ss_stream_out(s);
205 }
206 }
207
208 ss_update_busy_line(s);
209 sbi_update_irq(s);
210}
211
212static void ss_reset(DeviceState *);
213
214static void sbi_ctrl_postw(RegisterInfo *reg, uint64_t val64)
215{
216 SlaveBootInt *s = SBI(reg->opaque);
217 uint32_t val = val64;
218
219 if (val & R_SBI_CTRL_SOFT_RST_MASK) {
220 ss_reset(DEVICE(s));
221 ARRAY_FIELD_DP32(s->regs, SBI_CTRL, SOFT_RST, 0);
222 }
223
224 ss_update_busy_line(s);
225}
226
227static uint64_t sbi_mode_prew(RegisterInfo *reg, uint64_t val64)
228{
229 SlaveBootInt *s = SBI(reg->opaque);
230 uint32_t val = val64;
231
232 if (!s->cs) {
233 if ((s->regs[R_SBI_MODE] & R_SBI_MODE_SELECT_MASK) ^
234 (val & R_SBI_MODE_SELECT_MASK) && s->smap_busy) {
235 DPRINT("Warning: Changing SBI mode when cs is asserted\n");
236 }
237 }
238
239 if (!s->smap_busy) {
240 s->rdwr = FIELD_EX32(val, SBI_MODE, SELECT);
241 }
242 return val64;
243}
244
245static uint64_t sbi_irq_enable_prew(RegisterInfo *reg, uint64_t val64)
246{
247
248 SlaveBootInt *s = SBI(reg->opaque);
249 uint32_t val = val64;
250
251 s->regs[R_SBI_IRQ_MASK] &= ~val;
252 return 0;
253}
254
255static uint64_t sbi_irq_disable_prew(RegisterInfo *reg, uint64_t val64)
256{
257 SlaveBootInt *s = SBI(reg->opaque);
258 uint32_t val = val64;
259
260 s->regs[R_SBI_IRQ_MASK] |= val;
261 return 0;
262}
263
264static uint64_t sbi_irq_trigger_prew(RegisterInfo *reg, uint64_t val64)
265{
266 SlaveBootInt *s = SBI(reg->opaque);
267 uint32_t val = val64;
268
269 s->regs[R_SBI_IRQ_STATUS] |= val;
270 return 0;
271}
272
273static void ss_stream_notify(void *opaque)
274{
275 SlaveBootInt *s = SBI(opaque);
276 uint32_t num = 0;
277 uint8_t *data;
278
279 while (stream_can_push(s->tx_dev, ss_stream_notify, s)) {
280 if (fifo_is_empty(&s->fifo) || fifo_num_used(&s->fifo) < 4) {
281 break;
282 }
283
284
285
286 data = (uint8_t *) fifo_pop_buf(&s->fifo,
287 4, &num);
288
289 stream_push(s->tx_dev, data, num, false);
290 }
291 ss_update_busy_line(s);
292 sbi_update_irq(s);
293}
294
295static void ss_stream_out(SlaveBootInt *s)
296{
297 uint8_t *data;
298 uint32_t len;
299
300 if (!ARRAY_FIELD_EX32(s->regs, SBI_MODE, SELECT)) {
301 return;
302 }
303
304
305 while (!s->cs && s->rdwr) {
306 if (IF_BURST(s->fifo.num)) {
307 data = (uint8_t *) fifo_pop_buf(&s->fifo,
308 SMAP_BURST_SIZE(s),
309 &len);
310 qemu_chr_fe_write(&s->chr, data, len);
311 }
312
313 if (IF_NON_BURST(s->fifo.num)) {
314 data = (uint8_t *) fifo_pop_buf(&s->fifo, 4, &len);
315 qemu_chr_fe_write(&s->chr, data, len);
316 }
317
318 ss_update_busy_line(s);
319 if (s->busy_line) {
320 break;
321 }
322 }
323}
324
325static bool ss_stream_can_push(StreamSlave *obj,
326 StreamCanPushNotifyFn notify,
327 void *notify_opaque)
328{
329 SlaveBootInt *s = SBI(obj);
330
331
332
333
334
335 if (!s->smap_busy) {
336 smap_data_rdwr(s);
337 }
338 if (sbi_can_receive_from_dma(s)) {
339
340 s->notify = notify;
341 s->notify_opaque = notify_opaque;
342 return false;
343 } else {
344
345 s->notify = NULL;
346 s->notify_opaque = NULL;
347 return true;
348 }
349}
350
351static size_t ss_stream_push(StreamSlave *obj, uint8_t *buf, size_t len,
352 bool eop)
353{
354 SlaveBootInt *s = SBI(obj);
355 uint32_t free = fifo_num_free(&s->fifo);
356
357
358 fifo_push_all(&s->fifo, buf, free);
359 ss_update_busy_line(s);
360 sbi_update_irq(s);
361 return free > len ? len : free;
362}
363
364
365static int ss_sbi_can_receive(void *opaque)
366{
367 SlaveBootInt *s = SBI(opaque);
368 uint32_t num = fifo_num_free(&s->fifo);
369 uint32_t recvb = 0;
370
371 if (s->cs || s->rdwr) {
372
373
374
375 return 0;
376 }
377
378
379
380
381 if (ARRAY_FIELD_EX32(s->regs, SBI_CTRL, ENABLE) &&
382 !ARRAY_FIELD_EX32(s->regs, SBI_MODE, SELECT)) {
383 if (IF_BURST(num)) {
384 recvb = (1 << ARRAY_FIELD_EX32(s->regs, SMAP_CTRL, BURST_SIZE)) *
385 1024;
386 } else if (num >= 4) {
387 recvb = 4;
388 }
389
390 if (!s->busy_line) {
391 return recvb;
392 }
393 }
394 return 0;
395}
396
397static void ss_sbi_receive(void *opaque, const uint8_t *buf, int size)
398{
399 SlaveBootInt *s = SBI(opaque);
400 uint32_t free = fifo_num_free(&s->fifo);
401
402 while (s->BusWidthDetectCounter < 16) {
403
404
405
406
407 s->BusWidthDetectCounter++;
408 buf++;
409 size--;
410 if (!size) {
411 break;
412 }
413 }
414
415 DPRINT("%s: Payload of size: %d recv\n", __func__, size);
416 if (size <= free) {
417 fifo_push_all(&s->fifo, buf, size);
418 if (IF_BURST(free)) {
419 ss_stream_notify(s);
420 ARRAY_FIELD_DP32(s->regs, SBI_IRQ_STATUS, DATA_RDY, 1);
421 }
422
423 if (IF_NON_BURST(free)) {
424 ss_stream_notify(s);
425 ARRAY_FIELD_DP32(s->regs, SBI_IRQ_STATUS, DATA_RDY, 1);
426 }
427 }
428
429 ss_update_busy_line(s);
430 sbi_update_irq(s);
431}
432
433
434static void smap_update(void *opaque, int n, int level)
435{
436 SlaveBootInt *s = SBI(opaque);
437 switch (n) {
438 case SMAP_CS_B:
439 s->cs = level;
440 break;
441 case SMAP_RDWR_B:
442 if (!s->cs && (s->rdwr ^ level)) {
443 ARRAY_FIELD_DP32(s->regs, SBI_IRQ_STATUS, SMAP_ABORT, 1);
444 }
445 s->rdwr = level;
446 break;
447 };
448 smap_data_rdwr(s);
449}
450
451static RegisterAccessInfo slave_boot_regs_info[] = {
452 { .name = "SBI_MODE", .addr = A_SBI_MODE,
453 .reset = 0x2,
454 .rsvd = 0xfffffffe,
455 .pre_write = sbi_mode_prew,
456 },{ .name = "SBI_CTRL", .addr = A_SBI_CTRL,
457 .reset = 0x20,
458 .rsvd = 0xffffffc0,
459 .post_write = sbi_ctrl_postw,
460 },{ .name = "SMAP_CTRL", .addr = A_SMAP_CTRL,
461 .rsvd = 0xfffffff8,
462 },{ .name = "SBI_IRQ_STATUS", .addr = A_SBI_IRQ_STATUS,
463 .rsvd = 0xfffffff8,
464 .w1c = 0x7,
465 },{ .name = "SBI_IRQ_MASK", .addr = A_SBI_IRQ_MASK,
466 .reset = 0x7,
467 .rsvd = 0xfffffff8,
468 .ro = 0x7,
469 },{ .name = "SBI_IRQ_ENABLE", .addr = A_SBI_IRQ_ENABLE,
470 .rsvd = 0xfffffff8,
471 .pre_write = sbi_irq_enable_prew,
472 },{ .name = "SBI_IRQ_DISABLE", .addr = A_SBI_IRQ_DISABLE,
473 .rsvd = 0xfffffff8,
474 .pre_write = sbi_irq_disable_prew,
475 },{ .name = "SBI_IRQ_TRIGGER", .addr = A_SBI_IRQ_TRIGGER,
476 .rsvd = 0xfffffff8,
477 .pre_write = sbi_irq_trigger_prew,
478 },{ .name = "SBI_RAM", .addr = A_SBI_RAM,
479 .reset = 0x5b,
480 .rsvd = 0xffffff80,
481 },{ .name = "SBI_ECO", .addr = A_SBI_ECO,
482 }
483};
484
485static void sbi_write(void *opaque, hwaddr addr, uint64_t value,
486 unsigned size)
487{
488 RegisterInfoArray *reg_array = opaque;
489 SlaveBootInt *s = SBI(reg_array->r[0]->opaque);
490
491 register_write_memory(opaque, addr, value, size);
492 smap_data_rdwr(s);
493}
494
495static const MemoryRegionOps ss_ops = {
496 .read = register_read_memory,
497 .write = sbi_write,
498 .endianness = DEVICE_LITTLE_ENDIAN,
499 .valid = {
500 .min_access_size = 4,
501 .max_access_size = 4
502 }
503};
504
505static void ss_realize(DeviceState *dev, Error **errp)
506{
507 SlaveBootInt *s = SBI(dev);
508 const char *port_name;
509 Chardev *chr;
510
511 port_name = g_strdup("smap_busy_b");
512 qdev_init_gpio_out_named(dev, &s->smap_busy, port_name, 1);
513 g_free((gpointer) port_name);
514
515 port_name = g_strdup("smap_in_b");
516 qdev_init_gpio_in_named(dev, smap_update, port_name, 2);
517 g_free((gpointer) port_name);
518
519 chr = qemu_chr_find("sbi");
520 qdev_prop_set_chr(dev, "chardev", chr);
521 if (!qemu_chr_fe_get_driver(&s->chr)) {
522 DPRINT("SBI interface not connected\n");
523 } else {
524 qemu_chr_fe_set_handlers(&s->chr, ss_sbi_can_receive, ss_sbi_receive,
525 NULL, NULL, s, NULL, true);
526 }
527
528 fifo_create8(&s->fifo, 1024 * 4);
529}
530
531static void ss_reset(DeviceState *dev)
532{
533 SlaveBootInt *s = SBI(dev);
534 uint32_t i;
535
536 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
537 register_reset(&s->regs_info[i]);
538 }
539 fifo_reset(&s->fifo);
540 s->busy_line = 1;
541 qemu_set_irq(s->smap_busy, s->busy_line);
542 ss_update_busy_line(s);
543 sbi_update_irq(s);
544
545
546
547
548
549
550
551
552
553}
554
555static void ss_init(Object *obj)
556{
557 SlaveBootInt *s = SBI(obj);
558 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
559 RegisterInfoArray *reg_array;
560
561 object_property_add_link(obj, "stream-connected-sbi", TYPE_STREAM_SLAVE,
562 (Object **)&s->tx_dev,
563 qdev_prop_allow_set_link_before_realize,
564 OBJ_PROP_LINK_STRONG);
565
566 memory_region_init(&s->iomem, obj, TYPE_SBI, R_MAX * 4);
567 reg_array =
568 register_init_block32(DEVICE(obj), slave_boot_regs_info,
569 ARRAY_SIZE(slave_boot_regs_info),
570 s->regs_info, s->regs,
571 &ss_ops,
572 false,
573 R_MAX * 4);
574 memory_region_add_subregion(&s->iomem,
575 0x0,
576 ®_array->mem);
577
578 sysbus_init_mmio(sbd, &s->iomem);
579 sysbus_init_irq(sbd, &s->irq);
580}
581
582static const FDTGenericGPIOSet sbi_controller_gpios[] = {
583 {
584 .names = &fdt_generic_gpio_name_set_gpio,
585 .gpios = (FDTGenericGPIOConnection []) {
586 { .name = "smap_busy_b", .fdt_index = 0,
587 .range = 1},
588 { },
589 },
590 },
591 { },
592};
593
594static const FDTGenericGPIOSet sbi_client_gpios[] = {
595 {
596 .names = &fdt_generic_gpio_name_set_gpio,
597 .gpios = (FDTGenericGPIOConnection []) {
598 { .name = "smap_in_b", .fdt_index = 0,
599 .range = 2},
600 { },
601 },
602 },
603 { },
604};
605
606static Property sbi_props[] = {
607 DEFINE_PROP_CHR("chardev", SlaveBootInt, chr),
608 DEFINE_PROP_END_OF_LIST(),
609};
610
611static void ss_class_init(ObjectClass *klass, void *data)
612{
613 DeviceClass *dc = DEVICE_CLASS(klass);
614 StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
615 FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);
616 dc->realize = ss_realize;
617 dc->reset = ss_reset;
618 device_class_set_props(dc, sbi_props);
619 ssc->push = ss_stream_push;
620 ssc->can_push = ss_stream_can_push;
621 fggc->controller_gpios = sbi_controller_gpios;
622 fggc->client_gpios = sbi_client_gpios;
623}
624
625static TypeInfo ss_info = {
626 .name = TYPE_SBI,
627 .parent = TYPE_SYS_BUS_DEVICE,
628 .instance_size = sizeof(SlaveBootInt),
629 .instance_init = ss_init,
630 .class_init = ss_class_init,
631 .interfaces = (InterfaceInfo[]) {
632 { TYPE_STREAM_SLAVE },
633 { TYPE_FDT_GENERIC_GPIO},
634 {}
635 }
636};
637
638static void ss_register(void)
639{
640 type_register_static(&ss_info);
641}
642
643type_init(ss_register)
644