hw/misc: Support 8-bytes memop in NPCM GCR module

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>
Reviewed-by: Philippe Mathieu-Daude <philmd@linaro.org>
Message-id: 20250219184609.1839281-10-wuhaotsh@google.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Hao Wu 2025-02-19 10:46:00 -08:00 committed by Peter Maydell
parent 0ad46bbb56
commit ca2fd966ea
2 changed files with 73 additions and 23 deletions

View file

@ -200,6 +200,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,
@ -208,9 +209,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;
return s->regs[reg];
case 8:
value = deposit64(s->regs[reg], 32, 32, s->regs[reg + 1]);
break;
default:
g_assert_not_reached();
}
trace_npcm_gcr_read(offset, value);
return value;
}
static void npcm_gcr_write(void *opaque, hwaddr offset,
@ -230,29 +243,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;
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;
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 = {
@ -261,7 +310,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,
},
};

View file

@ -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