1*a8fb0a50SBin Meng /* 2*a8fb0a50SBin Meng * Microchip PolarFire SoC MMUART emulation 3*a8fb0a50SBin Meng * 4*a8fb0a50SBin Meng * Copyright (c) 2020 Wind River Systems, Inc. 5*a8fb0a50SBin Meng * 6*a8fb0a50SBin Meng * Author: 7*a8fb0a50SBin Meng * Bin Meng <bin.meng@windriver.com> 8*a8fb0a50SBin Meng * 9*a8fb0a50SBin Meng * This program is free software; you can redistribute it and/or 10*a8fb0a50SBin Meng * modify it under the terms of the GNU General Public License as 11*a8fb0a50SBin Meng * published by the Free Software Foundation; either version 2 or 12*a8fb0a50SBin Meng * (at your option) version 3 of the License. 13*a8fb0a50SBin Meng * 14*a8fb0a50SBin Meng * This program is distributed in the hope that it will be useful, 15*a8fb0a50SBin Meng * but WITHOUT ANY WARRANTY; without even the implied warranty of 16*a8fb0a50SBin Meng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*a8fb0a50SBin Meng * GNU General Public License for more details. 18*a8fb0a50SBin Meng * 19*a8fb0a50SBin Meng * You should have received a copy of the GNU General Public License along 20*a8fb0a50SBin Meng * with this program; if not, see <http://www.gnu.org/licenses/>. 21*a8fb0a50SBin Meng */ 22*a8fb0a50SBin Meng 23*a8fb0a50SBin Meng #include "qemu/osdep.h" 24*a8fb0a50SBin Meng #include "qemu/log.h" 25*a8fb0a50SBin Meng #include "chardev/char.h" 26*a8fb0a50SBin Meng #include "exec/address-spaces.h" 27*a8fb0a50SBin Meng #include "hw/char/mchp_pfsoc_mmuart.h" 28*a8fb0a50SBin Meng 29*a8fb0a50SBin Meng static uint64_t mchp_pfsoc_mmuart_read(void *opaque, hwaddr addr, unsigned size) 30*a8fb0a50SBin Meng { 31*a8fb0a50SBin Meng MchpPfSoCMMUartState *s = opaque; 32*a8fb0a50SBin Meng 33*a8fb0a50SBin Meng if (addr >= MCHP_PFSOC_MMUART_REG_SIZE) { 34*a8fb0a50SBin Meng qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n", 35*a8fb0a50SBin Meng __func__, addr); 36*a8fb0a50SBin Meng return 0; 37*a8fb0a50SBin Meng } 38*a8fb0a50SBin Meng 39*a8fb0a50SBin Meng return s->reg[addr / sizeof(uint32_t)]; 40*a8fb0a50SBin Meng } 41*a8fb0a50SBin Meng 42*a8fb0a50SBin Meng static void mchp_pfsoc_mmuart_write(void *opaque, hwaddr addr, 43*a8fb0a50SBin Meng uint64_t value, unsigned size) 44*a8fb0a50SBin Meng { 45*a8fb0a50SBin Meng MchpPfSoCMMUartState *s = opaque; 46*a8fb0a50SBin Meng uint32_t val32 = (uint32_t)value; 47*a8fb0a50SBin Meng 48*a8fb0a50SBin Meng if (addr >= MCHP_PFSOC_MMUART_REG_SIZE) { 49*a8fb0a50SBin Meng qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx 50*a8fb0a50SBin Meng " v=0x%x\n", __func__, addr, val32); 51*a8fb0a50SBin Meng return; 52*a8fb0a50SBin Meng } 53*a8fb0a50SBin Meng 54*a8fb0a50SBin Meng s->reg[addr / sizeof(uint32_t)] = val32; 55*a8fb0a50SBin Meng } 56*a8fb0a50SBin Meng 57*a8fb0a50SBin Meng static const MemoryRegionOps mchp_pfsoc_mmuart_ops = { 58*a8fb0a50SBin Meng .read = mchp_pfsoc_mmuart_read, 59*a8fb0a50SBin Meng .write = mchp_pfsoc_mmuart_write, 60*a8fb0a50SBin Meng .endianness = DEVICE_LITTLE_ENDIAN, 61*a8fb0a50SBin Meng .impl = { 62*a8fb0a50SBin Meng .min_access_size = 4, 63*a8fb0a50SBin Meng .max_access_size = 4, 64*a8fb0a50SBin Meng }, 65*a8fb0a50SBin Meng }; 66*a8fb0a50SBin Meng 67*a8fb0a50SBin Meng MchpPfSoCMMUartState *mchp_pfsoc_mmuart_create(MemoryRegion *sysmem, 68*a8fb0a50SBin Meng hwaddr base, qemu_irq irq, Chardev *chr) 69*a8fb0a50SBin Meng { 70*a8fb0a50SBin Meng MchpPfSoCMMUartState *s; 71*a8fb0a50SBin Meng 72*a8fb0a50SBin Meng s = g_new0(MchpPfSoCMMUartState, 1); 73*a8fb0a50SBin Meng 74*a8fb0a50SBin Meng memory_region_init_io(&s->iomem, NULL, &mchp_pfsoc_mmuart_ops, s, 75*a8fb0a50SBin Meng "mchp.pfsoc.mmuart", 0x1000); 76*a8fb0a50SBin Meng 77*a8fb0a50SBin Meng s->base = base; 78*a8fb0a50SBin Meng s->irq = irq; 79*a8fb0a50SBin Meng 80*a8fb0a50SBin Meng s->serial = serial_mm_init(sysmem, base, 2, irq, 399193, chr, 81*a8fb0a50SBin Meng DEVICE_LITTLE_ENDIAN); 82*a8fb0a50SBin Meng 83*a8fb0a50SBin Meng memory_region_add_subregion(sysmem, base + 0x20, &s->iomem); 84*a8fb0a50SBin Meng 85*a8fb0a50SBin Meng return s; 86*a8fb0a50SBin Meng } 87