1
2
3
4
5
6
7
8
9
10
11#include "qemu/osdep.h"
12#include "qemu/units.h"
13#include "qapi/error.h"
14#include "qemu/log.h"
15#include "hw/irq.h"
16#include "hw/ppc/ppc4xx.h"
17#include "hw/qdev-properties.h"
18#include "hw/pci/pci.h"
19#include "sysemu/reset.h"
20#include "cpu.h"
21#include "ppc440.h"
22
23
24
25
26enum {
27 DCR_L2CACHE_BASE = 0x30,
28 DCR_L2CACHE_CFG = DCR_L2CACHE_BASE,
29 DCR_L2CACHE_CMD,
30 DCR_L2CACHE_ADDR,
31 DCR_L2CACHE_DATA,
32 DCR_L2CACHE_STAT,
33 DCR_L2CACHE_CVER,
34 DCR_L2CACHE_SNP0,
35 DCR_L2CACHE_SNP1,
36 DCR_L2CACHE_END = DCR_L2CACHE_SNP1,
37};
38
39
40enum {
41 DCR_ISRAM0_BASE = 0x20,
42 DCR_ISRAM0_SB0CR = DCR_ISRAM0_BASE,
43 DCR_ISRAM0_SB1CR,
44 DCR_ISRAM0_SB2CR,
45 DCR_ISRAM0_SB3CR,
46 DCR_ISRAM0_BEAR,
47 DCR_ISRAM0_BESR0,
48 DCR_ISRAM0_BESR1,
49 DCR_ISRAM0_PMEG,
50 DCR_ISRAM0_CID,
51 DCR_ISRAM0_REVID,
52 DCR_ISRAM0_DPC,
53 DCR_ISRAM0_END = DCR_ISRAM0_DPC
54};
55
56enum {
57 DCR_ISRAM1_BASE = 0xb0,
58 DCR_ISRAM1_SB0CR = DCR_ISRAM1_BASE,
59
60 DCR_ISRAM1_BEAR = DCR_ISRAM1_BASE + 0x04,
61 DCR_ISRAM1_BESR0,
62 DCR_ISRAM1_BESR1,
63 DCR_ISRAM1_PMEG,
64 DCR_ISRAM1_CID,
65 DCR_ISRAM1_REVID,
66 DCR_ISRAM1_DPC,
67 DCR_ISRAM1_END = DCR_ISRAM1_DPC
68};
69
70typedef struct ppc4xx_l2sram_t {
71 MemoryRegion bank[4];
72 uint32_t l2cache[8];
73 uint32_t isram0[11];
74} ppc4xx_l2sram_t;
75
76#ifdef MAP_L2SRAM
77static void l2sram_update_mappings(ppc4xx_l2sram_t *l2sram,
78 uint32_t isarc, uint32_t isacntl,
79 uint32_t dsarc, uint32_t dsacntl)
80{
81 if (l2sram->isarc != isarc ||
82 (l2sram->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
83 if (l2sram->isacntl & 0x80000000) {
84
85 memory_region_del_subregion(get_system_memory(),
86 &l2sram->isarc_ram);
87 }
88 if (isacntl & 0x80000000) {
89
90 memory_region_add_subregion(get_system_memory(), isarc,
91 &l2sram->isarc_ram);
92 }
93 }
94 if (l2sram->dsarc != dsarc ||
95 (l2sram->dsacntl & 0x80000000) != (dsacntl & 0x80000000)) {
96 if (l2sram->dsacntl & 0x80000000) {
97
98 if (!(isacntl & 0x80000000) || l2sram->dsarc != isarc) {
99
100 memory_region_del_subregion(get_system_memory(),
101 &l2sram->dsarc_ram);
102 }
103 }
104 if (dsacntl & 0x80000000) {
105
106 if (!(isacntl & 0x80000000) || dsarc != isarc) {
107
108 memory_region_add_subregion(get_system_memory(), dsarc,
109 &l2sram->dsarc_ram);
110 }
111 }
112 }
113}
114#endif
115
116static uint32_t dcr_read_l2sram(void *opaque, int dcrn)
117{
118 ppc4xx_l2sram_t *l2sram = opaque;
119 uint32_t ret = 0;
120
121 switch (dcrn) {
122 case DCR_L2CACHE_CFG:
123 case DCR_L2CACHE_CMD:
124 case DCR_L2CACHE_ADDR:
125 case DCR_L2CACHE_DATA:
126 case DCR_L2CACHE_STAT:
127 case DCR_L2CACHE_CVER:
128 case DCR_L2CACHE_SNP0:
129 case DCR_L2CACHE_SNP1:
130 ret = l2sram->l2cache[dcrn - DCR_L2CACHE_BASE];
131 break;
132
133 case DCR_ISRAM0_SB0CR:
134 case DCR_ISRAM0_SB1CR:
135 case DCR_ISRAM0_SB2CR:
136 case DCR_ISRAM0_SB3CR:
137 case DCR_ISRAM0_BEAR:
138 case DCR_ISRAM0_BESR0:
139 case DCR_ISRAM0_BESR1:
140 case DCR_ISRAM0_PMEG:
141 case DCR_ISRAM0_CID:
142 case DCR_ISRAM0_REVID:
143 case DCR_ISRAM0_DPC:
144 ret = l2sram->isram0[dcrn - DCR_ISRAM0_BASE];
145 break;
146
147 default:
148 break;
149 }
150
151 return ret;
152}
153
154static void dcr_write_l2sram(void *opaque, int dcrn, uint32_t val)
155{
156
157
158
159 switch (dcrn) {
160 case DCR_L2CACHE_CFG:
161 case DCR_L2CACHE_CMD:
162 case DCR_L2CACHE_ADDR:
163 case DCR_L2CACHE_DATA:
164 case DCR_L2CACHE_STAT:
165 case DCR_L2CACHE_CVER:
166 case DCR_L2CACHE_SNP0:
167 case DCR_L2CACHE_SNP1:
168
169 break;
170
171 case DCR_ISRAM0_SB0CR:
172 case DCR_ISRAM0_SB1CR:
173 case DCR_ISRAM0_SB2CR:
174 case DCR_ISRAM0_SB3CR:
175 case DCR_ISRAM0_BEAR:
176 case DCR_ISRAM0_BESR0:
177 case DCR_ISRAM0_BESR1:
178 case DCR_ISRAM0_PMEG:
179 case DCR_ISRAM0_CID:
180 case DCR_ISRAM0_REVID:
181 case DCR_ISRAM0_DPC:
182
183 break;
184
185 case DCR_ISRAM1_SB0CR:
186 case DCR_ISRAM1_BEAR:
187 case DCR_ISRAM1_BESR0:
188 case DCR_ISRAM1_BESR1:
189 case DCR_ISRAM1_PMEG:
190 case DCR_ISRAM1_CID:
191 case DCR_ISRAM1_REVID:
192 case DCR_ISRAM1_DPC:
193
194 break;
195 }
196
197}
198
199static void l2sram_reset(void *opaque)
200{
201 ppc4xx_l2sram_t *l2sram = opaque;
202
203 memset(l2sram->l2cache, 0, sizeof(l2sram->l2cache));
204 l2sram->l2cache[DCR_L2CACHE_STAT - DCR_L2CACHE_BASE] = 0x80000000;
205 memset(l2sram->isram0, 0, sizeof(l2sram->isram0));
206
207}
208
209void ppc4xx_l2sram_init(CPUPPCState *env)
210{
211 ppc4xx_l2sram_t *l2sram;
212
213 l2sram = g_malloc0(sizeof(*l2sram));
214
215 memory_region_init_ram(&l2sram->bank[0], NULL, "ppc4xx.l2sram_bank0",
216 64 * KiB, &error_abort);
217 memory_region_init_ram(&l2sram->bank[1], NULL, "ppc4xx.l2sram_bank1",
218 64 * KiB, &error_abort);
219 memory_region_init_ram(&l2sram->bank[2], NULL, "ppc4xx.l2sram_bank2",
220 64 * KiB, &error_abort);
221 memory_region_init_ram(&l2sram->bank[3], NULL, "ppc4xx.l2sram_bank3",
222 64 * KiB, &error_abort);
223 qemu_register_reset(&l2sram_reset, l2sram);
224 ppc_dcr_register(env, DCR_L2CACHE_CFG,
225 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
226 ppc_dcr_register(env, DCR_L2CACHE_CMD,
227 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
228 ppc_dcr_register(env, DCR_L2CACHE_ADDR,
229 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
230 ppc_dcr_register(env, DCR_L2CACHE_DATA,
231 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
232 ppc_dcr_register(env, DCR_L2CACHE_STAT,
233 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
234 ppc_dcr_register(env, DCR_L2CACHE_CVER,
235 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
236 ppc_dcr_register(env, DCR_L2CACHE_SNP0,
237 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
238 ppc_dcr_register(env, DCR_L2CACHE_SNP1,
239 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
240
241 ppc_dcr_register(env, DCR_ISRAM0_SB0CR,
242 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
243 ppc_dcr_register(env, DCR_ISRAM0_SB1CR,
244 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
245 ppc_dcr_register(env, DCR_ISRAM0_SB2CR,
246 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
247 ppc_dcr_register(env, DCR_ISRAM0_SB3CR,
248 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
249 ppc_dcr_register(env, DCR_ISRAM0_PMEG,
250 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
251 ppc_dcr_register(env, DCR_ISRAM0_DPC,
252 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
253
254 ppc_dcr_register(env, DCR_ISRAM1_SB0CR,
255 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
256 ppc_dcr_register(env, DCR_ISRAM1_PMEG,
257 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
258 ppc_dcr_register(env, DCR_ISRAM1_DPC,
259 l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
260}
261
262
263
264enum {
265 CPR0_CFGADDR = 0xC,
266 CPR0_CFGDATA = 0xD,
267
268 CPR0_PLLD = 0x060,
269 CPR0_PLBED = 0x080,
270 CPR0_OPBD = 0x0C0,
271 CPR0_PERD = 0x0E0,
272 CPR0_AHBD = 0x100,
273};
274
275typedef struct ppc4xx_cpr_t {
276 uint32_t addr;
277} ppc4xx_cpr_t;
278
279static uint32_t dcr_read_cpr(void *opaque, int dcrn)
280{
281 ppc4xx_cpr_t *cpr = opaque;
282 uint32_t ret = 0;
283
284 switch (dcrn) {
285 case CPR0_CFGADDR:
286 ret = cpr->addr;
287 break;
288 case CPR0_CFGDATA:
289 switch (cpr->addr) {
290 case CPR0_PLLD:
291 ret = (0xb5 << 24) | (1 << 16) | (9 << 8);
292 break;
293 case CPR0_PLBED:
294 ret = (5 << 24);
295 break;
296 case CPR0_OPBD:
297 ret = (2 << 24);
298 break;
299 case CPR0_PERD:
300 case CPR0_AHBD:
301 ret = (1 << 24);
302 break;
303 default:
304 break;
305 }
306 break;
307 default:
308 break;
309 }
310
311 return ret;
312}
313
314static void dcr_write_cpr(void *opaque, int dcrn, uint32_t val)
315{
316 ppc4xx_cpr_t *cpr = opaque;
317
318 switch (dcrn) {
319 case CPR0_CFGADDR:
320 cpr->addr = val;
321 break;
322 case CPR0_CFGDATA:
323 break;
324 default:
325 break;
326 }
327}
328
329static void ppc4xx_cpr_reset(void *opaque)
330{
331 ppc4xx_cpr_t *cpr = opaque;
332
333 cpr->addr = 0;
334}
335
336void ppc4xx_cpr_init(CPUPPCState *env)
337{
338 ppc4xx_cpr_t *cpr;
339
340 cpr = g_malloc0(sizeof(*cpr));
341 ppc_dcr_register(env, CPR0_CFGADDR, cpr, &dcr_read_cpr, &dcr_write_cpr);
342 ppc_dcr_register(env, CPR0_CFGDATA, cpr, &dcr_read_cpr, &dcr_write_cpr);
343 qemu_register_reset(ppc4xx_cpr_reset, cpr);
344}
345
346
347
348typedef struct ppc4xx_sdr_t ppc4xx_sdr_t;
349struct ppc4xx_sdr_t {
350 uint32_t addr;
351};
352
353enum {
354 SDR0_CFGADDR = 0x00e,
355 SDR0_CFGDATA,
356 SDR0_STRP0 = 0x020,
357 SDR0_STRP1,
358 SDR0_102 = 0x66,
359 SDR0_103,
360 SDR0_128 = 0x80,
361 SDR0_ECID3 = 0x083,
362 SDR0_DDR0 = 0x0e1,
363 SDR0_USB0 = 0x320,
364};
365
366enum {
367 PESDR0_LOOP = 0x303,
368 PESDR0_RCSSET,
369 PESDR0_RCSSTS,
370 PESDR0_RSTSTA = 0x310,
371 PESDR1_LOOP = 0x343,
372 PESDR1_RCSSET,
373 PESDR1_RCSSTS,
374 PESDR1_RSTSTA = 0x365,
375};
376
377static uint32_t dcr_read_sdr(void *opaque, int dcrn)
378{
379 ppc4xx_sdr_t *sdr = opaque;
380 uint32_t ret = 0;
381
382 switch (dcrn) {
383 case SDR0_CFGADDR:
384 ret = sdr->addr;
385 break;
386 case SDR0_CFGDATA:
387 switch (sdr->addr) {
388 case SDR0_STRP0:
389 ret = (0xb5 << 8) | (1 << 4) | 9;
390 break;
391 case SDR0_STRP1:
392 ret = (5 << 29) | (2 << 26) | (1 << 24);
393 break;
394 case SDR0_ECID3:
395 ret = 1 << 20;
396 break;
397 case SDR0_DDR0:
398 ret = SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1;
399 break;
400 case PESDR0_RCSSET:
401 case PESDR1_RCSSET:
402 ret = (1 << 24) | (1 << 16);
403 break;
404 case PESDR0_RCSSTS:
405 case PESDR1_RCSSTS:
406 ret = (1 << 16) | (1 << 12);
407 break;
408 case PESDR0_RSTSTA:
409 case PESDR1_RSTSTA:
410 ret = 1;
411 break;
412 case PESDR0_LOOP:
413 case PESDR1_LOOP:
414 ret = 1 << 12;
415 break;
416 default:
417 break;
418 }
419 break;
420 default:
421 break;
422 }
423
424 return ret;
425}
426
427static void dcr_write_sdr(void *opaque, int dcrn, uint32_t val)
428{
429 ppc4xx_sdr_t *sdr = opaque;
430
431 switch (dcrn) {
432 case SDR0_CFGADDR:
433 sdr->addr = val;
434 break;
435 case SDR0_CFGDATA:
436 switch (sdr->addr) {
437 case 0x00:
438 break;
439 default:
440 break;
441 }
442 break;
443 default:
444 break;
445 }
446}
447
448static void sdr_reset(void *opaque)
449{
450 ppc4xx_sdr_t *sdr = opaque;
451
452 sdr->addr = 0;
453}
454
455void ppc4xx_sdr_init(CPUPPCState *env)
456{
457 ppc4xx_sdr_t *sdr;
458
459 sdr = g_malloc0(sizeof(*sdr));
460 qemu_register_reset(&sdr_reset, sdr);
461 ppc_dcr_register(env, SDR0_CFGADDR,
462 sdr, &dcr_read_sdr, &dcr_write_sdr);
463 ppc_dcr_register(env, SDR0_CFGDATA,
464 sdr, &dcr_read_sdr, &dcr_write_sdr);
465 ppc_dcr_register(env, SDR0_102,
466 sdr, &dcr_read_sdr, &dcr_write_sdr);
467 ppc_dcr_register(env, SDR0_103,
468 sdr, &dcr_read_sdr, &dcr_write_sdr);
469 ppc_dcr_register(env, SDR0_128,
470 sdr, &dcr_read_sdr, &dcr_write_sdr);
471 ppc_dcr_register(env, SDR0_USB0,
472 sdr, &dcr_read_sdr, &dcr_write_sdr);
473}
474
475
476
477enum {
478 AHB_TOP = 0xA4,
479 AHB_BOT = 0xA5,
480};
481
482typedef struct ppc4xx_ahb_t {
483 uint32_t top;
484 uint32_t bot;
485} ppc4xx_ahb_t;
486
487static uint32_t dcr_read_ahb(void *opaque, int dcrn)
488{
489 ppc4xx_ahb_t *ahb = opaque;
490 uint32_t ret = 0;
491
492 switch (dcrn) {
493 case AHB_TOP:
494 ret = ahb->top;
495 break;
496 case AHB_BOT:
497 ret = ahb->bot;
498 break;
499 default:
500 break;
501 }
502
503 return ret;
504}
505
506static void dcr_write_ahb(void *opaque, int dcrn, uint32_t val)
507{
508 ppc4xx_ahb_t *ahb = opaque;
509
510 switch (dcrn) {
511 case AHB_TOP:
512 ahb->top = val;
513 break;
514 case AHB_BOT:
515 ahb->bot = val;
516 break;
517 }
518}
519
520static void ppc4xx_ahb_reset(void *opaque)
521{
522 ppc4xx_ahb_t *ahb = opaque;
523
524
525 ahb->top = 0;
526 ahb->bot = 0;
527}
528
529void ppc4xx_ahb_init(CPUPPCState *env)
530{
531 ppc4xx_ahb_t *ahb;
532
533 ahb = g_malloc0(sizeof(*ahb));
534 ppc_dcr_register(env, AHB_TOP, ahb, &dcr_read_ahb, &dcr_write_ahb);
535 ppc_dcr_register(env, AHB_BOT, ahb, &dcr_read_ahb, &dcr_write_ahb);
536 qemu_register_reset(ppc4xx_ahb_reset, ahb);
537}
538
539
540
541
542#define DMA0_CR_CE (1 << 31)
543#define DMA0_CR_PW (1 << 26 | 1 << 25)
544#define DMA0_CR_DAI (1 << 24)
545#define DMA0_CR_SAI (1 << 23)
546#define DMA0_CR_DEC (1 << 2)
547
548enum {
549 DMA0_CR = 0x00,
550 DMA0_CT,
551 DMA0_SAH,
552 DMA0_SAL,
553 DMA0_DAH,
554 DMA0_DAL,
555 DMA0_SGH,
556 DMA0_SGL,
557
558 DMA0_SR = 0x20,
559 DMA0_SGC = 0x23,
560 DMA0_SLP = 0x25,
561 DMA0_POL = 0x26,
562};
563
564typedef struct {
565 uint32_t cr;
566 uint32_t ct;
567 uint64_t sa;
568 uint64_t da;
569 uint64_t sg;
570} PPC4xxDmaChnl;
571
572typedef struct {
573 int base;
574 PPC4xxDmaChnl ch[4];
575 uint32_t sr;
576} PPC4xxDmaState;
577
578static uint32_t dcr_read_dma(void *opaque, int dcrn)
579{
580 PPC4xxDmaState *dma = opaque;
581 uint32_t val = 0;
582 int addr = dcrn - dma->base;
583 int chnl = addr / 8;
584
585 switch (addr) {
586 case 0x00 ... 0x1f:
587 switch (addr % 8) {
588 case DMA0_CR:
589 val = dma->ch[chnl].cr;
590 break;
591 case DMA0_CT:
592 val = dma->ch[chnl].ct;
593 break;
594 case DMA0_SAH:
595 val = dma->ch[chnl].sa >> 32;
596 break;
597 case DMA0_SAL:
598 val = dma->ch[chnl].sa;
599 break;
600 case DMA0_DAH:
601 val = dma->ch[chnl].da >> 32;
602 break;
603 case DMA0_DAL:
604 val = dma->ch[chnl].da;
605 break;
606 case DMA0_SGH:
607 val = dma->ch[chnl].sg >> 32;
608 break;
609 case DMA0_SGL:
610 val = dma->ch[chnl].sg;
611 break;
612 }
613 break;
614 case DMA0_SR:
615 val = dma->sr;
616 break;
617 default:
618 qemu_log_mask(LOG_UNIMP, "%s: unimplemented register %x (%d, %x)\n",
619 __func__, dcrn, chnl, addr);
620 }
621
622 return val;
623}
624
625static void dcr_write_dma(void *opaque, int dcrn, uint32_t val)
626{
627 PPC4xxDmaState *dma = opaque;
628 int addr = dcrn - dma->base;
629 int chnl = addr / 8;
630
631 switch (addr) {
632 case 0x00 ... 0x1f:
633 switch (addr % 8) {
634 case DMA0_CR:
635 dma->ch[chnl].cr = val;
636 if (val & DMA0_CR_CE) {
637 int count = dma->ch[chnl].ct & 0xffff;
638
639 if (count) {
640 int width, i, sidx, didx;
641 uint8_t *rptr, *wptr;
642 hwaddr rlen, wlen;
643 hwaddr xferlen;
644
645 sidx = didx = 0;
646 width = 1 << ((val & DMA0_CR_PW) >> 25);
647 xferlen = count * width;
648 wlen = rlen = xferlen;
649 rptr = cpu_physical_memory_map(dma->ch[chnl].sa, &rlen,
650 false);
651 wptr = cpu_physical_memory_map(dma->ch[chnl].da, &wlen,
652 true);
653 if (rptr && rlen == xferlen && wptr && wlen == xferlen) {
654 if (!(val & DMA0_CR_DEC) &&
655 val & DMA0_CR_SAI && val & DMA0_CR_DAI) {
656
657 memmove(wptr, rptr, count * width);
658 sidx = didx = count * width;
659 } else {
660
661 for (sidx = didx = i = 0; i < count; i++) {
662 uint64_t v = ldn_le_p(rptr + sidx, width);
663 stn_le_p(wptr + didx, width, v);
664 if (val & DMA0_CR_SAI) {
665 sidx += width;
666 }
667 if (val & DMA0_CR_DAI) {
668 didx += width;
669 }
670 }
671 }
672 }
673 if (wptr) {
674 cpu_physical_memory_unmap(wptr, wlen, 1, didx);
675 }
676 if (rptr) {
677 cpu_physical_memory_unmap(rptr, rlen, 0, sidx);
678 }
679 }
680 }
681 break;
682 case DMA0_CT:
683 dma->ch[chnl].ct = val;
684 break;
685 case DMA0_SAH:
686 dma->ch[chnl].sa &= 0xffffffffULL;
687 dma->ch[chnl].sa |= (uint64_t)val << 32;
688 break;
689 case DMA0_SAL:
690 dma->ch[chnl].sa &= 0xffffffff00000000ULL;
691 dma->ch[chnl].sa |= val;
692 break;
693 case DMA0_DAH:
694 dma->ch[chnl].da &= 0xffffffffULL;
695 dma->ch[chnl].da |= (uint64_t)val << 32;
696 break;
697 case DMA0_DAL:
698 dma->ch[chnl].da &= 0xffffffff00000000ULL;
699 dma->ch[chnl].da |= val;
700 break;
701 case DMA0_SGH:
702 dma->ch[chnl].sg &= 0xffffffffULL;
703 dma->ch[chnl].sg |= (uint64_t)val << 32;
704 break;
705 case DMA0_SGL:
706 dma->ch[chnl].sg &= 0xffffffff00000000ULL;
707 dma->ch[chnl].sg |= val;
708 break;
709 }
710 break;
711 case DMA0_SR:
712 dma->sr &= ~val;
713 break;
714 default:
715 qemu_log_mask(LOG_UNIMP, "%s: unimplemented register %x (%d, %x)\n",
716 __func__, dcrn, chnl, addr);
717 }
718}
719
720static void ppc4xx_dma_reset(void *opaque)
721{
722 PPC4xxDmaState *dma = opaque;
723 int dma_base = dma->base;
724
725 memset(dma, 0, sizeof(*dma));
726 dma->base = dma_base;
727}
728
729void ppc4xx_dma_init(CPUPPCState *env, int dcr_base)
730{
731 PPC4xxDmaState *dma;
732 int i;
733
734 dma = g_malloc0(sizeof(*dma));
735 dma->base = dcr_base;
736 qemu_register_reset(&ppc4xx_dma_reset, dma);
737 for (i = 0; i < 4; i++) {
738 ppc_dcr_register(env, dcr_base + i * 8 + DMA0_CR,
739 dma, &dcr_read_dma, &dcr_write_dma);
740 ppc_dcr_register(env, dcr_base + i * 8 + DMA0_CT,
741 dma, &dcr_read_dma, &dcr_write_dma);
742 ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SAH,
743 dma, &dcr_read_dma, &dcr_write_dma);
744 ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SAL,
745 dma, &dcr_read_dma, &dcr_write_dma);
746 ppc_dcr_register(env, dcr_base + i * 8 + DMA0_DAH,
747 dma, &dcr_read_dma, &dcr_write_dma);
748 ppc_dcr_register(env, dcr_base + i * 8 + DMA0_DAL,
749 dma, &dcr_read_dma, &dcr_write_dma);
750 ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SGH,
751 dma, &dcr_read_dma, &dcr_write_dma);
752 ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SGL,
753 dma, &dcr_read_dma, &dcr_write_dma);
754 }
755 ppc_dcr_register(env, dcr_base + DMA0_SR,
756 dma, &dcr_read_dma, &dcr_write_dma);
757 ppc_dcr_register(env, dcr_base + DMA0_SGC,
758 dma, &dcr_read_dma, &dcr_write_dma);
759 ppc_dcr_register(env, dcr_base + DMA0_SLP,
760 dma, &dcr_read_dma, &dcr_write_dma);
761 ppc_dcr_register(env, dcr_base + DMA0_POL,
762 dma, &dcr_read_dma, &dcr_write_dma);
763}
764
765
766
767
768
769
770
771#include "hw/pci/pcie_host.h"
772
773OBJECT_DECLARE_SIMPLE_TYPE(PPC460EXPCIEState, PPC460EX_PCIE_HOST)
774
775struct PPC460EXPCIEState {
776 PCIExpressHost parent_obj;
777
778 MemoryRegion busmem;
779 MemoryRegion iomem;
780 qemu_irq irq[4];
781 int32_t num;
782 int32_t dcrn_base;
783 PowerPCCPU *cpu;
784
785 uint64_t cfg_base;
786 uint32_t cfg_mask;
787 uint64_t msg_base;
788 uint32_t msg_mask;
789 uint64_t omr1_base;
790 uint64_t omr1_mask;
791 uint64_t omr2_base;
792 uint64_t omr2_mask;
793 uint64_t omr3_base;
794 uint64_t omr3_mask;
795 uint64_t reg_base;
796 uint32_t reg_mask;
797 uint32_t special;
798 uint32_t cfg;
799};
800
801enum {
802 PEGPL_CFGBAH = 0x0,
803 PEGPL_CFGBAL,
804 PEGPL_CFGMSK,
805 PEGPL_MSGBAH,
806 PEGPL_MSGBAL,
807 PEGPL_MSGMSK,
808 PEGPL_OMR1BAH,
809 PEGPL_OMR1BAL,
810 PEGPL_OMR1MSKH,
811 PEGPL_OMR1MSKL,
812 PEGPL_OMR2BAH,
813 PEGPL_OMR2BAL,
814 PEGPL_OMR2MSKH,
815 PEGPL_OMR2MSKL,
816 PEGPL_OMR3BAH,
817 PEGPL_OMR3BAL,
818 PEGPL_OMR3MSKH,
819 PEGPL_OMR3MSKL,
820 PEGPL_REGBAH,
821 PEGPL_REGBAL,
822 PEGPL_REGMSK,
823 PEGPL_SPECIAL,
824 PEGPL_CFG,
825};
826
827static uint32_t dcr_read_pcie(void *opaque, int dcrn)
828{
829 PPC460EXPCIEState *s = opaque;
830 uint32_t ret = 0;
831
832 switch (dcrn - s->dcrn_base) {
833 case PEGPL_CFGBAH:
834 ret = s->cfg_base >> 32;
835 break;
836 case PEGPL_CFGBAL:
837 ret = s->cfg_base;
838 break;
839 case PEGPL_CFGMSK:
840 ret = s->cfg_mask;
841 break;
842 case PEGPL_MSGBAH:
843 ret = s->msg_base >> 32;
844 break;
845 case PEGPL_MSGBAL:
846 ret = s->msg_base;
847 break;
848 case PEGPL_MSGMSK:
849 ret = s->msg_mask;
850 break;
851 case PEGPL_OMR1BAH:
852 ret = s->omr1_base >> 32;
853 break;
854 case PEGPL_OMR1BAL:
855 ret = s->omr1_base;
856 break;
857 case PEGPL_OMR1MSKH:
858 ret = s->omr1_mask >> 32;
859 break;
860 case PEGPL_OMR1MSKL:
861 ret = s->omr1_mask;
862 break;
863 case PEGPL_OMR2BAH:
864 ret = s->omr2_base >> 32;
865 break;
866 case PEGPL_OMR2BAL:
867 ret = s->omr2_base;
868 break;
869 case PEGPL_OMR2MSKH:
870 ret = s->omr2_mask >> 32;
871 break;
872 case PEGPL_OMR2MSKL:
873 ret = s->omr3_mask;
874 break;
875 case PEGPL_OMR3BAH:
876 ret = s->omr3_base >> 32;
877 break;
878 case PEGPL_OMR3BAL:
879 ret = s->omr3_base;
880 break;
881 case PEGPL_OMR3MSKH:
882 ret = s->omr3_mask >> 32;
883 break;
884 case PEGPL_OMR3MSKL:
885 ret = s->omr3_mask;
886 break;
887 case PEGPL_REGBAH:
888 ret = s->reg_base >> 32;
889 break;
890 case PEGPL_REGBAL:
891 ret = s->reg_base;
892 break;
893 case PEGPL_REGMSK:
894 ret = s->reg_mask;
895 break;
896 case PEGPL_SPECIAL:
897 ret = s->special;
898 break;
899 case PEGPL_CFG:
900 ret = s->cfg;
901 break;
902 }
903
904 return ret;
905}
906
907static void dcr_write_pcie(void *opaque, int dcrn, uint32_t val)
908{
909 PPC460EXPCIEState *s = opaque;
910 uint64_t size;
911
912 switch (dcrn - s->dcrn_base) {
913 case PEGPL_CFGBAH:
914 s->cfg_base = ((uint64_t)val << 32) | (s->cfg_base & 0xffffffff);
915 break;
916 case PEGPL_CFGBAL:
917 s->cfg_base = (s->cfg_base & 0xffffffff00000000ULL) | val;
918 break;
919 case PEGPL_CFGMSK:
920 s->cfg_mask = val;
921 size = ~(val & 0xfffffffe) + 1;
922
923
924
925
926
927 if (size > PCIE_MMCFG_SIZE_MAX) {
928 size = PCIE_MMCFG_SIZE_MAX;
929 }
930 pcie_host_mmcfg_update(PCIE_HOST_BRIDGE(s), val & 1, s->cfg_base, size);
931 break;
932 case PEGPL_MSGBAH:
933 s->msg_base = ((uint64_t)val << 32) | (s->msg_base & 0xffffffff);
934 break;
935 case PEGPL_MSGBAL:
936 s->msg_base = (s->msg_base & 0xffffffff00000000ULL) | val;
937 break;
938 case PEGPL_MSGMSK:
939 s->msg_mask = val;
940 break;
941 case PEGPL_OMR1BAH:
942 s->omr1_base = ((uint64_t)val << 32) | (s->omr1_base & 0xffffffff);
943 break;
944 case PEGPL_OMR1BAL:
945 s->omr1_base = (s->omr1_base & 0xffffffff00000000ULL) | val;
946 break;
947 case PEGPL_OMR1MSKH:
948 s->omr1_mask = ((uint64_t)val << 32) | (s->omr1_mask & 0xffffffff);
949 break;
950 case PEGPL_OMR1MSKL:
951 s->omr1_mask = (s->omr1_mask & 0xffffffff00000000ULL) | val;
952 break;
953 case PEGPL_OMR2BAH:
954 s->omr2_base = ((uint64_t)val << 32) | (s->omr2_base & 0xffffffff);
955 break;
956 case PEGPL_OMR2BAL:
957 s->omr2_base = (s->omr2_base & 0xffffffff00000000ULL) | val;
958 break;
959 case PEGPL_OMR2MSKH:
960 s->omr2_mask = ((uint64_t)val << 32) | (s->omr2_mask & 0xffffffff);
961 break;
962 case PEGPL_OMR2MSKL:
963 s->omr2_mask = (s->omr2_mask & 0xffffffff00000000ULL) | val;
964 break;
965 case PEGPL_OMR3BAH:
966 s->omr3_base = ((uint64_t)val << 32) | (s->omr3_base & 0xffffffff);
967 break;
968 case PEGPL_OMR3BAL:
969 s->omr3_base = (s->omr3_base & 0xffffffff00000000ULL) | val;
970 break;
971 case PEGPL_OMR3MSKH:
972 s->omr3_mask = ((uint64_t)val << 32) | (s->omr3_mask & 0xffffffff);
973 break;
974 case PEGPL_OMR3MSKL:
975 s->omr3_mask = (s->omr3_mask & 0xffffffff00000000ULL) | val;
976 break;
977 case PEGPL_REGBAH:
978 s->reg_base = ((uint64_t)val << 32) | (s->reg_base & 0xffffffff);
979 break;
980 case PEGPL_REGBAL:
981 s->reg_base = (s->reg_base & 0xffffffff00000000ULL) | val;
982 break;
983 case PEGPL_REGMSK:
984 s->reg_mask = val;
985
986 size = (val == 0x7001 ? 4096 : ~(val & 0xfffffffe) + 1);
987 break;
988 case PEGPL_SPECIAL:
989 s->special = val;
990 break;
991 case PEGPL_CFG:
992 s->cfg = val;
993 break;
994 }
995}
996
997static void ppc460ex_set_irq(void *opaque, int irq_num, int level)
998{
999 PPC460EXPCIEState *s = opaque;
1000 qemu_set_irq(s->irq[irq_num], level);
1001}
1002
1003#define PPC440_PCIE_DCR(s, dcrn) \
1004 ppc_dcr_register(&(s)->cpu->env, (s)->dcrn_base + (dcrn), (s), \
1005 &dcr_read_pcie, &dcr_write_pcie)
1006
1007
1008static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s)
1009{
1010 PPC440_PCIE_DCR(s, PEGPL_CFGBAH);
1011 PPC440_PCIE_DCR(s, PEGPL_CFGBAL);
1012 PPC440_PCIE_DCR(s, PEGPL_CFGMSK);
1013 PPC440_PCIE_DCR(s, PEGPL_MSGBAH);
1014 PPC440_PCIE_DCR(s, PEGPL_MSGBAL);
1015 PPC440_PCIE_DCR(s, PEGPL_MSGMSK);
1016 PPC440_PCIE_DCR(s, PEGPL_OMR1BAH);
1017 PPC440_PCIE_DCR(s, PEGPL_OMR1BAL);
1018 PPC440_PCIE_DCR(s, PEGPL_OMR1MSKH);
1019 PPC440_PCIE_DCR(s, PEGPL_OMR1MSKL);
1020 PPC440_PCIE_DCR(s, PEGPL_OMR2BAH);
1021 PPC440_PCIE_DCR(s, PEGPL_OMR2BAL);
1022 PPC440_PCIE_DCR(s, PEGPL_OMR2MSKH);
1023 PPC440_PCIE_DCR(s, PEGPL_OMR2MSKL);
1024 PPC440_PCIE_DCR(s, PEGPL_OMR3BAH);
1025 PPC440_PCIE_DCR(s, PEGPL_OMR3BAL);
1026 PPC440_PCIE_DCR(s, PEGPL_OMR3MSKH);
1027 PPC440_PCIE_DCR(s, PEGPL_OMR3MSKL);
1028 PPC440_PCIE_DCR(s, PEGPL_REGBAH);
1029 PPC440_PCIE_DCR(s, PEGPL_REGBAL);
1030 PPC440_PCIE_DCR(s, PEGPL_REGMSK);
1031 PPC440_PCIE_DCR(s, PEGPL_SPECIAL);
1032 PPC440_PCIE_DCR(s, PEGPL_CFG);
1033}
1034
1035static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp)
1036{
1037 PPC460EXPCIEState *s = PPC460EX_PCIE_HOST(dev);
1038 PCIHostState *pci = PCI_HOST_BRIDGE(dev);
1039 int i;
1040 char buf[20];
1041
1042 if (!s->cpu) {
1043 error_setg(errp, "cpu link property must be set");
1044 return;
1045 }
1046 if (s->num < 0 || s->dcrn_base < 0) {
1047 error_setg(errp, "busnum and dcrn-base properties must be set");
1048 return;
1049 }
1050 snprintf(buf, sizeof(buf), "pcie%d-mem", s->num);
1051 memory_region_init(&s->busmem, OBJECT(s), buf, UINT64_MAX);
1052 snprintf(buf, sizeof(buf), "pcie%d-io", s->num);
1053 memory_region_init(&s->iomem, OBJECT(s), buf, 64 * KiB);
1054 for (i = 0; i < 4; i++) {
1055 sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
1056 }
1057 snprintf(buf, sizeof(buf), "pcie.%d", s->num);
1058 pci->bus = pci_register_root_bus(DEVICE(s), buf, ppc460ex_set_irq,
1059 pci_swizzle_map_irq_fn, s, &s->busmem,
1060 &s->iomem, 0, 4, TYPE_PCIE_BUS);
1061 ppc460ex_pcie_register_dcrs(s);
1062}
1063
1064static Property ppc460ex_pcie_props[] = {
1065 DEFINE_PROP_INT32("busnum", PPC460EXPCIEState, num, -1),
1066 DEFINE_PROP_INT32("dcrn-base", PPC460EXPCIEState, dcrn_base, -1),
1067 DEFINE_PROP_LINK("cpu", PPC460EXPCIEState, cpu, TYPE_POWERPC_CPU,
1068 PowerPCCPU *),
1069 DEFINE_PROP_END_OF_LIST(),
1070};
1071
1072static void ppc460ex_pcie_class_init(ObjectClass *klass, void *data)
1073{
1074 DeviceClass *dc = DEVICE_CLASS(klass);
1075
1076 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
1077 dc->realize = ppc460ex_pcie_realize;
1078 device_class_set_props(dc, ppc460ex_pcie_props);
1079 dc->hotpluggable = false;
1080}
1081
1082static const TypeInfo ppc460ex_pcie_host_info = {
1083 .name = TYPE_PPC460EX_PCIE_HOST,
1084 .parent = TYPE_PCIE_HOST_BRIDGE,
1085 .instance_size = sizeof(PPC460EXPCIEState),
1086 .class_init = ppc460ex_pcie_class_init,
1087};
1088
1089static void ppc460ex_pcie_register(void)
1090{
1091 type_register_static(&ppc460ex_pcie_host_info);
1092}
1093
1094type_init(ppc460ex_pcie_register)
1095