Statistics
| Branch: | Revision:

root / hw / ppc4xx_pci.c @ e8b36ba9

History | View | Annotate | Download (10.7 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 const VMStateDescription vmstate_pci_master_map = {
289
    .name = "pci_master_map",
290
    .version_id = 0,
291
    .minimum_version_id = 0,
292
    .minimum_version_id_old = 0,
293
    .fields      = (VMStateField[]) {
294
        VMSTATE_UINT32(la, struct PCIMasterMap),
295
        VMSTATE_UINT32(ma, struct PCIMasterMap),
296
        VMSTATE_UINT32(pcila, struct PCIMasterMap),
297
        VMSTATE_UINT32(pciha, struct PCIMasterMap),
298
        VMSTATE_END_OF_LIST()
299
    }
300
};
301

    
302
static const VMStateDescription vmstate_pci_target_map = {
303
    .name = "pci_target_map",
304
    .version_id = 0,
305
    .minimum_version_id = 0,
306
    .minimum_version_id_old = 0,
307
    .fields      = (VMStateField[]) {
308
        VMSTATE_UINT32(ms, struct PCITargetMap),
309
        VMSTATE_UINT32(la, struct PCITargetMap),
310
        VMSTATE_END_OF_LIST()
311
    }
312
};
313

    
314
static const VMStateDescription vmstate_ppc4xx_pci = {
315
    .name = "ppc4xx_pci",
316
    .version_id = 1,
317
    .minimum_version_id = 1,
318
    .minimum_version_id_old = 1,
319
    .fields      = (VMStateField[]) {
320
        VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPC4xxPCIState),
321
        VMSTATE_STRUCT_ARRAY(pmm, PPC4xxPCIState, PPC4xx_PCI_NR_PMMS, 1,
322
                             vmstate_pci_master_map,
323
                             struct PCIMasterMap),
324
        VMSTATE_STRUCT_ARRAY(ptm, PPC4xxPCIState, PPC4xx_PCI_NR_PTMS, 1,
325
                             vmstate_pci_target_map,
326
                             struct PCITargetMap),
327
        VMSTATE_END_OF_LIST()
328
    }
329
};
330

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

    
343
    controller = qemu_mallocz(sizeof(PPC4xxPCIState));
344

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

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

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

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

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

    
379
    qemu_register_reset(ppc4xx_pci_reset, controller);
380

    
381
    /* XXX load/save code not tested. */
382
    vmstate_register(&controller->pci_dev->qdev, ppc4xx_pci_id++,
383
                     &vmstate_ppc4xx_pci, controller);
384

    
385
    return controller->pci_state.bus;
386

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