]> Git Repo - qemu.git/blob - hw/ppce500_pci.c
Merge remote-tracking branch 'kwolf/for-anthony' into staging
[qemu.git] / hw / ppce500_pci.c
1 /*
2  * QEMU PowerPC E500 embedded processors pci controller emulation
3  *
4  * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
5  *
6  * Author: Yu Liu,     <[email protected]>
7  *
8  * This file is derived from hw/ppc4xx_pci.c,
9  * the copyright for that material belongs to the original owners.
10  *
11  * This is free software; you can redistribute it and/or modify
12  * it under the terms of  the GNU General  Public License as published by
13  * the Free Software Foundation;  either version 2 of the  License, or
14  * (at your option) any later version.
15  */
16
17 #include "hw.h"
18 #include "pci.h"
19 #include "pci_host.h"
20 #include "bswap.h"
21
22 #ifdef DEBUG_PCI
23 #define pci_debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
24 #else
25 #define pci_debug(fmt, ...)
26 #endif
27
28 #define PCIE500_CFGADDR       0x0
29 #define PCIE500_CFGDATA       0x4
30 #define PCIE500_REG_BASE      0xC00
31 #define PCIE500_ALL_SIZE      0x1000
32 #define PCIE500_REG_SIZE      (PCIE500_ALL_SIZE - PCIE500_REG_BASE)
33
34 #define PCIE500_PCI_IOLEN     0x10000ULL
35
36 #define PPCE500_PCI_CONFIG_ADDR         0x0
37 #define PPCE500_PCI_CONFIG_DATA         0x4
38 #define PPCE500_PCI_INTACK              0x8
39
40 #define PPCE500_PCI_OW1                 (0xC20 - PCIE500_REG_BASE)
41 #define PPCE500_PCI_OW2                 (0xC40 - PCIE500_REG_BASE)
42 #define PPCE500_PCI_OW3                 (0xC60 - PCIE500_REG_BASE)
43 #define PPCE500_PCI_OW4                 (0xC80 - PCIE500_REG_BASE)
44 #define PPCE500_PCI_IW3                 (0xDA0 - PCIE500_REG_BASE)
45 #define PPCE500_PCI_IW2                 (0xDC0 - PCIE500_REG_BASE)
46 #define PPCE500_PCI_IW1                 (0xDE0 - PCIE500_REG_BASE)
47
48 #define PPCE500_PCI_GASKET_TIMR         (0xE20 - PCIE500_REG_BASE)
49
50 #define PCI_POTAR               0x0
51 #define PCI_POTEAR              0x4
52 #define PCI_POWBAR              0x8
53 #define PCI_POWAR               0x10
54
55 #define PCI_PITAR               0x0
56 #define PCI_PIWBAR              0x8
57 #define PCI_PIWBEAR             0xC
58 #define PCI_PIWAR               0x10
59
60 #define PPCE500_PCI_NR_POBS     5
61 #define PPCE500_PCI_NR_PIBS     3
62
63 struct  pci_outbound {
64     uint32_t potar;
65     uint32_t potear;
66     uint32_t powbar;
67     uint32_t powar;
68 };
69
70 struct pci_inbound {
71     uint32_t pitar;
72     uint32_t piwbar;
73     uint32_t piwbear;
74     uint32_t piwar;
75 };
76
77 #define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost"
78
79 #define PPC_E500_PCI_HOST_BRIDGE(obj) \
80     OBJECT_CHECK(PPCE500PCIState, (obj), TYPE_PPC_E500_PCI_HOST_BRIDGE)
81
82 struct PPCE500PCIState {
83     PCIHostState parent_obj;
84
85     struct pci_outbound pob[PPCE500_PCI_NR_POBS];
86     struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
87     uint32_t gasket_time;
88     qemu_irq irq[4];
89     /* mmio maps */
90     MemoryRegion container;
91     MemoryRegion iomem;
92     MemoryRegion pio;
93 };
94
95 typedef struct PPCE500PCIState PPCE500PCIState;
96
97 static uint64_t pci_reg_read4(void *opaque, hwaddr addr,
98                               unsigned size)
99 {
100     PPCE500PCIState *pci = opaque;
101     unsigned long win;
102     uint32_t value = 0;
103     int idx;
104
105     win = addr & 0xfe0;
106
107     switch (win) {
108     case PPCE500_PCI_OW1:
109     case PPCE500_PCI_OW2:
110     case PPCE500_PCI_OW3:
111     case PPCE500_PCI_OW4:
112         idx = (addr >> 5) & 0x7;
113         switch (addr & 0xC) {
114         case PCI_POTAR:
115             value = pci->pob[idx].potar;
116             break;
117         case PCI_POTEAR:
118             value = pci->pob[idx].potear;
119             break;
120         case PCI_POWBAR:
121             value = pci->pob[idx].powbar;
122             break;
123         case PCI_POWAR:
124             value = pci->pob[idx].powar;
125             break;
126         default:
127             break;
128         }
129         break;
130
131     case PPCE500_PCI_IW3:
132     case PPCE500_PCI_IW2:
133     case PPCE500_PCI_IW1:
134         idx = ((addr >> 5) & 0x3) - 1;
135         switch (addr & 0xC) {
136         case PCI_PITAR:
137             value = pci->pib[idx].pitar;
138             break;
139         case PCI_PIWBAR:
140             value = pci->pib[idx].piwbar;
141             break;
142         case PCI_PIWBEAR:
143             value = pci->pib[idx].piwbear;
144             break;
145         case PCI_PIWAR:
146             value = pci->pib[idx].piwar;
147             break;
148         default:
149             break;
150         };
151         break;
152
153     case PPCE500_PCI_GASKET_TIMR:
154         value = pci->gasket_time;
155         break;
156
157     default:
158         break;
159     }
160
161     pci_debug("%s: win:%lx(addr:" TARGET_FMT_plx ") -> value:%x\n", __func__,
162               win, addr, value);
163     return value;
164 }
165
166 static void pci_reg_write4(void *opaque, hwaddr addr,
167                            uint64_t value, unsigned size)
168 {
169     PPCE500PCIState *pci = opaque;
170     unsigned long win;
171     int idx;
172
173     win = addr & 0xfe0;
174
175     pci_debug("%s: value:%x -> win:%lx(addr:" TARGET_FMT_plx ")\n",
176               __func__, (unsigned)value, win, addr);
177
178     switch (win) {
179     case PPCE500_PCI_OW1:
180     case PPCE500_PCI_OW2:
181     case PPCE500_PCI_OW3:
182     case PPCE500_PCI_OW4:
183         idx = (addr >> 5) & 0x7;
184         switch (addr & 0xC) {
185         case PCI_POTAR:
186             pci->pob[idx].potar = value;
187             break;
188         case PCI_POTEAR:
189             pci->pob[idx].potear = value;
190             break;
191         case PCI_POWBAR:
192             pci->pob[idx].powbar = value;
193             break;
194         case PCI_POWAR:
195             pci->pob[idx].powar = value;
196             break;
197         default:
198             break;
199         };
200         break;
201
202     case PPCE500_PCI_IW3:
203     case PPCE500_PCI_IW2:
204     case PPCE500_PCI_IW1:
205         idx = ((addr >> 5) & 0x3) - 1;
206         switch (addr & 0xC) {
207         case PCI_PITAR:
208             pci->pib[idx].pitar = value;
209             break;
210         case PCI_PIWBAR:
211             pci->pib[idx].piwbar = value;
212             break;
213         case PCI_PIWBEAR:
214             pci->pib[idx].piwbear = value;
215             break;
216         case PCI_PIWAR:
217             pci->pib[idx].piwar = value;
218             break;
219         default:
220             break;
221         };
222         break;
223
224     case PPCE500_PCI_GASKET_TIMR:
225         pci->gasket_time = value;
226         break;
227
228     default:
229         break;
230     };
231 }
232
233 static const MemoryRegionOps e500_pci_reg_ops = {
234     .read = pci_reg_read4,
235     .write = pci_reg_write4,
236     .endianness = DEVICE_BIG_ENDIAN,
237 };
238
239 static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
240 {
241     int devno = pci_dev->devfn >> 3, ret = 0;
242
243     switch (devno) {
244         /* Two PCI slot */
245         case 0x11:
246         case 0x12:
247             ret = (irq_num + devno - 0x10) % 4;
248             break;
249         default:
250             printf("Error:%s:unknown dev number\n", __func__);
251     }
252
253     pci_debug("%s: devfn %x irq %d -> %d  devno:%x\n", __func__,
254            pci_dev->devfn, irq_num, ret, devno);
255
256     return ret;
257 }
258
259 static void mpc85xx_pci_set_irq(void *opaque, int irq_num, int level)
260 {
261     qemu_irq *pic = opaque;
262
263     pci_debug("%s: PCI irq %d, level:%d\n", __func__, irq_num, level);
264
265     qemu_set_irq(pic[irq_num], level);
266 }
267
268 static const VMStateDescription vmstate_pci_outbound = {
269     .name = "pci_outbound",
270     .version_id = 0,
271     .minimum_version_id = 0,
272     .minimum_version_id_old = 0,
273     .fields      = (VMStateField[]) {
274         VMSTATE_UINT32(potar, struct pci_outbound),
275         VMSTATE_UINT32(potear, struct pci_outbound),
276         VMSTATE_UINT32(powbar, struct pci_outbound),
277         VMSTATE_UINT32(powar, struct pci_outbound),
278         VMSTATE_END_OF_LIST()
279     }
280 };
281
282 static const VMStateDescription vmstate_pci_inbound = {
283     .name = "pci_inbound",
284     .version_id = 0,
285     .minimum_version_id = 0,
286     .minimum_version_id_old = 0,
287     .fields      = (VMStateField[]) {
288         VMSTATE_UINT32(pitar, struct pci_inbound),
289         VMSTATE_UINT32(piwbar, struct pci_inbound),
290         VMSTATE_UINT32(piwbear, struct pci_inbound),
291         VMSTATE_UINT32(piwar, struct pci_inbound),
292         VMSTATE_END_OF_LIST()
293     }
294 };
295
296 static const VMStateDescription vmstate_ppce500_pci = {
297     .name = "ppce500_pci",
298     .version_id = 1,
299     .minimum_version_id = 1,
300     .minimum_version_id_old = 1,
301     .fields      = (VMStateField[]) {
302         VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1,
303                              vmstate_pci_outbound, struct pci_outbound),
304         VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1,
305                              vmstate_pci_outbound, struct pci_inbound),
306         VMSTATE_UINT32(gasket_time, PPCE500PCIState),
307         VMSTATE_END_OF_LIST()
308     }
309 };
310
311 #include "exec-memory.h"
312
313 static int e500_pcihost_initfn(SysBusDevice *dev)
314 {
315     PCIHostState *h;
316     PPCE500PCIState *s;
317     PCIBus *b;
318     int i;
319     MemoryRegion *address_space_mem = get_system_memory();
320
321     h = PCI_HOST_BRIDGE(dev);
322     s = PPC_E500_PCI_HOST_BRIDGE(dev);
323
324     for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
325         sysbus_init_irq(dev, &s->irq[i]);
326     }
327
328     memory_region_init(&s->pio, "pci-pio", PCIE500_PCI_IOLEN);
329
330     b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
331                          mpc85xx_pci_map_irq, s->irq, address_space_mem,
332                          &s->pio, PCI_DEVFN(0x11, 0), 4);
333     h->bus = b;
334
335     pci_create_simple(b, 0, "e500-host-bridge");
336
337     memory_region_init(&s->container, "pci-container", PCIE500_ALL_SIZE);
338     memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, h,
339                           "pci-conf-idx", 4);
340     memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
341                           "pci-conf-data", 4);
342     memory_region_init_io(&s->iomem, &e500_pci_reg_ops, s,
343                           "pci.reg", PCIE500_REG_SIZE);
344     memory_region_add_subregion(&s->container, PCIE500_CFGADDR, &h->conf_mem);
345     memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem);
346     memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem);
347     sysbus_init_mmio(dev, &s->container);
348     sysbus_init_mmio(dev, &s->pio);
349
350     return 0;
351 }
352
353 static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
354 {
355     DeviceClass *dc = DEVICE_CLASS(klass);
356     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
357
358     k->vendor_id = PCI_VENDOR_ID_FREESCALE;
359     k->device_id = PCI_DEVICE_ID_MPC8533E;
360     k->class_id = PCI_CLASS_PROCESSOR_POWERPC;
361     dc->desc = "Host bridge";
362 }
363
364 static const TypeInfo e500_host_bridge_info = {
365     .name          = "e500-host-bridge",
366     .parent        = TYPE_PCI_DEVICE,
367     .instance_size = sizeof(PCIDevice),
368     .class_init    = e500_host_bridge_class_init,
369 };
370
371 static void e500_pcihost_class_init(ObjectClass *klass, void *data)
372 {
373     DeviceClass *dc = DEVICE_CLASS(klass);
374     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
375
376     k->init = e500_pcihost_initfn;
377     dc->vmsd = &vmstate_ppce500_pci;
378 }
379
380 static const TypeInfo e500_pcihost_info = {
381     .name          = TYPE_PPC_E500_PCI_HOST_BRIDGE,
382     .parent        = TYPE_PCI_HOST_BRIDGE,
383     .instance_size = sizeof(PPCE500PCIState),
384     .class_init    = e500_pcihost_class_init,
385 };
386
387 static void e500_pci_register_types(void)
388 {
389     type_register_static(&e500_pcihost_info);
390     type_register_static(&e500_host_bridge_info);
391 }
392
393 type_init(e500_pci_register_types)
This page took 0.044157 seconds and 4 git commands to generate.