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>
Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
Link: https://lore.kernel.org/r/20230412131216.198313-5-angelogioacchino.delregno@collabora.com
Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
This commit is contained in:
AngeloGioacchino Del Regno 2023-04-12 15:12:14 +02:00 committed by Matthias Brugger
parent 2eb2730234
commit 41ae95aaa0

View File

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