Statistics
| Branch: | Revision:

root / hw / ppc4xx_pci.c @ 00914b7d

History | View | Annotate | Download (10.5 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, see <http://www.gnu.org/licenses/>.
13
 *
14
 * Copyright IBM Corp. 2008
15
 *
16
 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
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

    
28
#undef DEBUG
29
#ifdef DEBUG
30
#define DPRINTF(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0)
31
#else
32
#define DPRINTF(fmt, ...)
33
#endif /* DEBUG */
34

    
35
struct PCIMasterMap {
36
    uint32_t la;
37
    uint32_t ma;
38
    uint32_t pcila;
39
    uint32_t pciha;
40
};
41

    
42
struct PCITargetMap {
43
    uint32_t ms;
44
    uint32_t la;
45
};
46

    
47
#define PPC4xx_PCI_NR_PMMS 3
48
#define PPC4xx_PCI_NR_PTMS 2
49

    
50
struct PPC4xxPCIState {
51
    struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS];
52
    struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS];
53

    
54
    PCIHostState pci_state;
55
    PCIDevice *pci_dev;
56
};
57
typedef struct PPC4xxPCIState PPC4xxPCIState;
58

    
59
#define PCIC0_CFGADDR       0x0
60
#define PCIC0_CFGDATA       0x4
61

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

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

    
85

    
86
static uint32_t pci4xx_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
87
{
88
    PPC4xxPCIState *ppc4xx_pci = opaque;
89

    
90
    return ppc4xx_pci->pci_state.config_reg;
91
}
92

    
93
static CPUReadMemoryFunc * const pci4xx_cfgaddr_read[] = {
94
    &pci4xx_cfgaddr_readl,
95
    &pci4xx_cfgaddr_readl,
96
    &pci4xx_cfgaddr_readl,
97
};
98

    
99
static void pci4xx_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
100
                                  uint32_t value)
101
{
102
    PPC4xxPCIState *ppc4xx_pci = opaque;
103

    
104
    ppc4xx_pci->pci_state.config_reg = value & ~0x3;
105
}
106

    
107
static CPUWriteMemoryFunc * const pci4xx_cfgaddr_write[] = {
108
    &pci4xx_cfgaddr_writel,
109
    &pci4xx_cfgaddr_writel,
110
    &pci4xx_cfgaddr_writel,
111
};
112

    
113
static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
114
                                  uint32_t value)
115
{
116
    struct PPC4xxPCIState *pci = opaque;
117

    
118
    /* We ignore all target attempts at PCI configuration, effectively
119
     * assuming a bidirectional 1:1 mapping of PLB and PCI space. */
120

    
121
    switch (offset) {
122
    case PCIL0_PMM0LA:
123
        pci->pmm[0].la = value;
124
        break;
125
    case PCIL0_PMM0MA:
126
        pci->pmm[0].ma = value;
127
        break;
128
    case PCIL0_PMM0PCIHA:
129
        pci->pmm[0].pciha = value;
130
        break;
131
    case PCIL0_PMM0PCILA:
132
        pci->pmm[0].pcila = value;
133
        break;
134

    
135
    case PCIL0_PMM1LA:
136
        pci->pmm[1].la = value;
137
        break;
138
    case PCIL0_PMM1MA:
139
        pci->pmm[1].ma = value;
140
        break;
141
    case PCIL0_PMM1PCIHA:
142
        pci->pmm[1].pciha = value;
143
        break;
144
    case PCIL0_PMM1PCILA:
145
        pci->pmm[1].pcila = value;
146
        break;
147

    
148
    case PCIL0_PMM2LA:
149
        pci->pmm[2].la = value;
150
        break;
151
    case PCIL0_PMM2MA:
152
        pci->pmm[2].ma = value;
153
        break;
154
    case PCIL0_PMM2PCIHA:
155
        pci->pmm[2].pciha = value;
156
        break;
157
    case PCIL0_PMM2PCILA:
158
        pci->pmm[2].pcila = value;
159
        break;
160

    
161
    case PCIL0_PTM1MS:
162
        pci->ptm[0].ms = value;
163
        break;
164
    case PCIL0_PTM1LA:
165
        pci->ptm[0].la = value;
166
        break;
167
    case PCIL0_PTM2MS:
168
        pci->ptm[1].ms = value;
169
        break;
170
    case PCIL0_PTM2LA:
171
        pci->ptm[1].la = value;
172
        break;
173

    
174
    default:
175
        printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
176
               (unsigned long)offset);
177
        break;
178
    }
