Statistics
| Branch: | Revision:

root / hw / ppc4xx_pci.c @ 825bb581

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

    
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
}