pmdomain: mediatek: Add support for RTFF Hardware in MT8196/MT6991
New generation SoCs use a new RTFF Hardware to save power during
operation of various IPs, other than managing isolation of the
internal buck converters during powerup/down of power domains.
Since some of the power domains need different RTFF handling, add
a new scpys_rtff_type enumeration and hold the value for each
power domain in struct scpsys_domain_data.
If RTFF HW is available, the RTFF additional power sequences are
handled in scpsys_ctl_pwrseq_{on,off}().
Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20250805074746.29457-9-angelogioacchino.delregno@collabora.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
committed by
Ulf Hansson
parent
16d861d2bc
commit
9d02c94342
@@ -39,6 +39,12 @@
|
||||
#define PWR_SRAM_CLKISO_BIT BIT(5)
|
||||
#define PWR_SRAM_ISOINT_B_BIT BIT(6)
|
||||
|
||||
#define PWR_RTFF_SAVE BIT(24)
|
||||
#define PWR_RTFF_NRESTORE BIT(25)
|
||||
#define PWR_RTFF_CLK_DIS BIT(26)
|
||||
#define PWR_RTFF_SAVE_FLAG BIT(27)
|
||||
#define PWR_RTFF_UFS_CLK_DIS BIT(28)
|
||||
|
||||
struct scpsys_domain {
|
||||
struct generic_pm_domain genpd;
|
||||
const struct scpsys_domain_data *data;
|
||||
@@ -247,7 +253,7 @@ static int scpsys_regulator_disable(struct regulator *supply)
|
||||
static int scpsys_ctl_pwrseq_on(struct scpsys_domain *pd)
|
||||
{
|
||||
struct scpsys *scpsys = pd->scpsys;
|
||||
bool tmp;
|
||||
bool do_rtff_nrestore, tmp;
|
||||
int ret;
|
||||
|
||||
/* subsys power on */
|
||||
@@ -260,10 +266,72 @@ static int scpsys_ctl_pwrseq_on(struct scpsys_domain *pd)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (pd->data->rtff_type == SCPSYS_RTFF_TYPE_PCIE_PHY)
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
|
||||
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
|
||||
|
||||
/* Wait for RTFF HW to sync buck isolation state if this is PCIe PHY RTFF */
|
||||
if (pd->data->rtff_type == SCPSYS_RTFF_TYPE_PCIE_PHY)
|
||||
udelay(5);
|
||||
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
|
||||
|
||||
/*
|
||||
* RTFF HW state may be modified by secure world or remote processors.
|
||||
*
|
||||
* With the only exception of STOR_UFS, which always needs save/restore,
|
||||
* check if this power domain's RTFF is already on before trying to do
|
||||
* the NRESTORE procedure, otherwise the system will lock up.
|
||||
*/
|
||||
switch (pd->data->rtff_type) {
|
||||
case SCPSYS_RTFF_TYPE_GENERIC:
|
||||
case SCPSYS_RTFF_TYPE_PCIE_PHY:
|
||||
{
|
||||
u32 ctl_status;
|
||||
|
||||
regmap_read(scpsys->base, pd->data->ctl_offs, &ctl_status);
|
||||
do_rtff_nrestore = ctl_status & PWR_RTFF_SAVE_FLAG;
|
||||
break;
|
||||
}
|
||||
case SCPSYS_RTFF_TYPE_STOR_UFS:
|
||||
/* STOR_UFS always needs NRESTORE */
|
||||
do_rtff_nrestore = true;
|
||||
break;
|
||||
default:
|
||||
do_rtff_nrestore = false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return early if RTFF NRESTORE shall not be done */
|
||||
if (!do_rtff_nrestore)
|
||||
return 0;
|
||||
|
||||
switch (pd->data->rtff_type) {
|
||||
case SCPSYS_RTFF_TYPE_GENERIC:
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
|
||||
break;
|
||||
case SCPSYS_RTFF_TYPE_PCIE_PHY:
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
|
||||
break;
|
||||
case SCPSYS_RTFF_TYPE_STOR_UFS:
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -271,8 +339,32 @@ static void scpsys_ctl_pwrseq_off(struct scpsys_domain *pd)
|
||||
{
|
||||
struct scpsys *scpsys = pd->scpsys;
|
||||
|
||||
switch (pd->data->rtff_type) {
|
||||
case SCPSYS_RTFF_TYPE_GENERIC:
|
||||
case SCPSYS_RTFF_TYPE_PCIE_PHY:
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
|
||||
break;
|
||||
case SCPSYS_RTFF_TYPE_STOR_UFS:
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* subsys power off */
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
|
||||
|
||||
/* Wait for RTFF HW to sync buck isolation state if this is PCIe PHY RTFF */
|
||||
if (pd->data->rtff_type == SCPSYS_RTFF_TYPE_PCIE_PHY)
|
||||
udelay(1);
|
||||
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
|
||||
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
|
||||
|
||||
@@ -108,6 +108,22 @@ struct scpsys_bus_prot_data {
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum scpsys_rtff_type - Type of RTFF Hardware for power domain
|
||||
* @SCPSYS_RTFF_NONE: RTFF HW not present or domain not RTFF managed
|
||||
* @SCPSYS_RTFF_TYPE_GENERIC: Non-CPU, peripheral-generic RTFF HW
|
||||
* @SCPSYS_RTFF_TYPE_PCIE_PHY: PCI-Express PHY specific RTFF HW
|
||||
* @SCPSYS_RTFF_TYPE_STOR_UFS: Storage (UFS) specific RTFF HW
|
||||
* @SCPSYS_RTFF_TYPE_MAX: Number of supported RTFF HW Types
|
||||
*/
|
||||
enum scpsys_rtff_type {
|
||||
SCPSYS_RTFF_NONE = 0,
|
||||
SCPSYS_RTFF_TYPE_GENERIC,
|
||||
SCPSYS_RTFF_TYPE_PCIE_PHY,
|
||||
SCPSYS_RTFF_TYPE_STOR_UFS,
|
||||
SCPSYS_RTFF_TYPE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scpsys_domain_data - scp domain data for power on/off flow
|
||||
* @name: The name of the power domain.
|
||||
@@ -118,6 +134,7 @@ struct scpsys_bus_prot_data {
|
||||
* @ext_buck_iso_offs: The offset for external buck isolation
|
||||
* @ext_buck_iso_mask: The mask for external buck isolation
|
||||
* @caps: The flag for active wake-up action.
|
||||
* @rtff_type: The power domain RTFF HW type
|
||||
* @bp_cfg: bus protection configuration for any subsystem
|
||||
*/
|
||||
struct scpsys_domain_data {
|
||||
@@ -129,6 +146,7 @@ struct scpsys_domain_data {
|
||||
int ext_buck_iso_offs;
|
||||
u32 ext_buck_iso_mask;
|
||||
u16 caps;
|
||||
enum scpsys_rtff_type rtff_type;
|
||||
const struct scpsys_bus_prot_data bp_cfg[SPM_MAX_BUS_PROT_DATA];
|
||||
int pwr_sta_offs;
|
||||
int pwr_sta2nd_offs;
|
||||
|
||||
Reference in New Issue
Block a user