diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-10-07 14:21:26 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-10-07 14:21:26 +0000 |
commit | 008ff9d756fb8e33e7a799e47d03faac503f8b2e (patch) | |
tree | c1869b18671ac1e4f39f6a73ec2cd4cdcb81248f /hw/ppc405_uc.c | |
parent | 115646b6480b4f3f0fd9f7a66f46c96f68604cc7 (diff) |
Share devices that might be useful for all PowerPC 40x & 440 implementations
(mostly CPU registration and UIC, for now).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3340 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/ppc405_uc.c')
-rw-r--r-- | hw/ppc405_uc.c | 509 |
1 files changed, 2 insertions, 507 deletions
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index 8a31475ed1..55f4bcc3d1 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -27,7 +27,6 @@ extern int loglevel; extern FILE *logfile; -//#define DEBUG_MMIO #define DEBUG_OPBA #define DEBUG_SDRAM #define DEBUG_GPIO @@ -36,41 +35,9 @@ extern FILE *logfile; //#define DEBUG_I2C #define DEBUG_GPT #define DEBUG_MAL -#define DEBUG_UIC #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(); - 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_ppc_reset(env); - 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); - /* Register Qemu callbacks */ - qemu_register_reset(&cpu_ppc_reset, env); - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); - - return env; -} - ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd, uint32_t flags) { @@ -124,203 +91,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 { - target_phys_addr_t base; - CPUReadMemoryFunc **mem_read[MMIO_AREA_NB]; - CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB]; - void *opaque[MMIO_AREA_NB]; -}; - -static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr) -{ -#ifdef DEBUG_UNASSIGNED - ppc4xx_mmio_t *mmio; - - mmio = opaque; - printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n", - addr, mmio->base); -#endif - - return 0; -} - -static void unassigned_mmio_writeb (void *opaque, - target_phys_addr_t addr, uint32_t val) -{ -#ifdef DEBUG_UNASSIGNED - ppc4xx_mmio_t *mmio; - - mmio = opaque; - printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n", - addr, val, mmio->base); -#endif -} - -static CPUReadMemoryFunc *unassigned_mmio_read[3] = { - unassigned_mmio_readb, - unassigned_mmio_readb, - unassigned_mmio_readb, -}; - -static CPUWriteMemoryFunc *unassigned_mmio_write[3] = { - unassigned_mmio_writeb, - unassigned_mmio_writeb, - unassigned_mmio_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 - mmio->base); - - 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 - mmio->base, 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, - target_phys_addr_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, target_phys_addr_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_mmio_read, unassigned_mmio_write, - mmio); - } - - return mmio; -} - -/*****************************************************************************/ /* Peripheral local bus arbitrer */ enum { PLB0_BESR = 0x084, @@ -625,281 +395,6 @@ void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, } /*****************************************************************************/ -/* "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); - } -#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); -} - -/*****************************************************************************/ /* Code decompression controller */ /* XXX: TODO */ @@ -3040,7 +2535,7 @@ CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4], 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); @@ -3390,7 +2885,7 @@ CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2], memset(clk_setup, 0, sizeof(clk_setup)); /* init CPUs */ - env = ppc405_init("405ep", &clk_setup[PPC405EP_CPU_CLK], + 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; |