[v2,4/6] soc: mediatek: mtk-pmic-wrap: Add support for companion PMICs

Message ID 20230324094205.33266-5-angelogioacchino.delregno@collabora.com
State New
Headers
Series MediaTek Helio X10 MT6795 - MT6331/6332 PMIC Wrapper |

Commit Message

AngeloGioacchino Del Regno March 24, 2023, 9:42 a.m. UTC
  Some PMICs are designed to work with a companion part, which provides
more regulators and/or companion devices such as LED controllers,
display backlight controllers, battery charging, fuel gauge, etc:
this kind of PMICs are usually present in smartphone platforms, where
tight integration is required.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/soc/mediatek/mtk-pmic-wrap.c | 73 ++++++++++++++++++++++------
 1 file changed, 59 insertions(+), 14 deletions(-)
  

Comments

Alexandre Mergnat March 29, 2023, 10:40 p.m. UTC | #1
Le ven. 24 mars 2023 à 10:42, AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> a écrit :
>
> Some PMICs are designed to work with a companion part, which provides
> more regulators and/or companion devices such as LED controllers,
> display backlight controllers, battery charging, fuel gauge, etc:
> this kind of PMICs are usually present in smartphone platforms, where
> tight integration is required.
>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
>  drivers/soc/mediatek/mtk-pmic-wrap.c | 73 ++++++++++++++++++++++------
>  1 file changed, 59 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
> index a33a1b1820cb..366e40b802e4 100644
> --- a/drivers/soc/mediatek/mtk-pmic-wrap.c
> +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
> @@ -47,6 +47,7 @@
>
>  /* macro for device wrapper default value */
>  #define PWRAP_DEW_READ_TEST_VAL                0x5aa5
> +#define PWRAP_DEW_COMP_READ_TEST_VAL   0xa55a
>  #define PWRAP_DEW_WRITE_TEST_VAL       0xa55a
>
>  /* macro for manual command */
> @@ -1222,12 +1223,16 @@ struct pwrap_slv_regops {
>   * struct pwrap_slv_type - PMIC device wrapper definitions
>   * @dew_regs:      Device Wrapper (DeW) register offsets
>   * @type:          PMIC Type (model)
> + * @comp_dew_regs: Device Wrapper (DeW) register offsets for companion device
> + * @comp_type:     Companion PMIC Type (model)
>   * @regops:        Register R/W ops
>   * @caps:          Capability flags for the target device
>   */
>  struct pwrap_slv_type {
>         const u32 *dew_regs;
>         enum pmic_type type;
> +       const u32 *comp_dew_regs;
> +       enum pmic_type comp_type;
>         const struct pwrap_slv_regops *regops;
>         u32 caps;
>  };
> @@ -1548,9 +1553,12 @@ static int pwrap_init_dual_io(struct pmic_wrapper *wrp)
>  {
>         int ret;
>         bool read_ok, tmp;
> +       bool comp_read_ok = true;
>
>         /* Enable dual IO mode */
>         pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1);
> +       if (wrp->slave->comp_dew_regs)
> +               pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_DIO_EN], 1);
>
>         /* Check IDLE & INIT_DONE in advance */
>         ret = readx_poll_timeout(pwrap_is_fsm_idle_and_sync_idle, wrp, tmp, tmp,
> @@ -1564,8 +1572,14 @@ static int pwrap_init_dual_io(struct pmic_wrapper *wrp)
>
>         /* Read Test */
>         read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs, PWRAP_DEW_READ_TEST_VAL);
> -       if (!read_ok) {
> -               dev_err(wrp->dev, "Read failed on DIO mode.\n");
> +       if (wrp->slave->comp_dew_regs)
> +               comp_read_ok = pwrap_pmic_read_test(wrp, wrp->slave->comp_dew_regs,
> +                                                   PWRAP_DEW_COMP_READ_TEST_VAL);
> +       if (!read_ok || !comp_read_ok) {
> +               dev_err(wrp->dev, "Read failed on DIO mode. Main PMIC %s%s\n",
> +                       !read_ok ? "fail" : "success",
> +                       wrp->slave->comp_dew_regs && !comp_read_ok ?
> +                       ", Companion PMIC fail" : "");
>                 return -EFAULT;
>         }
>
> @@ -1640,19 +1654,41 @@ static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp)
>         return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1;
>  }
>
> -static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
> +static bool __pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp, const u32 *dew_regs)
>  {
>         u32 rdata;
>         int ret;
>
> -       ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY],
> -                        &rdata);
> +       ret = pwrap_read(wrp, dew_regs[PWRAP_DEW_CIPHER_RDY], &rdata);
>         if (ret)
>                 return false;
>
>         return rdata == 1;
>  }
>
> +

