xref: /openbmc/qemu/hw/pci-host/raven.c (revision bc831f37398b51dfe65d99a67bcff9352f84a9d2)
1 /*
2  * QEMU PREP PCI host
3  *
4  * Copyright (c) 2006 Fabrice Bellard
5  * Copyright (c) 2011-2013 Andreas Färber
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 
26 #include "qemu/osdep.h"
27 #include "qemu/units.h"
28 #include "qemu/log.h"
29 #include "qapi/error.h"
30 #include "hw/pci/pci_device.h"
31 #include "hw/pci/pci_bus.h"
32 #include "hw/pci/pci_host.h"
33 #include "hw/qdev-properties.h"
34 #include "hw/intc/i8259.h"
35 #include "hw/irq.h"
36 #include "hw/or-irq.h"
37 #include "qom/object.h"
38 
39 #define TYPE_RAVEN_PCI_DEVICE "raven"
40 #define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost"
41 
42 OBJECT_DECLARE_SIMPLE_TYPE(PREPPCIState, RAVEN_PCI_HOST_BRIDGE)
43 
44 struct PREPPCIState {
45     PCIHostState parent_obj;
46 
47     OrIRQState *or_irq;
48     qemu_irq pci_irqs[PCI_NUM_PINS];
49     AddressSpace pci_io_as;
50     MemoryRegion pci_io;
51     MemoryRegion pci_io_non_contiguous;
52     MemoryRegion pci_memory;
53     MemoryRegion pci_intack;
54     MemoryRegion bm;
55     MemoryRegion bm_ram_alias;
56     MemoryRegion bm_pci_memory_alias;
57     AddressSpace bm_as;
58 
59     int contiguous_map;
60 };
61 
62 #define PCI_IO_BASE_ADDR    0x80000000  /* Physical address on main bus */
63 
64 static inline uint32_t raven_idsel_to_addr(hwaddr addr)
65 {
66     return (ctz16(addr >> 11) << 11) | (addr & 0x7ff);
67 }
68 
69 static void raven_mmcfg_write(void *opaque, hwaddr addr, uint64_t val,
70                               unsigned int size)
71 {
72     PCIBus *hbus = opaque;
73 
74     pci_data_write(hbus, raven_idsel_to_addr(addr), val, size);
75 }
76 
77 static uint64_t raven_mmcfg_read(void *opaque, hwaddr addr, unsigned int size)
78 {
79     PCIBus *hbus = opaque;
80 
81     return pci_data_read(hbus, raven_idsel_to_addr(addr), size);
82 }
83 
84 static const MemoryRegionOps raven_mmcfg_ops = {
85     .read = raven_mmcfg_read,
86     .write = raven_mmcfg_write,
87     .endianness = DEVICE_LITTLE_ENDIAN,
88 };
89 
90 static uint64_t raven_intack_read(void *opaque, hwaddr addr,
91                                   unsigned int size)
92 {
93     return pic_read_irq(isa_pic);
94 }
95 
96 static void raven_intack_write(void *opaque, hwaddr addr,
97                                         uint64_t data, unsigned size)
98 {
99     qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__);
100 }
101 
102 static const MemoryRegionOps raven_intack_ops = {
103     .read = raven_intack_read,
104     .write = raven_intack_write,
105     .valid = {
106         .max_access_size = 1,
107     },
108 };
109 
110 static inline hwaddr raven_io_address(PREPPCIState *s,
111                                       hwaddr addr)
112 {
113     if (s->contiguous_map == 0) {
114         /* 64 KB contiguous space for IOs */
115         addr &= 0xFFFF;
116     } else {
117         /* 8 MB non-contiguous space for IOs */
118         addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7);
119     }
120 
121     /* FIXME: handle endianness switch */
122 
123     return addr;
124 }
125 
126 static uint64_t raven_io_read(void *opaque, hwaddr addr,
127                               unsigned int size)
128 {
129     PREPPCIState *s = opaque;
130     uint8_t buf[4];
131 
132     addr = raven_io_address(s, addr);
133     address_space_read(&s->pci_io_as, addr + PCI_IO_BASE_ADDR,
134                        MEMTXATTRS_UNSPECIFIED, buf, size);
135 
136     if (size == 1) {
137         return buf[0];
138     } else if (size == 2) {
139         return lduw_le_p(buf);
140     } else if (size == 4) {
141         return ldl_le_p(buf);
142     } else {
143         g_assert_not_reached();
144     }
145 }
146 
147 static void raven_io_write(void *opaque, hwaddr addr,
148                            uint64_t val, unsigned int size)
149 {
150     PREPPCIState *s = opaque;
151     uint8_t buf[4];
152 
153     addr = raven_io_address(s, addr);
154 
155     if (size == 1) {
156         buf[0] = val;
157     } else if (size == 2) {
158         stw_le_p(buf, val);
159     } else if (size == 4) {
160         stl_le_p(buf, val);
161     } else {
162         g_assert_not_reached();
163     }
164 
165     address_space_write(&s->pci_io_as, addr + PCI_IO_BASE_ADDR,
166                         MEMTXATTRS_UNSPECIFIED, buf, size);
167 }
168 
169 static const MemoryRegionOps raven_io_ops = {
170     .read = raven_io_read,
171     .write = raven_io_write,
172     .endianness = DEVICE_LITTLE_ENDIAN,
173     .impl.max_access_size = 4,
174     .impl.unaligned = true,
175     .valid.unaligned = true,
176 };
177 
178 static int raven_map_irq(PCIDevice *pci_dev, int irq_num)
179 {
180     return (irq_num + (pci_dev->devfn >> 3)) & 1;
181 }
182 
183 static void raven_set_irq(void *opaque, int irq_num, int level)
184 {
185     PREPPCIState *s = opaque;
186 
187     qemu_set_irq(s->pci_irqs[irq_num], level);
188 }
189 
190 static AddressSpace *raven_pcihost_set_iommu(PCIBus *bus, void *opaque,
191                                              int devfn)
192 {
193     PREPPCIState *s = opaque;
194 
195     return &s->bm_as;
196 }
197 
198 static const PCIIOMMUOps raven_iommu_ops = {
199     .get_address_space = raven_pcihost_set_iommu,
200 };
201 
202 static void raven_change_gpio(void *opaque, int n, int level)
203 {
204     PREPPCIState *s = opaque;
205 
206     s->contiguous_map = level;
207 }
208 
209 static void raven_pcihost_realizefn(DeviceState *d, Error **errp)
210 {
211     SysBusDevice *dev = SYS_BUS_DEVICE(d);
212     PCIHostState *h = PCI_HOST_BRIDGE(dev);
213     PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev);
214     MemoryRegion *address_space_mem = get_system_memory();
215     int i;
216 
217     /*
218      * According to PReP specification section 6.1.6 "System Interrupt
219      * Assignments", all PCI interrupts are routed via IRQ 15
220      */
221     s->or_irq = OR_IRQ(object_new(TYPE_OR_IRQ));
222     object_property_set_int(OBJECT(s->or_irq), "num-lines", PCI_NUM_PINS,
223                             &error_fatal);
224     qdev_realize(DEVICE(s->or_irq), NULL, &error_fatal);
225     sysbus_init_irq(dev, &s->or_irq->out_irq);
226 
227     for (i = 0; i < PCI_NUM_PINS; i++) {
228         s->pci_irqs[i] = qdev_get_gpio_in(DEVICE(s->or_irq), i);
229     }
230 
231     qdev_init_gpio_in(d, raven_change_gpio, 1);
232 
233     h->bus = pci_register_root_bus(d, NULL, raven_set_irq, raven_map_irq,
234                                    s, &s->pci_memory, &s->pci_io, 0, 4,
235                                    TYPE_PCI_BUS);
236 
237     memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, s,
238                           "pci-conf-idx", 4);
239     memory_region_add_subregion(&s->pci_io, 0xcf8, &h->conf_mem);
240 
241     memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, s,
242                           "pci-conf-data", 4);
243     memory_region_add_subregion(&s->pci_io, 0xcfc, &h->data_mem);
244 
245     memory_region_init_io(&h->mmcfg, OBJECT(h), &raven_mmcfg_ops, h->bus,
246                           "pci-mmcfg", 0x00400000);
247     memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg);
248 
249     memory_region_init_io(&s->pci_intack, OBJECT(s), &raven_intack_ops, s,
250                           "pci-intack", 1);
251     memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->pci_intack);
252 
253     pci_create_simple(h->bus, PCI_DEVFN(0, 0), TYPE_RAVEN_PCI_DEVICE);
254 
255     address_space_init(&s->bm_as, &s->bm, "raven-bm");
256     pci_setup_iommu(h->bus, &raven_iommu_ops, s);
257 }
258 
259 static void raven_pcihost_initfn(Object *obj)
260 {
261     PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(obj);
262     MemoryRegion *address_space_mem = get_system_memory();
263 
264     memory_region_init(&s->pci_io, obj, "pci-io", 0x3f800000);
265     memory_region_init_io(&s->pci_io_non_contiguous, obj, &raven_io_ops, s,
266                           "pci-io-non-contiguous", 0x00800000);
267     memory_region_init(&s->pci_memory, obj, "pci-memory", 0x3f000000);
268     address_space_init(&s->pci_io_as, &s->pci_io, "raven-io");
269 
270     /*
271      * Raven's raven_io_ops use the address-space API to access pci-conf-idx
272      * (which is also owned by the raven device). As such, mark the
273      * pci_io_non_contiguous as re-entrancy safe.
274      */
275     s->pci_io_non_contiguous.disable_reentrancy_guard = true;
276 
277     /* CPU address space */
278     memory_region_add_subregion(address_space_mem, PCI_IO_BASE_ADDR,
279                                 &s->pci_io);
280     memory_region_add_subregion_overlap(address_space_mem, PCI_IO_BASE_ADDR,
281                                         &s->pci_io_non_contiguous, 1);
282     memory_region_add_subregion(address_space_mem, 0xc0000000, &s->pci_memory);
283 
284     /* Bus master address space */
285     memory_region_init(&s->bm, obj, "bm-raven", 4 * GiB);
286     memory_region_init_alias(&s->bm_pci_memory_alias, obj, "bm-pci-memory",
287                              &s->pci_memory, 0,
288                              memory_region_size(&s->pci_memory));
289     memory_region_init_alias(&s->bm_ram_alias, obj, "bm-system",
290                              get_system_memory(), 0, 0x80000000);
291     memory_region_add_subregion(&s->bm, 0         , &s->bm_pci_memory_alias);
292     memory_region_add_subregion(&s->bm, 0x80000000, &s->bm_ram_alias);
293 }
294 
295 static void raven_pcihost_class_init(ObjectClass *klass, const void *data)
296 {
297     DeviceClass *dc = DEVICE_CLASS(klass);
298 
299     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
300     dc->realize = raven_pcihost_realizefn;
301     dc->fw_name = "pci";
302 }
303 
304 static void raven_realize(PCIDevice *d, Error **errp)
305 {
306     d->config[PCI_CACHE_LINE_SIZE] = 0x08;
307     d->config[PCI_LATENCY_TIMER] = 0x10;
308     d->config[PCI_CAPABILITY_LIST] = 0x00;
309 }
310 
311 static void raven_class_init(ObjectClass *klass, const void *data)
312 {
313     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
314     DeviceClass *dc = DEVICE_CLASS(klass);
315 
316     k->realize = raven_realize;
317     k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
318     k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN;
319     k->revision = 0x00;
320     k->class_id = PCI_CLASS_BRIDGE_HOST;
321     dc->desc = "PReP Host Bridge - Motorola Raven";
322     /*
323      * Reason: PCI-facing part of the host bridge, not usable without
324      * the host-facing part, which can't be device_add'ed, yet.
325      */
326     dc->user_creatable = false;
327 }
328 
329 static const TypeInfo raven_types[] = {
330     {
331         .name = TYPE_RAVEN_PCI_HOST_BRIDGE,
332         .parent = TYPE_PCI_HOST_BRIDGE,
333         .instance_size = sizeof(PREPPCIState),
334         .instance_init = raven_pcihost_initfn,
335         .class_init = raven_pcihost_class_init,
336     },
337     {
338         .name = TYPE_RAVEN_PCI_DEVICE,
339         .parent = TYPE_PCI_DEVICE,
340         .class_init = raven_class_init,
341         .interfaces = (const InterfaceInfo[]) {
342             { INTERFACE_CONVENTIONAL_PCI_DEVICE },
343             { },
344         },
345     },
346 };
347 
348 DEFINE_TYPES(raven_types)
349