Commit 8ecc7913525ecb6a1a41ceceac93d485a544054f

Authored by j_mayer
1 parent 3142255c

Add callbacks to allow dynamic change of PowerPC clocks (to be improved)

Fix embedded PowerPC watchdog and timers
Fix PowerPC 405 SPR
Add generic PowerPC 405 core instanciation code + resets support.
Implement simple peripherals shared by most PowerPC 405 implementations
PowerPC 405 EC & EP microcontrollers preliminary support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2690 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -421,9 +421,9 @@ CPPFLAGS += -DHAS_AUDIO
421 421 endif
422 422 ifeq ($(TARGET_BASE_ARCH), ppc)
423 423 VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
424   -VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
  424 +VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o pflash_cfi02.o
425 425 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
426   -VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
  426 +VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o ppc405_uc.o
427 427 CPPFLAGS += -DHAS_AUDIO
428 428 endif
429 429 ifeq ($(TARGET_BASE_ARCH), mips)
... ...
hw/ppc.c
... ... @@ -290,33 +290,55 @@ static void ppc405_set_irq (void *opaque, int pin, int level)
290 290 int cur_level;
291 291  
292 292 #if defined(PPC_DEBUG_IRQ)
293   - printf("%s: env %p pin %d level %d\n", __func__, env, pin, level);
  293 + if (loglevel & CPU_LOG_INT) {
  294 + fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
  295 + env, pin, level);
  296 + }
294 297 #endif
295 298 cur_level = (env->irq_input_state >> pin) & 1;
296 299 /* Don't generate spurious events */
297 300 if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
298 301 switch (pin) {
299 302 case PPC405_INPUT_RESET_SYS:
300   - /* XXX: TODO: reset all peripherals */
301   - /* No break here */
  303 + if (level) {
  304 +#if defined(PPC_DEBUG_IRQ)
  305 + if (loglevel & CPU_LOG_INT) {
  306 + fprintf(logfile, "%s: reset the PowerPC system\n",
  307 + __func__);
  308 + }
  309 +#endif
  310 + ppc40x_system_reset(env);
  311 + }
  312 + break;
302 313 case PPC405_INPUT_RESET_CHIP:
303   - /* XXX: TODO: reset on-chip peripherals */
  314 + if (level) {
  315 +#if defined(PPC_DEBUG_IRQ)
  316 + if (loglevel & CPU_LOG_INT) {
  317 + fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
  318 + }
  319 +#endif
  320 + ppc40x_chip_reset(env);
  321 + }
  322 + break;
304 323 /* No break here */
305 324 case PPC405_INPUT_RESET_CORE:
306 325 /* XXX: TODO: update DBSR[MRR] */
307 326 if (level) {
308   -#if 0 // XXX: TOFIX
309 327 #if defined(PPC_DEBUG_IRQ)
310   - printf("%s: reset the CPU\n", __func__);
311   -#endif
312   - cpu_reset(env);
  328 + if (loglevel & CPU_LOG_INT) {
  329 + fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
  330 + }
313 331 #endif
  332 + ppc40x_core_reset(env);
314 333 }
315 334 break;
316 335 case PPC405_INPUT_CINT:
317 336 /* Level sensitive - active high */
318 337 #if defined(PPC_DEBUG_IRQ)
319   - printf("%s: set the critical IRQ state to %d\n", __func__, level);
  338 + if (loglevel & CPU_LOG_INT) {
  339 + fprintf(logfile, "%s: set the critical IRQ state to %d\n",
  340 + __func__, level);
  341 + }
320 342 #endif
321 343 /* XXX: TOFIX */
322 344 ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
... ... @@ -538,8 +560,21 @@ static void cpu_ppc_decr_cb (void *opaque)
538 560 _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
539 561 }
540 562  
  563 +static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
  564 +{
  565 + CPUState *env = opaque;
  566 + ppc_tb_t *tb_env = env->tb_env;
  567 +
  568 + tb_env->tb_freq = freq;
  569 + /* There is a bug in Linux 2.4 kernels:
  570 + * if a decrementer exception is pending when it enables msr_ee at startup,
  571 + * it's not ready to handle it...
  572 + */
  573 + _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
  574 +}
  575 +
541 576 /* Set up (once) timebase frequency (in Hz) */
542   -ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq)
  577 +clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
543 578 {
544 579 ppc_tb_t *tb_env;
545 580  
... ... @@ -547,23 +582,15 @@ ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq)
547 582 if (tb_env == NULL)
548 583 return NULL;
549 584 env->tb_env = tb_env;
550   - if (tb_env->tb_freq == 0 || 1) {
551   - tb_env->tb_freq = freq;
552   - /* Create new timer */
553   - tb_env->decr_timer =
554   - qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
555   - /* There is a bug in Linux 2.4 kernels:
556   - * if a decrementer exception is pending when it enables msr_ee,
557   - * it's not ready to handle it...
558   - */
559   - _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
560   - }
  585 + /* Create new timer */
  586 + tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
  587 + cpu_ppc_set_tb_clk(env, freq);
561 588  
562   - return tb_env;
  589 + return &cpu_ppc_set_tb_clk;
563 590 }
564 591  
565 592 /* Specific helpers for POWER & PowerPC 601 RTC */
566   -ppc_tb_t *cpu_ppc601_rtc_init (CPUState *env)
  593 +clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
567 594 {
568 595 return cpu_ppc_tb_init(env, 7812500);
569 596 }
... ... @@ -733,10 +760,14 @@ static void cpu_4xx_wdt_cb (void *opaque)
733 760 /* No reset */
734 761 break;
735 762 case 0x1: /* Core reset */
  763 + ppc40x_core_reset(env);
  764 + break;
736 765 case 0x2: /* Chip reset */
  766 + ppc40x_chip_reset(env);
  767 + break;
737 768 case 0x3: /* System reset */
738   - qemu_system_reset_request();
739   - return;
  769 + ppc40x_system_reset(env);
  770 + break;
740 771 }
741 772 }
742 773 }
... ... @@ -784,20 +815,25 @@ void store_booke_tsr (CPUState *env, target_ulong val)
784 815  
785 816 void store_booke_tcr (CPUState *env, target_ulong val)
786 817 {
787   - /* We don't update timers now. Maybe we should... */
788 818 env->spr[SPR_40x_TCR] = val & 0xFF800000;
  819 + cpu_4xx_wdt_cb(env);
789 820 }
790 821  
791   -void ppc_emb_timers_init (CPUState *env)
  822 +clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