Remove this extra line please.

> +static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
> +{
> +       bool ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->dew_regs);
> +
> +       if (!ret)
> +               return ret;
> +
> +       /* If there's any companion, wait for it to be ready too */
> +       if (wrp->slave->comp_dew_regs)
> +               ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->comp_dew_regs);
> +
> +       return ret;
> +}
> +
> +static void pwrap_config_cipher(struct pmic_wrapper *wrp, const u32 *dew_regs)
> +{
> +       pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1);
> +       pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
> +       pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
> +       pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
> +}
> +
>  static int pwrap_init_cipher(struct pmic_wrapper *wrp)
>  {
>         int ret;
> @@ -1689,10 +1725,11 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
>         }
>
>         /* Config cipher mode @PMIC */
> -       pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1);
> -       pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
> -       pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
> -       pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
> +       pwrap_config_cipher(wrp, wrp->slave->dew_regs);
> +
> +       /* If there is any companion PMIC, configure cipher mode there too */
> +       if (wrp->slave->comp_type > 0)
> +               pwrap_config_cipher(wrp, wrp->slave->comp_dew_regs);
>
>         switch (wrp->slave->type) {
>         case PMIC_MT6397:
> @@ -1754,6 +1791,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
>
>  static int pwrap_init_security(struct pmic_wrapper *wrp)
>  {
> +       u32 crc_val;
>         int ret;
>
>         /* Enable encryption */
> @@ -1762,14 +1800,21 @@ static int pwrap_init_security(struct pmic_wrapper *wrp)
>                 return ret;
>
>         /* Signature checking - using CRC */
> -       if (pwrap_write(wrp,
> -                       wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1))
> -               return -EFAULT;
> +       ret = pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1);
> +       if (ret == 0 && wrp->slave->comp_dew_regs)
> +               ret = pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_EN], 0x1);
>
>         pwrap_writel(wrp, 0x1, PWRAP_CRC_EN);
>         pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE);
> -       pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL],
> -                    PWRAP_SIG_ADR);
> +
> +       /* CRC value */
> +       crc_val = wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL];
> +       if (wrp->slave->comp_dew_regs)
> +               crc_val |= wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_VAL] << 16;

IMHO, the number 16 should be replaced by a define even if I guess
it's a simple shift value.

> +
> +       pwrap_writel(wrp, crc_val, PWRAP_SIG_ADR);
> +
> +       /* PMIC Wrapper Arbiter priority */
>         pwrap_writel(wrp,
>                      wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN);
>
> --
> 2.40.0
>

Sounds good to me.

Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>

Regards,
Alex
  

Patch

diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index a33a1b1820cb..366e40b802e4 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -47,6 +47,7 @@ 
 
 /* macro for device wrapper default value */
 #define PWRAP_DEW_READ_TEST_VAL		0x5aa5
+#define PWRAP_DEW_COMP_READ_TEST_VAL	0xa55a
 #define PWRAP_DEW_WRITE_TEST_VAL	0xa55a
 
 /* macro for manual command */
@@ -1222,12 +1223,16 @@  struct pwrap_slv_regops {
  * struct pwrap_slv_type - PMIC device wrapper definitions
  * @dew_regs:      Device Wrapper (DeW) register offsets
  * @type:          PMIC Type (model)
+ * @comp_dew_regs: Device Wrapper (DeW) register offsets for companion device
+ * @comp_type:     Companion PMIC Type (model)
  * @regops:        Register R/W ops
  * @caps:          Capability flags for the target device
  */
 struct pwrap_slv_type {
 	const u32 *dew_regs;
 	enum pmic_type type;
+	const u32 *comp_dew_regs;
+	enum pmic_type comp_type;
 	const struct pwrap_slv_regops *regops;
 	u32 caps;
 };
@@ -1548,9 +1553,12 @@  static int pwrap_init_dual_io(struct pmic_wrapper *wrp)
 {
 	int ret;
 	bool read_ok, tmp;
+	bool comp_read_ok = true;
 
 	/* Enable dual IO mode */
 	pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1);
+	if (wrp->slave->comp_dew_regs)
+		pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_DIO_EN], 1);
 
 	/* Check IDLE & INIT_DONE in advance */
 	ret = readx_poll_timeout(pwrap_is_fsm_idle_and_sync_idle, wrp, tmp, tmp,
@@ -1564,8 +1572,14 @@  static int pwrap_init_dual_io(struct pmic_wrapper *wrp)
 
 	/* Read Test */
 	read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs, PWRAP_DEW_READ_TEST_VAL);
