2 * Marvell Discovery II MV64361 System Controller for
3 * QEMU PowerPC CHRP (Genesi/bPlan Pegasos II) hardware System Emulator
5 * Copyright (c) 2018-2020 BALATON Zoltan
7 * This work is licensed under the GNU GPL license version 2 or later.
11 #include "qemu/osdep.h"
12 #include "qemu-common.h"
13 #include "qemu/units.h"
14 #include "qapi/error.h"
16 #include "hw/sysbus.h"
17 #include "hw/pci/pci.h"
18 #include "hw/pci/pci_host.h"
20 #include "hw/intc/i8259.h"
21 #include "hw/qdev-properties.h"
22 #include "exec/address-spaces.h"
24 #include "qemu/error-report.h"
26 #include "hw/pci-host/mv64361.h"
29 #define TYPE_MV64361_PCI_BRIDGE "mv64361-pcibridge"
31 static void mv64361_pcibridge_class_init(ObjectClass
*klass
, void *data
)
33 DeviceClass
*dc
= DEVICE_CLASS(klass
);
34 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
36 k
->vendor_id
= PCI_VENDOR_ID_MARVELL
;
37 k
->device_id
= PCI_DEVICE_ID_MARVELL_MV6436X
;
38 k
->class_id
= PCI_CLASS_BRIDGE_HOST
;
40 * PCI-facing part of the host bridge,
41 * not usable without the host-facing part
43 dc
->user_creatable
= false;
46 static const TypeInfo mv64361_pcibridge_info
= {
47 .name
= TYPE_MV64361_PCI_BRIDGE
,
48 .parent
= TYPE_PCI_DEVICE
,
49 .instance_size
= sizeof(PCIDevice
),
50 .class_init
= mv64361_pcibridge_class_init
,
51 .interfaces
= (InterfaceInfo
[]) {
52 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
58 #define TYPE_MV64361_PCI "mv64361-pcihost"
59 OBJECT_DECLARE_SIMPLE_TYPE(MV64361PCIState
, MV64361_PCI
)
61 struct MV64361PCIState
{
62 PCIHostState parent_obj
;
67 qemu_irq irq
[PCI_NUM_PINS
];
76 static int mv64361_pcihost_map_irq(PCIDevice
*pci_dev
, int n
)
78 return (n
+ PCI_SLOT(pci_dev
->devfn
)) % PCI_NUM_PINS
;
81 static void mv64361_pcihost_set_irq(void *opaque
, int n
, int level
)
83 MV64361PCIState
*s
= opaque
;
84 qemu_set_irq(s
->irq
[n
], level
);
87 static void mv64361_pcihost_realize(DeviceState
*dev
, Error
**errp
)
89 MV64361PCIState
*s
= MV64361_PCI(dev
);
90 PCIHostState
*h
= PCI_HOST_BRIDGE(dev
);
93 name
= g_strdup_printf("pci%d-io", s
->index
);
94 memory_region_init(&s
->io
, OBJECT(dev
), name
, 0x10000);
96 name
= g_strdup_printf("pci%d-mem", s
->index
);
97 memory_region_init(&s
->mem
, OBJECT(dev
), name
, 1ULL << 32);
99 name
= g_strdup_printf("pci.%d", s
->index
);
100 h
->bus
= pci_register_root_bus(dev
, name
, mv64361_pcihost_set_irq
,
101 mv64361_pcihost_map_irq
, dev
,
102 &s
->mem
, &s
->io
, 0, 4, TYPE_PCI_BUS
);
104 pci_create_simple(h
->bus
, 0, TYPE_MV64361_PCI_BRIDGE
);
107 static Property mv64361_pcihost_props
[] = {
108 DEFINE_PROP_UINT8("index", MV64361PCIState
, index
, 0),
109 DEFINE_PROP_END_OF_LIST()
112 static void mv64361_pcihost_class_init(ObjectClass
*klass
, void *data
)
114 DeviceClass
*dc
= DEVICE_CLASS(klass
);
116 dc
->realize
= mv64361_pcihost_realize
;
117 device_class_set_props(dc
, mv64361_pcihost_props
);
118 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
121 static const TypeInfo mv64361_pcihost_info
= {
122 .name
= TYPE_MV64361_PCI
,
123 .parent
= TYPE_PCI_HOST_BRIDGE
,
124 .instance_size
= sizeof(MV64361PCIState
),
125 .class_init
= mv64361_pcihost_class_init
,
128 static void mv64361_pci_register_types(void)
130 type_register_static(&mv64361_pcihost_info
);
131 type_register_static(&mv64361_pcibridge_info
);
134 type_init(mv64361_pci_register_types
)
137 OBJECT_DECLARE_SIMPLE_TYPE(MV64361State
, MV64361
)
139 struct MV64361State
{
140 SysBusDevice parent_obj
;
143 MV64361PCIState pci
[2];
144 MemoryRegion cpu_win
[19];
147 /* registers state */
150 uint32_t base_addr_enable
;
151 uint64_t main_int_cr
;
152 uint64_t cpu0_int_mask
;
157 uint32_t gpp_int_mask
;
161 enum mv64361_irq_cause
{
162 MV64361_IRQ_DEVERR
= 1,
163 MV64361_IRQ_DMAERR
= 2,
164 MV64361_IRQ_CPUERR
= 3,
165 MV64361_IRQ_IDMA0
= 4,
166 MV64361_IRQ_IDMA1
= 5,
167 MV64361_IRQ_IDMA2
= 6,
168 MV64361_IRQ_IDMA3
= 7,
169 MV64361_IRQ_TIMER0
= 8,
170 MV64361_IRQ_TIMER1
= 9,
171 MV64361_IRQ_TIMER2
= 10,
172 MV64361_IRQ_TIMER3
= 11,
173 MV64361_IRQ_PCI0
= 12,
174 MV64361_IRQ_SRAMERR
= 13,
175 MV64361_IRQ_GBEERR
= 14,
176 MV64361_IRQ_CERR
= 15,
177 MV64361_IRQ_PCI1
= 16,
178 MV64361_IRQ_DRAMERR
= 17,
179 MV64361_IRQ_WDNMI
= 18,
180 MV64361_IRQ_WDE
= 19,
181 MV64361_IRQ_PCI0IN
= 20,
182 MV64361_IRQ_PCI0OUT
= 21,
183 MV64361_IRQ_PCI1IN
= 22,
184 MV64361_IRQ_PCI1OUT
= 23,
185 MV64361_IRQ_P1_GPP0_7
= 24,
186 MV64361_IRQ_P1_GPP8_15
= 25,
187 MV64361_IRQ_P1_GPP16_23
= 26,
188 MV64361_IRQ_P1_GPP24_31
= 27,
189 MV64361_IRQ_P1_CPU_DB
= 28,
190 /* 29-31: reserved */
191 MV64361_IRQ_GBE0
= 32,
192 MV64361_IRQ_GBE1
= 33,
193 MV64361_IRQ_GBE2
= 34,
195 MV64361_IRQ_SDMA0
= 36,
196 MV64361_IRQ_TWSI
= 37,
197 MV64361_IRQ_SDMA1
= 38,
198 MV64361_IRQ_BRG
= 39,
199 MV64361_IRQ_MPSC0
= 40,
200 MV64361_IRQ_MPSC1
= 41,
201 MV64361_IRQ_G0RX
= 42,
202 MV64361_IRQ_G0TX
= 43,
203 MV64361_IRQ_G0MISC
= 44,
204 MV64361_IRQ_G1RX
= 45,
205 MV64361_IRQ_G1TX
= 46,
206 MV64361_IRQ_G1MISC
= 47,
207 MV64361_IRQ_G2RX
= 48,
208 MV64361_IRQ_G2TX
= 49,
209 MV64361_IRQ_G2MISC
= 50,
210 /* 51-55: reserved */
211 MV64361_IRQ_P0_GPP0_7
= 56,
212 MV64361_IRQ_P0_GPP8_15
= 57,
213 MV64361_IRQ_P0_GPP16_23
= 58,
214 MV64361_IRQ_P0_GPP24_31
= 59,
215 MV64361_IRQ_P0_CPU_DB
= 60,
216 /* 61-63: reserved */
219 PCIBus
*mv64361_get_pci_bus(DeviceState
*dev
, int n
)
221 MV64361State
*mv
= MV64361(dev
);
222 return PCI_HOST_BRIDGE(&mv
->pci
[n
])->bus
;
225 static void unmap_region(MemoryRegion
*mr
)
227 if (memory_region_is_mapped(mr
)) {
228 memory_region_del_subregion(get_system_memory(), mr
);
229 object_unparent(OBJECT(mr
));
233 static void map_pci_region(MemoryRegion
*mr
, MemoryRegion
*parent
,
234 struct Object
*owner
, const char *name
,
235 hwaddr poffs
, uint64_t size
, hwaddr moffs
)
237 memory_region_init_alias(mr
, owner
, name
, parent
, poffs
, size
);
238 memory_region_add_subregion(get_system_memory(), moffs
, mr
);
239 trace_mv64361_region_map(name
, poffs
, size
, moffs
);
242 static void set_mem_windows(MV64361State
*s
, uint32_t val
)
250 for (mask
= 1, i
= 0; i
< 21; i
++, mask
<<= 1) {
251 if ((val
& mask
) != (s
->base_addr_enable
& mask
)) {
252 trace_mv64361_region_enable(!(val
& mask
) ? "enable" : "disable", i
);
254 * 0-3 are SDRAM chip selects but we map all RAM directly
255 * 4-7 are device chip selects (not sure what those are)
256 * 8 is Boot device (ROM) chip select but we map that directly too
263 map_pci_region(mr
, &p
->io
, OBJECT(s
), "pci0-io-win",
264 p
->remap
[4], (p
->io_size
+ 1) << 16,
265 (p
->io_base
& 0xfffff) << 16);
267 } else if (i
== 10) {
272 map_pci_region(mr
, &p
->mem
, OBJECT(s
), "pci0-mem0-win",
273 p
->remap
[0], (p
->mem_size
[0] + 1) << 16,
274 (p
->mem_base
[0] & 0xfffff) << 16);
276 } else if (i
== 11) {
281 map_pci_region(mr
, &p
->mem
, OBJECT(s
), "pci0-mem1-win",
282 p
->remap
[1], (p
->mem_size
[1] + 1) << 16,
283 (p
->mem_base
[1] & 0xfffff) << 16);
285 } else if (i
== 12) {
290 map_pci_region(mr
, &p
->mem
, OBJECT(s
), "pci0-mem2-win",
291 p
->remap
[2], (p
->mem_size
[2] + 1) << 16,
292 (p
->mem_base
[2] & 0xfffff) << 16);
294 } else if (i
== 13) {
299 map_pci_region(mr
, &p
->mem
, OBJECT(s
), "pci0-mem3-win",
300 p
->remap
[3], (p
->mem_size
[3] + 1) << 16,
301 (p
->mem_base
[3] & 0xfffff) << 16);
303 } else if (i
== 14) {
308 map_pci_region(mr
, &p
->io
, OBJECT(s
), "pci1-io-win",
309 p
->remap
[4], (p
->io_size
+ 1) << 16,
310 (p
->io_base
& 0xfffff) << 16);
312 } else if (i
== 15) {
317 map_pci_region(mr
, &p
->mem
, OBJECT(s
), "pci1-mem0-win",
318 p
->remap
[0], (p
->mem_size
[0] + 1) << 16,
319 (p
->mem_base
[0] & 0xfffff) << 16);
321 } else if (i
== 16) {
326 map_pci_region(mr
, &p
->mem
, OBJECT(s
), "pci1-mem1-win",
327 p
->remap
[1], (p
->mem_size
[1] + 1) << 16,
328 (p
->mem_base
[1] & 0xfffff) << 16);
330 } else if (i
== 17) {
335 map_pci_region(mr
, &p
->mem
, OBJECT(s
), "pci1-mem2-win",
336 p
->remap
[2], (p
->mem_size
[2] + 1) << 16,
337 (p
->mem_base
[2] & 0xfffff) << 16);
339 } else if (i
== 18) {
344 map_pci_region(mr
, &p
->mem
, OBJECT(s
), "pci1-mem3-win",
345 p
->remap
[3], (p
->mem_size
[3] + 1) << 16,
346 (p
->mem_base
[3] & 0xfffff) << 16);
348 /* 19 is integrated SRAM */
349 } else if (i
== 20) {
353 memory_region_add_subregion(get_system_memory(),
354 (s
->regs_base
& 0xfffff) << 16, mr
);
359 s
->base_addr_enable
= val
;
362 static void mv64361_update_irq(void *opaque
, int n
, int level
)
364 MV64361State
*s
= opaque
;
365 uint64_t val
= s
->main_int_cr
;
372 if ((s
->main_int_cr
& s
->cpu0_int_mask
) != (val
& s
->cpu0_int_mask
)) {
373 qemu_set_irq(s
->cpu_irq
, level
);
375 s
->main_int_cr
= val
;
378 static uint64_t mv64361_read(void *opaque
, hwaddr addr
, unsigned int size
)
380 MV64361State
*s
= MV64361(opaque
);
384 case MV64340_CPU_CONFIG
:
387 case MV64340_PCI_0_IO_BASE_ADDR
:
388 ret
= s
->pci
[0].io_base
;
390 case MV64340_PCI_0_IO_SIZE
:
391 ret
= s
->pci
[0].io_size
;
393 case MV64340_PCI_0_IO_ADDR_REMAP
:
394 ret
= s
->pci
[0].remap
[4] >> 16;
396 case MV64340_PCI_0_MEMORY0_BASE_ADDR
:
397 ret
= s
->pci
[0].mem_base
[0];
399 case MV64340_PCI_0_MEMORY0_SIZE
:
400 ret
= s
->pci
[0].mem_size
[0];
402 case MV64340_PCI_0_MEMORY0_LOW_ADDR_REMAP
:
403 ret
= (s
->pci
[0].remap
[0] & 0xffff0000) >> 16;
405 case MV64340_PCI_0_MEMORY0_HIGH_ADDR_REMAP
:
406 ret
= s
->pci
[0].remap
[0] >> 32;
408 case MV64340_PCI_0_MEMORY1_BASE_ADDR
:
409 ret
= s
->pci
[0].mem_base
[1];
411 case MV64340_PCI_0_MEMORY1_SIZE
:
412 ret
= s
->pci
[0].mem_size
[1];
414 case MV64340_PCI_0_MEMORY1_LOW_ADDR_REMAP
:
415 ret
= (s
->pci
[0].remap
[1] & 0xffff0000) >> 16;
417 case MV64340_PCI_0_MEMORY1_HIGH_ADDR_REMAP
:
418 ret
= s
->pci
[0].remap
[1] >> 32;
420 case MV64340_PCI_0_MEMORY2_BASE_ADDR
:
421 ret
= s
->pci
[0].mem_base
[2];
423 case MV64340_PCI_0_MEMORY2_SIZE
:
424 ret
= s
->pci
[0].mem_size
[2];
426 case MV64340_PCI_0_MEMORY2_LOW_ADDR_REMAP
:
427 ret
= (s
->pci
[0].remap
[2] & 0xffff0000) >> 16;
429 case MV64340_PCI_0_MEMORY2_HIGH_ADDR_REMAP
:
430 ret
= s
->pci
[0].remap
[2] >> 32;
432 case MV64340_PCI_0_MEMORY3_BASE_ADDR
:
433 ret
= s
->pci
[0].mem_base
[3];
435 case MV64340_PCI_0_MEMORY3_SIZE
:
436 ret
= s
->pci
[0].mem_size
[3];
438 case MV64340_PCI_0_MEMORY3_LOW_ADDR_REMAP
:
439 ret
= (s
->pci
[0].remap
[3] & 0xffff0000) >> 16;
441 case MV64340_PCI_0_MEMORY3_HIGH_ADDR_REMAP
:
442 ret
= s
->pci
[0].remap
[3] >> 32;
444 case MV64340_PCI_1_IO_BASE_ADDR
:
445 ret
= s
->pci
[1].io_base
;
447 case MV64340_PCI_1_IO_SIZE
:
448 ret
= s
->pci
[1].io_size
;
450 case MV64340_PCI_1_IO_ADDR_REMAP
:
451 ret
= s
->pci
[1].remap
[4] >> 16;
453 case MV64340_PCI_1_MEMORY0_BASE_ADDR
:
454 ret
= s
->pci
[1].mem_base
[0];
456 case MV64340_PCI_1_MEMORY0_SIZE
:
457 ret
= s
->pci
[1].mem_size
[0];
459 case MV64340_PCI_1_MEMORY0_LOW_ADDR_REMAP
:
460 ret
= (s
->pci
[1].remap
[0] & 0xffff0000) >> 16;
462 case MV64340_PCI_1_MEMORY0_HIGH_ADDR_REMAP
:
463 ret
= s
->pci
[1].remap
[0] >> 32;
465 case MV64340_PCI_1_MEMORY1_BASE_ADDR
:
466 ret
= s
->pci
[1].mem_base
[1];
468 case MV64340_PCI_1_MEMORY1_SIZE
:
469 ret
= s
->pci
[1].mem_size
[1];
471 case MV64340_PCI_1_MEMORY1_LOW_ADDR_REMAP
:
472 ret
= (s
->pci
[1].remap
[1] & 0xffff0000) >> 16;
474 case MV64340_PCI_1_MEMORY1_HIGH_ADDR_REMAP
:
475 ret
= s
->pci
[1].remap
[1] >> 32;
477 case MV64340_PCI_1_MEMORY2_BASE_ADDR
:
478 ret
= s
->pci
[1].mem_base
[2];
480 case MV64340_PCI_1_MEMORY2_SIZE
:
481 ret
= s
->pci
[1].mem_size
[2];
483 case MV64340_PCI_1_MEMORY2_LOW_ADDR_REMAP
:
484 ret
= (s
->pci
[1].remap
[2] & 0xffff0000) >> 16;
486 case MV64340_PCI_1_MEMORY2_HIGH_ADDR_REMAP
:
487 ret
= s
->pci
[1].remap
[2] >> 32;
489 case MV64340_PCI_1_MEMORY3_BASE_ADDR
:
490 ret
= s
->pci
[1].mem_base
[3];
492 case MV64340_PCI_1_MEMORY3_SIZE
:
493 ret
= s
->pci
[1].mem_size
[3];
495 case MV64340_PCI_1_MEMORY3_LOW_ADDR_REMAP
:
496 ret
= (s
->pci
[1].remap
[3] & 0xffff0000) >> 16;
498 case MV64340_PCI_1_MEMORY3_HIGH_ADDR_REMAP
:
499 ret
= s
->pci
[1].remap
[3] >> 32;
501 case MV64340_INTERNAL_SPACE_BASE_ADDR
:
504 case MV64340_BASE_ADDR_ENABLE
:
505 ret
= s
->base_addr_enable
;
507 case MV64340_PCI_0_CONFIG_ADDR
:
508 ret
= pci_host_conf_le_ops
.read(PCI_HOST_BRIDGE(&s
->pci
[0]), 0, size
);
510 case MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
...
511 MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
+ 3:
512 ret
= pci_host_data_le_ops
.read(PCI_HOST_BRIDGE(&s
->pci
[0]),
513 addr
- MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
, size
);
515 case MV64340_PCI_1_CONFIG_ADDR
:
516 ret
= pci_host_conf_le_ops
.read(PCI_HOST_BRIDGE(&s
->pci
[1]), 0, size
);
518 case MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
...
519 MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
+ 3:
520 ret
= pci_host_data_le_ops
.read(PCI_HOST_BRIDGE(&s
->pci
[1]),
521 addr
- MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
, size
);
523 case MV64340_PCI_1_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG
:
524 /* FIXME: Should this be sent via the PCI bus somehow? */
525 if (s
->gpp_int_level
&& (s
->gpp_value
& BIT(31))) {
526 ret
= pic_read_irq(isa_pic
);
529 case MV64340_MAIN_INTERRUPT_CAUSE_LOW
:
530 ret
= s
->main_int_cr
;
532 case MV64340_MAIN_INTERRUPT_CAUSE_HIGH
:
533 ret
= s
->main_int_cr
>> 32;
535 case MV64340_CPU_INTERRUPT0_MASK_LOW
:
536 ret
= s
->cpu0_int_mask
;
538 case MV64340_CPU_INTERRUPT0_MASK_HIGH
:
539 ret
= s
->cpu0_int_mask
>> 32;
541 case MV64340_CPU_INTERRUPT0_SELECT_CAUSE
:
542 ret
= s
->main_int_cr
;
543 if (s
->main_int_cr
& s
->cpu0_int_mask
) {
544 if (!(s
->main_int_cr
& s
->cpu0_int_mask
& 0xffffffff)) {
545 ret
= s
->main_int_cr
>> 32 | BIT(30);
546 } else if ((s
->main_int_cr
& s
->cpu0_int_mask
) >> 32) {
551 case MV64340_CUNIT_ARBITER_CONTROL_REG
:
552 ret
= 0x11ff0000 | (s
->gpp_int_level
<< 10);
554 case MV64340_GPP_IO_CONTROL
:
557 case MV64340_GPP_LEVEL_CONTROL
:
560 case MV64340_GPP_VALUE
:
563 case MV64340_GPP_VALUE_SET
:
564 case MV64340_GPP_VALUE_CLEAR
:
567 case MV64340_GPP_INTERRUPT_CAUSE
:
570 case MV64340_GPP_INTERRUPT_MASK0
:
571 case MV64340_GPP_INTERRUPT_MASK1
:
572 ret
= s
->gpp_int_mask
;
575 qemu_log_mask(LOG_UNIMP
, "%s: Unimplemented register read 0x%"
576 HWADDR_PRIx
"\n", __func__
, addr
);
579 if (addr
!= MV64340_PCI_1_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG
) {
580 trace_mv64361_reg_read(addr
, ret
);
585 static void warn_swap_bit(uint64_t val
)
587 if ((val
& 0x3000000ULL
) >> 24 != 1) {
588 qemu_log_mask(LOG_UNIMP
, "%s: Data swap not implemented", __func__
);
592 static void mv64361_set_pci_mem_remap(MV64361State
*s
, int bus
, int idx
,
593 uint64_t val
, bool high
)
596 s
->pci
[bus
].remap
[idx
] = val
;
598 s
->pci
[bus
].remap
[idx
] &= 0xffffffff00000000ULL
;
599 s
->pci
[bus
].remap
[idx
] |= (val
& 0xffffULL
) << 16;
603 static void mv64361_write(void *opaque
, hwaddr addr
, uint64_t val
,
606 MV64361State
*s
= MV64361(opaque
);
608 trace_mv64361_reg_write(addr
, val
);
610 case MV64340_CPU_CONFIG
:
611 s
->cpu_conf
= val
& 0xe4e3bffULL
;
612 s
->cpu_conf
|= BIT(23);
614 case MV64340_PCI_0_IO_BASE_ADDR
:
615 s
->pci
[0].io_base
= val
& 0x30fffffULL
;
617 if (!(s
->cpu_conf
& BIT(27))) {
618 s
->pci
[0].remap
[4] = (val
& 0xffffULL
) << 16;
621 case MV64340_PCI_0_IO_SIZE
:
622 s
->pci
[0].io_size
= val
& 0xffffULL
;
624 case MV64340_PCI_0_IO_ADDR_REMAP
:
625 s
->pci
[0].remap
[4] = (val
& 0xffffULL
) << 16;
627 case MV64340_PCI_0_MEMORY0_BASE_ADDR
:
628 s
->pci
[0].mem_base
[0] = val
& 0x70fffffULL
;
630 if (!(s
->cpu_conf
& BIT(27))) {
631 mv64361_set_pci_mem_remap(s
, 0, 0, val
, false);
634 case MV64340_PCI_0_MEMORY0_SIZE
:
635 s
->pci
[0].mem_size
[0] = val
& 0xffffULL
;
637 case MV64340_PCI_0_MEMORY0_LOW_ADDR_REMAP
:
638 case MV64340_PCI_0_MEMORY0_HIGH_ADDR_REMAP
:
639 mv64361_set_pci_mem_remap(s
, 0, 0, val
,
640 (addr
== MV64340_PCI_0_MEMORY0_HIGH_ADDR_REMAP
));
642 case MV64340_PCI_0_MEMORY1_BASE_ADDR
:
643 s
->pci
[0].mem_base
[1] = val
& 0x70fffffULL
;
645 if (!(s
->cpu_conf
& BIT(27))) {
646 mv64361_set_pci_mem_remap(s
, 0, 1, val
, false);
649 case MV64340_PCI_0_MEMORY1_SIZE
:
650 s
->pci
[0].mem_size
[1] = val
& 0xffffULL
;
652 case MV64340_PCI_0_MEMORY1_LOW_ADDR_REMAP
:
653 case MV64340_PCI_0_MEMORY1_HIGH_ADDR_REMAP
:
654 mv64361_set_pci_mem_remap(s
, 0, 1, val
,
655 (addr
== MV64340_PCI_0_MEMORY1_HIGH_ADDR_REMAP
));
657 case MV64340_PCI_0_MEMORY2_BASE_ADDR
:
658 s
->pci
[0].mem_base
[2] = val
& 0x70fffffULL
;
660 if (!(s
->cpu_conf
& BIT(27))) {
661 mv64361_set_pci_mem_remap(s
, 0, 2, val
, false);
664 case MV64340_PCI_0_MEMORY2_SIZE
:
665 s
->pci
[0].mem_size
[2] = val
& 0xffffULL
;
667 case MV64340_PCI_0_MEMORY2_LOW_ADDR_REMAP
:
668 case MV64340_PCI_0_MEMORY2_HIGH_ADDR_REMAP
:
669 mv64361_set_pci_mem_remap(s
, 0, 2, val
,
670 (addr
== MV64340_PCI_0_MEMORY2_HIGH_ADDR_REMAP
));
672 case MV64340_PCI_0_MEMORY3_BASE_ADDR
:
673 s
->pci
[0].mem_base
[3] = val
& 0x70fffffULL
;
675 if (!(s
->cpu_conf
& BIT(27))) {
676 mv64361_set_pci_mem_remap(s
, 0, 3, val
, false);
679 case MV64340_PCI_0_MEMORY3_SIZE
:
680 s
->pci
[0].mem_size
[3] = val
& 0xffffULL
;
682 case MV64340_PCI_0_MEMORY3_LOW_ADDR_REMAP
:
683 case MV64340_PCI_0_MEMORY3_HIGH_ADDR_REMAP
:
684 mv64361_set_pci_mem_remap(s
, 0, 3, val
,
685 (addr
== MV64340_PCI_0_MEMORY3_HIGH_ADDR_REMAP
));
687 case MV64340_PCI_1_IO_BASE_ADDR
:
688 s
->pci
[1].io_base
= val
& 0x30fffffULL
;
691 if (!(s
->cpu_conf
& BIT(27))) {
692 s
->pci
[1].remap
[4] = (val
& 0xffffULL
) << 16;
695 case MV64340_PCI_1_IO_SIZE
:
696 s
->pci
[1].io_size
= val
& 0xffffULL
;
698 case MV64340_PCI_1_MEMORY0_BASE_ADDR
:
699 s
->pci
[1].mem_base
[0] = val
& 0x70fffffULL
;
701 if (!(s
->cpu_conf
& BIT(27))) {
702 mv64361_set_pci_mem_remap(s
, 1, 0, val
, false);
705 case MV64340_PCI_1_MEMORY0_SIZE
:
706 s
->pci
[1].mem_size
[0] = val
& 0xffffULL
;
708 case MV64340_PCI_1_MEMORY0_LOW_ADDR_REMAP
:
709 case MV64340_PCI_1_MEMORY0_HIGH_ADDR_REMAP
:
710 mv64361_set_pci_mem_remap(s
, 1, 0, val
,
711 (addr
== MV64340_PCI_1_MEMORY0_HIGH_ADDR_REMAP
));
713 case MV64340_PCI_1_MEMORY1_BASE_ADDR
:
714 s
->pci
[1].mem_base
[1] = val
& 0x70fffffULL
;
716 if (!(s
->cpu_conf
& BIT(27))) {
717 mv64361_set_pci_mem_remap(s
, 1, 1, val
, false);
720 case MV64340_PCI_1_MEMORY1_SIZE
:
721 s
->pci
[1].mem_size
[1] = val
& 0xffffULL
;
723 case MV64340_PCI_1_MEMORY1_LOW_ADDR_REMAP
:
724 case MV64340_PCI_1_MEMORY1_HIGH_ADDR_REMAP
:
725 mv64361_set_pci_mem_remap(s
, 1, 1, val
,
726 (addr
== MV64340_PCI_1_MEMORY1_HIGH_ADDR_REMAP
));
728 case MV64340_PCI_1_MEMORY2_BASE_ADDR
:
729 s
->pci
[1].mem_base
[2] = val
& 0x70fffffULL
;
731 if (!(s
->cpu_conf
& BIT(27))) {
732 mv64361_set_pci_mem_remap(s
, 1, 2, val
, false);
735 case MV64340_PCI_1_MEMORY2_SIZE
:
736 s
->pci
[1].mem_size
[2] = val
& 0xffffULL
;
738 case MV64340_PCI_1_MEMORY2_LOW_ADDR_REMAP
:
739 case MV64340_PCI_1_MEMORY2_HIGH_ADDR_REMAP
:
740 mv64361_set_pci_mem_remap(s
, 1, 2, val
,
741 (addr
== MV64340_PCI_1_MEMORY2_HIGH_ADDR_REMAP
));
743 case MV64340_PCI_1_MEMORY3_BASE_ADDR
:
744 s
->pci
[1].mem_base
[3] = val
& 0x70fffffULL
;
746 if (!(s
->cpu_conf
& BIT(27))) {
747 mv64361_set_pci_mem_remap(s
, 1, 3, val
, false);
750 case MV64340_PCI_1_MEMORY3_SIZE
:
751 s
->pci
[1].mem_size
[3] = val
& 0xffffULL
;
753 case MV64340_PCI_1_MEMORY3_LOW_ADDR_REMAP
:
754 case MV64340_PCI_1_MEMORY3_HIGH_ADDR_REMAP
:
755 mv64361_set_pci_mem_remap(s
, 1, 3, val
,
756 (addr
== MV64340_PCI_1_MEMORY3_HIGH_ADDR_REMAP
));
758 case MV64340_INTERNAL_SPACE_BASE_ADDR
:
759 s
->regs_base
= val
& 0xfffffULL
;
761 case MV64340_BASE_ADDR_ENABLE
:
762 set_mem_windows(s
, val
);
764 case MV64340_PCI_0_CONFIG_ADDR
:
765 pci_host_conf_le_ops
.write(PCI_HOST_BRIDGE(&s
->pci
[0]), 0, val
, size
);
767 case MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
...
768 MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
+ 3:
769 pci_host_data_le_ops
.write(PCI_HOST_BRIDGE(&s
->pci
[0]),
770 addr
- MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
, val
, size
);
772 case MV64340_PCI_1_CONFIG_ADDR
:
773 pci_host_conf_le_ops
.write(PCI_HOST_BRIDGE(&s
->pci
[1]), 0, val
, size
);
775 case MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
...
776 MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
+ 3:
777 pci_host_data_le_ops
.write(PCI_HOST_BRIDGE(&s
->pci
[1]),
778 addr
- MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
, val
, size
);
780 case MV64340_CPU_INTERRUPT0_MASK_LOW
:
781 s
->cpu0_int_mask
&= 0xffffffff00000000ULL
;
782 s
->cpu0_int_mask
|= val
& 0xffffffffULL
;
784 case MV64340_CPU_INTERRUPT0_MASK_HIGH
:
785 s
->cpu0_int_mask
&= 0xffffffffULL
;
786 s
->cpu0_int_mask
|= val
<< 32;
788 case MV64340_CUNIT_ARBITER_CONTROL_REG
:
789 s
->gpp_int_level
= !!(val
& BIT(10));
791 case MV64340_GPP_IO_CONTROL
:
794 case MV64340_GPP_LEVEL_CONTROL
:
797 case MV64340_GPP_VALUE
:
798 s
->gpp_value
&= ~s
->gpp_io
;
799 s
->gpp_value
|= val
& s
->gpp_io
;
801 case MV64340_GPP_VALUE_SET
:
802 s
->gpp_value
|= val
& s
->gpp_io
;
804 case MV64340_GPP_VALUE_CLEAR
:
805 s
->gpp_value
&= ~(val
& s
->gpp_io
);
807 case MV64340_GPP_INTERRUPT_CAUSE
:
808 if (!s
->gpp_int_level
&& val
!= s
->gpp_int_cr
) {
810 uint32_t ch
= s
->gpp_int_cr
^ val
;
812 for (i
= 0; i
< 4; i
++) {
813 if ((ch
& 0xff << i
) && !(val
& 0xff << i
)) {
814 mv64361_update_irq(opaque
, MV64361_IRQ_P0_GPP0_7
+ i
, 0);
821 case MV64340_GPP_INTERRUPT_MASK0
:
822 case MV64340_GPP_INTERRUPT_MASK1
:
823 s
->gpp_int_mask
= val
;
826 qemu_log_mask(LOG_UNIMP
, "%s: Unimplemented register write 0x%"
827 HWADDR_PRIx
" = %"PRIx64
"\n", __func__
, addr
, val
);
832 static const MemoryRegionOps mv64361_ops
= {
833 .read
= mv64361_read
,
834 .write
= mv64361_write
,
835 .valid
.min_access_size
= 1,
836 .valid
.max_access_size
= 4,
837 .endianness
= DEVICE_LITTLE_ENDIAN
,
840 static void mv64361_gpp_irq(void *opaque
, int n
, int level
)
842 MV64361State
*s
= opaque
;
843 uint32_t mask
= BIT(n
);
844 uint32_t val
= s
->gpp_value
& ~mask
;
846 if (s
->gpp_level
& mask
) {
850 if (val
> s
->gpp_value
) {
852 s
->gpp_int_cr
|= mask
;
853 if (s
->gpp_int_mask
& mask
) {
854 mv64361_update_irq(opaque
, MV64361_IRQ_P0_GPP0_7
+ n
/ 8, 1);
856 } else if (val
< s
->gpp_value
) {
859 if (s
->gpp_int_level
&& !(val
& 0xff << b
)) {
860 mv64361_update_irq(opaque
, MV64361_IRQ_P0_GPP0_7
+ b
, 0);
865 static void mv64361_realize(DeviceState
*dev
, Error
**errp
)
867 MV64361State
*s
= MV64361(dev
);
870 s
->base_addr_enable
= 0x1fffff;
871 memory_region_init_io(&s
->regs
, OBJECT(s
), &mv64361_ops
, s
,
872 TYPE_MV64361
, 0x10000);
873 for (i
= 0; i
< 2; i
++) {
874 g_autofree
char *name
= g_strdup_printf("pcihost%d", i
);
875 object_initialize_child(OBJECT(dev
), name
, &s
->pci
[i
],
877 DeviceState
*pci
= DEVICE(&s
->pci
[i
]);
878 qdev_prop_set_uint8(pci
, "index", i
);
879 sysbus_realize_and_unref(SYS_BUS_DEVICE(pci
), &error_fatal
);
881 sysbus_init_irq(SYS_BUS_DEVICE(dev
), &s
->cpu_irq
);
882 qdev_init_gpio_in_named(dev
, mv64361_gpp_irq
, "gpp", 32);
883 /* FIXME: PCI IRQ connections may be board specific */
884 for (i
= 0; i
< PCI_NUM_PINS
; i
++) {
885 s
->pci
[1].irq
[i
] = qdev_get_gpio_in_named(dev
, "gpp", 12 + i
);
889 static void mv64361_reset(DeviceState
*dev
)
891 MV64361State
*s
= MV64361(dev
);
895 * These values may be board specific
896 * Real chip supports init from an eprom but that's not modelled
898 set_mem_windows(s
, 0x1fffff);
899 s
->cpu_conf
= 0x28000ff;
900 s
->regs_base
= 0x100f100;
901 s
->pci
[0].io_base
= 0x100f800;
902 s
->pci
[0].io_size
= 0xff;
903 s
->pci
[0].mem_base
[0] = 0x100c000;
904 s
->pci
[0].mem_size
[0] = 0x1fff;
905 s
->pci
[0].mem_base
[1] = 0x100f900;
906 s
->pci
[0].mem_size
[1] = 0xff;
907 s
->pci
[0].mem_base
[2] = 0x100f400;
908 s
->pci
[0].mem_size
[2] = 0x1ff;
909 s
->pci
[0].mem_base
[3] = 0x100f600;
910 s
->pci
[0].mem_size
[3] = 0x1ff;
911 s
->pci
[1].io_base
= 0x100fe00;
912 s
->pci
[1].io_size
= 0xff;
913 s
->pci
[1].mem_base
[0] = 0x1008000;
914 s
->pci
[1].mem_size
[0] = 0x3fff;
915 s
->pci
[1].mem_base
[1] = 0x100fd00;
916 s
->pci
[1].mem_size
[1] = 0xff;
917 s
->pci
[1].mem_base
[2] = 0x1002600;
918 s
->pci
[1].mem_size
[2] = 0x1ff;
919 s
->pci
[1].mem_base
[3] = 0x100ff80;
920 s
->pci
[1].mem_size
[3] = 0x7f;
921 for (i
= 0; i
< 2; i
++) {
922 for (j
= 0; j
< 4; j
++) {
923 s
->pci
[i
].remap
[j
] = s
->pci
[i
].mem_base
[j
] << 16;
926 s
->pci
[0].remap
[1] = 0;
927 s
->pci
[1].remap
[1] = 0;
928 set_mem_windows(s
, 0xfbfff);
931 static void mv64361_class_init(ObjectClass
*klass
, void *data
)
933 DeviceClass
*dc
= DEVICE_CLASS(klass
);
935 dc
->realize
= mv64361_realize
;
936 dc
->reset
= mv64361_reset
;
939 static const TypeInfo mv64361_type_info
= {
940 .name
= TYPE_MV64361
,
941 .parent
= TYPE_SYS_BUS_DEVICE
,
942 .instance_size
= sizeof(MV64361State
),
943 .class_init
= mv64361_class_init
,
946 static void mv64361_register_types(void)
948 type_register_static(&mv64361_type_info
);
951 type_init(mv64361_register_types
)