2 * Mai Logic Articia S emulation
4 * Copyright (c) 2023 BALATON Zoltan
6 * This work is licensed under the GNU GPL license version 2 or later.
10 #include "qemu/osdep.h"
12 #include "qapi/error.h"
13 #include "hw/pci/pci_device.h"
14 #include "hw/pci/pci_host.h"
16 #include "hw/i2c/bitbang_i2c.h"
17 #include "hw/intc/i8259.h"
18 #include "hw/pci-host/articia.h"
21 * This is a minimal emulation of this chip as used in AmigaOne board.
22 * Most features are missing but those are not needed by firmware and guests.
25 OBJECT_DECLARE_SIMPLE_TYPE(ArticiaState
, ARTICIA
)
27 OBJECT_DECLARE_SIMPLE_TYPE(ArticiaHostState
, ARTICIA_PCI_HOST
)
28 struct ArticiaHostState
{
37 PCIHostState parent_obj
;
39 qemu_irq irq
[PCI_NUM_PINS
];
44 bitbang_i2c_interface smbus
;
45 uint32_t gpio
; /* bits 0-7 in, 8-15 out, 16-23 direction (0 in, 1 out) */
47 MemoryRegion gpio_reg
;
50 static uint64_t articia_gpio_read(void *opaque
, hwaddr addr
, unsigned int size
)
52 ArticiaState
*s
= opaque
;
54 return (s
->gpio
>> (addr
* 8)) & 0xff;
57 static void articia_gpio_write(void *opaque
, hwaddr addr
, uint64_t val
,
60 ArticiaState
*s
= opaque
;
61 uint32_t sh
= addr
* 8;
64 /* in bits read only? */
68 if ((s
->gpio
& (0xff << sh
)) != (val
& 0xff) << sh
) {
69 s
->gpio
&= ~(0xff << sh
| 0xff);
70 s
->gpio
|= (val
& 0xff) << sh
;
71 s
->gpio
|= bitbang_i2c_set(&s
->smbus
, BITBANG_I2C_SDA
,
73 !!(s
->gpio
& BIT(8)) : 1);
74 if ((s
->gpio
& BIT(17))) {
76 s
->gpio
|= bitbang_i2c_set(&s
->smbus
, BITBANG_I2C_SCL
,
77 !!(s
->gpio
& BIT(9)));
82 static const MemoryRegionOps articia_gpio_ops
= {
83 .read
= articia_gpio_read
,
84 .write
= articia_gpio_write
,
85 .valid
.min_access_size
= 1,
86 .valid
.max_access_size
= 1,
87 .endianness
= DEVICE_LITTLE_ENDIAN
,
90 static uint64_t articia_reg_read(void *opaque
, hwaddr addr
, unsigned int size
)
92 ArticiaState
*s
= opaque
;
93 uint64_t ret
= UINT_MAX
;
97 ret
= pci_host_conf_le_ops
.read(PCI_HOST_BRIDGE(s
), 0, size
);
99 case 0xe00cfc ... 0xe00cff:
100 ret
= pci_host_data_le_ops
.read(PCI_HOST_BRIDGE(s
), addr
- 0xe00cfc, size
);
103 ret
= pic_read_irq(isa_pic
);
106 qemu_log_mask(LOG_UNIMP
, "%s: Unimplemented register read 0x%"
107 HWADDR_PRIx
" %d\n", __func__
, addr
, size
);
113 static void articia_reg_write(void *opaque
, hwaddr addr
, uint64_t val
,
116 ArticiaState
*s
= opaque
;
120 pci_host_conf_le_ops
.write(PCI_HOST_BRIDGE(s
), 0, val
, size
);
122 case 0xe00cfc ... 0xe00cff:
123 pci_host_data_le_ops
.write(PCI_HOST_BRIDGE(s
), addr
, val
, size
);
126 qemu_log_mask(LOG_UNIMP
, "%s: Unimplemented register write 0x%"
127 HWADDR_PRIx
" %d <- %"PRIx64
"\n", __func__
, addr
, size
, val
);
132 static const MemoryRegionOps articia_reg_ops
= {
133 .read
= articia_reg_read
,
134 .write
= articia_reg_write
,
135 .valid
.min_access_size
= 1,
136 .valid
.max_access_size
= 4,
137 .endianness
= DEVICE_LITTLE_ENDIAN
,
140 static void articia_pcihost_set_irq(void *opaque
, int n
, int level
)
142 ArticiaState
*s
= opaque
;
143 qemu_set_irq(s
->irq
[n
], level
);
147 * AmigaOne SE PCI slot to IRQ routing
149 * repository: https://source.denx.de/u-boot/custodians/u-boot-avr32.git
151 * file: board/MAI/AmigaOneG3SE/articiaS_pci.c
153 static int amigaone_pcihost_bus0_map_irq(PCIDevice
*pdev
, int pin
)
155 int devfn_slot
= PCI_SLOT(pdev
->devfn
);
157 switch (devfn_slot
) {
158 case 6: /* On board ethernet */
160 case 7: /* South bridge */
162 default: /* PCI Slot 1 Devfn slot 8, Slot 2 Devfn 9, Slot 3 Devfn 10 */
163 return pci_swizzle(devfn_slot
, pin
);
168 static void articia_realize(DeviceState
*dev
, Error
**errp
)
170 ArticiaState
*s
= ARTICIA(dev
);
171 PCIHostState
*h
= PCI_HOST_BRIDGE(dev
);
174 bitbang_i2c_init(&s
->smbus
, i2c_init_bus(dev
, "smbus"));
175 memory_region_init_io(&s
->gpio_reg
, OBJECT(s
), &articia_gpio_ops
, s
,
178 memory_region_init(&s
->mem
, OBJECT(dev
), "pci-mem", UINT64_MAX
);
179 memory_region_init(&s
->io
, OBJECT(dev
), "pci-io", 0xc00000);
180 memory_region_init_io(&s
->reg
, OBJECT(s
), &articia_reg_ops
, s
,
181 TYPE_ARTICIA
, 0x1000000);
182 memory_region_add_subregion_overlap(&s
->reg
, 0, &s
->io
, 1);
184 /* devfn_min is 8 that matches first PCI slot in AmigaOne */
185 h
->bus
= pci_register_root_bus(dev
, NULL
, articia_pcihost_set_irq
,
186 amigaone_pcihost_bus0_map_irq
, dev
, &s
->mem
,
187 &s
->io
, PCI_DEVFN(8, 0), 4, TYPE_PCI_BUS
);
188 pdev
= pci_create_simple_multifunction(h
->bus
, PCI_DEVFN(0, 0),
189 TYPE_ARTICIA_PCI_HOST
);
190 ARTICIA_PCI_HOST(pdev
)->as
= s
;
191 pci_create_simple(h
->bus
, PCI_DEVFN(0, 1), TYPE_ARTICIA_PCI_BRIDGE
);
193 sysbus_init_mmio(SYS_BUS_DEVICE(dev
), &s
->reg
);
194 sysbus_init_mmio(SYS_BUS_DEVICE(dev
), &s
->mem
);
195 qdev_init_gpio_out(dev
, s
->irq
, ARRAY_SIZE(s
->irq
));
198 static void articia_class_init(ObjectClass
*klass
, void *data
)
200 DeviceClass
*dc
= DEVICE_CLASS(klass
);
202 dc
->realize
= articia_realize
;
203 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
206 /* TYPE_ARTICIA_PCI_HOST */
208 static void articia_pci_host_cfg_write(PCIDevice
*d
, uint32_t addr
,
209 uint32_t val
, int len
)
211 ArticiaState
*s
= ARTICIA_PCI_HOST(d
)->as
;
213 pci_default_write_config(d
, addr
, val
, len
);
220 /* FIXME what do the bits actually mean? */
223 if (memory_region_is_mapped(&s
->gpio_reg
)) {
224 memory_region_del_subregion(&s
->io
, &s
->gpio_reg
);
226 memory_region_add_subregion(&s
->io
, s
->gpio_base
+ 0x38, &s
->gpio_reg
);
231 static void articia_pci_host_class_init(ObjectClass
*klass
, void *data
)
233 DeviceClass
*dc
= DEVICE_CLASS(klass
);
234 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
236 k
->config_write
= articia_pci_host_cfg_write
;
237 k
->vendor_id
= 0x10cc;
238 k
->device_id
= 0x0660;
239 k
->class_id
= PCI_CLASS_BRIDGE_HOST
;
241 * PCI-facing part of the host bridge,
242 * not usable without the host-facing part
244 dc
->user_creatable
= false;
247 /* TYPE_ARTICIA_PCI_BRIDGE */
249 static void articia_pci_bridge_class_init(ObjectClass
*klass
, void *data
)
251 DeviceClass
*dc
= DEVICE_CLASS(klass
);
252 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
254 k
->vendor_id
= 0x10cc;
255 k
->device_id
= 0x0661;
256 k
->class_id
= PCI_CLASS_BRIDGE_HOST
;
258 * PCI-facing part of the host bridge,
259 * not usable without the host-facing part
261 dc
->user_creatable
= false;
264 static const TypeInfo articia_types
[] = {
266 .name
= TYPE_ARTICIA
,
267 .parent
= TYPE_PCI_HOST_BRIDGE
,
268 .instance_size
= sizeof(ArticiaState
),
269 .class_init
= articia_class_init
,
272 .name
= TYPE_ARTICIA_PCI_HOST
,
273 .parent
= TYPE_PCI_DEVICE
,
274 .instance_size
= sizeof(ArticiaHostState
),
275 .class_init
= articia_pci_host_class_init
,
276 .interfaces
= (InterfaceInfo
[]) {
277 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
282 .name
= TYPE_ARTICIA_PCI_BRIDGE
,
283 .parent
= TYPE_PCI_DEVICE
,
284 .instance_size
= sizeof(PCIDevice
),
285 .class_init
= articia_pci_bridge_class_init
,
286 .interfaces
= (InterfaceInfo
[]) {
287 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
293 DEFINE_TYPES(articia_types
)