Statistics
| Branch: | Revision:

root / hw / ppc4xx_pci.c @ 1eed09cb

History | View | Annotate | Download (11 kB)

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 <hollisb@us.ibm.com>
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
#include "ppc.h"
25
#include "ppc4xx.h"
26

    
27
typedef target_phys_addr_t pci_addr_t;
28
#include "pci.h"
29
#include "pci_host.h"
30
#include "bswap.h"
31

    
32
#undef DEBUG
33
#ifdef DEBUG
34
#define DPRINTF(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0)
35
#else
36
#define DPRINTF(fmt, ...)
37
#endif /* DEBUG */
38

    
39
struct PCIMasterMap {
40
    uint32_t la;
41
    uint32_t ma;
42
    uint32_t pcila;
43
    uint32_t pciha;
44
};
45

    
46
struct PCITargetMap {
47
    uint32_t ms;
48
    uint32_t la;
49
};
50

    
51
#define PPC4xx_PCI_NR_PMMS 3
52
#define PPC4xx_PCI_NR_PTMS 2
53

    
54
struct PPC4xxPCIState {
55
    struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS];
56
    struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS];
57

    
58
    PCIHostState pci_state;
59
    PCIDevice *pci_dev;
60
};
61
typedef struct PPC4xxPCIState PPC4xxPCIState;
62

    
63
#define PCIC0_CFGADDR       0x0
64
#define PCIC0_CFGDATA       0x4
65

    
66
/* PLB Memory Map (PMM) registers specify which PLB addresses are translated to
67
 * PCI accesses. */
68
#define PCIL0_PMM0LA        0x0
69
#define PCIL0_PMM0MA        0x4
70
#define PCIL0_PMM0PCILA     0x8
71
#define PCIL0_PMM0PCIHA     0xc
72
#define PCIL0_PMM1LA        0x10
73
#define PCIL0_PMM1MA        0x14
74
#define PCIL0_PMM1PCILA     0x18
75
#define PCIL0_PMM1PCIHA     0x1c
76
#define PCIL0_PMM2LA        0x20
77
#define PCIL0_PMM2MA        0x24
78
#define PCIL0_PMM2PCILA     0x28
79
#define PCIL0_PMM2PCIHA     0x2c
80

    
81
/* PCI Target Map (PTM) registers specify which PCI addresses are translated to
82
 * PLB accesses. */
83
#define PCIL0_PTM1MS        0x30
84
#define PCIL0_PTM1LA        0x34
85
#define PCIL0_PTM2MS        0x38
86
#define PCIL0_PTM2LA        0x3c
87
#define PCI_REG_SIZE        0x40
88

    
89

    
90
static uint32_t pci4xx_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
91
{
92
    PPC4xxPCIState *ppc4xx_pci = opaque;
93

    
94
    return ppc4xx_pci->pci_state.config_reg;
95
}
96

    
97
static CPUReadMemoryFunc *pci4xx_cfgaddr_read[] = {
98
    &pci4xx_cfgaddr_readl,
99
    &pci4xx_cfgaddr_readl,
100
    &pci4xx_cfgaddr_readl,
101
};
102

    
103
static void pci4xx_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
104
                                  uint32_t value)
105
{
106
    PPC4xxPCIState *ppc4xx_pci = opaque;
107

    
108
#ifdef TARGET_WORDS_BIGENDIAN
109
    value = bswap32(value);
110
#endif
111

    
112
    ppc4xx_pci->pci_state.config_reg = value & ~0x3;
113
}
114

    
115
static CPUWriteMemoryFunc *pci4xx_cfgaddr_write[] = {
116
    &pci4xx_cfgaddr_writel,
117
    &pci4xx_cfgaddr_writel,
118
    &pci4xx_cfgaddr_writel,
119
};
120

    
121
static CPUReadMemoryFunc *pci4xx_cfgdata_read[] = {
122
    &pci_host_data_readb,
123
    &pci_host_data_readw,
124
    &pci_host_data_readl,
125
};
126

    
127
static CPUWriteMemoryFunc *pci4xx_cfgdata_write[] = {
128
    &pci_host_data_writeb,
129
    &pci_host_data_writew,
130
    &pci_host_data_writel,
131
};
132

    
133
static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
134
                                  uint32_t value)
