From: "Cédric Le Goater" <clg@redhat.com>
To: qemu-arm@nongnu.org, qemu-devel@nongnu.org
Cc: Jamin Lin <jamin_lin@aspeedtech.com>,
Andrew Jeffery <andrew@codeconstruct.com.au>
Subject: [PULL 04/17] hw/gpio/aspeed: Fix clear incorrect interrupt status for GPIO index mode
Date: Thu, 24 Oct 2024 08:34:54 +0200 [thread overview]
Message-ID: <20241024063507.1585765-5-clg@redhat.com> (raw)
In-Reply-To: <20241024063507.1585765-1-clg@redhat.com>
From: Jamin Lin <jamin_lin@aspeedtech.com>
The interrupt status field is W1C, where a set bit on read indicates an
interrupt is pending. If the bit extracted from data is set it should
clear the corresponding bit in reg_value. However, if the extracted
bit is clear then the value of the corresponding bit in reg_value
should be unchanged.
SHARED_FIELD_EX32() extracts the interrupt status bit from the write
(data). reg_value is set to the set's interrupt status, which means
that for any pin with an interrupt pending, the corresponding bit is
set. The deposit32() call updates the bit at pin_idx in the
reg_value, using the value extracted from the write (data).
The result is that if multiple interrupt status bits
were pending and the write was acknowledging specific one bit,
then the all interrupt status bits will be cleared.
However, it is index mode and should only clear the corresponding bit.
For example, say we have an interrupt pending for GPIOA0, where the
following statements are true:
set->int_status == 0b01
s->pending == 1
Before it is acknowledged, an interrupt becomes pending for GPIOA1:
set->int_status == 0b11
s->pending == 2
A write is issued to acknowledge the interrupt for GPIOA0. This causes
the following sequence:
reg_value == 0b11
pending == 2
s->pending == 0
set->int_status == 0b00
It should only clear bit 0 in index mode and the correct result
should be as following.
set->int_status == 0b11
s->pending == 2
pending == 1
s->pending == 1
set->int_status == 0b10
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Suggested-by: Andrew Jeffery <andrew@codeconstruct.com.au>
Reviewed-by: Andrew Jeffery <andrew@codeconstruct.com.au>
---
hw/gpio/aspeed_gpio.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
index 8725606aecae..16c18ea2f743 100644
--- a/hw/gpio/aspeed_gpio.c
+++ b/hw/gpio/aspeed_gpio.c
@@ -641,7 +641,7 @@ static void aspeed_gpio_write_index_mode(void *opaque, hwaddr offset,
uint32_t pin_idx = reg_idx_number % ASPEED_GPIOS_PER_SET;
uint32_t group_idx = pin_idx / GPIOS_PER_GROUP;
uint32_t reg_value = 0;
- uint32_t cleared;
+ uint32_t pending = 0;
set = &s->sets[set_idx];
props = &agc->props[set_idx];
@@ -703,16 +703,23 @@ static void aspeed_gpio_write_index_mode(void *opaque, hwaddr offset,
FIELD_EX32(data, GPIO_INDEX_REG, INT_SENS_2));
set->int_sens_2 = update_value_control_source(set, set->int_sens_2,
reg_value);
- /* set interrupt status */
- reg_value = set->int_status;
- reg_value = deposit32(reg_value, pin_idx, 1,
- FIELD_EX32(data, GPIO_INDEX_REG, INT_STATUS));
- cleared = ctpop32(reg_value & set->int_status);
- if (s->pending && cleared) {
- assert(s->pending >= cleared);
- s->pending -= cleared;
+ /* interrupt status */
+ if (FIELD_EX32(data, GPIO_INDEX_REG, INT_STATUS)) {
+ /* pending is either 1 or 0 for a 1-bit field */
+ pending = extract32(set->int_status, pin_idx, 1);
+
+ assert(s->pending >= pending);
+
+ /* No change to s->pending if pending is 0 */
+ s->pending -= pending;
+
+ /*
+ * The write acknowledged the interrupt regardless of whether it
+ * was pending or not. The post-condition is that it mustn't be
+ * pending. Unconditionally clear the status bit.
+ */
+ set->int_status = deposit32(set->int_status, pin_idx, 1, 0);
}
- set->int_status &= ~reg_value;
break;
case gpio_reg_idx_debounce:
reg_value = set->debounce_1;
--
2.47.0
next prev parent reply other threads:[~2024-10-24 6:37 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-24 6:34 [PULL 00/17] aspeed queue Cédric Le Goater
2024-10-24 6:34 ` [PULL 01/17] hw/gpio/aspeed: Fix coding style Cédric Le Goater
2024-10-24 6:34 ` [PULL 02/17] hw/gpio/aspeed: Support to set the different memory size Cédric Le Goater
2024-10-24 6:34 ` [PULL 03/17] hw/gpio/aspeed: Support different memory region ops Cédric Le Goater
2024-10-24 6:34 ` Cédric Le Goater [this message]
2024-10-24 6:34 ` [PULL 05/17] hw/gpio/aspeed: Add AST2700 support Cédric Le Goater
2024-10-24 6:34 ` [PULL 06/17] aspeed/soc: Correct GPIO irq 130 for AST2700 Cédric Le Goater
2024-10-24 6:34 ` [PULL 07/17] aspeed/soc: Support GPIO " Cédric Le Goater
2024-10-24 6:34 ` [PULL 08/17] tests/qtest:ast2700-gpio-test: Add GPIO test case " Cédric Le Goater
2024-10-24 6:34 ` [PULL 09/17] hw/misc/aspeed_hace: Fix SG Accumulative hashing Cédric Le Goater
2024-10-24 6:35 ` [PULL 10/17] tests/functional: Convert most Aspeed machine tests Cédric Le Goater
2024-11-05 16:14 ` Peter Maydell
2024-11-05 16:35 ` Stefan Berger
2024-11-05 17:13 ` Peter Maydell
2024-11-05 18:02 ` Stefan Berger
2024-11-05 18:12 ` Peter Maydell
2024-11-05 18:35 ` Stefan Berger
2024-11-05 19:54 ` Peter Maydell
2024-11-05 20:12 ` Stefan Berger
2024-11-05 21:34 ` Peter Maydell
2024-11-05 21:50 ` Stefan Berger
2024-11-06 15:21 ` Stefan Berger
2024-10-24 6:35 ` [PULL 11/17] aspeed/smc: Fix write incorrect data into flash in user mode Cédric Le Goater
2024-10-24 6:35 ` [PULL 12/17] hw/block:m25p80: Fix coding style Cédric Le Goater
2024-10-24 6:35 ` [PULL 13/17] hw/block:m25p80: Support write status register 2 command (0x31) for w25q01jvq Cédric Le Goater
2024-10-24 6:35 ` [PULL 14/17] hw/block/m25p80: Add SFDP table for w25q80bl flash Cédric Le Goater
2024-10-24 6:35 ` [PULL 15/17] hw/arm/aspeed: Correct spi_model w25q256 for ast1030-a1 EVB Cédric Le Goater
2024-10-24 6:35 ` [PULL 16/17] hw/arm/aspeed: Correct fmc_model w25q80bl " Cédric Le Goater
2024-10-24 6:35 ` [PULL 17/17] test/qtest/aspeed_smc-test: Fix coding style Cédric Le Goater
2024-10-25 14:23 ` [PULL 00/17] aspeed queue Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241024063507.1585765-5-clg@redhat.com \
--to=clg@redhat.com \
--cc=andrew@codeconstruct.com.au \
--cc=jamin_lin@aspeedtech.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).