Mailing List Archive

[PATCH v2 4/6] soc: mediatek: mtk-pmic-wrap: Add support for companion PMICs
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;
}

+
+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);

--
2.40.0
Re: [PATCH v2 4/6] soc: mediatek: mtk-pmic-wrap: Add support for companion PMICs [ In reply to ]
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