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; | ... | ... |