From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by 2002:a17:504:5f68:b0:1be9:327d:8ee3 with SMTP id gl8csp167333njc; Fri, 27 Sep 2024 00:32:33 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCWKSgrQTIOlk7M5C0nQN4ltJ2ay8TR3bWWlQ8AFSJ6iijd4tk6ucyYg5U84AJDFgVj7Yhxcjycp/t0m8g==@linaro.org X-Google-Smtp-Source: AGHT+IFMZJSiXBKiVmMPcmhpjODO8i3t6W9gGApY1p3Egttn2VNcyTsSH9Qtpo/ApifPA/n2XF54 X-Received: by 2002:a05:620a:2492:b0:7a9:c406:eebd with SMTP id af79cd13be357-7ae378c28fdmr284308985a.42.1727422352957; Fri, 27 Sep 2024 00:32:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1727422352; cv=none; d=google.com; s=arc-20240605; b=Jvz62/yCjbSNB9d4HMMRTDRhhMO4JV+g2J8W2CMPe1rTDp+G+0xJlr7VPtImrbpkeY ihpIGj5LY0AoRtKiKhYXPdV/OD92rvMxFk68i9sfF5ZcSbLj4M3x1dVrJ793A6eR/5Xl CFNIdJI1g0OeXbdOGGMrFRdOT1uxpatFnBrfJ2Rc/fQL/juDzsK6mUFMUwHwjgLX5Cqq hoynfYOntFIRx6LCP6YAUppE3Xqd7o7d3FSU/c0Y9Eq8kkiowxuDEK/pGNBQY6ovytAo 9JbB7amNIUdhS3vgnGeKkAH9932kP2rctTFZnvxavDCBGC4yYRCtJO5TL98tYTen4prq oRhQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:from:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to; bh=Cuelhesp2EJkf6+kUOINt1uwensPR6dAhjz7egcQUKc=; fh=bfdvnURtAD34fQ77QeZnvwdM4/zSvHk1Doa+KIkv0v8=; b=B4QEE1k8mE4W9vPf2+LGu2/Q1Bz4IwWbeGFrYRDlX2k1YGdNEo+VdOoUhuvb0eGW3Z c8V4PiSUxg+Qj0aHRlYQpAVlLvImoMkfu9gKmnsZVAa1TqXvRyWeAz2tWvcRmsc7iQx9 7dEXCOBJ6dMxU+IH9GxoGX7J3VEX5p9OZtJThO5CBImLv2JQ5KEuOG+PM8pz6erxqGno SMaR5pTbsejnTzyYp5vpXPdzcJw+GRSKc8OrmiN5iqkEIsB06vB3MMmqptzep1vyzhiF ibducfyn+q8p06lwVaVfup4Rkn6jCKf2sLGQY9PGrr1ay49+DyF7uj6Fov11BCFLI8tG y/gA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id af79cd13be357-7ae378529d2si155534185a.392.2024.09.27.00.32.32 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Fri, 27 Sep 2024 00:32:32 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=nongnu.org Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1su5SY-0001tX-MS; Fri, 27 Sep 2024 03:32:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1su5SW-0001mM-TE; Fri, 27 Sep 2024 03:32:12 -0400 Received: from mail.aspeedtech.com ([211.20.114.72] helo=TWMBX01.aspeed.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1su5SV-0004DY-8G; Fri, 27 Sep 2024 03:32:12 -0400 Received: from TWMBX01.aspeed.com (192.168.0.62) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.12; Fri, 27 Sep 2024 15:31:45 +0800 Received: from localhost.localdomain (192.168.10.10) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1258.12 via Frontend Transport; Fri, 27 Sep 2024 15:31:45 +0800 To: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Peter Maydell , Steven Lee , Troy Lee , Andrew Jeffery , "Joel Stanley" , Thomas Huth , Laurent Vivier , Paolo Bonzini , "open list:ASPEED BMCs" , "open list:All patches CC here" CC: , , Subject: [PATCH v4 4/7] hw/gpio/aspeed: Fix clear incorrect interrupt status for GPIO index mode Date: Fri, 27 Sep 2024 15:31:41 +0800 Message-ID: <20240927073144.2303522-5-jamin_lin@aspeedtech.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240927073144.2303522-1-jamin_lin@aspeedtech.com> References: <20240927073144.2303522-1-jamin_lin@aspeedtech.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain Received-SPF: pass client-ip=211.20.114.72; envelope-from=jamin_lin@aspeedtech.com; helo=TWMBX01.aspeed.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_FAIL=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-arm@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Jamin Lin From: Jamin Lin via Errors-To: qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org Sender: qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org X-TUID: xUSlVZPnZYMJ 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 Suggested-by: Andrew Jeffery Reviewed-by: Andrew Jeffery --- 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 8725606aec..16c18ea2f7 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.34.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3C77FCEBF80 for ; Fri, 27 Sep 2024 07:34:16 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1su5SZ-0001vb-7d; Fri, 27 Sep 2024 03:32:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1su5SW-0001mM-TE; Fri, 27 Sep 2024 03:32:12 -0400 Received: from mail.aspeedtech.com ([211.20.114.72] helo=TWMBX01.aspeed.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1su5SV-0004DY-8G; Fri, 27 Sep 2024 03:32:12 -0400 Received: from TWMBX01.aspeed.com (192.168.0.62) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.12; Fri, 27 Sep 2024 15:31:45 +0800 Received: from localhost.localdomain (192.168.10.10) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1258.12 via Frontend Transport; Fri, 27 Sep 2024 15:31:45 +0800 To: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Peter Maydell , Steven Lee , Troy Lee , Andrew Jeffery , "Joel Stanley" , Thomas Huth , Laurent Vivier , Paolo Bonzini , "open list:ASPEED BMCs" , "open list:All patches CC here" CC: , , Subject: [PATCH v4 4/7] hw/gpio/aspeed: Fix clear incorrect interrupt status for GPIO index mode Date: Fri, 27 Sep 2024 15:31:41 +0800 Message-ID: <20240927073144.2303522-5-jamin_lin@aspeedtech.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240927073144.2303522-1-jamin_lin@aspeedtech.com> References: <20240927073144.2303522-1-jamin_lin@aspeedtech.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain Received-SPF: pass client-ip=211.20.114.72; envelope-from=jamin_lin@aspeedtech.com; helo=TWMBX01.aspeed.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_FAIL=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Jamin Lin From: Jamin Lin via Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org 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 Suggested-by: Andrew Jeffery Reviewed-by: Andrew Jeffery --- 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 8725606aec..16c18ea2f7 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.34.1