179
}
180

    
181
static uint32_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset)
182
{
183
    struct PPC4xxPCIState *pci = opaque;
184
    uint32_t value;
185

    
186
    switch (offset) {
187
    case PCIL0_PMM0LA:
188
        value = pci->pmm[0].la;
189
        break;
190
    case PCIL0_PMM0MA:
191
        value = pci->pmm[0].ma;
192
        break;
193
    case PCIL0_PMM0PCIHA:
194
        value = pci->pmm[0].pciha;
195
        break;
196
    case PCIL0_PMM0PCILA:
197
        value = pci->pmm[0].pcila;
198
        break;
199

    
200
    case PCIL0_PMM1LA:
201
        value = pci->pmm[1].la;
202
        break;
203
    case PCIL0_PMM1MA:
204
        value = pci->pmm[1].ma;
205
        break;
206
    case PCIL0_PMM1PCIHA:
207
        value = pci->pmm[1].pciha;
208
        break;
209
    case PCIL0_PMM1PCILA:
210
        value = pci->pmm[1].pcila;
211
        break;
212

    
213
    case PCIL0_PMM2LA:
214
        value = pci->pmm[2].la;
215
        break;
216
    case PCIL0_PMM2MA:
217
        value = pci->pmm[2].ma;
218
        break;
219
    case PCIL0_PMM2PCIHA:
220
        value = pci->pmm[2].pciha;
221
        break;
222
    case PCIL0_PMM2PCILA:
223
        value = pci->pmm[2].pcila;
224
        break;
225

    
226
    case PCIL0_PTM1MS:
227
        value = pci->ptm[0].ms;
228
        break;
229
    case PCIL0_PTM1LA:
230
        value = pci->ptm[0].la;
231
        break;
232
    case PCIL0_PTM2MS:
233
        value = pci->ptm[1].ms;
234
        break;
235
    case PCIL0_PTM2LA:
236
        value = pci->ptm[1].la;
237
        break;
238

    
239
    default:
240
        printf("%s: invalid PCI internal register 0x%lx\n", __func__,
241
               (unsigned long)offset);
242
        value = 0;
243
    }
244

    
245
    return value;
246
}
247

    
248
static CPUReadMemoryFunc * const pci_reg_read[] = {
249
    &ppc4xx_pci_reg_read4,
250
    &ppc4xx_pci_reg_read4,
251
    &ppc4xx_pci_reg_read4,
252
};
253

    
254
static CPUWriteMemoryFunc * const pci_reg_write[] = {
255
    &ppc4xx_pci_reg_write4,
256
    &ppc4xx_pci_reg_write4,
257
    &ppc4xx_pci_reg_write4,
258
};
259

    
260
static void ppc4xx_pci_reset(void *opaque)
261
{
262
    struct PPC4xxPCIState *pci = opaque;
263

    
264
    memset(pci->pmm, 0, sizeof(pci->pmm));
265
    memset(pci->ptm, 0, sizeof(pci->ptm));
266
}
267

    
268
/* On Bamboo, all pins from each slot are tied to a single board IRQ. This
269
 * may need further refactoring for other boards. */
270
static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
271
{
272
    int slot = pci_dev->devfn >> 3;
273

    
274
    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
275
            pci_dev->devfn, irq_num, slot);
276

    
277
    return slot - 1;
