* [PATCH v2 phy-next 2/8] soc: fsl: guts: add a global structure to hold state
From: Vladimir Oltean @ 2026-06-12 21:08 UTC (permalink / raw)
To: linux-phy
Cc: devicetree, linuxppc-dev, linux-arm-kernel, Ioana Ciornei,
Vinod Koul, Neil Armstrong, Tanjeff Moos,
Christophe Leroy (CS GROUP), Michael Walle, Shawn Guo, Frank Li,
linux-kernel
In-Reply-To: <20260612210859.266759-1-vladimir.oltean@nxp.com>
From: Ioana Ciornei <ioana.ciornei@nxp.com>
Add the fsl_soc_guts structure in order to pass information like base
addresses, endianness etc between the init time and the runtime
operations (RCW override) which will get added in future patches.
There is no point in mapping and unmapping the DCFG CCSR space every
time we need to make a read, just map it once and keep its reference in
this new global struture.
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v1->v2: none
---
drivers/soc/fsl/guts.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
index f87ee47c1503..a0a52a5603a5 100644
--- a/drivers/soc/fsl/guts.c
+++ b/drivers/soc/fsl/guts.c
@@ -106,6 +106,11 @@ static const struct fsl_soc_die_attr fsl_soc_die[] = {
{ },
};
+static struct fsl_soc_guts {
+ struct ccsr_guts __iomem *dcfg_ccsr;
+ bool little_endian;
+} soc;
+
static const struct fsl_soc_die_attr *fsl_soc_die_match(
u32 svr, const struct fsl_soc_die_attr *matches)
{
@@ -187,9 +192,7 @@ static int __init fsl_guts_init(void)
const struct fsl_soc_die_attr *soc_die;
const struct fsl_soc_data *soc_data;
const struct of_device_id *match;
- struct ccsr_guts __iomem *regs;
struct device_node *np;
- bool little_endian;
u64 soc_uid = 0;
u32 svr;
int ret;
@@ -199,18 +202,17 @@ static int __init fsl_guts_init(void)
return 0;
soc_data = match->data;
- regs = of_iomap(np, DCFG_CCSR);
- if (!regs) {
+ soc.dcfg_ccsr = of_iomap(np, DCFG_CCSR);
+ if (!soc.dcfg_ccsr) {
of_node_put(np);
return -ENOMEM;
}
- little_endian = of_property_read_bool(np, "little-endian");
- if (little_endian)
- svr = ioread32(®s->svr);
+ soc.little_endian = of_property_read_bool(np, "little-endian");
+ if (soc.little_endian)
+ svr = ioread32(&soc.dcfg_ccsr->svr);
else
- svr = ioread32be(®s->svr);
- iounmap(regs);
+ svr = ioread32be(&soc.dcfg_ccsr->svr);
of_node_put(np);
/* Register soc device */
@@ -263,6 +265,8 @@ static int __init fsl_guts_init(void)
err_nomem:
ret = -ENOMEM;
+
+ iounmap(soc.dcfg_ccsr);
err:
kfree(soc_dev_attr->family);
kfree(soc_dev_attr->soc_id);
--
2.34.1
^ permalink raw reply related
* [PATCH v2 phy-next 0/8] RCW override for 10G Lynx dynamic protocol reconfiguration
From: Vladimir Oltean @ 2026-06-12 21:08 UTC (permalink / raw)
To: linux-phy
Cc: devicetree, linuxppc-dev, linux-arm-kernel, Ioana Ciornei,
Vinod Koul, Neil Armstrong, Tanjeff Moos,
Christophe Leroy (CS GROUP), Michael Walle, Shawn Guo, Frank Li,
linux-kernel, Conor Dooley, Krzysztof Kozlowski, Rob Herring
Previous set "New Generic PHY driver for Lynx 10G SerDes":
https://lore.kernel.org/linux-phy/20260610151952.2141019-1-vladimir.oltean@nxp.com/
introduced the 10G Lynx SerDes driver with a reduced functionality set.
Namely, only minor protocol changes are supported (1GbE <-> 2.5GbE).
The major protocol changes need a procedure named RCW override,
explained in more detail in commits 6/8 and 7/8.
This series adds kernel and device tree binding support for RCW
override, completing the SerDes PHY driver functionality.
Two components are involved:
- drivers/soc/fsl/guts.c (binding is fsl,layerscape-dcfg.yaml) - Device
Configuration Unit, this is API provider for the SerDes driver to
request RCW override depending on SoC
- drivers/phy/freescale/phy-fsl-lynx-10g.c - SerDes PHY driver, this is
API consumer
The guts driver probes on DCFG blocks from multiple Freescale SoC
generations:
- MPC85xx, BSC and QorIQ (PowerPC) are all covered by the
Documentation/devicetree/bindings/soc/fsl/guts.txt schema
- Layerscape (Arm) is covered by
Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-dcfg.yaml
It is ultimately the same hardware block, just that (from what I can
tell) the Layerscape nodes are also compatible with syscon, and PowerPC
aren't.
RCW override has only been validated on select Layerscape SoCs, so
converting guts.txt to a PowerPC schema is out of scope for this
series - we don't even touch that (just in case it gets asked).
Using syscon to map the DCFG_DCSR register block in the Lynx SerDes
driver instead of creating this guts <-> lynx API was considered, but
because the RCW procedure is SoC-specific, it was ruled out for
polluting the SerDes driver. The guts driver is all about SoC awareness
anyway, and it offers some abstraction of all the gory details.
Resending because Sashiko didn't run on v1 (it runs on linux-phy/master
instead of linux-phy/next, and linux-next, used as fallback when
applying to linux-phy/master fails, wasn't regenerated to include the
Lynx 10G base patches at the time v1 was sent). There was a build
failure on most arches except arm64 anyway, so it's good to have that
fixed.
Changes since v1:
- add Conor's review tag on 6/8
- update email addresses of DT maintainers
- drop DT maintainers from explicit CC on patch 7/8
- keep devicetree@vger.kernel.org CCed on entire series
- include missing <linux/bitfield.h> in patch 7/8
- namespace SRDS_PRTCL values for LS1046A and LS1088A, even if they are
the same. For LS1028A (not covered here) they are not.
- prefix SRDS_CLK_SEL_{GMII,XGMII} with LS2088A_
- reorder alphanumerically (LS1046A should come before LS1088A)
Change log also in individual patches.
v1 at:
https://lore.kernel.org/linux-phy/20260611193940.44416-1-vladimir.oltean@nxp.com/
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Ioana Ciornei (5):
soc: fsl: guts: use a macro to encode the DCFG CCSR space
soc: fsl: guts: add a global structure to hold state
soc: fsl: guts: add a central fsl_guts_read() function
soc: fsl: guts: make it easier to determine on which SoC we are
running
soc: fsl: guts: implement the RCW override procedure
Vladimir Oltean (3):
soc: fsl: guts: make fsl_soc_data available after fsl_guts_init()
dt-bindings: fsl: layerscape-dcfg: define DCFG_DCSR region
phy: lynx-10g: use RCW override procedure for dynamic protocol change
.../bindings/soc/fsl/fsl,layerscape-dcfg.yaml | 15 +-
drivers/phy/freescale/Kconfig | 1 +
drivers/phy/freescale/phy-fsl-lynx-10g.c | 24 +-
drivers/soc/fsl/guts.c | 369 ++++++++++++++++--
include/linux/fsl/guts.h | 20 +-
5 files changed, 393 insertions(+), 36 deletions(-)
--
2.34.1
^ permalink raw reply
* [PATCH v2 phy-next 1/8] soc: fsl: guts: use a macro to encode the DCFG CCSR space
From: Vladimir Oltean @ 2026-06-12 21:08 UTC (permalink / raw)
To: linux-phy
Cc: devicetree, linuxppc-dev, linux-arm-kernel, Ioana Ciornei,
Vinod Koul, Neil Armstrong, Tanjeff Moos,
Christophe Leroy (CS GROUP), Michael Walle, Shawn Guo, Frank Li,
linux-kernel
In-Reply-To: <20260612210859.266759-1-vladimir.oltean@nxp.com>
From: Ioana Ciornei <ioana.ciornei@nxp.com>
Instead of using a hardcoded value when iomapping the DCFG CCSR space,
add a new macro for it. The code will be easier to follow this way,
especially when we add support for the DCFG DCSR space as well.
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v1->v2: none
---
drivers/soc/fsl/guts.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
index 9bee7baec2b9..f87ee47c1503 100644
--- a/drivers/soc/fsl/guts.c
+++ b/drivers/soc/fsl/guts.c
@@ -14,6 +14,8 @@
#include <linux/platform_device.h>
#include <linux/fsl/guts.h>
+#define DCFG_CCSR 0
+
struct fsl_soc_die_attr {
char *die;
u32 svr;
@@ -197,7 +199,7 @@ static int __init fsl_guts_init(void)
return 0;
soc_data = match->data;
- regs = of_iomap(np, 0);
+ regs = of_iomap(np, DCFG_CCSR);
if (!regs) {
of_node_put(np);
return -ENOMEM;
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v1 4/4] media: qcom: jpeg: Add Qualcomm JPEG V4L2 encoder
From: Frank Li @ 2026-06-12 20:53 UTC (permalink / raw)
To: Atanas Filipov
Cc: linux-media, mchehab, bod, robh, krzk+dt, conor+dt, andersson,
konradybcio, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260612194417.1737009-5-atanas.filipov@oss.qualcomm.com>
On Fri, Jun 12, 2026 at 10:44:17PM +0300, Atanas Filipov wrote:
> Add a Qualcomm JPEG encoder driver implemented on top of the
> V4L2 mem2mem framework.
>
> The driver wires vb2 queue handling, format negotiation, JPEG header
> handling, interrupt-driven job completion, and runtime PM/clock/ICC
> integration for the standalone JPEG encode hardware block.
>
> Initial support in this series targets SM8250, QCM6490, and SM8550
> class platforms.
>
> Signed-off-by: Atanas Filipov <atanas.filipov@oss.qualcomm.com>
> ---
...
> +
> +static __maybe_unused int qcom_jpeg_pm_suspend(struct device *dev)
new API needn't __maybe_unused, check below
> +{
> + struct qcom_jenc_dev *jenc = dev_get_drvdata(dev);
> +
> + qcom_jpeg_clk_off(jenc);
> +
> + qcom_jpeg_icc_off(jenc);
> +
> + return 0;
> +}
> +
...
> +static const struct dev_pm_ops qcom_jpeg_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(qcom_jpeg_suspend, qcom_jpeg_resume)
> + SET_RUNTIME_PM_OPS(qcom_jpeg_pm_suspend, qcom_jpeg_pm_resume, NULL)
use new macro RUNTIME_PM_OPS
> +};
> +
> +static int qcom_jpeg_probe(struct platform_device *pdev)
> +{
> + const struct qcom_dev_resources *res;
> + struct qcom_jenc_dev *jenc;
> + int rc;
> +
> + jenc = devm_kzalloc(&pdev->dev, sizeof(*jenc), GFP_KERNEL);
> + if (!jenc)
> + return -ENOMEM;
> +
> + jenc->dev = &pdev->dev;
> + mutex_init(&jenc->dev_mutex);
devm_mutex_init();
> + spin_lock_init(&jenc->hw_lock);
> + init_completion(&jenc->reset_complete);
> + init_completion(&jenc->stop_complete);
> +
> + res = device_get_match_data(jenc->dev);
> + if (!res)
> + return dev_err_probe(jenc->dev, -ENODEV, "unsupported SoC\n");
> + jenc->res = res;
> +
> + if (!jenc->res->hw_offs || !jenc->res->hw_ops)
> + return dev_err_probe(jenc->dev, -EINVAL, "missing hw resources\n");
> +
> + rc = dma_set_mask_and_coherent(jenc->dev, DMA_BIT_MASK(32));
when mask >= 32, needn't check return value.
> + if (rc)
> + return dev_err_probe(jenc->dev, rc, "failed to set DMA mask\n");
> +
> + jenc->jpeg_base = devm_platform_ioremap_resource_byname(pdev, "jpeg");
> + if (IS_ERR(jenc->jpeg_base))
> + return dev_err_probe(jenc->dev, PTR_ERR(jenc->jpeg_base),
> + "failed to map JPEG resource\n");
> +
> + rc = qcom_jpeg_clk_init(jenc);
> + if (rc)
> + return rc;
> +
> + jenc->irq = platform_get_irq(pdev, 0);
> + if (jenc->irq < 0)
> + return dev_err_probe(jenc->dev, jenc->irq, "failed to get IRQ\n");
> +
> + rc = devm_request_threaded_irq(jenc->dev, jenc->irq,
> + jenc->res->hw_ops->hw_irq_top,
> + jenc->res->hw_ops->hw_irq_bot,
> + IRQF_ONESHOT, dev_name(jenc->dev), jenc);
> + if (rc)
> + return dev_err_probe(jenc->dev, rc, "failed to request IRQ\n");
> +
> + rc = qcom_jpeg_icc_init(jenc);
> + if (rc)
> + return rc;
> +
> + rc = v4l2_device_register(jenc->dev, &jenc->v4l2_dev);
> + if (rc) {
> + dev_err(jenc->dev, "failed to register V4L2 device\n");
> + return rc;
> + }
> +
> + jenc->perf = QCOM_SOC_PERF_NOMINAL;
> +
> + rc = qcom_jpeg_v4l2_register(jenc);
> + if (rc) {
> + dev_err(jenc->dev, "failed to register video device\n");
> + goto err_v4l2_device_unregister;
> + }
> +
> + rc = devm_pm_runtime_enable(jenc->dev);
> + if (rc)
> + goto err_v4l2_unregister;
> +
> + dev_dbg(jenc->dev, "Qualcomm JPEG encoder registered\n");
> +
> + platform_set_drvdata(pdev, jenc);
It's better set at early phrase, include some async function use it.
> +
> + return 0;
> +
> +err_v4l2_unregister:
> + qcom_jpeg_v4l2_unregister(jenc);
> +err_v4l2_device_unregister:
> + v4l2_device_unregister(&jenc->v4l2_dev);
> + return rc;
> +}
> +
> +static void qcom_jpeg_remove(struct platform_device *pdev)
> +{
> + struct qcom_jenc_dev *jenc = platform_get_drvdata(pdev);
> +
> + qcom_jpeg_v4l2_unregister(jenc);
> +
> + v4l2_device_unregister(&jenc->v4l2_dev);
> +
> + dev_dbg(jenc->dev, "Qualcomm JPEG encoder deregistered\n");
> +}
> +
> +static const struct of_device_id qcom_jpeg_of_match[] = {
> + {
> + .compatible = "qcom,sm8250-jenc",
> + .data = &qcom_t165_t480_jpeg_drvdata
> + },
> + {
> + .compatible = "qcom,qcm6490-jenc",
> + .data = &qcom_t680_jpeg_drvdata
> + },
> + {
> + .compatible = "qcom,sm8550-jenc",
> + .data = &qcom_t780_jpeg_drvdata
> + },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, qcom_jpeg_of_match);
> +
> +static struct platform_driver qcom_jpeg_platform_driver = {
> + .probe = qcom_jpeg_probe,
> + .remove = qcom_jpeg_remove,
> + .driver = {
> + .name = QCOM_JPEG_ENC_NAME,
> + .of_match_table = qcom_jpeg_of_match,
> + .pm = &qcom_jpeg_pm_ops,
pm_ptr(&qcom_jpeg_pm_ops)
Frank
> + },
> +};
> +
^ permalink raw reply
* Re: [PATCH v6 4/7] mfd: mt6397: Add support for MT6392 PMIC
From: sashiko-bot @ 2026-06-12 20:44 UTC (permalink / raw)
To: Luca Leonardo Scorcia
Cc: linux-input, dmitry.torokhov, robh, conor+dt, devicetree
In-Reply-To: <20260612200717.361018-5-l.scorcia@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The PM notifier `chip->pm_nb` and the unmanaged `irq_domain` are leaked on probe failure and driver unbind, leading to a Use-After-Free during system suspend/resume.
--
commit 7e58614b47c19c51b0d112cc3708ab6bf5ecdc5a
Author: Fabien Parent <parent.f@gmail.com>
mfd: mt6397: Add support for MT6392 PMIC
Align the MT6397 PMIC driver to other MFD drivers by passing only an
identifier through mt6397_of_match[*].data and add support for the MT6392
PMIC and its RTC, keys and pinctrl devices.
> diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c
> index 5d2e5459f7444..80ea5b92d232f 100644
> --- a/drivers/mfd/mt6397-irq.c
> +++ b/drivers/mfd/mt6397-irq.c
> @@ -203,6 +205,12 @@ int mt6397_irq_init(struct mt6397_chip *chip)
> chip->int_status[0] = MT6397_INT_STATUS0;
> chip->int_status[1] = MT6397_INT_STATUS1;
> break;
> + case MT6392_CHIP_ID:
> + chip->int_con[0] = MT6392_INT_CON0;
> + chip->int_con[1] = MT6392_INT_CON1;
> + chip->int_status[0] = MT6392_INT_STATUS0;
> + chip->int_status[1] = MT6392_INT_STATUS1;
> + break;
>
> default:
> dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);
[Severity: High]
This is a pre-existing issue, but I noticed a potential memory safety
problem involving the initialization in mt6397_irq_init() and the probe
error path in mt6397_probe().
Later in mt6397_irq_init(), we call:
register_pm_notifier(&chip->pm_nb);
However, there doesn't seem to be a corresponding unregister_pm_notifier()
anywhere in the driver, nor a .remove callback in mt6397_driver.
If devm_mfd_add_devices() fails in mt6397_probe(), the devres mechanism
will free the mt6397_chip structure (pmic). Since the pm_nb remains
linked in the global pm_chain_head list, wouldn't a subsequent
suspend/resume event dereference the freed memory and cause a
use-after-free panic?
Additionally, could this also leak the irq_domain (created with
irq_domain_create_linear) if the driver is unbound via sysfs?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612200717.361018-1-l.scorcia@gmail.com?part=4
^ permalink raw reply
* Re: [PATCH v1 1/4] dt-bindings: media: qcom: Add JPEG encoder binding
From: Frank Li @ 2026-06-12 20:42 UTC (permalink / raw)
To: Atanas Filipov
Cc: linux-media, mchehab, bod, robh, krzk+dt, conor+dt, andersson,
konradybcio, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260612194417.1737009-2-atanas.filipov@oss.qualcomm.com>
On Fri, Jun 12, 2026 at 10:44:14PM +0300, Atanas Filipov wrote:
> Add device-tree binding for the standalone Qualcomm JPEG encoder
> hardware block (separate from CAMSS media pipelines).
>
> Document required resources briefly and scope initial support to
> currently used compatibles in this series, including SM8250,
> QCM6490, and SM8550 class platforms.
>
> Signed-off-by: Atanas Filipov <atanas.filipov@oss.qualcomm.com>
> ---
> .../bindings/media/qcom,jpeg-encoder.yaml | 142 ++++++++++++++++++
> 1 file changed, 142 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/qcom,jpeg-encoder.yaml
>
> diff --git a/Documentation/devicetree/bindings/media/qcom,jpeg-encoder.yaml b/Documentation/devicetree/bindings/media/qcom,jpeg-encoder.yaml
> new file mode 100644
> index 000000000000..83f19719a869
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/qcom,jpeg-encoder.yaml
> @@ -0,0 +1,142 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/qcom,jpeg-encoder.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm JPEG Encoder
> +
> +maintainers:
> + - Azam Sadiq Pasha Kapatrala Syed <akapatra@quicinc.com>
> + - Hariram Purushothaman <hariramp@quicinc.com>
> +
> +description: |
Needn't |
> + Qualcomm JPEG Encoder is the JPEG encode hardware present in Qualcomm SoCs.
> +
> + The JPEG hardware IP version 4.2.0 is shared across SM8250, QCM6490, SM8550
> + and related derivatives. Platforms based on the SM8550 register layout and
> + interrupt wiring can reuse the qcom,sm8550-jenc fallback compatible, provided
> + the correct register base address and IOMMU stream IDs are supplied in the
> + DTS node.
> +
> +properties:
> + compatible:
> + oneOf:
> + - items:
> + - const: qcom,sm8250-jenc
> + - items:
> + - enum:
> + - qcom,qcm6490-jenc
> + - const: qcom,sm8550-jenc
> + - items:
> + - const: qcom,sm8550-jenc
> +
> + cell-index:
> + description: Legacy JPEG HW instance index.
> + $ref: /schemas/types.yaml#/definitions/uint32
> +
> + reg:
> + maxItems: 1
> +
> + reg-names:
> + oneOf:
> + - items:
> + - const: jpeg
> + - items:
> + - const: jpeg-regs
> + - items:
> + - const: jpeg_regs
use enum
If reg only have 1, needn't reg-names.
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + minItems: 6
> + maxItems: 6
> +
> + clock-names:
> + oneOf:
> + - items:
> + - const: gcc_hf_axi
> + - const: gcc_sf_axi
> + - const: core_ahb
> + - const: cpas_ahb
> + - const: camnoc_axi
> + - const: jpeg
> + - items:
> + - const: gcc_hf_axi_clk
> + - const: gcc_sf_axi_clk
> + - const: core_ahb_clk
> + - const: cpas_ahb_clk
> + - const: camnoc_axi_clk
> + - const: jpeg_clk
Needn't _clk
after remove _clk, both is the same.
> +
> + power-domains:
> + maxItems: 1
> +
> + iommus:
> + maxItems: 2
> +
> + interconnects:
> + maxItems: 4
> +
> + interconnect-names:
> + items:
> + - const: cam_ahb
> + - const: cam_hf_0_mnoc
> + - const: cam_sf_0_mnoc
> + - const: cam_sf_icp_mnoc
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - interrupts
> + - power-domains
> + - iommus
iommus need be listed in top property
iommus:
maxItems: 2
Frank
> + - interconnects
> + - interconnect-names
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + jpeg-encoder@ac53000 {
> + compatible = "qcom,sm8250-jenc";
> + reg = <0xac53000 0x1000>;
> + reg-names = "jpeg";
> +
> + interrupts = <0 474 4>;
> + power-domains = <&camcc 0>;
> +
> + clock-names =
> + "gcc_hf_axi",
> + "gcc_sf_axi",
> + "core_ahb",
> + "cpas_ahb",
> + "camnoc_axi",
> + "jpeg";
> +
> + clocks =
> + <&gcc 0>,
> + <&gcc 1>,
> + <&camcc 0>,
> + <&camcc 1>,
> + <&camcc 2>,
> + <&camcc 3>;
> +
> + iommus = <&apps_smmu 0x2040 0x400>,
> + <&apps_smmu 0x2440 0x400>;
> +
> + interconnects =
> + <&gem_noc 0 0 &config_noc 8 0>,
> + <&mmss_noc 0 0 &mc_virt 0 0>,
> + <&mmss_noc 1 0 &mc_virt 0 0>,
> + <&mmss_noc 2 0 &mc_virt 0 0>;
> +
> + interconnect-names =
> + "cam_ahb",
> + "cam_hf_0_mnoc",
> + "cam_sf_0_mnoc",
> + "cam_sf_icp_mnoc";
> + };
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH v6 5/7] input: keyboard: mtk-pmic-keys: Add MT6392 support
From: sashiko-bot @ 2026-06-12 20:39 UTC (permalink / raw)
To: Luca Leonardo Scorcia
Cc: linux-input, dmitry.torokhov, conor+dt, robh, devicetree
In-Reply-To: <20260612200717.361018-6-l.scorcia@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Out-of-bounds array access and incorrect parsing of disabled DT nodes in `mtk_pmic_keys_probe` due to a mismatch between child counting and iteration macros.
- [High] `mt6357_regs` incorrectly uses `MTK_PMIC_HOMEKEY_INDEX` instead of `MTK_PMIC_HOMEKEY_RST` for the home key reset mask.
--
commit 2b2bdf18b713288536d3d56d4b82a48e65594233
Author: Val Packett <val@packett.cool>
input: keyboard: mtk-pmic-keys: Add MT6392 support
This commit adds support for the MT6392 PMIC to the mediatek pmic keys driver
by defining its specific register layout and adding the required compatible
string.
> diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
> index c78d9f6d97c4f..8b4a89fce4fb1 100644
> --- a/drivers/input/keyboard/mtk-pmic-keys.c
> +++ b/drivers/input/keyboard/mtk-pmic-keys.c
[ ... ]
> @@ -69,6 +70,19 @@ static const struct mtk_pmic_regs mt6397_regs = {
> .rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
> };
>
> +static const struct mtk_pmic_regs mt6392_regs = {
> + .keys_regs[MTK_PMIC_PWRKEY_INDEX] =
> + MTK_PMIC_KEYS_REGS(MT6392_CHRSTATUS, 0x2,
> + MT6392_INT_MISC_CON, 0x10,
> + MTK_PMIC_PWRKEY_RST),
> + .keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
> + MTK_PMIC_KEYS_REGS(MT6392_CHRSTATUS, 0x4,
> + MT6392_INT_MISC_CON, 0x8,
> + MTK_PMIC_HOMEKEY_RST),
> + .pmic_rst_reg = MT6392_TOP_RST_MISC,
> + .rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
> +};
> +
[Severity: High]
This isn't a bug introduced by this patch, but I noticed a potential
out-of-bounds access in mtk_pmic_keys_probe() due to a mismatch in child node
parsing:
drivers/input/keyboard/mtk-pmic-keys.c:mtk_pmic_keys_probe() {
...
keycount = of_get_available_child_count(node);
if (keycount > MTK_PMIC_MAX_KEY_COUNT) {
dev_err(dev, "too many keys defined (%d)\n", keycount);
return -EINVAL;
}
for_each_child_of_node_scoped(node, child) {
keys->keys[index].regs = &keys->mtk_regs->keys_regs[index];
...
}
The check uses of_get_available_child_count(), which skips nodes with
status="disabled", but the loop uses for_each_child_of_node_scoped(), which
iterates over all child nodes regardless of their availability.
If a device tree defines more than MTK_PMIC_MAX_KEY_COUNT nodes but disables
enough to pass the initial check, could the loop execute more than
MTK_PMIC_MAX_KEY_COUNT times? Would this cause an out-of-bounds array access
on the keys->keys[] and irqnames[] arrays?
[Severity: High]
This is a pre-existing issue as well, but looking at the existing register
definitions, mt6357_regs appears to use the wrong macro for the home key
reset mask:
drivers/input/keyboard/mtk-pmic-keys.c:
static const struct mtk_pmic_regs mt6357_regs = {
.keys_regs[MTK_PMIC_PWRKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6357_TOPSTATUS,
0x2, MT6357_INT_MISC_CON, 0x10, MTK_PMIC_PWRKEY_RST),
.keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6357_TOPSTATUS,
0x8, MT6357_INT_MISC_CON, 0x8, MTK_PMIC_HOMEKEY_INDEX),
...
};
Does this incorrectly use MTK_PMIC_HOMEKEY_INDEX instead of
MTK_PMIC_HOMEKEY_RST?
Because MTK_PMIC_HOMEKEY_INDEX is just an array index, would this result in
modifying the wrong bits in the reset register during
mtk_pmic_keys_lp_reset_setup() and failing to properly enable the long-press
hardware reset for the home key on MT6357?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612200717.361018-1-l.scorcia@gmail.com?part=5
^ permalink raw reply
* Re: [PATCH v6 1/7] dt-bindings: mfd: mt6397: Add MT6392 PMIC
From: sashiko-bot @ 2026-06-12 20:37 UTC (permalink / raw)
To: Luca Leonardo Scorcia
Cc: devicetree, linux-input, conor+dt, dmitry.torokhov, robh
In-Reply-To: <20260612200717.361018-2-l.scorcia@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The dt-bindings schema for the MT6392 PMIC omits the 'mediatek,mt6392-regulator' compatible string for the 'regulators' child node. Since the 'regulators' node is unconditionally marked as required in the schema, any complete device tree correctly describing the MT6392 hardware must include it. Omitting the MT6392-specific regulator compatible string from the schema forces DT authors to either write incomplete DTs (which fail validation because the node is required) or use incorrect/generic compatible strings, causing schema validation failures when they attempt to properly describe the hardware with 'mediatek,mt6392-regulator'.
--
commit a20444c8e4c98a81558d6d5c619b650c00235e18
Author: Fabien Parent <parent.f@gmail.com>
dt-bindings: mfd: mt6397: Add MT6392 PMIC
Add the initial bindings for the MT6392 PMIC and its RTC device.
> diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> index 3cbc0dc12c319..e39e81aa99249 100644
> --- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> +++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
[ ... ]
> @@ -72,6 +76,10 @@ properties:
> - mediatek,mt6331-rtc
> - mediatek,mt6358-rtc
> - mediatek,mt6397-rtc
> + - items:
> + - enum:
> + - mediatek,mt6392-rtc
> + - const: mediatek,mt6323-rtc
[Severity: Medium]
Should the mediatek,mt6392-regulator compatible string be added to the
regulators child node as well?
Since the regulators node is unconditionally marked as required in the schema,
any complete device tree describing the MT6392 hardware must include it.
Does this missing string cause a regression where DT authors are forced to
either write incomplete DTs (which fail validation) or use incorrect compatible
strings?
This causes schema validation failures when authors attempt to properly describe
the hardware with mediatek,mt6392-regulator:
Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml:
regulators:
...
properties:
compatible:
oneOf:
- enum:
- mediatek,mt6323-regulator
- mediatek,mt6328-regulator
...
> - items:
> - enum:
> - mediatek,mt6359-rtc
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612200717.361018-1-l.scorcia@gmail.com?part=1
^ permalink raw reply
* [PATCH v6 7/7] arm64: dts: mediatek: Add MediaTek MT6392 PMIC dtsi
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Val Packett, Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Louis-Alexis Eyraud,
Julien Massot, Fabien Parent, Akari Tsuyukusa, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
From: Val Packett <val@packett.cool>
Add the dts to be included by all boards using the MT6392 PMIC,
providing support for keys, pinctrl and RTC.
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
arch/arm64/boot/dts/mediatek/mt6392.dtsi | 41 ++++++++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6392.dtsi
diff --git a/arch/arm64/boot/dts/mediatek/mt6392.dtsi b/arch/arm64/boot/dts/mediatek/mt6392.dtsi
new file mode 100644
index 000000000000..b8d943e47816
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt6392.dtsi
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Copyright (c) 2024 Val Packett <val@packett.cool>
+ */
+
+#include <dt-bindings/input/input.h>
+
+&pwrap {
+ pmic: pmic {
+ compatible = "mediatek,mt6392", "mediatek,mt6323";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ mt6392keys: keys {
+ compatible = "mediatek,mt6392-keys";
+
+ key-power {
+ linux,keycodes = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ key-home {
+ linux,keycodes = <KEY_HOME>;
+ wakeup-source;
+ };
+ };
+
+ mt6392pio: pinctrl {
+ compatible = "mediatek,mt6392-pinctrl";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ mt6392rtc: rtc {
+ compatible = "mediatek,mt6392-rtc",
+ "mediatek,mt6323-rtc";
+ };
+ };
+};
--
2.43.0
^ permalink raw reply related
* [PATCH v6 6/7] pinctrl: mediatek: mt6397: Add MediaTek MT6392
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Luca Leonardo Scorcia, AngeloGioacchino Del Regno,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
Linus Walleij, Louis-Alexis Eyraud, Julien Massot, Val Packett,
Fabien Parent, Akari Tsuyukusa, Chen Zhong, linux-input,
devicetree, linux-kernel, linux-pm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
Add support for the MT6392 pinctrl device, which is very similar to
MT6397 with a handful of different property values and its own pins
definition.
Update the MT6397 driver to retrieve device data from the match table and
use it for driver init.
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/pinctrl/mediatek/pinctrl-mt6397.c | 37 ++++++++++-
drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h | 64 +++++++++++++++++++
2 files changed, 99 insertions(+), 2 deletions(-)
create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6397.c b/drivers/pinctrl/mediatek/pinctrl-mt6397.c
index 03d0f65d7bcc..8ba02e70595c 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt6397.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt6397.c
@@ -12,10 +12,32 @@
#include <linux/mfd/mt6397/core.h>
#include "pinctrl-mtk-common.h"
+#include "pinctrl-mtk-mt6392.h"
#include "pinctrl-mtk-mt6397.h"
#define MT6397_PIN_REG_BASE 0xc000
+static const struct mtk_pinctrl_devdata mt6392_pinctrl_data = {
+ .pins = mtk_pins_mt6392,
+ .npins = ARRAY_SIZE(mtk_pins_mt6392),
+ .dir_offset = (MT6397_PIN_REG_BASE + 0x000),
+ .ies_offset = MTK_PINCTRL_NOT_SUPPORT,
+ .smt_offset = MTK_PINCTRL_NOT_SUPPORT,
+ .pullen_offset = (MT6397_PIN_REG_BASE + 0x020),
+ .pullsel_offset = (MT6397_PIN_REG_BASE + 0x040),
+ .dout_offset = (MT6397_PIN_REG_BASE + 0x080),
+ .din_offset = (MT6397_PIN_REG_BASE + 0x0a0),
+ .pinmux_offset = (MT6397_PIN_REG_BASE + 0x0c0),
+ .type1_start = 7,
+ .type1_end = 7,
+ .port_shf = 3,
+ .port_mask = 0x3,
+ .port_align = 2,
+ .mode_mask = 0xf,
+ .mode_per_reg = 5,
+ .mode_shf = 4,
+};
+
static const struct mtk_pinctrl_devdata mt6397_pinctrl_data = {
.pins = mtk_pins_mt6397,
.npins = ARRAY_SIZE(mtk_pins_mt6397),
@@ -40,13 +62,24 @@ static const struct mtk_pinctrl_devdata mt6397_pinctrl_data = {
static int mt6397_pinctrl_probe(struct platform_device *pdev)
{
struct mt6397_chip *mt6397;
+ const struct mtk_pinctrl_devdata *data;
+
+ data = device_get_match_data(&pdev->dev);
+ if (!data)
+ return -ENOENT;
mt6397 = dev_get_drvdata(pdev->dev.parent);
- return mtk_pctrl_init(pdev, &mt6397_pinctrl_data, mt6397->regmap);
+ return mtk_pctrl_init(pdev, data, mt6397->regmap);
}
static const struct of_device_id mt6397_pctrl_match[] = {
- { .compatible = "mediatek,mt6397-pinctrl", },
+ {
+ .compatible = "mediatek,mt6392-pinctrl",
+ .data = &mt6392_pinctrl_data
+ }, {
+ .compatible = "mediatek,mt6397-pinctrl",
+ .data = &mt6397_pinctrl_data
+ },
{ }
};
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h
new file mode 100644
index 000000000000..e7241af28fdb
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PINCTRL_MTK_MT6392_H
+#define __PINCTRL_MTK_MT6392_H
+
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-mtk-common.h"
+
+static const struct mtk_desc_pin mtk_pins_mt6392[] = {
+ MTK_PIN(PINCTRL_PIN(0, "INT"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO0"),
+ MTK_FUNCTION(1, "INT"),
+ MTK_FUNCTION(5, "TEST_CK2"),
+ MTK_FUNCTION(6, "TEST_IN1"),
+ MTK_FUNCTION(7, "TEST_OUT1")
+ ),
+ MTK_PIN(PINCTRL_PIN(1, "SRCLKEN"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO1"),
+ MTK_FUNCTION(1, "SRCLKEN"),
+ MTK_FUNCTION(5, "TEST_CK0"),
+ MTK_FUNCTION(6, "TEST_IN2"),
+ MTK_FUNCTION(7, "TEST_OUT2")
+ ),
+ MTK_PIN(PINCTRL_PIN(2, "RTC_32K1V8"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO2"),
+ MTK_FUNCTION(1, "RTC_32K1V8"),
+ MTK_FUNCTION(5, "TEST_CK1"),
+ MTK_FUNCTION(6, "TEST_IN3"),
+ MTK_FUNCTION(7, "TEST_OUT3")
+ ),
+ MTK_PIN(PINCTRL_PIN(3, "SPI_CLK"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO3"),
+ MTK_FUNCTION(1, "SPI_CLK")
+ ),
+ MTK_PIN(PINCTRL_PIN(4, "SPI_CSN"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO4"),
+ MTK_FUNCTION(1, "SPI_CSN")
+ ),
+ MTK_PIN(PINCTRL_PIN(5, "SPI_MOSI"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO5"),
+ MTK_FUNCTION(1, "SPI_MOSI")
+ ),
+ MTK_PIN(PINCTRL_PIN(6, "SPI_MISO"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO6"),
+ MTK_FUNCTION(1, "SPI_MISO"),
+ MTK_FUNCTION(6, "TEST_IN4"),
+ MTK_FUNCTION(7, "TEST_OUT4")
+ ),
+};
+
+#endif /* __PINCTRL_MTK_MT6392_H */
--
2.43.0
^ permalink raw reply related
* [PATCH v6 5/7] input: keyboard: mtk-pmic-keys: Add MT6392 support
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Val Packett, Luca Leonardo Scorcia, AngeloGioacchino Del Regno,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
Linus Walleij, Julien Massot, Louis-Alexis Eyraud, Fabien Parent,
Akari Tsuyukusa, Chen Zhong, linux-input, devicetree,
linux-kernel, linux-pm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
From: Val Packett <val@packett.cool>
Add support for the MT6392 PMIC to the keys driver.
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/keyboard/mtk-pmic-keys.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
index c78d9f6d97c4..8b4a89fce4fb 100644
--- a/drivers/input/keyboard/mtk-pmic-keys.c
+++ b/drivers/input/keyboard/mtk-pmic-keys.c
@@ -13,6 +13,7 @@
#include <linux/mfd/mt6357/registers.h>
#include <linux/mfd/mt6358/registers.h>
#include <linux/mfd/mt6359/registers.h>
+#include <linux/mfd/mt6392/registers.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/registers.h>
#include <linux/module.h>
@@ -69,6 +70,19 @@ static const struct mtk_pmic_regs mt6397_regs = {
.rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
};
+static const struct mtk_pmic_regs mt6392_regs = {
+ .keys_regs[MTK_PMIC_PWRKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6392_CHRSTATUS, 0x2,
+ MT6392_INT_MISC_CON, 0x10,
+ MTK_PMIC_PWRKEY_RST),
+ .keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6392_CHRSTATUS, 0x4,
+ MT6392_INT_MISC_CON, 0x8,
+ MTK_PMIC_HOMEKEY_RST),
+ .pmic_rst_reg = MT6392_TOP_RST_MISC,
+ .rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
+};
+
static const struct mtk_pmic_regs mt6323_regs = {
.keys_regs[MTK_PMIC_PWRKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
@@ -301,6 +315,9 @@ static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = {
{
.compatible = "mediatek,mt6397-keys",
.data = &mt6397_regs,
+ }, {
+ .compatible = "mediatek,mt6392-keys",
+ .data = &mt6392_regs,
}, {
.compatible = "mediatek,mt6323-keys",
.data = &mt6323_regs,
--
2.43.0
^ permalink raw reply related
* [PATCH v6 4/7] mfd: mt6397: Add support for MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
AngeloGioacchino Del Regno, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger, Linus Walleij,
Louis-Alexis Eyraud, Julien Massot, Akari Tsuyukusa, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
Align the MT6397 PMIC driver to other MFD drivers by passing only an
identifier through mt6397_of_match[*].data and add support for the MT6392
PMIC and its RTC, keys and pinctrl devices.
The keys device manages two key IRQs named PWRKEY and FCHR_ENB in the data
sheet, but it does not explain what the last acronym means exactly.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/mfd/mt6397-core.c | 97 ++++--
drivers/mfd/mt6397-irq.c | 8 +
include/linux/mfd/mt6392/core.h | 43 +++
include/linux/mfd/mt6392/registers.h | 488 +++++++++++++++++++++++++++
include/linux/mfd/mt6397/core.h | 1 +
5 files changed, 611 insertions(+), 26 deletions(-)
create mode 100644 include/linux/mfd/mt6392/core.h
create mode 100644 include/linux/mfd/mt6392/registers.h
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index ccd97d66d7f1..8234210f148e 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -18,6 +18,7 @@
#include <linux/mfd/mt6357/core.h>
#include <linux/mfd/mt6358/core.h>
#include <linux/mfd/mt6359/core.h>
+#include <linux/mfd/mt6392/core.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6323/registers.h>
#include <linux/mfd/mt6328/registers.h>
@@ -25,6 +26,7 @@
#include <linux/mfd/mt6357/registers.h>
#include <linux/mfd/mt6358/registers.h>
#include <linux/mfd/mt6359/registers.h>
+#include <linux/mfd/mt6392/registers.h>
#include <linux/mfd/mt6397/registers.h>
#define MT6323_RTC_BASE 0x8000
@@ -39,6 +41,9 @@
#define MT6358_RTC_BASE 0x0588
#define MT6358_RTC_SIZE 0x3c
+#define MT6392_RTC_BASE 0x8000
+#define MT6392_RTC_SIZE 0x3e
+
#define MT6397_RTC_BASE 0xe000
#define MT6397_RTC_SIZE 0x3e
@@ -65,6 +70,11 @@ static const struct resource mt6358_rtc_resources[] = {
DEFINE_RES_IRQ(MT6358_IRQ_RTC),
};
+static const struct resource mt6392_rtc_resources[] = {
+ DEFINE_RES_MEM(MT6392_RTC_BASE, MT6392_RTC_SIZE),
+ DEFINE_RES_IRQ(MT6392_IRQ_RTC),
+};
+
static const struct resource mt6397_rtc_resources[] = {
DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE),
DEFINE_RES_IRQ(MT6397_IRQ_RTC),
@@ -114,6 +124,11 @@ static const struct resource mt6331_keys_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_HOMEKEY, "homekey"),
};
+static const struct resource mt6392_keys_resources[] = {
+ DEFINE_RES_IRQ_NAMED(MT6392_IRQ_PWRKEY, "powerkey"),
+ DEFINE_RES_IRQ_NAMED(MT6392_IRQ_FCHRKEY, "homekey"),
+};
+
static const struct resource mt6397_keys_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6397_IRQ_PWRKEY, "powerkey"),
DEFINE_RES_IRQ_NAMED(MT6397_IRQ_HOMEKEY, "homekey"),
@@ -193,6 +208,15 @@ static const struct mfd_cell mt6359_devs[] = {
"mediatek,mt6359-accdet"),
};
+static const struct mfd_cell mt6392_devs[] = {
+ MFD_CELL_OF("mt6392-keys", mt6392_keys_resources, NULL, 0, 0,
+ "mediatek,mt6392-keys"),
+ MFD_CELL_OF("mt6392-pinctrl", NULL, NULL, 0, 0,
+ "mediatek,mt6392-pinctrl"),
+ MFD_CELL_OF("mt6392-rtc", mt6392_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6392-rtc"),
+};
+
static const struct mfd_cell mt6397_devs[] = {
MFD_CELL_OF("mt6397-rtc", mt6397_rtc_resources, NULL, 0, 0,
"mediatek,mt6397-rtc"),
@@ -264,6 +288,14 @@ static const struct chip_data mt6359_core = {
.irq_init = mt6358_irq_init,
};
+static const struct chip_data mt6392_core = {
+ .cid_addr = MT6392_CID,
+ .cid_shift = 0,
+ .cells = mt6392_devs,
+ .cell_size = ARRAY_SIZE(mt6392_devs),
+ .irq_init = mt6397_irq_init,
+};
+
static const struct chip_data mt6397_core = {
.cid_addr = MT6397_CID,
.cid_shift = 0,
@@ -278,6 +310,7 @@ static int mt6397_probe(struct platform_device *pdev)
unsigned int id = 0;
struct mt6397_chip *pmic;
const struct chip_data *pmic_core;
+ int chip_variant;
pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
@@ -293,9 +326,36 @@ static int mt6397_probe(struct platform_device *pdev)
if (!pmic->regmap)
return -ENODEV;
- pmic_core = of_device_get_match_data(&pdev->dev);
- if (!pmic_core)
+ chip_variant = (unsigned int)(uintptr_t)device_get_match_data(&pdev->dev);
+ switch (chip_variant) {
+ case MT6323_CHIP_ID:
+ pmic_core = &mt6323_core;
+ break;
+ case MT6328_CHIP_ID:
+ pmic_core = &mt6328_core;
+ break;
+ case MT6331_CHIP_ID:
+ pmic_core = &mt6331_mt6332_core;
+ break;
+ case MT6357_CHIP_ID:
+ pmic_core = &mt6357_core;
+ break;
+ case MT6358_CHIP_ID:
+ pmic_core = &mt6358_core;
+ break;
+ case MT6359_CHIP_ID:
+ pmic_core = &mt6359_core;
+ break;
+ case MT6392_CHIP_ID:
+ pmic_core = &mt6392_core;
+ break;
+ case MT6397_CHIP_ID:
+ pmic_core = &mt6397_core;
+ break;
+ default:
+ dev_err(&pdev->dev, "Device not supported\n");
return -ENODEV;
+ }
ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
if (ret) {
@@ -327,30 +387,15 @@ static int mt6397_probe(struct platform_device *pdev)
}
static const struct of_device_id mt6397_of_match[] = {
- {
- .compatible = "mediatek,mt6323",
- .data = &mt6323_core,
- }, {
- .compatible = "mediatek,mt6328",
- .data = &mt6328_core,
- }, {
- .compatible = "mediatek,mt6331",
- .data = &mt6331_mt6332_core,
- }, {
- .compatible = "mediatek,mt6357",
- .data = &mt6357_core,
- }, {
- .compatible = "mediatek,mt6358",
- .data = &mt6358_core,
- }, {
- .compatible = "mediatek,mt6359",
- .data = &mt6359_core,
- }, {
- .compatible = "mediatek,mt6397",
- .data = &mt6397_core,
- }, {
- /* sentinel */
- }
+ { .compatible = "mediatek,mt6323", .data = (void *)MT6323_CHIP_ID, },
+ { .compatible = "mediatek,mt6328", .data = (void *)MT6328_CHIP_ID, },
+ { .compatible = "mediatek,mt6331", .data = (void *)MT6331_CHIP_ID, },
+ { .compatible = "mediatek,mt6357", .data = (void *)MT6357_CHIP_ID, },
+ { .compatible = "mediatek,mt6358", .data = (void *)MT6358_CHIP_ID, },
+ { .compatible = "mediatek,mt6359", .data = (void *)MT6359_CHIP_ID, },
+ { .compatible = "mediatek,mt6392", .data = (void *)MT6392_CHIP_ID, },
+ { .compatible = "mediatek,mt6397", .data = (void *)MT6397_CHIP_ID, },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mt6397_of_match);
diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c
index 5d2e5459f744..80ea5b92d232 100644
--- a/drivers/mfd/mt6397-irq.c
+++ b/drivers/mfd/mt6397-irq.c
@@ -15,6 +15,8 @@
#include <linux/mfd/mt6328/registers.h>
#include <linux/mfd/mt6331/core.h>
#include <linux/mfd/mt6331/registers.h>
+#include <linux/mfd/mt6392/core.h>
+#include <linux/mfd/mt6392/registers.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/registers.h>
@@ -203,6 +205,12 @@ int mt6397_irq_init(struct mt6397_chip *chip)
chip->int_status[0] = MT6397_INT_STATUS0;
chip->int_status[1] = MT6397_INT_STATUS1;
break;
+ case MT6392_CHIP_ID:
+ chip->int_con[0] = MT6392_INT_CON0;
+ chip->int_con[1] = MT6392_INT_CON1;
+ chip->int_status[0] = MT6392_INT_STATUS0;
+ chip->int_status[1] = MT6392_INT_STATUS1;
+ break;
default:
dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);
diff --git a/include/linux/mfd/mt6392/core.h b/include/linux/mfd/mt6392/core.h
new file mode 100644
index 000000000000..8777b3abf929
--- /dev/null
+++ b/include/linux/mfd/mt6392/core.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ * Copyright (c) 2026 Luca Leonardo Scorcia <l.scorcia@gmail.com>
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ */
+
+#ifndef __MFD_MT6392_CORE_H__
+#define __MFD_MT6392_CORE_H__
+
+enum mt6392_irq_numbers {
+ MT6392_IRQ_SPKL_AB = 0,
+ MT6392_IRQ_SPKL,
+ MT6392_IRQ_BAT_L,
+ MT6392_IRQ_BAT_H,
+ MT6392_IRQ_WATCHDOG,
+ MT6392_IRQ_PWRKEY,
+ MT6392_IRQ_THR_L,
+ MT6392_IRQ_THR_H,
+ MT6392_IRQ_VBATON_UNDET,
+ MT6392_IRQ_BVALID_DET,
+ MT6392_IRQ_CHRDET,
+ MT6392_IRQ_OV,
+ MT6392_IRQ_LDO = 16,
+ MT6392_IRQ_FCHRKEY,
+ MT6392_IRQ_RELEASE_PWRKEY,
+ MT6392_IRQ_RELEASE_FCHRKEY,
+ MT6392_IRQ_RTC,
+ MT6392_IRQ_VPROC,
+ MT6392_IRQ_VSYS,
+ MT6392_IRQ_VCORE,
+ MT6392_IRQ_TYPE_C_CC,
+ MT6392_IRQ_TYPEC_H_MAX,
+ MT6392_IRQ_TYPEC_H_MIN,
+ MT6392_IRQ_TYPEC_L_MAX,
+ MT6392_IRQ_TYPEC_L_MIN,
+ MT6392_IRQ_THR_MAX,
+ MT6392_IRQ_THR_MIN,
+ MT6392_IRQ_NAG_C_DLTV,
+ MT6392_IRQ_NR,
+};
+
+#endif /* __MFD_MT6392_CORE_H__ */
diff --git a/include/linux/mfd/mt6392/registers.h b/include/linux/mfd/mt6392/registers.h
new file mode 100644
index 000000000000..68fe9af448f5
--- /dev/null
+++ b/include/linux/mfd/mt6392/registers.h
@@ -0,0 +1,488 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ * Copyright (c) 2026 Luca Leonardo Scorcia <l.scorcia@gmail.com>
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ */
+
+#ifndef __MFD_MT6392_REGISTERS_H__
+#define __MFD_MT6392_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6392_CHR_CON0 0x0000
+#define MT6392_CHR_CON1 0x0002
+#define MT6392_CHR_CON2 0x0004
+#define MT6392_CHR_CON3 0x0006
+#define MT6392_CHR_CON4 0x0008
+#define MT6392_CHR_CON5 0x000A
+#define MT6392_CHR_CON6 0x000C
+#define MT6392_CHR_CON7 0x000E
+#define MT6392_CHR_CON8 0x0010
+#define MT6392_CHR_CON9 0x0012
+#define MT6392_CHR_CON10 0x0014
+#define MT6392_CHR_CON11 0x0016
+#define MT6392_CHR_CON12 0x0018
+#define MT6392_CHR_CON13 0x001A
+#define MT6392_CHR_CON14 0x001C
+#define MT6392_CHR_CON15 0x001E
+#define MT6392_CHR_CON16 0x0020
+#define MT6392_CHR_CON17 0x0022
+#define MT6392_CHR_CON18 0x0024
+#define MT6392_CHR_CON19 0x0026
+#define MT6392_CHR_CON20 0x0028
+#define MT6392_CHR_CON21 0x002A
+#define MT6392_CHR_CON22 0x002C
+#define MT6392_CHR_CON23 0x002E
+#define MT6392_CHR_CON24 0x0030
+#define MT6392_CHR_CON25 0x0032
+#define MT6392_CHR_CON26 0x0034
+#define MT6392_CHR_CON27 0x0036
+#define MT6392_CHR_CON28 0x0038
+#define MT6392_CHR_CON29 0x003A
+#define MT6392_STRUP_CON0 0x003C
+#define MT6392_STRUP_CON2 0x003E
+#define MT6392_STRUP_CON3 0x0040
+#define MT6392_STRUP_CON4 0x0042
+#define MT6392_STRUP_CON5 0x0044
+#define MT6392_STRUP_CON6 0x0046
+#define MT6392_STRUP_CON7 0x0048
+#define MT6392_STRUP_CON8 0x004A
+#define MT6392_STRUP_CON9 0x004C
+#define MT6392_STRUP_CON10 0x004E
+#define MT6392_STRUP_CON11 0x0050
+#define MT6392_SPK_CON0 0x0052
+#define MT6392_SPK_CON1 0x0054
+#define MT6392_SPK_CON2 0x0056
+#define MT6392_SPK_CON6 0x005E
+#define MT6392_SPK_CON7 0x0060
+#define MT6392_SPK_CON8 0x0062
+#define MT6392_SPK_CON9 0x0064
+#define MT6392_SPK_CON10 0x0066
+#define MT6392_SPK_CON11 0x0068
+#define MT6392_SPK_CON12 0x006A
+#define MT6392_STRUP_CON12 0x006E
+#define MT6392_STRUP_CON13 0x0070
+#define MT6392_STRUP_CON14 0x0072
+#define MT6392_STRUP_CON15 0x0074
+#define MT6392_STRUP_CON16 0x0076
+#define MT6392_STRUP_CON17 0x0078
+#define MT6392_STRUP_CON18 0x007A
+#define MT6392_STRUP_CON19 0x007C
+#define MT6392_STRUP_CON20 0x007E
+#define MT6392_CID 0x0100
+#define MT6392_TOP_CKPDN0 0x0102
+#define MT6392_TOP_CKPDN0_SET 0x0104
+#define MT6392_TOP_CKPDN0_CLR 0x0106
+#define MT6392_TOP_CKPDN1 0x0108
+#define MT6392_TOP_CKPDN1_SET 0x010A
+#define MT6392_TOP_CKPDN1_CLR 0x010C
+#define MT6392_TOP_CKPDN2 0x010E
+#define MT6392_TOP_CKPDN2_SET 0x0110
+#define MT6392_TOP_CKPDN2_CLR 0x0112
+#define MT6392_TOP_RST_CON 0x0114
+#define MT6392_TOP_RST_CON_SET 0x0116
+#define MT6392_TOP_RST_CON_CLR 0x0118
+#define MT6392_TOP_RST_MISC 0x011A
+#define MT6392_TOP_RST_MISC_SET 0x011C
+#define MT6392_TOP_RST_MISC_CLR 0x011E
+#define MT6392_TOP_CKCON0 0x0120
+#define MT6392_TOP_CKCON0_SET 0x0122
+#define MT6392_TOP_CKCON0_CLR 0x0124
+#define MT6392_TOP_CKCON1 0x0126
+#define MT6392_TOP_CKCON1_SET 0x0128
+#define MT6392_TOP_CKCON1_CLR 0x012A
+#define MT6392_TOP_CKTST0 0x012C
+#define MT6392_TOP_CKTST1 0x012E
+#define MT6392_TOP_CKTST2 0x0130
+#define MT6392_TEST_OUT 0x0132
+#define MT6392_TEST_CON0 0x0134
+#define MT6392_TEST_CON1 0x0136
+#define MT6392_EN_STATUS0 0x0138
+#define MT6392_EN_STATUS1 0x013A
+#define MT6392_OCSTATUS0 0x013C
+#define MT6392_OCSTATUS1 0x013E
+#define MT6392_PGSTATUS 0x0140
+#define MT6392_CHRSTATUS 0x0142
+#define MT6392_TDSEL_CON 0x0144
+#define MT6392_RDSEL_CON 0x0146
+#define MT6392_SMT_CON0 0x0148
+#define MT6392_SMT_CON1 0x014A
+#define MT6392_DRV_CON0 0x0152
+#define MT6392_DRV_CON1 0x0154
+#define MT6392_INT_CON0 0x0160
+#define MT6392_INT_CON0_SET 0x0162
+#define MT6392_INT_CON0_CLR 0x0164
+#define MT6392_INT_CON1 0x0166
+#define MT6392_INT_CON1_SET 0x0168
+#define MT6392_INT_CON1_CLR 0x016A
+#define MT6392_INT_MISC_CON 0x016C
+#define MT6392_INT_MISC_CON_SET 0x016E
+#define MT6392_INT_MISC_CON_CLR 0x0170
+#define MT6392_INT_STATUS0 0x0172
+#define MT6392_INT_STATUS1 0x0174
+#define MT6392_OC_GEAR_0 0x0176
+#define MT6392_OC_GEAR_1 0x0178
+#define MT6392_OC_GEAR_2 0x017A
+#define MT6392_OC_CTL_VPROC 0x017C
+#define MT6392_OC_CTL_VSYS 0x017E
+#define MT6392_OC_CTL_VCORE 0x0180
+#define MT6392_FQMTR_CON0 0x0182
+#define MT6392_FQMTR_CON1 0x0184
+#define MT6392_FQMTR_CON2 0x0186
+#define MT6392_RG_SPI_CON 0x0188
+#define MT6392_DEW_DIO_EN 0x018A
+#define MT6392_DEW_READ_TEST 0x018C
+#define MT6392_DEW_WRITE_TEST 0x018E
+#define MT6392_DEW_CRC_SWRST 0x0190
+#define MT6392_DEW_CRC_EN 0x0192
+#define MT6392_DEW_CRC_VAL 0x0194
+#define MT6392_DEW_DBG_MON_SEL 0x0196
+#define MT6392_DEW_CIPHER_KEY_SEL 0x0198
+#define MT6392_DEW_CIPHER_IV_SEL 0x019A
+#define MT6392_DEW_CIPHER_EN 0x019C
+#define MT6392_DEW_CIPHER_RDY 0x019E
+#define MT6392_DEW_CIPHER_MODE 0x01A0
+#define MT6392_DEW_CIPHER_SWRST 0x01A2
+#define MT6392_DEW_RDDMY_NO 0x01A4
+#define MT6392_DEW_RDATA_DLY_SEL 0x01A6
+#define MT6392_CLK_TRIM_CON0 0x01A8
+#define MT6392_BUCK_CON0 0x0200
+#define MT6392_BUCK_CON1 0x0202
+#define MT6392_BUCK_CON2 0x0204
+#define MT6392_BUCK_CON3 0x0206
+#define MT6392_BUCK_CON4 0x0208
+#define MT6392_BUCK_CON5 0x020A
+#define MT6392_VPROC_CON0 0x020C
+#define MT6392_VPROC_CON1 0x020E
+#define MT6392_VPROC_CON2 0x0210
+#define MT6392_VPROC_CON3 0x0212
+#define MT6392_VPROC_CON4 0x0214
+#define MT6392_VPROC_CON5 0x0216
+#define MT6392_VPROC_CON7 0x021A
+#define MT6392_VPROC_CON8 0x021C
+#define MT6392_VPROC_CON9 0x021E
+#define MT6392_VPROC_CON10 0x0220
+#define MT6392_VPROC_CON11 0x0222
+#define MT6392_VPROC_CON12 0x0224
+#define MT6392_VPROC_CON13 0x0226
+#define MT6392_VPROC_CON14 0x0228
+#define MT6392_VPROC_CON15 0x022A
+#define MT6392_VPROC_CON18 0x0230
+#define MT6392_VSYS_CON0 0x0232
+#define MT6392_VSYS_CON1 0x0234
+#define MT6392_VSYS_CON2 0x0236
+#define MT6392_VSYS_CON3 0x0238
+#define MT6392_VSYS_CON4 0x023A
+#define MT6392_VSYS_CON5 0x023C
+#define MT6392_VSYS_CON7 0x0240
+#define MT6392_VSYS_CON8 0x0242
+#define MT6392_VSYS_CON9 0x0244
+#define MT6392_VSYS_CON10 0x0246
+#define MT6392_VSYS_CON11 0x0248
+#define MT6392_VSYS_CON12 0x024A
+#define MT6392_VSYS_CON13 0x024C
+#define MT6392_VSYS_CON14 0x024E
+#define MT6392_VSYS_CON15 0x0250
+#define MT6392_VSYS_CON18 0x0256
+#define MT6392_BUCK_OC_CON0 0x0258
+#define MT6392_BUCK_OC_CON1 0x025A
+#define MT6392_BUCK_OC_CON2 0x025C
+#define MT6392_BUCK_OC_CON3 0x025E
+#define MT6392_BUCK_OC_CON4 0x0260
+#define MT6392_BUCK_OC_VPROC_CON0 0x0262
+#define MT6392_BUCK_OC_VCORE_CON0 0x0264
+#define MT6392_BUCK_OC_VSYS_CON0 0x0266
+#define MT6392_BUCK_ANA_MON_CON0 0x0268
+#define MT6392_BUCK_EFUSE_OC_CON0 0x026A
+#define MT6392_VCORE_CON0 0x0300
+#define MT6392_VCORE_CON1 0x0302
+#define MT6392_VCORE_CON2 0x0304
+#define MT6392_VCORE_CON3 0x0306
+#define MT6392_VCORE_CON4 0x0308
+#define MT6392_VCORE_CON5 0x030A
+#define MT6392_VCORE_CON7 0x030E
+#define MT6392_VCORE_CON8 0x0310
+#define MT6392_VCORE_CON9 0x0312
+#define MT6392_VCORE_CON10 0x0314
+#define MT6392_VCORE_CON11 0x0316
+#define MT6392_VCORE_CON12 0x0318
+#define MT6392_VCORE_CON13 0x031A
+#define MT6392_VCORE_CON14 0x031C
+#define MT6392_VCORE_CON15 0x031E
+#define MT6392_VCORE_CON18 0x0324
+#define MT6392_BUCK_K_CON0 0x032A
+#define MT6392_BUCK_K_CON1 0x032C
+#define MT6392_BUCK_K_CON2 0x032E
+#define MT6392_ANALDO_CON0 0x0400
+#define MT6392_ANALDO_CON1 0x0402
+#define MT6392_ANALDO_CON2 0x0404
+#define MT6392_ANALDO_CON3 0x0406
+#define MT6392_ANALDO_CON4 0x0408
+#define MT6392_ANALDO_CON6 0x040C
+#define MT6392_ANALDO_CON7 0x040E
+#define MT6392_ANALDO_CON8 0x0410
+#define MT6392_ANALDO_CON10 0x0412
+#define MT6392_ANALDO_CON15 0x0414
+#define MT6392_ANALDO_CON16 0x0416
+#define MT6392_ANALDO_CON17 0x0418
+#define MT6392_ANALDO_CON21 0x0420
+#define MT6392_ANALDO_CON22 0x0422
+#define MT6392_ANALDO_CON23 0x0424
+#define MT6392_ANALDO_CON24 0x0426
+#define MT6392_ANALDO_CON25 0x0428
+#define MT6392_ANALDO_CON26 0x042A
+#define MT6392_ANALDO_CON27 0x042C
+#define MT6392_ANALDO_CON28 0x042E
+#define MT6392_ANALDO_CON29 0x0430
+#define MT6392_DIGLDO_CON0 0x0500
+#define MT6392_DIGLDO_CON2 0x0502
+#define MT6392_DIGLDO_CON3 0x0504
+#define MT6392_DIGLDO_CON5 0x0506
+#define MT6392_DIGLDO_CON6 0x0508
+#define MT6392_DIGLDO_CON7 0x050A
+#define MT6392_DIGLDO_CON8 0x050C
+#define MT6392_DIGLDO_CON10 0x0510
+#define MT6392_DIGLDO_CON11 0x0512
+#define MT6392_DIGLDO_CON12 0x0514
+#define MT6392_DIGLDO_CON15 0x051A
+#define MT6392_DIGLDO_CON20 0x0524
+#define MT6392_DIGLDO_CON21 0x0526
+#define MT6392_DIGLDO_CON23 0x0528
+#define MT6392_DIGLDO_CON24 0x052A
+#define MT6392_DIGLDO_CON26 0x052C
+#define MT6392_DIGLDO_CON27 0x052E
+#define MT6392_DIGLDO_CON28 0x0530
+#define MT6392_DIGLDO_CON29 0x0532
+#define MT6392_DIGLDO_CON30 0x0534
+#define MT6392_DIGLDO_CON31 0x0536
+#define MT6392_DIGLDO_CON32 0x0538
+#define MT6392_DIGLDO_CON33 0x053A
+#define MT6392_DIGLDO_CON36 0x0540
+#define MT6392_DIGLDO_CON41 0x0546
+#define MT6392_DIGLDO_CON44 0x054C
+#define MT6392_DIGLDO_CON47 0x0552
+#define MT6392_DIGLDO_CON48 0x0554
+#define MT6392_DIGLDO_CON49 0x0556
+#define MT6392_DIGLDO_CON50 0x0558
+#define MT6392_DIGLDO_CON51 0x055A
+#define MT6392_DIGLDO_CON52 0x055C
+#define MT6392_DIGLDO_CON53 0x055E
+#define MT6392_DIGLDO_CON54 0x0560
+#define MT6392_DIGLDO_CON55 0x0562
+#define MT6392_DIGLDO_CON56 0x0564
+#define MT6392_DIGLDO_CON57 0x0566
+#define MT6392_DIGLDO_CON58 0x0568
+#define MT6392_DIGLDO_CON59 0x056A
+#define MT6392_DIGLDO_CON60 0x056C
+#define MT6392_DIGLDO_CON61 0x056E
+#define MT6392_DIGLDO_CON62 0x0570
+#define MT6392_DIGLDO_CON63 0x0572
+#define MT6392_EFUSE_CON0 0x0600
+#define MT6392_EFUSE_CON1 0x0602
+#define MT6392_EFUSE_CON2 0x0604
+#define MT6392_EFUSE_CON3 0x0606
+#define MT6392_EFUSE_CON4 0x0608
+#define MT6392_EFUSE_CON5 0x060A
+#define MT6392_EFUSE_CON6 0x060C
+#define MT6392_EFUSE_VAL_0_15 0x060E
+#define MT6392_EFUSE_VAL_16_31 0x0610
+#define MT6392_EFUSE_VAL_32_47 0x0612
+#define MT6392_EFUSE_VAL_48_63 0x0614
+#define MT6392_EFUSE_VAL_64_79 0x0616
+#define MT6392_EFUSE_VAL_80_95 0x0618
+#define MT6392_EFUSE_VAL_96_111 0x061A
+#define MT6392_EFUSE_VAL_112_127 0x061C
+#define MT6392_EFUSE_VAL_128_143 0x061E
+#define MT6392_EFUSE_VAL_144_159 0x0620
+#define MT6392_EFUSE_VAL_160_175 0x0622
+#define MT6392_EFUSE_VAL_176_191 0x0624
+#define MT6392_EFUSE_VAL_192_207 0x0626
+#define MT6392_EFUSE_VAL_208_223 0x0628
+#define MT6392_EFUSE_VAL_224_239 0x062A
+#define MT6392_EFUSE_VAL_240_255 0x062C
+#define MT6392_EFUSE_VAL_256_271 0x062E
+#define MT6392_EFUSE_VAL_272_287 0x0630
+#define MT6392_EFUSE_VAL_288_303 0x0632
+#define MT6392_EFUSE_VAL_304_319 0x0634
+#define MT6392_EFUSE_VAL_320_335 0x0636
+#define MT6392_EFUSE_VAL_336_351 0x0638
+#define MT6392_EFUSE_VAL_352_367 0x063A
+#define MT6392_EFUSE_VAL_368_383 0x063C
+#define MT6392_EFUSE_VAL_384_399 0x063E
+#define MT6392_EFUSE_VAL_400_415 0x0640
+#define MT6392_EFUSE_VAL_416_431 0x0642
+#define MT6392_RTC_MIX_CON0 0x0644
+#define MT6392_RTC_MIX_CON1 0x0646
+#define MT6392_EFUSE_VAL_432_447 0x0648
+#define MT6392_EFUSE_VAL_448_463 0x064A
+#define MT6392_EFUSE_VAL_464_479 0x064C
+#define MT6392_EFUSE_VAL_480_495 0x064E
+#define MT6392_EFUSE_VAL_496_511 0x0650
+#define MT6392_EFUSE_DOUT_0_15 0x0652
+#define MT6392_EFUSE_DOUT_16_31 0x0654
+#define MT6392_EFUSE_DOUT_32_47 0x0656
+#define MT6392_EFUSE_DOUT_48_63 0x0658
+#define MT6392_EFUSE_DOUT_64_79 0x065A
+#define MT6392_EFUSE_DOUT_80_95 0x065C
+#define MT6392_EFUSE_DOUT_96_111 0x065E
+#define MT6392_EFUSE_DOUT_112_127 0x0660
+#define MT6392_EFUSE_DOUT_128_143 0x0662
+#define MT6392_EFUSE_DOUT_144_159 0x0664
+#define MT6392_EFUSE_DOUT_160_175 0x0666
+#define MT6392_EFUSE_DOUT_176_191 0x0668
+#define MT6392_EFUSE_DOUT_192_207 0x066A
+#define MT6392_EFUSE_DOUT_208_223 0x066C
+#define MT6392_EFUSE_DOUT_224_239 0x066E
+#define MT6392_EFUSE_DOUT_240_255 0x0670
+#define MT6392_EFUSE_DOUT_256_271 0x0672
+#define MT6392_EFUSE_DOUT_272_287 0x0674
+#define MT6392_EFUSE_DOUT_288_303 0x0676
+#define MT6392_EFUSE_DOUT_304_319 0x0678
+#define MT6392_EFUSE_DOUT_320_335 0x067A
+#define MT6392_EFUSE_DOUT_336_351 0x067C
+#define MT6392_EFUSE_DOUT_352_367 0x067E
+#define MT6392_EFUSE_DOUT_368_383 0x0680
+#define MT6392_EFUSE_DOUT_384_399 0x0682
+#define MT6392_EFUSE_DOUT_400_415 0x0684
+#define MT6392_EFUSE_DOUT_416_431 0x0686
+#define MT6392_EFUSE_DOUT_432_447 0x0688
+#define MT6392_EFUSE_DOUT_448_463 0x068A
+#define MT6392_EFUSE_DOUT_464_479 0x068C
+#define MT6392_EFUSE_DOUT_480_495 0x068E
+#define MT6392_EFUSE_DOUT_496_511 0x0690
+#define MT6392_EFUSE_CON7 0x0692
+#define MT6392_EFUSE_CON8 0x0694
+#define MT6392_EFUSE_CON9 0x0696
+#define MT6392_AUXADC_ADC0 0x0700
+#define MT6392_AUXADC_ADC1 0x0702
+#define MT6392_AUXADC_ADC2 0x0704
+#define MT6392_AUXADC_ADC3 0x0706
+#define MT6392_AUXADC_ADC4 0x0708
+#define MT6392_AUXADC_ADC5 0x070A
+#define MT6392_AUXADC_ADC6 0x070C
+#define MT6392_AUXADC_ADC7 0x070E
+#define MT6392_AUXADC_ADC8 0x0710
+#define MT6392_AUXADC_ADC9 0x0712
+#define MT6392_AUXADC_ADC10 0x0714
+#define MT6392_AUXADC_ADC11 0x0716
+#define MT6392_AUXADC_ADC12 0x0718
+#define MT6392_AUXADC_ADC13 0x071A
+#define MT6392_AUXADC_ADC14 0x071C
+#define MT6392_AUXADC_ADC15 0x071E
+#define MT6392_AUXADC_ADC16 0x0720
+#define MT6392_AUXADC_ADC17 0x0722
+#define MT6392_AUXADC_ADC18 0x0724
+#define MT6392_AUXADC_ADC19 0x0726
+#define MT6392_AUXADC_ADC20 0x0728
+#define MT6392_AUXADC_ADC21 0x072A
+#define MT6392_AUXADC_ADC22 0x072C
+#define MT6392_AUXADC_STA0 0x072E
+#define MT6392_AUXADC_STA1 0x0730
+#define MT6392_AUXADC_RQST0 0x0732
+#define MT6392_AUXADC_RQST0_SET 0x0734
+#define MT6392_AUXADC_RQST0_CLR 0x0736
+#define MT6392_AUXADC_CON0 0x0738
+#define MT6392_AUXADC_CON0_SET 0x073A
+#define MT6392_AUXADC_CON0_CLR 0x073C
+#define MT6392_AUXADC_CON1 0x073E
+#define MT6392_AUXADC_CON2 0x0740
+#define MT6392_AUXADC_CON3 0x0742
+#define MT6392_AUXADC_CON4 0x0744
+#define MT6392_AUXADC_CON5 0x0746
+#define MT6392_AUXADC_CON6 0x0748
+#define MT6392_AUXADC_CON7 0x074A
+#define MT6392_AUXADC_CON8 0x074C
+#define MT6392_AUXADC_CON9 0x074E
+#define MT6392_AUXADC_CON10 0x0750
+#define MT6392_AUXADC_CON11 0x0752
+#define MT6392_AUXADC_CON12 0x0754
+#define MT6392_AUXADC_CON13 0x0756
+#define MT6392_AUXADC_CON14 0x0758
+#define MT6392_AUXADC_CON15 0x075A
+#define MT6392_AUXADC_CON16 0x075C
+#define MT6392_AUXADC_AUTORPT0 0x075E
+#define MT6392_AUXADC_LBAT0 0x0760
+#define MT6392_AUXADC_LBAT1 0x0762
+#define MT6392_AUXADC_LBAT2 0x0764
+#define MT6392_AUXADC_LBAT3 0x0766
+#define MT6392_AUXADC_LBAT4 0x0768
+#define MT6392_AUXADC_LBAT5 0x076A
+#define MT6392_AUXADC_LBAT6 0x076C
+#define MT6392_AUXADC_THR0 0x076E
+#define MT6392_AUXADC_THR1 0x0770
+#define MT6392_AUXADC_THR2 0x0772
+#define MT6392_AUXADC_THR3 0x0774
+#define MT6392_AUXADC_THR4 0x0776
+#define MT6392_AUXADC_THR5 0x0778
+#define MT6392_AUXADC_THR6 0x077A
+#define MT6392_AUXADC_EFUSE0 0x077C
+#define MT6392_AUXADC_EFUSE1 0x077E
+#define MT6392_AUXADC_EFUSE2 0x0780
+#define MT6392_AUXADC_EFUSE3 0x0782
+#define MT6392_AUXADC_EFUSE4 0x0784
+#define MT6392_AUXADC_EFUSE5 0x0786
+#define MT6392_AUXADC_NAG_0 0x0788
+#define MT6392_AUXADC_NAG_1 0x078A
+#define MT6392_AUXADC_NAG_2 0x078C
+#define MT6392_AUXADC_NAG_3 0x078E
+#define MT6392_AUXADC_NAG_4 0x0790
+#define MT6392_AUXADC_NAG_5 0x0792
+#define MT6392_AUXADC_NAG_6 0x0794
+#define MT6392_AUXADC_NAG_7 0x0796
+#define MT6392_AUXADC_NAG_8 0x0798
+#define MT6392_AUXADC_TYPEC_H_1 0x079A
+#define MT6392_AUXADC_TYPEC_H_2 0x079C
+#define MT6392_AUXADC_TYPEC_H_3 0x079E
+#define MT6392_AUXADC_TYPEC_H_4 0x07A0
+#define MT6392_AUXADC_TYPEC_H_5 0x07A2
+#define MT6392_AUXADC_TYPEC_H_6 0x07A4
+#define MT6392_AUXADC_TYPEC_H_7 0x07A6
+#define MT6392_AUXADC_TYPEC_L_1 0x07A8
+#define MT6392_AUXADC_TYPEC_L_2 0x07AA
+#define MT6392_AUXADC_TYPEC_L_3 0x07AC
+#define MT6392_AUXADC_TYPEC_L_4 0x07AE
+#define MT6392_AUXADC_TYPEC_L_5 0x07B0
+#define MT6392_AUXADC_TYPEC_L_6 0x07B2
+#define MT6392_AUXADC_TYPEC_L_7 0x07B4
+#define MT6392_AUXADC_NAG_9 0x07B6
+#define MT6392_TYPE_C_PHY_RG_0 0x0800
+#define MT6392_TYPE_C_PHY_RG_CC_RESERVE_CSR 0x0802
+#define MT6392_TYPE_C_VCMP_CTRL 0x0804
+#define MT6392_TYPE_C_CTRL 0x0806
+#define MT6392_TYPE_C_CC_SW_CTRL 0x080a
+#define MT6392_TYPE_C_CC_VOL_PERIODIC_MEAS_VAL 0x080c
+#define MT6392_TYPE_C_CC_VOL_DEBOUNCE_CNT_VAL 0x080e
+#define MT6392_TYPE_C_DRP_SRC_CNT_VAL_0 0x0810
+#define MT6392_TYPE_C_DRP_SNK_CNT_VAL_0 0x0814
+#define MT6392_TYPE_C_DRP_TRY_CNT_VAL_0 0x0818
+#define MT6392_TYPE_C_CC_SRC_DEFAULT_DAC_VAL 0x0820
+#define MT6392_TYPE_C_CC_SRC_15_DAC_VAL 0x0822
+#define MT6392_TYPE_C_CC_SRC_30_DAC_VAL 0x0824
+#define MT6392_TYPE_C_CC_SNK_DAC_VAL_0 0x0828
+#define MT6392_TYPE_C_CC_SNK_DAC_VAL_1 0x082a
+#define MT6392_TYPE_C_INTR_EN_0 0x0830
+#define MT6392_TYPE_C_INTR_EN_2 0x0834
+#define MT6392_TYPE_C_INTR_0 0x0838
+#define MT6392_TYPE_C_INTR_2 0x083C
+#define MT6392_TYPE_C_CC_STATUS 0x0840
+#define MT6392_TYPE_C_PWR_STATUS 0x0842
+#define MT6392_TYPE_C_PHY_RG_CC1_RESISTENCE_0 0x0844
+#define MT6392_TYPE_C_PHY_RG_CC1_RESISTENCE_1 0x0846
+#define MT6392_TYPE_C_PHY_RG_CC2_RESISTENCE_0 0x0848
+#define MT6392_TYPE_C_PHY_RG_CC2_RESISTENCE_1 0x084a
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_ENABLE_0 0x0860
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_0 0x0864
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_1 0x0866
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_ENABLE_1 0x0868
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_2 0x086c
+#define MT6392_TYPE_C_CC_DAC_CALI_CTRL 0x0870
+#define MT6392_TYPE_C_CC_DAC_CALI_RESULT 0x0872
+#define MT6392_TYPE_C_DEBUG_PORT_SELECT_0 0x0880
+#define MT6392_TYPE_C_DEBUG_PORT_SELECT_1 0x0882
+#define MT6392_TYPE_C_DEBUG_MODE_SELECT 0x0884
+#define MT6392_TYPE_C_DEBUG_OUT_READ_0 0x0888
+#define MT6392_TYPE_C_DEBUG_OUT_READ_1 0x088a
+#define MT6392_TYPE_C_SW_DEBUG_PORT_0 0x088c
+#define MT6392_TYPE_C_SW_DEBUG_PORT_1 0x088e
+
+#endif /* __MFD_MT6392_REGISTERS_H__ */
diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
index 340fc72e22aa..3729a6856c13 100644
--- a/include/linux/mfd/mt6397/core.h
+++ b/include/linux/mfd/mt6397/core.h
@@ -20,6 +20,7 @@ enum chip_id {
MT6359_CHIP_ID = 0x59,
MT6366_CHIP_ID = 0x66,
MT6391_CHIP_ID = 0x91,
+ MT6392_CHIP_ID = 0x92,
MT6397_CHIP_ID = 0x97,
};
--
2.43.0
^ permalink raw reply related
* [PATCH v6 3/7] mfd: mt6397: Use MFD_CELL_* to describe sub-devices
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Louis-Alexis Eyraud,
Julien Massot, Val Packett, Fabien Parent, Akari Tsuyukusa,
Chen Zhong, linux-input, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
Use the MFD_CELL_* macros to describe sub-devices. No functional changes.
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
drivers/mfd/mt6397-core.c | 197 ++++++++++++--------------------------
1 file changed, 63 insertions(+), 134 deletions(-)
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 1bdacda9a933..ccd97d66d7f1 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -124,159 +124,88 @@ static const struct resource mt6323_pwrc_resources[] = {
};
static const struct mfd_cell mt6323_devs[] = {
- {
- .name = "mt6323-rtc",
- .num_resources = ARRAY_SIZE(mt6323_rtc_resources),
- .resources = mt6323_rtc_resources,
- .of_compatible = "mediatek,mt6323-rtc",
- }, {
- .name = "mt6323-regulator",
- .of_compatible = "mediatek,mt6323-regulator"
- }, {
- .name = "mt6323-led",
- .of_compatible = "mediatek,mt6323-led"
- }, {
- .name = "mt6323-keys",
- .num_resources = ARRAY_SIZE(mt6323_keys_resources),
- .resources = mt6323_keys_resources,
- .of_compatible = "mediatek,mt6323-keys"
- }, {
- .name = "mt6323-pwrc",
- .num_resources = ARRAY_SIZE(mt6323_pwrc_resources),
- .resources = mt6323_pwrc_resources,
- .of_compatible = "mediatek,mt6323-pwrc"
- },
+ MFD_CELL_OF("mt6323-rtc", mt6323_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6323-rtc"),
+ MFD_CELL_OF("mt6323-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6323-regulator"),
+ MFD_CELL_OF("mt6323-led", NULL, NULL, 0, 0,
+ "mediatek,mt6323-led"),
+ MFD_CELL_OF("mt6323-keys", mt6323_keys_resources, NULL, 0, 0,
+ "mediatek,mt6323-keys"),
+ MFD_CELL_OF("mt6323-pwrc", mt6323_pwrc_resources, NULL, 0, 0,
+ "mediatek,mt6323-pwrc"),
};
static const struct mfd_cell mt6328_devs[] = {
- {
- .name = "mt6328-regulator",
- .of_compatible = "mediatek,mt6328-regulator"
- }, {
- .name = "mt6328-keys",
- .num_resources = ARRAY_SIZE(mt6328_keys_resources),
- .resources = mt6328_keys_resources,
- .of_compatible = "mediatek,mt6328-keys"
- },
+ MFD_CELL_OF("mt6328-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6328-regulator"),
+ MFD_CELL_OF("mt6328-keys", mt6328_keys_resources, NULL, 0, 0,
+ "mediatek,mt6328-keys"),
};
static const struct mfd_cell mt6357_devs[] = {
- {
- .name = "mt6359-auxadc",
- .of_compatible = "mediatek,mt6357-auxadc"
- }, {
- .name = "mt6357-regulator",
- }, {
- .name = "mt6357-rtc",
- .num_resources = ARRAY_SIZE(mt6357_rtc_resources),
- .resources = mt6357_rtc_resources,
- .of_compatible = "mediatek,mt6357-rtc",
- }, {
- .name = "mt6357-sound",
- .of_compatible = "mediatek,mt6357-sound"
- }, {
- .name = "mt6357-keys",
- .num_resources = ARRAY_SIZE(mt6357_keys_resources),
- .resources = mt6357_keys_resources,
- .of_compatible = "mediatek,mt6357-keys"
- },
+ MFD_CELL_OF("mt6359-auxadc", NULL, NULL, 0, 0,
+ "mediatek,mt6357-auxadc"),
+ MFD_CELL_NAME("mt6357-regulator"),
+ MFD_CELL_OF("mt6357-rtc", mt6357_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6357-rtc"),
+ MFD_CELL_OF("mt6357-sound", NULL, NULL, 0, 0,
+ "mediatek,mt6357-sound"),
+ MFD_CELL_OF("mt6357-keys", mt6357_keys_resources, NULL, 0, 0,
+ "mediatek,mt6357-keys"),
};
/* MT6331 is always used in combination with MT6332 */
static const struct mfd_cell mt6331_mt6332_devs[] = {
- {
- .name = "mt6331-rtc",
- .num_resources = ARRAY_SIZE(mt6331_rtc_resources),
- .resources = mt6331_rtc_resources,
- .of_compatible = "mediatek,mt6331-rtc",
- }, {
- .name = "mt6331-regulator",
- .of_compatible = "mediatek,mt6331-regulator"
- }, {
- .name = "mt6332-regulator",
- .of_compatible = "mediatek,mt6332-regulator"
- }, {
- .name = "mt6331-keys",
- .num_resources = ARRAY_SIZE(mt6331_keys_resources),
- .resources = mt6331_keys_resources,
- .of_compatible = "mediatek,mt6331-keys"
- },
+ MFD_CELL_OF("mt6331-rtc", mt6331_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6331-rtc"),
+ MFD_CELL_OF("mt6331-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6331-regulator"),
+ MFD_CELL_OF("mt6332-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6332-regulator"),
+ MFD_CELL_OF("mt6331-keys", mt6331_keys_resources, NULL, 0, 0,
+ "mediatek,mt6331-keys"),
};
static const struct mfd_cell mt6358_devs[] = {
- {
- .name = "mt6359-auxadc",
- .of_compatible = "mediatek,mt6358-auxadc"
- }, {
- .name = "mt6358-regulator",
- .of_compatible = "mediatek,mt6358-regulator"
- }, {
- .name = "mt6358-rtc",
- .num_resources = ARRAY_SIZE(mt6358_rtc_resources),
- .resources = mt6358_rtc_resources,
- .of_compatible = "mediatek,mt6358-rtc",
- }, {
- .name = "mt6358-sound",
- .of_compatible = "mediatek,mt6358-sound"
- }, {
- .name = "mt6358-keys",
- .num_resources = ARRAY_SIZE(mt6358_keys_resources),
- .resources = mt6358_keys_resources,
- .of_compatible = "mediatek,mt6358-keys"
- },
+ MFD_CELL_OF("mt6359-auxadc", NULL, NULL, 0, 0,
+ "mediatek,mt6358-auxadc"),
+ MFD_CELL_OF("mt6358-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6358-regulator"),
+ MFD_CELL_OF("mt6358-rtc", mt6358_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6358-rtc"),
+ MFD_CELL_OF("mt6358-sound", NULL, NULL, 0, 0,
+ "mediatek,mt6358-sound"),
+ MFD_CELL_OF("mt6358-keys", mt6358_keys_resources, NULL, 0, 0,
+ "mediatek,mt6358-keys"),
};
static const struct mfd_cell mt6359_devs[] = {
- {
- .name = "mt6359-auxadc",
- .of_compatible = "mediatek,mt6359-auxadc"
- },
- { .name = "mt6359-regulator", },
- {
- .name = "mt6359-rtc",
- .num_resources = ARRAY_SIZE(mt6358_rtc_resources),
- .resources = mt6358_rtc_resources,
- .of_compatible = "mediatek,mt6358-rtc",
- },
- { .name = "mt6359-sound", },
- {
- .name = "mt6359-keys",
- .num_resources = ARRAY_SIZE(mt6359_keys_resources),
- .resources = mt6359_keys_resources,
- .of_compatible = "mediatek,mt6359-keys"
- },
- {
- .name = "mt6359-accdet",
- .of_compatible = "mediatek,mt6359-accdet",
- .num_resources = ARRAY_SIZE(mt6359_accdet_resources),
- .resources = mt6359_accdet_resources,
- },
+ MFD_CELL_OF("mt6359-auxadc", NULL, NULL, 0, 0,
+ "mediatek,mt6359-auxadc"),
+ MFD_CELL_NAME("mt6359-regulator"),
+ MFD_CELL_OF("mt6359-rtc", mt6358_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6358-rtc"),
+ MFD_CELL_NAME("mt6359-sound"),
+ MFD_CELL_OF("mt6359-keys", mt6359_keys_resources, NULL, 0, 0,
+ "mediatek,mt6359-keys"),
+ MFD_CELL_OF("mt6359-accdet", mt6359_accdet_resources, NULL, 0, 0,
+ "mediatek,mt6359-accdet"),
};
static const struct mfd_cell mt6397_devs[] = {
- {
- .name = "mt6397-rtc",
- .num_resources = ARRAY_SIZE(mt6397_rtc_resources),
- .resources = mt6397_rtc_resources,
- .of_compatible = "mediatek,mt6397-rtc",
- }, {
- .name = "mt6397-regulator",
- .of_compatible = "mediatek,mt6397-regulator",
- }, {
- .name = "mt6397-codec",
- .of_compatible = "mediatek,mt6397-codec",
- }, {
- .name = "mt6397-clk",
- .of_compatible = "mediatek,mt6397-clk",
- }, {
- .name = "mt6397-pinctrl",
- .of_compatible = "mediatek,mt6397-pinctrl",
- }, {
- .name = "mt6397-keys",
- .num_resources = ARRAY_SIZE(mt6397_keys_resources),
- .resources = mt6397_keys_resources,
- .of_compatible = "mediatek,mt6397-keys"
- }
+ MFD_CELL_OF("mt6397-rtc", mt6397_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6397-rtc"),
+ MFD_CELL_OF("mt6397-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6397-regulator"),
+ MFD_CELL_OF("mt6397-codec", NULL, NULL, 0, 0,
+ "mediatek,mt6397-codec"),
+ MFD_CELL_OF("mt6397-clk", NULL, NULL, 0, 0,
+ "mediatek,mt6397-clk"),
+ MFD_CELL_OF("mt6397-pinctrl", NULL, NULL, 0, 0,
+ "mediatek,mt6397-pinctrl"),
+ MFD_CELL_OF("mt6397-keys", mt6397_keys_resources, NULL, 0, 0,
+ "mediatek,mt6397-keys"),
};
struct chip_data {
--
2.43.0
^ permalink raw reply related
* [PATCH v6 2/7] dt-bindings: input: mtk-pmic-keys: Add MT6392 PMIC keys
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
AngeloGioacchino Del Regno, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger, Linus Walleij,
Louis-Alexis Eyraud, Julien Massot, Akari Tsuyukusa, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
Add the binding documentation of mtk-pmic-keys for the MT6392 PMIC.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
---
Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
index 140a862ecfbe..ff720588128b 100644
--- a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
+++ b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
@@ -31,6 +31,7 @@ properties:
- mediatek,mt6357-keys
- mediatek,mt6358-keys
- mediatek,mt6359-keys
+ - mediatek,mt6392-keys
- mediatek,mt6397-keys
- items:
- enum:
--
2.43.0
^ permalink raw reply related
* [PATCH v6 1/7] dt-bindings: mfd: mt6397: Add MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Julien Massot,
Louis-Alexis Eyraud, Akari Tsuyukusa, Chen Zhong, linux-input,
devicetree, linux-kernel, linux-pm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
Add the initial bindings for the MT6392 PMIC and its RTC device.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
.../devicetree/bindings/mfd/mediatek,mt6397.yaml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
index 3cbc0dc12c31..e39e81aa9924 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
@@ -40,6 +40,10 @@ properties:
- mediatek,mt6358
- mediatek,mt6359
- mediatek,mt6397
+ - items:
+ - enum:
+ - mediatek,mt6392
+ - const: mediatek,mt6323
- items:
- enum:
- mediatek,mt6366
@@ -72,6 +76,10 @@ properties:
- mediatek,mt6331-rtc
- mediatek,mt6358-rtc
- mediatek,mt6397-rtc
+ - items:
+ - enum:
+ - mediatek,mt6392-rtc
+ - const: mediatek,mt6323-rtc
- items:
- enum:
- mediatek,mt6359-rtc
--
2.43.0
^ permalink raw reply related
* [PATCH v6 0/7] Add support for MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Julien Massot,
Louis-Alexis Eyraud, Val Packett, Fabien Parent, Akari Tsuyukusa,
Chen Zhong, linux-input, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-gpio
The MediaTek MT6392 PMIC is usually found on devices powered by
the MT8516/MT8167 SoC and is yet another MT6323/MT6397 variant.
This series is mostly based around patches submitted a couple
years ago by Fabien Parent and not merged and from Val Packett's
submission from Jan 2025 that included extra cleanups, fixes, and a
new dtsi file similar to ones that exist for other PMICs. Some
comments weren't addressed and the series was ultimately not merged.
These patches only enable three functions: keys, pinctrl and RTC.
Regulators and speaker amp will follow later as I still need to further
improve those two, but getting the main PMIC in will make the series
easier to review.
I added a handful of device tree improvements to fix some dtbs_check
errors, added support for the pinctrl device and addressed the comments
from last year's reviews.
Please note that patch 0005 depends on patch 0004 as they both need the
registers.h file, but they belong to different driver areas. I'm not sure
if I'm supposed to squash them even if they belong to different driver
areas of if it's fine like this. Any advice is welcome.
The series has been tested on Xiaomi Mi Smart Clock X04G and on the
Lenovo Smart Clock 2.
Changes in v6:
- Dropped the regulators driver for the moment
- Explained the FCHR key name origin in the commit message
- Introduced the MFD_CELL_* macro in the sub-devices definitions.
A separate, independent commit introduced MFD_CELL_* to all the
subdevices in the mt6397-core.c file for consistency
- Replaced of_device_get_match_data with device_get_match_data
- Removed the mfd_match_data enum in favor of the preexisting
chip_id enum
- Adjusted the error message if the device is unsupported
Changes in v5 [5]:
- Double checked regulator driver with data sheet and Android sources.
The data sheet I have misses a lot of register descriptions, but
Android sources have been helpful to fill the gaps
- Reintroduced the required attribute for the regulator compatible
in the bindings
- Fixed the missing reference to the MT6392 schema
- Fixed casts/unused vars reported by kernel test robot
- Removed Reviewed-by tags from the regulator patches as they have been
modified in this version
Changes in v4 [4]:
- Dropped usage of the regulator compatible
- Fixed commit messages text to properly reference the target subsystem
- Added supply rails to the regulator
- Reworked the regulator schema and PMIC dtsi. Now all supplies are
documented and the schema no longer includes voltage information
- Removed redundant ldo- / buck- prefixes
- Renamed the pinfunc header to mediatek,mt6392-pinfunc.h
- Modified the MFD driver to use a simple identifier in the of_match
data properties
Changes in v3 [3]:
- Added pinctrl device
- Changed mt6397-rtc fallback to mt6323-rtc
- Added schema for regulators
- Fixed checkpatch issues
Changes in v2 [2]:
- Replaced explicit compatibles with fallbacks
Initial version: [1]
[1] https://lore.kernel.org/linux-mediatek/cover.1771865014.git.l.scorcia@gmail.com/
[2] https://lore.kernel.org/linux-mediatek/20260306120521.163654-1-l.scorcia@gmail.com/
[3] https://lore.kernel.org/linux-mediatek/20260317184507.523060-1-l.scorcia@gmail.com/
[4] https://lore.kernel.org/linux-mediatek/20260330083429.359819-1-l.scorcia@gmail.com/
[5] https://lore.kernel.org/linux-mediatek/20260420213529.1645560-1-l.scorcia@gmail.com/
Fabien Parent (3):
dt-bindings: mfd: mt6397: Add MT6392 PMIC
dt-bindings: input: mtk-pmic-keys: Add MT6392 PMIC keys
mfd: mt6397: Add support for MT6392 PMIC
Luca Leonardo Scorcia (2):
mfd: mt6397: Use MFD_CELL_* to describe sub-devices
pinctrl: mediatek: mt6397: Add MediaTek MT6392
Val Packett (2):
input: keyboard: mtk-pmic-keys: Add MT6392 support
arm64: dts: mediatek: Add MediaTek MT6392 PMIC dtsi
.../bindings/input/mediatek,pmic-keys.yaml | 1 +
.../bindings/mfd/mediatek,mt6397.yaml | 8 +
arch/arm64/boot/dts/mediatek/mt6392.dtsi | 41 ++
drivers/input/keyboard/mtk-pmic-keys.c | 17 +
drivers/mfd/mt6397-core.c | 294 +++++------
drivers/mfd/mt6397-irq.c | 8 +
drivers/pinctrl/mediatek/pinctrl-mt6397.c | 37 +-
drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h | 64 +++
include/linux/mfd/mt6392/core.h | 43 ++
include/linux/mfd/mt6392/registers.h | 488 ++++++++++++++++++
include/linux/mfd/mt6397/core.h | 1 +
11 files changed, 840 insertions(+), 162 deletions(-)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6392.dtsi
create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h
create mode 100644 include/linux/mfd/mt6392/core.h
create mode 100644 include/linux/mfd/mt6392/registers.h
--
2.43.0
^ permalink raw reply
* Re: [PATCH v1 phy-next 7/8] soc: fsl: guts: implement the RCW override procedure
From: Vladimir Oltean @ 2026-06-12 20:25 UTC (permalink / raw)
To: Conor Dooley
Cc: linux-phy, devicetree, linuxppc-dev, linux-arm-kernel,
Ioana Ciornei, Vinod Koul, Neil Armstrong, Tanjeff Moos,
Christophe Leroy (CS GROUP), Michael Walle, Shawn Guo, Frank Li,
linux-kernel, Krzysztof Kozlowski, Rob Herring
In-Reply-To: <20260612-twenty-diary-4aab5327f9c2@spud>
On Fri, Jun 12, 2026 at 04:44:30PM +0100, Conor Dooley wrote:
> On Thu, Jun 11, 2026 at 10:39:39PM +0300, Vladimir Oltean wrote:
> > From: Ioana Ciornei <ioana.ciornei@nxp.com>
> >
> > Add support for the RCW override procedure which enables runtime
> > reconfiguration of the protocol running on a SerDes lane. The procedure
> > is done through the DCFG DCSR space which now can be defined as the
> > second memory region of the guts DT node.
> > Support is added on the following SoCs: LS1046A, LS1088A, LS2088A.
> >
> > The procedure is exported to the "client" driver - the Lynx10G SerDes
> > PHY driver - through the following functions:
> > - fsl_guts_lane_init() used to notify the initial / boot time lane mode
> > running on a SerDes lane.
> > - fsl_guts_lane_validate() used to validate that changing the protocol
> > on a specific lane is supported.
> > - fsl_guts_lane_set_mode() which can be used to request the RCW
> > procedure be executed for a specific lane.
> >
> > Since the RCW override procedure is different depending on the SoC, the
> > private fsl_soc_data structure is updated with two new per SoC callbacks
> > (.serdes_get_rcw_override() and .serdes_init_rcwcr()) which get used
> > from the generic fsl_guts_lane_set_mode() function. These two callbacks
> > hide all the SoC specific register offsets, masks and values so that the
> > _set_mode() procedure is straightforward.
> >
> > Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
> > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > ---
> > Cc: Conor Dooley <conor@kernel.org>
> > Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
> > Cc: Rob Herring <robh@kernel.org>
> > Cc: devicetree@vger.kernel.org
>
> Wrong CC list for this specific patch?
No, it was intentional. Provided for context, so DT reviewers can check
that extra properties not defined in the schema aren't being used.
^ permalink raw reply
* Re: [PATCH v1 phy-next 6/8] dt-bindings: fsl: layerscape-dcfg: define DCFG_DCSR region
From: Vladimir Oltean @ 2026-06-12 20:23 UTC (permalink / raw)
To: Conor Dooley
Cc: linux-phy, devicetree, linuxppc-dev, linux-arm-kernel,
Ioana Ciornei, Vinod Koul, Neil Armstrong, Tanjeff Moos,
Christophe Leroy (CS GROUP), Michael Walle, Shawn Guo, Frank Li,
linux-kernel, Krzysztof Kozlowski, Rob Herring
In-Reply-To: <20260612-graveyard-hacked-c65d54a1ece8@spud>
On Fri, Jun 12, 2026 at 04:44:00PM +0100, Conor Dooley wrote:
> On Thu, Jun 11, 2026 at 10:39:38PM +0300, Vladimir Oltean wrote:
> > In Layerscape (Arm) and QorIQ (PowerPC) devices, hardware peripherals
> > are accessed by the CPU through a portion of the SoC address space
> > called CCSR ("Configuration, Control, and Status Registers"). All
> > hardware IP blocks have their registers mapped here, and the Device
> > Configuration block makes no exception.
> >
> > However, there exists a secondary range of the address space named DCSR
> > ("Debug Control and Status Registers") which, like CCSR, also holds
> > registers of hardware IP blocks, except the DCSR contents is hidden in
> > all public reference manuals.
> >
> > The intention of the CCSR/DCSR split, to the best of my knowledge, was
> > to place the functionality that is too low level for normal use, and
> > which is necessary only for debug, in a completely separate address
> > space which can be hidden.
> >
> > A use case has appeared where networking SerDes lanes need to be
> > reconfigured at runtime for a different protocol (example: 10GBase-R to
> > SGMII), and the architecture of the SoCs does not normally permit that.
> > The Reset Configuration Word (RCW) is a data structure read by the SoC
> > preboot loader (PBL) which contains stuff like pinmuxing and SerDes
> > protocol mapping for each lane.
> >
> > The RCW that the PBL has loaded is visible in the DCFG block's normal
> > status registers (from CCSR), as read only. Turns out, the RCW is also
> > mapped in the DCFG's shadow register map (in DCSR), in a write-only
> > form. Writing to the RCW registers from the DCFG's DCSR space to change
> > what the PBL has loaded is called "RCW override".
> >
> > It has been validated that the RCW override procedure is necessary to
> > reconfigure the networking data path when a SerDes lane performs a major
> > protocol change. It changes some internal muxes which connect the PCS to
> > either the 10G MAC or to the 1G MAC.
> >
> > Defining the DCSR area of the DCFG as a secondary 'reg' array element
> > allows operating systems to perform RCW overrides. Since it is
> > introduced late in the binding's lifetime, it is optional. It can be
> > identified by name, but also by index (first 'reg' is CCSR).
> >
> > Note that while all SoCs should have a DCFG register block in DCSR, we
> > only need to expose it for the SoCs where the RCW override procedure is
> > known to be needed and has been validated.
> >
> > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > ---
> > Cc: Conor Dooley <conor@kernel.org>
>
> Where did this email come from btw? get_maintainer.pl result should have
> +dt in it.
Historical data. I am keeping all sorts of commands (here git send-email)
in *.txt files and that's where I got the stale email addresses from.
Krzysztof's is also bouncing. Will fix for v2.
> Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
> pw-bot: not-applicable
Thanks for the review!
^ permalink raw reply
* Re: [PATCH v1 4/4] media: qcom: jpeg: Add Qualcomm JPEG V4L2 encoder
From: sashiko-bot @ 2026-06-12 20:23 UTC (permalink / raw)
To: Atanas Filipov; +Cc: devicetree, robh, conor+dt
In-Reply-To: <20260612194417.1737009-5-atanas.filipov@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 14 potential issue(s) to consider:
- [High] The hardware is programmed with a single DMA base address per plane, silently assuming the mapping is always contiguous, but the driver utilizes `VIDEOBUF2_DMA_SG`.
- [High] Active DMA buffers are unconditionally returned to userspace during stop or abort operations without halting the hardware, causing use-after-free and DMA memory corruption.
- [High] The IRQ handler accesses hardware registers without verifying the device's power state, triggering a fatal bus error upon receiving a spurious interrupt during runtime suspend.
- [High] Synchronizing capture buffers with `DMA_BIDIRECTIONAL` when they are mapped as `DMA_FROM_DEVICE` violates the DMA API rules.
- [High] The hardware DMA buffer size is programmed improperly, enabling writes past the allocation boundary.
- [High] The main device structure is allocated using devm_kzalloc but its lifetime is decoupled from the video_device file descriptors, resulting in a Use-After-Free upon device unbind.
- [High] Multiple self-deadlocks and mismatched lock ordering issues related to `dev_mutex` in V4L2 callbacks.
- [High] A race condition between the IRQ bottom half and a worker thread can erroneously halt a newly started hardware job.
- [High] Unconditional `schedule_work` during file release after cancellation barriers leads to a use-after-free of `ectx`.
- [Medium] The driver reports an overly large payload size for the encoded JPEG, leaking uninitialized buffer contents.
- [Medium] `V4L2_ENC_CMD_STOP` incorrectly flushes all pending buffers immediately instead of draining them.
- [Medium] Hardware teardown hangs due to incorrect `reinit_completion` ordering in `jpeg_deinit()`.
- [Medium] Failure to allocate the V4L2 control in `fop_jpeg_file_open` bypasses handler cleanup, leaking bucket memory.
- [Low] Unconditional assignment of `dev_pm_ops` structure without wrapper macros produces dead code when `CONFIG_PM` is disabled.
--
commit 1ef0c6ce9870449657c8ef931f50d481ec34b483
Author: Atanas Filipov <atanas.filipov@oss.qualcomm.com>
media: qcom: jpeg: Add Qualcomm JPEG V4L2 encoder
Add a Qualcomm JPEG encoder driver implemented on top of the
V4L2 mem2mem framework. The driver handles vb2 queue, formats, header,
interrupts, and runtime PM/ICC for SM8250, QCM6490, and SM8550.
> diff --git a/drivers/media/platform/qcom/jpeg/qcom_jenc_dev.c b/drivers/media/platform/qcom/jpeg/qcom_jenc_dev.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/media/platform/qcom/jpeg/qcom_jenc_dev.c
[ ... ]
> +static int qcom_jpeg_probe(struct platform_device *pdev)
> +{
> + const struct qcom_dev_resources *res;
> + struct qcom_jenc_dev *jenc;
> + int rc;
> +
> + jenc = devm_kzalloc(&pdev->dev, sizeof(*jenc), GFP_KERNEL);
[Severity: High]
Does allocating this structure with devm_kzalloc() decouple its lifetime
from the video_device file descriptors? Later in qcom_jpeg_v4l2_register(),
jenc->dev_mutex is used as the vdev->lock. When the device unbinds, devres
frees jenc, but userspace may still hold open file descriptors that keep
the video_device alive, leading to a use-after-free when ioctls try to take
the freed lock.
[ ... ]
> +static struct platform_driver qcom_jpeg_platform_driver = {
> + .probe = qcom_jpeg_probe,
> + .remove = qcom_jpeg_remove,
> + .driver = {
> + .name = QCOM_JPEG_ENC_NAME,
> + .of_match_table = qcom_jpeg_of_match,
> + .pm = &qcom_jpeg_pm_ops,
[Severity: Low]
Could this unconditional assignment produce dead code when CONFIG_PM is
disabled? Using the pm_ptr() wrapper macro here is usually recommended to
allow the compiler to remove unused power management structures.
> + },
> +};
> +
> +module_platform_driver(qcom_jpeg_platform_driver);
> diff --git a/drivers/media/platform/qcom/jpeg/qcom_jenc_ops.c b/drivers/media/platform/qcom/jpeg/qcom_jenc_ops.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/media/platform/qcom/jpeg/qcom_jenc_ops.c
[ ... ]
> +static int jpeg_deinit(struct qcom_jenc_dev *jenc)
> +{
> + const struct qcom_jpeg_reg_offs *offs = jenc->res->hw_offs;
> + unsigned long rtime;
> +
> + jpeg_wo_bits(jenc, offs->int_clr, JMSK_IRQ_STATUS_ALL_BITS, JPEG_SET_U32);
> + jpeg_rw_bits(jenc, offs->int_mask, JMSK_IRQ_STATUS_STOP_ACK, JPEG_SET_U32);
> +
> + jpeg_wo_bits(jenc, offs->hw_cmd, JMSK_CMD_HW_STOP, 1);
> +
> + reinit_completion(&jenc->stop_complete);
[Severity: Medium]
Is there a race condition here if the hardware stops extremely quickly?
The completion is re-initialized after the STOP command has been written,
so if the interrupt fires before reinit_completion(), the completion state
might be incorrectly cleared, causing a timeout.
> + rtime = wait_for_completion_timeout(&jenc->stop_complete,
[ ... ]
> +static int jpeg_store_fe_next(struct jenc_context *ectx, struct vb2_buffer *vb2)
> +{
> + struct qcom_jenc_queue *q = &ectx->bufq[TYPE2QID(vb2->type)];
> + struct qcom_jpeg_buff *buff = &q->buff[vb2->index];
> + u8 pln = 0;
> +
> + buff->plns[pln].sgt = vb2_dma_sg_plane_desc(vb2, pln);
> + if (!buff->plns[pln].sgt)
> + return -EINVAL;
> +
> + if (!buff->plns[pln].sgt->sgl)
> + return -EINVAL;
> +
> + buff->plns[pln].dma = sg_dma_address(buff->plns[pln].sgt->sgl);
[Severity: High]
Does this safely handle fragmented scatterlists? Since the queues are
configured to use vb2_dma_sg_memops, userspace might provide DMABUF or
USERPTR buffers mapped into multiple non-contiguous IOVA segments. Just
extracting the first segment's IOVA without checking contiguousness
(sg_nents == 1) might cause the hardware to write past the first segment into
unmapped memory.
> + if (!buff->plns[pln].dma)
> + return -EINVAL;
[ ... ]
> +static int jpeg_apply_we_addr(struct jenc_context *ectx, struct qcom_jenc_queue *q,
> + struct vb2_buffer *vb)
> +{
> + struct qcom_jenc_dev *jenc = ectx->jenc;
> + const struct qcom_jpeg_reg_offs *offs = jenc->res->hw_offs;
> + struct qcom_jpeg_buff *frame = &q->buff[vb->index];
> + void *mptr = vb2_plane_vaddr(vb, 0);
> + dma_addr_t dma = frame->plns[0].dma;
> + unsigned long flags;
> + int rc;
> + u8 pln = 0;
> +
> + if (WARN_ON_ONCE(!dma))
> + return -EPERM;
> +
> + if (WARN_ON_ONCE(!mptr))
> + return -EPERM;
> +
> + rc = jpeg_ensure_header_cache(ectx);
> + if (rc)
> + return rc;
> +
> + /*
> + * Under quality_mutex: force a DQT refresh if the header was just
> + * (re)created (quality_programmed == 0) or if quality changed since
> + * the last frame. Both the cache update and the HW DMI upload are
> + * done here so that hdr_cache and the hardware are always in sync
> + * before jpeg_exec() fires.
> + */
> + mutex_lock(&ectx->quality_mutex);
> + if (!ectx->hdr_cache.size || ectx->quality_programmed != ectx->quality_requested) {
> + jpeg_update_dqt_cache(ectx);
> + jpeg_upload_dmi_table(ectx);
> + }
> + mutex_unlock(&ectx->quality_mutex);
> +
> + /*
> + * Invalidate stale CPU cache lines before writing the JPEG header
> + * with the CPU into the destination buffer.
> + */
> + jpeg_sync_sg(jenc->dev, frame, DMA_BIDIRECTIONAL, false);
[Severity: High]
Does this violate the DMA API rules? The capture buffers are typically
mapped as DMA_FROM_DEVICE. Syncing them with DMA_BIDIRECTIONAL when the
mapped direction differs can trigger debug warnings or coherency issues.
> +
> + dma += qcom_jenc_header_emit(&ectx->hdr_cache, mptr,
> + min_t(size_t, vb->planes[0].length, ectx->hdr_cache.size),
> + q->vf.width, q->vf.height);
[Severity: High]
Can this advancement cause a DMA buffer overflow? The hardware limit (bsize)
is configured to the full sizeimage in jpeg_setup_we_size(). If the base
address is shifted forward by the header size here, the hardware will attempt
to write sizeimage bytes starting from this shifted address, running past the
end of the allocated buffer.
> + qcom_jenc_dqts_emit(&ectx->hdr_cache, mptr);
[ ... ]
> +static irqreturn_t op_jpeg_irq_bot(int irq, void *data)
> +{
> + struct qcom_jenc_dev *jenc = data;
> + const struct qcom_jpeg_reg_offs *offs = jenc->res->hw_offs;
> + u32 irq_status;
> + u32 irq_mask;
> + unsigned long flags;
> +
> + irq_status = READ_ONCE(jenc->pending_irq_status);
> +
> + irq_mask = jenc->res->hw_mask[JMSK_IRQ_STATUS_SESSION_DONE];
> + if (jpeg_bits_get(irq_mask, irq_status)) {
> + struct jenc_context *ctx = jenc->actx;
[Severity: High]
Is there a possibility that jenc->actx points to a freed context here?
Active buffers are forcefully removed and the context can be freed during
an abort (see jpeg_v4l2_work_stop and fop_jpeg_file_release) without halting
the hardware. When the interrupt eventually fires, this dereference could
result in a use-after-free.
> + struct qcom_jenc_queue *dq;
> + size_t out_size;
> +
> + spin_lock_irqsave(&jenc->hw_lock, flags);
> + jenc->actx = NULL;
> + spin_unlock_irqrestore(&jenc->hw_lock, flags);
> +
> + if (!ctx)
> + return IRQ_HANDLED;
> +
> + dq = &ctx->bufq[JENC_DST_QUEUE];
> + if (dq->buff_id >= 0) {
> + struct qcom_jpeg_buff *frame;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&jenc->hw_lock, flags);
> + frame = &dq->buff[dq->buff_id];
> + out_size = jpeg_io_read(jenc, offs->enc_out_size);
> + spin_unlock_irqrestore(&jenc->hw_lock, flags);
> +
> + dev_dbg(jenc->dev, "complete idx:%d addr=0x%llx size=%zu\n",
> + dq->buff_id, frame->plns[0].dma, out_size);
> +
> + jenc->enc_hw_irq_cb(ctx, VB2_BUF_STATE_DONE,
> + out_size + JPEG_HEADER_MAX);
[Severity: Medium]
Does adding the fixed JPEG_HEADER_MAX (1024) to out_size accurately reflect
the payload? The actual header emitted via qcom_jenc_header_emit() is
usually smaller. Reporting an inflated size can leak residual uninitialized
memory contents to userspace.
> + jpeg_stop(jenc);
[Severity: High]
Could this jpeg_stop() call inadvertently stop a completely new job?
The callback jenc->enc_hw_irq_cb() schedules work that can queue and start
the next job asynchronously. Because this jpeg_stop() is called after the
callback, it could end up cancelling the newly submitted hardware operation
instead of the current one.
> + }
> + }
> +
> + irq_mask = jenc->res->hw_mask[JMSK_IRQ_STATUS_SESSION_ERROR];
[ ... ]
> +static irqreturn_t op_jpeg_irq_top(int irq, void *data)
> +{
> + struct qcom_jenc_dev *jenc = data;
> + const struct qcom_jpeg_reg_offs *offs = jenc->res->hw_offs;
> + u32 irq_status;
> + u32 irq_mask;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&jenc->hw_lock, flags);
> +
> + irq_status = jpeg_io_read(jenc, offs->int_status);
[Severity: High]
Is it safe to unconditionally access hardware registers in the interrupt
handler? If a spurious interrupt arrives while the device is in runtime
suspend, its interconnects or clocks might be off, which could trigger a
synchronous external abort. A check using pm_runtime_get_if_active() is
usually required here before reading.
> + jpeg_wo_bits(jenc, offs->int_clr, JMSK_IRQ_STATUS_ALL_BITS, irq_status);
[ ... ]
> diff --git a/drivers/media/platform/qcom/jpeg/qcom_jenc_v4l2.c b/drivers/media/platform/qcom/jpeg/qcom_jenc_v4l2.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/media/platform/qcom/jpeg/qcom_jenc_v4l2.c
[ ... ]
> +static void jpeg_v4l2_work_stop(struct jenc_context *ctx, enum vb2_buffer_state buff_state)
> +{
> + struct vb2_v4l2_buffer *vb;
> +
> + while ((vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) {
> + if (!v4l2_m2m_last_dst_buf(ctx->fh.m2m_ctx)) {
> + if (ctx->is_stopping) {
> + ctx->is_stopping = false;
> + vb2_set_plane_payload(&vb->vb2_buf, 0, 0);
> + }
> + v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vb);
> + } else {
> + v4l2_m2m_buf_done(vb, buff_state);
> + }
> + }
> +
> + while ((vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
> + v4l2_m2m_buf_done(vb, buff_state);
[Severity: High]
Does draining these buffers while the hardware is potentially still active
lead to issues? During an abort or streamoff, active buffers are immediately
returned to userspace via v4l2_m2m_buf_done(), but the driver never issues a
STOP command to halt the hardware DMA. This can cause the hardware to write
to buffers that userspace considers free.
> +
> + schedule_work(&ctx->finish_work);
> +}
[ ... ]
> +static void bop_jpeg_vb2_stop_streaming(struct vb2_queue *q)
> +{
> + struct jenc_context *ectx = vb2_get_drv_priv(q);
> + struct qcom_jenc_dev *jenc = ectx->jenc;
> + const struct qcom_jpeg_hw_ops *hw = jenc->res->hw_ops;
> +
> + mutex_lock(&jenc->dev_mutex);
[Severity: High]
Can this cause a self-deadlock? The V4L2 core invokes the stop_streaming
callback while already holding the lock assigned to jenc->vdev->lock, which
in this driver is set to &jenc->dev_mutex. Attempting to acquire the same
mutex here will hang.
> +
> + jpeg_v4l2_work_stop(ectx, VB2_BUF_STATE_ERROR);
> +
> + hw->hw_release(ectx, q);
> +
> + mutex_unlock(&jenc->dev_mutex);
> +}
[ ... ]
> +static int iop_jpeg_encoder_command(struct file *file, void *priv, struct v4l2_encoder_cmd *ec)
> +{
> + struct jenc_context *ectx = jpeg_file2ctx(file);
> + struct vb2_queue *vq;
> + int rc;
> +
> + if (ec->cmd == V4L2_ENC_CMD_STOP) {
> + vq = v4l2_m2m_get_src_vq(ectx->fh.m2m_ctx);
> + if (!vb2_is_streaming(vq))
> + return 0;
> +
> + vq = v4l2_m2m_get_dst_vq(ectx->fh.m2m_ctx);
> + if (!vb2_is_streaming(vq))
> + return 0;
> +
> + rc = v4l2_m2m_ioctl_encoder_cmd(file, priv, ec);
> + if (rc)
> + return rc;
> +
> + ectx->is_stopping = true;
> + schedule_work(&ectx->stop_work);
[Severity: Medium]
Should the V4L2_ENC_CMD_STOP command allow currently queued source buffers
to finish encoding instead of immediately aborting them? The V4L2 spec states
that a stop command on an encoder should encode the remaining buffers and set
the LAST flag on the final capture buffer. Scheduling stop_work abruptly drops
all queued data.
> +
> + return 0;
> + }
> +
> + return v4l2_m2m_ioctl_encoder_cmd(file, priv, ec);
> +}
[ ... ]
> +static int jpeg_v4l2_init_queue(void *priv, struct vb2_queue *sq, struct vb2_queue *dq)
> +{
> + struct jenc_context *ectx = priv;
> + int rc;
> +
> + sq->drv_priv = ectx;
> + sq->dev = ectx->dev;
> + sq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
> + sq->io_modes = VB2_MMAP | VB2_DMABUF | VB2_USERPTR;
> + sq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
> + sq->ops = &qcom_jpeg_v4l2_vb2_ops;
> + sq->mem_ops = &vb2_dma_sg_memops;
[Severity: High]
Is it correct to use sg_memops instead of contig_memops? If the hardware
is programmed with a single DMA base address per plane, it likely expects a
contiguous physical memory range. Using sg_memops allows fragmented
scatterlists which the hardware won't be able to process linearly.
> + sq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
[ ... ]
> +static int fop_jpeg_file_open(struct file *file)
> +{
> + struct video_device *vdev = video_devdata(file);
> + struct qcom_jenc_dev *jenc = video_drvdata(file);
> + struct jenc_context *ectx;
> + int rc;
> +
> + ectx = kzalloc_obj(*ectx, GFP_KERNEL);
> + if (!ectx)
> + return -ENOMEM;
> +
> + ectx->dev = jenc->dev;
> + ectx->jenc = jenc;
[ ... ]
> + ectx->quality_ctl = v4l2_ctrl_new_std(&ectx->ctrl_hdl,
> + &qcom_jpeg_v4l2_ctrl_ops,
> + V4L2_CID_JPEG_COMPRESSION_QUALITY,
> + QCOM_JPEG_QUALITY_MIN,
> + QCOM_JPEG_QUALITY_MAX,
> + QCOM_JPEG_QUALITY_UNT,
> + QCOM_JPEG_QUALITY_DEF);
> + if (ectx->ctrl_hdl.error) {
> + rc = ectx->ctrl_hdl.error;
> + goto err_fh_exit;
[Severity: Medium]
Will jumping to err_fh_exit leak the V4L2 control handler memory? The
v4l2_ctrl_handler_free() call is placed at the err_ctrl_handler_free label,
which gets skipped entirely if we jump to err_fh_exit.
> + }
> +
> + ectx->fh.ctrl_handler = &ectx->ctrl_hdl;
> +
> + rc = v4l2_ctrl_handler_setup(&ectx->ctrl_hdl);
[ ... ]
> +static int fop_jpeg_file_release(struct file *file)
> +{
> + struct jenc_context *ectx = jpeg_file2ctx(file);
> + struct v4l2_m2m_dev *m2m_dev = ectx->fh.m2m_ctx->m2m_dev;
> +
> + cancel_work_sync(&ectx->stop_work);
> + cancel_work_sync(&ectx->finish_work);
> +
> + v4l2_m2m_ctx_release(ectx->fh.m2m_ctx);
[Severity: High]
Does v4l2_m2m_ctx_release() re-schedule finish_work after it was just
cancelled? Internally, it aborts jobs which invokes jpeg_v4l2_work_stop().
That function unconditionally calls schedule_work(&ctx->finish_work). Because
the cancellation barriers were executed first, the work item will run after
ectx is freed below, causing a use-after-free.
> + v4l2_m2m_put(m2m_dev);
> + v4l2_ctrl_handler_free(&ectx->ctrl_hdl);
> + v4l2_fh_del(&ectx->fh, file);
> + v4l2_fh_exit(&ectx->fh);
> + kfree(ectx);
> +
> + return 0;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612194417.1737009-1-atanas.filipov@oss.qualcomm.com?part=4
^ permalink raw reply
* Re: [PATCH v11 8/9] i3c: hub: p3h2x4x: Add support for NXP P3H2x4x I3C hub functionality
From: Frank Li @ 2026-06-12 20:14 UTC (permalink / raw)
To: sashiko-reviews
Cc: Lakshay Piplani, Frank.Li, linux-i3c, devicetree, conor+dt, robh
In-Reply-To: <20260612113948.F33BF1F000E9@smtp.kernel.org>
On Fri, Jun 12, 2026 at 11:39:48AM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 10 potential issue(s) to consider:
> - [High] Regulator devres cleanup actions are erroneously attached to the parent device instead of the child device being probed.
> - [High] SMBus I2C adapters are not unregistered on probe error paths, causing a Use-After-Free.
> - [High] In-Band Interrupt (IBI) remains requested and enabled on probe failure, causing a Use-After-Free.
> - [High] Unsafe reliance on non-deterministic delays without polling the SMBus finish flag causes premature data reads.
> - [High] The driver dynamically overwrites the shared platform device's `of_node` pointer, corrupting the core device tree state.
> - [High] `regmap_update_bits` uses the configuration value as the bitmask, failing to clear stale bits.
> - [High] DAA is performed on the upstream bus before the downstream target ports are physically enabled.
> - [Medium] Target port device tree node references acquired during probe are leaked on error paths.
> - [Medium] Default configuration structures are populated with enum values instead of Ohms, causing misconfiguration.
> - [Low] Dead code due to incorrect `IS_ERR` check on `devm_kzalloc` return value.
> --
>
> commit 8d18a29a52d0297c45635edaf397ce828e709ef9
> Author: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
>
> i3c: hub: p3h2x4x: Add support for NXP P3H2x4x I3C hub functionality
>
> Add I3C hub functionality for the NXP P3H2x4x family of multiport hubs.
> These devices support downstream target ports that can be configured
> as I3C, I2C, or SMBus.
>
> > diff --git a/drivers/i3c/hub/p3h2840_i3c_hub_common.c b/drivers/i3c/hub/p3h2840_i3c_hub_common.c
> > new file mode 100644
> > index 0000000000000..fedcb978f07ee
> > --- /dev/null
> > +++ b/drivers/i3c/hub/p3h2840_i3c_hub_common.c
>
> [ ... ]
>
> > +static int p3h2x4x_configure_ldo(struct device *dev)
> > +{
> > + static const char * const supplies[] = {
> > + "vcc1",
> > + "vcc2",
> > + "vcc3",
> > + "vcc4"
> > + };
> > + int ret, i;
> > +
> > + for (i = 0; i < ARRAY_SIZE(supplies); i++) {
> > + ret = devm_regulator_get_enable_optional(dev->parent, supplies[i]);
>
> [Severity: High]
> Could this leak devres memory on the parent device? By passing dev->parent
> (the MFD parent device) instead of dev (the child hub device), the regulator
> cleanup actions are attached to the parent. If the hub driver fails probe
> or is repeatedly bound/unbound, it looks like these regulators won't be
> disabled and the references will be leaked.
look like make sense, please check it.
>
> [ ... ]
>
> > +static int p3h2x4x_configure_tp(struct device *dev)
> > +{
> > + struct p3h2x4x_i3c_hub_dev *hub = dev_get_drvdata(dev);
> > + u8 mode = 0, smbus = 0, pullup = 0, target_port = 0;
> > + int tp, ret;
> > +
> > + for (tp = 0; tp < P3H2X4X_TP_MAX_COUNT; tp++) {
> > + pullup |= hub->hub_config.tp_config[tp].pullup_en ? P3H2X4X_SET_BIT(tp) : 0;
>
> [ ... ]
>
> > + ret = regmap_update_bits(hub->regmap, P3H2X4X_TP_PULLUP_EN, pullup, pullup);
>
> [Severity: High]
> Does this fail to clear stale bits? The third argument to regmap_update_bits()
> is the mask. By using 'pullup' as the mask, it seems this only applies
> operations to bits that are 1. Any bit that is 0 in 'pullup' is ignored,
> which might leave stale hardware state (like pullups enabled by the
> bootloader) unmodified. Should this use a proper mask covering all relevant
> bits?
Make sense, please check it.
>
> [ ... ]
>
> > +static void p3h2x4x_get_target_port_dt_conf(struct device *dev,
> > + const struct device_node *node)
> > +{
> > + struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = dev_get_drvdata(dev);
> > + u64 tp_port;
> > +
> > + for_each_available_child_of_node_scoped(node, dev_node) {
> > + if (of_property_read_reg(dev_node, 0, &tp_port, NULL))
> > + continue;
> > +
> > + if (tp_port < P3H2X4X_TP_MAX_COUNT) {
> > + p3h2x4x_i3c_hub->tp_bus[tp_port].of_node = of_node_get(dev_node);
>
> [Severity: Medium]
> Is there a resource leak here on probe error paths? This manually increments
> the reference count of the child nodes using of_node_get(). While
> p3h2x4x_i3c_hub_remove() correctly drops these references, if
> p3h2x4x_i3c_hub_probe() fails and returns an error, the remove callback
> isn't executed. Without a devm cleanup action, could these OF nodes leak
> memory?
>
> [ ... ]
>
> > +static void p3h2x4x_default_configuration(struct device *dev)
> > +{
> > + struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = dev_get_drvdata(dev);
> > + int tp_count;
> > +
> > + p3h2x4x_i3c_hub->hub_config.tp0145_pullup = P3H2X4X_TP_PULLUP_500R;
>
> [Severity: Medium]
> Are these default configuration values being set correctly? These fields
> appear to be designed to store physical Ohm measurements, but they are
> initialized to macros like P3H2X4X_TP_PULLUP_500R which evaluate to enum
> indices (e.g., 1). When the default value 1 is later processed by
> p3h2x4x_pullup_dt_to_reg() using find_closest(), it would resolve to the
> closest table entry 250 instead of the intended 500. Should these initialize
> with real-world units?
>
> [ ... ]
>
> > +static int p3h2x4x_i3c_hub_probe(struct platform_device *pdev)
> > +{
>
> [ ... ]
>
> > + /* Register virtual I2C adapters for SMBus target ports */
> > + ret = p3h2x4x_tp_smbus_algo(p3h2x4x_i3c_hub);
> > + if (ret)
> > + return dev_err_probe(dev, ret, "Failed to add i2c adapter\n");
> > +
> > + /* Lock access to protected registers */
> > + ret = regmap_write(p3h2x4x_i3c_hub->regmap, P3H2X4X_DEV_REG_PROTECTION_CODE,
> > + P3H2X4X_REGISTERS_LOCK_CODE);
> > + if (ret)
> > + return dev_err_probe(dev, ret, "Failed to lock HUB's protected registers\n");
>
> [Severity: High]
> Are the SMBus I2C adapters cleaned up if this final regmap_write() fails?
> p3h2x4x_tp_smbus_algo() registers adapters using i2c_add_adapter(), which
> requires an explicit i2c_del_adapter(). If the probe fails here, the adapters
> are never unregistered, which leaves the I2C core with active references to
> devm-freed memory. Could this cause a use-after-free?
>
> > +
> > + return 0;
> > +}
>
> > diff --git a/drivers/i3c/hub/p3h2840_i3c_hub_i3c.c b/drivers/i3c/hub/p3h2840_i3c_hub_i3c.c
> > new file mode 100644
> > index 0000000000000..38505dda0e81b
> > --- /dev/null
> > +++ b/drivers/i3c/hub/p3h2840_i3c_hub_i3c.c
>
> [ ... ]
>
> > +int p3h2x4x_tp_i3c_algo(struct p3h2x4x_i3c_hub_dev *p3h2x4x_hub)
> > +{
>
> [ ... ]
>
> > + p3h2x4x_hub->hub = devm_kzalloc(p3h2x4x_hub->dev,
> > + sizeof(*p3h2x4x_hub->hub),
> > + GFP_KERNEL);
> > +
> > + if (!p3h2x4x_hub->hub)
> > + return -ENOMEM;
> > +
> > + i3c_hub_init(p3h2x4x_hub->hub,
> > + &p3h2x4x_hub_ops,
> > + p3h2x4x_hub->i3cdev);
> > +
> > + if (IS_ERR(p3h2x4x_hub->hub))
> > + return PTR_ERR(p3h2x4x_hub->hub);
>
> [Severity: Low]
> Is this IS_ERR() check necessary? devm_kzalloc() returns either a valid
> pointer or NULL on failure, never an error pointer. It seems this block of
> code might be dead.
Make sense, please fix it
Frank
>
> [ ... ]
>
> > + for (tp = 0; tp < P3H2X4X_TP_MAX_COUNT; tp++) {
> > + if (!p3h2x4x_hub->tp_bus[tp].of_node ||
> > + p3h2x4x_hub->hub_config.tp_config[tp].mode != P3H2X4X_TP_MODE_I3C)
> > + continue;
> > +
> > + /* Assign DT node for this TP */
> > + p3h2x4x_hub->dev->of_node = p3h2x4x_hub->tp_bus[tp].of_node;
>
> [Severity: High]
> Can dynamically overwriting the platform device's of_node pointer corrupt the
> core device tree state? By changing p3h2x4x_hub->dev->of_node in a loop
> without saving and restoring the original, it looks like this permanently
> changes the node the device points to. Could this break device tree links,
> sysfs topologies, or devres lookups that rely on the original parent hub
> of_node?
>
> [ ... ]
>
> > + /* Perform DAA */
> > + ret = i3c_master_do_daa(parent);
> > + if (ret)
> > + return ret;
> > +
> > + ntwk_mask |= p3h2x4x_hub->tp_bus[tp].tp_mask;
> > + p3h2x4x_hub->tp_bus[tp].is_registered = true;
> > + p3h2x4x_hub->hub_config.tp_config[tp].always_enable = true;
> > + }
>
> [ ... ]
>
> > +#if IS_ENABLED(CONFIG_I2C_SLAVE)
> > + ret = i3c_device_request_ibi(p3h2x4x_hub->i3cdev, &p3h2x4x_ibireq);
> > + if (ret)
> > + return ret;
> > +
> > + ret = i3c_device_enable_ibi(p3h2x4x_hub->i3cdev);
>
> [Severity: High]
> If a subsequent step in p3h2x4x_i3c_hub_probe() fails, are the IBIs safely
> cleaned up? The devm framework would free the p3h2x4x_i3c_hub structure,
> but the IBI might remain active on the master. If an interrupt fires later
> and accesses the freed structure via i3cdev_get_drvdata(i3cdev), could this
> trigger a use-after-free?
>
> > + if (ret) {
> > + i3c_device_free_ibi(p3h2x4x_hub->i3cdev);
> > + return ret;
> > + }
> > +#endif
> > + ret = regmap_write(p3h2x4x_hub->regmap, P3H2X4X_TP_NET_CON_CONF, ntwk_mask);
>
> [Severity: High]
> Does performing DAA here actually reach the downstream targets? The DAA is
> executed earlier on the upstream bus inside the target port loop, but the
> downstream target ports don't appear to be logically connected to the upstream
> bus until ntwk_mask is written to P3H2X4X_TP_NET_CON_CONF at the end of the
> function. Will downstream targets receive the ENTDAA command if DAA is done
> before the physical ports are enabled?
>
> > diff --git a/drivers/i3c/hub/p3h2840_i3c_hub_smbus.c b/drivers/i3c/hub/p3h2840_i3c_hub_smbus.c
> > new file mode 100644
> > index 0000000000000..edb75f790e92e
> > --- /dev/null
> > +++ b/drivers/i3c/hub/p3h2840_i3c_hub_smbus.c
>
> [ ... ]
>
> > +static int p3h2x4x_read_smbus_transaction_status(struct p3h2x4x_i3c_hub_dev *hub,
> > + u8 target_port_status,
> > + u8 data_length)
> > +{
> > + u32 status_read;
> > + u8 status;
> > + int ret;
> > +
> > + fsleep(P3H2X4X_SMBUS_400kHz_TRANSFER_TIMEOUT(data_length));
> > +
> > + ret = regmap_read(hub->regmap, target_port_status, &status_read);
>
> [Severity: High]
> Could relying on a fixed timeout instead of polling the hardware finish flag
> cause the driver to read stale data? Because the top 4 bits of the status
> register are initialized to 0 before the transaction begins, they remain 0
> while the hardware is busy. If the transaction exceeds the timeout (e.g., due
> to clock stretching), status evaluates to 0
> (P3H2X4X_SMBUS_CNTRL_STATUS_TXN_OK). Should this code poll the
> P3H2X4X_SMBUS_TRANSACTION_FINISH_FLAG instead to ensure completion?
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260612111816.3688240-1-lakshay.piplani@nxp.com?part=8
^ permalink raw reply
* Re: [PATCH v1 2/4] arm64: dts: qcom: sm8550: Add JPEG encoder node
From: sashiko-bot @ 2026-06-12 20:06 UTC (permalink / raw)
To: Atanas Filipov; +Cc: devicetree, conor+dt, robh
In-Reply-To: <20260612194417.1737009-3-atanas.filipov@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Low] Unnecessary presence of the deprecated `cell-index` property in the newly added JPEG encoder node.
- [Low] The `interconnects` property uses the hardcoded magic number `0` for path tags instead of semantic macros.
- [Low] Device tree node `jpeg-encoder@ac4e000` is placed out of order based on its unit-address.
--
commit 7c79d5580891bdc3ade6113afec02f777f964fdb
Author: Atanas Filipov <atanas.filipov@oss.qualcomm.com>
arm64: dts: qcom: sm8550: Add JPEG encoder node
This patch adds the JPEG encoder hardware node to the SM8550 device tree.
It configures resources like clocks, power domains, IOMMUs, and interconnects
to allow the qcom-jpeg V4L2 encoder driver to bind and operate.
> diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi
> index 912525e9bca6f..8090b8b1d7bda 100644
> --- a/arch/arm64/boot/dts/qcom/sm8550.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi
[ ... ]
> @@ -3677,6 +3677,48 @@ port@7 {
> };
> };
>
> + qcom_jpeg_enc: jpeg-encoder@ac4e000 {
[Severity: Low]
Is this node placed out of order according to its unit-address?
Usually, nodes within the soc container are strictly sorted by their unit
address. Since this is at 0xac4e000, should it be placed before
isp@acb7000 rather than appended after it?
> + cell-index = <0>;
[Severity: Low]
Is the cell-index property still needed here?
The device tree binding typically describes this as a legacy hardware instance
index, and modern upstream drivers usually do not rely on it. Could we remove
it to align with modern device tree conventions?
> + compatible = "qcom,sm8550-jenc";
> +
> + reg = <0 0xac4e000 0 0x4000>;
[ ... ]
> + iommus = <&apps_smmu 0x20C0 0x20>,
> + <&apps_smmu 0x20E0 0x20>;
> +
> + interconnects = <&gem_noc MASTER_APPSS_PROC 0
> + &config_noc SLAVE_CAMERA_CFG 0>,
> + <&mmss_noc MASTER_CAMNOC_HF 0
> + &mc_virt SLAVE_EBI1 0>,
> + <&mmss_noc MASTER_CAMNOC_SF 0
> + &mc_virt SLAVE_EBI1 0>,
> + <&mmss_noc MASTER_CAMNOC_ICP 0
> + &mc_virt SLAVE_EBI1 0>;
[Severity: Low]
Would it be better to use the standard semantic macros for the interconnect
path tags instead of hardcoding 0?
While the Qualcomm RPMh driver might map 0 to QCOM_ICC_TAG_ALWAYS internally,
using the macro explicitly would maintain consistency with the other
interconnect nodes in the tree and clarify the intended power and bandwidth
configuration.
> +
> + interconnect-names = "cam_ahb",
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612194417.1737009-1-atanas.filipov@oss.qualcomm.com?part=2
^ permalink raw reply
* Re: [PATCH v11 5/9] mfd: p3h2x4x: Add driver for NXP P3H2x4x i3c hub and on-die regulator
From: Frank Li @ 2026-06-12 20:02 UTC (permalink / raw)
To: Lakshay Piplani
Cc: linux-kernel, linux-i3c, alexandre.belloni, krzk+dt, robh,
conor+dt, devicetree, broonie, lee, Frank.Li, lgirdwood,
vikash.bansal, priyanka.jain, aman.kumarpandey
In-Reply-To: <20260612111816.3688240-6-lakshay.piplani@nxp.com>
On Fri, Jun 12, 2026 at 04:48:12PM +0530, Lakshay Piplani wrote:
> From: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
>
> Add core MFD support for the NXP P3H2x4x (P3H2440/P3H2441/P3H2840/P3H2841)
> family of multiport I3C hub devices. These devices connect to a host via
> I3C/I2C/SMBus and expose multiple downstream target ports.
>
> Signed-off-by: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
> Signed-off-by: Vikash Bansal <vikash.bansal@nxp.com>
> Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
>
> ---
> Changes in v11:
> - Use MFD_CELL_NAME() for child device registration
> - Rename local variables for consistency
> - Rename driver names to follow subsystem conventions:
> - Use '-' instead of '_' in driver names
> - Drop the "_drv" suffix from driver names
>
> Changes in v10:
> - Drop redundant is_p3h2x4x_in_i3c flag
>
> Changes in v9:
> - Renamed macros to follow consistent uppercase naming conventions
> - Made REGMAP selects in the P3H2X4X MFD Kconfig conditional,
> to avoid I3C/I2C dependency issues
>
> Changes in v8:
> - No change
>
> Changes in v7:
> - Use new config I3C_OR_I2C
>
> Changes in v6:
> - No change
>
> Changes in v5:
> - Corrected the ordering in the Makefile and Kconfig for MFD_P3H2X4X
> - Updated dev_err_probe() for regmap_init failure.
> - Updated module description
>
> Changes in v4:
> - Split the driver into three separate patches(mfd, regulator and I3C hub)
> - Added support for NXP P3H2x4x MFD functionality
> ---
> ---
> MAINTAINERS | 2 +
> drivers/mfd/Kconfig | 13 ++++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/p3h2840.c | 119 ++++++++++++++++++++++++++++++++++++
> include/linux/i3c/device.h | 1 +
> include/linux/mfd/p3h2840.h | 26 ++++++++
> 6 files changed, 162 insertions(+)
> create mode 100644 drivers/mfd/p3h2840.c
> create mode 100644 include/linux/mfd/p3h2840.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ba65ae5a008b..3420701a75c5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -19311,6 +19311,8 @@ L: linux-kernel@vger.kernel.org
> L: linux-i3c@lists.infradead.org
> S: Maintained
> F: Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
> +F: drivers/mfd/p3h2840.c
> +F: include/linux/mfd/p3h2840.h
>
> NXP PF5300/PF5301/PF5302 PMIC REGULATOR DEVICE DRIVER
> M: Woodrow Douglass <wdouglass@carnegierobotics.com>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 7192c9d1d268..405b50c3c77b 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -617,6 +617,19 @@ config MFD_MX25_TSADC
> i.MX25 processors. They consist of a conversion queue for general
> purpose ADC and a queue for Touchscreens.
>
> +config MFD_P3H2X4X
> + tristate "NXP P3H2X4X I3C Hub Device"
> + depends on I3C_OR_I2C
> + select MFD_CORE
> + select REGMAP_I3C if I3C
> + select REGMAP_I2C if I2C
> + help
> + Enable Support for NXP P3H244x/P3H284x I3C HUB device using I3C/I2C
> + communication interface.
> +
> + This driver provides support for I3C hub and regulator, each subdriver
> + can be enabled independently depending on the required functionality.
> +
> config MFD_PF1550
> tristate "NXP PF1550 PMIC Support"
> depends on I2C=y && OF
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index e75e8045c28a..a284b22c7b13 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -122,6 +122,7 @@ obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
> obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o
> obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
>
> +obj-$(CONFIG_MFD_P3H2X4X) += p3h2840.o
> obj-$(CONFIG_MFD_PF1550) += pf1550.o
>
> obj-$(CONFIG_MFD_NCT6694) += nct6694.o
> diff --git a/drivers/mfd/p3h2840.c b/drivers/mfd/p3h2840.c
> new file mode 100644
> index 000000000000..0a80992d6250
> --- /dev/null
> +++ b/drivers/mfd/p3h2840.c
> @@ -0,0 +1,119 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025-2026 NXP
> + * P3H2X4X i3c hub and regulator device.
> + */
> +
> +#include <linux/i2c.h>
> +#include <linux/i3c/master.h>
> +#include <linux/mfd/core.h>
> +#include <linux/mfd/p3h2840.h>
> +#include <linux/regmap.h>
> +
> +static const struct mfd_cell p3h2x4x_devs[] = {
> + MFD_CELL_NAME("p3h2x4x-regulator"),
> + MFD_CELL_NAME("p3h2x4x-i3c-hub"),
> +};
> +
> +static const struct regmap_config p3h2x4x_regmap_config = {
> + .reg_bits = P3H2X4X_REG_BITS,
> + .val_bits = P3H2X4X_VAL_BITS,
> + .max_register = 0xFF,
> +};
> +
> +static int p3h2x4x_device_probe_i3c(struct i3c_device *i3cdev)
> +{
> + struct p3h2x4x_dev *ddata;
> + int ret;
> +
> + ddata = devm_kzalloc(&i3cdev->dev, sizeof(*ddata), GFP_KERNEL);
> + if (!ddata)
> + return -ENOMEM;
> +
> + i3cdev_set_drvdata(i3cdev, ddata);
> +
> + ddata->regmap = devm_regmap_init_i3c(i3cdev, &p3h2x4x_regmap_config);
> + if (IS_ERR(ddata->regmap))
> + return dev_err_probe(&i3cdev->dev, PTR_ERR(ddata->regmap),
> + "Failed to register HUB regmap\n");
> +
> + // The hub child driver retrieves information from i3cdev
> + ddata->i3cdev = i3cdev;
> +
> + ret = devm_mfd_add_devices(&i3cdev->dev, PLATFORM_DEVID_AUTO,
> + p3h2x4x_devs, ARRAY_SIZE(p3h2x4x_devs),
> + NULL, 0, NULL);
> + if (ret)
> + return dev_err_probe(&i3cdev->dev, ret, "Failed to add sub devices\n");
> +
> + return 0;
> +}
> +
> +static int p3h2x4x_device_probe_i2c(struct i2c_client *client)
> +{
> + struct p3h2x4x_dev *ddata;
> + int ret;
> +
> + ddata = devm_kzalloc(&client->dev, sizeof(*ddata), GFP_KERNEL);
> + if (!ddata)
> + return -ENOMEM;
> +
> + i2c_set_clientdata(client, ddata);
> +
> + ddata->regmap = devm_regmap_init_i2c(client, &p3h2x4x_regmap_config);
> + if (IS_ERR(ddata->regmap))
> + return dev_err_probe(&client->dev, PTR_ERR(ddata->regmap),
> + "Failed to register HUB regmap\n");
> +
> + ddata->i3cdev = NULL;
> +
> + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO,
> + p3h2x4x_devs, ARRAY_SIZE(p3h2x4x_devs),
> + NULL, 0, NULL);
> + if (ret)
> + return dev_err_probe(&client->dev, ret, "Failed to add sub devices\n");
> +
> + return 0;
> +}
> +
> +static const struct i3c_device_id p3h2x4x_i3c_ids[] = {
> + I3C_CLASS(I3C_DCR_HUB, NULL),
> + { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(i3c, p3h2x4x_i3c_ids);
> +
> +static const struct i2c_device_id p3h2x4x_i2c_id_table[] = {
> + { "nxp-i3c-hub" },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(i2c, p3h2x4x_i2c_id_table);
> +
> +static const struct of_device_id p3h2x4x_i2c_of_match[] = {
> + { .compatible = "nxp,p3h2840", },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, p3h2x4x_i2c_of_match);
> +
> +static struct i3c_driver p3h2x4x_i3c = {
> + .driver = {
> + .name = "p3h2x4x-i3c",
> + },
> + .probe = p3h2x4x_device_probe_i3c,
> + .id_table = p3h2x4x_i3c_ids,
> +};
> +
> +static struct i2c_driver p3h2x4x_i2c = {
> + .driver = {
> + .name = "p3h2x4x-i2c",
> + .of_match_table = p3h2x4x_i2c_of_match,
> + },
> + .probe = p3h2x4x_device_probe_i2c,
> + .id_table = p3h2x4x_i2c_id_table,
> +};
> +module_i3c_i2c_driver(p3h2x4x_i3c, &p3h2x4x_i2c);
> +
> +MODULE_AUTHOR("Aman Kumar Pandey <aman.kumarpandey@nxp.com>");
> +MODULE_AUTHOR("Vikash Bansal <vikash.bansal@nxp.com>");
> +MODULE_AUTHOR("Lakshay Piplani <lakshay.piplani@nxp.com>");
> +MODULE_DESCRIPTION("NXP P3H2X4X I3C HUB multi function driver");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h
> index 971d53349b6f..6188082599dd 100644
> --- a/include/linux/i3c/device.h
> +++ b/include/linux/i3c/device.h
> @@ -85,6 +85,7 @@ struct i3c_xfer {
> */
> enum i3c_dcr {
> I3C_DCR_GENERIC_DEVICE = 0,
> + I3C_DCR_HUB = 194,
> };
>
> #define I3C_PID_MANUF_ID(pid) (((pid) & GENMASK_ULL(47, 33)) >> 33)
> diff --git a/include/linux/mfd/p3h2840.h b/include/linux/mfd/p3h2840.h
> new file mode 100644
> index 000000000000..2d4fae2176ae
> --- /dev/null
> +++ b/include/linux/mfd/p3h2840.h
> @@ -0,0 +1,26 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2025-2026 NXP
> + * This header file contains register definitions and bit masks for the P3H2X4X.
> + */
> +
> +#ifndef _LINUX_MFD_P3H2840_H
> +#define _LINUX_MFD_P3H2840_H
> +
> +#include <linux/types.h>
> +
> +/* Device Configuration Registers */
> +#define P3H2X4X_DEV_REG_PROTECTION_CODE 0x10
> +#define P3H2X4X_REGISTERS_LOCK_CODE 0x00
> +#define P3H2X4X_REGISTERS_UNLOCK_CODE 0x69
> +#define P3H2X4X_CP1_REGISTERS_UNLOCK_CODE 0x6a
> +
> +/* Reg config for Regmap */
> +#define P3H2X4X_REG_BITS 8
> +#define P3H2X4X_VAL_BITS 8
> +
> +struct p3h2x4x_dev {
> + struct i3c_device *i3cdev;
> + struct regmap *regmap;
> +};
> +#endif /* _LINUX_MFD_P3H2840_H */
> --
> 2.25.1
>
^ permalink raw reply
* Re: [PATCH v11 4/9] dt-bindings: i3c: Add NXP P3H2x4x i3c-hub support
From: Frank Li @ 2026-06-12 20:00 UTC (permalink / raw)
To: Lakshay Piplani
Cc: linux-kernel, linux-i3c, alexandre.belloni, krzk+dt, robh,
conor+dt, devicetree, broonie, lee, Frank.Li, lgirdwood,
vikash.bansal, priyanka.jain, aman.kumarpandey
In-Reply-To: <20260612111816.3688240-5-lakshay.piplani@nxp.com>
On Fri, Jun 12, 2026 at 04:48:11PM +0530, Lakshay Piplani wrote:
> From: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
>
> Add bindings for the NXP P3H2x4x (P3H2440/P3H2441/P3H2840/P3H2841)
> multiport I3C hub family. These devices connect to a host via
> I3C/I2C/SMBus and allow communication with multiple downstream
> peripherals.
>
> Signed-off-by: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
> Signed-off-by: Vikash Bansal <vikash.bansal@nxp.com>
> Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com>
> Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
>
> ---
> Changes in v11:
> - No change
>
> Changes in v10:
> - No change, added Reviewed-By tag
>
> Changes in v9:
> - Referenced i3c.yaml and i2c-controller.yaml for child nodes
> - Dropped unnecessary #address-cells and #size-cells from child nodes
>
> Changes in v8:
> - Add compatible in i3c example
>
> Changes in v7:
> - Fix schema validation issues
> - Adjust required properties
> - Add I2C example
>
> Changes in v6:
> - Use a vendor prefix for the attributes
>
> Changes in v5:
> - Removed SW properties: cp0-ldo-microvolt,cp1-ldo-microvolt,
> tp0145-ldo-microvolt, tp2367-ldo-microvolt
> - Changed supply entries and its descriptions
>
> Changes in v4:
> - Fixed DT binding check warning
> - Removed SW properties: ibi-enable, local-dev, and always-enable
>
> Changes in v3:
> - Added MFD (Multi-Function Device) support for I3C hub and on-die regulator
> - Added Regulator supply node
>
> Changes in v2:
> - Fixed DT binding check warning
> - Revised logic for parsing DTS nodes
> ---
> ---
> .../devicetree/bindings/i3c/nxp,p3h2840.yaml | 291 ++++++++++++++++++
> MAINTAINERS | 9 +
> 2 files changed, 300 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
>
> diff --git a/Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml b/Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
> new file mode 100644
> index 000000000000..c080eeb0eeaa
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
> @@ -0,0 +1,291 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +# Copyright 2025 NXP
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/i3c/nxp,p3h2840.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NXP P3H2X4X I3C HUB
> +
> +maintainers:
> + - Aman Kumar Pandey <aman.kumarpandey@nxp.com>
> + - Vikash Bansal <vikash.bansal@nxp.com>
> + - Lakshay Piplani <lakshay.piplani@nxp.com>
> +
> +description: |
> + P3H2x4x (P3H2440/P3H2441/P3H2840/P3H2841) is a family of multiport I3C
> + hub devices that connect to:-
> + 1. A host CPU via I3C/I2C/SMBus bus on upstream side and connect to multiple
> + peripheral devices on the downstream side.
> + 2. Have two Controller Ports which can support either
> + I2C/SMBus or I3C buses and connect to a CPU, BMC or SOC.
> + 3. P3H2840/ P3H2841 are 8 port I3C hub with eight I3C/I2C Target Port.
> + 4. P3H2440/ P3H2441 are 4 port I3C hub with four I3C/I2C Target Port.
> + Target ports can be configured as I2C/SMBus, I3C or GPIO and connect to
> + peripherals.
> +
> +properties:
> + compatible:
> + const: nxp,p3h2840
> +
> + reg:
> + maxItems: 1
> +
> + '#address-cells':
> + const: 1
> +
> + '#size-cells':
> + const: 0
> +
> + assigned-address:
> + maximum: 0x7f
> +
> + nxp,tp0145-pullup-ohms:
> + description:
> + Selects the pull up resistance for target Port 0/1/4/5, in ohms.
> + enum: [250, 500, 1000, 2000]
> + default: 500
> +
> + nxp,tp2367-pullup-ohms:
> + description:
> + Selects the pull up resistance for target Port 2/3/6/7, in ohms.
> + enum: [250, 500, 1000, 2000]
> + default: 500
> +
> + nxp,cp0-io-strength-ohms:
> + description:
> + Selects the IO drive strength for controller Port 0, in ohms.
> + enum: [20, 30, 40, 50]
> + default: 20
> +
> + nxp,cp1-io-strength-ohms:
> + description:
> + Selects the IO drive strength for controller Port 1, in ohms.
> + enum: [20, 30, 40, 50]
> + default: 20
> +
> + nxp,tp0145-io-strength-ohms:
> + description:
> + Selects the IO drive strength for target port 0/1/4/5, in ohms.
> + enum: [20, 30, 40, 50]
> + default: 20
> +
> + nxp,tp2367-io-strength-ohms:
> + description:
> + Selects the IO drive strength for target port 2/3/6/7, in ohms.
> + enum: [20, 30, 40, 50]
> + default: 20
> +
> + vcc1-supply:
> + description: Controller port 0 power supply.
> +
> + vcc2-supply:
> + description: Controller port 1 power supply.
> +
> + vcc3-supply:
> + description: Target port 0/1/4/5 power supply.
> +
> + vcc4-supply:
> + description: Target port 2/3/6/7 power supply.
> +
> + regulators:
> + type: object
> + additionalProperties: false
> +
> + properties:
> + ldo-cp0:
> + type: object
> + $ref: /schemas/regulator/regulator.yaml#
> + unevaluatedProperties: false
> +
> + ldo-cp1:
> + type: object
> + $ref: /schemas/regulator/regulator.yaml#
> + unevaluatedProperties: false
> +
> + ldo-tpg0:
> + type: object
> + $ref: /schemas/regulator/regulator.yaml#
> + unevaluatedProperties: false
> +
> + ldo-tpg1:
> + type: object
> + $ref: /schemas/regulator/regulator.yaml#
> + unevaluatedProperties: false
> +
> +required:
> + - reg
> +
> +patternProperties:
> + "^i3c@[0-7]$":
> + type: object
> + $ref: /schemas/i3c/i3c.yaml#
> + unevaluatedProperties: false
> +
> + properties:
> + reg:
> + description:
> + The I3C HUB Target Port number.
> + maximum: 7
> +
> + nxp,pullup-enable:
> + type: boolean
> + description:
> + Enables the on-die pull-up for Target Port.
> +
> + required:
> + - reg
> +
> + "^(i2c|smbus)@[0-7]$":
> + type: object
> + $ref: /schemas/i2c/i2c-controller.yaml#
> + unevaluatedProperties: false
> +
> + properties:
> + reg:
> + description:
> + The I3C HUB Target Port number.
> + maximum: 7
> +
> + nxp,pullup-enable:
> + type: boolean
> + description:
> + Enables the on-die pull-up for Target Port.
> +
> + required:
> + - reg
> +
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + i3c {
> + #address-cells = <3>;
> + #size-cells = <0>;
> +
> + hub@70,236153000c2 {
> + reg = <0x70 0x236 0x3000c2>;
> + compatible = "nxp,p3h2840";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + assigned-address = <0x50>;
> +
> + nxp,tp0145-pullup-ohms = <1000>;
> + nxp,tp2367-pullup-ohms = <1000>;
> + nxp,cp0-io-strength-ohms = <50>;
> + nxp,cp1-io-strength-ohms = <50>;
> + nxp,tp0145-io-strength-ohms = <50>;
> + nxp,tp2367-io-strength-ohms = <50>;
> + vcc3-supply = <®_tpg0>;
> + vcc4-supply = <®_tpg1>;
> +
> + regulators {
> + reg_cp0: ldo-cp0 {
> + regulator-name = "ldo-cp0";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + };
> +
> + reg_cp1: ldo-cp1 {
> + regulator-name = "ldo-cp1";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + };
> +
> + reg_tpg0: ldo-tpg0 {
> + regulator-name = "ldo-tpg0";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + };
> +
> + reg_tpg1: ldo-tpg1 {
> + regulator-name = "ldo-tpg1";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + };
> + };
> +
> + smbus@0 {
> + reg = <0x0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + nxp,pullup-enable;
> + };
> +
> + i2c@1 {
> + reg = <0x1>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + nxp,pullup-enable;
> + };
> +
> + i3c@2 {
> + reg = <0x2>;
> + #address-cells = <3>;
> + #size-cells = <0>;
> + nxp,pullup-enable;
> + };
> + };
> + };
> +
> + - |
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + hub@70 {
> + reg = <0x70>;
> + compatible = "nxp,p3h2840";
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + nxp,tp0145-pullup-ohms = <1000>;
> + nxp,tp2367-pullup-ohms = <1000>;
> + nxp,cp0-io-strength-ohms = <50>;
> + nxp,cp1-io-strength-ohms = <50>;
> + nxp,tp0145-io-strength-ohms = <50>;
> + nxp,tp2367-io-strength-ohms = <50>;
> + vcc3-supply = <®_tpg0_i2c>;
> + vcc4-supply = <®_tpg1_i2c>;
> +
> + regulators {
> + reg_cp0_i2c: ldo-cp0 {
> + regulator-name = "ldo-cp0";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + };
> +
> + reg_cp1_i2c: ldo-cp1 {
> + regulator-name = "ldo-cp1";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + };
> +
> + reg_tpg0_i2c: ldo-tpg0 {
> + regulator-name = "ldo-tpg0";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + };
> +
> + reg_tpg1_i2c: ldo-tpg1 {
> + regulator-name = "ldo-tpg1";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + };
> + };
> +
> + smbus@0 {
> + reg = <0x0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + nxp,pullup-enable;
> + };
> +
> + i2c@1 {
> + reg = <0x1>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + nxp,pullup-enable;
> + };
> + };
> + };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c2c6d79275c6..ba65ae5a008b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -19303,6 +19303,15 @@ S: Maintained
> F: Documentation/devicetree/bindings/ptp/nxp,ptp-netc.yaml
> F: drivers/ptp/ptp_netc.c
>
> +NXP P3H2X4X I3C-HUB DRIVER
> +M: Vikash Bansal <vikash.bansal@nxp.com>
> +M: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
> +M: Lakshay Piplani <lakshay.piplani@nxp.com>
> +L: linux-kernel@vger.kernel.org
> +L: linux-i3c@lists.infradead.org
> +S: Maintained
> +F: Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
> +
> NXP PF5300/PF5301/PF5302 PMIC REGULATOR DEVICE DRIVER
> M: Woodrow Douglass <wdouglass@carnegierobotics.com>
> S: Maintained
> --
> 2.25.1
>
^ permalink raw reply
* Re: [PATCH v11 3/9] i3c: master: Add APIs for I3C hub support
From: Frank Li @ 2026-06-12 19:59 UTC (permalink / raw)
To: sashiko-reviews
Cc: Lakshay Piplani, linux-i3c, devicetree, conor+dt, Frank.Li, robh
In-Reply-To: <20260612114844.5D7B71F000E9@smtp.kernel.org>
On Fri, Jun 12, 2026 at 11:48:43AM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] i3c_master_direct_detach_i3c_dev_locked lacks the unaddressable device check present in its attach counterpart, leading to a NULL pointer dereference in controller drivers.
> --
>
> commit a7f74140d15672b8f2824666071ce06e3051e0d8
> Author: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
>
> i3c: master: Add APIs for I3C hub support
>
> Add helpers for attaching and detaching I3C devices and CCC helpers
> to check CCC support and send CCC commands to prepare for I3C hub support.
>
> > diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> > index ec3547f75469e..59e0f82de6ebd 100644
> > --- a/drivers/i3c/master.c
> > +++ b/drivers/i3c/master.c
>
> [ ... ]
>
> > +int i3c_master_direct_attach_i3c_dev_locked(struct i3c_master_controller *master,
> > + struct i3c_dev_desc *dev)
> > +{
> > + int ret = 0;
> > +
> > + /*
> > + * We don't attach devices to the controller until they are
> > + * addressable on the bus.
> > + */
> > +
> > + if (!dev->info.static_addr && !dev->info.dyn_addr)
> > + return 0;
> > +
> > + /* Do not attach the master device itself. */
> > + if (master->this != dev && master->ops->attach_i3c_dev)
> > + ret = master->ops->attach_i3c_dev(dev);
> > +
> > + return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(i3c_master_direct_attach_i3c_dev_locked);
>
> [ ... ]
>
> > +void i3c_master_direct_detach_i3c_dev_locked(struct i3c_dev_desc *dev)
> > +{
> > + struct i3c_master_controller *master = i3c_dev_get_master(dev);
> > +
> > + /* Do not detach the master device itself. */
> > + if (master->this != dev && master->ops->detach_i3c_dev)
> > + master->ops->detach_i3c_dev(dev);
>
> [Severity: High]
> Does this missing address check in the detach helper lead to a NULL pointer
> dereference in controller drivers?
>
> The attach helper i3c_master_direct_attach_i3c_dev_locked() gracefully skips
> attaching devices without a static or dynamic address and returns 0 (success).
> Because it returns success, callers might naturally invoke this companion
> detach API during teardown for these same devices.
>
> However, since this helper lacks the corresponding address check, it
> unconditionally invokes the controller's detach callback. Controller drivers
> often retrieve the device's private data and immediately dereference it. Since
> the attach phase was skipped, this private data would be NULL.
>
> Should this function also check if the device has an address before calling
> the detach callback?
Make sense, please fix it.
Frank
>
> > +}
> > +EXPORT_SYMBOL_GPL(i3c_master_direct_detach_i3c_dev_locked);
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260612111816.3688240-1-lakshay.piplani@nxp.com?part=3
^ permalink raw reply
* Re: [PATCH v1 1/4] dt-bindings: media: qcom: Add JPEG encoder binding
From: sashiko-bot @ 2026-06-12 19:57 UTC (permalink / raw)
To: Atanas Filipov; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260612194417.1737009-2-atanas.filipov@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Schema validation weakness and missing required properties cause driver probe failure.
- [Medium] Chronologically backward compatible fallback with mismatched hardware constraints.
- [Low] The binding introduces the deprecated `cell-index` property.
--
commit 8d581d21294da3512a77773ccfed01692993fa7b
Author: Atanas Filipov <atanas.filipov@oss.qualcomm.com>
dt-bindings: media: qcom: Add JPEG encoder binding
Add device-tree binding for the standalone Qualcomm JPEG encoder hardware
block (separate from CAMSS media pipelines). Document required resources
briefly and scope initial support to currently used compatibles in this
series, including SM8250, QCM6490, and SM8550 class platforms.
> diff --git a/Documentation/devicetree/bindings/media/qcom,jpeg-encoder.yaml b/Documentation/devicetree/bindings/media/qcom,jpeg-encoder.yaml
> new file mode 100644
> index 0000000000000..83f19719a8693
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/qcom,jpeg-encoder.yaml
> @@ -0,0 +1,142 @@
[ ... ]
> +properties:
> + compatible:
> + oneOf:
> + - items:
> + - const: qcom,sm8250-jenc
> + - items:
> + - enum:
> + - qcom,qcm6490-jenc
> + - const: qcom,sm8550-jenc
[Severity: Medium]
Is it safe to use qcom,sm8550-jenc as a fallback for qcom,qcm6490-jenc?
It looks like the driver uses different performance and clock configuration
data for these two SoCs (qcom_t680_jpeg_drvdata vs qcom_t780_jpeg_drvdata
in drivers/media/platform/qcom/jpeg/qcom_jenc_res.c).
If a generic driver relies on this fallback, it would apply SM8550 clock
frequencies to QCM6490 hardware, which might cause instability. Also, newer
hardware falling back to older hardware is usually the standard devicetree
convention.
> + - items:
> + - const: qcom,sm8550-jenc
> +
> + cell-index:
> + description: Legacy JPEG HW instance index.
> + $ref: /schemas/types.yaml#/definitions/uint32
[Severity: Low]
Is this deprecated cell-index property still required?
The introduced Linux driver does not appear to read or use this property.
Could instance identification be handled dynamically or via standardized
devicetree aliases nodes instead?
> + reg:
> + maxItems: 1
> +
> + reg-names:
> + oneOf:
> + - items:
> + - const: jpeg
> + - items:
> + - const: jpeg-regs
> + - items:
> + - const: jpeg_regs
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + minItems: 6
> + maxItems: 6
> +
> + clock-names:
> + oneOf:
> + - items:
> + - const: gcc_hf_axi
> + - const: gcc_sf_axi
> + - const: core_ahb
> + - const: cpas_ahb
> + - const: camnoc_axi
> + - const: jpeg
> + - items:
> + - const: gcc_hf_axi_clk
> + - const: gcc_sf_axi_clk
> + - const: core_ahb_clk
> + - const: cpas_ahb_clk
> + - const: camnoc_axi_clk
> + - const: jpeg_clk
[Severity: High]
Should the binding strictly enforce the exact resource names the driver expects?
The schema allows variations like "jpeg-regs" and "_clk" suffixes, but the
driver probe in qcom_jpeg_probe() strictly calls:
devm_platform_ioremap_resource_byname(pdev, "jpeg")
and expects non-suffix clock names (e.g., "core_ahb"). If a devicetree uses
the alternative schema-approved names, won't the driver probe fail?
[ ... ]
> +required:
> + - compatible
> + - reg
> + - clocks
> + - interrupts
> + - power-domains
> + - iommus
> + - interconnects
> + - interconnect-names
[Severity: High]
Should reg-names and clock-names be added to this required list?
Since the driver strictly relies on these names to find its resources during
probe, omitting them from the devicetree will cause probe failures.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612194417.1737009-1-atanas.filipov@oss.qualcomm.com?part=1
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox