* Re: [PATCH 2/9] dt-bindings: arm: apple: apple,pmgr: Add t8122 compatible
From: Rob Herring (Arm) @ 2026-04-07 16:07 UTC (permalink / raw)
To: Janne Grunau
Cc: Linus Walleij, linux-arm-kernel, devicetree, asahi,
Wim Van Sebroeck, linux-pwm, Lorenzo Pieralisi, Guenter Roeck,
linux-kernel, linux-i2c, linux-gpio, Andi Shyti, Mark Kettenis,
Sasha Finkelstein, Uwe Kleine-König, Sven Peter, Neal Gompa,
Krzysztof Kozlowski, linux-watchdog, Conor Dooley
In-Reply-To: <20260320-apple-m3-initial-devicetrees-v1-2-5842e1e393a8@jannau.net>
On Fri, 20 Mar 2026 13:23:20 +0100, Janne Grunau wrote:
> The PMGR blocks on Apple silicon M3 SoCs (t8122) are compatible with the
> M1 and M2 predecessors. Add "apple,t8122-pmgr" as M3 specific
> compatible.
>
> Signed-off-by: Janne Grunau <j@jannau.net>
> ---
> Documentation/devicetree/bindings/arm/apple/apple,pmgr.yaml | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH 1/9] dt-bindings: arm: cpus: Add Apple M3 CPU core compatibles
From: Rob Herring @ 2026-04-07 16:06 UTC (permalink / raw)
To: Janne Grunau
Cc: Krzysztof Kozlowski, Conor Dooley, Lorenzo Pieralisi, Sven Peter,
Neal Gompa, Wim Van Sebroeck, Guenter Roeck, Linus Walleij,
Mark Kettenis, Andi Shyti, Uwe Kleine-König,
Sasha Finkelstein, devicetree, linux-kernel, asahi,
linux-arm-kernel, linux-watchdog, linux-gpio, linux-i2c,
linux-pwm
In-Reply-To: <20260320-apple-m3-initial-devicetrees-v1-1-5842e1e393a8@jannau.net>
On Fri, Mar 20, 2026 at 01:23:19PM +0100, Janne Grunau wrote:
> Add "apple,everest" compatible for the M3 performance core and
> "apple,sawtooth" for the M3 efficiency CPU core. These CPU cores are
> found on Apple Silicon SoCs M3 and M3 Pro, Max and Ultra.
>
> Signed-off-by: Janne Grunau <j@jannau.net>
> ---
> Documentation/devicetree/bindings/arm/cpus.yaml | 2 ++
> 1 file changed, 2 insertions(+)
Applied, thanks.
Rob
^ permalink raw reply
* Re: [PATCH v2 6/6] perf arm_spe: Print remaining IMPDEF event numbers
From: Leo Yan @ 2026-04-07 15:46 UTC (permalink / raw)
To: James Clark
Cc: John Garry, Will Deacon, Mike Leach, Leo Yan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Al Grant, linux-arm-kernel, linux-perf-users, linux-kernel
In-Reply-To: <20260407-james-spe-impdef-decode-v2-6-55d3ef997c48@linaro.org>
On Tue, Apr 07, 2026 at 03:05:20PM +0100, James Clark wrote:
> Any IMPDEF events not printed out from a known core's IMPDEF list or for
> a completely unknown core will still not be shown to the user. Fix this
> by printing the remaining bits as comma separated raw numbers, e.g.
> "IMPDEF:1,2,3,4".
>
> Suggested-by: Al Grant <al.grant@arm.com>
> Signed-off-by: James Clark <james.clark@linaro.org>
Reviewed-by: Leo Yan <leo.yan@arm.com>
^ permalink raw reply
* [PATCH mt76] wifi: mt76: mt76x2u: Add support for ELECOM WDC-867SU3S
From: Zenm Chen @ 2026-04-07 15:44 UTC (permalink / raw)
To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg,
angelogioacchino.delregno, linux-wireless, linux-kernel,
linux-arm-kernel, linux-mediatek
Cc: zenmchen, stable
Add the ID 056e:400a to the table to support an additional MT7612U
adapter: ELECOM WDC-867SU3S.
Compile tested only.
Cc: stable@vger.kernel.org # 5.10.x
Signed-off-by: Zenm Chen <zenmchen@gmail.com>
---
This ID was found from [1] and adding it to the device table should be
enough to make it work. Hardware probes at [2] can prove its existence.
[1] https://bushowhige.blogspot.com/2019/08/ubuntu-1804-mediatek-usb-wi-fi.html
[2] https://linux-hardware.org/?id=usb:056e-400a
---
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
index 01cb3b283..459c4044f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
@@ -16,6 +16,7 @@ static const struct usb_device_id mt76x2u_device_table[] = {
{ USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USBAC1200 - Alfa AWUS036ACM */
{ USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */
{ USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */
+ { USB_DEVICE(0x056e, 0x400a) }, /* ELECOM WDC-867SU3S */
{ USB_DEVICE(0x0e8d, 0x7632) }, /* HC-M7662BU1 */
{ USB_DEVICE(0x0471, 0x2126) }, /* LiteOn WN4516R module, nonstandard USB connector */
{ USB_DEVICE(0x0471, 0x7600) }, /* LiteOn WN4519R module, nonstandard USB connector */
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v2 5/6] perf arm_spe: Decode Arm N1 IMPDEF events
From: Leo Yan @ 2026-04-07 15:44 UTC (permalink / raw)
To: James Clark
Cc: John Garry, Will Deacon, Mike Leach, Leo Yan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Al Grant, linux-arm-kernel, linux-perf-users, linux-kernel
In-Reply-To: <20260407-james-spe-impdef-decode-v2-5-55d3ef997c48@linaro.org>
On Tue, Apr 07, 2026 at 03:05:19PM +0100, James Clark wrote:
> From the TRM [1], N1 has one IMPDEF event which isn't covered by the
> common list. Add a framework so that more cores can be added in the
> future and that the N1 IMPDEF event can be decoded. Also increase the
> size of the buffer because we're adding more strings and if it gets
> truncated it falls back to a hex dump only.
>
> [1]: https://developer.arm.com/documentation/100616/0401/Statistical-Profiling-Extension/implementation-defined-features-of-SPE
> Suggested-by: Al Grant <al.grant@arm.com>
> Signed-off-by: James Clark <james.clark@linaro.org>
Reviewed-by: Leo Yan <leo.yan@arm.com>
^ permalink raw reply
* Re: [PATCH net-next v9 1/4] net: stmmac: Add DW25GMAC support in stmmac core driver
From: Russell King (Oracle) @ 2026-04-07 15:42 UTC (permalink / raw)
To: Jitendra Vegiraju
Cc: netdev, alexandre.torgue, davem, edumazet, kuba, pabeni,
mcoquelin.stm32, bcm-kernel-feedback-list, richardcochran, ast,
daniel, hawk, john.fastabend, rohan.g.thomas, linux-kernel,
linux-stm32, linux-arm-kernel, bpf, andrew+netdev, horms, sdf, me,
siyanteng, prabhakar.mahadev-lad.rj, weishangjuan, wens,
vladimir.oltean, lizhi2, boon.khai.ng, maxime.chevallier,
chenchuangyu, yangtiezhu, ovidiu.panait.rb, chenhuacai,
florian.fainelli, quic_abchauha
In-Reply-To: <adUQHHBD0d3p1OSI@shell.armlinux.org.uk>
On Tue, Apr 07, 2026 at 03:09:32PM +0100, Russell King (Oracle) wrote:
> Not withstanding my comment about the other Synopsys xlgmac driver that
> we have in the kernel...
>
> On Thu, Apr 02, 2026 at 02:36:26PM -0700, Jitendra Vegiraju wrote:
> > From: Jitendra Vegiraju <jitendra.vegiraju@broadcom.com>
> >
> > The DW25GMAC introduced a new DMA architecture called Hyper-DMA (HDMA) for
> > virtualization scalability. This is realized by decoupling physical DMA
> > channels(PDMA) from potentially large number of virtual DMA channels(VDMA).
> > The VDMAs provide software abstraction to driver that map to PDMAs for
> > frame transmission and reception.
> > Since 25GMAC is a derivative of XGMAC, majority of IP is common to both.
> >
> > To add support for the HDMA in 25GMAC, a new instance of dma_ops,
> > dw25gmac400_dma_ops is introduced.
> > To support the current needs, a simple one-to-one mapping of dw25gmac's
> > logical VDMA (channel) to TC to PDMAs is used. Most of the other dma
> > operation functions in existing dwxgamc2_dma.c file are reused whereever
>
> Typo: dwxgmac2_dma.c
>
> > applicable.
> > Added setup function for DW25GMAC's stmmac_hwif_entry in stmmac core.
>
> In a previous review, I questioned the use of DWMAC_CORE_25GMAC and
> asked about its version numberspace. I believe you indicated that the
> version numberspace is the same as the existing XGMAC core.
>
> I'm going to question the value of adding DWMAC_CORE_25GMAC.
>
> 1. What is the value of splitting DWMAC_CORE_25GMAC from
> DWMAC_CORE_XGMAC given that it's in the same versioning numberspace
> as XGMAC, and most tests (via dwmac_is_xgmac()) test for XGMAC or
> 25GMAC?
>
> 2. Have you reviewed all the places that explicitly test for
> DWMAC_CORE_XGMAC, looking at their "false" paths (for non-XGMAC
> cores) to determine whether they are suitable? For example:
>
> if (priv->plat->core_type == DWMAC_CORE_XGMAC)
> ndev->max_mtu = XGMAC_JUMBO_LEN;
> else if (priv->plat->enh_desc || priv->synopsys_id >= DWMAC_CORE_4_00)
> ndev->max_mtu = JUMBO_LEN;
> else
> ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
>
> XGMAC can handle a max MTU of 16368, but with your code using
> DWMAC_CORE_25GMAC, we fall back to the next test, which tests the
> IP version against 0x40, and uses a max MTU of 9000. Given that
> DWMAC_CORE_4_00 is a different "version number space" this seems
> wrong.
This is actually wrong - for DWMAC_CORE_25GMAC with a synopsys_id
less than 0x40, this will fall back to SKB_MAX_HEAD(NET_SKB_PAD +
NET_IP_ALIGN) which is as good as "pluck a number out of the air
and watch the driver fall over if you increase the MTU to maximum".
max_mtu ends up being dependent on the system page size, not on any
hardware limitation, which is garbage.
> 3. Looking at the MDIO code, this looks very wrong if you're
> introducing DWMAC_CORE_25GMAC. Have you tested MDIO accesses?
>
> dwxgmac2_setup() is called for DWMAC_CORE_XGMAC core-type. In
> stmmac_mdio_register(), DWMAC_CORE_XGMAC uses different functions
> for MDIO bus access for C22 and C45 from other cores - it uses the
> stmmac_xgmac2_mdio_* functions.
>
> These use stmmac_xgmac2_c45_format() and stmmac_xgmac2_c22_format()
> to format the register values which do not depend on mii.*_mask, but
> do use mii.address and mii.data for the register offsets. Thus, is
> there any point to setting mii.addr_mask and mii.reg_mask ?
>
> For non-DWMAC_CORE_XGMAC cores, we fall back to the stmmac_mdio_*()
> functions, which for non-DWMAC_CORE_GMAC4 will only support Clause
> 22 access, not Clause 45 - which would be very strange for a 25G
> core.
>
> 4. What about the feature printing in
> stmmac_main.c::stmmac_dma_cap_show() ?
>
> 5. What about similar tests in stmmac_est.c and stmmac_ethtool.c ?
Another issue that needs to be looked into is all the tests that
check priv->synopsys_id without checking the core_type. I'm already
concerned that many of these are wrong.
I have some patches now that rename synopsys_id to snpsver (it's really
the Synopsys IP version field which is BCD of the major version and
first digit of the minor version, not some random ID that identifies
the core.)
From what I've ascertained so far:
GMAC100 cores do not have a readable snpsver number, thus this
will be zero.
GMAC cores generally have a snpsver number less than 0x40.
GMAC4 cores may have a version number that overlaps GMAC cores
(see first entry for DWMAC_CORE_GMAC4).
XGMAC and XLGMAC cores each have an entirely separate IP version
number space from GMAC and GMAC4, which are distinguished by their
respective userver.
For example:
/* Only DWMAC core version 5.20 onwards supports HW descriptor prefetch.
*/
if (priv->snpsver < DWMAC_CORE_5_20)
priv->plat->dma_cfg->dche = false;
This will match your 25GMAC cores and the XGMAC cores because they have
a Synopsys IP version number less than 0x52. What saves us there is
that dche is only read by dwmac4_dma_init(), used by dwmac4_dma_ops and
dwmac410_dma_ops. These are all used by hwif entries that require
priv->plat->core_type to be DWMAC_CORE_GMAC4. Thus, I'm changing this
one to:
/* Only DWMAC4 core version 5.20 onwards support HW descriptor prefetch.
*/
if (priv->plat->core_type != DWMAC_CORE_GMAC4 ||
priv->snpsver < DWMAC_CORE_5_20)
priv->plat->dma_cfg->dche = false;
although I'm wondering if that should really be == && to avoid writing
to it for non-GMAC4 cores (it really doesn't matter.)
Then there this:
case HWTSTAMP_FILTER_PTP_V2_EVENT:
/* PTP v2/802.AS1 any layer, any kind of event packet */
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
ptp_v2 = PTP_TCR_TSVER2ENA;
snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
if (priv->snpsver < DWMAC_CORE_4_10)
ts_event_en = PTP_TCR_TSEVNTENA;
Is PTP_TCR_TSEVNTENA needed for this PTP filter type for XGMAC and
25GMAC cores - because they'll get it because they have snpsver
smaller than 0x41.
Similar here:
if (priv->plat->rx_coe) {
priv->hw->rx_csum = priv->plat->rx_coe;
dev_info(priv->device, "RX Checksum Offload Engine supported\n")+;
if (priv->snpsver < DWMAC_CORE_4_00)
dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csu+m);
}
In stmmac_ethtool.c, stmmac_mac_debug() won't be called for XGMAC or
25GMAC cores, because:
if (priv->snpsver >= DWMAC_CORE_3_50)
stmmac_mac_debug(priv, priv->ioaddr,
(void *)&priv->xstats,
rx_queues_count, tx_queues_count);
snpsver (synopsys_id) will be smaller than 0x35. Is this correct?
The good news is that stmmac_mdio.c at gates all its checks on the
Synopsys IP version against the core type.
I'll post my RFC patches tidying up some of the version mess in the
next day or so.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply
* Re: [PATCH v2 3/6] perf arm_spe: Store MIDR in arm_spe_pkt
From: Leo Yan @ 2026-04-07 15:41 UTC (permalink / raw)
To: James Clark
Cc: John Garry, Will Deacon, Mike Leach, Leo Yan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Al Grant, linux-arm-kernel, linux-perf-users, linux-kernel
In-Reply-To: <20260407-james-spe-impdef-decode-v2-3-55d3ef997c48@linaro.org>
On Tue, Apr 07, 2026 at 03:05:17PM +0100, James Clark wrote:
> The MIDR will affect printing of arm_spe_pkts, so store a copy of it
> there. Technically it's constant for each decoder, but there is no
> decoder when doing a raw dump, so it has to be stored in every packet.
> It will only be used in raw dump mode and not in normal decoding for
> now, but to avoid any surprises, set MIDR properly on the decoder too.
>
> Having both the MIDR and the arm_spe_pkt (which has a copy of it) in the
> decoder seemed a bit weird, so remove arm_spe_pkt from the decoder. The
> packet is only short lived anyway so probably shouldn't have been there
> in the first place.
>
> Signed-off-by: James Clark <james.clark@linaro.org>
Reviewed-by: Leo Yan <leo.yan@arm.com>
^ permalink raw reply
* [PATCH v4 0/2] perf: marvell: Add CN20K DDR PMU support
From: Geetha sowjanya @ 2026-04-07 15:35 UTC (permalink / raw)
To: linux-perf-users, linux-kernel, linux-arm-kernel, devicetree
Cc: mark.rutland, will, krzk+dt
This series adds support for the DDR Performance Monitoring Unit (PMU)
present in Marvell CN20K SoCs.
The DDR PMU is part of the DRAM Subsystem (DSS) and provides hardware
counters to monitor DDR traffic and performance events. The block
implements eight programmable counters and two fixed-function counters
tracking DDR read and write activity, and is accessed via a dedicated
MMIO region.
CN20K is the successor to CN10K, and the DDR PMU hardware is functionally
equivalent to the CN10K implementation, with only minor differences in
register offsets and event mappings. To allow software to distinguish
between the two silicon variants, this series introduces a specific
"marvell,cn20k-ddr-pmu" compatible and extends the existing
marvell_cn10k_ddr_pmu driver to handle CN20K via variant-specific data.
Signed-off-by: Geetha sowjanya <gakula@marvell.com>
Chnages in v3:
- Expanded cover letter and commit message to better describe the DDR PMU
hardware and its relationship to CN10K
- Fixed the file name.
Changes in v2:
- Fixed YAML syntax error triggered by a tab character in the examples
section, which caused dt_binding_check to fail.
Changes in v1:
- Added a description field to the binding.
- Simplified the compatible property using 'const' instead of 'items/enum'.
- Updated the example node name to include a unit-address matching the reg base.
Geetha sowjanya (2):
dt-bindings: perf: marvell: Document CN20K DDR PMU
perf: marvell: Add CN20K DDR PMU support
.../bindings/perf/marvell-cn20k-ddr-pmu.yaml | 39 ++++
drivers/perf/marvell_cn10k_ddr_pmu.c | 187 ++++++++++++++++--
2 files changed, 210 insertions(+), 16 deletions(-)
create mode 100644 Documentation/devicetree/bindings/perf/marvell-cn20k-ddr-pmu.yaml
--
2.25.1
^ permalink raw reply
* [PATCH v4 1/2] dt-bindings: perf: marvell: Add CN20K DDR PMU binding
From: Geetha sowjanya @ 2026-04-07 15:35 UTC (permalink / raw)
To: linux-perf-users, linux-kernel, linux-arm-kernel, devicetree
Cc: mark.rutland, will, krzk+dt
In-Reply-To: <20260407153511.4250-1-gakula@marvell.com>
Marvell CN20K SoCs integrate a DDR Performance Monitoring Unit (PMU)
associated with the DDR controller. The block provides hardware counters
to monitor DDR traffic and performance events and is accessed via a
dedicated MMIO region.
The CN20K DDR PMU is functionally equivalent to the CN10K DDR PMU, with
minor register offset differences. This binding documents the CN20K
variant and introduces a specific compatible string to allow software
to distinguish between the two implementations.
Signed-off-by: Geetha sowjanya <gakula@marvell.com>
---
.../bindings/perf/marvell-cn20k-ddr-pmu.yaml | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)
create mode 100644 Documentation/devicetree/bindings/perf/marvell-cn20k-ddr-pmu.yaml
diff --git a/Documentation/devicetree/bindings/perf/marvell-cn20k-ddr-pmu.yaml b/Documentation/devicetree/bindings/perf/marvell-cn20k-ddr-pmu.yaml
new file mode 100644
index 000000000000..78a0cd9a7b1f
--- /dev/null
+++ b/Documentation/devicetree/bindings/perf/marvell-cn20k-ddr-pmu.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/perf/marvell-cn20k-ddr-pmu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell CN20K DDR performance monitor
+
+description:
+ Performance Monitoring Unit (PMU) for the DDR controller
+ in Marvell CN20K SoCs.
+
+maintainers:
+ - Geetha sowjanya <gakula@marvell.com>
+
+properties:
+ compatible:
+ const: marvell,cn20k-ddr-pmu
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ ddr-pmu@c200000000 {
+ compatible = "marvell,cn20k-ddr-pmu";
+ reg = <0xc200 0x00000000 0x0 0x100000>;
+ };
+ };
--
2.25.1
^ permalink raw reply related
* [PATCH v4 2/2] perf: marvell: Add CN20K DDR PMU support
From: Geetha sowjanya @ 2026-04-07 15:35 UTC (permalink / raw)
To: linux-perf-users, linux-kernel, linux-arm-kernel, devicetree
Cc: mark.rutland, will, krzk+dt
In-Reply-To: <20260407153511.4250-1-gakula@marvell.com>
The CN20K DRAM Subsystem exposes eight programmable
performance counters and two fixed counters for DDR
read and write traffic. Software selects events for
the programmable counters from traffic at the DDR PHY
interface, the CHI interconnect, or inside the DDR controller.
Add CN20K register offsets, event maps, and sysfs attributes;
match the device via OF (marvell,cn20k-ddr-pmu) and ACPI (MRVL000B).
Represent the SoC variant in platform data with bit flags so
CN20K can reuse the CN10K PMU code path where appropriate.
Signed-off-by: Geetha sowjanya <gakula@marvell.com>
---
drivers/perf/marvell_cn10k_ddr_pmu.c | 187 ++++++++++++++++++++++++---
1 file changed, 171 insertions(+), 16 deletions(-)
diff --git a/drivers/perf/marvell_cn10k_ddr_pmu.c b/drivers/perf/marvell_cn10k_ddr_pmu.c
index 72ac17efd846..7e2e1823b009 100644
--- a/drivers/perf/marvell_cn10k_ddr_pmu.c
+++ b/drivers/perf/marvell_cn10k_ddr_pmu.c
@@ -13,31 +13,43 @@
#include <linux/hrtimer.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
+#include <linux/bits.h>
+
+/* SoC variant flags for struct ddr_pmu_platform_data (mutually exclusive in pdata) */
+#define IS_CN10K BIT(0)
+#define IS_ODY BIT(1)
+#define IS_CN20K BIT(2)
/* Performance Counters Operating Mode Control Registers */
#define CN10K_DDRC_PERF_CNT_OP_MODE_CTRL 0x8020
#define ODY_DDRC_PERF_CNT_OP_MODE_CTRL 0x20020
+#define CN20K_DDRC_PERF_CNT_OP_MODE_CTRL 0x20000
#define OP_MODE_CTRL_VAL_MANUAL 0x1
/* Performance Counters Start Operation Control Registers */
#define CN10K_DDRC_PERF_CNT_START_OP_CTRL 0x8028
#define ODY_DDRC_PERF_CNT_START_OP_CTRL 0x200A0
+#define CN20K_DDRC_PERF_CNT_START_OP_CTRL 0x20080
#define START_OP_CTRL_VAL_START 0x1ULL
#define START_OP_CTRL_VAL_ACTIVE 0x2
/* Performance Counters End Operation Control Registers */
#define CN10K_DDRC_PERF_CNT_END_OP_CTRL 0x8030
#define ODY_DDRC_PERF_CNT_END_OP_CTRL 0x200E0
+#define CN20K_DDRC_PERF_CNT_END_OP_CTRL 0x200C0
#define END_OP_CTRL_VAL_END 0x1ULL
/* Performance Counters End Status Registers */
#define CN10K_DDRC_PERF_CNT_END_STATUS 0x8038
#define ODY_DDRC_PERF_CNT_END_STATUS 0x20120
+#define CN20K_DDRC_PERF_CNT_END_STATUS 0x20100
#define END_STATUS_VAL_END_TIMER_MODE_END 0x1
/* Performance Counters Configuration Registers */
#define CN10K_DDRC_PERF_CFG_BASE 0x8040
#define ODY_DDRC_PERF_CFG_BASE 0x20160
+#define CN20K_DDRC_PERF_CFG_BASE 0x20140
+#define CN20K_DDRC_PERF_CFG1_BASE 0x20180
/* 8 Generic event counter + 2 fixed event counters */
#define DDRC_PERF_NUM_GEN_COUNTERS 8
@@ -61,6 +73,23 @@
* DO NOT change these event-id numbers, they are used to
* program event bitmap in h/w.
*/
+
+/* CN20K specific events */
+#define EVENT_PERF_OP_IS_RD16 61
+#define EVENT_PERF_OP_IS_RD32 60
+#define EVENT_PERF_OP_IS_WR16 59
+#define EVENT_PERF_OP_IS_WR32 58
+#define EVENT_OP_IS_ENTER_DSM 44
+#define EVENT_OP_IS_RFM 43
+
+#define EVENT_CN20K_OP_IS_TCR_MRR 50
+#define EVENT_CN20K_OP_IS_DQSOSC_MRR 49
+#define EVENT_CN20K_OP_IS_DQSOSC_MPC 48
+#define EVENT_CN20K_VISIBLE_WIN_LIMIT_REACHED_WR 47
+#define EVENT_CN20K_VISIBLE_WIN_LIMIT_REACHED_RD 46
+#define EVENT_CN20K_OP_IS_ZQLATCH 21
+#define EVENT_CN20K_OP_IS_ZQSTART 22
+
#define EVENT_DFI_CMD_IS_RETRY 61
#define EVENT_RD_UC_ECC_ERROR 60
#define EVENT_RD_CRC_ERROR 59
@@ -87,6 +116,9 @@
#define EVENT_OP_IS_SPEC_REF 41
#define EVENT_OP_IS_CRIT_REF 40
#define EVENT_OP_IS_REFRESH 39
+#define EVENT_OP_IS_CAS_WCK_SUS 38
+#define EVENT_OP_IS_CAS_WS_OFF 37
+#define EVENT_OP_IS_CAS_WS 36
#define EVENT_OP_IS_ENTER_MPSM 35
#define EVENT_OP_IS_ENTER_POWERDOWN 31
#define EVENT_OP_IS_ENTER_SELFREF 27
@@ -183,8 +215,8 @@ struct ddr_pmu_platform_data {
u64 cnt_freerun_clr;
u64 cnt_value_wr_op;
u64 cnt_value_rd_op;
- bool is_cn10k;
- bool is_ody;
+ u64 cfg1_base;
+ unsigned int silicon_flags; /* IS_CN10K, IS_ODY, or IS_CN20K */
};
static ssize_t cn10k_ddr_pmu_event_show(struct device *dev,
@@ -336,6 +368,80 @@ static struct attribute *odyssey_ddr_perf_events_attrs[] = {
NULL
};
+static struct attribute *cn20k_ddr_perf_events_attrs[] = {
+ /* Programmable */
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_rd_or_wr_access, EVENT_HIF_RD_OR_WR),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_wr_access, EVENT_HIF_WR),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_rd_access, EVENT_HIF_RD),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_rmw_access, EVENT_HIF_RMW),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_pri_rdaccess, EVENT_HIF_HI_PRI_RD),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_rd_bypass_access, EVENT_READ_BYPASS),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_act_bypass_access, EVENT_ACT_BYPASS),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_dfi_wr_data_access,
+ EVENT_DFI_WR_DATA_CYCLES),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_dfi_rd_data_access,
+ EVENT_DFI_RD_DATA_CYCLES),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hpri_sched_rd_crit_access,
+ EVENT_HPR_XACT_WHEN_CRITICAL),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_lpri_sched_rd_crit_access,
+ EVENT_LPR_XACT_WHEN_CRITICAL),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_wr_trxn_crit_access,
+ EVENT_WR_XACT_WHEN_CRITICAL),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_active_access, EVENT_OP_IS_ACTIVATE),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_rd_or_wr_access,
+ EVENT_OP_IS_RD_OR_WR),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_rd_active_access,
+ EVENT_OP_IS_RD_ACTIVATE),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_read, EVENT_OP_IS_RD),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_write, EVENT_OP_IS_WR),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_mwr, EVENT_OP_IS_MWR),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_precharge, EVENT_OP_IS_PRECHARGE),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_precharge_for_rdwr,
+ EVENT_PRECHARGE_FOR_RDWR),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_precharge_for_other,
+ EVENT_PRECHARGE_FOR_OTHER),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_rdwr_transitions, EVENT_RDWR_TRANSITIONS),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_write_combine, EVENT_WRITE_COMBINE),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_war_hazard, EVENT_WAR_HAZARD),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_raw_hazard, EVENT_RAW_HAZARD),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_waw_hazard, EVENT_WAW_HAZARD),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_enter_selfref, EVENT_OP_IS_ENTER_SELFREF),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_enter_powerdown,
+ EVENT_OP_IS_ENTER_POWERDOWN),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cas_ws, EVENT_OP_IS_CAS_WS),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cas_ws_off, EVENT_OP_IS_CAS_WS_OFF),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cas_wck_sus, EVENT_OP_IS_CAS_WCK_SUS),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_refresh, EVENT_OP_IS_REFRESH),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_crit_ref, EVENT_OP_IS_CRIT_REF),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_spec_ref, EVENT_OP_IS_SPEC_REF),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_load_mode, EVENT_OP_IS_LOAD_MODE),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_rfm, EVENT_OP_IS_RFM),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_enter_dsm, EVENT_OP_IS_ENTER_DSM),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_dfi_cycles, EVENT_DFI_CYCLES),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_win_limit_reached_rd,
+ EVENT_CN20K_VISIBLE_WIN_LIMIT_REACHED_RD),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_win_limit_reached_wr,
+ EVENT_CN20K_VISIBLE_WIN_LIMIT_REACHED_WR),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_dqsosc_mpc, EVENT_CN20K_OP_IS_DQSOSC_MPC),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_dqsosc_mrr, EVENT_CN20K_OP_IS_DQSOSC_MRR),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_tcr_mrr, EVENT_CN20K_OP_IS_TCR_MRR),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_zqstart, EVENT_CN20K_OP_IS_ZQSTART),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_zqlatch, EVENT_CN20K_OP_IS_ZQLATCH),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_read16, EVENT_PERF_OP_IS_RD16),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_read32, EVENT_PERF_OP_IS_RD32),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_write16, EVENT_PERF_OP_IS_WR16),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_write32, EVENT_PERF_OP_IS_WR32),
+ /* Free run event counters */
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_ddr_reads, EVENT_DDR_READS),
+ CN10K_DDR_PMU_EVENT_ATTR(ddr_ddr_writes, EVENT_DDR_WRITES),
+ NULL
+};
+
+static struct attribute_group cn20k_ddr_perf_events_attr_group = {
+ .name = "events",
+ .attrs = cn20k_ddr_perf_events_attrs,
+};
+
static struct attribute_group odyssey_ddr_perf_events_attr_group = {
.name = "events",
.attrs = odyssey_ddr_perf_events_attrs,
@@ -393,6 +499,13 @@ static const struct attribute_group *odyssey_attr_groups[] = {
NULL
};
+static const struct attribute_group *cn20k_attr_groups[] = {
+ &cn20k_ddr_perf_events_attr_group,
+ &cn10k_ddr_perf_format_attr_group,
+ &cn10k_ddr_perf_cpumask_attr_group,
+ NULL
+};
+
/* Default poll timeout is 100 sec, which is very sufficient for
* 48 bit counter incremented max at 5.6 GT/s, which may take many
* hours to overflow.
@@ -412,7 +525,7 @@ static int ddr_perf_get_event_bitmap(int eventid, u64 *event_bitmap,
switch (eventid) {
case EVENT_DFI_PARITY_POISON ...EVENT_DFI_CMD_IS_RETRY:
- if (!ddr_pmu->p_data->is_ody) {
+ if (!(ddr_pmu->p_data->silicon_flags & IS_ODY)) {
err = -EINVAL;
break;
}
@@ -524,9 +637,9 @@ static void cn10k_ddr_perf_counter_enable(struct cn10k_ddr_pmu *pmu,
int counter, bool enable)
{
const struct ddr_pmu_platform_data *p_data = pmu->p_data;
+ unsigned int silicon_flags = pmu->p_data->silicon_flags;
u64 ctrl_reg = pmu->p_data->cnt_op_mode_ctrl;
const struct ddr_pmu_ops *ops = pmu->ops;
- bool is_ody = pmu->p_data->is_ody;
u32 reg;
u64 val;
@@ -546,7 +659,7 @@ static void cn10k_ddr_perf_counter_enable(struct cn10k_ddr_pmu *pmu,
writeq_relaxed(val, pmu->base + reg);
- if (is_ody) {
+ if (silicon_flags & IS_ODY) {
if (enable) {
/*
* Setup the PMU counter to work in
@@ -621,6 +734,7 @@ static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
{
struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
const struct ddr_pmu_platform_data *p_data = pmu->p_data;
+ unsigned int silicon_flags = pmu->p_data->silicon_flags;
const struct ddr_pmu_ops *ops = pmu->ops;
struct hw_perf_event *hwc = &event->hw;
u8 config = event->attr.config;
@@ -642,10 +756,17 @@ static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
if (counter < DDRC_PERF_NUM_GEN_COUNTERS) {
/* Generic counters, configure event id */
reg_offset = DDRC_PERF_CFG(p_data->cfg_base, counter);
- ret = ddr_perf_get_event_bitmap(config, &val, pmu);
- if (ret)
- return ret;
+ if (silicon_flags & IS_CN20K) {
+ val = (1ULL << (config - 1));
+ if (config == EVENT_CN20K_OP_IS_ZQSTART ||
+ config == EVENT_CN20K_OP_IS_ZQLATCH)
+ reg_offset = DDRC_PERF_CFG(p_data->cfg1_base, counter);
+ } else {
+ ret = ddr_perf_get_event_bitmap(config, &val, pmu);
+ if (ret)
+ return ret;
+ }
writeq_relaxed(val, pmu->base + reg_offset);
} else {
/* fixed event counter, clear counter value */
@@ -952,7 +1073,25 @@ static const struct ddr_pmu_platform_data cn10k_ddr_pmu_pdata = {
.cnt_freerun_clr = 0,
.cnt_value_wr_op = CN10K_DDRC_PERF_CNT_VALUE_WR_OP,
.cnt_value_rd_op = CN10K_DDRC_PERF_CNT_VALUE_RD_OP,
- .is_cn10k = TRUE,
+ .silicon_flags = IS_CN10K,
+};
+
+static const struct ddr_pmu_platform_data cn20k_ddr_pmu_pdata = {
+ .counter_overflow_val = 0,
+ .counter_max_val = GENMASK_ULL(63, 0),
+ .cnt_base = ODY_DDRC_PERF_CNT_VALUE_BASE,
+ .cfg_base = CN20K_DDRC_PERF_CFG_BASE,
+ .cfg1_base = CN20K_DDRC_PERF_CFG1_BASE,
+ .cnt_op_mode_ctrl = CN20K_DDRC_PERF_CNT_OP_MODE_CTRL,
+ .cnt_start_op_ctrl = CN20K_DDRC_PERF_CNT_START_OP_CTRL,
+ .cnt_end_op_ctrl = CN20K_DDRC_PERF_CNT_END_OP_CTRL,
+ .cnt_end_status = CN20K_DDRC_PERF_CNT_END_STATUS,
+ .cnt_freerun_en = 0,
+ .cnt_freerun_ctrl = ODY_DDRC_PERF_CNT_FREERUN_CTRL,
+ .cnt_freerun_clr = ODY_DDRC_PERF_CNT_FREERUN_CLR,
+ .cnt_value_wr_op = ODY_DDRC_PERF_CNT_VALUE_WR_OP,
+ .cnt_value_rd_op = ODY_DDRC_PERF_CNT_VALUE_RD_OP,
+ .silicon_flags = IS_CN20K,
};
#endif
@@ -979,7 +1118,7 @@ static const struct ddr_pmu_platform_data odyssey_ddr_pmu_pdata = {
.cnt_freerun_clr = ODY_DDRC_PERF_CNT_FREERUN_CLR,
.cnt_value_wr_op = ODY_DDRC_PERF_CNT_VALUE_WR_OP,
.cnt_value_rd_op = ODY_DDRC_PERF_CNT_VALUE_RD_OP,
- .is_ody = TRUE,
+ .silicon_flags = IS_ODY,
};
#endif
@@ -989,8 +1128,7 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev)
struct cn10k_ddr_pmu *ddr_pmu;
struct resource *res;
void __iomem *base;
- bool is_cn10k;
- bool is_ody;
+ unsigned int silicon_flags;
char *name;
int ret;
@@ -1014,10 +1152,9 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev)
ddr_pmu->base = base;
ddr_pmu->p_data = dev_data;
- is_cn10k = ddr_pmu->p_data->is_cn10k;
- is_ody = ddr_pmu->p_data->is_ody;
+ silicon_flags = ddr_pmu->p_data->silicon_flags;
- if (is_cn10k) {
+ if (silicon_flags & IS_CN10K) {
ddr_pmu->ops = &ddr_pmu_ops;
/* Setup the PMU counter to work in manual mode */
writeq_relaxed(OP_MODE_CTRL_VAL_MANUAL, ddr_pmu->base +
@@ -1039,7 +1176,7 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev)
};
}
- if (is_ody) {
+ if (silicon_flags & IS_ODY) {
ddr_pmu->ops = &ddr_pmu_ody_ops;
ddr_pmu->pmu = (struct pmu) {
@@ -1056,6 +1193,22 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev)
};
}
+ if (silicon_flags & IS_CN20K) {
+ ddr_pmu->ops = &ddr_pmu_ody_ops;
+
+ ddr_pmu->pmu = (struct pmu) {
+ .module = THIS_MODULE,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
+ .task_ctx_nr = perf_invalid_context,
+ .attr_groups = cn20k_attr_groups,
+ .event_init = cn10k_ddr_perf_event_init,
+ .add = cn10k_ddr_perf_event_add,
+ .del = cn10k_ddr_perf_event_del,
+ .start = cn10k_ddr_perf_event_start,
+ .stop = cn10k_ddr_perf_event_stop,
+ .read = cn10k_ddr_perf_event_update,
+ };
+ }
/* Choose this cpu to collect perf data */
ddr_pmu->cpu = raw_smp_processor_id();
@@ -1098,6 +1251,7 @@ static void cn10k_ddr_perf_remove(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id cn10k_ddr_pmu_of_match[] = {
{ .compatible = "marvell,cn10k-ddr-pmu", .data = &cn10k_ddr_pmu_pdata },
+ { .compatible = "marvell,cn20k-ddr-pmu", .data = &cn20k_ddr_pmu_pdata },
{ },
};
MODULE_DEVICE_TABLE(of, cn10k_ddr_pmu_of_match);
@@ -1107,6 +1261,7 @@ MODULE_DEVICE_TABLE(of, cn10k_ddr_pmu_of_match);
static const struct acpi_device_id cn10k_ddr_pmu_acpi_match[] = {
{"MRVL000A", (kernel_ulong_t)&cn10k_ddr_pmu_pdata },
{"MRVL000C", (kernel_ulong_t)&odyssey_ddr_pmu_pdata},
+ {"MRVL000B", (kernel_ulong_t)&cn20k_ddr_pmu_pdata},
{},
};
MODULE_DEVICE_TABLE(acpi, cn10k_ddr_pmu_acpi_match);
--
2.25.1
^ permalink raw reply related
* Re: [PATCH v2 2/6] perf arm_spe: Handle missing CPU IDs
From: Leo Yan @ 2026-04-07 15:30 UTC (permalink / raw)
To: James Clark
Cc: John Garry, Will Deacon, Mike Leach, Leo Yan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Al Grant, linux-arm-kernel, linux-perf-users, linux-kernel
In-Reply-To: <20260407-james-spe-impdef-decode-v2-2-55d3ef997c48@linaro.org>
On Tue, Apr 07, 2026 at 03:05:16PM +0100, James Clark wrote:
> Don't call strtol() with a null pointer to avoid undefined behavior.
>
> I'm not sure of the exact scenario for missing CPU IDs but I don't think
> it happens in practice. SPE decoding can continue without them with
> reduced functionality, but print an error message anyway.
>
> Signed-off-by: James Clark <james.clark@linaro.org>
Reviewed-by: Leo Yan <leo.yan@arm.com>
> ---
> tools/perf/util/arm-spe.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
> index 7447b000f9cd..fc11f32e4911 100644
> --- a/tools/perf/util/arm-spe.c
> +++ b/tools/perf/util/arm-spe.c
> @@ -968,16 +968,23 @@ static int arm_spe__get_midr(struct arm_spe *spe, int cpu, u64 *midr)
>
> pr_warning_once("Old SPE metadata, re-record to improve decode accuracy\n");
> cpuid = perf_env__cpuid(perf_session__env(spe->session));
> + if (!cpuid)
> + goto err;
> +
> *midr = strtol(cpuid, NULL, 16);
> return 0;
> }
>
> metadata = arm_spe__get_metadata_by_cpu(spe, cpu);
> if (!metadata)
> - return -EINVAL;
> + goto err;
>
> *midr = metadata[ARM_SPE_CPU_MIDR];
> return 0;
> +
> +err:
> + pr_err("Failed to get MIDR for CPU %d\n", cpu);
> + return -EINVAL;
> }
>
> static void arm_spe__synth_ds(struct arm_spe_queue *speq,
>
> --
> 2.34.1
>
>
^ permalink raw reply
* [PATCH] arm64: rsi: use linear-map alias for realm config buffer
From: Aneesh Kumar K.V (Arm) @ 2026-04-07 15:29 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel
Cc: Aneesh Kumar K.V (Arm), Catalin Marinas, Will Deacon,
Suzuki K Poulose, Steven Price, Gavin Shan
rsi_get_realm_config() passes its argument to virt_to_phys(), but
&config is a kernel image address and not a linear-map alias.
On arm64 this triggers the below warning:
virt_to_phys used for non-linear address: (____ptrval____) (config+0x0/0x1000)
WARNING: arch/arm64/mm/physaddr.c:15 at __virt_to_phys+0x50/0x70, CPU#0: swapper/0
Modules linked in:
.....
Hardware name: linux,dummy-virt (DT)
pstate: 200000c5 (nzCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : __virt_to_phys+0x50/0x70
lr : __virt_to_phys+0x4c/0x70
.....
......
Call trace:
__virt_to_phys+0x50/0x70 (P)
arm64_rsi_init+0xa0/0x1b8
setup_arch+0x13c/0x1a0
start_kernel+0x68/0x398
__primary_switched+0x88/0x90
Pass lm_alias(&config) instead so the RSI call uses the linear-map
alias of the same buffer and avoids the boot-time warning.
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Steven Price <steven.price@arm.com>
Cc: Gavin Shan <gshan@redhat.com>
---
arch/arm64/kernel/rsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
index 9e846ce4ef9c..92160f2e57ff 100644
--- a/arch/arm64/kernel/rsi.c
+++ b/arch/arm64/kernel/rsi.c
@@ -145,7 +145,7 @@ void __init arm64_rsi_init(void)
return;
if (!rsi_version_matches())
return;
- if (WARN_ON(rsi_get_realm_config(&config)))
+ if (WARN_ON(rsi_get_realm_config(lm_alias(&config))))
return;
prot_ns_shared = __phys_to_pte_val(BIT(config.ipa_bits - 1));
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v3] arm64: dts: imx8mp: Add DT overlays for DH i.MX8M Plus DHCOM SoM and boards
From: Marek Vasut @ 2026-04-07 15:26 UTC (permalink / raw)
To: linux-arm-kernel, Frank Li
Cc: Christoph Niedermaier, Conor Dooley, Fabio Estevam,
Krzysztof Kozlowski, Pengutronix Kernel Team, Rob Herring,
Sascha Hauer, devicetree, imx, kernel, linux-kernel
In-Reply-To: <20260326044411.222907-1-marex@nabladev.com>
On 3/26/26 5:43 AM, Marek Vasut wrote:
> Add DT overlays to support DH i.MX8M Plus DHCOM SoM variants and carrier
> board expansion modules. The following DT overlays are implemented:
> - SoM:
> - DH 660-x00 SoM with 1xRMII PHY
> - DH 660-x00 SoM with 2xRMII PHY
> - PDK2:
> - DH 505-200 Display board in edge connector X12 via direct LVDS
> - DH 531-100 SPI/I2C board in header X21
> - DH 531-200 SPI/I2C board in header X22
> - DH 560-200 Display board in edge connector X12
> - PDK3:
> - DH 505-200 Display board in edge connector X36 via direct LVDS
> - DH 531-100 SPI/I2C board in header X40
> - DH 531-200 SPI/I2C board in header X41
> - DH 560-300 Display board in edge connector X36
> - EA muRata 2AE M.2 A/E-Key card in connector X20
> - NXP SPF-29853-C1 MINISASTOCSI with OV5640 sensor in connector X31
> - NXP SPF-29853-C1 MINISASTOCSI with OV5640 sensor in connector X29
> - PicoITX:
> - DH 626-100 Display board in edge connector X2
Hello Frank,
I know I was sending quite a few DTOs recently. Is this set still on
your review list, or was this one missed ?
Thank you for reviewing the DTOs so actively, it really helps a lot !
^ permalink raw reply
* Re: [PATCH 1/4] exec: inherit HWCAPs from the parent process
From: Mark Rutland @ 2026-04-07 15:23 UTC (permalink / raw)
To: Andrei Vagin
Cc: Will Deacon, Kees Cook, Andrew Morton, Marek Szyprowski,
Cyrill Gorcunov, Mike Rapoport, Alexander Mikhalitsyn,
linux-kernel, linux-fsdevel, linux-mm, criu, Catalin Marinas,
linux-arm-kernel, Chen Ridong, Christian Brauner,
David Hildenbrand, Eric Biederman, Lorenzo Stoakes, Michal Koutny,
Alexander Mikhalitsyn, Linux API
In-Reply-To: <CAEWA0a7AZiuy1F+0LDxtEtJpdu=zA-RKhPb1wcDMpy2tSMFO5g@mail.gmail.com>
On Fri, Mar 27, 2026 at 05:21:26PM -0700, Andrei Vagin wrote:
> Hi Mark,
>
> I understand all these points and they are valid. However, as I
> mentioned, we are not trying to introduce a mechanism that will strictly
> enforce feature sets for every container. While we would like to have
> that functionality, as you and will mentioned, it would require
> substantially more complexity to address, and maintainers would unlikely
> to pick up that complexity.
The crux of my complaint here is that unless you do that (to some
degree), this is not going to work reliably, even with the constraints
you outline.
Further, I disagree with your proposed solution of pushing more
constraints onto userspace (to also consider HWCAPs as overriding other
mechainsms, etc).
I think that as-is, the approach is flawed.
> Even masking ID registers on a per-container basis would introduce
> extra complexity that could make architecture maintainers unhappy.
> There were a few attempts to introduce container CPUID masking on
> x86_64 in the past.
> In CRIU, we are not aiming to handle every possible workload. Our goal
> is to target workloads where developers are ready to cooperate and
> willing to make adjustments to be C/R compatible. The goal here is to
> provide developers with clear instructions on what they can do to ensure
> their applications are C/R compatible. When I say "workloads", I mean
> this in a broad sense. A container might pack a set of tools with
> different runtimes (Go, Java, libc-based). All these runtimes should
> detect only allowed features.
I do not think that arbitrary applications (and libraries!) should have
to pick up additional constraints that are unnecessary without CRIU,
especially where that goes against deliberate design decisions (e.g.
features in arm64's HINT instruction space, which are designed to be
usable in fast paths WITHOUT needing explicit checks of things like
HWCAPs). Note that those typically *do* have kernel controls.
I think there's a much larger problem space than you anticipate, and
adding an incomplete solution now is just going to introduce a
maintenance burden.
> Returning to the subject of this patchset: this series extends the role
> of hwcaps. With this change, we would establish that hwcaps is the
> "source of truth" for which features an application can safely use. Any
> other features available on the current CPU would not be guaranteed to
> remain available after migration to another machine.
>
> After this discussion, I found that the current version missed one major
> thing: there should be a signal indicating that hwcaps must be used for
> feature detection. Since we will need to integrate this interface into
> libc, Go, and other runtimes, they definitely should not rely just on
> hwcaps by default, especially in the early stages. This can be solved
> via the prctl command. Libraries like libc would call
> prctl(PR_USER_HWCAP_ENABLED). If this returns true, the runtime knows
> that only the features explicitly listed in hwcaps should be used.
I do not think we should be pushing that shape of constraint onto
userspace.
> You are right, the controlled feature set will be limited to features
> the kernel knows about. And yes, we would need to report CPU features in
> hwcaps even if the kernel isn't directly involved in handling them.
To be clear, that is not what I am arguing.
As I mentioned before, the way this works on arm64 is that the kernel
only exposes what it is aware of, even in the ID regs accessible to
userspace. We usually *can* hide features, and do that for cases of
mismatched big.LITTLE, virtual machines, etc.
> Honestly, I am not certain if this is the "right" interface for that,
> and I would be happy to consider other ideas. I understand that these
> hwcaps will not work right out of the box, but we need a way to solve
> this problem. Having a centralized API for CPU/kernel feature detection
> seems like the right direction.
I think that for better or worse the approach you are tkaing here simply
does not solve enough of the problem to actually be worthwhile.
> As for signal frame size and extended states like SVE/SME, we aware
> about this problem. However, it is partly mitigated by the fact that if
> an application does not use some features, those states are not placed
> in the signal frame.
That is not true. The kernel can and will create signal frames for
architectural state that a task might never have touched.
Generally arm64 creates signal frames for features when the feature
*exists*, regardless of whether the task has actively manipulated the
relevant state. For example, on systems with SVE a trivial SVE signal
frame gets created even if a task only uses the FPSIMD registers, and on
systms with SME a TPIDR2 signal frame gets created even if the task has
never read/written TPIDR2.
When restoring, an unrecognised signal frame is treated as invalid, and
we can require that certain signal frames are present.
> In the future, when we construct/reload a signal frame, we could look
> at a process feature set for a process and generate a frame according
> to those features...
When you say 'we' here, are you talking about within the kernel, or
within the userspace C/R mechanism?
Mark.
^ permalink raw reply
* Re: [PATCH v2 2/3] remoteproc: imx_rproc: Pass bootaddr to SM CPU/LMM reset vector
From: Mathieu Poirier @ 2026-04-07 15:19 UTC (permalink / raw)
To: Peng Fan
Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Daniel Baluta, linux-remoteproc, devicetree, imx,
linux-arm-kernel, linux-kernel, Peng Fan
In-Reply-To: <acs2PAZq2k3zjmDW@shlinux89>
On Tue, Mar 31, 2026 at 10:49:32AM +0800, Peng Fan wrote:
> On Mon, Mar 30, 2026 at 10:22:35AM -0600, Mathieu Poirier wrote:
> >On Fri, Mar 27, 2026 at 10:42:03AM +0800, Peng Fan (OSS) wrote:
> >> From: Peng Fan <peng.fan@nxp.com>
> >>
> >> Cortex-M[7,33] processors use a fixed reset vector table format:
> >>
> >> 0x00 Initial SP value
> >> 0x04 Reset vector
> >> 0x08 NMI
> >> 0x0C ...
> >> ...
> >> IRQ[n]
> >>
> >> In ELF images, the corresponding layout is:
> >>
> >> reset_vectors: --> hardware reset address
> >> .word __stack_end__
> >> .word Reset_Handler
> >> .word NMI_Handler
> >> .word HardFault_Handler
> >> ...
> >> .word UART_IRQHandler
> >> .word SPI_IRQHandler
> >> ...
> >>
> >> Reset_Handler: --> ELF entry point address
> >> ...
> >>
> >> The hardware fetches the first two words from reset_vectors and populates
> >> SP with __stack_end__ and PC with Reset_Handler. Execution proceeds from
> >> Reset_Handler.
> >>
> >> However, the ELF entry point does not always match the hardware reset
> >> address. For example, on i.MX94 CM33S:
> >>
> >> ELF entry point: 0x0ffc211d
> >> hardware reset base: 0x0ffc0000 (default reset value, sw programmable)
> >>
> >
> >But why? Why can't the ELF image be set to the right reset base?
>
> Per zephyr general link script[1]:
> ENTRY(CONFIG_KERNEL_ENTRY)
>
> CONFIG_KERNEL_ENTRY(_start) is the first instruction that Cortex-M starts to
> execute.
>
> config KERNEL_ENTRY
> string "Kernel entry symbol"
> default "__start"
> help
> Code entry symbol, to be set at linking phase.
>
> The hardware reset base is different: it is the address where the hardware
> fetches the initial MSP and PC values from the vector table. Hardware uses
> this base to initialize the stack pointer and program counter, and only then
> does the Cortex‑M begin execution at the reset handler.
That part is clear.
>
> Aligning the ELF entry point with the hardware reset base on Cortex‑M systems
> is possible, but it comes with several risks.
I'm not asking to align the ELF entry point with the hardware reset base. All I
want is to have the correct start address embedded in the ELF file to avoid
having to use a mask.
> 1, Semantic mismatch (ELF vs. hardware behavior)
> 2, Debuggers may attempt to set breakpoints or start execution at the entry symbol
>
> [1] https://elixir.bootlin.com/zephyr/v4.4.0-rc1/source/include/zephyr/arch/arm/cortex_m/scripts/linker.ld#L103
>
> Regards
> Peng.
> >
^ permalink raw reply
* Re: [PATCH] arm64: kexec: Remove duplicate allocation for trans_pgd
From: Pasha Tatashin @ 2026-04-07 15:02 UTC (permalink / raw)
To: Wang Wensheng
Cc: catalin.marinas, will, mrigendra.chaubey, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260405114231.264761-1-wsw9603@163.com>
On Sun, Apr 5, 2026 at 7:44 AM Wang Wensheng <wsw9603@163.com> wrote:
>
> trans_pgd would be allocated in trans_pgd_create_copy(), so remove the
> duplicate allocation before calling trans_pgd_create_copy().
>
> Fixes: 3744b5280e67 ("arm64: kexec: install a copy of the linear-map")
> Signed-off-by: Wang Wensheng <wsw9603@163.com>
Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Thanks,
Pasha
> ---
> arch/arm64/kernel/machine_kexec.c | 3 ---
> 1 file changed, 3 deletions(-)
>
> diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
> index 239c16e3d02f..c5693a32e49b 100644
> --- a/arch/arm64/kernel/machine_kexec.c
> +++ b/arch/arm64/kernel/machine_kexec.c
> @@ -129,9 +129,6 @@ int machine_kexec_post_load(struct kimage *kimage)
> }
>
> /* Create a copy of the linear map */
> - trans_pgd = kexec_page_alloc(kimage);
> - if (!trans_pgd)
> - return -ENOMEM;
> rc = trans_pgd_create_copy(&info, &trans_pgd, PAGE_OFFSET, PAGE_END);
> if (rc)
> return rc;
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH v2 2/2] drm: lcdif: Wait for vblank before disabling DMA
From: Paul Kocialkowski @ 2026-04-07 15:01 UTC (permalink / raw)
To: Lucas Stach
Cc: dri-devel, imx, linux-arm-kernel, linux-kernel, Marek Vasut,
Stefan Agner, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Krzysztof Hałasa,
Marco Felsch, Liu Ying
In-Reply-To: <d6bbf0c23dc5cf0c6ab0375fb1d2d3f6b4579737.camel@pengutronix.de>
[-- Attachment #1: Type: text/plain, Size: 3404 bytes --]
Hi Lucas,
On Tue 07 Apr 26, 10:28, Lucas Stach wrote:
> Am Donnerstag, dem 02.04.2026 um 20:33 +0200 schrieb Paul Kocialkowski:
> > It is necessary to wait for the full frame to finish streaming
> > through the DMA engine before we can safely disable it by removing
> > the DISP_PARA_DISP_ON bit. Disabling it in-flight can leave the
> > hardware confused and unable to resume streaming for the next frame.
> >
> > This causes the FIFO underrun and empty status bits to be set and
> > a single solid color to be shown on the display, coming from one of
> > the pixels of the previous frame. The issue occurs sporadically when
> > a new mode is set, which triggers the crtc disable and enable paths.
> >
> > Setting the shadow load bit and waiting for it to be cleared by the
> > DMA engine allows waiting for completion.
> >
> > The NXP BSP driver addresses this issue with a hardcoded 25 ms sleep.
> >
> > Fixes: 9db35bb349a0 ("drm: lcdif: Add support for i.MX8MP LCDIF variant")
> > Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
> > Co-developed-by: Lucas Stach <l.stach@pengutronix.de>
>
> Looks good to me. Since the co-developed tag requires a sign-off from
> me, I'll add that instead of a review tag. And you might want to move
> your sign-off down, as you are the one submitting the patch.
Sounds good to me! This can probably be done when picking up the patch,
but if maintainers need me to respin the series to get all the tags in
order myself, just let me know!
All the best,
Paul
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
>
> > ---
> > drivers/gpu/drm/mxsfb/lcdif_kms.c | 15 ++++++++++++---
> > 1 file changed, 12 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > index a00c4f6d63f4..0d04a0028671 100644
> > --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > @@ -375,14 +375,23 @@ static void lcdif_disable_controller(struct lcdif_drm_private *lcdif)
> > int ret;
> >
> > reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5);
> > + /* Disable the layer for DMA. */
> > reg &= ~CTRLDESCL0_5_EN;
> > + /*
> > + * It is necessary to wait for the full frame to finish streaming
> > + * through the DMA engine before we can safely disable it by removing
> > + * the DISP_PARA_DISP_ON bit. Disabling it in-flight can leave the
> > + * hardware confused and unable to resume streaming for the next frame.
> > + */
> > + reg |= CTRLDESCL0_5_SHADOW_LOAD_EN;
> > writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5);
> >
> > + /* Wait for the frame to finish or timeout after 50 ms. */
> > ret = readl_poll_timeout(lcdif->base + LCDC_V8_CTRLDESCL0_5,
> > - reg, !(reg & CTRLDESCL0_5_EN),
> > - 0, 36000); /* Wait ~2 frame times max */
> > + reg, !(reg & CTRLDESCL0_5_SHADOW_LOAD_EN),
> > + 200, 50000);
> > if (ret)
> > - drm_err(lcdif->drm, "Failed to disable controller!\n");
> > + drm_err(lcdif->drm, "Timed out waiting for final vblank!\n");
> >
> > reg = readl(lcdif->base + LCDC_V8_DISP_PARA);
> > reg &= ~DISP_PARA_DISP_ON;
>
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH 0/4] drm/exynos: Random cleanups
From: Inki Dae @ 2026-04-07 15:00 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Chen-Yu Tsai, Seung-Woo Kim, Kyungmin Park, Krzysztof Kozlowski,
Alim Akhtar, David Airlie, Simona Vetter, dri-devel,
linux-samsung-soc, linux-arm-kernel, linux-kernel
In-Reply-To: <52a26d5b-67ec-4a99-98f6-6216e930cdb7@samsung.com>
2026년 3월 31일 (화) 오후 11:39, Marek Szyprowski <m.szyprowski@samsung.com>님이 작성:
>
> On 27.03.2026 06:44, Chen-Yu Tsai wrote:
> > On Thu, Mar 26, 2026 at 5:43 PM Chen-Yu Tsai <wenst@chromium.org> wrote:
> >> Here are some cleanups for the exynos drm driver. This was done as part
> >> of the conversion of the driver to GEM DMA helpers. These patches have
> >> no dependency, unlike the actual conversion, so I am sending them
> >> separately for inclusion now.
> >>
> >> Please take a look.
> > I should add that these patches were only compile tested.
>
> I've tested this on the real hardware and it works fine.
>
> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
Thanks Marek, :)
Inki Dae
>
> Best regards
> --
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
>
>
^ permalink raw reply
* Re: [PATCH v1 2/4] drm/bridge: dw-hdmi: Allow &dw_hdmi_plat_data.output_port = 0 without DRM_BRIDGE_ATTACH_NO_CONNECTOR
From: Luca Ceresoli @ 2026-04-07 14:53 UTC (permalink / raw)
To: Damon Ding, andrzej.hajda, neil.armstrong, rfoss,
maarten.lankhorst, mripard, tzimmermann, airlied, simona, hjc,
heiko, andy.yan, wens, samuel
Cc: Laurent.pinchart, jonas, jernej.skrabec, victor.liu,
dmitry.baryshkov, shengjiu.wang, dri-devel, linux-kernel,
linux-arm-kernel, linux-rockchip, linux-sunxi
In-Reply-To: <20260403070032.447102-3-damon.ding@rock-chips.com>
Hello Damon,
On Fri Apr 3, 2026 at 9:00 AM CEST, Damon Ding wrote:
> In the previous commit, Luca split the dw-hdmi attach process into two
> cases:
>
> A. hdmi->plat_data->output_port = 0:
> the HDMI output (port@1) in device tree is not used
>
> B. hdmi->plat_data->output_port = 1:
> the HDMI output (port@1) is parsed to find the next bridge
>
> For Rockchip, many older platforms (RK3288, RK3399, etc.) only support
> case A by default. They can support DRM_BRIDGE_ATTACH_NO_CONNECTOR flag
> after adapting to the bridge connector helper. Relax this constraint in
> preparation for Rockchip dw-hdmi bridge-connector adaptation.
>
> Link: https://lore.kernel.org/all/20260402-drm-lcdif-dbanc-v3-6-27cd247a0847@bootlin.com/
> Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
> ---
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index dd50dda3a4f5..20b2f9e145b0 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -2912,9 +2912,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
> {
> struct dw_hdmi *hdmi = bridge->driver_private;
>
> - /* DRM_BRIDGE_ATTACH_NO_CONNECTOR requires a remote-endpoint to the next bridge */
> - if (WARN_ON((flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) && !hdmi->plat_data->output_port))
> - return -EINVAL;
> + if ((flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) && !hdmi->plat_data->output_port)
> + return 0;
>
> if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
> struct device_node *remote __free(device_node) =
My understanding is that a hdmi-connector node is required in DT when using
drm_bridge_connector and DRM_BRIDGE_ATTACH_NO_CONNECTOR. Among others, it
is necessary to expose the correct connector type instead of defaulting to
DRM_MODE_CONNECTOR_HDMIA.
@Dmitry, others, can you confirm or deny the above?
If I'm correct, then the right way to support
DRM_BRIDGE_ATTACH_NO_CONNECTOR here is adding an hdmi-connector node in DT,
perhaps reusing the device tree overlay I proposed in [0].
[0] https://lore.kernel.org/lkml/20260407-drm-lcdif-dbanc-v4-8-247a16e61ef9@bootlin.com/
Luca
--
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [RFC V1 00/16] arm64/mm: Enable 128 bit page table entries
From: David Hildenbrand (Arm) @ 2026-04-07 14:44 UTC (permalink / raw)
To: Anshuman Khandual, linux-arm-kernel
Cc: Catalin Marinas, Will Deacon, Ryan Roberts, Mark Rutland,
Lorenzo Stoakes, Andrew Morton, Mike Rapoport, Linu Cherian,
linux-kernel, linux-mm
In-Reply-To: <20260224051153.3150613-1-anshuman.khandual@arm.com>
On 2/24/26 06:11, 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 been changed with D128 as there are now 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 |
> ------------------------------------------------
>
Interesting. That means user space will have it even harder to optimize
for THP sizes.
What's the effect on cont-pte? Do they still span the same number of
entries and there is effectively no change?
> From arm64 kernel features perspective KVM, KASAN and UNMAP_KERNEL_AT_EL0
> are currently not supported as well.
>
> Open Questions:
>
> - Do we need to support UNMAP_KERNEL_AT_EL0 with D128
> - Do we need to emulate traditional D64 sizes at PUD, PMD level with D128
It would certainly make user space interaction easier. But then, user
space already has to consider various PMD sizes (and is better of
querying /sys/kernel/mm/transparent_hugepage/hpage_pmd_size instead of
hardcoding it). s390x, for example, also has 1M PMD size.
I guess with "emulating" you mean something simple like always
allocating order-1 page tables that effectively have the same number of
page table entries?
The would be an option, but I recall that the pte_map_* infrastructure
currently expects that leaf page tables only ever span a single page.
So it wouldn't really give us a lot of easy benefit I guess.
--
Cheers,
David
^ permalink raw reply
* Re: [PATCH 2/4] drm/exynos: Use DRM core dedicated DMA device tracking facility
From: Inki Dae @ 2026-04-07 14:43 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Seung-Woo Kim, Kyungmin Park, Krzysztof Kozlowski, Alim Akhtar,
David Airlie, Simona Vetter, dri-devel, linux-samsung-soc,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260326094308.1161335-3-wenst@chromium.org>
2026년 3월 26일 (목) 오후 6:51, Chen-Yu Tsai <wenst@chromium.org>님이 작성:
>
> The exynos driver tracks a dedicated DMA device in its private data.
> The DRM core already has facilities to do this, and it is integrated
> into DRM PRIME imports and GEM DMA helpers.
>
> Convert the exynos driver to use the core's dedicated DMA device
> tracking facility. Also get rid of exynos_drm_gem_prime_import() as
> it is identical to drm_gem_prime_import() after the conversion.
>
> Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
> ---
> drivers/gpu/drm/exynos/exynos_drm_dma.c | 11 +++++-----
> drivers/gpu/drm/exynos/exynos_drm_drv.c | 1 -
> drivers/gpu/drm/exynos/exynos_drm_drv.h | 8 --------
> drivers/gpu/drm/exynos/exynos_drm_g2d.c | 11 +++++-----
> drivers/gpu/drm/exynos/exynos_drm_gem.c | 27 ++++++++++---------------
> drivers/gpu/drm/exynos/exynos_drm_gem.h | 2 --
> 6 files changed, 23 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dma.c b/drivers/gpu/drm/exynos/exynos_drm_dma.c
> index ccc6b852ee7d..734741c80cbe 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dma.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dma.c
> @@ -8,6 +8,7 @@
> #include <linux/iommu.h>
> #include <linux/platform_device.h>
>
> +#include <drm/drm_device.h>
> #include <drm/drm_print.h>
> #include <drm/exynos_drm.h>
>
> @@ -41,7 +42,7 @@ static int drm_iommu_attach_device(struct drm_device *drm_dev,
> struct exynos_drm_private *priv = drm_dev->dev_private;
> int ret = 0;
>
> - if (get_dma_ops(priv->dma_dev) != get_dma_ops(subdrv_dev)) {
> + if (get_dma_ops(drm_dev_dma_dev(drm_dev)) != get_dma_ops(subdrv_dev)) {
> DRM_DEV_ERROR(subdrv_dev, "Device %s lacks support for IOMMU\n",
> dev_name(subdrv_dev));
> return -EINVAL;
> @@ -93,8 +94,8 @@ int exynos_drm_register_dma(struct drm_device *drm, struct device *dev,
> {
> struct exynos_drm_private *priv = drm->dev_private;
>
> - if (!priv->dma_dev) {
> - priv->dma_dev = dev;
> + if (drm_dev_dma_dev(drm) == drm->dev) {
> + drm_dev_set_dma_dev(drm, dev);
> DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n",
> dev_name(dev));
> }
> @@ -109,7 +110,7 @@ int exynos_drm_register_dma(struct drm_device *drm, struct device *dev,
> mapping = arm_iommu_create_mapping(dev,
> EXYNOS_DEV_ADDR_START, EXYNOS_DEV_ADDR_SIZE);
> else if (IS_ENABLED(CONFIG_IOMMU_DMA))
> - mapping = iommu_get_domain_for_dev(priv->dma_dev);
> + mapping = iommu_get_domain_for_dev(dev);
>
> if (!mapping)
> return -ENODEV;
> @@ -135,5 +136,5 @@ void exynos_drm_cleanup_dma(struct drm_device *drm)
>
> arm_iommu_release_mapping(priv->mapping);
> priv->mapping = NULL;
> - priv->dma_dev = NULL;
> + drm_dev_set_dma_dev(drm, NULL);
> }
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> index 2101a74dc1ed..9ee30086879f 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> @@ -109,7 +109,6 @@ static const struct drm_driver exynos_drm_driver = {
> .open = exynos_drm_open,
> .postclose = exynos_drm_postclose,
> .dumb_create = exynos_drm_gem_dumb_create,
> - .gem_prime_import = exynos_drm_gem_prime_import,
> .gem_prime_import_sg_table = exynos_drm_gem_prime_import_sg_table,
> EXYNOS_DRM_FBDEV_DRIVER_OPS,
> .ioctls = exynos_ioctls,
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> index 06c29ff2aac0..1ab7195d09ae 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> @@ -198,7 +198,6 @@ struct drm_exynos_file_private {
> */
> struct exynos_drm_private {
> struct device *g2d_dev;
> - struct device *dma_dev;
> struct device *vidi_dev;
> void *mapping;
>
> @@ -208,13 +207,6 @@ struct exynos_drm_private {
> wait_queue_head_t wait;
> };
>
> -static inline struct device *to_dma_dev(struct drm_device *dev)
> -{
> - struct exynos_drm_private *priv = dev->dev_private;
> -
> - return priv->dma_dev;
> -}
> -
> static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
> {
> struct exynos_drm_private *priv = drm_dev->dev_private;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> index 348603262af0..85a3a247dfca 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> @@ -20,6 +20,7 @@
> #include <linux/uaccess.h>
> #include <linux/workqueue.h>
>
> +#include <drm/drm_device.h>
> #include <drm/drm_file.h>
> #include <drm/drm_print.h>
> #include <drm/exynos_drm.h>
> @@ -278,7 +279,7 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
>
> g2d->cmdlist_dma_attrs = DMA_ATTR_WRITE_COMBINE;
>
> - g2d->cmdlist_pool_virt = dma_alloc_attrs(to_dma_dev(g2d->drm_dev),
> + g2d->cmdlist_pool_virt = dma_alloc_attrs(drm_dev_dma_dev(g2d->drm_dev),
> G2D_CMDLIST_POOL_SIZE,
> &g2d->cmdlist_pool, GFP_KERNEL,
> g2d->cmdlist_dma_attrs);
> @@ -311,7 +312,7 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
> return 0;
>
> err:
> - dma_free_attrs(to_dma_dev(g2d->drm_dev), G2D_CMDLIST_POOL_SIZE,
> + dma_free_attrs(drm_dev_dma_dev(g2d->drm_dev), G2D_CMDLIST_POOL_SIZE,
to_dma_dev returns only the dedicated DMA device explicitly stored by
the Exynos driver, whereas drm_dev_dma_dev falls back to the DRM
master device when no dedicated DMA device has been set. So this does
change the existing behavior, but it does not look problematic to me.
Thanks,
Inki Dae
^ permalink raw reply
* [PATCH v8 2/4] backlight: add max25014atg backlight
From: Maud Spierings via B4 Relay @ 2026-04-07 14:41 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Helge Deller, Shawn Guo,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Liam Girdwood, Mark Brown, Frank Li
Cc: dri-devel, linux-leds, devicetree, linux-kernel, linux-fbdev, imx,
linux-arm-kernel, Maud Spierings
In-Reply-To: <20260407-max25014-v8-0-14eac7ed673a@gocontroll.com>
From: Maud Spierings <maudspierings@gocontroll.com>
The Maxim MAX25014 is a 4-channel automotive grade backlight driver IC
with integrated boost controller.
Reviewed-by: Daniel Thompson (RISCstar) <danielt@kernel.org>
Signed-off-by: Maud Spierings <maudspierings@gocontroll.com>
---
MAINTAINERS | 1 +
drivers/video/backlight/Kconfig | 7 +
drivers/video/backlight/Makefile | 1 +
drivers/video/backlight/max25014.c | 377 +++++++++++++++++++++++++++++++++++++
4 files changed, 386 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 7e3ad236537fe..1f1a5326a6aab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15692,6 +15692,7 @@ MAX25014 BACKLIGHT DRIVER
M: Maud Spierings <maudspierings@gocontroll.com>
S: Maintained
F: Documentation/devicetree/bindings/leds/backlight/maxim,max25014.yaml
+F: drivers/video/backlight/max25014.c
MAX31335 RTC DRIVER
M: Antoniu Miclaus <antoniu.miclaus@analog.com>
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index a7a3fbaf7c29e..f4e99542ffe8f 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -282,6 +282,13 @@ config BACKLIGHT_DA9052
help
Enable the Backlight Driver for DA9052-BC and DA9053-AA/Bx PMICs.
+config BACKLIGHT_MAX25014
+ tristate "Backlight driver for Maxim MAX25014"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you are using a MAX25014 chip as a backlight driver say Y to enable it.
+
config BACKLIGHT_MAX8925
tristate "Backlight driver for MAX8925"
depends on MFD_MAX8925
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 794820a98ed49..21c8313cfb121 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o
obj-$(CONFIG_BACKLIGHT_LP8788) += lp8788_bl.o
obj-$(CONFIG_BACKLIGHT_LV5207LP) += lv5207lp.o
+obj-$(CONFIG_BACKLIGHT_MAX25014) += max25014.o
obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o
obj-$(CONFIG_BACKLIGHT_MP3309C) += mp3309c.o
obj-$(CONFIG_BACKLIGHT_MT6370) += mt6370-backlight.o
diff --git a/drivers/video/backlight/max25014.c b/drivers/video/backlight/max25014.c
new file mode 100644
index 0000000000000..3ee45617261f3
--- /dev/null
+++ b/drivers/video/backlight/max25014.c
@@ -0,0 +1,377 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Backlight driver for Maxim MAX25014
+ *
+ * Copyright (C) 2025 GOcontroll B.V.
+ * Author: Maud Spierings <maudspierings@gocontroll.com>
+ */
+
+#include <linux/backlight.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define MAX25014_ISET_DEFAULT_100 11
+#define MAX_BRIGHTNESS 100
+#define MIN_BRIGHTNESS 0
+#define TON_MAX 130720 /* @153Hz */
+#define TON_STEP 1307 /* @153Hz */
+#define TON_MIN 0
+
+#define MAX25014_DEV_ID 0x00
+#define MAX25014_REV_ID 0x01
+#define MAX25014_ISET 0x02
+#define MAX25014_IMODE 0x03
+#define MAX25014_TON1H 0x04
+#define MAX25014_TON1L 0x05
+#define MAX25014_TON2H 0x06
+#define MAX25014_TON2L 0x07
+#define MAX25014_TON3H 0x08
+#define MAX25014_TON3L 0x09
+#define MAX25014_TON4H 0x0A
+#define MAX25014_TON4L 0x0B
+#define MAX25014_TON_1_4_LSB 0x0C
+#define MAX25014_SETTING 0x12
+#define MAX25014_DISABLE 0x13
+#define MAX25014_BSTMON 0x14
+#define MAX25014_IOUT1 0x15
+#define MAX25014_IOUT2 0x16
+#define MAX25014_IOUT3 0x17
+#define MAX25014_IOUT4 0x18
+#define MAX25014_OPEN 0x1B
+#define MAX25014_SHORTGND 0x1C
+#define MAX25014_SHORTED_LED 0x1D
+#define MAX25014_MASK 0x1E
+#define MAX25014_DIAG 0x1F
+
+#define MAX25014_ISET_ENA BIT(5)
+#define MAX25014_ISET_PSEN BIT(4)
+#define MAX25014_IMODE_HDIM BIT(2)
+#define MAX25014_SETTING_FPWM GENMASK(6, 4)
+#define MAX25014_DISABLE_DIS_MASK GENMASK(3, 0)
+#define MAX25014_DIAG_OT BIT(0)
+#define MAX25014_DIAG_OTW BIT(1)
+#define MAX25014_DIAG_HW_RST BIT(2)
+#define MAX25014_DIAG_BSTOV BIT(3)
+#define MAX25014_DIAG_BSTUV BIT(4)
+#define MAX25014_DIAG_IREFOOR BIT(5)
+
+struct max25014 {
+ struct i2c_client *client;
+ struct backlight_device *bl;
+ struct regmap *regmap;
+ struct gpio_desc *enable;
+ uint32_t iset;
+ uint8_t strings_mask;
+};
+
+static const struct regmap_config max25014_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX25014_DIAG,
+};
+
+static int max25014_initial_power_state(struct max25014 *maxim)
+{
+ uint32_t val;
+ int ret;
+
+ ret = regmap_read(maxim->regmap, MAX25014_ISET, &val);
+ if (ret)
+ return ret;
+
+ return val & MAX25014_ISET_ENA ? BACKLIGHT_POWER_ON : BACKLIGHT_POWER_OFF;
+}
+
+static int max25014_check_errors(struct max25014 *maxim)
+{
+ uint32_t val;
+ uint8_t i;
+ int ret;
+
+ ret = regmap_read(maxim->regmap, MAX25014_OPEN, &val);
+ if (ret)
+ return ret;
+ if (val) {
+ dev_err(&maxim->client->dev, "Open led strings detected on:\n");
+ for (i = 0; i < 4; i++) {
+ if (val & 1 << i)
+ dev_err(&maxim->client->dev, "string %d\n", i + 1);
+ }
+ return -EIO;
+ }
+
+ ret = regmap_read(maxim->regmap, MAX25014_SHORTGND, &val);
+ if (ret)
+ return ret;
+ if (val) {
+ dev_err(&maxim->client->dev, "Short to ground detected on:\n");
+ for (i = 0; i < 4; i++) {
+ if (val & 1 << i)
+ dev_err(&maxim->client->dev, "string %d\n", i + 1);
+ }
+ return -EIO;
+ }
+
+ ret = regmap_read(maxim->regmap, MAX25014_SHORTED_LED, &val);
+ if (ret)
+ return ret;
+ if (val) {
+ dev_err(&maxim->client->dev, "Shorted led detected on:\n");
+ for (i = 0; i < 4; i++) {
+ if (val & 1 << i)
+ dev_err(&maxim->client->dev, "string %d\n", i + 1);
+ }
+ return -EIO;
+ }
+
+ ret = regmap_read(maxim->regmap, MAX25014_DIAG, &val);
+ if (ret)
+ return ret;
+ /*
+ * The HW_RST bit always starts at 1 after power up.
+ * It is reset on first read, does not indicate an error.
+ */
+ if (val && val != MAX25014_DIAG_HW_RST) {
+ if (val & MAX25014_DIAG_OT)
+ dev_err(&maxim->client->dev,
+ "Overtemperature shutdown\n");
+ if (val & MAX25014_DIAG_OTW)
+ dev_err(&maxim->client->dev,
+ "Chip is getting too hot (>125C)\n");
+ if (val & MAX25014_DIAG_BSTOV)
+ dev_err(&maxim->client->dev,
+ "Boost converter overvoltage\n");
+ if (val & MAX25014_DIAG_BSTUV)
+ dev_err(&maxim->client->dev,
+ "Boost converter undervoltage\n");
+ if (val & MAX25014_DIAG_IREFOOR)
+ dev_err(&maxim->client->dev, "IREF out of range\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+/*
+ * 1. disable unused strings
+ * 2. set dim mode
+ * 3. set setting register
+ * 4. enable the backlight
+ */
+static int max25014_configure(struct max25014 *maxim, int initial_state)
+{
+ uint32_t val;
+ int ret;
+
+ ret = regmap_read(maxim->regmap, MAX25014_DISABLE, &val);
+ if (ret)
+ return ret;
+
+ /*
+ * Strings can only be disabled when MAX25014_ISET_ENA == 0, check if
+ * it needs to be changed at all to prevent the backlight flashing when
+ * it is configured correctly by the bootloader
+ */
+ if (!((val & MAX25014_DISABLE_DIS_MASK) == maxim->strings_mask)) {
+ if (initial_state == BACKLIGHT_POWER_ON) {
+ ret = regmap_write(maxim->regmap, MAX25014_ISET, 0);
+ if (ret)
+ return ret;
+ }
+ ret = regmap_write(maxim->regmap, MAX25014_DISABLE, maxim->strings_mask);
+ if (ret)
+ return ret;
+ }
+
+ ret = regmap_write(maxim->regmap, MAX25014_IMODE, MAX25014_IMODE_HDIM);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(maxim->regmap, MAX25014_SETTING, &val);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(maxim->regmap, MAX25014_SETTING,
+ val & ~MAX25014_SETTING_FPWM);
+ if (ret)
+ return ret;
+
+ return regmap_write(maxim->regmap, MAX25014_ISET,
+ maxim->iset | MAX25014_ISET_ENA |
+ MAX25014_ISET_PSEN);
+}
+
+static int max25014_update_status(struct backlight_device *bl_dev)
+{
+ struct max25014 *maxim = bl_get_data(bl_dev);
+ uint32_t reg;
+ int ret;
+
+ reg = TON_STEP * backlight_get_brightness(bl_dev);
+
+ /*
+ * 18 bit number lowest, 2 bits in first register,
+ * next lowest 8 in the L register, next 8 in the H register
+ * Seemingly setting the strength of only one string controls all of
+ * them, individual settings don't affect the outcome.
+ */
+ ret = regmap_write(maxim->regmap, MAX25014_TON_1_4_LSB, reg & 0b00000011);
+ if (ret != 0)
+ return ret;
+ ret = regmap_write(maxim->regmap, MAX25014_TON1L, (reg >> 2) & 0b11111111);
+ if (ret != 0)
+ return ret;
+ return regmap_write(maxim->regmap, MAX25014_TON1H, (reg >> 10) & 0b11111111);
+}
+
+static const struct backlight_ops max25014_bl_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .update_status = max25014_update_status,
+};
+
+static int max25014_parse_dt(struct max25014 *maxim,
+ uint32_t *initial_brightness)
+{
+ struct device *dev = &maxim->client->dev;
+ struct device_node *node = dev->of_node;
+ uint32_t strings[4];
+ int res, i;
+
+ res = of_property_count_u32_elems(node, "maxim,strings");
+ if (res == 4) {
+ of_property_read_u32_array(node, "maxim,strings", strings, 4);
+ for (i = 0; i < 4; i++) {
+ if (strings[i] == 0)
+ maxim->strings_mask |= 1 << i;
+ }
+ } else {
+ maxim->strings_mask = 0;
+ }
+
+ *initial_brightness = 50U;
+ of_property_read_u32(node, "default-brightness", initial_brightness);
+
+ maxim->iset = MAX25014_ISET_DEFAULT_100;
+ of_property_read_u32(node, "maxim,iset", &maxim->iset);
+
+ if (maxim->iset > 15)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid iset, should be a value from 0-15, entered was %d\n",
+ maxim->iset);
+
+ if (*initial_brightness > 100)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid initial brightness, should be a value from 0-100, entered was %d\n",
+ *initial_brightness);
+
+ return 0;
+}
+
+static int max25014_probe(struct i2c_client *cl)
+{
+ const struct i2c_device_id *id = i2c_client_get_device_id(cl);
+ struct backlight_properties props;
+ uint32_t initial_brightness = 50;
+ struct backlight_device *bl;
+ struct max25014 *maxim;
+ int ret;
+
+ maxim = devm_kzalloc(&cl->dev, sizeof(struct max25014), GFP_KERNEL);
+ if (!maxim)
+ return -ENOMEM;
+
+ maxim->client = cl;
+
+ ret = max25014_parse_dt(maxim, &initial_brightness);
+ if (ret)
+ return ret;
+
+ ret = devm_regulator_get_enable(&maxim->client->dev, "power");
+ if (ret)
+ return dev_err_probe(&maxim->client->dev, ret,
+ "failed to get power-supply");
+
+ maxim->enable = devm_gpiod_get_optional(&maxim->client->dev, "enable",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(maxim->enable))
+ return dev_err_probe(&maxim->client->dev, PTR_ERR(maxim->enable),
+ "failed to get enable gpio\n");
+
+ /* Datasheet Electrical Characteristics tSTARTUP 2ms */
+ fsleep(2000);
+
+ maxim->regmap = devm_regmap_init_i2c(cl, &max25014_regmap_config);
+ if (IS_ERR(maxim->regmap))
+ return dev_err_probe(&maxim->client->dev, PTR_ERR(maxim->regmap),
+ "failed to initialize the i2c regmap\n");
+
+ i2c_set_clientdata(cl, maxim);
+
+ ret = max25014_check_errors(maxim);
+ if (ret) /* error is already reported in the above function */
+ return ret;
+
+ ret = max25014_initial_power_state(maxim);
+ if (ret < 0)
+ return dev_err_probe(&maxim->client->dev, ret, "Could not get enabled state\n");
+
+ memset(&props, 0, sizeof(struct backlight_properties));
+ props.type = BACKLIGHT_PLATFORM;
+ props.max_brightness = MAX_BRIGHTNESS;
+ props.brightness = initial_brightness;
+ props.scale = BACKLIGHT_SCALE_LINEAR;
+ props.power = ret;
+
+ ret = max25014_configure(maxim, ret);
+ if (ret)
+ return dev_err_probe(&maxim->client->dev, ret, "device config error");
+
+ bl = devm_backlight_device_register(&maxim->client->dev, id->name,
+ &maxim->client->dev, maxim,
+ &max25014_bl_ops, &props);
+ if (IS_ERR(bl))
+ return dev_err_probe(&maxim->client->dev, PTR_ERR(bl),
+ "failed to register backlight\n");
+
+ maxim->bl = bl;
+
+ backlight_update_status(maxim->bl);
+
+ return 0;
+}
+
+static void max25014_remove(struct i2c_client *cl)
+{
+ struct max25014 *maxim = i2c_get_clientdata(cl);
+
+ backlight_device_set_brightness(maxim->bl, 0);
+ gpiod_set_value_cansleep(maxim->enable, 0);
+}
+
+static const struct of_device_id max25014_dt_ids[] = {
+ { .compatible = "maxim,max25014", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max25014_dt_ids);
+
+static const struct i2c_device_id max25014_ids[] = {
+ { "max25014" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max25014_ids);
+
+static struct i2c_driver max25014_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = of_match_ptr(max25014_dt_ids),
+ },
+ .probe = max25014_probe,
+ .remove = max25014_remove,
+ .id_table = max25014_ids,
+};
+module_i2c_driver(max25014_driver);
+
+MODULE_DESCRIPTION("Maxim MAX25014 backlight driver");
+MODULE_AUTHOR("Maud Spierings <maudspierings@gocontroll.com>");
+MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related
* [PATCH v8 0/4] backlight: add new max25014 backlight driver
From: Maud Spierings via B4 Relay @ 2026-04-07 14:41 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Helge Deller, Shawn Guo,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Liam Girdwood, Mark Brown, Frank Li
Cc: dri-devel, linux-leds, devicetree, linux-kernel, linux-fbdev, imx,
linux-arm-kernel, Maud Spierings
The Maxim MAX25014 is an automotive grade backlight driver IC. Its
datasheet can be found at [1].
With its integrated boost controller, it can power 4 channels (led
strings) and has a number of different modes using pwm and or i2c.
Currently implemented is only i2c control.
link: https://www.analog.com/media/en/technical-documentation/data-sheets/MAX25014.pdf [1]
Signed-off-by: Maud Spierings <maudspierings@gocontroll.com>
---
Changes in v8:
- Clean up some leftovers from the led subnodes, address/size-cells (Rob)
- Add Robs rb tag
- Add Daniels rb tag
- Bring the Kconfig option in line text wise with other drivers
- Rebase on the latest next
- Link to v7: https://lore.kernel.org/r/20260123-max25014-v7-0-15e504b9acc7@gocontroll.com
Changes in v7:
- remove the led subnodes
- always enable the regulator by using devm_regulator_get_enable()
- remove the no longer required gotos and simplify early returns
- fix the name of the SHORTED_LED error field
- fix the name of the SHORTGND error field
- use the proper backlight helper functions for setting/getting
brightness
- Link to v6: https://lore.kernel.org/r/20251201-max25014-v6-0-88e3ac8112ff@gocontroll.com
Changes in v6:
- fixup changes in v4 where default brightness handling was changed but
not noted
- remove leftover comment about initializing brightness
- use BIT definitions for fields in the DIAG register
- apply reverse christmas tree initialization of local variables
- remove !=0 from checks, just check if (ret)
- remove > 0 from checks, just check if (val)
- use dev_err_probe() more
- set enable gpio high in the get() instead of seperately calling set()
- change usleep_range() to fsleep()
- remove null checks when setting gpio value
- get regular regulator, not optional to avoid further NULL checks in
case none is provided
- introduce max25014_initial_power_state() to check if the bootloader
has already initialized the backlight and to correctly set props.power
- squash max25014_register_control() into max25014_update_status()
- in max25014_configure() perform extra checking on the DISABLE register
now that the state from the bootloader is taken into account
- Link to v5: https://lore.kernel.org/r/20251107-max25014-v5-0-9a6aa57306bf@gocontroll.com
Changes in v5:
- moved comment about current functions of the driver to the actual
comment section of the commit
- fixed the led@0 property, regex patternProperty is not needed as of
now
- added extra clarification about the ISET field/register
- moved #address-cells and #size-cells to the correct location
- remove leftover default-brightness in backlight nodes
- Link to v4: https://lore.kernel.org/r/20251009-max25014-v4-0-6adb2a0aa35f@gocontroll.com
Changes in v4:
- remove setting default brightness, let backlight core take care of it
- use a led node to describe the backlight
- use led-sources to enable specific channels
- also wait 2ms when there is a supply but no enable
- change dev_warn() to dev_err() in error path in max25014_check_errors()
- set backlight_properties.scale to BACKLIGHT_SCALE_LINEAR
- rebase latest next
- add address-cells and size-cells to i2c4 in av101hdt-a10.dtso
- Link to v3: https://lore.kernel.org/r/20250911-max25014-v3-0-d03f4eba375e@gocontroll.com
Changes in v3:
- fixed commit message type intgrated -> integrated
- added maximum and description to maxim,iset-property
- dropped unused labels and pinctrl in bindings example
- put the compatible first in the bindings example and dts
- removed brackets around defines
- removed the leftover pdata struct field
- removed the initial_brightness struct field
- Link to v2: https://lore.kernel.org/r/20250819-max25014-v2-0-5fd7aeb141ea@gocontroll.com
Changes in v2:
- Remove leftover unused property from the bindings example
- Complete the bindings example with all properties
- Remove some double info from the maxim,iset property
- Remove platform_data header, fold its data into the max25014 struct
- Don't force defines to be unsigned
- Remove stray struct max25014 declaration
- Remove chipname and device from the max25014 struct
- Inline the max25014_backlight_register() and strings_mask() functions
- Remove CONFIG_OF ifdef
- Link to v1: https://lore.kernel.org/r/20250725-max25014-v1-0-0e8cce92078e@gocontroll.com
---
Maud Spierings (4):
dt-bindings: backlight: Add max25014 support
backlight: add max25014atg backlight
arm64: dts: freescale: moduline-display-av101hdt-a10: add backlight
arm64: dts: freescale: moduline-display-av123z7m-n17: add backlight
.../bindings/leds/backlight/maxim,max25014.yaml | 83 +++++
MAINTAINERS | 6 +
...x8p-ml81-moduline-display-106-av101hdt-a10.dtso | 24 ++
...x8p-ml81-moduline-display-106-av123z7m-n17.dtso | 19 +-
drivers/video/backlight/Kconfig | 7 +
drivers/video/backlight/Makefile | 1 +
drivers/video/backlight/max25014.c | 377 +++++++++++++++++++++
7 files changed, 516 insertions(+), 1 deletion(-)
---
base-commit: f3e6330d7fe42b204af05a2dbc68b379e0ad179e
change-id: 20250626-max25014-4207591e1af5
Best regards,
--
Maud Spierings <maudspierings@gocontroll.com>
^ permalink raw reply
* [PATCH v8 3/4] arm64: dts: freescale: moduline-display-av101hdt-a10: add backlight
From: Maud Spierings via B4 Relay @ 2026-04-07 14:41 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Helge Deller, Shawn Guo,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Liam Girdwood, Mark Brown, Frank Li
Cc: dri-devel, linux-leds, devicetree, linux-kernel, linux-fbdev, imx,
linux-arm-kernel, Maud Spierings
In-Reply-To: <20260407-max25014-v8-0-14eac7ed673a@gocontroll.com>
From: Maud Spierings <maudspierings@gocontroll.com>
Add the missing backlight driver.
Signed-off-by: Maud Spierings <maudspierings@gocontroll.com>
---
...x8p-ml81-moduline-display-106-av101hdt-a10.dtso | 24 ++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tx8p-ml81-moduline-display-106-av101hdt-a10.dtso b/arch/arm64/boot/dts/freescale/imx8mp-tx8p-ml81-moduline-display-106-av101hdt-a10.dtso
index c6fc5d5b1e5fa..23e4bf64b28b5 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-tx8p-ml81-moduline-display-106-av101hdt-a10.dtso
+++ b/arch/arm64/boot/dts/freescale/imx8mp-tx8p-ml81-moduline-display-106-av101hdt-a10.dtso
@@ -17,6 +17,7 @@
panel {
compatible = "boe,av101hdt-a10";
+ backlight = <&backlight>;
enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
pinctrl-0 = <&pinctrl_panel>;
pinctrl-names = "default";
@@ -40,7 +41,30 @@ reg_vbus: regulator-vbus {
};
};
+&i2c4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ backlight: backlight@6f {
+ compatible = "maxim,max25014";
+ reg = <0x6f>;
+ default-brightness = <50>;
+ enable-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_backlight>;
+ maxim,iset = <7>;
+ maxim,strings = <1 1 1 0>;
+ };
+};
+
&iomuxc {
+ pinctrl_backlight: backlightgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO04__GPIO1_IO04
+ (MX8MP_PULL_UP | MX8MP_PULL_ENABLE)
+ >;
+ };
+
pinctrl_panel: panelgrp {
fsl,pins = <
MX8MP_IOMUXC_GPIO1_IO07__GPIO1_IO07
--
2.53.0
^ permalink raw reply related
* [PATCH v8 4/4] arm64: dts: freescale: moduline-display-av123z7m-n17: add backlight
From: Maud Spierings via B4 Relay @ 2026-04-07 14:41 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Helge Deller, Shawn Guo,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Liam Girdwood, Mark Brown, Frank Li
Cc: dri-devel, linux-leds, devicetree, linux-kernel, linux-fbdev, imx,
linux-arm-kernel, Maud Spierings
In-Reply-To: <20260407-max25014-v8-0-14eac7ed673a@gocontroll.com>
From: Maud Spierings <maudspierings@gocontroll.com>
Add the missing backlight.
Signed-off-by: Maud Spierings <maudspierings@gocontroll.com>
---
...p-tx8p-ml81-moduline-display-106-av123z7m-n17.dtso | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tx8p-ml81-moduline-display-106-av123z7m-n17.dtso b/arch/arm64/boot/dts/freescale/imx8mp-tx8p-ml81-moduline-display-106-av123z7m-n17.dtso
index 3eb665ce9d5d2..0b969c8c04db1 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-tx8p-ml81-moduline-display-106-av123z7m-n17.dtso
+++ b/arch/arm64/boot/dts/freescale/imx8mp-tx8p-ml81-moduline-display-106-av123z7m-n17.dtso
@@ -16,6 +16,7 @@
panel {
compatible = "boe,av123z7m-n17";
+ backlight = <&backlight>;
enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
pinctrl-0 = <&pinctrl_panel>;
pinctrl-names = "default";
@@ -91,10 +92,26 @@ lvds1_out: endpoint {
};
};
- /* max25014 @ 0x6f */
+ backlight: backlight@6f {
+ compatible = "maxim,max25014";
+ reg = <0x6f>;
+ default-brightness = <50>;
+ enable-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_backlight>;
+ maxim,iset = <7>;
+ maxim,strings = <1 1 1 1>;
+ };
};
&iomuxc {
+ pinctrl_backlight: backlightgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO04__GPIO1_IO04
+ (MX8MP_PULL_UP | MX8MP_PULL_ENABLE)
+ >;
+ };
+
pinctrl_lvds_bridge: lvdsbridgegrp {
fsl,pins = <
MX8MP_IOMUXC_SAI1_TXD2__GPIO4_IO14
--
2.53.0
^ permalink raw reply related
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