]> git.proxmox.com Git - mirror_qemu.git/blame - hw/pci-host/apb.c
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
[mirror_qemu.git] / hw / pci-host / apb.c
CommitLineData
502a5395
PB
1/*
2 * QEMU Ultrasparc APB PCI host
3 *
4 * Copyright (c) 2006 Fabrice Bellard
9625036d 5 * Copyright (c) 2012,2013 Artyom Tarasenko
5fafdf24 6 *
502a5395
PB
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
80b3ada7 25
a94fd955 26/* XXX This file and most of its contents are somewhat misnamed. The
80b3ada7
PB
27 Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is
28 the secondary PCI bridge. */
29
83c9f4ca
PB
30#include "hw/sysbus.h"
31#include "hw/pci/pci.h"
32#include "hw/pci/pci_host.h"
33#include "hw/pci/pci_bridge.h"
34#include "hw/pci/pci_bus.h"
0d09e41a 35#include "hw/pci-host/apb.h"
9c17d615 36#include "sysemu/sysemu.h"
022c62cb 37#include "exec/address-spaces.h"
a94fd955
BS
38
39/* debug APB */
40//#define DEBUG_APB
41
42#ifdef DEBUG_APB
001faf32
BS
43#define APB_DPRINTF(fmt, ...) \
44do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
a94fd955 45#else
001faf32 46#define APB_DPRINTF(fmt, ...)
a94fd955
BS
47#endif
48
f38b1612
MCA
49/* debug IOMMU */
50//#define DEBUG_IOMMU
51
52#ifdef DEBUG_IOMMU
53#define IOMMU_DPRINTF(fmt, ...) \
54do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
55#else
56#define IOMMU_DPRINTF(fmt, ...)
57#endif
58
930f3fe1
BS
59/*
60 * Chipset docs:
61 * PBM: "UltraSPARC IIi User's Manual",
62 * http://www.sun.com/processors/manuals/805-0087.pdf
63 *
64 * APB: "Advanced PCI Bridge (APB) User's Manual",
65 * http://www.sun.com/processors/manuals/805-1251.pdf
66 */
67
95819af0
BS
68#define PBM_PCI_IMR_MASK 0x7fffffff
69#define PBM_PCI_IMR_ENABLED 0x80000000
70
af23906d
PM
71#define POR (1U << 31)
72#define SOFT_POR (1U << 30)
73#define SOFT_XIR (1U << 29)
74#define BTN_POR (1U << 28)
75#define BTN_XIR (1U << 27)
95819af0
BS
76#define RESET_MASK 0xf8000000
77#define RESET_WCMASK 0x98000000
78#define RESET_WMASK 0x60000000
79
852e82f3 80#define MAX_IVEC 0x40
9625036d 81#define NO_IRQ_REQUEST (MAX_IVEC + 1)
361dea40 82
ae74bbe7
MCA
83#define IOMMU_PAGE_SIZE_8K (1ULL << 13)
84#define IOMMU_PAGE_MASK_8K (~(IOMMU_PAGE_SIZE_8K - 1))
85#define IOMMU_PAGE_SIZE_64K (1ULL << 16)
86#define IOMMU_PAGE_MASK_64K (~(IOMMU_PAGE_SIZE_64K - 1))
87
f38b1612 88#define IOMMU_NREGS 3
ae74bbe7 89
f38b1612 90#define IOMMU_CTRL 0x0
ae74bbe7
MCA
91#define IOMMU_CTRL_TBW_SIZE (1ULL << 2)
92#define IOMMU_CTRL_MMU_EN (1ULL)
93
94#define IOMMU_CTRL_TSB_SHIFT 16
95
f38b1612 96#define IOMMU_BASE 0x8
b87b0644 97#define IOMMU_FLUSH 0x10
f38b1612 98
ae74bbe7
MCA
99#define IOMMU_TTE_DATA_V (1ULL << 63)
100#define IOMMU_TTE_DATA_SIZE (1ULL << 61)
101#define IOMMU_TTE_DATA_W (1ULL << 1)
102
d1180c1e
SW
103#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000ULL
104#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000ULL
ae74bbe7
MCA
105
106#define IOMMU_TSB_8K_OFFSET_MASK_8M 0x00000000007fe000ULL
107#define IOMMU_TSB_8K_OFFSET_MASK_16M 0x0000000000ffe000ULL
108#define IOMMU_TSB_8K_OFFSET_MASK_32M 0x0000000001ffe000ULL
109#define IOMMU_TSB_8K_OFFSET_MASK_64M 0x0000000003ffe000ULL
110#define IOMMU_TSB_8K_OFFSET_MASK_128M 0x0000000007ffe000ULL
111#define IOMMU_TSB_8K_OFFSET_MASK_256M 0x000000000fffe000ULL
112#define IOMMU_TSB_8K_OFFSET_MASK_512M 0x000000001fffe000ULL
113#define IOMMU_TSB_8K_OFFSET_MASK_1G 0x000000003fffe000ULL
114
115#define IOMMU_TSB_64K_OFFSET_MASK_64M 0x0000000003ff0000ULL
116#define IOMMU_TSB_64K_OFFSET_MASK_128M 0x0000000007ff0000ULL
117#define IOMMU_TSB_64K_OFFSET_MASK_256M 0x000000000fff0000ULL
118#define IOMMU_TSB_64K_OFFSET_MASK_512M 0x000000001fff0000ULL
119#define IOMMU_TSB_64K_OFFSET_MASK_1G 0x000000003fff0000ULL
120#define IOMMU_TSB_64K_OFFSET_MASK_2G 0x000000007fff0000ULL
121
ea9a6606 122typedef struct IOMMUState {
ae74bbe7
MCA
123 AddressSpace iommu_as;
124 MemoryRegion iommu;
125
f38b1612 126 uint64_t regs[IOMMU_NREGS];
ea9a6606
MCA
127} IOMMUState;
128
2b8fbcd8
PB
129#define TYPE_APB "pbm"
130
131#define APB_DEVICE(obj) \
132 OBJECT_CHECK(APBState, (obj), TYPE_APB)
133
72f44c8c 134typedef struct APBState {
2b8fbcd8
PB
135 PCIHostState parent_obj;
136
3812ed0b
AK
137 MemoryRegion apb_config;
138 MemoryRegion pci_config;
f69539b1 139 MemoryRegion pci_mmio;
3812ed0b 140 MemoryRegion pci_ioport;
9625036d 141 uint64_t pci_irq_in;
ea9a6606 142 IOMMUState iommu;
95819af0
BS
143 uint32_t pci_control[16];
144 uint32_t pci_irq_map[8];
145 uint32_t obio_irq_map[32];
361dea40
BS
146 qemu_irq *pbm_irqs;
147 qemu_irq *ivec_irqs;
9625036d 148 unsigned int irq_request;
95819af0 149 uint32_t reset_control;
9c0afd0e 150 unsigned int nr_resets;
72f44c8c 151} APBState;
502a5395 152
9625036d
AT
153static inline void pbm_set_request(APBState *s, unsigned int irq_num)
154{
155 APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
156
157 s->irq_request = irq_num;
158 qemu_set_irq(s->ivec_irqs[irq_num], 1);
159}
160
161static inline void pbm_check_irqs(APBState *s)
162{
163
164 unsigned int i;
165
166 /* Previous request is not acknowledged, resubmit */
167 if (s->irq_request != NO_IRQ_REQUEST) {
168 pbm_set_request(s, s->irq_request);
169 return;
170 }
171 /* no request pending */
172 if (s->pci_irq_in == 0ULL) {
173 return;
174 }
175 for (i = 0; i < 32; i++) {
176 if (s->pci_irq_in & (1ULL << i)) {
177 if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) {
178 pbm_set_request(s, i);
179 return;
180 }
181 }
182 }
183 for (i = 32; i < 64; i++) {
184 if (s->pci_irq_in & (1ULL << i)) {
185 if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) {
186 pbm_set_request(s, i);
187 break;
188 }
189 }
190 }
191}
192
193static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
194{
195 APB_DPRINTF("%s: clear request irq %d\n", __func__, irq_num);
196 qemu_set_irq(s->ivec_irqs[irq_num], 0);
197 s->irq_request = NO_IRQ_REQUEST;
198}
94d19914 199
ae74bbe7
MCA
200static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
201{
202 IOMMUState *is = opaque;
203
204 return &is->iommu_as;
205}
206
8d7b8cb9
LT
207static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
208 bool is_write)
ae74bbe7
MCA
209{
210 IOMMUState *is = container_of(iommu, IOMMUState, iommu);
211 hwaddr baseaddr, offset;
212 uint64_t tte;
213 uint32_t tsbsize;
214 IOMMUTLBEntry ret = {
215 .target_as = &address_space_memory,
216 .iova = 0,
217 .translated_addr = 0,
218 .addr_mask = ~(hwaddr)0,
219 .perm = IOMMU_NONE,
220 };
221
222 if (!(is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_MMU_EN)) {
223 /* IOMMU disabled, passthrough using standard 8K page */
224 ret.iova = addr & IOMMU_PAGE_MASK_8K;
225 ret.translated_addr = addr;
226 ret.addr_mask = IOMMU_PAGE_MASK_8K;
227 ret.perm = IOMMU_RW;
228
229 return ret;
230 }
231
232 baseaddr = is->regs[IOMMU_BASE >> 3];
233 tsbsize = (is->regs[IOMMU_CTRL >> 3] >> IOMMU_CTRL_TSB_SHIFT) & 0x7;
234
235 if (is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_TBW_SIZE) {
236 /* 64K */
237 switch (tsbsize) {
238 case 0:
239 offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_64M) >> 13;
240 break;
241 case 1:
242 offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_128M) >> 13;
243 break;
244 case 2:
245 offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_256M) >> 13;
246 break;
247 case 3:
248 offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_512M) >> 13;
249 break;
250 case 4:
251 offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_1G) >> 13;
252 break;
253 case 5:
254 offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_2G) >> 13;
255 break;
256 default:
257 /* Not implemented, error */
258 return ret;
259 }
260 } else {
261 /* 8K */
262 switch (tsbsize) {
263 case 0:
264 offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_8M) >> 10;
265 break;
266 case 1:
267 offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_16M) >> 10;
268 break;
269 case 2:
270 offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_32M) >> 10;
271 break;
272 case 3:
273 offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_64M) >> 10;
274 break;
275 case 4:
276 offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_128M) >> 10;
277 break;
278 case 5:
279 offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_256M) >> 10;
280 break;
281 case 6:
282 offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_512M) >> 10;
283 break;
284 case 7:
285 offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_1G) >> 10;
286 break;
287 }
288 }
289
290 tte = ldq_be_phys(&address_space_memory, baseaddr + offset);
291
292 if (!(tte & IOMMU_TTE_DATA_V)) {
293 /* Invalid mapping */
294 return ret;
295 }
296
297 if (tte & IOMMU_TTE_DATA_W) {
298 /* Writeable */
299 ret.perm = IOMMU_RW;
300 } else {
301 ret.perm = IOMMU_RO;
302 }
303
304 /* Extract phys */
305 if (tte & IOMMU_TTE_DATA_SIZE) {
306 /* 64K */
307 ret.iova = addr & IOMMU_PAGE_MASK_64K;
308 ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_64K;
309 ret.addr_mask = (IOMMU_PAGE_SIZE_64K - 1);
310 } else {
311 /* 8K */
312 ret.iova = addr & IOMMU_PAGE_MASK_8K;
313 ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_8K;
314 ret.addr_mask = (IOMMU_PAGE_SIZE_8K - 1);
315 }
316
317 return ret;
318}
319
320static MemoryRegionIOMMUOps pbm_iommu_ops = {
321 .translate = pbm_translate_iommu,
322};
323
f38b1612
MCA
324static void iommu_config_write(void *opaque, hwaddr addr,
325 uint64_t val, unsigned size)
326{
327 IOMMUState *is = opaque;
328
329 IOMMU_DPRINTF("IOMMU config write: 0x%" HWADDR_PRIx " val: %" PRIx64
330 " size: %d\n", addr, val, size);
331
332 switch (addr) {
333 case IOMMU_CTRL:
334 if (size == 4) {
335 is->regs[IOMMU_CTRL >> 3] &= 0xffffffffULL;
336 is->regs[IOMMU_CTRL >> 3] |= val << 32;
337 } else {
68716da7 338 is->regs[IOMMU_CTRL >> 3] = val;
f38b1612
MCA
339 }
340 break;
341 case IOMMU_CTRL + 0x4:
342 is->regs[IOMMU_CTRL >> 3] &= 0xffffffff00000000ULL;
343 is->regs[IOMMU_CTRL >> 3] |= val & 0xffffffffULL;
344 break;
345 case IOMMU_BASE:
346 if (size == 4) {
347 is->regs[IOMMU_BASE >> 3] &= 0xffffffffULL;
348 is->regs[IOMMU_BASE >> 3] |= val << 32;
349 } else {
68716da7 350 is->regs[IOMMU_BASE >> 3] = val;
f38b1612
MCA
351 }
352 break;
353 case IOMMU_BASE + 0x4:
354 is->regs[IOMMU_BASE >> 3] &= 0xffffffff00000000ULL;
355 is->regs[IOMMU_BASE >> 3] |= val & 0xffffffffULL;
356 break;
b87b0644
MCA
357 case IOMMU_FLUSH:
358 case IOMMU_FLUSH + 0x4:
359 break;
f38b1612
MCA
360 default:
361 qemu_log_mask(LOG_UNIMP,
362 "apb iommu: Unimplemented register write "
363 "reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n",
364 addr, size, val);
365 break;
366 }
367}
368
369static uint64_t iommu_config_read(void *opaque, hwaddr addr, unsigned size)
370{
371 IOMMUState *is = opaque;
372 uint64_t val;
373
374 switch (addr) {
375 case IOMMU_CTRL:
376 if (size == 4) {
377 val = is->regs[IOMMU_CTRL >> 3] >> 32;
378 } else {
379 val = is->regs[IOMMU_CTRL >> 3];
380 }
381 break;
382 case IOMMU_CTRL + 0x4:
383 val = is->regs[IOMMU_CTRL >> 3] & 0xffffffffULL;
384 break;
385 case IOMMU_BASE:
386 if (size == 4) {
387 val = is->regs[IOMMU_BASE >> 3] >> 32;
388 } else {
389 val = is->regs[IOMMU_BASE >> 3];
390 }
391 break;
392 case IOMMU_BASE + 0x4:
393 val = is->regs[IOMMU_BASE >> 3] & 0xffffffffULL;
394 break;
b87b0644
MCA
395 case IOMMU_FLUSH:
396 case IOMMU_FLUSH + 0x4:
397 val = 0;
398 break;
f38b1612
MCA
399 default:
400 qemu_log_mask(LOG_UNIMP,
401 "apb iommu: Unimplemented register read "
402 "reg 0x%" HWADDR_PRIx " size 0x%x\n",
403 addr, size);
404 val = 0;
405 break;
406 }
407
408 IOMMU_DPRINTF("IOMMU config read: 0x%" HWADDR_PRIx " val: %" PRIx64
409 " size: %d\n", addr, val, size);
410
411 return val;
412}
413
a8170e5e 414static void apb_config_writel (void *opaque, hwaddr addr,
3812ed0b 415 uint64_t val, unsigned size)
502a5395 416{
95819af0 417 APBState *s = opaque;
ea9a6606 418 IOMMUState *is = &s->iommu;
95819af0 419
c0907c9e 420 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
95819af0
BS
421
422 switch (addr & 0xffff) {
423 case 0x30 ... 0x4f: /* DMA error registers */
424 /* XXX: not implemented yet */
425 break;
fd7fbc8f 426 case 0x200 ... 0x217: /* IOMMU */
b87b0644 427 iommu_config_write(is, (addr & 0x1f), val, size);
95819af0 428 break;
95819af0
BS
429 case 0xc00 ... 0xc3f: /* PCI interrupt control */
430 if (addr & 4) {
9625036d
AT
431 unsigned int ino = (addr & 0x3f) >> 3;
432 s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK;
433 s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
434 if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) {
435 pbm_clear_request(s, ino);
436 }
437 pbm_check_irqs(s);
95819af0
BS
438 }
439 break;
361dea40
BS
440 case 0x1000 ... 0x1080: /* OBIO interrupt control */
441 if (addr & 4) {
9625036d
AT
442 unsigned int ino = ((addr & 0xff) >> 3);
443 s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK;
444 s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
445 if ((s->irq_request == (ino | 0x20))
446 && !(val & ~PBM_PCI_IMR_MASK)) {
447 pbm_clear_request(s, ino | 0x20);
448 }
449 pbm_check_irqs(s);
361dea40
BS
450 }
451 break;
9625036d 452 case 0x1400 ... 0x14ff: /* PCI interrupt clear */
94d19914 453 if (addr & 4) {
9625036d
AT
454 unsigned int ino = (addr & 0xff) >> 5;
455 if ((s->irq_request / 4) == ino) {
456 pbm_clear_request(s, s->irq_request);
457 pbm_check_irqs(s);
458 }
94d19914
AT
459 }
460 break;
461 case 0x1800 ... 0x1860: /* OBIO interrupt clear */
462 if (addr & 4) {
9625036d
AT
463 unsigned int ino = ((addr & 0xff) >> 3) | 0x20;
464 if (s->irq_request == ino) {
465 pbm_clear_request(s, ino);
466 pbm_check_irqs(s);
467 }
94d19914
AT
468 }
469 break;
95819af0
BS
470 case 0x2000 ... 0x202f: /* PCI control */
471 s->pci_control[(addr & 0x3f) >> 2] = val;
472 break;
473 case 0xf020 ... 0xf027: /* Reset control */
474 if (addr & 4) {
475 val &= RESET_MASK;
476 s->reset_control &= ~(val & RESET_WCMASK);
477 s->reset_control |= val & RESET_WMASK;
478 if (val & SOFT_POR) {
9c0afd0e 479 s->nr_resets = 0;
95819af0
BS
480 qemu_system_reset_request();
481 } else if (val & SOFT_XIR) {
482 qemu_system_reset_request();
483 }
484 }
485 break;
486 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
487 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
488 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
489 case 0xf000 ... 0xf01f: /* FFB config, memory control */
490 /* we don't care */
502a5395 491 default:
f930d07e 492 break;
502a5395
PB
493 }
494}
495
3812ed0b 496static uint64_t apb_config_readl (void *opaque,
a8170e5e 497 hwaddr addr, unsigned size)
502a5395 498{
95819af0 499 APBState *s = opaque;
ea9a6606 500 IOMMUState *is = &s->iommu;
502a5395
PB
501 uint32_t val;
502
95819af0
BS
503 switch (addr & 0xffff) {
504 case 0x30 ... 0x4f: /* DMA error registers */
505 val = 0;
506 /* XXX: not implemented yet */
507 break;
fd7fbc8f 508 case 0x200 ... 0x217: /* IOMMU */
b87b0644 509 val = iommu_config_read(is, (addr & 0x1f), size);
95819af0 510 break;
95819af0
BS
511 case 0xc00 ... 0xc3f: /* PCI interrupt control */
512 if (addr & 4) {
513 val = s->pci_irq_map[(addr & 0x3f) >> 3];
514 } else {
515 val = 0;
516 }
517 break;
361dea40
BS
518 case 0x1000 ... 0x1080: /* OBIO interrupt control */
519 if (addr & 4) {
520 val = s->obio_irq_map[(addr & 0xff) >> 3];
521 } else {
522 val = 0;
523 }
524 break;
95819af0
BS
525 case 0x2000 ... 0x202f: /* PCI control */
526 val = s->pci_control[(addr & 0x3f) >> 2];
527 break;
528 case 0xf020 ... 0xf027: /* Reset control */
529 if (addr & 4) {
530 val = s->reset_control;
531 } else {
532 val = 0;
533 }
534 break;
535 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
536 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
537 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
538 case 0xf000 ... 0xf01f: /* FFB config, memory control */
539 /* we don't care */
502a5395 540 default:
f930d07e
BS
541 val = 0;
542 break;
502a5395 543 }
c0907c9e 544 APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, val);
95819af0 545
502a5395
PB
546 return val;
547}
548
3812ed0b
AK
549static const MemoryRegionOps apb_config_ops = {
550 .read = apb_config_readl,
551 .write = apb_config_writel,
552 .endianness = DEVICE_NATIVE_ENDIAN,
502a5395
PB
553};
554
a8170e5e 555static void apb_pci_config_write(void *opaque, hwaddr addr,
3812ed0b 556 uint64_t val, unsigned size)
5a5d4a76 557{
3812ed0b 558 APBState *s = opaque;
2b8fbcd8 559 PCIHostState *phb = PCI_HOST_BRIDGE(s);
63e6f31d
MT
560
561 val = qemu_bswap_len(val, size);
c0907c9e 562 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
2b8fbcd8 563 pci_data_write(phb->bus, addr, val, size);
5a5d4a76
BS
564}
565
a8170e5e 566static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
3812ed0b 567 unsigned size)
5a5d4a76
BS
568{
569 uint32_t ret;
3812ed0b 570 APBState *s = opaque;
2b8fbcd8 571 PCIHostState *phb = PCI_HOST_BRIDGE(s);
5a5d4a76 572
2b8fbcd8 573 ret = pci_data_read(phb->bus, addr, size);
63e6f31d 574 ret = qemu_bswap_len(ret, size);
c0907c9e 575 APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
5a5d4a76
BS
576 return ret;
577}
578
80b3ada7 579/* The APB host has an IRQ line for each IRQ line of each slot. */
d2b59317 580static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
502a5395 581{
80b3ada7
PB
582 return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
583}
584
585static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
586{
587 int bus_offset;
588 if (pci_dev->devfn & 1)
589 bus_offset = 16;
590 else
591 bus_offset = 0;
903ce9fe 592 return (bus_offset + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
d2b59317
PB
593}
594
5d4e84c8 595static void pci_apb_set_irq(void *opaque, int irq_num, int level)
d2b59317 596{
95819af0 597 APBState *s = opaque;
5d4e84c8 598
9625036d 599 APB_DPRINTF("%s: set irq_in %d level %d\n", __func__, irq_num, level);
80b3ada7 600 /* PCI IRQ map onto the first 32 INO. */
95819af0 601 if (irq_num < 32) {
9625036d
AT
602 if (level) {
603 s->pci_irq_in |= 1ULL << irq_num;
604 if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
605 pbm_set_request(s, irq_num);
606 }
361dea40 607 } else {
9625036d 608 s->pci_irq_in &= ~(1ULL << irq_num);
361dea40
BS
609 }
610 } else {
9625036d
AT
611 /* OBIO IRQ map onto the next 32 INO. */
612 if (level) {
361dea40 613 APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
9625036d
AT
614 s->pci_irq_in |= 1ULL << irq_num;
615 if ((s->irq_request == NO_IRQ_REQUEST)
616 && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) {
617 pbm_set_request(s, irq_num);
618 }
95819af0 619 } else {
9625036d 620 s->pci_irq_in &= ~(1ULL << irq_num);
95819af0
BS
621 }
622 }
502a5395
PB
623}
624
68f79994 625static int apb_pci_bridge_initfn(PCIDevice *dev)
d6318738 626{
68f79994
IY
627 int rc;
628
60a0e443 629 rc = pci_bridge_initfn(dev, TYPE_PCI_BUS);
68f79994
IY
630 if (rc < 0) {
631 return rc;
632 }
633
d6318738
MT
634 /*
635 * command register:
636 * According to PCI bridge spec, after reset
637 * bus master bit is off
638 * memory space enable bit is off
639 * According to manual (805-1251.pdf).
640 * the reset value should be zero unless the boot pin is tied high
641 * (which is true) and thus it should be PCI_COMMAND_MEMORY.
642 */
643 pci_set_word(dev->config + PCI_COMMAND,
9fe52c7f
BS
644 PCI_COMMAND_MEMORY);
645 pci_set_word(dev->config + PCI_STATUS,
646 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
647 PCI_STATUS_DEVSEL_MEDIUM);
68f79994 648 return 0;
d6318738
MT
649}
650
a8170e5e
AK
651PCIBus *pci_apb_init(hwaddr special_base,
652 hwaddr mem_base,
361dea40
BS
653 qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
654 qemu_irq **pbm_irqs)
502a5395 655{
72f44c8c
BS
656 DeviceState *dev;
657 SysBusDevice *s;
2b8fbcd8 658 PCIHostState *phb;
72f44c8c 659 APBState *d;
ea9a6606 660 IOMMUState *is;
68f79994
IY
661 PCIDevice *pci_dev;
662 PCIBridge *br;
502a5395 663
80b3ada7 664 /* Ultrasparc PBM main bus */
2b8fbcd8 665 dev = qdev_create(NULL, TYPE_APB);
e23a1b33 666 qdev_init_nofail(dev);
1356b98d 667 s = SYS_BUS_DEVICE(dev);
72f44c8c 668 /* apb_config */
bae7b517 669 sysbus_mmio_map(s, 0, special_base);
d63baf92
IK
670 /* PCI configuration space */
671 sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
72f44c8c 672 /* pci_ioport */
d63baf92 673 sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
2b8fbcd8 674 d = APB_DEVICE(dev);
d63baf92 675
40c5dce9 676 memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL);
f69539b1
BS
677 memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
678
2b8fbcd8
PB
679 phb = PCI_HOST_BRIDGE(dev);
680 phb->bus = pci_register_bus(DEVICE(phb), "pci",
681 pci_apb_set_irq, pci_pbm_map_irq, d,
682 &d->pci_mmio,
683 get_system_io(),
684 0, 32, TYPE_PCI_BUS);
f6b6f1bc 685
361dea40
BS
686 *pbm_irqs = d->pbm_irqs;
687 d->ivec_irqs = ivec_irqs;
95819af0 688
2b8fbcd8 689 pci_create_simple(phb->bus, 0, "pbm-pci");
d63baf92 690
ea9a6606
MCA
691 /* APB IOMMU */
692 is = &d->iommu;
693 memset(is, 0, sizeof(IOMMUState));
694
ae74bbe7
MCA
695 memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
696 "iommu-apb", UINT64_MAX);
697 address_space_init(&is->iommu_as, &is->iommu, "pbm-as");
698 pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
699
72f44c8c 700 /* APB secondary busses */
2b8fbcd8 701 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
68f79994 702 "pbm-bridge");
f055e96b 703 br = PCI_BRIDGE(pci_dev);
68f79994
IY
704 pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
705 pci_apb_map_irq);
706 qdev_init_nofail(&pci_dev->qdev);
707 *bus2 = pci_bridge_get_sec_bus(br);
708
2b8fbcd8 709 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
68f79994 710 "pbm-bridge");
f055e96b 711 br = PCI_BRIDGE(pci_dev);
68f79994
IY
712 pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
713 pci_apb_map_irq);
714 qdev_init_nofail(&pci_dev->qdev);
715 *bus3 = pci_bridge_get_sec_bus(br);
502a5395 716
2b8fbcd8 717 return phb->bus;
72f44c8c
BS
718}
719
95819af0 720static void pci_pbm_reset(DeviceState *d)
72f44c8c 721{
95819af0 722 unsigned int i;
2b8fbcd8 723 APBState *s = APB_DEVICE(d);
72f44c8c 724
95819af0
BS
725 for (i = 0; i < 8; i++) {
726 s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
727 }
d1d80055
AT
728 for (i = 0; i < 32; i++) {
729 s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
730 }
95819af0 731
9625036d
AT
732 s->irq_request = NO_IRQ_REQUEST;
733 s->pci_irq_in = 0ULL;
734
9c0afd0e 735 if (s->nr_resets++ == 0) {
95819af0
BS
736 /* Power on reset */
737 s->reset_control = POR;
738 }
739}
740
3812ed0b
AK
741static const MemoryRegionOps pci_config_ops = {
742 .read = apb_pci_config_read,
743 .write = apb_pci_config_write,
744 .endianness = DEVICE_NATIVE_ENDIAN,
745};
746
95819af0
BS
747static int pci_pbm_init_device(SysBusDevice *dev)
748{
72f44c8c 749 APBState *s;
95819af0 750 unsigned int i;
72f44c8c 751
2b8fbcd8 752 s = APB_DEVICE(dev);
95819af0
BS
753 for (i = 0; i < 8; i++) {
754 s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
755 }
d1d80055
AT
756 for (i = 0; i < 32; i++) {
757 s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
758 }
361dea40 759 s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
9625036d
AT
760 s->irq_request = NO_IRQ_REQUEST;
761 s->pci_irq_in = 0ULL;
95819af0 762
72f44c8c 763 /* apb_config */
40c5dce9
PB
764 memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s,
765 "apb-config", 0x10000);
d63baf92 766 /* at region 0 */
750ecd44 767 sysbus_init_mmio(dev, &s->apb_config);
d63baf92 768
40c5dce9
PB
769 memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s,
770 "apb-pci-config", 0x1000000);
d63baf92 771 /* at region 1 */
750ecd44 772 sysbus_init_mmio(dev, &s->pci_config);
d63baf92
IK
773
774 /* pci_ioport */
5519ad0c
PB
775 memory_region_init_alias(&s->pci_ioport, OBJECT(s), "apb-pci-ioport",
776 get_system_io(), 0, 0x10000);
d63baf92 777 /* at region 2 */
750ecd44 778 sysbus_init_mmio(dev, &s->pci_ioport);
d63baf92 779
81a322d4 780 return 0;
72f44c8c 781}
502a5395 782
81a322d4 783static int pbm_pci_host_init(PCIDevice *d)
72f44c8c 784{
9fe52c7f
BS
785 pci_set_word(d->config + PCI_COMMAND,
786 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
787 pci_set_word(d->config + PCI_STATUS,
788 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
789 PCI_STATUS_DEVSEL_MEDIUM);
81a322d4 790 return 0;
72f44c8c 791}
80b3ada7 792
40021f08
AL
793static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
794{
795 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
08c58f92 796 DeviceClass *dc = DEVICE_CLASS(klass);
40021f08
AL
797
798 k->init = pbm_pci_host_init;
799 k->vendor_id = PCI_VENDOR_ID_SUN;
800 k->device_id = PCI_DEVICE_ID_SUN_SABRE;
801 k->class_id = PCI_CLASS_BRIDGE_HOST;
08c58f92
MA
802 /*
803 * PCI-facing part of the host bridge, not usable without the
804 * host-facing part, which can't be device_add'ed, yet.
805 */
806 dc->cannot_instantiate_with_device_add_yet = true;
40021f08
AL
807}
808
8c43a6f0 809static const TypeInfo pbm_pci_host_info = {
39bffca2
AL
810 .name = "pbm-pci",
811 .parent = TYPE_PCI_DEVICE,
812 .instance_size = sizeof(PCIDevice),
813 .class_init = pbm_pci_host_class_init,
72f44c8c
BS
814};
815
999e12bb
AL
816static void pbm_host_class_init(ObjectClass *klass, void *data)
817{
39bffca2 818 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb
AL
819 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
820
821 k->init = pci_pbm_init_device;
125ee0ed 822 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
39bffca2 823 dc->reset = pci_pbm_reset;
999e12bb
AL
824}
825
8c43a6f0 826static const TypeInfo pbm_host_info = {
2b8fbcd8
PB
827 .name = TYPE_APB,
828 .parent = TYPE_PCI_HOST_BRIDGE,
39bffca2
AL
829 .instance_size = sizeof(APBState),
830 .class_init = pbm_host_class_init,
95819af0 831};
68f79994 832
40021f08
AL
833static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
834{
39bffca2 835 DeviceClass *dc = DEVICE_CLASS(klass);
40021f08
AL
836 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
837
838 k->init = apb_pci_bridge_initfn;
839 k->exit = pci_bridge_exitfn;
840 k->vendor_id = PCI_VENDOR_ID_SUN;
841 k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
842 k->revision = 0x11;
843 k->config_write = pci_bridge_write_config;
844 k->is_bridge = 1;
125ee0ed 845 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
39bffca2
AL
846 dc->reset = pci_bridge_reset;
847 dc->vmsd = &vmstate_pci_device;
40021f08
AL
848}
849
8c43a6f0 850static const TypeInfo pbm_pci_bridge_info = {
39bffca2 851 .name = "pbm-bridge",
f055e96b 852 .parent = TYPE_PCI_BRIDGE,
39bffca2 853 .class_init = pbm_pci_bridge_class_init,
68f79994
IY
854};
855
83f7d43a 856static void pbm_register_types(void)
72f44c8c 857{
39bffca2
AL
858 type_register_static(&pbm_host_info);
859 type_register_static(&pbm_pci_host_info);
860 type_register_static(&pbm_pci_bridge_info);
502a5395 861}
72f44c8c 862
83f7d43a 863type_init(pbm_register_types)