On 9/24/26 11:02 AM, Arnaud Ferraris wrote:
> This driver acts mostly as an interface between PMIC/regulator devices
> connected to MediaTek SoCs over SPMI, providing read/write functions to
> those devices.
>
> It has been successfully tested with the MT6373 PMIC but should work
> just as well with other PMICs as long as the corresponding compatible
> string is added to the driver.
>
> Signed-off-by: Arnaud Ferraris <[email protected]>
> ---
> drivers/power/pmic/Kconfig | 6 +++
> drivers/power/pmic/Makefile | 1 +
> drivers/power/pmic/mtk-spmi.c | 88
> +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 95 insertions(+)
>
> diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
> index 95687d0bdfd..8f35dfdea84 100644
> --- a/drivers/power/pmic/Kconfig
> +++ b/drivers/power/pmic/Kconfig
> @@ -464,6 +464,12 @@ config DM_PMIC_MTK_PWRAP
> on different MediaTek SoCs. The PMIC wrapper is a proprietary
> hardware to connect the PMIC.
>
> +config DM_PMIC_MTK_SPMI
> + bool "Enable driver for MediaTek PMIC Support over SPMI"
This won't work without SPMI, so...
depends on SPMI
> + help
> + Say yes here to add support for controlling MediaTek PMICs using the
> + SPMI bus.
> +
> endif
>
> config PMIC_TPS65217
> diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
> index da9b810de90..a6a16b90bc6 100644
> --- a/drivers/power/pmic/Makefile
> +++ b/drivers/power/pmic/Makefile
> @@ -42,6 +42,7 @@ obj-$(CONFIG_PMIC_RAA215300) += raa215300.o
> obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
> obj-$(CONFIG_$(PHASE_)DM_PMIC_CPCAP) += cpcap.o
> obj-$(CONFIG_DM_PMIC_MTK_PWRAP) += mtk-pwrap.o
> +obj-$(CONFIG_DM_PMIC_MTK_SPMI) += mtk-spmi.o
>
> ifeq ($(CONFIG_$(PHASE_)POWER_LEGACY),y)
> obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
> diff --git a/drivers/power/pmic/mtk-spmi.c b/drivers/power/pmic/mtk-spmi.c
> new file mode 100644
> index 00000000000..39895bf9c0d
> --- /dev/null
> +++ b/drivers/power/pmic/mtk-spmi.c
> @@ -0,0 +1,88 @@
> +// SPDX-License-Identifier: GPL-2.0+
GPL-2.0-or-later
> +/*
> + * MediaTek generic PMIC driver
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <[email protected]>
> + * (C) Copyright 2026 Collabora Ltd
> + * Author: Arnaud Ferraris <[email protected]>
> + */
> +#include <dm.h>
> +#include <power/pmic.h>
> +#include <spmi/spmi.h>
> +
> +#define REG_MASK 0xFFFF
> +
> +struct pmic_mtk_priv {
> + u32 usid; /* Slave ID on SPMI bus */
> +};
> +
> +static int pmic_mtk_reg_count(struct udevice *dev)
> +{
> + return 0xFFFF;
Do we know what the actual max defined register is? Making this smaller
makes the register dump command go faster.
> +}
> +
> +static int pmic_mtk_write(struct udevice *dev, uint reg, const u8 *buff, int
> len)
> +{
> + struct pmic_mtk_priv *priv = dev_get_priv(dev);
> +
> + if (len != 1)
> + return -EINVAL;
> +
> + return spmi_reg_write(dev->parent, priv->usid, /* pid */ 0, reg &
> REG_MASK, *buff);
Could make a macro for pid rather than the inline comment.
> +}
> +
> +static int pmic_mtk_read(struct udevice *dev, uint reg, u8 *buff, int len)
> +{
> + struct pmic_mtk_priv *priv = dev_get_priv(dev);
> + int val;
> +
> + if (len != 1)
> + return -EINVAL;
> +
> + val = spmi_reg_read(dev->parent, priv->usid, /* pid */ 0, reg &
> REG_MASK);
> +
> + if (val < 0)
> + return val;
> + *buff = val;
> + return 0;
> +}
> +
> +static struct dm_pmic_ops pmic_mtk_ops = {
> + .reg_count = pmic_mtk_reg_count,
> + .read = pmic_mtk_read,
> + .write = pmic_mtk_write,
> +};
> +
> +static const struct udevice_id pmic_mtk_ids[] = {
> + { .compatible = "mediatek,mt6373" },
> + { }
> +};
> +
> +static int pmic_mtk_probe(struct udevice *dev)
> +{
> + struct pmic_mtk_priv *priv = dev_get_priv(dev);
> + int ret;
> +
> + /*
> + * dev_read_addr() can't be used here because the reg property actually
> + * contains two discrete values, not a single 64-bit address.
> + * The address is the first value.
> + */
> + ret = ofnode_read_u32_index(dev_ofnode(dev), "reg", 0, &priv->usid);
> + if (ret < 0)
> + return -EINVAL;
> +
> + debug("usid: %d\n", priv->usid);
> +
> + return 0;
> +}
> +
> +U_BOOT_DRIVER(pmic_mtk_spmi) = {
> + .name = "pmic_mtk_spmi",
> + .id = UCLASS_PMIC,
> + .of_match = pmic_mtk_ids,
> + .bind = dm_scan_fdt_dev,
> + .probe = pmic_mtk_probe,
> + .ops = &pmic_mtk_ops,
> + .priv_auto = sizeof(struct pmic_mtk_priv),
Make this a space like everything else above.
> +};
>