792 823 {
793 824 ppc_tb_t *tb_env;
794 825 ppcemb_timer_t *ppcemb_timer;
795 826  
796   - tb_env = env->tb_env;
  827 + tb_env = qemu_mallocz(sizeof(ppc_tb_t));
  828 + if (tb_env == NULL)
  829 + return NULL;
  830 + env->tb_env = tb_env;
797 831 ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
  832 + tb_env->tb_freq = freq;
798 833 tb_env->opaque = ppcemb_timer;
799   - if (loglevel)
  834 + if (loglevel) {
800 835 fprintf(logfile, "%s %p %p\n", __func__, tb_env, ppcemb_timer);
  836 + }
801 837 if (ppcemb_timer != NULL) {
802 838 /* We use decr timer for PIT */
803 839 tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
... ... @@ -806,6 +842,9 @@ void ppc_emb_timers_init (CPUState *env)
806 842 ppcemb_timer->wdt_timer =
807 843 qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
808 844 }
  845 +
  846 + /* XXX: TODO: add callback for clock frequency change */
  847 + return NULL;
809 848 }
810 849  
811 850 /*****************************************************************************/
... ...
hw/ppc405_uc.c 0 โ†’ 100644
  1 +/*
  2 + * QEMU PowerPC 405 embedded processors emulation
  3 + *
  4 + * Copyright (c) 2007 Jocelyn Mayer
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +extern int loglevel;
  27 +extern FILE *logfile;
  28 +
  29 +#define DEBUG_MMIO
  30 +#define DEBUG_OPBA
  31 +#define DEBUG_SDRAM
  32 +#define DEBUG_GPIO
  33 +#define DEBUG_SERIAL
  34 +#define DEBUG_OCM
  35 +#define DEBUG_I2C
  36 +#define DEBUG_UIC
  37 +#define DEBUG_CLOCKS
  38 +#define DEBUG_UNASSIGNED
  39 +
  40 +/*****************************************************************************/
  41 +/* Generic PowerPC 405 processor instanciation */
  42 +CPUState *ppc405_init (const unsigned char *cpu_model,
  43 + clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
  44 + uint32_t sysclk)
  45 +{
  46 + CPUState *env;
  47 + ppc_def_t *def;
  48 +
  49 + /* init CPUs */
  50 + env = cpu_init();
  51 + qemu_register_reset(&cpu_ppc_reset, env);
  52 + register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
  53 + ppc_find_by_name(cpu_model, &def);
  54 + if (def == NULL) {
  55 + cpu_abort(env, "Unable to find PowerPC %s CPU definition\n",
  56 + cpu_model);
  57 + }
  58 + cpu_ppc_register(env, def);
  59 + cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
  60 + cpu_clk->opaque = env;
  61 + /* Set time-base frequency to sysclk */
  62 + tb_clk->cb = ppc_emb_timers_init(env, sysclk);
  63 + tb_clk->opaque = env;
  64 + ppc_dcr_init(env, NULL, NULL);
  65 +
  66 + return env;
  67 +}
  68 +
  69 +/*****************************************************************************/
  70 +/* Shared peripherals */
  71 +
  72 +/*****************************************************************************/
  73 +/* Fake device used to map multiple devices in a single memory page */
  74 +#define MMIO_AREA_BITS 8
  75 +#define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
  76 +#define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
  77 +#define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
  78 +struct ppc4xx_mmio_t {
  79 + uint32_t base;
  80 + CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
  81 + CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
  82 + void *opaque[MMIO_AREA_NB];
  83 +};
  84 +
  85 +static uint32_t unassigned_mem_readb (void *opaque, target_phys_addr_t addr)
  86 +{
  87 +#ifdef DEBUG_UNASSIGNED
  88 + printf("Unassigned mem read 0x" PADDRX "\n", addr);
  89 +#endif
  90 +
  91 + return 0;
  92 +}
  93 +
  94 +static void unassigned_mem_writeb (void *opaque,
  95 + target_phys_addr_t addr, uint32_t val)
  96 +{
  97 +#ifdef DEBUG_UNASSIGNED
  98 + printf("Unassigned mem write 0x" PADDRX " = 0x%x\n", addr, val);
  99 +#endif
  100 +}
  101 +
  102 +static CPUReadMemoryFunc *unassigned_mem_read[3] = {
  103 + unassigned_mem_readb,
  104 + unassigned_mem_readb,
  105 + unassigned_mem_readb,
  106 +};
  107 +
  108 +static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
  109 + unassigned_mem_writeb,
  110 + unassigned_mem_writeb,
  111 + unassigned_mem_writeb,
  112 +};
  113 +
  114 +static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
  115 + target_phys_addr_t addr, int len)
  116 +{
  117 + CPUReadMemoryFunc **mem_read;
  118 + uint32_t ret;
  119 + int idx;
  120 +
  121 + idx = MMIO_IDX(addr - mmio->base);
  122 +#if defined(DEBUG_MMIO)
  123 + printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
  124 + mmio, len, addr, idx);
  125 +#endif
  126 + mem_read = mmio->mem_read[idx];
  127 + ret = (*mem_read[len])(mmio->opaque[idx], addr);
  128 +
  129 + return ret;
  130 +}
  131 +
  132 +static void mmio_writelen (ppc4xx_mmio_t *mmio,
  133 + target_phys_addr_t addr, uint32_t value, int len)
  134 +{
  135 + CPUWriteMemoryFunc **mem_write;
  136 + int idx;
  137 +
  138 + idx = MMIO_IDX(addr - mmio->base);
  139 +#if defined(DEBUG_MMIO)
  140 + printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08x\n", __func__,
  141 + mmio, len, addr, idx, value);
  142 +#endif
  143 + mem_write = mmio->mem_write[idx];
  144 + (*mem_write[len])(mmio->opaque[idx], addr, value);
  145 +}
  146 +
  147 +static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
  148 +{
  149 +#if defined(DEBUG_MMIO)
  150 + printf("%s: addr " PADDRX "\n", __func__, addr);
  151 +#endif
  152 +
  153 + return mmio_readlen(opaque, addr, 0);
  154 +}
  155 +
  156 +static void mmio_writeb (void *opaque,
  157 + target_phys_addr_t addr, uint32_t value)
  158 +{
  159 +#if defined(DEBUG_MMIO)
  160 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  161 +#endif
  162 + mmio_writelen(opaque, addr, value, 0);
  163 +}
  164 +
  165 +static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
  166 +{
  167 +#if defined(DEBUG_MMIO)
  168 + printf("%s: addr " PADDRX "\n", __func__, addr);
  169 +#endif
  170 +
  171 + return mmio_readlen(opaque, addr, 1);
  172 +}
  173 +
  174 +static void mmio_writew (void *opaque,
  175 + target_phys_addr_t addr, uint32_t value)
  176 +{
  177 +#if defined(DEBUG_MMIO)
  178 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  179 +#endif
  180 + mmio_writelen(opaque, addr, value, 1);
  181 +}
  182 +
  183 +static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
  184 +{
  185 +#if defined(DEBUG_MMIO)
  186 + printf("%s: addr " PADDRX "\n", __func__, addr);
  187 +#endif
  188 +
  189 + return mmio_readlen(opaque, addr, 2);
  190 +}
  191 +
  192 +static void mmio_writel (void *opaque,
  193 + target_phys_addr_t addr, uint32_t value)
  194 +{
  195 +#if defined(DEBUG_MMIO)
  196 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  197 +#endif
  198 + mmio_writelen(opaque, addr, value, 2);
  199 +}
  200 +
  201 +static CPUReadMemoryFunc *mmio_read[] = {
  202 + &mmio_readb,
  203 + &mmio_readw,
  204 + &mmio_readl,
  205 +};
  206 +
  207 +static CPUWriteMemoryFunc *mmio_write[] = {
  208 + &mmio_writeb,
  209 + &mmio_writew,
  210 + &mmio_writel,
  211 +};
  212 +
  213 +int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
  214 + uint32_t offset, uint32_t len,
  215 + CPUReadMemoryFunc **mem_read,
  216 + CPUWriteMemoryFunc **mem_write, void *opaque)
  217 +{
  218 + uint32_t end;
  219 + int idx, eidx;
  220 +
  221 + if ((offset + len) > TARGET_PAGE_SIZE)
  222 + return -1;
  223 + idx = MMIO_IDX(offset);
  224 + end = offset + len - 1;
  225 + eidx = MMIO_IDX(end);
  226 +#if defined(DEBUG_MMIO)
  227 + printf("%s: offset %08x len %08x %08x %d %d\n", __func__, offset, len,
  228 + end, idx, eidx);
  229 +#endif
  230 + for (; idx <= eidx; idx++) {
  231 + mmio->mem_read[idx] = mem_read;
  232 + mmio->mem_write[idx] = mem_write;
  233 + mmio->opaque[idx] = opaque;
  234 + }
  235 +
  236 + return 0;
  237 +}
  238 +
  239 +ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, uint32_t base)
  240 +{
  241 + ppc4xx_mmio_t *mmio;
  242 + int mmio_memory;
  243 +
  244 + mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
  245 + if (mmio != NULL) {
  246 + mmio->base = base;
  247 + mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio);
  248 +#if defined(DEBUG_MMIO)
  249 + printf("%s: %p base %08x len %08x %d\n", __func__,
  250 + mmio, base, TARGET_PAGE_SIZE, mmio_memory);
  251 +#endif
  252 + cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
  253 + ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
  254 + unassigned_mem_read, unassigned_mem_write, NULL);
  255 + }
  256 +
  257 + return mmio;
  258 +}
  259 +
  260 +/*****************************************************************************/
  261 +/* Peripheral local bus arbitrer */
  262 +enum {
  263 + PLB0_BESR = 0x084,
  264 + PLB0_BEAR = 0x086,
  265 + PLB0_ACR = 0x087,
  266 +};
  267 +
  268 +typedef struct ppc4xx_plb_t ppc4xx_plb_t;
  269 +struct ppc4xx_plb_t {
  270 + uint32_t acr;
  271 + uint32_t bear;
  272 + uint32_t besr;
  273 +};
  274 +
  275 +static target_ulong dcr_read_plb (void *opaque, int dcrn)
  276 +{
  277 + ppc4xx_plb_t *plb;
  278 + target_ulong ret;
  279 +
  280 + plb = opaque;
  281 + switch (dcrn) {
  282 + case PLB0_ACR:
  283 + ret = plb->acr;
  284 + break;
  285 + case PLB0_BEAR:
  286 + ret = plb->bear;
  287 + break;
  288 + case PLB0_BESR:
  289 + ret = plb->besr;
  290 + break;
  291 + default:
  292 + /* Avoid gcc warning */
  293 + ret = 0;
  294 + break;
  295 + }
  296 +
  297 + return ret;
  298 +}
  299 +
  300 +static void dcr_write_plb (void *opaque, int dcrn, target_ulong val)
  301 +{
  302 + ppc4xx_plb_t *plb;
  303 +
  304 + plb = opaque;
  305 + switch (dcrn) {
  306 + case PLB0_ACR:
  307 + plb->acr = val & 0xFC000000;
  308 + break;
  309 + case PLB0_BEAR:
  310 + /* Read only */
  311 + break;
  312 + case PLB0_BESR:
  313 + /* Write-clear */
  314 + plb->besr &= ~val;
  315 + break;
  316 + }
  317 +}
  318 +
  319 +static void ppc4xx_plb_reset (void *opaque)
  320 +{
  321 + ppc4xx_plb_t *plb;
  322 +
  323 + plb = opaque;
  324 + plb->acr = 0x00000000;
  325 + plb->bear = 0x00000000;
  326 + plb->besr = 0x00000000;
  327 +}
  328 +
  329 +void ppc4xx_plb_init (CPUState *env)
  330 +{
  331 + ppc4xx_plb_t *plb;
  332 +
  333 + plb = qemu_mallocz(sizeof(ppc4xx_plb_t));
  334 + if (plb != NULL) {
  335 + ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
  336 + ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
  337 + ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
  338 + ppc4xx_plb_reset(plb);
  339 + qemu_register_reset(ppc4xx_plb_reset, plb);
  340 + }
  341 +}
  342 +
  343 +/*****************************************************************************/
  344 +/* PLB to OPB bridge */
  345 +enum {
  346 + POB0_BESR0 = 0x0A0,
  347 + POB0_BESR1 = 0x0A2,
  348 + POB0_BEAR = 0x0A4,
  349 +};
  350 +
  351 +typedef struct ppc4xx_pob_t ppc4xx_pob_t;
  352 +struct ppc4xx_pob_t {
  353 + uint32_t bear;
  354 + uint32_t besr[2];
  355 +};
  356 +
  357 +static target_ulong dcr_read_pob (void *opaque, int dcrn)
  358 +{
  359 + ppc4xx_pob_t *pob;
  360 + target_ulong ret;
  361 +
  362 + pob = opaque;
  363 + switch (dcrn) {
  364 + case POB0_BEAR:
  365 + ret = pob->bear;
  366 + break;
  367 + case POB0_BESR0:
  368 + case POB0_BESR1:
  369 + ret = pob->besr[dcrn - POB0_BESR0];
  370 + break;
  371 + default:
  372 + /* Avoid gcc warning */
  373 + ret = 0;
  374 + break;
  375 + }
  376 +
  377 + return ret;
  378 +}
  379 +
  380 +static void dcr_write_pob (void *opaque, int dcrn, target_ulong val)
  381 +{
  382 + ppc4xx_pob_t *pob;
  383 +
  384 + pob = opaque;
  385 + switch (dcrn) {
  386 + case POB0_BEAR:
  387 + /* Read only */
  388 + break;
  389 + case POB0_BESR0:
  390 + case POB0_BESR1:
  391 + /* Write-clear */
  392 + pob->besr[dcrn - POB0_BESR0] &= ~val;
  393 + break;
  394 + }
  395 +}
  396 +
  397 +static void ppc4xx_pob_reset (void *opaque)
  398 +{
  399 + ppc4xx_pob_t *pob;
  400 +
  401 + pob = opaque;
  402 + /* No error */
  403 + pob->bear = 0x00000000;
  404 + pob->besr[0] = 0x0000000;
  405 + pob->besr[1] = 0x0000000;
  406 +}
  407 +
  408 +void ppc4xx_pob_init (CPUState *env)
  409 +{
  410 + ppc4xx_pob_t *pob;
  411 +
  412 + pob = qemu_mallocz(sizeof(ppc4xx_pob_t));
  413 + if (pob != NULL) {
  414 + ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob);
  415 + ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob);
  416 + ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob);
  417 + qemu_register_reset(ppc4xx_pob_reset, pob);
  418 + ppc4xx_pob_reset(env);
  419 + }
  420 +}
  421 +
  422 +/*****************************************************************************/
  423 +/* OPB arbitrer */
  424 +typedef struct ppc4xx_opba_t ppc4xx_opba_t;
  425 +struct ppc4xx_opba_t {
  426 + target_ulong base;
  427 + uint8_t cr;
  428 + uint8_t pr;
  429 +};
  430 +
  431 +static uint32_t opba_readb (void *opaque, target_phys_addr_t addr)
  432 +{
  433 + ppc4xx_opba_t *opba;
  434 + uint32_t ret;
  435 +
  436 +#ifdef DEBUG_OPBA
  437 + printf("%s: addr " PADDRX "\n", __func__, addr);
  438 +#endif
  439 + opba = opaque;
  440 + switch (addr - opba->base) {
  441 + case 0x00:
  442 + ret = opba->cr;
  443 + break;
  444 + case 0x01:
  445 + ret = opba->pr;
  446 + break;
  447 + default:
  448 + ret = 0x00;
  449 + break;
  450 + }
  451 +
  452 + return ret;
  453 +}
  454 +
  455 +static void opba_writeb (void *opaque,
  456 + target_phys_addr_t addr, uint32_t value)
  457 +{
  458 + ppc4xx_opba_t *opba;
  459 +
  460 +#ifdef DEBUG_OPBA
  461 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  462 +#endif
  463 + opba = opaque;
  464 + switch (addr - opba->base) {
  465 + case 0x00:
  466 + opba->cr = value & 0xF8;
  467 + break;
  468 + case 0x01:
  469 + opba->pr = value & 0xFF;
  470 + break;
  471 + default:
  472 + break;
  473 + }
  474 +}
  475 +
  476 +static uint32_t opba_readw (void *opaque, target_phys_addr_t addr)
  477 +{
  478 + uint32_t ret;
  479 +
  480 +#ifdef DEBUG_OPBA
  481 + printf("%s: addr " PADDRX "\n", __func__, addr);
  482 +#endif
  483 + ret = opba_readb(opaque, addr) << 8;
  484 + ret |= opba_readb(opaque, addr + 1);
  485 +
  486 + return ret;
  487 +}
  488 +
  489 +static void opba_writew (void *opaque,
  490 + target_phys_addr_t addr, uint32_t value)
  491 +{
  492 +#ifdef DEBUG_OPBA
  493 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  494 +#endif
  495 + opba_writeb(opaque, addr, value >> 8);
  496 + opba_writeb(opaque, addr + 1, value);
  497 +}
  498 +
  499 +static uint32_t opba_readl (void *opaque, target_phys_addr_t addr)
  500 +{
  501 + uint32_t ret;
  502 +
  503 +#ifdef DEBUG_OPBA
  504 + printf("%s: addr " PADDRX "\n", __func__, addr);
  505 +#endif
  506 + ret = opba_readb(opaque, addr) << 24;
  507 + ret |= opba_readb(opaque, addr + 1) << 16;
  508 +
  509 + return ret;
  510 +}
  511 +
  512 +static void opba_writel (void *opaque,
  513 + target_phys_addr_t addr, uint32_t value)
  514 +{
  515 +#ifdef DEBUG_OPBA
  516 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  517 +#endif
  518 + opba_writeb(opaque, addr, value >> 24);
  519 + opba_writeb(opaque, addr + 1, value >> 16);
  520 +}
  521 +
  522 +static CPUReadMemoryFunc *opba_read[] = {
  523 + &opba_readb,
  524 + &opba_readw,
  525 + &opba_readl,
  526 +};
  527 +
  528 +static CPUWriteMemoryFunc *opba_write[] = {
  529 + &opba_writeb,
  530 + &opba_writew,
  531 + &opba_writel,
  532 +};
  533 +
  534 +static void ppc4xx_opba_reset (void *opaque)
  535 +{
  536 + ppc4xx_opba_t *opba;
  537 +
  538 + opba = opaque;
  539 + opba->cr = 0x00; /* No dynamic priorities - park disabled */
  540 + opba->pr = 0x11;
  541 +}
  542 +
  543 +void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset)
  544 +{
  545 + ppc4xx_opba_t *opba;
  546 +
  547 + opba = qemu_mallocz(sizeof(ppc4xx_opba_t));
  548 + if (opba != NULL) {
  549 + opba->base = mmio->base + offset;
  550 +#ifdef DEBUG_OPBA
  551 + printf("%s: offset=%08x\n", __func__, offset);
  552 +#endif
  553 + ppc4xx_mmio_register(env, mmio, offset, 0x002,
  554 + opba_read, opba_write, opba);
  555 + qemu_register_reset(ppc4xx_opba_reset, opba);
  556 + ppc4xx_opba_reset(opba);
  557 + }
  558 +}
  559 +
  560 +/*****************************************************************************/
  561 +/* "Universal" Interrupt controller */
  562 +enum {
  563 + DCR_UICSR = 0x000,
  564 + DCR_UICSRS = 0x001,
  565 + DCR_UICER = 0x002,
  566 + DCR_UICCR = 0x003,
  567 + DCR_UICPR = 0x004,
  568 + DCR_UICTR = 0x005,
  569 + DCR_UICMSR = 0x006,
  570 + DCR_UICVR = 0x007,
  571 + DCR_UICVCR = 0x008,
  572 + DCR_UICMAX = 0x009,
  573 +};
  574 +
  575 +#define UIC_MAX_IRQ 32
  576 +typedef struct ppcuic_t ppcuic_t;
  577 +struct ppcuic_t {
  578 + uint32_t dcr_base;
  579 + int use_vectors;
  580 + uint32_t uicsr; /* Status register */
  581 + uint32_t uicer; /* Enable register */
  582 + uint32_t uiccr; /* Critical register */
  583 + uint32_t uicpr; /* Polarity register */
  584 + uint32_t uictr; /* Triggering register */
  585 + uint32_t uicvcr; /* Vector configuration register */
  586 + uint32_t uicvr;
  587 + qemu_irq *irqs;
  588 +};
  589 +
  590 +static void ppcuic_trigger_irq (ppcuic_t *uic)
  591 +{
  592 + uint32_t ir, cr;
  593 + int start, end, inc, i;
  594 +
  595 + /* Trigger interrupt if any is pending */
  596 + ir = uic->uicsr & uic->uicer & (~uic->uiccr);
  597 + cr = uic->uicsr & uic->uicer & uic->uiccr;
  598 +#ifdef DEBUG_UIC
  599 + if (loglevel & CPU_LOG_INT) {
  600 + fprintf(logfile, "%s: uicsr %08x uicer %08x uiccr %08x\n"
  601 + " %08x ir %08x cr %08x\n", __func__,
  602 + uic->uicsr, uic->uicer, uic->uiccr,
  603 + uic->uicsr & uic->uicer, ir, cr);
  604 + }
  605 +#endif
  606 + if (ir != 0x0000000) {
  607 +#ifdef DEBUG_UIC
  608 + if (loglevel & CPU_LOG_INT) {
  609 + fprintf(logfile, "Raise UIC interrupt\n");
  610 + }
  611 +#endif
  612 + qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
  613 + } else {
  614 +#ifdef DEBUG_UIC
  615 + if (loglevel & CPU_LOG_INT) {
  616 + fprintf(logfile, "Lower UIC interrupt\n");
  617 + }
  618 +#endif
  619 + qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
  620 + }
  621 + /* Trigger critical interrupt if any is pending and update vector */
  622 + if (cr != 0x0000000) {
  623 + qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
  624 + if (uic->use_vectors) {
  625 + /* Compute critical IRQ vector */
  626 + if (uic->uicvcr & 1) {
  627 + start = 31;
  628 + end = 0;
  629 + inc = -1;
  630 + } else {
  631 + start = 0;
  632 + end = 31;
  633 + inc = 1;
  634 + }
  635 + uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
  636 + for (i = start; i <= end; i += inc) {
  637 + if (cr & (1 << i)) {
  638 + uic->uicvr += (i - start) * 512 * inc;
  639 + break;
  640 + }
  641 + }
  642 + }
  643 +#ifdef DEBUG_UIC
  644 + if (loglevel & CPU_LOG_INT) {
  645 + fprintf(logfile, "Raise UIC critical interrupt - vector %08x\n",
  646 + uic->uicvr);
  647 + }
  648 +#endif
  649 + } else {
  650 +#ifdef DEBUG_UIC
  651 + if (loglevel & CPU_LOG_INT) {
  652 + fprintf(logfile, "Lower UIC critical interrupt\n");
  653 + }
  654 +#endif
  655 + qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
  656 + uic->uicvr = 0x00000000;
  657 + }
  658 +}
  659 +
  660 +static void ppcuic_set_irq (void *opaque, int irq_num, int level)
  661 +{
  662 + ppcuic_t *uic;
  663 + uint32_t mask, sr;
  664 +
  665 + uic = opaque;
  666 + mask = 1 << irq_num;
  667 +#ifdef DEBUG_UIC
  668 + if (loglevel & CPU_LOG_INT) {
  669 + fprintf(logfile, "%s: irq %d level %d uicsr %08x mask %08x => %08x "
  670 + "%08x\n", __func__, irq_num, level,
  671 + uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
  672 + }
  673 +#endif
  674 + if (irq_num < 0 || irq_num > 31)
  675 + return;
  676 + sr = uic->uicsr;
  677 + if (!(uic->uicpr & mask)) {
  678 + /* Negatively asserted IRQ */
  679 + level = level == 0 ? 1 : 0;
  680 + }
  681 + /* Update status register */
  682 + if (uic->uictr & mask) {
  683 + /* Edge sensitive interrupt */
  684 + if (level == 1)
  685 + uic->uicsr |= mask;
  686 + } else {
  687 + /* Level sensitive interrupt */
  688 + if (level == 1)
  689 + uic->uicsr |= mask;
  690 + else
  691 + uic->uicsr &= ~mask;
  692 + }
  693 +#ifdef DEBUG_UIC
  694 + if (loglevel & CPU_LOG_INT) {
  695 + fprintf(logfile, "%s: irq %d level %d sr %08x => %08x\n", __func__,
  696 + irq_num, level, uic->uicsr, sr);
  697 + }
  698 +#endif
  699 + if (sr != uic->uicsr)
  700 + ppcuic_trigger_irq(uic);
  701 +}
  702 +
  703 +static target_ulong dcr_read_uic (void *opaque, int dcrn)
  704 +{
  705 + ppcuic_t *uic;
  706 + target_ulong ret;
  707 +
  708 + uic = opaque;
  709 + dcrn -= uic->dcr_base;
  710 + switch (dcrn) {
  711 + case DCR_UICSR:
  712 + case DCR_UICSRS:
  713 + ret = uic->uicsr;
  714 + break;
  715 + case DCR_UICER:
  716 + ret = uic->uicer;
  717 + break;
  718 + case DCR_UICCR:
  719 + ret = uic->uiccr;
  720 + break;
  721 + case DCR_UICPR:
  722 + ret = uic->uicpr;
  723 + break;
  724 + case DCR_UICTR:
  725 + ret = uic->uictr;
  726 + break;
  727 + case DCR_UICMSR:
  728 + ret = uic->uicsr & uic->uicer;
  729 + break;
  730 + case DCR_UICVR:
  731 + if (!uic->use_vectors)
  732 + goto no_read;
  733 + ret = uic->uicvr;
  734 + break;
  735 + case DCR_UICVCR:
  736 + if (!uic->use_vectors)
  737 + goto no_read;
  738 + ret = uic->uicvcr;
  739 + break;
  740 + default:
  741 + no_read:
  742 + ret = 0x00000000;
  743 + break;
  744 + }
  745 +
  746 + return ret;
  747 +}
  748 +
  749 +static void dcr_write_uic (void *opaque, int dcrn, target_ulong val)
  750 +{
  751 + ppcuic_t *uic;
  752 +
  753 + uic = opaque;
  754 + dcrn -= uic->dcr_base;
  755 +#ifdef DEBUG_UIC
  756 + if (loglevel & CPU_LOG_INT) {
  757 + fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val);
  758 + }
  759 +#endif
  760 + switch (dcrn) {
  761 + case DCR_UICSR:
  762 + uic->uicsr &= ~val;
  763 + ppcuic_trigger_irq(uic);
  764 + break;
  765 + case DCR_UICSRS:
  766 + uic->uicsr |= val;
  767 + ppcuic_trigger_irq(uic);
  768 + break;
  769 + case DCR_UICER:
  770 + uic->uicer = val;
  771 + ppcuic_trigger_irq(uic);
  772 + break;
  773 + case DCR_UICCR:
  774 + uic->uiccr = val;
  775 + ppcuic_trigger_irq(uic);
  776 + break;
  777 + case DCR_UICPR:
  778 + uic->uicpr = val;
  779 + ppcuic_trigger_irq(uic);
  780 + break;
  781 + case DCR_UICTR:
  782 + uic->uictr = val;
  783 + ppcuic_trigger_irq(uic);
  784 + break;
  785 + case DCR_UICMSR:
  786 + break;
  787 + case DCR_UICVR:
  788 + break;
  789 + case DCR_UICVCR:
  790 + uic->uicvcr = val & 0xFFFFFFFD;
  791 + ppcuic_trigger_irq(uic);
  792 + break;
  793 + }
  794 +}
  795 +
  796 +static void ppcuic_reset (void *opaque)
  797 +{
  798 + ppcuic_t *uic;
  799 +
  800 + uic = opaque;
  801 + uic->uiccr = 0x00000000;
  802 + uic->uicer = 0x00000000;
  803 + uic->uicpr = 0x00000000;
  804 + uic->uicsr = 0x00000000;
  805 + uic->uictr = 0x00000000;
  806 + if (uic->use_vectors) {
  807 + uic->uicvcr = 0x00000000;
  808 + uic->uicvr = 0x0000000;
  809 + }
  810 +}
  811 +
  812 +qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
  813 + uint32_t dcr_base, int has_ssr, int has_vr)
  814 +{
  815 + ppcuic_t *uic;
  816 + int i;
  817 +
  818 + uic = qemu_mallocz(sizeof(ppcuic_t));
  819 + if (uic != NULL) {
  820 + uic->dcr_base = dcr_base;
  821 + uic->irqs = irqs;
  822 + if (has_vr)
  823 + uic->use_vectors = 1;
  824 + for (i = 0; i < DCR_UICMAX; i++) {
  825 + ppc_dcr_register(env, dcr_base + i, uic,
  826 + &dcr_read_uic, &dcr_write_uic);
  827 + }
  828 + qemu_register_reset(ppcuic_reset, uic);
  829 + ppcuic_reset(uic);
  830 + }
  831 +
  832 + return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
  833 +}
  834 +
  835 +/*****************************************************************************/
  836 +/* Code decompression controller */
  837 +/* XXX: TODO */
  838 +
  839 +/*****************************************************************************/
  840 +/* SDRAM controller */
  841 +typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
  842 +struct ppc4xx_sdram_t {
  843 + uint32_t addr;
  844 + int nbanks;
  845 + target_ulong ram_bases[4];
  846 + target_ulong ram_sizes[4];
  847 + uint32_t besr0;
  848 + uint32_t besr1;
  849 + uint32_t bear;
  850 + uint32_t cfg;
  851 + uint32_t status;
  852 + uint32_t rtr;
  853 + uint32_t pmit;
  854 + uint32_t bcr[4];
  855 + uint32_t tr;
  856 + uint32_t ecccfg;
  857 + uint32_t eccesr;
  858 + qemu_irq irq;
  859 +};
  860 +
  861 +enum {
  862 + SDRAM0_CFGADDR = 0x010,
  863 + SDRAM0_CFGDATA = 0x011,
  864 +};
  865 +
  866 +static uint32_t sdram_bcr (target_ulong ram_base, target_ulong ram_size)
  867 +{
  868 + uint32_t bcr;
  869 +
  870 + switch (ram_size) {
  871 + case (4 * 1024 * 1024):
  872 + bcr = 0x00000000;
  873 + break;
  874 + case (8 * 1024 * 1024):
  875 + bcr = 0x00020000;
  876 + break;
  877 + case (16 * 1024 * 1024):
  878 + bcr = 0x00040000;
  879 + break;
  880 + case (32 * 1024 * 1024):
  881 + bcr = 0x00060000;
  882 + break;
  883 + case (64 * 1024 * 1024):
  884 + bcr = 0x00080000;
  885 + break;
  886 + case (128 * 1024 * 1024):
  887 + bcr = 0x000A0000;
  888 + break;
  889 + case (256 * 1024 * 1024):
  890 + bcr = 0x000C0000;
  891 + break;
  892 + default:
  893 + printf("%s: invalid RAM size " TARGET_FMT_ld "\n", __func__, ram_size);
  894 + return 0x00000000;
  895 + }
  896 + bcr |= ram_base & 0xFF800000;
  897 + bcr |= 1;
  898 +
  899 + return bcr;
  900 +}
  901 +
  902 +static inline target_ulong sdram_base (uint32_t bcr)
  903 +{
  904 + return bcr & 0xFF800000;
  905 +}
  906 +
  907 +static target_ulong sdram_size (uint32_t bcr)
  908 +{
  909 + target_ulong size;
  910 + int sh;
  911 +
  912 + sh = (bcr >> 17) & 0x7;
  913 + if (sh == 7)
  914 + size = -1;
  915 + else
  916 + size = (4 * 1024 * 1024) << sh;
  917 +
  918 + return size;
  919 +}
  920 +
  921 +static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
  922 +{
  923 + if (*bcrp & 0x00000001) {
  924 + /* Unmap RAM */
  925 +#ifdef DEBUG_SDRAM
  926 + printf("%s: unmap RAM area " ADDRX " " ADDRX "\n", __func__,
  927 + sdram_base(*bcrp), sdram_size(*bcrp));
  928 +#endif
  929 + cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
  930 + IO_MEM_UNASSIGNED);
  931 + }
  932 + *bcrp = bcr & 0xFFDEE001;
  933 + if (enabled && (bcr & 0x00000001)) {
  934 +#ifdef DEBUG_SDRAM
  935 + printf("%s: Map RAM area " ADDRX " " ADDRX "\n", __func__,
  936 + sdram_base(bcr), sdram_size(bcr));
  937 +#endif
  938 + cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
  939 + sdram_base(bcr) | IO_MEM_RAM);
  940 + }
  941 +}
  942 +
  943 +static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
  944 +{
  945 + int i;
  946 +
  947 + for (i = 0; i < sdram->nbanks; i++) {
  948 + if (sdram->ram_sizes[i] != 0) {
  949 + sdram_set_bcr(&sdram->bcr[i],
  950 + sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
  951 + 1);
  952 + } else {
  953 + sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
  954 + }
  955 + }
  956 +}
  957 +
  958 +static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
  959 +{
  960 + int i;
  961 +
  962 + for (i = 0; i < sdram->nbanks; i++) {
  963 + cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
  964 + sdram_size(sdram->bcr[i]),
  965 + IO_MEM_UNASSIGNED);
  966 + }
  967 +}
  968 +
  969 +static target_ulong dcr_read_sdram (void *opaque, int dcrn)
  970 +{
  971 + ppc4xx_sdram_t *sdram;
  972 + target_ulong ret;
  973 +
  974 + sdram = opaque;
  975 + switch (dcrn) {
  976 + case SDRAM0_CFGADDR:
  977 + ret = sdram->addr;
  978 + break;
  979 + case SDRAM0_CFGDATA:
  980 + switch (sdram->addr) {
  981 + case 0x00: /* SDRAM_BESR0 */
  982 + ret = sdram->besr0;
  983 + break;
  984 + case 0x08: /* SDRAM_BESR1 */
  985 + ret = sdram->besr1;
  986 + break;
  987 + case 0x10: /* SDRAM_BEAR */
  988 + ret = sdram->bear;
  989 + break;
  990 + case 0x20: /* SDRAM_CFG */
  991 + ret = sdram->cfg;
  992 + break;
  993 + case 0x24: /* SDRAM_STATUS */
  994 + ret = sdram->status;
  995 + break;
  996 + case 0x30: /* SDRAM_RTR */
  997 + ret = sdram->rtr;
  998 + break;
  999 + case 0x34: /* SDRAM_PMIT */
  1000 + ret = sdram->pmit;
  1001 + break;
  1002 + case 0x40: /* SDRAM_B0CR */
  1003 + ret = sdram->bcr[0];
  1004 + break;
  1005 + case 0x44: /* SDRAM_B1CR */
  1006 + ret = sdram->bcr[1];
  1007 + break;
  1008 + case 0x48: /* SDRAM_B2CR */
  1009 + ret = sdram->bcr[2];
  1010 + break;
  1011 + case 0x4C: /* SDRAM_B3CR */
  1012 + ret = sdram->bcr[3];
  1013 + break;
  1014 + case 0x80: /* SDRAM_TR */
  1015 + ret = -1; /* ? */
  1016 + break;
  1017 + case 0x94: /* SDRAM_ECCCFG */
  1018 + ret = sdram->ecccfg;
  1019 + break;
  1020 + case 0x98: /* SDRAM_ECCESR */
  1021 + ret = sdram->eccesr;
  1022 + break;
  1023 + default: /* Error */
  1024 + ret = -1;
  1025 + break;
  1026 + }
  1027 + break;
  1028 + default:
  1029 + /* Avoid gcc warning */
  1030 + ret = 0x00000000;
  1031 + break;
  1032 + }
  1033 +
  1034 + return ret;
  1035 +}
  1036 +
  1037 +static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
  1038 +{
  1039 + ppc4xx_sdram_t *sdram;
  1040 +
  1041 + sdram = opaque;
  1042 + switch (dcrn) {
  1043 + case SDRAM0_CFGADDR:
  1044 + sdram->addr = val;
  1045 + break;
  1046 + case SDRAM0_CFGDATA:
  1047 + switch (sdram->addr) {
  1048 + case 0x00: /* SDRAM_BESR0 */
  1049 + sdram->besr0 &= ~val;
  1050 + break;
  1051 + case 0x08: /* SDRAM_BESR1 */
  1052 + sdram->besr1 &= ~val;
  1053 + break;
  1054 + case 0x10: /* SDRAM_BEAR */
  1055 + sdram->bear = val;
  1056 + break;
  1057 + case 0x20: /* SDRAM_CFG */
  1058 + val &= 0xFFE00000;
  1059 + if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
  1060 +#ifdef DEBUG_SDRAM
  1061 + printf("%s: enable SDRAM controller\n", __func__);
  1062 +#endif
  1063 + /* validate all RAM mappings */
  1064 + sdram_map_bcr(sdram);
  1065 + sdram->status &= ~0x80000000;
  1066 + } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
  1067 +#ifdef DEBUG_SDRAM
  1068 + printf("%s: disable SDRAM controller\n", __func__);
  1069 +#endif
  1070 + /* invalidate all RAM mappings */
  1071 + sdram_unmap_bcr(sdram);
  1072 + sdram->status |= 0x80000000;
  1073 + }
  1074 + if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
  1075 + sdram->status |= 0x40000000;
  1076 + else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
  1077 + sdram->status &= ~0x40000000;
  1078 + sdram->cfg = val;
  1079 + break;
  1080 + case 0x24: /* SDRAM_STATUS */
  1081 + /* Read-only register */
  1082 + break;
  1083 + case 0x30: /* SDRAM_RTR */
  1084 + sdram->rtr = val & 0x3FF80000;
  1085 + break;
  1086 + case 0x34: /* SDRAM_PMIT */
  1087 + sdram->pmit = (val & 0xF8000000) | 0x07C00000;
  1088 + break;
  1089 + case 0x40: /* SDRAM_B0CR */
  1090 + sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
  1091 + break;
  1092 + case 0x44: /* SDRAM_B1CR */
  1093 + sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
  1094 + break;
  1095 + case 0x48: /* SDRAM_B2CR */
  1096 + sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
  1097 + break;
  1098 + case 0x4C: /* SDRAM_B3CR */
  1099 + sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
  1100 + break;
  1101 + case 0x80: /* SDRAM_TR */
  1102 + sdram->tr = val & 0x018FC01F;
  1103 + break;
  1104 + case 0x94: /* SDRAM_ECCCFG */
  1105 + sdram->ecccfg = val & 0x00F00000;
  1106 + break;
  1107 + case 0x98: /* SDRAM_ECCESR */
  1108 + val &= 0xFFF0F000;
  1109 + if (sdram->eccesr == 0 && val != 0)
  1110 + qemu_irq_raise(sdram->irq);
  1111 + else if (sdram->eccesr != 0 && val == 0)
  1112 + qemu_irq_lower(sdram->irq);
  1113 + sdram->eccesr = val;
  1114 + break;
  1115 + default: /* Error */
  1116 + break;
  1117 + }
  1118 + break;
  1119 + }
  1120 +}
  1121 +
  1122 +static void sdram_reset (void *opaque)
  1123 +{
  1124 + ppc4xx_sdram_t *sdram;
  1125 +
  1126 + sdram = opaque;
  1127 + sdram->addr = 0x00000000;
  1128 + sdram->bear = 0x00000000;
  1129 + sdram->besr0 = 0x00000000; /* No error */
  1130 + sdram->besr1 = 0x00000000; /* No error */
  1131 + sdram->cfg = 0x00000000;
  1132 + sdram->ecccfg = 0x00000000; /* No ECC */
  1133 + sdram->eccesr = 0x00000000; /* No error */
  1134 + sdram->pmit = 0x07C00000;
  1135 + sdram->rtr = 0x05F00000;
  1136 + sdram->tr = 0x00854009;
  1137 + /* We pre-initialize RAM banks */
  1138 + sdram->status = 0x00000000;
  1139 + sdram->cfg = 0x00800000;
  1140 + sdram_unmap_bcr(sdram);
  1141 +}
  1142 +
  1143 +void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
  1144 + target_ulong *ram_bases, target_ulong *ram_sizes)
  1145 +{
  1146 + ppc4xx_sdram_t *sdram;
  1147 +
  1148 + sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
  1149 + if (sdram != NULL) {
  1150 + sdram->irq = irq;
  1151 + sdram->nbanks = nbanks;
  1152 + memset(sdram->ram_bases, 0, 4 * sizeof(target_ulong));
  1153 + memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(target_ulong));
  1154 + memset(sdram->ram_sizes, 0, 4 * sizeof(target_ulong));
  1155 + memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(target_ulong));
  1156 + sdram_reset(sdram);
  1157 + qemu_register_reset(&sdram_reset, sdram);
  1158 + ppc_dcr_register(env, SDRAM0_CFGADDR,
  1159 + sdram, &dcr_read_sdram, &dcr_write_sdram);
  1160 + ppc_dcr_register(env, SDRAM0_CFGDATA,
  1161 + sdram, &dcr_read_sdram, &dcr_write_sdram);
  1162 + }
  1163 +}
  1164 +
  1165 +/*****************************************************************************/
  1166 +/* Peripheral controller */
  1167 +typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
  1168 +struct ppc4xx_ebc_t {
  1169 + uint32_t addr;
  1170 + uint32_t bcr[8];
  1171 + uint32_t bap[8];
  1172 + uint32_t bear;
  1173 + uint32_t besr0;
  1174 + uint32_t besr1;
  1175 + uint32_t cfg;
  1176 +};
  1177 +
  1178 +enum {
  1179 + EBC0_CFGADDR = 0x012,
  1180 + EBC0_CFGDATA = 0x013,
  1181 +};
  1182 +
  1183 +static target_ulong dcr_read_ebc (void *opaque, int dcrn)
  1184 +{
  1185 + ppc4xx_ebc_t *ebc;
  1186 + target_ulong ret;
  1187 +
  1188 + ebc = opaque;
  1189 + switch (dcrn) {
  1190 + case EBC0_CFGADDR:
  1191 + ret = ebc->addr;
  1192 + break;
  1193 + case EBC0_CFGDATA:
  1194 + switch (ebc->addr) {
  1195 + case 0x00: /* B0CR */
  1196 + ret = ebc->bcr[0];
  1197 + break;
  1198 + case 0x01: /* B1CR */
  1199 + ret = ebc->bcr[1];
  1200 + break;
  1201 + case 0x02: /* B2CR */
  1202 + ret = ebc->bcr[2];
  1203 + break;
  1204 + case 0x03: /* B3CR */
  1205 + ret = ebc->bcr[3];
  1206 + break;
  1207 + case 0x04: /* B4CR */
  1208 + ret = ebc->bcr[4];
  1209 + break;
  1210 + case 0x05: /* B5CR */
  1211 + ret = ebc->bcr[5];
  1212 + break;
  1213 + case 0x06: /* B6CR */
  1214 + ret = ebc->bcr[6];
  1215 + break;
  1216 + case 0x07: /* B7CR */
  1217 + ret = ebc->bcr[7];
  1218 + break;
  1219 + case 0x10: /* B0AP */
  1220 + ret = ebc->bap[0];
  1221 + break;
  1222 + case 0x11: /* B1AP */
  1223 + ret = ebc->bap[1];
  1224 + break;
  1225 + case 0x12: /* B2AP */
  1226 + ret = ebc->bap[2];
  1227 + break;
  1228 + case 0x13: /* B3AP */
  1229 + ret = ebc->bap[3];
  1230 + break;
  1231 + case 0x14: /* B4AP */
  1232 + ret = ebc->bap[4];
  1233 + break;
  1234 + case 0x15: /* B5AP */
  1235 + ret = ebc->bap[5];
  1236 + break;
  1237 + case 0x16: /* B6AP */
  1238 + ret = ebc->bap[6];
  1239 + break;
  1240 + case 0x17: /* B7AP */
  1241 + ret = ebc->bap[7];
  1242 + break;
  1243 + case 0x20: /* BEAR */
  1244 + ret = ebc->bear;
  1245 + break;
  1246 + case 0x21: /* BESR0 */
  1247 + ret = ebc->besr0;
  1248 + break;
  1249 + case 0x22: /* BESR1 */
  1250 + ret = ebc->besr1;
  1251 + break;
  1252 + case 0x23: /* CFG */
  1253 + ret = ebc->cfg;
  1254 + break;
  1255 + default:
  1256 + ret = 0x00000000;
  1257 + break;
  1258 + }
  1259 + default:
  1260 + ret = 0x00000000;
  1261 + break;
  1262 + }
  1263 +
  1264 + return ret;
  1265 +}
  1266 +
  1267 +static void dcr_write_ebc (void *opaque, int dcrn, target_ulong val)
  1268 +{
  1269 + ppc4xx_ebc_t *ebc;
  1270 +
  1271 + ebc = opaque;
  1272 + switch (dcrn) {
  1273 + case EBC0_CFGADDR:
  1274 + ebc->addr = val;
  1275 + break;
  1276 + case EBC0_CFGDATA:
  1277 + switch (ebc->addr) {
  1278 + case 0x00: /* B0CR */
  1279 + break;
  1280 + case 0x01: /* B1CR */
  1281 + break;
  1282 + case 0x02: /* B2CR */
  1283 + break;
  1284 + case 0x03: /* B3CR */
  1285 + break;
  1286 + case 0x04: /* B4CR */
  1287 + break;
  1288 + case 0x05: /* B5CR */
  1289 + break;
  1290 + case 0x06: /* B6CR */
  1291 + break;
  1292 + case 0x07: /* B7CR */
  1293 + break;
  1294 + case 0x10: /* B0AP */
  1295 + break;
  1296 + case 0x11: /* B1AP */
  1297 + break;
  1298 + case 0x12: /* B2AP */
  1299 + break;
  1300 + case 0x13: /* B3AP */
  1301 + break;
  1302 + case 0x14: /* B4AP */
  1303 + break;
  1304 + case 0x15: /* B5AP */
  1305 + break;
  1306 + case 0x16: /* B6AP */
  1307 + break;
  1308 + case 0x17: /* B7AP */
  1309 + break;
  1310 + case 0x20: /* BEAR */
  1311 + break;
  1312 + case 0x21: /* BESR0 */
  1313 + break;
  1314 + case 0x22: /* BESR1 */
  1315 + break;
  1316 + case 0x23: /* CFG */
  1317 + break;
  1318 + default:
  1319 + break;
  1320 + }
  1321 + break;
  1322 + default:
  1323 + break;
  1324 + }
  1325 +}
  1326 +
  1327 +static void ebc_reset (void *opaque)
  1328 +{
  1329 + ppc4xx_ebc_t *ebc;
  1330 + int i;
  1331 +
  1332 + ebc = opaque;
  1333 + ebc->addr = 0x00000000;
  1334 + ebc->bap[0] = 0x7F8FFE80;
  1335 + ebc->bcr[0] = 0xFFE28000;
  1336 + for (i = 0; i < 8; i++) {
  1337 + ebc->bap[i] = 0x00000000;
  1338 + ebc->bcr[i] = 0x00000000;
  1339 + }
  1340 + ebc->besr0 = 0x00000000;
  1341 + ebc->besr1 = 0x00000000;
  1342 + ebc->cfg = 0x07C00000;
  1343 +}
  1344 +
  1345 +void ppc405_ebc_init (CPUState *env)
  1346 +{
  1347 + ppc4xx_ebc_t *ebc;
  1348 +
  1349 + ebc = qemu_mallocz(sizeof(ppc4xx_ebc_t));
  1350 + if (ebc != NULL) {
  1351 + ebc_reset(ebc);
  1352 + qemu_register_reset(&ebc_reset, ebc);
  1353 + ppc_dcr_register(env, EBC0_CFGADDR,
  1354 + ebc, &dcr_read_ebc, &dcr_write_ebc);
  1355 + ppc_dcr_register(env, EBC0_CFGDATA,
  1356 + ebc, &dcr_read_ebc, &dcr_write_ebc);
  1357 + }
  1358 +}
  1359 +
  1360 +/*****************************************************************************/
  1361 +/* DMA controller */
  1362 +enum {
  1363 + DMA0_CR0 = 0x100,
  1364 + DMA0_CT0 = 0x101,
  1365 + DMA0_DA0 = 0x102,
  1366 + DMA0_SA0 = 0x103,
  1367 + DMA0_SG0 = 0x104,
  1368 + DMA0_CR1 = 0x108,
  1369 + DMA0_CT1 = 0x109,
  1370 + DMA0_DA1 = 0x10A,
  1371 + DMA0_SA1 = 0x10B,
  1372 + DMA0_SG1 = 0x10C,
  1373 + DMA0_CR2 = 0x110,
  1374 + DMA0_CT2 = 0x111,
  1375 + DMA0_DA2 = 0x112,
  1376 + DMA0_SA2 = 0x113,
  1377 + DMA0_SG2 = 0x114,
  1378 + DMA0_CR3 = 0x118,
  1379 + DMA0_CT3 = 0x119,
  1380 + DMA0_DA3 = 0x11A,
  1381 + DMA0_SA3 = 0x11B,
  1382 + DMA0_SG3 = 0x11C,
  1383 + DMA0_SR = 0x120,
  1384 + DMA0_SGC = 0x123,
  1385 + DMA0_SLP = 0x125,
  1386 + DMA0_POL = 0x126,
  1387 +};
  1388 +
  1389 +typedef struct ppc405_dma_t ppc405_dma_t;
  1390 +struct ppc405_dma_t {
  1391 + qemu_irq irqs[4];
  1392 + uint32_t cr[4];
  1393 + uint32_t ct[4];
  1394 + uint32_t da[4];
  1395 + uint32_t sa[4];
  1396 + uint32_t sg[4];
  1397 + uint32_t sr;
  1398 + uint32_t sgc;
  1399 + uint32_t slp;
  1400 + uint32_t pol;
  1401 +};
  1402 +
  1403 +static target_ulong dcr_read_dma (void *opaque, int dcrn)
  1404 +{
  1405 + ppc405_dma_t *dma;
  1406 +
  1407 + dma = opaque;
  1408 +
  1409 + return 0;
  1410 +}
  1411 +
  1412 +static void dcr_write_dma (void *opaque, int dcrn, target_ulong val)
  1413 +{
  1414 + ppc405_dma_t *dma;
  1415 +
  1416 + dma = opaque;
  1417 +}
  1418 +
  1419 +static void ppc405_dma_reset (void *opaque)
  1420 +{
  1421 + ppc405_dma_t *dma;
  1422 + int i;
  1423 +
  1424 + dma = opaque;
  1425 + for (i = 0; i < 4; i++) {
  1426 + dma->cr[i] = 0x00000000;
  1427 + dma->ct[i] = 0x00000000;
  1428 + dma->da[i] = 0x00000000;
  1429 + dma->sa[i] = 0x00000000;
  1430 + dma->sg[i] = 0x00000000;
  1431 + }
  1432 + dma->sr = 0x00000000;
  1433 + dma->sgc = 0x00000000;
  1434 + dma->slp = 0x7C000000;
  1435 + dma->pol = 0x00000000;
  1436 +}
  1437 +
  1438 +void ppc405_dma_init (CPUState *env, qemu_irq irqs[4])
  1439 +{
  1440 + ppc405_dma_t *dma;
  1441 +
  1442 + dma = qemu_mallocz(sizeof(ppc405_dma_t));
  1443 + if (dma != NULL) {
  1444 + memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq));
  1445 + ppc405_dma_reset(dma);
  1446 + qemu_register_reset(&ppc405_dma_reset, dma);
  1447 + ppc_dcr_register(env, DMA0_CR0,
  1448 + dma, &dcr_read_dma, &dcr_write_dma);
  1449 + ppc_dcr_register(env, DMA0_CT0,
  1450 + dma, &dcr_read_dma, &dcr_write_dma);
  1451 + ppc_dcr_register(env, DMA0_DA0,
  1452 + dma, &dcr_read_dma, &dcr_write_dma);
  1453 + ppc_dcr_register(env, DMA0_SA0,
  1454 + dma, &dcr_read_dma, &dcr_write_dma);
  1455 + ppc_dcr_register(env, DMA0_SG0,
  1456 + dma, &dcr_read_dma, &dcr_write_dma);
  1457 + ppc_dcr_register(env, DMA0_CR1,
  1458 + dma, &dcr_read_dma, &dcr_write_dma);
  1459 + ppc_dcr_register(env, DMA0_CT1,
  1460 + dma, &dcr_read_dma, &dcr_write_dma);
  1461 + ppc_dcr_register(env, DMA0_DA1,
  1462 + dma, &dcr_read_dma, &dcr_write_dma);
  1463 + ppc_dcr_register(env, DMA0_SA1,
  1464 + dma, &dcr_read_dma, &dcr_write_dma);
  1465 + ppc_dcr_register(env, DMA0_SG1,
  1466 + dma, &dcr_read_dma, &dcr_write_dma);
  1467 + ppc_dcr_register(env, DMA0_CR2,
  1468 + dma, &dcr_read_dma, &dcr_write_dma);
  1469 + ppc_dcr_register(env, DMA0_CT2,
  1470 + dma, &dcr_read_dma, &dcr_write_dma);
  1471 + ppc_dcr_register(env, DMA0_DA2,
  1472 + dma, &dcr_read_dma, &dcr_write_dma);
  1473 + ppc_dcr_register(env, DMA0_SA2,
  1474 + dma, &dcr_read_dma, &dcr_write_dma);
  1475 + ppc_dcr_register(env, DMA0_SG2,
  1476 + dma, &dcr_read_dma, &dcr_write_dma);
  1477 + ppc_dcr_register(env, DMA0_CR3,
  1478 + dma, &dcr_read_dma, &dcr_write_dma);
  1479 + ppc_dcr_register(env, DMA0_CT3,
  1480 + dma, &dcr_read_dma, &dcr_write_dma);
  1481 + ppc_dcr_register(env, DMA0_DA3,
  1482 + dma, &dcr_read_dma, &dcr_write_dma);
  1483 + ppc_dcr_register(env, DMA0_SA3,
  1484 + dma, &dcr_read_dma, &dcr_write_dma);
  1485 + ppc_dcr_register(env, DMA0_SG3,
  1486 + dma, &dcr_read_dma, &dcr_write_dma);
  1487 + ppc_dcr_register(env, DMA0_SR,
  1488 + dma, &dcr_read_dma, &dcr_write_dma);
  1489 + ppc_dcr_register(env, DMA0_SGC,
  1490 + dma, &dcr_read_dma, &dcr_write_dma);
  1491 + ppc_dcr_register(env, DMA0_SLP,
  1492 + dma, &dcr_read_dma, &dcr_write_dma);
  1493 + ppc_dcr_register(env, DMA0_POL,
  1494 + dma, &dcr_read_dma, &dcr_write_dma);
  1495 + }
  1496 +}
  1497 +
  1498 +/*****************************************************************************/
  1499 +/* GPIO */
  1500 +typedef struct ppc405_gpio_t ppc405_gpio_t;
  1501 +struct ppc405_gpio_t {
  1502 + uint32_t base;
  1503 + uint32_t or;
  1504 + uint32_t tcr;
  1505 + uint32_t osrh;
  1506 + uint32_t osrl;
  1507 + uint32_t tsrh;
  1508 + uint32_t tsrl;
  1509 + uint32_t odr;
  1510 + uint32_t ir;
  1511 + uint32_t rr1;
  1512 + uint32_t isr1h;
  1513 + uint32_t isr1l;
  1514 +};
  1515 +
  1516 +static uint32_t ppc405_gpio_readb (void *opaque, target_phys_addr_t addr)
  1517 +{
  1518 + ppc405_gpio_t *gpio;
  1519 +
  1520 + gpio = opaque;
  1521 +#ifdef DEBUG_GPIO
  1522 + printf("%s: addr " PADDRX "\n", __func__, addr);
  1523 +#endif
  1524 +
  1525 + return 0;
  1526 +}
  1527 +
  1528 +static void ppc405_gpio_writeb (void *opaque,
  1529 + target_phys_addr_t addr, uint32_t value)
  1530 +{
  1531 + ppc405_gpio_t *gpio;
  1532 +
  1533 + gpio = opaque;
  1534 +#ifdef DEBUG_GPIO
  1535 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  1536 +#endif
  1537 +}
  1538 +
  1539 +static uint32_t ppc405_gpio_readw (void *opaque, target_phys_addr_t addr)
  1540 +{
  1541 + ppc405_gpio_t *gpio;
  1542 +
  1543 + gpio = opaque;
  1544 +#ifdef DEBUG_GPIO
  1545 + printf("%s: addr " PADDRX "\n", __func__, addr);
  1546 +#endif
  1547 +
  1548 + return 0;
  1549 +}
  1550 +
  1551 +static void ppc405_gpio_writew (void *opaque,
  1552 + target_phys_addr_t addr, uint32_t value)
  1553 +{
  1554 + ppc405_gpio_t *gpio;
  1555 +
  1556 + gpio = opaque;
  1557 +#ifdef DEBUG_GPIO
  1558 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  1559 +#endif
  1560 +}
  1561 +
  1562 +static uint32_t ppc405_gpio_readl (void *opaque, target_phys_addr_t addr)
  1563 +{
  1564 + ppc405_gpio_t *gpio;
  1565 +
  1566 + gpio = opaque;
  1567 +#ifdef DEBUG_GPIO
  1568 + printf("%s: addr " PADDRX "\n", __func__, addr);
  1569 +#endif
  1570 +
  1571 + return 0;
  1572 +}
  1573 +
  1574 +static void ppc405_gpio_writel (void *opaque,
  1575 + target_phys_addr_t addr, uint32_t value)
  1576 +{
  1577 + ppc405_gpio_t *gpio;
  1578 +
  1579 + gpio = opaque;
  1580 +#ifdef DEBUG_GPIO
  1581 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  1582 +#endif
  1583 +}
  1584 +
  1585 +static CPUReadMemoryFunc *ppc405_gpio_read[] = {
  1586 + &ppc405_gpio_readb,
  1587 + &ppc405_gpio_readw,
  1588 + &ppc405_gpio_readl,
  1589 +};
  1590 +
  1591 +static CPUWriteMemoryFunc *ppc405_gpio_write[] = {
  1592 + &ppc405_gpio_writeb,
  1593 + &ppc405_gpio_writew,
  1594 + &ppc405_gpio_writel,
  1595 +};
  1596 +
  1597 +static void ppc405_gpio_reset (void *opaque)
  1598 +{
  1599 + ppc405_gpio_t *gpio;
  1600 +
  1601 + gpio = opaque;
  1602 +}
  1603 +
  1604 +void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset)
  1605 +{
  1606 + ppc405_gpio_t *gpio;
  1607 +
  1608 + gpio = qemu_mallocz(sizeof(ppc405_gpio_t));
  1609 + if (gpio != NULL) {
  1610 + gpio->base = mmio->base + offset;
  1611 + ppc405_gpio_reset(gpio);
  1612 + qemu_register_reset(&ppc405_gpio_reset, gpio);
  1613 +#ifdef DEBUG_GPIO
  1614 + printf("%s: offset=%08x\n", __func__, offset);
  1615 +#endif
  1616 + ppc4xx_mmio_register(env, mmio, offset, 0x038,
  1617 + ppc405_gpio_read, ppc405_gpio_write, gpio);
  1618 + }
  1619 +}
  1620 +
  1621 +/*****************************************************************************/
  1622 +/* Serial ports */
  1623 +static CPUReadMemoryFunc *serial_mm_read[] = {
  1624 + &serial_mm_readb,
  1625 + &serial_mm_readw,
  1626 + &serial_mm_readl,
  1627 +};
  1628 +
  1629 +static CPUWriteMemoryFunc *serial_mm_write[] = {
  1630 + &serial_mm_writeb,
  1631 + &serial_mm_writew,
  1632 + &serial_mm_writel,
  1633 +};
  1634 +
  1635 +void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio,
  1636 + uint32_t offset, qemu_irq irq,
  1637 + CharDriverState *chr)
  1638 +{
  1639 + void *serial;
  1640 +
  1641 +#ifdef DEBUG_SERIAL
  1642 + printf("%s: offset=%08x\n", __func__, offset);
  1643 +#endif
  1644 + serial = serial_mm_init(mmio->base + offset, 0, irq, chr, 0);
  1645 + ppc4xx_mmio_register(env, mmio, offset, 0x008,
  1646 + serial_mm_read, serial_mm_write, serial);
  1647 +}
  1648 +
  1649 +/*****************************************************************************/
  1650 +/* On Chip Memory */
  1651 +enum {
  1652 + OCM0_ISARC = 0x018,
  1653 + OCM0_ISACNTL = 0x019,
  1654 + OCM0_DSARC = 0x01A,
  1655 + OCM0_DSACNTL = 0x01B,
  1656 +};
  1657 +
  1658 +typedef struct ppc405_ocm_t ppc405_ocm_t;
  1659 +struct ppc405_ocm_t {
  1660 + target_ulong offset;
  1661 + uint32_t isarc;
  1662 + uint32_t isacntl;
  1663 + uint32_t dsarc;
  1664 + uint32_t dsacntl;
  1665 +};
  1666 +
  1667 +static void ocm_update_mappings (ppc405_ocm_t *ocm,
  1668 + uint32_t isarc, uint32_t isacntl,
  1669 + uint32_t dsarc, uint32_t dsacntl)
  1670 +{
  1671 +#ifdef DEBUG_OCM
  1672 + printf("OCM update ISA %08x %08x (%08x %08x) DSA %08x %08x (%08x %08x)\n",
  1673 + isarc, isacntl, dsarc, dsacntl,
  1674 + ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl);
  1675 +#endif
  1676 + if (ocm->isarc != isarc ||
  1677 + (ocm->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
  1678 + if (ocm->isacntl & 0x80000000) {
  1679 + /* Unmap previously assigned memory region */
  1680 + printf("OCM unmap ISA %08x\n", ocm->isarc);
  1681 + cpu_register_physical_memory(ocm->isarc, 0x04000000,
  1682 + IO_MEM_UNASSIGNED);
  1683 + }
  1684 + if (isacntl & 0x80000000) {
  1685 + /* Map new instruction memory region */
  1686 +#ifdef DEBUG_OCM
  1687 + printf("OCM map ISA %08x\n", isarc);
  1688 +#endif
  1689 + cpu_register_physical_memory(isarc, 0x04000000,
  1690 + ocm->offset | IO_MEM_RAM);
  1691 + }
  1692 + }
  1693 + if (ocm->dsarc != dsarc ||
  1694 + (ocm->dsacntl & 0x80000000) != (dsacntl & 0x80000000)) {
  1695 + if (ocm->dsacntl & 0x80000000) {
  1696 + /* Beware not to unmap the region we just mapped */
  1697 + if (!(isacntl & 0x80000000) || ocm->dsarc != isarc) {
  1698 + /* Unmap previously assigned memory region */
  1699 +#ifdef DEBUG_OCM
  1700 + printf("OCM unmap DSA %08x\n", ocm->dsarc);
  1701 +#endif
  1702 + cpu_register_physical_memory(ocm->dsarc, 0x04000000,
  1703 + IO_MEM_UNASSIGNED);
  1704 + }
  1705 + }
  1706 + if (dsacntl & 0x80000000) {
  1707 + /* Beware not to remap the region we just mapped */
  1708 + if (!(isacntl & 0x80000000) || dsarc != isarc) {
  1709 + /* Map new data memory region */
  1710 +#ifdef DEBUG_OCM
  1711 + printf("OCM map DSA %08x\n", dsarc);
  1712 +#endif
  1713 + cpu_register_physical_memory(dsarc, 0x04000000,
  1714 + ocm->offset | IO_MEM_RAM);
  1715 + }
  1716 + }
  1717 + }
  1718 +}
  1719 +
  1720 +static target_ulong dcr_read_ocm (void *opaque, int dcrn)
  1721 +{
  1722 + ppc405_ocm_t *ocm;
  1723 + target_ulong ret;
  1724 +
  1725 + ocm = opaque;
  1726 + switch (dcrn) {
  1727 + case OCM0_ISARC:
  1728 + ret = ocm->isarc;
  1729 + break;
  1730 + case OCM0_ISACNTL:
  1731 + ret = ocm->isacntl;
  1732 + break;
  1733 + case OCM0_DSARC:
  1734 + ret = ocm->dsarc;
  1735 + break;
  1736 + case OCM0_DSACNTL:
  1737 + ret = ocm->dsacntl;
  1738 + break;
  1739 + default:
  1740 + ret = 0;
  1741 + break;
  1742 + }
  1743 +
  1744 + return ret;
  1745 +}
  1746 +
  1747 +static void dcr_write_ocm (void *opaque, int dcrn, target_ulong val)
  1748 +{
  1749 + ppc405_ocm_t *ocm;
  1750 + uint32_t isarc, dsarc, isacntl, dsacntl;
  1751 +
  1752 + ocm = opaque;
  1753 + isarc = ocm->isarc;
  1754 + dsarc = ocm->dsarc;
  1755 + isacntl = ocm->isacntl;
  1756 + dsacntl = ocm->dsacntl;
  1757 + switch (dcrn) {
  1758 + case OCM0_ISARC:
  1759 + isarc = val & 0xFC000000;
  1760 + break;
  1761 + case OCM0_ISACNTL:
  1762 + isacntl = val & 0xC0000000;
  1763 + break;
  1764 + case OCM0_DSARC:
  1765 + isarc = val & 0xFC000000;
  1766 + break;
  1767 + case OCM0_DSACNTL:
  1768 + isacntl = val & 0xC0000000;
  1769 + break;
  1770 + }
  1771 + ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
  1772 + ocm->isarc = isarc;
  1773 + ocm->dsarc = dsarc;
  1774 + ocm->isacntl = isacntl;
  1775 + ocm->dsacntl = dsacntl;
  1776 +}
  1777 +
  1778 +static void ocm_reset (void *opaque)
  1779 +{
  1780 + ppc405_ocm_t *ocm;
  1781 + uint32_t isarc, dsarc, isacntl, dsacntl;
  1782 +
  1783 + ocm = opaque;
  1784 + isarc = 0x00000000;
  1785 + isacntl = 0x00000000;
  1786 + dsarc = 0x00000000;
  1787 + dsacntl = 0x00000000;
  1788 + ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
  1789 + ocm->isarc = isarc;
  1790 + ocm->dsarc = dsarc;
  1791 + ocm->isacntl = isacntl;
  1792 + ocm->dsacntl = dsacntl;
  1793 +}
  1794 +
  1795 +void ppc405_ocm_init (CPUState *env, unsigned long offset)
  1796 +{
  1797 + ppc405_ocm_t *ocm;
  1798 +
  1799 + ocm = qemu_mallocz(sizeof(ppc405_ocm_t));
  1800 + if (ocm != NULL) {
  1801 + ocm->offset = offset;
  1802 + ocm_reset(ocm);
  1803 + qemu_register_reset(&ocm_reset, ocm);
  1804 + ppc_dcr_register(env, OCM0_ISARC,
  1805 + ocm, &dcr_read_ocm, &dcr_write_ocm);
  1806 + ppc_dcr_register(env, OCM0_ISACNTL,
  1807 + ocm, &dcr_read_ocm, &dcr_write_ocm);
  1808 + ppc_dcr_register(env, OCM0_DSARC,
  1809 + ocm, &dcr_read_ocm, &dcr_write_ocm);
  1810 + ppc_dcr_register(env, OCM0_DSACNTL,
  1811 + ocm, &dcr_read_ocm, &dcr_write_ocm);
  1812 + }
  1813 +}
  1814 +
  1815 +/*****************************************************************************/
  1816 +/* I2C controller */
  1817 +typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
  1818 +struct ppc4xx_i2c_t {
  1819 + uint32_t base;
  1820 + uint8_t mdata;
  1821 + uint8_t lmadr;
  1822 + uint8_t hmadr;
  1823 + uint8_t cntl;
  1824 + uint8_t mdcntl;
  1825 + uint8_t sts;
  1826 + uint8_t extsts;
  1827 + uint8_t sdata;
  1828 + uint8_t lsadr;
  1829 + uint8_t hsadr;
  1830 + uint8_t clkdiv;
  1831 + uint8_t intrmsk;
  1832 + uint8_t xfrcnt;
  1833 + uint8_t xtcntlss;
  1834 + uint8_t directcntl;
  1835 +};
  1836 +
  1837 +static uint32_t ppc4xx_i2c_readb (void *opaque, target_phys_addr_t addr)
  1838 +{
  1839 + ppc4xx_i2c_t *i2c;
  1840 + uint32_t ret;
  1841 +
  1842 +#ifdef DEBUG_I2C
  1843 + printf("%s: addr " PADDRX "\n", __func__, addr);
  1844 +#endif
  1845 + i2c = opaque;
  1846 + switch (addr - i2c->base) {
  1847 + case 0x00:
  1848 + // i2c_readbyte(&i2c->mdata);
  1849 + ret = i2c->mdata;
  1850 + break;
  1851 + case 0x02:
  1852 + ret = i2c->sdata;
  1853 + break;
  1854 + case 0x04:
  1855 + ret = i2c->lmadr;
  1856 + break;
  1857 + case 0x05:
  1858 + ret = i2c->hmadr;
  1859 + break;
  1860 + case 0x06:
  1861 + ret = i2c->cntl;
  1862 + break;
  1863 + case 0x07:
  1864 + ret = i2c->mdcntl;
  1865 + break;
  1866 + case 0x08:
  1867 + ret = i2c->sts;
  1868 + break;
  1869 + case 0x09:
  1870 + ret = i2c->extsts;
  1871 + break;
  1872 + case 0x0A:
  1873 + ret = i2c->lsadr;
  1874 + break;
  1875 + case 0x0B:
  1876 + ret = i2c->hsadr;
  1877 + break;
  1878 + case 0x0C:
  1879 + ret = i2c->clkdiv;
  1880 + break;
  1881 + case 0x0D:
  1882 + ret = i2c->intrmsk;
  1883 + break;
  1884 + case 0x0E:
  1885 + ret = i2c->xfrcnt;
  1886 + break;
  1887 + case 0x0F:
  1888 + ret = i2c->xtcntlss;
  1889 + break;
  1890 + case 0x10:
  1891 + ret = i2c->directcntl;
  1892 + break;
  1893 + default:
  1894 + ret = 0x00;
  1895 + break;
  1896 + }
  1897 +#ifdef DEBUG_I2C
  1898 + printf("%s: addr " PADDRX " %02x\n", __func__, addr, ret);
  1899 +#endif
  1900 +
  1901 + return ret;
  1902 +}
  1903 +
  1904 +static void ppc4xx_i2c_writeb (void *opaque,
  1905 + target_phys_addr_t addr, uint32_t value)
  1906 +{
  1907 + ppc4xx_i2c_t *i2c;
  1908 +
  1909 +#ifdef DEBUG_I2C
  1910 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  1911 +#endif
  1912 + i2c = opaque;
  1913 + switch (addr - i2c->base) {
  1914 + case 0x00:
  1915 + i2c->mdata = value;
  1916 + // i2c_sendbyte(&i2c->mdata);
  1917 + break;
  1918 + case 0x02:
  1919 + i2c->sdata = value;
  1920 + break;
  1921 + case 0x04:
  1922 + i2c->lmadr = value;
  1923 + break;
  1924 + case 0x05:
  1925 + i2c->hmadr = value;
  1926 + break;
  1927 + case 0x06:
  1928 + i2c->cntl = value;
  1929 + break;
  1930 + case 0x07:
  1931 + i2c->mdcntl = value & 0xDF;
  1932 + break;
  1933 + case 0x08:
  1934 + i2c->sts &= ~(value & 0x0A);
  1935 + break;
  1936 + case 0x09:
  1937 + i2c->extsts &= ~(value & 0x8F);
  1938 + break;
  1939 + case 0x0A:
  1940 + i2c->lsadr = value;
  1941 + break;
  1942 + case 0x0B:
  1943 + i2c->hsadr = value;
  1944 + break;
  1945 + case 0x0C:
  1946 + i2c->clkdiv = value;
  1947 + break;
  1948 + case 0x0D:
  1949 + i2c->intrmsk = value;
  1950 + break;
  1951 + case 0x0E:
  1952 + i2c->xfrcnt = value & 0x77;
  1953 + break;
  1954 + case 0x0F:
  1955 + i2c->xtcntlss = value;
  1956 + break;
  1957 + case 0x10:
  1958 + i2c->directcntl = value & 0x7;
  1959 + break;
  1960 + }
  1961 +}
  1962 +
  1963 +static uint32_t ppc4xx_i2c_readw (void *opaque, target_phys_addr_t addr)
  1964 +{
  1965 + uint32_t ret;
  1966 +
  1967 +#ifdef DEBUG_I2C
  1968 + printf("%s: addr " PADDRX "\n", __func__, addr);
  1969 +#endif
  1970 + ret = ppc4xx_i2c_readb(opaque, addr) << 8;
  1971 + ret |= ppc4xx_i2c_readb(opaque, addr + 1);
  1972 +
  1973 + return ret;
  1974 +}
  1975 +
  1976 +static void ppc4xx_i2c_writew (void *opaque,
  1977 + target_phys_addr_t addr, uint32_t value)
  1978 +{
  1979 +#ifdef DEBUG_I2C
  1980 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  1981 +#endif
  1982 + ppc4xx_i2c_writeb(opaque, addr, value >> 8);
  1983 + ppc4xx_i2c_writeb(opaque, addr + 1, value);
  1984 +}
  1985 +
  1986 +static uint32_t ppc4xx_i2c_readl (void *opaque, target_phys_addr_t addr)
  1987 +{
  1988 + uint32_t ret;
  1989 +
  1990 +#ifdef DEBUG_I2C
  1991 + printf("%s: addr " PADDRX "\n", __func__, addr);
  1992 +#endif
  1993 + ret = ppc4xx_i2c_readb(opaque, addr) << 24;
  1994 + ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
  1995 + ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
  1996 + ret |= ppc4xx_i2c_readb(opaque, addr + 3);
  1997 +
  1998 + return ret;
  1999 +}
  2000 +
  2001 +static void ppc4xx_i2c_writel (void *opaque,
  2002 + target_phys_addr_t addr, uint32_t value)
  2003 +{
  2004 +#ifdef DEBUG_I2C
  2005 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  2006 +#endif
  2007 + ppc4xx_i2c_writeb(opaque, addr, value >> 24);
  2008 + ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
  2009 + ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
  2010 + ppc4xx_i2c_writeb(opaque, addr + 3, value);
  2011 +}
  2012 +
  2013 +static CPUReadMemoryFunc *i2c_read[] = {
  2014 + &ppc4xx_i2c_readb,
  2015 + &ppc4xx_i2c_readw,
  2016 + &ppc4xx_i2c_readl,
  2017 +};
  2018 +
  2019 +static CPUWriteMemoryFunc *i2c_write[] = {
  2020 + &ppc4xx_i2c_writeb,
  2021 + &ppc4xx_i2c_writew,
  2022 + &ppc4xx_i2c_writel,
  2023 +};
  2024 +
  2025 +static void ppc4xx_i2c_reset (void *opaque)
  2026 +{
  2027 + ppc4xx_i2c_t *i2c;
  2028 +
  2029 + i2c = opaque;
  2030 + i2c->mdata = 0x00;
  2031 + i2c->sdata = 0x00;
  2032 + i2c->cntl = 0x00;
  2033 + i2c->mdcntl = 0x00;
  2034 + i2c->sts = 0x00;
  2035 + i2c->extsts = 0x00;
  2036 + i2c->clkdiv = 0x00;
  2037 + i2c->xfrcnt = 0x00;
  2038 + i2c->directcntl = 0x0F;
  2039 +}
  2040 +
  2041 +void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset)
  2042 +{
  2043 + ppc4xx_i2c_t *i2c;
  2044 +
  2045 + i2c = qemu_mallocz(sizeof(ppc4xx_i2c_t));
  2046 + if (i2c != NULL) {
  2047 + i2c->base = mmio->base + offset;
  2048 + ppc4xx_i2c_reset(i2c);
  2049 +#ifdef DEBUG_I2C
  2050 + printf("%s: offset=%08x\n", __func__, offset);
  2051 +#endif
  2052 + ppc4xx_mmio_register(env, mmio, offset, 0x011,
  2053 + i2c_read, i2c_write, i2c);
  2054 + qemu_register_reset(ppc4xx_i2c_reset, i2c);
  2055 + }
  2056 +}
  2057 +
  2058 +/*****************************************************************************/
  2059 +/* SPR */
  2060 +void ppc40x_core_reset (CPUState *env)
  2061 +{
  2062 + target_ulong dbsr;
  2063 +
  2064 + printf("Reset PowerPC core\n");
  2065 + cpu_ppc_reset(env);
  2066 + dbsr = env->spr[SPR_40x_DBSR];
  2067 + dbsr &= ~0x00000300;
  2068 + dbsr |= 0x00000100;
  2069 + env->spr[SPR_40x_DBSR] = dbsr;
  2070 + cpu_loop_exit();
  2071 +}
  2072 +
  2073 +void ppc40x_chip_reset (CPUState *env)
  2074 +{
  2075 + target_ulong dbsr;
  2076 +
  2077 + printf("Reset PowerPC chip\n");
  2078 + cpu_ppc_reset(env);
  2079 + /* XXX: TODO reset all internal peripherals */
  2080 + dbsr = env->spr[SPR_40x_DBSR];
  2081 + dbsr &= ~0x00000300;
  2082 + dbsr |= 0x00000100;
  2083 + env->spr[SPR_40x_DBSR] = dbsr;
  2084 + cpu_loop_exit();
  2085 +}
  2086 +
  2087 +void ppc40x_system_reset (CPUState *env)
  2088 +{
  2089 + printf("Reset PowerPC system\n");
  2090 + qemu_system_reset_request();
  2091 +}
  2092 +
  2093 +void store_40x_dbcr0 (CPUState *env, uint32_t val)
  2094 +{
  2095 + switch ((val >> 28) & 0x3) {
  2096 + case 0x0:
  2097 + /* No action */
  2098 + break;
  2099 + case 0x1:
  2100 + /* Core reset */
  2101 + ppc40x_core_reset(env);
  2102 + break;
  2103 + case 0x2:
  2104 + /* Chip reset */
  2105 + ppc40x_chip_reset(env);
  2106 + break;
  2107 + case 0x3:
  2108 + /* System reset */
  2109 + ppc40x_system_reset(env);
  2110 + break;
  2111 + }
  2112 +}
  2113 +
  2114 +/*****************************************************************************/
  2115 +/* PowerPC 405CR */
  2116 +enum {
  2117 + PPC405CR_CPC0_PLLMR = 0x0B0,
  2118 + PPC405CR_CPC0_CR0 = 0x0B1,
  2119 + PPC405CR_CPC0_CR1 = 0x0B2,
  2120 + PPC405CR_CPC0_PSR = 0x0B4,
  2121 + PPC405CR_CPC0_JTAGID = 0x0B5,
  2122 + PPC405CR_CPC0_ER = 0x0B9,
  2123 + PPC405CR_CPC0_FR = 0x0BA,
  2124 + PPC405CR_CPC0_SR = 0x0BB,
  2125 +};
  2126 +
  2127 +typedef struct ppc405cr_cpc_t ppc405cr_cpc_t;
  2128 +struct ppc405cr_cpc_t {
  2129 + clk_setup_t clk_setup[7];
  2130 + uint32_t sysclk;
  2131 + uint32_t psr;
  2132 + uint32_t cr0;
  2133 + uint32_t cr1;
  2134 + uint32_t jtagid;
  2135 + uint32_t pllmr;
  2136 + uint32_t er;
  2137 + uint32_t fr;
  2138 +};
  2139 +
  2140 +static void ppc405cr_clk_setup (ppc405cr_cpc_t *cpc)
  2141 +{
  2142 + uint64_t VCO_out, PLL_out;
  2143 + uint32_t CPU_clk, TMR_clk, SDRAM_clk, PLB_clk, OPB_clk, EXT_clk, UART_clk;
  2144 + int M, D0, D1, D2;
  2145 +
  2146 + D0 = ((cpc->pllmr >> 26) & 0x3) + 1; /* CBDV */
  2147 + if (cpc->pllmr & 0x80000000) {
  2148 + D1 = (((cpc->pllmr >> 20) - 1) & 0xF) + 1; /* FBDV */
  2149 + D2 = 8 - ((cpc->pllmr >> 16) & 0x7); /* FWDVA */
  2150 + M = D0 * D1 * D2;
  2151 + VCO_out = cpc->sysclk * M;
  2152 + if (VCO_out < 400000000 || VCO_out > 800000000) {
  2153 + /* PLL cannot lock */
  2154 + cpc->pllmr &= ~0x80000000;
  2155 + goto bypass_pll;
  2156 + }
  2157 + PLL_out = VCO_out / D2;
  2158 + } else {
  2159 + /* Bypass PLL */
  2160 + bypass_pll:
  2161 + M = D0;
  2162 + PLL_out = cpc->sysclk * M;
  2163 + }
  2164 + CPU_clk = PLL_out;
  2165 + if (cpc->cr1 & 0x00800000)
  2166 + TMR_clk = cpc->sysclk; /* Should have a separate clock */
  2167 + else
  2168 + TMR_clk = CPU_clk;
  2169 + PLB_clk = CPU_clk / D0;
  2170 + SDRAM_clk = PLB_clk;
  2171 + D0 = ((cpc->pllmr >> 10) & 0x3) + 1;
  2172 + OPB_clk = PLB_clk / D0;
  2173 + D0 = ((cpc->pllmr >> 24) & 0x3) + 2;
  2174 + EXT_clk = PLB_clk / D0;
  2175 + D0 = ((cpc->cr0 >> 1) & 0x1F) + 1;
  2176 + UART_clk = CPU_clk / D0;
  2177 + /* Setup CPU clocks */
  2178 + clk_setup(&cpc->clk_setup[0], CPU_clk);
  2179 + /* Setup time-base clock */
  2180 + clk_setup(&cpc->clk_setup[1], TMR_clk);
  2181 + /* Setup PLB clock */
  2182 + clk_setup(&cpc->clk_setup[2], PLB_clk);
  2183 + /* Setup SDRAM clock */
  2184 + clk_setup(&cpc->clk_setup[3], SDRAM_clk);
  2185 + /* Setup OPB clock */
  2186 + clk_setup(&cpc->clk_setup[4], OPB_clk);
  2187 + /* Setup external clock */
  2188 + clk_setup(&cpc->clk_setup[5], EXT_clk);
  2189 + /* Setup UART clock */
  2190 + clk_setup(&cpc->clk_setup[6], UART_clk);
  2191 +}
  2192 +
  2193 +static target_ulong dcr_read_crcpc (void *opaque, int dcrn)
  2194 +{
  2195 + ppc405cr_cpc_t *cpc;
  2196 + target_ulong ret;
  2197 +
  2198 + cpc = opaque;
  2199 + switch (dcrn) {
  2200 + case PPC405CR_CPC0_PLLMR:
  2201 + ret = cpc->pllmr;
  2202 + break;
  2203 + case PPC405CR_CPC0_CR0:
  2204 + ret = cpc->cr0;
  2205 + break;
  2206 + case PPC405CR_CPC0_CR1:
  2207 + ret = cpc->cr1;
  2208 + break;
  2209 + case PPC405CR_CPC0_PSR:
  2210 + ret = cpc->psr;
  2211 + break;
  2212 + case PPC405CR_CPC0_JTAGID:
  2213 + ret = cpc->jtagid;
  2214 + break;
  2215 + case PPC405CR_CPC0_ER:
  2216 + ret = cpc->er;
  2217 + break;
  2218 + case PPC405CR_CPC0_FR:
  2219 + ret = cpc->fr;
  2220 + break;
  2221 + case PPC405CR_CPC0_SR:
  2222 + ret = ~(cpc->er | cpc->fr) & 0xFFFF0000;
  2223 + break;
  2224 + default:
  2225 + /* Avoid gcc warning */
  2226 + ret = 0;
  2227 + break;
  2228 + }
  2229 +
  2230 + return ret;
  2231 +}
  2232 +
  2233 +static void dcr_write_crcpc (void *opaque, int dcrn, target_ulong val)
  2234 +{
  2235 + ppc405cr_cpc_t *cpc;
  2236 +
  2237 + cpc = opaque;
  2238 + switch (dcrn) {
  2239 + case PPC405CR_CPC0_PLLMR:
  2240 + cpc->pllmr = val & 0xFFF77C3F;
  2241 + break;
  2242 + case PPC405CR_CPC0_CR0:
  2243 + cpc->cr0 = val & 0x0FFFFFFE;
  2244 + break;
  2245 + case PPC405CR_CPC0_CR1:
  2246 + cpc->cr1 = val & 0x00800000;
  2247 + break;
  2248 + case PPC405CR_CPC0_PSR:
  2249 + /* Read-only */
  2250 + break;
  2251 + case PPC405CR_CPC0_JTAGID:
  2252 + /* Read-only */
  2253 + break;
  2254 + case PPC405CR_CPC0_ER:
  2255 + cpc->er = val & 0xBFFC0000;
  2256 + break;
  2257 + case PPC405CR_CPC0_FR:
  2258 + cpc->fr = val & 0xBFFC0000;
  2259 + break;
  2260 + case PPC405CR_CPC0_SR:
  2261 + /* Read-only */
  2262 + break;
  2263 + }
  2264 +}
  2265 +
  2266 +static void ppc405cr_cpc_reset (void *opaque)
  2267 +{
  2268 + ppc405cr_cpc_t *cpc;
  2269 + int D;
  2270 +
  2271 + cpc = opaque;
  2272 + /* Compute PLLMR value from PSR settings */
  2273 + cpc->pllmr = 0x80000000;
  2274 + /* PFWD */
  2275 + switch ((cpc->psr >> 30) & 3) {
  2276 + case 0:
  2277 + /* Bypass */
  2278 + cpc->pllmr &= ~0x80000000;
  2279 + break;
  2280 + case 1:
  2281 + /* Divide by 3 */
  2282 + cpc->pllmr |= 5 << 16;
  2283 + break;
  2284 + case 2:
  2285 + /* Divide by 4 */
  2286 + cpc->pllmr |= 4 << 16;
  2287 + break;
  2288 + case 3:
  2289 + /* Divide by 6 */
  2290 + cpc->pllmr |= 2 << 16;
  2291 + break;
  2292 + }
  2293 + /* PFBD */
  2294 + D = (cpc->psr >> 28) & 3;
  2295 + cpc->pllmr |= (D + 1) << 20;
  2296 + /* PT */
  2297 + D = (cpc->psr >> 25) & 7;
  2298 + switch (D) {
  2299 + case 0x2:
  2300 + cpc->pllmr |= 0x13;
  2301 + break;
  2302 + case 0x4:
  2303 + cpc->pllmr |= 0x15;
  2304 + break;
  2305 + case 0x5:
  2306 + cpc->pllmr |= 0x16;
  2307 + break;
  2308 + default:
  2309 + break;
  2310 + }
  2311 + /* PDC */
  2312 + D = (cpc->psr >> 23) & 3;
  2313 + cpc->pllmr |= D << 26;
  2314 + /* ODP */
  2315 + D = (cpc->psr >> 21) & 3;
  2316 + cpc->pllmr |= D << 10;
  2317 + /* EBPD */
  2318 + D = (cpc->psr >> 17) & 3;
  2319 + cpc->pllmr |= D << 24;
  2320 + cpc->cr0 = 0x0000003C;
  2321 + cpc->cr1 = 0x2B0D8800;
  2322 + cpc->er = 0x00000000;
  2323 + cpc->fr = 0x00000000;
  2324 + ppc405cr_clk_setup(cpc);
  2325 +}
  2326 +
  2327 +static void ppc405cr_clk_init (ppc405cr_cpc_t *cpc)
  2328 +{
  2329 + int D;
  2330 +
  2331 + /* XXX: this should be read from IO pins */
  2332 + cpc->psr = 0x00000000; /* 8 bits ROM */
  2333 + /* PFWD */
  2334 + D = 0x2; /* Divide by 4 */
  2335 + cpc->psr |= D << 30;
  2336 + /* PFBD */
  2337 + D = 0x1; /* Divide by 2 */
  2338 + cpc->psr |= D << 28;
  2339 + /* PDC */
  2340 + D = 0x1; /* Divide by 2 */
  2341 + cpc->psr |= D << 23;
  2342 + /* PT */
  2343 + D = 0x5; /* M = 16 */
  2344 + cpc->psr |= D << 25;
  2345 + /* ODP */
  2346 + D = 0x1; /* Divide by 2 */
  2347 + cpc->psr |= D << 21;
  2348 + /* EBDP */
  2349 + D = 0x2; /* Divide by 4 */
  2350 + cpc->psr |= D << 17;
  2351 +}
  2352 +
  2353 +static void ppc405cr_cpc_init (CPUState *env, clk_setup_t clk_setup[7],
  2354 + uint32_t sysclk)
  2355 +{
  2356 + ppc405cr_cpc_t *cpc;
  2357 +
  2358 + cpc = qemu_mallocz(sizeof(ppc405cr_cpc_t));
  2359 + if (cpc != NULL) {
  2360 + memcpy(cpc->clk_setup, clk_setup, 7 * sizeof(clk_setup_t));
  2361 + cpc->sysclk = sysclk;
  2362 + cpc->jtagid = 0x42051049;
  2363 + ppc_dcr_register(env, PPC405CR_CPC0_PSR, cpc,
  2364 + &dcr_read_crcpc, &dcr_write_crcpc);
  2365 + ppc_dcr_register(env, PPC405CR_CPC0_CR0, cpc,
  2366 + &dcr_read_crcpc, &dcr_write_crcpc);
  2367 + ppc_dcr_register(env, PPC405CR_CPC0_CR1, cpc,
  2368 + &dcr_read_crcpc, &dcr_write_crcpc);
  2369 + ppc_dcr_register(env, PPC405CR_CPC0_JTAGID, cpc,
  2370 + &dcr_read_crcpc, &dcr_write_crcpc);
  2371 + ppc_dcr_register(env, PPC405CR_CPC0_PLLMR, cpc,
  2372 + &dcr_read_crcpc, &dcr_write_crcpc);
  2373 + ppc_dcr_register(env, PPC405CR_CPC0_ER, cpc,
  2374 + &dcr_read_crcpc, &dcr_write_crcpc);
  2375 + ppc_dcr_register(env, PPC405CR_CPC0_FR, cpc,
  2376 + &dcr_read_crcpc, &dcr_write_crcpc);
  2377 + ppc_dcr_register(env, PPC405CR_CPC0_SR, cpc,
  2378 + &dcr_read_crcpc, &dcr_write_crcpc);
  2379 + ppc405cr_clk_init(cpc);
  2380 + qemu_register_reset(ppc405cr_cpc_reset, cpc);
  2381 + ppc405cr_cpc_reset(cpc);
  2382 + }
  2383 +}
  2384 +
  2385 +CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4],
  2386 + uint32_t sysclk, qemu_irq **picp,
  2387 + ram_addr_t *offsetp)
  2388 +{
  2389 + clk_setup_t clk_setup[7];
  2390 + qemu_irq dma_irqs[4];
  2391 + CPUState *env;
  2392 + ppc4xx_mmio_t *mmio;
  2393 + qemu_irq *pic, *irqs;
  2394 + ram_addr_t offset;
  2395 + int i;
  2396 +
  2397 + memset(clk_setup, 0, sizeof(clk_setup));
  2398 + env = ppc405_init("405cr", &clk_setup[0], &clk_setup[1], sysclk);
  2399 + /* Memory mapped devices registers */
  2400 + mmio = ppc4xx_mmio_init(env, 0xEF600000);
  2401 + /* PLB arbitrer */
  2402 + ppc4xx_plb_init(env);
  2403 + /* PLB to OPB bridge */
  2404 + ppc4xx_pob_init(env);
  2405 + /* OBP arbitrer */
  2406 + ppc4xx_opba_init(env, mmio, 0x600);
  2407 + /* Universal interrupt controller */
  2408 + irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
  2409 + irqs[PPCUIC_OUTPUT_INT] =
  2410 + ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_INT];
  2411 + irqs[PPCUIC_OUTPUT_CINT] =
  2412 + ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_CINT];
  2413 + pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
  2414 + *picp = pic;
  2415 + /* SDRAM controller */
  2416 + ppc405_sdram_init(env, pic[17], 1, ram_bases, ram_sizes);
  2417 + offset = 0;
  2418 + for (i = 0; i < 4; i++)
  2419 + offset += ram_sizes[i];
  2420 + /* External bus controller */
  2421 + ppc405_ebc_init(env);
  2422 + /* DMA controller */
  2423 + dma_irqs[0] = pic[5];
  2424 + dma_irqs[1] = pic[6];
  2425 + dma_irqs[2] = pic[7];
  2426 + dma_irqs[3] = pic[8];
  2427 + ppc405_dma_init(env, dma_irqs);
  2428 + /* Serial ports */
  2429 + if (serial_hds[0] != NULL) {
  2430 + ppc405_serial_init(env, mmio, 0x400, pic[0], serial_hds[0]);
  2431 + }
  2432 + if (serial_hds[1] != NULL) {
  2433 + ppc405_serial_init(env, mmio, 0x300, pic[1], serial_hds[1]);
  2434 + }
  2435 + /* IIC controller */
  2436 + ppc405_i2c_init(env, mmio, 0x500);
  2437 + /* GPIO */
  2438 + ppc405_gpio_init(env, mmio, 0x700);
  2439 + /* CPU control */
  2440 + ppc405cr_cpc_init(env, clk_setup, sysclk);
  2441 + *offsetp = offset;
  2442 +
  2443 + return env;
  2444 +}
  2445 +
  2446 +/*****************************************************************************/
  2447 +/* PowerPC 405EP */
  2448 +/* CPU control */
  2449 +enum {
  2450 + PPC405EP_CPC0_PLLMR0 = 0x0F0,
  2451 + PPC405EP_CPC0_BOOT = 0x0F1,
  2452 + PPC405EP_CPC0_EPCTL = 0x0F3,
  2453 + PPC405EP_CPC0_PLLMR1 = 0x0F4,
  2454 + PPC405EP_CPC0_UCR = 0x0F5,
  2455 + PPC405EP_CPC0_SRR = 0x0F6,
  2456 + PPC405EP_CPC0_JTAGID = 0x0F7,
  2457 + PPC405EP_CPC0_PCI = 0x0F9,
  2458 +};
  2459 +
  2460 +typedef struct ppc405ep_cpc_t ppc405ep_cpc_t;
  2461 +struct ppc405ep_cpc_t {
  2462 + uint32_t sysclk;
  2463 + clk_setup_t clk_setup[8];
  2464 + uint32_t boot;
  2465 + uint32_t epctl;
  2466 + uint32_t pllmr[2];
  2467 + uint32_t ucr;
  2468 + uint32_t srr;
  2469 + uint32_t jtagid;
  2470 + uint32_t pci;
  2471 +};
  2472 +
  2473 +static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc)
  2474 +{
  2475 + uint32_t CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk;
  2476 + uint32_t UART0_clk, UART1_clk;
  2477 + uint64_t VCO_out, PLL_out;
  2478 + int M, D;
  2479 +
  2480 + VCO_out = 0;
  2481 + if ((cpc->pllmr[1] & 0x80000000) && !(cpc->pllmr[1] & 0x40000000)) {
  2482 + M = (((cpc->pllmr[1] >> 20) - 1) & 0xF) + 1; /* FBMUL */
  2483 + // printf("FBMUL %01x %d\n", (cpc->pllmr[1] >> 20) & 0xF, M);
  2484 + D = 8 - ((cpc->pllmr[1] >> 16) & 0x7); /* FWDA */
  2485 + // printf("FWDA %01x %d\n", (cpc->pllmr[1] >> 16) & 0x7, D);
  2486 + VCO_out = cpc->sysclk * M * D;
  2487 + if (VCO_out < 500000000UL || VCO_out > 1000000000UL) {
  2488 + /* Error - unlock the PLL */
  2489 + printf("VCO out of range %" PRIu64 "\n", VCO_out);
  2490 +#if 0
  2491 + cpc->pllmr[1] &= ~0x80000000;
  2492 + goto pll_bypass;
  2493 +#endif
  2494 + }
  2495 + PLL_out = VCO_out / D;
  2496 + } else {
  2497 +#if 0
  2498 + pll_bypass:
  2499 +#endif
  2500 + PLL_out = cpc->sysclk;
  2501 + }
  2502 + /* Now, compute all other clocks */
  2503 + D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */
  2504 +#ifdef DEBUG_CLOCKS
  2505 + // printf("CCDV %01x %d\n", (cpc->pllmr[0] >> 20) & 0x3, D);
  2506 +#endif
  2507 + CPU_clk = PLL_out / D;
  2508 + D = ((cpc->pllmr[0] >> 16) & 0x3) + 1; /* CBDV */
  2509 +#ifdef DEBUG_CLOCKS
  2510 + // printf("CBDV %01x %d\n", (cpc->pllmr[0] >> 16) & 0x3, D);
  2511 +#endif
  2512 + PLB_clk = CPU_clk / D;
  2513 + D = ((cpc->pllmr[0] >> 12) & 0x3) + 1; /* OPDV */
  2514 +#ifdef DEBUG_CLOCKS
  2515 + // printf("OPDV %01x %d\n", (cpc->pllmr[0] >> 12) & 0x3, D);
  2516 +#endif
  2517 + OPB_clk = PLB_clk / D;
  2518 + D = ((cpc->pllmr[0] >> 8) & 0x3) + 2; /* EPDV */
  2519 +#ifdef DEBUG_CLOCKS
  2520 + // printf("EPDV %01x %d\n", (cpc->pllmr[0] >> 8) & 0x3, D);
  2521 +#endif
  2522 + EBC_clk = PLB_clk / D;
  2523 + D = ((cpc->pllmr[0] >> 4) & 0x3) + 1; /* MPDV */
  2524 +#ifdef DEBUG_CLOCKS
  2525 + // printf("MPDV %01x %d\n", (cpc->pllmr[0] >> 4) & 0x3, D);
  2526 +#endif
  2527 + MAL_clk = PLB_clk / D;
  2528 + D = (cpc->pllmr[0] & 0x3) + 1; /* PPDV */
  2529 +#ifdef DEBUG_CLOCKS
  2530 + // printf("PPDV %01x %d\n", cpc->pllmr[0] & 0x3, D);
  2531 +#endif
  2532 + PCI_clk = PLB_clk / D;
  2533 + D = ((cpc->ucr - 1) & 0x7F) + 1; /* U0DIV */
  2534 +#ifdef DEBUG_CLOCKS
  2535 + // printf("U0DIV %01x %d\n", cpc->ucr & 0x7F, D);
  2536 +#endif
  2537 + UART0_clk = PLL_out / D;
  2538 + D = (((cpc->ucr >> 8) - 1) & 0x7F) + 1; /* U1DIV */
  2539 +#ifdef DEBUG_CLOCKS
  2540 + // printf("U1DIV %01x %d\n", (cpc->ucr >> 8) & 0x7F, D);
  2541 +#endif
  2542 + UART1_clk = PLL_out / D;
  2543 +#ifdef DEBUG_CLOCKS
  2544 + printf("Setup PPC405EP clocks - sysclk %d VCO %" PRIu64
  2545 + " PLL out %" PRIu64 " Hz\n", cpc->sysclk, VCO_out, PLL_out);
  2546 + printf("CPU %d PLB %d OPB %d EBC %d MAL %d PCI %d UART0 %d UART1 %d\n",
  2547 + CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk,
  2548 + UART0_clk, UART1_clk);
  2549 +#endif
  2550 + /* Setup CPU clocks */
  2551 + clk_setup(&cpc->clk_setup[0], CPU_clk);
  2552 + /* Setup PLB clock */
  2553 + clk_setup(&cpc->clk_setup[1], PLB_clk);
  2554 + /* Setup OPB clock */
  2555 + clk_setup(&cpc->clk_setup[2], OPB_clk);
  2556 + /* Setup external clock */
  2557 + clk_setup(&cpc->clk_setup[3], EBC_clk);
  2558 + /* Setup MAL clock */
  2559 + clk_setup(&cpc->clk_setup[4], MAL_clk);
  2560 + /* Setup PCI clock */
  2561 + clk_setup(&cpc->clk_setup[5], PCI_clk);
  2562 + /* Setup UART0 clock */
  2563 + clk_setup(&cpc->clk_setup[6], UART0_clk);
  2564 + /* Setup UART1 clock */
  2565 + clk_setup(&cpc->clk_setup[7], UART0_clk);
  2566 +}
  2567 +
  2568 +static target_ulong dcr_read_epcpc (void *opaque, int dcrn)
  2569 +{
  2570 + ppc405ep_cpc_t *cpc;
  2571 + target_ulong ret;
  2572 +
  2573 + cpc = opaque;
  2574 + switch (dcrn) {
  2575 + case PPC405EP_CPC0_BOOT:
  2576 + ret = cpc->boot;
  2577 + break;
  2578 + case PPC405EP_CPC0_EPCTL:
  2579 + ret = cpc->epctl;
  2580 + break;
  2581 + case PPC405EP_CPC0_PLLMR0:
  2582 + ret = cpc->pllmr[0];
  2583 + break;
  2584 + case PPC405EP_CPC0_PLLMR1:
  2585 + ret = cpc->pllmr[1];
  2586 + break;
  2587 + case PPC405EP_CPC0_UCR:
  2588 + ret = cpc->ucr;
  2589 + break;
  2590 + case PPC405EP_CPC0_SRR:
  2591 + ret = cpc->srr;
  2592 + break;
  2593 + case PPC405EP_CPC0_JTAGID:
  2594 + ret = cpc->jtagid;
  2595 + break;
  2596 + case PPC405EP_CPC0_PCI:
  2597 + ret = cpc->pci;
  2598 + break;
  2599 + default:
  2600 + /* Avoid gcc warning */
  2601 + ret = 0;
  2602 + break;
  2603 + }
  2604 +
  2605 + return ret;
  2606 +}
  2607 +
  2608 +static void dcr_write_epcpc (void *opaque, int dcrn, target_ulong val)
  2609 +{
  2610 + ppc405ep_cpc_t *cpc;
  2611 +
  2612 + cpc = opaque;
  2613 + switch (dcrn) {
  2614 + case PPC405EP_CPC0_BOOT:
  2615 + /* Read-only register */
  2616 + break;
  2617 + case PPC405EP_CPC0_EPCTL:
  2618 + /* Don't care for now */
  2619 + cpc->epctl = val & 0xC00000F3;
  2620 + break;
  2621 + case PPC405EP_CPC0_PLLMR0:
  2622 + cpc->pllmr[0] = val & 0x00633333;
  2623 + ppc405ep_compute_clocks(cpc);
  2624 + break;
  2625 + case PPC405EP_CPC0_PLLMR1:
  2626 + cpc->pllmr[1] = val & 0xC0F73FFF;
  2627 + ppc405ep_compute_clocks(cpc);
  2628 + break;
  2629 + case PPC405EP_CPC0_UCR:
  2630 + /* UART control - don't care for now */
  2631 + cpc->ucr = val & 0x003F7F7F;
  2632 + break;
  2633 + case PPC405EP_CPC0_SRR:
  2634 + cpc->srr = val;
  2635 + break;
  2636 + case PPC405EP_CPC0_JTAGID:
  2637 + /* Read-only */
  2638 + break;
  2639 + case PPC405EP_CPC0_PCI:
  2640 + cpc->pci = val;
  2641 + break;
  2642 + }
  2643 +}
  2644 +
  2645 +static void ppc405ep_cpc_reset (void *opaque)
  2646 +{
  2647 + ppc405ep_cpc_t *cpc = opaque;
  2648 +
  2649 + cpc->boot = 0x00000010; /* Boot from PCI - IIC EEPROM disabled */
  2650 + cpc->epctl = 0x00000000;
  2651 + cpc->pllmr[0] = 0x00011010;
  2652 + cpc->pllmr[1] = 0x40000000;
  2653 + cpc->ucr = 0x00000000;
  2654 + cpc->srr = 0x00040000;
  2655 + cpc->pci = 0x00000000;
  2656 + ppc405ep_compute_clocks(cpc);
  2657 +}
  2658 +
  2659 +/* XXX: sysclk should be between 25 and 100 MHz */
  2660 +static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8],
  2661 + uint32_t sysclk)
  2662 +{
  2663 + ppc405ep_cpc_t *cpc;
  2664 +
  2665 + cpc = qemu_mallocz(sizeof(ppc405ep_cpc_t));
  2666 + if (cpc != NULL) {
  2667 + memcpy(cpc->clk_setup, clk_setup, 7 * sizeof(clk_setup_t));
  2668 + cpc->jtagid = 0x20267049;
  2669 + cpc->sysclk = sysclk;
  2670 + ppc405ep_cpc_reset(cpc);
  2671 + qemu_register_reset(&ppc405ep_cpc_reset, cpc);
  2672 + ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc,
  2673 + &dcr_read_epcpc, &dcr_write_epcpc);
  2674 + ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc,
  2675 + &dcr_read_epcpc, &dcr_write_epcpc);
  2676 + ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc,
  2677 + &dcr_read_epcpc, &dcr_write_epcpc);
  2678 + ppc_dcr_register(env, PPC405EP_CPC0_PLLMR1, cpc,
  2679 + &dcr_read_epcpc, &dcr_write_epcpc);
  2680 + ppc_dcr_register(env, PPC405EP_CPC0_UCR, cpc,
  2681 + &dcr_read_epcpc, &dcr_write_epcpc);
  2682 + ppc_dcr_register(env, PPC405EP_CPC0_SRR, cpc,
  2683 + &dcr_read_epcpc, &dcr_write_epcpc);
  2684 + ppc_dcr_register(env, PPC405EP_CPC0_JTAGID, cpc,
  2685 + &dcr_read_epcpc, &dcr_write_epcpc);
  2686 + ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc,
  2687 + &dcr_read_epcpc, &dcr_write_epcpc);
  2688 + }
  2689 +}
  2690 +
  2691 +CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2],
  2692 + uint32_t sysclk, qemu_irq **picp,
  2693 + ram_addr_t *offsetp)
  2694 +{
  2695 + clk_setup_t clk_setup[8];
  2696 + qemu_irq dma_irqs[4];
  2697 + CPUState *env;
  2698 + ppc4xx_mmio_t *mmio;
  2699 + qemu_irq *pic, *irqs;
  2700 + ram_addr_t offset;
  2701 + int i;
  2702 +
  2703 + memset(clk_setup, 0, sizeof(clk_setup));
  2704 + /* init CPUs */
  2705 + env = ppc405_init("405ep", &clk_setup[0], &clk_setup[1], sysclk);
  2706 + /* Internal devices init */
  2707 + /* Memory mapped devices registers */
  2708 + mmio = ppc4xx_mmio_init(env, 0xEF600000);
  2709 + /* PLB arbitrer */
  2710 + ppc4xx_plb_init(env);
  2711 + /* PLB to OPB bridge */
  2712 + ppc4xx_pob_init(env);
  2713 + /* OBP arbitrer */
  2714 + ppc4xx_opba_init(env, mmio, 0x600);
  2715 + /* Universal interrupt controller */
  2716 + irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
  2717 + irqs[PPCUIC_OUTPUT_INT] =
  2718 + ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_INT];
  2719 + irqs[PPCUIC_OUTPUT_CINT] =
  2720 + ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_CINT];
  2721 + pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
  2722 + *picp = pic;
  2723 + /* SDRAM controller */
  2724 + ppc405_sdram_init(env, pic[17], 2, ram_bases, ram_sizes);
  2725 + offset = 0;
  2726 + for (i = 0; i < 2; i++)
  2727 + offset += ram_sizes[i];
  2728 + /* External bus controller */
  2729 + ppc405_ebc_init(env);
  2730 + /* DMA controller */
  2731 + dma_irqs[0] = pic[5];
  2732 + dma_irqs[1] = pic[6];
  2733 + dma_irqs[2] = pic[7];
  2734 + dma_irqs[3] = pic[8];
  2735 + ppc405_dma_init(env, dma_irqs);
  2736 + /* IIC controller */
  2737 + ppc405_i2c_init(env, mmio, 0x500);
  2738 + /* GPIO */
  2739 + ppc405_gpio_init(env, mmio, 0x700);
  2740 + /* Serial ports */
  2741 + if (serial_hds[0] != NULL) {
  2742 + ppc405_serial_init(env, mmio, 0x300, pic[0], serial_hds[0]);
  2743 + }
  2744 + if (serial_hds[1] != NULL) {
  2745 + ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]);
  2746 + }
  2747 + /* OCM */
  2748 + ppc405_ocm_init(env, ram_sizes[0] + ram_sizes[1]);
  2749 + offset += 4096;
  2750 + /* PCI */
  2751 + /* CPU control */
  2752 + ppc405ep_cpc_init(env, clk_setup, sysclk);
  2753 + *offsetp = offset;
  2754 +
  2755 + return env;
  2756 +}
