aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/genpd/imx/scu-pd.c59
1 files changed, 55 insertions, 4 deletions
diff --git a/drivers/genpd/imx/scu-pd.c b/drivers/genpd/imx/scu-pd.c
index fa840ebe38c5..2f693b67ddb4 100644
--- a/drivers/genpd/imx/scu-pd.c
+++ b/drivers/genpd/imx/scu-pd.c
@@ -72,6 +72,22 @@ struct imx_sc_msg_req_set_resource_power_mode {
u8 mode;
} __packed __aligned(4);
+struct req_get_resource_mode {
+ u16 resource;
+};
+
+struct resp_get_resource_mode {
+ u8 mode;
+};
+
+struct imx_sc_msg_req_get_resource_power_mode {
+ struct imx_sc_rpc_msg hdr;
+ union {
+ struct req_get_resource_mode req;
+ struct resp_get_resource_mode resp;
+ } data;
+} __packed __aligned(4);
+
#define IMX_SCU_PD_NAME_SIZE 20
struct imx_sc_pm_domain {
struct generic_pm_domain pd;
@@ -96,6 +112,14 @@ struct imx_sc_pd_soc {
static int imx_con_rsrc;
+/* Align with the IMX_SC_PM_PW_MODE_[OFF,STBY,LP,ON] macros */
+static const char * const imx_sc_pm_mode[] = {
+ "IMX_SC_PM_PW_MODE_OFF",
+ "IMX_SC_PM_PW_MODE_STBY",
+ "IMX_SC_PM_PW_MODE_LP",
+ "IMX_SC_PM_PW_MODE_ON"
+};
+
static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
/* LSIO SS */
{ "pwm", IMX_SC_R_PWM_0, 8, true, 0 },
@@ -308,6 +332,27 @@ static void imx_sc_pd_get_console_rsrc(void)
imx_con_rsrc = specs.args[0];
}
+static int imx_sc_get_pd_power(struct device *dev, u32 rsrc)
+{
+ struct imx_sc_msg_req_get_resource_power_mode msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+ int ret;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_PM;
+ hdr->func = IMX_SC_PM_FUNC_GET_RESOURCE_POWER_MODE;
+ hdr->size = 2;
+
+ msg.data.req.resource = rsrc;
+
+ ret = imx_scu_call_rpc(pm_ipc_handle, &msg, true);
+ if (ret)
+ dev_err(dev, "failed to get power resource %d mode, ret %d\n",
+ rsrc, ret);
+
+ return msg.data.resp.mode;
+}
+
static int imx_sc_pd_power(struct generic_pm_domain *domain, bool power_on)
{
struct imx_sc_msg_req_set_resource_power_mode msg;
@@ -372,8 +417,8 @@ imx_scu_add_pm_domain(struct device *dev, int idx,
const struct imx_sc_pd_range *pd_ranges)
{
struct imx_sc_pm_domain *sc_pd;
- bool is_off = true;
- int ret;
+ bool is_off;
+ int mode, ret;
if (!imx_sc_rm_is_resource_owned(pm_ipc_handle, pd_ranges->rsrc + idx))
return NULL;
@@ -394,10 +439,16 @@ imx_scu_add_pm_domain(struct device *dev, int idx,
"%s", pd_ranges->name);
sc_pd->pd.name = sc_pd->name;
- if (imx_con_rsrc == sc_pd->rsrc) {
+ if (imx_con_rsrc == sc_pd->rsrc)
sc_pd->pd.flags = GENPD_FLAG_RPM_ALWAYS_ON;
+
+ mode = imx_sc_get_pd_power(dev, pd_ranges->rsrc + idx);
+ if (mode == IMX_SC_PM_PW_MODE_ON)
is_off = false;
- }
+ else
+ is_off = true;
+
+ dev_dbg(dev, "%s : %s\n", sc_pd->name, imx_sc_pm_mode[mode]);
if (sc_pd->rsrc >= IMX_SC_R_LAST) {
dev_warn(dev, "invalid pd %s rsrc id %d found",