Commit 9c02f1a2e607b7be71f2dba1cafc096dd3c2dda9
1 parent
4b6d0a4c
PowerPC 405 microcontrollers fixes and improvments:
- use target_phys_addr_t for physical addresses / offsets - implement fake general purpose timers and memory access layer for PowerPC 405EP - more assigned internal IRQs. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2716 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
673 additions
and
49 deletions
hw/ppc405.h
| @@ -62,16 +62,17 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd); | @@ -62,16 +62,17 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd); | ||
| 62 | /* */ | 62 | /* */ |
| 63 | typedef struct ppc4xx_mmio_t ppc4xx_mmio_t; | 63 | typedef struct ppc4xx_mmio_t ppc4xx_mmio_t; |
| 64 | int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, | 64 | int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, |
| 65 | - uint32_t offset, uint32_t len, | 65 | + target_phys_addr_t offset, uint32_t len, |
| 66 | CPUReadMemoryFunc **mem_read, | 66 | CPUReadMemoryFunc **mem_read, |
| 67 | CPUWriteMemoryFunc **mem_write, void *opaque); | 67 | CPUWriteMemoryFunc **mem_write, void *opaque); |
| 68 | -ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, uint32_t base); | 68 | +ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base); |
| 69 | /* PowerPC 4xx peripheral local bus arbitrer */ | 69 | /* PowerPC 4xx peripheral local bus arbitrer */ |
| 70 | void ppc4xx_plb_init (CPUState *env); | 70 | void ppc4xx_plb_init (CPUState *env); |
| 71 | /* PLB to OPB bridge */ | 71 | /* PLB to OPB bridge */ |
| 72 | void ppc4xx_pob_init (CPUState *env); | 72 | void ppc4xx_pob_init (CPUState *env); |
| 73 | /* OPB arbitrer */ | 73 | /* OPB arbitrer */ |
| 74 | -void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset); | 74 | +void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, |
| 75 | + target_phys_addr_t offset); | ||
| 75 | /* PowerPC 4xx universal interrupt controller */ | 76 | /* PowerPC 4xx universal interrupt controller */ |
| 76 | enum { | 77 | enum { |
| 77 | PPCUIC_OUTPUT_INT = 0, | 78 | PPCUIC_OUTPUT_INT = 0, |
| @@ -89,15 +90,22 @@ void ppc405_ebc_init (CPUState *env); | @@ -89,15 +90,22 @@ void ppc405_ebc_init (CPUState *env); | ||
| 89 | /* DMA controller */ | 90 | /* DMA controller */ |
| 90 | void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]); | 91 | void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]); |
| 91 | /* GPIO */ | 92 | /* GPIO */ |
| 92 | -void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset); | 93 | +void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, |
| 94 | + target_phys_addr_t offset); | ||
| 93 | /* Serial ports */ | 95 | /* Serial ports */ |
| 94 | void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio, | 96 | void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio, |
| 95 | - uint32_t offset, qemu_irq irq, | 97 | + target_phys_addr_t offset, qemu_irq irq, |
| 96 | CharDriverState *chr); | 98 | CharDriverState *chr); |
| 97 | /* On Chip Memory */ | 99 | /* On Chip Memory */ |
| 98 | void ppc405_ocm_init (CPUState *env, unsigned long offset); | 100 | void ppc405_ocm_init (CPUState *env, unsigned long offset); |
| 99 | /* I2C controller */ | 101 | /* I2C controller */ |
| 100 | -void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset); | 102 | +void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, |
| 103 | + target_phys_addr_t offset, qemu_irq irq); | ||
| 104 | +/* General purpose timers */ | ||
| 105 | +void ppc4xx_gpt_init (CPUState *env, ppc4xx_mmio_t *mmio, | ||
| 106 | + target_phys_addr_t offset, qemu_irq irq[5]); | ||
| 107 | +/* Memory access layer */ | ||
| 108 | +void ppc405_mal_init (CPUState *env, qemu_irq irqs[4]); | ||
| 101 | /* PowerPC 405 microcontrollers */ | 109 | /* PowerPC 405 microcontrollers */ |
| 102 | CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], | 110 | CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], |
| 103 | uint32_t sysclk, qemu_irq **picp, | 111 | uint32_t sysclk, qemu_irq **picp, |
hw/ppc405_uc.c
| @@ -27,16 +27,18 @@ | @@ -27,16 +27,18 @@ | ||
| 27 | extern int loglevel; | 27 | extern int loglevel; |
| 28 | extern FILE *logfile; | 28 | extern FILE *logfile; |
| 29 | 29 | ||
| 30 | -#define DEBUG_MMIO | 30 | +//#define DEBUG_MMIO |
| 31 | #define DEBUG_OPBA | 31 | #define DEBUG_OPBA |
| 32 | #define DEBUG_SDRAM | 32 | #define DEBUG_SDRAM |
| 33 | #define DEBUG_GPIO | 33 | #define DEBUG_GPIO |
| 34 | #define DEBUG_SERIAL | 34 | #define DEBUG_SERIAL |
| 35 | #define DEBUG_OCM | 35 | #define DEBUG_OCM |
| 36 | -#define DEBUG_I2C | 36 | +//#define DEBUG_I2C |
| 37 | +#define DEBUG_GPT | ||
| 38 | +#define DEBUG_MAL | ||
| 37 | #define DEBUG_UIC | 39 | #define DEBUG_UIC |
| 38 | #define DEBUG_CLOCKS | 40 | #define DEBUG_CLOCKS |
| 39 | -#define DEBUG_UNASSIGNED | 41 | +//#define DEBUG_UNASSIGNED |
| 40 | 42 | ||
| 41 | /*****************************************************************************/ | 43 | /*****************************************************************************/ |
| 42 | /* Generic PowerPC 405 processor instanciation */ | 44 | /* Generic PowerPC 405 processor instanciation */ |
| @@ -122,39 +124,47 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd) | @@ -122,39 +124,47 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd) | ||
| 122 | #define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS)) | 124 | #define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS)) |
| 123 | #define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1)) | 125 | #define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1)) |
| 124 | struct ppc4xx_mmio_t { | 126 | struct ppc4xx_mmio_t { |
| 125 | - uint32_t base; | 127 | + target_phys_addr_t base; |
| 126 | CPUReadMemoryFunc **mem_read[MMIO_AREA_NB]; | 128 | CPUReadMemoryFunc **mem_read[MMIO_AREA_NB]; |
| 127 | CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB]; | 129 | CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB]; |
| 128 | void *opaque[MMIO_AREA_NB]; | 130 | void *opaque[MMIO_AREA_NB]; |
| 129 | }; | 131 | }; |
| 130 | 132 | ||
| 131 | -static uint32_t unassigned_mem_readb (void *opaque, target_phys_addr_t addr) | 133 | +static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr) |
| 132 | { | 134 | { |
| 133 | #ifdef DEBUG_UNASSIGNED | 135 | #ifdef DEBUG_UNASSIGNED |
| 134 | - printf("Unassigned mem read 0x" PADDRX "\n", addr); | 136 | + ppc4xx_mmio_t *mmio; |
| 137 | + | ||
| 138 | + mmio = opaque; | ||
| 139 | + printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n", | ||
| 140 | + addr, mmio->base); | ||
| 135 | #endif | 141 | #endif |
| 136 | 142 | ||
| 137 | return 0; | 143 | return 0; |
| 138 | } | 144 | } |
| 139 | 145 | ||
| 140 | -static void unassigned_mem_writeb (void *opaque, | 146 | +static void unassigned_mmio_writeb (void *opaque, |
| 141 | target_phys_addr_t addr, uint32_t val) | 147 | target_phys_addr_t addr, uint32_t val) |
| 142 | { | 148 | { |
| 143 | #ifdef DEBUG_UNASSIGNED | 149 | #ifdef DEBUG_UNASSIGNED |
| 144 | - printf("Unassigned mem write 0x" PADDRX " = 0x%x\n", addr, val); | 150 | + ppc4xx_mmio_t *mmio; |
| 151 | + | ||
| 152 | + mmio = opaque; | ||
| 153 | + printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n", | ||
| 154 | + addr, val, mmio->base); | ||
| 145 | #endif | 155 | #endif |
| 146 | } | 156 | } |
| 147 | 157 | ||
| 148 | -static CPUReadMemoryFunc *unassigned_mem_read[3] = { | ||
| 149 | - unassigned_mem_readb, | ||
| 150 | - unassigned_mem_readb, | ||
| 151 | - unassigned_mem_readb, | 158 | +static CPUReadMemoryFunc *unassigned_mmio_read[3] = { |
| 159 | + unassigned_mmio_readb, | ||
| 160 | + unassigned_mmio_readb, | ||
| 161 | + unassigned_mmio_readb, | ||
| 152 | }; | 162 | }; |
| 153 | 163 | ||
| 154 | -static CPUWriteMemoryFunc *unassigned_mem_write[3] = { | ||
| 155 | - unassigned_mem_writeb, | ||
| 156 | - unassigned_mem_writeb, | ||
| 157 | - unassigned_mem_writeb, | 164 | +static CPUWriteMemoryFunc *unassigned_mmio_write[3] = { |
| 165 | + unassigned_mmio_writeb, | ||
| 166 | + unassigned_mmio_writeb, | ||
| 167 | + unassigned_mmio_writeb, | ||
| 158 | }; | 168 | }; |
| 159 | 169 | ||
| 160 | static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio, | 170 | static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio, |
| @@ -170,7 +180,7 @@ static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio, | @@ -170,7 +180,7 @@ static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio, | ||
| 170 | mmio, len, addr, idx); | 180 | mmio, len, addr, idx); |
| 171 | #endif | 181 | #endif |
| 172 | mem_read = mmio->mem_read[idx]; | 182 | mem_read = mmio->mem_read[idx]; |
| 173 | - ret = (*mem_read[len])(mmio->opaque[idx], addr); | 183 | + ret = (*mem_read[len])(mmio->opaque[idx], addr - mmio->base); |
| 174 | 184 | ||
| 175 | return ret; | 185 | return ret; |
| 176 | } | 186 | } |
| @@ -187,7 +197,7 @@ static void mmio_writelen (ppc4xx_mmio_t *mmio, | @@ -187,7 +197,7 @@ static void mmio_writelen (ppc4xx_mmio_t *mmio, | ||
| 187 | mmio, len, addr, idx, value); | 197 | mmio, len, addr, idx, value); |
| 188 | #endif | 198 | #endif |
| 189 | mem_write = mmio->mem_write[idx]; | 199 | mem_write = mmio->mem_write[idx]; |
| 190 | - (*mem_write[len])(mmio->opaque[idx], addr, value); | 200 | + (*mem_write[len])(mmio->opaque[idx], addr - mmio->base, value); |
| 191 | } | 201 | } |
| 192 | 202 | ||
| 193 | static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr) | 203 | static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr) |
| @@ -257,7 +267,7 @@ static CPUWriteMemoryFunc *mmio_write[] = { | @@ -257,7 +267,7 @@ static CPUWriteMemoryFunc *mmio_write[] = { | ||
| 257 | }; | 267 | }; |
| 258 | 268 | ||
| 259 | int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, | 269 | int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, |
| 260 | - uint32_t offset, uint32_t len, | 270 | + target_phys_addr_t offset, uint32_t len, |
| 261 | CPUReadMemoryFunc **mem_read, | 271 | CPUReadMemoryFunc **mem_read, |
| 262 | CPUWriteMemoryFunc **mem_write, void *opaque) | 272 | CPUWriteMemoryFunc **mem_write, void *opaque) |
| 263 | { | 273 | { |
| @@ -282,7 +292,7 @@ int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, | @@ -282,7 +292,7 @@ int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, | ||
| 282 | return 0; | 292 | return 0; |
| 283 | } | 293 | } |
| 284 | 294 | ||
| 285 | -ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, uint32_t base) | 295 | +ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base) |
| 286 | { | 296 | { |
| 287 | ppc4xx_mmio_t *mmio; | 297 | ppc4xx_mmio_t *mmio; |
| 288 | int mmio_memory; | 298 | int mmio_memory; |
| @@ -297,7 +307,8 @@ ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, uint32_t base) | @@ -297,7 +307,8 @@ ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, uint32_t base) | ||
| 297 | #endif | 307 | #endif |
| 298 | cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory); | 308 | cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory); |
| 299 | ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE, | 309 | ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE, |
| 300 | - unassigned_mem_read, unassigned_mem_write, NULL); | 310 | + unassigned_mmio_read, unassigned_mmio_write, |
| 311 | + mmio); | ||
| 301 | } | 312 | } |
| 302 | 313 | ||
| 303 | return mmio; | 314 | return mmio; |
| @@ -350,7 +361,10 @@ static void dcr_write_plb (void *opaque, int dcrn, target_ulong val) | @@ -350,7 +361,10 @@ static void dcr_write_plb (void *opaque, int dcrn, target_ulong val) | ||
| 350 | plb = opaque; | 361 | plb = opaque; |
| 351 | switch (dcrn) { | 362 | switch (dcrn) { |
| 352 | case PLB0_ACR: | 363 | case PLB0_ACR: |
| 353 | - plb->acr = val & 0xFC000000; | 364 | + /* We don't care about the actual parameters written as |
| 365 | + * we don't manage any priorities on the bus | ||
| 366 | + */ | ||
| 367 | + plb->acr = val & 0xF8000000; | ||
| 354 | break; | 368 | break; |
| 355 | case PLB0_BEAR: | 369 | case PLB0_BEAR: |
| 356 | /* Read only */ | 370 | /* Read only */ |
| @@ -469,7 +483,7 @@ void ppc4xx_pob_init (CPUState *env) | @@ -469,7 +483,7 @@ void ppc4xx_pob_init (CPUState *env) | ||
| 469 | /* OPB arbitrer */ | 483 | /* OPB arbitrer */ |
| 470 | typedef struct ppc4xx_opba_t ppc4xx_opba_t; | 484 | typedef struct ppc4xx_opba_t ppc4xx_opba_t; |
| 471 | struct ppc4xx_opba_t { | 485 | struct ppc4xx_opba_t { |
| 472 | - target_ulong base; | 486 | + target_phys_addr_t base; |
| 473 | uint8_t cr; | 487 | uint8_t cr; |
| 474 | uint8_t pr; | 488 | uint8_t pr; |
| 475 | }; | 489 | }; |
| @@ -586,15 +600,16 @@ static void ppc4xx_opba_reset (void *opaque) | @@ -586,15 +600,16 @@ static void ppc4xx_opba_reset (void *opaque) | ||
| 586 | opba->pr = 0x11; | 600 | opba->pr = 0x11; |
| 587 | } | 601 | } |
| 588 | 602 | ||
| 589 | -void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset) | 603 | +void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, |
| 604 | + target_phys_addr_t offset) | ||
| 590 | { | 605 | { |
| 591 | ppc4xx_opba_t *opba; | 606 | ppc4xx_opba_t *opba; |
| 592 | 607 | ||
| 593 | opba = qemu_mallocz(sizeof(ppc4xx_opba_t)); | 608 | opba = qemu_mallocz(sizeof(ppc4xx_opba_t)); |
| 594 | if (opba != NULL) { | 609 | if (opba != NULL) { |
| 595 | - opba->base = mmio->base + offset; | 610 | + opba->base = offset; |
| 596 | #ifdef DEBUG_OPBA | 611 | #ifdef DEBUG_OPBA |
| 597 | - printf("%s: offset=%08x\n", __func__, offset); | 612 | + printf("%s: offset=" PADDRX "\n", __func__, offset); |
| 598 | #endif | 613 | #endif |
| 599 | ppc4xx_mmio_register(env, mmio, offset, 0x002, | 614 | ppc4xx_mmio_register(env, mmio, offset, 0x002, |
| 600 | opba_read, opba_write, opba); | 615 | opba_read, opba_write, opba); |
| @@ -1392,7 +1407,7 @@ static void ebc_reset (void *opaque) | @@ -1392,7 +1407,7 @@ static void ebc_reset (void *opaque) | ||
| 1392 | } | 1407 | } |
| 1393 | ebc->besr0 = 0x00000000; | 1408 | ebc->besr0 = 0x00000000; |
| 1394 | ebc->besr1 = 0x00000000; | 1409 | ebc->besr1 = 0x00000000; |
| 1395 | - ebc->cfg = 0x07C00000; | 1410 | + ebc->cfg = 0x80400000; |
| 1396 | } | 1411 | } |
| 1397 | 1412 | ||
| 1398 | void ppc405_ebc_init (CPUState *env) | 1413 | void ppc405_ebc_init (CPUState *env) |
| @@ -1552,7 +1567,7 @@ void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]) | @@ -1552,7 +1567,7 @@ void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]) | ||
| 1552 | /* GPIO */ | 1567 | /* GPIO */ |
| 1553 | typedef struct ppc405_gpio_t ppc405_gpio_t; | 1568 | typedef struct ppc405_gpio_t ppc405_gpio_t; |
| 1554 | struct ppc405_gpio_t { | 1569 | struct ppc405_gpio_t { |
| 1555 | - uint32_t base; | 1570 | + target_phys_addr_t base; |
| 1556 | uint32_t or; | 1571 | uint32_t or; |
| 1557 | uint32_t tcr; | 1572 | uint32_t tcr; |
| 1558 | uint32_t osrh; | 1573 | uint32_t osrh; |
| @@ -1654,17 +1669,18 @@ static void ppc405_gpio_reset (void *opaque) | @@ -1654,17 +1669,18 @@ static void ppc405_gpio_reset (void *opaque) | ||
| 1654 | gpio = opaque; | 1669 | gpio = opaque; |
| 1655 | } | 1670 | } |
| 1656 | 1671 | ||
| 1657 | -void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset) | 1672 | +void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, |
| 1673 | + target_phys_addr_t offset) | ||
| 1658 | { | 1674 | { |
| 1659 | ppc405_gpio_t *gpio; | 1675 | ppc405_gpio_t *gpio; |
| 1660 | 1676 | ||
| 1661 | gpio = qemu_mallocz(sizeof(ppc405_gpio_t)); | 1677 | gpio = qemu_mallocz(sizeof(ppc405_gpio_t)); |
| 1662 | if (gpio != NULL) { | 1678 | if (gpio != NULL) { |
| 1663 | - gpio->base = mmio->base + offset; | 1679 | + gpio->base = offset; |
| 1664 | ppc405_gpio_reset(gpio); | 1680 | ppc405_gpio_reset(gpio); |
| 1665 | qemu_register_reset(&ppc405_gpio_reset, gpio); | 1681 | qemu_register_reset(&ppc405_gpio_reset, gpio); |
| 1666 | #ifdef DEBUG_GPIO | 1682 | #ifdef DEBUG_GPIO |
| 1667 | - printf("%s: offset=%08x\n", __func__, offset); | 1683 | + printf("%s: offset=" PADDRX "\n", __func__, offset); |
| 1668 | #endif | 1684 | #endif |
| 1669 | ppc4xx_mmio_register(env, mmio, offset, 0x038, | 1685 | ppc4xx_mmio_register(env, mmio, offset, 0x038, |
| 1670 | ppc405_gpio_read, ppc405_gpio_write, gpio); | 1686 | ppc405_gpio_read, ppc405_gpio_write, gpio); |
| @@ -1686,15 +1702,15 @@ static CPUWriteMemoryFunc *serial_mm_write[] = { | @@ -1686,15 +1702,15 @@ static CPUWriteMemoryFunc *serial_mm_write[] = { | ||
| 1686 | }; | 1702 | }; |
| 1687 | 1703 | ||
| 1688 | void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio, | 1704 | void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio, |
| 1689 | - uint32_t offset, qemu_irq irq, | 1705 | + target_phys_addr_t offset, qemu_irq irq, |
| 1690 | CharDriverState *chr) | 1706 | CharDriverState *chr) |
| 1691 | { | 1707 | { |
| 1692 | void *serial; | 1708 | void *serial; |
| 1693 | 1709 | ||
| 1694 | #ifdef DEBUG_SERIAL | 1710 | #ifdef DEBUG_SERIAL |
| 1695 | - printf("%s: offset=%08x\n", __func__, offset); | 1711 | + printf("%s: offset=" PADDRX "\n", __func__, offset); |
| 1696 | #endif | 1712 | #endif |
| 1697 | - serial = serial_mm_init(mmio->base + offset, 0, irq, chr, 0); | 1713 | + serial = serial_mm_init(offset, 0, irq, chr, 0); |
| 1698 | ppc4xx_mmio_register(env, mmio, offset, 0x008, | 1714 | ppc4xx_mmio_register(env, mmio, offset, 0x008, |
| 1699 | serial_mm_read, serial_mm_write, serial); | 1715 | serial_mm_read, serial_mm_write, serial); |
| 1700 | } | 1716 | } |
| @@ -1869,7 +1885,8 @@ void ppc405_ocm_init (CPUState *env, unsigned long offset) | @@ -1869,7 +1885,8 @@ void ppc405_ocm_init (CPUState *env, unsigned long offset) | ||
| 1869 | /* I2C controller */ | 1885 | /* I2C controller */ |
| 1870 | typedef struct ppc4xx_i2c_t ppc4xx_i2c_t; | 1886 | typedef struct ppc4xx_i2c_t ppc4xx_i2c_t; |
| 1871 | struct ppc4xx_i2c_t { | 1887 | struct ppc4xx_i2c_t { |
| 1872 | - uint32_t base; | 1888 | + target_phys_addr_t base; |
| 1889 | + qemu_irq irq; | ||
| 1873 | uint8_t mdata; | 1890 | uint8_t mdata; |
| 1874 | uint8_t lmadr; | 1891 | uint8_t lmadr; |
| 1875 | uint8_t hmadr; | 1892 | uint8_t hmadr; |
| @@ -2091,16 +2108,18 @@ static void ppc4xx_i2c_reset (void *opaque) | @@ -2091,16 +2108,18 @@ static void ppc4xx_i2c_reset (void *opaque) | ||
| 2091 | i2c->directcntl = 0x0F; | 2108 | i2c->directcntl = 0x0F; |
| 2092 | } | 2109 | } |
| 2093 | 2110 | ||
| 2094 | -void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset) | 2111 | +void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, |
| 2112 | + target_phys_addr_t offset, qemu_irq irq) | ||
| 2095 | { | 2113 | { |
| 2096 | ppc4xx_i2c_t *i2c; | 2114 | ppc4xx_i2c_t *i2c; |
| 2097 | 2115 | ||
| 2098 | i2c = qemu_mallocz(sizeof(ppc4xx_i2c_t)); | 2116 | i2c = qemu_mallocz(sizeof(ppc4xx_i2c_t)); |
| 2099 | if (i2c != NULL) { | 2117 | if (i2c != NULL) { |
| 2100 | - i2c->base = mmio->base + offset; | 2118 | + i2c->base = offset; |
| 2119 | + i2c->irq = irq; | ||
| 2101 | ppc4xx_i2c_reset(i2c); | 2120 | ppc4xx_i2c_reset(i2c); |
| 2102 | #ifdef DEBUG_I2C | 2121 | #ifdef DEBUG_I2C |
| 2103 | - printf("%s: offset=%08x\n", __func__, offset); | 2122 | + printf("%s: offset=" PADDRX "\n", __func__, offset); |
| 2104 | #endif | 2123 | #endif |
| 2105 | ppc4xx_mmio_register(env, mmio, offset, 0x011, | 2124 | ppc4xx_mmio_register(env, mmio, offset, 0x011, |
| 2106 | i2c_read, i2c_write, i2c); | 2125 | i2c_read, i2c_write, i2c); |
| @@ -2109,6 +2128,557 @@ void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset) | @@ -2109,6 +2128,557 @@ void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset) | ||
| 2109 | } | 2128 | } |
| 2110 | 2129 | ||
| 2111 | /*****************************************************************************/ | 2130 | /*****************************************************************************/ |
| 2131 | +/* General purpose timers */ | ||
| 2132 | +typedef struct ppc4xx_gpt_t ppc4xx_gpt_t; | ||
| 2133 | +struct ppc4xx_gpt_t { | ||
| 2134 | + target_phys_addr_t base; | ||
| 2135 | + int64_t tb_offset; | ||
| 2136 | + uint32_t tb_freq; | ||
| 2137 | + struct QEMUTimer *timer; | ||
| 2138 | + qemu_irq irqs[5]; | ||
| 2139 | + uint32_t oe; | ||
| 2140 | + uint32_t ol; | ||
| 2141 | + uint32_t im; | ||
| 2142 | + uint32_t is; | ||
| 2143 | + uint32_t ie; | ||
| 2144 | + uint32_t comp[5]; | ||
| 2145 | + uint32_t mask[5]; | ||
| 2146 | +}; | ||
| 2147 | + | ||
| 2148 | +static uint32_t ppc4xx_gpt_readb (void *opaque, target_phys_addr_t addr) | ||
| 2149 | +{ | ||
| 2150 | +#ifdef DEBUG_GPT | ||
| 2151 | + printf("%s: addr " PADDRX "\n", __func__, addr); | ||
| 2152 | +#endif | ||
| 2153 | + /* XXX: generate a bus fault */ | ||
| 2154 | + return -1; | ||
| 2155 | +} | ||
| 2156 | + | ||
| 2157 | +static void ppc4xx_gpt_writeb (void *opaque, | ||
| 2158 | + target_phys_addr_t addr, uint32_t value) | ||
| 2159 | +{ | ||
| 2160 | +#ifdef DEBUG_I2C | ||
| 2161 | + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); | ||
| 2162 | +#endif | ||
| 2163 | + /* XXX: generate a bus fault */ | ||
| 2164 | +} | ||
| 2165 | + | ||
| 2166 | +static uint32_t ppc4xx_gpt_readw (void *opaque, target_phys_addr_t addr) | ||
| 2167 | +{ | ||
| 2168 | +#ifdef DEBUG_GPT | ||
| 2169 | + printf("%s: addr " PADDRX "\n", __func__, addr); | ||
| 2170 | +#endif | ||
| 2171 | + /* XXX: generate a bus fault */ | ||
| 2172 | + return -1; | ||
| 2173 | +} | ||
| 2174 | + | ||
| 2175 | +static void ppc4xx_gpt_writew (void *opaque, | ||
| 2176 | + target_phys_addr_t addr, uint32_t value) | ||
| 2177 | +{ | ||
| 2178 | +#ifdef DEBUG_I2C | ||
| 2179 | + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); | ||
| 2180 | +#endif | ||
| 2181 | + /* XXX: generate a bus fault */ | ||
| 2182 | +} | ||
| 2183 | + | ||
| 2184 | +static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n) | ||
| 2185 | +{ | ||
| 2186 | + /* XXX: TODO */ | ||
| 2187 | + return 0; | ||
| 2188 | +} | ||
| 2189 | + | ||
| 2190 | +static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level) | ||
| 2191 | +{ | ||
| 2192 | + /* XXX: TODO */ | ||
| 2193 | +} | ||
| 2194 | + | ||
| 2195 | +static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt) | ||
| 2196 | +{ | ||
| 2197 | + uint32_t mask; | ||
| 2198 | + int i; | ||
| 2199 | + | ||
| 2200 | + mask = 0x80000000; | ||
| 2201 | + for (i = 0; i < 5; i++) { | ||
| 2202 | + if (gpt->oe & mask) { | ||
| 2203 | + /* Output is enabled */ | ||
| 2204 | + if (ppc4xx_gpt_compare(gpt, i)) { | ||
| 2205 | + /* Comparison is OK */ | ||
| 2206 | + ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask); | ||
| 2207 | + } else { | ||
| 2208 | + /* Comparison is KO */ | ||
| 2209 | + ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask ? 0 : 1); | ||
| 2210 | + } | ||
| 2211 | + } | ||
| 2212 | + mask = mask >> 1; | ||
| 2213 | + } | ||
| 2214 | + | ||
| 2215 | +} | ||
| 2216 | + | ||
| 2217 | +static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt) | ||
| 2218 | +{ | ||
| 2219 | + uint32_t mask; | ||
| 2220 | + int i; | ||
| 2221 | + | ||
| 2222 | + mask = 0x00008000; | ||
| 2223 | + for (i = 0; i < 5; i++) { | ||
| 2224 | + if (gpt->is & gpt->im & mask) | ||
| 2225 | + qemu_irq_raise(gpt->irqs[i]); | ||
| 2226 | + else | ||
| 2227 | + qemu_irq_lower(gpt->irqs[i]); | ||
| 2228 | + mask = mask >> 1; | ||
| 2229 | + } | ||
| 2230 | + | ||
| 2231 | +} | ||
| 2232 | + | ||
| 2233 | +static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt) | ||
| 2234 | +{ | ||
| 2235 | + /* XXX: TODO */ | ||
| 2236 | +} | ||
| 2237 | + | ||
| 2238 | +static uint32_t ppc4xx_gpt_readl (void *opaque, target_phys_addr_t addr) | ||
| 2239 | +{ | ||
| 2240 | + ppc4xx_gpt_t *gpt; | ||
| 2241 | + uint32_t ret; | ||
| 2242 | + int idx; | ||
| 2243 | + | ||
| 2244 | +#ifdef DEBUG_GPT | ||
| 2245 | + printf("%s: addr " PADDRX "\n", __func__, addr); | ||
| 2246 | +#endif | ||
| 2247 | + gpt = opaque; | ||
| 2248 | + switch (addr - gpt->base) { | ||
| 2249 | + case 0x00: | ||
| 2250 | + /* Time base counter */ | ||
| 2251 | + ret = muldiv64(qemu_get_clock(vm_clock) + gpt->tb_offset, | ||
| 2252 | + gpt->tb_freq, ticks_per_sec); | ||
| 2253 | + break; | ||
| 2254 | + case 0x10: | ||
| 2255 | + /* Output enable */ | ||
| 2256 | + ret = gpt->oe; | ||
| 2257 | + break; | ||
| 2258 | + case 0x14: | ||
| 2259 | + /* Output level */ | ||
| 2260 | + ret = gpt->ol; | ||
| 2261 | + break; | ||
| 2262 | + case 0x18: | ||
| 2263 | + /* Interrupt mask */ | ||
| 2264 | + ret = gpt->im; | ||
| 2265 | + break; | ||
| 2266 | + case 0x1C: | ||
| 2267 | + case 0x20: | ||
| 2268 | + /* Interrupt status */ | ||
| 2269 | + ret = gpt->is; | ||
| 2270 | + break; | ||
| 2271 | + case 0x24: | ||
| 2272 | + /* Interrupt enable */ | ||
| 2273 | + ret = gpt->ie; | ||
| 2274 | + break; | ||
| 2275 | + case 0x80 ... 0x90: | ||
| 2276 | + /* Compare timer */ | ||
| 2277 | + idx = ((addr - gpt->base) - 0x80) >> 2; | ||
| 2278 | + ret = gpt->comp[idx]; | ||
| 2279 | + break; | ||
| 2280 | + case 0xC0 ... 0xD0: | ||
| 2281 | + /* Compare mask */ | ||
| 2282 | + idx = ((addr - gpt->base) - 0xC0) >> 2; | ||
| 2283 | + ret = gpt->mask[idx]; | ||
| 2284 | + break; | ||
| 2285 | + default: | ||
| 2286 | + ret = -1; | ||
| 2287 | + break; | ||
| 2288 | + } | ||
| 2289 | + | ||
| 2290 | + return ret; | ||
| 2291 | +} | ||
| 2292 | + | ||
| 2293 | +static void ppc4xx_gpt_writel (void *opaque, | ||
| 2294 | + target_phys_addr_t addr, uint32_t value) | ||
| 2295 | +{ | ||
| 2296 | + ppc4xx_gpt_t *gpt; | ||
| 2297 | + int idx; | ||
| 2298 | + | ||
| 2299 | +#ifdef DEBUG_I2C | ||
| 2300 | + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); | ||
| 2301 | +#endif | ||
| 2302 | + gpt = opaque; | ||
| 2303 | + switch (addr - gpt->base) { | ||
| 2304 | + case 0x00: | ||
| 2305 | + /* Time base counter */ | ||
| 2306 | + gpt->tb_offset = muldiv64(value, ticks_per_sec, gpt->tb_freq) | ||
| 2307 | + - qemu_get_clock(vm_clock); | ||
| 2308 | + ppc4xx_gpt_compute_timer(gpt); | ||
| 2309 | + break; | ||
| 2310 | + case 0x10: | ||
| 2311 | + /* Output enable */ | ||
| 2312 | + gpt->oe = value & 0xF8000000; | ||
| 2313 | + ppc4xx_gpt_set_outputs(gpt); | ||
| 2314 | + break; | ||
| 2315 | + case 0x14: | ||
| 2316 | + /* Output level */ | ||
| 2317 | + gpt->ol = value & 0xF8000000; | ||
| 2318 | + ppc4xx_gpt_set_outputs(gpt); | ||
| 2319 | + break; | ||
| 2320 | + case 0x18: | ||
| 2321 | + /* Interrupt mask */ | ||
| 2322 | + gpt->im = value & 0x0000F800; | ||
| 2323 | + break; | ||
| 2324 | + case 0x1C: | ||
| 2325 | + /* Interrupt status set */ | ||
| 2326 | + gpt->is |= value & 0x0000F800; | ||
| 2327 | + ppc4xx_gpt_set_irqs(gpt); | ||
| 2328 | + break; | ||
| 2329 | + case 0x20: | ||
| 2330 | + /* Interrupt status clear */ | ||
| 2331 | + gpt->is &= ~(value & 0x0000F800); | ||
| 2332 | + ppc4xx_gpt_set_irqs(gpt); | ||
| 2333 | + break; | ||
| 2334 | + case 0x24: | ||
| 2335 | + /* Interrupt enable */ | ||
| 2336 | + gpt->ie = value & 0x0000F800; | ||
| 2337 | + ppc4xx_gpt_set_irqs(gpt); | ||
| 2338 | + break; | ||
| 2339 | + case 0x80 ... 0x90: | ||
| 2340 | + /* Compare timer */ | ||
| 2341 | + idx = ((addr - gpt->base) - 0x80) >> 2; | ||
| 2342 | + gpt->comp[idx] = value & 0xF8000000; | ||
| 2343 | + ppc4xx_gpt_compute_timer(gpt); | ||
| 2344 | + break; | ||
| 2345 | + case 0xC0 ... 0xD0: | ||
| 2346 | + /* Compare mask */ | ||
| 2347 | + idx = ((addr - gpt->base) - 0xC0) >> 2; | ||
| 2348 | + gpt->mask[idx] = value & 0xF8000000; | ||
| 2349 | + ppc4xx_gpt_compute_timer(gpt); | ||
| 2350 | + break; | ||
| 2351 | + } | ||
| 2352 | +} | ||
| 2353 | + | ||
| 2354 | +static CPUReadMemoryFunc *gpt_read[] = { | ||
| 2355 | + &ppc4xx_gpt_readb, | ||
| 2356 | + &ppc4xx_gpt_readw, | ||
| 2357 | + &ppc4xx_gpt_readl, | ||
| 2358 | +}; | ||
| 2359 | + | ||
| 2360 | +static CPUWriteMemoryFunc *gpt_write[] = { | ||
| 2361 | + &ppc4xx_gpt_writeb, | ||
| 2362 | + &ppc4xx_gpt_writew, | ||
| 2363 | + &ppc4xx_gpt_writel, | ||
| 2364 | +}; | ||
| 2365 | + | ||
| 2366 | +static void ppc4xx_gpt_cb (void *opaque) | ||
| 2367 | +{ | ||
| 2368 | + ppc4xx_gpt_t *gpt; | ||
| 2369 | + | ||
| 2370 | + gpt = opaque; | ||
| 2371 | + ppc4xx_gpt_set_irqs(gpt); | ||
| 2372 | + ppc4xx_gpt_set_outputs(gpt); | ||
| 2373 | + ppc4xx_gpt_compute_timer(gpt); | ||
| 2374 | +} | ||
| 2375 | + | ||
| 2376 | +static void ppc4xx_gpt_reset (void *opaque) | ||
| 2377 | +{ | ||
| 2378 | + ppc4xx_gpt_t *gpt; | ||
| 2379 | + int i; | ||
| 2380 | + | ||
| 2381 | + gpt = opaque; | ||
| 2382 | + qemu_del_timer(gpt->timer); | ||
| 2383 | + gpt->oe = 0x00000000; | ||
| 2384 | + gpt->ol = 0x00000000; | ||
| 2385 | + gpt->im = 0x00000000; | ||
| 2386 | + gpt->is = 0x00000000; | ||
| 2387 | + gpt->ie = 0x00000000; | ||
| 2388 | + for (i = 0; i < 5; i++) { | ||
| 2389 | + gpt->comp[i] = 0x00000000; | ||
| 2390 | + gpt->mask[i] = 0x00000000; | ||
| 2391 | + } | ||
| 2392 | +} | ||
| 2393 | + | ||
| 2394 | +void ppc4xx_gpt_init (CPUState *env, ppc4xx_mmio_t *mmio, | ||
| 2395 | + target_phys_addr_t offset, qemu_irq irqs[5]) | ||
| 2396 | +{ | ||
| 2397 | + ppc4xx_gpt_t *gpt; | ||
| 2398 | + int i; | ||
| 2399 | + | ||
| 2400 | + gpt = qemu_mallocz(sizeof(ppc4xx_gpt_t)); | ||
| 2401 | + if (gpt != NULL) { | ||
| 2402 | + gpt->base = offset; | ||
| 2403 | + for (i = 0; i < 5; i++) | ||
| 2404 | + gpt->irqs[i] = irqs[i]; | ||
| 2405 | + gpt->timer = qemu_new_timer(vm_clock, &ppc4xx_gpt_cb, gpt); | ||
| 2406 | + ppc4xx_gpt_reset(gpt); | ||
| 2407 | +#ifdef DEBUG_GPT | ||
| 2408 | + printf("%s: offset=" PADDRX "\n", __func__, offset); | ||
| 2409 | +#endif | ||
| 2410 | + ppc4xx_mmio_register(env, mmio, offset, 0x0D4, | ||
| 2411 | + gpt_read, gpt_write, gpt); | ||
| 2412 | + qemu_register_reset(ppc4xx_gpt_reset, gpt); | ||
| 2413 | + } | ||
| 2414 | +} | ||
| 2415 | + | ||
| 2416 | +/*****************************************************************************/ | ||
| 2417 | +/* MAL */ | ||
| 2418 | +enum { | ||
| 2419 | + MAL0_CFG = 0x180, | ||
| 2420 | + MAL0_ESR = 0x181, | ||
| 2421 | + MAL0_IER = 0x182, | ||
| 2422 | + MAL0_TXCASR = 0x184, | ||
| 2423 | + MAL0_TXCARR = 0x185, | ||
| 2424 | + MAL0_TXEOBISR = 0x186, | ||
| 2425 | + MAL0_TXDEIR = 0x187, | ||
| 2426 | + MAL0_RXCASR = 0x190, | ||
| 2427 | + MAL0_RXCARR = 0x191, | ||
| 2428 | + MAL0_RXEOBISR = 0x192, | ||
| 2429 | + MAL0_RXDEIR = 0x193, | ||
| 2430 | + MAL0_TXCTP0R = 0x1A0, | ||
| 2431 | + MAL0_TXCTP1R = 0x1A1, | ||
| 2432 | + MAL0_TXCTP2R = 0x1A2, | ||
| 2433 | + MAL0_TXCTP3R = 0x1A3, | ||
| 2434 | + MAL0_RXCTP0R = 0x1C0, | ||
| 2435 | + MAL0_RXCTP1R = 0x1C1, | ||
| 2436 | + MAL0_RCBS0 = 0x1E0, | ||
| 2437 | + MAL0_RCBS1 = 0x1E1, | ||
| 2438 | +}; | ||
| 2439 | + | ||
| 2440 | +typedef struct ppc40x_mal_t ppc40x_mal_t; | ||
| 2441 | +struct ppc40x_mal_t { | ||
| 2442 | + qemu_irq irqs[4]; | ||
| 2443 | + uint32_t cfg; | ||
| 2444 | + uint32_t esr; | ||
| 2445 | + uint32_t ier; | ||
| 2446 | + uint32_t txcasr; | ||
| 2447 | + uint32_t txcarr; | ||
| 2448 | + uint32_t txeobisr; | ||
| 2449 | + uint32_t txdeir; | ||
| 2450 | + uint32_t rxcasr; | ||
| 2451 | + uint32_t rxcarr; | ||
| 2452 | + uint32_t rxeobisr; | ||
| 2453 | + uint32_t rxdeir; | ||
| 2454 | + uint32_t txctpr[4]; | ||
| 2455 | + uint32_t rxctpr[2]; | ||
| 2456 | + uint32_t rcbs[2]; | ||
| 2457 | +}; | ||
| 2458 | + | ||
| 2459 | +static void ppc40x_mal_reset (void *opaque); | ||
| 2460 | + | ||
| 2461 | +static target_ulong dcr_read_mal (void *opaque, int dcrn) | ||
| 2462 | +{ | ||
| 2463 | + ppc40x_mal_t *mal; | ||
| 2464 | + target_ulong ret; | ||
| 2465 | + | ||
| 2466 | + mal = opaque; | ||
| 2467 | + switch (dcrn) { | ||
| 2468 | + case MAL0_CFG: | ||
| 2469 | + ret = mal->cfg; | ||
| 2470 | + break; | ||
| 2471 | + case MAL0_ESR: | ||
| 2472 | + ret = mal->esr; | ||
| 2473 | + break; | ||
| 2474 | + case MAL0_IER: | ||
| 2475 | + ret = mal->ier; | ||
| 2476 | + break; | ||
| 2477 | + case MAL0_TXCASR: | ||
| 2478 | + ret = mal->txcasr; | ||
| 2479 | + break; | ||
| 2480 | + case MAL0_TXCARR: | ||
| 2481 | + ret = mal->txcarr; | ||
| 2482 | + break; | ||
| 2483 | + case MAL0_TXEOBISR: | ||
| 2484 | + ret = mal->txeobisr; | ||
| 2485 | + break; | ||
| 2486 | + case MAL0_TXDEIR: | ||
| 2487 | + ret = mal->txdeir; | ||
| 2488 | + break; | ||
| 2489 | + case MAL0_RXCASR: | ||
| 2490 | + ret = mal->rxcasr; | ||
| 2491 | + break; | ||
| 2492 | + case MAL0_RXCARR: | ||
| 2493 | + ret = mal->rxcarr; | ||
| 2494 | + break; | ||
| 2495 | + case MAL0_RXEOBISR: | ||
| 2496 | + ret = mal->rxeobisr; | ||
| 2497 | + break; | ||
| 2498 | + case MAL0_RXDEIR: | ||
| 2499 | + ret = mal->rxdeir; | ||
| 2500 | + break; | ||
| 2501 | + case MAL0_TXCTP0R: | ||
| 2502 | + ret = mal->txctpr[0]; | ||
| 2503 | + break; | ||
| 2504 | + case MAL0_TXCTP1R: | ||
| 2505 | + ret = mal->txctpr[1]; | ||
| 2506 | + break; | ||
| 2507 | + case MAL0_TXCTP2R: | ||
| 2508 | + ret = mal->txctpr[2]; | ||
| 2509 | + break; | ||
| 2510 | + case MAL0_TXCTP3R: | ||
| 2511 | + ret = mal->txctpr[3]; | ||
| 2512 | + break; | ||
| 2513 | + case MAL0_RXCTP0R: | ||
| 2514 | + ret = mal->rxctpr[0]; | ||
| 2515 | + break; | ||
| 2516 | + case MAL0_RXCTP1R: | ||
| 2517 | + ret = mal->rxctpr[1]; | ||
| 2518 | + break; | ||
| 2519 | + case MAL0_RCBS0: | ||
| 2520 | + ret = mal->rcbs[0]; | ||
| 2521 | + break; | ||
| 2522 | + case MAL0_RCBS1: | ||
| 2523 | + ret = mal->rcbs[1]; | ||
| 2524 | + break; | ||
| 2525 | + default: | ||
| 2526 | + ret = 0; | ||
| 2527 | + break; | ||
| 2528 | + } | ||
| 2529 | + | ||
| 2530 | + return ret; | ||
| 2531 | +} | ||
| 2532 | + | ||
| 2533 | +static void dcr_write_mal (void *opaque, int dcrn, target_ulong val) | ||
| 2534 | +{ | ||
| 2535 | + ppc40x_mal_t *mal; | ||
| 2536 | + int idx; | ||
| 2537 | + | ||
| 2538 | + mal = opaque; | ||
| 2539 | + switch (dcrn) { | ||
| 2540 | + case MAL0_CFG: | ||
| 2541 | + if (val & 0x80000000) | ||
| 2542 | + ppc40x_mal_reset(mal); | ||
| 2543 | + mal->cfg = val & 0x00FFC087; | ||
| 2544 | + break; | ||
| 2545 | + case MAL0_ESR: | ||
| 2546 | + /* Read/clear */ | ||
| 2547 | + mal->esr &= ~val; | ||
| 2548 | + break; | ||
| 2549 | + case MAL0_IER: | ||
| 2550 | + mal->ier = val & 0x0000001F; | ||
| 2551 | + break; | ||
| 2552 | + case MAL0_TXCASR: | ||
| 2553 | + mal->txcasr = val & 0xF0000000; | ||
| 2554 | + break; | ||
| 2555 | + case MAL0_TXCARR: | ||
| 2556 | + mal->txcarr = val & 0xF0000000; | ||
| 2557 | + break; | ||
| 2558 | + case MAL0_TXEOBISR: | ||
| 2559 | + /* Read/clear */ | ||
| 2560 | + mal->txeobisr &= ~val; | ||
| 2561 | + break; | ||
| 2562 | + case MAL0_TXDEIR: | ||
| 2563 | + /* Read/clear */ | ||
| 2564 | + mal->txdeir &= ~val; | ||
| 2565 | + break; | ||
| 2566 | + case MAL0_RXCASR: | ||
| 2567 | + mal->rxcasr = val & 0xC0000000; | ||
| 2568 | + break; | ||
| 2569 | + case MAL0_RXCARR: | ||
| 2570 | + mal->rxcarr = val & 0xC0000000; | ||
| 2571 | + break; | ||
| 2572 | + case MAL0_RXEOBISR: | ||
| 2573 | + /* Read/clear */ | ||
| 2574 | + mal->rxeobisr &= ~val; | ||
| 2575 | + break; | ||
| 2576 | + case MAL0_RXDEIR: | ||
| 2577 | + /* Read/clear */ | ||
| 2578 | + mal->rxdeir &= ~val; | ||
| 2579 | + break; | ||
| 2580 | + case MAL0_TXCTP0R: | ||
| 2581 | + idx = 0; | ||
| 2582 | + goto update_tx_ptr; | ||
| 2583 | + case MAL0_TXCTP1R: | ||
| 2584 | + idx = 1; | ||
| 2585 | + goto update_tx_ptr; | ||
| 2586 | + case MAL0_TXCTP2R: | ||
| 2587 | + idx = 2; | ||
| 2588 | + goto update_tx_ptr; | ||
| 2589 | + case MAL0_TXCTP3R: | ||
| 2590 | + idx = 3; | ||
| 2591 | + update_tx_ptr: | ||
| 2592 | + mal->txctpr[idx] = val; | ||
| 2593 | + break; | ||
| 2594 | + case MAL0_RXCTP0R: | ||
| 2595 | + idx = 0; | ||
| 2596 | + goto update_rx_ptr; | ||
| 2597 | + case MAL0_RXCTP1R: | ||
| 2598 | + idx = 1; | ||
| 2599 | + update_rx_ptr: | ||
| 2600 | + mal->rxctpr[idx] = val; | ||
| 2601 | + break; | ||
| 2602 | + case MAL0_RCBS0: | ||
| 2603 | + idx = 0; | ||
| 2604 | + goto update_rx_size; | ||
| 2605 | + case MAL0_RCBS1: | ||
| 2606 | + idx = 1; | ||
| 2607 | + update_rx_size: | ||
| 2608 | + mal->rcbs[idx] = val & 0x000000FF; | ||
| 2609 | + break; | ||
| 2610 | + } | ||
| 2611 | +} | ||
| 2612 | + | ||
| 2613 | +static void ppc40x_mal_reset (void *opaque) | ||
| 2614 | +{ | ||
| 2615 | + ppc40x_mal_t *mal; | ||
| 2616 | + | ||
| 2617 | + mal = opaque; | ||
| 2618 | + mal->cfg = 0x0007C000; | ||
| 2619 | + mal->esr = 0x00000000; | ||
| 2620 | + mal->ier = 0x00000000; | ||
| 2621 | + mal->rxcasr = 0x00000000; | ||
| 2622 | + mal->rxdeir = 0x00000000; | ||
| 2623 | + mal->rxeobisr = 0x00000000; | ||
| 2624 | + mal->txcasr = 0x00000000; | ||
| 2625 | + mal->txdeir = 0x00000000; | ||
| 2626 | + mal->txeobisr = 0x00000000; | ||
| 2627 | +} | ||
| 2628 | + | ||
| 2629 | +void ppc405_mal_init (CPUState *env, qemu_irq irqs[4]) | ||
| 2630 | +{ | ||
| 2631 | + ppc40x_mal_t *mal; | ||
| 2632 | + int i; | ||
| 2633 | + | ||
| 2634 | + mal = qemu_mallocz(sizeof(ppc40x_mal_t)); | ||
| 2635 | + if (mal != NULL) { | ||
| 2636 | + for (i = 0; i < 4; i++) | ||
| 2637 | + mal->irqs[i] = irqs[i]; | ||
| 2638 | + ppc40x_mal_reset(mal); | ||
| 2639 | + qemu_register_reset(&ppc40x_mal_reset, mal); | ||
| 2640 | + ppc_dcr_register(env, MAL0_CFG, | ||
| 2641 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2642 | + ppc_dcr_register(env, MAL0_ESR, | ||
| 2643 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2644 | + ppc_dcr_register(env, MAL0_IER, | ||
| 2645 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2646 | + ppc_dcr_register(env, MAL0_TXCASR, | ||
| 2647 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2648 | + ppc_dcr_register(env, MAL0_TXCARR, | ||
| 2649 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2650 | + ppc_dcr_register(env, MAL0_TXEOBISR, | ||
| 2651 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2652 | + ppc_dcr_register(env, MAL0_TXDEIR, | ||
| 2653 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2654 | + ppc_dcr_register(env, MAL0_RXCASR, | ||
| 2655 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2656 | + ppc_dcr_register(env, MAL0_RXCARR, | ||
| 2657 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2658 | + ppc_dcr_register(env, MAL0_RXEOBISR, | ||
| 2659 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2660 | + ppc_dcr_register(env, MAL0_RXDEIR, | ||
| 2661 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2662 | + ppc_dcr_register(env, MAL0_TXCTP0R, | ||
| 2663 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2664 | + ppc_dcr_register(env, MAL0_TXCTP1R, | ||
| 2665 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2666 | + ppc_dcr_register(env, MAL0_TXCTP2R, | ||
| 2667 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2668 | + ppc_dcr_register(env, MAL0_TXCTP3R, | ||
| 2669 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2670 | + ppc_dcr_register(env, MAL0_RXCTP0R, | ||
| 2671 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2672 | + ppc_dcr_register(env, MAL0_RXCTP1R, | ||
| 2673 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2674 | + ppc_dcr_register(env, MAL0_RCBS0, | ||
| 2675 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2676 | + ppc_dcr_register(env, MAL0_RCBS1, | ||
| 2677 | + mal, &dcr_read_mal, &dcr_write_mal); | ||
| 2678 | + } | ||
| 2679 | +} | ||
| 2680 | + | ||
| 2681 | +/*****************************************************************************/ | ||
| 2112 | /* SPR */ | 2682 | /* SPR */ |
| 2113 | void ppc40x_core_reset (CPUState *env) | 2683 | void ppc40x_core_reset (CPUState *env) |
| 2114 | { | 2684 | { |
| @@ -2499,7 +3069,7 @@ CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], | @@ -2499,7 +3069,7 @@ CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], | ||
| 2499 | ppc405_serial_init(env, mmio, 0x400, pic[30], serial_hds[1]); | 3069 | ppc405_serial_init(env, mmio, 0x400, pic[30], serial_hds[1]); |
| 2500 | } | 3070 | } |
| 2501 | /* IIC controller */ | 3071 | /* IIC controller */ |
| 2502 | - ppc405_i2c_init(env, mmio, 0x500); | 3072 | + ppc405_i2c_init(env, mmio, 0x500, pic[29]); |
| 2503 | /* GPIO */ | 3073 | /* GPIO */ |
| 2504 | ppc405_gpio_init(env, mmio, 0x700); | 3074 | ppc405_gpio_init(env, mmio, 0x700); |
| 2505 | /* CPU control */ | 3075 | /* CPU control */ |
| @@ -2521,6 +3091,11 @@ enum { | @@ -2521,6 +3091,11 @@ enum { | ||
| 2521 | PPC405EP_CPC0_SRR = 0x0F6, | 3091 | PPC405EP_CPC0_SRR = 0x0F6, |
| 2522 | PPC405EP_CPC0_JTAGID = 0x0F7, | 3092 | PPC405EP_CPC0_JTAGID = 0x0F7, |
| 2523 | PPC405EP_CPC0_PCI = 0x0F9, | 3093 | PPC405EP_CPC0_PCI = 0x0F9, |
| 3094 | +#if 0 | ||
| 3095 | + PPC405EP_CPC0_ER = xxx, | ||
| 3096 | + PPC405EP_CPC0_FR = xxx, | ||
| 3097 | + PPC405EP_CPC0_SR = xxx, | ||
| 3098 | +#endif | ||
| 2524 | }; | 3099 | }; |
| 2525 | 3100 | ||
| 2526 | enum { | 3101 | enum { |
| @@ -2546,6 +3121,10 @@ struct ppc405ep_cpc_t { | @@ -2546,6 +3121,10 @@ struct ppc405ep_cpc_t { | ||
| 2546 | uint32_t srr; | 3121 | uint32_t srr; |
| 2547 | uint32_t jtagid; | 3122 | uint32_t jtagid; |
| 2548 | uint32_t pci; | 3123 | uint32_t pci; |
| 3124 | + /* Clock and power management */ | ||
| 3125 | + uint32_t er; | ||
| 3126 | + uint32_t fr; | ||
| 3127 | + uint32_t sr; | ||
| 2549 | }; | 3128 | }; |
| 2550 | 3129 | ||
| 2551 | static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) | 3130 | static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) |
| @@ -2571,11 +3150,17 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) | @@ -2571,11 +3150,17 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) | ||
| 2571 | #endif | 3150 | #endif |
| 2572 | } | 3151 | } |
| 2573 | PLL_out = VCO_out / D; | 3152 | PLL_out = VCO_out / D; |
| 3153 | + /* Pretend the PLL is locked */ | ||
| 3154 | + cpc->boot |= 0x00000001; | ||
| 2574 | } else { | 3155 | } else { |
| 2575 | #if 0 | 3156 | #if 0 |
| 2576 | pll_bypass: | 3157 | pll_bypass: |
| 2577 | #endif | 3158 | #endif |
| 2578 | PLL_out = cpc->sysclk; | 3159 | PLL_out = cpc->sysclk; |
| 3160 | + if (cpc->pllmr[1] & 0x40000000) { | ||
| 3161 | + /* Pretend the PLL is not locked */ | ||
| 3162 | + cpc->boot &= ~0x00000001; | ||
| 3163 | + } | ||
| 2579 | } | 3164 | } |
| 2580 | /* Now, compute all other clocks */ | 3165 | /* Now, compute all other clocks */ |
| 2581 | D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */ | 3166 | D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */ |
| @@ -2624,6 +3209,8 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) | @@ -2624,6 +3209,8 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) | ||
| 2624 | printf("CPU %d PLB %d OPB %d EBC %d MAL %d PCI %d UART0 %d UART1 %d\n", | 3209 | printf("CPU %d PLB %d OPB %d EBC %d MAL %d PCI %d UART0 %d UART1 %d\n", |
| 2625 | CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk, | 3210 | CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk, |
| 2626 | UART0_clk, UART1_clk); | 3211 | UART0_clk, UART1_clk); |
| 3212 | + printf("CB %p opaque %p\n", cpc->clk_setup[PPC405EP_CPU_CLK].cb, | ||
| 3213 | + cpc->clk_setup[PPC405EP_CPU_CLK].opaque); | ||
| 2627 | #endif | 3214 | #endif |
| 2628 | /* Setup CPU clocks */ | 3215 | /* Setup CPU clocks */ |
| 2629 | clk_setup(&cpc->clk_setup[PPC405EP_CPU_CLK], CPU_clk); | 3216 | clk_setup(&cpc->clk_setup[PPC405EP_CPU_CLK], CPU_clk); |
| @@ -2731,6 +3318,9 @@ static void ppc405ep_cpc_reset (void *opaque) | @@ -2731,6 +3318,9 @@ static void ppc405ep_cpc_reset (void *opaque) | ||
| 2731 | cpc->ucr = 0x00000000; | 3318 | cpc->ucr = 0x00000000; |
| 2732 | cpc->srr = 0x00040000; | 3319 | cpc->srr = 0x00040000; |
| 2733 | cpc->pci = 0x00000000; | 3320 | cpc->pci = 0x00000000; |
| 3321 | + cpc->er = 0x00000000; | ||
| 3322 | + cpc->fr = 0x00000000; | ||
| 3323 | + cpc->sr = 0x00000000; | ||
| 2734 | ppc405ep_compute_clocks(cpc); | 3324 | ppc405ep_compute_clocks(cpc); |
| 2735 | } | 3325 | } |
| 2736 | 3326 | ||
| @@ -2764,6 +3354,14 @@ static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8], | @@ -2764,6 +3354,14 @@ static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8], | ||
| 2764 | &dcr_read_epcpc, &dcr_write_epcpc); | 3354 | &dcr_read_epcpc, &dcr_write_epcpc); |
| 2765 | ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc, | 3355 | ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc, |
| 2766 | &dcr_read_epcpc, &dcr_write_epcpc); | 3356 | &dcr_read_epcpc, &dcr_write_epcpc); |
| 3357 | +#if 0 | ||
| 3358 | + ppc_dcr_register(env, PPC405EP_CPC0_ER, cpc, | ||
| 3359 | + &dcr_read_epcpc, &dcr_write_epcpc); | ||
| 3360 | + ppc_dcr_register(env, PPC405EP_CPC0_FR, cpc, | ||
| 3361 | + &dcr_read_epcpc, &dcr_write_epcpc); | ||
| 3362 | + ppc_dcr_register(env, PPC405EP_CPC0_SR, cpc, | ||
| 3363 | + &dcr_read_epcpc, &dcr_write_epcpc); | ||
| 3364 | +#endif | ||
| 2767 | } | 3365 | } |
| 2768 | } | 3366 | } |
| 2769 | 3367 | ||
| @@ -2771,8 +3369,8 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], | @@ -2771,8 +3369,8 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], | ||
| 2771 | uint32_t sysclk, qemu_irq **picp, | 3369 | uint32_t sysclk, qemu_irq **picp, |
| 2772 | ram_addr_t *offsetp, int do_init) | 3370 | ram_addr_t *offsetp, int do_init) |
| 2773 | { | 3371 | { |
| 2774 | - clk_setup_t clk_setup[PPC405EP_CLK_NB]; | ||
| 2775 | - qemu_irq dma_irqs[4]; | 3372 | + clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup; |
| 3373 | + qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; | ||
| 2776 | CPUState *env; | 3374 | CPUState *env; |
| 2777 | ppc4xx_mmio_t *mmio; | 3375 | ppc4xx_mmio_t *mmio; |
| 2778 | qemu_irq *pic, *irqs; | 3376 | qemu_irq *pic, *irqs; |
| @@ -2782,7 +3380,9 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], | @@ -2782,7 +3380,9 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], | ||
| 2782 | memset(clk_setup, 0, sizeof(clk_setup)); | 3380 | memset(clk_setup, 0, sizeof(clk_setup)); |
| 2783 | /* init CPUs */ | 3381 | /* init CPUs */ |
| 2784 | env = ppc405_init("405ep", &clk_setup[PPC405EP_CPU_CLK], | 3382 | env = ppc405_init("405ep", &clk_setup[PPC405EP_CPU_CLK], |
| 2785 | - &clk_setup[PPC405EP_PLB_CLK], sysclk); | 3383 | + &tlb_clk_setup, sysclk); |
| 3384 | + clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb; | ||
| 3385 | + clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque; | ||
| 2786 | /* Internal devices init */ | 3386 | /* Internal devices init */ |
| 2787 | /* Memory mapped devices registers */ | 3387 | /* Memory mapped devices registers */ |
| 2788 | mmio = ppc4xx_mmio_init(env, 0xEF600000); | 3388 | mmio = ppc4xx_mmio_init(env, 0xEF600000); |
| @@ -2814,7 +3414,7 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], | @@ -2814,7 +3414,7 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], | ||
| 2814 | dma_irqs[3] = pic[23]; | 3414 | dma_irqs[3] = pic[23]; |
| 2815 | ppc405_dma_init(env, dma_irqs); | 3415 | ppc405_dma_init(env, dma_irqs); |
| 2816 | /* IIC controller */ | 3416 | /* IIC controller */ |
| 2817 | - ppc405_i2c_init(env, mmio, 0x500); | 3417 | + ppc405_i2c_init(env, mmio, 0x500, pic[29]); |
| 2818 | /* GPIO */ | 3418 | /* GPIO */ |
| 2819 | ppc405_gpio_init(env, mmio, 0x700); | 3419 | ppc405_gpio_init(env, mmio, 0x700); |
| 2820 | /* Serial ports */ | 3420 | /* Serial ports */ |
| @@ -2827,7 +3427,23 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], | @@ -2827,7 +3427,23 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], | ||
| 2827 | /* OCM */ | 3427 | /* OCM */ |
| 2828 | ppc405_ocm_init(env, ram_sizes[0] + ram_sizes[1]); | 3428 | ppc405_ocm_init(env, ram_sizes[0] + ram_sizes[1]); |
| 2829 | offset += 4096; | 3429 | offset += 4096; |
| 3430 | + /* GPT */ | ||
| 3431 | + gpt_irqs[0] = pic[12]; | ||
| 3432 | + gpt_irqs[1] = pic[11]; | ||
| 3433 | + gpt_irqs[2] = pic[10]; | ||
| 3434 | + gpt_irqs[3] = pic[9]; | ||
| 3435 | + gpt_irqs[4] = pic[8]; | ||
| 3436 | + ppc4xx_gpt_init(env, mmio, 0x000, gpt_irqs); | ||
| 2830 | /* PCI */ | 3437 | /* PCI */ |
| 3438 | + /* Uses pic[28], pic[15], pic[13] */ | ||
| 3439 | + /* MAL */ | ||
| 3440 | + mal_irqs[0] = pic[20]; | ||
| 3441 | + mal_irqs[1] = pic[19]; | ||
| 3442 | + mal_irqs[2] = pic[18]; | ||
| 3443 | + mal_irqs[3] = pic[17]; | ||
| 3444 | + ppc405_mal_init(env, mal_irqs); | ||
| 3445 | + /* Ethernet */ | ||
| 3446 | + /* Uses pic[22], pic[16], pic[14] */ | ||
| 2831 | /* CPU control */ | 3447 | /* CPU control */ |
| 2832 | ppc405ep_cpc_init(env, clk_setup, sysclk); | 3448 | ppc405ep_cpc_init(env, clk_setup, sysclk); |
| 2833 | *offsetp = offset; | 3449 | *offsetp = offset; |