10
#include "qemu/osdep.h"
12
#include "migration/vmstate.h"
14
#include "qemu/module.h"
15
#include "hw/dma/pl080.h"
18
#include "hw/qdev-properties.h"
19
#include "qapi/error.h"
21
#define PL080_CONF_E 0x1
22
#define PL080_CONF_M1 0x2
23
#define PL080_CONF_M2 0x4
25
#define PL080_CCONF_H 0x40000
26
#define PL080_CCONF_A 0x20000
27
#define PL080_CCONF_L 0x10000
28
#define PL080_CCONF_ITC 0x08000
29
#define PL080_CCONF_IE 0x04000
30
#define PL080_CCONF_E 0x00001
32
#define PL080_CCTRL_I 0x80000000
33
#define PL080_CCTRL_DI 0x08000000
34
#define PL080_CCTRL_SI 0x04000000
35
#define PL080_CCTRL_D 0x02000000
36
#define PL080_CCTRL_S 0x01000000
38
static const VMStateDescription vmstate_pl080_channel = {
39
.name = "pl080_channel",
41
.minimum_version_id = 1,
42
.fields = (const VMStateField[]) {
43
VMSTATE_UINT32(src, pl080_channel),
44
VMSTATE_UINT32(dest, pl080_channel),
45
VMSTATE_UINT32(lli, pl080_channel),
46
VMSTATE_UINT32(ctrl, pl080_channel),
47
VMSTATE_UINT32(conf, pl080_channel),
52
static const VMStateDescription vmstate_pl080 = {
55
.minimum_version_id = 1,
56
.fields = (const VMStateField[]) {
57
VMSTATE_UINT8(tc_int, PL080State),
58
VMSTATE_UINT8(tc_mask, PL080State),
59
VMSTATE_UINT8(err_int, PL080State),
60
VMSTATE_UINT8(err_mask, PL080State),
61
VMSTATE_UINT32(conf, PL080State),
62
VMSTATE_UINT32(sync, PL080State),
63
VMSTATE_UINT32(req_single, PL080State),
64
VMSTATE_UINT32(req_burst, PL080State),
65
VMSTATE_UINT8(tc_int, PL080State),
66
VMSTATE_UINT8(tc_int, PL080State),
67
VMSTATE_UINT8(tc_int, PL080State),
68
VMSTATE_STRUCT_ARRAY(chan, PL080State, PL080_MAX_CHANNELS,
69
1, vmstate_pl080_channel, pl080_channel),
70
VMSTATE_INT32(running, PL080State),
75
static const unsigned char pl080_id[] =
76
{ 0x80, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
78
static const unsigned char pl081_id[] =
79
{ 0x81, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
81
static void pl080_update(PL080State *s)
83
bool tclevel = (s->tc_int & s->tc_mask);
84
bool errlevel = (s->err_int & s->err_mask);
86
qemu_set_irq(s->interr, errlevel);
87
qemu_set_irq(s->inttc, tclevel);
88
qemu_set_irq(s->irq, errlevel || tclevel);
91
static void pl080_run(PL080State *s)
107
for (c = 0; c < s->nchannels; c++) {
108
if (s->chan[c].conf & PL080_CCONF_ITC)
109
s->tc_mask |= 1 << c;
110
if (s->chan[c].conf & PL080_CCONF_IE)
111
s->err_mask |= 1 << c;
114
if ((s->conf & PL080_CONF_E) == 0)
125
for (c = 0; c < s->nchannels; c++) {
129
if ((ch->conf & (PL080_CCONF_H | PL080_CCONF_E))
132
flow = (ch->conf >> 11) & 7;
135
"pl080_run: Peripheral flow control not implemented\n");
137
src_id = (ch->conf >> 1) & 0x1f;
138
dest_id = (ch->conf >> 6) & 0x1f;
139
size = ch->ctrl & 0xfff;
140
req = s->req_single | s->req_burst;
145
if ((req & (1u << dest_id)) == 0)
149
if ((req & (1u << src_id)) == 0)
153
if ((req & (1u << src_id)) == 0
154
|| (req & (1u << dest_id)) == 0)
165
swidth = 1 << ((ch->ctrl >> 18) & 7);
166
dwidth = 1 << ((ch->ctrl >> 21) & 7);
167
for (n = 0; n < dwidth; n+= swidth) {
168
address_space_read(&s->downstream_as, ch->src,
169
MEMTXATTRS_UNSPECIFIED, buff + n, swidth);
170
if (ch->ctrl & PL080_CCTRL_SI)
173
xsize = (dwidth < swidth) ? swidth : dwidth;
175
for (n = 0; n < xsize; n += dwidth) {
176
address_space_write(&s->downstream_as, ch->dest + n,
177
MEMTXATTRS_UNSPECIFIED, buff + n, dwidth);
178
if (ch->ctrl & PL080_CCTRL_DI)
183
ch->ctrl = (ch->ctrl & 0xfffff000) | size;
187
ch->src = address_space_ldl_le(&s->downstream_as,
189
MEMTXATTRS_UNSPECIFIED,
191
ch->dest = address_space_ldl_le(&s->downstream_as,
193
MEMTXATTRS_UNSPECIFIED,
195
ch->ctrl = address_space_ldl_le(&s->downstream_as,
197
MEMTXATTRS_UNSPECIFIED,
199
ch->lli = address_space_ldl_le(&s->downstream_as,
201
MEMTXATTRS_UNSPECIFIED,
204
ch->conf &= ~PL080_CCONF_E;
206
if (ch->ctrl & PL080_CCTRL_I) {
217
static uint64_t pl080_read(void *opaque, hwaddr offset,
220
PL080State *s = (PL080State *)opaque;
224
if (offset >= 0xfe0 && offset < 0x1000) {
225
if (s->nchannels == 8) {
226
return pl080_id[(offset - 0xfe0) >> 2];
228
return pl081_id[(offset - 0xfe0) >> 2];
231
if (offset >= 0x100 && offset < 0x200) {
232
i = (offset & 0xe0) >> 5;
233
if (i >= s->nchannels)
235
switch ((offset >> 2) & 7) {
237
return s->chan[i].src;
239
return s->chan[i].dest;
241
return s->chan[i].lli;
243
return s->chan[i].ctrl;
245
return s->chan[i].conf;
250
switch (offset >> 2) {
252
return (s->tc_int & s->tc_mask) | (s->err_int & s->err_mask);
254
return (s->tc_int & s->tc_mask);
256
return (s->err_int & s->err_mask);
263
for (i = 0; i < s->nchannels; i++) {
264
if (s->chan[i].conf & PL080_CCONF_E)
280
qemu_log_mask(LOG_GUEST_ERROR,
281
"pl080_read: Bad offset %x\n", (int)offset);
286
static void pl080_write(void *opaque, hwaddr offset,
287
uint64_t value, unsigned size)
289
PL080State *s = (PL080State *)opaque;
292
if (offset >= 0x100 && offset < 0x200) {
293
i = (offset & 0xe0) >> 5;
294
if (i >= s->nchannels)
296
switch ((offset >> 2) & 7) {
298
s->chan[i].src = value;
301
s->chan[i].dest = value;
304
s->chan[i].lli = value;
307
s->chan[i].ctrl = value;
310
s->chan[i].conf = value;
316
switch (offset >> 2) {
321
s->err_int &= ~value;
328
qemu_log_mask(LOG_UNIMP, "pl080_write: Soft DMA not implemented\n");
332
if (s->conf & (PL080_CONF_M1 | PL080_CONF_M2)) {
333
qemu_log_mask(LOG_UNIMP,
334
"pl080_write: Big-endian DMA not implemented\n");
343
qemu_log_mask(LOG_GUEST_ERROR,
344
"pl080_write: Bad offset %x\n", (int)offset);
349
static const MemoryRegionOps pl080_ops = {
351
.write = pl080_write,
352
.endianness = DEVICE_NATIVE_ENDIAN,
355
static void pl080_reset(DeviceState *dev)
357
PL080State *s = PL080(dev);
370
for (i = 0; i < s->nchannels; i++) {
379
static void pl080_init(Object *obj)
381
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
382
PL080State *s = PL080(obj);
384
memory_region_init_io(&s->iomem, OBJECT(s), &pl080_ops, s, "pl080", 0x1000);
385
sysbus_init_mmio(sbd, &s->iomem);
386
sysbus_init_irq(sbd, &s->irq);
387
sysbus_init_irq(sbd, &s->interr);
388
sysbus_init_irq(sbd, &s->inttc);
392
static void pl080_realize(DeviceState *dev, Error **errp)
394
PL080State *s = PL080(dev);
396
if (!s->downstream) {
397
error_setg(errp, "PL080 'downstream' link not set");
401
address_space_init(&s->downstream_as, s->downstream, "pl080-downstream");
404
static void pl081_init(Object *obj)
406
PL080State *s = PL080(obj);
411
static Property pl080_properties[] = {
412
DEFINE_PROP_LINK("downstream", PL080State, downstream,
413
TYPE_MEMORY_REGION, MemoryRegion *),
414
DEFINE_PROP_END_OF_LIST(),
417
static void pl080_class_init(ObjectClass *oc, void *data)
419
DeviceClass *dc = DEVICE_CLASS(oc);
421
dc->vmsd = &vmstate_pl080;
422
dc->realize = pl080_realize;
423
device_class_set_props(dc, pl080_properties);
424
dc->reset = pl080_reset;
427
static const TypeInfo pl080_info = {
429
.parent = TYPE_SYS_BUS_DEVICE,
430
.instance_size = sizeof(PL080State),
431
.instance_init = pl080_init,
432
.class_init = pl080_class_init,
435
static const TypeInfo pl081_info = {
437
.parent = TYPE_PL080,
438
.instance_init = pl081_init,
443
static void pl080_register_types(void)
445
type_register_static(&pl080_info);
446
type_register_static(&pl081_info);
449
type_init(pl080_register_types)