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.

> +};
> 

Reply via email to