Merge tag 'pmdomain-v6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm

Pull pmdomain updates from Ulf Hansson:

 - amlogic: Add support for S6/S7/S7D power-domains controller

 - imx: Add support for i.MX91 power-domains

 - marvell: Add support for PXA1908 power-domains

 - mediatek:
    - Add support for modem power sequence
    - Add support for RTFF Hardware in MT8196/MT6991

 - qcom: Align power-domain definitions for rpmpd

 - rockchip: Default to use power-domain support

 - thead: Create auxiliary device along with a corresponding reset
   driver

 - ti: Synchronize on/off state with HW-state for ti-sci power-domains

* tag 'pmdomain-v6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm: (25 commits)
  pmdomain: thead: Fix error pointer vs NULL bug in th1520_pd_reboot_init()
  pmdomain: thead: create auxiliary device for rebooting
  driver: reset: th1520-aon: add driver for poweroff/reboot via AON FW
  pmdomain: mediatek: airoha: convert from round_rate() to determine_rate()
  pmdomain: rockchip: enable ROCKCHIP_PM_DOMAINS with ARCH_ROCKCHIP
  pmdomain: marvell: Add PXA1908 power domains
  dt-bindings: clock: marvell,pxa1908: Add syscon compatible to apmu
  pmdomain: ti-sci: Set PD on/off state according to the HW state
  pmdomain: amlogic: Add support for S6 S7 S7D power domains controller
  dt-bindings: power: add Amlogic S6 S7 S7D power domains
  pmdomain: mediatek: Convert all SoCs to new style regmap retrieval
  pmdomain: mediatek: Add support for RTFF Hardware in MT8196/MT6991
  pmdomain: mediatek: Add support for modem power sequences
  pmdomain: mediatek: Move ctl sequences out of power_on/off functions
  pmdomain: mediatek: Handle SoCs with inverted SRAM power-down bits
  pmdomain: mediatek: Refactor bus protection regmaps retrieval
  dt-bindings: power: mediatek: Document access-controllers property
  pmdomain: remove unneeded 'fast_io' parameter in regmap_config
  pmdomain: imx93-blk-ctrl: mask DSI and PXP PD domain register on i.MX91
  pmdomain: imx93-blk-ctrl: use ARRAY_SIZE() instead of hardcode number
  ...
This commit is contained in:
Linus Torvalds
2025-10-01 11:51:53 -07:00
38 changed files with 1590 additions and 466 deletions

View File

@@ -19,11 +19,14 @@ description: |
properties:
compatible:
enum:
- marvell,pxa1908-apbc
- marvell,pxa1908-apbcp
- marvell,pxa1908-mpmu
- marvell,pxa1908-apmu
oneOf:
- enum:
- marvell,pxa1908-apbc
- marvell,pxa1908-apbcp
- marvell,pxa1908-mpmu
- items:
- const: marvell,pxa1908-apmu
- const: syscon
reg:
maxItems: 1
@@ -31,6 +34,9 @@ properties:
'#clock-cells':
const: 1
'#power-domain-cells':
const: 1
required:
- compatible
- reg
@@ -38,11 +44,23 @@ required:
additionalProperties: false
if:
not:
properties:
compatible:
contains:
const: marvell,pxa1908-apmu
then:
properties:
'#power-domain-cells': false
examples:
# APMU block:
- |
clock-controller@d4282800 {
compatible = "marvell,pxa1908-apmu";
compatible = "marvell,pxa1908-apmu", "syscon";
reg = <0xd4282800 0x400>;
#clock-cells = <1>;
#power-domain-cells = <1>;
};

View File

@@ -24,6 +24,9 @@ properties:
- amlogic,a5-pwrc
- amlogic,c3-pwrc
- amlogic,t7-pwrc
- amlogic,s6-pwrc
- amlogic,s7-pwrc
- amlogic,s7d-pwrc
"#power-domain-cells":
const: 1

View File

@@ -44,6 +44,15 @@ properties:
'#size-cells':
const: 0
access-controllers:
description:
A number of phandles to external blocks to set and clear the required
bits to enable or disable bus protection, necessary to avoid any bus
faults while enabling or disabling a power domain.
For example, this may hold phandles to INFRACFG and SMI.
minItems: 1
maxItems: 3
patternProperties:
"^power-domain@[0-9a-f]+$":
$ref: "#/$defs/power-domain-node"
@@ -123,14 +132,17 @@ $defs:
mediatek,infracfg:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle to the device containing the INFRACFG register range.
deprecated: true
mediatek,infracfg-nao:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle to the device containing the INFRACFG-NAO register range.
deprecated: true
mediatek,smi:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle to the device containing the SMI register range.
deprecated: true
required:
- reg
@@ -138,6 +150,31 @@ $defs:
required:
- compatible
allOf:
- if:
properties:
compatible:
contains:
enum:
- mediatek,mt8183-power-controller
then:
properties:
access-controllers:
minItems: 2
maxItems: 2
- if:
properties:
compatible:
contains:
enum:
- mediatek,mt8365-power-controller
then:
properties:
access-controllers:
minItems: 3
maxItems: 3
additionalProperties: false
examples:

View File

@@ -18,7 +18,9 @@ description:
properties:
compatible:
items:
- const: fsl,imx93-media-blk-ctrl
- enum:
- fsl,imx91-media-blk-ctrl
- fsl,imx93-media-blk-ctrl
- const: syscon
reg:
@@ -31,21 +33,54 @@ properties:
maxItems: 1
clocks:
minItems: 8
maxItems: 10
clock-names:
items:
- const: apb
- const: axi
- const: nic
- const: disp
- const: cam
- const: pxp
- const: lcdif
- const: isi
- const: csi
- const: dsi
minItems: 8
maxItems: 10
allOf:
- if:
properties:
compatible:
contains:
const: fsl,imx91-media-blk-ctrl
then:
properties:
clocks:
maxItems: 8
clock-names:
items:
- const: apb
- const: axi
- const: nic
- const: disp
- const: cam
- const: lcdif
- const: isi
- const: csi
- if:
properties:
compatible:
contains:
const: fsl,imx93-media-blk-ctrl
then:
properties:
clocks:
minItems: 10
clock-names:
items:
- const: apb
- const: axi
- const: nic
- const: disp
- const: cam
- const: pxp
- const: lcdif
- const: isi
- const: csi
- const: dsi
required:
- compatible
- reg

View File

@@ -2880,7 +2880,9 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm64/boot/dts/marvell/mmp/
F: drivers/clk/mmp/clk-pxa1908*.c
F: drivers/pmdomain/marvell/
F: include/dt-bindings/clock/marvell,pxa1908.h
F: include/dt-bindings/power/marvell,pxa1908-power.h
ARM/Mediatek RTC DRIVER
M: Eddie Huang <eddie.huang@mediatek.com>
@@ -21863,6 +21865,7 @@ F: drivers/mailbox/mailbox-th1520.c
F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
F: drivers/pinctrl/pinctrl-th1520.c
F: drivers/pmdomain/thead/
F: drivers/power/reset/th1520-aon-reboot.c
F: drivers/power/sequencing/pwrseq-thead-gpu.c
F: drivers/reset/reset-th1520.c
F: include/dt-bindings/clock/thead,th1520-clk-ap.h

View File

@@ -7,6 +7,7 @@ source "drivers/pmdomain/apple/Kconfig"
source "drivers/pmdomain/arm/Kconfig"
source "drivers/pmdomain/bcm/Kconfig"
source "drivers/pmdomain/imx/Kconfig"
source "drivers/pmdomain/marvell/Kconfig"
source "drivers/pmdomain/mediatek/Kconfig"
source "drivers/pmdomain/qcom/Kconfig"
source "drivers/pmdomain/renesas/Kconfig"

View File

@@ -5,6 +5,7 @@ obj-y += apple/
obj-y += arm/
obj-y += bcm/
obj-y += imx/
obj-y += marvell/
obj-y += mediatek/
obj-y += qcom/
obj-y += renesas/

View File

