blob: 75bc506965c0e4f10afa2c51c45d0c5983bed128 [file] [log] [blame]
pbrook502a5392006-05-13 16:11:23 +00001/*
2 * QEMU Uninorth PCI host (for all Mac99 and newer machines)
3 *
4 * Copyright (c) 2006 Fabrice Bellard
ths5fafdf22007-09-16 21:08:06 +00005 *
pbrook502a5392006-05-13 16:11:23 +00006 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
Markus Armbruster0b8fa322019-05-23 16:35:07 +020024
Peter Maydell0d755902016-01-26 18:16:58 +000025#include "qemu/osdep.h"
Markus Armbruster64552b62019-08-12 07:23:42 +020026#include "hw/irq.h"
Paolo Bonzini83c9f4c2013-02-04 15:40:22 +010027#include "hw/ppc/mac.h"
Markus Armbrustera27bd6c2019-08-12 07:23:51 +020028#include "hw/qdev-properties.h"
Markus Armbruster0b8fa322019-05-23 16:35:07 +020029#include "qemu/module.h"
Paolo Bonzini83c9f4c2013-02-04 15:40:22 +010030#include "hw/pci/pci.h"
31#include "hw/pci/pci_host.h"
Mark Cave-Ayland5d2eaa02018-03-06 20:30:49 +000032#include "hw/pci-host/uninorth.h"
Mark Cave-Ayland0b0c5e92018-01-26 09:20:28 +000033#include "trace.h"
blueswir1f3902382009-02-05 20:22:07 +000034
Alexander Graffa0be692010-02-09 17:37:04 +010035static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
36
pbrookd2b59312006-09-24 00:16:34 +000037static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
pbrook502a5392006-05-13 16:11:23 +000038{
Benjamin Herrenschmidt39d97e12016-11-21 00:12:31 +100039 return (irq_num + (pci_dev->devfn >> 3)) & 3;
pbrookd2b59312006-09-24 00:16:34 +000040}
41
Juan Quintela5d4e84c2009-08-28 15:28:17 +020042static void pci_unin_set_irq(void *opaque, int irq_num, int level)
pbrookd2b59312006-09-24 00:16:34 +000043{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +000044 UNINHostState *s = opaque;
Juan Quintela5d4e84c2009-08-28 15:28:17 +020045
Mark Cave-Ayland0b0c5e92018-01-26 09:20:28 +000046 trace_unin_set_irq(unin_irq_line[irq_num], level);
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +000047 qemu_set_irq(s->irqs[irq_num], level);
pbrook502a5392006-05-13 16:11:23 +000048}
49
Alexander Grafd86f0e32010-02-09 17:37:01 +010050static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
51{
52 uint32_t retval;
53
54 if (reg & (1u << 31)) {
55 /* XXX OpenBIOS compatibility hack */
56 retval = reg | (addr & 3);
57 } else if (reg & 1) {
58 /* CFA1 style */
59 retval = (reg & ~7u) | (addr & 7);
60 } else {
61 uint32_t slot, func;
62
63 /* Grab CFA0 style values */
Stefan Hajnoczi5863d372015-03-23 15:29:25 +000064 slot = ctz32(reg & 0xfffff800);
65 if (slot == 32) {
66 slot = -1; /* XXX: should this be 0? */
67 }
Alexander Grafd86f0e32010-02-09 17:37:01 +010068 func = (reg >> 8) & 7;
69
70 /* ... and then convert them to x86 format */
71 /* config pointer */
72 retval = (reg & (0xff - 7)) | (addr & 7);
73 /* slot */
74 retval |= slot << 11;
75 /* fn */
76 retval |= func << 8;
77 }
78
Mark Cave-Ayland0b0c5e92018-01-26 09:20:28 +000079 trace_unin_get_config_reg(reg, addr, retval);
Alexander Grafd86f0e32010-02-09 17:37:01 +010080
81 return retval;
82}
83
Avi Kivitya8170e52012-10-23 12:30:10 +020084static void unin_data_write(void *opaque, hwaddr addr,
Avi Kivityd0ed8072011-07-24 17:47:18 +030085 uint64_t val, unsigned len)
Alexander Grafd86f0e32010-02-09 17:37:01 +010086{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +000087 UNINHostState *s = opaque;
Andreas Färber67c332f2012-08-20 19:08:09 +020088 PCIHostState *phb = PCI_HOST_BRIDGE(s);
Mark Cave-Ayland0b0c5e92018-01-26 09:20:28 +000089 trace_unin_data_write(addr, len, val);
Andreas Färber67c332f2012-08-20 19:08:09 +020090 pci_data_write(phb->bus,
91 unin_get_config_reg(phb->config_reg, addr),
Alexander Grafd86f0e32010-02-09 17:37:01 +010092 val, len);
93}
94
Avi Kivitya8170e52012-10-23 12:30:10 +020095static uint64_t unin_data_read(void *opaque, hwaddr addr,
Avi Kivityd0ed8072011-07-24 17:47:18 +030096 unsigned len)
Alexander Grafd86f0e32010-02-09 17:37:01 +010097{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +000098 UNINHostState *s = opaque;
Andreas Färber67c332f2012-08-20 19:08:09 +020099 PCIHostState *phb = PCI_HOST_BRIDGE(s);
Alexander Grafd86f0e32010-02-09 17:37:01 +0100100 uint32_t val;
101
Andreas Färber67c332f2012-08-20 19:08:09 +0200102 val = pci_data_read(phb->bus,
103 unin_get_config_reg(phb->config_reg, addr),
Alexander Grafd86f0e32010-02-09 17:37:01 +0100104 len);
Mark Cave-Ayland0b0c5e92018-01-26 09:20:28 +0000105 trace_unin_data_read(addr, len, val);
Alexander Grafd86f0e32010-02-09 17:37:01 +0100106 return val;
107}
108
Avi Kivityd0ed8072011-07-24 17:47:18 +0300109static const MemoryRegionOps unin_data_ops = {
110 .read = unin_data_read,
111 .write = unin_data_write,
112 .endianness = DEVICE_LITTLE_ENDIAN,
113};
114
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000115static void pci_unin_init_irqs(UNINHostState *s)
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000116{
117 int i;
118
119 for (i = 0; i < ARRAY_SIZE(s->irqs); i++) {
120 s->irqs[i] = qdev_get_gpio_in(DEVICE(s->pic), unin_irq_line[i]);
121 }
122}
123
Mark Cave-Ayland03756c82018-08-29 17:59:10 +0100124static char *pci_unin_main_ofw_unit_address(const SysBusDevice *dev)
125{
126 UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(dev);
127
128 return g_strdup_printf("%x", s->ofw_addr);
129}
130
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000131static void pci_unin_main_realize(DeviceState *dev, Error **errp)
132{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000133 UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(dev);
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000134 PCIHostState *h = PCI_HOST_BRIDGE(dev);
135
136 h->bus = pci_register_root_bus(dev, NULL,
137 pci_unin_set_irq, pci_unin_map_irq,
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000138 s,
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000139 &s->pci_mmio,
Mark Cave-Aylande226efb2018-03-06 20:30:59 +0000140 &s->pci_io,
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000141 PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
142
Mark Cave-Aylandc1d66d32018-03-06 20:30:54 +0000143 pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-pci");
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000144 pci_unin_init_irqs(s);
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000145
146 /* DEC 21154 bridge */
147#if 0
148 /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
149 pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154");
150#endif
151}
152
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000153static void pci_unin_main_init(Object *obj)
pbrook502a5392006-05-13 16:11:23 +0000154{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000155 UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(obj);
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000156 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
157 PCIHostState *h = PCI_HOST_BRIDGE(obj);
pbrook502a5392006-05-13 16:11:23 +0000158
159 /* Use values found on a real PowerMac */
160 /* Uninorth main bus */
Paolo Bonzini40c5dce2013-06-06 21:25:08 -0400161 memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
Mark Cave-Ayland132e9902018-03-06 20:30:51 +0000162 obj, "unin-pci-conf-idx", 0x1000);
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000163 memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, obj,
Mark Cave-Ayland132e9902018-03-06 20:30:51 +0000164 "unin-pci-conf-data", 0x1000);
165
166 memory_region_init(&s->pci_mmio, OBJECT(s), "unin-pci-mmio",
167 0x100000000ULL);
Mark Cave-Aylande226efb2018-03-06 20:30:59 +0000168 memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
169 "unin-pci-isa-mmio", 0x00800000);
Mark Cave-Ayland132e9902018-03-06 20:30:51 +0000170
Mark Cave-Ayland7b193182018-03-06 20:30:56 +0000171 memory_region_init_alias(&s->pci_hole, OBJECT(s),
172 "unin-pci-hole", &s->pci_mmio,
173 0x80000000ULL, 0x10000000ULL);
174
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000175 object_property_add_link(obj, "pic", TYPE_OPENPIC,
176 (Object **) &s->pic,
177 qdev_prop_allow_set_link_before_realize,
178 0, NULL);
179
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000180 sysbus_init_mmio(sbd, &h->conf_mem);
181 sysbus_init_mmio(sbd, &h->data_mem);
Mark Cave-Ayland7b193182018-03-06 20:30:56 +0000182 sysbus_init_mmio(sbd, &s->pci_hole);
Mark Cave-Aylande226efb2018-03-06 20:30:59 +0000183 sysbus_init_mmio(sbd, &s->pci_io);
Blue Swirl2e29bd02009-07-31 20:23:28 +0000184}
185
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000186static void pci_u3_agp_realize(DeviceState *dev, Error **errp)
187{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000188 UNINHostState *s = U3_AGP_HOST_BRIDGE(dev);
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000189 PCIHostState *h = PCI_HOST_BRIDGE(dev);
190
191 h->bus = pci_register_root_bus(dev, NULL,
192 pci_unin_set_irq, pci_unin_map_irq,
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000193 s,
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000194 &s->pci_mmio,
Mark Cave-Aylande226efb2018-03-06 20:30:59 +0000195 &s->pci_io,
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000196 PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
197
198 pci_create_simple(h->bus, PCI_DEVFN(11, 0), "u3-agp");
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000199 pci_unin_init_irqs(s);
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000200}
201
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000202static void pci_u3_agp_init(Object *obj)
Alexander Graf0f921192010-02-09 17:37:02 +0100203{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000204 UNINHostState *s = U3_AGP_HOST_BRIDGE(obj);
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000205 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
206 PCIHostState *h = PCI_HOST_BRIDGE(obj);
Alexander Graf0f921192010-02-09 17:37:02 +0100207
208 /* Uninorth U3 AGP bus */
Paolo Bonzini40c5dce2013-06-06 21:25:08 -0400209 memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
Mark Cave-Ayland132e9902018-03-06 20:30:51 +0000210 obj, "unin-pci-conf-idx", 0x1000);
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000211 memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, obj,
Mark Cave-Ayland132e9902018-03-06 20:30:51 +0000212 "unin-pci-conf-data", 0x1000);
213
214 memory_region_init(&s->pci_mmio, OBJECT(s), "unin-pci-mmio",
215 0x100000000ULL);
Mark Cave-Aylande226efb2018-03-06 20:30:59 +0000216 memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
217 "unin-pci-isa-mmio", 0x00800000);
Mark Cave-Ayland132e9902018-03-06 20:30:51 +0000218
Mark Cave-Ayland8ce3f742018-03-06 20:30:57 +0000219 memory_region_init_alias(&s->pci_hole, OBJECT(s),
220 "unin-pci-hole", &s->pci_mmio,
221 0x80000000ULL, 0x70000000ULL);
222
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000223 object_property_add_link(obj, "pic", TYPE_OPENPIC,
224 (Object **) &s->pic,
225 qdev_prop_allow_set_link_before_realize,
226 0, NULL);
227
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000228 sysbus_init_mmio(sbd, &h->conf_mem);
229 sysbus_init_mmio(sbd, &h->data_mem);
Mark Cave-Ayland8ce3f742018-03-06 20:30:57 +0000230 sysbus_init_mmio(sbd, &s->pci_hole);
Mark Cave-Aylande226efb2018-03-06 20:30:59 +0000231 sysbus_init_mmio(sbd, &s->pci_io);
Alexander Graf0f921192010-02-09 17:37:02 +0100232}
233
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000234static void pci_unin_agp_realize(DeviceState *dev, Error **errp)
235{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000236 UNINHostState *s = UNI_NORTH_AGP_HOST_BRIDGE(dev);
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000237 PCIHostState *h = PCI_HOST_BRIDGE(dev);
238
239 h->bus = pci_register_root_bus(dev, NULL,
240 pci_unin_set_irq, pci_unin_map_irq,
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000241 s,
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000242 &s->pci_mmio,
Mark Cave-Aylande226efb2018-03-06 20:30:59 +0000243 &s->pci_io,
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000244 PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
Mark Cave-Aylandc1d66d32018-03-06 20:30:54 +0000245
246 pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp");
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000247 pci_unin_init_irqs(s);
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000248}
249
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000250static void pci_unin_agp_init(Object *obj)
Blue Swirl2e29bd02009-07-31 20:23:28 +0000251{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000252 UNINHostState *s = UNI_NORTH_AGP_HOST_BRIDGE(obj);
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000253 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
254 PCIHostState *h = PCI_HOST_BRIDGE(obj);
Blue Swirl2e29bd02009-07-31 20:23:28 +0000255
256 /* Uninorth AGP bus */
Paolo Bonzini40c5dce2013-06-06 21:25:08 -0400257 memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
Mark Cave-Ayland132e9902018-03-06 20:30:51 +0000258 obj, "unin-agp-conf-idx", 0x1000);
Paolo Bonzini40c5dce2013-06-06 21:25:08 -0400259 memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
Mark Cave-Ayland132e9902018-03-06 20:30:51 +0000260 obj, "unin-agp-conf-data", 0x1000);
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000261
262 object_property_add_link(obj, "pic", TYPE_OPENPIC,
263 (Object **) &s->pic,
264 qdev_prop_allow_set_link_before_realize,
265 0, NULL);
266
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000267 sysbus_init_mmio(sbd, &h->conf_mem);
268 sysbus_init_mmio(sbd, &h->data_mem);
Blue Swirl2e29bd02009-07-31 20:23:28 +0000269}
270
Mark Cave-Ayland1ff861d2018-03-06 20:30:55 +0000271static void pci_unin_internal_realize(DeviceState *dev, Error **errp)
272{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000273 UNINHostState *s = UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(dev);
Mark Cave-Ayland1ff861d2018-03-06 20:30:55 +0000274 PCIHostState *h = PCI_HOST_BRIDGE(dev);
275
276 h->bus = pci_register_root_bus(dev, NULL,
277 pci_unin_set_irq, pci_unin_map_irq,
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000278 s,
Mark Cave-Ayland1ff861d2018-03-06 20:30:55 +0000279 &s->pci_mmio,
Mark Cave-Aylande226efb2018-03-06 20:30:59 +0000280 &s->pci_io,
Mark Cave-Ayland1ff861d2018-03-06 20:30:55 +0000281 PCI_DEVFN(14, 0), 4, TYPE_PCI_BUS);
282
283 pci_create_simple(h->bus, PCI_DEVFN(14, 0), "uni-north-internal-pci");
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000284 pci_unin_init_irqs(s);
Mark Cave-Ayland1ff861d2018-03-06 20:30:55 +0000285}
286
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000287static void pci_unin_internal_init(Object *obj)
Blue Swirl2e29bd02009-07-31 20:23:28 +0000288{
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000289 UNINHostState *s = UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj);
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000290 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
291 PCIHostState *h = PCI_HOST_BRIDGE(obj);
Blue Swirl2e29bd02009-07-31 20:23:28 +0000292
293 /* Uninorth internal bus */
Paolo Bonzini40c5dce2013-06-06 21:25:08 -0400294 memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
Mark Cave-Ayland132e9902018-03-06 20:30:51 +0000295 obj, "unin-pci-conf-idx", 0x1000);
Paolo Bonzini40c5dce2013-06-06 21:25:08 -0400296 memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
Mark Cave-Ayland132e9902018-03-06 20:30:51 +0000297 obj, "unin-pci-conf-data", 0x1000);
Mark Cave-Aylande7755cc2018-03-06 20:30:58 +0000298
299 object_property_add_link(obj, "pic", TYPE_OPENPIC,
300 (Object **) &s->pic,
301 qdev_prop_allow_set_link_before_realize,
302 0, NULL);
303
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000304 sysbus_init_mmio(sbd, &h->conf_mem);
305 sysbus_init_mmio(sbd, &h->data_mem);
Blue Swirl2e29bd02009-07-31 20:23:28 +0000306}
307
Markus Armbruster9af21db2015-01-19 15:52:30 +0100308static void unin_main_pci_host_realize(PCIDevice *d, Error **errp)
Blue Swirl2e29bd02009-07-31 20:23:28 +0000309{
Mark Cave-Ayland4d309c92018-03-06 20:30:45 +0000310 /* cache_line_size */
311 d->config[0x0C] = 0x08;
312 /* latency_timer */
313 d->config[0x0D] = 0x10;
314 /* capabilities_pointer */
315 d->config[0x34] = 0x00;
Mark Cave-Ayland4d309c92018-03-06 20:30:45 +0000316
Programmingkid98ae3b22016-01-22 11:09:23 -0500317 /*
318 * Set kMacRISCPCIAddressSelect (0x48) register to indicate PCI
319 * memory space with base 0x80000000, size 0x10000000 for Apple's
320 * AppleMacRiscPCI driver
321 */
322 d->config[0x48] = 0x0;
323 d->config[0x49] = 0x0;
324 d->config[0x4a] = 0x0;
325 d->config[0x4b] = 0x1;
Blue Swirl2e29bd02009-07-31 20:23:28 +0000326}
pbrook502a5392006-05-13 16:11:23 +0000327
Mark Cave-Aylandc1d66d32018-03-06 20:30:54 +0000328static void unin_agp_pci_host_realize(PCIDevice *d, Error **errp)
329{
330 /* cache_line_size */
331 d->config[0x0C] = 0x08;
332 /* latency_timer */
333 d->config[0x0D] = 0x10;
334 /* capabilities_pointer
335 d->config[0x34] = 0x80; */
336}
337
Markus Armbruster9af21db2015-01-19 15:52:30 +0100338static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp)
Alexander Graf0f921192010-02-09 17:37:02 +0100339{
Alexander Graf0f921192010-02-09 17:37:02 +0100340 /* cache line size */
341 d->config[0x0C] = 0x08;
342 /* latency timer */
343 d->config[0x0D] = 0x10;
Alexander Graf0f921192010-02-09 17:37:02 +0100344}
345
Markus Armbruster9af21db2015-01-19 15:52:30 +0100346static void unin_internal_pci_host_realize(PCIDevice *d, Error **errp)
Blue Swirl2e29bd02009-07-31 20:23:28 +0000347{
Mark Cave-Ayland4d309c92018-03-06 20:30:45 +0000348 /* cache_line_size */
349 d->config[0x0C] = 0x08;
350 /* latency_timer */
351 d->config[0x0D] = 0x10;
352 /* capabilities_pointer */
353 d->config[0x34] = 0x00;
pbrook502a5392006-05-13 16:11:23 +0000354}
Blue Swirl2e29bd02009-07-31 20:23:28 +0000355
Anthony Liguori40021f02011-12-04 12:22:06 -0600356static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
357{
358 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
Markus Armbruster08c58f92013-11-28 17:26:58 +0100359 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori40021f02011-12-04 12:22:06 -0600360
Markus Armbruster9af21db2015-01-19 15:52:30 +0100361 k->realize = unin_main_pci_host_realize;
Anthony Liguori40021f02011-12-04 12:22:06 -0600362 k->vendor_id = PCI_VENDOR_ID_APPLE;
363 k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI;
364 k->revision = 0x00;
365 k->class_id = PCI_CLASS_BRIDGE_HOST;
Markus Armbruster08c58f92013-11-28 17:26:58 +0100366 /*
367 * PCI-facing part of the host bridge, not usable without the
368 * host-facing part, which can't be device_add'ed, yet.
369 */
Eduardo Habkoste90f2a82017-05-03 17:35:44 -0300370 dc->user_creatable = false;
Anthony Liguori40021f02011-12-04 12:22:06 -0600371}
372
Andreas Färber4240abf2012-08-20 19:07:56 +0200373static const TypeInfo unin_main_pci_host_info = {
Anthony Liguori40021f02011-12-04 12:22:06 -0600374 .name = "uni-north-pci",
Anthony Liguori39bffca2011-12-07 21:34:16 -0600375 .parent = TYPE_PCI_DEVICE,
376 .instance_size = sizeof(PCIDevice),
Anthony Liguori40021f02011-12-04 12:22:06 -0600377 .class_init = unin_main_pci_host_class_init,
Eduardo Habkostfd3b02c2017-09-27 16:56:34 -0300378 .interfaces = (InterfaceInfo[]) {
379 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
380 { },
381 },
Blue Swirl2e29bd02009-07-31 20:23:28 +0000382};
383
Anthony Liguori40021f02011-12-04 12:22:06 -0600384static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
385{
386 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
Markus Armbruster08c58f92013-11-28 17:26:58 +0100387 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori40021f02011-12-04 12:22:06 -0600388
Markus Armbruster9af21db2015-01-19 15:52:30 +0100389 k->realize = u3_agp_pci_host_realize;
Anthony Liguori40021f02011-12-04 12:22:06 -0600390 k->vendor_id = PCI_VENDOR_ID_APPLE;
391 k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP;
392 k->revision = 0x00;
393 k->class_id = PCI_CLASS_BRIDGE_HOST;
Markus Armbruster08c58f92013-11-28 17:26:58 +0100394 /*
395 * PCI-facing part of the host bridge, not usable without the
396 * host-facing part, which can't be device_add'ed, yet.
397 */
Eduardo Habkoste90f2a82017-05-03 17:35:44 -0300398 dc->user_creatable = false;
Anthony Liguori40021f02011-12-04 12:22:06 -0600399}
400
Andreas Färber4240abf2012-08-20 19:07:56 +0200401static const TypeInfo u3_agp_pci_host_info = {
Anthony Liguori40021f02011-12-04 12:22:06 -0600402 .name = "u3-agp",
Anthony Liguori39bffca2011-12-07 21:34:16 -0600403 .parent = TYPE_PCI_DEVICE,
404 .instance_size = sizeof(PCIDevice),
Anthony Liguori40021f02011-12-04 12:22:06 -0600405 .class_init = u3_agp_pci_host_class_init,
Eduardo Habkostfd3b02c2017-09-27 16:56:34 -0300406 .interfaces = (InterfaceInfo[]) {
407 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
408 { },
409 },
Alexander Graf0f921192010-02-09 17:37:02 +0100410};
411
Anthony Liguori40021f02011-12-04 12:22:06 -0600412static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
413{
414 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
Markus Armbruster08c58f92013-11-28 17:26:58 +0100415 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori40021f02011-12-04 12:22:06 -0600416
Markus Armbruster9af21db2015-01-19 15:52:30 +0100417 k->realize = unin_agp_pci_host_realize;
Anthony Liguori40021f02011-12-04 12:22:06 -0600418 k->vendor_id = PCI_VENDOR_ID_APPLE;
419 k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP;
420 k->revision = 0x00;
421 k->class_id = PCI_CLASS_BRIDGE_HOST;
Markus Armbruster08c58f92013-11-28 17:26:58 +0100422 /*
423 * PCI-facing part of the host bridge, not usable without the
424 * host-facing part, which can't be device_add'ed, yet.
425 */
Eduardo Habkoste90f2a82017-05-03 17:35:44 -0300426 dc->user_creatable = false;
Anthony Liguori40021f02011-12-04 12:22:06 -0600427}
428
Andreas Färber4240abf2012-08-20 19:07:56 +0200429static const TypeInfo unin_agp_pci_host_info = {
Anthony Liguori40021f02011-12-04 12:22:06 -0600430 .name = "uni-north-agp",
Anthony Liguori39bffca2011-12-07 21:34:16 -0600431 .parent = TYPE_PCI_DEVICE,
432 .instance_size = sizeof(PCIDevice),
Anthony Liguori40021f02011-12-04 12:22:06 -0600433 .class_init = unin_agp_pci_host_class_init,
Eduardo Habkostfd3b02c2017-09-27 16:56:34 -0300434 .interfaces = (InterfaceInfo[]) {
435 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
436 { },
437 },
Blue Swirl2e29bd02009-07-31 20:23:28 +0000438};
439
Anthony Liguori40021f02011-12-04 12:22:06 -0600440static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
441{
442 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
Markus Armbruster08c58f92013-11-28 17:26:58 +0100443 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori40021f02011-12-04 12:22:06 -0600444
Markus Armbruster9af21db2015-01-19 15:52:30 +0100445 k->realize = unin_internal_pci_host_realize;
Anthony Liguori40021f02011-12-04 12:22:06 -0600446 k->vendor_id = PCI_VENDOR_ID_APPLE;
447 k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI;
448 k->revision = 0x00;
449 k->class_id = PCI_CLASS_BRIDGE_HOST;
Markus Armbruster08c58f92013-11-28 17:26:58 +0100450 /*
451 * PCI-facing part of the host bridge, not usable without the
452 * host-facing part, which can't be device_add'ed, yet.
453 */
Eduardo Habkoste90f2a82017-05-03 17:35:44 -0300454 dc->user_creatable = false;
Anthony Liguori40021f02011-12-04 12:22:06 -0600455}
456
Andreas Färber4240abf2012-08-20 19:07:56 +0200457static const TypeInfo unin_internal_pci_host_info = {
Anthony Liguori40021f02011-12-04 12:22:06 -0600458 .name = "uni-north-internal-pci",
Anthony Liguori39bffca2011-12-07 21:34:16 -0600459 .parent = TYPE_PCI_DEVICE,
460 .instance_size = sizeof(PCIDevice),
Anthony Liguori40021f02011-12-04 12:22:06 -0600461 .class_init = unin_internal_pci_host_class_init,
Eduardo Habkostfd3b02c2017-09-27 16:56:34 -0300462 .interfaces = (InterfaceInfo[]) {
463 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
464 { },
465 },
Blue Swirl2e29bd02009-07-31 20:23:28 +0000466};
467
Mark Cave-Ayland03756c82018-08-29 17:59:10 +0100468static Property pci_unin_main_pci_host_props[] = {
469 DEFINE_PROP_UINT32("ofw-addr", UNINHostState, ofw_addr, -1),
470 DEFINE_PROP_END_OF_LIST()
471};
472
Anthony Liguori999e12b2012-01-24 13:12:29 -0600473static void pci_unin_main_class_init(ObjectClass *klass, void *data)
474{
Laurent Vivier1d16f862015-09-26 18:22:09 +0200475 DeviceClass *dc = DEVICE_CLASS(klass);
Mark Cave-Ayland03756c82018-08-29 17:59:10 +0100476 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
Anthony Liguori999e12b2012-01-24 13:12:29 -0600477
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000478 dc->realize = pci_unin_main_realize;
Mark Cave-Ayland03756c82018-08-29 17:59:10 +0100479 dc->props = pci_unin_main_pci_host_props;
Laurent Vivier1d16f862015-09-26 18:22:09 +0200480 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
Mark Cave-Ayland03756c82018-08-29 17:59:10 +0100481 dc->fw_name = "pci";
482 sbc->explicit_ofw_unit_address = pci_unin_main_ofw_unit_address;
Anthony Liguori999e12b2012-01-24 13:12:29 -0600483}
484
Andreas Färber4240abf2012-08-20 19:07:56 +0200485static const TypeInfo pci_unin_main_info = {
Andreas Färber57fd7b72012-08-20 19:08:06 +0200486 .name = TYPE_UNI_NORTH_PCI_HOST_BRIDGE,
Andreas Färber8558d942012-08-20 19:08:08 +0200487 .parent = TYPE_PCI_HOST_BRIDGE,
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000488 .instance_size = sizeof(UNINHostState),
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000489 .instance_init = pci_unin_main_init,
Anthony Liguori39bffca2011-12-07 21:34:16 -0600490 .class_init = pci_unin_main_class_init,
Andreas Färber70f9c982012-01-19 07:40:16 +0000491};
492
Anthony Liguori999e12b2012-01-24 13:12:29 -0600493static void pci_u3_agp_class_init(ObjectClass *klass, void *data)
494{
Laurent Vivier1d16f862015-09-26 18:22:09 +0200495 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori999e12b2012-01-24 13:12:29 -0600496
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000497 dc->realize = pci_u3_agp_realize;
Laurent Vivier1d16f862015-09-26 18:22:09 +0200498 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
Anthony Liguori999e12b2012-01-24 13:12:29 -0600499}
500
Andreas Färber4240abf2012-08-20 19:07:56 +0200501static const TypeInfo pci_u3_agp_info = {
Andreas Färber57fd7b72012-08-20 19:08:06 +0200502 .name = TYPE_U3_AGP_HOST_BRIDGE,
Andreas Färber8558d942012-08-20 19:08:08 +0200503 .parent = TYPE_PCI_HOST_BRIDGE,
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000504 .instance_size = sizeof(UNINHostState),
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000505 .instance_init = pci_u3_agp_init,
Anthony Liguori39bffca2011-12-07 21:34:16 -0600506 .class_init = pci_u3_agp_class_init,
Andreas Färber70f9c982012-01-19 07:40:16 +0000507};
508
Anthony Liguori999e12b2012-01-24 13:12:29 -0600509static void pci_unin_agp_class_init(ObjectClass *klass, void *data)
510{
Laurent Vivier1d16f862015-09-26 18:22:09 +0200511 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori999e12b2012-01-24 13:12:29 -0600512
Mark Cave-Ayland32cde612018-03-06 20:30:53 +0000513 dc->realize = pci_unin_agp_realize;
Laurent Vivier1d16f862015-09-26 18:22:09 +0200514 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
Anthony Liguori999e12b2012-01-24 13:12:29 -0600515}
516
Andreas Färber4240abf2012-08-20 19:07:56 +0200517static const TypeInfo pci_unin_agp_info = {
Andreas Färber57fd7b72012-08-20 19:08:06 +0200518 .name = TYPE_UNI_NORTH_AGP_HOST_BRIDGE,
Andreas Färber8558d942012-08-20 19:08:08 +0200519 .parent = TYPE_PCI_HOST_BRIDGE,
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000520 .instance_size = sizeof(UNINHostState),
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000521 .instance_init = pci_unin_agp_init,
Anthony Liguori39bffca2011-12-07 21:34:16 -0600522 .class_init = pci_unin_agp_class_init,
Andreas Färber70f9c982012-01-19 07:40:16 +0000523};
524
Anthony Liguori999e12b2012-01-24 13:12:29 -0600525static void pci_unin_internal_class_init(ObjectClass *klass, void *data)
526{
Laurent Vivier1d16f862015-09-26 18:22:09 +0200527 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori999e12b2012-01-24 13:12:29 -0600528
Mark Cave-Ayland1ff861d2018-03-06 20:30:55 +0000529 dc->realize = pci_unin_internal_realize;
Laurent Vivier1d16f862015-09-26 18:22:09 +0200530 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
Anthony Liguori999e12b2012-01-24 13:12:29 -0600531}
532
Andreas Färber4240abf2012-08-20 19:07:56 +0200533static const TypeInfo pci_unin_internal_info = {
Andreas Färber57fd7b72012-08-20 19:08:06 +0200534 .name = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE,
Andreas Färber8558d942012-08-20 19:08:08 +0200535 .parent = TYPE_PCI_HOST_BRIDGE,
Mark Cave-Aylandc90c3932018-03-06 20:31:00 +0000536 .instance_size = sizeof(UNINHostState),
Mark Cave-Ayland02034592018-03-06 20:30:47 +0000537 .instance_init = pci_unin_internal_init,
Anthony Liguori39bffca2011-12-07 21:34:16 -0600538 .class_init = pci_unin_internal_class_init,
Andreas Färber70f9c982012-01-19 07:40:16 +0000539};
540
Mark Cave-Ayland06629462018-05-03 21:24:39 +0100541/* UniN device */
542static void unin_write(void *opaque, hwaddr addr, uint64_t value,
543 unsigned size)
544{
545 trace_unin_write(addr, value);
Mark Cave-Ayland06629462018-05-03 21:24:39 +0100546}
547
548static uint64_t unin_read(void *opaque, hwaddr addr, unsigned size)
549{
550 uint32_t value;
551
Mark Cave-Ayland06629462018-05-03 21:24:39 +0100552 switch (addr) {
553 case 0:
Mark Cave-Ayland45fefe72018-05-06 15:20:05 +0100554 value = UNINORTH_VERSION_10A;
555 break;
556 default:
557 value = 0;
Mark Cave-Ayland06629462018-05-03 21:24:39 +0100558 }
559
560 trace_unin_read(addr, value);
561
562 return value;
563}
564
565static const MemoryRegionOps unin_ops = {
566 .read = unin_read,
567 .write = unin_write,
568 .endianness = DEVICE_BIG_ENDIAN,
569};
570
571static void unin_init(Object *obj)
572{
573 UNINState *s = UNI_NORTH(obj);
574 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
575
Mark Cave-Ayland45fefe72018-05-06 15:20:05 +0100576 memory_region_init_io(&s->mem, obj, &unin_ops, s, "unin", 0x1000);
Mark Cave-Ayland06629462018-05-03 21:24:39 +0100577
578 sysbus_init_mmio(sbd, &s->mem);
579}
580
581static void unin_class_init(ObjectClass *klass, void *data)
582{
583 DeviceClass *dc = DEVICE_CLASS(klass);
584
585 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
586}
587
588static const TypeInfo unin_info = {
589 .name = TYPE_UNI_NORTH,
590 .parent = TYPE_SYS_BUS_DEVICE,
591 .instance_size = sizeof(UNINState),
592 .instance_init = unin_init,
593 .class_init = unin_class_init,
594};
595
Andreas Färber83f7d432012-02-09 15:20:55 +0100596static void unin_register_types(void)
Blue Swirl2e29bd02009-07-31 20:23:28 +0000597{
Anthony Liguori39bffca2011-12-07 21:34:16 -0600598 type_register_static(&unin_main_pci_host_info);
599 type_register_static(&u3_agp_pci_host_info);
600 type_register_static(&unin_agp_pci_host_info);
601 type_register_static(&unin_internal_pci_host_info);
Anthony Liguori999e12b2012-01-24 13:12:29 -0600602
Anthony Liguori39bffca2011-12-07 21:34:16 -0600603 type_register_static(&pci_unin_main_info);
604 type_register_static(&pci_u3_agp_info);
605 type_register_static(&pci_unin_agp_info);
606 type_register_static(&pci_unin_internal_info);
Mark Cave-Ayland06629462018-05-03 21:24:39 +0100607
608 type_register_static(&unin_info);
Blue Swirl2e29bd02009-07-31 20:23:28 +0000609}
610
Andreas Färber83f7d432012-02-09 15:20:55 +0100611type_init(unin_register_types)