... ...
target-ppc/cpu.h
... ... @@ -880,6 +880,7 @@ void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value);
880 880 void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value);
881 881 target_ulong load_40x_pit (CPUPPCState *env);
882 882 void store_40x_pit (CPUPPCState *env, target_ulong val);
  883 +void store_40x_dbcr0 (CPUPPCState *env, uint32_t val);
883 884 void store_booke_tcr (CPUPPCState *env, target_ulong val);
884 885 void store_booke_tsr (CPUPPCState *env, target_ulong val);
885 886 void ppc_tlb_invalidate_all (CPUPPCState *env);
... ...
target-ppc/exec.h
... ... @@ -109,6 +109,7 @@ void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
109 109 int is_code);
110 110 void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
111 111 target_ulong pte0, target_ulong pte1);
  112 +void ppc4xx_tlb_invalidate_all (CPUState *env);
112 113  
113 114 static inline void env_to_regs(void)
114 115 {
... ...
target-ppc/op.c
... ... @@ -2454,6 +2454,11 @@ void OPPROTO op_store_40x_pit (void)
2454 2454 RETURN();
2455 2455 }
2456 2456  
  2457 +void OPPROTO op_store_40x_dbcr0 (void)
  2458 +{
  2459 + store_40x_dbcr0(env, T0);
  2460 +}
  2461 +
