From 04f20795ac815cf3ad5d1fdc99462f60eb871f25 Mon Sep 17 00:00:00 2001 From: j_mayer Date: Tue, 17 Apr 2007 02:50:56 +0000 Subject: Move PowerPC 405 specific definitions into a separate file Preliminary code for -kernel option support for PowerPC 405 boards Fix DBSR in case of PowerPC 405 chip reset Add enums for PowerPC 405 clocks. Fix IRQ numbers (IBM reversed bits numbering...) Fix SPRG4-7 read access right Fix MSR mask in CPU definitions git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2692 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/ppc405.h | 117 +++++++++++++++++++++++++++++++++++++++++ hw/ppc405_uc.c | 162 ++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 238 insertions(+), 41 deletions(-) create mode 100644 hw/ppc405.h (limited to 'hw') diff --git a/hw/ppc405.h b/hw/ppc405.h new file mode 100644 index 0000000..e3a544d --- /dev/null +++ b/hw/ppc405.h @@ -0,0 +1,117 @@ +/* + * QEMU PowerPC 405 shared definitions + * + * 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined(PPC_405_H) +#define PPC_405_H + +/* Bootinfo as set-up by u-boot */ +typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t; +struct ppc4xx_bd_info_t { + uint32_t bi_memstart; + uint32_t bi_memsize; + uint32_t bi_flashstart; + uint32_t bi_flashsize; + uint32_t bi_flashoffset; /* 0x10 */ + uint32_t bi_sramstart; + uint32_t bi_sramsize; + uint32_t bi_bootflags; + uint32_t bi_ipaddr; /* 0x20 */ + uint8_t bi_enetaddr[6]; + uint16_t bi_ethspeed; + uint32_t bi_intfreq; + uint32_t bi_busfreq; /* 0x30 */ + uint32_t bi_baudrate; + uint8_t bi_s_version[4]; + uint8_t bi_r_version[32]; + uint32_t bi_procfreq; + uint32_t bi_plb_busfreq; + uint32_t bi_pci_busfreq; + uint8_t bi_pci_enetaddr[6]; + uint32_t bi_pci_enetaddr2[6]; + uint32_t bi_opbfreq; + uint32_t bi_iic_fast[2]; +}; + +/* PowerPC 405 core */ +CPUState *ppc405_init (const unsigned char *cpu_model, + clk_setup_t *cpu_clk, clk_setup_t *tb_clk, + uint32_t sysclk); +ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd); + +void ppc40x_core_reset (CPUState *env); +void ppc40x_chip_reset (CPUState *env); +void ppc40x_system_reset (CPUState *env); +/* */ +typedef struct ppc4xx_mmio_t ppc4xx_mmio_t; +int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio, + uint32_t offset, uint32_t len, + CPUReadMemoryFunc **mem_read, + CPUWriteMemoryFunc **mem_write, void *opaque); +ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, uint32_t base); +/* PowerPC 4xx peripheral local bus arbitrer */ +void ppc4xx_plb_init (CPUState *env); +/* PLB to OPB bridge */ +void ppc4xx_pob_init (CPUState *env); +/* OPB arbitrer */ +void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset); +/* PowerPC 4xx universal interrupt controller */ +enum { + PPCUIC_OUTPUT_INT = 0, + PPCUIC_OUTPUT_CINT = 1, + PPCUIC_OUTPUT_NB, +}; +qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs, + uint32_t dcr_base, int has_ssr, int has_vr); +/* SDRAM controller */ +void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks, + target_ulong *ram_bases, target_ulong *ram_sizes, + int do_init); +/* Peripheral controller */ +void ppc405_ebc_init (CPUState *env); +/* DMA controller */ +void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]); +/* GPIO */ +void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset); +/* Serial ports */ +void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio, + uint32_t offset, qemu_irq irq, + CharDriverState *chr); +/* On Chip Memory */ +void ppc405_ocm_init (CPUState *env, unsigned long offset); +/* I2C controller */ +void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, uint32_t offset); +/* PowerPC 405 microcontrollers */ +CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], + uint32_t sysclk, qemu_irq **picp, + ram_addr_t *offsetp, int do_init); +CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], + uint32_t sysclk, qemu_irq **picp, + ram_addr_t *offsetp, int do_init); +/* IBM STBxxx microcontrollers */ +CPUState *ppc_stb025_init (target_ulong ram_bases[2], + target_ulong ram_sizes[2], + uint32_t sysclk, qemu_irq **picp, + ram_addr_t *offsetp); + +#endif /* !defined(PPC_405_H) */ diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index 0b7ef12..f5c1c31 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ #include "vl.h" +#include "ppc405.h" extern int loglevel; extern FILE *logfile; @@ -66,6 +67,51 @@ CPUState *ppc405_init (const unsigned char *cpu_model, return env; } +ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd) +{ + 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); + 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); + for (i = 0; i < 4; i++) + stb_raw(phys_ram_base + 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); + for (i = 0; i < 6; i++) + stb_raw(phys_ram_base + bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]); + n = 0x6A; + if (env->spr[SPR_PVR] == CPU_PPC_405EP) { + for (i = 0; i < 6; i++) + stb_raw(phys_ram_base + bdloc + n++, bd->bi_pci_enetaddr2[i]); + } + stl_raw(phys_ram_base + 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]); + n += 4; + } + + return bdloc; +} + /*****************************************************************************/ /* Shared peripherals */ @@ -960,6 +1006,10 @@ 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); @@ -1141,7 +1191,8 @@ static void sdram_reset (void *opaque) } void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks, - target_ulong *ram_bases, target_ulong *ram_sizes) + target_ulong *ram_bases, target_ulong *ram_sizes, + int do_init) { ppc4xx_sdram_t *sdram; @@ -1159,6 +1210,8 @@ void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks, 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); } } @@ -2079,7 +2132,7 @@ void ppc40x_chip_reset (CPUState *env) /* XXX: TODO reset all internal peripherals */ dbsr = env->spr[SPR_40x_DBSR]; dbsr &= ~0x00000300; - dbsr |= 0x00000100; + dbsr |= 0x00000200; env->spr[SPR_40x_DBSR] = dbsr; cpu_loop_exit(); } @@ -2124,9 +2177,20 @@ enum { PPC405CR_CPC0_SR = 0x0BB, }; +enum { + PPC405CR_CPU_CLK = 0, + PPC405CR_TMR_CLK = 1, + PPC405CR_PLB_CLK = 2, + PPC405CR_SDRAM_CLK = 3, + PPC405CR_OPB_CLK = 4, + PPC405CR_EXT_CLK = 5, + PPC405CR_UART_CLK = 6, + PPC405CR_CLK_NB = 7, +}; + typedef struct ppc405cr_cpc_t ppc405cr_cpc_t; struct ppc405cr_cpc_t { - clk_setup_t clk_setup[7]; + clk_setup_t clk_setup[PPC405CR_CLK_NB]; uint32_t sysclk; uint32_t psr; uint32_t cr0; @@ -2175,19 +2239,19 @@ static void ppc405cr_clk_setup (ppc405cr_cpc_t *cpc) D0 = ((cpc->cr0 >> 1) & 0x1F) + 1; UART_clk = CPU_clk / D0; /* Setup CPU clocks */ - clk_setup(&cpc->clk_setup[0], CPU_clk); + clk_setup(&cpc->clk_setup[PPC405CR_CPU_CLK], CPU_clk); /* Setup time-base clock */ - clk_setup(&cpc->clk_setup[1], TMR_clk); + clk_setup(&cpc->clk_setup[PPC405CR_TMR_CLK], TMR_clk); /* Setup PLB clock */ - clk_setup(&cpc->clk_setup[2], PLB_clk); + clk_setup(&cpc->clk_setup[PPC405CR_PLB_CLK], PLB_clk); /* Setup SDRAM clock */ - clk_setup(&cpc->clk_setup[3], SDRAM_clk); + clk_setup(&cpc->clk_setup[PPC405CR_SDRAM_CLK], SDRAM_clk); /* Setup OPB clock */ - clk_setup(&cpc->clk_setup[4], OPB_clk); + clk_setup(&cpc->clk_setup[PPC405CR_OPB_CLK], OPB_clk); /* Setup external clock */ - clk_setup(&cpc->clk_setup[5], EXT_clk); + clk_setup(&cpc->clk_setup[PPC405CR_EXT_CLK], EXT_clk); /* Setup UART clock */ - clk_setup(&cpc->clk_setup[6], UART_clk); + clk_setup(&cpc->clk_setup[PPC405CR_UART_CLK], UART_clk); } static target_ulong dcr_read_crcpc (void *opaque, int dcrn) @@ -2357,7 +2421,8 @@ static void ppc405cr_cpc_init (CPUState *env, clk_setup_t clk_setup[7], cpc = qemu_mallocz(sizeof(ppc405cr_cpc_t)); if (cpc != NULL) { - memcpy(cpc->clk_setup, clk_setup, 7 * sizeof(clk_setup_t)); + 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, @@ -2384,9 +2449,9 @@ static void ppc405cr_cpc_init (CPUState *env, clk_setup_t clk_setup[7], CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], uint32_t sysclk, qemu_irq **picp, - ram_addr_t *offsetp) + ram_addr_t *offsetp, int do_init) { - clk_setup_t clk_setup[7]; + clk_setup_t clk_setup[PPC405CR_CLK_NB]; qemu_irq dma_irqs[4]; CPUState *env; ppc4xx_mmio_t *mmio; @@ -2395,7 +2460,8 @@ CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], int i; memset(clk_setup, 0, sizeof(clk_setup)); - env = ppc405_init("405cr", &clk_setup[0], &clk_setup[1], sysclk); + env = ppc405_init("405cr", &clk_setup[PPC405CR_CPU_CLK], + &clk_setup[PPC405CR_TMR_CLK], sysclk); /* Memory mapped devices registers */ mmio = ppc4xx_mmio_init(env, 0xEF600000); /* PLB arbitrer */ @@ -2413,24 +2479,24 @@ CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4], pic = ppcuic_init(env, irqs, 0x0C0, 0, 1); *picp = pic; /* SDRAM controller */ - ppc405_sdram_init(env, pic[17], 1, ram_bases, ram_sizes); + 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]; /* External bus controller */ ppc405_ebc_init(env); /* DMA controller */ - dma_irqs[0] = pic[5]; - dma_irqs[1] = pic[6]; - dma_irqs[2] = pic[7]; - dma_irqs[3] = pic[8]; + dma_irqs[0] = pic[26]; + dma_irqs[1] = pic[25]; + dma_irqs[2] = pic[24]; + dma_irqs[3] = pic[23]; ppc405_dma_init(env, dma_irqs); /* Serial ports */ if (serial_hds[0] != NULL) { - ppc405_serial_init(env, mmio, 0x400, pic[0], serial_hds[0]); + ppc405_serial_init(env, mmio, 0x300, pic[31], serial_hds[0]); } if (serial_hds[1] != NULL) { - ppc405_serial_init(env, mmio, 0x300, pic[1], serial_hds[1]); + ppc405_serial_init(env, mmio, 0x400, pic[30], serial_hds[1]); } /* IIC controller */ ppc405_i2c_init(env, mmio, 0x500); @@ -2457,10 +2523,22 @@ enum { PPC405EP_CPC0_PCI = 0x0F9, }; +enum { + PPC405EP_CPU_CLK = 0, + PPC405EP_PLB_CLK = 1, + PPC405EP_OPB_CLK = 2, + PPC405EP_EBC_CLK = 3, + PPC405EP_MAL_CLK = 4, + PPC405EP_PCI_CLK = 5, + PPC405EP_UART0_CLK = 6, + PPC405EP_UART1_CLK = 7, + PPC405EP_CLK_NB = 8, +}; + typedef struct ppc405ep_cpc_t ppc405ep_cpc_t; struct ppc405ep_cpc_t { uint32_t sysclk; - clk_setup_t clk_setup[8]; + clk_setup_t clk_setup[PPC405EP_CLK_NB]; uint32_t boot; uint32_t epctl; uint32_t pllmr[2]; @@ -2548,21 +2626,21 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) UART0_clk, UART1_clk); #endif /* Setup CPU clocks */ - clk_setup(&cpc->clk_setup[0], CPU_clk); + clk_setup(&cpc->clk_setup[PPC405EP_CPU_CLK], CPU_clk); /* Setup PLB clock */ - clk_setup(&cpc->clk_setup[1], PLB_clk); + clk_setup(&cpc->clk_setup[PPC405EP_PLB_CLK], PLB_clk); /* Setup OPB clock */ - clk_setup(&cpc->clk_setup[2], OPB_clk); + clk_setup(&cpc->clk_setup[PPC405EP_OPB_CLK], OPB_clk); /* Setup external clock */ - clk_setup(&cpc->clk_setup[3], EBC_clk); + clk_setup(&cpc->clk_setup[PPC405EP_EBC_CLK], EBC_clk); /* Setup MAL clock */ - clk_setup(&cpc->clk_setup[4], MAL_clk); + clk_setup(&cpc->clk_setup[PPC405EP_MAL_CLK], MAL_clk); /* Setup PCI clock */ - clk_setup(&cpc->clk_setup[5], PCI_clk); + clk_setup(&cpc->clk_setup[PPC405EP_PCI_CLK], PCI_clk); /* Setup UART0 clock */ - clk_setup(&cpc->clk_setup[6], UART0_clk); + clk_setup(&cpc->clk_setup[PPC405EP_UART0_CLK], UART0_clk); /* Setup UART1 clock */ - clk_setup(&cpc->clk_setup[7], UART0_clk); + clk_setup(&cpc->clk_setup[PPC405EP_UART1_CLK], UART1_clk); } static target_ulong dcr_read_epcpc (void *opaque, int dcrn) @@ -2664,7 +2742,8 @@ static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8], cpc = qemu_mallocz(sizeof(ppc405ep_cpc_t)); if (cpc != NULL) { - memcpy(cpc->clk_setup, clk_setup, 7 * sizeof(clk_setup_t)); + memcpy(cpc->clk_setup, clk_setup, + PPC405EP_CLK_NB * sizeof(clk_setup_t)); cpc->jtagid = 0x20267049; cpc->sysclk = sysclk; ppc405ep_cpc_reset(cpc); @@ -2690,9 +2769,9 @@ static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8], CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], uint32_t sysclk, qemu_irq **picp, - ram_addr_t *offsetp) + ram_addr_t *offsetp, int do_init) { - clk_setup_t clk_setup[8]; + clk_setup_t clk_setup[PPC405EP_CLK_NB]; qemu_irq dma_irqs[4]; CPUState *env; ppc4xx_mmio_t *mmio; @@ -2702,7 +2781,8 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], memset(clk_setup, 0, sizeof(clk_setup)); /* init CPUs */ - env = ppc405_init("405ep", &clk_setup[0], &clk_setup[1], sysclk); + env = ppc405_init("405ep", &clk_setup[PPC405EP_CPU_CLK], + &clk_setup[PPC405EP_PLB_CLK], sysclk); /* Internal devices init */ /* Memory mapped devices registers */ mmio = ppc4xx_mmio_init(env, 0xEF600000); @@ -2721,17 +2801,17 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], pic = ppcuic_init(env, irqs, 0x0C0, 0, 1); *picp = pic; /* SDRAM controller */ - ppc405_sdram_init(env, pic[17], 2, ram_bases, ram_sizes); + 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]; /* External bus controller */ ppc405_ebc_init(env); /* DMA controller */ - dma_irqs[0] = pic[5]; - dma_irqs[1] = pic[6]; - dma_irqs[2] = pic[7]; - dma_irqs[3] = pic[8]; + dma_irqs[0] = pic[26]; + dma_irqs[1] = pic[25]; + dma_irqs[2] = pic[24]; + dma_irqs[3] = pic[23]; ppc405_dma_init(env, dma_irqs); /* IIC controller */ ppc405_i2c_init(env, mmio, 0x500); @@ -2739,10 +2819,10 @@ CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2], ppc405_gpio_init(env, mmio, 0x700); /* Serial ports */ if (serial_hds[0] != NULL) { - ppc405_serial_init(env, mmio, 0x300, pic[0], serial_hds[0]); + ppc405_serial_init(env, mmio, 0x300, pic[31], serial_hds[0]); } if (serial_hds[1] != NULL) { - ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]); + ppc405_serial_init(env, mmio, 0x400, pic[30], serial_hds[1]); } /* OCM */ ppc405_ocm_init(env, ram_sizes[0] + ram_sizes[1]); -- cgit v1.1