X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=hw%2Fppc405_uc.c;h=8dc33c7ec3f9947e0e222aaa0e3fcf7a98da30e3;hb=8217606e6edb49591b4a6fd5a0d1229cebe470a9;hp=f5c1c31bd24d407faaef5957434abfe0886d3b83;hpb=04f20795ac815cf3ad5d1fdc99462f60eb871f25;p=qemu diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index f5c1c31..8dc33c7 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -1,8 +1,8 @@ /* * QEMU PowerPC 405 embedded processors emulation - * + * * Copyright (c) 2007 Jocelyn Mayer - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -21,91 +21,68 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "vl.h" +#include "hw.h" +#include "ppc.h" #include "ppc405.h" +#include "pc.h" +#include "qemu-timer.h" +#include "sysemu.h" +#include "qemu-log.h" -extern int loglevel; -extern FILE *logfile; - -#define DEBUG_MMIO #define DEBUG_OPBA #define DEBUG_SDRAM #define DEBUG_GPIO #define DEBUG_SERIAL #define DEBUG_OCM -#define DEBUG_I2C -#define DEBUG_UIC +//#define DEBUG_I2C +#define DEBUG_GPT +#define DEBUG_MAL #define DEBUG_CLOCKS -#define DEBUG_UNASSIGNED - -/*****************************************************************************/ -/* Generic PowerPC 405 processor instanciation */ -CPUState *ppc405_init (const unsigned char *cpu_model, - clk_setup_t *cpu_clk, clk_setup_t *tb_clk, - uint32_t sysclk) -{ - CPUState *env; - ppc_def_t *def; - - /* init CPUs */ - env = cpu_init(); - qemu_register_reset(&cpu_ppc_reset, env); - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); - ppc_find_by_name(cpu_model, &def); - if (def == NULL) { - cpu_abort(env, "Unable to find PowerPC %s CPU definition\n", - cpu_model); - } - cpu_ppc_register(env, def); - cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */ - cpu_clk->opaque = env; - /* Set time-base frequency to sysclk */ - tb_clk->cb = ppc_emb_timers_init(env, sysclk); - tb_clk->opaque = env; - ppc_dcr_init(env, NULL, NULL); - - return env; -} +//#define DEBUG_CLOCKS_LL -ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd) +ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd, + uint32_t flags) { ram_addr_t bdloc; int i, n; /* We put the bd structure at the top of memory */ - bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t); - stl_raw(phys_ram_base + bdloc + 0x00, bd->bi_memstart); - stl_raw(phys_ram_base + bdloc + 0x04, bd->bi_memsize); - stl_raw(phys_ram_base + bdloc + 0x08, bd->bi_flashstart); - stl_raw(phys_ram_base + bdloc + 0x0C, bd->bi_flashsize); - stl_raw(phys_ram_base + bdloc + 0x10, bd->bi_flashoffset); - stl_raw(phys_ram_base + bdloc + 0x14, bd->bi_sramstart); - stl_raw(phys_ram_base + bdloc + 0x18, bd->bi_sramsize); - stl_raw(phys_ram_base + bdloc + 0x1C, bd->bi_bootflags); - stl_raw(phys_ram_base + bdloc + 0x20, bd->bi_ipaddr); + if (bd->bi_memsize >= 0x01000000UL) + bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t); + else + bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t); + stl_phys(bdloc + 0x00, bd->bi_memstart); + stl_phys(bdloc + 0x04, bd->bi_memsize); + stl_phys(bdloc + 0x08, bd->bi_flashstart); + stl_phys(bdloc + 0x0C, bd->bi_flashsize); + stl_phys(bdloc + 0x10, bd->bi_flashoffset); + stl_phys(bdloc + 0x14, bd->bi_sramstart); + stl_phys(bdloc + 0x18, bd->bi_sramsize); + stl_phys(bdloc + 0x1C, bd->bi_bootflags); + stl_phys(bdloc + 0x20, bd->bi_ipaddr); for (i = 0; i < 6; i++) - stb_raw(phys_ram_base + bdloc + 0x24 + i, bd->bi_enetaddr[i]); - stw_raw(phys_ram_base + bdloc + 0x2A, bd->bi_ethspeed); - stl_raw(phys_ram_base + bdloc + 0x2C, bd->bi_intfreq); - stl_raw(phys_ram_base + bdloc + 0x30, bd->bi_busfreq); - stl_raw(phys_ram_base + bdloc + 0x34, bd->bi_baudrate); + stb_phys(bdloc + 0x24 + i, bd->bi_enetaddr[i]); + stw_phys(bdloc + 0x2A, bd->bi_ethspeed); + stl_phys(bdloc + 0x2C, bd->bi_intfreq); + stl_phys(bdloc + 0x30, bd->bi_busfreq); + stl_phys(bdloc + 0x34, bd->bi_baudrate); for (i = 0; i < 4; i++) - stb_raw(phys_ram_base + bdloc + 0x38 + i, bd->bi_s_version[i]); + stb_phys(bdloc + 0x38 + i, bd->bi_s_version[i]); for (i = 0; i < 32; i++) - stb_raw(phys_ram_base + bdloc + 0x3C + i, bd->bi_s_version[i]); - stl_raw(phys_ram_base + bdloc + 0x5C, bd->bi_plb_busfreq); - stl_raw(phys_ram_base + bdloc + 0x60, bd->bi_pci_busfreq); + stb_phys(bdloc + 0x3C + i, bd->bi_s_version[i]); + stl_phys(bdloc + 0x5C, bd->bi_plb_busfreq); + stl_phys(bdloc + 0x60, bd->bi_pci_busfreq); for (i = 0; i < 6; i++) - stb_raw(phys_ram_base + bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]); + stb_phys(bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]); n = 0x6A; - if (env->spr[SPR_PVR] == CPU_PPC_405EP) { + if (flags & 0x00000001) { for (i = 0; i < 6; i++) - stb_raw(phys_ram_base + bdloc + n++, bd->bi_pci_enetaddr2[i]); + stb_phys(bdloc + n++, bd->bi_pci_enetaddr2[i]); } - stl_raw(phys_ram_base + bdloc + n, bd->bi_opbfreq); + stl_phys(bdloc + n, bd->bi_opbfreq); n += 4; for (i = 0; i < 2; i++) { - stl_raw(phys_ram_base + bdloc + n, bd->bi_iic_fast[i]); + stl_phys(bdloc + n, bd->bi_iic_fast[i]); n += 4; } @@ -116,194 +93,6 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd) /* Shared peripherals */ /*****************************************************************************/ -/* Fake device used to map multiple devices in a single memory page */ -#define MMIO_AREA_BITS 8 -#define MMIO_AREA_LEN (1 << MMIO_AREA_BITS) -#define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS)) -#define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1)) -struct ppc4xx_mmio_t { - uint32_t base; - CPUReadMemoryFunc **mem_read[MMIO_AREA_NB]; - CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB]; - void *opaque[MMIO_AREA_NB]; -}; - -static uint32_t unassigned_mem_readb (void *opaque, target_phys_addr_t addr) -{ -#ifdef DEBUG_UNASSIGNED - printf("Unassigned mem read 0x" PADDRX "\n", addr); -#endif - - return 0; -} - -static void unassigned_mem_writeb (void *opaque, - target_phys_addr_t addr, uint32_t val) -{ -#ifdef DEBUG_UNASSIGNED - printf("Unassigned mem write 0x" PADDRX " = 0x%x\n", addr, val); -#endif -} - -static CPUReadMemoryFunc *unassigned_mem_read[3] = { - unassigned_mem_readb, - unassigned_mem_readb, - unassigned_mem_readb, -}; - -static CPUWriteMemoryFunc *unassigned_mem_write[3] = { - unassigned_mem_writeb, - unassigned_mem_writeb, - unassigned_mem_writeb, -}; - -static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio, - target_phys_addr_t addr, int len) -{ - CPUReadMemoryFunc **mem_read; - uint32_t ret; - int idx; - - idx = MMIO_IDX(addr - mmio->base); -#if defined(DEBUG_MMIO) - printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__, - mmio, len, addr, idx); -#endif - mem_read = mmio->mem_read[idx]; - ret = (*mem_read[len])(mmio->opaque[idx], addr); - - return ret; -} - -static void mmio_writelen (ppc4xx_mmio_t *mmio, - target_phys_addr_t addr, uint32_t value, int len) -{ - CPUWriteMemoryFunc **mem_write; - int idx; - - idx = MMIO_IDX(addr - mmio->base); -#if defined(DEBUG_MMIO) - printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08x\n", __func__, - mmio, len, addr, idx, value); -#endif - mem_write = mmio->mem_write[idx]; - (*mem_write[len])(mmio->opaque[idx], addr, value); -} - -static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr) -{ -#if defined(DEBUG_MMIO) - printf("%s: addr " PADDRX "\n", __func__, addr); -#endif - - return mmio_readlen(opaque, addr, 0); -} - -static void mmio_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) -{ -#if defined(DEBUG_MMIO) - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); -#endif - mmio_writelen(opaque, addr, value, 0); -} - -static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr) -{ -#if defined(DEBUG_MMIO) - printf("%s: addr " PADDRX "\n", __func__, addr); -#endif - - return mmio_readlen(opaque, addr, 1); -} - -static void mmio_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) -{ -#if defined(DEBUG_MMIO) - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); -#endif - mmio_writelen(opaque, addr, value, 1); -} - -static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr) -{ -#if defined(DEBUG_MMIO) - printf("%s: addr " PADDRX "\n", __func__, addr); -#endif - - return mmio_readlen(opaque, addr, 2); -} - -static void mmio_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) -{ -#if defined(DEBUG_MMIO) - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); -#endif - mmio_writelen(opaque, addr, value, 2); -} - -static CPUReadMemoryFunc *mmio_read[] = { - &mmio_readb, - &mmio_readw, - &mmio_readl, -}; - -static CPUWriteMemoryFunc *mmio_write[] = { - &mmio_writeb, - &mmio_writew, - &mmio_writel, -}; - -int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, - uint32_t offset, uint32_t len, - CPUReadMemoryFunc **mem_read, - CPUWriteMemoryFunc **mem_write, void *opaque) -{ - uint32_t end; - int idx, eidx; - - if ((offset + len) > TARGET_PAGE_SIZE) - return -1; - idx = MMIO_IDX(offset); - end = offset + len - 1; - eidx = MMIO_IDX(end); -#if defined(DEBUG_MMIO) - printf("%s: offset %08x len %08x %08x %d %d\n", __func__, offset, len, - end, idx, eidx); -#endif - for (; idx <= eidx; idx++) { - mmio->mem_read[idx] = mem_read; - mmio->mem_write[idx] = mem_write; - mmio->opaque[idx] = opaque; - } - - return 0; -} - -ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, uint32_t base) -{ - ppc4xx_mmio_t *mmio; - int mmio_memory; - - mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t)); - if (mmio != NULL) { - mmio->base = base; - mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio); -#if defined(DEBUG_MMIO) - printf("%s: %p base %08x len %08x %d\n", __func__, - mmio, base, TARGET_PAGE_SIZE, mmio_memory); -#endif - cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory); - ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE, - unassigned_mem_read, unassigned_mem_write, NULL); - } - - return mmio; -} - -/*****************************************************************************/ /* Peripheral local bus arbitrer */ enum { PLB0_BESR = 0x084, @@ -350,7 +139,10 @@ static void dcr_write_plb (void *opaque, int dcrn, target_ulong val) plb = opaque; switch (dcrn) { case PLB0_ACR: - plb->acr = val & 0xFC000000; + /* We don't care about the actual parameters written as + * we don't manage any priorities on the bus + */ + plb->acr = val & 0xF8000000; break; case PLB0_BEAR: /* Read only */ @@ -377,13 +169,11 @@ void ppc4xx_plb_init (CPUState *env) ppc4xx_plb_t *plb; plb = qemu_mallocz(sizeof(ppc4xx_plb_t)); - if (plb != NULL) { - ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); - ppc4xx_plb_reset(plb); - qemu_register_reset(ppc4xx_plb_reset, plb); - } + ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); + ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_plb_reset(plb); + qemu_register_reset(ppc4xx_plb_reset, 0, plb); } /*****************************************************************************/ @@ -456,20 +246,18 @@ void ppc4xx_pob_init (CPUState *env) ppc4xx_pob_t *pob; pob = qemu_mallocz(sizeof(ppc4xx_pob_t)); - if (pob != NULL) { - ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob); - ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob); - ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob); - qemu_register_reset(ppc4xx_pob_reset, pob); - ppc4xx_pob_reset(env); - } + ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob); + ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob); + ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob); + qemu_register_reset(ppc4xx_pob_reset, 0, pob); + ppc4xx_pob_reset(env); } /*****************************************************************************/ /* OPB arbitrer */ typedef struct ppc4xx_opba_t ppc4xx_opba_t; struct ppc4xx_opba_t { - target_ulong base; + target_phys_addr_t base; uint8_t cr; uint8_t pr; }; @@ -504,7 +292,7 @@ static void opba_writeb (void *opaque, ppc4xx_opba_t *opba; #ifdef DEBUG_OPBA - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); #endif opba = opaque; switch (addr - opba->base) { @@ -536,7 +324,7 @@ static void opba_writew (void *opaque, target_phys_addr_t addr, uint32_t value) { #ifdef DEBUG_OPBA - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); #endif opba_writeb(opaque, addr, value >> 8); opba_writeb(opaque, addr + 1, value); @@ -559,7 +347,7 @@ static void opba_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { #ifdef DEBUG_OPBA - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); #endif opba_writeb(opaque, addr, value >> 24); opba_writeb(opaque, addr + 1, value >> 16); @@ -586,296 +374,20 @@ static void ppc4xx_opba_reset (void *opaque) opba->pr = 0x11; } -void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset) +void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, + target_phys_addr_t offset) { ppc4xx_opba_t *opba; opba = qemu_mallocz(sizeof(ppc4xx_opba_t)); - if (opba != NULL) { - opba->base = mmio->base + offset; + opba->base = offset; #ifdef DEBUG_OPBA - printf("%s: offset=%08x\n", __func__, offset); -#endif - ppc4xx_mmio_register(env, mmio, offset, 0x002, - opba_read, opba_write, opba); - qemu_register_reset(ppc4xx_opba_reset, opba); - ppc4xx_opba_reset(opba); - } -} - -/*****************************************************************************/ -/* "Universal" Interrupt controller */ -enum { - DCR_UICSR = 0x000, - DCR_UICSRS = 0x001, - DCR_UICER = 0x002, - DCR_UICCR = 0x003, - DCR_UICPR = 0x004, - DCR_UICTR = 0x005, - DCR_UICMSR = 0x006, - DCR_UICVR = 0x007, - DCR_UICVCR = 0x008, - DCR_UICMAX = 0x009, -}; - -#define UIC_MAX_IRQ 32 -typedef struct ppcuic_t ppcuic_t; -struct ppcuic_t { - uint32_t dcr_base; - int use_vectors; - uint32_t uicsr; /* Status register */ - uint32_t uicer; /* Enable register */ - uint32_t uiccr; /* Critical register */ - uint32_t uicpr; /* Polarity register */ - uint32_t uictr; /* Triggering register */ - uint32_t uicvcr; /* Vector configuration register */ - uint32_t uicvr; - qemu_irq *irqs; -}; - -static void ppcuic_trigger_irq (ppcuic_t *uic) -{ - uint32_t ir, cr; - int start, end, inc, i; - - /* Trigger interrupt if any is pending */ - ir = uic->uicsr & uic->uicer & (~uic->uiccr); - cr = uic->uicsr & uic->uicer & uic->uiccr; -#ifdef DEBUG_UIC - if (loglevel & CPU_LOG_INT) { - fprintf(logfile, "%s: uicsr %08x uicer %08x uiccr %08x\n" - " %08x ir %08x cr %08x\n", __func__, - uic->uicsr, uic->uicer, uic->uiccr, - uic->uicsr & uic->uicer, ir, cr); - } -#endif - if (ir != 0x0000000) { -#ifdef DEBUG_UIC - if (loglevel & CPU_LOG_INT) { - fprintf(logfile, "Raise UIC interrupt\n"); - } -#endif - qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]); - } else { -#ifdef DEBUG_UIC - if (loglevel & CPU_LOG_INT) { - fprintf(logfile, "Lower UIC interrupt\n"); - } -#endif - qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]); - } - /* Trigger critical interrupt if any is pending and update vector */ - if (cr != 0x0000000) { - qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]); - if (uic->use_vectors) { - /* Compute critical IRQ vector */ - if (uic->uicvcr & 1) { - start = 31; - end = 0; - inc = -1; - } else { - start = 0; - end = 31; - inc = 1; - } - uic->uicvr = uic->uicvcr & 0xFFFFFFFC; - for (i = start; i <= end; i += inc) { - if (cr & (1 << i)) { - uic->uicvr += (i - start) * 512 * inc; - break; - } - } - } -#ifdef DEBUG_UIC - if (loglevel & CPU_LOG_INT) { - fprintf(logfile, "Raise UIC critical interrupt - vector %08x\n", - uic->uicvr); - } -#endif - } else { -#ifdef DEBUG_UIC - if (loglevel & CPU_LOG_INT) { - fprintf(logfile, "Lower UIC critical interrupt\n"); - } -#endif - qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]); - uic->uicvr = 0x00000000; - } -} - -static void ppcuic_set_irq (void *opaque, int irq_num, int level) -{ - ppcuic_t *uic; - uint32_t mask, sr; - - uic = opaque; - mask = 1 << irq_num; -#ifdef DEBUG_UIC - if (loglevel & CPU_LOG_INT) { - fprintf(logfile, "%s: irq %d level %d uicsr %08x mask %08x => %08x " - "%08x\n", __func__, irq_num, level, - uic->uicsr, mask, uic->uicsr & mask, level << irq_num); - } -#endif - if (irq_num < 0 || irq_num > 31) - return; - sr = uic->uicsr; - if (!(uic->uicpr & mask)) { - /* Negatively asserted IRQ */ - level = level == 0 ? 1 : 0; - } - /* Update status register */ - if (uic->uictr & mask) { - /* Edge sensitive interrupt */ - if (level == 1) - uic->uicsr |= mask; - } else { - /* Level sensitive interrupt */ - if (level == 1) - uic->uicsr |= mask; - else - uic->uicsr &= ~mask; - } -#ifdef DEBUG_UIC - if (loglevel & CPU_LOG_INT) { - fprintf(logfile, "%s: irq %d level %d sr %08x => %08x\n", __func__, - irq_num, level, uic->uicsr, sr); - } -#endif - if (sr != uic->uicsr) - ppcuic_trigger_irq(uic); -} - -static target_ulong dcr_read_uic (void *opaque, int dcrn) -{ - ppcuic_t *uic; - target_ulong ret; - - uic = opaque; - dcrn -= uic->dcr_base; - switch (dcrn) { - case DCR_UICSR: - case DCR_UICSRS: - ret = uic->uicsr; - break; - case DCR_UICER: - ret = uic->uicer; - break; - case DCR_UICCR: - ret = uic->uiccr; - break; - case DCR_UICPR: - ret = uic->uicpr; - break; - case DCR_UICTR: - ret = uic->uictr; - break; - case DCR_UICMSR: - ret = uic->uicsr & uic->uicer; - break; - case DCR_UICVR: - if (!uic->use_vectors) - goto no_read; - ret = uic->uicvr; - break; - case DCR_UICVCR: - if (!uic->use_vectors) - goto no_read; - ret = uic->uicvcr; - break; - default: - no_read: - ret = 0x00000000; - break; - } - - return ret; -} - -static void dcr_write_uic (void *opaque, int dcrn, target_ulong val) -{ - ppcuic_t *uic; - - uic = opaque; - dcrn -= uic->dcr_base; -#ifdef DEBUG_UIC - if (loglevel & CPU_LOG_INT) { - fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val); - } + printf("%s: offset " PADDRX "\n", __func__, offset); #endif - switch (dcrn) { - case DCR_UICSR: - uic->uicsr &= ~val; - ppcuic_trigger_irq(uic); - break; - case DCR_UICSRS: - uic->uicsr |= val; - ppcuic_trigger_irq(uic); - break; - case DCR_UICER: - uic->uicer = val; - ppcuic_trigger_irq(uic); - break; - case DCR_UICCR: - uic->uiccr = val; - ppcuic_trigger_irq(uic); - break; - case DCR_UICPR: - uic->uicpr = val; - ppcuic_trigger_irq(uic); - break; - case DCR_UICTR: - uic->uictr = val; - ppcuic_trigger_irq(uic); - break; - case DCR_UICMSR: - break; - case DCR_UICVR: - break; - case DCR_UICVCR: - uic->uicvcr = val & 0xFFFFFFFD; - ppcuic_trigger_irq(uic); - break; - } -} - -static void ppcuic_reset (void *opaque) -{ - ppcuic_t *uic; - - uic = opaque; - uic->uiccr = 0x00000000; - uic->uicer = 0x00000000; - uic->uicpr = 0x00000000; - uic->uicsr = 0x00000000; - uic->uictr = 0x00000000; - if (uic->use_vectors) { - uic->uicvcr = 0x00000000; - uic->uicvr = 0x0000000; - } -} - -qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs, - uint32_t dcr_base, int has_ssr, int has_vr) -{ - ppcuic_t *uic; - int i; - - uic = qemu_mallocz(sizeof(ppcuic_t)); - if (uic != NULL) { - uic->dcr_base = dcr_base; - uic->irqs = irqs; - if (has_vr) - uic->use_vectors = 1; - for (i = 0; i < DCR_UICMAX; i++) { - ppc_dcr_register(env, dcr_base + i, uic, - &dcr_read_uic, &dcr_write_uic); - } - qemu_register_reset(ppcuic_reset, uic); - ppcuic_reset(uic); - } - - return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ); + ppc4xx_mmio_register(env, mmio, offset, 0x002, + opba_read, opba_write, opba); + qemu_register_reset(ppc4xx_opba_reset, 0, opba); + ppc4xx_opba_reset(opba); } /*****************************************************************************/ @@ -883,339 +395,6 @@ qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs, /* XXX: TODO */ /*****************************************************************************/ -/* SDRAM controller */ -typedef struct ppc4xx_sdram_t ppc4xx_sdram_t; -struct ppc4xx_sdram_t { - uint32_t addr; - int nbanks; - target_ulong ram_bases[4]; - target_ulong ram_sizes[4]; - uint32_t besr0; - uint32_t besr1; - uint32_t bear; - uint32_t cfg; - uint32_t status; - uint32_t rtr; - uint32_t pmit; - uint32_t bcr[4]; - uint32_t tr; - uint32_t ecccfg; - uint32_t eccesr; - qemu_irq irq; -}; - -enum { - SDRAM0_CFGADDR = 0x010, - SDRAM0_CFGDATA = 0x011, -}; - -static uint32_t sdram_bcr (target_ulong ram_base, target_ulong ram_size) -{ - uint32_t bcr; - - switch (ram_size) { - case (4 * 1024 * 1024): - bcr = 0x00000000; - break; - case (8 * 1024 * 1024): - bcr = 0x00020000; - break; - case (16 * 1024 * 1024): - bcr = 0x00040000; - break; - case (32 * 1024 * 1024): - bcr = 0x00060000; - break; - case (64 * 1024 * 1024): - bcr = 0x00080000; - break; - case (128 * 1024 * 1024): - bcr = 0x000A0000; - break; - case (256 * 1024 * 1024): - bcr = 0x000C0000; - break; - default: - printf("%s: invalid RAM size " TARGET_FMT_ld "\n", __func__, ram_size); - return 0x00000000; - } - bcr |= ram_base & 0xFF800000; - bcr |= 1; - - return bcr; -} - -static inline target_ulong sdram_base (uint32_t bcr) -{ - return bcr & 0xFF800000; -} - -static target_ulong sdram_size (uint32_t bcr) -{ - target_ulong size; - int sh; - - sh = (bcr >> 17) & 0x7; - if (sh == 7) - size = -1; - else - size = (4 * 1024 * 1024) << sh; - - return size; -} - -static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled) -{ - if (*bcrp & 0x00000001) { - /* Unmap RAM */ -#ifdef DEBUG_SDRAM - printf("%s: unmap RAM area " ADDRX " " ADDRX "\n", __func__, - sdram_base(*bcrp), sdram_size(*bcrp)); -#endif - cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp), - IO_MEM_UNASSIGNED); - } - *bcrp = bcr & 0xFFDEE001; - if (enabled && (bcr & 0x00000001)) { -#ifdef DEBUG_SDRAM - printf("%s: Map RAM area " ADDRX " " ADDRX "\n", __func__, - sdram_base(bcr), sdram_size(bcr)); -#endif - cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr), - sdram_base(bcr) | IO_MEM_RAM); - } -} - -static void sdram_map_bcr (ppc4xx_sdram_t *sdram) -{ - int i; - - for (i = 0; i < sdram->nbanks; i++) { - if (sdram->ram_sizes[i] != 0) { - sdram_set_bcr(&sdram->bcr[i], - sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]), - 1); - } else { - sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0); - } - } -} - -static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram) -{ - int i; - - for (i = 0; i < sdram->nbanks; i++) { -#ifdef DEBUG_SDRAM - printf("%s: Unmap RAM area " ADDRX " " ADDRX "\n", __func__, - sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i])); -#endif - cpu_register_physical_memory(sdram_base(sdram->bcr[i]), - sdram_size(sdram->bcr[i]), - IO_MEM_UNASSIGNED); - } -} - -static target_ulong dcr_read_sdram (void *opaque, int dcrn) -{ - ppc4xx_sdram_t *sdram; - target_ulong ret; - - sdram = opaque; - switch (dcrn) { - case SDRAM0_CFGADDR: - ret = sdram->addr; - break; - case SDRAM0_CFGDATA: - switch (sdram->addr) { - case 0x00: /* SDRAM_BESR0 */ - ret = sdram->besr0; - break; - case 0x08: /* SDRAM_BESR1 */ - ret = sdram->besr1; - break; - case 0x10: /* SDRAM_BEAR */ - ret = sdram->bear; - break; - case 0x20: /* SDRAM_CFG */ - ret = sdram->cfg; - break; - case 0x24: /* SDRAM_STATUS */ - ret = sdram->status; - break; - case 0x30: /* SDRAM_RTR */ - ret = sdram->rtr; - break; - case 0x34: /* SDRAM_PMIT */ - ret = sdram->pmit; - break; - case 0x40: /* SDRAM_B0CR */ - ret = sdram->bcr[0]; - break; - case 0x44: /* SDRAM_B1CR */ - ret = sdram->bcr[1]; - break; - case 0x48: /* SDRAM_B2CR */ - ret = sdram->bcr[2]; - break; - case 0x4C: /* SDRAM_B3CR */ - ret = sdram->bcr[3]; - break; - case 0x80: /* SDRAM_TR */ - ret = -1; /* ? */ - break; - case 0x94: /* SDRAM_ECCCFG */ - ret = sdram->ecccfg; - break; - case 0x98: /* SDRAM_ECCESR */ - ret = sdram->eccesr; - break; - default: /* Error */ - ret = -1; - break; - } - break; - default: - /* Avoid gcc warning */ - ret = 0x00000000; - break; - } - - return ret; -} - -static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val) -{ - ppc4xx_sdram_t *sdram; - - sdram = opaque; - switch (dcrn) { - case SDRAM0_CFGADDR: - sdram->addr = val; - break; - case SDRAM0_CFGDATA: - switch (sdram->addr) { - case 0x00: /* SDRAM_BESR0 */ - sdram->besr0 &= ~val; - break; - case 0x08: /* SDRAM_BESR1 */ - sdram->besr1 &= ~val; - break; - case 0x10: /* SDRAM_BEAR */ - sdram->bear = val; - break; - case 0x20: /* SDRAM_CFG */ - val &= 0xFFE00000; - if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) { -#ifdef DEBUG_SDRAM - printf("%s: enable SDRAM controller\n", __func__); -#endif - /* validate all RAM mappings */ - sdram_map_bcr(sdram); - sdram->status &= ~0x80000000; - } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) { -#ifdef DEBUG_SDRAM - printf("%s: disable SDRAM controller\n", __func__); -#endif - /* invalidate all RAM mappings */ - sdram_unmap_bcr(sdram); - sdram->status |= 0x80000000; - } - if (!(sdram->cfg & 0x40000000) && (val & 0x40000000)) - sdram->status |= 0x40000000; - else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000)) - sdram->status &= ~0x40000000; - sdram->cfg = val; - break; - case 0x24: /* SDRAM_STATUS */ - /* Read-only register */ - break; - case 0x30: /* SDRAM_RTR */ - sdram->rtr = val & 0x3FF80000; - break; - case 0x34: /* SDRAM_PMIT */ - sdram->pmit = (val & 0xF8000000) | 0x07C00000; - break; - case 0x40: /* SDRAM_B0CR */ - sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000); - break; - case 0x44: /* SDRAM_B1CR */ - sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000); - break; - case 0x48: /* SDRAM_B2CR */ - sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000); - break; - case 0x4C: /* SDRAM_B3CR */ - sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000); - break; - case 0x80: /* SDRAM_TR */ - sdram->tr = val & 0x018FC01F; - break; - case 0x94: /* SDRAM_ECCCFG */ - sdram->ecccfg = val & 0x00F00000; - break; - case 0x98: /* SDRAM_ECCESR */ - val &= 0xFFF0F000; - if (sdram->eccesr == 0 && val != 0) - qemu_irq_raise(sdram->irq); - else if (sdram->eccesr != 0 && val == 0) - qemu_irq_lower(sdram->irq); - sdram->eccesr = val; - break; - default: /* Error */ - break; - } - break; - } -} - -static void sdram_reset (void *opaque) -{ - ppc4xx_sdram_t *sdram; - - sdram = opaque; - sdram->addr = 0x00000000; - sdram->bear = 0x00000000; - sdram->besr0 = 0x00000000; /* No error */ - sdram->besr1 = 0x00000000; /* No error */ - sdram->cfg = 0x00000000; - sdram->ecccfg = 0x00000000; /* No ECC */ - sdram->eccesr = 0x00000000; /* No error */ - sdram->pmit = 0x07C00000; - sdram->rtr = 0x05F00000; - sdram->tr = 0x00854009; - /* We pre-initialize RAM banks */ - sdram->status = 0x00000000; - sdram->cfg = 0x00800000; - sdram_unmap_bcr(sdram); -} - -void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks, - target_ulong *ram_bases, target_ulong *ram_sizes, - int do_init) -{ - ppc4xx_sdram_t *sdram; - - sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t)); - if (sdram != NULL) { - sdram->irq = irq; - sdram->nbanks = nbanks; - memset(sdram->ram_bases, 0, 4 * sizeof(target_ulong)); - memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(target_ulong)); - memset(sdram->ram_sizes, 0, 4 * sizeof(target_ulong)); - memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(target_ulong)); - sdram_reset(sdram); - qemu_register_reset(&sdram_reset, sdram); - ppc_dcr_register(env, SDRAM0_CFGADDR, - sdram, &dcr_read_sdram, &dcr_write_sdram); - ppc_dcr_register(env, SDRAM0_CFGDATA, - sdram, &dcr_read_sdram, &dcr_write_sdram); - if (do_init) - sdram_map_bcr(sdram); - } -} - -/*****************************************************************************/ /* Peripheral controller */ typedef struct ppc4xx_ebc_t ppc4xx_ebc_t; struct ppc4xx_ebc_t { @@ -1392,7 +571,7 @@ static void ebc_reset (void *opaque) } ebc->besr0 = 0x00000000; ebc->besr1 = 0x00000000; - ebc->cfg = 0x07C00000; + ebc->cfg = 0x80400000; } void ppc405_ebc_init (CPUState *env) @@ -1400,14 +579,12 @@ void ppc405_ebc_init (CPUState *env) ppc4xx_ebc_t *ebc; ebc = qemu_mallocz(sizeof(ppc4xx_ebc_t)); - if (ebc != NULL) { - ebc_reset(ebc); - qemu_register_reset(&ebc_reset, ebc); - ppc_dcr_register(env, EBC0_CFGADDR, - ebc, &dcr_read_ebc, &dcr_write_ebc); - ppc_dcr_register(env, EBC0_CFGDATA, - ebc, &dcr_read_ebc, &dcr_write_ebc); - } + ebc_reset(ebc); + qemu_register_reset(&ebc_reset, 0, ebc); + ppc_dcr_register(env, EBC0_CFGADDR, + ebc, &dcr_read_ebc, &dcr_write_ebc); + ppc_dcr_register(env, EBC0_CFGDATA, + ebc, &dcr_read_ebc, &dcr_write_ebc); } /*****************************************************************************/ @@ -1493,66 +670,64 @@ void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]) ppc405_dma_t *dma; dma = qemu_mallocz(sizeof(ppc405_dma_t)); - if (dma != NULL) { - memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq)); - ppc405_dma_reset(dma); - qemu_register_reset(&ppc405_dma_reset, dma); - ppc_dcr_register(env, DMA0_CR0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CR1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CR2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CR3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SR, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SGC, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SLP, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_POL, - dma, &dcr_read_dma, &dcr_write_dma); - } + memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq)); + ppc405_dma_reset(dma); + qemu_register_reset(&ppc405_dma_reset, 0, dma); + ppc_dcr_register(env, DMA0_CR0, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_CT0, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_DA0, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SA0, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SG0, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_CR1, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_CT1, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_DA1, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SA1, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SG1, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_CR2, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_CT2, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_DA2, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SA2, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SG2, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_CR3, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_CT3, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_DA3, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SA3, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SG3, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SR, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SGC, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_SLP, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, DMA0_POL, + dma, &dcr_read_dma, &dcr_write_dma); } /*****************************************************************************/ /* GPIO */ typedef struct ppc405_gpio_t ppc405_gpio_t; struct ppc405_gpio_t { - uint32_t base; + target_phys_addr_t base; uint32_t or; uint32_t tcr; uint32_t osrh; @@ -1585,7 +760,7 @@ static void ppc405_gpio_writeb (void *opaque, gpio = opaque; #ifdef DEBUG_GPIO - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); #endif } @@ -1608,7 +783,7 @@ static void ppc405_gpio_writew (void *opaque, gpio = opaque; #ifdef DEBUG_GPIO - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); #endif } @@ -1631,7 +806,7 @@ static void ppc405_gpio_writel (void *opaque, gpio = opaque; #ifdef DEBUG_GPIO - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); #endif } @@ -1654,21 +829,20 @@ static void ppc405_gpio_reset (void *opaque) gpio = opaque; } -void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset) +void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, + target_phys_addr_t offset) { ppc405_gpio_t *gpio; gpio = qemu_mallocz(sizeof(ppc405_gpio_t)); - if (gpio != NULL) { - gpio->base = mmio->base + offset; - ppc405_gpio_reset(gpio); - qemu_register_reset(&ppc405_gpio_reset, gpio); + gpio->base = offset; + ppc405_gpio_reset(gpio); + qemu_register_reset(&ppc405_gpio_reset, 0, gpio); #ifdef DEBUG_GPIO - printf("%s: offset=%08x\n", __func__, offset); + printf("%s: offset " PADDRX "\n", __func__, offset); #endif - ppc4xx_mmio_register(env, mmio, offset, 0x038, - ppc405_gpio_read, ppc405_gpio_write, gpio); - } + ppc4xx_mmio_register(env, mmio, offset, 0x038, + ppc405_gpio_read, ppc405_gpio_write, gpio); } /*****************************************************************************/ @@ -1686,15 +860,15 @@ static CPUWriteMemoryFunc *serial_mm_write[] = { }; void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio, - uint32_t offset, qemu_irq irq, + target_phys_addr_t offset, qemu_irq irq, CharDriverState *chr) { void *serial; #ifdef DEBUG_SERIAL - printf("%s: offset=%08x\n", __func__, offset); + printf("%s: offset " PADDRX "\n", __func__, offset); #endif - serial = serial_mm_init(mmio->base + offset, 0, irq, chr, 0); + serial = serial_mm_init(offset, 0, irq, 399193, chr, 0); ppc4xx_mmio_register(env, mmio, offset, 0x008, serial_mm_read, serial_mm_write, serial); } @@ -1722,7 +896,9 @@ static void ocm_update_mappings (ppc405_ocm_t *ocm, uint32_t dsarc, uint32_t dsacntl) { #ifdef DEBUG_OCM - printf("OCM update ISA %08x %08x (%08x %08x) DSA %08x %08x (%08x %08x)\n", + printf("OCM update ISA %08" PRIx32 " %08" PRIx32 " (%08" PRIx32 + " %08" PRIx32 ") DSA %08" PRIx32 " %08" PRIx32 + " (%08" PRIx32 " %08" PRIx32 ")\n", isarc, isacntl, dsarc, dsacntl, ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl); #endif @@ -1730,14 +906,14 @@ static void ocm_update_mappings (ppc405_ocm_t *ocm, (ocm->isacntl & 0x80000000) != (isacntl & 0x80000000)) { if (ocm->isacntl & 0x80000000) { /* Unmap previously assigned memory region */ - printf("OCM unmap ISA %08x\n", ocm->isarc); + printf("OCM unmap ISA %08" PRIx32 "\n", ocm->isarc); cpu_register_physical_memory(ocm->isarc, 0x04000000, IO_MEM_UNASSIGNED); } if (isacntl & 0x80000000) { /* Map new instruction memory region */ #ifdef DEBUG_OCM - printf("OCM map ISA %08x\n", isarc); + printf("OCM map ISA %08" PRIx32 "\n", isarc); #endif cpu_register_physical_memory(isarc, 0x04000000, ocm->offset | IO_MEM_RAM); @@ -1750,7 +926,7 @@ static void ocm_update_mappings (ppc405_ocm_t *ocm, if (!(isacntl & 0x80000000) || ocm->dsarc != isarc) { /* Unmap previously assigned memory region */ #ifdef DEBUG_OCM - printf("OCM unmap DSA %08x\n", ocm->dsarc); + printf("OCM unmap DSA %08" PRIx32 "\n", ocm->dsarc); #endif cpu_register_physical_memory(ocm->dsarc, 0x04000000, IO_MEM_UNASSIGNED); @@ -1761,7 +937,7 @@ static void ocm_update_mappings (ppc405_ocm_t *ocm, if (!(isacntl & 0x80000000) || dsarc != isarc) { /* Map new data memory region */ #ifdef DEBUG_OCM - printf("OCM map DSA %08x\n", dsarc); + printf("OCM map DSA %08" PRIx32 "\n", dsarc); #endif cpu_register_physical_memory(dsarc, 0x04000000, ocm->offset | IO_MEM_RAM); @@ -1845,31 +1021,30 @@ static void ocm_reset (void *opaque) ocm->dsacntl = dsacntl; } -void ppc405_ocm_init (CPUState *env, unsigned long offset) +void ppc405_ocm_init (CPUState *env) { ppc405_ocm_t *ocm; ocm = qemu_mallocz(sizeof(ppc405_ocm_t)); - if (ocm != NULL) { - ocm->offset = offset; - ocm_reset(ocm); - qemu_register_reset(&ocm_reset, ocm); - ppc_dcr_register(env, OCM0_ISARC, - ocm, &dcr_read_ocm, &dcr_write_ocm); - ppc_dcr_register(env, OCM0_ISACNTL, - ocm, &dcr_read_ocm, &dcr_write_ocm); - ppc_dcr_register(env, OCM0_DSARC, - ocm, &dcr_read_ocm, &dcr_write_ocm); - ppc_dcr_register(env, OCM0_DSACNTL, - ocm, &dcr_read_ocm, &dcr_write_ocm); - } + ocm->offset = qemu_ram_alloc(4096); + ocm_reset(ocm); + qemu_register_reset(&ocm_reset, 0, ocm); + ppc_dcr_register(env, OCM0_ISARC, + ocm, &dcr_read_ocm, &dcr_write_ocm); + ppc_dcr_register(env, OCM0_ISACNTL, + ocm, &dcr_read_ocm, &dcr_write_ocm); + ppc_dcr_register(env, OCM0_DSARC, + ocm, &dcr_read_ocm, &dcr_write_ocm); + ppc_dcr_register(env, OCM0_DSACNTL, + ocm, &dcr_read_ocm, &dcr_write_ocm); } /*****************************************************************************/ /* I2C controller */ typedef struct ppc4xx_i2c_t ppc4xx_i2c_t; struct ppc4xx_i2c_t { - uint32_t base; + target_phys_addr_t base; + qemu_irq irq; uint8_t mdata; uint8_t lmadr; uint8_t hmadr; @@ -1948,7 +1123,7 @@ static uint32_t ppc4xx_i2c_readb (void *opaque, target_phys_addr_t addr) break; } #ifdef DEBUG_I2C - printf("%s: addr " PADDRX " %02x\n", __func__, addr, ret); + printf("%s: addr " PADDRX " %02" PRIx32 "\n", __func__, addr, ret); #endif return ret; @@ -1960,7 +1135,7 @@ static void ppc4xx_i2c_writeb (void *opaque, ppc4xx_i2c_t *i2c; #ifdef DEBUG_I2C - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); #endif i2c = opaque; switch (addr - i2c->base) { @@ -2030,7 +1205,7 @@ static void ppc4xx_i2c_writew (void *opaque, target_phys_addr_t addr, uint32_t value) { #ifdef DEBUG_I2C - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); #endif ppc4xx_i2c_writeb(opaque, addr, value >> 8); ppc4xx_i2c_writeb(opaque, addr + 1, value); @@ -2055,7 +1230,7 @@ static void ppc4xx_i2c_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { #ifdef DEBUG_I2C - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value); + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); #endif ppc4xx_i2c_writeb(opaque, addr, value >> 24); ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16); @@ -2091,21 +1266,566 @@ static void ppc4xx_i2c_reset (void *opaque) i2c->directcntl = 0x0F; } -void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset) +void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, + target_phys_addr_t offset, qemu_irq irq) { ppc4xx_i2c_t *i2c; i2c = qemu_mallocz(sizeof(ppc4xx_i2c_t)); - if (i2c != NULL) { - i2c->base = mmio->base + offset; - ppc4xx_i2c_reset(i2c); + i2c->base = offset; + i2c->irq = irq; + ppc4xx_i2c_reset(i2c); +#ifdef DEBUG_I2C + printf("%s: offset " PADDRX "\n", __func__, offset); +#endif + ppc4xx_mmio_register(env, mmio, offset, 0x011, + i2c_read, i2c_write, i2c); + qemu_register_reset(ppc4xx_i2c_reset, 0, i2c); +} + +/*****************************************************************************/ +/* General purpose timers */ +typedef struct ppc4xx_gpt_t ppc4xx_gpt_t; +struct ppc4xx_gpt_t { + target_phys_addr_t base; + int64_t tb_offset; + uint32_t tb_freq; + struct QEMUTimer *timer; + qemu_irq irqs[5]; + uint32_t oe; + uint32_t ol; + uint32_t im; + uint32_t is; + uint32_t ie; + uint32_t comp[5]; + uint32_t mask[5]; +}; + +static uint32_t ppc4xx_gpt_readb (void *opaque, target_phys_addr_t addr) +{ +#ifdef DEBUG_GPT + printf("%s: addr " PADDRX "\n", __func__, addr); +#endif + /* XXX: generate a bus fault */ + return -1; +} + +static void ppc4xx_gpt_writeb (void *opaque, + target_phys_addr_t addr, uint32_t value) +{ +#ifdef DEBUG_I2C + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); +#endif + /* XXX: generate a bus fault */ +} + +static uint32_t ppc4xx_gpt_readw (void *opaque, target_phys_addr_t addr) +{ +#ifdef DEBUG_GPT + printf("%s: addr " PADDRX "\n", __func__, addr); +#endif + /* XXX: generate a bus fault */ + return -1; +} + +static void ppc4xx_gpt_writew (void *opaque, + target_phys_addr_t addr, uint32_t value) +{ +#ifdef DEBUG_I2C + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); +#endif + /* XXX: generate a bus fault */ +} + +static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n) +{ + /* XXX: TODO */ + return 0; +} + +static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level) +{ + /* XXX: TODO */ +} + +static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt) +{ + uint32_t mask; + int i; + + mask = 0x80000000; + for (i = 0; i < 5; i++) { + if (gpt->oe & mask) { + /* Output is enabled */ + if (ppc4xx_gpt_compare(gpt, i)) { + /* Comparison is OK */ + ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask); + } else { + /* Comparison is KO */ + ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask ? 0 : 1); + } + } + mask = mask >> 1; + } +} + +static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt) +{ + uint32_t mask; + int i; + + mask = 0x00008000; + for (i = 0; i < 5; i++) { + if (gpt->is & gpt->im & mask) + qemu_irq_raise(gpt->irqs[i]); + else + qemu_irq_lower(gpt->irqs[i]); + mask = mask >> 1; + } +} + +static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt) +{ + /* XXX: TODO */ +} + +static uint32_t ppc4xx_gpt_readl (void *opaque, target_phys_addr_t addr) +{ + ppc4xx_gpt_t *gpt; + uint32_t ret; + int idx; + +#ifdef DEBUG_GPT + printf("%s: addr " PADDRX "\n", __func__, addr); +#endif + gpt = opaque; + switch (addr - gpt->base) { + case 0x00: + /* Time base counter */ + ret = muldiv64(qemu_get_clock(vm_clock) + gpt->tb_offset, + gpt->tb_freq, ticks_per_sec); + break; + case 0x10: + /* Output enable */ + ret = gpt->oe; + break; + case 0x14: + /* Output level */ + ret = gpt->ol; + break; + case 0x18: + /* Interrupt mask */ + ret = gpt->im; + break; + case 0x1C: + case 0x20: + /* Interrupt status */ + ret = gpt->is; + break; + case 0x24: + /* Interrupt enable */ + ret = gpt->ie; + break; + case 0x80 ... 0x90: + /* Compare timer */ + idx = ((addr - gpt->base) - 0x80) >> 2; + ret = gpt->comp[idx]; + break; + case 0xC0 ... 0xD0: + /* Compare mask */ + idx = ((addr - gpt->base) - 0xC0) >> 2; + ret = gpt->mask[idx]; + break; + default: + ret = -1; + break; + } + + return ret; +} + +static void ppc4xx_gpt_writel (void *opaque, + target_phys_addr_t addr, uint32_t value) +{ + ppc4xx_gpt_t *gpt; + int idx; + #ifdef DEBUG_I2C - printf("%s: offset=%08x\n", __func__, offset); + printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value); +#endif + gpt = opaque; + switch (addr - gpt->base) { + case 0x00: + /* Time base counter */ + gpt->tb_offset = muldiv64(value, ticks_per_sec, gpt->tb_freq) + - qemu_get_clock(vm_clock); + ppc4xx_gpt_compute_timer(gpt); + break; + case 0x10: + /* Output enable */ + gpt->oe = value & 0xF8000000; + ppc4xx_gpt_set_outputs(gpt); + break; + case 0x14: + /* Output level */ + gpt->ol = value & 0xF8000000; + ppc4xx_gpt_set_outputs(gpt); + break; + case 0x18: + /* Interrupt mask */ + gpt->im = value & 0x0000F800; + break; + case 0x1C: + /* Interrupt status set */ + gpt->is |= value & 0x0000F800; + ppc4xx_gpt_set_irqs(gpt); + break; + case 0x20: + /* Interrupt status clear */ + gpt->is &= ~(value & 0x0000F800); + ppc4xx_gpt_set_irqs(gpt); + break; + case 0x24: + /* Interrupt enable */ + gpt->ie = value & 0x0000F800; + ppc4xx_gpt_set_irqs(gpt); + break; + case 0x80 ... 0x90: + /* Compare timer */ + idx = ((addr - gpt->base) - 0x80) >> 2; + gpt->comp[idx] = value & 0xF8000000; + ppc4xx_gpt_compute_timer(gpt); + break; + case 0xC0 ... 0xD0: + /* Compare mask */ + idx = ((addr - gpt->base) - 0xC0) >> 2; + gpt->mask[idx] = value & 0xF8000000; + ppc4xx_gpt_compute_timer(gpt); + break; + } +} + +static CPUReadMemoryFunc *gpt_read[] = { + &ppc4xx_gpt_readb, + &ppc4xx_gpt_readw, + &ppc4xx_gpt_readl, +}; + +static CPUWriteMemoryFunc *gpt_write[] = { + &ppc4xx_gpt_writeb, + &ppc4xx_gpt_writew, + &ppc4xx_gpt_writel, +}; + +static void ppc4xx_gpt_cb (void *opaque) +{ + ppc4xx_gpt_t *gpt; + + gpt = opaque; + ppc4xx_gpt_set_irqs(gpt); + ppc4xx_gpt_set_outputs(gpt); + ppc4xx_gpt_compute_timer(gpt); +} + +static void ppc4xx_gpt_reset (void *opaque) +{ + ppc4xx_gpt_t *gpt; + int i; + + gpt = opaque; + qemu_del_timer(gpt->timer); + gpt->oe = 0x00000000; + gpt->ol = 0x00000000; + gpt->im = 0x00000000; + gpt->is = 0x00000000; + gpt->ie = 0x00000000; + for (i = 0; i < 5; i++) { + gpt->comp[i] = 0x00000000; + gpt->mask[i] = 0x00000000; + } +} + +void ppc4xx_gpt_init (CPUState *env, ppc4xx_mmio_t *mmio, + target_phys_addr_t offset, qemu_irq irqs[5]) +{ + ppc4xx_gpt_t *gpt; + int i; + + gpt = qemu_mallocz(sizeof(ppc4xx_gpt_t)); + gpt->base = offset; + for (i = 0; i < 5; i++) + gpt->irqs[i] = irqs[i]; + gpt->timer = qemu_new_timer(vm_clock, &ppc4xx_gpt_cb, gpt); + ppc4xx_gpt_reset(gpt); +#ifdef DEBUG_GPT + printf("%s: offset " PADDRX "\n", __func__, offset); #endif - ppc4xx_mmio_register(env, mmio, offset, 0x011, - i2c_read, i2c_write, i2c); - qemu_register_reset(ppc4xx_i2c_reset, i2c); + ppc4xx_mmio_register(env, mmio, offset, 0x0D4, + gpt_read, gpt_write, gpt); + qemu_register_reset(ppc4xx_gpt_reset, 0, gpt); +} + +/*****************************************************************************/ +/* MAL */ +enum { + MAL0_CFG = 0x180, + MAL0_ESR = 0x181, + MAL0_IER = 0x182, + MAL0_TXCASR = 0x184, + MAL0_TXCARR = 0x185, + MAL0_TXEOBISR = 0x186, + MAL0_TXDEIR = 0x187, + MAL0_RXCASR = 0x190, + MAL0_RXCARR = 0x191, + MAL0_RXEOBISR = 0x192, + MAL0_RXDEIR = 0x193, + MAL0_TXCTP0R = 0x1A0, + MAL0_TXCTP1R = 0x1A1, + MAL0_TXCTP2R = 0x1A2, + MAL0_TXCTP3R = 0x1A3, + MAL0_RXCTP0R = 0x1C0, + MAL0_RXCTP1R = 0x1C1, + MAL0_RCBS0 = 0x1E0, + MAL0_RCBS1 = 0x1E1, +}; + +typedef struct ppc40x_mal_t ppc40x_mal_t; +struct ppc40x_mal_t { + qemu_irq irqs[4]; + uint32_t cfg; + uint32_t esr; + uint32_t ier; + uint32_t txcasr; + uint32_t txcarr; + uint32_t txeobisr; + uint32_t txdeir; + uint32_t rxcasr; + uint32_t rxcarr; + uint32_t rxeobisr; + uint32_t rxdeir; + uint32_t txctpr[4]; + uint32_t rxctpr[2]; + uint32_t rcbs[2]; +}; + +static void ppc40x_mal_reset (void *opaque); + +static target_ulong dcr_read_mal (void *opaque, int dcrn) +{ + ppc40x_mal_t *mal; + target_ulong ret; + + mal = opaque; + switch (dcrn) { + case MAL0_CFG: + ret = mal->cfg; + break; + case MAL0_ESR: + ret = mal->esr; + break; + case MAL0_IER: + ret = mal->ier; + break; + case MAL0_TXCASR: + ret = mal->txcasr; + break; + case MAL0_TXCARR: + ret = mal->txcarr; + break; + case MAL0_TXEOBISR: + ret = mal->txeobisr; + break; + case MAL0_TXDEIR: + ret = mal->txdeir; + break; + case MAL0_RXCASR: + ret = mal->rxcasr; + break; + case MAL0_RXCARR: + ret = mal->rxcarr; + break; + case MAL0_RXEOBISR: + ret = mal->rxeobisr; + break; + case MAL0_RXDEIR: + ret = mal->rxdeir; + break; + case MAL0_TXCTP0R: + ret = mal->txctpr[0]; + break; + case MAL0_TXCTP1R: + ret = mal->txctpr[1]; + break; + case MAL0_TXCTP2R: + ret = mal->txctpr[2]; + break; + case MAL0_TXCTP3R: + ret = mal->txctpr[3]; + break; + case MAL0_RXCTP0R: + ret = mal->rxctpr[0]; + break; + case MAL0_RXCTP1R: + ret = mal->rxctpr[1]; + break; + case MAL0_RCBS0: + ret = mal->rcbs[0]; + break; + case MAL0_RCBS1: + ret = mal->rcbs[1]; + break; + default: + ret = 0; + break; } + + return ret; +} + +static void dcr_write_mal (void *opaque, int dcrn, target_ulong val) +{ + ppc40x_mal_t *mal; + int idx; + + mal = opaque; + switch (dcrn) { + case MAL0_CFG: + if (val & 0x80000000) + ppc40x_mal_reset(mal); + mal->cfg = val & 0x00FFC087; + break; + case MAL0_ESR: + /* Read/clear */ + mal->esr &= ~val; + break; + case MAL0_IER: + mal->ier = val & 0x0000001F; + break; + case MAL0_TXCASR: + mal->txcasr = val & 0xF0000000; + break; + case MAL0_TXCARR: + mal->txcarr = val & 0xF0000000; + break; + case MAL0_TXEOBISR: + /* Read/clear */ + mal->txeobisr &= ~val; + break; + case MAL0_TXDEIR: + /* Read/clear */ + mal->txdeir &= ~val; + break; + case MAL0_RXCASR: + mal->rxcasr = val & 0xC0000000; + break; + case MAL0_RXCARR: + mal->rxcarr = val & 0xC0000000; + break; + case MAL0_RXEOBISR: + /* Read/clear */ + mal->rxeobisr &= ~val; + break; + case MAL0_RXDEIR: + /* Read/clear */ + mal->rxdeir &= ~val; + break; + case MAL0_TXCTP0R: + idx = 0; + goto update_tx_ptr; + case MAL0_TXCTP1R: + idx = 1; + goto update_tx_ptr; + case MAL0_TXCTP2R: + idx = 2; + goto update_tx_ptr; + case MAL0_TXCTP3R: + idx = 3; + update_tx_ptr: + mal->txctpr[idx] = val; + break; + case MAL0_RXCTP0R: + idx = 0; + goto update_rx_ptr; + case MAL0_RXCTP1R: + idx = 1; + update_rx_ptr: + mal->rxctpr[idx] = val; + break; + case MAL0_RCBS0: + idx = 0; + goto update_rx_size; + case MAL0_RCBS1: + idx = 1; + update_rx_size: + mal->rcbs[idx] = val & 0x000000FF; + break; + } +} + +static void ppc40x_mal_reset (void *opaque) +{ + ppc40x_mal_t *mal; + + mal = opaque; + mal->cfg = 0x0007C000; + mal->esr = 0x00000000; + mal->ier = 0x00000000; + mal->rxcasr = 0x00000000; + mal->rxdeir = 0x00000000; + mal->rxeobisr = 0x00000000; + mal->txcasr = 0x00000000; + mal->txdeir = 0x00000000; + mal->txeobisr = 0x00000000; +} + +void ppc405_mal_init (CPUState *env, qemu_irq irqs[4]) +{ + ppc40x_mal_t *mal; + int i; + + mal = qemu_mallocz(sizeof(ppc40x_mal_t)); + for (i = 0; i < 4; i++) + mal->irqs[i] = irqs[i]; + ppc40x_mal_reset(mal); + qemu_register_reset(&ppc40x_mal_reset, 0, mal); + ppc_dcr_register(env, MAL0_CFG, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_ESR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_IER, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCASR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCARR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXEOBISR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXDEIR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXCASR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXCARR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXEOBISR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXDEIR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCTP0R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCTP1R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCTP2R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCTP3R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXCTP0R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXCTP1R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RCBS0, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RCBS1, + mal, &dcr_read_mal, &dcr_write_mal); } /*****************************************************************************/ @@ -2115,12 +1835,17 @@ void ppc40x_core_reset (CPUState *env) target_ulong dbsr; printf("Reset PowerPC core\n"); + env->interrupt_request |= CPU_INTERRUPT_EXITTB; + /* XXX: TOFIX */ +#if 0 cpu_ppc_reset(env); +#else + qemu_system_reset_request(); +#endif dbsr = env->spr[SPR_40x_DBSR]; dbsr &= ~0x00000300; dbsr |= 0x00000100; env->spr[SPR_40x_DBSR] = dbsr; - cpu_loop_exit(); } void ppc40x_chip_reset (CPUState *env) @@ -2128,13 +1853,18 @@ void ppc40x_chip_reset (CPUState *env) target_ulong dbsr; printf("Reset PowerPC chip\n"); + env->interrupt_request |= CPU_INTERRUPT_EXITTB; + /* XXX: TOFIX */ +#if 0 cpu_ppc_reset(env); +#else + qemu_system_reset_request(); +#endif /* XXX: TODO reset all internal peripherals */ dbsr = env->spr[SPR_40x_DBSR]; dbsr &= ~0x00000300; dbsr |= 0x00000200; env->spr[SPR_40x_DBSR] = dbsr; - cpu_loop_exit(); } void ppc40x_system_reset (CPUState *env) @@ -2420,47 +2150,44 @@ static void ppc405cr_cpc_init (CPUState *env, clk_setup_t clk_setup[7], ppc405cr_cpc_t *cpc; cpc = qemu_mallocz(sizeof(ppc405cr_cpc_t)); - if (cpc != NULL) { - memcpy(cpc->clk_setup, clk_setup, - PPC405CR_CLK_NB * sizeof(clk_setup_t)); - cpc->sysclk = sysclk; - cpc->jtagid = 0x42051049; - ppc_dcr_register(env, PPC405CR_CPC0_PSR, cpc, - &dcr_read_crcpc, &dcr_write_crcpc); - ppc_dcr_register(env, PPC405CR_CPC0_CR0, cpc, - &dcr_read_crcpc, &dcr_write_crcpc); - ppc_dcr_register(env, PPC405CR_CPC0_CR1, cpc, - &dcr_read_crcpc, &dcr_write_crcpc); - ppc_dcr_register(env, PPC405CR_CPC0_JTAGID, cpc, - &dcr_read_crcpc, &dcr_write_crcpc); - ppc_dcr_register(env, PPC405CR_CPC0_PLLMR, cpc, - &dcr_read_crcpc, &dcr_write_crcpc); - ppc_dcr_register(env, PPC405CR_CPC0_ER, cpc, - &dcr_read_crcpc, &dcr_write_crcpc); - ppc_dcr_register(env, PPC405CR_CPC0_FR, cpc, - &dcr_read_crcpc, &dcr_write_crcpc); - ppc_dcr_register(env, PPC405CR_CPC0_SR, cpc, - &dcr_read_crcpc, &dcr_write_crcpc); - ppc405cr_clk_init(cpc); - qemu_register_reset(ppc405cr_cpc_reset, cpc); - ppc405cr_cpc_reset(cpc); - } -} - -CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], + memcpy(cpc->clk_setup, clk_setup, + PPC405CR_CLK_NB * sizeof(clk_setup_t)); + cpc->sysclk = sysclk; + cpc->jtagid = 0x42051049; + ppc_dcr_register(env, PPC405CR_CPC0_PSR, cpc, + &dcr_read_crcpc, &dcr_write_crcpc); + ppc_dcr_register(env, PPC405CR_CPC0_CR0, cpc, + &dcr_read_crcpc, &dcr_write_crcpc); + ppc_dcr_register(env, PPC405CR_CPC0_CR1, cpc, + &dcr_read_crcpc, &dcr_write_crcpc); + ppc_dcr_register(env, PPC405CR_CPC0_JTAGID, cpc, + &dcr_read_crcpc, &dcr_write_crcpc); + ppc_dcr_register(env, PPC405CR_CPC0_PLLMR, cpc, + &dcr_read_crcpc, &dcr_write_crcpc); + ppc_dcr_register(env, PPC405CR_CPC0_ER, cpc, + &dcr_read_crcpc, &dcr_write_crcpc); + ppc_dcr_register(env, PPC405CR_CPC0_FR, cpc, + &dcr_read_crcpc, &dcr_write_crcpc); + ppc_dcr_register(env, PPC405CR_CPC0_SR, cpc, + &dcr_read_crcpc, &dcr_write_crcpc); + ppc405cr_clk_init(cpc); + qemu_register_reset(ppc405cr_cpc_reset, 0, cpc); + ppc405cr_cpc_reset(cpc); +} + +CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4], + target_phys_addr_t ram_sizes[4], uint32_t sysclk, qemu_irq **picp, - ram_addr_t *offsetp, int do_init) + int do_init) { clk_setup_t clk_setup[PPC405CR_CLK_NB]; qemu_irq dma_irqs[4]; CPUState *env; ppc4xx_mmio_t *mmio; qemu_irq *pic, *irqs; - ram_addr_t offset; - int i; memset(clk_setup, 0, sizeof(clk_setup)); - env = ppc405_init("405cr", &clk_setup[PPC405CR_CPU_CLK], + env = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK], &clk_setup[PPC405CR_TMR_CLK], sysclk); /* Memory mapped devices registers */ mmio = ppc4xx_mmio_init(env, 0xEF600000); @@ -2473,16 +2200,13 @@ CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], /* Universal interrupt controller */ irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); irqs[PPCUIC_OUTPUT_INT] = - ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_INT]; + ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT]; irqs[PPCUIC_OUTPUT_CINT] = - ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_CINT]; + ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT]; pic = ppcuic_init(env, irqs, 0x0C0, 0, 1); *picp = pic; /* SDRAM controller */ - ppc405_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init); - offset = 0; - for (i = 0; i < 4; i++) - offset += ram_sizes[i]; + ppc4xx_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init); /* External bus controller */ ppc405_ebc_init(env); /* DMA controller */ @@ -2493,18 +2217,17 @@ CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], ppc405_dma_init(env, dma_irqs); /* Serial ports */ if (serial_hds[0] != NULL) { - ppc405_serial_init(env, mmio, 0x300, pic[31], serial_hds[0]); + ppc405_serial_init(env, mmio, 0x300, pic[0], serial_hds[0]); } if (serial_hds[1] != NULL) { - ppc405_serial_init(env, mmio, 0x400, pic[30], serial_hds[1]); + ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]); } /* IIC controller */ - ppc405_i2c_init(env, mmio, 0x500); + ppc405_i2c_init(env, mmio, 0x500, pic[2]); /* GPIO */ ppc405_gpio_init(env, mmio, 0x700); /* CPU control */ ppc405cr_cpc_init(env, clk_setup, sysclk); - *offsetp = offset; return env; } @@ -2521,6 +2244,11 @@ enum { PPC405EP_CPC0_SRR = 0x0F6, PPC405EP_CPC0_JTAGID = 0x0F7, PPC405EP_CPC0_PCI = 0x0F9, +#if 0 + PPC405EP_CPC0_ER = xxx, + PPC405EP_CPC0_FR = xxx, + PPC405EP_CPC0_SR = xxx, +#endif }; enum { @@ -2546,6 +2274,10 @@ struct ppc405ep_cpc_t { uint32_t srr; uint32_t jtagid; uint32_t pci; + /* Clock and power management */ + uint32_t er; + uint32_t fr; + uint32_t sr; }; static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) @@ -2558,9 +2290,13 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) VCO_out = 0; if ((cpc->pllmr[1] & 0x80000000) && !(cpc->pllmr[1] & 0x40000000)) { M = (((cpc->pllmr[1] >> 20) - 1) & 0xF) + 1; /* FBMUL */ - // printf("FBMUL %01x %d\n", (cpc->pllmr[1] >> 20) & 0xF, M); +#ifdef DEBUG_CLOCKS_LL + printf("FBMUL %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 20) & 0xF, M); +#endif D = 8 - ((cpc->pllmr[1] >> 16) & 0x7); /* FWDA */ - // printf("FWDA %01x %d\n", (cpc->pllmr[1] >> 16) & 0x7, D); +#ifdef DEBUG_CLOCKS_LL + printf("FWDA %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 16) & 0x7, D); +#endif VCO_out = cpc->sysclk * M * D; if (VCO_out < 500000000UL || VCO_out > 1000000000UL) { /* Error - unlock the PLL */ @@ -2571,57 +2307,65 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) #endif } PLL_out = VCO_out / D; + /* Pretend the PLL is locked */ + cpc->boot |= 0x00000001; } else { #if 0 pll_bypass: #endif PLL_out = cpc->sysclk; + if (cpc->pllmr[1] & 0x40000000) { + /* Pretend the PLL is not locked */ + cpc->boot &= ~0x00000001; + } } /* Now, compute all other clocks */ D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */ -#ifdef DEBUG_CLOCKS - // printf("CCDV %01x %d\n", (cpc->pllmr[0] >> 20) & 0x3, D); +#ifdef DEBUG_CLOCKS_LL + printf("CCDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 20) & 0x3, D); #endif CPU_clk = PLL_out / D; D = ((cpc->pllmr[0] >> 16) & 0x3) + 1; /* CBDV */ -#ifdef DEBUG_CLOCKS - // printf("CBDV %01x %d\n", (cpc->pllmr[0] >> 16) & 0x3, D); +#ifdef DEBUG_CLOCKS_LL + printf("CBDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 16) & 0x3, D); #endif PLB_clk = CPU_clk / D; D = ((cpc->pllmr[0] >> 12) & 0x3) + 1; /* OPDV */ -#ifdef DEBUG_CLOCKS - // printf("OPDV %01x %d\n", (cpc->pllmr[0] >> 12) & 0x3, D); +#ifdef DEBUG_CLOCKS_LL + printf("OPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 12) & 0x3, D); #endif OPB_clk = PLB_clk / D; D = ((cpc->pllmr[0] >> 8) & 0x3) + 2; /* EPDV */ -#ifdef DEBUG_CLOCKS - // printf("EPDV %01x %d\n", (cpc->pllmr[0] >> 8) & 0x3, D); +#ifdef DEBUG_CLOCKS_LL + printf("EPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 8) & 0x3, D); #endif EBC_clk = PLB_clk / D; D = ((cpc->pllmr[0] >> 4) & 0x3) + 1; /* MPDV */ -#ifdef DEBUG_CLOCKS - // printf("MPDV %01x %d\n", (cpc->pllmr[0] >> 4) & 0x3, D); +#ifdef DEBUG_CLOCKS_LL + printf("MPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 4) & 0x3, D); #endif MAL_clk = PLB_clk / D; D = (cpc->pllmr[0] & 0x3) + 1; /* PPDV */ -#ifdef DEBUG_CLOCKS - // printf("PPDV %01x %d\n", cpc->pllmr[0] & 0x3, D); +#ifdef DEBUG_CLOCKS_LL + printf("PPDV %01" PRIx32 " %d\n", cpc->pllmr[0] & 0x3, D); #endif PCI_clk = PLB_clk / D; D = ((cpc->ucr - 1) & 0x7F) + 1; /* U0DIV */ -#ifdef DEBUG_CLOCKS - // printf("U0DIV %01x %d\n", cpc->ucr & 0x7F, D); +#ifdef DEBUG_CLOCKS_LL + printf("U0DIV %01" PRIx32 " %d\n", cpc->ucr & 0x7F, D); #endif UART0_clk = PLL_out / D; D = (((cpc->ucr >> 8) - 1) & 0x7F) + 1; /* U1DIV */ -#ifdef DEBUG_CLOCKS - // printf("U1DIV %01x %d\n", (cpc->ucr >> 8) & 0x7F, D); +#ifdef DEBUG_CLOCKS_LL + printf("U1DIV %01" PRIx32 " %d\n", (cpc->ucr >> 8) & 0x7F, D); #endif UART1_clk = PLL_out / D; #ifdef DEBUG_CLOCKS - printf("Setup PPC405EP clocks - sysclk %d VCO %" PRIu64 + printf("Setup PPC405EP clocks - sysclk %" PRIu32 " VCO %" PRIu64 " PLL out %" PRIu64 " Hz\n", cpc->sysclk, VCO_out, PLL_out); - printf("CPU %d PLB %d OPB %d EBC %d MAL %d PCI %d UART0 %d UART1 %d\n", + printf("CPU %" PRIu32 " PLB %" PRIu32 " OPB %" PRIu32 " EBC %" PRIu32 + " MAL %" PRIu32 " PCI %" PRIu32 " UART0 %" PRIu32 + " UART1 %" PRIu32 "\n", CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk, UART0_clk, UART1_clk); #endif @@ -2731,6 +2475,9 @@ static void ppc405ep_cpc_reset (void *opaque) cpc->ucr = 0x00000000; cpc->srr = 0x00040000; cpc->pci = 0x00000000; + cpc->er = 0x00000000; + cpc->fr = 0x00000000; + cpc->sr = 0x00000000; ppc405ep_compute_clocks(cpc); } @@ -2741,48 +2488,55 @@ static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8], ppc405ep_cpc_t *cpc; cpc = qemu_mallocz(sizeof(ppc405ep_cpc_t)); - if (cpc != NULL) { - memcpy(cpc->clk_setup, clk_setup, - PPC405EP_CLK_NB * sizeof(clk_setup_t)); - cpc->jtagid = 0x20267049; - cpc->sysclk = sysclk; - ppc405ep_cpc_reset(cpc); - qemu_register_reset(&ppc405ep_cpc_reset, cpc); - ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_PLLMR1, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_UCR, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_SRR, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_JTAGID, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - } + memcpy(cpc->clk_setup, clk_setup, + PPC405EP_CLK_NB * sizeof(clk_setup_t)); + cpc->jtagid = 0x20267049; + cpc->sysclk = sysclk; + ppc405ep_cpc_reset(cpc); + qemu_register_reset(&ppc405ep_cpc_reset, 0, cpc); + ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc_dcr_register(env, PPC405EP_CPC0_PLLMR1, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc_dcr_register(env, PPC405EP_CPC0_UCR, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc_dcr_register(env, PPC405EP_CPC0_SRR, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc_dcr_register(env, PPC405EP_CPC0_JTAGID, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); +#if 0 + ppc_dcr_register(env, PPC405EP_CPC0_ER, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc_dcr_register(env, PPC405EP_CPC0_FR, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc_dcr_register(env, PPC405EP_CPC0_SR, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); +#endif } -CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], +CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2], + target_phys_addr_t ram_sizes[2], uint32_t sysclk, qemu_irq **picp, - ram_addr_t *offsetp, int do_init) + int do_init) { - clk_setup_t clk_setup[PPC405EP_CLK_NB]; - qemu_irq dma_irqs[4]; + clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup; + qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; CPUState *env; ppc4xx_mmio_t *mmio; qemu_irq *pic, *irqs; - ram_addr_t offset; - int i; memset(clk_setup, 0, sizeof(clk_setup)); /* init CPUs */ - env = ppc405_init("405ep", &clk_setup[PPC405EP_CPU_CLK], - &clk_setup[PPC405EP_PLB_CLK], sysclk); + env = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK], + &tlb_clk_setup, sysclk); + clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb; + clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque; /* Internal devices init */ /* Memory mapped devices registers */ mmio = ppc4xx_mmio_init(env, 0xEF600000); @@ -2795,42 +2549,54 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], /* Universal interrupt controller */ irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); irqs[PPCUIC_OUTPUT_INT] = - ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_INT]; + ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT]; irqs[PPCUIC_OUTPUT_CINT] = - ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_CINT]; + ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT]; pic = ppcuic_init(env, irqs, 0x0C0, 0, 1); *picp = pic; /* SDRAM controller */ - ppc405_sdram_init(env, pic[14], 2, ram_bases, ram_sizes, do_init); - offset = 0; - for (i = 0; i < 2; i++) - offset += ram_sizes[i]; + /* XXX 405EP has no ECC interrupt */ + ppc4xx_sdram_init(env, pic[17], 2, ram_bases, ram_sizes, do_init); /* External bus controller */ ppc405_ebc_init(env); /* DMA controller */ - dma_irqs[0] = pic[26]; - dma_irqs[1] = pic[25]; - dma_irqs[2] = pic[24]; - dma_irqs[3] = pic[23]; + dma_irqs[0] = pic[5]; + dma_irqs[1] = pic[6]; + dma_irqs[2] = pic[7]; + dma_irqs[3] = pic[8]; ppc405_dma_init(env, dma_irqs); /* IIC controller */ - ppc405_i2c_init(env, mmio, 0x500); + ppc405_i2c_init(env, mmio, 0x500, pic[2]); /* GPIO */ ppc405_gpio_init(env, mmio, 0x700); /* Serial ports */ if (serial_hds[0] != NULL) { - ppc405_serial_init(env, mmio, 0x300, pic[31], serial_hds[0]); + ppc405_serial_init(env, mmio, 0x300, pic[0], serial_hds[0]); } if (serial_hds[1] != NULL) { - ppc405_serial_init(env, mmio, 0x400, pic[30], serial_hds[1]); + ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]); } /* OCM */ - ppc405_ocm_init(env, ram_sizes[0] + ram_sizes[1]); - offset += 4096; + ppc405_ocm_init(env); + /* GPT */ + gpt_irqs[0] = pic[19]; + gpt_irqs[1] = pic[20]; + gpt_irqs[2] = pic[21]; + gpt_irqs[3] = pic[22]; + gpt_irqs[4] = pic[23]; + ppc4xx_gpt_init(env, mmio, 0x000, gpt_irqs); /* PCI */ + /* Uses pic[3], pic[16], pic[18] */ + /* MAL */ + mal_irqs[0] = pic[11]; + mal_irqs[1] = pic[12]; + mal_irqs[2] = pic[13]; + mal_irqs[3] = pic[14]; + ppc405_mal_init(env, mal_irqs); + /* Ethernet */ + /* Uses pic[9], pic[15], pic[17] */ /* CPU control */ ppc405ep_cpc_init(env, clk_setup, sysclk); - *offsetp = offset; return env; }