Revision 802670e6
b/hw/pc.h | ||
---|---|---|
12 | 12 |
SerialState *serial_mm_init (target_phys_addr_t base, int it_shift, |
13 | 13 |
qemu_irq irq, int baudbase, |
14 | 14 |
CharDriverState *chr, int ioregister); |
15 |
uint32_t serial_mm_readb (void *opaque, target_phys_addr_t addr); |
|
16 |
void serial_mm_writeb (void *opaque, target_phys_addr_t addr, uint32_t value); |
|
17 |
uint32_t serial_mm_readw (void *opaque, target_phys_addr_t addr); |
|
18 |
void serial_mm_writew (void *opaque, target_phys_addr_t addr, uint32_t value); |
|
19 |
uint32_t serial_mm_readl (void *opaque, target_phys_addr_t addr); |
|
20 |
void serial_mm_writel (void *opaque, target_phys_addr_t addr, uint32_t value); |
|
21 | 15 |
|
22 | 16 |
/* parallel.c */ |
23 | 17 |
|
b/hw/ppc.h | ||
---|---|---|
45 | 45 |
#define FW_CFG_PPC_WIDTH (FW_CFG_ARCH_LOCAL + 0x00) |
46 | 46 |
#define FW_CFG_PPC_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01) |
47 | 47 |
#define FW_CFG_PPC_DEPTH (FW_CFG_ARCH_LOCAL + 0x02) |
48 |
|
|
49 |
#define PPC_SERIAL_MM_BAUDBASE 399193 |
b/hw/ppc405.h | ||
---|---|---|
59 | 59 |
ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd, |
60 | 60 |
uint32_t flags); |
61 | 61 |
|
62 |
/* PowerPC 4xx peripheral local bus arbitrer */ |
|
63 |
void ppc4xx_plb_init (CPUState *env); |
|
64 |
/* PLB to OPB bridge */ |
|
65 |
void ppc4xx_pob_init (CPUState *env); |
|
66 |
/* OPB arbitrer */ |
|
67 |
void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, |
|
68 |
target_phys_addr_t offset); |
|
69 |
/* Peripheral controller */ |
|
70 |
void ppc405_ebc_init (CPUState *env); |
|
71 |
/* DMA controller */ |
|
72 |
void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]); |
|
73 |
/* GPIO */ |
|
74 |
void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, |
|
75 |
target_phys_addr_t offset); |
|
76 |
/* Serial ports */ |
|
77 |
void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio, |
|
78 |
target_phys_addr_t offset, qemu_irq irq, |
|
79 |
CharDriverState *chr); |
|
80 |
/* On Chip Memory */ |
|
81 |
void ppc405_ocm_init (CPUState *env); |
|
82 |
/* I2C controller */ |
|
83 |
void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, |
|
84 |
target_phys_addr_t offset, qemu_irq irq); |
|
85 |
/* General purpose timers */ |
|
86 |
void ppc4xx_gpt_init (CPUState *env, ppc4xx_mmio_t *mmio, |
|
87 |
target_phys_addr_t offset, qemu_irq irq[5]); |
|
88 |
/* Memory access layer */ |
|
89 |
void ppc405_mal_init (CPUState *env, qemu_irq irqs[4]); |
|
90 |
/* PowerPC 405 microcontrollers */ |
|
91 | 62 |
CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4], |
92 | 63 |
target_phys_addr_t ram_sizes[4], |
93 | 64 |
uint32_t sysclk, qemu_irq **picp, |
b/hw/ppc405_uc.c | ||
---|---|---|
164 | 164 |
plb->besr = 0x00000000; |
165 | 165 |
} |
166 | 166 |
|
167 |
void ppc4xx_plb_init (CPUState *env)
|
|
167 |
static void ppc4xx_plb_init(CPUState *env)
|
|
168 | 168 |
{ |
169 | 169 |
ppc4xx_plb_t *plb; |
170 | 170 |
|
... | ... | |
241 | 241 |
pob->besr[1] = 0x0000000; |
242 | 242 |
} |
243 | 243 |
|
244 |
void ppc4xx_pob_init (CPUState *env)
|
|
244 |
static void ppc4xx_pob_init(CPUState *env)
|
|
245 | 245 |
{ |
246 | 246 |
ppc4xx_pob_t *pob; |
247 | 247 |
|
... | ... | |
250 | 250 |
ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob); |
251 | 251 |
ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob); |
252 | 252 |
qemu_register_reset(ppc4xx_pob_reset, pob); |
253 |
ppc4xx_pob_reset(env);
|
|
253 |
ppc4xx_pob_reset(pob);
|
|
254 | 254 |
} |
255 | 255 |
|
256 | 256 |
/*****************************************************************************/ |
257 | 257 |
/* OPB arbitrer */ |
258 | 258 |
typedef struct ppc4xx_opba_t ppc4xx_opba_t; |
259 | 259 |
struct ppc4xx_opba_t { |
260 |
target_phys_addr_t base; |
|
261 | 260 |
uint8_t cr; |
262 | 261 |
uint8_t pr; |
263 | 262 |
}; |
... | ... | |
271 | 270 |
printf("%s: addr " PADDRX "\n", __func__, addr); |
272 | 271 |
#endif |
273 | 272 |
opba = opaque; |
274 |
switch (addr - opba->base) {
|
|
273 |
switch (addr) { |
|
275 | 274 |
case 0x00: |
276 | 275 |
ret = opba->cr; |
277 | 276 |
break; |
... | ... | |
295 | 294 |
printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); |
296 | 295 |
#endif |
297 | 296 |
opba = opaque; |
298 |
switch (addr - opba->base) {
|
|
297 |
switch (addr) { |
|
299 | 298 |
case 0x00: |
300 | 299 |
opba->cr = value & 0xF8; |
301 | 300 |
break; |
... | ... | |
374 | 373 |
opba->pr = 0x11; |
375 | 374 |
} |
376 | 375 |
|
377 |
void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, |
|
378 |
target_phys_addr_t offset) |
|
376 |
static void ppc4xx_opba_init(target_phys_addr_t base) |
|
379 | 377 |
{ |
380 | 378 |
ppc4xx_opba_t *opba; |
379 |
int io; |
|
381 | 380 |
|
382 | 381 |
opba = qemu_mallocz(sizeof(ppc4xx_opba_t)); |
383 |
opba->base = offset; |
|
384 | 382 |
#ifdef DEBUG_OPBA |
385 |
printf("%s: offset " PADDRX "\n", __func__, offset);
|
|
383 |
printf("%s: offset " PADDRX "\n", __func__, base);
|
|
386 | 384 |
#endif |
387 |
ppc4xx_mmio_register(env, mmio, offset, 0x002, |
|
388 |
opba_read, opba_write, opba); |
|
389 |
qemu_register_reset(ppc4xx_opba_reset, opba); |
|
385 |
io = cpu_register_io_memory(opba_read, opba_write, opba); |
|
386 |
cpu_register_physical_memory(base, 0x002, io); |
|
390 | 387 |
ppc4xx_opba_reset(opba); |
388 |
qemu_register_reset(ppc4xx_opba_reset, opba); |
|
391 | 389 |
} |
392 | 390 |
|
393 | 391 |
/*****************************************************************************/ |
... | ... | |
574 | 572 |
ebc->cfg = 0x80400000; |
575 | 573 |
} |
576 | 574 |
|
577 |
void ppc405_ebc_init (CPUState *env)
|
|
575 |
static void ppc405_ebc_init(CPUState *env)
|
|
578 | 576 |
{ |
579 | 577 |
ppc4xx_ebc_t *ebc; |
580 | 578 |
|
... | ... | |
665 | 663 |
dma->pol = 0x00000000; |
666 | 664 |
} |
667 | 665 |
|
668 |
void ppc405_dma_init (CPUState *env, qemu_irq irqs[4])
|
|
666 |
static void ppc405_dma_init(CPUState *env, qemu_irq irqs[4])
|
|
669 | 667 |
{ |
670 | 668 |
ppc405_dma_t *dma; |
671 | 669 |
|
... | ... | |
727 | 725 |
/* GPIO */ |
728 | 726 |
typedef struct ppc405_gpio_t ppc405_gpio_t; |
729 | 727 |
struct ppc405_gpio_t { |
730 |
target_phys_addr_t base; |
|
731 | 728 |
uint32_t or; |
732 | 729 |
uint32_t tcr; |
733 | 730 |
uint32_t osrh; |
... | ... | |
829 | 826 |
gpio = opaque; |
830 | 827 |
} |
831 | 828 |
|
832 |
void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, |
|
833 |
target_phys_addr_t offset) |
|
829 |
static void ppc405_gpio_init(target_phys_addr_t base) |
|
834 | 830 |
{ |
835 | 831 |
ppc405_gpio_t *gpio; |
832 |
int io; |
|
836 | 833 |
|
837 | 834 |
gpio = qemu_mallocz(sizeof(ppc405_gpio_t)); |
838 |
gpio->base = offset; |
|
839 |
ppc405_gpio_reset(gpio); |
|
840 |
qemu_register_reset(&ppc405_gpio_reset, gpio); |
|
841 | 835 |
#ifdef DEBUG_GPIO |
842 |
printf("%s: offset " PADDRX "\n", __func__, offset); |
|
843 |
#endif |
|
844 |
ppc4xx_mmio_register(env, mmio, offset, 0x038, |
|
845 |
ppc405_gpio_read, ppc405_gpio_write, gpio); |
|
846 |
} |
|
847 |
|
|
848 |
/*****************************************************************************/ |
|
849 |
/* Serial ports */ |
|
850 |
static CPUReadMemoryFunc *serial_mm_read[] = { |
|
851 |
&serial_mm_readb, |
|
852 |
&serial_mm_readw, |
|
853 |
&serial_mm_readl, |
|
854 |
}; |
|
855 |
|
|
856 |
static CPUWriteMemoryFunc *serial_mm_write[] = { |
|
857 |
&serial_mm_writeb, |
|
858 |
&serial_mm_writew, |
|
859 |
&serial_mm_writel, |
|
860 |
}; |
|
861 |
|
|
862 |
void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio, |
|
863 |
target_phys_addr_t offset, qemu_irq irq, |
|
864 |
CharDriverState *chr) |
|
865 |
{ |
|
866 |
void *serial; |
|
867 |
|
|
868 |
#ifdef DEBUG_SERIAL |
|
869 |
printf("%s: offset " PADDRX "\n", __func__, offset); |
|
836 |
printf("%s: offset " PADDRX "\n", __func__, base); |
|
870 | 837 |
#endif |
871 |
serial = serial_mm_init(offset, 0, irq, 399193, chr, 0); |
|
872 |
ppc4xx_mmio_register(env, mmio, offset, 0x008, |
|
873 |
serial_mm_read, serial_mm_write, serial); |
|
838 |
io = cpu_register_io_memory(ppc405_gpio_read, ppc405_gpio_write, gpio); |
|
839 |
cpu_register_physical_memory(base, 0x038, io); |
|
840 |
ppc405_gpio_reset(gpio); |
|
841 |
qemu_register_reset(&ppc405_gpio_reset, gpio); |
|
874 | 842 |
} |
875 | 843 |
|
876 | 844 |
/*****************************************************************************/ |
... | ... | |
1021 | 989 |
ocm->dsacntl = dsacntl; |
1022 | 990 |
} |
1023 | 991 |
|
1024 |
void ppc405_ocm_init (CPUState *env)
|
|
992 |
static void ppc405_ocm_init(CPUState *env)
|
|
1025 | 993 |
{ |
1026 | 994 |
ppc405_ocm_t *ocm; |
1027 | 995 |
|
... | ... | |
1043 | 1011 |
/* I2C controller */ |
1044 | 1012 |
typedef struct ppc4xx_i2c_t ppc4xx_i2c_t; |
1045 | 1013 |
struct ppc4xx_i2c_t { |
1046 |
target_phys_addr_t base; |
|
1047 | 1014 |
qemu_irq irq; |
1048 | 1015 |
uint8_t mdata; |
1049 | 1016 |
uint8_t lmadr; |
... | ... | |
1071 | 1038 |
printf("%s: addr " PADDRX "\n", __func__, addr); |
1072 | 1039 |
#endif |
1073 | 1040 |
i2c = opaque; |
1074 |
switch (addr - i2c->base) {
|
|
1041 |
switch (addr) { |
|
1075 | 1042 |
case 0x00: |
1076 | 1043 |
// i2c_readbyte(&i2c->mdata); |
1077 | 1044 |
ret = i2c->mdata; |
... | ... | |
1138 | 1105 |
printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); |
1139 | 1106 |
#endif |
1140 | 1107 |
i2c = opaque; |
1141 |
switch (addr - i2c->base) {
|
|
1108 |
switch (addr) { |
|
1142 | 1109 |
case 0x00: |
1143 | 1110 |
i2c->mdata = value; |
1144 | 1111 |
// i2c_sendbyte(&i2c->mdata); |
... | ... | |
1266 | 1233 |
i2c->directcntl = 0x0F; |
1267 | 1234 |
} |
1268 | 1235 |
|
1269 |
void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, |
|
1270 |
target_phys_addr_t offset, qemu_irq irq) |
|
1236 |
static void ppc405_i2c_init(target_phys_addr_t base, qemu_irq irq) |
|
1271 | 1237 |
{ |
1272 | 1238 |
ppc4xx_i2c_t *i2c; |
1239 |
int io; |
|
1273 | 1240 |
|
1274 | 1241 |
i2c = qemu_mallocz(sizeof(ppc4xx_i2c_t)); |
1275 |
i2c->base = offset; |
|
1276 | 1242 |
i2c->irq = irq; |
1277 |
ppc4xx_i2c_reset(i2c); |
|
1278 | 1243 |
#ifdef DEBUG_I2C |
1279 |
printf("%s: offset " PADDRX "\n", __func__, offset);
|
|
1244 |
printf("%s: offset " PADDRX "\n", __func__, base);
|
|
1280 | 1245 |
#endif |
1281 |
ppc4xx_mmio_register(env, mmio, offset, 0x011, |
|
1282 |
i2c_read, i2c_write, i2c); |
|
1246 |
io = cpu_register_io_memory(i2c_read, i2c_write, i2c); |
|
1247 |
cpu_register_physical_memory(base, 0x011, io); |
|
1248 |
ppc4xx_i2c_reset(i2c); |
|
1283 | 1249 |
qemu_register_reset(ppc4xx_i2c_reset, i2c); |
1284 | 1250 |
} |
1285 | 1251 |
|
... | ... | |
1287 | 1253 |
/* General purpose timers */ |
1288 | 1254 |
typedef struct ppc4xx_gpt_t ppc4xx_gpt_t; |
1289 | 1255 |
struct ppc4xx_gpt_t { |
1290 |
target_phys_addr_t base; |
|
1291 | 1256 |
int64_t tb_offset; |
1292 | 1257 |
uint32_t tb_freq; |
1293 | 1258 |
struct QEMUTimer *timer; |
... | ... | |
1399 | 1364 |
printf("%s: addr " PADDRX "\n", __func__, addr); |
1400 | 1365 |
#endif |
1401 | 1366 |
gpt = opaque; |
1402 |
switch (addr - gpt->base) {
|
|
1367 |
switch (addr) { |
|
1403 | 1368 |
case 0x00: |
1404 | 1369 |
/* Time base counter */ |
1405 | 1370 |
ret = muldiv64(qemu_get_clock(vm_clock) + gpt->tb_offset, |
... | ... | |
1428 | 1393 |
break; |
1429 | 1394 |
case 0x80 ... 0x90: |
1430 | 1395 |
/* Compare timer */ |
1431 |
idx = ((addr - gpt->base) - 0x80) >> 2;
|
|
1396 |
idx = (addr - 0x80) >> 2;
|
|
1432 | 1397 |
ret = gpt->comp[idx]; |
1433 | 1398 |
break; |
1434 | 1399 |
case 0xC0 ... 0xD0: |
1435 | 1400 |
/* Compare mask */ |
1436 |
idx = ((addr - gpt->base) - 0xC0) >> 2;
|
|
1401 |
idx = (addr - 0xC0) >> 2;
|
|
1437 | 1402 |
ret = gpt->mask[idx]; |
1438 | 1403 |
break; |
1439 | 1404 |
default: |
... | ... | |
1454 | 1419 |
printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); |
1455 | 1420 |
#endif |
1456 | 1421 |
gpt = opaque; |
1457 |
switch (addr - gpt->base) {
|
|
1422 |
switch (addr) { |
|
1458 | 1423 |
case 0x00: |
1459 | 1424 |
/* Time base counter */ |
1460 | 1425 |
gpt->tb_offset = muldiv64(value, ticks_per_sec, gpt->tb_freq) |
... | ... | |
1492 | 1457 |
break; |
1493 | 1458 |
case 0x80 ... 0x90: |
1494 | 1459 |
/* Compare timer */ |
1495 |
idx = ((addr - gpt->base) - 0x80) >> 2;
|
|
1460 |
idx = (addr - 0x80) >> 2;
|
|
1496 | 1461 |
gpt->comp[idx] = value & 0xF8000000; |
1497 | 1462 |
ppc4xx_gpt_compute_timer(gpt); |
1498 | 1463 |
break; |
1499 | 1464 |
case 0xC0 ... 0xD0: |
1500 | 1465 |
/* Compare mask */ |
1501 |
idx = ((addr - gpt->base) - 0xC0) >> 2;
|
|
1466 |
idx = (addr - 0xC0) >> 2;
|
|
1502 | 1467 |
gpt->mask[idx] = value & 0xF8000000; |
1503 | 1468 |
ppc4xx_gpt_compute_timer(gpt); |
1504 | 1469 |
break; |
... | ... | |
1545 | 1510 |
} |
1546 | 1511 |
} |
1547 | 1512 |
|
1548 |
void ppc4xx_gpt_init (CPUState *env, ppc4xx_mmio_t *mmio, |
|
1549 |
target_phys_addr_t offset, qemu_irq irqs[5]) |
|
1513 |
static void ppc4xx_gpt_init(target_phys_addr_t base, qemu_irq irqs[5]) |
|
1550 | 1514 |
{ |
1551 | 1515 |
ppc4xx_gpt_t *gpt; |
1552 | 1516 |
int i; |
1517 |
int io; |
|
1553 | 1518 |
|
1554 | 1519 |
gpt = qemu_mallocz(sizeof(ppc4xx_gpt_t)); |
1555 |
gpt->base = offset; |
|
1556 |
for (i = 0; i < 5; i++) |
|
1520 |
for (i = 0; i < 5; i++) { |
|
1557 | 1521 |
gpt->irqs[i] = irqs[i]; |
1522 |
} |
|
1558 | 1523 |
gpt->timer = qemu_new_timer(vm_clock, &ppc4xx_gpt_cb, gpt); |
1559 |
ppc4xx_gpt_reset(gpt); |
|
1560 | 1524 |
#ifdef DEBUG_GPT |
1561 |
printf("%s: offset " PADDRX "\n", __func__, offset);
|
|
1525 |
printf("%s: offset " PADDRX "\n", __func__, base);
|
|
1562 | 1526 |
#endif |
1563 |
ppc4xx_mmio_register(env, mmio, offset, 0x0D4,
|
|
1564 |
gpt_read, gpt_write, gpt);
|
|
1527 |
io = cpu_register_io_memory(gpt_read, gpt_write, gpt);
|
|
1528 |
cpu_register_physical_memory(base, 0x0d4, io);
|
|
1565 | 1529 |
qemu_register_reset(ppc4xx_gpt_reset, gpt); |
1530 |
ppc4xx_gpt_reset(gpt); |
|
1566 | 1531 |
} |
1567 | 1532 |
|
1568 | 1533 |
/*****************************************************************************/ |
... | ... | |
1778 | 1743 |
mal->txeobisr = 0x00000000; |
1779 | 1744 |
} |
1780 | 1745 |
|
1781 |
void ppc405_mal_init (CPUState *env, qemu_irq irqs[4])
|
|
1746 |
static void ppc405_mal_init(CPUState *env, qemu_irq irqs[4])
|
|
1782 | 1747 |
{ |
1783 | 1748 |
ppc40x_mal_t *mal; |
1784 | 1749 |
int i; |
... | ... | |
2183 | 2148 |
clk_setup_t clk_setup[PPC405CR_CLK_NB]; |
2184 | 2149 |
qemu_irq dma_irqs[4]; |
2185 | 2150 |
CPUState *env; |
2186 |
ppc4xx_mmio_t *mmio; |
|
2187 | 2151 |
qemu_irq *pic, *irqs; |
2188 | 2152 |
|
2189 | 2153 |
memset(clk_setup, 0, sizeof(clk_setup)); |
2190 | 2154 |
env = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK], |
2191 | 2155 |
&clk_setup[PPC405CR_TMR_CLK], sysclk); |
2192 | 2156 |
/* Memory mapped devices registers */ |
2193 |
mmio = ppc4xx_mmio_init(env, 0xEF600000); |
|
2194 | 2157 |
/* PLB arbitrer */ |
2195 | 2158 |
ppc4xx_plb_init(env); |
2196 | 2159 |
/* PLB to OPB bridge */ |
2197 | 2160 |
ppc4xx_pob_init(env); |
2198 | 2161 |
/* OBP arbitrer */ |
2199 |
ppc4xx_opba_init(env, mmio, 0x600);
|
|
2162 |
ppc4xx_opba_init(0xef600600);
|
|
2200 | 2163 |
/* Universal interrupt controller */ |
2201 | 2164 |
irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); |
2202 | 2165 |
irqs[PPCUIC_OUTPUT_INT] = |
... | ... | |
2217 | 2180 |
ppc405_dma_init(env, dma_irqs); |
2218 | 2181 |
/* Serial ports */ |
2219 | 2182 |
if (serial_hds[0] != NULL) { |
2220 |
ppc405_serial_init(env, mmio, 0x300, pic[0], serial_hds[0]); |
|
2183 |
serial_mm_init(0xef600300, 0, pic[0], PPC_SERIAL_MM_BAUDBASE, |
|
2184 |
serial_hds[0], 1); |
|
2221 | 2185 |
} |
2222 | 2186 |
if (serial_hds[1] != NULL) { |
2223 |
ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]); |
|
2187 |
serial_mm_init(0xef600400, 0, pic[1], PPC_SERIAL_MM_BAUDBASE, |
|
2188 |
serial_hds[1], 1); |
|
2224 | 2189 |
} |
2225 | 2190 |
/* IIC controller */ |
2226 |
ppc405_i2c_init(env, mmio, 0x500, pic[2]);
|
|
2191 |
ppc405_i2c_init(0xef600500, pic[2]);
|
|
2227 | 2192 |
/* GPIO */ |
2228 |
ppc405_gpio_init(env, mmio, 0x700);
|
|
2193 |
ppc405_gpio_init(0xef600700);
|
|
2229 | 2194 |
/* CPU control */ |
2230 | 2195 |
ppc405cr_cpc_init(env, clk_setup, sysclk); |
2231 | 2196 |
|
... | ... | |
2528 | 2493 |
clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup; |
2529 | 2494 |
qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; |
2530 | 2495 |
CPUState *env; |
2531 |
ppc4xx_mmio_t *mmio; |
|
2532 | 2496 |
qemu_irq *pic, *irqs; |
2533 | 2497 |
|
2534 | 2498 |
memset(clk_setup, 0, sizeof(clk_setup)); |
... | ... | |
2539 | 2503 |
clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque; |
2540 | 2504 |
/* Internal devices init */ |
2541 | 2505 |
/* Memory mapped devices registers */ |
2542 |
mmio = ppc4xx_mmio_init(env, 0xEF600000); |
|
2543 | 2506 |
/* PLB arbitrer */ |
2544 | 2507 |
ppc4xx_plb_init(env); |
2545 | 2508 |
/* PLB to OPB bridge */ |
2546 | 2509 |
ppc4xx_pob_init(env); |
2547 | 2510 |
/* OBP arbitrer */ |
2548 |
ppc4xx_opba_init(env, mmio, 0x600);
|
|
2511 |
ppc4xx_opba_init(0xef600600);
|
|
2549 | 2512 |
/* Universal interrupt controller */ |
2550 | 2513 |
irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); |
2551 | 2514 |
irqs[PPCUIC_OUTPUT_INT] = |
... | ... | |
2566 | 2529 |
dma_irqs[3] = pic[8]; |
2567 | 2530 |
ppc405_dma_init(env, dma_irqs); |
2568 | 2531 |
/* IIC controller */ |
2569 |
ppc405_i2c_init(env, mmio, 0x500, pic[2]);
|
|
2532 |
ppc405_i2c_init(0xef600500, pic[2]);
|
|
2570 | 2533 |
/* GPIO */ |
2571 |
ppc405_gpio_init(env, mmio, 0x700);
|
|
2534 |
ppc405_gpio_init(0xef600700);
|
|
2572 | 2535 |
/* Serial ports */ |
2573 | 2536 |
if (serial_hds[0] != NULL) { |
2574 |
ppc405_serial_init(env, mmio, 0x300, pic[0], serial_hds[0]); |
|
2537 |
serial_mm_init(0xef600300, 0, pic[0], PPC_SERIAL_MM_BAUDBASE, |
|
2538 |
serial_hds[0], 1); |
|
2575 | 2539 |
} |
2576 | 2540 |
if (serial_hds[1] != NULL) { |
2577 |
ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]); |
|
2541 |
serial_mm_init(0xef600400, 0, pic[1], PPC_SERIAL_MM_BAUDBASE, |
|
2542 |
serial_hds[1], 1); |
|
2578 | 2543 |
} |
2579 | 2544 |
/* OCM */ |
2580 | 2545 |
ppc405_ocm_init(env); |
... | ... | |
2584 | 2549 |
gpt_irqs[2] = pic[21]; |
2585 | 2550 |
gpt_irqs[3] = pic[22]; |
2586 | 2551 |
gpt_irqs[4] = pic[23]; |
2587 |
ppc4xx_gpt_init(env, mmio, 0x000, gpt_irqs);
|
|
2552 |
ppc4xx_gpt_init(0xef600000, gpt_irqs);
|
|
2588 | 2553 |
/* PCI */ |
2589 | 2554 |
/* Uses pic[3], pic[16], pic[18] */ |
2590 | 2555 |
/* MAL */ |
b/hw/ppc440.c | ||
---|---|---|
12 | 12 |
*/ |
13 | 13 |
|
14 | 14 |
#include "hw.h" |
15 |
#include "pc.h" |
|
15 | 16 |
#include "isa.h" |
16 | 17 |
#include "ppc.h" |
17 | 18 |
#include "ppc4xx.h" |
... | ... | |
40 | 41 |
target_phys_addr_t ram_bases[PPC440EP_SDRAM_NR_BANKS]; |
41 | 42 |
target_phys_addr_t ram_sizes[PPC440EP_SDRAM_NR_BANKS]; |
42 | 43 |
CPUState *env; |
43 |
ppc4xx_mmio_t *mmio; |
|
44 | 44 |
qemu_irq *pic; |
45 | 45 |
qemu_irq *irqs; |
46 | 46 |
qemu_irq *pci_irqs; |
... | ... | |
87 | 87 |
|
88 | 88 |
isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN); |
89 | 89 |
|
90 |
/* MMIO -- most "miscellaneous" devices live above 0xef600000. */
|
|
91 |
mmio = ppc4xx_mmio_init(env, 0xef600000);
|
|
92 |
|
|
93 |
if (serial_hds[0])
|
|
94 |
ppc405_serial_init(env, mmio, 0x300, pic[0], serial_hds[0]);
|
|
95 |
|
|
96 |
if (serial_hds[1])
|
|
97 |
ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]);
|
|
90 |
if (serial_hds[0] != NULL) {
|
|
91 |
serial_mm_init(0xef600300, 0, pic[0], PPC_SERIAL_MM_BAUDBASE,
|
|
92 |
serial_hds[0], 1); |
|
93 |
}
|
|
94 |
if (serial_hds[1] != NULL) {
|
|
95 |
serial_mm_init(0xef600400, 0, pic[1], PPC_SERIAL_MM_BAUDBASE, |
|
96 |
serial_hds[1], 1);
|
|
97 |
}
|
|
98 | 98 |
|
99 | 99 |
return env; |
100 | 100 |
} |
b/hw/ppc4xx.h | ||
---|---|---|
32 | 32 |
clk_setup_t *cpu_clk, clk_setup_t *tb_clk, |
33 | 33 |
uint32_t sysclk); |
34 | 34 |
|
35 |
typedef struct ppc4xx_mmio_t ppc4xx_mmio_t; |
|
36 |
int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, |
|
37 |
target_phys_addr_t offset, uint32_t len, |
|
38 |
CPUReadMemoryFunc **mem_read, |
|
39 |
CPUWriteMemoryFunc **mem_write, void *opaque); |
|
40 |
ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base); |
|
41 |
|
|
42 | 35 |
/* PowerPC 4xx universal interrupt controller */ |
43 | 36 |
enum { |
44 | 37 |
PPCUIC_OUTPUT_INT = 0, |
b/hw/ppc4xx_devs.c | ||
---|---|---|
66 | 66 |
} |
67 | 67 |
|
68 | 68 |
/*****************************************************************************/ |
69 |
/* Fake device used to map multiple devices in a single memory page */ |
|
70 |
#define MMIO_AREA_BITS 8 |
|
71 |
#define MMIO_AREA_LEN (1 << MMIO_AREA_BITS) |
|
72 |
#define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS)) |
|
73 |
#define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1)) |
|
74 |
struct ppc4xx_mmio_t { |
|
75 |
target_phys_addr_t base; |
|
76 |
CPUReadMemoryFunc **mem_read[MMIO_AREA_NB]; |
|
77 |
CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB]; |
|
78 |
void *opaque[MMIO_AREA_NB]; |
|
79 |
}; |
|
80 |
|
|
81 |
static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr) |
|
82 |
{ |
|
83 |
#ifdef DEBUG_UNASSIGNED |
|
84 |
ppc4xx_mmio_t *mmio; |
|
85 |
|
|
86 |
mmio = opaque; |
|
87 |
printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n", |
|
88 |
addr, mmio->base); |
|
89 |
#endif |
|
90 |
|
|
91 |
return 0; |
|
92 |
} |
|
93 |
|
|
94 |
static void unassigned_mmio_writeb (void *opaque, |
|
95 |
target_phys_addr_t addr, uint32_t val) |
|
96 |
{ |
|
97 |
#ifdef DEBUG_UNASSIGNED |
|
98 |
ppc4xx_mmio_t *mmio; |
|
99 |
|
|
100 |
mmio = opaque; |
|
101 |
printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n", |
|
102 |
addr, val, mmio->base); |
|
103 |
#endif |
|
104 |
} |
|
105 |
|
|
106 |
static CPUReadMemoryFunc *unassigned_mmio_read[3] = { |
|
107 |
unassigned_mmio_readb, |
|
108 |
unassigned_mmio_readb, |
|
109 |
unassigned_mmio_readb, |
|
110 |
}; |
|
111 |
|
|
112 |
static CPUWriteMemoryFunc *unassigned_mmio_write[3] = { |
|
113 |
unassigned_mmio_writeb, |
|
114 |
unassigned_mmio_writeb, |
|
115 |
unassigned_mmio_writeb, |
|
116 |
}; |
|
117 |
|
|
118 |
static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio, |
|
119 |
target_phys_addr_t addr, int len) |
|
120 |
{ |
|
121 |
CPUReadMemoryFunc **mem_read; |
|
122 |
uint32_t ret; |
|
123 |
int idx; |
|
124 |
|
|
125 |
idx = MMIO_IDX(addr); |
|
126 |
#if defined(DEBUG_MMIO) |
|
127 |
printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__, |
|
128 |
mmio, len, addr, idx); |
|
129 |
#endif |
|
130 |
mem_read = mmio->mem_read[idx]; |
|
131 |
ret = (*mem_read[len])(mmio->opaque[idx], addr); |
|
132 |
|
|
133 |
return ret; |
|
134 |
} |
|
135 |
|
|
136 |
static void mmio_writelen (ppc4xx_mmio_t *mmio, |
|
137 |
target_phys_addr_t addr, uint32_t value, int len) |
|
138 |
{ |
|
139 |
CPUWriteMemoryFunc **mem_write; |
|
140 |
int idx; |
|
141 |
|
|
142 |
idx = MMIO_IDX(addr); |
|
143 |
#if defined(DEBUG_MMIO) |
|
144 |
printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08" PRIx32 "\n", |
|
145 |
__func__, mmio, len, addr, idx, value); |
|
146 |
#endif |
|
147 |
mem_write = mmio->mem_write[idx]; |
|
148 |
(*mem_write[len])(mmio->opaque[idx], addr, value); |
|
149 |
} |
|
150 |
|
|
151 |
static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr) |
|
152 |
{ |
|
153 |
#if defined(DEBUG_MMIO) |
|
154 |
printf("%s: addr " PADDRX "\n", __func__, addr); |
|
155 |
#endif |
|
156 |
|
|
157 |
return mmio_readlen(opaque, addr, 0); |
|
158 |
} |
|
159 |
|
|
160 |
static void mmio_writeb (void *opaque, |
|
161 |
target_phys_addr_t addr, uint32_t value) |
|
162 |
{ |
|
163 |
#if defined(DEBUG_MMIO) |
|
164 |
printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); |
|
165 |
#endif |
|
166 |
mmio_writelen(opaque, addr, value, 0); |
|
167 |
} |
|
168 |
|
|
169 |
static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr) |
|
170 |
{ |
|
171 |
#if defined(DEBUG_MMIO) |
|
172 |
printf("%s: addr " PADDRX "\n", __func__, addr); |
|
173 |
#endif |
|
174 |
|
|
175 |
return mmio_readlen(opaque, addr, 1); |
|
176 |
} |
|
177 |
|
|
178 |
static void mmio_writew (void *opaque, |
|
179 |
target_phys_addr_t addr, uint32_t value) |
|
180 |
{ |
|
181 |
#if defined(DEBUG_MMIO) |
|
182 |
printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); |
|
183 |
#endif |
|
184 |
mmio_writelen(opaque, addr, value, 1); |
|
185 |
} |
|
186 |
|
|
187 |
static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr) |
|
188 |
{ |
|
189 |
#if defined(DEBUG_MMIO) |
|
190 |
printf("%s: addr " PADDRX "\n", __func__, addr); |
|
191 |
#endif |
|
192 |
|
|
193 |
return mmio_readlen(opaque, addr, 2); |
|
194 |
} |
|
195 |
|
|
196 |
static void mmio_writel (void *opaque, |
|
197 |
target_phys_addr_t addr, uint32_t value) |
|
198 |
{ |
|
199 |
#if defined(DEBUG_MMIO) |
|
200 |
printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); |
|
201 |
#endif |
|
202 |
mmio_writelen(opaque, addr, value, 2); |
|
203 |
} |
|
204 |
|
|
205 |
static CPUReadMemoryFunc *mmio_read[] = { |
|
206 |
&mmio_readb, |
|
207 |
&mmio_readw, |
|
208 |
&mmio_readl, |
|
209 |
}; |
|
210 |
|
|
211 |
static CPUWriteMemoryFunc *mmio_write[] = { |
|
212 |
&mmio_writeb, |
|
213 |
&mmio_writew, |
|
214 |
&mmio_writel, |
|
215 |
}; |
|
216 |
|
|
217 |
int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, |
|
218 |
target_phys_addr_t offset, uint32_t len, |
|
219 |
CPUReadMemoryFunc **mem_read, |
|
220 |
CPUWriteMemoryFunc **mem_write, void *opaque) |
|
221 |
{ |
|
222 |
target_phys_addr_t end; |
|
223 |
int idx, eidx; |
|
224 |
|
|
225 |
if ((offset + len) > TARGET_PAGE_SIZE) |
|
226 |
return -1; |
|
227 |
idx = MMIO_IDX(offset); |
|
228 |
end = offset + len - 1; |
|
229 |
eidx = MMIO_IDX(end); |
|
230 |
#if defined(DEBUG_MMIO) |
|
231 |
printf("%s: offset " PADDRX " len %08" PRIx32 " " PADDRX " %d %d\n", |
|
232 |
__func__, offset, len, end, idx, eidx); |
|
233 |
#endif |
|
234 |
for (; idx <= eidx; idx++) { |
|
235 |
mmio->mem_read[idx] = mem_read; |
|
236 |
mmio->mem_write[idx] = mem_write; |
|
237 |
mmio->opaque[idx] = opaque; |
|
238 |
} |
|
239 |
|
|
240 |
return 0; |
|
241 |
} |
|
242 |
|
|
243 |
ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base) |
|
244 |
{ |
|
245 |
ppc4xx_mmio_t *mmio; |
|
246 |
int mmio_memory; |
|
247 |
|
|
248 |
mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t)); |
|
249 |
mmio->base = base; |
|
250 |
mmio_memory = cpu_register_io_memory(mmio_read, mmio_write, mmio); |
|
251 |
#if defined(DEBUG_MMIO) |
|
252 |
printf("%s: base " PADDRX " len %08x %d\n", __func__, |
|
253 |
base, TARGET_PAGE_SIZE, mmio_memory); |
|
254 |
#endif |
|
255 |
cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory); |
|
256 |
ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE, |
|
257 |
unassigned_mmio_read, unassigned_mmio_write, |
|
258 |
mmio); |
|
259 |
|
|
260 |
return mmio; |
|
261 |
} |
|
262 |
|
|
263 |
/*****************************************************************************/ |
|
264 | 69 |
/* "Universal" Interrupt controller */ |
265 | 70 |
enum { |
266 | 71 |
DCR_UICSR = 0x000, |
b/hw/serial.c | ||
---|---|---|
745 | 745 |
} |
746 | 746 |
|
747 | 747 |
/* Memory mapped interface */ |
748 |
uint32_t serial_mm_readb (void *opaque, target_phys_addr_t addr)
|
|
748 |
static uint32_t serial_mm_readb(void *opaque, target_phys_addr_t addr)
|
|
749 | 749 |
{ |
750 | 750 |
SerialState *s = opaque; |
751 | 751 |
|
752 | 752 |
return serial_ioport_read(s, addr >> s->it_shift) & 0xFF; |
753 | 753 |
} |
754 | 754 |
|
755 |
void serial_mm_writeb (void *opaque,
|
|
756 |
target_phys_addr_t addr, uint32_t value)
|
|
755 |
static void serial_mm_writeb(void *opaque, target_phys_addr_t addr,
|
|
756 |
uint32_t value)
|
|
757 | 757 |
{ |
758 | 758 |
SerialState *s = opaque; |
759 | 759 |
|
760 | 760 |
serial_ioport_write(s, addr >> s->it_shift, value & 0xFF); |
761 | 761 |
} |
762 | 762 |
|
763 |
uint32_t serial_mm_readw (void *opaque, target_phys_addr_t addr)
|
|
763 |
static uint32_t serial_mm_readw(void *opaque, target_phys_addr_t addr)
|
|
764 | 764 |
{ |
765 | 765 |
SerialState *s = opaque; |
766 | 766 |
uint32_t val; |
... | ... | |
772 | 772 |
return val; |
773 | 773 |
} |
774 | 774 |
|
775 |
void serial_mm_writew (void *opaque,
|
|
776 |
target_phys_addr_t addr, uint32_t value)
|
|
775 |
static void serial_mm_writew(void *opaque, target_phys_addr_t addr,
|
|
776 |
uint32_t value)
|
|
777 | 777 |
{ |
778 | 778 |
SerialState *s = opaque; |
779 | 779 |
#ifdef TARGET_WORDS_BIGENDIAN |
... | ... | |
782 | 782 |
serial_ioport_write(s, addr >> s->it_shift, value & 0xFFFF); |
783 | 783 |
} |
784 | 784 |
|
785 |
uint32_t serial_mm_readl (void *opaque, target_phys_addr_t addr)
|
|
785 |
static uint32_t serial_mm_readl(void *opaque, target_phys_addr_t addr)
|
|
786 | 786 |
{ |
787 | 787 |
SerialState *s = opaque; |
788 | 788 |
uint32_t val; |
... | ... | |
794 | 794 |
return val; |
795 | 795 |
} |
796 | 796 |
|
797 |
void serial_mm_writel (void *opaque,
|
|
798 |
target_phys_addr_t addr, uint32_t value)
|
|
797 |
static void serial_mm_writel(void *opaque, target_phys_addr_t addr,
|
|
798 |
uint32_t value)
|
|
799 | 799 |
{ |
800 | 800 |
SerialState *s = opaque; |
801 | 801 |
#ifdef TARGET_WORDS_BIGENDIAN |
Also available in: Unified diff