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