135
{
136
    struct PPC4xxPCIState *pci = opaque;
137

    
138
#ifdef TARGET_WORDS_BIGENDIAN
139
    value = bswap32(value);
140
#endif
141

    
142
    /* We ignore all target attempts at PCI configuration, effectively
143
     * assuming a bidirectional 1:1 mapping of PLB and PCI space. */
144

    
145
    switch (offset) {
146
    case PCIL0_PMM0LA:
147
        pci->pmm[0].la = value;
148
        break;
149
    case PCIL0_PMM0MA:
150
        pci->pmm[0].ma = value;
151
        break;
152
    case PCIL0_PMM0PCIHA:
153
        pci->pmm[0].pciha = value;
154
        break;
155
    case PCIL0_PMM0PCILA:
156
        pci->pmm[0].pcila = value;
157
        break;
158

    
159
    case PCIL0_PMM1LA:
160
        pci->pmm[1].la = value;
161
        break;
162
    case PCIL0_PMM1MA:
163
        pci->pmm[1].ma = value;
164
        break;
165
    case PCIL0_PMM1PCIHA:
166
        pci->pmm[1].pciha = value;
167
        break;
168
    case PCIL0_PMM1PCILA:
169
        pci->pmm[1].pcila = value;
170
        break;
171

    
172
    case PCIL0_PMM2LA:
173
        pci->pmm[2].la = value;
174
        break;
175
    case PCIL0_PMM2MA:
176
        pci->pmm[2].ma = value;
177
        break;
178
    case PCIL0_PMM2PCIHA:
179
        pci->pmm[2].pciha = value;
180
        break;
181
    case PCIL0_PMM2PCILA:
182
        pci->pmm[2].pcila = value;
183
        break;
184

    
185
    case PCIL0_PTM1MS:
186
        pci->ptm[0].ms = value;
187
        break;
188
    case PCIL0_PTM1LA:
189
        pci->ptm[0].la = value;
190
        break;
191
    case PCIL0_PTM2MS:
192
        pci->ptm[1].ms = value;
193
        break;
194
    case PCIL0_PTM2LA:
195
        pci->ptm[1].la = value;
196
        break;
197

    
198
    default:
199
        printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
200
               (unsigned long)offset);
201
        break;
202
    }
203
}
204

    
205
static uint32_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset)
206
{
207
    struct PPC4xxPCIState *pci = opaque;
208
    uint32_t value;
209

    
210
    switch (offset) {
211
    case PCIL0_PMM0LA:
212
        value = pci->pmm[0].la;
213
        break;
214
    case PCIL0_PMM0MA:
215
        value = pci->pmm[0].ma;
216
        break;
217
    case PCIL0_PMM0PCIHA:
218
        value = pci->pmm[0].pciha;
219
        break;
220
    case PCIL0_PMM0PCILA:
221
        value = pci->pmm[0].pcila;
222
        break;
223

    
224
    case PCIL0_PMM1LA:
225
        value = pci->pmm[1].la;
226
        break;
227
    case PCIL0_PMM1MA:
228
        value = pci->pmm[1].ma;
229
        break;
230
    case PCIL0_PMM1PCIHA:
231
        value = pci->pmm[1].pciha;
232
        break;
233
    case PCIL0_PMM1PCILA:
234
        value = pci->pmm[1].pcila;
235
        break;
236

    
237
    case PCIL0_PMM2LA:
238
        value = pci->pmm[2].la;
239
        break;
240
    case PCIL0_PMM2MA:
241
        value = pci->pmm[2].ma;
242
        break;
243
    case PCIL0_PMM2PCIHA:
244
        value = pci->pmm[2].pciha;
245
        break;
246
    case PCIL0_PMM2PCILA:
247
        value = pci->pmm[2].pcila;
248
        break;
249

    
250
    case PCIL0_PTM1MS:
251
        value = pci->ptm[0].ms;
252
        break;
253
    case PCIL0_PTM1LA:
254
        value = pci->ptm[0].la;
255
        break;
256
    case PCIL0_PTM2MS:
257
        value = pci->ptm[1].ms;
258
        break;
259
    case PCIL0_PTM2LA:
260
        value = pci->ptm[1].la;
261
        break;
262

    
263
    default:
264
        printf("%s: invalid PCI internal register 0x%lx\n", __func__,
265
               (unsigned long)offset);
266
        value = 0;
267
    }
268

    
269
#ifdef TARGET_WORDS_BIGENDIAN
270
    value = bswap32(value);
271
#endif
272

    
273
    return value;
274
}
275

    
276
static CPUReadMemoryFunc *pci_reg_read[] = {
277
    &ppc4xx_pci_reg_read4,
278
    &ppc4xx_pci_reg_read4,
279
    &ppc4xx_pci_reg_read4,
280
};
281

    
282
static CPUWriteMemoryFunc *pci_reg_write[] = {
283
    &ppc4xx_pci_reg_write4,
284
    &ppc4xx_pci_reg_write4,
285
    &ppc4xx_pci_reg_write4,
286
};
287

    
288
static void ppc4xx_pci_reset(void *opaque)
289
{
290
    struct PPC4xxPCIState *pci = opaque;
291

    
292
    memset(pci->pmm, 0, sizeof(pci->pmm));
293
    memset(pci->ptm, 0, sizeof(pci->ptm));
294
}
295

    
296
/* On Bamboo, all pins from each slot are tied to a single board IRQ. This
297
 * may need further refactoring for other boards. */