2457 2462 void OPPROTO op_store_booke_tcr (void)
2458 2463 {
2459 2464 store_booke_tcr(env, T0);
... ...
target-ppc/translate_init.c
... ... @@ -344,6 +344,15 @@ static void spr_write_40x_pit (void *opaque, int sprn)
344 344 gen_op_store_40x_pit();
345 345 }
346 346  
  347 +static void spr_write_40x_dbcr0 (void *opaque, int sprn)
  348 +{
  349 + DisasContext *ctx = opaque;
  350 +
  351 + gen_op_store_40x_dbcr0();
  352 + /* We must stop translation as we may have rebooted */
  353 + RET_STOP(ctx);
  354 +}
  355 +
347 356 static void spr_write_booke_tcr (void *opaque, int sprn)
348 357 {
349 358 gen_op_store_booke_tcr();
... ... @@ -1175,7 +1184,7 @@ static void gen_spr_BookE (CPUPPCState *env)
1175 1184 /* XXX : not implemented */
1176 1185 spr_register(env, SPR_BOOKE_DBSR, "DBSR",
1177 1186 SPR_NOACCESS, SPR_NOACCESS,
1178   - &spr_read_generic, &spr_write_generic,
  1187 + &spr_read_generic, &spr_write_clear,
1179 1188 0x00000000);
1180 1189 spr_register(env, SPR_BOOKE_DEAR, "DEAR",
1181 1190 SPR_NOACCESS, SPR_NOACCESS,
... ... @@ -1651,13 +1660,13 @@ static void gen_spr_40x (CPUPPCState *env)
1651 1660 /* XXX : not implemented */
1652 1661 spr_register(env, SPR_40x_DBCR0, "DBCR0",
1653 1662 SPR_NOACCESS, SPR_NOACCESS,
1654   - &spr_read_generic, &spr_write_generic,
  1663 + &spr_read_generic, &spr_write_40x_dbcr0,
1655 1664 0x00000000);
1656 1665 /* XXX : not implemented */
1657 1666 spr_register(env, SPR_40x_DBSR, "DBSR",
1658 1667 SPR_NOACCESS, SPR_NOACCESS,
1659   - &spr_read_generic, &spr_write_generic,
1660   - /* Last reset was system reset (system boot */
  1668 + &spr_read_generic, &spr_write_clear,
  1669 + /* Last reset was system reset */
1661 1670 0x00000300);
1662 1671 /* XXX : not implemented */
1663 1672 spr_register(env, SPR_40x_IAC1, "IAC1",
... ... @@ -1751,17 +1760,6 @@ static void gen_spr_405 (CPUPPCState *env)
1751 1760 &spr_read_ureg, SPR_NOACCESS,
1752 1761 &spr_read_ureg, SPR_NOACCESS,
1753 1762 0x00000000);
1754   - /* Debug */
1755   - /* XXX : not implemented */
1756   - spr_register(env, SPR_40x_DAC2, "DAC2",
1757   - SPR_NOACCESS, SPR_NOACCESS,
1758   - &spr_read_generic, &spr_write_generic,
1759   - 0x00000000);
1760   - /* XXX : not implemented */
1761   - spr_register(env, SPR_40x_IAC2, "IAC2",
1762   - SPR_NOACCESS, SPR_NOACCESS,
1763   - &spr_read_generic, &spr_write_generic,
1764   - 0x00000000);
1765 1763 }
1766 1764  
1767 1765 /* SPR shared between PowerPC 401 & 403 implementations */
... ...
... ... @@ -1151,7 +1151,19 @@ extern QEMUMachine shix_machine;
1151 1151  
1152 1152 #ifdef TARGET_PPC
1153 1153 /* PowerPC hardware exceptions management helpers */
1154   -ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq);
  1154 +typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
  1155 +typedef struct clk_setup_t clk_setup_t;
  1156 +struct clk_setup_t {
  1157 + clk_setup_cb cb;
  1158 + void *opaque;
  1159 +};
  1160 +static inline void clk_setup (clk_setup_t *clk, uint32_t freq)
  1161 +{
  1162 + if (clk->cb != NULL)
  1163 + (*clk->cb)(clk->opaque, freq);
  1164 +}
  1165 +
  1166 +clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq);
