From nobody Sat Feb 7 08:45:23 2026 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA83D341077; Fri, 23 Jan 2026 09:26:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160405; cv=none; b=HVnFIWEAoHUppxcp7k1/YLJ3NaykkFOgBjbuEzmsjyp/7DxU2uZa+UYm1blmmZvxHPG+zWFSi+LlQN00FxXquZ7LePz8mQdgaKXdmXUpSmGJ8/3XfsUUc6DrRamRWRCOQcx7GExB63wRaD94qZoDya9iFlcP5vIG+MFCYlRbcSg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160405; c=relaxed/simple; bh=FTZzog1cghOkYQGpXnNtMtKiobZwLYO/6gvXhdqdfb4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=O3zO0dzB3KVFyW7ucyVCFJKdcW5liQjNzLmGNmHAqpoaFSi6U5jNTiINVS2xheApIVug85XgMsTQq+DMO/b8tOAgf1VMIFvxXDrj2eG2wH+Ss/wL55HNuiCGSWjJFviCrD7dGf61oy4Gs4aVbl9DKR2xW5sgTfLBcvJ1I4YU/u0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com 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.1748.10; Fri, 23 Jan 2026 17:26:26 +0800 Received: from [127.0.1.1] (192.168.10.13) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1748.10 via Frontend Transport; Fri, 23 Jan 2026 17:26:26 +0800 From: Billy Tsai Date: Fri, 23 Jan 2026 17:26:26 +0800 Subject: [PATCH v2 1/6] gpio: aspeed-sgpio: Change the macro to support deferred probe Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20260123-upstream_sgpio-v2-1-69cfd1631400@aspeedtech.com> References: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> In-Reply-To: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> To: Linus Walleij , Bartosz Golaszewski , Joel Stanley , Andrew Jeffery , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: , , , , "Andrew Jeffery" , , , Billy Tsai X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1769160386; l=1736; i=billy_tsai@aspeedtech.com; s=20251118; h=from:subject:message-id; bh=FTZzog1cghOkYQGpXnNtMtKiobZwLYO/6gvXhdqdfb4=; b=wKbf6vtm34F3bElj6iOkpuUp+S+jsMo3UdPcDnjnNF4IqHIRoFFFISw6vZIdQM/oYix7J6q08 dpN2LDBi1BYDC0WFVJMRqJui7jZUWtpQnF4vHxc9VT+tFrZbTazV81Q X-Developer-Key: i=billy_tsai@aspeedtech.com; a=ed25519; pk=/A8qvgZ6CPfnwKgT6/+k+nvXOkN477MshEGJvVdzeeQ= Use module_platform_driver() to replace module_platform_driver_probe(). The former utilizes platform_driver_register(), which allows the driver to defer probing when it doesn't acquire the necessary resources due to probe order. In contrast, the latter uses __platform_driver_probe(), which includes the comment "Note that this is incompatible with deferred probing." Since our SGPIO driver requires access to the clock resource, the former is more suitable. Reviewed-by: Linus Walleij Signed-off-by: Billy Tsai --- drivers/gpio/gpio-aspeed-sgpio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sg= pio.c index 7622f9e9f54a..318cd0e39741 100644 --- a/drivers/gpio/gpio-aspeed-sgpio.c +++ b/drivers/gpio/gpio-aspeed-sgpio.c @@ -516,7 +516,7 @@ static const struct of_device_id aspeed_sgpio_of_table[= ] =3D { =20 MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table); =20 -static int __init aspeed_sgpio_probe(struct platform_device *pdev) +static int aspeed_sgpio_probe(struct platform_device *pdev) { u32 nr_gpios, sgpio_freq, sgpio_clk_div, gpio_cnt_regval, pin_mask; const struct aspeed_sgpio_pdata *pdata; @@ -611,11 +611,12 @@ static int __init aspeed_sgpio_probe(struct platform_= device *pdev) } =20 static struct platform_driver aspeed_sgpio_driver =3D { + .probe =3D aspeed_sgpio_probe, .driver =3D { .name =3D KBUILD_MODNAME, .of_match_table =3D aspeed_sgpio_of_table, }, }; =20 -module_platform_driver_probe(aspeed_sgpio_driver, aspeed_sgpio_probe); +module_platform_driver(aspeed_sgpio_driver); MODULE_DESCRIPTION("Aspeed Serial GPIO Driver"); --=20 2.34.1 From nobody Sat Feb 7 08:45:23 2026 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5701A354AE7; Fri, 23 Jan 2026 09:26:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160410; cv=none; b=SehqFMTvvZbx+c+QbF0MJ7jABvvhtLEIXB/DTYIpDGZ3CmV/mtmxoyYVuE4LbwcLutAtcsuuZMWAKut5R1ipEuKXzPHBm3QygACPRthfhWhiRR3bo/q92vCzYSKhF388l+OCVmapxEv01AdONeb369Tpa1lejwWUCn597RXmGZc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160410; c=relaxed/simple; bh=wq9nW1jVro6VbeJ8h0mIqtAis/vwp9TjCPIxWOSBwOI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=HxpohYQn8ed17DCJ/xr0koHFHRytOOldfK2HnP6ztFgd1MgVPwFPKXuNRUmBKZ4Xbx/Jpf2eqmE7YVa4rvmw3fS7nE2ztIPZi8qccP3BmCCNoFtWyoYeF70S5SgprbAlHi17CgWF+ZmPT4Rfn1HMF/meqnpc4evKJSoEe7WoMaI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com 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.1748.10; Fri, 23 Jan 2026 17:26:26 +0800 Received: from [127.0.1.1] (192.168.10.13) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1748.10 via Frontend Transport; Fri, 23 Jan 2026 17:26:26 +0800 From: Billy Tsai Date: Fri, 23 Jan 2026 17:26:27 +0800 Subject: [PATCH v2 2/6] gpio: aspeed-sgpio: Remove unused bank name field Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20260123-upstream_sgpio-v2-2-69cfd1631400@aspeedtech.com> References: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> In-Reply-To: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> To: Linus Walleij , Bartosz Golaszewski , Joel Stanley , Andrew Jeffery , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: , , , , "Andrew Jeffery" , , , Billy Tsai X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1769160386; l=1327; i=billy_tsai@aspeedtech.com; s=20251118; h=from:subject:message-id; bh=wq9nW1jVro6VbeJ8h0mIqtAis/vwp9TjCPIxWOSBwOI=; b=YC9UInze1Bq7V+AeVOJPr9VhTHhX2yJDKM/ZG0zONoIDK+mvEveIiX4wTrP4BEdrd5OhEcCIj NdxYKnFKt9TCSaNByioCJ1UngylgmFMsaNFYivrP/D/Yo7N9Gt/NNhW X-Developer-Key: i=billy_tsai@aspeedtech.com; a=ed25519; pk=/A8qvgZ6CPfnwKgT6/+k+nvXOkN477MshEGJvVdzeeQ= Drops the names array from the bank struct and its initializers, as it is unused in the driver. Reviewed-by: Linus Walleij Signed-off-by: Billy Tsai --- drivers/gpio/gpio-aspeed-sgpio.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sg= pio.c index 318cd0e39741..a96ed6d8a55d 100644 --- a/drivers/gpio/gpio-aspeed-sgpio.c +++ b/drivers/gpio/gpio-aspeed-sgpio.c @@ -43,7 +43,6 @@ struct aspeed_sgpio_bank { u16 rdata_reg; u16 irq_regs; u16 tolerance_regs; - const char names[4][3]; }; =20 /* @@ -59,28 +58,24 @@ static const struct aspeed_sgpio_bank aspeed_sgpio_bank= s[] =3D { .rdata_reg =3D 0x0070, .irq_regs =3D 0x0004, .tolerance_regs =3D 0x0018, - .names =3D { "A", "B", "C", "D" }, }, { .val_regs =3D 0x001C, .rdata_reg =3D 0x0074, .irq_regs =3D 0x0020, .tolerance_regs =3D 0x0034, - .names =3D { "E", "F", "G", "H" }, }, { .val_regs =3D 0x0038, .rdata_reg =3D 0x0078, .irq_regs =3D 0x003C, .tolerance_regs =3D 0x0050, - .names =3D { "I", "J", "K", "L" }, }, { .val_regs =3D 0x0090, .rdata_reg =3D 0x007C, .irq_regs =3D 0x0094, .tolerance_regs =3D 0x00A8, - .names =3D { "M", "N", "O", "P" }, }, }; =20 --=20 2.34.1 From nobody Sat Feb 7 08:45:23 2026 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD9B534A78F; Fri, 23 Jan 2026 09:26:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160419; cv=none; b=Y4zQ+r2b62mHSgUm3UFjY2nFCeuVFy1wi/daHsftzjrFvWnM/YJJeerOu7iibyXUxMt97OwS6srdgOCsN1wUk7WN2ZpAzYY1pRLXenV7mLwdbtjOFmsR55K8GQSNiN2hVANn7y5p+KTQC9XRVkHxfHVsyEwXNjeqETr9T0aZymE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160419; c=relaxed/simple; bh=TIUq6Bl35VgW6ICCGoaNyUDXHZLqPismF+NB5DqxhLo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=B3C/p0+roBfDMTs7jL2qKImYeVaXZvpyDA91DPvtJKBW+/+rWxoGSFMYoK9MlmPkFaiA6L0Snl64lIipAg8oawJwdg6Qv0bXj8y8fTGJ9eF4tIicQtg3e1a16GfXJzRx997QlBk7ax8wSTQo+5mwrJswXIco57z3jFU9yNOBU+w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com 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.1748.10; Fri, 23 Jan 2026 17:26:26 +0800 Received: from [127.0.1.1] (192.168.10.13) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1748.10 via Frontend Transport; Fri, 23 Jan 2026 17:26:26 +0800 From: Billy Tsai Date: Fri, 23 Jan 2026 17:26:28 +0800 Subject: [PATCH v2 3/6] gpio: aspeed-sgpio: Create llops to handle hardware access Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20260123-upstream_sgpio-v2-3-69cfd1631400@aspeedtech.com> References: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> In-Reply-To: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> To: Linus Walleij , Bartosz Golaszewski , Joel Stanley , Andrew Jeffery , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: , , , , "Andrew Jeffery" , , , Billy Tsai X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1769160386; l=13135; i=billy_tsai@aspeedtech.com; s=20251118; h=from:subject:message-id; bh=TIUq6Bl35VgW6ICCGoaNyUDXHZLqPismF+NB5DqxhLo=; b=obMqessuTmX60BRWTJ7mRRxobx/F49iFV4cGbeaMYmAwEI9AZWiDs2byiKKxuw+uWGINs7kbJ KKwJviwmP88CuezioottWLHWXWDIlutEZUifrE4vhmfKA3wT+Gsw/vB X-Developer-Key: i=billy_tsai@aspeedtech.com; a=ed25519; pk=/A8qvgZ6CPfnwKgT6/+k+nvXOkN477MshEGJvVdzeeQ= Add low-level operations (llops) to abstract the register access for SGPIO registers. With this abstraction layer, the driver can separate the hardware and software logic, making it easier to extend the driver to support different hardware register layouts. The llops abstraction changes the programming semantics from bitmask-based writes to a value-based interface. Instead of passing a pre-shifted bitmask to the caller, the driver now passes: - the GPIO offset, and - the value to be set (0 or 1), and the llops helpers are responsible for deriving the correct register and bit position internally. As a result, assignments such as: type0 =3D 1; type1 =3D 1; type2 =3D 1; do not represent a behavioral change. They indicate that the bit corresponding to the given GPIO offset should be set, with the actual bit manipulation handled by llops. Reviewed-by: Linus Walleij Signed-off-by: Billy Tsai --- drivers/gpio/gpio-aspeed-sgpio.c | 222 ++++++++++++++++++-----------------= ---- 1 file changed, 104 insertions(+), 118 deletions(-) diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sg= pio.c index a96ed6d8a55d..33a830ea7d28 100644 --- a/drivers/gpio/gpio-aspeed-sgpio.c +++ b/drivers/gpio/gpio-aspeed-sgpio.c @@ -27,6 +27,7 @@ =20 struct aspeed_sgpio_pdata { const u32 pin_mask; + const struct aspeed_sgpio_llops *llops; }; =20 struct aspeed_sgpio { @@ -36,6 +37,7 @@ struct aspeed_sgpio { raw_spinlock_t lock; void __iomem *base; int irq; + const struct aspeed_sgpio_pdata *pdata; }; =20 struct aspeed_sgpio_bank { @@ -90,6 +92,15 @@ enum aspeed_sgpio_reg { reg_tolerance, }; =20 +struct aspeed_sgpio_llops { + void (*reg_bit_set)(struct aspeed_sgpio *gpio, unsigned int offset, + const enum aspeed_sgpio_reg reg, bool val); + bool (*reg_bit_get)(struct aspeed_sgpio *gpio, unsigned int offset, + const enum aspeed_sgpio_reg reg); + int (*reg_bank_get)(struct aspeed_sgpio *gpio, unsigned int offset, + const enum aspeed_sgpio_reg reg); +}; + #define GPIO_VAL_VALUE 0x00 #define GPIO_IRQ_ENABLE 0x00 #define GPIO_IRQ_TYPE0 0x04 @@ -97,9 +108,9 @@ enum aspeed_sgpio_reg { #define GPIO_IRQ_TYPE2 0x0C #define GPIO_IRQ_STATUS 0x10 =20 -static void __iomem *bank_reg(struct aspeed_sgpio *gpio, - const struct aspeed_sgpio_bank *bank, - const enum aspeed_sgpio_reg reg) +static void __iomem *aspeed_sgpio_g4_bank_reg(struct aspeed_sgpio *gpio, + const struct aspeed_sgpio_bank *bank, + const enum aspeed_sgpio_reg reg) { switch (reg) { case reg_val: @@ -165,14 +176,13 @@ static bool aspeed_sgpio_is_input(unsigned int offset) static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset) { struct aspeed_sgpio *gpio =3D gpiochip_get_data(gc); - const struct aspeed_sgpio_bank *bank =3D to_bank(offset); enum aspeed_sgpio_reg reg; int rc =3D 0; =20 guard(raw_spinlock_irqsave)(&gpio->lock); =20 reg =3D aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata; - rc =3D !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset)); + rc =3D gpio->pdata->llops->reg_bit_get(gpio, offset, reg); =20 return rc; } @@ -180,26 +190,11 @@ static int aspeed_sgpio_get(struct gpio_chip *gc, uns= igned int offset) static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int = val) { struct aspeed_sgpio *gpio =3D gpiochip_get_data(gc); - const struct aspeed_sgpio_bank *bank =3D to_bank(offset); - void __iomem *addr_r, *addr_w; - u32 reg =3D 0; =20 if (aspeed_sgpio_is_input(offset)) return -EINVAL; =20 - /* Since this is an output, read the cached value from rdata, then - * update val. */ - addr_r =3D bank_reg(gpio, bank, reg_rdata); - addr_w =3D bank_reg(gpio, bank, reg_val); - - reg =3D ioread32(addr_r); - - if (val) - reg |=3D GPIO_BIT(offset); - else - reg &=3D ~GPIO_BIT(offset); - - iowrite32(reg, addr_w); + gpio->pdata->llops->reg_bit_set(gpio, offset, reg_val, val); =20 return 0; } @@ -238,69 +233,34 @@ static int aspeed_sgpio_get_direction(struct gpio_chi= p *gc, unsigned int offset) return !!aspeed_sgpio_is_input(offset); } =20 -static void irqd_to_aspeed_sgpio_data(struct irq_data *d, - struct aspeed_sgpio **gpio, - const struct aspeed_sgpio_bank **bank, - u32 *bit, int *offset) -{ - struct aspeed_sgpio *internal; - - *offset =3D irqd_to_hwirq(d); - internal =3D irq_data_get_irq_chip_data(d); - WARN_ON(!internal); - - *gpio =3D internal; - *bank =3D to_bank(*offset); - *bit =3D GPIO_BIT(*offset); -} =20 static void aspeed_sgpio_irq_ack(struct irq_data *d) { - const struct aspeed_sgpio_bank *bank; - struct aspeed_sgpio *gpio; - void __iomem *status_addr; - int offset; - u32 bit; - - irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); - - status_addr =3D bank_reg(gpio, bank, reg_irq_status); + struct aspeed_sgpio *gpio =3D irq_data_get_irq_chip_data(d); + int offset =3D irqd_to_hwirq(d); =20 guard(raw_spinlock_irqsave)(&gpio->lock); =20 - iowrite32(bit, status_addr); + gpio->pdata->llops->reg_bit_set(gpio, offset, reg_irq_status, 1); } =20 static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set) { - const struct aspeed_sgpio_bank *bank; - struct aspeed_sgpio *gpio; - u32 reg, bit; - void __iomem *addr; - int offset; - - irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); - addr =3D bank_reg(gpio, bank, reg_irq_enable); + struct aspeed_sgpio *gpio =3D irq_data_get_irq_chip_data(d); + int offset =3D irqd_to_hwirq(d); =20 /* Unmasking the IRQ */ if (set) - gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(d)); - - scoped_guard(raw_spinlock_irqsave, &gpio->lock) { - reg =3D ioread32(addr); - if (set) - reg |=3D bit; - else - reg &=3D ~bit; - - iowrite32(reg, addr); + gpiochip_enable_irq(&gpio->chip, offset); + scoped_guard(raw_spinlock_irqsave, &gpio->lock) + { + gpio->pdata->llops->reg_bit_set(gpio, offset, reg_irq_enable, + set); } =20 /* Masking the IRQ */ if (!set) - gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(d)); - - + gpiochip_disable_irq(&gpio->chip, offset); } =20 static void aspeed_sgpio_irq_mask(struct irq_data *d) @@ -318,30 +278,25 @@ static int aspeed_sgpio_set_type(struct irq_data *d, = unsigned int type) u32 type0 =3D 0; u32 type1 =3D 0; u32 type2 =3D 0; - u32 bit, reg; - const struct aspeed_sgpio_bank *bank; irq_flow_handler_t handler; - struct aspeed_sgpio *gpio; - void __iomem *addr; - int offset; - - irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); + struct aspeed_sgpio *gpio =3D irq_data_get_irq_chip_data(d); + int offset =3D irqd_to_hwirq(d); =20 switch (type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_BOTH: - type2 |=3D bit; + type2 =3D 1; fallthrough; case IRQ_TYPE_EDGE_RISING: - type0 |=3D bit; + type0 =3D 1; fallthrough; case IRQ_TYPE_EDGE_FALLING: handler =3D handle_edge_irq; break; case IRQ_TYPE_LEVEL_HIGH: - type0 |=3D bit; + type0 =3D 1; fallthrough; case IRQ_TYPE_LEVEL_LOW: - type1 |=3D bit; + type1 =3D 1; handler =3D handle_level_irq; break; default: @@ -349,20 +304,9 @@ static int aspeed_sgpio_set_type(struct irq_data *d, u= nsigned int type) } =20 scoped_guard(raw_spinlock_irqsave, &gpio->lock) { - addr =3D bank_reg(gpio, bank, reg_irq_type0); - reg =3D ioread32(addr); - reg =3D (reg & ~bit) | type0; - iowrite32(reg, addr); - - addr =3D bank_reg(gpio, bank, reg_irq_type1); - reg =3D ioread32(addr); - reg =3D (reg & ~bit) | type1; - iowrite32(reg, addr); - - addr =3D bank_reg(gpio, bank, reg_irq_type2); - reg =3D ioread32(addr); - reg =3D (reg & ~bit) | type2; - iowrite32(reg, addr); + gpio->pdata->llops->reg_bit_set(gpio, offset, reg_irq_type0, type0); + gpio->pdata->llops->reg_bit_set(gpio, offset, reg_irq_type1, type1); + gpio->pdata->llops->reg_bit_set(gpio, offset, reg_irq_type2, type2); } =20 irq_set_handler_locked(d, handler); @@ -381,9 +325,7 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *d= esc) chained_irq_enter(ic, desc); =20 for (i =3D 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { - const struct aspeed_sgpio_bank *bank =3D &aspeed_sgpio_banks[i]; - - reg =3D ioread32(bank_reg(data, bank, reg_irq_status)); + reg =3D data->pdata->llops->reg_bank_get(data, i << 6, reg_irq_status); =20 for_each_set_bit(p, ®, 32) generic_handle_domain_irq(gc->irq.domain, (i * 32 + p) * 2); @@ -394,12 +336,8 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *= desc) =20 static void aspeed_sgpio_irq_print_chip(struct irq_data *d, struct seq_fil= e *p) { - const struct aspeed_sgpio_bank *bank; - struct aspeed_sgpio *gpio; - u32 bit; - int offset; + struct aspeed_sgpio *gpio =3D irq_data_get_irq_chip_data(d); =20 - irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); seq_puts(p, dev_name(gpio->dev)); } =20 @@ -447,7 +385,7 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio = *gpio, =20 /* Apply default IRQ settings */ for (i =3D 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { - bank =3D &aspeed_sgpio_banks[i]; + bank =3D &aspeed_sgpio_banks[i]; /* set falling or level-low irq */ iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type0)); /* trigger type is edge */ @@ -459,29 +397,78 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpi= o *gpio, return 0; } =20 +static void aspeed_sgpio_g4_reg_bit_set(struct aspeed_sgpio *gpio, unsigne= d int offset, + const enum aspeed_sgpio_reg reg, bool val) +{ + const struct aspeed_sgpio_bank *bank =3D to_bank(offset); + void __iomem *addr =3D aspeed_sgpio_g4_bank_reg(gpio, bank, reg); + u32 temp; + + if (reg =3D=3D reg_val) { + /* Since this is an output, read the cached value from rdata, then updat= e val. */ + addr =3D aspeed_sgpio_g4_bank_reg(gpio, bank, reg_rdata); + temp =3D ioread32(addr); + if (val) + temp |=3D GPIO_BIT(offset); + else + temp &=3D ~GPIO_BIT(offset); + + addr =3D aspeed_sgpio_g4_bank_reg(gpio, bank, reg_val); + iowrite32(temp, addr); + } else if (reg =3D=3D reg_irq_status) { + if (val) + iowrite32(GPIO_BIT(offset), addr); + } else { + /* When setting other registers, we read from the register itself */ + temp =3D ioread32(addr); + if (val) + temp |=3D GPIO_BIT(offset); + else + temp &=3D ~GPIO_BIT(offset); + iowrite32(temp, addr); + } +} + +static bool aspeed_sgpio_g4_reg_bit_get(struct aspeed_sgpio *gpio, unsigne= d int offset, + const enum aspeed_sgpio_reg reg) +{ + const struct aspeed_sgpio_bank *bank =3D to_bank(offset); + void __iomem *addr =3D aspeed_sgpio_g4_bank_reg(gpio, bank, reg); + + return !!(ioread32(addr) & GPIO_BIT(offset)); +} + +static int aspeed_sgpio_g4_reg_bank_get(struct aspeed_sgpio *gpio, unsigne= d int offset, + const enum aspeed_sgpio_reg reg) +{ + const struct aspeed_sgpio_bank *bank =3D to_bank(offset); + void __iomem *addr =3D aspeed_sgpio_g4_bank_reg(gpio, bank, reg); + + if (reg =3D=3D reg_irq_status) + return ioread32(addr); + else + return -EOPNOTSUPP; +} + +static const struct aspeed_sgpio_llops aspeed_sgpio_g4_llops =3D { + .reg_bit_set =3D aspeed_sgpio_g4_reg_bit_set, + .reg_bit_get =3D aspeed_sgpio_g4_reg_bit_get, + .reg_bank_get =3D aspeed_sgpio_g4_reg_bank_get, +}; + static const struct aspeed_sgpio_pdata ast2400_sgpio_pdata =3D { .pin_mask =3D GENMASK(9, 6), + .llops =3D &aspeed_sgpio_g4_llops, }; =20 static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip, unsigned int offset, bool enable) { struct aspeed_sgpio *gpio =3D gpiochip_get_data(chip); - void __iomem *reg; - u32 val; - - reg =3D bank_reg(gpio, to_bank(offset), reg_tolerance); =20 guard(raw_spinlock_irqsave)(&gpio->lock); =20 - val =3D readl(reg); - - if (enable) - val |=3D GPIO_BIT(offset); - else - val &=3D ~GPIO_BIT(offset); - - writel(val, reg); + gpio->pdata->llops->reg_bit_set(gpio, offset, reg_tolerance, enable); =20 return 0; } @@ -500,6 +487,7 @@ static int aspeed_sgpio_set_config(struct gpio_chip *ch= ip, unsigned int offset, =20 static const struct aspeed_sgpio_pdata ast2600_sgpiom_pdata =3D { .pin_mask =3D GENMASK(10, 6), + .llops =3D &aspeed_sgpio_g4_llops, }; =20 static const struct of_device_id aspeed_sgpio_of_table[] =3D { @@ -514,7 +502,6 @@ MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table); static int aspeed_sgpio_probe(struct platform_device *pdev) { u32 nr_gpios, sgpio_freq, sgpio_clk_div, gpio_cnt_regval, pin_mask; - const struct aspeed_sgpio_pdata *pdata; struct aspeed_sgpio *gpio; unsigned long apb_freq; int rc; @@ -529,12 +516,11 @@ static int aspeed_sgpio_probe(struct platform_device = *pdev) =20 gpio->dev =3D &pdev->dev; =20 - pdata =3D device_get_match_data(&pdev->dev); - if (!pdata) + gpio->pdata =3D device_get_match_data(&pdev->dev); + if (!gpio->pdata) return -EINVAL; =20 - pin_mask =3D pdata->pin_mask; - + pin_mask =3D gpio->pdata->pin_mask; rc =3D device_property_read_u32(&pdev->dev, "ngpios", &nr_gpios); if (rc < 0) { dev_err(&pdev->dev, "Could not read ngpios property\n"); --=20 2.34.1 From nobody Sat Feb 7 08:45:23 2026 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AE6BC34DB5F; Fri, 23 Jan 2026 09:26:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160425; cv=none; b=Pxq4XqkjVEBlbcshHLtxTp/GsL7E/P96PM69i2vr7MFqadgNv307iiRWocj1K8n5a8+AedOA5VwZ1i2VIzUwySIHL4fwbCQVI1C1CRR05I/PHPg6I6uzaCQ3UZTkUmslOLxuaLWJihR1ztdLbI3e6nDaPXIEEs63/N/fujtrcDM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160425; c=relaxed/simple; bh=Hl9LdLVmaEDP86aDOaXmV5qwrfCQGY8Vf57r/K2vfGo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=VEtwXMPKjnMu4sIV4U37E48jC7holUojeQavNd9lfuMg2bEYqW4MR3ANuuN+Qqw+yrOSZPPSb3jy/1DDfNT/lMnt8QntU3lR6gHczZzIc7WefBYnZzBIOg3Y+5lhAIyapeUDh7l5KsWUVJt1UpVNS38nMtv3hWMdtUnkUD0CSUo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com 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.1748.10; Fri, 23 Jan 2026 17:26:27 +0800 Received: from [127.0.1.1] (192.168.10.13) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1748.10 via Frontend Transport; Fri, 23 Jan 2026 17:26:27 +0800 From: Billy Tsai Date: Fri, 23 Jan 2026 17:26:29 +0800 Subject: [PATCH v2 4/6] gpio: aspeed-sgpio: Convert IRQ functions to use llops callbacks Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20260123-upstream_sgpio-v2-4-69cfd1631400@aspeedtech.com> References: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> In-Reply-To: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> To: Linus Walleij , Bartosz Golaszewski , Joel Stanley , Andrew Jeffery , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: , , , , "Andrew Jeffery" , , , Billy Tsai X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1769160386; l=3203; i=billy_tsai@aspeedtech.com; s=20251118; h=from:subject:message-id; bh=Hl9LdLVmaEDP86aDOaXmV5qwrfCQGY8Vf57r/K2vfGo=; b=K5o16m1x6dewUe7aGBZCQd8VhK7H5qvqCsuX/OtBs3wmUEm1li/l9HmMHp3sC1i6NAm2bdliC pd+fJU5ZViyAfNRcAtJ7kLlypsitiC5xTGENG39S2WcBt/1oECAdTz9 X-Developer-Key: i=billy_tsai@aspeedtech.com; a=ed25519; pk=/A8qvgZ6CPfnwKgT6/+k+nvXOkN477MshEGJvVdzeeQ= Update aspeed_sgpio_irq_handler() and aspeed_sgpio_setup_irqs() to use the llops callbacks for register access instead of direct iowrite32(). This creates a unified hardware access layer, which is essential for supporting SoCs with different register layouts like the AST2700. Additionally, change the loop bounds to use ngpio instead of the static ARRAY_SIZE(aspeed_sgpio_banks). This allows the driver to adapt to the actual number of supported pins on the running SoC. Signed-off-by: Billy Tsai --- drivers/gpio/gpio-aspeed-sgpio.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sg= pio.c index 33a830ea7d28..b5270e11b153 100644 --- a/drivers/gpio/gpio-aspeed-sgpio.c +++ b/drivers/gpio/gpio-aspeed-sgpio.c @@ -319,12 +319,13 @@ static void aspeed_sgpio_irq_handler(struct irq_desc = *desc) struct gpio_chip *gc =3D irq_desc_get_handler_data(desc); struct irq_chip *ic =3D irq_desc_get_chip(desc); struct aspeed_sgpio *data =3D gpiochip_get_data(gc); - unsigned int i, p; + unsigned int i, p, banks; unsigned long reg; =20 chained_irq_enter(ic, desc); =20 - for (i =3D 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { + banks =3D DIV_ROUND_UP(gc->ngpio, 64); + for (i =3D 0; i < banks; i++) { reg =3D data->pdata->llops->reg_bank_get(data, i << 6, reg_irq_status); =20 for_each_set_bit(p, ®, 32) @@ -355,7 +356,6 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio = *gpio, struct platform_device *pdev) { int rc, i; - const struct aspeed_sgpio_bank *bank; struct gpio_irq_chip *irq; =20 rc =3D platform_get_irq(pdev, 0); @@ -365,12 +365,11 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpi= o *gpio, gpio->irq =3D rc; =20 /* Disable IRQ and clear Interrupt status registers for all SGPIO Pins. */ - for (i =3D 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { - bank =3D &aspeed_sgpio_banks[i]; + for (i =3D 0; i < gpio->chip.ngpio; i +=3D 2) { /* disable irq enable bits */ - iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_enable)); + gpio->pdata->llops->reg_bit_set(gpio, i, reg_irq_enable, 0); /* clear status bits */ - iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status)); + gpio->pdata->llops->reg_bit_set(gpio, i, reg_irq_status, 1); } =20 irq =3D &gpio->chip.irq; @@ -384,14 +383,13 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpi= o *gpio, irq->num_parents =3D 1; =20 /* Apply default IRQ settings */ - for (i =3D 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { - bank =3D &aspeed_sgpio_banks[i]; + for (i =3D 0; i < gpio->chip.ngpio; i +=3D 2) { /* set falling or level-low irq */ - iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type0)); + gpio->pdata->llops->reg_bit_set(gpio, i, reg_irq_type0, 0); /* trigger type is edge */ - iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1)); + gpio->pdata->llops->reg_bit_set(gpio, i, reg_irq_type1, 0); /* single edge trigger */ - iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type2)); + gpio->pdata->llops->reg_bit_set(gpio, i, reg_irq_type2, 0); } =20 return 0; --=20 2.34.1 From nobody Sat Feb 7 08:45:23 2026 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD57236075B; Fri, 23 Jan 2026 09:27:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160432; cv=none; b=pn7xE/+tmFNTGYV98zeye1wjZvDszigsiih7oHBgiq+nwV2roDuFnklIf3sgbODBOWgELpM++fNaLllVb1np/QPJjo5c1i2NUGaaxVvQNQjjEBYYZPAQl1FyPX2WC0CANHsEBW221r0LJ6NWjSS54etaH6VumQuUtWmA+K/krGk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160432; c=relaxed/simple; bh=OYQyaNUanZ/szVOiycqY145Jb/KVGUWm/mc3+XgZG6w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=tXnEM3rDJTb6ghx0eAhH2LbR+hjMluWvVpNZDiCh/PD0kzb6IpCj5+//pD0NmTc9EUWjvf3V7s58Uk748YG0FY2/BDuzFyGl3F0YyZiwsFwQUkPm3t3X4lTldZrqYULq+0oAeFAnIkvg18/y6SzHQMUarNLYHSG4mJ7oi/la0Mc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com 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.1748.10; Fri, 23 Jan 2026 17:26:27 +0800 Received: from [127.0.1.1] (192.168.10.13) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1748.10 via Frontend Transport; Fri, 23 Jan 2026 17:26:27 +0800 From: Billy Tsai Date: Fri, 23 Jan 2026 17:26:30 +0800 Subject: [PATCH v2 5/6] dt-bindings: gpio: aspeed,sgpio: Support ast2700 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20260123-upstream_sgpio-v2-5-69cfd1631400@aspeedtech.com> References: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> In-Reply-To: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> To: Linus Walleij , Bartosz Golaszewski , Joel Stanley , Andrew Jeffery , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: , , , , "Andrew Jeffery" , , , Billy Tsai , "Krzysztof Kozlowski" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1769160386; l=1452; i=billy_tsai@aspeedtech.com; s=20251118; h=from:subject:message-id; bh=OYQyaNUanZ/szVOiycqY145Jb/KVGUWm/mc3+XgZG6w=; b=VR/6NrxX2u5NjM3K8c6vXsi9KCB2tRBkKiyvhKw5FtnZxjYkpWWICR6Q7XiO80MXlaG/NgSGU lNfThdxLSPjAhGQCLHzTpsLj2b2Q7iHdkVl6VaZUEW8DsGoLzKIKlyn X-Developer-Key: i=billy_tsai@aspeedtech.com; a=ed25519; pk=/A8qvgZ6CPfnwKgT6/+k+nvXOkN477MshEGJvVdzeeQ= The AST2700 is the 7th generation SoC from Aspeed, featuring two SGPIO master controllers: both with 256 serial inputs and outputs. Acked-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Billy Tsai --- Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml b/Doc= umentation/devicetree/bindings/gpio/aspeed,sgpio.yaml index 1046f0331c09..974185e3478f 100644 --- a/Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml +++ b/Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml @@ -10,7 +10,8 @@ maintainers: - Andrew Jeffery =20 description: - This SGPIO controller is for ASPEED AST2400, AST2500 and AST2600 SoC, + This SGPIO controller is for ASPEED AST2400, AST2500, AST2600 and AST270= 0 SoC, + AST2700 have two sgpio master both with 256 pins, AST2600 have two sgpio master one with 128 pins another one with 80 pins, AST2500/AST2400 have one sgpio master with 80 pins. Each of the Serial GPIO pins can be programmed to support the following options @@ -27,6 +28,7 @@ properties: - aspeed,ast2400-sgpio - aspeed,ast2500-sgpio - aspeed,ast2600-sgpiom + - aspeed,ast2700-sgpiom =20 reg: maxItems: 1 --=20 2.34.1 From nobody Sat Feb 7 08:45:23 2026 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CDB7E366075; Fri, 23 Jan 2026 09:27:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160438; cv=none; b=kDWp8chQf5uVpNmTRuSW2458EFoFd8Ub4S8iVZ3THIAQvRbO92xPwnmTDyC5DneR5KjleOKtBf/nrzvWX2RmCE4qEg+FqDcEXZKt72Tm1Bo6/OaPURceCEcmK14mg9o4CIFqq44M4pus816CCg+j6r6UIZnGzH8kvf66//Ho05M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769160438; c=relaxed/simple; bh=Yc0Am0JOK83f2qlQR8wy0adnCkIm88yQxe8eRCbOxTw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=C9rZCZQ4etOE8C6RRxQMvDyMTbJLSS4u5cXVLABhLQkXauhGSXqzUr67mY8lCrlWZTHnLf+KoDRB01hmoc6h15hV0egMiC0fEz2TGihjMQqxalhpgrZo+BTdu9k9hdMWPW9omaucNrIwudaGX2oku4wOM0zQK6RDN0dAPqm5iAw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com 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.1748.10; Fri, 23 Jan 2026 17:26:27 +0800 Received: from [127.0.1.1] (192.168.10.13) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1748.10 via Frontend Transport; Fri, 23 Jan 2026 17:26:27 +0800 From: Billy Tsai Date: Fri, 23 Jan 2026 17:26:31 +0800 Subject: [PATCH v2 6/6] gpio: aspeed-sgpio: Support G7 Aspeed sgpiom controller Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20260123-upstream_sgpio-v2-6-69cfd1631400@aspeedtech.com> References: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> In-Reply-To: <20260123-upstream_sgpio-v2-0-69cfd1631400@aspeedtech.com> To: Linus Walleij , Bartosz Golaszewski , Joel Stanley , Andrew Jeffery , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: , , , , "Andrew Jeffery" , , , Billy Tsai X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1769160386; l=5872; i=billy_tsai@aspeedtech.com; s=20251118; h=from:subject:message-id; bh=Yc0Am0JOK83f2qlQR8wy0adnCkIm88yQxe8eRCbOxTw=; b=qDEskd91oEVv3mtQ7vh96cpdr2vm6lBb1mwHJDfrJmAukdsk6JrYvA9PUjH5GxI1Rikq2++1z jOWA1tTl43NCaSCKupaIC6opihZ2EYMQNMir4ljwlIbTtckHZ+MwOMJ X-Developer-Key: i=billy_tsai@aspeedtech.com; a=ed25519; pk=/A8qvgZ6CPfnwKgT6/+k+nvXOkN477MshEGJvVdzeeQ= In the 7th generation of the SoC from Aspeed, the control logic of the SGPIO controller has been updated to support per-pin control. Each pin now has its own 32-bit register, allowing for individual control of the pin's value, interrupt type, and other settings. Reviewed-by: Linus Walleij Signed-off-by: Billy Tsai --- drivers/gpio/gpio-aspeed-sgpio.c | 110 +++++++++++++++++++++++++++++++++++= +++- 1 file changed, 108 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sg= pio.c index b5270e11b153..4225261f61c8 100644 --- a/drivers/gpio/gpio-aspeed-sgpio.c +++ b/drivers/gpio/gpio-aspeed-sgpio.c @@ -19,7 +19,31 @@ #include #include =20 -#define ASPEED_SGPIO_CTRL 0x54 +#define SGPIO_G7_IRQ_STS_BASE 0x40 +#define SGPIO_G7_IRQ_STS_OFFSET(x) (SGPIO_G7_IRQ_STS_BASE + (x) * 0x4) +#define SGPIO_G7_CTRL_REG_BASE 0x80 +#define SGPIO_G7_CTRL_REG_OFFSET(x) (SGPIO_G7_CTRL_REG_BASE + (x) * 0x4) +#define SGPIO_G7_OUT_DATA BIT(0) +#define SGPIO_G7_PARALLEL_OUT_DATA BIT(1) +#define SGPIO_G7_IRQ_EN BIT(2) +#define SGPIO_G7_IRQ_TYPE0 BIT(3) +#define SGPIO_G7_IRQ_TYPE1 BIT(4) +#define SGPIO_G7_IRQ_TYPE2 BIT(5) +#define SGPIO_G7_RST_TOLERANCE BIT(6) +#define SGPIO_G7_INPUT_MASK BIT(9) +#define SGPIO_G7_HW_BYPASS_EN BIT(10) +#define SGPIO_G7_HW_IN_SEL BIT(11) +#define SGPIO_G7_IRQ_STS BIT(12) +#define SGPIO_G7_IN_DATA BIT(13) +#define SGPIO_G7_PARALLEL_IN_DATA BIT(14) +#define SGPIO_G7_SERIAL_OUT_SEL GENMASK(17, 16) +#define SGPIO_G7_PARALLEL_OUT_SEL GENMASK(19, 18) +#define SELECT_FROM_CSR 0 +#define SELECT_FROM_PARALLEL_IN 1 +#define SELECT_FROM_SERIAL_IN 2 + +#define ASPEED_SGPIO_G4_CFG_OFFSET 0x54 +#define ASPEED_SGPIO_G7_CFG_OFFSET 0x0 =20 #define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16) #define ASPEED_SGPIO_ENABLE BIT(0) @@ -28,6 +52,7 @@ struct aspeed_sgpio_pdata { const u32 pin_mask; const struct aspeed_sgpio_llops *llops; + const u32 cfg_offset; }; =20 struct aspeed_sgpio { @@ -135,6 +160,30 @@ static void __iomem *aspeed_sgpio_g4_bank_reg(struct a= speed_sgpio *gpio, } } =20 +static u32 aspeed_sgpio_g7_reg_mask(const enum aspeed_sgpio_reg reg) +{ + switch (reg) { + case reg_val: + case reg_rdata: + return SGPIO_G7_OUT_DATA; + case reg_irq_enable: + return SGPIO_G7_IRQ_EN; + case reg_irq_type0: + return SGPIO_G7_IRQ_TYPE0; + case reg_irq_type1: + return SGPIO_G7_IRQ_TYPE1; + case reg_irq_type2: + return SGPIO_G7_IRQ_TYPE2; + case reg_irq_status: + return SGPIO_G7_IRQ_STS; + case reg_tolerance: + return SGPIO_G7_RST_TOLERANCE; + default: + WARN_ON_ONCE(1); + return 0; + } +} + #define GPIO_BANK(x) ((x) >> 6) #define GPIO_OFFSET(x) ((x) & GENMASK(5, 0)) #define GPIO_BIT(x) BIT(GPIO_OFFSET(x) >> 1) @@ -457,6 +506,7 @@ static const struct aspeed_sgpio_llops aspeed_sgpio_g4_= llops =3D { static const struct aspeed_sgpio_pdata ast2400_sgpio_pdata =3D { .pin_mask =3D GENMASK(9, 6), .llops =3D &aspeed_sgpio_g4_llops, + .cfg_offset =3D ASPEED_SGPIO_G4_CFG_OFFSET, }; =20 static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip, @@ -486,12 +536,68 @@ static int aspeed_sgpio_set_config(struct gpio_chip *= chip, unsigned int offset, static const struct aspeed_sgpio_pdata ast2600_sgpiom_pdata =3D { .pin_mask =3D GENMASK(10, 6), .llops =3D &aspeed_sgpio_g4_llops, + .cfg_offset =3D ASPEED_SGPIO_G4_CFG_OFFSET, +}; + +static void aspeed_sgpio_g7_reg_bit_set(struct aspeed_sgpio *gpio, unsigne= d int offset, + const enum aspeed_sgpio_reg reg, bool val) +{ + u32 mask =3D aspeed_sgpio_g7_reg_mask(reg); + void __iomem *addr =3D gpio->base + SGPIO_G7_CTRL_REG_OFFSET(offset >> 1); + u32 write_val; + + if (mask) { + write_val =3D (ioread32(addr) & ~(mask)) | field_prep(mask, val); + iowrite32(write_val, addr); + } +} + +static bool aspeed_sgpio_g7_reg_bit_get(struct aspeed_sgpio *gpio, unsigne= d int offset, + const enum aspeed_sgpio_reg reg) +{ + u32 mask =3D aspeed_sgpio_g7_reg_mask(reg); + void __iomem *addr; + + addr =3D gpio->base + SGPIO_G7_CTRL_REG_OFFSET(offset >> 1); + if (reg =3D=3D reg_val) + mask =3D SGPIO_G7_IN_DATA; + + if (mask) + return field_get(mask, ioread32(addr)); + else + return 0; +} + +static int aspeed_sgpio_g7_reg_bank_get(struct aspeed_sgpio *gpio, unsigne= d int offset, + const enum aspeed_sgpio_reg reg) +{ + void __iomem *addr; + + if (reg =3D=3D reg_irq_status) { + addr =3D gpio->base + SGPIO_G7_IRQ_STS_OFFSET(offset >> 6); + return ioread32(addr); + } else { + return -EOPNOTSUPP; + } +} + +static const struct aspeed_sgpio_llops aspeed_sgpio_g7_llops =3D { + .reg_bit_set =3D aspeed_sgpio_g7_reg_bit_set, + .reg_bit_get =3D aspeed_sgpio_g7_reg_bit_get, + .reg_bank_get =3D aspeed_sgpio_g7_reg_bank_get, +}; + +static const struct aspeed_sgpio_pdata ast2700_sgpiom_pdata =3D { + .pin_mask =3D GENMASK(11, 6), + .llops =3D &aspeed_sgpio_g7_llops, + .cfg_offset =3D ASPEED_SGPIO_G7_CFG_OFFSET, }; =20 static const struct of_device_id aspeed_sgpio_of_table[] =3D { { .compatible =3D "aspeed,ast2400-sgpio", .data =3D &ast2400_sgpio_pdata,= }, { .compatible =3D "aspeed,ast2500-sgpio", .data =3D &ast2400_sgpio_pdata,= }, { .compatible =3D "aspeed,ast2600-sgpiom", .data =3D &ast2600_sgpiom_pdat= a, }, + { .compatible =3D "aspeed,ast2700-sgpiom", .data =3D &ast2700_sgpiom_pdat= a, }, {} }; =20 @@ -562,7 +668,7 @@ static int aspeed_sgpio_probe(struct platform_device *p= dev) =20 gpio_cnt_regval =3D ((nr_gpios / 8) << ASPEED_SGPIO_PINS_SHIFT) & pin_mas= k; iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | gpio_cnt= _regval | - ASPEED_SGPIO_ENABLE, gpio->base + ASPEED_SGPIO_CTRL); + ASPEED_SGPIO_ENABLE, gpio->base + gpio->pdata->cfg_offset); =20 raw_spin_lock_init(&gpio->lock); =20 --=20 2.34.1