298
static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
299
{
300
    int slot = pci_dev->devfn >> 3;
301

    
302
    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
303
            pci_dev->devfn, irq_num, slot);
304

    
305
    return slot - 1;
306
}
307

    
308
static void ppc4xx_pci_set_irq(qemu_irq *pci_irqs, int irq_num, int level)
309
{
310
    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
311
    qemu_set_irq(pci_irqs[irq_num], level);
312
}
313

    
314
static void ppc4xx_pci_save(QEMUFile *f, void *opaque)
315
{
316
    PPC4xxPCIState *controller = opaque;
317
    int i;
318

    
319
    pci_device_save(controller->pci_dev, f);
320

    
321
    for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
322
        qemu_put_be32s(f, &controller->pmm[i].la);
323
        qemu_put_be32s(f, &controller->pmm[i].ma);
324
        qemu_put_be32s(f, &controller->pmm[i].pcila);
325
        qemu_put_be32s(f, &controller->pmm[i].pciha);
326
    }
327

    
328
    for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
329
        qemu_put_be32s(f, &controller->ptm[i].ms);
330
        qemu_put_be32s(f, &controller->ptm[i].la);
331
    }
332
}
333

    
334
static int ppc4xx_pci_load(QEMUFile *f, void *opaque, int version_id)
335
{
336
    PPC4xxPCIState *controller = opaque;
337
    int i;
338

    
339
    if (version_id != 1)
340
        return -EINVAL;
341

    
342
    pci_device_load(controller->pci_dev, f);
343

    
344
    for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
345
        qemu_get_be32s(f, &controller->pmm[i].la);
346
        qemu_get_be32s(f, &controller->pmm[i].ma);
347
        qemu_get_be32s(f, &controller->pmm[i].pcila);
348
        qemu_get_be32s(f, &controller->pmm[i].pciha);
349
    }
350

    
351
    for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
352
        qemu_get_be32s(f, &controller->ptm[i].ms);
353
        qemu_get_be32s(f, &controller->ptm[i].la);
354
    }
355

    
356
    return 0;
357
}
358

    
359
/* XXX Interrupt acknowledge cycles not supported. */
360
PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
361
                        target_phys_addr_t config_space,
362
                        target_phys_addr_t int_ack,
363
                        target_phys_addr_t special_cycle,
364
                        target_phys_addr_t registers)
365
{
366
    PPC4xxPCIState *controller;
367
    int index;
368
    static int ppc4xx_pci_id;
369
    uint8_t *pci_conf;
370

    
371
    controller = qemu_mallocz(sizeof(PPC4xxPCIState));
372

    
373
    controller->pci_state.bus = pci_register_bus(NULL, "pci",
374
                                                 ppc4xx_pci_set_irq,
375
                                                 ppc4xx_pci_map_irq,
376
                                                 pci_irqs, 0, 4);
377

    
378
    controller->pci_dev = pci_register_device(controller->pci_state.bus,
379
                                              "host bridge", sizeof(PCIDevice),
380
                                              0, NULL, NULL);
381
    pci_conf = controller->pci_dev->config;
382
    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
383
    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_440GX);
384
    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
385

    
386
    /* CFGADDR */
387
    index = cpu_register_io_memory(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(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(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, 0, 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
}