xref: /openbmc/qemu/hw/pci-host/uninorth.c (revision a5ed75fe2e6625b2ab9ed0694d7a5c95a74b84f7)
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     qemu_irq *pic = opaque;
42 
43     trace_unin_set_irq(unin_irq_line[irq_num], level);
44     qemu_set_irq(pic[unin_irq_line[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     UNINState *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     UNINState *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_main_init(Object *obj)
113 {
114     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
115     PCIHostState *h = PCI_HOST_BRIDGE(obj);
116 
117     /* Use values found on a real PowerMac */
118     /* Uninorth main bus */
119     memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
120                           obj, "pci-conf-idx", 0x1000);
121     memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, obj,
122                           "pci-conf-data", 0x1000);
123     sysbus_init_mmio(sbd, &h->conf_mem);
124     sysbus_init_mmio(sbd, &h->data_mem);
125 }
126 
127 static void pci_u3_agp_init(Object *obj)
128 {
129     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
130     PCIHostState *h = PCI_HOST_BRIDGE(obj);
131 
132     /* Uninorth U3 AGP bus */
133     memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
134                           obj, "pci-conf-idx", 0x1000);
135     memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, obj,
136                           "pci-conf-data", 0x1000);
137     sysbus_init_mmio(sbd, &h->conf_mem);
138     sysbus_init_mmio(sbd, &h->data_mem);
139 }
140 
141 static void pci_unin_agp_init(Object *obj)
142 {
143     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
144     PCIHostState *h = PCI_HOST_BRIDGE(obj);
145 
146     /* Uninorth AGP bus */
147     memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
148                           obj, "pci-conf-idx", 0x1000);
149     memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
150                           obj, "pci-conf-data", 0x1000);
151     sysbus_init_mmio(sbd, &h->conf_mem);
152     sysbus_init_mmio(sbd, &h->data_mem);
153 }
154 
155 static void pci_unin_internal_init(Object *obj)
156 {
157     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
158     PCIHostState *h = PCI_HOST_BRIDGE(obj);
159 
160     /* Uninorth internal bus */
161     memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
162                           obj, "pci-conf-idx", 0x1000);
163     memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
164                           obj, "pci-conf-data", 0x1000);
165     sysbus_init_mmio(sbd, &h->conf_mem);
166     sysbus_init_mmio(sbd, &h->data_mem);
167 }
168 
169 UNINState *pci_pmac_init(qemu_irq *pic,
170                          MemoryRegion *address_space_mem,
171                          MemoryRegion *address_space_io)
172 {
173     DeviceState *dev;
174     SysBusDevice *s;
175     PCIHostState *h;
176     UNINState *d;
177 
178     /* Use values found on a real PowerMac */
179     /* Uninorth main bus */
180     dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE);
181     qdev_init_nofail(dev);
182     s = SYS_BUS_DEVICE(dev);
183     h = PCI_HOST_BRIDGE(s);
184     d = UNI_NORTH_PCI_HOST_BRIDGE(dev);
185     memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL);
186     memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio,
187                              0x80000000ULL, 0x10000000ULL);
188     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
189                                 &d->pci_hole);
190 
191     h->bus = pci_register_root_bus(dev, NULL,
192                                    pci_unin_set_irq, pci_unin_map_irq,
193                                    pic,
194                                    &d->pci_mmio,
195                                    address_space_io,
196                                    PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
197 
198 #if 0
199     pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north");
200 #endif
201 
202     sysbus_mmio_map(s, 0, 0xf2800000);
203     sysbus_mmio_map(s, 1, 0xf2c00000);
204 
205     /* DEC 21154 bridge */
206 #if 0
207     /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
208     pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154");
209 #endif
210 
211     /* Uninorth AGP bus */
212     pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp");
213     dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE);
214     qdev_init_nofail(dev);
215     s = SYS_BUS_DEVICE(dev);
216     sysbus_mmio_map(s, 0, 0xf0800000);
217     sysbus_mmio_map(s, 1, 0xf0c00000);
218 
219     /* Uninorth internal bus */
220 #if 0
221     /* XXX: not needed for now */
222     pci_create_simple(h->bus, PCI_DEVFN(14, 0),
223                       "uni-north-internal-pci");
224     dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE);
225     qdev_init_nofail(dev);
226     s = SYS_BUS_DEVICE(dev);
227     sysbus_mmio_map(s, 0, 0xf4800000);
228     sysbus_mmio_map(s, 1, 0xf4c00000);
229 #endif
230 
231     return d;
232 }
233 
234 UNINState *pci_pmac_u3_init(qemu_irq *pic,
235                             MemoryRegion *address_space_mem,
236                             MemoryRegion *address_space_io)
237 {
238     DeviceState *dev;
239     SysBusDevice *s;
240     PCIHostState *h;
241     UNINState *d;
242 
243     /* Uninorth AGP bus */
244     dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE);
245     qdev_init_nofail(dev);
246     s = SYS_BUS_DEVICE(dev);
247     h = PCI_HOST_BRIDGE(dev);
248     d = U3_AGP_HOST_BRIDGE(dev);
249 
250     memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL);
251     memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio,
252                              0x80000000ULL, 0x70000000ULL);
253     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
254                                 &d->pci_hole);
255 
256     h->bus = pci_register_root_bus(dev, NULL,
257                                    pci_unin_set_irq, pci_unin_map_irq,
258                                    pic,
259                                    &d->pci_mmio,
260                                    address_space_io,
261                                    PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
262 
263     sysbus_mmio_map(s, 0, 0xf0800000);
264     sysbus_mmio_map(s, 1, 0xf0c00000);
265 
266     pci_create_simple(h->bus, 11 << 3, "u3-agp");
267 
268     return d;
269 }
270 
271 static void unin_main_pci_host_realize(PCIDevice *d, Error **errp)
272 {
273     /* cache_line_size */
274     d->config[0x0C] = 0x08;
275     /* latency_timer */
276     d->config[0x0D] = 0x10;
277     /* capabilities_pointer */
278     d->config[0x34] = 0x00;
279 }
280 
281 static void unin_agp_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] = 0x80; */
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 u3_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 }
308 
309 static void unin_internal_pci_host_realize(PCIDevice *d, Error **errp)
310 {
311     /* cache_line_size */
312     d->config[0x0C] = 0x08;
313     /* latency_timer */
314     d->config[0x0D] = 0x10;
315     /* capabilities_pointer */
316     d->config[0x34] = 0x00;
317 }
318 
319 static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
320 {
321     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
322     DeviceClass *dc = DEVICE_CLASS(klass);
323 
324     k->realize   = unin_main_pci_host_realize;
325     k->vendor_id = PCI_VENDOR_ID_APPLE;
326     k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI;
327     k->revision  = 0x00;
328     k->class_id  = PCI_CLASS_BRIDGE_HOST;
329     /*
330      * PCI-facing part of the host bridge, not usable without the
331      * host-facing part, which can't be device_add'ed, yet.
332      */
333     dc->user_creatable = false;
334 }
335 
336 static const TypeInfo unin_main_pci_host_info = {
337     .name = "uni-north-pci",
338     .parent = TYPE_PCI_DEVICE,
339     .instance_size = sizeof(PCIDevice),
340     .class_init = unin_main_pci_host_class_init,
341     .interfaces = (InterfaceInfo[]) {
342         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
343         { },
344     },
345 };
346 
347 static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
348 {
349     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
350     DeviceClass *dc = DEVICE_CLASS(klass);
351 
352     k->realize   = u3_agp_pci_host_realize;
353     k->vendor_id = PCI_VENDOR_ID_APPLE;
354     k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP;
355     k->revision  = 0x00;
356     k->class_id  = PCI_CLASS_BRIDGE_HOST;
357     /*
358      * PCI-facing part of the host bridge, not usable without the
359      * host-facing part, which can't be device_add'ed, yet.
360      */
361     dc->user_creatable = false;
362 }
363 
364 static const TypeInfo u3_agp_pci_host_info = {
365     .name = "u3-agp",
366     .parent = TYPE_PCI_DEVICE,
367     .instance_size = sizeof(PCIDevice),
368     .class_init = u3_agp_pci_host_class_init,
369     .interfaces = (InterfaceInfo[]) {
370         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
371         { },
372     },
373 };
374 
375 static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
376 {
377     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
378     DeviceClass *dc = DEVICE_CLASS(klass);
379 
380     k->realize   = unin_agp_pci_host_realize;
381     k->vendor_id = PCI_VENDOR_ID_APPLE;
382     k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP;
383     k->revision  = 0x00;
384     k->class_id  = PCI_CLASS_BRIDGE_HOST;
385     /*
386      * PCI-facing part of the host bridge, not usable without the
387      * host-facing part, which can't be device_add'ed, yet.
388      */
389     dc->user_creatable = false;
390 }
391 
392 static const TypeInfo unin_agp_pci_host_info = {
393     .name = "uni-north-agp",
394     .parent = TYPE_PCI_DEVICE,
395     .instance_size = sizeof(PCIDevice),
396     .class_init = unin_agp_pci_host_class_init,
397     .interfaces = (InterfaceInfo[]) {
398         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
399         { },
400     },
401 };
402 
403 static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
404 {
405     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
406     DeviceClass *dc = DEVICE_CLASS(klass);
407 
408     k->realize   = unin_internal_pci_host_realize;
409     k->vendor_id = PCI_VENDOR_ID_APPLE;
410     k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI;
411     k->revision  = 0x00;
412     k->class_id  = PCI_CLASS_BRIDGE_HOST;
413     /*
414      * PCI-facing part of the host bridge, not usable without the
415      * host-facing part, which can't be device_add'ed, yet.
416      */
417     dc->user_creatable = false;
418 }
419 
420 static const TypeInfo unin_internal_pci_host_info = {
421     .name = "uni-north-internal-pci",
422     .parent = TYPE_PCI_DEVICE,
423     .instance_size = sizeof(PCIDevice),
424     .class_init = unin_internal_pci_host_class_init,
425     .interfaces = (InterfaceInfo[]) {
426         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
427         { },
428     },
429 };
430 
431 static void pci_unin_main_class_init(ObjectClass *klass, void *data)
432 {
433     DeviceClass *dc = DEVICE_CLASS(klass);
434 
435     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
436 }
437 
438 static const TypeInfo pci_unin_main_info = {
439     .name          = TYPE_UNI_NORTH_PCI_HOST_BRIDGE,
440     .parent        = TYPE_PCI_HOST_BRIDGE,
441     .instance_size = sizeof(UNINState),
442     .instance_init = pci_unin_main_init,
443     .class_init    = pci_unin_main_class_init,
444 };
445 
446 static void pci_u3_agp_class_init(ObjectClass *klass, void *data)
447 {
448     DeviceClass *dc = DEVICE_CLASS(klass);
449 
450     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
451 }
452 
453 static const TypeInfo pci_u3_agp_info = {
454     .name          = TYPE_U3_AGP_HOST_BRIDGE,
455     .parent        = TYPE_PCI_HOST_BRIDGE,
456     .instance_size = sizeof(UNINState),
457     .instance_init = pci_u3_agp_init,
458     .class_init    = pci_u3_agp_class_init,
459 };
460 
461 static void pci_unin_agp_class_init(ObjectClass *klass, void *data)
462 {
463     DeviceClass *dc = DEVICE_CLASS(klass);
464 
465     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
466 }
467 
468 static const TypeInfo pci_unin_agp_info = {
469     .name          = TYPE_UNI_NORTH_AGP_HOST_BRIDGE,
470     .parent        = TYPE_PCI_HOST_BRIDGE,
471     .instance_size = sizeof(UNINState),
472     .instance_init = pci_unin_agp_init,
473     .class_init    = pci_unin_agp_class_init,
474 };
475 
476 static void pci_unin_internal_class_init(ObjectClass *klass, void *data)
477 {
478     DeviceClass *dc = DEVICE_CLASS(klass);
479 
480     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
481 }
482 
483 static const TypeInfo pci_unin_internal_info = {
484     .name          = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE,
485     .parent        = TYPE_PCI_HOST_BRIDGE,
486     .instance_size = sizeof(UNINState),
487     .instance_init = pci_unin_internal_init,
488     .class_init    = pci_unin_internal_class_init,
489 };
490 
491 static void unin_register_types(void)
492 {
493     type_register_static(&unin_main_pci_host_info);
494     type_register_static(&u3_agp_pci_host_info);
495     type_register_static(&unin_agp_pci_host_info);
496     type_register_static(&unin_internal_pci_host_info);
497 
498     type_register_static(&pci_unin_main_info);
499     type_register_static(&pci_u3_agp_info);
500     type_register_static(&pci_unin_agp_info);
501     type_register_static(&pci_unin_internal_info);
502 }
503 
504 type_init(unin_register_types)
505