Statistics
| Branch: | Revision:

root / hw / ppc4xx_pci.c @ 0200db65

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, 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
#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
}