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 | 62 | /* */ |
| 63 | 63 | typedef struct ppc4xx_mmio_t ppc4xx_mmio_t; |
| 64 | 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 | 66 | CPUReadMemoryFunc **mem_read, |
| 67 | 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 | 69 | /* PowerPC 4xx peripheral local bus arbitrer */ |
| 70 | 70 | void ppc4xx_plb_init (CPUState *env); |
| 71 | 71 | /* PLB to OPB bridge */ |
| 72 | 72 | void ppc4xx_pob_init (CPUState *env); |
| 73 | 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 | 76 | /* PowerPC 4xx universal interrupt controller */ |
| 76 | 77 | enum { |
| 77 | 78 | PPCUIC_OUTPUT_INT = 0, |
| ... | ... | @@ -89,15 +90,22 @@ void ppc405_ebc_init (CPUState *env); |
| 89 | 90 | /* DMA controller */ |
| 90 | 91 | void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]); |
| 91 | 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 | 95 | /* Serial ports */ |
| 94 | 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 | 98 | CharDriverState *chr); |
| 97 | 99 | /* On Chip Memory */ |
| 98 | 100 | void ppc405_ocm_init (CPUState *env, unsigned long offset); |
| 99 | 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 | 109 | /* PowerPC 405 microcontrollers */ |
| 102 | 110 | CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], |
| 103 | 111 | uint32_t sysclk, qemu_irq **picp, | ... | ... |
hw/ppc405_uc.c
| ... | ... | @@ -27,16 +27,18 @@ |
| 27 | 27 | extern int loglevel; |
| 28 | 28 | extern FILE *logfile; |
| 29 | 29 | |
| 30 | -#define DEBUG_MMIO | |
| 30 | +//#define DEBUG_MMIO | |
| 31 | 31 | #define DEBUG_OPBA |
| 32 | 32 | #define DEBUG_SDRAM |
| 33 | 33 | #define DEBUG_GPIO |
| 34 | 34 | #define DEBUG_SERIAL |
| 35 | 35 | #define DEBUG_OCM |
| 36 | -#define DEBUG_I2C | |
| 36 | +//#define DEBUG_I2C | |
| 37 | +#define DEBUG_GPT | |
| 38 | +#define DEBUG_MAL | |
| 37 | 39 | #define DEBUG_UIC |
| 38 | 40 | #define DEBUG_CLOCKS |
| 39 | -#define DEBUG_UNASSIGNED | |
| 41 | +//#define DEBUG_UNASSIGNED | |
| 40 | 42 | |
| 41 | 43 | /*****************************************************************************/ |
| 42 | 44 | /* Generic PowerPC 405 processor instanciation */ |
| ... | ... | @@ -122,39 +124,47 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd) |
| 122 | 124 | #define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS)) |
| 123 | 125 | #define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1)) |
| 124 | 126 | struct ppc4xx_mmio_t { |
| 125 | - uint32_t base; | |
| 127 | + target_phys_addr_t base; | |
| 126 | 128 | CPUReadMemoryFunc **mem_read[MMIO_AREA_NB]; |
| 127 | 129 | CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB]; |
| 128 | 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 | 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 | 141 | #endif |
| 136 | 142 | |
| 137 | 143 | return 0; |
| 138 | 144 | } |
| 139 | 145 | |
| 140 | -static void unassigned_mem_writeb (void *opaque, | |
| 146 | +static void unassigned_mmio_writeb (void *opaque, | |
| 141 | 147 | target_phys_addr_t addr, uint32_t val) |
| 142 | 148 | { |
| 143 | 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 | 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 | 170 | static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio, |
| ... | ... | @@ -170,7 +180,7 @@ static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio, |
| 170 | 180 | mmio, len, addr, idx); |
| 171 | 181 | #endif |
| 172 | 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 | 185 | return ret; |
| 176 | 186 | } |
| ... | ... | @@ -187,7 +197,7 @@ static void mmio_writelen (ppc4xx_mmio_t *mmio, |
| 187 | 197 | mmio, len, addr, idx, value); |
| 188 | 198 | #endif |
| 189 | 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 | 203 | static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr) |
| ... | ... | @@ -257,7 +267,7 @@ static CPUWriteMemoryFunc *mmio_write[] = { |
| 257 | 267 | }; |
| 258 | 268 | |
| 259 | 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 | 271 | CPUReadMemoryFunc **mem_read, |
| 262 | 272 | CPUWriteMemoryFunc **mem_write, void *opaque) |
| 263 | 273 | { |
| ... | ... | @@ -282,7 +292,7 @@ int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, |
| 282 | 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 | 297 | ppc4xx_mmio_t *mmio; |
| 288 | 298 | int mmio_memory; |
| ... | ... | @@ -297,7 +307,8 @@ ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, uint32_t base) |
| 297 | 307 | #endif |
| 298 | 308 | cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory); |
| 299 | 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 | 314 | return mmio; |
| ... | ... | @@ -350,7 +361,10 @@ static void dcr_write_plb (void *opaque, int dcrn, target_ulong val) |
| 350 | 361 | plb = opaque; |
| 351 | 362 | switch (dcrn) { |
| 352 | 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 | 368 | break; |
| 355 | 369 | case PLB0_BEAR: |
| 356 | 370 | /* Read only */ |
| ... | ... | @@ -469,7 +483,7 @@ void ppc4xx_pob_init (CPUState *env) |
| 469 | 483 | /* OPB arbitrer */ |
| 470 | 484 | typedef struct ppc4xx_opba_t ppc4xx_opba_t; |
| 471 | 485 | struct ppc4xx_opba_t { |
| 472 | - target_ulong base; | |
| 486 | + target_phys_addr_t base; | |
| 473 | 487 | uint8_t cr; |
| 474 | 488 | uint8_t pr; |
| 475 | 489 | }; |
| ... | ... | @@ -586,15 +600,16 @@ static void ppc4xx_opba_reset (void *opaque) |
| 586 | 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 | 606 | ppc4xx_opba_t *opba; |
| 592 | 607 | |
| 593 | 608 | opba = qemu_mallocz(sizeof(ppc4xx_opba_t)); |
| 594 | 609 | if (opba != NULL) { |
| 595 | - opba->base = mmio->base + offset; | |
| 610 | + opba->base = offset; | |
| 596 | 611 | #ifdef DEBUG_OPBA |
| 597 | - printf("%s: offset=%08x\n", __func__, offset); | |
| 612 | + printf("%s: offset=" PADDRX "\n", __func__, offset); | |
| 598 | 613 | #endif |
| 599 | 614 | ppc4xx_mmio_register(env, mmio, offset, 0x002, |
| 600 | 615 | opba_read, opba_write, opba); |
| ... | ... | @@ -1392,7 +1407,7 @@ static void ebc_reset (void *opaque) |
| 1392 | 1407 | } |
| 1393 | 1408 | ebc->besr0 = 0x00000000; |
| 1394 | 1409 | ebc->besr1 = 0x00000000; |
| 1395 | - ebc->cfg = 0x07C00000; | |
| 1410 | + ebc->cfg = 0x80400000; | |
| 1396 | 1411 | } |
| 1397 | 1412 | |
| 1398 | 1413 | void ppc405_ebc_init (CPUState *env) |
| ... | ... | @@ -1552,7 +1567,7 @@ void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]) |
| 1552 | 1567 | /* GPIO */ |
| 1553 | 1568 | typedef struct ppc405_gpio_t ppc405_gpio_t; |
| 1554 | 1569 | struct ppc405_gpio_t { |
| 1555 | - uint32_t base; | |
| 1570 | + target_phys_addr_t base; | |
| 1556 | 1571 | uint32_t or; |
| 1557 | 1572 | uint32_t tcr; |
| 1558 | 1573 | uint32_t osrh; |
| ... | ... | @@ -1654,17 +1669,18 @@ static void ppc405_gpio_reset (void *opaque) |
| 1654 | 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 | 1675 | ppc405_gpio_t *gpio; |
| 1660 | 1676 | |
| 1661 | 1677 | gpio = qemu_mallocz(sizeof(ppc405_gpio_t)); |
| 1662 | 1678 | if (gpio != NULL) { |
| 1663 | - gpio->base = mmio->base + offset; | |
| 1679 | + gpio->base = offset; | |
| 1664 | 1680 | ppc405_gpio_reset(gpio); |
| 1665 | 1681 | qemu_register_reset(&ppc405_gpio_reset, gpio); |
| 1666 | 1682 | #ifdef DEBUG_GPIO |
| 1667 | - printf("%s: offset=%08x\n", __func__, offset); | |
| 1683 | + printf("%s: offset=" PADDRX "\n", __func__, offset); | |
| 1668 | 1684 | #endif |
| 1669 | 1685 | ppc4xx_mmio_register(env, mmio, offset, 0x038, |
| 1670 | 1686 | ppc405_gpio_read, ppc405_gpio_write, gpio); |
| ... | ... | @@ -1686,15 +1702,15 @@ static CPUWriteMemoryFunc *serial_mm_write[] = { |
| 1686 | 1702 | }; |
| 1687 | 1703 | |
| 1688 | 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 | 1706 | CharDriverState *chr) |
| 1691 | 1707 | { |
| 1692 | 1708 | void *serial; |
| 1693 | 1709 | |
| 1694 | 1710 | #ifdef DEBUG_SERIAL |
| 1695 | - printf("%s: offset=%08x\n", __func__, offset); | |
| 1711 | + printf("%s: offset=" PADDRX "\n", __func__, offset); | |
| 1696 | 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 | 1714 | ppc4xx_mmio_register(env, mmio, offset, 0x008, |
| 1699 | 1715 | serial_mm_read, serial_mm_write, serial); |
| 1700 | 1716 | } |
| ... | ... | @@ -1869,7 +1885,8 @@ void ppc405_ocm_init (CPUState *env, unsigned long offset) |
| 1869 | 1885 | /* I2C controller */ |
| 1870 | 1886 | typedef struct ppc4xx_i2c_t ppc4xx_i2c_t; |
| 1871 | 1887 | struct ppc4xx_i2c_t { |
| 1872 | - uint32_t base; | |
| 1888 | + target_phys_addr_t base; | |
| 1889 | + qemu_irq irq; | |
| 1873 | 1890 | uint8_t mdata; |
| 1874 | 1891 | uint8_t lmadr; |
| 1875 | 1892 | uint8_t hmadr; |
| ... | ... | @@ -2091,16 +2108,18 @@ static void ppc4xx_i2c_reset (void *opaque) |
| 2091 | 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 | 2114 | ppc4xx_i2c_t *i2c; |
| 2097 | 2115 | |
| 2098 | 2116 | i2c = qemu_mallocz(sizeof(ppc4xx_i2c_t)); |
| 2099 | 2117 | if (i2c != NULL) { |
| 2100 | - i2c->base = mmio->base + offset; | |
| 2118 | + i2c->base = offset; | |
| 2119 | + i2c->irq = irq; | |
| 2101 | 2120 | ppc4xx_i2c_reset(i2c); |
| 2102 | 2121 | #ifdef DEBUG_I2C |
| 2103 | - printf("%s: offset=%08x\n", __func__, offset); | |
| 2122 | + printf("%s: offset=" PADDRX "\n", __func__, offset); | |
| 2104 | 2123 | #endif |
| 2105 | 2124 | ppc4xx_mmio_register(env, mmio, offset, 0x011, |
| 2106 | 2125 | i2c_read, i2c_write, i2c); |
| ... | ... | @@ -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 | 2682 | /* SPR */ |
| 2113 | 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 | 3069 | ppc405_serial_init(env, mmio, 0x400, pic[30], serial_hds[1]); |
| 2500 | 3070 | } |
| 2501 | 3071 | /* IIC controller */ |
| 2502 | - ppc405_i2c_init(env, mmio, 0x500); | |
| 3072 | + ppc405_i2c_init(env, mmio, 0x500, pic[29]); | |
| 2503 | 3073 | /* GPIO */ |
| 2504 | 3074 | ppc405_gpio_init(env, mmio, 0x700); |
| 2505 | 3075 | /* CPU control */ |
| ... | ... | @@ -2521,6 +3091,11 @@ enum { |
| 2521 | 3091 | PPC405EP_CPC0_SRR = 0x0F6, |
| 2522 | 3092 | PPC405EP_CPC0_JTAGID = 0x0F7, |
| 2523 | 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 | 3101 | enum { |
| ... | ... | @@ -2546,6 +3121,10 @@ struct ppc405ep_cpc_t { |
| 2546 | 3121 | uint32_t srr; |
| 2547 | 3122 | uint32_t jtagid; |
| 2548 | 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 | 3130 | static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) |
| ... | ... | @@ -2571,11 +3150,17 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) |
| 2571 | 3150 | #endif |
| 2572 | 3151 | } |
| 2573 | 3152 | PLL_out = VCO_out / D; |
| 3153 | + /* Pretend the PLL is locked */ | |
| 3154 | + cpc->boot |= 0x00000001; | |
| 2574 | 3155 | } else { |
| 2575 | 3156 | #if 0 |
| 2576 | 3157 | pll_bypass: |
| 2577 | 3158 | #endif |
| 2578 | 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 | 3165 | /* Now, compute all other clocks */ |
| 2581 | 3166 | D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */ |
| ... | ... | @@ -2624,6 +3209,8 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) |
| 2624 | 3209 | printf("CPU %d PLB %d OPB %d EBC %d MAL %d PCI %d UART0 %d UART1 %d\n", |
| 2625 | 3210 | CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk, |
| 2626 | 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 | 3214 | #endif |
| 2628 | 3215 | /* Setup CPU clocks */ |
| 2629 | 3216 | clk_setup(&cpc->clk_setup[PPC405EP_CPU_CLK], CPU_clk); |
| ... | ... | @@ -2731,6 +3318,9 @@ static void ppc405ep_cpc_reset (void *opaque) |
| 2731 | 3318 | cpc->ucr = 0x00000000; |
| 2732 | 3319 | cpc->srr = 0x00040000; |
| 2733 | 3320 | cpc->pci = 0x00000000; |
| 3321 | + cpc->er = 0x00000000; | |
| 3322 | + cpc->fr = 0x00000000; | |
| 3323 | + cpc->sr = 0x00000000; | |
| 2734 | 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 | 3354 | &dcr_read_epcpc, &dcr_write_epcpc); |
| 2765 | 3355 | ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc, |
| 2766 | 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 | 3369 | uint32_t sysclk, qemu_irq **picp, |
| 2772 | 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 | 3374 | CPUState *env; |
| 2777 | 3375 | ppc4xx_mmio_t *mmio; |
| 2778 | 3376 | qemu_irq *pic, *irqs; |
| ... | ... | @@ -2782,7 +3380,9 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], |
| 2782 | 3380 | memset(clk_setup, 0, sizeof(clk_setup)); |
| 2783 | 3381 | /* init CPUs */ |
| 2784 | 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 | 3386 | /* Internal devices init */ |
| 2787 | 3387 | /* Memory mapped devices registers */ |
| 2788 | 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 | 3414 | dma_irqs[3] = pic[23]; |
| 2815 | 3415 | ppc405_dma_init(env, dma_irqs); |
| 2816 | 3416 | /* IIC controller */ |
| 2817 | - ppc405_i2c_init(env, mmio, 0x500); | |
| 3417 | + ppc405_i2c_init(env, mmio, 0x500, pic[29]); | |
| 2818 | 3418 | /* GPIO */ |
| 2819 | 3419 | ppc405_gpio_init(env, mmio, 0x700); |
| 2820 | 3420 | /* Serial ports */ |
| ... | ... | @@ -2827,7 +3427,23 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], |
| 2827 | 3427 | /* OCM */ |
| 2828 | 3428 | ppc405_ocm_init(env, ram_sizes[0] + ram_sizes[1]); |
| 2829 | 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 | 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 | 3447 | /* CPU control */ |
| 2832 | 3448 | ppc405ep_cpc_init(env, clk_setup, sysclk); |
| 2833 | 3449 | *offsetp = offset; | ... | ... |