-	if (!read_ok) {
-		dev_err(wrp->dev, "Read failed on DIO mode.\n");
+	if (wrp->slave->comp_dew_regs)
+		comp_read_ok = pwrap_pmic_read_test(wrp, wrp->slave->comp_dew_regs,
+						    PWRAP_DEW_COMP_READ_TEST_VAL);
+	if (!read_ok || !comp_read_ok) {
+		dev_err(wrp->dev, "Read failed on DIO mode. Main PMIC %s%s\n",
+			!read_ok ? "fail" : "success",
+			wrp->slave->comp_dew_regs && !comp_read_ok ?
+			", Companion PMIC fail" : "");
 		return -EFAULT;
 	}
 
@@ -1640,19 +1654,41 @@  static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp)
 	return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1;
 }
 
-static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
+static bool __pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp, const u32 *dew_regs)
 {
 	u32 rdata;
 	int ret;
 
-	ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY],
-			 &rdata);
+	ret = pwrap_read(wrp, dew_regs[PWRAP_DEW_CIPHER_RDY], &rdata);
 	if (ret)
 		return false;
 
 	return rdata == 1;
 }
 
+
+static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
+{
+	bool ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->dew_regs);
+
+	if (!ret)
+		return ret;
+
+	/* If there's any companion, wait for it to be ready too */
+	if (wrp->slave->comp_dew_regs)
+		ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->comp_dew_regs);
+
+	return ret;
+}
+
+static void pwrap_config_cipher(struct pmic_wrapper *wrp, const u32 *dew_regs)
+{
+	pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1);
+	pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
+	pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
+	pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
+}
+
 static int pwrap_init_cipher(struct pmic_wrapper *wrp)
 {
 	int ret;
@@ -1689,10 +1725,11 @@  static int pwrap_init_cipher(struct pmic_wrapper *wrp)
 	}
 
 	/* Config cipher mode @PMIC */
-	pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1);
-	pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
-	pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
-	pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
+	pwrap_config_cipher(wrp, wrp->slave->dew_regs);
+
+	/* If there is any companion PMIC, configure cipher mode there too */
+	if (wrp->slave->comp_type > 0)
+		pwrap_config_cipher(wrp, wrp->slave->comp_dew_regs);
 
 	switch (wrp->slave->type) {
 	case PMIC_MT6397:
@@ -1754,6 +1791,7 @@  static int pwrap_init_cipher(struct pmic_wrapper *wrp)
 
 static int pwrap_init_security(struct pmic_wrapper *wrp)
 {
+	u32 crc_val;
 	int ret;
 
 	/* Enable encryption */
@@ -1762,14 +1800,21 @@  static int pwrap_init_security(struct pmic_wrapper *wrp)
 		return ret;
 
 	/* Signature checking - using CRC */
-	if (pwrap_write(wrp,
-			wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1))
-		return -EFAULT;
+	ret = pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1);
+	if (ret == 0 && wrp->slave->comp_dew_regs)
+		ret = pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_EN], 0x1);
 
 	pwrap_writel(wrp, 0x1, PWRAP_CRC_EN);
 	pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE);
-	pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL],
-		     PWRAP_SIG_ADR);
+
+	/* CRC value */
+	crc_val = wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL];
+	if (wrp->slave->comp_dew_regs)
+		crc_val |= wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_VAL] << 16;
+
+	pwrap_writel(wrp, crc_val, PWRAP_SIG_ADR);
+
+	/* PMIC Wrapper Arbiter priority */
 	pwrap_writel(wrp,
 		     wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN);