Commit 9c02f1a2e607b7be71f2dba1cafc096dd3c2dda9

Authored by j_mayer
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;
... ...