mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
pmdomain core:
- Set the required dev for a required OPP during genpd attach - Add support for required OPPs to dev_pm_domain_attach_list() pmdomain providers: - ti: Enable GENPD_FLAG_ACTIVE_WAKEUP flag for ti_sci PM domains - mediatek: Add support for MT6735 PM domains - mediatek: Use OF-specific regulator API to get power domain supply - qcom: Add support for the SM8750/SAR2130P/qcs615/qcs8300 rpmhpds pmdomain consumers: - Convert a couple of consumer drivers to *_pm_domain_attach|detach_list() opp core: - Rework and cleanup some code that manages required OPPs - Remove *_opp_attach|detach_genpd() -----BEGIN PGP SIGNATURE----- iQJLBAABCgA1FiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAmc7Y+QXHHVsZi5oYW5z c29uQGxpbmFyby5vcmcACgkQ/iaEJXNYjCmbrw/9FVdo3+mo6EZne+Zsxc0+3N9G bRwkgyCB8WSFy6MHD1TRyP9u8bFgFDitSxcUGuBW0l9t1le3IcsYwfbTEEZpUkU4 iasPoZoFKA3Akfr7tvQpIpSNh8MIBMFy7CfxWpsfiHlmwrIH6oT6HmlwWwFsbVxh Fv8xA5SOE1KRHq0Aos23h7MizPsav/PYSh/4Ga5l6ZBlm40c16cE0i0M4RRUnoNY FmUBe57HoumDd05ToFR9wrqMEVWbAJHV4xZpZwnfYUhwGrgbxUWI/1FIfwxtob12 OExPr9kiV8/f8Kfp3E3ul0R8q8XYaYZaT3R7nF5QOngLZCCpD5H9aWEcAihUryBh Ol9Wao0Ku1JqLc776bjwf92ozFDtx0yUN/8LXmQgUu+e+MC3eAOrsls+U4731p+Y V80mvBpqn8AbX7LOjJvmbOhK6Qnm0cHo2cs0afBSS5c9RBcCWuEy9d7n8dks6JX2 7H6ySDaKoEEK06V6VzEKdHQoRFkmw95w4n7Ei3OL0cxNLcT1ILGA1+O7PPw+6h4T 3UnSik6szZCBXFFaDsw4J53HZACVZWbkyrk5Dbsigte8lh6e2VI+qd9whd46nuCY Sn4vJ399FJvXBuEIu+8yymGwn/NSpgd6ybpkwdDNJ+fItbes7DQhtxM6k74ANAhf 0irf1o4Yv0S5W+pXBAM= =SpyF -----END PGP SIGNATURE----- Merge tag 'pmdomain-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm Pull pmdomain updates from Ulf Hansson: "pmdomain core: - Set the required dev for a required OPP during genpd attach - Add support for required OPPs to dev_pm_domain_attach_list() pmdomain providers: - ti: Enable GENPD_FLAG_ACTIVE_WAKEUP flag for ti_sci PM domains - mediatek: Add support for MT6735 PM domains - mediatek: Use OF-specific regulator API to get power domain supply - qcom: Add support for the SM8750/SAR2130P/qcs615/qcs8300 rpmhpds pmdomain consumers: - Convert a couple of consumer drivers to *_pm_domain_attach|detach_list() opp core: - Rework and cleanup some code that manages required OPPs - Remove *_opp_attach|detach_genpd()" * tag 'pmdomain-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm: (25 commits) pmdomain: qcom: rpmhpd: Add rpmhpd support for SM8750 dt-bindings: power: qcom,rpmpd: document the SM8750 RPMh Power Domains pmdomain: imx: Use of_property_present() for non-boolean properties pmdomain: imx: gpcv2: replace dev_err() with dev_err_probe() pmdomain: ti-sci: Use scope based of_node_put() to simplify code. pmdomain: ti-sci: Add missing of_node_put() for args.np pmdomain: ti-sci: set the GENPD_FLAG_ACTIVE_WAKEUP flag for all PM domains pmdomain: mediatek: Add support for MT6735 pmdomain: qcom: rpmhpd: add support for SAR2130P dt-bindings: power: Add binding for MediaTek MT6735 power controller dt-bindings: power: rpmpd: Add SAR2130P compatible OPP: Drop redundant *_opp_attach|detach_genpd() cpufreq: qcom-nvmem: Convert to dev_pm_domain_attach|detach_list() media: venus: Convert into devm_pm_domain_attach_list() for OPP PM domain drm/tegra: gr3d: Convert into devm_pm_domain_attach_list() OPP: Drop redundant code in _link_required_opps() pmdomain: core: Set the required dev for a required OPP during genpd attach pmdomain: core: Manage the default required OPP from a separate function PM: domains: Support required OPPs in dev_pm_domain_attach_list() OPP: Rework _set_required_devs() to manage a single device per call ...
This commit is contained in:
commit
75f2b37dd0
@ -23,6 +23,7 @@ properties:
|
|||||||
|
|
||||||
compatible:
|
compatible:
|
||||||
enum:
|
enum:
|
||||||
|
- mediatek,mt6735-power-controller
|
||||||
- mediatek,mt6795-power-controller
|
- mediatek,mt6795-power-controller
|
||||||
- mediatek,mt8167-power-controller
|
- mediatek,mt8167-power-controller
|
||||||
- mediatek,mt8173-power-controller
|
- mediatek,mt8173-power-controller
|
||||||
|
@ -32,11 +32,14 @@ properties:
|
|||||||
- qcom,msm8998-rpmpd
|
- qcom,msm8998-rpmpd
|
||||||
- qcom,qcm2290-rpmpd
|
- qcom,qcm2290-rpmpd
|
||||||
- qcom,qcs404-rpmpd
|
- qcom,qcs404-rpmpd
|
||||||
|
- qcom,qcs615-rpmhpd
|
||||||
|
- qcom,qcs8300-rpmhpd
|
||||||
- qcom,qdu1000-rpmhpd
|
- qcom,qdu1000-rpmhpd
|
||||||
- qcom,qm215-rpmpd
|
- qcom,qm215-rpmpd
|
||||||
- qcom,sa8155p-rpmhpd
|
- qcom,sa8155p-rpmhpd
|
||||||
- qcom,sa8540p-rpmhpd
|
- qcom,sa8540p-rpmhpd
|
||||||
- qcom,sa8775p-rpmhpd
|
- qcom,sa8775p-rpmhpd
|
||||||
|
- qcom,sar2130p-rpmhpd
|
||||||
- qcom,sc7180-rpmhpd
|
- qcom,sc7180-rpmhpd
|
||||||
- qcom,sc7280-rpmhpd
|
- qcom,sc7280-rpmhpd
|
||||||
- qcom,sc8180x-rpmhpd
|
- qcom,sc8180x-rpmhpd
|
||||||
@ -58,6 +61,7 @@ properties:
|
|||||||
- qcom,sm8450-rpmhpd
|
- qcom,sm8450-rpmhpd
|
||||||
- qcom,sm8550-rpmhpd
|
- qcom,sm8550-rpmhpd
|
||||||
- qcom,sm8650-rpmhpd
|
- qcom,sm8650-rpmhpd
|
||||||
|
- qcom,sm8750-rpmhpd
|
||||||
- qcom,x1e80100-rpmhpd
|
- qcom,x1e80100-rpmhpd
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- enum:
|
||||||
|
@ -20,6 +20,7 @@ Required properties:
|
|||||||
- compatible: Should be one of:
|
- compatible: Should be one of:
|
||||||
- "mediatek,mt2701-scpsys"
|
- "mediatek,mt2701-scpsys"
|
||||||
- "mediatek,mt2712-scpsys"
|
- "mediatek,mt2712-scpsys"
|
||||||
|
- "mediatek,mt6735-scpsys"
|
||||||
- "mediatek,mt6765-scpsys"
|
- "mediatek,mt6765-scpsys"
|
||||||
- "mediatek,mt6797-scpsys"
|
- "mediatek,mt6797-scpsys"
|
||||||
- "mediatek,mt7622-scpsys"
|
- "mediatek,mt7622-scpsys"
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <linux/pm_clock.h>
|
#include <linux/pm_clock.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/pm_domain.h>
|
#include <linux/pm_domain.h>
|
||||||
|
#include <linux/pm_opp.h>
|
||||||
|
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
|
||||||
@ -222,13 +223,15 @@ int dev_pm_domain_attach_list(struct device *dev,
|
|||||||
if (!pds)
|
if (!pds)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
size = sizeof(*pds->pd_devs) + sizeof(*pds->pd_links);
|
size = sizeof(*pds->pd_devs) + sizeof(*pds->pd_links) +
|
||||||
|
sizeof(*pds->opp_tokens);
|
||||||
pds->pd_devs = kcalloc(num_pds, size, GFP_KERNEL);
|
pds->pd_devs = kcalloc(num_pds, size, GFP_KERNEL);
|
||||||
if (!pds->pd_devs) {
|
if (!pds->pd_devs) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto free_pds;
|
goto free_pds;
|
||||||
}
|
}
|
||||||
pds->pd_links = (void *)(pds->pd_devs + num_pds);
|
pds->pd_links = (void *)(pds->pd_devs + num_pds);
|
||||||
|
pds->opp_tokens = (void *)(pds->pd_links + num_pds);
|
||||||
|
|
||||||
if (link_flags && pd_flags & PD_FLAG_DEV_LINK_ON)
|
if (link_flags && pd_flags & PD_FLAG_DEV_LINK_ON)
|
||||||
link_flags |= DL_FLAG_RPM_ACTIVE;
|
link_flags |= DL_FLAG_RPM_ACTIVE;
|
||||||
@ -244,6 +247,19 @@ int dev_pm_domain_attach_list(struct device *dev,
|
|||||||
goto err_attach;
|
goto err_attach;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pd_flags & PD_FLAG_REQUIRED_OPP) {
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.required_dev = pd_dev,
|
||||||
|
.required_dev_index = i,
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = dev_pm_opp_set_config(dev, &config);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_link;
|
||||||
|
|
||||||
|
pds->opp_tokens[i] = ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (link_flags) {
|
if (link_flags) {
|
||||||
struct device_link *link;
|
struct device_link *link;
|
||||||
|
|
||||||
@ -264,9 +280,11 @@ int dev_pm_domain_attach_list(struct device *dev,
|
|||||||
return num_pds;
|
return num_pds;
|
||||||
|
|
||||||
err_link:
|
err_link:
|
||||||
|
dev_pm_opp_clear_config(pds->opp_tokens[i]);
|
||||||
dev_pm_domain_detach(pd_dev, true);
|
dev_pm_domain_detach(pd_dev, true);
|
||||||
err_attach:
|
err_attach:
|
||||||
while (--i >= 0) {
|
while (--i >= 0) {
|
||||||
|
dev_pm_opp_clear_config(pds->opp_tokens[i]);
|
||||||
if (pds->pd_links[i])
|
if (pds->pd_links[i])
|
||||||
device_link_del(pds->pd_links[i]);
|
device_link_del(pds->pd_links[i]);
|
||||||
dev_pm_domain_detach(pds->pd_devs[i], true);
|
dev_pm_domain_detach(pds->pd_devs[i], true);
|
||||||
@ -361,6 +379,7 @@ void dev_pm_domain_detach_list(struct dev_pm_domain_list *list)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < list->num_pds; i++) {
|
for (i = 0; i < list->num_pds; i++) {
|
||||||
|
dev_pm_opp_clear_config(list->opp_tokens[i]);
|
||||||
if (list->pd_links[i])
|
if (list->pd_links[i])
|
||||||
device_link_del(list->pd_links[i]);
|
device_link_del(list->pd_links[i]);
|
||||||
dev_pm_domain_detach(list->pd_devs[i], true);
|
dev_pm_domain_detach(list->pd_devs[i], true);
|
||||||
|
@ -52,12 +52,13 @@ struct qcom_cpufreq_match_data {
|
|||||||
struct nvmem_cell *speedbin_nvmem,
|
struct nvmem_cell *speedbin_nvmem,
|
||||||
char **pvs_name,
|
char **pvs_name,
|
||||||
struct qcom_cpufreq_drv *drv);
|
struct qcom_cpufreq_drv *drv);
|
||||||
const char **genpd_names;
|
const char **pd_names;
|
||||||
|
unsigned int num_pd_names;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qcom_cpufreq_drv_cpu {
|
struct qcom_cpufreq_drv_cpu {
|
||||||
int opp_token;
|
int opp_token;
|
||||||
struct device **virt_devs;
|
struct dev_pm_domain_list *pd_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qcom_cpufreq_drv {
|
struct qcom_cpufreq_drv {
|
||||||
@ -395,8 +396,6 @@ static int qcom_cpufreq_ipq8074_name_version(struct device *cpu_dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *generic_genpd_names[] = { "perf", NULL };
|
|
||||||
|
|
||||||
static const struct qcom_cpufreq_match_data match_data_kryo = {
|
static const struct qcom_cpufreq_match_data match_data_kryo = {
|
||||||
.get_version = qcom_cpufreq_kryo_name_version,
|
.get_version = qcom_cpufreq_kryo_name_version,
|
||||||
};
|
};
|
||||||
@ -407,13 +406,13 @@ static const struct qcom_cpufreq_match_data match_data_krait = {
|
|||||||
|
|
||||||
static const struct qcom_cpufreq_match_data match_data_msm8909 = {
|
static const struct qcom_cpufreq_match_data match_data_msm8909 = {
|
||||||
.get_version = qcom_cpufreq_simple_get_version,
|
.get_version = qcom_cpufreq_simple_get_version,
|
||||||
.genpd_names = generic_genpd_names,
|
.pd_names = (const char *[]) { "perf" },
|
||||||
|
.num_pd_names = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *qcs404_genpd_names[] = { "cpr", NULL };
|
|
||||||
|
|
||||||
static const struct qcom_cpufreq_match_data match_data_qcs404 = {
|
static const struct qcom_cpufreq_match_data match_data_qcs404 = {
|
||||||
.genpd_names = qcs404_genpd_names,
|
.pd_names = (const char *[]) { "cpr" },
|
||||||
|
.num_pd_names = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_cpufreq_match_data match_data_ipq6018 = {
|
static const struct qcom_cpufreq_match_data match_data_ipq6018 = {
|
||||||
@ -428,28 +427,16 @@ static const struct qcom_cpufreq_match_data match_data_ipq8074 = {
|
|||||||
.get_version = qcom_cpufreq_ipq8074_name_version,
|
.get_version = qcom_cpufreq_ipq8074_name_version,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void qcom_cpufreq_suspend_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
|
static void qcom_cpufreq_suspend_pd_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
|
||||||
{
|
{
|
||||||
const char * const *name = drv->data->genpd_names;
|
struct dev_pm_domain_list *pd_list = drv->cpus[cpu].pd_list;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!drv->cpus[cpu].virt_devs)
|
if (!pd_list)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; *name; i++, name++)
|
for (i = 0; i < pd_list->num_pds; i++)
|
||||||
device_set_awake_path(drv->cpus[cpu].virt_devs[i]);
|
device_set_awake_path(pd_list->pd_devs[i]);
|
||||||
}
|
|
||||||
|
|
||||||
static void qcom_cpufreq_put_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
|
|
||||||
{
|
|
||||||
const char * const *name = drv->data->genpd_names;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!drv->cpus[cpu].virt_devs)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; *name; i++, name++)
|
|
||||||
pm_runtime_put(drv->cpus[cpu].virt_devs[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qcom_cpufreq_probe(struct platform_device *pdev)
|
static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||||
@ -503,7 +490,6 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
struct device **virt_devs = NULL;
|
|
||||||
struct dev_pm_opp_config config = {
|
struct dev_pm_opp_config config = {
|
||||||
.supported_hw = NULL,
|
.supported_hw = NULL,
|
||||||
};
|
};
|
||||||
@ -522,12 +508,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
|||||||
config.prop_name = pvs_name;
|
config.prop_name = pvs_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drv->data->genpd_names) {
|
if (config.supported_hw) {
|
||||||
config.genpd_names = drv->data->genpd_names;
|
|
||||||
config.virt_devs = &virt_devs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.supported_hw || config.genpd_names) {
|
|
||||||
drv->cpus[cpu].opp_token = dev_pm_opp_set_config(cpu_dev, &config);
|
drv->cpus[cpu].opp_token = dev_pm_opp_set_config(cpu_dev, &config);
|
||||||
if (drv->cpus[cpu].opp_token < 0) {
|
if (drv->cpus[cpu].opp_token < 0) {
|
||||||
ret = drv->cpus[cpu].opp_token;
|
ret = drv->cpus[cpu].opp_token;
|
||||||
@ -536,27 +517,20 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virt_devs) {
|
if (drv->data->pd_names) {
|
||||||
const char * const *name = config.genpd_names;
|
struct dev_pm_domain_attach_data attach_data = {
|
||||||
int i, j;
|
.pd_names = drv->data->pd_names,
|
||||||
|
.num_pd_names = drv->data->num_pd_names,
|
||||||
for (i = 0; *name; i++, name++) {
|
.pd_flags = PD_FLAG_DEV_LINK_ON |
|
||||||
ret = pm_runtime_resume_and_get(virt_devs[i]);
|
PD_FLAG_REQUIRED_OPP,
|
||||||
if (ret) {
|
};
|
||||||
dev_err(cpu_dev, "failed to resume %s: %d\n",
|
|
||||||
*name, ret);
|
|
||||||
|
|
||||||
/* Rollback previous PM runtime calls */
|
|
||||||
name = config.genpd_names;
|
|
||||||
for (j = 0; *name && j < i; j++, name++)
|
|
||||||
pm_runtime_put(virt_devs[j]);
|
|
||||||
|
|
||||||
|
ret = dev_pm_domain_attach_list(cpu_dev, &attach_data,
|
||||||
|
&drv->cpus[cpu].pd_list);
|
||||||
|
if (ret < 0)
|
||||||
goto free_opp;
|
goto free_opp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drv->cpus[cpu].virt_devs = virt_devs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
|
cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
@ -570,7 +544,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
free_opp:
|
free_opp:
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
qcom_cpufreq_put_virt_devs(drv, cpu);
|
dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
|
||||||
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
|
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -584,7 +558,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
|
|||||||
platform_device_unregister(cpufreq_dt_pdev);
|
platform_device_unregister(cpufreq_dt_pdev);
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
qcom_cpufreq_put_virt_devs(drv, cpu);
|
dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
|
||||||
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
|
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -595,7 +569,7 @@ static int qcom_cpufreq_suspend(struct device *dev)
|
|||||||
unsigned int cpu;
|
unsigned int cpu;
|
||||||
|
|
||||||
for_each_possible_cpu(cpu)
|
for_each_possible_cpu(cpu)
|
||||||
qcom_cpufreq_suspend_virt_devs(drv, cpu);
|
qcom_cpufreq_suspend_pd_devs(drv, cpu);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ struct gr3d {
|
|||||||
unsigned int nclocks;
|
unsigned int nclocks;
|
||||||
struct reset_control_bulk_data resets[RST_GR3D_MAX];
|
struct reset_control_bulk_data resets[RST_GR3D_MAX];
|
||||||
unsigned int nresets;
|
unsigned int nresets;
|
||||||
|
struct dev_pm_domain_list *pd_list;
|
||||||
|
|
||||||
DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
|
DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
|
||||||
};
|
};
|
||||||
@ -369,18 +370,13 @@ static int gr3d_power_up_legacy_domain(struct device *dev, const char *name,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gr3d_del_link(void *link)
|
|
||||||
{
|
|
||||||
device_link_del(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int gr3d_init_power(struct device *dev, struct gr3d *gr3d)
|
static int gr3d_init_power(struct device *dev, struct gr3d *gr3d)
|
||||||
{
|
{
|
||||||
static const char * const opp_genpd_names[] = { "3d0", "3d1", NULL };
|
struct dev_pm_domain_attach_data pd_data = {
|
||||||
const u32 link_flags = DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
|
.pd_names = (const char *[]) { "3d0", "3d1" },
|
||||||
struct device **opp_virt_devs, *pd_dev;
|
.num_pd_names = 2,
|
||||||
struct device_link *link;
|
.pd_flags = PD_FLAG_REQUIRED_OPP,
|
||||||
unsigned int i;
|
};
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = of_count_phandle_with_args(dev->of_node, "power-domains",
|
err = of_count_phandle_with_args(dev->of_node, "power-domains",
|
||||||
@ -414,29 +410,10 @@ static int gr3d_init_power(struct device *dev, struct gr3d *gr3d)
|
|||||||
if (dev->pm_domain)
|
if (dev->pm_domain)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err = devm_pm_opp_attach_genpd(dev, opp_genpd_names, &opp_virt_devs);
|
err = devm_pm_domain_attach_list(dev, &pd_data, &gr3d->pd_list);
|
||||||
if (err)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
for (i = 0; opp_genpd_names[i]; i++) {
|
|
||||||
pd_dev = opp_virt_devs[i];
|
|
||||||
if (!pd_dev) {
|
|
||||||
dev_err(dev, "failed to get %s power domain\n",
|
|
||||||
opp_genpd_names[i]);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
link = device_link_add(dev, pd_dev, link_flags);
|
|
||||||
if (!link) {
|
|
||||||
dev_err(dev, "failed to link to %s\n", dev_name(pd_dev));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = devm_add_action_or_reset(dev, gr3d_del_link, link);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,7 +752,7 @@ static const struct venus_resources sdm845_res_v2 = {
|
|||||||
.vcodec_clks_num = 2,
|
.vcodec_clks_num = 2,
|
||||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0", "vcodec1" },
|
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0", "vcodec1" },
|
||||||
.vcodec_pmdomains_num = 3,
|
.vcodec_pmdomains_num = 3,
|
||||||
.opp_pmdomain = (const char *[]) { "cx", NULL },
|
.opp_pmdomain = (const char *[]) { "cx" },
|
||||||
.vcodec_num = 2,
|
.vcodec_num = 2,
|
||||||
.max_load = 3110400, /* 4096x2160@90 */
|
.max_load = 3110400, /* 4096x2160@90 */
|
||||||
.hfi_version = HFI_VERSION_4XX,
|
.hfi_version = HFI_VERSION_4XX,
|
||||||
@ -801,7 +801,7 @@ static const struct venus_resources sc7180_res = {
|
|||||||
.vcodec_clks_num = 2,
|
.vcodec_clks_num = 2,
|
||||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
||||||
.vcodec_pmdomains_num = 2,
|
.vcodec_pmdomains_num = 2,
|
||||||
.opp_pmdomain = (const char *[]) { "cx", NULL },
|
.opp_pmdomain = (const char *[]) { "cx" },
|
||||||
.vcodec_num = 1,
|
.vcodec_num = 1,
|
||||||
.hfi_version = HFI_VERSION_4XX,
|
.hfi_version = HFI_VERSION_4XX,
|
||||||
.vpu_version = VPU_VERSION_AR50,
|
.vpu_version = VPU_VERSION_AR50,
|
||||||
@ -858,7 +858,7 @@ static const struct venus_resources sm8250_res = {
|
|||||||
.vcodec_clks_num = 1,
|
.vcodec_clks_num = 1,
|
||||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
||||||
.vcodec_pmdomains_num = 2,
|
.vcodec_pmdomains_num = 2,
|
||||||
.opp_pmdomain = (const char *[]) { "mx", NULL },
|
.opp_pmdomain = (const char *[]) { "mx" },
|
||||||
.vcodec_num = 1,
|
.vcodec_num = 1,
|
||||||
.max_load = 7833600,
|
.max_load = 7833600,
|
||||||
.hfi_version = HFI_VERSION_6XX,
|
.hfi_version = HFI_VERSION_6XX,
|
||||||
@ -917,7 +917,7 @@ static const struct venus_resources sc7280_res = {
|
|||||||
.vcodec_clks_num = 2,
|
.vcodec_clks_num = 2,
|
||||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
||||||
.vcodec_pmdomains_num = 2,
|
.vcodec_pmdomains_num = 2,
|
||||||
.opp_pmdomain = (const char *[]) { "cx", NULL },
|
.opp_pmdomain = (const char *[]) { "cx" },
|
||||||
.vcodec_num = 1,
|
.vcodec_num = 1,
|
||||||
.hfi_version = HFI_VERSION_6XX,
|
.hfi_version = HFI_VERSION_6XX,
|
||||||
.vpu_version = VPU_VERSION_IRIS2_1,
|
.vpu_version = VPU_VERSION_IRIS2_1,
|
||||||
|
@ -132,9 +132,7 @@ struct venus_format {
|
|||||||
* @vcodec1_clks: an array of vcodec1 struct clk pointers
|
* @vcodec1_clks: an array of vcodec1 struct clk pointers
|
||||||
* @video_path: an interconnect handle to video to/from memory path
|
* @video_path: an interconnect handle to video to/from memory path
|
||||||
* @cpucfg_path: an interconnect handle to cpu configuration path
|
* @cpucfg_path: an interconnect handle to cpu configuration path
|
||||||
* @has_opp_table: does OPP table exist
|
|
||||||
* @pmdomains: a pointer to a list of pmdomains
|
* @pmdomains: a pointer to a list of pmdomains
|
||||||
* @opp_dl_venus: an device-link for device OPP
|
|
||||||
* @opp_pmdomain: an OPP power-domain
|
* @opp_pmdomain: an OPP power-domain
|
||||||
* @resets: an array of reset signals
|
* @resets: an array of reset signals
|
||||||
* @vdev_dec: a reference to video device structure for decoder instances
|
* @vdev_dec: a reference to video device structure for decoder instances
|
||||||
@ -186,10 +184,8 @@ struct venus_core {
|
|||||||
struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
|
struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
|
||||||
struct icc_path *video_path;
|
struct icc_path *video_path;
|
||||||
struct icc_path *cpucfg_path;
|
struct icc_path *cpucfg_path;
|
||||||
bool has_opp_table;
|
|
||||||
struct dev_pm_domain_list *pmdomains;
|
struct dev_pm_domain_list *pmdomains;
|
||||||
struct device_link *opp_dl_venus;
|
struct dev_pm_domain_list *opp_pmdomain;
|
||||||
struct device *opp_pmdomain;
|
|
||||||
struct reset_control *resets[VIDC_RESETS_NUM_MAX];
|
struct reset_control *resets[VIDC_RESETS_NUM_MAX];
|
||||||
struct video_device *vdev_dec;
|
struct video_device *vdev_dec;
|
||||||
struct video_device *vdev_enc;
|
struct video_device *vdev_enc;
|
||||||
|
@ -864,7 +864,6 @@ static int venc_power_v4(struct device *dev, int on)
|
|||||||
static int vcodec_domains_get(struct venus_core *core)
|
static int vcodec_domains_get(struct venus_core *core)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct device **opp_virt_dev;
|
|
||||||
struct device *dev = core->dev;
|
struct device *dev = core->dev;
|
||||||
const struct venus_resources *res = core->res;
|
const struct venus_resources *res = core->res;
|
||||||
struct dev_pm_domain_attach_data vcodec_data = {
|
struct dev_pm_domain_attach_data vcodec_data = {
|
||||||
@ -872,6 +871,11 @@ static int vcodec_domains_get(struct venus_core *core)
|
|||||||
.num_pd_names = res->vcodec_pmdomains_num,
|
.num_pd_names = res->vcodec_pmdomains_num,
|
||||||
.pd_flags = PD_FLAG_NO_DEV_LINK,
|
.pd_flags = PD_FLAG_NO_DEV_LINK,
|
||||||
};
|
};
|
||||||
|
struct dev_pm_domain_attach_data opp_pd_data = {
|
||||||
|
.pd_names = res->opp_pmdomain,
|
||||||
|
.num_pd_names = 1,
|
||||||
|
.pd_flags = PD_FLAG_DEV_LINK_ON | PD_FLAG_REQUIRED_OPP,
|
||||||
|
};
|
||||||
|
|
||||||
if (!res->vcodec_pmdomains_num)
|
if (!res->vcodec_pmdomains_num)
|
||||||
goto skip_pmdomains;
|
goto skip_pmdomains;
|
||||||
@ -881,37 +885,15 @@ static int vcodec_domains_get(struct venus_core *core)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
skip_pmdomains:
|
skip_pmdomains:
|
||||||
if (!core->res->opp_pmdomain)
|
if (!res->opp_pmdomain)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Attach the power domain for setting performance state */
|
/* Attach the power domain for setting performance state */
|
||||||
ret = devm_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev);
|
ret = devm_pm_domain_attach_list(dev, &opp_pd_data, &core->opp_pmdomain);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
goto opp_attach_err;
|
return ret;
|
||||||
|
|
||||||
core->opp_pmdomain = *opp_virt_dev;
|
|
||||||
core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain,
|
|
||||||
DL_FLAG_RPM_ACTIVE |
|
|
||||||
DL_FLAG_PM_RUNTIME |
|
|
||||||
DL_FLAG_STATELESS);
|
|
||||||
if (!core->opp_dl_venus) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
goto opp_attach_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
opp_attach_err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vcodec_domains_put(struct venus_core *core)
|
|
||||||
{
|
|
||||||
if (!core->has_opp_table)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (core->opp_dl_venus)
|
|
||||||
device_link_del(core->opp_dl_venus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int core_resets_reset(struct venus_core *core)
|
static int core_resets_reset(struct venus_core *core)
|
||||||
@ -1000,9 +982,7 @@ static int core_get_v4(struct venus_core *core)
|
|||||||
|
|
||||||
if (core->res->opp_pmdomain) {
|
if (core->res->opp_pmdomain) {
|
||||||
ret = devm_pm_opp_of_add_table(dev);
|
ret = devm_pm_opp_of_add_table(dev);
|
||||||
if (!ret) {
|
if (ret && ret != -ENODEV) {
|
||||||
core->has_opp_table = true;
|
|
||||||
} else if (ret != -ENODEV) {
|
|
||||||
dev_err(dev, "invalid OPP table in device tree\n");
|
dev_err(dev, "invalid OPP table in device tree\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1013,10 +993,6 @@ static int core_get_v4(struct venus_core *core)
|
|||||||
|
|
||||||
static void core_put_v4(struct venus_core *core)
|
static void core_put_v4(struct venus_core *core)
|
||||||
{
|
{
|
||||||
if (legacy_binding)
|
|
||||||
return;
|
|
||||||
|
|
||||||
vcodec_domains_put(core);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int core_power_v4(struct venus_core *core, int on)
|
static int core_power_v4(struct venus_core *core, int on)
|
||||||
|
@ -2360,48 +2360,13 @@ static void _opp_put_config_regulators_helper(struct opp_table *opp_table)
|
|||||||
opp_table->config_regulators = NULL;
|
opp_table->config_regulators = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _opp_detach_genpd(struct opp_table *opp_table)
|
static int _opp_set_required_dev(struct opp_table *opp_table,
|
||||||
|
struct device *dev,
|
||||||
|
struct device *required_dev,
|
||||||
|
unsigned int index)
|
||||||
{
|
{
|
||||||
int index;
|
struct opp_table *required_table, *pd_table;
|
||||||
|
struct device *gdev;
|
||||||
for (index = 0; index < opp_table->required_opp_count; index++) {
|
|
||||||
if (!opp_table->required_devs[index])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
dev_pm_domain_detach(opp_table->required_devs[index], false);
|
|
||||||
opp_table->required_devs[index] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Multiple generic power domains for a device are supported with the help of
|
|
||||||
* virtual genpd devices, which are created for each consumer device - genpd
|
|
||||||
* pair. These are the device structures which are attached to the power domain
|
|
||||||
* and are required by the OPP core to set the performance state of the genpd.
|
|
||||||
* The same API also works for the case where single genpd is available and so
|
|
||||||
* we don't need to support that separately.
|
|
||||||
*
|
|
||||||
* This helper will normally be called by the consumer driver of the device
|
|
||||||
* "dev", as only that has details of the genpd names.
|
|
||||||
*
|
|
||||||
* This helper needs to be called once with a list of all genpd to attach.
|
|
||||||
* Otherwise the original device structure will be used instead by the OPP core.
|
|
||||||
*
|
|
||||||
* The order of entries in the names array must match the order in which
|
|
||||||
* "required-opps" are added in DT.
|
|
||||||
*/
|
|
||||||
static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev,
|
|
||||||
const char * const *names, struct device ***virt_devs)
|
|
||||||
{
|
|
||||||
struct device *virt_dev, *gdev;
|
|
||||||
struct opp_table *genpd_table;
|
|
||||||
int index = 0, ret = -EINVAL;
|
|
||||||
const char * const *name = names;
|
|
||||||
|
|
||||||
if (!opp_table->required_devs) {
|
|
||||||
dev_err(dev, "Required OPPs not available, can't attach genpd\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Genpd core takes care of propagation to parent genpd */
|
/* Genpd core takes care of propagation to parent genpd */
|
||||||
if (opp_table->is_genpd) {
|
if (opp_table->is_genpd) {
|
||||||
@ -2409,114 +2374,59 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev,
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checking only the first one is enough ? */
|
|
||||||
if (opp_table->required_devs[0])
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while (*name) {
|
|
||||||
if (index >= opp_table->required_opp_count) {
|
if (index >= opp_table->required_opp_count) {
|
||||||
dev_err(dev, "Index can't be greater than required-opp-count - 1, %s (%d : %d)\n",
|
|
||||||
*name, opp_table->required_opp_count, index);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
virt_dev = dev_pm_domain_attach_by_name(dev, *name);
|
|
||||||
if (IS_ERR_OR_NULL(virt_dev)) {
|
|
||||||
ret = virt_dev ? PTR_ERR(virt_dev) : -ENODEV;
|
|
||||||
dev_err(dev, "Couldn't attach to pm_domain: %d\n", ret);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The required_opp_tables parsing is not perfect, as the OPP
|
|
||||||
* core does the parsing solely based on the DT node pointers.
|
|
||||||
* The core sets the required_opp_tables entry to the first OPP
|
|
||||||
* table in the "opp_tables" list, that matches with the node
|
|
||||||
* pointer.
|
|
||||||
*
|
|
||||||
* If the target DT OPP table is used by multiple devices and
|
|
||||||
* they all create separate instances of 'struct opp_table' from
|
|
||||||
* it, then it is possible that the required_opp_tables entry
|
|
||||||
* may be set to the incorrect sibling device.
|
|
||||||
*
|
|
||||||
* Cross check it again and fix if required.
|
|
||||||
*/
|
|
||||||
gdev = dev_to_genpd_dev(virt_dev);
|
|
||||||
if (IS_ERR(gdev)) {
|
|
||||||
ret = PTR_ERR(gdev);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
genpd_table = _find_opp_table(gdev);
|
|
||||||
if (!IS_ERR(genpd_table)) {
|
|
||||||
if (genpd_table != opp_table->required_opp_tables[index]) {
|
|
||||||
dev_pm_opp_put_opp_table(opp_table->required_opp_tables[index]);
|
|
||||||
opp_table->required_opp_tables[index] = genpd_table;
|
|
||||||
} else {
|
|
||||||
dev_pm_opp_put_opp_table(genpd_table);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
opp_table->required_devs[index] = virt_dev;
|
|
||||||
index++;
|
|
||||||
name++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virt_devs)
|
|
||||||
*virt_devs = opp_table->required_devs;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err:
|
|
||||||
_opp_detach_genpd(opp_table);
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _opp_set_required_devs(struct opp_table *opp_table,
|
|
||||||
struct device *dev,
|
|
||||||
struct device **required_devs)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!opp_table->required_devs) {
|
|
||||||
dev_err(dev, "Required OPPs not available, can't set required devs\n");
|
dev_err(dev, "Required OPPs not available, can't set required devs\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Another device that shares the OPP table has set the required devs ? */
|
required_table = opp_table->required_opp_tables[index];
|
||||||
if (opp_table->required_devs[0])
|
if (IS_ERR(required_table)) {
|
||||||
return 0;
|
dev_err(dev, "Missing OPP table, unable to set the required devs\n");
|
||||||
|
return -ENODEV;
|
||||||
for (i = 0; i < opp_table->required_opp_count; i++) {
|
|
||||||
/* Genpd core takes care of propagation to parent genpd */
|
|
||||||
if (required_devs[i] && opp_table->is_genpd &&
|
|
||||||
opp_table->required_opp_tables[i]->is_genpd) {
|
|
||||||
dev_err(dev, "%s: Operation not supported for genpds\n", __func__);
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
opp_table->required_devs[i] = required_devs[i];
|
/*
|
||||||
|
* The required_opp_tables parsing is not perfect, as the OPP core does
|
||||||
|
* the parsing solely based on the DT node pointers. The core sets the
|
||||||
|
* required_opp_tables entry to the first OPP table in the "opp_tables"
|
||||||
|
* list, that matches with the node pointer.
|
||||||
|
*
|
||||||
|
* If the target DT OPP table is used by multiple devices and they all
|
||||||
|
* create separate instances of 'struct opp_table' from it, then it is
|
||||||
|
* possible that the required_opp_tables entry may be set to the
|
||||||
|
* incorrect sibling device.
|
||||||
|
*
|
||||||
|
* Cross check it again and fix if required.
|
||||||
|
*/
|
||||||
|
gdev = dev_to_genpd_dev(required_dev);
|
||||||
|
if (IS_ERR(gdev))
|
||||||
|
return PTR_ERR(gdev);
|
||||||
|
|
||||||
|
pd_table = _find_opp_table(gdev);
|
||||||
|
if (!IS_ERR(pd_table)) {
|
||||||
|
if (pd_table != required_table) {
|
||||||
|
dev_pm_opp_put_opp_table(required_table);
|
||||||
|
opp_table->required_opp_tables[index] = pd_table;
|
||||||
|
} else {
|
||||||
|
dev_pm_opp_put_opp_table(pd_table);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opp_table->required_devs[index] = required_dev;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _opp_put_required_devs(struct opp_table *opp_table)
|
static void _opp_put_required_dev(struct opp_table *opp_table,
|
||||||
|
unsigned int index)
|
||||||
{
|
{
|
||||||
int i;
|
opp_table->required_devs[index] = NULL;
|
||||||
|
|
||||||
for (i = 0; i < opp_table->required_opp_count; i++)
|
|
||||||
opp_table->required_devs[i] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _opp_clear_config(struct opp_config_data *data)
|
static void _opp_clear_config(struct opp_config_data *data)
|
||||||
{
|
{
|
||||||
if (data->flags & OPP_CONFIG_REQUIRED_DEVS)
|
if (data->flags & OPP_CONFIG_REQUIRED_DEV)
|
||||||
_opp_put_required_devs(data->opp_table);
|
_opp_put_required_dev(data->opp_table,
|
||||||
else if (data->flags & OPP_CONFIG_GENPD)
|
data->required_dev_index);
|
||||||
_opp_detach_genpd(data->opp_table);
|
|
||||||
|
|
||||||
if (data->flags & OPP_CONFIG_REGULATOR)
|
if (data->flags & OPP_CONFIG_REGULATOR)
|
||||||
_opp_put_regulators(data->opp_table);
|
_opp_put_regulators(data->opp_table);
|
||||||
if (data->flags & OPP_CONFIG_SUPPORTED_HW)
|
if (data->flags & OPP_CONFIG_SUPPORTED_HW)
|
||||||
@ -2628,26 +2538,15 @@ int dev_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config)
|
|||||||
data->flags |= OPP_CONFIG_REGULATOR;
|
data->flags |= OPP_CONFIG_REGULATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attach genpds */
|
if (config->required_dev) {
|
||||||
if (config->genpd_names) {
|
ret = _opp_set_required_dev(opp_table, dev,
|
||||||
if (config->required_devs) {
|
config->required_dev,
|
||||||
ret = -EINVAL;
|
config->required_dev_index);
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = _opp_attach_genpd(opp_table, dev, config->genpd_names,
|
|
||||||
config->virt_devs);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
data->flags |= OPP_CONFIG_GENPD;
|
data->required_dev_index = config->required_dev_index;
|
||||||
} else if (config->required_devs) {
|
data->flags |= OPP_CONFIG_REQUIRED_DEV;
|
||||||
ret = _opp_set_required_devs(opp_table, dev,
|
|
||||||
config->required_devs);
|
|
||||||
if (ret)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
data->flags |= OPP_CONFIG_REQUIRED_DEVS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = xa_alloc(&opp_configs, &id, data, XA_LIMIT(1, INT_MAX),
|
ret = xa_alloc(&opp_configs, &id, data, XA_LIMIT(1, INT_MAX),
|
||||||
|
@ -295,7 +295,7 @@ void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp)
|
|||||||
of_node_put(opp->np);
|
of_node_put(opp->np);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _link_required_opps(struct dev_pm_opp *opp, struct opp_table *opp_table,
|
static int _link_required_opps(struct dev_pm_opp *opp,
|
||||||
struct opp_table *required_table, int index)
|
struct opp_table *required_table, int index)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
@ -313,39 +313,6 @@ static int _link_required_opps(struct dev_pm_opp *opp, struct opp_table *opp_tab
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* There are two genpd (as required-opp) cases that we need to handle,
|
|
||||||
* devices with a single genpd and ones with multiple genpds.
|
|
||||||
*
|
|
||||||
* The single genpd case requires special handling as we need to use the
|
|
||||||
* same `dev` structure (instead of a virtual one provided by genpd
|
|
||||||
* core) for setting the performance state.
|
|
||||||
*
|
|
||||||
* It doesn't make sense for a device's DT entry to have both
|
|
||||||
* "opp-level" and single "required-opps" entry pointing to a genpd's
|
|
||||||
* OPP, as that would make the OPP core call
|
|
||||||
* dev_pm_domain_set_performance_state() for two different values for
|
|
||||||
* the same device structure. Lets treat single genpd configuration as a
|
|
||||||
* case where the OPP's level is directly available without required-opp
|
|
||||||
* link in the DT.
|
|
||||||
*
|
|
||||||
* Just update the `level` with the right value, which
|
|
||||||
* dev_pm_opp_set_opp() will take care of in the normal path itself.
|
|
||||||
*
|
|
||||||
* There is another case though, where a genpd's OPP table has
|
|
||||||
* required-opps set to a parent genpd. The OPP core expects the user to
|
|
||||||
* set the respective required `struct device` pointer via
|
|
||||||
* dev_pm_opp_set_config().
|
|
||||||
*/
|
|
||||||
if (required_table->is_genpd && opp_table->required_opp_count == 1 &&
|
|
||||||
!opp_table->required_devs[0]) {
|
|
||||||
/* Genpd core takes care of propagation to parent genpd */
|
|
||||||
if (!opp_table->is_genpd) {
|
|
||||||
if (!WARN_ON(opp->level != OPP_LEVEL_UNSET))
|
|
||||||
opp->level = opp->required_opps[0]->level;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +337,7 @@ static int _of_opp_alloc_required_opps(struct opp_table *opp_table,
|
|||||||
if (IS_ERR_OR_NULL(required_table))
|
if (IS_ERR_OR_NULL(required_table))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = _link_required_opps(opp, opp_table, required_table, i);
|
ret = _link_required_opps(opp, required_table, i);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto free_required_opps;
|
goto free_required_opps;
|
||||||
}
|
}
|
||||||
@ -391,7 +358,7 @@ static int lazy_link_required_opps(struct opp_table *opp_table,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
list_for_each_entry(opp, &opp_table->opp_list, node) {
|
list_for_each_entry(opp, &opp_table->opp_list, node) {
|
||||||
ret = _link_required_opps(opp, opp_table, new_table, index);
|
ret = _link_required_opps(opp, new_table, index);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -34,13 +34,13 @@ extern struct list_head opp_tables;
|
|||||||
#define OPP_CONFIG_REGULATOR_HELPER BIT(2)
|
#define OPP_CONFIG_REGULATOR_HELPER BIT(2)
|
||||||
#define OPP_CONFIG_PROP_NAME BIT(3)
|
#define OPP_CONFIG_PROP_NAME BIT(3)
|
||||||
#define OPP_CONFIG_SUPPORTED_HW BIT(4)
|
#define OPP_CONFIG_SUPPORTED_HW BIT(4)
|
||||||
#define OPP_CONFIG_GENPD BIT(5)
|
#define OPP_CONFIG_REQUIRED_DEV BIT(5)
|
||||||
#define OPP_CONFIG_REQUIRED_DEVS BIT(6)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct opp_config_data - data for set config operations
|
* struct opp_config_data - data for set config operations
|
||||||
* @opp_table: OPP table
|
* @opp_table: OPP table
|
||||||
* @flags: OPP config flags
|
* @flags: OPP config flags
|
||||||
|
* @required_dev_index: The position in the array of required_devs
|
||||||
*
|
*
|
||||||
* This structure stores the OPP config information for each OPP table
|
* This structure stores the OPP config information for each OPP table
|
||||||
* configuration by the callers.
|
* configuration by the callers.
|
||||||
@ -48,6 +48,7 @@ extern struct list_head opp_tables;
|
|||||||
struct opp_config_data {
|
struct opp_config_data {
|
||||||
struct opp_table *opp_table;
|
struct opp_table *opp_table;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
unsigned int required_dev_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1727,6 +1727,7 @@ static void genpd_free_dev_data(struct device *dev,
|
|||||||
|
|
||||||
spin_unlock_irq(&dev->power.lock);
|
spin_unlock_irq(&dev->power.lock);
|
||||||
|
|
||||||
|
dev_pm_opp_clear_config(gpd_data->opp_token);
|
||||||
kfree(gpd_data->td);
|
kfree(gpd_data->td);
|
||||||
kfree(gpd_data);
|
kfree(gpd_data);
|
||||||
dev_pm_put_subsys_data(dev);
|
dev_pm_put_subsys_data(dev);
|
||||||
@ -2903,12 +2904,58 @@ static void genpd_dev_pm_sync(struct device *dev)
|
|||||||
genpd_queue_power_off_work(pd);
|
genpd_queue_power_off_work(pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int genpd_set_required_opp_dev(struct device *dev,
|
||||||
|
struct device *base_dev)
|
||||||
|
{
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.required_dev = dev,
|
||||||
|
};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Limit support to non-providers for now. */
|
||||||
|
if (of_property_present(base_dev->of_node, "#power-domain-cells"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!dev_pm_opp_of_has_required_opp(base_dev))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = dev_pm_opp_set_config(base_dev, &config);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
dev_gpd_data(dev)->opp_token = ret;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int genpd_set_required_opp(struct device *dev, unsigned int index)
|
||||||
|
{
|
||||||
|
int ret, pstate;
|
||||||
|
|
||||||
|
/* Set the default performance state */
|
||||||
|
pstate = of_get_required_opp_performance_state(dev->of_node, index);
|
||||||
|
if (pstate < 0 && pstate != -ENODEV && pstate != -EOPNOTSUPP) {
|
||||||
|
ret = pstate;
|
||||||
|
goto err;
|
||||||
|
} else if (pstate > 0) {
|
||||||
|
ret = dev_pm_genpd_set_performance_state(dev, pstate);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
dev_gpd_data(dev)->default_pstate = pstate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
dev_err(dev, "failed to set required performance state for power-domain %s: %d\n",
|
||||||
|
dev_to_genpd(dev)->name, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
|
static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
|
||||||
unsigned int index, bool power_on)
|
unsigned int index, unsigned int num_domains,
|
||||||
|
bool power_on)
|
||||||
{
|
{
|
||||||
struct of_phandle_args pd_args;
|
struct of_phandle_args pd_args;
|
||||||
struct generic_pm_domain *pd;
|
struct generic_pm_domain *pd;
|
||||||
int pstate;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
|
ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
|
||||||
@ -2937,18 +2984,21 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
|
|||||||
dev->pm_domain->detach = genpd_dev_pm_detach;
|
dev->pm_domain->detach = genpd_dev_pm_detach;
|
||||||
dev->pm_domain->sync = genpd_dev_pm_sync;
|
dev->pm_domain->sync = genpd_dev_pm_sync;
|
||||||
|
|
||||||
/* Set the default performance state */
|
/*
|
||||||
pstate = of_get_required_opp_performance_state(dev->of_node, index);
|
* For a single PM domain the index of the required OPP must be zero, so
|
||||||
if (pstate < 0 && pstate != -ENODEV && pstate != -EOPNOTSUPP) {
|
* let's try to assign a required dev in that case. In the multiple PM
|
||||||
ret = pstate;
|
* domains case, we need platform code to specify the index.
|
||||||
goto err;
|
*/
|
||||||
} else if (pstate > 0) {
|
if (num_domains == 1) {
|
||||||
ret = dev_pm_genpd_set_performance_state(dev, pstate);
|
ret = genpd_set_required_opp_dev(dev, base_dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
dev_gpd_data(dev)->default_pstate = pstate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = genpd_set_required_opp(dev, index);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
if (power_on) {
|
if (power_on) {
|
||||||
genpd_lock(pd);
|
genpd_lock(pd);
|
||||||
ret = genpd_power_on(pd, 0);
|
ret = genpd_power_on(pd, 0);
|
||||||
@ -2969,8 +3019,6 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
dev_err(dev, "failed to set required performance state for power-domain %s: %d\n",
|
|
||||||
pd->name, ret);
|
|
||||||
genpd_remove_device(pd, dev);
|
genpd_remove_device(pd, dev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -3001,7 +3049,7 @@ int genpd_dev_pm_attach(struct device *dev)
|
|||||||
"#power-domain-cells") != 1)
|
"#power-domain-cells") != 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return __genpd_dev_pm_attach(dev, dev, 0, true);
|
return __genpd_dev_pm_attach(dev, dev, 0, 1, true);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
|
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
|
||||||
|
|
||||||
@ -3054,7 +3102,7 @@ struct device *genpd_dev_pm_attach_by_id(struct device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Try to attach the device to the PM domain at the specified index. */
|
/* Try to attach the device to the PM domain at the specified index. */
|
||||||
ret = __genpd_dev_pm_attach(virt_dev, dev, index, false);
|
ret = __genpd_dev_pm_attach(virt_dev, dev, index, num_domains, false);
|
||||||
if (ret < 1) {
|
if (ret < 1) {
|
||||||
device_unregister(virt_dev);
|
device_unregister(virt_dev);
|
||||||
return ret ? ERR_PTR(ret) : NULL;
|
return ret ? ERR_PTR(ret) : NULL;
|
||||||
|
@ -411,7 +411,7 @@ static int imx_gpc_probe(struct platform_device *pdev)
|
|||||||
pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
|
pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
|
||||||
|
|
||||||
/* bail out if DT too old and doesn't provide the necessary info */
|
/* bail out if DT too old and doesn't provide the necessary info */
|
||||||
if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
|
if (!of_property_present(pdev->dev.of_node, "#power-domain-cells") &&
|
||||||
!pgc_node)
|
!pgc_node)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -511,7 +511,7 @@ static void imx_gpc_remove(struct platform_device *pdev)
|
|||||||
pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
|
pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
|
||||||
|
|
||||||
/* bail out if DT too old and doesn't provide the necessary info */
|
/* bail out if DT too old and doesn't provide the necessary info */
|
||||||
if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
|
if (!of_property_present(pdev->dev.of_node, "#power-domain-cells") &&
|
||||||
!pgc_node)
|
!pgc_node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1356,7 +1356,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
ret = pm_genpd_init(&domain->genpd, NULL, true);
|
ret = pm_genpd_init(&domain->genpd, NULL, true);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(domain->dev, "Failed to init power domain\n");
|
dev_err_probe(domain->dev, ret, "Failed to init power domain\n");
|
||||||
goto out_domain_unmap;
|
goto out_domain_unmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1367,7 +1367,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
|
|||||||
ret = of_genpd_add_provider_simple(domain->dev->of_node,
|
ret = of_genpd_add_provider_simple(domain->dev->of_node,
|
||||||
&domain->genpd);
|
&domain->genpd);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(domain->dev, "Failed to add genpd provider\n");
|
dev_err_probe(domain->dev, ret, "Failed to add genpd provider\n");
|
||||||
goto out_genpd_remove;
|
goto out_genpd_remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
96
drivers/pmdomain/mediatek/mt6735-pm-domains.h
Normal file
96
drivers/pmdomain/mediatek/mt6735-pm-domains.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef __SOC_MEDIATEK_MT6735_PM_DOMAINS_H
|
||||||
|
#define __SOC_MEDIATEK_MT6735_PM_DOMAINS_H
|
||||||
|
|
||||||
|
#include "mtk-pm-domains.h"
|
||||||
|
#include <dt-bindings/power/mediatek,mt6735-power-controller.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MT6735 power domain support
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const struct scpsys_domain_data scpsys_domain_data_mt6735[] = {
|
||||||
|
[MT6735_POWER_DOMAIN_MD1] = {
|
||||||
|
.name = "md1",
|
||||||
|
.sta_mask = PWR_STATUS_MD1,
|
||||||
|
.ctl_offs = SPM_MD1_PWR_CON,
|
||||||
|
.pwr_sta_offs = SPM_PWR_STATUS,
|
||||||
|
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
|
||||||
|
.sram_pdn_bits = GENMASK(8, 8),
|
||||||
|
.sram_pdn_ack_bits = 0,
|
||||||
|
.bp_cfg = {
|
||||||
|
BUS_PROT_INFRA_UPDATE_TOPAXI(MT6735_TOP_AXI_PROT_EN_MD1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[MT6735_POWER_DOMAIN_CONN] = {
|
||||||
|
.name = "conn",
|
||||||
|
.sta_mask = PWR_STATUS_CONN,
|
||||||
|
.ctl_offs = SPM_CONN_PWR_CON,
|
||||||
|
.pwr_sta_offs = SPM_PWR_STATUS,
|
||||||
|
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
|
||||||
|
.sram_pdn_bits = GENMASK(8, 8),
|
||||||
|
.sram_pdn_ack_bits = 0,
|
||||||
|
.bp_cfg = {
|
||||||
|
BUS_PROT_INFRA_UPDATE_TOPAXI(MT6735_TOP_AXI_PROT_EN_CONN),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[MT6735_POWER_DOMAIN_DIS] = {
|
||||||
|
.name = "dis",
|
||||||
|
.sta_mask = PWR_STATUS_DISP,
|
||||||
|
.ctl_offs = SPM_DIS_PWR_CON,
|
||||||
|
.pwr_sta_offs = SPM_PWR_STATUS,
|
||||||
|
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
|
||||||
|
.sram_pdn_bits = GENMASK(11, 8),
|
||||||
|
.sram_pdn_ack_bits = GENMASK(12, 12),
|
||||||
|
.bp_cfg = {
|
||||||
|
BUS_PROT_INFRA_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[MT6735_POWER_DOMAIN_MFG] = {
|
||||||
|
.name = "mfg",
|
||||||
|
.sta_mask = PWR_STATUS_MFG,
|
||||||
|
.ctl_offs = SPM_MFG_PWR_CON,
|
||||||
|
.pwr_sta_offs = SPM_PWR_STATUS,
|
||||||
|
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
|
||||||
|
.sram_pdn_bits = GENMASK(11, 8),
|
||||||
|
.sram_pdn_ack_bits = GENMASK(12, 12),
|
||||||
|
.bp_cfg = {
|
||||||
|
BUS_PROT_INFRA_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[MT6735_POWER_DOMAIN_ISP] = {
|
||||||
|
.name = "isp",
|
||||||
|
.sta_mask = PWR_STATUS_ISP,
|
||||||
|
.ctl_offs = SPM_ISP_PWR_CON,
|
||||||
|
.pwr_sta_offs = SPM_PWR_STATUS,
|
||||||
|
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
|
||||||
|
.sram_pdn_bits = GENMASK(11, 8),
|
||||||
|
.sram_pdn_ack_bits = GENMASK(13, 12),
|
||||||
|
},
|
||||||
|
[MT6735_POWER_DOMAIN_VDE] = {
|
||||||
|
.name = "vde",
|
||||||
|
.sta_mask = PWR_STATUS_VDEC,
|
||||||
|
.ctl_offs = SPM_VDE_PWR_CON,
|
||||||
|
.pwr_sta_offs = SPM_PWR_STATUS,
|
||||||
|
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
|
||||||
|
.sram_pdn_bits = GENMASK(11, 8),
|
||||||
|
.sram_pdn_ack_bits = GENMASK(12, 12),
|
||||||
|
},
|
||||||
|
[MT6735_POWER_DOMAIN_VEN] = {
|
||||||
|
.name = "ven",
|
||||||
|
.sta_mask = BIT(8),
|
||||||
|
.ctl_offs = SPM_VEN_PWR_CON,
|
||||||
|
.pwr_sta_offs = SPM_PWR_STATUS,
|
||||||
|
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
|
||||||
|
.sram_pdn_bits = GENMASK(11, 8),
|
||||||
|
.sram_pdn_ack_bits = GENMASK(15, 12),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct scpsys_soc_data mt6735_scpsys_data = {
|
||||||
|
.domains_data = scpsys_domain_data_mt6735,
|
||||||
|
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt6735),
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __SOC_MEDIATEK_MT6735_PM_DOMAINS_H */
|
@ -16,6 +16,7 @@
|
|||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/soc/mediatek/infracfg.h>
|
#include <linux/soc/mediatek/infracfg.h>
|
||||||
|
|
||||||
|
#include "mt6735-pm-domains.h"
|
||||||
#include "mt6795-pm-domains.h"
|
#include "mt6795-pm-domains.h"
|
||||||
#include "mt8167-pm-domains.h"
|
#include "mt8167-pm-domains.h"
|
||||||
#include "mt8173-pm-domains.h"
|
#include "mt8173-pm-domains.h"
|
||||||
@ -353,7 +354,6 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
|
|||||||
{
|
{
|
||||||
const struct scpsys_domain_data *domain_data;
|
const struct scpsys_domain_data *domain_data;
|
||||||
struct scpsys_domain *pd;
|
struct scpsys_domain *pd;
|
||||||
struct device_node *root_node = scpsys->dev->of_node;
|
|
||||||
struct device_node *smi_node;
|
struct device_node *smi_node;
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
const char *clk_name;
|
const char *clk_name;
|
||||||
@ -388,16 +388,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
|
|||||||
pd->scpsys = scpsys;
|
pd->scpsys = scpsys;
|
||||||
|
|
||||||
if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) {
|
if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) {
|
||||||
/*
|
pd->supply = devm_of_regulator_get_optional(scpsys->dev, node, "domain");
|
||||||
* Find regulator in current power domain node.
|
|
||||||
* devm_regulator_get() finds regulator in a node and its child
|
|
||||||
* node, so set of_node to current power domain node then change
|
|
||||||
* back to original node after regulator is found for current
|
|
||||||
* power domain node.
|
|
||||||
*/
|
|
||||||
scpsys->dev->of_node = node;
|
|
||||||
pd->supply = devm_regulator_get(scpsys->dev, "domain");
|
|
||||||
scpsys->dev->of_node = root_node;
|
|
||||||
if (IS_ERR(pd->supply))
|
if (IS_ERR(pd->supply))
|
||||||
return dev_err_cast_probe(scpsys->dev, pd->supply,
|
return dev_err_cast_probe(scpsys->dev, pd->supply,
|
||||||
"%pOF: failed to get power supply.\n",
|
"%pOF: failed to get power supply.\n",
|
||||||
@ -618,6 +609,10 @@ static void scpsys_domain_cleanup(struct scpsys *scpsys)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id scpsys_of_match[] = {
|
static const struct of_device_id scpsys_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "mediatek,mt6735-power-controller",
|
||||||
|
.data = &mt6735_scpsys_data,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.compatible = "mediatek,mt6795-power-controller",
|
.compatible = "mediatek,mt6795-power-controller",
|
||||||
.data = &mt6795_scpsys_data,
|
.data = &mt6795_scpsys_data,
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define SPM_ISP_PWR_CON 0x0238
|
#define SPM_ISP_PWR_CON 0x0238
|
||||||
#define SPM_DIS_PWR_CON 0x023c
|
#define SPM_DIS_PWR_CON 0x023c
|
||||||
#define SPM_CONN_PWR_CON 0x0280
|
#define SPM_CONN_PWR_CON 0x0280
|
||||||
|
#define SPM_MD1_PWR_CON 0x0284
|
||||||
#define SPM_VEN2_PWR_CON 0x0298
|
#define SPM_VEN2_PWR_CON 0x0298
|
||||||
#define SPM_AUDIO_PWR_CON 0x029c
|
#define SPM_AUDIO_PWR_CON 0x029c
|
||||||
#define SPM_MFG_2D_PWR_CON 0x02c0
|
#define SPM_MFG_2D_PWR_CON 0x02c0
|
||||||
@ -30,6 +31,7 @@
|
|||||||
#define SPM_PWR_STATUS 0x060c
|
#define SPM_PWR_STATUS 0x060c
|
||||||
#define SPM_PWR_STATUS_2ND 0x0610
|
#define SPM_PWR_STATUS_2ND 0x0610
|
||||||
|
|
||||||
|
#define PWR_STATUS_MD1 BIT(0)
|
||||||
#define PWR_STATUS_CONN BIT(1)
|
#define PWR_STATUS_CONN BIT(1)
|
||||||
#define PWR_STATUS_DISP BIT(3)
|
#define PWR_STATUS_DISP BIT(3)
|
||||||
#define PWR_STATUS_MFG BIT(4)
|
#define PWR_STATUS_MFG BIT(4)
|
||||||
|
@ -259,6 +259,30 @@ static const struct rpmhpd_desc sa8775p_desc = {
|
|||||||
.num_pds = ARRAY_SIZE(sa8775p_rpmhpds),
|
.num_pds = ARRAY_SIZE(sa8775p_rpmhpds),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* SAR2130P RPMH powerdomains */
|
||||||
|
static struct rpmhpd *sar2130p_rpmhpds[] = {
|
||||||
|
[RPMHPD_CX] = &cx,
|
||||||
|
[RPMHPD_CX_AO] = &cx_ao,
|
||||||
|
[RPMHPD_EBI] = &ebi,
|
||||||
|
[RPMHPD_GFX] = &gfx,
|
||||||
|
[RPMHPD_LCX] = &lcx,
|
||||||
|
[RPMHPD_LMX] = &lmx,
|
||||||
|
[RPMHPD_MMCX] = &mmcx_w_cx_parent,
|
||||||
|
[RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent,
|
||||||
|
[RPMHPD_MSS] = &mss,
|
||||||
|
[RPMHPD_MX] = &mx,
|
||||||
|
[RPMHPD_MX_AO] = &mx_ao,
|
||||||
|
[RPMHPD_MXC] = &mxc,
|
||||||
|
[RPMHPD_MXC_AO] = &mxc_ao,
|
||||||
|
[RPMHPD_NSP] = &nsp,
|
||||||
|
[RPMHPD_QPHY] = &qphy,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rpmhpd_desc sar2130p_desc = {
|
||||||
|
.rpmhpds = sar2130p_rpmhpds,
|
||||||
|
.num_pds = ARRAY_SIZE(sar2130p_rpmhpds),
|
||||||
|
};
|
||||||
|
|
||||||
/* SDM670 RPMH powerdomains */
|
/* SDM670 RPMH powerdomains */
|
||||||
static struct rpmhpd *sdm670_rpmhpds[] = {
|
static struct rpmhpd *sdm670_rpmhpds[] = {
|
||||||
[SDM670_CX] = &cx_w_mx_parent,
|
[SDM670_CX] = &cx_w_mx_parent,
|
||||||
@ -513,6 +537,31 @@ static const struct rpmhpd_desc sm8650_desc = {
|
|||||||
.num_pds = ARRAY_SIZE(sm8650_rpmhpds),
|
.num_pds = ARRAY_SIZE(sm8650_rpmhpds),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* SM8750 RPMH powerdomains */
|
||||||
|
static struct rpmhpd *sm8750_rpmhpds[] = {
|
||||||
|
[RPMHPD_CX] = &cx,
|
||||||
|
[RPMHPD_CX_AO] = &cx_ao,
|
||||||
|
[RPMHPD_EBI] = &ebi,
|
||||||
|
[RPMHPD_GFX] = &gfx,
|
||||||
|
[RPMHPD_GMXC] = &gmxc,
|
||||||
|
[RPMHPD_LCX] = &lcx,
|
||||||
|
[RPMHPD_LMX] = &lmx,
|
||||||
|
[RPMHPD_MX] = &mx,
|
||||||
|
[RPMHPD_MX_AO] = &mx_ao,
|
||||||
|
[RPMHPD_MMCX] = &mmcx_w_cx_parent,
|
||||||
|
[RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent,
|
||||||
|
[RPMHPD_MSS] = &mss,
|
||||||
|
[RPMHPD_MXC] = &mxc,
|
||||||
|
[RPMHPD_MXC_AO] = &mxc_ao,
|
||||||
|
[RPMHPD_NSP] = &nsp,
|
||||||
|
[RPMHPD_NSP2] = &nsp2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rpmhpd_desc sm8750_desc = {
|
||||||
|
.rpmhpds = sm8750_rpmhpds,
|
||||||
|
.num_pds = ARRAY_SIZE(sm8750_rpmhpds),
|
||||||
|
};
|
||||||
|
|
||||||
/* QDU1000/QRU1000 RPMH powerdomains */
|
/* QDU1000/QRU1000 RPMH powerdomains */
|
||||||
static struct rpmhpd *qdu1000_rpmhpds[] = {
|
static struct rpmhpd *qdu1000_rpmhpds[] = {
|
||||||
[QDU1000_CX] = &cx,
|
[QDU1000_CX] = &cx,
|
||||||
@ -624,11 +673,48 @@ static const struct rpmhpd_desc x1e80100_desc = {
|
|||||||
.num_pds = ARRAY_SIZE(x1e80100_rpmhpds),
|
.num_pds = ARRAY_SIZE(x1e80100_rpmhpds),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* QCS8300 RPMH power domains */
|
||||||
|
static struct rpmhpd *qcs8300_rpmhpds[] = {
|
||||||
|
[RPMHPD_CX] = &cx,
|
||||||
|
[RPMHPD_CX_AO] = &cx_ao,
|
||||||
|
[RPMHPD_EBI] = &ebi,
|
||||||
|
[RPMHPD_GFX] = &gfx,
|
||||||
|
[RPMHPD_LCX] = &lcx,
|
||||||
|
[RPMHPD_LMX] = &lmx,
|
||||||
|
[RPMHPD_MMCX] = &mmcx_w_cx_parent,
|
||||||
|
[RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent,
|
||||||
|
[RPMHPD_MXC] = &mxc,
|
||||||
|
[RPMHPD_MXC_AO] = &mxc_ao,
|
||||||
|
[RPMHPD_MX] = &mx,
|
||||||
|
[RPMHPD_MX_AO] = &mx_ao,
|
||||||
|
[RPMHPD_NSP0] = &nsp0,
|
||||||
|
[RPMHPD_NSP1] = &nsp1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rpmhpd_desc qcs8300_desc = {
|
||||||
|
.rpmhpds = qcs8300_rpmhpds,
|
||||||
|
.num_pds = ARRAY_SIZE(qcs8300_rpmhpds),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* QCS615 RPMH powerdomains */
|
||||||
|
static struct rpmhpd *qcs615_rpmhpds[] = {
|
||||||
|
[RPMHPD_CX] = &cx,
|
||||||
|
[RPMHPD_CX_AO] = &cx_ao,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rpmhpd_desc qcs615_desc = {
|
||||||
|
.rpmhpds = qcs615_rpmhpds,
|
||||||
|
.num_pds = ARRAY_SIZE(qcs615_rpmhpds),
|
||||||
|
};
|
||||||
|
|
||||||
static const struct of_device_id rpmhpd_match_table[] = {
|
static const struct of_device_id rpmhpd_match_table[] = {
|
||||||
|
{ .compatible = "qcom,qcs615-rpmhpd", .data = &qcs615_desc },
|
||||||
|
{ .compatible = "qcom,qcs8300-rpmhpd", .data = &qcs8300_desc },
|
||||||
{ .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc },
|
{ .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc },
|
||||||
{ .compatible = "qcom,sa8155p-rpmhpd", .data = &sa8155p_desc },
|
{ .compatible = "qcom,sa8155p-rpmhpd", .data = &sa8155p_desc },
|
||||||
{ .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc },
|
{ .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc },
|
||||||
{ .compatible = "qcom,sa8775p-rpmhpd", .data = &sa8775p_desc },
|
{ .compatible = "qcom,sa8775p-rpmhpd", .data = &sa8775p_desc },
|
||||||
|
{ .compatible = "qcom,sar2130p-rpmhpd", .data = &sar2130p_desc},
|
||||||
{ .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc },
|
{ .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc },
|
||||||
{ .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_desc },
|
{ .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_desc },
|
||||||
{ .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc },
|
{ .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc },
|
||||||
@ -646,6 +732,7 @@ static const struct of_device_id rpmhpd_match_table[] = {
|
|||||||
{ .compatible = "qcom,sm8450-rpmhpd", .data = &sm8450_desc },
|
{ .compatible = "qcom,sm8450-rpmhpd", .data = &sm8450_desc },
|
||||||
{ .compatible = "qcom,sm8550-rpmhpd", .data = &sm8550_desc },
|
{ .compatible = "qcom,sm8550-rpmhpd", .data = &sm8550_desc },
|
||||||
{ .compatible = "qcom,sm8650-rpmhpd", .data = &sm8650_desc },
|
{ .compatible = "qcom,sm8650-rpmhpd", .data = &sm8650_desc },
|
||||||
|
{ .compatible = "qcom,sm8750-rpmhpd", .data = &sm8750_desc },
|
||||||
{ .compatible = "qcom,x1e80100-rpmhpd", .data = &x1e80100_desc },
|
{ .compatible = "qcom,x1e80100-rpmhpd", .data = &x1e80100_desc },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
@ -131,9 +131,8 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev)
|
|||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct ti_sci_genpd_provider *pd_provider;
|
struct ti_sci_genpd_provider *pd_provider;
|
||||||
struct ti_sci_pm_domain *pd;
|
struct ti_sci_pm_domain *pd;
|
||||||
struct device_node *np;
|
struct device_node *np __free(device_node) = NULL;
|
||||||
struct of_phandle_args args;
|
struct of_phandle_args args;
|
||||||
int ret;
|
|
||||||
u32 max_id = 0;
|
u32 max_id = 0;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@ -153,14 +152,12 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev)
|
|||||||
for_each_node_with_property(np, "power-domains") {
|
for_each_node_with_property(np, "power-domains") {
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
while (1) {
|
while (!of_parse_phandle_with_args(np, "power-domains",
|
||||||
ret = of_parse_phandle_with_args(np, "power-domains",
|
|
||||||
"#power-domain-cells",
|
"#power-domain-cells",
|
||||||
index, &args);
|
index, &args)) {
|
||||||
if (ret)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (args.args_count >= 1 && args.np == dev->of_node) {
|
if (args.args_count >= 1 && args.np == dev->of_node) {
|
||||||
|
of_node_put(args.np);
|
||||||
if (args.args[0] > max_id) {
|
if (args.args[0] > max_id) {
|
||||||
max_id = args.args[0];
|
max_id = args.args[0];
|
||||||
} else {
|
} else {
|
||||||
@ -171,28 +168,28 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
|
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
|
||||||
if (!pd) {
|
if (!pd)
|
||||||
of_node_put(np);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
pd->pd.name = devm_kasprintf(dev, GFP_KERNEL,
|
pd->pd.name = devm_kasprintf(dev, GFP_KERNEL,
|
||||||
"pd:%d",
|
"pd:%d",
|
||||||
args.args[0]);
|
args.args[0]);
|
||||||
if (!pd->pd.name) {
|
if (!pd->pd.name)
|
||||||
of_node_put(np);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
pd->pd.power_off = ti_sci_pd_power_off;
|
pd->pd.power_off = ti_sci_pd_power_off;
|
||||||
pd->pd.power_on = ti_sci_pd_power_on;
|
pd->pd.power_on = ti_sci_pd_power_on;
|
||||||
|
pd->pd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
|
||||||
pd->idx = args.args[0];
|
pd->idx = args.args[0];
|
||||||
pd->parent = pd_provider;
|
pd->parent = pd_provider;
|
||||||
|
|
||||||
pm_genpd_init(&pd->pd, NULL, true);
|
pm_genpd_init(&pd->pd, NULL, true);
|
||||||
|
|
||||||
list_add(&pd->node, &pd_provider->pd_list);
|
list_add(&pd->node, &pd_provider->pd_list);
|
||||||
|
} else {
|
||||||
|
of_node_put(args.np);
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
include/dt-bindings/power/mediatek,mt6735-power-controller.h
Normal file
14
include/dt-bindings/power/mediatek,mt6735-power-controller.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||||
|
|
||||||
|
#ifndef _DT_BINDINGS_POWER_MT6735_POWER_CONTROLLER_H
|
||||||
|
#define _DT_BINDINGS_POWER_MT6735_POWER_CONTROLLER_H
|
||||||
|
|
||||||
|
#define MT6735_POWER_DOMAIN_MD1 0
|
||||||
|
#define MT6735_POWER_DOMAIN_CONN 1
|
||||||
|
#define MT6735_POWER_DOMAIN_DIS 2
|
||||||
|
#define MT6735_POWER_DOMAIN_MFG 3
|
||||||
|
#define MT6735_POWER_DOMAIN_ISP 4
|
||||||
|
#define MT6735_POWER_DOMAIN_VDE 5
|
||||||
|
#define MT6735_POWER_DOMAIN_VEN 6
|
||||||
|
|
||||||
|
#endif
|
@ -218,6 +218,7 @@
|
|||||||
/* SDM845 Power Domain performance levels */
|
/* SDM845 Power Domain performance levels */
|
||||||
#define RPMH_REGULATOR_LEVEL_RETENTION 16
|
#define RPMH_REGULATOR_LEVEL_RETENTION 16
|
||||||
#define RPMH_REGULATOR_LEVEL_MIN_SVS 48
|
#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_D2 52
|
||||||
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D1 56
|
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D1 56
|
||||||
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D0 60
|
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D0 60
|
||||||
@ -238,6 +239,7 @@
|
|||||||
#define RPMH_REGULATOR_LEVEL_TURBO_L1 416
|
#define RPMH_REGULATOR_LEVEL_TURBO_L1 416
|
||||||
#define RPMH_REGULATOR_LEVEL_TURBO_L2 432
|
#define RPMH_REGULATOR_LEVEL_TURBO_L2 432
|
||||||
#define RPMH_REGULATOR_LEVEL_TURBO_L3 448
|
#define RPMH_REGULATOR_LEVEL_TURBO_L3 448
|
||||||
|
#define RPMH_REGULATOR_LEVEL_TURBO_L4 452
|
||||||
#define RPMH_REGULATOR_LEVEL_SUPER_TURBO 464
|
#define RPMH_REGULATOR_LEVEL_SUPER_TURBO 464
|
||||||
#define RPMH_REGULATOR_LEVEL_SUPER_TURBO_NO_CPR 480
|
#define RPMH_REGULATOR_LEVEL_SUPER_TURBO_NO_CPR 480
|
||||||
|
|
||||||
|
@ -30,9 +30,16 @@
|
|||||||
* supplier and its PM domain when creating the
|
* supplier and its PM domain when creating the
|
||||||
* device-links.
|
* device-links.
|
||||||
*
|
*
|
||||||
|
* PD_FLAG_REQUIRED_OPP: Assign required_devs for the required OPPs. The
|
||||||
|
* index of the required OPP must correspond to the
|
||||||
|
* index in the array of the pd_names. If pd_names
|
||||||
|
* isn't specified, the index just follows the
|
||||||
|
* index for the attached PM domain.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
#define PD_FLAG_NO_DEV_LINK BIT(0)
|
#define PD_FLAG_NO_DEV_LINK BIT(0)
|
||||||
#define PD_FLAG_DEV_LINK_ON BIT(1)
|
#define PD_FLAG_DEV_LINK_ON BIT(1)
|
||||||
|
#define PD_FLAG_REQUIRED_OPP BIT(2)
|
||||||
|
|
||||||
struct dev_pm_domain_attach_data {
|
struct dev_pm_domain_attach_data {
|
||||||
const char * const *pd_names;
|
const char * const *pd_names;
|
||||||
@ -43,6 +50,7 @@ struct dev_pm_domain_attach_data {
|
|||||||
struct dev_pm_domain_list {
|
struct dev_pm_domain_list {
|
||||||
struct device **pd_devs;
|
struct device **pd_devs;
|
||||||
struct device_link **pd_links;
|
struct device_link **pd_links;
|
||||||
|
u32 *opp_tokens;
|
||||||
u32 num_pds;
|
u32 num_pds;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -250,6 +258,7 @@ struct generic_pm_domain_data {
|
|||||||
unsigned int performance_state;
|
unsigned int performance_state;
|
||||||
unsigned int default_pstate;
|
unsigned int default_pstate;
|
||||||
unsigned int rpm_pstate;
|
unsigned int rpm_pstate;
|
||||||
|
unsigned int opp_token;
|
||||||
bool hw_mode;
|
bool hw_mode;
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
@ -62,11 +62,8 @@ typedef int (*config_clks_t)(struct device *dev, struct opp_table *opp_table,
|
|||||||
* @supported_hw: Array of hierarchy of versions to match.
|
* @supported_hw: Array of hierarchy of versions to match.
|
||||||
* @supported_hw_count: Number of elements in the array.
|
* @supported_hw_count: Number of elements in the array.
|
||||||
* @regulator_names: Array of pointers to the names of the regulator, NULL terminated.
|
* @regulator_names: Array of pointers to the names of the regulator, NULL terminated.
|
||||||
* @genpd_names: Null terminated array of pointers containing names of genpd to
|
* @required_dev: The required OPP device.
|
||||||
* attach. Mutually exclusive with required_devs.
|
* @required_dev_index: The index of the required OPP for the @required_dev.
|
||||||
* @virt_devs: Pointer to return the array of genpd virtual devices. Mutually
|
|
||||||
* exclusive with required_devs.
|
|
||||||
* @required_devs: Required OPP devices. Mutually exclusive with genpd_names/virt_devs.
|
|
||||||
*
|
*
|
||||||
* This structure contains platform specific OPP configurations for the device.
|
* This structure contains platform specific OPP configurations for the device.
|
||||||
*/
|
*/
|
||||||
@ -79,9 +76,8 @@ struct dev_pm_opp_config {
|
|||||||
const unsigned int *supported_hw;
|
const unsigned int *supported_hw;
|
||||||
unsigned int supported_hw_count;
|
unsigned int supported_hw_count;
|
||||||
const char * const *regulator_names;
|
const char * const *regulator_names;
|
||||||
const char * const *genpd_names;
|
struct device *required_dev;
|
||||||
struct device ***virt_devs;
|
unsigned int required_dev_index;
|
||||||
struct device **required_devs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define OPP_LEVEL_UNSET U32_MAX
|
#define OPP_LEVEL_UNSET U32_MAX
|
||||||
@ -675,36 +671,6 @@ static inline void dev_pm_opp_put_config_regulators(int token)
|
|||||||
dev_pm_opp_clear_config(token);
|
dev_pm_opp_clear_config(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* genpd helpers */
|
|
||||||
static inline int dev_pm_opp_attach_genpd(struct device *dev,
|
|
||||||
const char * const *names,
|
|
||||||
struct device ***virt_devs)
|
|
||||||
{
|
|
||||||
struct dev_pm_opp_config config = {
|
|
||||||
.genpd_names = names,
|
|
||||||
.virt_devs = virt_devs,
|
|
||||||
};
|
|
||||||
|
|
||||||
return dev_pm_opp_set_config(dev, &config);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dev_pm_opp_detach_genpd(int token)
|
|
||||||
{
|
|
||||||
dev_pm_opp_clear_config(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int devm_pm_opp_attach_genpd(struct device *dev,
|
|
||||||
const char * const *names,
|
|
||||||
struct device ***virt_devs)
|
|
||||||
{
|
|
||||||
struct dev_pm_opp_config config = {
|
|
||||||
.genpd_names = names,
|
|
||||||
.virt_devs = virt_devs,
|
|
||||||
};
|
|
||||||
|
|
||||||
return devm_pm_opp_set_config(dev, &config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* prop-name helpers */
|
/* prop-name helpers */
|
||||||
static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
|
static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
|
||||||
{
|
{
|
||||||
|
@ -434,6 +434,11 @@
|
|||||||
#define MT7622_TOP_AXI_PROT_EN_WB (BIT(2) | BIT(6) | \
|
#define MT7622_TOP_AXI_PROT_EN_WB (BIT(2) | BIT(6) | \
|
||||||
BIT(7) | BIT(8))
|
BIT(7) | BIT(8))
|
||||||
|
|
||||||
|
#define MT6735_TOP_AXI_PROT_EN_CONN (BIT(2) | BIT(8))
|
||||||
|
#define MT6735_TOP_AXI_PROT_EN_MD1 (BIT(24) | BIT(25) | \
|
||||||
|
BIT(26) | BIT(27) | \
|
||||||
|
BIT(28))
|
||||||
|
|
||||||
#define INFRA_TOPAXI_PROTECTEN 0x0220
|
#define INFRA_TOPAXI_PROTECTEN 0x0220
|
||||||
#define INFRA_TOPAXI_PROTECTSTA1 0x0228
|
#define INFRA_TOPAXI_PROTECTSTA1 0x0228
|
||||||
#define INFRA_TOPAXI_PROTECTEN_SET 0x0260
|
#define INFRA_TOPAXI_PROTECTEN_SET 0x0260
|
||||||
|
Loading…
Reference in New Issue
Block a user