Skip to content

Commit 9d02c94

Browse files
AngeloGioacchino Del RegnoUlf Hansson
authored andcommitted
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>
1 parent 16d861d commit 9d02c94

2 files changed

Lines changed: 111 additions & 1 deletion

File tree

drivers/pmdomain/mediatek/mtk-pm-domains.c

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@
3939
#define PWR_SRAM_CLKISO_BIT BIT(5)
4040
#define PWR_SRAM_ISOINT_B_BIT BIT(6)
4141

42+
#define PWR_RTFF_SAVE BIT(24)
43+
#define PWR_RTFF_NRESTORE BIT(25)
44+
#define PWR_RTFF_CLK_DIS BIT(26)
45+
#define PWR_RTFF_SAVE_FLAG BIT(27)
46+
#define PWR_RTFF_UFS_CLK_DIS BIT(28)
47+
4248
struct scpsys_domain {
4349
struct generic_pm_domain genpd;
4450
const struct scpsys_domain_data *data;
@@ -247,7 +253,7 @@ static int scpsys_regulator_disable(struct regulator *supply)
247253
static int scpsys_ctl_pwrseq_on(struct scpsys_domain *pd)
248254
{
249255
struct scpsys *scpsys = pd->scpsys;
250-
bool tmp;
256+
bool do_rtff_nrestore, tmp;
251257
int ret;
252258

253259
/* subsys power on */
@@ -260,19 +266,105 @@ static int scpsys_ctl_pwrseq_on(struct scpsys_domain *pd)
260266
if (ret < 0)
261267
return ret;
262268

269+
if (pd->data->rtff_type == SCPSYS_RTFF_TYPE_PCIE_PHY)
270+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
271+
263272
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
264273
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
274+
275+
/* Wait for RTFF HW to sync buck isolation state if this is PCIe PHY RTFF */
276+
if (pd->data->rtff_type == SCPSYS_RTFF_TYPE_PCIE_PHY)
277+
udelay(5);
278+
265279
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
266280

281+
/*
282+
* RTFF HW state may be modified by secure world or remote processors.
283+
*
284+
* With the only exception of STOR_UFS, which always needs save/restore,
285+
* check if this power domain's RTFF is already on before trying to do
286+
* the NRESTORE procedure, otherwise the system will lock up.
287+
*/
288+
switch (pd->data->rtff_type) {
289+
case SCPSYS_RTFF_TYPE_GENERIC:
290+
case SCPSYS_RTFF_TYPE_PCIE_PHY:
291+
{
292+
u32 ctl_status;
293+
294+
regmap_read(scpsys->base, pd->data->ctl_offs, &ctl_status);
295+
do_rtff_nrestore = ctl_status & PWR_RTFF_SAVE_FLAG;
296+
break;
297+
}
298+
case SCPSYS_RTFF_TYPE_STOR_UFS:
299+
/* STOR_UFS always needs NRESTORE */
300+
do_rtff_nrestore = true;
301+
break;
302+
default:
303+
do_rtff_nrestore = false;
304+
break;
305+
}
306+
307+
/* Return early if RTFF NRESTORE shall not be done */
308+
if (!do_rtff_nrestore)
309+
return 0;
310+
311+
switch (pd->data->rtff_type) {
312+
case SCPSYS_RTFF_TYPE_GENERIC:
313+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
314+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
315+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
316+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
317+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
318+
break;
319+
case SCPSYS_RTFF_TYPE_PCIE_PHY:
320+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
321+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
322+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
323+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
324+
break;
325+
case SCPSYS_RTFF_TYPE_STOR_UFS:
326+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
327+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
328+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
329+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
330+
break;
331+
default:
332+
break;
333+
}
334+
267335
return 0;
268336
}
269337

270338
static void scpsys_ctl_pwrseq_off(struct scpsys_domain *pd)
271339
{
272340
struct scpsys *scpsys = pd->scpsys;
273341

342+
switch (pd->data->rtff_type) {
343+
case SCPSYS_RTFF_TYPE_GENERIC:
344+
case SCPSYS_RTFF_TYPE_PCIE_PHY:
345+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
346+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
347+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
348+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
349+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
350+
break;
351+
case SCPSYS_RTFF_TYPE_STOR_UFS:
352+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
353+
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
354+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
355+
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
356+
break;
357+
default:
358+
break;
359+
}
360+
274361
/* subsys power off */
275362
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
363+
364+
/* Wait for RTFF HW to sync buck isolation state if this is PCIe PHY RTFF */
365+
if (pd->data->rtff_type == SCPSYS_RTFF_TYPE_PCIE_PHY)
366+
udelay(1);
367+
276368
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
277369
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
278370
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);

drivers/pmdomain/mediatek/mtk-pm-domains.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,22 @@ struct scpsys_bus_prot_data {
108108
u8 flags;
109109
};
110110

111+
/**
112+
* enum scpsys_rtff_type - Type of RTFF Hardware for power domain
113+
* @SCPSYS_RTFF_NONE: RTFF HW not present or domain not RTFF managed
114+
* @SCPSYS_RTFF_TYPE_GENERIC: Non-CPU, peripheral-generic RTFF HW
115+
* @SCPSYS_RTFF_TYPE_PCIE_PHY: PCI-Express PHY specific RTFF HW
116+
* @SCPSYS_RTFF_TYPE_STOR_UFS: Storage (UFS) specific RTFF HW
117+
* @SCPSYS_RTFF_TYPE_MAX: Number of supported RTFF HW Types
118+
*/
119+
enum scpsys_rtff_type {
120+
SCPSYS_RTFF_NONE = 0,
121+
SCPSYS_RTFF_TYPE_GENERIC,
122+
SCPSYS_RTFF_TYPE_PCIE_PHY,
123+
SCPSYS_RTFF_TYPE_STOR_UFS,
124+
SCPSYS_RTFF_TYPE_MAX
125+
};
126+
111127
/**
112128
* struct scpsys_domain_data - scp domain data for power on/off flow
113129
* @name: The name of the power domain.
@@ -118,6 +134,7 @@ struct scpsys_bus_prot_data {
118134
* @ext_buck_iso_offs: The offset for external buck isolation
119135
* @ext_buck_iso_mask: The mask for external buck isolation
120136
* @caps: The flag for active wake-up action.
137+
* @rtff_type: The power domain RTFF HW type
121138
* @bp_cfg: bus protection configuration for any subsystem
122139
*/
123140
struct scpsys_domain_data {
@@ -129,6 +146,7 @@ struct scpsys_domain_data {
129146
int ext_buck_iso_offs;
130147
u32 ext_buck_iso_mask;
131148
u16 caps;
149+
enum scpsys_rtff_type rtff_type;
132150
const struct scpsys_bus_prot_data bp_cfg[SPM_MAX_BUS_PROT_DATA];
133151
int pwr_sta_offs;
134152
int pwr_sta2nd_offs;

0 commit comments

Comments
 (0)