]> Git Repo - qemu.git/blob - hw/ppc4xx_pci.c
usb: fix port reset
[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, see <http://www.gnu.org/licenses/>.
13  *
14  * Copyright IBM Corp. 2008
15  *
16  * Authors: Hollis Blanchard <[email protected]>
17  */
18
19 /* This file implements emulation of the 32-bit PCI controller found in some
20  * 4xx SoCs, such as the 440EP. */
21
22 #include "hw.h"
23 #include "ppc.h"
24 #include "ppc4xx.h"
25 #include "pci.h"
26 #include "pci_host.h"
27 #include "exec-memory.h"
28
29 #undef DEBUG
30 #ifdef DEBUG
31 #define DPRINTF(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0)
32 #else
33 #define DPRINTF(fmt, ...)
34 #endif /* DEBUG */
35
36 struct PCIMasterMap {
37     uint32_t la;
38     uint32_t ma;
39     uint32_t pcila;
40     uint32_t pciha;
41 };
42
43 struct PCITargetMap {
44     uint32_t ms;
45     uint32_t la;
46 };
47
48 #define PPC4xx_PCI_NR_PMMS 3
49 #define PPC4xx_PCI_NR_PTMS 2
50
51 struct PPC4xxPCIState {
52     struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS];
53     struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS];
54
55     PCIHostState pci_state;
56     PCIDevice *pci_dev;
57 };
58 typedef struct PPC4xxPCIState PPC4xxPCIState;
59
60 #define PCIC0_CFGADDR       0x0
61 #define PCIC0_CFGDATA       0x4
62
63 /* PLB Memory Map (PMM) registers specify which PLB addresses are translated to
64  * PCI accesses. */
65 #define PCIL0_PMM0LA        0x0
66 #define PCIL0_PMM0MA        0x4
67 #define PCIL0_PMM0PCILA     0x8
68 #define PCIL0_PMM0PCIHA     0xc
69 #define PCIL0_PMM1LA        0x10
70 #define PCIL0_PMM1MA        0x14
71 #define PCIL0_PMM1PCILA     0x18
72 #define PCIL0_PMM1PCIHA     0x1c
73 #define PCIL0_PMM2LA        0x20
74 #define PCIL0_PMM2MA        0x24
75 #define PCIL0_PMM2PCILA     0x28
76 #define PCIL0_PMM2PCIHA     0x2c
77
78 /* PCI Target Map (PTM) registers specify which PCI addresses are translated to
79  * PLB accesses. */
80 #define PCIL0_PTM1MS        0x30
81 #define PCIL0_PTM1LA        0x34
82 #define PCIL0_PTM2MS        0x38
83 #define PCIL0_PTM2LA        0x3c
84 #define PCI_REG_SIZE        0x40
85
86
87 static uint32_t pci4xx_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
88 {
89     PPC4xxPCIState *ppc4xx_pci = opaque;
90
91     return ppc4xx_pci->pci_state.config_reg;
92 }
93
94 static CPUReadMemoryFunc * const pci4xx_cfgaddr_read[] = {
95     &pci4xx_cfgaddr_readl,
96     &pci4xx_cfgaddr_readl,
97     &pci4xx_cfgaddr_readl,
98 };
99
100 static void pci4xx_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
101                                   uint32_t value)
102 {
103     PPC4xxPCIState *ppc4xx_pci = opaque;
104
105     ppc4xx_pci->pci_state.config_reg = value & ~0x3;
106 }
107
108 static CPUWriteMemoryFunc * const pci4xx_cfgaddr_write[] = {
109     &pci4xx_cfgaddr_writel,
110     &pci4xx_cfgaddr_writel,
111     &pci4xx_cfgaddr_writel,
112 };
113
114 static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
115                                   uint32_t value)
116 {
117     struct PPC4xxPCIState *pci = opaque;
118
119     /* We ignore all target attempts at PCI configuration, effectively
120      * assuming a bidirectional 1:1 mapping of PLB and PCI space. */
121
122     switch (offset) {
123     case PCIL0_PMM0LA:
124         pci->pmm[0].la = value;
125         break;
126     case PCIL0_PMM0MA:
127         pci->pmm[0].ma = value;
128         break;
129     case PCIL0_PMM0PCIHA:
130         pci->pmm[0].pciha = value;
131         break;
132     case PCIL0_PMM0PCILA:
133         pci->pmm[0].pcila = value;
134         break;
135
136     case PCIL0_PMM1LA:
137         pci->pmm[1].la = value;
138         break;
139     case PCIL0_PMM1MA:
140         pci->pmm[1].ma = value;
141         break;
142     case PCIL0_PMM1PCIHA:
143         pci->pmm[1].pciha = value;
144         break;
145     case PCIL0_PMM1PCILA:
146         pci->pmm[1].pcila = value;
147         break;
148
149     case PCIL0_PMM2LA:
150         pci->pmm[2].la = value;
151         break;
152     case PCIL0_PMM2MA:
153         pci->pmm[2].ma = value;
154         break;
155     case PCIL0_PMM2PCIHA:
156         pci->pmm[2].pciha = value;
157         break;
158     case PCIL0_PMM2PCILA:
159         pci->pmm[2].pcila = value;
160         break;
161
162     case PCIL0_PTM1MS:
163         pci->ptm[0].ms = value;
164         break;
165     case PCIL0_PTM1LA:
166         pci->ptm[0].la = value;
167         break;
168     case PCIL0_PTM2MS:
169         pci->ptm[1].ms = value;
170         break;
171     case PCIL0_PTM2LA:
172         pci->ptm[1].la = value;
173         break;
174
175     default:
176         printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
177                (unsigned long)offset);
178         break;
179     }
180 }
181
182 static uint32_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset)
183 {
184     struct PPC4xxPCIState *pci = opaque;
185     uint32_t value;
186
187     switch (offset) {
188     case PCIL0_PMM0LA:
189         value = pci->pmm[0].la;
190         break;
191     case PCIL0_PMM0MA:
192         value = pci->pmm[0].ma;
193         break;
194     case PCIL0_PMM0PCIHA:
195         value = pci->pmm[0].pciha;
196         break;
197     case PCIL0_PMM0PCILA:
198         value = pci->pmm[0].pcila;
199         break;
200
201     case PCIL0_PMM1LA:
202         value = pci->pmm[1].la;
203         break;
204     case PCIL0_PMM1MA:
205         value = pci->pmm[1].ma;
206         break;
207     case PCIL0_PMM1PCIHA:
208         value = pci->pmm[1].pciha;
209         break;
210     case PCIL0_PMM1PCILA:
211         value = pci->pmm[1].pcila;
212         break;
213
214     case PCIL0_PMM2LA:
215         value = pci->pmm[2].la;
216         break;
217     case PCIL0_PMM2MA:
218         value = pci->pmm[2].ma;
219         break;
220     case PCIL0_PMM2PCIHA:
221         value = pci->pmm[2].pciha;
222         break;
223     case PCIL0_PMM2PCILA:
224         value = pci->pmm[2].pcila;
225         break;
226
227     case PCIL0_PTM1MS:
228         value = pci->ptm[0].ms;
229         break;
230     case PCIL0_PTM1LA:
231         value = pci->ptm[0].la;
232         break;
233     case PCIL0_PTM2MS:
234         value = pci->ptm[1].ms;
235         break;
236     case PCIL0_PTM2LA:
237         value = pci->ptm[1].la;
238         break;
239
240     default:
241         printf("%s: invalid PCI internal register 0x%lx\n", __func__,
242                (unsigned long)offset);
243         value = 0;
244     }
245
246     return value;
247 }
248
249 static CPUReadMemoryFunc * const pci_reg_read[] = {
250     &ppc4xx_pci_reg_read4,
251     &ppc4xx_pci_reg_read4,
252     &ppc4xx_pci_reg_read4,
253 };
254
255 static CPUWriteMemoryFunc * const pci_reg_write[] = {
256     &ppc4xx_pci_reg_write4,
257     &ppc4xx_pci_reg_write4,
258     &ppc4xx_pci_reg_write4,
259 };
260
261 static void ppc4xx_pci_reset(void *opaque)
262 {
263     struct PPC4xxPCIState *pci = opaque;
264
265     memset(pci->pmm, 0, sizeof(pci->pmm));
266     memset(pci->ptm, 0, sizeof(pci->ptm));
267 }
268
269 /* On Bamboo, all pins from each slot are tied to a single board IRQ. This
270  * may need further refactoring for other boards. */
271 static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
272 {
273     int slot = pci_dev->devfn >> 3;
274
275     DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
276             pci_dev->devfn, irq_num, slot);
277
278     return slot - 1;
279 }
280
281 static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level)
282 {
283     qemu_irq *pci_irqs = opaque;
284
285     DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
286     qemu_set_irq(pci_irqs[irq_num], level);
287 }
288
289 static const VMStateDescription vmstate_pci_master_map = {
290     .name = "pci_master_map",
291     .version_id = 0,
292     .minimum_version_id = 0,
293     .minimum_version_id_old = 0,
294     .fields      = (VMStateField[]) {
295         VMSTATE_UINT32(la, struct PCIMasterMap),
296         VMSTATE_UINT32(ma, struct PCIMasterMap),
297         VMSTATE_UINT32(pcila, struct PCIMasterMap),
298         VMSTATE_UINT32(pciha, struct PCIMasterMap),
299         VMSTATE_END_OF_LIST()
300     }
301 };
302
303 static const VMStateDescription vmstate_pci_target_map = {
304     .name = "pci_target_map",
305     .version_id = 0,
306     .minimum_version_id = 0,
307     .minimum_version_id_old = 0,
308     .fields      = (VMStateField[]) {
309         VMSTATE_UINT32(ms, struct PCITargetMap),
310         VMSTATE_UINT32(la, struct PCITargetMap),
311         VMSTATE_END_OF_LIST()
312     }
313 };
314
315 static const VMStateDescription vmstate_ppc4xx_pci = {
316     .name = "ppc4xx_pci",
317     .version_id = 1,
318     .minimum_version_id = 1,
319     .minimum_version_id_old = 1,
320     .fields      = (VMStateField[]) {
321         VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPC4xxPCIState),
322         VMSTATE_STRUCT_ARRAY(pmm, PPC4xxPCIState, PPC4xx_PCI_NR_PMMS, 1,
323                              vmstate_pci_master_map,
324                              struct PCIMasterMap),
325         VMSTATE_STRUCT_ARRAY(ptm, PPC4xxPCIState, PPC4xx_PCI_NR_PTMS, 1,
326                              vmstate_pci_target_map,
327                              struct PCITargetMap),
328         VMSTATE_END_OF_LIST()
329     }
330 };
331
332 /* XXX Interrupt acknowledge cycles not supported. */
333 PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
334                         target_phys_addr_t config_space,
335                         target_phys_addr_t int_ack,
336                         target_phys_addr_t special_cycle,
337                         target_phys_addr_t registers)
338 {
339     PPC4xxPCIState *controller;
340     int index;
341     static int ppc4xx_pci_id;
342     uint8_t *pci_conf;
343
344     controller = g_malloc0(sizeof(PPC4xxPCIState));
345
346     controller->pci_state.bus = pci_register_bus(NULL, "pci",
347                                                  ppc4xx_pci_set_irq,
348                                                  ppc4xx_pci_map_irq,
349                                                  pci_irqs,
350                                                  get_system_memory(),
351                                                  get_system_io(),
352                                                  0, 4);
353
354     controller->pci_dev = pci_register_device(controller->pci_state.bus,
355                                               "host bridge", sizeof(PCIDevice),
356                                               0, NULL, NULL);
357     pci_conf = controller->pci_dev->config;
358     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
359     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_440GX);
360     pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
361
362     /* CFGADDR */
363     index = cpu_register_io_memory(pci4xx_cfgaddr_read,
364                                    pci4xx_cfgaddr_write, controller,
365                                    DEVICE_LITTLE_ENDIAN);
366     if (index < 0)
367         goto free;
368     cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
369
370     /* CFGDATA */
371     memory_region_init_io(&controller->pci_state.data_mem,
372                           &pci_host_data_be_ops,
373                           &controller->pci_state, "pci-conf-data", 4);
374     memory_region_add_subregion(get_system_memory(),
375                                 config_space + PCIC0_CFGDATA,
376                                 &controller->pci_state.data_mem);
377
378     /* Internal registers */
379     index = cpu_register_io_memory(pci_reg_read, pci_reg_write, controller,
380                                    DEVICE_LITTLE_ENDIAN);
381     if (index < 0)
382         goto free;
383     cpu_register_physical_memory(registers, PCI_REG_SIZE, index);
384
385     qemu_register_reset(ppc4xx_pci_reset, controller);
386
387     /* XXX load/save code not tested. */
388     vmstate_register(&controller->pci_dev->qdev, ppc4xx_pci_id++,
389                      &vmstate_ppc4xx_pci, controller);
390
391     return controller->pci_state.bus;
392
393 free:
394     printf("%s error\n", __func__);
395     g_free(controller);
396     return NULL;
397 }
This page took 0.046305 seconds and 4 git commands to generate.