1155 1167 /* Embedded PowerPC DCR management */
1156 1168 typedef target_ulong (*dcr_read_cb)(void *opaque, int dcrn);
1157 1169 typedef void (*dcr_write_cb)(void *opaque, int dcrn, target_ulong val);
... ... @@ -1159,6 +1171,59 @@ int ppc_dcr_init (CPUState *env, int (*dcr_read_error)(int dcrn),
1159 1171 int (*dcr_write_error)(int dcrn));
1160 1172 int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1161 1173 dcr_read_cb drc_read, dcr_write_cb dcr_write);
  1174 +clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq);
  1175 +/* PowerPC 405 core */
  1176 +CPUPPCState *ppc405_init (const unsigned char *cpu_model,
  1177 + clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
  1178 + uint32_t sysclk);
  1179 +void ppc40x_core_reset (CPUState *env);
  1180 +void ppc40x_chip_reset (CPUState *env);
  1181 +void ppc40x_system_reset (CPUState *env);
  1182 +/* */
  1183 +typedef struct ppc4xx_mmio_t ppc4xx_mmio_t;
  1184 +int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
  1185 + uint32_t offset, uint32_t len,
  1186 + CPUReadMemoryFunc **mem_read,
  1187 + CPUWriteMemoryFunc **mem_write, void *opaque);
  1188 +ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, uint32_t base);
  1189 +/* PowerPC 4xx peripheral local bus arbitrer */
  1190 +void ppc4xx_plb_init (CPUState *env);
  1191 +/* PLB to OPB bridge */
  1192 +void ppc4xx_pob_init (CPUState *env);
  1193 +/* OPB arbitrer */
  1194 +void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset);
  1195 +/* PowerPC 4xx universal interrupt controller */
  1196 +enum {
  1197 + PPCUIC_OUTPUT_INT = 0,
  1198 + PPCUIC_OUTPUT_CINT = 1,
  1199 + PPCUIC_OUTPUT_NB,
  1200 +};
  1201 +qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
  1202 + uint32_t dcr_base, int has_ssr, int has_vr);
  1203 +/* SDRAM controller */
  1204 +void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
  1205 + target_ulong *ram_bases, target_ulong *ram_sizes);
  1206 +/* Peripheral controller */
  1207 +void ppc405_ebc_init (CPUState *env);
  1208 +/* DMA controller */
  1209 +void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]);
  1210 +/* GPIO */
  1211 +void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset);
  1212 +/* Serial ports */
  1213 +void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio,
  1214 + uint32_t offset, qemu_irq irq,
  1215 + CharDriverState *chr);
  1216 +/* On Chip Memory */
  1217 +void ppc405_ocm_init (CPUState *env, unsigned long offset);
  1218 +/* I2C controller */
  1219 +void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset);
  1220 +/* PowerPC 405 microcontrollers */
  1221 +CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4],
  1222 + uint32_t sysclk, qemu_irq **picp,
  1223 + ram_addr_t *offsetp);
  1224 +CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2],
  1225 + uint32_t sysclk, qemu_irq **picp,
  1226 + ram_addr_t *offsetp);
1162 1227 #endif
1163 1228 void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val);
1164 1229  
... ...