* [GIT PULL] Devicetree updates for v7.1
From: Rob Herring @ 2026-04-17 18:44 UTC (permalink / raw)
To: Linus Torvalds
Cc: Saravana Kannan, Krzysztof Kozlowski, Conor Dooley, linux-kernel,
devicetree
Linus,
Please pull DT updates for 7.1.
There's a couple of conflicts now with your current tree. linux-next has
the correct resolutions.
Rob
The following changes since commit 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f:
Linux 7.0-rc1 (2026-02-22 13:18:59 -0800)
are available in the Git repository at:
ssh://git@gitolite.kernel.org/pub/scm/linux/kernel/git/robh/linux.git tags/devicetree-for-7.1
for you to fetch changes up to a74c2e55ab66519ffa2069ac9ae83cd937bff4c4:
dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible (2026-04-16 08:57:47 -0500)
----------------------------------------------------------------
Devicetree updates for v7.1:
DT core:
- Cleanup of the reserved memory code to keep CMA specifics in CMA code
- Add and convert several users to new of_machine_get_match() helper
- Validate nul termination in string properties
- Update dtc to upstream v1.7.2-69-g53373d135579
- Limit matching reserved memory devices to /reserved-memory nodes
- Fix some UAF in unittests
- Remove Baikal SoC bus driver
- Fix false DT_SPLIT_BINDING_PATCH checkpatch warning
- Allow fw_devlink device-tree on x86
- Fix kerneldoc return description for of_property_count_elems_of_size()
DT bindings:
- Add fsl,imx25-aips, fsl,imx25-tcq, qcom,eliza-pdc,
qcom,eliza-spmi-pmic-arb, qcom,hawi-imem, qcom,milos-imem,
qcom,hawi-pdc, and lg,sw49410 bindings
- Convert arm,vexpress-scc to DT schema
- Deprecate Qualcomm generic CPU compatibles. Add Apple M3 CPU cores.
- Move some dual-link display panels to the dual-link schema
- Drop mux controller node name constraints
- Remove Baikal SoC bus bindings
- Fix a false warning in the thermal trip node binding
----------------------------------------------------------------
Abel Vesa (2):
dt-bindings: qcom,pdc: document the Eliza Power Domain Controller
dt-bindings: spmi: qcom,x1e80100-spmi-pmic-arb: Document Eliza compatible
Andy Shevchenko (2):
bus: Remove not-going-to-be-supported code for Baikal SoC
dt-bindings: bus: Remove unused bindings
Frank Li (2):
dt-bindings: fsl: add compatible string fsl,imx25-aips
dt-bindings: input: touchscreen: convert fsl-mx25-tcq.txt to yaml
Geert Uytterhoeven (7):
dt-bindings: interrupt-controller: arm,gic-v3: Fix EPPI range
of: Add of_machine_get_match() helper
of: Convert to of_machine_get_match()
cpufreq: airoha: Convert to of_machine_get_match()
cpufreq: qcom-nvmem: Convert to of_machine_get_match()
cpufreq: ti-cpufreq: Convert to of_machine_get_match()
soc: qcom: pd-mapper: Convert to of_machine_get_match()
Herve Codina (1):
of: property: Allow fw_devlink device-tree on x86
Janne Grunau (1):
dt-bindings: arm: cpus: Add Apple M3 CPU core compatibles
Kenny Cheng (1):
of: fix incorrect device creation for reserved memory nodes
Khushal Chitturi (1):
dt-bindings: ARM: arm,vexpress-scc: convert to DT schema
Konrad Dybcio (1):
dt-bindings: sram: Allow multiple-word prefixes to sram subnode
Krzysztof Kozlowski (2):
dt-bindings: arm: cpus: Deprecate Qualcomm generic compatibles
dt-bindings: display: lt8912b: Drop redundant endpoint properties
Luca Weiss (1):
dt-bindings: sram: Document qcom,milos-imem
Marek Szyprowski (7):
of: reserved_mem: remove fdt node from the structure
of: reserved_mem: use -ENODEV instead of -ENOENT
of: reserved_mem: switch to ops based OF_DECLARE()
of: reserved_mem: replace CMA quirks by generic methods
of: reserved_mem: rearrange code a bit
of: reserved_mem: clarify fdt_scan_reserved_mem*() functions
of: reserved_mem: rework fdt_init_reserved_mem_node()
Marek Vasut (2):
dt-bindings: display: simple: Move AUO 21.5" FHD to dual-link
dt-bindings: display: simple: Move Innolux G156HCE-L01 panel to dual-link
Markus Heidelberg (1):
docs: dt: unittest: update to current unittest filenames
Mukesh Ojha (2):
dt-bindings: sram: Document qcom,hawi-imem compatible
dt-bindings: qcom,pdc: document the Hawi Power Domain Controller
Paul Sajna (1):
dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible
Pengpeng Hou (2):
drivers/of: fdt: validate stdout-path properties before parsing them
drivers/of: fdt: validate flat DT string properties before string use
Rob Herring (Arm) (4):
checkpatch: Fix false DT_SPLIT_BINDING_PATCH warnings
Merge branch 'dt-reserved-mem-cleanups' into dt/next
scripts/dtc: Update to upstream version v1.7.2-69-g53373d135579
dt-bindings: thermal: Fix false warning with 'phandle' in trips nodes
Song Hongyi (1):
of: property: fix typo in kernel-doc return description
Swamil Jain (1):
dt-bindings: display: ti, am65x-dss: Fix AM62L DSS reg and clock constraints
Tommaso Merciai (1):
dt-bindings: mux: Remove nodename pattern constraints
Vivian Wang (1):
dt-bindings: opp-v2: Fix example 3 CPU reg value
Wentao Liang (2):
of: unittest: fix use-after-free in of_unittest_changeset()
of: unittest: fix use-after-free in testdrv_probe()
Xu Yang (1):
dt-bindings: connector: add pd-disable dependency
.../devicetree/bindings/arm/arm,vexpress-scc.yaml | 53 +++
Documentation/devicetree/bindings/arm/cpus.yaml | 292 +++++++--------
.../bindings/arm/freescale/fsl,imx51-m4if.yaml | 1 +
.../devicetree/bindings/arm/vexpress-scc.txt | 33 --
.../devicetree/bindings/bus/baikal,bt1-apb.yaml | 90 -----
.../devicetree/bindings/bus/baikal,bt1-axi.yaml | 107 ------
.../bindings/connector/usb-connector.yaml | 1 +
.../bindings/display/bridge/lontium,lt8912b.yaml | 3 -
.../panel/panel-simple-lvds-dual-ports.yaml | 4 +
.../bindings/display/panel/panel-simple.yaml | 6 +-
.../bindings/display/ti/ti,am65x-dss.yaml | 70 +++-
.../bindings/input/touchscreen/fsl,imx25-tcq.yaml | 69 ++++
.../bindings/input/touchscreen/fsl-mx25-tcq.txt | 34 --
.../bindings/interrupt-controller/arm,gic-v3.yaml | 2 +-
.../bindings/interrupt-controller/qcom,pdc.yaml | 2 +
.../devicetree/bindings/mux/mux-controller.yaml | 6 -
Documentation/devicetree/bindings/opp/opp-v2.yaml | 8 +-
.../bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml | 4 +-
Documentation/devicetree/bindings/sram/sram.yaml | 4 +-
.../devicetree/bindings/thermal/thermal-zones.yaml | 111 +++---
Documentation/devicetree/of_unittest.rst | 20 +-
.../translations/zh_CN/devicetree/of_unittest.rst | 21 +-
drivers/bus/Kconfig | 30 --
drivers/bus/Makefile | 2 -
drivers/bus/bt1-apb.c | 396 ---------------------
drivers/bus/bt1-axi.c | 292 ---------------
drivers/cpufreq/airoha-cpufreq.c | 7 +-
drivers/cpufreq/qcom-cpufreq-nvmem.c | 16 +-
drivers/cpufreq/ti-cpufreq.c | 12 +-
drivers/memory/tegra/tegra210-emc-table.c | 19 +-
drivers/of/base.c | 20 +-
drivers/of/fdt.c | 44 +--
drivers/of/of_private.h | 2 +-
drivers/of/of_reserved_mem.c | 320 ++++++++++-------
drivers/of/platform.c | 12 +-
drivers/of/property.c | 28 +-
drivers/of/unittest.c | 4 +-
drivers/soc/qcom/qcom_pd_mapper.c | 8 +-
include/linux/cma.h | 10 -
include/linux/dma-map-ops.h | 3 -
include/linux/of.h | 11 +-
include/linux/of_reserved_mem.h | 16 +-
kernel/dma/coherent.c | 19 +-
kernel/dma/contiguous.c | 86 +++--
kernel/dma/swiotlb.c | 19 +-
scripts/checkpatch.pl | 2 +-
scripts/dtc/checks.c | 2 +-
scripts/dtc/dtc-lexer.l | 3 -
scripts/dtc/dtc.h | 2 +-
scripts/dtc/libfdt/fdt.c | 8 +
scripts/dtc/libfdt/fdt_rw.c | 9 +-
scripts/dtc/version_gen.h | 2 +-
52 files changed, 795 insertions(+), 1550 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/arm,vexpress-scc.yaml
delete mode 100644 Documentation/devicetree/bindings/arm/vexpress-scc.txt
delete mode 100644 Documentation/devicetree/bindings/bus/baikal,bt1-apb.yaml
delete mode 100644 Documentation/devicetree/bindings/bus/baikal,bt1-axi.yaml
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/fsl,imx25-tcq.yaml
delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt
delete mode 100644 drivers/bus/bt1-apb.c
delete mode 100644 drivers/bus/bt1-axi.c
^ permalink raw reply
* [PATCH v3] dt-bindings: iio: gyroscope: add mount-matrix for bmg160
From: Vishwas Rajashekar via B4 Relay @ 2026-04-17 18:41 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
H. Nikolaus Schaller
Cc: linux-iio, devicetree, linux-kernel, luca, Vishwas Rajashekar
From: Vishwas Rajashekar <vishwas.dev@vrajashkr.com>
The mount-matrix property supplies a 3x3 matrix that is used
to transform the values from the gyroscope to get vector
values that are relative to the way the sensor has been mounted
on the device. When the property is not specified, the identity
matrix is used.
This change adds mount-matrix as an optional property to the
dt-bindings for the bmg160 gyroscope.
Signed-off-by: Vishwas Rajashekar <vishwas.dev@vrajashkr.com>
---
The bmg160 driver reads an optional mount-matrix using
"iio_read_mount_matrix" in "bmg160_core_probe" and stores
this orientation data in "struct bmg160_data". As the "mount-matrix"
property is used by the driver, this change proposes to add it to
the corresponding dt-bindings.
---
Changes in v3:
- Addressed review feedback: updated the commit message to indicate
relevance to hardware and remove references to the Linux driver.
- Link to v2: https://patch.msgid.link/20260416-bmg160-mount-matrix-dt-binding-v2-1-e66cf5cff8e8@vrajashkr.com
Changes in v2:
- Addressed review feedback: add mount-matrix example for bmg160
- Link to v1: https://patch.msgid.link/20260415-bmg160-mount-matrix-dt-binding-v1-1-0e2c85964ee6@vrajashkr.com
To: Jonathan Cameron <jic23@kernel.org>
To: David Lechner <dlechner@baylibre.com>
To: Nuno Sá <nuno.sa@analog.com>
To: Andy Shevchenko <andy@kernel.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: "H. Nikolaus Schaller" <hns@goldelico.com>
Cc: linux-iio@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml b/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml
index 3c6fe74af0b8..ec97778cca78 100644
--- a/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml
+++ b/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml
@@ -22,6 +22,9 @@ properties:
vdd-supply: true
vddio-supply: true
+ mount-matrix:
+ description: an optional 3x3 mounting rotation matrix.
+
spi-max-frequency:
maximum: 10000000
@@ -52,6 +55,9 @@ examples:
reg = <0x69>;
interrupt-parent = <&gpio6>;
interrupts = <18 IRQ_TYPE_EDGE_RISING>;
+ mount-matrix = "0", "1", "0",
+ "1", "0", "0",
+ "0", "0", "1";
};
};
...
---
base-commit: 591cd656a1bf5ea94a222af5ef2ee76df029c1d2
change-id: 20260414-bmg160-mount-matrix-dt-binding-e76ddde94866
Best regards,
--
Vishwas Rajashekar <vishwas.dev@vrajashkr.com>
^ permalink raw reply related
* Re: [PATCH 04/11] media: iris: Add helper to create a context bank device on iris vpu bus
From: Dmitry Baryshkov @ 2026-04-17 18:23 UTC (permalink / raw)
To: Vishnu Reddy
Cc: Bryan O'Donoghue, Vikash Garodia, Dikshita Agarwal,
Abhinav Kumar, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Joerg Roedel, Will Deacon,
Robin Murphy, Bjorn Andersson, Konrad Dybcio, Stefan Schmidt,
Hans Verkuil, linux-media, linux-arm-msm, devicetree,
linux-kernel, iommu
In-Reply-To: <b0ba2172-3f66-c912-29e9-0a48b4480987@oss.qualcomm.com>
On Fri, Apr 17, 2026 at 08:49:44PM +0530, Vishnu Reddy wrote:
>
> On 4/14/2026 8:48 PM, Dmitry Baryshkov wrote:
> > On Tue, Apr 14, 2026 at 10:30:00AM +0530, Vishnu Reddy wrote:
> > > From: Vikash Garodia<vikash.garodia@oss.qualcomm.com>
> > >
> > > Add a helper function to allocate and register context bank (CB) device
> > > on the iris vpu bus. The function ID associated with the CB is specified
> > > from the platform data, allowing the bus dma_configure callback to apply
> > > correct stream ID mapping when device is registered.
> > >
> > > Signed-off-by: Vikash Garodia<vikash.garodia@oss.qualcomm.com>
> > > Signed-off-by: Vishnu Reddy<busanna.reddy@oss.qualcomm.com>
> > > ---
> > > drivers/media/platform/qcom/iris/iris_resources.c | 33 +++++++++++++++++++++++
> > > drivers/media/platform/qcom/iris/iris_resources.h | 1 +
> > > 2 files changed, 34 insertions(+)
> > >
> > > diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c
> > > index 773f6548370a..a25e0f2e9d26 100644
> > > --- a/drivers/media/platform/qcom/iris/iris_resources.c
> > > +++ b/drivers/media/platform/qcom/iris/iris_resources.c
> > > @@ -6,6 +6,7 @@
> > > #include <linux/clk.h>
> > > #include <linux/devfreq.h>
> > > #include <linux/interconnect.h>
> > > +#include <linux/iris_vpu_bus.h>
> > > #include <linux/pm_domain.h>
> > > #include <linux/pm_opp.h>
> > > #include <linux/pm_runtime.h>
> > > @@ -141,3 +142,35 @@ int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type
> > > return 0;
> > > }
> > > +
> > > +static void iris_release_cb_dev(struct device *dev)
> > > +{
> > > + kfree(dev);
> > > +}
> > > +
> > > +struct device *iris_create_cb_dev(struct iris_core *core, const char *name, const u32 *f_id)
> > Please move into the bus code and make it generic enough.
> Do you suggest to add a wrapper to pass the varying inputs to the generic
> bus, something like this
> struct device* create_and_register_device(dma_mask, parent_dev, *release,
> dev_name,...)
Definitely not the release function. The devname is also not that
important. The rest, yes, you are correct.
> > > +{
> > > + struct device *dev;
> > > + int ret;
> > > +
> > > + dev = kzalloc_obj(*dev);
> > > + if (!dev)
> > > + return ERR_PTR(-ENOMEM);
> > > +
> > > + dev->release = iris_release_cb_dev;
> > > + dev->bus = &iris_vpu_bus_type;
> > > + dev->parent = core->dev;
> > > + dev->coherent_dma_mask = core->iris_platform_data->dma_mask;
> > > + dev->dma_mask = &dev->coherent_dma_mask;
> > Would you also need to set the of_node? See
> > device_set_of_node_from_dev()
>
> It might be needed for FastRPC as they are following sub node approach, Iris
> does not need.
Wouldn't it save you from passing it to of_dma_configure_id()?
> > > +
> > > + dev_set_name(dev, "%s", name);
> > > + dev_set_drvdata(dev, (void *)f_id);
> > > +
> > > + ret = device_register(dev);
> > > + if (ret) {
> > > + put_device(dev);
> > > + return ERR_PTR(ret);
> > > + }
> > > +
> > > + return dev;
> > > +}
> > > diff --git a/drivers/media/platform/qcom/iris/iris_resources.h b/drivers/media/platform/qcom/iris/iris_resources.h
> > > index 6bfbd2dc6db0..4a494627ff23 100644
> > > --- a/drivers/media/platform/qcom/iris/iris_resources.h
> > > +++ b/drivers/media/platform/qcom/iris/iris_resources.h
> > > @@ -15,5 +15,6 @@ int iris_unset_icc_bw(struct iris_core *core);
> > > int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw);
> > > int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type clk_type);
> > > int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type);
> > > +struct device *iris_create_cb_dev(struct iris_core *core, const char *name, const u32 *f_id);
> > > #endif
> > >
> > > --
> > > 2.34.1
> > >
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH 02/11] media: iris: Add iris vpu bus support and register it with iommu_buses
From: Dmitry Baryshkov @ 2026-04-17 18:19 UTC (permalink / raw)
To: Vishnu Reddy
Cc: Bryan O'Donoghue, Vikash Garodia, Dikshita Agarwal,
Abhinav Kumar, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Joerg Roedel, Will Deacon,
Robin Murphy, Bjorn Andersson, Konrad Dybcio, Stefan Schmidt,
Hans Verkuil, linux-media, linux-arm-msm, devicetree,
linux-kernel, iommu
In-Reply-To: <26b71f52-3355-d4e9-f640-007123e3aba2@oss.qualcomm.com>
On Fri, Apr 17, 2026 at 08:29:21PM +0530, Vishnu Reddy wrote:
> apologies for re-sending (earlier responses was rejected due to HTML format)
Ugh.
>
> On 4/17/2026 8:22 PM, Vishnu Reddy wrote:
> > On 4/14/2026 8:44 PM, Dmitry Baryshkov wrote:
> > > On Tue, Apr 14, 2026 at 10:29:58AM +0530, Vishnu Reddy wrote:
> > > > From: Vikash Garodia<vikash.garodia@oss.qualcomm.com>
> > > >
> > > > Add a dedicated iris VPU bus type and register it into the iommu_buses
> > > > list. Iris devices require their own bus so that each device can run its
> > > > own dma_configure() logic.
> > > This really tells nothing, unless one has full context about the Iris
> > > needs. Start by describing the issue (that the device needs to have
> > > multiple devices talking to describe IOMMUs / VAs for several hardware
> > > functions), then continue by describing what is needed from the IOMMU
> > > subsys.
> >
> > This series handles firmware device which do not require multiple
> > devices part.
> > given this device need for specific IOMMU configuration, I'll update the
> > description
> > accordingly.
> >
> > > > Signed-off-by: Vikash Garodia<vikash.garodia@oss.qualcomm.com>
> > > > Signed-off-by: Vishnu Reddy<busanna.reddy@oss.qualcomm.com>
> > > > ---
> > > > drivers/iommu/iommu.c | 4 ++++
> > > > drivers/media/platform/qcom/iris/Makefile | 4 ++++
> > > > drivers/media/platform/qcom/iris/iris_vpu_bus.c | 32 +++++++++++++++++++++++++
> > > > include/linux/iris_vpu_bus.h | 13 ++++++++++
> > > How are you supposed to merge this? Through IOMMU tree? Through venus
> > > tree? Can we add one single bus to the IOMMU code and use it for Iris,
> > > Venus, FastRPC, host1x and all other device drivers which require
> > > per-device DMA configuration?
> >
> > Separating out the bus definition and the Iris driver handling would
> > provide a
> > cleaner merge path.
Then why wasn't it done from the ground up?
> >
> > > Your colleagues from the FastRPC team posted a very similar code few
> > > weeks ago and got exactly the same feedback. Is there a reason why your
> > > teams don't sync on the IOMMU parts at all?
> >
> > I would admit that I missed to review that, thank you for bringing that
> > discussion.
> > FastRPC patches generalizes the handling for host1x, FastRPC and the
> > same can be
> > extended for Iris. I have left few comments there.
> >
> > > > 4 files changed, 53 insertions(+)
> > > >
> > > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> > > > index 61c12ba78206..d8ed6ef70ecd 100644
> > > > --- a/drivers/iommu/iommu.c
> > > > +++ b/drivers/iommu/iommu.c
> > > > @@ -13,6 +13,7 @@
> > > > #include <linux/bug.h>
> > > > #include <linux/types.h>
> > > > #include <linux/init.h>
> > > > +#include <linux/iris_vpu_bus.h>
> > > > #include <linux/export.h>
> > > > #include <linux/slab.h>
> > > > #include <linux/errno.h>
> > > > @@ -179,6 +180,9 @@ static const struct bus_type * const iommu_buses[] = {
> > > > #ifdef CONFIG_CDX_BUS
> > > > &cdx_bus_type,
> > > > #endif
> > > > +#if IS_ENABLED(CONFIG_VIDEO_QCOM_IRIS)
> > > > + &iris_vpu_bus_type,
> > > > +#endif
> > > > };
> > > > /*
> > > > diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
> > > > index 2abbd3aeb4af..6f4052b98491 100644
> > > > --- a/drivers/media/platform/qcom/iris/Makefile
> > > > +++ b/drivers/media/platform/qcom/iris/Makefile
> > > > @@ -31,3 +31,7 @@ qcom-iris-objs += iris_platform_gen1.o
> > > > endif
> > > > obj-$(CONFIG_VIDEO_QCOM_IRIS) += qcom-iris.o
> > > > +
> > > > +ifdef CONFIG_VIDEO_QCOM_IRIS
> > > > +obj-y += iris_vpu_bus.o
> > > > +endif
> > > > diff --git a/drivers/media/platform/qcom/iris/iris_vpu_bus.c b/drivers/media/platform/qcom/iris/iris_vpu_bus.c
> > > > new file mode 100644
> > > > index 000000000000..b51bb4b82b0e
> > > > --- /dev/null
> > > > +++ b/drivers/media/platform/qcom/iris/iris_vpu_bus.c
> > > > @@ -0,0 +1,32 @@
> > > > +// SPDX-License-Identifier: GPL-2.0-only
> > > > +/*
> > > > + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved.
> > > > + */
> > > > +
> > > > +#include <linux/device.h>
> > > > +#include <linux/of_device.h>
> > > > +
> > > > +#include "iris_platform_common.h"
> > > > +
> > > > +static int iris_vpu_bus_dma_configure(struct device *dev)
> > > > +{
> > > > + const u32 *f_id = dev_get_drvdata(dev);
> > > > +
> > > > + if (!f_id)
> > > > + return -ENODEV;
> > > > +
> > > > + return of_dma_configure_id(dev, dev->parent->of_node, true, f_id);
> > > I think it was discussed that this is not enough. Some of devices need
> > > multiple function IDs.
> >
> > In this glymur series we are following the legacy way of handling IOMMUs
> > and does not
> > require multi map.
Why can't we land the version that has multiple entries? It's as if the
teams are totally not in sync. The corresponding version is in works, it
has been implemented, etc.
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH 4/4] arm64: dts: qcom: sdm630: assign adsp_mem region to ADSP FastRPC node
From: Dmitry Baryshkov @ 2026-04-17 18:12 UTC (permalink / raw)
To: Nickolay Goppen
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-arm-msm, devicetree, linux-kernel,
~postmarketos/upstreaming
In-Reply-To: <20260415-qcom-sdm660-cdsp-adsp-fastrpc-dts-fix-v1-4-03b475b29554@mainlining.org>
On Wed, Apr 15, 2026 at 12:40:26PM +0300, Nickolay Goppen wrote:
> Downstream [1] ADSP FastRPC node has the adsp_mem region assigned, so
> assign it to the ADSP FastRPC node.
>
> [1]: https://github.com/xiaomi-sdm660/android_kernel_xiaomi_sdm660/blob/11-EAS/arch/arm/boot/dts/qcom/sdm660.dtsi#L1693
>
> Signed-off-by: Nickolay Goppen <setotau@mainlining.org>
> ---
> arch/arm64/boot/dts/qcom/sdm630.dtsi | 1 +
> 1 file changed, 1 insertion(+)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH 2/4] arm64: dts: qcom: sdm630: set adsp compute-cbs' regs properly
From: Dmitry Baryshkov @ 2026-04-17 18:08 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Nickolay Goppen, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, devicetree,
linux-kernel, ~postmarketos/upstreaming
In-Reply-To: <455942ab-a55e-48cd-a37b-6ab9efde84f4@oss.qualcomm.com>
On Wed, Apr 15, 2026 at 11:50:09AM +0200, Konrad Dybcio wrote:
> On 4/15/26 11:40 AM, Nickolay Goppen wrote:
> > Changing FastRPC compute-cbs' reg values to matching iommu streams
> > solves SMMU translation errors when trying to use FastRPC on ADSP
> > so change FastRPC compute-cbs' reg values that way
> >
> > Signed-off-by: Nickolay Goppen <setotau@mainlining.org>
> > ---
>
> Fixes: af2ce7296643 ("arm64: dts: qcom: sdm630: Add FastRPC nodes to ADSP")
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>
> Konrad
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH 1/4] arm64: dts: qcom: sdm660: set cdsp compute-cbs' regs properly
From: Dmitry Baryshkov @ 2026-04-17 18:08 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Nickolay Goppen, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, devicetree,
linux-kernel, ~postmarketos/upstreaming
In-Reply-To: <42649c1c-3868-44ea-8186-49e34abf10b9@oss.qualcomm.com>
On Wed, Apr 15, 2026 at 11:43:29AM +0200, Konrad Dybcio wrote:
> On 4/15/26 11:40 AM, Nickolay Goppen wrote:
> > Changing FastRPC compute-cbs' reg values to matching iommu streams
> > solves SMMU translation errors when trying to use FastRPC on CDSP
> > so change FastRPC compute-cbs' reg values that way
> >
> > Signed-off-by: Nickolay Goppen <setotau@mainlining.org>
> > ---
>
> Fixes: c0c32a9e3493 ("arm64: dts: qcom: sdm630/660: Add CDSP-related nodes")
With Fixes in place:
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>
> Konrad
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH 2/4] hwmon: Add Qualcomm PMIC BCL hardware monitor driver
From: Manaf Meethalavalappu Pallikunhi @ 2026-04-17 18:08 UTC (permalink / raw)
To: Daniel Lezcano, Guenter Roeck
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, amit.kucheria, Daniel Lezcano, Gaurav Kohli,
linux-hwmon, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <6f4b27c5-074e-403a-90b8-fe7ef3a993b5@oss.qualcomm.com>
Hi Daniel/Guenter,
On 3/20/2026 9:38 PM, Daniel Lezcano wrote:
>
> Hi Guenter,
>
> On 3/20/26 16:22, Guenter Roeck wrote:
>> On 3/20/26 07:52, Daniel Lezcano wrote:
>
> [ ... ]
>
>>>> +
>>>> +ADD_BCL_HWMON_ALARM_MAPS(in, min, lcrit);
>>>> +ADD_BCL_HWMON_ALARM_MAPS(curr, max, crit);
>>>> +
>>>> +/* Interrupt names for each alarm level */
>>>> +static const char * const bcl_int_names[ALARM_MAX] = {
>>>> + [LVL0] = "bcl-max-min",
>>>> + [LVL1] = "bcl-critical",
>>>> +};
>>>
>>> IIUC there are three levels of alarms but the hwmon only has max/min
>>> and critical. Would it make sense to do adaptative min / max ? So when
>>
>> hwmon has lcrit, min, max, and crit alarms for all sensor types, plus
>> an additional _cap_alarm for power attributes and _emergency_alarm
>> for temperature attributes. There is also a generic _alarm attribute
>> for each sensor, which is supposed to be used if the specific alarm
>> type is not known.
>>
>> What exactly are the three levels of alarms ?
>
> Manaf can give more clarifications, but it is like we have yellow,
> orange and red alarms. So there is an additional alarm comparing to what
> is available in hwmon. The proposed driver maps orange and red alarms,
> respectively to bcl-max and bcl-critical.
Yes, it is different limit level alarms (3 low voltage and 3 over
current) like yellow, orange and Red.
Currently I mapped, yellow and orange. Red is not enabled.
Thanks,
Manaf
>
> I'm just asking if it is important to have this 'yellow' alarm ? And as
> there is a missing alarm to describe it in hwmon, how can we use it ?
^ permalink raw reply
* Re: [PATCH v8 2/2] iio: dac: ad5706r: Add support for AD5706R DAC
From: Andy Shevchenko @ 2026-04-17 18:05 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Alexis Czezar Torreno, Lars-Peter Clausen, Michael Hennerich,
Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-iio,
devicetree, linux-kernel
In-Reply-To: <20260417135624.000030e5@huawei.com>
On Fri, Apr 17, 2026 at 01:56:24PM +0100, Jonathan Cameron wrote:
> On Fri, 17 Apr 2026 11:35:12 +0300
> Andy Shevchenko <andriy.shevchenko@intel.com> wrote:
> > On Fri, Apr 17, 2026 at 04:27:16PM +0800, Alexis Czezar Torreno wrote:
...
> > > +#define AD5706R_DAC_RESOLUTION 16
> > > +#define AD5706R_DAC_MAX_CODE GENMASK(15, 0)
> >
> > I know Jonathan asked for this, hence it's comment for him.
> > I think that BIT() notation in a form of (BIT(16) - 1) is
> > also appropriate here as it gives the relationship to the
> > resolution of the given register / bitfield in HW.
> >
> > GENMASK() works for me, but it might require an additional
> > operation to deduce the above.
> >
> > (Note, there is no request to change or resend for you, Alexis. It's just
> > a remark to make Jonathan to think about which one suits better. He might
> > change that whilst applying.)
> >
> I'm not against that form. It was more being against bare BIT(16) as that was
> 1 greater than the maximum value it can take.
> However making the relationship explicit would be even better.
>
> #define AD5705_DAC_MAX_CODE (BIT(AD5706R_DAC_RESOLUTION) - 1)
While that's technically correct, I would still prefer an explicit number
#define AD5705_DAC_MAX_CODE (BIT(16) - 1)
Note, GENMASK() is also fine with me, this is really a minor difference.
> I might tweak it when picking this up.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 2/4] hwmon: Add Qualcomm PMIC BCL hardware monitor driver
From: Manaf Meethalavalappu Pallikunhi @ 2026-04-17 18:01 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, amit.kucheria, Daniel Lezcano,
Gaurav Kohli, linux-hwmon, linux-arm-msm, devicetree,
linux-kernel
In-Reply-To: <ab1fSWx7pqlSANph@mai.linaro.org>
Hi Daniel,
On 3/20/2026 8:22 PM, Daniel Lezcano wrote:
> Hi Manaf,
>
> On Fri, Feb 06, 2026 at 02:44:06AM +0530, Manaf Meethalavalappu Pallikunhi wrote:
>> Add support for Qualcomm PMIC Battery Current Limiting (BCL) hardware
>> monitor driver. The BCL peripheral is present in Qualcomm PMICs and
>> provides real-time monitoring and protection against battery
>> overcurrent and under voltage conditions.
>>
>> The driver monitors:
>> - Battery voltage with configurable low voltage thresholds
>> - Battery current with configurable high current thresholds
>> - Two limit alarm interrupts (max/min, critical)
>
> Can you describe the behavior of the alarm ?
>
> I assume the alarm is raised when a threshold is crossed from normal
> to anormal condition leading to a hwmon event.
>
> * Does the BCL trigger an interrupt when going back to the normal condition ?
NO, there is no any clear interrupt to software, It can trigger only
from normal to abnormal condition.
>
> * When is the alarm flag reset ?
The hardware implements predefined deglitch set and clear timers for
each alarm level, configured by early‑boot firmware. Alarm state
transitions occur only if the input current or voltage persists beyond
or within the specified threshold for the defined deglitch duration.
>
> * Can we have a flood of events if the current / voltage is wavering
> around the thresholds ?
Yes, it is possible. Short deglitch timings on higher-level alarms can
cause spurious interrupts. Also, corrective actions in IPs in hardware
path may cause current or voltage to vary around the threshold.
The Purpose of different BCL alarms is to provide quick entry and slow
exit for BCL. This avoids oscillation, and allows SW time to observe the
system reaction during the hardware mitigation. SW should not need to
react to each interrupt. SW takes additional steps if the system is
stressed.
When an alarm is triggered, clients are notified via a hwmon_event,
corrective actions are initiated, interrupt for that level will be
disabled, and polling is enabled (50–100 ms) until the alarm condition
clears. Upon alarm reset, clients are notified again, interrupts are
re‑enabled, and polling is stopped.
>
> Overall, the driver is too big, so hard to review. It is better to
> provide a simplified version with one version supported.
>
>> The driver integrates with the Linux hwmon subsystem and provides
>> standard hwmon attributes for monitoring battery conditions.
>>
>> Signed-off-by: Manaf Meethalavalappu Pallikunhi <manaf.pallikunhi@oss.qualcomm.com>
>> ---
>> MAINTAINERS | 9 +
>> drivers/hwmon/Kconfig | 9 +
>> drivers/hwmon/Makefile | 1 +
>> drivers/hwmon/qcom-bcl-hwmon.c | 982 +++++++++++++++++++++++++++++++++++++++++
>> drivers/hwmon/qcom-bcl-hwmon.h | 311 +++++++++++++
>> 5 files changed, 1312 insertions(+)
>
> [ ... ]
>
>> diff --git a/drivers/hwmon/qcom-bcl-hwmon.c b/drivers/hwmon/qcom-bcl-hwmon.c
>> new file mode 100644
>> index 000000000000..a7e3b865de5c
>> --- /dev/null
>> +++ b/drivers/hwmon/qcom-bcl-hwmon.c
>> @@ -0,0 +1,982 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Qualcomm pmic BCL hardware driver for battery overcurrent and
>> + * battery or system under voltage monitor
>> + *
>> + * Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>
> Old copyright format
Ack
>
>> +#include <linux/devm-helpers.h>
>> +#include <linux/err.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/mod_devicetable.h>
>> +#include <linux/mutex.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/property.h>
>> +#include <linux/regmap.h>
>> +#include <linux/workqueue.h>
>> +
>> +#include "qcom-bcl-hwmon.h"
>> +
>> +ADD_BCL_HWMON_ALARM_MAPS(in, min, lcrit);
>> +ADD_BCL_HWMON_ALARM_MAPS(curr, max, crit);
>> +
>> +/* Interrupt names for each alarm level */
>> +static const char * const bcl_int_names[ALARM_MAX] = {
>> + [LVL0] = "bcl-max-min",
>> + [LVL1] = "bcl-critical",
>> +};
>
> IIUC there are three levels of alarms but the hwmon only has max/min
> and critical. Would it make sense to do adaptative min / max ? So when
> LVL0 is reached, update min / max with LVL1 value, LVL2 is critical
> and does not change ?
>
>> +static const char * const bcl_channel_label[CHANNEL_MAX] = {
>> + "BCL Voltage",
>> + "BCL Current",
>> +};
>
> s/[CHANNEL_MAX]/[]/
Ack
>
>> +/* Common Reg Fields */
>> +static const struct reg_field common_reg_fields[COMMON_FIELD_MAX] = {
>> + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7),
>> + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7),
>> + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7),
>> + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0),
>> + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1),
>> +};
>> +
>> +/* BCL Version/Modes specific fields */
>> +static const struct reg_field bcl_v1_reg_fields[] = {
>> + [F_IN_MON_EN] = REG_FIELD(MODE_CTL1, 0, 2),
>> + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7),
>> + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5),
>> + [F_IN_INPUT_EN] = REG_FIELD(VADC_CONV_REQ, 0, 0),
>> + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7),
>> + [F_CURR_MON_EN] = REG_FIELD(IADC_CONV_REQ, 0, 0),
>> + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7),
>> + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 7),
>> + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7),
>> +};
>> +
>> +static const struct reg_field bcl_v2_reg_fields[] = {
>> + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 1),
>> + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7),
>> + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5),
>> + [F_IN_INPUT_EN] = REG_FIELD(VADC_CONV_REQ, 0, 0),
>> + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7),
>> + [F_CURR_MON_EN] = REG_FIELD(IADC_CONV_REQ, 0, 0),
>> + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7),
>> + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 7),
>> + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7),
>> +};
>
> Please begin with a simplified driver supporting one version and then
> add more versions. That will help for the review process.
Basic functionality of all versions are the same, mainly the register
offsets and scaling factors are different. Hence added all of them.
Will check and update with single target BCL hardware in V2.
>
> [ ... ]
>
>> +/* V1 BMX and core */
>> +static const struct bcl_desc pm7250b_data = {
>> + .reg_fields = bcl_v1_reg_fields,
>> + .num_reg_fields = F_MAX_FIELDS,
>> + .data_field_bits_size = 8,
>> + .thresh_field_bits_size = 7,
>> + .channel[IN] = {
>> + .base = 2250,
>> + .max = 3600,
>> + .step = 25,
>> + .default_scale_nu = 194637,
>> + .thresh_type = {ADC, INDEX},
>> + },
>> + .channel[CURR] = {
>> + .max = 10000,
>> + .default_scale_nu = 305180,
>> + .thresh_type = {ADC, ADC},
>> + },
>> +};
>>
>> +/* V2 BMX and core */
>
> Ditto
Ack
>
> [ ... ]
>
>> +/**
>> + * bcl_convert_raw_to_milliunit - Convert raw value to milli unit
>> + * @desc: BCL device descriptor
>> + * @raw_val: Raw ADC value from hardware
>> + * @type: type of the channel, in or curr
>> + * @field_width: bits size for data or threshold field
>> + *
>> + * Return: value in milli unit
>> + */
>> +static unsigned int bcl_convert_raw_to_milliunit(const struct bcl_desc *desc, int raw_val,
>> + enum bcl_channel_type type, u8 field_width)
>> +{
>> + u32 def_scale = desc->channel[type].default_scale_nu;
>> + u32 lsb_weight = field_width > 8 ? 1 : 1 << field_width;
>> + u32 scaling_factor = def_scale * lsb_weight;
>
> This is confusing, can you explain ?
>
> if 'field_width' == 7, then we do def_scale * 1^7 ?
>
> Why ?
This behavior exists to support multiple BCL hardware generations with
different register layouts.
In older implementations, only a single byte is provided for ADC data,
which maps to the MSB byte of a 16‑bit ADC value. The LSB byte is not
available, meaning values are effectively reported in MSB‑byte
granularity. As a result, the value must be scaled by 256 to account for
the missing LSB bits.
Newer generations provide full 16‑bit ADC support, where both MSB and
LSB bytes are available and no additional scaling is required.
For threshold registers in the v1 hardware, only the upper 7 bits of the
ADC value are mapped (field_width = 7), while the remaining 9 LSB bits
are implicitly zero. This requires adjusting the scale factor
accordingly to align software values with the actual ADC resolution.
>
>> + return div_s64((s64)raw_val * scaling_factor, 1000000);
>
> If it is milliunit why dividing by 10^6 ?
>
>> +/**
>> + * bcl_convert_milliunit_to_index - Convert milliunit to in or curr index
>> + * @desc: BCL device descriptor
>> + * @val: in or curr value in milli unit
>> + * @type: type of the channel, in or curr
>> + *
>> + * Converts a value in milli unit to an index for BCL that use indexed thresholds.
>> + *
>> + * Return: Voltage index value
>> + */
>> +static unsigned int bcl_convert_milliunit_to_index(const struct bcl_desc *desc, int val,
>> + enum bcl_channel_type type)
>> +{
>> + return div_s64((s64)val - desc->channel[type].base, desc->channel[type].step);
>> +}
>> +
>> +/**
>> + * bcl_convert_index_to_milliunit - Convert in or curr index to milli unit
>> + * @desc: BCL device descriptor
>> + * @val: index value
>> + * @type: type of the channel, in or curr
>> + *
>> + * Converts an index value to milli unit for BCL that use indexed thresholds.
>> + *
>> + * Return: Voltage value in millivolts
>> + */
>> +static unsigned int bcl_convert_index_to_milliunit(const struct bcl_desc *desc, int val,
>> + enum bcl_channel_type type)
>> +{
>> + return desc->channel[type].base + val * desc->channel[type].step;
>
> To be sure, is it (A + val) * B, or, A + (val * B) ?
Ack, it is A + (val * B)
>
>> +}
>> +
>> +static int bcl_in_thresh_write(struct bcl_device *bcl, long value, enum bcl_limit_alarm lvl)
>> +{
>> + const struct bcl_desc *desc = bcl->desc;
>> + u32 raw_val;
>> +
>> + int thresh = clamp_val(value, desc->channel[IN].base, desc->channel[IN].max);
>> +
>> + if (desc->channel[IN].thresh_type[lvl] == ADC)
>> + raw_val = bcl_convert_milliunit_to_raw(desc, thresh, IN,
>> + desc->thresh_field_bits_size);
>> + else
>> + raw_val = bcl_convert_milliunit_to_index(desc, thresh, IN);
>> +
>> + return regmap_field_write(bcl->fields[F_IN_L0_THR + lvl], raw_val);
>> +}
>> +
>> +static int bcl_curr_thresh_write(struct bcl_device *bcl, long value, enum bcl_limit_alarm lvl)
>> +{
>> + const struct bcl_desc *desc = bcl->desc;
>> + u32 raw_val;
>> +
>> + /* Clamp only to curr max */
>> + int thresh = clamp_val(value, value, desc->channel[CURR].max);
>> +
>> + if (desc->channel[CURR].thresh_type[lvl] == ADC)
>> + raw_val = bcl_convert_milliunit_to_raw(desc, thresh, CURR,
>> + desc->thresh_field_bits_size);
>> + else
>> + raw_val = bcl_convert_milliunit_to_index(desc, thresh, CURR);
>> +
>> + return regmap_field_write(bcl->fields[F_CURR_H0_THR + lvl], raw_val);
>> +}
>> +
>> +static int bcl_in_thresh_read(struct bcl_device *bcl, enum bcl_limit_alarm lvl, long *out)
>> +{
>> + int ret, thresh;
>> + u32 raw_val = 0;
>> + const struct bcl_desc *desc = bcl->desc;
>> +
>> + ret = bcl_read_field_value(bcl, F_IN_L0_THR + lvl, &raw_val);
>> + if (ret)
>> + return ret;
>> +
>> + if (desc->channel[IN].thresh_type[lvl] == ADC)
>> + thresh = bcl_convert_raw_to_milliunit(desc, raw_val, IN,
>> + desc->thresh_field_bits_size);
>> + else
>> + thresh = bcl_convert_index_to_milliunit(desc, raw_val, IN);
>> +
>> + *out = thresh;
>> +
>> + return 0;
>> +}
>> +
>> +static int bcl_curr_thresh_read(struct bcl_device *bcl, enum bcl_limit_alarm lvl, long *out)
>> +{
>> + int ret, thresh;
>> + u32 raw_val = 0;
>> + const struct bcl_desc *desc = bcl->desc;
>> +
>> + ret = bcl_read_field_value(bcl, F_CURR_H0_THR + lvl, &raw_val);
>> + if (ret)
>> + return ret;
>> +
>> + if (desc->channel[CURR].thresh_type[lvl] == ADC)
>> + thresh = bcl_convert_raw_to_milliunit(desc, raw_val, CURR,
>> + desc->thresh_field_bits_size);
>> + else
>> + thresh = bcl_convert_index_to_milliunit(desc, raw_val, CURR);
>> +
>> + *out = thresh;
>> +
>> + return 0;
>> +}
>> +
>> +static int bcl_curr_input_read(struct bcl_device *bcl, long *out)
>> +{
>> + int ret;
>> + u32 raw_val = 0;
>> + const struct bcl_desc *desc = bcl->desc;
>> +
>> + ret = bcl_read_field_value(bcl, F_CURR_INPUT, &raw_val);
>> + if (ret)
>> + return ret;
>> +
>> + /*
>> + * The sensor sometime can read a value 0 if there are
>> + * consecutive reads
>> + */
>
> In order to prevent the userspace to read in a too high rate the
> values of a hwmon, where I guess it is the reason why the value can be
> 0, the cached value is returned if two reads are under a minimal
> jiffies based interval.
>
> Something like:
>
> if (time_before(jiffies, last_updated + HZ))
> return bcl->last_curr_input;
>
> If it is correct, then that could be put at the beginning of the
> function instead of checking the zero value.
ACK, Will check and update in V2
>
>> + if (raw_val != 0)
>> + bcl->last_curr_input =
>> + bcl_convert_raw_to_milliunit(desc, raw_val, CURR,
>> + desc->data_field_bits_size);
>> +
>> + *out = bcl->last_curr_input;
>> +
>> + return 0;
>> +}
>> +
>> +static int bcl_in_input_read(struct bcl_device *bcl, long *out)
>> +{
>> + int ret;
>> + u32 raw_val = 0;
>> + const struct bcl_desc *desc = bcl->desc;
>> +
>> + ret = bcl_read_field_value(bcl, F_IN_INPUT, &raw_val);
>> + if (ret)
>> + return ret;
>> +
>> + if (raw_val < GENMASK(desc->data_field_bits_size - 1, 0))
>> + bcl->last_in_input =
>> + bcl_convert_raw_to_milliunit(desc, raw_val, IN,
>> + desc->data_field_bits_size);
>> +
>> + *out = bcl->last_in_input;
>> +
>> + return 0;
>> +}
>> +
>> +static int bcl_read_alarm_status(struct bcl_device *bcl,
>> + enum bcl_limit_alarm lvl, long *status)
>> +{
>> + int ret;
>> + u32 raw_val = 0;
>> +
>> + ret = bcl_read_field_value(bcl, F_LVL0_ALARM + lvl, &raw_val);
>> + if (ret)
>> + return ret;
>> +
>> + *status = raw_val;
>> +
>> + return 0;
>> +}
>> +
>> +static unsigned int bcl_get_version_major(const struct bcl_device *bcl)
>> +{
>> + u32 raw_val = 0;
>> +
>> + bcl_read_field_value(bcl, F_V_MAJOR, &raw_val);
>> +
>> + return raw_val;
>> +}
>> +
>> +static unsigned int bcl_get_version_minor(const struct bcl_device *bcl)
>> +{
>> + u32 raw_val = 0;
>> +
>> + bcl_read_field_value(bcl, F_V_MINOR, &raw_val);
>> +
>> + return raw_val;
>> +}
>> +
>> +static void bcl_hwmon_notify_event(struct bcl_device *bcl, enum bcl_limit_alarm alarm)
>> +{
>> + if (bcl->in_mon_enabled)
>> + hwmon_notify_event(bcl->hwmon_dev, hwmon_in,
>> + in_lvl_to_attr_map[alarm], 0);
>> + if (bcl->curr_mon_enabled)
>> + hwmon_notify_event(bcl->hwmon_dev, hwmon_curr,
>> + curr_lvl_to_attr_map[alarm], 0);
>> +}
>
> What is the rate of the events we can face if they are mitigations
> happening under the hood from the HW ?
Hardware can generate events on the order of microseconds to
milliseconds, depending on the source (ADC or comparator) for that level
alarm. However, as noted earlier, software is not expected to monitor or
handle every interrupt.
>
>> +static void bcl_alarm_enable_poll(struct work_struct *work)
>> +{
>> + struct bcl_alarm_data *alarm = container_of(work, struct bcl_alarm_data,
>> + alarm_poll_work.work);
>> + struct bcl_device *bcl = alarm->device;
>> + long status;
>> +
>> + guard(mutex)(&bcl->lock);
>> +
>> + if (bcl_read_alarm_status(bcl, alarm->type, &status))
>> + goto re_schedule;
>> +
>> + if (!status & !alarm->irq_enabled) {
>> + bcl_enable_irq(alarm);
>> + bcl_hwmon_notify_event(bcl, alarm->type);
>> + return;
>> + }
>> +
>> +re_schedule:
>> + schedule_delayed_work(&alarm->alarm_poll_work,
>> + msecs_to_jiffies(BCL_ALARM_POLLING_MS));
>> +}
>> +
>> +static irqreturn_t bcl_handle_alarm(int irq, void *data)
>> +{
>> + struct bcl_alarm_data *alarm = data;
>> + struct bcl_device *bcl = alarm->device;
>> + long status;
>> +
>> + guard(mutex)(&bcl->lock);
>> +
>> + if (bcl_read_alarm_status(bcl, alarm->type, &status) || !status)
>> + return IRQ_HANDLED;
>
> So it is possible to have an interrupt but not an alarm (!status) ?
There can be a case where , by the time software handle interrupts
status can be reset due to hardware mitigation.
>
>> + if (!bcl->hwmon_dev)
>> + return IRQ_HANDLED;
>
> This should not be needed, revisit the init routine
Ack
>
>> +
>> + bcl_hwmon_notify_event(bcl, alarm->type);
>> +
>> + bcl_disable_irq(alarm);
>> + schedule_delayed_work(&alarm->alarm_poll_work,
>> + msecs_to_jiffies(BCL_ALARM_POLLING_MS));
>
> Why ?
I hope I explained this in above comment.
>
>> + dev_dbg(bcl->dev, "Irq:%d triggered for bcl type:%d\n",
>> + irq, alarm->type);
>
> Please remove, that is debug code
Ack
>
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static umode_t bcl_hwmon_is_visible(const void *data,
>> + enum hwmon_sensor_types type,
>> + u32 attr, int channel)
>> +{
>> + const struct bcl_device *bcl = data;
>> +
>> + switch (type) {
>> + case hwmon_in:
>> + if (!bcl->in_mon_enabled)
>> + return 0;
>> + switch (attr) {
>> + case hwmon_in_input:
>> + return bcl->in_input_enabled ? 0444 : 0;
>> + case hwmon_in_label:
>> + case hwmon_in_min_alarm:
>> + case hwmon_in_lcrit_alarm:
>> + return 0444;
>> + case hwmon_in_min:
>> + case hwmon_in_lcrit:
>> + return 0644;
>> + default:
>> + return 0;
>> + }
>> + case hwmon_curr:
>> + if (!bcl->curr_mon_enabled)
>> + return 0;
>> + switch (attr) {
>> + case hwmon_curr_input:
>> + case hwmon_curr_label:
>> + case hwmon_curr_max_alarm:
>> + case hwmon_curr_crit_alarm:
>> + return 0444;
>> + case hwmon_curr_max:
>> + case hwmon_curr_crit:
>> + return 0644;
>> + default:
>> + return 0;
>> + }
>> + default:
>> + return 0;
>> + }
>> +}
>> +
>> +static int bcl_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
>> + u32 attr, int channel, long val)
>
> What is the benefit of the userspace to set the thresholds ? Should
> they be a platform property ?
Both use cases are required
1. Platform‑specific properties are needed to override default settings
when a platform requires different configurations due to factors such as
battery OCP Spec, attached peripherals, or differences in BCL mitigation
behavior.
2. For certain batteries, voltage droop behavior varies with ambient
conditions—particularly at low temperatures—and at low state of charge.
In these scenarios, it is recommended to trigger BCL mitigation more
aggressively than under normal conditions. User space can proactively
detect these conditions and adjust the thresholds dynamically at runtime.
>
> Should the thresholds be check to be in ascending order and separated
> with 100mV (for IN) ?
The sysfs nodes are different for each level, we don't know what order
client will request, right ? Each level settings are independent in
hardware. for IN, we can have 25mV granularity for thresholds as per
HW spec.
>
>> +{
>> + struct bcl_device *bcl = dev_get_drvdata(dev);
>> + int ret = -EOPNOTSUPP;
>> +
>> + guard(mutex)(&bcl->lock);
>> +
>> + switch (type) {
>> + case hwmon_in:
>> + switch (attr) {
>> + case hwmon_in_min:
>> + case hwmon_in_lcrit:
>> + ret = bcl_in_thresh_write(bcl, val, in_attr_to_lvl_map[attr]);
>> + break;
>> + default:
>> + ret = -EOPNOTSUPP;
>> + }
>> + break;
>> + case hwmon_curr:
>> + switch (attr) {
>> + case hwmon_curr_max:
>> + case hwmon_curr_crit:
>> + ret = bcl_curr_thresh_write(bcl, val, curr_attr_to_lvl_map[attr]);
>> + break;
>> + default:
>> + ret = -EOPNOTSUPP;
>> + }
>> + break;
>> + default:
>> + break;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static int bcl_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
>> + u32 attr, int channel, long *value)
>> +{
>> + struct bcl_device *bcl = dev_get_drvdata(dev);
>> + int ret;
>> +
>> + guard(mutex)(&bcl->lock);
>> +
>> + switch (type) {
>> + case hwmon_in:
>> + switch (attr) {
>> + case hwmon_in_input:
>> + ret = bcl_in_input_read(bcl, value);
>> + break;
>> + case hwmon_in_min:
>> + case hwmon_in_lcrit:
>> + ret = bcl_in_thresh_read(bcl, in_attr_to_lvl_map[attr], value);
>> + break;
>> + case hwmon_in_min_alarm:
>> + case hwmon_in_lcrit_alarm:
>> + ret = bcl_read_alarm_status(bcl, in_attr_to_lvl_map[attr], value);
>> + break;
>> + default:
>> + ret = -EOPNOTSUPP;
>> + }
>> + break;
>
> Please split this function into:
>
> case hwmon_in:
> return bcl_in_read();
> case hwmon_curr:
> return bcl_curr_read();
> default:
> return -EOPNOTSUPP;
>
Ack
>> + case hwmon_curr:
>> + switch (attr) {
>> + case hwmon_curr_input:
>> + ret = bcl_curr_input_read(bcl, value);
>> + break;
>> + case hwmon_curr_max:
>> + case hwmon_curr_crit:
>> + ret = bcl_curr_thresh_read(bcl, curr_attr_to_lvl_map[attr], value);
>> + break;
>> + case hwmon_curr_max_alarm:
>> + case hwmon_curr_crit_alarm:
>> + ret = bcl_read_alarm_status(bcl, curr_attr_to_lvl_map[attr], value);
>> + break;
>> + default:
>> + ret = -EOPNOTSUPP;
>> + }
>> + break;
>> + default:
>> + ret = -EOPNOTSUPP;
>> + break;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static int bcl_hwmon_read_string(struct device *dev,
>> + enum hwmon_sensor_types type,
>> + u32 attr, int channel, const char **str)
>> +{
>> + switch (type) {
>> + case hwmon_in:
>> + if (attr != hwmon_in_label)
>> + break;
>> + *str = bcl_channel_label[IN];
>
> Why not use 'channel' passed as parameter ?
Ack, Since we are already enabling IN macros, explictly used it. I can
change it into channel id.
>
>> + return 0;
>> + case hwmon_curr:
>> + if (attr != hwmon_curr_label)
>> + break;
>> + *str = bcl_channel_label[CURR];
>> + return 0;
>> + default:
>> + break;
>> + }
>> +
>> + return -EOPNOTSUPP;
>
> Given there are few channels I suggest to simplify to:
>
> if (type == hwmon_in && attr == hwmon_in_label) {
> *str = "BCL Voltage";
> } else if (type == hwmon_curr && attr == hwmon_curr_label) {
> *str = "BCL Current";
> } else {
> *str = NULL;
> }
>
> return *str ? 0 : -EOPNOTSUPP;
>
> Up to you.
Ack
>
>> +}
>> +
>> +static const struct hwmon_ops bcl_hwmon_ops = {
>> + .is_visible = bcl_hwmon_is_visible,
>> + .read = bcl_hwmon_read,
>> + .read_string = bcl_hwmon_read_string,
>> + .write = bcl_hwmon_write,
>> +};
>> +
>> +static const struct hwmon_channel_info *bcl_hwmon_info[] = {
>> + HWMON_CHANNEL_INFO(in,
>> + HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_MIN |
>> + HWMON_I_LCRIT | HWMON_I_MIN_ALARM |
>> + HWMON_I_LCRIT_ALARM),
>> + HWMON_CHANNEL_INFO(curr,
>> + HWMON_C_INPUT | HWMON_C_LABEL | HWMON_C_MAX |
>> + HWMON_C_CRIT | HWMON_C_MAX_ALARM |
>> + HWMON_C_CRIT_ALARM),
>> + NULL,
>> +};
>> +
>> +static const struct hwmon_chip_info bcl_hwmon_chip_info = {
>> + .ops = &bcl_hwmon_ops,
>> + .info = bcl_hwmon_info,
>> +};
>> +
>> +static int bcl_curr_thresh_update(struct bcl_device *bcl)
>> +{
>> + int ret, i;
>> +
>> + if (!bcl->curr_thresholds[0])
>> + return 0;
>> +
>> + for (i = 0; i < ALARM_MAX; i++) {
>> + ret = bcl_curr_thresh_write(bcl, bcl->curr_thresholds[i], i);
>> + if (ret < 0)
>> + return ret;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static void bcl_hw_channel_mon_init(struct bcl_device *bcl)
>> +{
>> + bcl->in_mon_enabled = bcl_in_monitor_enabled(bcl);
>> + bcl->in_input_enabled = bcl_in_input_enabled(bcl);
>> + bcl->curr_mon_enabled = bcl_curr_monitor_enabled(bcl);
>
> Can you describe why we can have this optionnal ?
There are different type of BCL where same hw is used with reduced
fuctionality due to limitation of source/input of alarm in underlying pmic.
>
> Why not set bcl_hwmon_info[] regarding what is enabled instead of
> having boolean checks all over the place ?
I could see multiple reference where all dynamic controls of
channel/channel attributes are controlled via is_visible callback. I
followed the same approach here.
>
>> +}
>> +
>> +static int bcl_alarm_irq_init(struct platform_device *pdev,
>> + struct bcl_device *bcl)
>> +{
>> + int ret = 0, irq_num = 0, i = 0;
>> + struct bcl_alarm_data *alarm;
>> +
>> + for (i = LVL0; i < ALARM_MAX; i++) {
>> + alarm = &bcl->bcl_alarms[i];
>> + alarm->type = i;
>> + alarm->device = bcl;
>> +
>> + ret = devm_delayed_work_autocancel(bcl->dev, &alarm->alarm_poll_work,
>> + bcl_alarm_enable_poll);
>> + if (ret)
>> + return ret;
>
> Why ?
I hope I explained it in above comment.
>
>> + irq_num = platform_get_irq_byname(pdev, bcl_int_names[i]);
>> + if (irq_num <= 0)
>> + continue;
>> +
>> + ret = devm_request_threaded_irq(&pdev->dev, irq_num, NULL,
>> + bcl_handle_alarm, IRQF_ONESHOT,
>> + bcl_int_names[i], alarm);
>> + if (ret) {
>> + dev_err(&pdev->dev, "Error requesting irq(%s).err:%d\n",
>> + bcl_int_names[i], ret);
>> + return ret;
>> + }
>> + enable_irq_wake(alarm->irq);
>> + alarm->irq_enabled = true;
>> + alarm->irq = irq_num;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int bcl_regmap_field_init(struct device *dev, struct bcl_device *bcl,
>> + const struct bcl_desc *data)
>> +{
>> + int i;
>> + struct reg_field fields[F_MAX_FIELDS];
>> +
>> + BUILD_BUG_ON(ARRAY_SIZE(common_reg_fields) != COMMON_FIELD_MAX);
>
> No, this error implies the way the fields are declared is fragile, may
> be revisit the declaration.
Ack
>
>> +
>> + for (i = 0; i < data->num_reg_fields; i++) {
>> + if (i < COMMON_FIELD_MAX)
>> + fields[i] = common_reg_fields[i];
>> + else
>> + fields[i] = data->reg_fields[i];
>> +
>> + /* Need to adjust BCL base from regmap dynamically */
>> + fields[i].reg += bcl->base;
>> + }
>> +
>> + return devm_regmap_field_bulk_alloc(dev, bcl->regmap, bcl->fields,
>> + fields, data->num_reg_fields);
>> +}
>> +
>> +static int bcl_get_device_property_data(struct platform_device *pdev,
>> + struct bcl_device *bcl)
>
> *dev could be passed as parameter instead of *pdev
Ack
>
>> +{
>> + struct device *dev = &pdev->dev;
>> + int ret;
>> + u32 reg;
>> +
>> + ret = device_property_read_u32(dev, "reg", ®);
>> + if (ret < 0)
>> + return ret;
>> +
>> + bcl->base = reg;
>> +
>> + device_property_read_u32_array(dev, "overcurrent-thresholds-milliamp",
>> + bcl->curr_thresholds, 2);
>
> Why don't you want this as a required property ?
Default settings will be enabled in early boot firmware. If need to
change different setting, then only need to enable this property due to
different platform factors mentioned above.
>
>> + return 0;
>> +}
>> +
>> +static int bcl_probe(struct platform_device *pdev)
>> +{
>> + struct bcl_device *bcl;
>> + int ret;
>> +
>> + bcl = devm_kzalloc(&pdev->dev, sizeof(*bcl), GFP_KERNEL);
>> + if (!bcl)
>> + return -ENOMEM;
>> +
>> + bcl->dev = &pdev->dev;
>> + bcl->desc = device_get_match_data(&pdev->dev);
>> + if (!bcl->desc)
>> + return -EINVAL;
>> +
>> + ret = devm_mutex_init(bcl->dev, &bcl->lock);
>> + if (ret)
>> + return ret;
>> +
>> + bcl->regmap = dev_get_regmap(pdev->dev.parent, NULL);
>> + if (!bcl->regmap) {
>> + dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
>> + return -EINVAL;
>> + }
>> +
>> + ret = bcl_get_device_property_data(pdev, bcl);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = bcl_regmap_field_init(bcl->dev, bcl, bcl->desc);
>> + if (ret < 0) {
>> + dev_err(&pdev->dev, "Unable to allocate regmap fields, err:%d\n", ret);
>> + return ret;
>> + }
>> +
>> + if (!bcl_hw_is_enabled(bcl))
>> + return -ENODEV;
>> +
>> + ret = bcl_curr_thresh_update(bcl);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = bcl_alarm_irq_init(pdev, bcl);
>> + if (ret < 0)
>> + return ret;
>> +
>> + bcl_hw_channel_mon_init(bcl);
>> +
>> + dev_set_drvdata(&pdev->dev, bcl);
>> +
>> + bcl->hwmon_name = devm_hwmon_sanitize_name(&pdev->dev,
>> + dev_name(bcl->dev));
>> + if (IS_ERR(bcl->hwmon_name)) {
>> + dev_err(&pdev->dev, "Failed to sanitize hwmon name\n");
>> + return PTR_ERR(bcl->hwmon_name);
>> + }
>> +
>> + bcl->hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
>> + bcl->hwmon_name,
>> + bcl,
>> + &bcl_hwmon_chip_info,
>> + NULL);
>> + if (IS_ERR(bcl->hwmon_dev)) {
>> + dev_err(&pdev->dev, "Failed to register hwmon device: %ld\n",
>> + PTR_ERR(bcl->hwmon_dev));
>> + return PTR_ERR(bcl->hwmon_dev);
>> + }
>> +
>> + dev_dbg(&pdev->dev, "BCL hwmon device with version: %u.%u registered\n",
>> + bcl_get_version_major(bcl), bcl_get_version_minor(bcl));
>> +
>> + return 0;
>> +}
>> +
>> +static const struct of_device_id bcl_match[] = {
>> + {
>> + .compatible = "qcom,bcl-v1",
>> + .data = &pm7250b_data,
>> + }, {
>> + .compatible = "qcom,bcl-v2",
>> + .data = &pm8350_data,
>> + }, {
>> + .compatible = "qcom,bcl-v3-bmx",
>> + .data = &pm8550b_data,
>> + }, {
>> + .compatible = "qcom,bcl-v3-wb",
>> + .data = &pmw5100_data,
>> + }, {
>> + .compatible = "qcom,bcl-v3-core",
>> + .data = &pm8550_data,
>> + }, {
>> + .compatible = "qcom,bcl-v4-bmx",
>> + .data = &pmih010_data,
>> + }, {
>> + .compatible = "qcom,bcl-v4-wb",
>> + .data = &pmw6100_data,
>> + }, {
>> + .compatible = "qcom,bcl-v4-core",
>> + .data = &pmh010_data,
>> + }, {
>> + .compatible = "qcom,bcl-v4-pmv010",
>> + .data = &pmv010_data,
>> + },
>> + { }
>> +};
>> +MODULE_DEVICE_TABLE(of, bcl_match);
>> +
>> +static struct platform_driver bcl_driver = {
>> + .probe = bcl_probe,
>> + .driver = {
>> + .name = BCL_DRIVER_NAME,
>> + .of_match_table = bcl_match,
>> + },
>> +};
>> +
>> +MODULE_AUTHOR("Manaf Meethalavalappu Pallikunhi <manaf.pallikunhi@oss.qualcomm.com>");
>> +MODULE_DESCRIPTION("QCOM BCL HWMON driver");
>> +module_platform_driver(bcl_driver);
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/hwmon/qcom-bcl-hwmon.h b/drivers/hwmon/qcom-bcl-hwmon.h
>> new file mode 100644
>> index 000000000000..28a7154d9486
>> --- /dev/null
>> +++ b/drivers/hwmon/qcom-bcl-hwmon.h
>
> As there is nothing shared with other files, no header is needed.
Ack
>
>> @@ -0,0 +1,311 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#ifndef __QCOM_BCL_HWMON_H__
>> +#define __QCOM_BCL_HWMON_H__
>> +
>> +#define BCL_DRIVER_NAME "qcom-bcl-hwmon"
>> +
>> +/* BCL common regmap offset */
>> +#define REVISION1 0x0
>> +#define REVISION2 0x1
>> +#define STATUS 0x8
>> +#define INT_RT_STS 0x10
>> +#define EN_CTL1 0x46
>> +
>> +/* BCL GEN1 regmap offsets */
>> +#define MODE_CTL1 0x41
>> +#define VADC_L0_THR 0x48
>> +#define VCMP_L1_THR 0x49
>> +#define IADC_H0_THR 0x4b
>> +#define IADC_H1_THR 0x4c
>> +#define VADC_CONV_REQ 0x72
>> +#define IADC_CONV_REQ 0x82
>> +#define VADC_DATA1 0x76
>> +#define IADC_DATA1 0x86
>> +
>> +/* BCL GEN3 regmap offsets */
>> +#define VCMP_CTL 0x44
>> +#define VCMP_L0_THR 0x47
>> +#define PARAM_1 0x0e
>> +#define IADC_H1_THR_GEN3 0x4d
>> +
>> +#define BCL_IN_INC_MV 25
>> +#define BCL_ALARM_POLLING_MS 50
>> +
>> +/**
>> + * enum bcl_limit_alarm - BCL alarm threshold levels
>> + * @LVL0: Level 0 alarm threshold (mapped to in_min_alarm or curr_max_alarm)
>> + * @LVL1: Level 1 alarm threshold (mapped to in_lcrit_alarm or curr_crit_alarm)
>> + * @ALARM_MAX: sentinel value
>> + *
>> + * Defines the three threshold levels for BCL monitoring. Each level corresponds
>> + * to different severity of in or curr conditions.
>> + */
>> +enum bcl_limit_alarm {
>> + LVL0,
>> + LVL1,
>> + ALARM_MAX,
>> +};
>
> These are too generic names and they can collide with other
> subsystems. BCL_LIMIT_ALRM_LVL0/1, BLC_LIMIT_ALRM_MAX should be fine.
Ack
>
>> +/**
>> + * enum bcl_channel_type - BCL supported sensor channel type
>> + * @IN: in (voltage) channel
>> + * @CURR: curr (current) channel
>> + * @CHANNEL_MAX: sentinel value
>> + *
>> + * Defines the supported channel types for bcl.
>> + */
>> +enum bcl_channel_type {
>
> s/bcl_channel_type/bcl_channel/ ?
Ack
>
>> + IN,
>> + CURR,
>> +
>> + CHANNEL_MAX,
>> +};
>
> Same comment: BCL_CHANNEL_IN, BCL_CHANNEL_CURR, BCL_CHANNEL_MAX
Ack
>
>> +/**
>> + * enum bcl_thresh_type - voltage or current threshold representation type
>> + * @ADC: Raw ADC value representation
>> + * @INDEX: Index-based voltage or current representation
>> + *
>> + * Specifies how voltage or current thresholds are stored and interpreted in
>> + * registers. Some PMICs use raw ADC values while others use indexed values.
>> + */
>> +enum bcl_thresh_type {
>> + ADC,
>> + INDEX,
>> +};
>
> Ditto
Ack
>
>> +/**
>> + * enum bcl_fields - BCL register field identifiers
>> + * @F_V_MAJOR: Major revision info field
>> + * @F_V_MINOR: Minor revision info field
>> + * @F_CTL_EN: Monitor enable control field
>> + * @F_LVL0_ALARM: Level 0 alarm status field
>> + * @F_LVL1_ALARM: Level 1 alarm status field
>> + * @COMMON_FIELD_MAX: sentinel value for common fields
>> + * @F_IN_MON_EN: voltage monitor enable control field
>> + * @F_IN_L0_THR: voltage level 0 threshold field
>> + * @F_IN_L1_THR: voltage level 1 threshold field
>> + * @F_IN_INPUT_EN: voltage input enable control field
>> + * @F_IN_INPUT: voltage input data field
>> + * @F_CURR_MON_EN: current monitor enable control field
>> + * @F_CURR_H0_THR: current level 0 threshold field
>> + * @F_CURR_H1_THR: current level 1 threshold field
>> + * @F_CURR_INPUT: current input data field
>> + * @F_MAX_FIELDS: sentinel value
>> + *
>> + * Enumeration of all register fields used by the BCL driver for accessing
>> + * registers through regmap fields.
>> + */
>> +enum bcl_fields {
>> + F_V_MAJOR,
>> + F_V_MINOR,
>> +
>> + F_CTL_EN,
>> +
>> + /* common alarm for in and curr channel */
>> + F_LVL0_ALARM,
>> + F_LVL1_ALARM,
>> +
>> + COMMON_FIELD_MAX,
>> +
>> + F_IN_MON_EN = COMMON_FIELD_MAX,
>> + F_IN_L0_THR,
>> + F_IN_L1_THR,
>> +
>> + F_IN_INPUT_EN,
>> + F_IN_INPUT,
>> +
>> + F_CURR_MON_EN,
>> + F_CURR_H0_THR,
>> + F_CURR_H1_THR,
>> +
>> + F_CURR_INPUT,
>> +
>> + F_MAX_FIELDS
>> +};
>
> Usually this is described with macro, not enum.
We need field index in ascending order. enum by default will do the
same, right ?
>
>> +#define ADD_BCL_HWMON_ALARM_MAPS(_type, lvl0_attr, lvl1_attr) \
>> + \
>> +static const u8 _type##_attr_to_lvl_map[] = { \
>> + [hwmon_##_type##_##lvl0_attr] = LVL0, \
>> + [hwmon_##_type##_##lvl1_attr] = LVL1, \
>> + [hwmon_##_type##_##lvl0_attr##_alarm] = LVL0, \
>> + [hwmon_##_type##_##lvl1_attr##_alarm] = LVL1, \
>> +}; \
>> + \
>> +static const u8 _type##_lvl_to_attr_map[ALARM_MAX] = { \
>> + [LVL0] = hwmon_##_type##_##lvl0_attr##_alarm, \
>> + [LVL1] = hwmon_##_type##_##lvl1_attr##_alarm, \
>> +}
>
> Please avoid these macros, they don't help to the readability.
Ack
>
>> +/**
>> + * struct bcl_channel_cfg - BCL channel related configuration
>> + * @default_scale_nu: Default scaling factor in nano unit
>> + * @base: Base threshold value in milli unit
>> + * @max: Maximum threshold value in milli unit
>> + * @step: step increment value between two indexed threshold value
>> + * @thresh_type: Array specifying threshold representation type for each alarm level
>> + *
>> + * Contains hardware-specific configuration and scaling parameters for different
>> + * channel(voltage and current)..
>> + */
>> +
>> +struct bcl_channel_cfg {
>> + u32 default_scale_nu;
>> + u32 base;
>> + u32 max;
>> + u32 step;
>> + u8 thresh_type[ALARM_MAX];
>> +};
>> +
>> +/**
>> + * struct bcl_desc - BCL device descriptor
>> + * @reg_fields: Array of register field definitions for this device variant
>> + * @channel: Each channel specific(voltage or current) configuration
>> + * @num_reg_fields: Number of register field definitions for this device variant
>> + * @data_field_bits_size: data read register bit size
>> + * @thresh_field_bits_size: lsb bit size those are not included in threshold register
>> + *
>> + * Contains hardware-specific configuration and scaling parameters for different
>> + * BCL variants. Each PMIC model may have different register layouts and
>> + * conversion factors.
>> + */
>> +
>> +struct bcl_desc {
>> + const struct reg_field *reg_fields;
>> + struct bcl_channel_cfg channel[CHANNEL_MAX];
>> + u8 num_reg_fields;
>> + u8 data_field_bits_size;
>> + u8 thresh_field_bits_size;
>> +};
>> +
>> +struct bcl_device;
>
> No forward declaration, reorg the structure definitions below
Ack
>
>> +/**
>> + * struct bcl_alarm_data - BCL alarm interrupt data
>> + * @irq: IRQ number assigned to this alarm
>> + * @irq_enabled: Flag indicating if IRQ is enabled
>> + * @type: Alarm level type (LVL0, or LVL1)
>> + * @device: Pointer to parent BCL device structure
>> + * @alarm_poll_work: delayed_work to poll alarm status
>
> Why do you want to poll the alarm status if there is an interrupt ?
Please see above response for the same.
>
>> + *
>> + * Stores interrupt-related information for each alarm threshold level.
>> + * Used by the IRQ handler to identify which alarm triggered.
>> + */
>> +struct bcl_alarm_data {
>> + int irq;
>> + bool irq_enabled;
>> + enum bcl_limit_alarm type;
>> + struct bcl_device *device;
>> + struct delayed_work alarm_poll_work;
>> +};
>> +
>> +/**
>> + * struct bcl_device - Main BCL device structure
>> + * @dev: Pointer to device structure
>> + * @regmap: Regmap for accessing PMIC registers
>> + * @fields: Array of regmap fields for register access
>> + * @bcl_alarms: Array of alarm data structures for each threshold level
>> + * @lock: Mutex for protecting concurrent hardware access
>> + * @in_mon_enabled: Flag indicating if voltage monitoring is enabled
>> + * @curr_mon_enabled: Flag indicating if current monitoring is enabled
>> + * @curr_thresholds: Current threshold values in milliamps from dt-binding(LVL0 and LVL1)
>> + * @base: the BCL regbase offset from regmap
>> + * @in_input_enabled: Flag indicating if voltage input reading is enabled
>> + * @last_in_input: Last valid voltage input reading in millivolts
>> + * @last_curr_input: Last valid current input reading in milliamps
>> + * @desc: Pointer to device descriptor with hardware-specific parameters
>> + * @hwmon_dev: Pointer to registered hwmon device
>> + * @hwmon_name: Sanitized name for hwmon device
>> + *
>> + * Main driver structure containing all state and configuration for a BCL
>> + * monitoring instance. Manages voltage and current monitoring, thresholds,
>> + * and alarm handling.
>> + */
>> +struct bcl_device {
>> + struct device *dev;
>
> This field is unnecessary if the debug message is removed from the
> interrupt handler.
Ack
>
>> + struct regmap *regmap;
>> + u16 base;
>> + struct regmap_field *fields[F_MAX_FIELDS];
>> + struct bcl_alarm_data bcl_alarms[ALARM_MAX];
>> + struct mutex lock;
>
> What is this lock for ?
To synchronize userspace request and irq handler handling.
I also need to add per alarm lock to avoid some race conditon based on
another comment.
Thanks,
Manaf
>
>> + u32 curr_thresholds[ALARM_MAX];
>> + u32 last_in_input;
>> + u32 last_curr_input;
>> + bool in_mon_enabled;
>> + bool curr_mon_enabled;
>> + bool in_input_enabled;
>> + const struct bcl_desc *desc;
>> + struct device *hwmon_dev;
>> + char *hwmon_name;
>> +};
>> +
>> +/**
>> + * bcl_read_field_value - Read alarm status for a given level
>> + * @bcl: BCL device structure
>> + * @id: Index in bcl->fields[]
>> + * @val: Pointer to store val
>> + *
>> + * Return: 0 on success or regmap error code
>> + */
>> +static inline int bcl_read_field_value(const struct bcl_device *bcl, enum bcl_fields id, u32 *val)
>> +{
>> + return regmap_field_read(bcl->fields[id], val);
>> +}
>> +
>> +/**
>> + * bcl_field_enabled - Generic helper to check if a regmap field is enabled
>> + * @bcl: BCL device structure
>> + * @field: Index in bcl->fields[]
>> + *
>> + * Return: true if field is non-zero, false otherwise
>> + */
>> +static inline bool bcl_field_enabled(const struct bcl_device *bcl, enum bcl_fields id)
>> +{
>> + int ret;
>> + u32 val = 0;
>> +
>> + ret = regmap_field_read(bcl->fields[id], &val);
>> + if (ret)
>> + return false;
>> +
>> + return !!val;
>> +}
>> +
>> +#define bcl_in_input_enabled(bcl) bcl_field_enabled(bcl, F_IN_INPUT_EN)
>> +#define bcl_curr_monitor_enabled(bcl) bcl_field_enabled(bcl, F_CURR_MON_EN)
>> +#define bcl_in_monitor_enabled(bcl) bcl_field_enabled(bcl, F_IN_MON_EN)
>> +#define bcl_hw_is_enabled(bcl) bcl_field_enabled(bcl, F_CTL_EN)
>> +
>> +/**
>> + * bcl_enable_irq - Generic helper to enable alarm irq
>> + * @alarm: BCL level alarm data
>> + */
>> +static inline void bcl_enable_irq(struct bcl_alarm_data *alarm)
>> +{
>> + if (alarm->irq_enabled)
>> + return;
>> + alarm->irq_enabled = true;
>> + enable_irq(alarm->irq);
>> + enable_irq_wake(alarm->irq);
>> +}
>> +
>> +/**
>> + * bcl_disable_irq - Generic helper to disable alarm irq
>> + * @alarm: BCL level alarm data
>> + */
>> +static inline void bcl_disable_irq(struct bcl_alarm_data *alarm)
>> +{
>> + if (!alarm->irq_enabled)
>> + return;
>> + alarm->irq_enabled = false;
>> + disable_irq_nosync(alarm->irq);
>> + disable_irq_wake(alarm->irq);
>> +}
>> +#endif /* __QCOM_BCL_HWMON_H__ */
>>
>> --
>> 2.43.0
>>
>
^ permalink raw reply
* Re: [PATCH 00/40] arm64: dts: rockchip: Wire up frl-enable-gpios for RK3576/RK3588 boards
From: Cristian Ciocaltea @ 2026-04-17 17:55 UTC (permalink / raw)
To: Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: kernel, devicetree, linux-arm-kernel, linux-rockchip,
linux-kernel
In-Reply-To: <2297365.1BCLMh4Saa@phil>
Hi Heiko,
On 4/17/26 2:34 PM, Heiko Stuebner wrote:
> Hi Cristan,
>
> Am Freitag, 17. April 2026, 11:24:34 Mitteleuropäische Sommerzeit schrieb Cristian Ciocaltea:
>
> [...]
>
>> Cristian Ciocaltea (40):
>> arm64: dts: rockchip: Add frl-enable-gpios to rk3576-100ask-dshanpi-a1
>> arm64: dts: rockchip: Add frl-enable-gpios to rk3576-armsom-sige5
>> arm64: dts: rockchip: Add frl-enable-gpios to rk3576-evb1-v10
>> arm64: dts: rockchip: Add frl-enable-gpios to rk3576-evb2-v10
>> arm64: dts: rockchip: Add frl-enable-gpios to rk3576-luckfox-core3576
>> arm64: dts: rockchip: Add frl-enable-gpios to rk3576-nanopi-m5
>> arm64: dts: rockchip: Add frl-enable-gpios to rk3576-nanopi-r76s
>> arm64: dts: rockchip: Add frl-enable-gpios to rk3576-roc-pc
>> arm64: dts: rockchip: Add frl-enable-gpios to rk3576-rock-4d
>
> I do think one patch per SoC (rk3576, rk3588, rk3588s) would make more
> sense, because these patches really are mostly identical :-)
Yeah, apologies for the large number of patches, I went this way to allow
per-board reviews. As previously noted, I tried to identify the GPIO pins from
multiple sources, so I'm not entirely sure about the accuracy in every case.
Would it be preferable to squash the patches per SoC and board vendor, instead?
Thanks,
Cristian
^ permalink raw reply
* [PATCH 2/3] dt-bindings: display: bridge: Document Renesas RZ/G3L LVDS encoder
From: Biju @ 2026-04-17 17:52 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Geert Uytterhoeven, Magnus Damm
Cc: Biju Das, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Tommaso Merciai, dri-devel, devicetree, linux-kernel,
linux-renesas-soc, Prabhakar Mahadev Lad, Biju Das
In-Reply-To: <20260417175235.224809-1-biju.das.jz@bp.renesas.com>
From: Biju Das <biju.das.jz@bp.renesas.com>
Document the LVDS encoder IP found on the RZ/G3L SoC. It supports
single-link mode. LVDS and the DSI interface share a peripheral clock and
the MIPI_DSI_PRESET_N reset signal. However, the LVDS module cannot be
used at the same time as MIPI-DSI.
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
.../bridge/renesas,r9a08g046-lvds.yaml | 128 ++++++++++++++++++
1 file changed, 128 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/bridge/renesas,r9a08g046-lvds.yaml
diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,r9a08g046-lvds.yaml b/Documentation/devicetree/bindings/display/bridge/renesas,r9a08g046-lvds.yaml
new file mode 100644
index 000000000000..b1f6d020ae7b
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/renesas,r9a08g046-lvds.yaml
@@ -0,0 +1,128 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/renesas,r9a08g046-lvds.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G3L LVDS Encoder
+
+maintainers:
+ - Biju Das <biju.das.jz@bp.renesas.com>
+ - Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
+
+description: |
+ This binding describe the LVDS encoder embedded in the Renesas RZ/G3L
+ SoC. The encoder can operate in LVDS Single-link mode with 4 lanes
+ (Data) + 1 lane (Clock).
+
+properties:
+ compatible:
+ const: renesas,r9a08g046-lvds
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: Peripheral clock
+ - description: PHY clock
+ - description: Dot clock
+
+ clock-names:
+ items:
+ - const: pclk
+ - const: phyclk
+ - const: dotclk
+
+ resets:
+ items:
+ - description: LVDS_RESET_N
+ - description: MIPI_DSI_PRESET_N
+ - description: MIPI_DSI_CMN_RSTB
+ - description: MIPI_DSI_ARESET_N
+
+ reset-names:
+ items:
+ - const: lvdrst
+ - const: prst
+ - const: rst
+ - const: arst
+
+ power-domains:
+ maxItems: 1
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Input channel, directly connected to the Display Unit.
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: |
+ Output channel, directly connected to the LVDS panel or bridge.
+
+ required:
+ - port@0
+ - port@1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - power-domains
+ - ports
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/renesas,r9a08g046-cpg.h>
+
+ lvds-cmn@108a0000 {
+ compatible = "renesas,r9a08g046-lvds-cmn",
+ "simple-mfd", "syscon";
+ reg = <0x108a0000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ lvds0: lvds@10 {
+ compatible = "renesas,r9a08g046-lvds";
+ reg = <0x10 0x8>;
+ clocks = <&cpg CPG_MOD R9A08G046_MIPI_DSI_PCLK>,
+ <&cpg CPG_MOD R9A08G046_LVDS_PLLCLK>,
+ <&cpg CPG_MOD R9A08G046_LVDS_CLK_DOT0>;
+ clock-names = "pclk", "phyclk", "dotclk";
+ resets = <&cpg R9A08G046_LVDS_RESET_N>,
+ <&cpg R9A08G046_MIPI_DSI_PRESET_N>,
+ <&cpg R9A08G046_MIPI_DSI_CMN_RSTB>,
+ <&cpg R9A08G046_MIPI_DSI_ARESET_N>;
+ reset-names = "lvdrst", "prst", "rst", "arst";
+ power-domains = <&cpg>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_in: endpoint {
+ remote-endpoint = <&du_out_lvds0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
+ };
+ };
+ };
+...
--
2.43.0
^ permalink raw reply related
* [PATCH 1/3] dt-bindings: mfd: syscon: Document the LVDS_CMN syscon for the RZ/G3L
From: Biju @ 2026-04-17 17:52 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Geert Uytterhoeven, Magnus Damm
Cc: Biju Das, devicetree, linux-kernel, linux-renesas-soc,
Prabhakar Mahadev Lad, Biju Das, Tommaso Merciai
In-Reply-To: <20260417175235.224809-1-biju.das.jz@bp.renesas.com>
From: Biju Das <biju.das.jz@bp.renesas.com>
The RZ/G3{E,L} SoCs have an LVDS Common (LVDS_CMN) region which is common
to all LVDS channels. The RZ/G3L has single-link, but the RZ/G3E has both
single and dual-link.
Use the syscon interface to access these registers for scalability.
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
Documentation/devicetree/bindings/mfd/syscon.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index e22867088063..9c81010d5a74 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -221,6 +221,7 @@ properties:
- nxp,s32g3-gpr
- qcom,apq8064-mmss-sfpb
- qcom,apq8064-sps-sic
+ - renesas,r9a08g046-lvds-cmn
- rockchip,px30-qos
- rockchip,rk3036-qos
- rockchip,rk3066-qos
--
2.43.0
^ permalink raw reply related
* [PATCH 0/3] Add support for Renesas RZ/G3L LVDS encoder
From: Biju @ 2026-04-17 17:52 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven, Magnus Damm
Cc: Biju Das, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Tommaso Merciai, dri-devel, devicetree, linux-kernel,
linux-renesas-soc, Prabhakar Mahadev Lad, Biju Das
From: Biju Das <biju.das.jz@bp.renesas.com>
Add support for the RZ/G3L LVDS encoder driver. It operates in single-link
mode with 4 lanes (Data) + 1 lane (Clock) and supports pixel clock rates
from 25 to 87 MHz. The LVDS module cannot be used at the same time as
MIPI-DSI. However, LVDS and the DSI interface share a peripheral clock and
the MIPI_DSI_PRESET_N reset signal. Also, the MIPI_DSI_CMN_RSTB and
MIPI_DSI_ARESET_N reset signals must be asserted before using the LVDS
module.
Biju Das (3):
dt-bindings: mfd: syscon: Document the LVDS_CMN syscon for the RZ/G3L
dt-bindings: display: bridge: Document Renesas RZ/G3L LVDS encoder
drm: renesas: rz-du: Add support for RZ/G3L LVDS encoder
.../bridge/renesas,r9a08g046-lvds.yaml | 128 +++++++
.../devicetree/bindings/mfd/syscon.yaml | 1 +
drivers/gpu/drm/renesas/rz-du/Kconfig | 13 +
drivers/gpu/drm/renesas/rz-du/Makefile | 1 +
drivers/gpu/drm/renesas/rz-du/rzg3l_lvds.c | 333 ++++++++++++++++++
drivers/gpu/drm/renesas/rz-du/rzg3l_lvds.h | 22 ++
.../gpu/drm/renesas/rz-du/rzg3l_lvds_regs.h | 26 ++
7 files changed, 524 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/bridge/renesas,r9a08g046-lvds.yaml
create mode 100644 drivers/gpu/drm/renesas/rz-du/rzg3l_lvds.c
create mode 100644 drivers/gpu/drm/renesas/rz-du/rzg3l_lvds.h
create mode 100644 drivers/gpu/drm/renesas/rz-du/rzg3l_lvds_regs.h
--
2.43.0
^ permalink raw reply
* RE:[net-next v2 4/5] net: stmmac: starfive: Add JHB100 SGMII interface
From: Sai Krishna Gajula @ 2026-04-17 17:44 UTC (permalink / raw)
To: Minda Chen, Alexandre Torgue, Andrew Lunn, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin,
Emil Renner Berthing, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
linux-stm32@st-md-mailman.stormreply.com,
devicetree@vger.kernel.org
In-Reply-To: <20260417024523.107786-5-minda.chen@starfivetech.com>
> -----Original Message-----
> From: Minda Chen <minda.chen@starfivetech.com>
> Sent: Friday, April 17, 2026 8:15 AM
> To: Alexandre Torgue <alexandre.torgue@foss.st.com>; Andrew Lunn
> <andrew+netdev@lunn.ch>; David S . Miller <davem@davemloft.net>; Eric
> Dumazet <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo
> Abeni <pabeni@redhat.com>; Maxime Coquelin
> <mcoquelin.stm32@gmail.com>; Emil Renner Berthing
> <emil.renner.berthing@canonical.com>; Rob Herring <robh+dt@kernel.org>;
> Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor Dooley
> <conor@kernel.org>; netdev@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org; linux-stm32@st-md-
> mailman.stormreply.com; devicetree@vger.kernel.org; Minda Chen
> <minda.chen@starfivetech.com>
> Subject: [net-next v2 4/5] net: stmmac: starfive: Add JHB100
> SGMII interface
>
> Add JHB100 compatible and SGMII support. JHB100 soc contains 2 SGMII
> interfaces and integrated with serdes PHY. SGMII with split TX/RX MAC clock
> and need to set 2. 5M/25M/125M TX/RX clock rate in 10M/100M/1000M
> speed mode. Signed-off-by:
> Add JHB100 compatible and SGMII support. JHB100 soc contains
> 2 SGMII interfaces and integrated with serdes PHY. SGMII with split TX/RX
> MAC clock and need to set 2.5M/25M/125M TX/RX clock rate in
> 10M/100M/1000M speed mode.
>
> Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
> ---
> .../ethernet/stmicro/stmmac/dwmac-starfive.c | 54 ++++++++++++++-----
> 1 file changed, 42 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
> index 16b955a6d77b..91698c763dac 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
> @@ -26,6 +26,7 @@ struct starfive_dwmac_data { struct starfive_dwmac {
> struct device *dev;
> const struct starfive_dwmac_data *data;
> + struct clk *sgmii_rx;
> };
>
> static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat)
> @@ -68,6 +69,24 @@ static int starfive_dwmac_set_mode(struct
> plat_stmmacenet_data *plat_dat)
> return 0;
> }
>
> +static int stmmac_starfive_sgmii_set_clk_rate(void *bsp_priv, struct clk
> *clk_tx_i,
> + phy_interface_t interface, int
> speed) {
phy_interface_t interface is likely unused in stmmac_starfive_sgmii_set_clk_rate → may need __maybe_unused or (void)interface to avoid -Werror=unused-parameter on strict builds.
> + struct starfive_dwmac *dwmac = (void *)bsp_priv;
> + long rate = rgmii_clock(speed);
> + int ret;
> +
> + /* MAC clock rate the same as RGMII */
> + if (rate < 0)
> + return 0;
> +
> + ret = clk_set_rate(clk_tx_i, rate);
> + if (ret)
> + return ret;
> +
> + return clk_set_rate(dwmac->sgmii_rx, rate); }
> +
> static int starfive_dwmac_probe(struct platform_device *pdev) {
> struct plat_stmmacenet_data *plat_dat; @@ -102,24 +121,34 @@
> static int starfive_dwmac_probe(struct platform_device *pdev)
> return dev_err_probe(&pdev->dev, PTR_ERR(clk_gtx),
> "error getting gtx clock\n");
>
> - /* Generally, the rgmii_tx clock is provided by the internal clock,
> - * which needs to match the corresponding clock frequency according
> - * to different speeds. If the rgmii_tx clock is provided by the
> - * external rgmii_rxin, there is no need to configure the clock
> - * internally, because rgmii_rxin will be adaptively adjusted.
> - */
> - if (!device_property_read_bool(&pdev->dev, "starfive,tx-use-rgmii-
> clk"))
> - plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate;
> + if (plat_dat->phy_interface == PHY_INTERFACE_MODE_SGMII) {
> + dwmac->sgmii_rx = devm_clk_get_enabled(&pdev->dev,
> "sgmii_rx");
> + if (IS_ERR(dwmac->sgmii_rx))
> + return dev_err_probe(&pdev->dev,
> + PTR_ERR(dwmac->sgmii_rx),
> + "error getting sgmii rx clock\n");
> + plat_dat->set_clk_tx_rate =
> stmmac_starfive_sgmii_set_clk_rate;
> + } else {
> + /*
> + * Generally, the rgmii_tx clock is provided by the internal
> clock,
> + * which needs to match the corresponding clock frequency
> according
> + * to different speeds. If the rgmii_tx clock is provided by the
> + * external rgmii_rxin, there is no need to configure the clock
> + * internally, because rgmii_rxin will be adaptively adjusted.
> + */
> + if (!device_property_read_bool(&pdev->dev, "starfive,tx-use-
> rgmii-clk"))
> + plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate;
> +
> + err = starfive_dwmac_set_mode(plat_dat);
> + if (err)
> + return err;
> + }
>
> dwmac->dev = &pdev->dev;
> plat_dat->flags |= STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP;
> plat_dat->bsp_priv = dwmac;
> plat_dat->dma_cfg->dche = true;
>
> - err = starfive_dwmac_set_mode(plat_dat);
> - if (err)
> - return err;
> -
> return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); }
>
> @@ -130,6 +159,7 @@ static const struct starfive_dwmac_data jh7100_data =
> { static const struct of_device_id starfive_dwmac_match[] = {
> { .compatible = "starfive,jh7100-dwmac", .data = &jh7100_data },
> { .compatible = "starfive,jh7110-dwmac" },
> + { .compatible = "starfive,jhb100-dwmac" },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, starfive_dwmac_match);
> --
> 2.17.1
>
Reviewed-by: Sai Krishna <saikrishnag@marvell.com>
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: qcom: sdm630: describe adsp_mem region properly
From: Nickolay Goppen @ 2026-04-17 17:36 UTC (permalink / raw)
To: Ekansh Gupta, Konrad Dybcio, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-msm, devicetree, linux-kernel,
~postmarketos/upstreaming
In-Reply-To: <54b1be0d-1ec3-405c-b1ff-bc759b80e7bc@oss.qualcomm.com>
I'm assigning this region in the fourth patch
17 апреля 2026 г. 18:15:45 GMT+03:00, Ekansh Gupta <ekansh.gupta@oss.qualcomm.com> wrote:
>On 15-04-2026 15:22, Konrad Dybcio wrote:
>> On 4/15/26 11:40 AM, Nickolay Goppen wrote:
>>> Downstream [1] this region is marked as shared and reusable so
>>> describe it that way.
>>>
>>> [1]: https://github.com/xiaomi-sdm660/android_kernel_xiaomi_sdm660/blob/11-EAS/arch/arm/boot/dts/qcom/sdm660.dtsi#L448
>>>
>>> Signed-off-by: Nickolay Goppen <setotau@mainlining.org>
>>> ---
>>
>> +Ekansh some insight, please?
>>
>> We're giving away that memory via qcom_scm_assign_mem() anyway
>> and I would assume that making it not-"no-map" could introduce issues
>> when the OS tries to access that region
>>
>With the current version and the upcoming planned enhancements, I don't
>see any major benefits of making this as not-"no-map".
>
>With posted enhancements[1], the plan is to qcom_scm_assign_mem() the
>entire memory-region to lpass VMIDs. and un-assign it only during
>fastrpc_rpmsg_remove(). There have been implementation in downstream
>where this memory is dumped in case of SSR or audio PDR using minidump,
>so marking it `reusable` might make sense there, but that dump logic is
>not added upstream.
>
>Upon checking the DT, I see a bigger problem here, this memory-region
>looks to me unused, it's not added under fastrpc adsp node(ref. [2]).
>Please correct me if I am wrong about this point.
>
>[1]
>https://lore.kernel.org/all/20260409062617.1182-1-jianping.li@oss.qualcomm.com/
>[2]
>https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/arch/arm64/boot/dts/qcom/lemans.dtsi#n7500
>
>//Ekansh
>> Konrad
>>
>>
>>> arch/arm64/boot/dts/qcom/sdm630.dtsi | 3 ++-
>>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi
>>> index 4b47efdb57b2..13094b5e9339 100644
>>> --- a/arch/arm64/boot/dts/qcom/sdm630.dtsi
>>> +++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi
>>> @@ -495,8 +495,9 @@ venus_region: venus@9f800000 {
>>> };
>>>
>>> adsp_mem: adsp-region@f6000000 {
>>> + compatible = "shared-dma-pool";
>>> reg = <0x0 0xf6000000 0x0 0x800000>;
>>> - no-map;
>>> + reusable;
>>> };
>>>
>>> qseecom_mem: qseecom-region@f6800000 {
>>>
Best regards
Nickolay
^ permalink raw reply
* Re: [PATCH v4 7/8] ARM: dts: Declare UART1 on zx297520v3 boards
From: Stefan Dösinger @ 2026-04-17 17:24 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Krzysztof Kozlowski,
Alexandre Belloni, Linus Walleij, Drew Fustini,
Greg Kroah-Hartman, Jiri Slaby, linux-doc, linux-kernel,
linux-arm-kernel, devicetree, soc, linux-serial
In-Reply-To: <0d80dcbe-cb46-45e5-821a-de5299d6a663@app.fastmail.com>
[-- Attachment #1: Type: text/plain, Size: 2283 bytes --]
Hi Arnd,
Thanks for your comments.
> Am 17.04.2026 um 11:59 schrieb Arnd Bergmann <arnd@arndb.de>:
>
> On Thu, Apr 16, 2026, at 22:19, Stefan Dösinger wrote:
>>
>> The reason why I add the serial1=uart1 alias is to keep console=ttyAMA1
>> stable regardless of the other enabled UARTs. UART0, as the name
>> implies, has a lower MMIO address, but uart1 is the one that usually has
>> the boot output and console.
>
> I'm not sure I'm following here. You generally want to either make
> sure the alias matches whatever number is printed on the product
> if there are multiple numbered ports, or you just use 'serial0'
> as the only alias if there is only one port.
Not all boards have their uart pins labeled, but those that do have the pins that connect to the UART at 0x01408000 named UART1RX/UART1TX. Most boards have only one though. I have seen a picture of only one that has UART0 and UART1. I could not test that board myself yet.
My original reason is one of developer convenience: If I have
uart0=serial@131000{
reg = <0x00131000 0x1000>;
...
status = "disabled";
};
uart1=serial@1408000{
reg = <0x01408000 0x1000>;
...
status = "okay";
};
cmdline="... console=ttyAMA{0/1} ..."
changing uart0.status between disabled and okay (e.g. to experiment with uart0 and pinctrl) required changing the command line to match. I found that pretty annoying and the aliases seemed like the best way to avoid this.
Either way I am open to do whatever. I can keep the current naming for the reasons stated above, I can name serial@1408000 "uart0" and leave the others without an alias or I can drop the alias altogether.
> Either way, the alias should go into the board specific file, not
> the general SoC file, as a board might be using a different
> set of UARTs.
That works for me, I'll move them. The aliases will most likely be the same for all boards based on this chipset, meaning duplicate code, but matching the alias to the board labels makes sense to me.
> Since you know the addresses of the other uart instances, I would
> suggest you add all of them at the same time.
Will do.
I'll hold off for a bit before I resend the patches to see if some other comments come up.
Cheers,
Stefan
[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH] dt-bindings: cpufreq: add mt8189 cpufreq hw dt-bindings
From: Conor Dooley @ 2026-04-17 16:40 UTC (permalink / raw)
To: Binbin Shi
Cc: Rafael J . Wysocki, Viresh Kumar, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Hector Yuan, linux-pm, devicetree,
linux-kernel, linux-arm-kernel, linux-mediatek,
Project_Global_Chrome_Upstream_Group, vince-wl.liu
In-Reply-To: <20260417080648.3692438-1-binbin.shi@mediatek.com>
[-- Attachment #1: Type: text/plain, Size: 1144 bytes --]
On Fri, Apr 17, 2026 at 04:06:17PM +0800, Binbin Shi wrote:
> Add mt8189 cpufreq hw compatible in dt-bindings.
Why's this not compatible with the existing device? You've got no driver
change with this so I can't even guess as why. The incompatibility should
be explained in the commit message.
pw-bot: changes-requested
Cheers,
Conor.
>
> Signed-off-by: Binbin Shi <binbin.shi@mediatek.com>
> ---
> .../devicetree/bindings/cpufreq/cpufreq-mediatek-hw.yaml | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek-hw.yaml b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek-hw.yaml
> index d0aecde2b89b..cff52fffc6b8 100644
> --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek-hw.yaml
> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek-hw.yaml
> @@ -16,7 +16,9 @@ description:
>
> properties:
> compatible:
> - const: mediatek,cpufreq-hw
> + enum:
> + - mediatek,cpufreq-hw
> + - mediatek,mt8189-cpufreq-hw
>
> reg:
> minItems: 1
> --
> 2.45.2
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH v3 8/8] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node
From: Ronald Claveau @ 2026-04-17 16:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260417-add-mcu-fan-khadas-vim4-v3-0-a6a7f570b11b@aliel.fr>
Enable and configure i2c MCU node to get fan working on Khadas VIM4.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
.../boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
index 69d6118ba57e7..5d7f5390f3a66 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
@@ -157,6 +157,19 @@ wifi32k: wifi32k {
};
};
+&i2c_m_ao_a {
+ status = "okay";
+ pinctrl-0 = <&i2c0_ao_d_pins>;
+ pinctrl-names = "default";
+
+ khadas_mcu: system-controller@18 {
+ compatible = "khadas,vim4-mcu";
+ reg = <0x18>;
+ fan-supply = <&vcc5v>;
+ #cooling-cells = <2>;
+ };
+};
+
&pwm_ab {
status = "okay";
pinctrl-0 = <&pwm_a_pins>;
--
2.49.0
^ permalink raw reply related
* [PATCH v3 7/8] arm64: dts: amlogic: t7: Add i2c controller node
From: Ronald Claveau @ 2026-04-17 16:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260417-add-mcu-fan-khadas-vim4-v3-0-a6a7f570b11b@aliel.fr>
Add the T7 i2c controller node used by the Khadas VIM4
for MCU communication.
Use amlogic,meson-axg-i2c as fallback compatible.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index e96fe10b251a0..560c9dce35266 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -711,6 +711,16 @@ pwm_ao_cd: pwm@60000 {
status = "disabled";
};
+ i2c_m_ao_a: i2c@76000 {
+ compatible = "amlogic,t7-i2c", "amlogic,meson-axg-i2c";
+ reg = <0x0 0x76000 0x0 0x48>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_periphs CLKID_SYS_I2C_AO_A>;
+ status = "disabled";
+ };
+
sd_emmc_a: mmc@88000 {
compatible = "amlogic,t7-mmc", "amlogic,meson-axg-mmc";
reg = <0x0 0x88000 0x0 0x800>;
--
2.49.0
^ permalink raw reply related
* [PATCH v3 6/8] arm64: dts: amlogic: t7: Add i2c pinctrl node
From: Ronald Claveau @ 2026-04-17 16:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260417-add-mcu-fan-khadas-vim4-v3-0-a6a7f570b11b@aliel.fr>
Add the T7 pinctrl used by the Khadas VIM4 for MCU communication.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index 7fe72c94ed623..e96fe10b251a0 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -376,6 +376,16 @@ mux {
};
};
+ i2c0_ao_d_pins: i2c0-ao-d {
+ mux {
+ groups = "i2c0_ao_sck_d",
+ "i2c0_ao_sda_d";
+ function = "i2c0_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
pwm_a_pins: pwm-a {
mux {
groups = "pwm_a";
--
2.49.0
^ permalink raw reply related
* [PATCH v3 5/8] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
From: Ronald Claveau @ 2026-04-17 16:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260417-add-mcu-fan-khadas-vim4-v3-0-a6a7f570b11b@aliel.fr>
Replace the hardcoded MAX_LEVEL constant and fan register
with values read from platform_data (fan_reg, max_level),
as new MCUs need different values.
Optionally acquire and enable a "fan" regulator supply
at probe time and on resume,
so boards that gate fan power through a regulator are handled.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
drivers/thermal/khadas_mcu_fan.c | 49 +++++++++++++++++++++++++++++++++++-----
1 file changed, 43 insertions(+), 6 deletions(-)
diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
index d35e5313bea41..24559bf65de46 100644
--- a/drivers/thermal/khadas_mcu_fan.c
+++ b/drivers/thermal/khadas_mcu_fan.c
@@ -13,13 +13,15 @@
#include <linux/regmap.h>
#include <linux/sysfs.h>
#include <linux/thermal.h>
-
-#define MAX_LEVEL 3
+#include <linux/regulator/consumer.h>
struct khadas_mcu_fan_ctx {
struct khadas_mcu *mcu;
+ unsigned int fan_reg;
unsigned int level;
+ unsigned int max_level;
struct thermal_cooling_device *cdev;
+ struct regulator *power;
};
static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
@@ -27,8 +29,7 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
{
int ret;
- ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
- level);
+ ret = regmap_write(ctx->mcu->regmap, ctx->fan_reg, level);
if (ret)
return ret;
@@ -40,7 +41,9 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
- *state = MAX_LEVEL;
+ struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
+
+ *state = ctx->max_level;
return 0;
}
@@ -61,7 +64,7 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
{
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
- if (state > MAX_LEVEL)
+ if (state > ctx->max_level)
return -EINVAL;
if (state == ctx->level)
@@ -83,11 +86,32 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct khadas_mcu_fan_ctx *ctx;
int ret;
+ const struct khadas_mcu_fan_pdata *pdata = dev_get_platdata(&pdev->dev);
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
+
ctx->mcu = mcu;
+ ctx->fan_reg = pdata->fan_reg;
+ ctx->max_level = pdata->max_level;
+
+ ctx->power = devm_regulator_get_optional(dev->parent, "fan");
+ if (IS_ERR(ctx->power)) {
+ if (PTR_ERR(ctx->power) == -ENODEV)
+ ctx->power = NULL;
+ else
+ return PTR_ERR(ctx->power);
+ }
+
+ if (ctx->power) {
+ ret = regulator_enable(ctx->power);
+ if (ret) {
+ dev_err(dev, "Failed to enable fan power supply: %d\n", ret);
+ return ret;
+ }
+ }
+
platform_set_drvdata(pdev, ctx);
cdev = devm_thermal_of_cooling_device_register(dev->parent,
@@ -124,12 +148,25 @@ static int khadas_mcu_fan_suspend(struct device *dev)
ctx->level = level_save;
+ if (ctx->power) {
+ ret = regulator_disable(ctx->power);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
static int khadas_mcu_fan_resume(struct device *dev)
{
struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
+ int ret;
+
+ if (ctx->power) {
+ ret = regulator_enable(ctx->power);
+ if (ret)
+ return ret;
+ }
return khadas_mcu_fan_set_level(ctx, ctx->level);
}
--
2.49.0
^ permalink raw reply related
* [PATCH v3 4/8] mfd: khadas-mcu: Add support for VIM4 MCU variant
From: Ronald Claveau @ 2026-04-17 16:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260417-add-mcu-fan-khadas-vim4-v3-0-a6a7f570b11b@aliel.fr>
Refactor probe() to use per-variant khadas_mcu_data
instead of hardcoded globals.
Add dedicated regmap configuration and device data for the VIM4 MCU,
with its own volatile/writeable registers.
Add the fan control register
(0–100 levels vs 0–3 for previous supported boards).
Add a new compatible string "khadas,vim4-mcu".
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
drivers/mfd/khadas-mcu.c | 106 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 95 insertions(+), 11 deletions(-)
diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index ba981a7886921..b36b3b3ab73c0 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -75,15 +75,91 @@ static const struct regmap_config khadas_mcu_regmap_config = {
.cache_type = REGCACHE_MAPLE,
};
+static const struct khadas_mcu_fan_pdata khadas_mcu_fan_pdata = {
+ .fan_reg = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
+ .max_level = 3,
+};
+
static struct mfd_cell khadas_mcu_fan_cells[] = {
/* VIM1/2 Rev13+ and VIM3 only */
- { .name = "khadas-mcu-fan-ctrl", },
+ {
+ .name = "khadas-mcu-fan-ctrl",
+ .platform_data = &khadas_mcu_fan_pdata,
+ .pdata_size = sizeof(khadas_mcu_fan_pdata),
+ },
};
static struct mfd_cell khadas_mcu_cells[] = {
{ .name = "khadas-mcu-user-mem", },
};
+static const struct khadas_mcu_data khadas_mcu_data = {
+ .regmap_config = &khadas_mcu_regmap_config,
+ .cells = khadas_mcu_cells,
+ .ncells = ARRAY_SIZE(khadas_mcu_cells),
+ .fan_cells = khadas_mcu_fan_cells,
+ .nfan_cells = ARRAY_SIZE(khadas_mcu_fan_cells),
+};
+
+static bool khadas_mcu_vim4_reg_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case KHADAS_MCU_PWR_OFF_CMD_REG:
+ case KHADAS_MCU_VIM4_REST_CONF_REG:
+ case KHADAS_MCU_WOL_INIT_START_REG:
+ case KHADAS_MCU_VIM4_LED_ON_RAM_REG:
+ case KHADAS_MCU_VIM4_FAN_CTRL_REG:
+ case KHADAS_MCU_VIM4_WDT_EN_REG:
+ case KHADAS_MCU_VIM4_SYS_RST_REG:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool khadas_mcu_vim4_reg_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case KHADAS_MCU_VERSION_0_REG:
+ case KHADAS_MCU_VERSION_1_REG:
+ case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static const struct regmap_config khadas_mcu_vim4_regmap_config = {
+ .reg_bits = 8,
+ .reg_stride = 1,
+ .val_bits = 8,
+ .max_register = KHADAS_MCU_VIM4_SYS_RST_REG,
+ .volatile_reg = khadas_mcu_vim4_reg_volatile,
+ .writeable_reg = khadas_mcu_vim4_reg_writeable,
+ .cache_type = REGCACHE_MAPLE,
+};
+
+static const struct khadas_mcu_fan_pdata khadas_vim4_fan_pdata = {
+ .fan_reg = KHADAS_MCU_VIM4_FAN_CTRL_REG,
+ .max_level = 0x64,
+};
+
+static const struct mfd_cell khadas_mcu_vim4_cells[] = {
+ {
+ .name = "khadas-mcu-fan-ctrl",
+ .platform_data = &khadas_vim4_fan_pdata,
+ .pdata_size = sizeof(khadas_vim4_fan_pdata),
+ },
+};
+
+static const struct khadas_mcu_data khadas_vim4_mcu_data = {
+ .regmap_config = &khadas_mcu_vim4_regmap_config,
+ .cells = NULL,
+ .ncells = 0,
+ .fan_cells = khadas_mcu_vim4_cells,
+ .nfan_cells = ARRAY_SIZE(khadas_mcu_vim4_cells),
+};
+
static int khadas_mcu_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -94,28 +170,35 @@ static int khadas_mcu_probe(struct i2c_client *client)
if (!ddata)
return -ENOMEM;
+ ddata->data = i2c_get_match_data(client);
+ if (!ddata->data)
+ return -EINVAL;
+
i2c_set_clientdata(client, ddata);
ddata->dev = dev;
- ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config);
+ ddata->regmap = devm_regmap_init_i2c(client,
+ ddata->data->regmap_config);
if (IS_ERR(ddata->regmap)) {
ret = PTR_ERR(ddata->regmap);
dev_err(dev, "Failed to allocate register map: %d\n", ret);
return ret;
}
- ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
- khadas_mcu_cells,
- ARRAY_SIZE(khadas_mcu_cells),
- NULL, 0, NULL);
- if (ret)
- return ret;
+ if (ddata->data->cells && ddata->data->ncells) {
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+ ddata->data->cells,
+ ddata->data->ncells,
+ NULL, 0, NULL);
+ if (ret)
+ return ret;
+ }
if (of_property_present(dev->of_node, "#cooling-cells"))
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
- khadas_mcu_fan_cells,
- ARRAY_SIZE(khadas_mcu_fan_cells),
+ ddata->data->fan_cells,
+ ddata->data->nfan_cells,
NULL, 0, NULL);
return 0;
@@ -123,7 +206,8 @@ static int khadas_mcu_probe(struct i2c_client *client)
#ifdef CONFIG_OF
static const struct of_device_id khadas_mcu_of_match[] = {
- { .compatible = "khadas,mcu", },
+ { .compatible = "khadas,mcu", .data = &khadas_mcu_data },
+ { .compatible = "khadas,vim4-mcu", .data = &khadas_vim4_mcu_data },
{},
};
MODULE_DEVICE_TABLE(of, khadas_mcu_of_match);
--
2.49.0
^ permalink raw reply related
* [PATCH v3 3/8] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
From: Ronald Claveau @ 2026-04-17 16:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260417-add-mcu-fan-khadas-vim4-v3-0-a6a7f570b11b@aliel.fr>
Introduce a per-variant configuration structure (khadas_mcu_data)
holding the regmap config and MFD cells,
selected at probe time via the of_device_id match data.
This makes adding other variants straightforward.
Also introduce khadas_mcu_fan_pdata to pass fan register address and
maximum level to the fan sub-driver, removing the hardcoded constants.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
include/linux/mfd/khadas-mcu.h | 39 +++++++++++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h
index a99ba2ed0e4e0..75e275d3fa8d9 100644
--- a/include/linux/mfd/khadas-mcu.h
+++ b/include/linux/mfd/khadas-mcu.h
@@ -70,6 +70,13 @@
#define KHADAS_MCU_WOL_INIT_START_REG 0x87 /* WO */
#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88 /* WO */
+/* VIM4 specific registers */
+#define KHADAS_MCU_VIM4_REST_CONF_REG 0x2c /* WO - reset EEPROM */
+#define KHADAS_MCU_VIM4_LED_ON_RAM_REG 0x89 /* WO - LED volatile */
+#define KHADAS_MCU_VIM4_FAN_CTRL_REG 0x8a /* WO */
+#define KHADAS_MCU_VIM4_WDT_EN_REG 0x8b /* WO */
+#define KHADAS_MCU_VIM4_SYS_RST_REG 0x91 /* WO */
+
enum {
KHADAS_BOARD_VIM1 = 0x1,
KHADAS_BOARD_VIM2,
@@ -82,10 +89,38 @@ enum {
* struct khadas_mcu - Khadas MCU structure
* @device: device reference used for logs
* @regmap: register map
+ * @data: pointer to variant-specific config
*/
struct khadas_mcu {
- struct device *dev;
- struct regmap *regmap;
+ struct device *dev;
+ struct regmap *regmap;
+ const struct khadas_mcu_data *data;
+};
+
+/**
+ * struct khadas_mcu_data - per-variant configuration
+ * @regmap_config: regmap configuration
+ * @cells: MFD sub-devices
+ * @ncells: number of sub-devices
+ * @fan_cells: MFD fan sub-devices
+ * @nfan_cells: number of fan sub-devices
+ */
+struct khadas_mcu_data {
+ const struct regmap_config *regmap_config;
+ const struct mfd_cell *cells;
+ int ncells;
+ const struct mfd_cell *fan_cells;
+ int nfan_cells;
+};
+
+/**
+ * struct khadas_mcu_fan_pdata - fan sub-driver configuration
+ * @fan_reg: register address to write the fan level
+ * @max_level: maximum fan level
+ */
+struct khadas_mcu_fan_pdata {
+ unsigned int fan_reg;
+ unsigned int max_level;
};
#endif /* MFD_KHADAS_MCU_H */
--
2.49.0
^ permalink raw reply related
* [PATCH v3 2/8] dt-bindings: i2c: amlogic: Add compatible for T7 SOC
From: Ronald Claveau @ 2026-04-17 16:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260417-add-mcu-fan-khadas-vim4-v3-0-a6a7f570b11b@aliel.fr>
Add the T7 SOC compatible which fallback to AXG compatible.
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
.../devicetree/bindings/i2c/amlogic,meson6-i2c.yaml | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
index c4cc8af182807..7b59b60b62e5b 100644
--- a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
@@ -16,10 +16,15 @@ allOf:
properties:
compatible:
- enum:
- - amlogic,meson6-i2c # Meson6, Meson8 and compatible SoCs
- - amlogic,meson-gxbb-i2c # GXBB and compatible SoCs
- - amlogic,meson-axg-i2c # AXG and compatible SoCs
+ oneOf:
+ - items:
+ - enum:
+ - amlogic,t7-i2c
+ - const: amlogic,meson-axg-i2c
+ - enum:
+ - amlogic,meson6-i2c # Meson6, Meson8 and compatible SoCs
+ - amlogic,meson-gxbb-i2c # GXBB and compatible SoCs
+ - amlogic,meson-axg-i2c # AXG and compatible SoCs
reg:
maxItems: 1
--
2.49.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