@@ -16,6 +16,9 @@
#include <dt-bindings/power/amlogic,t7-pwrc.h>
#include <dt-bindings/power/amlogic,a4-pwrc.h>
#include <dt-bindings/power/amlogic,a5-pwrc.h>
#include <dt-bindings/power/amlogic,s6-pwrc.h>
#include <dt-bindings/power/amlogic,s7-pwrc.h>
#include <dt-bindings/power/amlogic,s7d-pwrc.h>
#include <linux/arm-smccc.h>
#include <linux/firmware/meson/meson_sm.h>
#include <linux/module.h>
@@ -201,6 +204,71 @@ static const struct meson_secure_pwrc_domain_desc s4_pwrc_domains[] = {
SEC_PD(S4_AUDIO, 0),
};
static const struct meson_secure_pwrc_domain_desc s6_pwrc_domains[] = {
SEC_PD(S6_DSPA, 0),
SEC_PD(S6_DOS_HEVC, 0),
SEC_PD(S6_DOS_VDEC, 0),
SEC_PD(S6_VPU_HDMI, 0),
SEC_PD(S6_U2DRD, 0),
SEC_PD(S6_U3DRD, 0),
SEC_PD(S6_SD_EMMC_C, 0),
SEC_PD(S6_GE2D, 0),
SEC_PD(S6_AMFC, 0),
SEC_PD(S6_VC9000E, 0),
SEC_PD(S6_DEWARP, 0),
SEC_PD(S6_VICP, 0),
SEC_PD(S6_SD_EMMC_A, 0),
SEC_PD(S6_SD_EMMC_B, 0),
/* ETH is for ethernet online wakeup, and should be always on */
SEC_PD(S6_ETH, GENPD_FLAG_ALWAYS_ON),
SEC_PD(S6_PCIE, 0),
SEC_PD(S6_NNA_4T, 0),
SEC_PD(S6_AUDIO, 0),
SEC_PD(S6_AUCPU, 0),
SEC_PD(S6_ADAPT, 0),
};
static const struct meson_secure_pwrc_domain_desc s7_pwrc_domains[] = {
SEC_PD(S7_DOS_HEVC, 0),
SEC_PD(S7_DOS_VDEC, 0),
SEC_PD(S7_VPU_HDMI, 0),
SEC_PD(S7_USB_COMB, 0),
SEC_PD(S7_SD_EMMC_C, 0),
SEC_PD(S7_GE2D, 0),
SEC_PD(S7_SD_EMMC_A, 0),
SEC_PD(S7_SD_EMMC_B, 0),
/* ETH is for ethernet online wakeup, and should be always on */
SEC_PD(S7_ETH, GENPD_FLAG_ALWAYS_ON),
SEC_PD(S7_AUCPU, 0),
SEC_PD(S7_AUDIO, 0),
};
static const struct meson_secure_pwrc_domain_desc s7d_pwrc_domains[] = {
SEC_PD(S7D_DOS_HCODEC, 0),
SEC_PD(S7D_DOS_HEVC, 0),
SEC_PD(S7D_DOS_VDEC, 0),
SEC_PD(S7D_VPU_HDMI, 0),
SEC_PD(S7D_USB_U2DRD, 0),
SEC_PD(S7D_USB_U2H, 0),
SEC_PD(S7D_SSD_EMMC_C, 0),
SEC_PD(S7D_GE2D, 0),
SEC_PD(S7D_AMFC, 0),
SEC_PD(S7D_EMMC_A, 0),
SEC_PD(S7D_EMMC_B, 0),
/* ETH is for ethernet online wakeup, and should be always on */
SEC_PD(S7D_ETH, GENPD_FLAG_ALWAYS_ON),
SEC_PD(S7D_AUCPU, 0),
SEC_PD(S7D_AUDIO, 0),
/* SRAMA is used as ATF runtime memory, and should be always on */
SEC_PD(S7D_SRAMA, GENPD_FLAG_ALWAYS_ON),
/* DMC0 is for DDR PHY ana/dig and DMC, and should be always on */
SEC_PD(S7D_DMC0, GENPD_FLAG_ALWAYS_ON),
/* DMC1 is for DDR PHY ana/dig and DMC, and should be always on */
SEC_PD(S7D_DMC1, GENPD_FLAG_ALWAYS_ON),
/* DDR should be always on */
SEC_PD(S7D_DDR, GENPD_FLAG_ALWAYS_ON),
};
static const struct meson_secure_pwrc_domain_desc t7_pwrc_domains[] = {
SEC_PD(T7_DSPA, 0),
SEC_PD(T7_DSPB, 0),
@@ -367,6 +435,21 @@ static const struct meson_secure_pwrc_domain_data meson_secure_s4_pwrc_data = {
.count = ARRAY_SIZE(s4_pwrc_domains),
};
static const struct meson_secure_pwrc_domain_data amlogic_secure_s6_pwrc_data = {
.domains = s6_pwrc_domains,
.count = ARRAY_SIZE(s6_pwrc_domains),
};
static const struct meson_secure_pwrc_domain_data amlogic_secure_s7_pwrc_data = {
.domains = s7_pwrc_domains,
.count = ARRAY_SIZE(s7_pwrc_domains),
};
static const struct meson_secure_pwrc_domain_data amlogic_secure_s7d_pwrc_data = {
.domains = s7d_pwrc_domains,
.count = ARRAY_SIZE(s7d_pwrc_domains),
};
static const struct meson_secure_pwrc_domain_data amlogic_secure_t7_pwrc_data = {
.domains = t7_pwrc_domains,
.count = ARRAY_SIZE(t7_pwrc_domains),
@@ -393,6 +476,18 @@ static const struct of_device_id meson_secure_pwrc_match_table[] = {
.compatible = "amlogic,meson-s4-pwrc",
.data = &meson_secure_s4_pwrc_data,
},
{
.compatible = "amlogic,s6-pwrc",
.data = &amlogic_secure_s6_pwrc_data,
},
{
.compatible = "amlogic,s7-pwrc",
.data = &amlogic_secure_s7_pwrc_data,
},
{
.compatible = "amlogic,s7d-pwrc",
.data = &amlogic_secure_s7d_pwrc_data,
},
{
.compatible = "amlogic,t7-pwrc",
.data = &amlogic_secure_t7_pwrc_data,

View File

@@ -343,7 +343,6 @@ static const struct regmap_config imx_gpc_regmap_config = {
.rd_table = &access_table,
.wr_table = &access_table,
.max_register = 0x2ac,
.fast_io = true,
};
static struct generic_pm_domain *imx_gpc_onecell_domains[] = {

View File

@@ -86,6 +86,7 @@ struct imx93_blk_ctrl_domain {
struct imx93_blk_ctrl_data {
const struct imx93_blk_ctrl_domain_data *domains;
u32 skip_mask;
int num_domains;
const char * const *clk_names;
int num_clks;
@@ -250,6 +251,8 @@ static int imx93_blk_ctrl_probe(struct platform_device *pdev)
int j;
domain->data = data;
if (bc_data->skip_mask & BIT(i))
continue;
for (j = 0; j < data->num_clks; j++)
domain->clks[j].id = data->clk_names[j];
@@ -418,16 +421,32 @@ static const struct regmap_access_table imx93_media_blk_ctl_access_table = {
.n_yes_ranges = ARRAY_SIZE(imx93_media_blk_ctl_yes_ranges),
};
static const char * const media_blk_clk_names[] = {
"axi", "apb", "nic"
};
static const struct imx93_blk_ctrl_data imx91_media_blk_ctl_dev_data = {
.domains = imx93_media_blk_ctl_domain_data,
.skip_mask = BIT(IMX93_MEDIABLK_PD_MIPI_DSI) | BIT(IMX93_MEDIABLK_PD_PXP),
.num_domains = ARRAY_SIZE(imx93_media_blk_ctl_domain_data),
.clk_names = media_blk_clk_names,
.num_clks = ARRAY_SIZE(media_blk_clk_names),
.reg_access_table = &imx93_media_blk_ctl_access_table,
};
static const struct imx93_blk_ctrl_data imx93_media_blk_ctl_dev_data = {
.domains = imx93_media_blk_ctl_domain_data,
.num_domains = ARRAY_SIZE(imx93_media_blk_ctl_domain_data),
.clk_names = (const char *[]){ "axi", "apb", "nic", },
.num_clks = 3,
.clk_names = media_blk_clk_names,
.num_clks = ARRAY_SIZE(media_blk_clk_names),
.reg_access_table = &imx93_media_blk_ctl_access_table,
};
static const struct of_device_id imx93_blk_ctrl_of_match[] = {
{
.compatible = "fsl,imx91-media-blk-ctrl",
.data = &imx91_media_blk_ctl_dev_data
}, {
.compatible = "fsl,imx93-media-blk-ctrl",
.data = &imx93_media_blk_ctl_dev_data
}, {

View File

@@ -0,0 +1,18 @@
# SPDX-License-Identifier: GPL-2.0-only
menu "Marvell PM Domains"
depends on ARCH_MMP || COMPILE_TEST
config PXA1908_PM_DOMAINS
tristate "Marvell PXA1908 power domains"
depends on OF
depends on PM
default y if ARCH_MMP && ARM64
select AUXILIARY_BUS
select MFD_SYSCON
select PM_GENERIC_DOMAINS
select PM_GENERIC_DOMAINS_OF
help
Say Y here to enable support for Marvell PXA1908's power domanis.
endmenu

View File

@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_PXA1908_PM_DOMAINS) += pxa1908-power-controller.o

View File

@@ -0,0 +1,274 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2025 Duje Mihanović <duje@dujemihanovic.xyz>
*/
#include <linux/auxiliary_bus.h>
#include <linux/container_of.h>
#include <linux/dev_printk.h>
#include <linux/device.h>
#include <linux/mfd/syscon.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm_domain.h>
#include <linux/regmap.h>
#include <dt-bindings/power/marvell,pxa1908-power.h>
/* VPU, GPU, ISP */
#define APMU_PWR_CTRL_REG 0xd8
#define APMU_PWR_BLK_TMR_REG 0xdc
#define APMU_PWR_STATUS_REG 0xf0
/* DSI */
#define APMU_DEBUG 0x88
#define DSI_PHY_DVM_MASK BIT(31)
#define POWER_ON_LATENCY_US 300
#define POWER_OFF_LATENCY_US 20
#define POWER_POLL_TIMEOUT_US (25 * USEC_PER_MSEC)
#define POWER_POLL_SLEEP_US 6
#define NR_DOMAINS 5
#define to_pxa1908_pd(_genpd) container_of(_genpd, struct pxa1908_pd, genpd)
struct pxa1908_pd_ctrl {
struct generic_pm_domain *domains[NR_DOMAINS];
struct genpd_onecell_data onecell_data;
struct regmap *base;
struct device *dev;
};
struct pxa1908_pd_data {
u32 reg_clk_res_ctrl;
u32 pwr_state;
u32 hw_mode;
bool keep_on;
int id;
};
struct pxa1908_pd {
const struct pxa1908_pd_data data;
struct pxa1908_pd_ctrl *ctrl;
struct generic_pm_domain genpd;
bool initialized;
};
static inline bool pxa1908_pd_is_on(struct pxa1908_pd *pd)
{
struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
return pd->data.id != PXA1908_POWER_DOMAIN_DSI
? regmap_test_bits(ctrl->base, APMU_PWR_STATUS_REG, pd->data.pwr_state)
: regmap_test_bits(ctrl->base, APMU_DEBUG, DSI_PHY_DVM_MASK);
}
static int pxa1908_pd_power_on(struct generic_pm_domain *genpd)
{
struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
const struct pxa1908_pd_data *data = &pd->data;
struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
unsigned int status;
int ret = 0;
regmap_set_bits(ctrl->base, data->reg_clk_res_ctrl, data->hw_mode);
if (data->id != PXA1908_POWER_DOMAIN_ISP)
regmap_write(ctrl->base, APMU_PWR_BLK_TMR_REG, 0x20001fff);
regmap_set_bits(ctrl->base, APMU_PWR_CTRL_REG, data->pwr_state);
ret = regmap_read_poll_timeout(ctrl->base, APMU_PWR_STATUS_REG, status,
status & data->pwr_state, POWER_POLL_SLEEP_US,
POWER_ON_LATENCY_US + POWER_POLL_TIMEOUT_US);
if (ret == -ETIMEDOUT)
dev_err(ctrl->dev, "timed out powering on domain '%s'\n", pd->genpd.name);
return ret;
}
static int pxa1908_pd_power_off(struct generic_pm_domain *genpd)
{
struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
const struct pxa1908_pd_data *data = &pd->data;
struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
unsigned int status;
int ret;
regmap_clear_bits(ctrl->base, APMU_PWR_CTRL_REG, data->pwr_state);
ret = regmap_read_poll_timeout(ctrl->base, APMU_PWR_STATUS_REG, status,
!(status & data->pwr_state), POWER_POLL_SLEEP_US,
POWER_OFF_LATENCY_US + POWER_POLL_TIMEOUT_US);
if (ret == -ETIMEDOUT) {
dev_err(ctrl->dev, "timed out powering off domain '%s'\n", pd->genpd.name);
return ret;
}
return regmap_clear_bits(ctrl->base, data->reg_clk_res_ctrl, data->hw_mode);
}
static inline int pxa1908_dsi_power_on(struct generic_pm_domain *genpd)
{
struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
return regmap_set_bits(ctrl->base, APMU_DEBUG, DSI_PHY_DVM_MASK);
}
static inline int pxa1908_dsi_power_off(struct generic_pm_domain *genpd)
{
struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
return regmap_clear_bits(ctrl->base, APMU_DEBUG, DSI_PHY_DVM_MASK);
}
#define DOMAIN(_id, _name, ctrl, mode, state) \
[_id] = { \
.data = { \
.reg_clk_res_ctrl = ctrl, \
.hw_mode = BIT(mode), \
.pwr_state = BIT(state), \
.id = _id, \
}, \
.genpd = { \
.name = _name, \
.power_on = pxa1908_pd_power_on, \
.power_off = pxa1908_pd_power_off, \
}, \
}
static struct pxa1908_pd domains[NR_DOMAINS] = {
DOMAIN(PXA1908_POWER_DOMAIN_VPU, "vpu", 0xa4, 19, 2),
DOMAIN(PXA1908_POWER_DOMAIN_GPU, "gpu", 0xcc, 11, 0),
DOMAIN(PXA1908_POWER_DOMAIN_GPU2D, "gpu2d", 0xf4, 11, 6),
DOMAIN(PXA1908_POWER_DOMAIN_ISP, "isp", 0x38, 15, 4),
[PXA1908_POWER_DOMAIN_DSI] = {
.genpd = {
.name = "dsi",
.power_on = pxa1908_dsi_power_on,
.power_off = pxa1908_dsi_power_off,
/*
* TODO: There is no DSI driver written yet and until then we probably
* don't want to power off the DSI PHY ever.
*/
.flags = GENPD_FLAG_ALWAYS_ON,
},
.data = {
/* See above. */
.keep_on = true,
},
},
};
static void pxa1908_pd_remove(struct auxiliary_device *auxdev)
{
struct pxa1908_pd *pd;
int ret;
for (int i = NR_DOMAINS - 1; i >= 0; i--) {
pd = &domains[i];
if (!pd->initialized)
continue;
if (pxa1908_pd_is_on(pd) && !pd->data.keep_on)
pxa1908_pd_power_off(&pd->genpd);
ret = pm_genpd_remove(&pd->genpd);
if (ret)
dev_err(&auxdev->dev, "failed to remove domain '%s': %d\n",
pd->genpd.name, ret);
}
}
static int
pxa1908_pd_init(struct pxa1908_pd_ctrl *ctrl, int id, struct device *dev)
{
struct pxa1908_pd *pd = &domains[id];
int ret;
ctrl->domains[id] = &pd->genpd;
pd->ctrl = ctrl;
/* Make sure the state of the hardware is synced with the domain table above. */
if (pd->data.keep_on) {
ret = pd->genpd.power_on(&pd->genpd);
if (ret)
return dev_err_probe(dev, ret, "failed to power on domain '%s'\n",
pd->genpd.name);
} else {
if (pxa1908_pd_is_on(pd)) {
dev_warn(dev,
"domain '%s' is on despite being default off; powering off\n",
pd->genpd.name);
ret = pd->genpd.power_off(&pd->genpd);
if (ret)
return dev_err_probe(dev, ret,
"failed to power off domain '%s'\n",
pd->genpd.name);
}
}
ret = pm_genpd_init(&pd->genpd, NULL, !pd->data.keep_on);
if (ret)
return dev_err_probe(dev, ret, "domain '%s' failed to initialize\n",
pd->genpd.name);
pd->initialized = true;
return 0;
}
static int
pxa1908_pd_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *aux_id)
{
struct pxa1908_pd_ctrl *ctrl;
struct device *dev = &auxdev->dev;
int ret;
ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
if (!ctrl)
return -ENOMEM;
auxiliary_set_drvdata(auxdev, ctrl);
ctrl->base = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(ctrl->base))
return dev_err_probe(dev, PTR_ERR(ctrl->base), "no regmap available\n");
ctrl->dev = dev;
ctrl->onecell_data.domains = ctrl->domains;
ctrl->onecell_data.num_domains = NR_DOMAINS;
for (int i = 0; i < NR_DOMAINS; i++) {
ret = pxa1908_pd_init(ctrl, i, dev);
if (ret)
goto err;
}
return of_genpd_add_provider_onecell(dev->parent->of_node, &ctrl->onecell_data);
err:
pxa1908_pd_remove(auxdev);
return ret;
}
static const struct auxiliary_device_id pxa1908_pd_id[] = {
{ .name = "clk_pxa1908_apmu.power" },
{ }
};
MODULE_DEVICE_TABLE(auxiliary, pxa1908_pd_id);
static struct auxiliary_driver pxa1908_pd_driver = {
.probe = pxa1908_pd_probe,
.remove = pxa1908_pd_remove,
.id_table = pxa1908_pd_id,
};
module_auxiliary_driver(pxa1908_pd_driver);
MODULE_AUTHOR("Duje Mihanović <duje@dujemihanovic.xyz>");
MODULE_DESCRIPTION("Marvell PXA1908 power domain driver");
MODULE_LICENSE("GPL");

View File

@@ -21,10 +21,10 @@ struct airoha_cpu_pmdomain_priv {
struct generic_pm_domain pd;
};
static long airoha_cpu_pmdomain_clk_round(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int airoha_cpu_pmdomain_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return rate;
return 0;
}
static unsigned long airoha_cpu_pmdomain_clk_get(struct clk_hw *hw,
@@ -48,7 +48,7 @@ static int airoha_cpu_pmdomain_clk_is_enabled(struct clk_hw *hw)
static const struct clk_ops airoha_cpu_pmdomain_clk_ops = {
.recalc_rate = airoha_cpu_pmdomain_clk_get,
.is_enabled = airoha_cpu_pmdomain_clk_is_enabled,
.round_rate = airoha_cpu_pmdomain_clk_round,
.determine_rate = airoha_cpu_pmdomain_clk_determine_rate,
};
static int airoha_cpu_pmdomain_set_performance_state(struct generic_pm_domain *domain,

View File

@@ -9,6 +9,9 @@
/*
* MT6795 power domain support
*/
static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt6795[] = {
BUS_PROT_BLOCK_INFRA
};
static const struct scpsys_domain_data scpsys_domain_data_mt6795[] = {
[MT6795_POWER_DOMAIN_VDEC] = {
@@ -107,6 +110,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt6795[] = {
static const struct scpsys_soc_data mt6795_scpsys_data = {
.domains_data = scpsys_domain_data_mt6795,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt6795),
.bus_prot_blocks = scpsys_bus_prot_blocks_mt6795,
.num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt6795),
};
#endif /* __SOC_MEDIATEK_MT6795_PM_DOMAINS_H */

View File

@@ -12,6 +12,9 @@
/*
* MT8167 power domain support
*/
static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8167[] = {
BUS_PROT_BLOCK_INFRA
};
static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = {
[MT8167_POWER_DOMAIN_MM] = {
@@ -99,6 +102,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = {
static const struct scpsys_soc_data mt8167_scpsys_data = {
.domains_data = scpsys_domain_data_mt8167,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8167),
.bus_prot_blocks = scpsys_bus_prot_blocks_mt8167,
.num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8167),
};
#endif /* __SOC_MEDIATEK_MT8167_PM_DOMAINS_H */

View File

@@ -9,6 +9,9 @@
/*
* MT8173 power domain support
*/
static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8173[] = {
BUS_PROT_BLOCK_INFRA
};
static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = {
[MT8173_POWER_DOMAIN_VDEC] = {
@@ -118,6 +121,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = {
static const struct scpsys_soc_data mt8173_scpsys_data = {
.domains_data = scpsys_domain_data_mt8173,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8173),
.bus_prot_blocks = scpsys_bus_prot_blocks_mt8173,
.num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8173),
};
#endif /* __SOC_MEDIATEK_MT8173_PM_DOMAINS_H */

View File

@@ -9,6 +9,9 @@
/*
* MT8183 power domain support
*/
static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8183[] = {
BUS_PROT_BLOCK_INFRA, BUS_PROT_BLOCK_SMI
};
static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
[MT8183_POWER_DOMAIN_AUDIO] = {
@@ -290,6 +293,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
static const struct scpsys_soc_data mt8183_scpsys_data = {
.domains_data = scpsys_domain_data_mt8183,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8183),
.bus_prot_blocks = scpsys_bus_prot_blocks_mt8183,
.num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8183),
};
#endif /* __SOC_MEDIATEK_MT8183_PM_DOMAINS_H */

View File

@@ -13,6 +13,9 @@
/*
* MT8186 power domain support
*/
static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8186[] = {
BUS_PROT_BLOCK_INFRA
};
static const struct scpsys_domain_data scpsys_domain_data_mt8186[] = {
[MT8186_POWER_DOMAIN_MFG0] = {
@@ -361,6 +364,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8186[] = {
static const struct scpsys_soc_data mt8186_scpsys_data = {
.domains_data = scpsys_domain_data_mt8186,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8186),
.bus_prot_blocks = scpsys_bus_prot_blocks_mt8186,
.num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8186),
};
#endif /* __SOC_MEDIATEK_MT8186_PM_DOMAINS_H */

View File

@@ -14,6 +14,10 @@
* MT8188 power domain support
*/
static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8188[] = {
BUS_PROT_BLOCK_INFRA
};
static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
[MT8188_POWER_DOMAIN_MFG0] = {
.name = "mfg0",
@@ -685,6 +689,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
static const struct scpsys_soc_data mt8188_scpsys_data = {
.domains_data = scpsys_domain_data_mt8188,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8188),
.bus_prot_blocks = scpsys_bus_prot_blocks_mt8188,
.num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8188),
};
#endif /* __SOC_MEDIATEK_MT8188_PM_DOMAINS_H */

View File

@@ -9,6 +9,9 @@
/*
* MT8192 power domain support
*/
static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8192[] = {
BUS_PROT_BLOCK_INFRA
};
static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = {
[MT8192_POWER_DOMAIN_AUDIO] = {
@@ -380,6 +383,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = {
static const struct scpsys_soc_data mt8192_scpsys_data = {
.domains_data = scpsys_domain_data_mt8192,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8192),
.bus_prot_blocks = scpsys_bus_prot_blocks_mt8192,
.num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8192),
};
#endif /* __SOC_MEDIATEK_MT8192_PM_DOMAINS_H */

View File

@@ -13,6 +13,9 @@
/*
* MT8195 power domain support
*/
static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8195[] = {
BUS_PROT_BLOCK_INFRA
};
static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = {
[MT8195_POWER_DOMAIN_PCIE_MAC_P0] = {
@@ -662,6 +665,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = {
static const struct scpsys_soc_data mt8195_scpsys_data = {
.domains_data = scpsys_domain_data_mt8195,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8195),
.bus_prot_blocks = scpsys_bus_prot_blocks_mt8195,
.num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8195),
};
#endif /* __SOC_MEDIATEK_MT8195_PM_DOMAINS_H */

View File

@@ -29,11 +29,13 @@
MT8365_SMI_COMMON_CLAMP_EN)
#define MT8365_BUS_PROT_WAY_EN(_set_mask, _set, _sta_mask, _sta) \
_BUS_PROT(_set_mask, _set, _set, _sta_mask, _sta, \
BUS_PROT_COMPONENT_INFRA | \
BUS_PROT_STA_COMPONENT_INFRA_NAO | \
BUS_PROT_INVERTED | \
BUS_PROT_REG_UPDATE)
_BUS_PROT_STA(INFRA, INFRA_NAO, _set_mask, _set, _set, \
_sta_mask, _sta, \
BUS_PROT_INVERTED | BUS_PROT_REG_UPDATE)
static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8365[] = {
BUS_PROT_BLOCK_INFRA, BUS_PROT_BLOCK_INFRA_NAO, BUS_PROT_BLOCK_SMI
};
static const struct scpsys_domain_data scpsys_domain_data_mt8365[] = {
[MT8365_POWER_DOMAIN_MM] = {
@@ -192,6 +194,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8365[] = {
static const struct scpsys_soc_data mt8365_scpsys_data = {
.domains_data = scpsys_domain_data_mt8365,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8365),
.bus_prot_blocks = scpsys_bus_prot_blocks_mt8365,
.num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8365),
};
#endif /* __SOC_MEDIATEK_MT8365_PM_DOMAINS_H */

View File

@@ -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;
@@ -47,9 +53,6 @@ struct scpsys_domain {
struct clk_bulk_data *clks;
int num_subsys_clks;
struct clk_bulk_data *subsys_clks;
struct regmap *infracfg_nao;
struct regmap *infracfg;
struct regmap *smi;
struct regulator *supply;
};
@@ -57,6 +60,8 @@ struct scpsys {
struct device *dev;
struct regmap *base;
const struct scpsys_soc_data *soc_data;
u8 bus_prot_index[BUS_PROT_BLOCK_COUNT];
struct regmap **bus_prot;
struct genpd_onecell_data pd_data;
struct generic_pm_domain *domains[];
};
@@ -80,16 +85,23 @@ static bool scpsys_domain_is_on(struct scpsys_domain *pd)
static int scpsys_sram_enable(struct scpsys_domain *pd)
{
u32 pdn_ack = pd->data->sram_pdn_ack_bits;
u32 expected_ack, pdn_ack = pd->data->sram_pdn_ack_bits;
struct scpsys *scpsys = pd->scpsys;
unsigned int tmp;
int ret;
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_PDN_INVERTED)) {
regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
expected_ack = pdn_ack;
} else {
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
expected_ack = 0;
}
/* Either wait until SRAM_PDN_ACK all 1 or 0 */
ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
(tmp & pdn_ack) == 0, MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
(tmp & pdn_ack) == expected_ack,
MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
if (ret < 0)
return ret;
@@ -104,7 +116,7 @@ static int scpsys_sram_enable(struct scpsys_domain *pd)
static int scpsys_sram_disable(struct scpsys_domain *pd)
{
u32 pdn_ack = pd->data->sram_pdn_ack_bits;
u32 expected_ack, pdn_ack = pd->data->sram_pdn_ack_bits;
struct scpsys *scpsys = pd->scpsys;
unsigned int tmp;
@@ -114,30 +126,36 @@ static int scpsys_sram_disable(struct scpsys_domain *pd)
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
}
regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_PDN_INVERTED)) {
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
expected_ack = 0;
} else {
regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
expected_ack = pdn_ack;
}
/* Either wait until SRAM_PDN_ACK all 1 or 0 */
return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
(tmp & pdn_ack) == pdn_ack, MTK_POLL_DELAY_US,
MTK_POLL_TIMEOUT);
(tmp & pdn_ack) == expected_ack,
MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
}
static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd,
const struct scpsys_bus_prot_data *bpd)
{
if (bpd->flags & BUS_PROT_COMPONENT_SMI)
return pd->smi;
else
return pd->infracfg;
struct scpsys *scpsys = pd->scpsys;
unsigned short block_idx = scpsys->bus_prot_index[bpd->bus_prot_block];
return scpsys->bus_prot[block_idx];
}
static struct regmap *scpsys_bus_protect_get_sta_regmap(struct scpsys_domain *pd,
const struct scpsys_bus_prot_data *bpd)
{
if (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO)
return pd->infracfg_nao;
else
return scpsys_bus_protect_get_regmap(pd, bpd);
struct scpsys *scpsys = pd->scpsys;
int block_idx = scpsys->bus_prot_index[bpd->bus_prot_sta_block];
return scpsys->bus_prot[block_idx];
}
static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
@@ -149,7 +167,7 @@ static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
u32 expected_ack;
u32 val;
expected_ack = (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO ? sta_mask : 0);
expected_ack = (bpd->bus_prot_sta_block == BUS_PROT_BLOCK_INFRA_NAO ? sta_mask : 0);
if (bpd->flags & BUS_PROT_REG_UPDATE)
regmap_clear_bits(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask);
@@ -232,11 +250,161 @@ static int scpsys_regulator_disable(struct regulator *supply)
return supply ? regulator_disable(supply) : 0;
}
static int scpsys_ctl_pwrseq_on(struct scpsys_domain *pd)
{
struct scpsys *scpsys = pd->scpsys;
bool do_rtff_nrestore, tmp;
int ret;
/* subsys power on */
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
/* wait until PWR_ACK = 1 */
ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US,
MTK_POLL_TIMEOUT);
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;
}
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);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
}
static int scpsys_modem_pwrseq_on(struct scpsys_domain *pd)
{
struct scpsys *scpsys = pd->scpsys;
bool tmp;
int ret;
if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SKIP_RESET_B))
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
/* wait until PWR_ACK = 1 */
ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US,
MTK_POLL_TIMEOUT);
if (ret < 0)
return ret;
return 0;
}
static void scpsys_modem_pwrseq_off(struct scpsys_domain *pd)
{
struct scpsys *scpsys = pd->scpsys;
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SKIP_RESET_B))
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
}
static int scpsys_power_on(struct generic_pm_domain *genpd)
{
struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
struct scpsys *scpsys = pd->scpsys;
bool tmp;
int ret;
ret = scpsys_regulator_enable(pd->supply);
@@ -251,20 +419,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs,
pd->data->ext_buck_iso_mask);
/* subsys power on */
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
ret = scpsys_modem_pwrseq_on(pd);
else
ret = scpsys_ctl_pwrseq_on(pd);
/* wait until PWR_ACK = 1 */
ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US,
MTK_POLL_TIMEOUT);
if (ret < 0)
if (ret)
goto err_pwr_ack;
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);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
/*
* In few Mediatek platforms(e.g. MT6779), the bus protect policy is
* stricter, which leads to bus protect release must be prior to bus
@@ -330,12 +492,10 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
/* subsys power off */
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
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);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
scpsys_modem_pwrseq_off(pd);
else
scpsys_ctl_pwrseq_off(pd);
/* wait until PWR_ACK = 0 */
ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
@@ -355,7 +515,6 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
{
const struct scpsys_domain_data *domain_data;
struct scpsys_domain *pd;
struct device_node *smi_node;
struct property *prop;
const char *clk_name;
int i, ret, num_clks;
@@ -396,32 +555,6 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
node);
}
pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg");
if (IS_ERR(pd->infracfg))
return dev_err_cast_probe(scpsys->dev, pd->infracfg,
"%pOF: failed to get infracfg regmap\n",
node);
smi_node = of_parse_phandle(node, "mediatek,smi", 0);
if (smi_node) {
pd->smi = device_node_to_regmap(smi_node);
of_node_put(smi_node);
if (IS_ERR(pd->smi))
return dev_err_cast_probe(scpsys->dev, pd->smi,
"%pOF: failed to get SMI regmap\n",
node);
}
if (MTK_SCPD_CAPS(pd, MTK_SCPD_HAS_INFRA_NAO)) {
pd->infracfg_nao = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
if (IS_ERR(pd->infracfg_nao))
return dev_err_cast_probe(scpsys->dev, pd->infracfg_nao,
"%pOF: failed to get infracfg-nao regmap\n",
node);
} else {
pd->infracfg_nao = NULL;
}
num_clks = of_clk_get_parent_count(node);
if (num_clks > 0) {
/* Calculate number of subsys_clks */
@@ -615,6 +748,136 @@ static void scpsys_domain_cleanup(struct scpsys *scpsys)
}
}
static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *scpsys)
{
const u8 bp_blocks[3] = {
BUS_PROT_BLOCK_INFRA, BUS_PROT_BLOCK_SMI, BUS_PROT_BLOCK_INFRA_NAO
};
struct device_node *np = dev->of_node;
struct device_node *node, *smi_np;
int num_regmaps = 0, i, j;
struct regmap *regmap[3];
/*
* Legacy code retrieves a maximum of three bus protection handles:
* some may be optional, or may not be, so the array of bp blocks
* that is normally passed in as platform data must be dynamically
* built in this case.
*
* Here, try to retrieve all of the regmaps that the legacy code
* supported and then count the number of the ones that are present,
* this makes it then possible to allocate the array of bus_prot
* regmaps and convert all to the new style handling.
*/
node = of_find_node_with_property(np, "mediatek,infracfg");
if (node) {
regmap[0] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg");
of_node_put(node);
num_regmaps++;
if (IS_ERR(regmap[0]))
return dev_err_probe(dev, PTR_ERR(regmap[0]),
"%pOF: failed to get infracfg regmap\n",
node);
} else {
regmap[0] = NULL;
}
node = of_find_node_with_property(np, "mediatek,smi");
if (node) {
smi_np = of_parse_phandle(node, "mediatek,smi", 0);
of_node_put(node);
if (!smi_np)
return -ENODEV;
regmap[1] = device_node_to_regmap(smi_np);
num_regmaps++;
of_node_put(smi_np);
if (IS_ERR(regmap[1]))
return dev_err_probe(dev, PTR_ERR(regmap[1]),
"%pOF: failed to get SMI regmap\n",
node);
} else {
regmap[1] = NULL;
}
node = of_find_node_with_property(np, "mediatek,infracfg-nao");
if (node) {
regmap[2] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
num_regmaps++;
of_node_put(node);
if (IS_ERR(regmap[2]))
return dev_err_probe(dev, PTR_ERR(regmap[2]),
"%pOF: failed to get infracfg regmap\n",
node);
} else {
regmap[2] = NULL;
}
scpsys->bus_prot = devm_kmalloc_array(dev, num_regmaps,
sizeof(*scpsys->bus_prot), GFP_KERNEL);
if (!scpsys->bus_prot)
return -ENOMEM;
for (i = 0, j = 0; i < ARRAY_SIZE(bp_blocks); i++) {
enum scpsys_bus_prot_block bp_type;
if (!regmap[i])
continue;
bp_type = bp_blocks[i];
scpsys->bus_prot_index[bp_type] = j;
scpsys->bus_prot[j] = regmap[i];
j++;
}
return 0;
}
static int scpsys_get_bus_protection(struct device *dev, struct scpsys *scpsys)
{
const struct scpsys_soc_data *soc = scpsys->soc_data;
struct device_node *np = dev->of_node;
int i, num_handles;
num_handles = of_count_phandle_with_args(np, "access-controllers", NULL);
if (num_handles < 0 || num_handles != soc->num_bus_prot_blocks)
return dev_err_probe(dev, -EINVAL,
"Cannot get access controllers: expected %u, got %d\n",
soc->num_bus_prot_blocks, num_handles);
scpsys->bus_prot = devm_kmalloc_array(dev, soc->num_bus_prot_blocks,
sizeof(*scpsys->bus_prot), GFP_KERNEL);
if (!scpsys->bus_prot)
return -ENOMEM;
for (i = 0; i < soc->num_bus_prot_blocks; i++) {
enum scpsys_bus_prot_block bp_type;
struct device_node *node;
node = of_parse_phandle(np, "access-controllers", i);
if (!node)
return -EINVAL;
/*
* Index the bus protection regmaps so that we don't have to
* find the right one by type with a loop at every execution
* of power sequence(s).
*/
bp_type = soc->bus_prot_blocks[i];
scpsys->bus_prot_index[bp_type] = i;
scpsys->bus_prot[i] = device_node_to_regmap(node);
of_node_put(node);
if (IS_ERR_OR_NULL(scpsys->bus_prot[i]))
return dev_err_probe(dev, scpsys->bus_prot[i] ?
PTR_ERR(scpsys->bus_prot[i]) : -ENXIO,
"Cannot get regmap for access controller %d\n", i);
}
return 0;
}
static const struct of_device_id scpsys_of_match[] = {
{
.compatible = "mediatek,mt6735-power-controller",
@@ -701,6 +964,14 @@ static int scpsys_probe(struct platform_device *pdev)
return PTR_ERR(scpsys->base);
}
if (of_find_property(np, "access-controllers", NULL))
ret = scpsys_get_bus_protection(dev, scpsys);
else
ret = scpsys_get_bus_protection_legacy(dev, scpsys);
if (ret)
return ret;
ret = -ENODEV;
for_each_available_child_of_node(np, node) {
struct generic_pm_domain *domain;

View File

@@ -13,6 +13,9 @@
#define MTK_SCPD_EXT_BUCK_ISO BIT(6)
#define MTK_SCPD_HAS_INFRA_NAO BIT(7)
#define MTK_SCPD_STRICT_BUS_PROTECTION BIT(8)
#define MTK_SCPD_SRAM_PDN_INVERTED BIT(9)
#define MTK_SCPD_MODEM_PWRSEQ BIT(10)
#define MTK_SCPD_SKIP_RESET_B BIT(11)
#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x))
#define SPM_VDE_PWR_CON 0x0210
@@ -50,30 +53,43 @@ enum scpsys_bus_prot_flags {
BUS_PROT_REG_UPDATE = BIT(1),
BUS_PROT_IGNORE_CLR_ACK = BIT(2),
BUS_PROT_INVERTED = BIT(3),
BUS_PROT_COMPONENT_INFRA = BIT(4),
BUS_PROT_COMPONENT_SMI = BIT(5),
BUS_PROT_STA_COMPONENT_INFRA_NAO = BIT(6),
};
#define _BUS_PROT(_set_clr_mask, _set, _clr, _sta_mask, _sta, _flags) { \
.bus_prot_set_clr_mask = (_set_clr_mask), \
.bus_prot_set = _set, \
.bus_prot_clr = _clr, \
.bus_prot_sta_mask = (_sta_mask), \
.bus_prot_sta = _sta, \
.flags = _flags \
enum scpsys_bus_prot_block {
BUS_PROT_BLOCK_INFRA,
BUS_PROT_BLOCK_INFRA_NAO,
BUS_PROT_BLOCK_SMI,
BUS_PROT_BLOCK_COUNT,
};
#define _BUS_PROT_STA(_hwip, _sta_hwip, _set_clr_mask, _set, _clr, \
_sta_mask, _sta, _flags) \
{ \
.bus_prot_block = BUS_PROT_BLOCK_##_hwip, \
.bus_prot_sta_block = BUS_PROT_BLOCK_##_sta_hwip, \
.bus_prot_set_clr_mask = (_set_clr_mask), \
.bus_prot_set = _set, \
.bus_prot_clr = _clr, \
.bus_prot_sta_mask = (_sta_mask), \
.bus_prot_sta = _sta, \
.flags = _flags \
}
#define BUS_PROT_WR(_hwip, _mask, _set, _clr, _sta) \
_BUS_PROT(_mask, _set, _clr, _mask, _sta, BUS_PROT_COMPONENT_##_hwip)
#define _BUS_PROT(_hwip, _set_clr_mask, _set, _clr, _sta_mask, \
_sta, _flags) \
_BUS_PROT_STA(_hwip, _hwip, _set_clr_mask, _set, _clr, \
_sta_mask, _sta, _flags)
#define BUS_PROT_WR_IGN(_hwip, _mask, _set, _clr, _sta) \
_BUS_PROT(_mask, _set, _clr, _mask, _sta, \
BUS_PROT_COMPONENT_##_hwip | BUS_PROT_IGNORE_CLR_ACK)
#define BUS_PROT_WR(_hwip, _mask, _set, _clr, _sta) \
_BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, 0)
#define BUS_PROT_UPDATE(_hwip, _mask, _set, _clr, _sta) \
_BUS_PROT(_mask, _set, _clr, _mask, _sta, \
BUS_PROT_COMPONENT_##_hwip | BUS_PROT_REG_UPDATE)
#define BUS_PROT_WR_IGN(_hwip, _mask, _set, _clr, _sta) \
_BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, \
BUS_PROT_IGNORE_CLR_ACK)
#define BUS_PROT_UPDATE(_hwip, _mask, _set, _clr, _sta) \
_BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, \
BUS_PROT_REG_UPDATE)
#define BUS_PROT_INFRA_UPDATE_TOPAXI(_mask) \
BUS_PROT_UPDATE(INFRA, _mask, \
@@ -82,6 +98,8 @@ enum scpsys_bus_prot_flags {
INFRA_TOPAXI_PROTECTSTA1)
struct scpsys_bus_prot_data {
u8 bus_prot_block;
u8 bus_prot_sta_block;
u32 bus_prot_set_clr_mask;
u32 bus_prot_set;
u32 bus_prot_clr;
@@ -90,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.
@@ -100,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 {
@@ -111,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;
@@ -119,6 +155,8 @@ struct scpsys_domain_data {
struct scpsys_soc_data {
const struct scpsys_domain_data *domains_data;
int num_domains;
enum scpsys_bus_prot_block *bus_prot_blocks;
int num_bus_prot_blocks;
};
#endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */

View File

@@ -631,12 +631,12 @@ static struct rpmpd ssc_mx_rwsm0_vfl = {
};
static struct rpmpd *mdm9607_rpmpds[] = {
[MDM9607_VDDCX] = &cx_s3a_lvl,
[MDM9607_VDDCX_AO] = &cx_s3a_lvl_ao,
[MDM9607_VDDCX_VFL] = &cx_s3a_vfl,
[MDM9607_VDDMX] = &mx_l12a_lvl,
[MDM9607_VDDMX_AO] = &mx_l12a_lvl_ao,
[MDM9607_VDDMX_VFL] = &mx_l12a_vfl,
[RPMPD_VDDCX] = &cx_s3a_lvl,
[RPMPD_VDDCX_AO] = &cx_s3a_lvl_ao,
[RPMPD_VDDCX_VFL] = &cx_s3a_vfl,
[RPMPD_VDDMX] = &mx_l12a_lvl,
[RPMPD_VDDMX_AO] = &mx_l12a_lvl_ao,
[RPMPD_VDDMX_VFL] = &mx_l12a_vfl,
};
static const struct rpmpd_desc mdm9607_desc = {
@@ -646,9 +646,9 @@ static const struct rpmpd_desc mdm9607_desc = {
};
static struct rpmpd *msm8226_rpmpds[] = {
[MSM8226_VDDCX] = &cx_s1a_corner,
[MSM8226_VDDCX_AO] = &cx_s1a_corner_ao,
[MSM8226_VDDCX_VFC] = &cx_s1a_vfc,
[RPMPD_VDDCX] = &cx_s1a_corner,
[RPMPD_VDDCX_AO] = &cx_s1a_corner_ao,
[RPMPD_VDDCX_VFC] = &cx_s1a_vfc,
};
static const struct rpmpd_desc msm8226_desc = {
@@ -675,11 +675,11 @@ static const struct rpmpd_desc msm8939_desc = {
};
static struct rpmpd *msm8916_rpmpds[] = {
[MSM8916_VDDCX] = &cx_s1a_corner,
[MSM8916_VDDCX_AO] = &cx_s1a_corner_ao,
[MSM8916_VDDCX_VFC] = &cx_s1a_vfc,
[MSM8916_VDDMX] = &mx_l3a_corner,
[MSM8916_VDDMX_AO] = &mx_l3a_corner_ao,
[RPMPD_VDDCX] = &cx_s1a_corner,
[RPMPD_VDDCX_AO] = &cx_s1a_corner_ao,
[RPMPD_VDDCX_VFC] = &cx_s1a_vfc,
[RPMPD_VDDMX] = &mx_l3a_corner,
[RPMPD_VDDMX_AO] = &mx_l3a_corner_ao,
};
static const struct rpmpd_desc msm8916_desc = {
@@ -689,11 +689,11 @@ static const struct rpmpd_desc msm8916_desc = {
};
static struct rpmpd *msm8917_rpmpds[] = {
[MSM8917_VDDCX] = &cx_s2a_lvl,
[MSM8917_VDDCX_AO] = &cx_s2a_lvl_ao,
[MSM8917_VDDCX_VFL] = &cx_s2a_vfl,
[MSM8917_VDDMX] = &mx_l3a_lvl,
[MSM8917_VDDMX_AO] = &mx_l3a_lvl_ao,
[RPMPD_VDDCX] = &cx_s2a_lvl,
[RPMPD_VDDCX_AO] = &cx_s2a_lvl_ao,
[RPMPD_VDDCX_VFL] = &cx_s2a_vfl,
[RPMPD_VDDMX] = &mx_l3a_lvl,
[RPMPD_VDDMX_AO] = &mx_l3a_lvl_ao,
};
static const struct rpmpd_desc msm8917_desc = {
@@ -747,12 +747,12 @@ static const struct rpmpd_desc msm8974pro_pma8084_desc = {
};
static struct rpmpd *msm8976_rpmpds[] = {
[MSM8976_VDDCX] = &cx_s2a_lvl,
[MSM8976_VDDCX_AO] = &cx_s2a_lvl_ao,
[MSM8976_VDDCX_VFL] = &cx_rwsc2_vfl,
[MSM8976_VDDMX] = &mx_s6a_lvl,
[MSM8976_VDDMX_AO] = &mx_s6a_lvl_ao,
[MSM8976_VDDMX_VFL] = &mx_rwsm6_vfl,
[RPMPD_VDDCX] = &cx_s2a_lvl,
[RPMPD_VDDCX_AO] = &cx_s2a_lvl_ao,
[RPMPD_VDDCX_VFL] = &cx_rwsc2_vfl,
[RPMPD_VDDMX] = &mx_s6a_lvl,
[RPMPD_VDDMX_AO] = &mx_s6a_lvl_ao,
[RPMPD_VDDMX_VFL] = &mx_rwsm6_vfl,
};
static const struct rpmpd_desc msm8976_desc = {
@@ -796,16 +796,16 @@ static const struct rpmpd_desc msm8996_desc = {
};
static struct rpmpd *msm8998_rpmpds[] = {
[MSM8998_VDDCX] = &cx_rwcx0_lvl,
[MSM8998_VDDCX_AO] = &cx_rwcx0_lvl_ao,
[MSM8998_VDDCX_VFL] = &cx_rwcx0_vfl,
[MSM8998_VDDMX] = &mx_rwmx0_lvl,
[MSM8998_VDDMX_AO] = &mx_rwmx0_lvl_ao,
[MSM8998_VDDMX_VFL] = &mx_rwmx0_vfl,
[MSM8998_SSCCX] = &ssc_cx_rwsc0_lvl,
[MSM8998_SSCCX_VFL] = &ssc_cx_rwsc0_vfl,
[MSM8998_SSCMX] = &ssc_mx_rwsm0_lvl,
[MSM8998_SSCMX_VFL] = &ssc_mx_rwsm0_vfl,
[RPMPD_VDDCX] = &cx_rwcx0_lvl,
[RPMPD_VDDCX_AO] = &cx_rwcx0_lvl_ao,
[RPMPD_VDDCX_VFL] = &cx_rwcx0_vfl,
[RPMPD_VDDMX] = &mx_rwmx0_lvl,
[RPMPD_VDDMX_AO] = &mx_rwmx0_lvl_ao,
[RPMPD_VDDMX_VFL] = &mx_rwmx0_vfl,
[RPMPD_SSCCX] = &ssc_cx_rwsc0_lvl,
[RPMPD_SSCCX_VFL] = &ssc_cx_rwsc0_vfl,
[RPMPD_SSCMX] = &ssc_mx_rwsm0_lvl,
[RPMPD_SSCMX_VFL] = &ssc_mx_rwsm0_vfl,
};
static const struct rpmpd_desc msm8998_desc = {
@@ -831,11 +831,11 @@ static const struct rpmpd_desc qcs404_desc = {
};
static struct rpmpd *qm215_rpmpds[] = {
[QM215_VDDCX] = &cx_s1a_lvl,
[QM215_VDDCX_AO] = &cx_s1a_lvl_ao,
[QM215_VDDCX_VFL] = &cx_s1a_vfl,
[QM215_VDDMX] = &mx_l2a_lvl,
[QM215_VDDMX_AO] = &mx_l2a_lvl_ao,
[RPMPD_VDDCX] = &cx_s1a_lvl,
[RPMPD_VDDCX_AO] = &cx_s1a_lvl_ao,
[RPMPD_VDDCX_VFL] = &cx_s1a_vfl,
[RPMPD_VDDMX] = &mx_l2a_lvl,
[RPMPD_VDDMX_AO] = &mx_l2a_lvl_ao,
};
static const struct rpmpd_desc qm215_desc = {
@@ -845,16 +845,16 @@ static const struct rpmpd_desc qm215_desc = {
};
static struct rpmpd *sdm660_rpmpds[] = {
[SDM660_VDDCX] = &cx_rwcx0_lvl,
[SDM660_VDDCX_AO] = &cx_rwcx0_lvl_ao,
[SDM660_VDDCX_VFL] = &cx_rwcx0_vfl,
[SDM660_VDDMX] = &mx_rwmx0_lvl,
[SDM660_VDDMX_AO] = &mx_rwmx0_lvl_ao,
[SDM660_VDDMX_VFL] = &mx_rwmx0_vfl,
[SDM660_SSCCX] = &ssc_cx_rwlc0_lvl,
[SDM660_SSCCX_VFL] = &ssc_cx_rwlc0_vfl,
[SDM660_SSCMX] = &ssc_mx_rwlm0_lvl,
[SDM660_SSCMX_VFL] = &ssc_mx_rwlm0_vfl,
[RPMPD_VDDCX] = &cx_rwcx0_lvl,
[RPMPD_VDDCX_AO] = &cx_rwcx0_lvl_ao,
[RPMPD_VDDCX_VFL] = &cx_rwcx0_vfl,
[RPMPD_VDDMX] = &mx_rwmx0_lvl,
[RPMPD_VDDMX_AO] = &mx_rwmx0_lvl_ao,
[RPMPD_VDDMX_VFL] = &mx_rwmx0_vfl,
[RPMPD_SSCCX] = &ssc_cx_rwlc0_lvl,
[RPMPD_SSCCX_VFL] = &ssc_cx_rwlc0_vfl,
[RPMPD_SSCMX] = &ssc_mx_rwlm0_lvl,
[RPMPD_SSCMX_VFL] = &ssc_mx_rwlm0_vfl,
};
static const struct rpmpd_desc sdm660_desc = {
@@ -881,12 +881,12 @@ static const struct rpmpd_desc sm6115_desc = {
};
static struct rpmpd *sm6125_rpmpds[] = {
[SM6125_VDDCX] = &cx_rwcx0_lvl,
[SM6125_VDDCX_AO] = &cx_rwcx0_lvl_ao,
[SM6125_VDDCX_VFL] = &cx_rwcx0_vfl,
[SM6125_VDDMX] = &mx_rwmx0_lvl,
[SM6125_VDDMX_AO] = &mx_rwmx0_lvl_ao,
[SM6125_VDDMX_VFL] = &mx_rwmx0_vfl,
[RPMPD_VDDCX] = &cx_rwcx0_lvl,
[RPMPD_VDDCX_AO] = &cx_rwcx0_lvl_ao,
[RPMPD_VDDCX_VFL] = &cx_rwcx0_vfl,
[RPMPD_VDDMX] = &mx_rwmx0_lvl,
[RPMPD_VDDMX_AO] = &mx_rwmx0_lvl_ao,
[RPMPD_VDDMX_VFL] = &mx_rwmx0_vfl,
};
static const struct rpmpd_desc sm6125_desc = {

View File

@@ -3,6 +3,7 @@ if ARCH_ROCKCHIP || COMPILE_TEST
config ROCKCHIP_PM_DOMAINS
bool "Rockchip generic power domain"
default ARCH_ROCKCHIP
depends on PM
depends on HAVE_ARM_SMCCC_DISCOVERY
depends on REGULATOR

View File

@@ -173,6 +173,18 @@ static int th1520_pd_pwrseq_gpu_init(struct device *dev)
adev);
}
static int th1520_pd_reboot_init(struct device *dev,
struct th1520_aon_chan *aon_chan)
{
struct auxiliary_device *adev;
adev = devm_auxiliary_device_create(dev, "reboot", aon_chan);
if (!adev)
return -ENODEV;
return 0;
}
static int th1520_pd_probe(struct platform_device *pdev)
{
struct generic_pm_domain **domains;
@@ -235,6 +247,10 @@ static int th1520_pd_probe(struct platform_device *pdev)
if (ret)
goto err_clean_provider;
ret = th1520_pd_reboot_init(dev, aon_chan);
if (ret)
goto err_clean_provider;
return 0;
err_clean_provider:

View File

@@ -200,6 +200,23 @@ static bool ti_sci_pm_idx_exists(struct ti_sci_genpd_provider *pd_provider, u32
return false;
}
static bool ti_sci_pm_pd_is_on(struct ti_sci_genpd_provider *pd_provider,
int pd_idx)
{
bool is_on;
int ret;
if (!pd_provider->ti_sci->ops.dev_ops.is_on)
return false;
ret = pd_provider->ti_sci->ops.dev_ops.is_on(pd_provider->ti_sci,
pd_idx, NULL, &is_on);
if (ret)
return false;
return is_on;
}
static int ti_sci_pm_domain_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -231,6 +248,8 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev)
index, &args)) {
if (args.args_count >= 1 && args.np == dev->of_node) {
bool is_on;
of_node_put(args.np);
if (args.args[0] > max_id) {
max_id = args.args[0];
@@ -264,7 +283,10 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev)
pd_provider->ti_sci->ops.pm_ops.set_latency_constraint)
pd->pd.domain.ops.suspend = ti_sci_pd_suspend;
pm_genpd_init(&pd->pd, NULL, true);
is_on = ti_sci_pm_pd_is_on(pd_provider,
pd->idx);
pm_genpd_init(&pd->pd, NULL, !is_on);
list_add(&pd->node, &pd_provider->pd_list);
} else {

View File

@@ -225,6 +225,13 @@ config POWER_RESET_ST
help
Reset support for STMicroelectronics boards.
config POWER_RESET_TH1520_AON
tristate "T-Head TH1520 AON firmware poweroff and reset driver"
depends on TH1520_PM_DOMAINS
help
This driver supports power-off and reset operations for T-Head
TH1520 SoCs running the AON firmware.
config POWER_RESET_TORADEX_EC
tristate "Toradex Embedded Controller power-off and reset driver"
depends on ARCH_MXC || COMPILE_TEST

View File

@@ -25,6 +25,7 @@ obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o
obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o
obj-$(CONFIG_POWER_RESET_TH1520_AON) += th1520-aon-reboot.o
obj-$(CONFIG_POWER_RESET_TORADEX_EC) += tdx-ec-poweroff.o
obj-$(CONFIG_POWER_RESET_TPS65086) += tps65086-restart.o
obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o

View File

@@ -0,0 +1,98 @@
// SPDX-License-Identifier: GPL-2.0
/*
* T-HEAD TH1520 AON Firmware Reboot Driver
*
* Copyright (c) 2025 Icenowy Zheng <uwu@icenowy.me>
*/
#include <linux/auxiliary_bus.h>
#include <linux/firmware/thead/thead,th1520-aon.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/reboot.h>
#include <linux/slab.h>
#define TH1520_AON_REBOOT_PRIORITY 200
struct th1520_aon_msg_empty_body {
struct th1520_aon_rpc_msg_hdr hdr;
u16 reserved[12];
} __packed __aligned(1);
static int th1520_aon_pwroff_handler(struct sys_off_data *data)
{
struct th1520_aon_chan *aon_chan = data->cb_data;
struct th1520_aon_msg_empty_body msg = {};
msg.hdr.svc = TH1520_AON_RPC_SVC_WDG;
msg.hdr.func = TH1520_AON_WDG_FUNC_POWER_OFF;
msg.hdr.size = TH1520_AON_RPC_MSG_NUM;
th1520_aon_call_rpc(aon_chan, &msg);
return NOTIFY_DONE;
}
static int th1520_aon_restart_handler(struct sys_off_data *data)
{
struct th1520_aon_chan *aon_chan = data->cb_data;
struct th1520_aon_msg_empty_body msg = {};
msg.hdr.svc = TH1520_AON_RPC_SVC_WDG;
msg.hdr.func = TH1520_AON_WDG_FUNC_RESTART;
msg.hdr.size = TH1520_AON_RPC_MSG_NUM;
th1520_aon_call_rpc(aon_chan, &msg);
return NOTIFY_DONE;
}
static int th1520_aon_reboot_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct device *dev = &adev->dev;
int ret;
/* Expect struct th1520_aon_chan to be passed via platform_data */
ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF,
TH1520_AON_REBOOT_PRIORITY,
th1520_aon_pwroff_handler,
adev->dev.platform_data);
if (ret) {
dev_err(dev, "Failed to register power off handler\n");
return ret;
}
ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART,
TH1520_AON_REBOOT_PRIORITY,
th1520_aon_restart_handler,
adev->dev.platform_data);
if (ret) {
dev_err(dev, "Failed to register restart handler\n");
return ret;
}
return 0;
}
static const struct auxiliary_device_id th1520_aon_reboot_id_table[] = {
{ .name = "th1520_pm_domains.reboot" },
{},
};
MODULE_DEVICE_TABLE(auxiliary, th1520_aon_reboot_id_table);
static struct auxiliary_driver th1520_aon_reboot_driver = {
.driver = {
.name = "th1520-aon-reboot",
},
.probe = th1520_aon_reboot_probe,
.id_table = th1520_aon_reboot_id_table,
};
module_auxiliary_driver(th1520_aon_reboot_driver);
MODULE_AUTHOR("Icenowy Zheng <uwu@icenowy.me>");
MODULE_DESCRIPTION("T-HEAD TH1520 AON-firmware-based reboot driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
/*
* Copyright (C) 2025 Amlogic, Inc. All rights reserved
*/
#ifndef _DT_BINDINGS_AMLOGIC_S6_POWER_H
#define _DT_BINDINGS_AMLOGIC_S6_POWER_H
#define PWRC_S6_DSPA_ID 0
#define PWRC_S6_DOS_HEVC_ID 1
#define PWRC_S6_DOS_VDEC_ID 2
#define PWRC_S6_VPU_HDMI_ID 3
#define PWRC_S6_U2DRD_ID 4
#define PWRC_S6_U3DRD_ID 5
#define PWRC_S6_SD_EMMC_C_ID 6
#define PWRC_S6_GE2D_ID 7
#define PWRC_S6_AMFC_ID 8
#define PWRC_S6_VC9000E_ID 9
#define PWRC_S6_DEWARP_ID 10
#define PWRC_S6_VICP_ID 11
#define PWRC_S6_SD_EMMC_A_ID 12
#define PWRC_S6_SD_EMMC_B_ID 13
#define PWRC_S6_ETH_ID 14
#define PWRC_S6_PCIE_ID 15
#define PWRC_S6_NNA_4T_ID 16
#define PWRC_S6_AUDIO_ID 17
#define PWRC_S6_AUCPU_ID 18
#define PWRC_S6_ADAPT_ID 19
#endif

View File

@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
/*
* Copyright (C) 2025 Amlogic, Inc. All rights reserved
*/
#ifndef _DT_BINDINGS_AMLOGIC_S7_POWER_H
#define _DT_BINDINGS_AMLOGIC_S7_POWER_H
#define PWRC_S7_DOS_HEVC_ID 0
#define PWRC_S7_DOS_VDEC_ID 1
#define PWRC_S7_VPU_HDMI_ID 2
#define PWRC_S7_USB_COMB_ID 3
#define PWRC_S7_SD_EMMC_C_ID 4
#define PWRC_S7_GE2D_ID 5
#define PWRC_S7_SD_EMMC_A_ID 6
#define PWRC_S7_SD_EMMC_B_ID 7
#define PWRC_S7_ETH_ID 8
#define PWRC_S7_AUCPU_ID 9
#define PWRC_S7_AUDIO_ID 10
#endif

View File

@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
/*
* Copyright (C) 2025 Amlogic, Inc. All rights reserved
*/
#ifndef _DT_BINDINGS_AMLOGIC_S7D_POWER_H
#define _DT_BINDINGS_AMLOGIC_S7D_POWER_H
#define PWRC_S7D_DOS_HCODEC_ID 0
#define PWRC_S7D_DOS_HEVC_ID 1
#define PWRC_S7D_DOS_VDEC_ID 2
#define PWRC_S7D_VPU_HDMI_ID 3
#define PWRC_S7D_USB_U2DRD_ID 4
#define PWRC_S7D_USB_U2H_ID 5
#define PWRC_S7D_SSD_EMMC_C_ID 6
#define PWRC_S7D_GE2D_ID 7
#define PWRC_S7D_AMFC_ID 8
#define PWRC_S7D_EMMC_A_ID 9
#define PWRC_S7D_EMMC_B_ID 10
#define PWRC_S7D_ETH_ID 11
#define PWRC_S7D_AUCPU_ID 12
#define PWRC_S7D_AUDIO_ID 13
#define PWRC_S7D_SRAMA_ID 14
#define PWRC_S7D_DMC0_ID 15
#define PWRC_S7D_DMC1_ID 16
#define PWRC_S7D_DDR_ID 17
#endif

View File

@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
/*
* Marvell PXA1908 power domains
*
* Copyright 2025, Duje Mihanović <duje@dujemihanovic.xyz>
*/
#ifndef __DTS_MARVELL_PXA1908_POWER_H
#define __DTS_MARVELL_PXA1908_POWER_H
#define PXA1908_POWER_DOMAIN_VPU 0
#define PXA1908_POWER_DOMAIN_GPU 1
#define PXA1908_POWER_DOMAIN_GPU2D 2
#define PXA1908_POWER_DOMAIN_DSI 3
#define PXA1908_POWER_DOMAIN_ISP 4
#endif

View File

@@ -29,4 +29,237 @@
#define RPMHPD_NSP2 19
#define RPMHPD_GMXC 20
/* RPMh Power Domain performance levels */
#define RPMH_REGULATOR_LEVEL_RETENTION 16
#define RPMH_REGULATOR_LEVEL_MIN_SVS 48
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D3 50
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D2 52
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D1 56
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D0 60
#define RPMH_REGULATOR_LEVEL_LOW_SVS 64
#define RPMH_REGULATOR_LEVEL_LOW_SVS_P1 72
#define RPMH_REGULATOR_LEVEL_LOW_SVS_L1 80
#define RPMH_REGULATOR_LEVEL_LOW_SVS_L2 96
#define RPMH_REGULATOR_LEVEL_SVS 128
#define RPMH_REGULATOR_LEVEL_SVS_L0 144
#define RPMH_REGULATOR_LEVEL_SVS_L1 192
#define RPMH_REGULATOR_LEVEL_SVS_L2 224
#define RPMH_REGULATOR_LEVEL_NOM 256
#define RPMH_REGULATOR_LEVEL_NOM_L0 288
#define RPMH_REGULATOR_LEVEL_NOM_L1 320
#define RPMH_REGULATOR_LEVEL_NOM_L2 336
#define RPMH_REGULATOR_LEVEL_TURBO 384
#define RPMH_REGULATOR_LEVEL_TURBO_L0 400
#define RPMH_REGULATOR_LEVEL_TURBO_L1 416
#define RPMH_REGULATOR_LEVEL_TURBO_L2 432
#define RPMH_REGULATOR_LEVEL_TURBO_L3 448
#define RPMH_REGULATOR_LEVEL_TURBO_L4 452
#define RPMH_REGULATOR_LEVEL_TURBO_L5 456
#define RPMH_REGULATOR_LEVEL_SUPER_TURBO 464
#define RPMH_REGULATOR_LEVEL_SUPER_TURBO_NO_CPR 480
/*
* Platform-specific power domain bindings. Don't add new entries here, use
* RPMHPD_* above.
*/
/* SA8775P Power Domain Indexes */
#define SA8775P_CX 0
#define SA8775P_CX_AO 1
#define SA8775P_DDR 2
#define SA8775P_EBI 3
#define SA8775P_GFX 4
#define SA8775P_LCX 5
#define SA8775P_LMX 6
#define SA8775P_MMCX 7
#define SA8775P_MMCX_AO 8
#define SA8775P_MSS 9
#define SA8775P_MX 10
#define SA8775P_MX_AO 11
#define SA8775P_MXC 12
#define SA8775P_MXC_AO 13
#define SA8775P_NSP0 14
#define SA8775P_NSP1 15
#define SA8775P_XO 16
/* SDM670 Power Domain Indexes */
#define SDM670_MX 0
#define SDM670_MX_AO 1
#define SDM670_CX 2
#define SDM670_CX_AO 3
#define SDM670_LMX 4
#define SDM670_LCX 5
#define SDM670_GFX 6
#define SDM670_MSS 7
/* SDM845 Power Domain Indexes */
#define SDM845_EBI 0
#define SDM845_MX 1
#define SDM845_MX_AO 2
#define SDM845_CX 3
#define SDM845_CX_AO 4
#define SDM845_LMX 5
#define SDM845_LCX 6
#define SDM845_GFX 7
#define SDM845_MSS 8
/* SDX55 Power Domain Indexes */
#define SDX55_MSS 0
#define SDX55_MX 1
#define SDX55_CX 2
/* SDX65 Power Domain Indexes */
#define SDX65_MSS 0
#define SDX65_MX 1
#define SDX65_MX_AO 2
#define SDX65_CX 3
#define SDX65_CX_AO 4
#define SDX65_MXC 5
/* SM6350 Power Domain Indexes */
#define SM6350_CX 0
#define SM6350_GFX 1
#define SM6350_LCX 2
#define SM6350_LMX 3
#define SM6350_MSS 4
#define SM6350_MX 5
/* SM8150 Power Domain Indexes */
#define SM8150_MSS 0
#define SM8150_EBI 1
#define SM8150_LMX 2
#define SM8150_LCX 3
#define SM8150_GFX 4
#define SM8150_MX 5
#define SM8150_MX_AO 6
#define SM8150_CX 7
#define SM8150_CX_AO 8
#define SM8150_MMCX 9
#define SM8150_MMCX_AO 10
/* SA8155P is a special case, kept for backwards compatibility */
#define SA8155P_CX SM8150_CX
#define SA8155P_CX_AO SM8150_CX_AO
#define SA8155P_EBI SM8150_EBI
#define SA8155P_GFX SM8150_GFX
#define SA8155P_MSS SM8150_MSS
#define SA8155P_MX SM8150_MX
#define SA8155P_MX_AO SM8150_MX_AO
/* SM8250 Power Domain Indexes */
#define SM8250_CX 0
#define SM8250_CX_AO 1
#define SM8250_EBI 2
#define SM8250_GFX 3
#define SM8250_LCX 4
#define SM8250_LMX 5
#define SM8250_MMCX 6
#define SM8250_MMCX_AO 7
#define SM8250_MX 8
#define SM8250_MX_AO 9
/* SM8350 Power Domain Indexes */
#define SM8350_CX 0
#define SM8350_CX_AO 1
#define SM8350_EBI 2
#define SM8350_GFX 3
#define SM8350_LCX 4
#define SM8350_LMX 5
#define SM8350_MMCX 6
#define SM8350_MMCX_AO 7
#define SM8350_MX 8
#define SM8350_MX_AO 9
#define SM8350_MXC 10
#define SM8350_MXC_AO 11
#define SM8350_MSS 12
/* SM8450 Power Domain Indexes */
#define SM8450_CX 0
#define SM8450_CX_AO 1
#define SM8450_EBI 2
#define SM8450_GFX 3
#define SM8450_LCX 4
#define SM8450_LMX 5
#define SM8450_MMCX 6
#define SM8450_MMCX_AO 7
#define SM8450_MX 8
#define SM8450_MX_AO 9
#define SM8450_MXC 10
#define SM8450_MXC_AO 11
#define SM8450_MSS 12
/* SM8550 Power Domain Indexes */
#define SM8550_CX 0
#define SM8550_CX_AO 1
#define SM8550_EBI 2
#define SM8550_GFX 3
#define SM8550_LCX 4
#define SM8550_LMX 5
#define SM8550_MMCX 6
#define SM8550_MMCX_AO 7
#define SM8550_MX 8
#define SM8550_MX_AO 9
#define SM8550_MXC 10
#define SM8550_MXC_AO 11
#define SM8550_MSS 12
#define SM8550_NSP 13
/* QDU1000/QRU1000 Power Domain Indexes */
#define QDU1000_EBI 0
#define QDU1000_MSS 1
#define QDU1000_CX 2
#define QDU1000_MX 3
/* SC7180 Power Domain Indexes */
#define SC7180_CX 0
#define SC7180_CX_AO 1
#define SC7180_GFX 2
#define SC7180_MX 3
#define SC7180_MX_AO 4
#define SC7180_LMX 5
#define SC7180_LCX 6
#define SC7180_MSS 7
/* SC7280 Power Domain Indexes */
#define SC7280_CX 0
#define SC7280_CX_AO 1
#define SC7280_EBI 2
#define SC7280_GFX 3
#define SC7280_MX 4
#define SC7280_MX_AO 5
#define SC7280_LMX 6
#define SC7280_LCX 7
#define SC7280_MSS 8
/* SC8180X Power Domain Indexes */
#define SC8180X_CX 0
#define SC8180X_CX_AO 1
#define SC8180X_EBI 2
#define SC8180X_GFX 3
#define SC8180X_LCX 4
#define SC8180X_LMX 5
#define SC8180X_MMCX 6
#define SC8180X_MMCX_AO 7
#define SC8180X_MSS 8
#define SC8180X_MX 9
#define SC8180X_MX_AO 10
/* SC8280XP Power Domain Indexes */
#define SC8280XP_CX 0
#define SC8280XP_CX_AO 1
#define SC8280XP_DDR 2
#define SC8280XP_EBI 3
#define SC8280XP_GFX 4
#define SC8280XP_LCX 5
#define SC8280XP_LMX 6
#define SC8280XP_MMCX 7
#define SC8280XP_MMCX_AO 8
#define SC8280XP_MSS 9
#define SC8280XP_MX 10
#define SC8280XP_MXC 12
#define SC8280XP_MX_AO 11
#define SC8280XP_NSP 13
#define SC8280XP_QPHY 14
#define SC8280XP_XO 15
#endif

View File

@@ -4,258 +4,39 @@
#ifndef _DT_BINDINGS_POWER_QCOM_RPMPD_H
#define _DT_BINDINGS_POWER_QCOM_RPMPD_H
/* SA8775P Power Domain Indexes */
#define SA8775P_CX 0
#define SA8775P_CX_AO 1
#define SA8775P_DDR 2
#define SA8775P_EBI 3
#define SA8775P_GFX 4
#define SA8775P_LCX 5
#define SA8775P_LMX 6
#define SA8775P_MMCX 7
#define SA8775P_MMCX_AO 8
#define SA8775P_MSS 9
#define SA8775P_MX 10
#define SA8775P_MX_AO 11
#define SA8775P_MXC 12
#define SA8775P_MXC_AO 13
#define SA8775P_NSP0 14
#define SA8775P_NSP1 15
#define SA8775P_XO 16
#include <dt-bindings/power/qcom,rpmhpd.h>
/* SDM670 Power Domain Indexes */
#define SDM670_MX 0
#define SDM670_MX_AO 1
#define SDM670_CX 2
#define SDM670_CX_AO 3
#define SDM670_LMX 4
#define SDM670_LCX 5
#define SDM670_GFX 6
#define SDM670_MSS 7
/* Generic RPM Power Domain Indexes */
#define RPMPD_VDDCX 0
#define RPMPD_VDDCX_AO 1
/* VFC and VFL are mutually exclusive and can not be present on the same platform */
#define RPMPD_VDDCX_VFC 2
#define RPMPD_VDDCX_VFL 2
#define RPMPD_VDDMX 3
#define RPMPD_VDDMX_AO 4
#define RPMPD_VDDMX_VFL 5
#define RPMPD_SSCCX 6
#define RPMPD_SSCCX_VFL 7
#define RPMPD_SSCMX 8
#define RPMPD_SSCMX_VFL 9
/* SDM845 Power Domain Indexes */
#define SDM845_EBI 0
#define SDM845_MX 1
#define SDM845_MX_AO 2
#define SDM845_CX 3
#define SDM845_CX_AO 4
#define SDM845_LMX 5
#define SDM845_LCX 6
#define SDM845_GFX 7
#define SDM845_MSS 8
/* SDX55 Power Domain Indexes */
#define SDX55_MSS 0
#define SDX55_MX 1
#define SDX55_CX 2
/* SDX65 Power Domain Indexes */
#define SDX65_MSS 0
#define SDX65_MX 1
#define SDX65_MX_AO 2
#define SDX65_CX 3
#define SDX65_CX_AO 4
#define SDX65_MXC 5
/* SM6350 Power Domain Indexes */
#define SM6350_CX 0
#define SM6350_GFX 1
#define SM6350_LCX 2
#define SM6350_LMX 3
#define SM6350_MSS 4
#define SM6350_MX 5
/* SM6375 Power Domain Indexes */
#define SM6375_VDDCX 0
#define SM6375_VDDCX_AO 1
#define SM6375_VDDCX_VFL 2
#define SM6375_VDDMX 3
#define SM6375_VDDMX_AO 4
#define SM6375_VDDMX_VFL 5
#define SM6375_VDDGX 6
#define SM6375_VDDGX_AO 7
#define SM6375_VDD_LPI_CX 8
#define SM6375_VDD_LPI_MX 9
/* SM8150 Power Domain Indexes */
#define SM8150_MSS 0
#define SM8150_EBI 1
#define SM8150_LMX 2
#define SM8150_LCX 3
#define SM8150_GFX 4
#define SM8150_MX 5
#define SM8150_MX_AO 6
#define SM8150_CX 7
#define SM8150_CX_AO 8
#define SM8150_MMCX 9
#define SM8150_MMCX_AO 10
/* SA8155P is a special case, kept for backwards compatibility */
#define SA8155P_CX SM8150_CX
#define SA8155P_CX_AO SM8150_CX_AO
#define SA8155P_EBI SM8150_EBI
#define SA8155P_GFX SM8150_GFX
#define SA8155P_MSS SM8150_MSS
#define SA8155P_MX SM8150_MX
#define SA8155P_MX_AO SM8150_MX_AO
/* SM8250 Power Domain Indexes */
#define SM8250_CX 0
#define SM8250_CX_AO 1
#define SM8250_EBI 2
#define SM8250_GFX 3
#define SM8250_LCX 4
#define SM8250_LMX 5
#define SM8250_MMCX 6
#define SM8250_MMCX_AO 7
#define SM8250_MX 8
#define SM8250_MX_AO 9
/* SM8350 Power Domain Indexes */
#define SM8350_CX 0
#define SM8350_CX_AO 1
#define SM8350_EBI 2
#define SM8350_GFX 3
#define SM8350_LCX 4
#define SM8350_LMX 5
#define SM8350_MMCX 6
#define SM8350_MMCX_AO 7
#define SM8350_MX 8
#define SM8350_MX_AO 9
#define SM8350_MXC 10
#define SM8350_MXC_AO 11
#define SM8350_MSS 12
/* SM8450 Power Domain Indexes */
#define SM8450_CX 0
#define SM8450_CX_AO 1
#define SM8450_EBI 2
#define SM8450_GFX 3
#define SM8450_LCX 4
#define SM8450_LMX 5
#define SM8450_MMCX 6
#define SM8450_MMCX_AO 7
#define SM8450_MX 8
#define SM8450_MX_AO 9
#define SM8450_MXC 10
#define SM8450_MXC_AO 11
#define SM8450_MSS 12
/* SM8550 Power Domain Indexes */
#define SM8550_CX 0
#define SM8550_CX_AO 1
#define SM8550_EBI 2
#define SM8550_GFX 3
#define SM8550_LCX 4
#define SM8550_LMX 5
#define SM8550_MMCX 6
#define SM8550_MMCX_AO 7
#define SM8550_MX 8
#define SM8550_MX_AO 9
#define SM8550_MXC 10
#define SM8550_MXC_AO 11
#define SM8550_MSS 12
#define SM8550_NSP 13
/* QDU1000/QRU1000 Power Domain Indexes */
#define QDU1000_EBI 0
#define QDU1000_MSS 1
#define QDU1000_CX 2
#define QDU1000_MX 3
/* SC7180 Power Domain Indexes */
#define SC7180_CX 0
#define SC7180_CX_AO 1
#define SC7180_GFX 2
#define SC7180_MX 3
#define SC7180_MX_AO 4
#define SC7180_LMX 5
#define SC7180_LCX 6
#define SC7180_MSS 7
/* SC7280 Power Domain Indexes */
#define SC7280_CX 0
#define SC7280_CX_AO 1
#define SC7280_EBI 2
#define SC7280_GFX 3
#define SC7280_MX 4
#define SC7280_MX_AO 5
#define SC7280_LMX 6
#define SC7280_LCX 7
#define SC7280_MSS 8
/* SC8180X Power Domain Indexes */
#define SC8180X_CX 0
#define SC8180X_CX_AO 1
#define SC8180X_EBI 2
#define SC8180X_GFX 3
#define SC8180X_LCX 4
#define SC8180X_LMX 5
#define SC8180X_MMCX 6
#define SC8180X_MMCX_AO 7
#define SC8180X_MSS 8
#define SC8180X_MX 9
#define SC8180X_MX_AO 10
/* SC8280XP Power Domain Indexes */
#define SC8280XP_CX 0
#define SC8280XP_CX_AO 1
#define SC8280XP_DDR 2
#define SC8280XP_EBI 3
#define SC8280XP_GFX 4
#define SC8280XP_LCX 5
#define SC8280XP_LMX 6
#define SC8280XP_MMCX 7
#define SC8280XP_MMCX_AO 8
#define SC8280XP_MSS 9
#define SC8280XP_MX 10
#define SC8280XP_MXC 12
#define SC8280XP_MX_AO 11
#define SC8280XP_NSP 13
#define SC8280XP_QPHY 14
#define SC8280XP_XO 15
/* SDM845 Power Domain performance levels */
#define RPMH_REGULATOR_LEVEL_RETENTION 16
#define RPMH_REGULATOR_LEVEL_MIN_SVS 48
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D3 50
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D2 52
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D1 56
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D0 60
#define RPMH_REGULATOR_LEVEL_LOW_SVS 64
#define RPMH_REGULATOR_LEVEL_LOW_SVS_P1 72
#define RPMH_REGULATOR_LEVEL_LOW_SVS_L1 80
#define RPMH_REGULATOR_LEVEL_LOW_SVS_L2 96
#define RPMH_REGULATOR_LEVEL_SVS 128
#define RPMH_REGULATOR_LEVEL_SVS_L0 144
#define RPMH_REGULATOR_LEVEL_SVS_L1 192
#define RPMH_REGULATOR_LEVEL_SVS_L2 224
#define RPMH_REGULATOR_LEVEL_NOM 256
#define RPMH_REGULATOR_LEVEL_NOM_L0 288
#define RPMH_REGULATOR_LEVEL_NOM_L1 320
#define RPMH_REGULATOR_LEVEL_NOM_L2 336
#define RPMH_REGULATOR_LEVEL_TURBO 384
#define RPMH_REGULATOR_LEVEL_TURBO_L0 400
#define RPMH_REGULATOR_LEVEL_TURBO_L1 416
#define RPMH_REGULATOR_LEVEL_TURBO_L2 432
#define RPMH_REGULATOR_LEVEL_TURBO_L3 448
#define RPMH_REGULATOR_LEVEL_TURBO_L4 452
#define RPMH_REGULATOR_LEVEL_TURBO_L5 456
#define RPMH_REGULATOR_LEVEL_SUPER_TURBO 464
#define RPMH_REGULATOR_LEVEL_SUPER_TURBO_NO_CPR 480
/*
* Platform-specific power domain bindings. Don't add new entries here, use
* RPMPD_* above.
*/
/* MDM9607 Power Domains */
#define MDM9607_VDDCX 0
#define MDM9607_VDDCX_AO 1
#define MDM9607_VDDCX_VFL 2
#define MDM9607_VDDMX 3
#define MDM9607_VDDMX_AO 4
#define MDM9607_VDDMX_VFL 5
#define MDM9607_VDDCX RPMPD_VDDCX
#define MDM9607_VDDCX_AO RPMPD_VDDCX_AO
#define MDM9607_VDDCX_VFL RPMPD_VDDCX_VFL
#define MDM9607_VDDMX RPMPD_VDDMX
#define MDM9607_VDDMX_AO RPMPD_VDDMX_AO
#define MDM9607_VDDMX_VFL RPMPD_VDDMX_VFL
/* MSM8226 Power Domain Indexes */
#define MSM8226_VDDCX 0
#define MSM8226_VDDCX_AO 1
#define MSM8226_VDDCX_VFC 2
#define MSM8226_VDDCX RPMPD_VDDCX
#define MSM8226_VDDCX_AO RPMPD_VDDCX_AO
#define MSM8226_VDDCX_VFC RPMPD_VDDCX_VFC
/* MSM8939 Power Domains */
#define MSM8939_VDDMDCX 0
@@ -268,11 +49,11 @@
#define MSM8939_VDDMX_AO 7
/* MSM8916 Power Domain Indexes */
#define MSM8916_VDDCX 0
#define MSM8916_VDDCX_AO 1
#define MSM8916_VDDCX_VFC 2
#define MSM8916_VDDMX 3
#define MSM8916_VDDMX_AO 4
#define MSM8916_VDDCX RPMPD_VDDCX
#define MSM8916_VDDCX_AO RPMPD_VDDCX_AO
#define MSM8916_VDDCX_VFC RPMPD_VDDCX_VFC
#define MSM8916_VDDMX RPMPD_VDDMX
#define MSM8916_VDDMX_AO RPMPD_VDDMX_AO
/* MSM8909 Power Domain Indexes */
#define MSM8909_VDDCX MSM8916_VDDCX
@@ -282,11 +63,11 @@
#define MSM8909_VDDMX_AO MSM8916_VDDMX_AO
/* MSM8917 Power Domain Indexes */
#define MSM8917_VDDCX 0
#define MSM8917_VDDCX_AO 1
#define MSM8917_VDDCX_VFL 2
#define MSM8917_VDDMX 3
#define MSM8917_VDDMX_AO 4
#define MSM8917_VDDCX RPMPD_VDDCX
#define MSM8917_VDDCX_AO RPMPD_VDDCX_AO
#define MSM8917_VDDCX_VFL RPMPD_VDDCX_VFL
#define MSM8917_VDDMX RPMPD_VDDMX
#define MSM8917_VDDMX_AO RPMPD_VDDMX_AO
/* MSM8937 Power Domain Indexes */
#define MSM8937_VDDCX MSM8917_VDDCX
@@ -319,12 +100,12 @@
#define MSM8974_VDDGFX_VFC 4
/* MSM8976 Power Domain Indexes */
#define MSM8976_VDDCX 0
#define MSM8976_VDDCX_AO 1
#define MSM8976_VDDCX_VFL 2
#define MSM8976_VDDMX 3
#define MSM8976_VDDMX_AO 4
#define MSM8976_VDDMX_VFL 5
#define MSM8976_VDDCX RPMPD_VDDCX
#define MSM8976_VDDCX_AO RPMPD_VDDCX_AO
#define MSM8976_VDDCX_VFL RPMPD_VDDCX_VFL
#define MSM8976_VDDMX RPMPD_VDDMX
#define MSM8976_VDDMX_AO RPMPD_VDDMX_AO
#define MSM8976_VDDMX_VFL RPMPD_VDDMX_VFL
/* MSM8994 Power Domain Indexes */
#define MSM8994_VDDCX 0
@@ -345,16 +126,26 @@
#define MSM8996_VDDSSCX_VFC 6
/* MSM8998 Power Domain Indexes */
#define MSM8998_VDDCX 0
#define MSM8998_VDDCX_AO 1
#define MSM8998_VDDCX_VFL 2
#define MSM8998_VDDMX 3
#define MSM8998_VDDMX_AO 4
#define MSM8998_VDDMX_VFL 5
#define MSM8998_SSCCX 6
#define MSM8998_SSCCX_VFL 7
#define MSM8998_SSCMX 8
#define MSM8998_SSCMX_VFL 9
#define MSM8998_VDDCX RPMPD_VDDCX
#define MSM8998_VDDCX_AO RPMPD_VDDCX_AO
#define MSM8998_VDDCX_VFL RPMPD_VDDCX_VFL
#define MSM8998_VDDMX RPMPD_VDDMX
#define MSM8998_VDDMX_AO RPMPD_VDDMX_AO
#define MSM8998_VDDMX_VFL RPMPD_VDDMX_VFL
#define MSM8998_SSCCX RPMPD_SSCCX
#define MSM8998_SSCCX_VFL RPMPD_SSCCX_VFL
#define MSM8998_SSCMX RPMPD_SSCMX
#define MSM8998_SSCMX_VFL RPMPD_SSCMX_VFL
/* QCM2290 Power Domains */
#define QCM2290_VDDCX 0
#define QCM2290_VDDCX_AO 1
#define QCM2290_VDDCX_VFL 2
#define QCM2290_VDDMX 3
#define QCM2290_VDDMX_AO 4
#define QCM2290_VDDMX_VFL 5
#define QCM2290_VDD_LPI_CX 6
#define QCM2290_VDD_LPI_MX 7
/* QCS404 Power Domains */
#define QCS404_VDDMX 0
@@ -366,16 +157,16 @@
#define QCS404_LPIMX_VFL 6
/* SDM660 Power Domains */
#define SDM660_VDDCX 0
#define SDM660_VDDCX_AO 1
#define SDM660_VDDCX_VFL 2
#define SDM660_VDDMX 3
#define SDM660_VDDMX_AO 4
#define SDM660_VDDMX_VFL 5
#define SDM660_SSCCX 6
#define SDM660_SSCCX_VFL 7
#define SDM660_SSCMX 8
#define SDM660_SSCMX_VFL 9
#define SDM660_VDDCX RPMPD_VDDCX
#define SDM660_VDDCX_AO RPMPD_VDDCX_AO
#define SDM660_VDDCX_VFL RPMPD_VDDCX_VFL
#define SDM660_VDDMX RPMPD_VDDMX
#define SDM660_VDDMX_AO RPMPD_VDDMX_AO
#define SDM660_VDDMX_VFL RPMPD_VDDMX_VFL
#define SDM660_SSCCX RPMPD_SSCCX
#define SDM660_SSCCX_VFL RPMPD_SSCCX_VFL
#define SDM660_SSCMX RPMPD_SSCMX
#define SDM660_SSCMX_VFL RPMPD_SSCMX_VFL
/* SM6115 Power Domains */
#define SM6115_VDDCX 0
@@ -388,22 +179,24 @@
#define SM6115_VDD_LPI_MX 7
/* SM6125 Power Domains */
#define SM6125_VDDCX 0
#define SM6125_VDDCX_AO 1
#define SM6125_VDDCX_VFL 2
#define SM6125_VDDMX 3
#define SM6125_VDDMX_AO 4
#define SM6125_VDDMX_VFL 5
#define SM6125_VDDCX RPMPD_VDDCX
#define SM6125_VDDCX_AO RPMPD_VDDCX_AO
#define SM6125_VDDCX_VFL RPMPD_VDDCX_VFL
#define SM6125_VDDMX RPMPD_VDDMX
#define SM6125_VDDMX_AO RPMPD_VDDMX_AO
#define SM6125_VDDMX_VFL RPMPD_VDDMX_VFL
/* QCM2290 Power Domains */
#define QCM2290_VDDCX 0
#define QCM2290_VDDCX_AO 1
#define QCM2290_VDDCX_VFL 2
#define QCM2290_VDDMX 3
#define QCM2290_VDDMX_AO 4
#define QCM2290_VDDMX_VFL 5
#define QCM2290_VDD_LPI_CX 6
#define QCM2290_VDD_LPI_MX 7
/* SM6375 Power Domain Indexes */
#define SM6375_VDDCX 0
#define SM6375_VDDCX_AO 1
#define SM6375_VDDCX_VFL 2
#define SM6375_VDDMX 3
#define SM6375_VDDMX_AO 4
#define SM6375_VDDMX_VFL 5
#define SM6375_VDDGX 6
#define SM6375_VDDGX_AO 7
#define SM6375_VDD_LPI_CX 8
#define SM6375_VDD_LPI_MX 9
/* RPM SMD Power Domain performance levels */
#define RPM_SMD_LEVEL_RETENTION 16