From 9d5a9ae962eec0788a6ac5a8e9a7a116ff30f50a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 28 Jun 2022 16:47:24 +0100 Subject: hw/intc/armv7m_nvic: ICPRn must not unpend an IRQ that is being held high MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the M-profile Arm ARM, rule R_CVJS defines when an interrupt should be set to the Pending state: A) when the input line is high and the interrupt is not Active B) when the input line transitions from low to high and the interrupt is Active (Note that the first of these is an ongoing condition, and the second is a point-in-time event.) This can be rephrased as: 1 when the line goes from low to high, set Pending 2 when Active goes from 1 to 0, if line is high then set Pending 3 ignore attempts to clear Pending when the line is high and Active is 0 where 1 covers both B and one of the "transition into condition A" cases, 2 deals with the other "transition into condition A" possibility, and 3 is "don't drop Pending if we're already in condition A". Transitions out of condition A don't affect Pending state. We handle case 1 in set_irq_level(). For an interrupt (as opposed to other kinds of exception) the only place where we clear Active is in armv7m_nvic_complete_irq(), where we handle case 2 by checking for whether we need to re-pend the exception. For case 3, the only places where we clear Pending state on an interrupt are in armv7m_nvic_acknowledge_irq() (where we are setting Active so it doesn't count) and for writes to NVIC_ICPRn. It is the "write to NVIC_ICPRn" case that we missed: we must ignore this if the input line is high and the interrupt is not Active. (This required behaviour is differently and perhaps more clearly stated in the v7M Arm ARM, which has pseudocode in section B3.4.1 that implies it.) Reported-by: Igor Kotrasiński Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Message-id: 20220628154724.3297442-1-peter.maydell@linaro.org --- hw/intc/armv7m_nvic.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 13df002..1f77639 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -2389,8 +2389,15 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr, startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) { + /* + * Note that if the input line is still held high and the interrupt + * is not active then rule R_CVJS requires that the Pending state + * remains set; in that case we mustn't let it be cleared. + */ if (value & (1 << i) && - (attrs.secure || s->itns[startvec + i])) { + (attrs.secure || s->itns[startvec + i]) && + !(setval == 0 && s->vectors[startvec + i].level && + !s->vectors[startvec + i].active)) { s->vectors[startvec + i].pending = setval; } } -- cgit v1.1 From 4a84e85413acaad9e84b64786e44e190080d78a6 Mon Sep 17 00:00:00 2001 From: Hao Wu Date: Thu, 14 Jul 2022 11:28:31 -0700 Subject: hw/adc: Fix CONV bit in NPCM7XX ADC CON register The correct bit for the CONV bit in NPCM7XX ADC is bit 13. This patch fixes that in the module, and also lower the IRQ when the guest is done handling an interrupt event from the ADC module. Signed-off-by: Hao Wu Reviewed-by: Patrick Venture Reviewed-by: Peter Maydell Message-id: 20220714182836.89602-4-wuhaotsh@google.com Signed-off-by: Peter Maydell --- hw/adc/npcm7xx_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c index 0f0a9f6..47fb9e5 100644 --- a/hw/adc/npcm7xx_adc.c +++ b/hw/adc/npcm7xx_adc.c @@ -36,7 +36,7 @@ REG32(NPCM7XX_ADC_DATA, 0x4) #define NPCM7XX_ADC_CON_INT BIT(18) #define NPCM7XX_ADC_CON_EN BIT(17) #define NPCM7XX_ADC_CON_RST BIT(16) -#define NPCM7XX_ADC_CON_CONV BIT(14) +#define NPCM7XX_ADC_CON_CONV BIT(13) #define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8) #define NPCM7XX_ADC_MAX_RESULT 1023 -- cgit v1.1 From 99638ba9d86b7707adabbf0b223a6e0ae144cd88 Mon Sep 17 00:00:00 2001 From: Hao Wu Date: Thu, 14 Jul 2022 11:28:32 -0700 Subject: hw/adc: Make adci[*] R/W in NPCM7XX ADC Our sensor test requires both reading and writing from a sensor's QOM property. So we need to make the input of ADC module R/W instead of write only for that to work. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Reviewed-by: Peter Maydell Message-id: 20220714182836.89602-5-wuhaotsh@google.com Signed-off-by: Peter Maydell --- hw/adc/npcm7xx_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c index 47fb9e5..bc6f3f5 100644 --- a/hw/adc/npcm7xx_adc.c +++ b/hw/adc/npcm7xx_adc.c @@ -242,7 +242,7 @@ static void npcm7xx_adc_init(Object *obj) for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) { object_property_add_uint32_ptr(obj, "adci[*]", - &s->adci[i], OBJ_PROP_FLAG_WRITE); + &s->adci[i], OBJ_PROP_FLAG_READWRITE); } object_property_add_uint32_ptr(obj, "vref", &s->vref, OBJ_PROP_FLAG_WRITE); -- cgit v1.1 From 004c8a8bc569c8b18fca6fc90ffe3223daaf17b7 Mon Sep 17 00:00:00 2001 From: Andrey Makarov Date: Sat, 16 Jul 2022 14:32:10 +0300 Subject: Align Raspberry Pi DMA interrupts with Linux DTS There is nothing in the specs on DMA engine interrupt lines: it should have been in the "BCM2835 ARM Peripherals" datasheet but the appropriate "ARM peripherals interrupt table" (p.113) is nearly empty. All Raspberry Pi models 1-3 (based on bcm2835) have Linux device tree (arch/arm/boot/dts/bcm2835-common.dtsi +25): /* dma channel 11-14 share one irq */ This information is repeated in the driver code (drivers/dma/bcm2835-dma.c +1344): /* * in case of channel >= 11 * use the 11th interrupt and that is shared */ In this patch channels 0--10 and 11--14 are handled separately. Signed-off-by: Andrey Makarov Message-id: 20220716113210.349153-1-andrey.makarov@auriga.com [PMM: fixed checkpatch nits] Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/bcm2835_peripherals.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index 48538c9..3c2a416 100644 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -23,6 +23,13 @@ /* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */ #define BCM2835_SDHC_CAPAREG 0x52134b4 +/* + * According to Linux driver & DTS, dma channels 0--10 have separate IRQ, + * while channels 11--14 share one IRQ: + */ +#define SEPARATE_DMA_IRQ_MAX 10 +#define ORGATED_DMA_IRQ_COUNT 4 + static void create_unimp(BCM2835PeripheralState *ps, UnimplementedDeviceState *uds, const char *name, hwaddr ofs, hwaddr size) @@ -101,6 +108,11 @@ static void bcm2835_peripherals_init(Object *obj) /* DMA Channels */ object_initialize_child(obj, "dma", &s->dma, TYPE_BCM2835_DMA); + object_initialize_child(obj, "orgated-dma-irq", + &s->orgated_dma_irq, TYPE_OR_IRQ); + object_property_set_int(OBJECT(&s->orgated_dma_irq), "num-lines", + ORGATED_DMA_IRQ_COUNT, &error_abort); + object_property_add_const_link(OBJECT(&s->dma), "dma-mr", OBJECT(&s->gpu_bus_mr)); @@ -322,12 +334,24 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->peri_mr, DMA15_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 1)); - for (n = 0; n <= 12; n++) { + for (n = 0; n <= SEPARATE_DMA_IRQ_MAX; n++) { sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), n, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA0 + n)); } + if (!qdev_realize(DEVICE(&s->orgated_dma_irq), NULL, errp)) { + return; + } + for (n = 0; n < ORGATED_DMA_IRQ_COUNT; n++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), + SEPARATE_DMA_IRQ_MAX + 1 + n, + qdev_get_gpio_in(DEVICE(&s->orgated_dma_irq), n)); + } + qdev_connect_gpio_out(DEVICE(&s->orgated_dma_irq), 0, + qdev_get_gpio_in_named(DEVICE(&s->ic), + BCM2835_IC_GPU_IRQ, + INTERRUPT_DMA0 + SEPARATE_DMA_IRQ_MAX + 1)); /* THERMAL */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->thermal), errp)) { -- cgit v1.1