* [PATCH v3 2/3] i2c: xiic: defer RX_FULL until all trailing bytes are in FIFO
From: Abdurrahman Hussain @ 2026-05-13 10:09 UTC (permalink / raw)
To: Michal Simek, Andi Shyti
Cc: linux-arm-kernel, linux-i2c, linux-kernel, Abdurrahman Hussain
In-Reply-To: <20260513-i2c-xiic-v3-0-ccb3cf70ba03@nexthop.ai>
For the normal path of xiic_smbus_block_read_setup() (rxmsg_len less
than IIC_RX_FIFO_DEPTH), RFD was programmed to rxmsg_len - 2, which
fires the RX_FULL interrupt while the last payload byte is still in
flight. xiic_read_rx()'s bytes_rem == 1 branch then sets NACK on that
byte still on the wire, truncating the read in the PEC-enabled case.
Raise the threshold so RX_FULL fires only once every remaining byte
(payload plus optional PEC) is already buffered in the FIFO. That
routes the drain through xiic_read_rx()'s bytes_rem == 0 path, which
reads everything out and emits the stop cleanly. For the non-PEC path
the full payload is still read out through the same bytes_rem == 0
branch; the only user-visible change is that the controller waits one
extra byte-time before servicing the interrupt.
The deferred-fire formula is rxmsg_len + pec_len - 1, and the RFD
register at XIIC_RFD_REG_OFFSET is a 4-bit field. Widen the
chunk-vs-defer guard to (rxmsg_len + pec_len > IIC_RX_FIFO_DEPTH) so
the boundary case rxmsg_len == IIC_RX_FIFO_DEPTH with PEC enabled
cannot write 16 into that 4-bit register; it routes through the
chunked drain instead, which already caps RFD at IIC_RX_FIFO_DEPTH - 1.
Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
---
drivers/i2c/busses/i2c-xiic.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index d4308716d461..2bdba6c0931f 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -548,10 +548,11 @@ static void xiic_smbus_block_read_setup(struct xiic_i2c *i2c)
unsigned int pec_len = i2c->rx_msg->len - 1;
/* Set Receive fifo depth */
- if (rxmsg_len > IIC_RX_FIFO_DEPTH) {
+ if (rxmsg_len + pec_len > IIC_RX_FIFO_DEPTH) {
/*
- * When Rx msg len greater than or equal to Rx fifo capacity
- * Receive fifo depth should set to Rx fifo capacity minus 1
+ * Trailing payload (data + optional PEC) exceeds Rx FIFO
+ * capacity; drain in chunks. Fire RX_FULL when the FIFO is
+ * full and let the ISR re-arm for the remainder.
*/
rfd_set = IIC_RX_FIFO_DEPTH - 1;
i2c->rx_msg->len = rxmsg_len + 1 + pec_len;
@@ -572,11 +573,8 @@ static void xiic_smbus_block_read_setup(struct xiic_i2c *i2c)
i2c->rx_msg->len = SMBUS_BLOCK_READ_MIN_LEN;
i2c->smbus_actual_len = 1 + rxmsg_len + pec_len;
} else {
- /*
- * When Rx msg len less than Rx fifo capacity
- * Receive fifo depth should set to Rx msg len minus 2
- */
- rfd_set = rxmsg_len - 2;
+ /* Defer RX_FULL until all trailing bytes are in FIFO. */
+ rfd_set = rxmsg_len + pec_len - 1;
i2c->rx_msg->len = rxmsg_len + 1 + pec_len;
}
xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rfd_set);
--
2.53.0
^ permalink raw reply related
* [PATCH v3 3/3] i2c: xiic: don't clobber msg->len to signal block-read completion
From: Abdurrahman Hussain @ 2026-05-13 10:09 UTC (permalink / raw)
To: Michal Simek, Andi Shyti
Cc: linux-arm-kernel, linux-i2c, linux-kernel, Abdurrahman Hussain
In-Reply-To: <20260513-i2c-xiic-v3-0-ccb3cf70ba03@nexthop.ai>
At the end of a SMBus block read the BNB handler force-set
tx_msg->len = 1 to push xiic_tx_space() to zero so the STATE_DONE
branch would fire. Two problems:
1. tx_msg and rx_msg alias the same i2c_msg struct during a receive
(see xiic_start_recv), so overwriting tx_msg->len also changes
rx_msg->len. The i2c core's i2c_smbus_check_pec() then reads the
PEC from the wrong offset -- buf[0] instead of buf[rxmsg_len + 1]
-- and either mis-validates or returns -EBADMSG.
2. xiic_start_recv sets tx_pos = msg->len (typically 2 when PEC is
enabled). xiic_tx_space() is unsigned msg->len - tx_pos, so
setting msg->len = 1 with tx_pos = 2 underflows to 0xFFFFFFFF and
xiic_tx_space() never compares equal to 0 -- the STATE_DONE check
falls through to STATE_ERROR, giving -EIO.
Instead, advance tx_pos up to msg->len. That drives tx_space to 0
without touching msg->len, preserving the buffer length that
xiic_smbus_block_read_setup() already grew to cover the length byte,
the payload and the optional PEC byte.
Also clear smbus_actual_len here so a subsequent non-SMBus transfer
does not see a stale trim value from this completed block read.
Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
---
drivers/i2c/busses/i2c-xiic.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index 2bdba6c0931f..8eaa411411c1 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -889,8 +889,17 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
if (i2c->tx_msg && i2c->smbus_block_read) {
i2c->smbus_block_read = false;
- /* Set requested message len=1 to indicate STATE_DONE */
- i2c->tx_msg->len = 1;
+ /*
+ * Defensive: reset the per-transfer trim state in case
+ * the rx phase completed via an error path that
+ * skipped the trim site in the RX_FULL branch above.
+ */
+ i2c->smbus_actual_len = 0;
+ /*
+ * Drive xiic_tx_space() to 0 to signal STATE_DONE
+ * without truncating the rx_msg length.
+ */
+ i2c->tx_pos = i2c->tx_msg->len;
}
if (!i2c->tx_msg)
--
2.53.0
^ permalink raw reply related
* [PATCH v3 0/3] i2c: xiic: fix SMBus block read and PEC support
From: Abdurrahman Hussain @ 2026-05-13 10:09 UTC (permalink / raw)
To: Michal Simek, Andi Shyti
Cc: linux-arm-kernel, linux-i2c, linux-kernel, Abdurrahman Hussain
This series fixes three independent bugs in the Xilinx AXI IIC driver
that together make SMBus block reads with PEC return -EBADMSG or -EIO
on otherwise clean transfers. They only surface when the client has
I2C_CLIENT_PEC set; non-PEC block reads happen to mask each issue in
turn.
The problems were uncovered driving an adm1266 PMBus device behind a
Xilinx AXI IIC FPGA block and reading its 64-byte blackbox record.
Patch 1 stops xiic_smbus_block_read_setup() from truncating rx_msg->len.
The i2c core appends a byte to msg->len when PEC is enabled, so
overwriting the length to "block size + 1" silently drops the PEC byte
and i2c_smbus_check_pec() then reads the last payload byte as the PEC.
Patch 2 raises the RX_FULL threshold so the interrupt only fires once
every remaining byte (payload plus optional PEC) is already buffered in
the FIFO. The previous threshold of rxmsg_len - 2 caused the
bytes_rem == 1 path in xiic_read_rx() to NACK a byte still on the wire.
The chunk-vs-defer guard now also accounts for the PEC byte so a
rxmsg_len == IIC_RX_FIFO_DEPTH PEC-enabled read does not push
XIIC_RFD_REG_OFFSET past its 4-bit range.
Patch 3 stops the BNB handler from forcing tx_msg->len = 1 to signal
completion. tx_msg and rx_msg alias the same i2c_msg during a receive,
so this also clobbered rx_msg->len; and because tx_pos is already at 2
in the PEC case, the unsigned subtraction in xiic_tx_space() underflowed
and the STATE_DONE check fell through to STATE_ERROR. Advancing tx_pos
up to msg->len drives tx_space to zero without touching the length.
All three patches are pure bug fixes; non-PEC behaviour is unchanged.
Tested on real hardware -- a Xilinx AXI IIC controller talking to an
adm1266, where 64-byte PEC-checked block reads now complete cleanly.
Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
---
Changes in v3 (addresses the sashiko automated review of v2):
- Patch 1: handle short SMBus block reads where the controller pads
rx_msg->len up to SMBUS_BLOCK_READ_MIN_LEN for its end-of-message
workaround. In v2 this branch left the PEC byte at the padded
offset rather than the actual end-of-payload, so the i2c core's
PEC validator read past the chip data. Track the on-wire length
in a new smbus_actual_len field populated in the minlen branch
of xiic_smbus_block_read_setup(), and trim rx_msg->len back at
RX_FULL completion before passing the message up. Addresses
sashiko's v2 note about the pec_len adjustment missing the
rxmsg_len < 3 padding branch; that branch was indeed the cause
of pmbus_check_block_register() silently failing on zero-length
MFR_* fields and skipping debugfs auto-discovery on affected
hardware.
- Patch 3: defensively reset smbus_actual_len in the BNB completion
handler so a subsequent non-SMBus transfer cannot see a stale
trim value from a completed short block read.
- Patch 2 is unchanged from v2. sashiko's two other v2 notes were
investigated and judged not to require code changes: the concern
about removed padding in the chunked-vs-deferred drain misread
the patch (the padding survives via the else branch and the new
PEC-aware guard preserves the original semantics), and the
flagged unsigned underflow in xiic_tx_space() is unreachable
because tx_pos is bounded by tx_msg->len at the call site.
- Link to v2: https://patch.msgid.link/20260511-i2c-xiic-v2-0-c16380cb1594@nexthop.ai
Changes in v2:
- Patch 2: widen the chunk-vs-defer guard in xiic_smbus_block_read_setup()
to include pec_len, so a 16-byte PEC-enabled block read routes through
the chunked drain rather than writing 16 into the 4-bit
XIIC_RFD_REG_OFFSET register. No tree-level change to patches 1 or 3.
- Link to v1: https://patch.msgid.link/20260427-i2c-xiic-v1-0-e6207f9aa5ad@nexthop.ai
To: Michal Simek <michal.simek@amd.com>
To: Andi Shyti <andi.shyti@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-i2c@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
Abdurrahman Hussain (3):
i2c: xiic: preserve PEC byte length in SMBus block read setup
i2c: xiic: defer RX_FULL until all trailing bytes are in FIFO
i2c: xiic: don't clobber msg->len to signal block-read completion
drivers/i2c/busses/i2c-xiic.c | 67 ++++++++++++++++++++++++++++++++-----------
1 file changed, 50 insertions(+), 17 deletions(-)
---
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
change-id: 20260427-i2c-xiic-2aeb501ec02a
Best regards,
--
Abdurrahman Hussain <abdurrahman@nexthop.ai>
^ permalink raw reply
* [PATCH 3/3] arm64: dts: imx93-11x11-evk: Add DY1212W-4856 LVDS panel
From: Liu Ying @ 2026-05-13 10:02 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Liu Ying
In-Reply-To: <20260513-imx93-ldb-v1-0-d11c5c3cc197@nxp.com>
DY1212W-4856 [1] is a 12.1" (WXGA) TFT LCD panel with LVDS interface.
The panel's 40-pin connector allows it to be directly connected to
i.MX93 11x11 EVK board.
Link: https://www.nxp.com/design/design-center/development-boards-and-designs/dy1212w-4856-tft-lcd-panel-with-lvds-interface:DY1212W-4856 [1]
Signed-off-by: Liu Ying <victor.liu@nxp.com>
---
arch/arm64/boot/dts/freescale/Makefile | 4 ++
.../freescale/imx93-11x11-evk-dy1212w-4856.dtso | 81 ++++++++++++++++++++++
2 files changed, 85 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index d1bb303962db..42f655986987 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -467,6 +467,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-9x9-qsb-i3c.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93-9x9-qsb-ontat-kd50g21-40nt-a1.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-evk.dtb
+
+imx93-11x11-evk-dy1212w-4856-dtbs += imx93-11x11-evk.dtb imx93-11x11-evk-dy1212w-4856.dtbo
+dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-evk-dy1212w-4856.dtb
+
dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-frdm.dtb
imx93-11x11-frdm-pixpaper-dtbs += imx93-11x11-frdm.dtb imx93-11x11-frdm-pixpaper.dtbo
diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-dy1212w-4856.dtso b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-dy1212w-4856.dtso
new file mode 100644
index 000000000000..35f7c5699e3a
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-dy1212w-4856.dtso
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2026 NXP
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/imx93-clock.h>
+
+&{/} {
+ panel-lvds {
+ compatible = "boe,ev121wxm-n10-1850";
+ backlight = <&backlight_lvds>;
+ power-supply = <&buck4>;
+
+ panel-timing {
+ /*
+ * Set clock frequency to 71142858Hz to accommodate
+ * IMX93_CLK_VIDEO_PLL rate at 498000000Hz in a rate
+ * table.
+ */
+ clock-frequency = <71142858>;
+ hactive = <1280>;
+ vactive = <800>;
+ hfront-porch = <48>;
+ hback-porch = <80>;
+ hsync-len = <32>;
+ vfront-porch = <3>;
+ vback-porch = <14>;
+ vsync-len = <6>;
+ };
+
+ port {
+ panel_lvds_in: endpoint {
+ remote-endpoint = <&ldb_lvds_ch0>;
+ };
+ };
+ };
+};
+
+&backlight_lvds {
+ status = "okay";
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&lvds_bridge {
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ reg = <1>;
+
+ ldb_lvds_ch0: endpoint {
+ remote-endpoint = <&panel_lvds_in>;
+ };
+ };
+ };
+};
+
+&media_blk_ctrl {
+ assigned-clocks = <&clk IMX93_CLK_MEDIA_AXI>,
+ <&clk IMX93_CLK_MEDIA_APB>,
+ <&clk IMX93_CLK_MEDIA_DISP_PIX>,
+ <&clk IMX93_CLK_VIDEO_PLL>;
+ assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1>,
+ <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>,
+ <&clk IMX93_CLK_VIDEO_PLL>;
+ /*
+ * Set IMX93_CLK_MEDIA_DISP_PIX rate to 71142858Hz to accommodate
+ * IMX93_CLK_VIDEO_PLL rate at 498000000Hz in a rate table.
+ */
+ assigned-clock-rates = <400000000>, <133333333>, <71142858>, <498000000>;
+ status = "okay";
+};
--
2.43.0
^ permalink raw reply related
* [PATCH 2/3] arm64: dts: imx93: Add LVDS Display Bridge support
From: Liu Ying @ 2026-05-13 10:02 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Liu Ying
In-Reply-To: <20260513-imx93-ldb-v1-0-d11c5c3cc197@nxp.com>
Add LVDS Display Bridge(LDB) child node to mediamix blk-ctrl node
so that video could be output through a LVDS interface.
Signed-off-by: Liu Ying <victor.liu@nxp.com>
---
arch/arm64/boot/dts/freescale/imx93.dtsi | 37 ++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi
index b9abe143cb56..79fb4a15b733 100644
--- a/arch/arm64/boot/dts/freescale/imx93.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93.dtsi
@@ -178,6 +178,7 @@ &lcdif {
port {
lcdif_to_ldb: endpoint@1 {
reg = <1>;
+ remote-endpoint = <&ldb_from_lcdif>;
};
lcdif_to_dsi: endpoint@2 {
@@ -186,6 +187,42 @@ lcdif_to_dsi: endpoint@2 {
};
};
+&media_blk_ctrl {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ lvds_bridge: bridge@20 {
+ compatible = "fsl,imx93-ldb";
+ reg = <0x20 0x4>, <0x24 0x4>;
+ reg-names = "ldb", "lvds";
+ clocks = <&clk IMX93_CLK_LVDS_GATE>;
+ clock-names = "ldb";
+ assigned-clocks = <&clk IMX93_CLK_MEDIA_LDB>;
+ assigned-clock-parents = <&clk IMX93_CLK_VIDEO_PLL>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ ldb_from_lcdif: endpoint {
+ remote-endpoint = <&lcdif_to_ldb>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ ldb_lvds_ch0: endpoint {
+ };
+ };
+ };
+ };
+};
+
&src {
mlmix: power-domain@44461800 {
compatible = "fsl,imx93-src-slice";
--
2.43.0
^ permalink raw reply related
* [PATCH 1/3] dt-bindings: soc: imx: fsl,imx93-media-blk-ctrl: Allow LVDS Display Bridge child node
From: Liu Ying @ 2026-05-13 10:02 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Liu Ying
In-Reply-To: <20260513-imx93-ldb-v1-0-d11c5c3cc197@nxp.com>
i.MX93 SoC mediamix blk-ctrl contains one LDB_CTRL register and one LVDS
register which control video output through a LVDS interface. Allow the
LVDS Display Bridge(LDB) child node and add the child node to example.
Signed-off-by: Liu Ying <victor.liu@nxp.com>
---
.../bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml | 38 ++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
index d828c2e82965..ab563b457e07 100644
--- a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
+++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
@@ -26,6 +26,12 @@ properties:
reg:
maxItems: 1
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 1
+
'#power-domain-cells':
const: 1
@@ -92,6 +98,11 @@ properties:
- compatible
- ports
+ bridge@20:
+ type: object
+ $ref: /schemas/display/bridge/fsl,ldb.yaml#
+ unevaluatedProperties: false
+
allOf:
- if:
properties:
@@ -163,6 +174,8 @@ examples:
<&clk IMX93_CLK_MIPI_DSI_GATE>;
clock-names = "apb", "axi", "nic", "disp", "cam",
"pxp", "lcdif", "isi", "csi", "dsi";
+ #address-cells = <1>;
+ #size-cells = <1>;
#power-domain-cells = <1>;
dpi-bridge {
@@ -190,4 +203,29 @@ examples:
};
};
};
+
+ bridge@20 {
+ compatible = "fsl,imx93-ldb";
+ reg = <0x20 0x4>, <0x24 0x4>;
+ reg-names = "ldb", "lvds";
+ clocks = <&clk IMX93_CLK_LVDS_GATE>;
+ clock-names = "ldb";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&lcdif_to_ldb>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ };
+ };
+ };
};
--
2.43.0
^ permalink raw reply related
* [PATCH 0/3] arm64: dts: imx93-11x11-evk: Add DY1212W-4856 LVDS panel
From: Liu Ying @ 2026-05-13 10:02 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Liu Ying
Hi,
This patch series aims to add DY1212W-4856 [1] LVDS panel to i.MX93 11x11
EVK board.
Patch 1 allows LVDS Display Bridge (LDB) child node in i.MX93 mediamix
blk-ctrl DT binding.
Patch 2 adds LDB child node to mediamix blk-ctrl node in imx93.dtsi.
Patch 3 adds a DT overlay to support the DY1212W-4856 LVDS panel on
i.MX93 11x11 EVK board.
[1] https://www.nxp.com/design/design-center/development-boards-and-designs/dy1212w-4856-tft-lcd-panel-with-lvds-interface:DY1212W-4856
Signed-off-by: Liu Ying <victor.liu@nxp.com>
---
Liu Ying (3):
dt-bindings: soc: imx: fsl,imx93-media-blk-ctrl: Allow LVDS Display Bridge child node
arm64: dts: imx93: Add LVDS Display Bridge support
arm64: dts: imx93-11x11-evk: Add DY1212W-4856 LVDS panel
.../bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml | 38 ++++++++++
arch/arm64/boot/dts/freescale/Makefile | 4 ++
.../freescale/imx93-11x11-evk-dy1212w-4856.dtso | 81 ++++++++++++++++++++++
arch/arm64/boot/dts/freescale/imx93.dtsi | 37 ++++++++++
4 files changed, 160 insertions(+)
---
base-commit: e98d21c170b01ddef366f023bbfcf6b31509fa83
change-id: 20260513-imx93-ldb-c5a4194e41ce
Best regards,
--
Regards,
Liu Ying
^ permalink raw reply
* Re: [PATCH] coresight: trbe: Hide enable_sink sysfs file
From: Leo Yan @ 2026-05-13 9:54 UTC (permalink / raw)
To: James Clark
Cc: Suzuki K Poulose, Mike Leach, Alexander Shishkin, coresight,
linux-arm-kernel, linux-kernel
In-Reply-To: <cfb27efd-4887-4d47-8b38-99fc2d7bcfac@linaro.org>
On Wed, May 13, 2026 at 10:33:40AM +0100, James Clark wrote:
[...]
> > > +static umode_t coresight_attr_is_visible(struct kobject *kobj,
> > > + struct attribute *attr, int n)
> > > {
> > > struct device *dev = kobj_to_dev(kobj);
> > > + struct coresight_device *csdev = to_coresight_device(dev);
> > > if (attr == &dev_attr_label.attr) {
> > > if (fwnode_property_present(dev_fwnode(dev), "label"))
> > > return attr->mode;
> > > else
> > > return 0;
> > > + } else if (attr == &dev_attr_enable_sink.attr ||
> > > + attr == &dev_attr_enable_source.attr) {
> > > + if (csdev->no_sysfs_mode)
> > > + return 0;
> > > + else
> > > + return attr->mode;
> >
> > I'd prefer no_sysfs_mode to work as a general flag rather than being
> > limited to sink/source devices only. Otherwise, LGTM.
>
> Which other files would you hide though? These are the only two that I could
> think of.
>
> I wouldn't hide all sysfs files for 'no_sysfs_mode' as there are read only
> things that aren't strictly related to sysfs mode.
In coresight-sysfs.c, there are two kinds of attributes: the label and
the sink/source enable knobs.
The label is already handled separately. So we can hide the rest
attributes when no_sysfs_mode is set?
Thanks,
Leo
^ permalink raw reply
* [PATCH] iio: adc: sun20i-gpadc: support non-contiguous channel lookups
From: Michal Piekos @ 2026-05-13 9:51 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: linux-iio, linux-arm-kernel, linux-sunxi, linux-kernel,
Michal Piekos
Using consumer driver like iio-hwmon which resolve channels thorugh
io-channels phandles will fail for sparse channels because IIO core
threats phandle argument as index into channel array.
eg. <&gpadc 1> will fail if there is only channel@1 specified
Add fwnode_xlate which maps DT phandle to the registered channel whose
chan->channel matches the hardware channel number. It allows sparse
channel maps to be consumed by drivers like iio-hwmon.
Tested on Radxa Cubie A5E.
Signed-off-by: Michal Piekos <michal.piekos@mmpsystems.pl>
---
drivers/iio/adc/sun20i-gpadc-iio.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index 861c14da75ad..95f34a352158 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -139,8 +139,21 @@ static irqreturn_t sun20i_gpadc_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
+static int sun20i_gpadc_fwnode_xlate(struct iio_dev *indio_dev,
+ const struct fwnode_reference_args *iiospec)
+{
+ int i;
+
+ for (i = 0; i < indio_dev->num_channels; i++)
+ if (indio_dev->channels[i].channel == iiospec->args[0])
+ return i;
+
+ return -EINVAL;
+}
+
static const struct iio_info sun20i_gpadc_iio_info = {
.read_raw = sun20i_gpadc_read_raw,
+ .fwnode_xlate = sun20i_gpadc_fwnode_xlate,
};
static void sun20i_gpadc_reset_assert(void *data)
---
base-commit: 1d5dcaa3bd65f2e8c9baa14a393d3a2dc5db7524
change-id: 20260513-fix-sunxi-gpadc-sparse-channels-2b6b2063bd49
Best regards,
--
Michal Piekos <michal.piekos@mmpsystems.pl>
^ permalink raw reply related
* Re: [PATCH v4 2/2] coco: guest: arm64: Drop dummy RSI platform device stub
From: Aneesh Kumar K.V @ 2026-05-13 9:51 UTC (permalink / raw)
To: Greg KH
Cc: Catalin Marinas, linux-kernel, linux-arm-kernel, Jeremy Linton,
Jonathan Cameron, Lorenzo Pieralisi, Mark Rutland, Sudeep Holla,
Will Deacon, Jonathan Cameron, Suzuki K Poulose
In-Reply-To: <yq5a4ikbu1w2.fsf@kernel.org>
Aneesh Kumar K.V <aneesh.kumar@kernel.org> writes:
> Greg KH <gregkh@linuxfoundation.org> writes:
>
>> On Wed, May 13, 2026 at 12:28:12PM +0530, Aneesh Kumar K.V wrote:
>>> Catalin Marinas <catalin.marinas@arm.com> writes:
>>>
>>> > + Suzuki again
>>> >
>>> > On Mon, Apr 27, 2026 at 11:46:15AM +0530, Aneesh Kumar K.V (Arm) wrote:
>>> >> The SMCCC firmware driver now creates the `arm-smccc` platform device
>>> >> and also creates the CCA auxiliary devices once the RSI ABI is
>>> >> discovered. This makes the arch-specific arm64_create_dummy_rsi_dev()
>>> >> helper redundant. Remove the arm-cca-dev platform device registration
>>> >> and let the SMCCC probe manage the RSI device.
>>> >>
>>> >> systemd match on platform:arm-cca-dev for confidential vm detection [1].
>>> >> Losing the platform device registration can break that. Keeping this
>>> >> removal in its own change makes it easy to revert if that regression
>>> >> blocks the rollout.
>>> >>
>>> >> [1] https://lore.kernel.org/all/4a7d84b2-2ec4-4773-a2d5-7b63d5c683cf@arm.com
>>> >
>>> > I wouldn't merge this now given that systemd checks this file. Could we
>>> > have a symbolic link instead for some time until systemd eventually gets
>>> > updated (years?).
>>> >
>>>
>>> I’ll add this in the next revision.
>>>
>>> static int create_rsi_compat_link(struct device *target_dev)
>>> {
>>> struct kobject *platform_kobj;
>>> /*
>>> * target_dev is:
>>> * /sys/devices/platform/arm-smccc/arm_cca_guest.arm-rsi-dev.0
>>> * Create compat link /sys/devices/platform/arm-cca-dev
>>> */
>>> platform_kobj = target_dev->kobj.parent->parent;
>>
>> What? That is crazy, you don't know that is always going to be ok.
>>
>>> return sysfs_create_link(platform_kobj,
>>> &target_dev->kobj,
>>> "arm-cca-dev");
>>
>> No, don't do that, if a driver calls a sysfs* function, something is
>> almost always wrong. Don't be making random sysfs symlinks please.
>>
>
> Sure, but could you explain why this is wrong? Below is the full version
> of the updated patch.
>
> coco: guest: arm64 Replace RSI platform device with compat symlink
>
> The SMCCC firmware driver now creates the arm-smccc platform device and
> registers the RSI device as an auxiliary device once the RSI ABI has been
> discovered. This makes the arch-specific arm64 arm-cca-dev platform device
> redundant.
>
> Remove the arm64 platform device stub and let the SMCCC core manage RSI
> device creation.
>
> This changes the real device location from the old platform device path to:
>
> /sys/devices/platform/arm-smccc/arm_cca_guest.arm-rsi-dev.0
>
> Keep userspace compatibility by creating a sysfs symlink at the old path:
>
> /sys/devices/platform/arm-cca-dev
>
> A Debian Code Search check found systemd matching on the old
> platform:arm-cca-dev device path for confidential VM detection. No other
> userspace dependency on the old platform device path was found, but keeping
> the compatibility symlink avoids breaking existing systemd-based detection
> [1].
>
> [1] https://lore.kernel.org/all/4a7d84b2-2ec4-4773-a2d5-7b63d5c683cf@arm.com
>
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
>
> modified arch/arm64/kernel/rsi.c
> @@ -159,18 +159,3 @@ void __init arm64_rsi_init(void)
>
> static_branch_enable(&rsi_present);
> }
> -
> -static struct platform_device rsi_dev = {
> - .name = "arm-cca-dev",
> - .id = PLATFORM_DEVID_NONE
> -};
> -
> -static int __init arm64_create_dummy_rsi_dev(void)
> -{
> - if (is_realm_world() &&
> - platform_device_register(&rsi_dev))
> - pr_err("failed to register rsi platform device\n");
> - return 0;
> -}
> -
> -arch_initcall(arm64_create_dummy_rsi_dev)
> modified drivers/firmware/smccc/rmm.c
> @@ -4,13 +4,31 @@
> */
>
> #include <linux/auxiliary_bus.h>
> +#include <linux/sysfs.h>
> +#include <linux/device.h>
>
> #include "rmm.h"
>
> +static int create_rsi_compat_link(struct device *target_dev)
> +{
> + struct kobject *platform_kobj;
> + /*
> + * target_dev is:
> + * /sys/devices/platform/arm-smccc/arm_cca_guest.arm-rsi-dev.0
> + * Create compat link /sys/devices/platform/arm-cca-dev
> + */
> + platform_kobj = target_dev->kobj.parent->parent;
> +
> + return sysfs_create_link(platform_kobj,
> + &target_dev->kobj,
> + "arm-cca-dev");
> +}
> +
> void __init register_rsi_device(struct platform_device *pdev)
> {
> unsigned long ret;
> unsigned long ver_lower, ver_higher;
> + struct auxiliary_device *adev;
>
> if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
> return;
> @@ -19,6 +37,10 @@ void __init register_rsi_device(struct platform_device *pdev)
> if (ret != RSI_SUCCESS)
> return;
>
> - __devm_auxiliary_device_create(&pdev->dev,
> - "arm_cca_guest", RSI_DEV_NAME, NULL, 0);
> + adev = __devm_auxiliary_device_create(&pdev->dev,
> + "arm_cca_guest", RSI_DEV_NAME, NULL, 0);
> + if (!adev)
> + return;
> +
> + create_rsi_compat_link(&adev->dev);
> }
To make this clear, the above implies that adev parent is a platform
device and hence target_dev->kobj.parent->parent should be platform
kobject?
>
>
>>
>> If userspace can not find the device anymore, that's fine, that's how
>> sysfs works, devices move around all the time. Especially platform
>> devices as those are almost always not supposed to be platform devices :)
>>
>> thanks,
>>
>> greg k-h
>
-aneesh
^ permalink raw reply
* [PATCH v2 2/6] devfreq: Use mutex guard in devfreq_add/remove_governor()
From: Jie Zhan @ 2026-05-13 9:38 UTC (permalink / raw)
To: cwchoi00, cw00.choi, myungjoo.ham, kyungmin.park, linux-pm,
linux-arm-kernel
Cc: linuxarm, tianyaxiong, zhanjie9, zhenglifeng1, zhangpengjie2,
lihuisong, prime.zeng
In-Reply-To: <20260513093832.1645890-1-zhanjie9@hisilicon.com>
Use mutex guard in devfreq_add/remove_governor() so as to simplify the
locking logic.
No functional impact intended.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 22 +++++++---------------
1 file changed, 7 insertions(+), 15 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 7a70dd051644..53c40d795a13 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1261,28 +1261,23 @@ void devfreq_resume(void)
int devfreq_add_governor(struct devfreq_governor *governor)
{
struct devfreq_governor *g;
- int err = 0;
if (!governor) {
pr_err("%s: Invalid parameters.\n", __func__);
return -EINVAL;
}
- mutex_lock(&devfreq_list_lock);
+ guard(mutex)(&devfreq_list_lock);
g = find_devfreq_governor(governor->name);
if (!IS_ERR(g)) {
pr_err("%s: governor %s already registered\n", __func__,
g->name);
- err = -EINVAL;
- goto err_out;
+ return -EINVAL;
}
list_add(&governor->node, &devfreq_governor_list);
-err_out:
- mutex_unlock(&devfreq_list_lock);
-
- return err;
+ return 0;
}
EXPORT_SYMBOL(devfreq_add_governor);
@@ -1320,21 +1315,20 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
{
struct devfreq_governor *g;
struct devfreq *devfreq;
- int err = 0;
if (!governor) {
pr_err("%s: Invalid parameters.\n", __func__);
return -EINVAL;
}
- mutex_lock(&devfreq_list_lock);
+ guard(mutex)(&devfreq_list_lock);
g = find_devfreq_governor(governor->name);
if (IS_ERR(g)) {
pr_err("%s: governor %s not registered\n", __func__,
governor->name);
- err = PTR_ERR(g);
- goto err_out;
+ return PTR_ERR(g);
}
+
list_for_each_entry(devfreq, &devfreq_list, node) {
int ret;
struct device *dev = devfreq->dev.parent;
@@ -1356,10 +1350,8 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
}
list_del(&governor->node);
-err_out:
- mutex_unlock(&devfreq_list_lock);
- return err;
+ return 0;
}
EXPORT_SYMBOL(devfreq_remove_governor);
--
2.43.0
^ permalink raw reply related
* [PATCH v2 5/6] devfreq: Get and put module refcount when switching governor
From: Jie Zhan @ 2026-05-13 9:38 UTC (permalink / raw)
To: cwchoi00, cw00.choi, myungjoo.ham, kyungmin.park, linux-pm,
linux-arm-kernel
Cc: linuxarm, tianyaxiong, zhanjie9, zhenglifeng1, zhangpengjie2,
lihuisong, prime.zeng
In-Reply-To: <20260513093832.1645890-1-zhanjie9@hisilicon.com>
A governor module can be dynamically inserted or removed if compiled as a
kernel module. 'devfreq->governor' would become NULL if the governor
module is removed when it's in use.
To prevent the governor module from being removed (except for force
unload) when it's in use, get and put a refcount of the governor module
when starting and stopping the governor.
As a result, unloading a governor module in use returns an error, e.g.:
$ cat governor
performance
$ rmmod governor_performance
rmmod: ERROR: Module governor_performance is in use
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index e1363ab69173..2ea42325d030 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -345,24 +345,37 @@ static int devfreq_set_governor(struct devfreq *df,
__func__, df->governor->name, ret);
return ret;
}
+ module_put(old_gov->owner);
}
/* Start the new governor */
+ if (!try_module_get(new_gov->owner)) {
+ df->governor = NULL;
+ return -EINVAL;
+ }
+
df->governor = new_gov;
ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
if (ret) {
dev_warn(dev, "%s: Governor %s not started(%d)\n",
__func__, df->governor->name, ret);
+ module_put(new_gov->owner);
/* Restore previous governor */
df->governor = old_gov;
if (!df->governor)
return ret;
+ if (!try_module_get(old_gov->owner)) {
+ df->governor = NULL;
+ return -EINVAL;
+ }
+
ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
if (ret) {
dev_err(dev, "%s: restore Governor %s failed (%d)\n",
__func__, df->governor->name, ret);
+ module_put(old_gov->owner);
df->governor = NULL;
return ret;
}
@@ -1040,9 +1053,11 @@ int devfreq_remove_device(struct devfreq *devfreq)
devfreq_cooling_unregister(devfreq->cdev);
- if (devfreq->governor)
+ if (devfreq->governor) {
devfreq->governor->event_handler(devfreq,
DEVFREQ_GOV_STOP, NULL);
+ module_put(devfreq->governor->owner);
+ }
device_unregister(&devfreq->dev);
return 0;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 3/6] devfreq: Factor out devfreq_set_governor()
From: Jie Zhan @ 2026-05-13 9:38 UTC (permalink / raw)
To: cwchoi00, cw00.choi, myungjoo.ham, kyungmin.park, linux-pm,
linux-arm-kernel
Cc: linuxarm, tianyaxiong, zhanjie9, zhenglifeng1, zhangpengjie2,
lihuisong, prime.zeng
In-Reply-To: <20260513093832.1645890-1-zhanjie9@hisilicon.com>
Factor out common governor setting logic into devfreq_set_governor() so as
to consolidate the code in governor_store() and devfreq_add_device().
The caller is expected to hold 'devfreq_list_lock', enforced via
lockdep_assert_held(). This is required because devfreq_add_device() must
hold the lock from setting governor until the device is added to
'devfreq_list', so that a concurrent devfreq_remove_governor() cannot free
the governor in between.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 117 ++++++++++++++++++--------------------
1 file changed, 56 insertions(+), 61 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 53c40d795a13..9e3e6a7348f8 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -318,6 +318,59 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
return governor;
}
+static int devfreq_set_governor(struct devfreq *df,
+ const struct devfreq_governor *new_gov)
+{
+ const struct devfreq_governor *old_gov;
+ struct device *dev;
+ int ret;
+
+ lockdep_assert_held(&devfreq_list_lock);
+
+ old_gov = df->governor;
+ dev = &df->dev;
+
+ if (old_gov) {
+ if (old_gov == new_gov)
+ return 0;
+
+ if (IS_SUPPORTED_FLAG(old_gov->flags, IMMUTABLE) ||
+ IS_SUPPORTED_FLAG(new_gov->flags, IMMUTABLE))
+ return -EINVAL;
+
+ /* Stop the current governor */
+ ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
+ if (ret) {
+ dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
+ __func__, df->governor->name, ret);
+ return ret;
+ }
+ }
+
+ /* Start the new governor */
+ df->governor = new_gov;
+ ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
+ if (ret) {
+ dev_warn(dev, "%s: Governor %s not started(%d)\n",
+ __func__, df->governor->name, ret);
+
+ /* Restore previous governor */
+ df->governor = old_gov;
+ if (!df->governor)
+ return ret;
+
+ ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
+ if (ret) {
+ dev_err(dev, "%s: restore Governor %s failed (%d)\n",
+ __func__, df->governor->name, ret);
+ df->governor = NULL;
+ return ret;
+ }
+ }
+
+ return sysfs_update_group(&df->dev.kobj, &gov_attr_group);
+}
+
static int devfreq_notify_transition(struct devfreq *devfreq,
struct devfreq_freqs *freqs, unsigned int state)
{
@@ -942,9 +995,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
goto err_init;
}
- devfreq->governor = governor;
- err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
- NULL);
+ err = devfreq_set_governor(devfreq, governor);
if (err) {
dev_err_probe(dev, err,
"%s: Unable to start governor for the device\n",
@@ -952,10 +1003,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
goto err_init;
}
- err = sysfs_update_group(&devfreq->dev.kobj, &gov_attr_group);
- if (err)
- goto err_init;
-
list_add(&devfreq->node, &devfreq_list);
mutex_unlock(&devfreq_list_lock);
@@ -1380,7 +1427,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
struct devfreq *df = to_devfreq(dev);
int ret;
char str_governor[DEVFREQ_NAME_LEN + 1];
- const struct devfreq_governor *governor, *prev_governor;
+ const struct devfreq_governor *governor;
ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
if (ret != 1)
@@ -1391,59 +1438,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
if (IS_ERR(governor))
return PTR_ERR(governor);
- if (!df->governor)
- goto start_new_governor;
-
- if (df->governor == governor)
- return count;
-
- if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE) ||
- IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE))
- return -EINVAL;
-
- /*
- * Stop the current governor and remove the specific sysfs files
- * which depend on current governor.
- */
- ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
- if (ret) {
- dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
- __func__, df->governor->name, ret);
- return ret;
- }
-
-start_new_governor:
- /*
- * Start the new governor and create the specific sysfs files
- * which depend on the new governor.
- */
- prev_governor = df->governor;
- df->governor = governor;
- ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
- if (ret) {
- dev_warn(dev, "%s: Governor %s not started(%d)\n",
- __func__, df->governor->name, ret);
-
- /* Restore previous governor */
- df->governor = prev_governor;
- if (!df->governor)
- return ret;
-
- ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
- if (ret) {
- dev_err(dev,
- "%s: reverting to Governor %s failed (%d)\n",
- __func__, prev_governor->name, ret);
- df->governor = NULL;
- return ret;
- }
- }
-
- /*
- * Create the sysfs files for the new governor. But if failed to start
- * the new governor, restore the sysfs files of previous governor.
- */
- ret = sysfs_update_group(&df->dev.kobj, &gov_attr_group);
+ ret = devfreq_set_governor(df, governor);
if (ret)
return ret;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/6] devfreq: Use mutex guard in governor_store()
From: Jie Zhan @ 2026-05-13 9:38 UTC (permalink / raw)
To: cwchoi00, cw00.choi, myungjoo.ham, kyungmin.park, linux-pm,
linux-arm-kernel
Cc: linuxarm, tianyaxiong, zhanjie9, zhenglifeng1, zhangpengjie2,
lihuisong, prime.zeng
In-Reply-To: <20260513093832.1645890-1-zhanjie9@hisilicon.com>
Use mutex guard in governor_store() so as to simplify the locking logic.
No functional impact intended.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 38 ++++++++++++++++----------------------
1 file changed, 16 insertions(+), 22 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index f08fc6966eae..7a70dd051644 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1394,23 +1394,20 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
if (ret != 1)
return -EINVAL;
- mutex_lock(&devfreq_list_lock);
+ guard(mutex)(&devfreq_list_lock);
governor = try_then_request_governor(str_governor);
- if (IS_ERR(governor)) {
- ret = PTR_ERR(governor);
- goto out;
- }
+ if (IS_ERR(governor))
+ return PTR_ERR(governor);
+
if (!df->governor)
goto start_new_governor;
- if (df->governor == governor) {
- ret = 0;
- goto out;
- } else if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)
- || IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE)) {
- ret = -EINVAL;
- goto out;
- }
+ if (df->governor == governor)
+ return count;
+
+ if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE) ||
+ IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE))
+ return -EINVAL;
/*
* Stop the current governor and remove the specific sysfs files
@@ -1420,7 +1417,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
if (ret) {
dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
__func__, df->governor->name, ret);
- goto out;
+ return ret;
}
start_new_governor:
@@ -1438,7 +1435,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
/* Restore previous governor */
df->governor = prev_governor;
if (!df->governor)
- goto out;
+ return ret;
ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
if (ret) {
@@ -1446,7 +1443,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
"%s: reverting to Governor %s failed (%d)\n",
__func__, prev_governor->name, ret);
df->governor = NULL;
- goto out;
+ return ret;
}
}
@@ -1455,13 +1452,10 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
* the new governor, restore the sysfs files of previous governor.
*/
ret = sysfs_update_group(&df->dev.kobj, &gov_attr_group);
+ if (ret)
+ return ret;
-out:
- mutex_unlock(&devfreq_list_lock);
-
- if (!ret)
- ret = count;
- return ret;
+ return count;
}
static DEVICE_ATTR_RW(governor);
--
2.43.0
^ permalink raw reply related
* [PATCH v2 6/6] devfreq: Get module refcount in try_then_request_governor()
From: Jie Zhan @ 2026-05-13 9:38 UTC (permalink / raw)
To: cwchoi00, cw00.choi, myungjoo.ham, kyungmin.park, linux-pm,
linux-arm-kernel
Cc: linuxarm, tianyaxiong, zhanjie9, zhenglifeng1, zhangpengjie2,
lihuisong, prime.zeng
In-Reply-To: <20260513093832.1645890-1-zhanjie9@hisilicon.com>
Get a refcount of the governor module in try_then_request_governor() so
that the governor module cannot be unloaded between finding the governor
and the caller using it.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 2ea42325d030..fb1a7aa168aa 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -285,6 +285,9 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
* and the driver that call devfreq_add_device) are built as modules.
* devfreq_list_lock should be held by the caller. Returns the matched
* governor's pointer or an error pointer.
+ * On success, this holds a refcount of the governor module to prevent the
+ * module from being unloaded during usage, so the caller should put a module
+ * refcount after using it.
*/
static struct devfreq_governor *try_then_request_governor(const char *name)
{
@@ -313,8 +316,13 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
return (err < 0) ? ERR_PTR(err) : ERR_PTR(-EINVAL);
governor = find_devfreq_governor(name);
+ if (IS_ERR(governor))
+ return governor;
}
+ if (!try_module_get(governor->owner))
+ return ERR_PTR(-EBUSY);
+
return governor;
}
@@ -1009,6 +1017,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
}
err = devfreq_set_governor(devfreq, governor);
+ module_put(governor->owner);
if (err) {
dev_err_probe(dev, err,
"%s: Unable to start governor for the device\n",
@@ -1446,6 +1455,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
return PTR_ERR(governor);
ret = devfreq_set_governor(df, governor);
+ module_put(governor->owner);
if (ret)
return ret;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/6] devfreq: Add refcounts for governor modules
From: Jie Zhan @ 2026-05-13 9:38 UTC (permalink / raw)
To: cwchoi00, cw00.choi, myungjoo.ham, kyungmin.park, linux-pm,
linux-arm-kernel
Cc: linuxarm, tianyaxiong, zhanjie9, zhenglifeng1, zhangpengjie2,
lihuisong, prime.zeng
A governor module can be dynamically inserted or removed if compiled as a
kernel module. 'devfreq->governor' would become NULL if the governor
module is removed when it's in use.
For user-friendliness, get and put the module refcount of a governor module
when it's in use. As a result, unloading a governor module in use returns
an error, e.g.:
$ cat governor
performance
$ rmmod governor_performance
rmmod: ERROR: Module governor_performance is in use
Note that this can't stop force unload, so it's more of a
user-friendliness improvement rather than strict protection. The
existing code that keeps devfreq working when 'devfreq->governor' is
NULL should still be there.
Patch 1-3 clean up mutex with guards and factor out a common governor
setting function, so as to prepare for implementing governor reference
counting. They can be applied separately.
Patch 4-6 add the reference counting mechanism for devfreq governor modules.
Changelog:
v2:
- Rebase on devfreq-next of 7.1-rc1.
- Drop the patches related to the NULL pointer deference issue of
'devfreq->governor', which has been solved and merged recently.
- Remove the dedicated mutex for 'devfreq_governor_list' because the
refcount changes don't depend on that.
- Some minor cleanups and fixes.
v1:
https://lore.kernel.org/all/20260326123428.800407-1-zhanjie9@hisilicon.com/
Jie Zhan (6):
devfreq: Use mutex guard in governor_store()
devfreq: Use mutex guard in devfreq_add/remove_governor()
devfreq: Factor out devfreq_set_governor()
devfreq: Add module owner to devfreq governor
devfreq: Get and put module refcount when switching governor
devfreq: Get module refcount in try_then_request_governor()
drivers/devfreq/devfreq.c | 210 +++++++++++++++----------------
include/linux/devfreq-governor.h | 26 +++-
2 files changed, 127 insertions(+), 109 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH v2 4/6] devfreq: Add module owner to devfreq governor
From: Jie Zhan @ 2026-05-13 9:38 UTC (permalink / raw)
To: cwchoi00, cw00.choi, myungjoo.ham, kyungmin.park, linux-pm,
linux-arm-kernel
Cc: linuxarm, tianyaxiong, zhanjie9, zhenglifeng1, zhangpengjie2,
lihuisong, prime.zeng
In-Reply-To: <20260513093832.1645890-1-zhanjie9@hisilicon.com>
Add an 'owner' member to struct devfreq_governor, such that we can find
the module that holds the governor code when it's compiled as a kernel
module. This allows the devfreq core to properly manage the lifecycle
of governors.
Update devfreq_add_governor() and devm_devfreq_add_governor() to
automatically set 'owner' to THIS_MODULE via helper macros.
This is a prerequisite for implementing governor reference counting to
prevent a governor module from being unloaded (except for force unload)
while a governor is in use.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 26 +++++++++-----------------
include/linux/devfreq-governor.h | 26 +++++++++++++++++++++++---
2 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 9e3e6a7348f8..e1363ab69173 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1301,11 +1301,8 @@ void devfreq_resume(void)
mutex_unlock(&devfreq_list_lock);
}
-/**
- * devfreq_add_governor() - Add devfreq governor
- * @governor: the devfreq governor to be added
- */
-int devfreq_add_governor(struct devfreq_governor *governor)
+int __devfreq_add_governor(struct devfreq_governor *governor,
+ struct module *mod)
{
struct devfreq_governor *g;
@@ -1322,37 +1319,32 @@ int devfreq_add_governor(struct devfreq_governor *governor)
return -EINVAL;
}
+ governor->owner = mod;
list_add(&governor->node, &devfreq_governor_list);
return 0;
}
-EXPORT_SYMBOL(devfreq_add_governor);
+EXPORT_SYMBOL(__devfreq_add_governor);
static void devm_devfreq_remove_governor(void *governor)
{
WARN_ON(devfreq_remove_governor(governor));
}
-/**
- * devm_devfreq_add_governor() - Add devfreq governor
- * @dev: device which adds devfreq governor
- * @governor: the devfreq governor to be added
- *
- * This is a resource-managed variant of devfreq_add_governor().
- */
-int devm_devfreq_add_governor(struct device *dev,
- struct devfreq_governor *governor)
+int __devm_devfreq_add_governor(struct device *dev,
+ struct devfreq_governor *governor,
+ struct module *mod)
{
int err;
- err = devfreq_add_governor(governor);
+ err = __devfreq_add_governor(governor, mod);
if (err)
return err;
return devm_add_action_or_reset(dev, devm_devfreq_remove_governor,
governor);
}
-EXPORT_SYMBOL(devm_devfreq_add_governor);
+EXPORT_SYMBOL(__devm_devfreq_add_governor);
/**
* devfreq_remove_governor() - Remove devfreq feature from a device.
diff --git a/include/linux/devfreq-governor.h b/include/linux/devfreq-governor.h
index dfdd0160a29f..1c4ff57e24de 100644
--- a/include/linux/devfreq-governor.h
+++ b/include/linux/devfreq-governor.h
@@ -12,6 +12,7 @@
#define __LINUX_DEVFREQ_DEVFREQ_H__
#include <linux/devfreq.h>
+struct module;
#define DEVFREQ_NAME_LEN 16
@@ -50,6 +51,7 @@
/**
* struct devfreq_governor - Devfreq policy governor
* @node: list node - contains registered devfreq governors
+ * @owner: Module that this governor belongs to
* @name: Governor's name
* @attrs: Governor's sysfs attribute flags
* @flags: Governor's feature flags
@@ -67,6 +69,7 @@
struct devfreq_governor {
struct list_head node;
+ struct module *owner;
const char name[DEVFREQ_NAME_LEN];
const u64 attrs;
const u64 flags;
@@ -81,11 +84,28 @@ void devfreq_monitor_suspend(struct devfreq *devfreq);
void devfreq_monitor_resume(struct devfreq *devfreq);
void devfreq_update_interval(struct devfreq *devfreq, unsigned int *delay);
-int devfreq_add_governor(struct devfreq_governor *governor);
+/**
+ * devfreq_add_governor() - Add devfreq governor
+ * @governor: The devfreq governor to be added
+ */
+#define devfreq_add_governor(governor) \
+ __devfreq_add_governor((governor), THIS_MODULE)
+int __devfreq_add_governor(struct devfreq_governor *governor,
+ struct module *mod);
int devfreq_remove_governor(struct devfreq_governor *governor);
-int devm_devfreq_add_governor(struct device *dev,
- struct devfreq_governor *governor);
+/**
+ * devm_devfreq_add_governor() - Add devfreq governor
+ * @dev: device which adds devfreq governor
+ * @governor: the devfreq governor to be added
+ *
+ * This is a resource-managed variant of devfreq_add_governor().
+ */
+#define devm_devfreq_add_governor(dev, governor) \
+ __devm_devfreq_add_governor((dev), (governor), THIS_MODULE)
+int __devm_devfreq_add_governor(struct device *dev,
+ struct devfreq_governor *governor,
+ struct module *mod);
int devfreq_update_status(struct devfreq *devfreq, unsigned long freq);
int devfreq_update_target(struct devfreq *devfreq, unsigned long freq);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 01/16] ACPI: GTDT: Parse information related to the EL2 virtual timer
From: Sudeep Holla @ 2026-05-13 9:41 UTC (permalink / raw)
To: Marc Zyngier
Cc: linux-arm-kernel, linux-acpi, linux-kernel, devicetree,
Sudeep Holla, Lorenzo Pieralisi, Hanjun Guo, Catalin Marinas,
Will Deacon, Rafael J. Wysocki, Mark Rutland, Daniel Lezcano,
Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Neil Armstrong,
Kevin Hilman, Jerome Brunet, Martin Blumenstingl, Ge Gordon,
BST Linux Kernel Upstream Group, Jesper Nilsson, Lars Persson,
Alim Akhtar, Ivaylo Ivanov, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Dinh Nguyen,
Matthias Brugger, AngeloGioacchino Del Regno, Thierry Reding,
Jonathan Hunter, Bjorn Andersson, Konrad Dybcio,
Andreas Färber, Heiko Stuebner, Shawn Lin, Orson Zhai,
Baolin Wang, Michal Simek
In-Reply-To: <20260507125544.2903406-2-maz@kernel.org>
On Thu, May 07, 2026 at 01:55:29PM +0100, Marc Zyngier wrote:
> Since ARMv8.1, the architecture has grown an EL2-private virtual
> timer. This has been described in ACPI since ACPI v6.3 and revision
> 3 of the GTDT table.
>
> An aditional structure was added in ACPICA, though in a rather
> bizarre way, and merged in v5.1 as 8f5a14d053100 ("ACPICA: ACPI 6.3:
> add GTDT Revision 3 support").
>
> Finally plug the table parsing in GTDT, and allow it to be eventually
> presented to the architected timer driver.
>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
> drivers/acpi/arm64/gtdt.c | 25 +++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
> index ffc867bac2d60..1a58007fccf0a 100644
> --- a/drivers/acpi/arm64/gtdt.c
> +++ b/drivers/acpi/arm64/gtdt.c
> @@ -88,6 +88,19 @@ static int __init map_gt_gsi(u32 interrupt, u32 flags)
> return acpi_register_gsi(NULL, interrupt, trigger, polarity);
> }
>
> +struct gtdt_v3 {
> + struct acpi_table_gtdt gtdt_v2;
> + struct acpi_gtdt_el2 el2_vtimer;
> +};
> +
> +static struct acpi_gtdt_el2 *gtdt_to_el2_vtimer(struct acpi_table_gtdt *gtdt)
> +{
> + if (gtdt->header.revision < 3)
> + return NULL;
> +
We should validate the length as well just in case some platform bumped version
but didn't add these fields. Again it is problem if the platform timers are
also missing. We can just add the check in acpi_gtdt_init() if the version >=3
perhaps? If (gtdt->header.length < sizeof(struct gtdt_v3) invalid table or
something.
Also we have in platform_timer_valid()
platform_timer >= (void *)(acpi_gtdt_desc.gtdt + 1)
which is still valid, but again if someone messes up in v3 keeping
offset where virtual EL2 timer GSI should be present as they just copied
it from v2, then we might allow it as valid.
Do it make sense to add that check as well in acpi_gtdt_init()? I mean
the offset should be >= sizeof(struct gtdt_v3).
Both checks can be added to acpi_gtdt_init() to avoid checking for each
platform timer instance may be ?
Other than this couple of minor nit, this patch looks fine.
Reviewed-by: Sudeep Holla <sudeep.holla@kernel.org>
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH] pmdomain: ti_sci: add wakeup constraint to parent devices of wakeup source
From: Vitor Soares @ 2026-05-13 9:40 UTC (permalink / raw)
To: Kendall Willis
Cc: Nishanth Menon, Tero Kristo, Santosh Shilimkar, Ulf Hansson,
Kevin Hilman, Dhruva Gole, linux-arm-kernel, linux-pm,
linux-kernel, stable, tomi.valkeinen, sebin.francis, devarsht,
vigneshr, vishalm, vitor.soares
In-Reply-To: <20260512161737.pflweaz2r3q3nrfl@uda0506412>
On Tue, 2026-05-12 at 11:17 -0500, Kendall Willis wrote:
> On 17:51-20260511, Vitor Soares wrote:
> > Hi Kendall,
> >
> > On Wed, 2026-05-06 at 22:16 -0500, Kendall Willis wrote:
> > > Set wakeup constraint for any device in a wakeup path. All parent devices
> > > of a wakeup device should not be turned off during suspend. This ensures
> > > the wakeup device is kept on while the system is suspended.
> > >
> >
> > Thanks for the patch.
> >
> > I tested it on our Verdin AM62P. As expected, suspend now fails cleanly with
> > "-
> > 19" when an SDIO WiFi module is registered as a wakeup source, instead of
> > crashing on resume:
> >
> > ti-sci 44043000.system-controller: PM: failed to suspend: error -19
> >
> > I did not test the IO daisy chain wakeup path, since that is out of scope
> > for
> > this patch.
> >
> > Best regards,
> > Vitor Soares
> >
>
> Hi Vitor,
>
> Thanks for testing the patch! Could you add your Tested-by tag?
>
> Best,
> Kendall
Hi Kendall,
Sure:
Tested-by: Vitor Soares vitor.soares@toradex.com
Best regards,
Vitor
^ permalink raw reply
* Re: [RFC V2 00/14] arm64/mm: Enable 128 bit page table entries
From: Lorenzo Stoakes @ 2026-05-13 9:39 UTC (permalink / raw)
To: Anshuman Khandual
Cc: linux-arm-kernel, Catalin Marinas, Will Deacon, Ryan Roberts,
Mark Rutland, Andrew Morton, David Hildenbrand, Mike Rapoport,
Linu Cherian, Usama Arif, linux-kernel, linux-mm
In-Reply-To: <20260513044547.4128549-1-anshuman.khandual@arm.com>
-cc my previous kernel address
Hi Anshuman,
Sorry to be a pain, but I'm using ljs@kernel.org now for my kernel mail, so
I am at risk of missing stuff sent to my @oracle.com address (I changed
things around to make managing the... rather large quantities of mail I get
a bit easier :)
Hence I missed this previously, can you send future revisions to
ljs@kernel.org? Thanks!
Cheers, Lorenzo
On Wed, May 13, 2026 at 10:15:33AM +0530, Anshuman Khandual wrote:
> FEAT_D128 is a new arm architecture feature adding support for VMSAv9-128
> translation system. FEAT_D128 is an optional feature from ARMV9.3 onwards.
> So with this feature arm64 platforms could have two different translation
> systems, VMSAv8-64 and VMSAv9-128 could selectively be enabled.
>
> FEAT_D128 adds 128 bit page table entries, thus supporting larger physical
> and virtual address range while also expanding available room for more MMU
> management feature bits both for HW and SW.
>
> This series has been split into two parts. Generic MM changes followed by
> arm64 platform changes, finally enabling D128 with a new config ARM64_D128.
>
> READ_ONCE() on page table entries get routed via level specific pxdp_get()
> helpers which platforms could then override when required. These accessors
> on arm64 platform help in ensuring page table accesses are performed in an
> atomic manner while reading 128 bit page table entries.
>
> All ARM64_VA_BITS and ARM64_PA_BITS combinations for all page sizes are now
> supported both on D64 and D128 translation regimes. Although new 56 bits VA
> space is not yet supported. Similarly FEAT_D128 skip level is not supported
> currently.
>
> Basic page table geometry has also been changed with D128 as there are fewer
> entries per level. Please refer to the following table for leaf entry sizes.
>
> D64 D128
> ------------------------------------------------
> | PAGE_SIZE | PMD | PUD | PMD | PUD |
> -----------------------------|-----------------|
> | 4K | 2M | 1G | 1M | 256M |
> | 16K | 32M | 64G | 16M | 16G |
> | 64K | 512M | 4T | 256M | 1T |
> ------------------------------------------------
>
> D64 D128
> --------------------------------------------------------------------
> | PAGE_SIZE | CONT_PTE | CONT_PMD | CONT_PTE | CONT_PMD |
> --------------------------|------------|-------------|--------------
> | 4K | 64K | 32M | 64K | 16M |
> | 16K | 2M | 1G | 1M | 256M |
> | 64K | 2M | 16G | 1M | 16G |
> --------------------------------------------------------------------
>
> From arm64 kernel features perspective KVM, KASAN and UNMAP_KERNEL_AT_EL0
> are currently not supported as well.
>
> This series applies on v7.1-rc3 and there are no apparent problems while
> running MM kselftests with and without CONFIG_ARM64_D128. Besides this has
> been built tested on other platform such as x86, powerpc, riscv, arm and
> s390 etc.
>
> Changes in RFC V2:
>
> - Dropped some patches that were merged upstream and rebased on v7.1-rc3
> - Moved pxdval_t definition inside generic page table header per Mike
> - Restored print format in __print_bad_page_map_pgtable() per Usama
> - Renamed __PRIpte as __PRIpxx per David
> - Dropped _once from pgprot_[read|write]() callbacks per Mike
> - Moved back all helpers back from arch/arm64/mm/mmu.c into the header
> - Renamed all ptdesc_ instances as pxxval_ instead
> - Moved arm64 pgtable header READ_ONCE() replacements later in the series
> - Updated commit message for the 5-level fixmap change per David
> - Updated ARM64_CONT_[PTE|PMD]_SHIFT both for 16K and 64K base pages
> - Added abstraction for tlbi_op
> - Adopted TLBIP implementation to recent TLB flush changes
> - Updated all commit messages as required and suggested
>
> Changes in RFC V1:
>
> https://lore.kernel.org/linux-arm-kernel/20260224051153.3150613-2-anshuman.khandual@arm.com/
>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Ryan Roberts <ryan.roberts@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: David Hildenbrand <david@kernel.org>
> Cc: Mike Rapoport <rppt@kernel.org>
> Cc: Linu Cherian <linu.cherian@arm.com>
> Cc: Usama Arif <usama.arif@linux.dev>
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-mm@kvack.org
>
> Anshuman Khandual (13):
> mm: Abstract printing of pxd_val()
> mm: Add read-write accessors for vm_page_prot
> arm64/mm: Convert READ_ONCE() as pmdp_get() while accessing PMD
> arm64/mm: Convert READ_ONCE() as pudp_get() while accessing PUD
> arm64/mm: Convert READ_ONCE() as p4dp_get() while accessing P4D
> arm64/mm: Convert READ_ONCE() as pgdp_get() while accessing PGD
> arm64/mm: Route all pgtable reads via pxxval_get()
> arm64/mm: Route all pgtable writes via pxxval_set()
> arm64/mm: Route all pgtable atomics to central helpers
> arm64/mm: Abstract printing of pxd_val()
> arm64/mm: Override read-write accessors for vm_page_prot
> arm64/mm: Enable fixmap with 5 level page table
> arm64/mm: Add initial support for FEAT_D128 page tables
>
> Linu Cherian (1):
> arm64/mm: Add an abstraction level for tlbi_op
>
> arch/arm64/Kconfig | 51 +++++++-
> arch/arm64/Makefile | 4 +
> arch/arm64/include/asm/assembler.h | 4 +-
> arch/arm64/include/asm/el2_setup.h | 9 ++
> arch/arm64/include/asm/pgtable-hwdef.h | 137 ++++++++++++++++++++
> arch/arm64/include/asm/pgtable-prot.h | 18 ++-
> arch/arm64/include/asm/pgtable-types.h | 12 ++
> arch/arm64/include/asm/pgtable.h | 169 ++++++++++++++++++++-----
> arch/arm64/include/asm/smp.h | 1 +
> arch/arm64/include/asm/tlbflush.h | 138 ++++++++++++++------
> arch/arm64/kernel/head.S | 12 ++
> arch/arm64/mm/fault.c | 20 +--
> arch/arm64/mm/fixmap.c | 24 +++-
> arch/arm64/mm/hugetlbpage.c | 10 +-
> arch/arm64/mm/kasan_init.c | 14 +-
> arch/arm64/mm/mmu.c | 65 +++++-----
> arch/arm64/mm/pageattr.c | 8 +-
> arch/arm64/mm/proc.S | 25 +++-
> arch/arm64/mm/trans_pgd.c | 14 +-
> include/linux/pgtable.h | 25 ++++
> mm/huge_memory.c | 4 +-
> mm/memory.c | 25 ++--
> mm/migrate.c | 2 +-
> mm/mmap.c | 2 +-
> 24 files changed, 624 insertions(+), 169 deletions(-)
>
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH v3 06/13] pmdomain: core: Add initial fine grained sync_state support
From: Ulf Hansson @ 2026-05-13 9:35 UTC (permalink / raw)
To: Saravana Kannan
Cc: Danilo Krummrich, Rafael J . Wysocki, Greg Kroah-Hartman,
driver-core, linux-pm, Sudeep Holla, Cristian Marussi,
Kevin Hilman, Stephen Boyd, Marek Szyprowski, Bjorn Andersson,
Abel Vesa, Peng Fan, Tomi Valkeinen, Maulik Shah, Konrad Dybcio,
Thierry Reding, Jonathan Hunter, Geert Uytterhoeven,
Dmitry Baryshkov, linux-arm-kernel, linux-kernel
In-Reply-To: <CACRMN=cyMjHtW1xjoYPWa8_TjmQEoJBvKtMo-UgP5yZJ=zDh2Q@mail.gmail.com>
On Wed, 13 May 2026 at 07:34, Saravana Kannan <saravanak@kernel.org> wrote:
>
> On Mon, May 11, 2026 at 3:25 AM Ulf Hansson <ulf.hansson@linaro.org> wrote:
> >
> > On Mon, 11 May 2026 at 07:09, Saravana Kannan <saravanak@kernel.org> wrote:
> > >
> > > On Fri, May 8, 2026 at 5:39 AM Ulf Hansson <ulf.hansson@linaro.org> wrote:
> > > >
> > > > A onecell (#power-domain-cells = <1 or 2>; in DT) power domain provider
> > > > typically provides multiple independent power domains, each with their own
> > > > corresponding consumers. In these cases we have to wait for all consumers
> > > > for all the provided power domains before the ->sync_state() callback gets
> > > > called for the supplier.
> > > >
> > > > In a first step to improve this, let's implement support for fine grained
> > > > sync_state support a per genpd basis by using the ->queue_sync_state()
> > > > callback. To take step by step, let's initially limit the improvement to
> > > > the internal genpd provider driver and to its corresponding genpd devices
> > > > for onecell providers.
> > > >
> > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > ---
> > > >
> > > > Changes in v3:
> > > > - Addressed some cosmetic comments from Geert.
> > > >
> > > > ---
> > > > drivers/pmdomain/core.c | 124 ++++++++++++++++++++++++++++++++++++++
> > > > include/linux/pm_domain.h | 1 +
> > > > 2 files changed, 125 insertions(+)
> > > >
> > > > diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
> > > > index ad57846f02a3..c01a9a96e5c2 100644
> > > > --- a/drivers/pmdomain/core.c
> > > > +++ b/drivers/pmdomain/core.c
> > > > @@ -2699,6 +2699,119 @@ static struct generic_pm_domain *genpd_get_from_provider(
> > > > return genpd;
> > > > }
> > > >
> > > > +static bool genpd_should_wait_for_consumer(struct device_node *np)
> > > > +{
> > > > + struct generic_pm_domain *genpd;
> > > > + bool should_wait = false;
> > > > +
> > > > + mutex_lock(&gpd_list_lock);
> > > > + list_for_each_entry(genpd, &gpd_list, gpd_list_node) {
> > > > + if (genpd->provider == of_fwnode_handle(np)) {
> > > > + genpd_lock(genpd);
> > > > +
> > > > + /* Clear the previous state before reevaluating. */
> > > > + genpd->wait_for_consumer = false;
> > > > +
> > > > + /*
> > > > + * Unless there is at least one genpd for the provider
> > > > + * that is being kept powered-on, we don't have to care
> > > > + * about waiting for consumers.
> > > > + */
> > > > + if (genpd->stay_on)
> > > > + should_wait = true;
> > > > +
> > > > + genpd_unlock(genpd);
> > > > + }
> > > > + }
> > > > + mutex_unlock(&gpd_list_lock);
> > >
> > > I think I understand the intent of this function, but haven't dug into
> > > genpd code enough to comment on this yet. I'll come back to this
> > > later.
> > >
> > > > +
> > > > + return should_wait;
> > > > +}
> > > > +
> > > > +static void genpd_parse_for_consumer(struct device_node *sup,
> > > > + struct device_node *con)
> > > > +{
> > > > + struct generic_pm_domain *genpd;
> > > > +
> > > > + for (unsigned int i = 0; ; i++) {
> > > > + struct of_phandle_args pd_args;
> > > > +
> > > > + if (of_parse_phandle_with_args(con, "power-domains",
> > > > + "#power-domain-cells",
> > > > + i, &pd_args))
> > > > + break;
> > >
> > > Why not use a while or a do while() instead of this infinite for loop
> > > with a break?
> >
> > I guess it's a matter of personal preference. I'm not sure the code
> > gets any nicer with a do/while, but if you really insist I can change
> > it.
> >
> > >
> > > > +
> > > > + /*
> > > > + * The phandle must correspond to the supplier's genpd provider
> > > > + * to be relevant else let's move to the next index.
> > > > + */
> > > > + if (sup != pd_args.np) {
> > > > + of_node_put(pd_args.np);
> > > > + continue;
> > > > + }
> > > > +
> > > > + mutex_lock(&gpd_list_lock);
> > > > + genpd = genpd_get_from_provider(&pd_args);
> > > > + if (!IS_ERR(genpd)) {
> > > > + genpd_lock(genpd);
> > > > + genpd->wait_for_consumer = true;
> > > > + genpd_unlock(genpd);
> > > > + }
> > > > + mutex_unlock(&gpd_list_lock);
> > > > +
> > > > + of_node_put(pd_args.np);
> > > > + }
> > > > +}
> > > > +
> > > > +static void _genpd_queue_sync_state(struct device_node *np)
> > > > +{
> > > > + struct generic_pm_domain *genpd;
> > > > +
> > > > + mutex_lock(&gpd_list_lock);
> > > > + list_for_each_entry(genpd, &gpd_list, gpd_list_node) {
> > > > + if (genpd->provider == of_fwnode_handle(np)) {
> > > > + genpd_lock(genpd);
> > > > + if (genpd->stay_on && !genpd->wait_for_consumer) {
> > > > + genpd->stay_on = false;
> > > > + genpd_queue_power_off_work(genpd);
> > > > + }
> > > > + genpd_unlock(genpd);
> > > > + }
> > > > + }
> > > > + mutex_unlock(&gpd_list_lock);
> > > > +}
> > > > +
> > > > +static void genpd_queue_sync_state(struct device *dev)
> > > > +{
> > > > + struct device_node *np = dev->of_node;
> > > > + struct device_link *link;
> > > > +
> > > > + if (!genpd_should_wait_for_consumer(np))
> > > > + return;
> > > > +
> > > > + list_for_each_entry(link, &dev->links.consumers, s_node) {
> > >
> > > Couple of issues:
> > > 1. I don't want the frameworks to be so deeply aware of driver core
> > > internals. I want the driver core maintainers to be able to change the
> > > devlink implementation without having to worry about going and fixing
> > > all the frameworks. So, please add a for_each_consumer_dev(supplier,
> > > callback) and for_each_supplier_dev(consumer, callback) helper
> > > functions.
> >
> > I understand your concern and I like the idea. However, maybe it's
> > better to get this landed (the series is complicated as is) first and
> > then can continue to improve the code on top, with helper functions
> > etc.
>
> That patch should be pretty simple, so let's just do it? You are
> literally just moving the code to another file and massaging it a bit.
> I can send one out if you want/
Okay, I will fold in a patch into my series that adds the helper. No
point you sending it as it needs to be apart of my series to have a
user for it.
>
> > >
> > > 2. This doesn't ignore "SYNC_STATE_ONLY" links and that's going to
> > > confuse the consumer count/check you might do or at the least waste
> > > parsing those.
> >
> > I am not sure I understand how I should take SYNC_STATE_ONLY links
> > into account here.
> >
> > At each call to the genpd_queue_sync_state(), we walk through all the
> > provided genpds for the provider. No previous state is cached to track
> > consumer counts.
>
> Ok, correct me if I'm wrong here, but it looks like you are looking at
> all the consumers, finding the ones that haven't probed yet and then
> trying to see which specific genpd provider each one of them is using
> by parsing their dt properties and then keep those ON.
The code cares only about the genpd OF provider that the supplier
device belongs to, if any. Any other genpd OF providers and their
genpds is untouched.
The corresponding genpd OF provider may provide multiple genpds
through the same fwnode.
>
> If my understanding above is wrong then, please help me understand
> what the code is trying to do.
>
> If it's right, then here's the issue:
>
> fw_devlink relies on device links and fwnode links to keep track of
> consumers. fwnode links get created first and then get converted to
> device links when both the supplier AND consumer devices are created.
>
> Consider a case when the supplier S is created and the consumer device
> C is several levels deep inside a parent device A.
> S { #power-domain-cells = <1>; }
> A { B { C { power-domains = <&S MY_DOMAIN>; } } }
>
> fw_devlink can't just go "oh there's no consumer device that hasn't
> probed yet, let me call sync_state()". It needs to wait for C. But
> there's no way to create a device link to C. So, here's the sequence
> that happens:
>
> 1. When device A gets added, it creates a "proxy" SYNC_STATE_ONLY link
> between S and A.
> 2. When A probes, it adds device B.
> 3. The SYNC_STATE_ONLY link between S to B is created.
> 4. The SYNC_STATE_ONLY link between S to A is deleted.
> 5. When B probes, it adds device C.
> 6. The actual device link between S and C is created.
> 7. The SYNC_STATE_ONLY link between S to B is deleted.
> 8. Device C probes, the device links get updated, sync_state() gets called.
>
> So, if your code doesn't account for SYNC_STATE_ONLY links, you are
> going to check device "A" to see which providers are used. You'll
> think that MY_DOMAIN isn't used by any unprobed consumer and turn it
> off.
>
> >
> > >
> > > 3. **Device** links are not the complete list of consumers because
> > > they can only link consumer **devices** once the consumer **device**
> > > is created.
> > >
> > > 4. What you really need is a for_each_consumer_fwnode(supplier,
> > > callback) that first loops through all the consumer device links and
> > > calls the callback() on their fwnode and then the same function needs
> > > to loop through all the fwnode links and then pass those consumer
> > > fwnodes to the callback. And inside that callback you can do whatever
> > > you want.
> >
> > The ->queue_sync_state() callback is invoked *after*
> > __device_links_queue_sync_state() has been called for the device,
> > which is also when the conditions for calling ->sync_state() is
> > checked.
>
> I'm not sure what you are trying to say here. Yes, what you are saying
> is true. But at the point the current code returns before calling
> sync_state(), your patch 2/13 ends up calling the "consumer_probed()"
> callback.
>
> If you see the example I gave above, there is a SYNC_STATE_ONLY link
> all the way up to step 7 that'll prevent sync_state() from being
> called. And until step 5, there is no device link between S and C and
> you'll have to go look at S's fwnode links to find C.
Thanks for the details, but I don't think the code in genpd needs to
take these details into account. Or at least that is my goal, if
possible.
As I understand it, all of the above should already been taken care of
when __device_links_queue_sync_state() is called, as it's at that
point when we can validate whether all consumers for a supplier have
been probed, right?
>
> > If there are problems with not yet registered consumer device links,
> > why isn't that as problem for regular ->sync_state() in
> > __device_links_queue_sync_state()?
>
> Does my explanation above make sense?
I think you may have misunderstood how the code in $subject patch
works. Let's try again.
>
> Welcome to the annoying worlds of fw_devlink corner cases/nuances.
> There's a case where the child is the supplier of the
> parent/grandparent. There's a comment for that in the fw_devlink code.
Yeah, I am fully aware of the high level of complexity and as I said,
I don't want genpd to have to know about *all* of that.
[...]
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH] coresight: trbe: Hide enable_sink sysfs file
From: James Clark @ 2026-05-13 9:33 UTC (permalink / raw)
To: Leo Yan
Cc: Suzuki K Poulose, Mike Leach, Alexander Shishkin, coresight,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260513081551.GC34802@e132581.arm.com>
On 13/05/2026 9:15 am, Leo Yan wrote:
> On Thu, May 07, 2026 at 11:53:45AM +0100, James Clark wrote:
>
> [...]
>
>> +static umode_t coresight_attr_is_visible(struct kobject *kobj,
>> + struct attribute *attr, int n)
>> {
>> struct device *dev = kobj_to_dev(kobj);
>> + struct coresight_device *csdev = to_coresight_device(dev);
>>
>> if (attr == &dev_attr_label.attr) {
>> if (fwnode_property_present(dev_fwnode(dev), "label"))
>> return attr->mode;
>> else
>> return 0;
>> + } else if (attr == &dev_attr_enable_sink.attr ||
>> + attr == &dev_attr_enable_source.attr) {
>> + if (csdev->no_sysfs_mode)
>> + return 0;
>> + else
>> + return attr->mode;
>
> I'd prefer no_sysfs_mode to work as a general flag rather than being
> limited to sink/source devices only. Otherwise, LGTM.
>
> Thanks,
> Leo
Which other files would you hide though? These are the only two that I
could think of.
I wouldn't hide all sysfs files for 'no_sysfs_mode' as there are read
only things that aren't strictly related to sysfs mode.
^ permalink raw reply
* Re: [PATCH] Documentation: KVM: Document guest-visible compatibility expectations
From: David Woodhouse @ 2026-05-13 9:24 UTC (permalink / raw)
To: Marc Zyngier, Paolo Bonzini
Cc: Jonathan Corbet, Shuah Khan, kvm, linux-doc, linux-kernel,
Sean Christopherson, Jim Mattson, Oliver Upton, Joey Gouly,
Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
Raghavendra Rao Ananta, Eric Auger, Kees Cook, Arnd Bergmann,
Nathan Chancellor, linux-arm-kernel, kvmarm, linux-kselftest
In-Reply-To: <86h5obya2r.wl-maz@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 4564 bytes --]
On Wed, 2026-05-13 at 09:42 +0100, Marc Zyngier wrote:
> On Mon, 11 May 2026 17:56:15 +0100,
> Paolo Bonzini <pbonzini@redhat.com> wrote:
> >
> > On 5/11/26 18:38, David Woodhouse wrote:
> > > Not *everything* is in CPUID; one recent exception that comes to mind
> > > is the SUPPRESS_EOI_BROADCAST quirk. But on x86 we preserve the
> > > existing behaviour of older kernels — even when that behaviour doesn't
> > > make much sense, as with SUPPRESS_EOI_BROADCAST where older KVM would
> > > *advertise* the feature, but not actually *implement* it. Nevertheless,
> > > that remains the default behaviour of future kernels unless userspace
> > > explicitly opts in to fully enable (or disable) the feature.
> > >
> > > But this documentation update isn't even asking for that compatible-by-
> > > default behaviour, even though that is the right thing to do. It's only
> > > asking that it be *possible* to reinstate the old behaviour, for
> > > userspace that *knows* about the change and explicitly wants to go back
> > > to the old way to remain compatible.
> >
> > Yep, these are the "quirks"---if it's too early for Arm to commit to
> > that, I guess it's fine.
>
> Compatible by default means nothing, because userspace needs to
> discover the combined capabilities of the host and KVM. This is not a
> "CPU model" architecture.
>
> If userspace is not a total joke, it will read all the ID registers,
> and configure what it wants to see, assuming it is a feature that can
> be configured (not everything can, because the architecture itself is
> not fully backward compatible).
>
> Yes, this is buggy at times, because the combinatorial explosion of
> CPU capabilities and supported features makes it pretty hard to test
> (and really nobody actually does). But overall, it works, and QEMU is
> growing an infrastructure to manage it in a "user friendly" way.
Yes, that is precisely what I'm asking for. I'm prepared to deal with
the fact that KVM/Arm64 is not a stable and mature platform like x86
is, and that userspace has to find all the random changes from one
version to the next, and explicitly pin things down to be compatible.
All I'm asking for is that KVM makes it *possible* to pin things down
to the behaviour of previously released Linux/KVM kernels.
> But really, this isn't what David is asking. He's demanding "bug for
> bug" compatibility. For that, we have two possible cases:
No, I am not asking you to meet that bar. I merely observed that x86
does and that it would be nice. But we are a *long* way from that.
> - this is a behaviour that, while undesirable, is allowed by the
> architecture: fine, we preserve the behaviour and add another way to
> expose the one we really want. it is ugly, but we manage.
>
> - this is a behaviour that is not allowed by the architecture: we fix
> it for good. We do that on every release. Some minor, some much more
> visible. And there is no way we will add this sort of "bring the
> bugs back" type of behaviours. Specially when it is really obvious
> that no SW can make any reasonable use of the defect. We allow
> userspace to keep behaving as before, but the guest will not see a
> non-compliant behaviour.
>
> That being said, there is a way out of that: convince people in charge
> of the architecture that the non-compliant KVM behaviour is actually
> valuable, and deserves to be tolerated. This has happened before (VHE
> only and NV2 only, just to name two recent changes).
>
> Other terrible hacks (such as GICv3's GICD_TYPER.num_LPIs which KVM
> doesn't support) were added at the request of cloud vendors that David
> might be familiar with, so it isn't like it is a brand new process.
>
> And once it is in the architecture, it becomes a behaviour that is
> allowed to be exposed to a guest, for better or worse.
Marc, this is complete nonsense and you should know better.
Once a behaviour is present in a released version of Linux/KVM, we
can't just declare it "wrong" and unilaterally impose a change in
guest-visible behaviour on *running* guests as a side-effect of a
kernel upgrade.
The criterion for *KVM* to remain compatible is "once it has been in a
released version of the kernel". Not "once it is in the architecture".
> These are the rules we have followed since we started KVM/arm, and I
> intend to stick to them.
Then KVM/arm is falling far short of the standards we expect of KVM and
of Linux in general.
Please do better.
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]
^ permalink raw reply
* Re: [PATCH 10/10] clk: amlogic: Add A9 AO clock controller driver
From: Jian Hu @ 2026-05-13 9:19 UTC (permalink / raw)
To: Brian Masney
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao,
Kevin Hilman, Martin Blumenstingl, linux-kernel, linux-clk,
devicetree, linux-amlogic, linux-arm-kernel
In-Reply-To: <agH5q01HHszGc6ud@redhat.com>
On 5/11/2026 11:45 PM, Brian Masney wrote:
> [ EXTERNAL EMAIL ]
>
> Hi Jian,
>
> On Mon, May 11, 2026 at 08:47:32PM +0800, Jian Hu via B4 Relay wrote:
>> From: Jian Hu <jian.hu@amlogic.com>
>>
>> Add the Always-on clock controller driver for the Amlogic A9 SoC family.
>>
>> Signed-off-by: Jian Hu <jian.hu@amlogic.com>
> I'll only flag new things that I spot here that weren't mentioned in
> the other patches I reviewed in this series.
Got you, I will sort the header, also use
CLK_HW_INIT_FW_NAME/CLK_HW_INIT_HWS for this driver.
[......]
>> +static A9_COMP_SEL(ao_pwm_a, AO_PWM_CLK_A_CTRL, 9, 0x7, a9_ao_pwm_parents);
>> +static A9_COMP_DIV(ao_pwm_a, AO_PWM_CLK_A_CTRL, 0, 8);
>> +static A9_COMP_GATE(ao_pwm_a, AO_PWM_CLK_A_CTRL, 8);
>> +
>> +static A9_COMP_SEL(ao_pwm_b, AO_PWM_CLK_B_CTRL, 9, 0x7, a9_ao_pwm_parents);
>> +static A9_COMP_DIV(ao_pwm_b, AO_PWM_CLK_B_CTRL, 0, 8);
>> +static A9_COMP_GATE(ao_pwm_b, AO_PWM_CLK_A_CTRL, 8);
> Should this be AO_PWM_CLK_B_CTRL ?
Yes, it should be AO_PWM_CLK_B_CTRL.
Thank you for pointing it out.
>> +
>> +static A9_COMP_SEL(ao_pwm_c, AO_PWM_CLK_C_CTRL, 9, 0x7, a9_ao_pwm_parents);
>> +static A9_COMP_DIV(ao_pwm_c, AO_PWM_CLK_C_CTRL, 0, 8);
>> +static A9_COMP_GATE(ao_pwm_c, AO_PWM_CLK_C_CTRL, 8);
>> +
>> +static A9_COMP_SEL(ao_pwm_d, AO_PWM_CLK_D_CTRL, 9, 0x7, a9_ao_pwm_parents);
>> +static A9_COMP_DIV(ao_pwm_d, AO_PWM_CLK_D_CTRL, 0, 8);
>> +static A9_COMP_GATE(ao_pwm_d, AO_PWM_CLK_D_CTRL, 8);
>> +
>> +static A9_COMP_SEL(ao_pwm_e, AO_PWM_CLK_E_CTRL, 9, 0x7, a9_ao_pwm_parents);
>> +static A9_COMP_DIV(ao_pwm_e, AO_PWM_CLK_E_CTRL, 0, 8);
>> +static A9_COMP_GATE(ao_pwm_e, AO_PWM_CLK_E_CTRL, 8);
>> +
>> +static A9_COMP_SEL(ao_pwm_f, AO_PWM_CLK_F_CTRL, 9, 0x7, a9_ao_pwm_parents);
>> +static A9_COMP_DIV(ao_pwm_f, AO_PWM_CLK_F_CTRL, 0, 8);
>> +static A9_COMP_GATE(ao_pwm_f, AO_PWM_CLK_F_CTRL, 8);
>> +
>> +static A9_COMP_SEL(ao_pwm_g, AO_PWM_CLK_G_CTRL, 9, 0x7, a9_ao_pwm_parents);
>> +static A9_COMP_DIV(ao_pwm_g, AO_PWM_CLK_G_CTRL, 0, 8);
>> +static A9_COMP_GATE(ao_pwm_g, AO_PWM_CLK_G_CTRL, 8);
>> +
>> +static struct clk_regmap a9_ao_rtc_dualdiv_in = {
>> + .data = &(struct clk_regmap_gate_data){
>> + .offset = AO_RTC_BY_OSCIN_CTRL0,
>> + .bit_idx = 31,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "ao_rtc_duandiv_in",
> s/duandiv/dualdiv/ ?
>
> Brian
Ok, I will fix the duandiv name.
Thank you for pointing it out.
^ permalink raw reply
* Re: [PATCH] arm64: dts: allwinner: Cubie A5E: enable SPI flash
From: Andre Przywara @ 2026-05-13 9:19 UTC (permalink / raw)
To: wens
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec,
Samuel Holland, devicetree, linux-arm-kernel, linux-sunxi
In-Reply-To: <CAGb2v64u4sqwiiQcEBg-XvmJ2DLEpSj-_AWNbp14RAp-GXP7OA@mail.gmail.com>
Hi Chen-Yu,
thanks for chipping in!
On 5/13/26 07:21, Chen-Yu Tsai wrote:
> Hi,
>
> On Tue, May 12, 2026 at 6:18 AM Andre Przywara <andre.przywara@arm.com> wrote:
>>
>> The Cubie A5E board comes with 16MiB of SPI NOR flash.
>>
>> Enable the SPI0 DT node and describe the configuration.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>> .../boot/dts/allwinner/sun55i-a527-cubie-a5e.dts | 15 +++++++++++++++
>> 1 file changed, 15 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts
>> index bfdf1728cd14b..7ad22fc85d1fd 100644
>> --- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts
>> +++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts
>> @@ -344,6 +344,21 @@ &r_pio {
>> vcc-pm-supply = <®_aldo3>;
>> };
>>
>> +&spi0 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&spi0_pc_pins>, <&spi0_cs0_pc_pin>,
>> + <&spi0_hold_pc_pin>, <&spi0_wp_pc_pin>;
>
> This whole thing needs to be an overlay. The HOLD and WP pins
> conflict with eMMC usage, so it seems that Radxa only populates
> one or the other.
>
> If you look at the pictures on their official website, you'll see the
> SPI NOR chip populated, but not the eMMC chip. On the linux-sunxi wiki
> page, you'll see the opposite.
Well, I have a hard time spotting any actual eMMC SKUs in the shops anyway.
But you are right, the hold and WP pins conflict with eMMC, whereas the
other pins are not.
> And you probably want to enable QSPI, like Sashiko mentioned.
Well, in the interest of keeping this simple and enabling the usage of
SPI flash for all the users out there, I'd rather drop the extra pins.
This is mostly really useful for booting the firmware, maybe loading a
tiny kernel or other data once, so performance is not a big concern in
this use case. The BootROM surely does not use QSPI.
And as you say, if people are really interested in the last bit of
performance, they can use an overlay.
Cheers,
Andre
>
>
> ChenYu
>
>
>> + status = "okay";
>> +
>> + flash@0 {
>> + compatible = "winbond,w25q128", "jedec,spi-nor";
>> + reg = <0>;
>> + spi-max-frequency = <40000000>;
>> + #address-cells = <1>;
>> + #size-cells = <1>;
>> + };
>> +};
>> +
>> &uart0 {
>> pinctrl-names = "default";
>> pinctrl-0 = <&uart0_pb_pins>;
>> --
>> 2.46.4
>>
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox