1008ff9d7Sj_mayer /* 2008ff9d7Sj_mayer * QEMU PowerPC 4xx embedded processors shared devices emulation 3008ff9d7Sj_mayer * 4008ff9d7Sj_mayer * Copyright (c) 2007 Jocelyn Mayer 5008ff9d7Sj_mayer * 6008ff9d7Sj_mayer * Permission is hereby granted, free of charge, to any person obtaining a copy 7008ff9d7Sj_mayer * of this software and associated documentation files (the "Software"), to deal 8008ff9d7Sj_mayer * in the Software without restriction, including without limitation the rights 9008ff9d7Sj_mayer * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10008ff9d7Sj_mayer * copies of the Software, and to permit persons to whom the Software is 11008ff9d7Sj_mayer * furnished to do so, subject to the following conditions: 12008ff9d7Sj_mayer * 13008ff9d7Sj_mayer * The above copyright notice and this permission notice shall be included in 14008ff9d7Sj_mayer * all copies or substantial portions of the Software. 15008ff9d7Sj_mayer * 16008ff9d7Sj_mayer * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17008ff9d7Sj_mayer * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18008ff9d7Sj_mayer * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19008ff9d7Sj_mayer * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20008ff9d7Sj_mayer * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21008ff9d7Sj_mayer * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22008ff9d7Sj_mayer * THE SOFTWARE. 23008ff9d7Sj_mayer */ 2471e8a915SMarkus Armbruster 250d75590dSPeter Maydell #include "qemu/osdep.h" 26ab3dd749SPhilippe Mathieu-Daudé #include "qemu/units.h" 2771e8a915SMarkus Armbruster #include "sysemu/reset.h" 2833c11879SPaolo Bonzini #include "cpu.h" 2964552b6bSMarkus Armbruster #include "hw/irq.h" 300d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 310d09e41aSPaolo Bonzini #include "hw/ppc/ppc4xx.h" 3234d0831fSPeter Maydell #include "hw/intc/ppc-uic.h" 3334d0831fSPeter Maydell #include "hw/qdev-properties.h" 341de7afc9SPaolo Bonzini #include "qemu/log.h" 35022c62cbSPaolo Bonzini #include "exec/address-spaces.h" 36ab3dd749SPhilippe Mathieu-Daudé #include "qemu/error-report.h" 3734d0831fSPeter Maydell #include "qapi/error.h" 38b3b5c5d3SCédric Le Goater #include "trace.h" 39d12d51d5Saliguori 40008ff9d7Sj_mayer /*****************************************************************************/ 4161b24405Saurel32 /* SDRAM controller */ 42c227f099SAnthony Liguori typedef struct ppc4xx_sdram_t ppc4xx_sdram_t; 43c227f099SAnthony Liguori struct ppc4xx_sdram_t { 4461b24405Saurel32 uint32_t addr; 4561b24405Saurel32 int nbanks; 46b6dcbe08SAvi Kivity MemoryRegion containers[4]; /* used for clipping */ 47b6dcbe08SAvi Kivity MemoryRegion *ram_memories; 48a8170e5eSAvi Kivity hwaddr ram_bases[4]; 49a8170e5eSAvi Kivity hwaddr ram_sizes[4]; 5061b24405Saurel32 uint32_t besr0; 5161b24405Saurel32 uint32_t besr1; 5261b24405Saurel32 uint32_t bear; 5361b24405Saurel32 uint32_t cfg; 5461b24405Saurel32 uint32_t status; 5561b24405Saurel32 uint32_t rtr; 5661b24405Saurel32 uint32_t pmit; 5761b24405Saurel32 uint32_t bcr[4]; 5861b24405Saurel32 uint32_t tr; 5961b24405Saurel32 uint32_t ecccfg; 6061b24405Saurel32 uint32_t eccesr; 6161b24405Saurel32 qemu_irq irq; 6261b24405Saurel32 }; 6361b24405Saurel32 6461b24405Saurel32 enum { 6561b24405Saurel32 SDRAM0_CFGADDR = 0x010, 6661b24405Saurel32 SDRAM0_CFGDATA = 0x011, 6761b24405Saurel32 }; 6861b24405Saurel32 6961b24405Saurel32 /* XXX: TOFIX: some patches have made this code become inconsistent: 70a8170e5eSAvi Kivity * there are type inconsistencies, mixing hwaddr, target_ulong 7161b24405Saurel32 * and uint32_t 7261b24405Saurel32 */ 73a8170e5eSAvi Kivity static uint32_t sdram_bcr (hwaddr ram_base, 74a8170e5eSAvi Kivity hwaddr ram_size) 7561b24405Saurel32 { 7661b24405Saurel32 uint32_t bcr; 7761b24405Saurel32 7861b24405Saurel32 switch (ram_size) { 79ab3dd749SPhilippe Mathieu-Daudé case 4 * MiB: 8061b24405Saurel32 bcr = 0x00000000; 8161b24405Saurel32 break; 82ab3dd749SPhilippe Mathieu-Daudé case 8 * MiB: 8361b24405Saurel32 bcr = 0x00020000; 8461b24405Saurel32 break; 85ab3dd749SPhilippe Mathieu-Daudé case 16 * MiB: 8661b24405Saurel32 bcr = 0x00040000; 8761b24405Saurel32 break; 88ab3dd749SPhilippe Mathieu-Daudé case 32 * MiB: 8961b24405Saurel32 bcr = 0x00060000; 9061b24405Saurel32 break; 91ab3dd749SPhilippe Mathieu-Daudé case 64 * MiB: 9261b24405Saurel32 bcr = 0x00080000; 9361b24405Saurel32 break; 94ab3dd749SPhilippe Mathieu-Daudé case 128 * MiB: 9561b24405Saurel32 bcr = 0x000A0000; 9661b24405Saurel32 break; 97ab3dd749SPhilippe Mathieu-Daudé case 256 * MiB: 9861b24405Saurel32 bcr = 0x000C0000; 9961b24405Saurel32 break; 10061b24405Saurel32 default: 101b3b5c5d3SCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, 102b3b5c5d3SCédric Le Goater "%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__, 10390e189ecSBlue Swirl ram_size); 10461b24405Saurel32 return 0x00000000; 10561b24405Saurel32 } 10661b24405Saurel32 bcr |= ram_base & 0xFF800000; 10761b24405Saurel32 bcr |= 1; 10861b24405Saurel32 10961b24405Saurel32 return bcr; 11061b24405Saurel32 } 11161b24405Saurel32 112a8170e5eSAvi Kivity static inline hwaddr sdram_base(uint32_t bcr) 11361b24405Saurel32 { 11461b24405Saurel32 return bcr & 0xFF800000; 11561b24405Saurel32 } 11661b24405Saurel32 11761b24405Saurel32 static target_ulong sdram_size (uint32_t bcr) 11861b24405Saurel32 { 11961b24405Saurel32 target_ulong size; 12061b24405Saurel32 int sh; 12161b24405Saurel32 12261b24405Saurel32 sh = (bcr >> 17) & 0x7; 12361b24405Saurel32 if (sh == 7) 12461b24405Saurel32 size = -1; 12561b24405Saurel32 else 126ab3dd749SPhilippe Mathieu-Daudé size = (4 * MiB) << sh; 12761b24405Saurel32 12861b24405Saurel32 return size; 12961b24405Saurel32 } 13061b24405Saurel32 13170812bf7SBALATON Zoltan static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i, 13270812bf7SBALATON Zoltan uint32_t bcr, int enabled) 13361b24405Saurel32 { 13470812bf7SBALATON Zoltan if (sdram->bcr[i] & 0x00000001) { 13561b24405Saurel32 /* Unmap RAM */ 136b3b5c5d3SCédric Le Goater trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]), 137b3b5c5d3SCédric Le Goater sdram_size(sdram->bcr[i])); 138b6dcbe08SAvi Kivity memory_region_del_subregion(get_system_memory(), 13970812bf7SBALATON Zoltan &sdram->containers[i]); 14070812bf7SBALATON Zoltan memory_region_del_subregion(&sdram->containers[i], 14170812bf7SBALATON Zoltan &sdram->ram_memories[i]); 14270812bf7SBALATON Zoltan object_unparent(OBJECT(&sdram->containers[i])); 14361b24405Saurel32 } 14470812bf7SBALATON Zoltan sdram->bcr[i] = bcr & 0xFFDEE001; 14561b24405Saurel32 if (enabled && (bcr & 0x00000001)) { 146b3b5c5d3SCédric Le Goater trace_ppc4xx_sdram_unmap(sdram_base(bcr), sdram_size(bcr)); 14770812bf7SBALATON Zoltan memory_region_init(&sdram->containers[i], NULL, "sdram-containers", 148b6dcbe08SAvi Kivity sdram_size(bcr)); 14970812bf7SBALATON Zoltan memory_region_add_subregion(&sdram->containers[i], 0, 15070812bf7SBALATON Zoltan &sdram->ram_memories[i]); 151b6dcbe08SAvi Kivity memory_region_add_subregion(get_system_memory(), 152b6dcbe08SAvi Kivity sdram_base(bcr), 15370812bf7SBALATON Zoltan &sdram->containers[i]); 15461b24405Saurel32 } 15561b24405Saurel32 } 15661b24405Saurel32 157c227f099SAnthony Liguori static void sdram_map_bcr (ppc4xx_sdram_t *sdram) 15861b24405Saurel32 { 15961b24405Saurel32 int i; 16061b24405Saurel32 16161b24405Saurel32 for (i = 0; i < sdram->nbanks; i++) { 16261b24405Saurel32 if (sdram->ram_sizes[i] != 0) { 16370812bf7SBALATON Zoltan sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i], 16470812bf7SBALATON Zoltan sdram->ram_sizes[i]), 1); 16561b24405Saurel32 } else { 16670812bf7SBALATON Zoltan sdram_set_bcr(sdram, i, 0x00000000, 0); 16761b24405Saurel32 } 16861b24405Saurel32 } 16961b24405Saurel32 } 17061b24405Saurel32 171c227f099SAnthony Liguori static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram) 17261b24405Saurel32 { 17361b24405Saurel32 int i; 17461b24405Saurel32 17561b24405Saurel32 for (i = 0; i < sdram->nbanks; i++) { 176b3b5c5d3SCédric Le Goater trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]), 177b3b5c5d3SCédric Le Goater sdram_size(sdram->bcr[i])); 178b6dcbe08SAvi Kivity memory_region_del_subregion(get_system_memory(), 179b6dcbe08SAvi Kivity &sdram->ram_memories[i]); 18061b24405Saurel32 } 18161b24405Saurel32 } 18261b24405Saurel32 18373b01960SAlexander Graf static uint32_t dcr_read_sdram (void *opaque, int dcrn) 18461b24405Saurel32 { 185c227f099SAnthony Liguori ppc4xx_sdram_t *sdram; 18673b01960SAlexander Graf uint32_t ret; 18761b24405Saurel32 18861b24405Saurel32 sdram = opaque; 18961b24405Saurel32 switch (dcrn) { 19061b24405Saurel32 case SDRAM0_CFGADDR: 19161b24405Saurel32 ret = sdram->addr; 19261b24405Saurel32 break; 19361b24405Saurel32 case SDRAM0_CFGDATA: 19461b24405Saurel32 switch (sdram->addr) { 19561b24405Saurel32 case 0x00: /* SDRAM_BESR0 */ 19661b24405Saurel32 ret = sdram->besr0; 19761b24405Saurel32 break; 19861b24405Saurel32 case 0x08: /* SDRAM_BESR1 */ 19961b24405Saurel32 ret = sdram->besr1; 20061b24405Saurel32 break; 20161b24405Saurel32 case 0x10: /* SDRAM_BEAR */ 20261b24405Saurel32 ret = sdram->bear; 20361b24405Saurel32 break; 20461b24405Saurel32 case 0x20: /* SDRAM_CFG */ 20561b24405Saurel32 ret = sdram->cfg; 20661b24405Saurel32 break; 20761b24405Saurel32 case 0x24: /* SDRAM_STATUS */ 20861b24405Saurel32 ret = sdram->status; 20961b24405Saurel32 break; 21061b24405Saurel32 case 0x30: /* SDRAM_RTR */ 21161b24405Saurel32 ret = sdram->rtr; 21261b24405Saurel32 break; 21361b24405Saurel32 case 0x34: /* SDRAM_PMIT */ 21461b24405Saurel32 ret = sdram->pmit; 21561b24405Saurel32 break; 21661b24405Saurel32 case 0x40: /* SDRAM_B0CR */ 21761b24405Saurel32 ret = sdram->bcr[0]; 21861b24405Saurel32 break; 21961b24405Saurel32 case 0x44: /* SDRAM_B1CR */ 22061b24405Saurel32 ret = sdram->bcr[1]; 22161b24405Saurel32 break; 22261b24405Saurel32 case 0x48: /* SDRAM_B2CR */ 22361b24405Saurel32 ret = sdram->bcr[2]; 22461b24405Saurel32 break; 22561b24405Saurel32 case 0x4C: /* SDRAM_B3CR */ 22661b24405Saurel32 ret = sdram->bcr[3]; 22761b24405Saurel32 break; 22861b24405Saurel32 case 0x80: /* SDRAM_TR */ 22961b24405Saurel32 ret = -1; /* ? */ 23061b24405Saurel32 break; 23161b24405Saurel32 case 0x94: /* SDRAM_ECCCFG */ 23261b24405Saurel32 ret = sdram->ecccfg; 23361b24405Saurel32 break; 23461b24405Saurel32 case 0x98: /* SDRAM_ECCESR */ 23561b24405Saurel32 ret = sdram->eccesr; 23661b24405Saurel32 break; 23761b24405Saurel32 default: /* Error */ 23861b24405Saurel32 ret = -1; 23961b24405Saurel32 break; 24061b24405Saurel32 } 24161b24405Saurel32 break; 24261b24405Saurel32 default: 24361b24405Saurel32 /* Avoid gcc warning */ 24461b24405Saurel32 ret = 0x00000000; 24561b24405Saurel32 break; 24661b24405Saurel32 } 24761b24405Saurel32 24861b24405Saurel32 return ret; 24961b24405Saurel32 } 25061b24405Saurel32 25173b01960SAlexander Graf static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) 25261b24405Saurel32 { 253c227f099SAnthony Liguori ppc4xx_sdram_t *sdram; 25461b24405Saurel32 25561b24405Saurel32 sdram = opaque; 25661b24405Saurel32 switch (dcrn) { 25761b24405Saurel32 case SDRAM0_CFGADDR: 25861b24405Saurel32 sdram->addr = val; 25961b24405Saurel32 break; 26061b24405Saurel32 case SDRAM0_CFGDATA: 26161b24405Saurel32 switch (sdram->addr) { 26261b24405Saurel32 case 0x00: /* SDRAM_BESR0 */ 26361b24405Saurel32 sdram->besr0 &= ~val; 26461b24405Saurel32 break; 26561b24405Saurel32 case 0x08: /* SDRAM_BESR1 */ 26661b24405Saurel32 sdram->besr1 &= ~val; 26761b24405Saurel32 break; 26861b24405Saurel32 case 0x10: /* SDRAM_BEAR */ 26961b24405Saurel32 sdram->bear = val; 27061b24405Saurel32 break; 27161b24405Saurel32 case 0x20: /* SDRAM_CFG */ 27261b24405Saurel32 val &= 0xFFE00000; 27361b24405Saurel32 if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) { 274b3b5c5d3SCédric Le Goater trace_ppc4xx_sdram_enable("enable"); 27561b24405Saurel32 /* validate all RAM mappings */ 27661b24405Saurel32 sdram_map_bcr(sdram); 27761b24405Saurel32 sdram->status &= ~0x80000000; 27861b24405Saurel32 } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) { 279b3b5c5d3SCédric Le Goater trace_ppc4xx_sdram_enable("disable"); 28061b24405Saurel32 /* invalidate all RAM mappings */ 28161b24405Saurel32 sdram_unmap_bcr(sdram); 28261b24405Saurel32 sdram->status |= 0x80000000; 28361b24405Saurel32 } 28461b24405Saurel32 if (!(sdram->cfg & 0x40000000) && (val & 0x40000000)) 28561b24405Saurel32 sdram->status |= 0x40000000; 28661b24405Saurel32 else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000)) 28761b24405Saurel32 sdram->status &= ~0x40000000; 28861b24405Saurel32 sdram->cfg = val; 28961b24405Saurel32 break; 29061b24405Saurel32 case 0x24: /* SDRAM_STATUS */ 29161b24405Saurel32 /* Read-only register */ 29261b24405Saurel32 break; 29361b24405Saurel32 case 0x30: /* SDRAM_RTR */ 29461b24405Saurel32 sdram->rtr = val & 0x3FF80000; 29561b24405Saurel32 break; 29661b24405Saurel32 case 0x34: /* SDRAM_PMIT */ 29761b24405Saurel32 sdram->pmit = (val & 0xF8000000) | 0x07C00000; 29861b24405Saurel32 break; 29961b24405Saurel32 case 0x40: /* SDRAM_B0CR */ 30070812bf7SBALATON Zoltan sdram_set_bcr(sdram, 0, val, sdram->cfg & 0x80000000); 30161b24405Saurel32 break; 30261b24405Saurel32 case 0x44: /* SDRAM_B1CR */ 30370812bf7SBALATON Zoltan sdram_set_bcr(sdram, 1, val, sdram->cfg & 0x80000000); 30461b24405Saurel32 break; 30561b24405Saurel32 case 0x48: /* SDRAM_B2CR */ 30670812bf7SBALATON Zoltan sdram_set_bcr(sdram, 2, val, sdram->cfg & 0x80000000); 30761b24405Saurel32 break; 30861b24405Saurel32 case 0x4C: /* SDRAM_B3CR */ 30970812bf7SBALATON Zoltan sdram_set_bcr(sdram, 3, val, sdram->cfg & 0x80000000); 31061b24405Saurel32 break; 31161b24405Saurel32 case 0x80: /* SDRAM_TR */ 31261b24405Saurel32 sdram->tr = val & 0x018FC01F; 31361b24405Saurel32 break; 31461b24405Saurel32 case 0x94: /* SDRAM_ECCCFG */ 31561b24405Saurel32 sdram->ecccfg = val & 0x00F00000; 31661b24405Saurel32 break; 31761b24405Saurel32 case 0x98: /* SDRAM_ECCESR */ 31861b24405Saurel32 val &= 0xFFF0F000; 31961b24405Saurel32 if (sdram->eccesr == 0 && val != 0) 32061b24405Saurel32 qemu_irq_raise(sdram->irq); 32161b24405Saurel32 else if (sdram->eccesr != 0 && val == 0) 32261b24405Saurel32 qemu_irq_lower(sdram->irq); 32361b24405Saurel32 sdram->eccesr = val; 32461b24405Saurel32 break; 32561b24405Saurel32 default: /* Error */ 32661b24405Saurel32 break; 32761b24405Saurel32 } 32861b24405Saurel32 break; 32961b24405Saurel32 } 33061b24405Saurel32 } 33161b24405Saurel32 33261b24405Saurel32 static void sdram_reset (void *opaque) 33361b24405Saurel32 { 334c227f099SAnthony Liguori ppc4xx_sdram_t *sdram; 33561b24405Saurel32 33661b24405Saurel32 sdram = opaque; 33761b24405Saurel32 sdram->addr = 0x00000000; 33861b24405Saurel32 sdram->bear = 0x00000000; 33961b24405Saurel32 sdram->besr0 = 0x00000000; /* No error */ 34061b24405Saurel32 sdram->besr1 = 0x00000000; /* No error */ 34161b24405Saurel32 sdram->cfg = 0x00000000; 34261b24405Saurel32 sdram->ecccfg = 0x00000000; /* No ECC */ 34361b24405Saurel32 sdram->eccesr = 0x00000000; /* No error */ 34461b24405Saurel32 sdram->pmit = 0x07C00000; 34561b24405Saurel32 sdram->rtr = 0x05F00000; 34661b24405Saurel32 sdram->tr = 0x00854009; 34761b24405Saurel32 /* We pre-initialize RAM banks */ 34861b24405Saurel32 sdram->status = 0x00000000; 34961b24405Saurel32 sdram->cfg = 0x00800000; 35061b24405Saurel32 } 35161b24405Saurel32 352e2684c0bSAndreas Färber void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, 353b6dcbe08SAvi Kivity MemoryRegion *ram_memories, 354a8170e5eSAvi Kivity hwaddr *ram_bases, 355a8170e5eSAvi Kivity hwaddr *ram_sizes, 35661b24405Saurel32 int do_init) 35761b24405Saurel32 { 358c227f099SAnthony Liguori ppc4xx_sdram_t *sdram; 35961b24405Saurel32 360b21e2380SMarkus Armbruster sdram = g_new0(ppc4xx_sdram_t, 1); 36161b24405Saurel32 sdram->irq = irq; 36261b24405Saurel32 sdram->nbanks = nbanks; 363b6dcbe08SAvi Kivity sdram->ram_memories = ram_memories; 364a8170e5eSAvi Kivity memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr)); 36561b24405Saurel32 memcpy(sdram->ram_bases, ram_bases, 366a8170e5eSAvi Kivity nbanks * sizeof(hwaddr)); 367a8170e5eSAvi Kivity memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr)); 36861b24405Saurel32 memcpy(sdram->ram_sizes, ram_sizes, 369a8170e5eSAvi Kivity nbanks * sizeof(hwaddr)); 370a08d4367SJan Kiszka qemu_register_reset(&sdram_reset, sdram); 37161b24405Saurel32 ppc_dcr_register(env, SDRAM0_CFGADDR, 37261b24405Saurel32 sdram, &dcr_read_sdram, &dcr_write_sdram); 37361b24405Saurel32 ppc_dcr_register(env, SDRAM0_CFGDATA, 37461b24405Saurel32 sdram, &dcr_read_sdram, &dcr_write_sdram); 37561b24405Saurel32 if (do_init) 37661b24405Saurel32 sdram_map_bcr(sdram); 37761b24405Saurel32 } 378b7da58fdSaurel32 379b28f0188SIgor Mammedov /* 380b28f0188SIgor Mammedov * Split RAM between SDRAM banks. 381b7da58fdSaurel32 * 382a0258e4aSIgor Mammedov * sdram_bank_sizes[] must be in descending order, that is sizes[i] > sizes[i+1] 383a0258e4aSIgor Mammedov * and must be 0-terminated. 384b7da58fdSaurel32 * 385b7da58fdSaurel32 * The 4xx SDRAM controller supports a small number of banks, and each bank 386b7da58fdSaurel32 * must be one of a small set of sizes. The number of banks and the supported 387b28f0188SIgor Mammedov * sizes varies by SoC. 388b28f0188SIgor Mammedov */ 389b28f0188SIgor Mammedov void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks, 390b6dcbe08SAvi Kivity MemoryRegion ram_memories[], 391a0258e4aSIgor Mammedov hwaddr ram_bases[], hwaddr ram_sizes[], 3927d8ccf58SBALATON Zoltan const ram_addr_t sdram_bank_sizes[]) 393b7da58fdSaurel32 { 394b28f0188SIgor Mammedov ram_addr_t size_left = memory_region_size(ram); 395b6dcbe08SAvi Kivity ram_addr_t base = 0; 3967d8ccf58SBALATON Zoltan ram_addr_t bank_size; 397b7da58fdSaurel32 int i; 398b7da58fdSaurel32 int j; 399b7da58fdSaurel32 400b7da58fdSaurel32 for (i = 0; i < nr_banks; i++) { 401b7da58fdSaurel32 for (j = 0; sdram_bank_sizes[j] != 0; j++) { 402e206ad48SHu Tao bank_size = sdram_bank_sizes[j]; 4035c130f65Spbrook if (bank_size <= size_left) { 404b28f0188SIgor Mammedov char name[32]; 405b28f0188SIgor Mammedov 406a0258e4aSIgor Mammedov ram_bases[i] = base; 407a0258e4aSIgor Mammedov ram_sizes[i] = bank_size; 408a0258e4aSIgor Mammedov base += bank_size; 4095c130f65Spbrook size_left -= bank_size; 410b28f0188SIgor Mammedov snprintf(name, sizeof(name), "ppc4xx.sdram%d", i); 411b28f0188SIgor Mammedov memory_region_init_alias(&ram_memories[i], NULL, name, ram, 412b28f0188SIgor Mammedov ram_bases[i], ram_sizes[i]); 413a0258e4aSIgor Mammedov break; 414b7da58fdSaurel32 } 415b7da58fdSaurel32 } 4165c130f65Spbrook if (!size_left) { 417b7da58fdSaurel32 /* No need to use the remaining banks. */ 418b7da58fdSaurel32 break; 419b7da58fdSaurel32 } 420b7da58fdSaurel32 } 421b7da58fdSaurel32 422e206ad48SHu Tao if (size_left) { 423b28f0188SIgor Mammedov ram_addr_t used_size = memory_region_size(ram) - size_left; 424a0258e4aSIgor Mammedov GString *s = g_string_new(NULL); 425a0258e4aSIgor Mammedov 426a0258e4aSIgor Mammedov for (i = 0; sdram_bank_sizes[i]; i++) { 427a0258e4aSIgor Mammedov g_string_append_printf(s, "%" PRIi64 "%s", 428a0258e4aSIgor Mammedov sdram_bank_sizes[i] / MiB, 429a0258e4aSIgor Mammedov sdram_bank_sizes[i + 1] ? ", " : ""); 430a0258e4aSIgor Mammedov } 4310f1eddf5SMarkus Armbruster error_report("at most %d bank%s of %s MiB each supported", 4320f1eddf5SMarkus Armbruster nr_banks, nr_banks == 1 ? "" : "s", s->str); 4330f1eddf5SMarkus Armbruster error_printf("Possible valid RAM size: %" PRIi64 " MiB \n", 434a0258e4aSIgor Mammedov used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB); 435a0258e4aSIgor Mammedov 436a0258e4aSIgor Mammedov g_string_free(s, true); 437a0258e4aSIgor Mammedov exit(EXIT_FAILURE); 438e206ad48SHu Tao } 439e206ad48SHu Tao } 440517284a7SBALATON Zoltan 441517284a7SBALATON Zoltan /*****************************************************************************/ 442517284a7SBALATON Zoltan /* MAL */ 44304534280SBALATON Zoltan 444517284a7SBALATON Zoltan enum { 445517284a7SBALATON Zoltan MAL0_CFG = 0x180, 446517284a7SBALATON Zoltan MAL0_ESR = 0x181, 447517284a7SBALATON Zoltan MAL0_IER = 0x182, 448517284a7SBALATON Zoltan MAL0_TXCASR = 0x184, 449517284a7SBALATON Zoltan MAL0_TXCARR = 0x185, 450517284a7SBALATON Zoltan MAL0_TXEOBISR = 0x186, 451517284a7SBALATON Zoltan MAL0_TXDEIR = 0x187, 452517284a7SBALATON Zoltan MAL0_RXCASR = 0x190, 453517284a7SBALATON Zoltan MAL0_RXCARR = 0x191, 454517284a7SBALATON Zoltan MAL0_RXEOBISR = 0x192, 455517284a7SBALATON Zoltan MAL0_RXDEIR = 0x193, 456517284a7SBALATON Zoltan MAL0_TXCTP0R = 0x1A0, 457517284a7SBALATON Zoltan MAL0_RXCTP0R = 0x1C0, 458517284a7SBALATON Zoltan MAL0_RCBS0 = 0x1E0, 459517284a7SBALATON Zoltan MAL0_RCBS1 = 0x1E1, 460517284a7SBALATON Zoltan }; 461517284a7SBALATON Zoltan 462da116a8aSCédric Le Goater static void ppc4xx_mal_reset(DeviceState *dev) 46304534280SBALATON Zoltan { 464da116a8aSCédric Le Goater Ppc4xxMalState *mal = PPC4xx_MAL(dev); 46504534280SBALATON Zoltan 46604534280SBALATON Zoltan mal->cfg = 0x0007C000; 46704534280SBALATON Zoltan mal->esr = 0x00000000; 46804534280SBALATON Zoltan mal->ier = 0x00000000; 46904534280SBALATON Zoltan mal->rxcasr = 0x00000000; 47004534280SBALATON Zoltan mal->rxdeir = 0x00000000; 47104534280SBALATON Zoltan mal->rxeobisr = 0x00000000; 47204534280SBALATON Zoltan mal->txcasr = 0x00000000; 47304534280SBALATON Zoltan mal->txdeir = 0x00000000; 47404534280SBALATON Zoltan mal->txeobisr = 0x00000000; 47504534280SBALATON Zoltan } 476517284a7SBALATON Zoltan 477517284a7SBALATON Zoltan static uint32_t dcr_read_mal(void *opaque, int dcrn) 478517284a7SBALATON Zoltan { 479da116a8aSCédric Le Goater Ppc4xxMalState *mal = opaque; 480517284a7SBALATON Zoltan uint32_t ret; 481517284a7SBALATON Zoltan 482517284a7SBALATON Zoltan switch (dcrn) { 483517284a7SBALATON Zoltan case MAL0_CFG: 484517284a7SBALATON Zoltan ret = mal->cfg; 485517284a7SBALATON Zoltan break; 486517284a7SBALATON Zoltan case MAL0_ESR: 487517284a7SBALATON Zoltan ret = mal->esr; 488517284a7SBALATON Zoltan break; 489517284a7SBALATON Zoltan case MAL0_IER: 490517284a7SBALATON Zoltan ret = mal->ier; 491517284a7SBALATON Zoltan break; 492517284a7SBALATON Zoltan case MAL0_TXCASR: 493517284a7SBALATON Zoltan ret = mal->txcasr; 494517284a7SBALATON Zoltan break; 495517284a7SBALATON Zoltan case MAL0_TXCARR: 496517284a7SBALATON Zoltan ret = mal->txcarr; 497517284a7SBALATON Zoltan break; 498517284a7SBALATON Zoltan case MAL0_TXEOBISR: 499517284a7SBALATON Zoltan ret = mal->txeobisr; 500517284a7SBALATON Zoltan break; 501517284a7SBALATON Zoltan case MAL0_TXDEIR: 502517284a7SBALATON Zoltan ret = mal->txdeir; 503517284a7SBALATON Zoltan break; 504517284a7SBALATON Zoltan case MAL0_RXCASR: 505517284a7SBALATON Zoltan ret = mal->rxcasr; 506517284a7SBALATON Zoltan break; 507517284a7SBALATON Zoltan case MAL0_RXCARR: 508517284a7SBALATON Zoltan ret = mal->rxcarr; 509517284a7SBALATON Zoltan break; 510517284a7SBALATON Zoltan case MAL0_RXEOBISR: 511517284a7SBALATON Zoltan ret = mal->rxeobisr; 512517284a7SBALATON Zoltan break; 513517284a7SBALATON Zoltan case MAL0_RXDEIR: 514517284a7SBALATON Zoltan ret = mal->rxdeir; 515517284a7SBALATON Zoltan break; 516517284a7SBALATON Zoltan default: 517517284a7SBALATON Zoltan ret = 0; 518517284a7SBALATON Zoltan break; 519517284a7SBALATON Zoltan } 52004534280SBALATON Zoltan if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) { 52104534280SBALATON Zoltan ret = mal->txctpr[dcrn - MAL0_TXCTP0R]; 52204534280SBALATON Zoltan } 52304534280SBALATON Zoltan if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) { 52404534280SBALATON Zoltan ret = mal->rxctpr[dcrn - MAL0_RXCTP0R]; 52504534280SBALATON Zoltan } 52604534280SBALATON Zoltan if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) { 52704534280SBALATON Zoltan ret = mal->rcbs[dcrn - MAL0_RCBS0]; 52804534280SBALATON Zoltan } 529517284a7SBALATON Zoltan 530517284a7SBALATON Zoltan return ret; 531517284a7SBALATON Zoltan } 532517284a7SBALATON Zoltan 533517284a7SBALATON Zoltan static void dcr_write_mal(void *opaque, int dcrn, uint32_t val) 534517284a7SBALATON Zoltan { 535da116a8aSCédric Le Goater Ppc4xxMalState *mal = opaque; 536517284a7SBALATON Zoltan 537517284a7SBALATON Zoltan switch (dcrn) { 538517284a7SBALATON Zoltan case MAL0_CFG: 539517284a7SBALATON Zoltan if (val & 0x80000000) { 540da116a8aSCédric Le Goater ppc4xx_mal_reset(DEVICE(mal)); 541517284a7SBALATON Zoltan } 542517284a7SBALATON Zoltan mal->cfg = val & 0x00FFC087; 543517284a7SBALATON Zoltan break; 544517284a7SBALATON Zoltan case MAL0_ESR: 545517284a7SBALATON Zoltan /* Read/clear */ 546517284a7SBALATON Zoltan mal->esr &= ~val; 547517284a7SBALATON Zoltan break; 548517284a7SBALATON Zoltan case MAL0_IER: 549517284a7SBALATON Zoltan mal->ier = val & 0x0000001F; 550517284a7SBALATON Zoltan break; 551517284a7SBALATON Zoltan case MAL0_TXCASR: 552517284a7SBALATON Zoltan mal->txcasr = val & 0xF0000000; 553517284a7SBALATON Zoltan break; 554517284a7SBALATON Zoltan case MAL0_TXCARR: 555517284a7SBALATON Zoltan mal->txcarr = val & 0xF0000000; 556517284a7SBALATON Zoltan break; 557517284a7SBALATON Zoltan case MAL0_TXEOBISR: 558517284a7SBALATON Zoltan /* Read/clear */ 559517284a7SBALATON Zoltan mal->txeobisr &= ~val; 560517284a7SBALATON Zoltan break; 561517284a7SBALATON Zoltan case MAL0_TXDEIR: 562517284a7SBALATON Zoltan /* Read/clear */ 563517284a7SBALATON Zoltan mal->txdeir &= ~val; 564517284a7SBALATON Zoltan break; 565517284a7SBALATON Zoltan case MAL0_RXCASR: 566517284a7SBALATON Zoltan mal->rxcasr = val & 0xC0000000; 567517284a7SBALATON Zoltan break; 568517284a7SBALATON Zoltan case MAL0_RXCARR: 569517284a7SBALATON Zoltan mal->rxcarr = val & 0xC0000000; 570517284a7SBALATON Zoltan break; 571517284a7SBALATON Zoltan case MAL0_RXEOBISR: 572517284a7SBALATON Zoltan /* Read/clear */ 573517284a7SBALATON Zoltan mal->rxeobisr &= ~val; 574517284a7SBALATON Zoltan break; 575517284a7SBALATON Zoltan case MAL0_RXDEIR: 576517284a7SBALATON Zoltan /* Read/clear */ 577517284a7SBALATON Zoltan mal->rxdeir &= ~val; 578517284a7SBALATON Zoltan break; 57904534280SBALATON Zoltan } 58004534280SBALATON Zoltan if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) { 58104534280SBALATON Zoltan mal->txctpr[dcrn - MAL0_TXCTP0R] = val; 58204534280SBALATON Zoltan } 58304534280SBALATON Zoltan if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) { 58404534280SBALATON Zoltan mal->rxctpr[dcrn - MAL0_RXCTP0R] = val; 58504534280SBALATON Zoltan } 58604534280SBALATON Zoltan if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) { 58704534280SBALATON Zoltan mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF; 588517284a7SBALATON Zoltan } 589517284a7SBALATON Zoltan } 590517284a7SBALATON Zoltan 591da116a8aSCédric Le Goater static void ppc4xx_mal_realize(DeviceState *dev, Error **errp) 592517284a7SBALATON Zoltan { 593da116a8aSCédric Le Goater Ppc4xxMalState *mal = PPC4xx_MAL(dev); 594da116a8aSCédric Le Goater Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); 595517284a7SBALATON Zoltan int i; 596517284a7SBALATON Zoltan 597da116a8aSCédric Le Goater if (mal->txcnum > 32 || mal->rxcnum > 32) { 598da116a8aSCédric Le Goater error_setg(errp, "invalid TXC/RXC number"); 599da116a8aSCédric Le Goater return; 600517284a7SBALATON Zoltan } 601da116a8aSCédric Le Goater 602da116a8aSCédric Le Goater mal->txctpr = g_new0(uint32_t, mal->txcnum); 603da116a8aSCédric Le Goater mal->rxctpr = g_new0(uint32_t, mal->rxcnum); 604da116a8aSCédric Le Goater mal->rcbs = g_new0(uint32_t, mal->rxcnum); 605da116a8aSCédric Le Goater 606da116a8aSCédric Le Goater for (i = 0; i < ARRAY_SIZE(mal->irqs); i++) { 607da116a8aSCédric Le Goater sysbus_init_irq(SYS_BUS_DEVICE(dev), &mal->irqs[i]); 608da116a8aSCédric Le Goater } 609da116a8aSCédric Le Goater 610da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_CFG, mal, &dcr_read_mal, &dcr_write_mal); 611da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_ESR, mal, &dcr_read_mal, &dcr_write_mal); 612da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_IER, mal, &dcr_read_mal, &dcr_write_mal); 613da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_TXCASR, mal, &dcr_read_mal, &dcr_write_mal); 614da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_TXCARR, mal, &dcr_read_mal, &dcr_write_mal); 615da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_TXEOBISR, mal, &dcr_read_mal, &dcr_write_mal); 616da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_TXDEIR, mal, &dcr_read_mal, &dcr_write_mal); 617da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_RXCASR, mal, &dcr_read_mal, &dcr_write_mal); 618da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_RXCARR, mal, &dcr_read_mal, &dcr_write_mal); 619da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_RXEOBISR, mal, &dcr_read_mal, &dcr_write_mal); 620da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_RXDEIR, mal, &dcr_read_mal, &dcr_write_mal); 621da116a8aSCédric Le Goater for (i = 0; i < mal->txcnum; i++) { 622da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_TXCTP0R + i, 623517284a7SBALATON Zoltan mal, &dcr_read_mal, &dcr_write_mal); 62404534280SBALATON Zoltan } 625da116a8aSCédric Le Goater for (i = 0; i < mal->rxcnum; i++) { 626da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_RXCTP0R + i, 627517284a7SBALATON Zoltan mal, &dcr_read_mal, &dcr_write_mal); 62804534280SBALATON Zoltan } 629da116a8aSCédric Le Goater for (i = 0; i < mal->rxcnum; i++) { 630da116a8aSCédric Le Goater ppc4xx_dcr_register(dcr, MAL0_RCBS0 + i, 631517284a7SBALATON Zoltan mal, &dcr_read_mal, &dcr_write_mal); 63204534280SBALATON Zoltan } 633517284a7SBALATON Zoltan } 634629cae61SCédric Le Goater 635da116a8aSCédric Le Goater static void ppc4xx_mal_finalize(Object *obj) 636da116a8aSCédric Le Goater { 637da116a8aSCédric Le Goater Ppc4xxMalState *mal = PPC4xx_MAL(obj); 638da116a8aSCédric Le Goater 639da116a8aSCédric Le Goater g_free(mal->rcbs); 640da116a8aSCédric Le Goater g_free(mal->rxctpr); 641da116a8aSCédric Le Goater g_free(mal->txctpr); 642da116a8aSCédric Le Goater } 643da116a8aSCédric Le Goater 644da116a8aSCédric Le Goater static Property ppc4xx_mal_properties[] = { 645da116a8aSCédric Le Goater DEFINE_PROP_UINT8("txc-num", Ppc4xxMalState, txcnum, 0), 646da116a8aSCédric Le Goater DEFINE_PROP_UINT8("rxc-num", Ppc4xxMalState, rxcnum, 0), 647da116a8aSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 648da116a8aSCédric Le Goater }; 649da116a8aSCédric Le Goater 650da116a8aSCédric Le Goater static void ppc4xx_mal_class_init(ObjectClass *oc, void *data) 651da116a8aSCédric Le Goater { 652da116a8aSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(oc); 653da116a8aSCédric Le Goater 654da116a8aSCédric Le Goater dc->realize = ppc4xx_mal_realize; 655da116a8aSCédric Le Goater dc->reset = ppc4xx_mal_reset; 656da116a8aSCédric Le Goater /* Reason: only works as function of a ppc4xx SoC */ 657da116a8aSCédric Le Goater dc->user_creatable = false; 658da116a8aSCédric Le Goater device_class_set_props(dc, ppc4xx_mal_properties); 659da116a8aSCédric Le Goater } 660da116a8aSCédric Le Goater 661*2d54aaf1SBALATON Zoltan /*****************************************************************************/ 662*2d54aaf1SBALATON Zoltan /* Peripheral local bus arbitrer */ 663*2d54aaf1SBALATON Zoltan enum { 664*2d54aaf1SBALATON Zoltan PLB3A0_ACR = 0x077, 665*2d54aaf1SBALATON Zoltan PLB4A0_ACR = 0x081, 666*2d54aaf1SBALATON Zoltan PLB0_BESR = 0x084, 667*2d54aaf1SBALATON Zoltan PLB0_BEAR = 0x086, 668*2d54aaf1SBALATON Zoltan PLB0_ACR = 0x087, 669*2d54aaf1SBALATON Zoltan PLB4A1_ACR = 0x089, 670*2d54aaf1SBALATON Zoltan }; 671*2d54aaf1SBALATON Zoltan 672*2d54aaf1SBALATON Zoltan static uint32_t dcr_read_plb(void *opaque, int dcrn) 673*2d54aaf1SBALATON Zoltan { 674*2d54aaf1SBALATON Zoltan Ppc405PlbState *plb = opaque; 675*2d54aaf1SBALATON Zoltan uint32_t ret; 676*2d54aaf1SBALATON Zoltan 677*2d54aaf1SBALATON Zoltan switch (dcrn) { 678*2d54aaf1SBALATON Zoltan case PLB0_ACR: 679*2d54aaf1SBALATON Zoltan ret = plb->acr; 680*2d54aaf1SBALATON Zoltan break; 681*2d54aaf1SBALATON Zoltan case PLB0_BEAR: 682*2d54aaf1SBALATON Zoltan ret = plb->bear; 683*2d54aaf1SBALATON Zoltan break; 684*2d54aaf1SBALATON Zoltan case PLB0_BESR: 685*2d54aaf1SBALATON Zoltan ret = plb->besr; 686*2d54aaf1SBALATON Zoltan break; 687*2d54aaf1SBALATON Zoltan default: 688*2d54aaf1SBALATON Zoltan /* Avoid gcc warning */ 689*2d54aaf1SBALATON Zoltan ret = 0; 690*2d54aaf1SBALATON Zoltan break; 691*2d54aaf1SBALATON Zoltan } 692*2d54aaf1SBALATON Zoltan 693*2d54aaf1SBALATON Zoltan return ret; 694*2d54aaf1SBALATON Zoltan } 695*2d54aaf1SBALATON Zoltan 696*2d54aaf1SBALATON Zoltan static void dcr_write_plb(void *opaque, int dcrn, uint32_t val) 697*2d54aaf1SBALATON Zoltan { 698*2d54aaf1SBALATON Zoltan Ppc405PlbState *plb = opaque; 699*2d54aaf1SBALATON Zoltan 700*2d54aaf1SBALATON Zoltan switch (dcrn) { 701*2d54aaf1SBALATON Zoltan case PLB0_ACR: 702*2d54aaf1SBALATON Zoltan /* 703*2d54aaf1SBALATON Zoltan * We don't care about the actual parameters written as 704*2d54aaf1SBALATON Zoltan * we don't manage any priorities on the bus 705*2d54aaf1SBALATON Zoltan */ 706*2d54aaf1SBALATON Zoltan plb->acr = val & 0xF8000000; 707*2d54aaf1SBALATON Zoltan break; 708*2d54aaf1SBALATON Zoltan case PLB0_BEAR: 709*2d54aaf1SBALATON Zoltan /* Read only */ 710*2d54aaf1SBALATON Zoltan break; 711*2d54aaf1SBALATON Zoltan case PLB0_BESR: 712*2d54aaf1SBALATON Zoltan /* Write-clear */ 713*2d54aaf1SBALATON Zoltan plb->besr &= ~val; 714*2d54aaf1SBALATON Zoltan break; 715*2d54aaf1SBALATON Zoltan } 716*2d54aaf1SBALATON Zoltan } 717*2d54aaf1SBALATON Zoltan 718*2d54aaf1SBALATON Zoltan static void ppc405_plb_reset(DeviceState *dev) 719*2d54aaf1SBALATON Zoltan { 720*2d54aaf1SBALATON Zoltan Ppc405PlbState *plb = PPC405_PLB(dev); 721*2d54aaf1SBALATON Zoltan 722*2d54aaf1SBALATON Zoltan plb->acr = 0x00000000; 723*2d54aaf1SBALATON Zoltan plb->bear = 0x00000000; 724*2d54aaf1SBALATON Zoltan plb->besr = 0x00000000; 725*2d54aaf1SBALATON Zoltan } 726*2d54aaf1SBALATON Zoltan 727*2d54aaf1SBALATON Zoltan static void ppc405_plb_realize(DeviceState *dev, Error **errp) 728*2d54aaf1SBALATON Zoltan { 729*2d54aaf1SBALATON Zoltan Ppc405PlbState *plb = PPC405_PLB(dev); 730*2d54aaf1SBALATON Zoltan Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); 731*2d54aaf1SBALATON Zoltan 732*2d54aaf1SBALATON Zoltan ppc4xx_dcr_register(dcr, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); 733*2d54aaf1SBALATON Zoltan ppc4xx_dcr_register(dcr, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); 734*2d54aaf1SBALATON Zoltan ppc4xx_dcr_register(dcr, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); 735*2d54aaf1SBALATON Zoltan ppc4xx_dcr_register(dcr, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); 736*2d54aaf1SBALATON Zoltan ppc4xx_dcr_register(dcr, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); 737*2d54aaf1SBALATON Zoltan ppc4xx_dcr_register(dcr, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb); 738*2d54aaf1SBALATON Zoltan } 739*2d54aaf1SBALATON Zoltan 740*2d54aaf1SBALATON Zoltan static void ppc405_plb_class_init(ObjectClass *oc, void *data) 741*2d54aaf1SBALATON Zoltan { 742*2d54aaf1SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(oc); 743*2d54aaf1SBALATON Zoltan 744*2d54aaf1SBALATON Zoltan dc->realize = ppc405_plb_realize; 745*2d54aaf1SBALATON Zoltan dc->reset = ppc405_plb_reset; 746*2d54aaf1SBALATON Zoltan /* Reason: only works as function of a ppc4xx SoC */ 747*2d54aaf1SBALATON Zoltan dc->user_creatable = false; 748*2d54aaf1SBALATON Zoltan } 749*2d54aaf1SBALATON Zoltan 750629cae61SCédric Le Goater /* PPC4xx_DCR_DEVICE */ 751629cae61SCédric Le Goater 752629cae61SCédric Le Goater void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque, 753629cae61SCédric Le Goater dcr_read_cb dcr_read, dcr_write_cb dcr_write) 754629cae61SCédric Le Goater { 755629cae61SCédric Le Goater assert(dev->cpu); 756629cae61SCédric Le Goater ppc_dcr_register(&dev->cpu->env, dcrn, opaque, dcr_read, dcr_write); 757629cae61SCédric Le Goater } 758629cae61SCédric Le Goater 759629cae61SCédric Le Goater bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu, 760629cae61SCédric Le Goater Error **errp) 761629cae61SCédric Le Goater { 762629cae61SCédric Le Goater object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); 763629cae61SCédric Le Goater return sysbus_realize(SYS_BUS_DEVICE(dev), errp); 764629cae61SCédric Le Goater } 765629cae61SCédric Le Goater 766629cae61SCédric Le Goater static Property ppc4xx_dcr_properties[] = { 767629cae61SCédric Le Goater DEFINE_PROP_LINK("cpu", Ppc4xxDcrDeviceState, cpu, TYPE_POWERPC_CPU, 768629cae61SCédric Le Goater PowerPCCPU *), 769629cae61SCédric Le Goater DEFINE_PROP_END_OF_LIST(), 770629cae61SCédric Le Goater }; 771629cae61SCédric Le Goater 772629cae61SCédric Le Goater static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data) 773629cae61SCédric Le Goater { 774629cae61SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(oc); 775629cae61SCédric Le Goater 776629cae61SCédric Le Goater device_class_set_props(dc, ppc4xx_dcr_properties); 777629cae61SCédric Le Goater } 778629cae61SCédric Le Goater 779629cae61SCédric Le Goater static const TypeInfo ppc4xx_types[] = { 780629cae61SCédric Le Goater { 781da116a8aSCédric Le Goater .name = TYPE_PPC4xx_MAL, 782da116a8aSCédric Le Goater .parent = TYPE_PPC4xx_DCR_DEVICE, 783da116a8aSCédric Le Goater .instance_size = sizeof(Ppc4xxMalState), 784da116a8aSCédric Le Goater .instance_finalize = ppc4xx_mal_finalize, 785da116a8aSCédric Le Goater .class_init = ppc4xx_mal_class_init, 786da116a8aSCédric Le Goater }, { 787*2d54aaf1SBALATON Zoltan .name = TYPE_PPC405_PLB, 788*2d54aaf1SBALATON Zoltan .parent = TYPE_PPC4xx_DCR_DEVICE, 789*2d54aaf1SBALATON Zoltan .instance_size = sizeof(Ppc405PlbState), 790*2d54aaf1SBALATON Zoltan .class_init = ppc405_plb_class_init, 791*2d54aaf1SBALATON Zoltan }, { 792629cae61SCédric Le Goater .name = TYPE_PPC4xx_DCR_DEVICE, 793629cae61SCédric Le Goater .parent = TYPE_SYS_BUS_DEVICE, 794629cae61SCédric Le Goater .instance_size = sizeof(Ppc4xxDcrDeviceState), 795629cae61SCédric Le Goater .class_init = ppc4xx_dcr_class_init, 796629cae61SCédric Le Goater .abstract = true, 797629cae61SCédric Le Goater } 798629cae61SCédric Le Goater }; 799629cae61SCédric Le Goater 800629cae61SCédric Le Goater DEFINE_TYPES(ppc4xx_types) 801