Message ID | 20250206013105.3228344-10-wuhaotsh@google.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | hw/arm: Add NPCM8XX Support | expand |
On 6/2/25 02:30, Hao Wu wrote: > The NPCM8xx GCR device can be accessed with 64-bit memory operations. > This patch supports that. > > Reviewed-by: Peter Maydell <peter.maydell@linaro.org> > Signed-off-by: Hao Wu <wuhaotsh@google.com> > --- > hw/misc/npcm_gcr.c | 94 +++++++++++++++++++++++++++++++++----------- > hw/misc/trace-events | 4 +- > 2 files changed, 74 insertions(+), 24 deletions(-) > > diff --git a/hw/misc/npcm_gcr.c b/hw/misc/npcm_gcr.c > index 820b730606..654e048048 100644 > --- a/hw/misc/npcm_gcr.c > +++ b/hw/misc/npcm_gcr.c > @@ -201,6 +201,7 @@ static uint64_t npcm_gcr_read(void *opaque, hwaddr offset, unsigned size) > uint32_t reg = offset / sizeof(uint32_t); > NPCMGCRState *s = opaque; > NPCMGCRClass *c = NPCM_GCR_GET_CLASS(s); > + uint64_t value; > > if (reg >= c->nr_regs) { > qemu_log_mask(LOG_GUEST_ERROR, > @@ -209,9 +210,21 @@ static uint64_t npcm_gcr_read(void *opaque, hwaddr offset, unsigned size) > return 0; > } > > - trace_npcm_gcr_read(offset, s->regs[reg]); > + switch (size) { > + case 4: > + value = s->regs[reg]; > + break; > + > + case 8: Should we assert(!(reg & 1)) in case someone want to enable unaligned accesses? > + value = deposit64(s->regs[reg], 32, 32, s->regs[reg + 1]); > + break; > + > + default: > + g_assert_not_reached(); > + } > > - return s->regs[reg]; > + trace_npcm_gcr_read(offset, value); > + return value; > } > > static void npcm_gcr_write(void *opaque, hwaddr offset, > @@ -231,29 +244,65 @@ static void npcm_gcr_write(void *opaque, hwaddr offset, > return; > } > > - switch (reg) { > - case NPCM7XX_GCR_PDID: > - case NPCM7XX_GCR_PWRON: > - case NPCM7XX_GCR_INTSR: > - qemu_log_mask(LOG_GUEST_ERROR, > - "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n", > - __func__, offset); > - return; > - > - case NPCM7XX_GCR_RESSR: > - case NPCM7XX_GCR_CP2BST: > - /* Write 1 to clear */ > - value = s->regs[reg] & ~value; > + switch (size) { > + case 4: > + switch (reg) { > + case NPCM7XX_GCR_PDID: > + case NPCM7XX_GCR_PWRON: > + case NPCM7XX_GCR_INTSR: > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n", > + __func__, offset); > + return; > + > + case NPCM7XX_GCR_RESSR: > + case NPCM7XX_GCR_CP2BST: > + /* Write 1 to clear */ > + value = s->regs[reg] & ~value; > + break; > + > + case NPCM7XX_GCR_RLOCKR1: > + case NPCM7XX_GCR_MDLR: > + /* Write 1 to set */ > + value |= s->regs[reg]; > + break; > + }; > + s->regs[reg] = value; > break; > > - case NPCM7XX_GCR_RLOCKR1: > - case NPCM7XX_GCR_MDLR: > - /* Write 1 to set */ > - value |= s->regs[reg]; > + case 8: Ditto. > + s->regs[reg] = value; > + s->regs[reg + 1] = extract64(v, 32, 32); > break; > - }; > > - s->regs[reg] = value; > + default: > + g_assert_not_reached(); > + } > +} > + > +static bool npcm_gcr_check_mem_op(void *opaque, hwaddr offset, > + unsigned size, bool is_write, > + MemTxAttrs attrs) > +{ > + NPCMGCRClass *c = NPCM_GCR_GET_CLASS(opaque); > + > + if (offset >= c->nr_regs * sizeof(uint32_t)) { > + return false; > + } > + > + switch (size) { > + case 4: > + return true; > + case 8: > + if (offset >= NPCM8XX_GCR_SCRPAD_00 * sizeof(uint32_t) && > + offset < (NPCM8XX_GCR_NR_REGS - 1) * sizeof(uint32_t)) { > + return true; > + } else { > + return false; > + } > + default: > + return false; > + } > } > > static const struct MemoryRegionOps npcm_gcr_ops = { > @@ -262,7 +311,8 @@ static const struct MemoryRegionOps npcm_gcr_ops = { > .endianness = DEVICE_LITTLE_ENDIAN, > .valid = { > .min_access_size = 4, > - .max_access_size = 4, > + .max_access_size = 8, > + .accepts = npcm_gcr_check_mem_op, > .unaligned = false, > }, > }; > diff --git a/hw/misc/trace-events b/hw/misc/trace-events > index 0f7204a237..f25dbd6030 100644 > --- a/hw/misc/trace-events > +++ b/hw/misc/trace-events > @@ -135,8 +135,8 @@ npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " valu > npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 > > # npcm_gcr.c > -npcm_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 > -npcm_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 > +npcm_gcr_read(uint64_t offset, uint64_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx64 > +npcm_gcr_write(uint64_t offset, uint64_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx64 > > # npcm7xx_mft.c > npcm7xx_mft_read(const char *name, uint64_t offset, uint16_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
diff --git a/hw/misc/npcm_gcr.c b/hw/misc/npcm_gcr.c index 820b730606..654e048048 100644 --- a/hw/misc/npcm_gcr.c +++ b/hw/misc/npcm_gcr.c @@ -201,6 +201,7 @@ static uint64_t npcm_gcr_read(void *opaque, hwaddr offset, unsigned size) uint32_t reg = offset / sizeof(uint32_t); NPCMGCRState *s = opaque; NPCMGCRClass *c = NPCM_GCR_GET_CLASS(s); + uint64_t value; if (reg >= c->nr_regs) { qemu_log_mask(LOG_GUEST_ERROR, @@ -209,9 +210,21 @@ static uint64_t npcm_gcr_read(void *opaque, hwaddr offset, unsigned size) return 0; } - trace_npcm_gcr_read(offset, s->regs[reg]); + switch (size) { + case 4: + value = s->regs[reg]; + break; + + case 8: + value = deposit64(s->regs[reg], 32, 32, s->regs[reg + 1]); + break; + + default: + g_assert_not_reached(); + } - return s->regs[reg]; + trace_npcm_gcr_read(offset, value); + return value; } static void npcm_gcr_write(void *opaque, hwaddr offset, @@ -231,29 +244,65 @@ static void npcm_gcr_write(void *opaque, hwaddr offset, return; } - switch (reg) { - case NPCM7XX_GCR_PDID: - case NPCM7XX_GCR_PWRON: - case NPCM7XX_GCR_INTSR: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n", - __func__, offset); - return; - - case NPCM7XX_GCR_RESSR: - case NPCM7XX_GCR_CP2BST: - /* Write 1 to clear */ - value = s->regs[reg] & ~value; + switch (size) { + case 4: + switch (reg) { + case NPCM7XX_GCR_PDID: + case NPCM7XX_GCR_PWRON: + case NPCM7XX_GCR_INTSR: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n", + __func__, offset); + return; + + case NPCM7XX_GCR_RESSR: + case NPCM7XX_GCR_CP2BST: + /* Write 1 to clear */ + value = s->regs[reg] & ~value; + break; + + case NPCM7XX_GCR_RLOCKR1: + case NPCM7XX_GCR_MDLR: + /* Write 1 to set */ + value |= s->regs[reg]; + break; + }; + s->regs[reg] = value; break; - case NPCM7XX_GCR_RLOCKR1: - case NPCM7XX_GCR_MDLR: - /* Write 1 to set */ - value |= s->regs[reg]; + case 8: + s->regs[reg] = value; + s->regs[reg + 1] = extract64(v, 32, 32); break; - }; - s->regs[reg] = value; + default: + g_assert_not_reached(); + } +} + +static bool npcm_gcr_check_mem_op(void *opaque, hwaddr offset, + unsigned size, bool is_write, + MemTxAttrs attrs) +{ + NPCMGCRClass *c = NPCM_GCR_GET_CLASS(opaque); + + if (offset >= c->nr_regs * sizeof(uint32_t)) { + return false; + } + + switch (size) { + case 4: + return true; + case 8: + if (offset >= NPCM8XX_GCR_SCRPAD_00 * sizeof(uint32_t) && + offset < (NPCM8XX_GCR_NR_REGS - 1) * sizeof(uint32_t)) { + return true; + } else { + return false; + } + default: + return false; + } } static const struct MemoryRegionOps npcm_gcr_ops = { @@ -262,7 +311,8 @@ static const struct MemoryRegionOps npcm_gcr_ops = { .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 4, - .max_access_size = 4, + .max_access_size = 8, + .accepts = npcm_gcr_check_mem_op, .unaligned = false, }, }; diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 0f7204a237..f25dbd6030 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -135,8 +135,8 @@ npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " valu npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 # npcm_gcr.c -npcm_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 -npcm_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 +npcm_gcr_read(uint64_t offset, uint64_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx64 +npcm_gcr_write(uint64_t offset, uint64_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx64 # npcm7xx_mft.c npcm7xx_mft_read(const char *name, uint64_t offset, uint16_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx16