]> Git Repo - qemu.git/blob - hw/ppc4xx_pci.c
hw/ppc4xx_pci.c: kill two warnings
[qemu.git] / hw / ppc4xx_pci.c
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License, version 2, as
4  * published by the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program; if not, write to the Free Software
13  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
14  *
15  * Copyright IBM Corp. 2008
16  *
17  * Authors: Hollis Blanchard <[email protected]>
18  */
19
20 /* This file implements emulation of the 32-bit PCI controller found in some
21  * 4xx SoCs, such as the 440EP. */
22
23 #include "hw.h"
24
25 typedef target_phys_addr_t pci_addr_t;
26 #include "pci.h"
27 #include "pci_host.h"
28 #include "bswap.h"
29
30 #undef DEBUG
31 #ifdef DEBUG
32 #define DPRINTF(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0)
33 #else
34 #define DPRINTF(fmt, args...)
35 #endif /* DEBUG */
36
37 struct PCIMasterMap {
38     uint32_t la;
39     uint32_t ma;
40     uint32_t pcila;
41     uint32_t pciha;
42 };
43
44 struct PCITargetMap {
45     uint32_t ms;
46     uint32_t la;
47 };
48
49 #define PPC4xx_PCI_NR_PMMS 3
50 #define PPC4xx_PCI_NR_PTMS 2
51
52 struct PPC4xxPCIState {
53     struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS];
54     struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS];
55
56     PCIHostState pci_state;
57     PCIDevice *pci_dev;
58 };
59 typedef struct PPC4xxPCIState PPC4xxPCIState;
60
61 #define PCIC0_CFGADDR       0x0
62 #define PCIC0_CFGDATA       0x4
63
64 /* PLB Memory Map (PMM) registers specify which PLB addresses are translated to
65  * PCI accesses. */
66 #define PCIL0_PMM0LA        0x0
67 #define PCIL0_PMM0MA        0x4
68 #define PCIL0_PMM0PCILA     0x8
69 #define PCIL0_PMM0PCIHA     0xc
70 #define PCIL0_PMM1LA        0x10
71 #define PCIL0_PMM1MA        0x14
72 #define PCIL0_PMM1PCILA     0x18
73 #define PCIL0_PMM1PCIHA     0x1c
74 #define PCIL0_PMM2LA        0x20
75 #define PCIL0_PMM2MA        0x24
76 #define PCIL0_PMM2PCILA     0x28
77 #define PCIL0_PMM2PCIHA     0x2c
78
79 /* PCI Target Map (PTM) registers specify which PCI addresses are translated to
80  * PLB accesses. */
81 #define PCIL0_PTM1MS        0x30
82 #define PCIL0_PTM1LA        0x34
83 #define PCIL0_PTM2MS        0x38
84 #define PCIL0_PTM2LA        0x3c
85 #define PCI_REG_SIZE        0x40
86
87
88 static uint32_t pci4xx_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
89 {
90     PPC4xxPCIState *ppc4xx_pci = opaque;
91
92     return ppc4xx_pci->pci_state.config_reg;
93 }
94
95 static CPUReadMemoryFunc *pci4xx_cfgaddr_read[] = {
96     &pci4xx_cfgaddr_readl,
97     &pci4xx_cfgaddr_readl,
98     &pci4xx_cfgaddr_readl,
99 };
100
101 static void pci4xx_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
102                                   uint32_t value)
103 {
104     PPC4xxPCIState *ppc4xx_pci = opaque;
105
106 #ifdef TARGET_WORDS_BIGENDIAN
107     value = bswap32(value);
108 #endif
109
110     ppc4xx_pci->pci_state.config_reg = value & ~0x3;
111 }
112
113 static CPUWriteMemoryFunc *pci4xx_cfgaddr_write[] = {
114     &pci4xx_cfgaddr_writel,
115     &pci4xx_cfgaddr_writel,
116     &pci4xx_cfgaddr_writel,
117 };
118
119 static CPUReadMemoryFunc *pci4xx_cfgdata_read[] = {
120     &pci_host_data_readb,
121     &pci_host_data_readw,
122     &pci_host_data_readl,
123 };
124
125 static CPUWriteMemoryFunc *pci4xx_cfgdata_write[] = {
126     &pci_host_data_writeb,
127     &pci_host_data_writew,
128     &pci_host_data_writel,
129 };
130
131 static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
132                                   uint32_t value)
133 {
134     struct PPC4xxPCIState *pci = opaque;
135
136 #ifdef TARGET_WORDS_BIGENDIAN
137     value = bswap32(value);
138 #endif
139
140     /* We ignore all target attempts at PCI configuration, effectively
141      * assuming a bidirectional 1:1 mapping of PLB and PCI space. */
142
143     switch (offset) {
144     case PCIL0_PMM0LA:
145         pci->pmm[0].la = value;
146         break;
147     case PCIL0_PMM0MA:
148         pci->pmm[0].ma = value;
149         break;
150     case PCIL0_PMM0PCIHA:
151         pci->pmm[0].pciha = value;
152         break;
153     case PCIL0_PMM0PCILA:
154         pci->pmm[0].pcila = value;
155         break;
156
157     case PCIL0_PMM1LA:
158         pci->pmm[1].la = value;
159         break;
160     case PCIL0_PMM1MA:
161         pci->pmm[1].ma = value;
162         break;
163     case PCIL0_PMM1PCIHA:
164         pci->pmm[1].pciha = value;
165         break;
166     case PCIL0_PMM1PCILA:
167         pci->pmm[1].pcila = value;
168         break;
169
170     case PCIL0_PMM2LA:
171         pci->pmm[2].la = value;
172         break;
173     case PCIL0_PMM2MA:
174         pci->pmm[2].ma = value;
175         break;
176     case PCIL0_PMM2PCIHA:
177         pci->pmm[2].pciha = value;
178         break;
179     case PCIL0_PMM2PCILA:
180         pci->pmm[2].pcila = value;
181         break;
182
183     case PCIL0_PTM1MS:
184         pci->ptm[0].ms = value;
185         break;
186     case PCIL0_PTM1LA:
187         pci->ptm[0].la = value;
188         break;
189     case PCIL0_PTM2MS:
190         pci->ptm[1].ms = value;
191         break;
192     case PCIL0_PTM2LA:
193         pci->ptm[1].la = value;
194         break;
195
196     default:
197         printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
198                (unsigned long)offset);
199         break;
200     }
201 }
202
203 static uint32_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset)
204 {
205     struct PPC4xxPCIState *pci = opaque;
206     uint32_t value;
207
208     switch (offset) {
209     case PCIL0_PMM0LA:
210         value = pci->pmm[0].la;
211         break;
212     case PCIL0_PMM0MA:
213         value = pci->pmm[0].ma;
214         break;
215     case PCIL0_PMM0PCIHA:
216         value = pci->pmm[0].pciha;
217         break;
218     case PCIL0_PMM0PCILA:
219         value = pci->pmm[0].pcila;
220         break;
221
222     case PCIL0_PMM1LA:
223         value = pci->pmm[1].la;
224         break;
225     case PCIL0_PMM1MA:
226         value = pci->pmm[1].ma;
227         break;
228     case PCIL0_PMM1PCIHA:
229         value = pci->pmm[1].pciha;
230         break;
231     case PCIL0_PMM1PCILA:
232         value = pci->pmm[1].pcila;
233         break;
234
235     case PCIL0_PMM2LA:
236         value = pci->pmm[2].la;
237         break;
238     case PCIL0_PMM2MA:
239         value = pci->pmm[2].ma;
240         break;
241     case PCIL0_PMM2PCIHA:
242         value = pci->pmm[2].pciha;
243         break;
244     case PCIL0_PMM2PCILA:
245         value = pci->pmm[2].pcila;
246         break;
247
248     case PCIL0_PTM1MS:
249         value = pci->ptm[0].ms;
250         break;
251     case PCIL0_PTM1LA:
252         value = pci->ptm[0].la;
253         break;
254     case PCIL0_PTM2MS:
255         value = pci->ptm[1].ms;
256         break;
257     case PCIL0_PTM2LA:
258         value = pci->ptm[1].la;
259         break;
260
261     default:
262         printf("%s: invalid PCI internal register 0x%lx\n", __func__,
263                (unsigned long)offset);
264         value = 0;
265     }
266
267 #ifdef TARGET_WORDS_BIGENDIAN
268     value = bswap32(value);
269 #endif
270
271     return value;
272 }
273
274 static CPUReadMemoryFunc *pci_reg_read[] = {
275     &ppc4xx_pci_reg_read4,
276     &ppc4xx_pci_reg_read4,
277     &ppc4xx_pci_reg_read4,
278 };
279
280 static CPUWriteMemoryFunc *pci_reg_write[] = {
281     &ppc4xx_pci_reg_write4,
282     &ppc4xx_pci_reg_write4,
283     &ppc4xx_pci_reg_write4,
284 };
285
286 static void ppc4xx_pci_reset(void *opaque)
287 {
288     struct PPC4xxPCIState *pci = opaque;
289
290     memset(pci->pmm, 0, sizeof(pci->pmm));
291     memset(pci->ptm, 0, sizeof(pci->ptm));
292 }
293
294 /* On Bamboo, all pins from each slot are tied to a single board IRQ. This
295  * may need further refactoring for other boards. */
296 static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
297 {
298     int slot = pci_dev->devfn >> 3;
299
300     DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
301             pci_dev->devfn, irq_num, slot);
302
303     return slot - 1;
304 }
305
306 static void ppc4xx_pci_set_irq(qemu_irq *pci_irqs, int irq_num, int level)
307 {
308     DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
309     qemu_set_irq(pci_irqs[irq_num], level);
310 }
311
312 static void ppc4xx_pci_save(QEMUFile *f, void *opaque)
313 {
314     PPC4xxPCIState *controller = opaque;
315     int i;
316
317     pci_device_save(controller->pci_dev, f);
318
319     for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
320         qemu_put_be32s(f, &controller->pmm[i].la);
321         qemu_put_be32s(f, &controller->pmm[i].ma);
322         qemu_put_be32s(f, &controller->pmm[i].pcila);
323         qemu_put_be32s(f, &controller->pmm[i].pciha);
324     }
325
326     for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
327         qemu_put_be32s(f, &controller->ptm[i].ms);
328         qemu_put_be32s(f, &controller->ptm[i].la);
329     }
330 }
331
332 static int ppc4xx_pci_load(QEMUFile *f, void *opaque, int version_id)
333 {
334     PPC4xxPCIState *controller = opaque;
335     int i;
336
337     if (version_id != 1)
338         return -EINVAL;
339
340     pci_device_load(controller->pci_dev, f);
341
342     for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
343         qemu_get_be32s(f, &controller->pmm[i].la);
344         qemu_get_be32s(f, &controller->pmm[i].ma);
345         qemu_get_be32s(f, &controller->pmm[i].pcila);
346         qemu_get_be32s(f, &controller->pmm[i].pciha);
347     }
348
349     for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
350         qemu_get_be32s(f, &controller->ptm[i].ms);
351         qemu_get_be32s(f, &controller->ptm[i].la);
352     }
353
354     return 0;
355 }
356
357 /* XXX Interrupt acknowledge cycles not supported. */
358 PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
359                         target_phys_addr_t config_space,
360                         target_phys_addr_t int_ack,
361                         target_phys_addr_t special_cycle,
362                         target_phys_addr_t registers)
363 {
364     PPC4xxPCIState *controller;
365     int index;
366     static int ppc4xx_pci_id;
367
368     controller = qemu_mallocz(sizeof(PPC4xxPCIState));
369     if (!controller)
370         return NULL;
371
372     controller->pci_state.bus = pci_register_bus(ppc4xx_pci_set_irq,
373                                                  ppc4xx_pci_map_irq,
374                                                  pci_irqs, 0, 4);
375
376     controller->pci_dev = pci_register_device(controller->pci_state.bus,
377                                               "host bridge", sizeof(PCIDevice),
378                                               0, NULL, NULL);
379     controller->pci_dev->config[0x00] = 0x14; // vendor_id
380     controller->pci_dev->config[0x01] = 0x10;
381     controller->pci_dev->config[0x02] = 0x7f; // device_id
382     controller->pci_dev->config[0x03] = 0x02;
383     controller->pci_dev->config[0x0a] = 0x80; // class_sub = other bridge type
384     controller->pci_dev->config[0x0b] = 0x06; // class_base = PCI_bridge
385
386     /* CFGADDR */
387     index = cpu_register_io_memory(0, pci4xx_cfgaddr_read,
388                                    pci4xx_cfgaddr_write, controller);
389     if (index < 0)
390         goto free;
391     cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
392
393     /* CFGDATA */
394     index = cpu_register_io_memory(0, pci4xx_cfgdata_read,
395                                    pci4xx_cfgdata_write,
396                                    &controller->pci_state);
397     if (index < 0)
398         goto free;
399     cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index);
400
401     /* Internal registers */
402     index = cpu_register_io_memory(0, pci_reg_read, pci_reg_write, controller);
403     if (index < 0)
404         goto free;
405     cpu_register_physical_memory(registers, PCI_REG_SIZE, index);
406
407     qemu_register_reset(ppc4xx_pci_reset, controller);
408
409     /* XXX load/save code not tested. */
410     register_savevm("ppc4xx_pci", ppc4xx_pci_id++, 1,
411                     ppc4xx_pci_save, ppc4xx_pci_load, controller);
412
413     return controller->pci_state.bus;
414
415 free:
416     printf("%s error\n", __func__);
417     qemu_free(controller);
418     return NULL;
419 }
This page took 0.050032 seconds and 4 git commands to generate.