]> Git Repo - qemu.git/blob - hw/apb_pci.c
sparc64: use PCI accessors for APB/PBM
[qemu.git] / hw / apb_pci.c
1 /*
2  * QEMU Ultrasparc APB PCI host
3  *
4  * Copyright (c) 2006 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 /* XXX This file and most of its contents are somewhat misnamed.  The
26    Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
27    the secondary PCI bridge.  */
28
29 #include "sysbus.h"
30 #include "pci.h"
31 #include "pci_host.h"
32 #include "apb_pci.h"
33
34 /* debug APB */
35 //#define DEBUG_APB
36
37 #ifdef DEBUG_APB
38 #define APB_DPRINTF(fmt, ...) \
39 do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
40 #else
41 #define APB_DPRINTF(fmt, ...)
42 #endif
43
44 /*
45  * Chipset docs:
46  * PBM: "UltraSPARC IIi User's Manual",
47  * http://www.sun.com/processors/manuals/805-0087.pdf
48  *
49  * APB: "Advanced PCI Bridge (APB) User's Manual",
50  * http://www.sun.com/processors/manuals/805-1251.pdf
51  */
52
53 #define PBM_PCI_IMR_MASK    0x7fffffff
54 #define PBM_PCI_IMR_ENABLED 0x80000000
55
56 #define POR          (1 << 31)
57 #define SOFT_POR     (1 << 30)
58 #define SOFT_XIR     (1 << 29)
59 #define BTN_POR      (1 << 28)
60 #define BTN_XIR      (1 << 27)
61 #define RESET_MASK   0xf8000000
62 #define RESET_WCMASK 0x98000000
63 #define RESET_WMASK  0x60000000
64
65 typedef struct APBState {
66     SysBusDevice busdev;
67     PCIHostState host_state;
68     uint32_t iommu[4];
69     uint32_t pci_control[16];
70     uint32_t pci_irq_map[8];
71     uint32_t obio_irq_map[32];
72     qemu_irq pci_irqs[32];
73     uint32_t reset_control;
74 } APBState;
75
76 static unsigned int nr_resets;
77
78 static void apb_config_writel (void *opaque, target_phys_addr_t addr,
79                                uint32_t val)
80 {
81     APBState *s = opaque;
82
83     APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
84
85     switch (addr & 0xffff) {
86     case 0x30 ... 0x4f: /* DMA error registers */
87         /* XXX: not implemented yet */
88         break;
89     case 0x200 ... 0x20b: /* IOMMU */
90         s->iommu[(addr & 0xf) >> 2] = val;
91         break;
92     case 0x20c ... 0x3ff: /* IOMMU flush */
93         break;
94     case 0xc00 ... 0xc3f: /* PCI interrupt control */
95         if (addr & 4) {
96             s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
97             s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
98         }
99         break;
100     case 0x2000 ... 0x202f: /* PCI control */
101         s->pci_control[(addr & 0x3f) >> 2] = val;
102         break;
103     case 0xf020 ... 0xf027: /* Reset control */
104         if (addr & 4) {
105             val &= RESET_MASK;
106             s->reset_control &= ~(val & RESET_WCMASK);
107             s->reset_control |= val & RESET_WMASK;
108             if (val & SOFT_POR) {
109                 nr_resets = 0;
110                 qemu_system_reset_request();
111             } else if (val & SOFT_XIR) {
112                 qemu_system_reset_request();
113             }
114         }
115         break;
116     case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
117     case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
118     case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
119     case 0xf000 ... 0xf01f: /* FFB config, memory control */
120         /* we don't care */
121     default:
122         break;
123     }
124 }
125
126 static uint32_t apb_config_readl (void *opaque,
127                                   target_phys_addr_t addr)
128 {
129     APBState *s = opaque;
130     uint32_t val;
131
132     switch (addr & 0xffff) {
133     case 0x30 ... 0x4f: /* DMA error registers */
134         val = 0;
135         /* XXX: not implemented yet */
136         break;
137     case 0x200 ... 0x20b: /* IOMMU */
138         val = s->iommu[(addr & 0xf) >> 2];
139         break;
140     case 0x20c ... 0x3ff: /* IOMMU flush */
141         val = 0;
142         break;
143     case 0xc00 ... 0xc3f: /* PCI interrupt control */
144         if (addr & 4) {
145             val = s->pci_irq_map[(addr & 0x3f) >> 3];
146         } else {
147             val = 0;
148         }
149         break;
150     case 0x2000 ... 0x202f: /* PCI control */
151         val = s->pci_control[(addr & 0x3f) >> 2];
152         break;
153     case 0xf020 ... 0xf027: /* Reset control */
154         if (addr & 4) {
155             val = s->reset_control;
156         } else {
157             val = 0;
158         }
159         break;
160     case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
161     case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
162     case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
163     case 0xf000 ... 0xf01f: /* FFB config, memory control */
164         /* we don't care */
165     default:
166         val = 0;
167         break;
168     }
169     APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val);
170
171     return val;
172 }
173
174 static CPUWriteMemoryFunc * const apb_config_write[] = {
175     &apb_config_writel,
176     &apb_config_writel,
177     &apb_config_writel,
178 };
179
180 static CPUReadMemoryFunc * const apb_config_read[] = {
181     &apb_config_readl,
182     &apb_config_readl,
183     &apb_config_readl,
184 };
185
186 static void apb_pci_config_write(APBState *s, target_phys_addr_t addr,
187                                  uint32_t val, int size)
188 {
189     APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
190     pci_data_write(s->host_state.bus, (addr & 0x00ffffff) | (1u << 31), val,
191                    size);
192 }
193
194 static uint32_t apb_pci_config_read(APBState *s, target_phys_addr_t addr,
195                                     int size)
196 {
197     uint32_t ret;
198
199     ret = pci_data_read(s->host_state.bus, (addr & 0x00ffffff) | (1u << 31),
200                         size);
201     APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
202     return ret;
203 }
204
205 static void apb_pci_config_writel(void *opaque, target_phys_addr_t addr,
206                                   uint32_t val)
207 {
208     APBState *s = opaque;
209
210     apb_pci_config_write(s, addr, bswap32(val), 4);
211 }
212
213 static void apb_pci_config_writew(void *opaque, target_phys_addr_t addr,
214                                   uint32_t val)
215 {
216     APBState *s = opaque;
217
218     apb_pci_config_write(s, addr, bswap16(val), 2);
219 }
220
221 static void apb_pci_config_writeb(void *opaque, target_phys_addr_t addr,
222                                   uint32_t val)
223 {
224     APBState *s = opaque;
225
226     apb_pci_config_write(s, addr, val, 1);
227 }
228
229 static uint32_t apb_pci_config_readl(void *opaque, target_phys_addr_t addr)
230 {
231     APBState *s = opaque;
232
233     return bswap32(apb_pci_config_read(s, addr, 4));
234 }
235
236 static uint32_t apb_pci_config_readw(void *opaque, target_phys_addr_t addr)
237 {
238     APBState *s = opaque;
239
240     return bswap16(apb_pci_config_read(s, addr, 2));
241 }
242
243 static uint32_t apb_pci_config_readb(void *opaque, target_phys_addr_t addr)
244 {
245     APBState *s = opaque;
246
247     return apb_pci_config_read(s, addr, 1);
248 }
249
250 static CPUWriteMemoryFunc * const apb_pci_config_writes[] = {
251     &apb_pci_config_writeb,
252     &apb_pci_config_writew,
253     &apb_pci_config_writel,
254 };
255
256 static CPUReadMemoryFunc * const apb_pci_config_reads[] = {
257     &apb_pci_config_readb,
258     &apb_pci_config_readw,
259     &apb_pci_config_readl,
260 };
261
262 static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
263                                   uint32_t val)
264 {
265     cpu_outb(addr & IOPORTS_MASK, val);
266 }
267
268 static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
269                                   uint32_t val)
270 {
271     cpu_outw(addr & IOPORTS_MASK, bswap16(val));
272 }
273
274 static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
275                                 uint32_t val)
276 {
277     cpu_outl(addr & IOPORTS_MASK, bswap32(val));
278 }
279
280 static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
281 {
282     uint32_t val;
283
284     val = cpu_inb(addr & IOPORTS_MASK);
285     return val;
286 }
287
288 static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
289 {
290     uint32_t val;
291
292     val = bswap16(cpu_inw(addr & IOPORTS_MASK));
293     return val;
294 }
295
296 static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
297 {
298     uint32_t val;
299
300     val = bswap32(cpu_inl(addr & IOPORTS_MASK));
301     return val;
302 }
303
304 static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
305     &pci_apb_iowriteb,
306     &pci_apb_iowritew,
307     &pci_apb_iowritel,
308 };
309
310 static CPUReadMemoryFunc * const pci_apb_ioread[] = {
311     &pci_apb_ioreadb,
312     &pci_apb_ioreadw,
313     &pci_apb_ioreadl,
314 };
315
316 /* The APB host has an IRQ line for each IRQ line of each slot.  */
317 static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
318 {
319     return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
320 }
321
322 static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
323 {
324     int bus_offset;
325     if (pci_dev->devfn & 1)
326         bus_offset = 16;
327     else
328         bus_offset = 0;
329     return bus_offset + irq_num;
330 }
331
332 static void pci_apb_set_irq(void *opaque, int irq_num, int level)
333 {
334     APBState *s = opaque;
335
336     /* PCI IRQ map onto the first 32 INO.  */
337     if (irq_num < 32) {
338         if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
339             APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
340             qemu_set_irq(s->pci_irqs[irq_num], level);
341         } else {
342             APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
343             qemu_irq_lower(s->pci_irqs[irq_num]);
344         }
345     }
346 }
347
348 static void apb_pci_bridge_init(PCIBus *b)
349 {
350     PCIDevice *dev = pci_bridge_get_device(b);
351
352     /*
353      * command register:
354      * According to PCI bridge spec, after reset
355      *   bus master bit is off
356      *   memory space enable bit is off
357      * According to manual (805-1251.pdf).
358      *   the reset value should be zero unless the boot pin is tied high
359      *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
360      */
361     pci_set_word(dev->config + PCI_COMMAND,
362                  PCI_COMMAND_MEMORY);
363     pci_set_word(dev->config + PCI_STATUS,
364                  PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
365                  PCI_STATUS_DEVSEL_MEDIUM);
366     pci_set_byte(dev->config + PCI_REVISION_ID, 0x11);
367     pci_set_byte(dev->config + PCI_HEADER_TYPE,
368                  pci_get_byte(dev->config + PCI_HEADER_TYPE) |
369                  PCI_HEADER_TYPE_MULTI_FUNCTION);
370 }
371
372 PCIBus *pci_apb_init(target_phys_addr_t special_base,
373                      target_phys_addr_t mem_base,
374                      qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
375 {
376     DeviceState *dev;
377     SysBusDevice *s;
378     APBState *d;
379     unsigned int i;
380
381     /* Ultrasparc PBM main bus */
382     dev = qdev_create(NULL, "pbm");
383     qdev_init_nofail(dev);
384     s = sysbus_from_qdev(dev);
385     /* apb_config */
386     sysbus_mmio_map(s, 0, special_base);
387     /* pci_ioport */
388     sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
389     /* pci_config */
390     sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
391     /* mem_data */
392     sysbus_mmio_map(s, 3, mem_base);
393     d = FROM_SYSBUS(APBState, s);
394     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
395                                          pci_apb_set_irq, pci_pbm_map_irq, d,
396                                          0, 32);
397     pci_bus_set_mem_base(d->host_state.bus, mem_base);
398
399     for (i = 0; i < 32; i++) {
400         sysbus_connect_irq(s, i, pic[i]);
401     }
402
403     pci_create_simple(d->host_state.bus, 0, "pbm");
404     /* APB secondary busses */
405     *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
406                             PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
407                             pci_apb_map_irq,
408                             "Advanced PCI Bus secondary bridge 1");
409     apb_pci_bridge_init(*bus2);
410
411     *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
412                             PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
413                             pci_apb_map_irq,
414                             "Advanced PCI Bus secondary bridge 2");
415     apb_pci_bridge_init(*bus3);
416
417     return d->host_state.bus;
418 }
419
420 static void pci_pbm_reset(DeviceState *d)
421 {
422     unsigned int i;
423     APBState *s = container_of(d, APBState, busdev.qdev);
424
425     for (i = 0; i < 8; i++) {
426         s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
427     }
428
429     if (nr_resets++ == 0) {
430         /* Power on reset */
431         s->reset_control = POR;
432     }
433 }
434
435 static int pci_pbm_init_device(SysBusDevice *dev)
436 {
437     APBState *s;
438     int pci_mem_data, apb_config, pci_ioport, pci_config;
439     unsigned int i;
440
441     s = FROM_SYSBUS(APBState, dev);
442     for (i = 0; i < 8; i++) {
443         s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
444     }
445     for (i = 0; i < 32; i++) {
446         sysbus_init_irq(dev, &s->pci_irqs[i]);
447     }
448
449     /* apb_config */
450     apb_config = cpu_register_io_memory(apb_config_read,
451                                         apb_config_write, s);
452     sysbus_init_mmio(dev, 0x10000ULL, apb_config);
453     /* pci_ioport */
454     pci_ioport = cpu_register_io_memory(pci_apb_ioread,
455                                           pci_apb_iowrite, s);
456     sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
457     /* pci_config */
458     pci_config = cpu_register_io_memory(apb_pci_config_reads,
459                                         apb_pci_config_writes, s);
460     sysbus_init_mmio(dev, 0x1000000ULL, pci_config);
461     /* mem_data */
462     pci_mem_data = pci_host_data_register_mmio(&s->host_state);
463     sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
464     return 0;
465 }
466
467 static int pbm_pci_host_init(PCIDevice *d)
468 {
469     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
470     pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
471     pci_set_word(d->config + PCI_COMMAND,
472                  PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
473     pci_set_word(d->config + PCI_STATUS,
474                  PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
475                  PCI_STATUS_DEVSEL_MEDIUM);
476     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
477     pci_set_byte(d->config + PCI_HEADER_TYPE,
478                  PCI_HEADER_TYPE_NORMAL);
479     return 0;
480 }
481
482 static PCIDeviceInfo pbm_pci_host_info = {
483     .qdev.name = "pbm",
484     .qdev.size = sizeof(PCIDevice),
485     .init      = pbm_pci_host_init,
486     .header_type  = PCI_HEADER_TYPE_BRIDGE,
487 };
488
489 static SysBusDeviceInfo pbm_host_info = {
490     .qdev.name = "pbm",
491     .qdev.size = sizeof(APBState),
492     .qdev.reset = pci_pbm_reset,
493     .init = pci_pbm_init_device,
494 };
495 static void pbm_register_devices(void)
496 {
497     sysbus_register_withprop(&pbm_host_info);
498     pci_qdev_register(&pbm_pci_host_info);
499 }
500
501 device_init(pbm_register_devices)
This page took 0.05123 seconds and 4 git commands to generate.