278
}
279

    
280
static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level)
281
{
282
    qemu_irq *pci_irqs = opaque;
283

    
284
    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
285
    qemu_set_irq(pci_irqs[irq_num], level);
286
}
287

    
288
static void ppc4xx_pci_save(QEMUFile *f, void *opaque)
289
{
290
    PPC4xxPCIState *controller = opaque;
291
    int i;
292

    
293
    pci_device_save(controller->pci_dev, f);
294

    
295
    for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
296
        qemu_put_be32s(f, &controller->pmm[i].la);
297
        qemu_put_be32s(f, &controller->pmm[i].ma);
298
        qemu_put_be32s(f, &controller->pmm[i].pcila);
299
        qemu_put_be32s(f, &controller->pmm[i].pciha);
300
    }
301

    
302
    for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
303
        qemu_put_be32s(f, &controller->ptm[i].ms);
304
        qemu_put_be32s(f, &controller->ptm[i].la);
305
    }
306
}
307

    
308
static int ppc4xx_pci_load(QEMUFile *f, void *opaque, int version_id)
309
{
310
    PPC4xxPCIState *controller = opaque;
311
    int i;
312

    
313
    if (version_id != 1)
314
        return -EINVAL;
315

    
316
    pci_device_load(controller->pci_dev, f);
317

    
318
    for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
319
        qemu_get_be32s(f, &controller->pmm[i].la);
320
        qemu_get_be32s(f, &controller->pmm[i].ma);
321
        qemu_get_be32s(f, &controller->pmm[i].pcila);
322
        qemu_get_be32s(f, &controller->pmm[i].pciha);
323
    }
324

    
325
    for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
326
        qemu_get_be32s(f, &controller->ptm[i].ms);
327
        qemu_get_be32s(f, &controller->ptm[i].la);
328
    }
329

    
330
    return 0;
331
}
332

    
333
/* XXX Interrupt acknowledge cycles not supported. */
334
PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
335
                        target_phys_addr_t config_space,
336
                        target_phys_addr_t int_ack,
337
                        target_phys_addr_t special_cycle,
338
                        target_phys_addr_t registers)
339
{
340
    PPC4xxPCIState *controller;
341
    int index;
342
    static int ppc4xx_pci_id;
343
    uint8_t *pci_conf;
344

    
345
    controller = qemu_mallocz(sizeof(PPC4xxPCIState));
346

    
347
    controller->pci_state.bus = pci_register_bus(NULL, "pci",
348
                                                 ppc4xx_pci_set_irq,
349
                                                 ppc4xx_pci_map_irq,
350
                                                 pci_irqs, 0, 4);
351

    
352
    controller->pci_dev = pci_register_device(controller->pci_state.bus,
353
                                              "host bridge", sizeof(PCIDevice),
354
                                              0, NULL, NULL);
355
    pci_conf = controller->pci_dev->config;
356
    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
357
    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_440GX);
358
    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
359

    
360
    /* CFGADDR */
361
    index = cpu_register_io_memory(pci4xx_cfgaddr_read,
362
                                   pci4xx_cfgaddr_write, controller,
363
                                   DEVICE_LITTLE_ENDIAN);
364
    if (index < 0)
365
        goto free;
366
    cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
367

    
368
    /* CFGDATA */
369
    index = pci_host_data_register_mmio(&controller->pci_state, 1);
370
    if (index < 0)
371
        goto free;
372
    cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index);
373

    
374
    /* Internal registers */
375
    index = cpu_register_io_memory(pci_reg_read, pci_reg_write, controller,
376
                                   DEVICE_LITTLE_ENDIAN);
377
    if (index < 0)
378
        goto free;
379
    cpu_register_physical_memory(registers, PCI_REG_SIZE, index);
380

    
381
    qemu_register_reset(ppc4xx_pci_reset, controller);
382

    
383
    /* XXX load/save code not tested. */
384
    register_savevm(&controller->pci_dev->qdev, "ppc4xx_pci", ppc4xx_pci_id++,
385
                    1, ppc4xx_pci_save, ppc4xx_pci_load, controller);
386

    
387
    return controller->pci_state.bus;
388

    
389
free:
390
    printf("%s error\n", __func__);
391
    qemu_free(controller);
392
    return NULL;
393
}