xref: /openbmc/qemu/hw/pci-host/uninorth.c (revision e6b5a071)
1 /*
2  * QEMU Uninorth PCI host (for all Mac99 and newer machines)
3  *
4  * Copyright (c) 2006 Fabrice Bellard
5  *
6  * 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  */
24 
25 #include "qemu/osdep.h"
26 #include "hw/irq.h"
27 #include "hw/ppc/mac.h"
28 #include "hw/qdev-properties.h"
29 #include "qemu/module.h"
30 #include "hw/pci/pci.h"
31 #include "hw/pci/pci_host.h"
32 #include "hw/pci-host/uninorth.h"
33 #include "trace.h"
34 
35 static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
36 {
37     return (irq_num + (pci_dev->devfn >> 3)) & 3;
38 }
39 
40 static void pci_unin_set_irq(void *opaque, int irq_num, int level)
41 {
42     UNINHostState *s = opaque;
43 
44     trace_unin_set_irq(irq_num, level);
45     qemu_set_irq(s->irqs[irq_num], level);
46 }
47 
48 static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
49 {
50     uint32_t retval;
51 
52     if (reg & (1u << 31)) {
53         /* XXX OpenBIOS compatibility hack */
54         retval = reg | (addr & 3);
55     } else if (reg & 1) {
56         /* CFA1 style */
57         retval = (reg & ~7u) | (addr & 7);
58     } else {
59         uint32_t slot, func;
60 
61         /* Grab CFA0 style values */
62         slot = ctz32(reg & 0xfffff800);
63         if (slot == 32) {
64             slot = -1; /* XXX: should this be 0? */
65         }
66         func = (reg >> 8) & 7;
67 
68         /* ... and then convert them to x86 format */
69         /* config pointer */
70         retval = (reg & (0xff - 7)) | (addr & 7);
71         /* slot */
72         retval |= slot << 11;
73         /* fn */
74         retval |= func << 8;
75     }
76 
77     trace_unin_get_config_reg(reg, addr, retval);
78 
79     return retval;
80 }
81 
82 static void unin_data_write(void *opaque, hwaddr addr,
83                             uint64_t val, unsigned len)
84 {
85     UNINHostState *s = opaque;
86     PCIHostState *phb = PCI_HOST_BRIDGE(s);
87     trace_unin_data_write(addr, len, val);
88     pci_data_write(phb->bus,
89                    unin_get_config_reg(phb->config_reg, addr),
90                    val, len);
91 }
92 
93 static uint64_t unin_data_read(void *opaque, hwaddr addr,
94                                unsigned len)
95 {
96     UNINHostState *s = opaque;
97     PCIHostState *phb = PCI_HOST_BRIDGE(s);
98     uint32_t val;
99 
100     val = pci_data_read(phb->bus,
101                         unin_get_config_reg(phb->config_reg, addr),
102                         len);
103     trace_unin_data_read(addr, len, val);
104     return val;
105 }
106 
107 static const MemoryRegionOps unin_data_ops = {
108     .read = unin_data_read,
109     .write = unin_data_write,
110     .endianness = DEVICE_LITTLE_ENDIAN,
111 };
112 
113 static char *pci_unin_main_ofw_unit_address(const SysBusDevice *dev)
114 {
115     UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(dev);
116 
117     return g_strdup_printf("%x", s->ofw_addr);
118 }
119 
120 static void pci_unin_main_realize(DeviceState *dev, Error **errp)
121 {
122     UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(dev);
123     PCIHostState *h = PCI_HOST_BRIDGE(dev);
124 
125     h->bus = pci_register_root_bus(dev, NULL,
126                                    pci_unin_set_irq, pci_unin_map_irq,
127                                    s,
128                                    &s->pci_mmio,
129                                    &s->pci_io,
130                                    PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
131 
132     pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-pci");
133 
134     /* DEC 21154 bridge */
135 #if 0
136     /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
137     pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154");
138 #endif
139 }
140 
141 static void pci_unin_main_init(Object *obj)
142 {
143     UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(obj);
144     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
145     PCIHostState *h = PCI_HOST_BRIDGE(obj);
146 
147     /* Use values found on a real PowerMac */
148     /* Uninorth main bus */
149     memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
150                           obj, "unin-pci-conf-idx", 0x1000);
151     memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, obj,
152                           "unin-pci-conf-data", 0x1000);
153 
154     memory_region_init(&s->pci_mmio, OBJECT(s), "unin-pci-mmio",
155                        0x100000000ULL);
156     memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
157                           "unin-pci-isa-mmio", 0x00800000);
158 
159     memory_region_init_alias(&s->pci_hole, OBJECT(s),
160                              "unin-pci-hole", &s->pci_mmio,
161                              0x80000000ULL, 0x10000000ULL);
162 
163     sysbus_init_mmio(sbd, &h->conf_mem);
164     sysbus_init_mmio(sbd, &h->data_mem);
165     sysbus_init_mmio(sbd, &s->pci_hole);
166     sysbus_init_mmio(sbd, &s->pci_io);
167 
168     qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs));
169 }
170 
171 static void pci_u3_agp_realize(DeviceState *dev, Error **errp)
172 {
173     UNINHostState *s = U3_AGP_HOST_BRIDGE(dev);
174     PCIHostState *h = PCI_HOST_BRIDGE(dev);
175 
176     h->bus = pci_register_root_bus(dev, NULL,
177                                    pci_unin_set_irq, pci_unin_map_irq,
178                                    s,
179                                    &s->pci_mmio,
180                                    &s->pci_io,
181                                    PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
182 
183     pci_create_simple(h->bus, PCI_DEVFN(11, 0), "u3-agp");
184 }
185 
186 static void pci_u3_agp_init(Object *obj)
187 {
188     UNINHostState *s = U3_AGP_HOST_BRIDGE(obj);
189     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
190     PCIHostState *h = PCI_HOST_BRIDGE(obj);
191 
192     /* Uninorth U3 AGP bus */
193     memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
194                           obj, "unin-pci-conf-idx", 0x1000);
195     memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, obj,
196                           "unin-pci-conf-data", 0x1000);
197 
198     memory_region_init(&s->pci_mmio, OBJECT(s), "unin-pci-mmio",
199                        0x100000000ULL);
200     memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
201                           "unin-pci-isa-mmio", 0x00800000);
202 
203     memory_region_init_alias(&s->pci_hole, OBJECT(s),
204                              "unin-pci-hole", &s->pci_mmio,
205                              0x80000000ULL, 0x70000000ULL);
206 
207     sysbus_init_mmio(sbd, &h->conf_mem);
208     sysbus_init_mmio(sbd, &h->data_mem);
209     sysbus_init_mmio(sbd, &s->pci_hole);
210     sysbus_init_mmio(sbd, &s->pci_io);
211 
212     qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs));
213 }
214 
215 static void pci_unin_agp_realize(DeviceState *dev, Error **errp)
216 {
217     UNINHostState *s = UNI_NORTH_AGP_HOST_BRIDGE(dev);
218     PCIHostState *h = PCI_HOST_BRIDGE(dev);
219 
220     h->bus = pci_register_root_bus(dev, NULL,
221                                    pci_unin_set_irq, pci_unin_map_irq,
222                                    s,
223                                    &s->pci_mmio,
224                                    &s->pci_io,
225                                    PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
226 
227     pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp");
228 }
229 
230 static void pci_unin_agp_init(Object *obj)
231 {
232     UNINHostState *s = UNI_NORTH_AGP_HOST_BRIDGE(obj);
233     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
234     PCIHostState *h = PCI_HOST_BRIDGE(obj);
235 
236     /* Uninorth AGP bus */
237     memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
238                           obj, "unin-agp-conf-idx", 0x1000);
239     memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
240                           obj, "unin-agp-conf-data", 0x1000);
241 
242     sysbus_init_mmio(sbd, &h->conf_mem);
243     sysbus_init_mmio(sbd, &h->data_mem);
244 
245     qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs));
246 }
247 
248 static void pci_unin_internal_realize(DeviceState *dev, Error **errp)
249 {
250     UNINHostState *s = UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(dev);
251     PCIHostState *h = PCI_HOST_BRIDGE(dev);
252 
253     h->bus = pci_register_root_bus(dev, NULL,
254                                    pci_unin_set_irq, pci_unin_map_irq,
255                                    s,
256                                    &s->pci_mmio,
257                                    &s->pci_io,
258                                    PCI_DEVFN(14, 0), 4, TYPE_PCI_BUS);
259 
260     pci_create_simple(h->bus, PCI_DEVFN(14, 0), "uni-north-internal-pci");
261 }
262 
263 static void pci_unin_internal_init(Object *obj)
264 {
265     UNINHostState *s = UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj);
266     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
267     PCIHostState *h = PCI_HOST_BRIDGE(obj);
268 
269     /* Uninorth internal bus */
270     memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
271                           obj, "unin-pci-conf-idx", 0x1000);
272     memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
273                           obj, "unin-pci-conf-data", 0x1000);
274 
275     sysbus_init_mmio(sbd, &h->conf_mem);
276     sysbus_init_mmio(sbd, &h->data_mem);
277 
278     qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs));
279 }
280 
281 static void unin_main_pci_host_realize(PCIDevice *d, Error **errp)
282 {
283     /* cache_line_size */
284     d->config[0x0C] = 0x08;
285     /* latency_timer */
286     d->config[0x0D] = 0x10;
287     /* capabilities_pointer */
288     d->config[0x34] = 0x00;
289 
290     /*
291      * Set kMacRISCPCIAddressSelect (0x48) register to indicate PCI
292      * memory space with base 0x80000000, size 0x10000000 for Apple's
293      * AppleMacRiscPCI driver
294      */
295     d->config[0x48] = 0x0;
296     d->config[0x49] = 0x0;
297     d->config[0x4a] = 0x0;
298     d->config[0x4b] = 0x1;
299 }
300 
301 static void unin_agp_pci_host_realize(PCIDevice *d, Error **errp)
302 {
303     /* cache_line_size */
304     d->config[0x0C] = 0x08;
305     /* latency_timer */
306     d->config[0x0D] = 0x10;
307     /* capabilities_pointer
308     d->config[0x34] = 0x80; */
309 }
310 
311 static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp)
312 {
313     /* cache line size */
314     d->config[0x0C] = 0x08;
315     /* latency timer */
316     d->config[0x0D] = 0x10;
317 }
318 
319 static void unin_internal_pci_host_realize(PCIDevice *d, Error **errp)
320 {
321     /* cache_line_size */
322     d->config[0x0C] = 0x08;
323     /* latency_timer */
324     d->config[0x0D] = 0x10;
325     /* capabilities_pointer */
326     d->config[0x34] = 0x00;
327 }
328 
329 static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
330 {
331     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
332     DeviceClass *dc = DEVICE_CLASS(klass);
333 
334     k->realize   = unin_main_pci_host_realize;
335     k->vendor_id = PCI_VENDOR_ID_APPLE;
336     k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI;
337     k->revision  = 0x00;
338     k->class_id  = PCI_CLASS_BRIDGE_HOST;
339     /*
340      * PCI-facing part of the host bridge, not usable without the
341      * host-facing part, which can't be device_add'ed, yet.
342      */
343     dc->user_creatable = false;
344 }
345 
346 static const TypeInfo unin_main_pci_host_info = {
347     .name = "uni-north-pci",
348     .parent = TYPE_PCI_DEVICE,
349     .instance_size = sizeof(PCIDevice),
350     .class_init = unin_main_pci_host_class_init,
351     .interfaces = (InterfaceInfo[]) {
352         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
353         { },
354     },
355 };
356 
357 static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
358 {
359     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
360     DeviceClass *dc = DEVICE_CLASS(klass);
361 
362     k->realize   = u3_agp_pci_host_realize;
363     k->vendor_id = PCI_VENDOR_ID_APPLE;
364     k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP;
365     k->revision  = 0x00;
366     k->class_id  = PCI_CLASS_BRIDGE_HOST;
367     /*
368      * PCI-facing part of the host bridge, not usable without the
369      * host-facing part, which can't be device_add'ed, yet.
370      */
371     dc->user_creatable = false;
372 }
373 
374 static const TypeInfo u3_agp_pci_host_info = {
375     .name = "u3-agp",
376     .parent = TYPE_PCI_DEVICE,
377     .instance_size = sizeof(PCIDevice),
378     .class_init = u3_agp_pci_host_class_init,
379     .interfaces = (InterfaceInfo[]) {
380         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
381         { },
382     },
383 };
384 
385 static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
386 {
387     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
388     DeviceClass *dc = DEVICE_CLASS(klass);
389 
390     k->realize   = unin_agp_pci_host_realize;
391     k->vendor_id = PCI_VENDOR_ID_APPLE;
392     k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP;
393     k->revision  = 0x00;
394     k->class_id  = PCI_CLASS_BRIDGE_HOST;
395     /*
396      * PCI-facing part of the host bridge, not usable without the
397      * host-facing part, which can't be device_add'ed, yet.
398      */
399     dc->user_creatable = false;
400 }
401 
402 static const TypeInfo unin_agp_pci_host_info = {
403     .name = "uni-north-agp",
404     .parent = TYPE_PCI_DEVICE,
405     .instance_size = sizeof(PCIDevice),
406     .class_init = unin_agp_pci_host_class_init,
407     .interfaces = (InterfaceInfo[]) {
408         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
409         { },
410     },
411 };
412 
413 static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
414 {
415     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
416     DeviceClass *dc = DEVICE_CLASS(klass);
417 
418     k->realize   = unin_internal_pci_host_realize;
419     k->vendor_id = PCI_VENDOR_ID_APPLE;
420     k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI;
421     k->revision  = 0x00;
422     k->class_id  = PCI_CLASS_BRIDGE_HOST;
423     /*
424      * PCI-facing part of the host bridge, not usable without the
425      * host-facing part, which can't be device_add'ed, yet.
426      */
427     dc->user_creatable = false;
428 }
429 
430 static const TypeInfo unin_internal_pci_host_info = {
431     .name = "uni-north-internal-pci",
432     .parent = TYPE_PCI_DEVICE,
433     .instance_size = sizeof(PCIDevice),
434     .class_init = unin_internal_pci_host_class_init,
435     .interfaces = (InterfaceInfo[]) {
436         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
437         { },
438     },
439 };
440 
441 static Property pci_unin_main_pci_host_props[] = {
442     DEFINE_PROP_UINT32("ofw-addr", UNINHostState, ofw_addr, -1),
443     DEFINE_PROP_END_OF_LIST()
444 };
445 
446 static void pci_unin_main_class_init(ObjectClass *klass, void *data)
447 {
448     DeviceClass *dc = DEVICE_CLASS(klass);
449     SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
450 
451     dc->realize = pci_unin_main_realize;
452     device_class_set_props(dc, pci_unin_main_pci_host_props);
453     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
454     dc->fw_name = "pci";
455     sbc->explicit_ofw_unit_address = pci_unin_main_ofw_unit_address;
456 }
457 
458 static const TypeInfo pci_unin_main_info = {
459     .name          = TYPE_UNI_NORTH_PCI_HOST_BRIDGE,
460     .parent        = TYPE_PCI_HOST_BRIDGE,
461     .instance_size = sizeof(UNINHostState),
462     .instance_init = pci_unin_main_init,
463     .class_init    = pci_unin_main_class_init,
464 };
465 
466 static void pci_u3_agp_class_init(ObjectClass *klass, void *data)
467 {
468     DeviceClass *dc = DEVICE_CLASS(klass);
469 
470     dc->realize = pci_u3_agp_realize;
471     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
472 }
473 
474 static const TypeInfo pci_u3_agp_info = {
475     .name          = TYPE_U3_AGP_HOST_BRIDGE,
476     .parent        = TYPE_PCI_HOST_BRIDGE,
477     .instance_size = sizeof(UNINHostState),
478     .instance_init = pci_u3_agp_init,
479     .class_init    = pci_u3_agp_class_init,
480 };
481 
482 static void pci_unin_agp_class_init(ObjectClass *klass, void *data)
483 {
484     DeviceClass *dc = DEVICE_CLASS(klass);
485 
486     dc->realize = pci_unin_agp_realize;
487     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
488 }
489 
490 static const TypeInfo pci_unin_agp_info = {
491     .name          = TYPE_UNI_NORTH_AGP_HOST_BRIDGE,
492     .parent        = TYPE_PCI_HOST_BRIDGE,
493     .instance_size = sizeof(UNINHostState),
494     .instance_init = pci_unin_agp_init,
495     .class_init    = pci_unin_agp_class_init,
496 };
497 
498 static void pci_unin_internal_class_init(ObjectClass *klass, void *data)
499 {
500     DeviceClass *dc = DEVICE_CLASS(klass);
501 
502     dc->realize = pci_unin_internal_realize;
503     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
504 }
505 
506 static const TypeInfo pci_unin_internal_info = {
507     .name          = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE,
508     .parent        = TYPE_PCI_HOST_BRIDGE,
509     .instance_size = sizeof(UNINHostState),
510     .instance_init = pci_unin_internal_init,
511     .class_init    = pci_unin_internal_class_init,
512 };
513 
514 /* UniN device */
515 static void unin_write(void *opaque, hwaddr addr, uint64_t value,
516                        unsigned size)
517 {
518     trace_unin_write(addr, value);
519 }
520 
521 static uint64_t unin_read(void *opaque, hwaddr addr, unsigned size)
522 {
523     uint32_t value;
524 
525     switch (addr) {
526     case 0:
527         value = UNINORTH_VERSION_10A;
528         break;
529     default:
530         value = 0;
531     }
532 
533     trace_unin_read(addr, value);
534 
535     return value;
536 }
537 
538 static const MemoryRegionOps unin_ops = {
539     .read = unin_read,
540     .write = unin_write,
541     .endianness = DEVICE_BIG_ENDIAN,
542 };
543 
544 static void unin_init(Object *obj)
545 {
546     UNINState *s = UNI_NORTH(obj);
547     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
548 
549     memory_region_init_io(&s->mem, obj, &unin_ops, s, "unin", 0x1000);
550 
551     sysbus_init_mmio(sbd, &s->mem);
552 }
553 
554 static void unin_class_init(ObjectClass *klass, void *data)
555 {
556     DeviceClass *dc = DEVICE_CLASS(klass);
557 
558     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
559 }
560 
561 static const TypeInfo unin_info = {
562     .name          = TYPE_UNI_NORTH,
563     .parent        = TYPE_SYS_BUS_DEVICE,
564     .instance_size = sizeof(UNINState),
565     .instance_init = unin_init,
566     .class_init    = unin_class_init,
567 };
568 
569 static void unin_register_types(void)
570 {
571     type_register_static(&unin_main_pci_host_info);
572     type_register_static(&u3_agp_pci_host_info);
573     type_register_static(&unin_agp_pci_host_info);
574     type_register_static(&unin_internal_pci_host_info);
575 
576     type_register_static(&pci_unin_main_info);
577     type_register_static(&pci_u3_agp_info);
578     type_register_static(&pci_unin_agp_info);
579     type_register_static(&pci_unin_internal_info);
580 
581     type_register_static(&unin_info);
582 }
583 
584 type_init(unin_register_types)
585