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:
|
||||
enum:
|
||||
- mediatek,mt6735-power-controller
|
||||
- mediatek,mt6795-power-controller
|
||||
- mediatek,mt8167-power-controller
|
||||
- mediatek,mt8173-power-controller
|
||||
|
@ -32,11 +32,14 @@ properties:
|
||||
- qcom,msm8998-rpmpd
|
||||
- qcom,qcm2290-rpmpd
|
||||
- qcom,qcs404-rpmpd
|
||||
- qcom,qcs615-rpmhpd
|
||||
- qcom,qcs8300-rpmhpd
|
||||
- qcom,qdu1000-rpmhpd
|
||||
- qcom,qm215-rpmpd
|
||||
- qcom,sa8155p-rpmhpd
|
||||
- qcom,sa8540p-rpmhpd
|
||||
- qcom,sa8775p-rpmhpd
|
||||
- qcom,sar2130p-rpmhpd
|
||||
- qcom,sc7180-rpmhpd
|
||||
- qcom,sc7280-rpmhpd
|
||||
- qcom,sc8180x-rpmhpd
|
||||
@ -58,6 +61,7 @@ properties:
|
||||
- qcom,sm8450-rpmhpd
|
||||
- qcom,sm8550-rpmhpd
|
||||
- qcom,sm8650-rpmhpd
|
||||
- qcom,sm8750-rpmhpd
|
||||
- qcom,x1e80100-rpmhpd
|
||||
- items:
|
||||
- enum:
|
||||
|
@ -20,6 +20,7 @@ Required properties:
|
||||
- compatible: Should be one of:
|
||||
- "mediatek,mt2701-scpsys"
|
||||
- "mediatek,mt2712-scpsys"
|
||||
- "mediatek,mt6735-scpsys"
|
||||
- "mediatek,mt6765-scpsys"
|
||||
- "mediatek,mt6797-scpsys"
|
||||
- "mediatek,mt7622-scpsys"
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/pm_clock.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_opp.h>
|
||||
|
||||
#include "power.h"
|
||||
|
||||
@ -222,13 +223,15 @@ int dev_pm_domain_attach_list(struct device *dev,
|
||||
if (!pds)
|
||||
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);
|
||||
if (!pds->pd_devs) {
|
||||
ret = -ENOMEM;
|
||||
goto free_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)
|
||||
link_flags |= DL_FLAG_RPM_ACTIVE;
|
||||
@ -244,6 +247,19 @@ int dev_pm_domain_attach_list(struct device *dev,
|
||||
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) {
|
||||
struct device_link *link;
|
||||
|
||||
@ -264,9 +280,11 @@ int dev_pm_domain_attach_list(struct device *dev,
|
||||
return num_pds;
|
||||
|
||||
err_link:
|
||||
dev_pm_opp_clear_config(pds->opp_tokens[i]);
|
||||
dev_pm_domain_detach(pd_dev, true);
|
||||
err_attach:
|
||||
while (--i >= 0) {
|
||||
dev_pm_opp_clear_config(pds->opp_tokens[i]);
|
||||
if (pds->pd_links[i])
|
||||
device_link_del(pds->pd_links[i]);
|
||||
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;
|
||||
|
||||
for (i = 0; i < list->num_pds; i++) {
|
||||
dev_pm_opp_clear_config(list->opp_tokens[i]);
|
||||
if (list->pd_links[i])
|
||||
device_link_del(list->pd_links[i]);
|
||||
dev_pm_domain_detach(list->pd_devs[i], true);
|
||||
|
@ -52,12 +52,13 @@ struct qcom_cpufreq_match_data {
|
||||
struct nvmem_cell *speedbin_nvmem,
|
||||
char **pvs_name,
|
||||
struct qcom_cpufreq_drv *drv);
|
||||
const char **genpd_names;
|
||||
const char **pd_names;
|
||||
unsigned int num_pd_names;
|
||||
};
|
||||
|
||||
struct qcom_cpufreq_drv_cpu {
|
||||
int opp_token;
|
||||
struct device **virt_devs;
|
||||
struct dev_pm_domain_list *pd_list;
|
||||
};
|
||||
|
||||
struct qcom_cpufreq_drv {
|
||||
@ -395,8 +396,6 @@ static int qcom_cpufreq_ipq8074_name_version(struct device *cpu_dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *generic_genpd_names[] = { "perf", NULL };
|
||||
|
||||
static const struct qcom_cpufreq_match_data match_data_kryo = {
|
||||
.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 = {
|
||||
.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 = {
|
||||
.genpd_names = qcs404_genpd_names,
|
||||
.pd_names = (const char *[]) { "cpr" },
|
||||
.num_pd_names = 1,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
if (!drv->cpus[cpu].virt_devs)
|
||||
if (!pd_list)
|
||||
return;
|
||||
|
||||
for (i = 0; *name; i++, name++)
|
||||
device_set_awake_path(drv->cpus[cpu].virt_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]);
|
||||
for (i = 0; i < pd_list->num_pds; i++)
|
||||
device_set_awake_path(pd_list->pd_devs[i]);
|
||||
}
|
||||
|
||||
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) {
|
||||
struct device **virt_devs = NULL;
|
||||
struct dev_pm_opp_config config = {
|
||||
.supported_hw = NULL,
|
||||
};
|
||||
@ -522,12 +508,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||
config.prop_name = pvs_name;
|
||||
}
|
||||
|
||||
if (drv->data->genpd_names) {
|
||||
config.genpd_names = drv->data->genpd_names;
|
||||
config.virt_devs = &virt_devs;
|
||||
}
|
||||
|
||||
if (config.supported_hw || config.genpd_names) {
|
||||
if (config.supported_hw) {
|
||||
drv->cpus[cpu].opp_token = dev_pm_opp_set_config(cpu_dev, &config);
|
||||
if (drv->cpus[cpu].opp_token < 0) {
|
||||
ret = drv->cpus[cpu].opp_token;
|
||||
@ -536,27 +517,20 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
if (virt_devs) {
|
||||
const char * const *name = config.genpd_names;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; *name; i++, name++) {
|
||||
ret = pm_runtime_resume_and_get(virt_devs[i]);
|
||||
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]);
|
||||
if (drv->data->pd_names) {
|
||||
struct dev_pm_domain_attach_data attach_data = {
|
||||
.pd_names = drv->data->pd_names,
|
||||
.num_pd_names = drv->data->num_pd_names,
|
||||
.pd_flags = PD_FLAG_DEV_LINK_ON |
|
||||
PD_FLAG_REQUIRED_OPP,
|
||||
};
|
||||
|
||||
ret = dev_pm_domain_attach_list(cpu_dev, &attach_data,
|
||||
&drv->cpus[cpu].pd_list);
|
||||
if (ret < 0)
|
||||
goto free_opp;
|
||||
}
|
||||
}
|
||||
drv->cpus[cpu].virt_devs = virt_devs;
|
||||
}
|
||||
}
|
||||
|
||||
cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
|
||||
NULL, 0);
|
||||
@ -570,7 +544,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||
|
||||
free_opp:
|
||||
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);
|
||||
}
|
||||
return ret;
|
||||
@ -584,7 +558,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
|
||||
platform_device_unregister(cpufreq_dt_pdev);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -595,7 +569,7 @@ static int qcom_cpufreq_suspend(struct device *dev)
|
||||
unsigned int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu)
|
||||
qcom_cpufreq_suspend_virt_devs(drv, cpu);
|
||||
qcom_cpufreq_suspend_pd_devs(drv, cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ struct gr3d {
|
||||
unsigned int nclocks;
|
||||
struct reset_control_bulk_data resets[RST_GR3D_MAX];
|
||||
unsigned int nresets;
|
||||
struct dev_pm_domain_list *pd_list;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void gr3d_del_link(void *link)
|
||||
{
|
||||
device_link_del(link);
|
||||
}
|
||||
|
||||
static int gr3d_init_power(struct device *dev, struct gr3d *gr3d)
|
||||
{
|
||||
static const char * const opp_genpd_names[] = { "3d0", "3d1", NULL };
|
||||
const u32 link_flags = DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
|
||||
struct device **opp_virt_devs, *pd_dev;
|
||||
struct device_link *link;
|
||||
unsigned int i;
|
||||
struct dev_pm_domain_attach_data pd_data = {
|
||||
.pd_names = (const char *[]) { "3d0", "3d1" },
|
||||
.num_pd_names = 2,
|
||||
.pd_flags = PD_FLAG_REQUIRED_OPP,
|
||||
};
|
||||
int err;
|
||||
|
||||
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)
|
||||
return 0;
|
||||
|
||||
err = devm_pm_opp_attach_genpd(dev, opp_genpd_names, &opp_virt_devs);
|
||||
if (err)
|
||||
err = devm_pm_domain_attach_list(dev, &pd_data, &gr3d->pd_list);
|
||||
if (err < 0)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -752,7 +752,7 @@ static const struct venus_resources sdm845_res_v2 = {
|
||||
.vcodec_clks_num = 2,
|
||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0", "vcodec1" },
|
||||
.vcodec_pmdomains_num = 3,
|
||||
.opp_pmdomain = (const char *[]) { "cx", NULL },
|
||||
.opp_pmdomain = (const char *[]) { "cx" },
|
||||
.vcodec_num = 2,
|
||||
.max_load = 3110400, /* 4096x2160@90 */
|
||||
.hfi_version = HFI_VERSION_4XX,
|
||||
@ -801,7 +801,7 @@ static const struct venus_resources sc7180_res = {
|
||||
.vcodec_clks_num = 2,
|
||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
||||
.vcodec_pmdomains_num = 2,
|
||||
.opp_pmdomain = (const char *[]) { "cx", NULL },
|
||||
.opp_pmdomain = (const char *[]) { "cx" },
|
||||
.vcodec_num = 1,
|
||||
.hfi_version = HFI_VERSION_4XX,
|
||||
.vpu_version = VPU_VERSION_AR50,
|
||||
@ -858,7 +858,7 @@ static const struct venus_resources sm8250_res = {
|
||||
.vcodec_clks_num = 1,
|
||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
||||
.vcodec_pmdomains_num = 2,
|
||||
.opp_pmdomain = (const char *[]) { "mx", NULL },
|
||||
.opp_pmdomain = (const char *[]) { "mx" },
|
||||
.vcodec_num = 1,
|
||||
.max_load = 7833600,
|
||||
.hfi_version = HFI_VERSION_6XX,
|
||||
@ -917,7 +917,7 @@ static const struct venus_resources sc7280_res = {
|
||||
.vcodec_clks_num = 2,
|
||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
||||
.vcodec_pmdomains_num = 2,
|
||||
.opp_pmdomain = (const char *[]) { "cx", NULL },
|
||||
.opp_pmdomain = (const char *[]) { "cx" },
|
||||
.vcodec_num = 1,
|
||||
.hfi_version = HFI_VERSION_6XX,
|
||||
.vpu_version = VPU_VERSION_IRIS2_1,
|
||||
|
@ -132,9 +132,7 @@ struct venus_format {
|
||||
* @vcodec1_clks: an array of vcodec1 struct clk pointers
|
||||
* @video_path: an interconnect handle to video to/from memory 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
|
||||
* @opp_dl_venus: an device-link for device OPP
|
||||
* @opp_pmdomain: an OPP power-domain
|
||||
* @resets: an array of reset signals
|
||||
* @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 icc_path *video_path;
|
||||
struct icc_path *cpucfg_path;
|
||||
bool has_opp_table;
|
||||
struct dev_pm_domain_list *pmdomains;
|
||||
struct device_link *opp_dl_venus;
|
||||
struct device *opp_pmdomain;
|
||||
struct dev_pm_domain_list *opp_pmdomain;
|
||||
struct reset_control *resets[VIDC_RESETS_NUM_MAX];
|
||||
struct video_device *vdev_dec;
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
struct device **opp_virt_dev;
|
||||
struct device *dev = core->dev;
|
||||
const struct venus_resources *res = core->res;
|
||||
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,
|
||||
.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)
|
||||
goto skip_pmdomains;
|
||||
@ -881,37 +885,15 @@ static int vcodec_domains_get(struct venus_core *core)
|
||||
return ret;
|
||||
|
||||
skip_pmdomains:
|
||||
if (!core->res->opp_pmdomain)
|
||||
if (!res->opp_pmdomain)
|
||||
return 0;
|
||||
|
||||
/* Attach the power domain for setting performance state */
|
||||
ret = devm_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev);
|
||||
if (ret)
|
||||
goto opp_attach_err;
|
||||
|
||||
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;
|
||||
}
|
||||
ret = devm_pm_domain_attach_list(dev, &opp_pd_data, &core->opp_pmdomain);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
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)
|
||||
@ -1000,9 +982,7 @@ static int core_get_v4(struct venus_core *core)
|
||||
|
||||
if (core->res->opp_pmdomain) {
|
||||
ret = devm_pm_opp_of_add_table(dev);
|
||||
if (!ret) {
|
||||
core->has_opp_table = true;
|
||||
} else if (ret != -ENODEV) {
|
||||
if (ret && ret != -ENODEV) {
|
||||
dev_err(dev, "invalid OPP table in device tree\n");
|
||||
return ret;
|
||||
}
|
||||
@ -1013,10 +993,6 @@ static int core_get_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)
|
||||
|
@ -2360,48 +2360,13 @@ static void _opp_put_config_regulators_helper(struct opp_table *opp_table)
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
struct opp_table *required_table, *pd_table;
|
||||
struct device *gdev;
|
||||
|
||||
/* Genpd core takes care of propagation to parent 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;
|
||||
}
|
||||
|
||||
/* Checking only the first one is enough ? */
|
||||
if (opp_table->required_devs[0])
|
||||
return 0;
|
||||
|
||||
while (*name) {
|
||||
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");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Another device that shares the OPP table has set the required devs ? */
|
||||
if (opp_table->required_devs[0])
|
||||
return 0;
|
||||
|
||||
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;
|
||||
required_table = opp_table->required_opp_tables[index];
|
||||
if (IS_ERR(required_table)) {
|
||||
dev_err(dev, "Missing OPP table, unable to set the required devs\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
for (i = 0; i < opp_table->required_opp_count; i++)
|
||||
opp_table->required_devs[i] = NULL;
|
||||
opp_table->required_devs[index] = NULL;
|
||||
}
|
||||
|
||||
static void _opp_clear_config(struct opp_config_data *data)
|
||||
{
|
||||
if (data->flags & OPP_CONFIG_REQUIRED_DEVS)
|
||||
_opp_put_required_devs(data->opp_table);
|
||||
else if (data->flags & OPP_CONFIG_GENPD)
|
||||
_opp_detach_genpd(data->opp_table);
|
||||
|
||||
if (data->flags & OPP_CONFIG_REQUIRED_DEV)
|
||||
_opp_put_required_dev(data->opp_table,
|
||||
data->required_dev_index);
|
||||
if (data->flags & OPP_CONFIG_REGULATOR)
|
||||
_opp_put_regulators(data->opp_table);
|
||||
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;
|
||||
}
|
||||
|
||||
/* Attach genpds */
|
||||
if (config->genpd_names) {
|
||||
if (config->required_devs) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = _opp_attach_genpd(opp_table, dev, config->genpd_names,
|
||||
config->virt_devs);
|
||||
if (config->required_dev) {
|
||||
ret = _opp_set_required_dev(opp_table, dev,
|
||||
config->required_dev,
|
||||
config->required_dev_index);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
data->flags |= OPP_CONFIG_GENPD;
|
||||
} else if (config->required_devs) {
|
||||
ret = _opp_set_required_devs(opp_table, dev,
|
||||
config->required_devs);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
data->flags |= OPP_CONFIG_REQUIRED_DEVS;
|
||||
data->required_dev_index = config->required_dev_index;
|
||||
data->flags |= OPP_CONFIG_REQUIRED_DEV;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 device_node *np;
|
||||
@ -313,39 +313,6 @@ static int _link_required_opps(struct dev_pm_opp *opp, struct opp_table *opp_tab
|
||||
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;
|
||||
}
|
||||
|
||||
@ -370,7 +337,7 @@ static int _of_opp_alloc_required_opps(struct opp_table *opp_table,
|
||||
if (IS_ERR_OR_NULL(required_table))
|
||||
continue;
|
||||
|
||||
ret = _link_required_opps(opp, opp_table, required_table, i);
|
||||
ret = _link_required_opps(opp, required_table, i);
|
||||
if (ret)
|
||||
goto free_required_opps;
|
||||
}
|
||||
@ -391,7 +358,7 @@ static int lazy_link_required_opps(struct opp_table *opp_table,
|
||||
int ret;
|
||||
|
||||
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)
|
||||
return ret;
|
||||
}
|
||||
|
@ -34,13 +34,13 @@ extern struct list_head opp_tables;
|
||||
#define OPP_CONFIG_REGULATOR_HELPER BIT(2)
|
||||
#define OPP_CONFIG_PROP_NAME BIT(3)
|
||||
#define OPP_CONFIG_SUPPORTED_HW BIT(4)
|
||||
#define OPP_CONFIG_GENPD BIT(5)
|
||||
#define OPP_CONFIG_REQUIRED_DEVS BIT(6)
|
||||
#define OPP_CONFIG_REQUIRED_DEV BIT(5)
|
||||
|
||||
/**
|
||||
* struct opp_config_data - data for set config operations
|
||||
* @opp_table: OPP table
|
||||
* @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
|
||||
* configuration by the callers.
|
||||
@ -48,6 +48,7 @@ extern struct list_head opp_tables;
|
||||
struct opp_config_data {
|
||||
struct opp_table *opp_table;
|
||||
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);
|
||||
|
||||
dev_pm_opp_clear_config(gpd_data->opp_token);
|
||||
kfree(gpd_data->td);
|
||||
kfree(gpd_data);
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
unsigned int index, bool power_on)
|
||||
unsigned int index, unsigned int num_domains,
|
||||
bool power_on)
|
||||
{
|
||||
struct of_phandle_args pd_args;
|
||||
struct generic_pm_domain *pd;
|
||||
int pstate;
|
||||
int ret;
|
||||
|
||||
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->sync = genpd_dev_pm_sync;
|
||||
|
||||
/* 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);
|
||||
/*
|
||||
* For a single PM domain the index of the required OPP must be zero, so
|
||||
* let's try to assign a required dev in that case. In the multiple PM
|
||||
* domains case, we need platform code to specify the index.
|
||||
*/
|
||||
if (num_domains == 1) {
|
||||
ret = genpd_set_required_opp_dev(dev, base_dev);
|
||||
if (ret)
|
||||
goto err;
|
||||
dev_gpd_data(dev)->default_pstate = pstate;
|
||||
}
|
||||
|
||||
ret = genpd_set_required_opp(dev, index);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (power_on) {
|
||||
genpd_lock(pd);
|
||||
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;
|
||||
|
||||
err:
|
||||
dev_err(dev, "failed to set required performance state for power-domain %s: %d\n",
|
||||
pd->name, ret);
|
||||
genpd_remove_device(pd, dev);
|
||||
return ret;
|
||||
}
|
||||
@ -3001,7 +3049,7 @@ int genpd_dev_pm_attach(struct device *dev)
|
||||
"#power-domain-cells") != 1)
|
||||
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);
|
||||
|
||||
@ -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. */
|
||||
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) {
|
||||
device_unregister(virt_dev);
|
||||
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");
|
||||
|
||||
/* 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)
|
||||
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");
|
||||
|
||||
/* 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)
|
||||
return;
|
||||
|
||||
|
@ -1356,7 +1356,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
|
||||
|
||||
ret = pm_genpd_init(&domain->genpd, NULL, true);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1367,7 +1367,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
|
||||
ret = of_genpd_add_provider_simple(domain->dev->of_node,
|
||||
&domain->genpd);
|
||||
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;
|
||||
}
|
||||
|
||||
|
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/soc/mediatek/infracfg.h>
|
||||
|
||||
#include "mt6735-pm-domains.h"
|
||||
#include "mt6795-pm-domains.h"
|
||||
#include "mt8167-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;
|
||||
struct scpsys_domain *pd;
|
||||
struct device_node *root_node = scpsys->dev->of_node;
|
||||
struct device_node *smi_node;
|
||||
struct property *prop;
|
||||
const char *clk_name;
|
||||
@ -388,16 +388,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
|
||||
pd->scpsys = scpsys;
|
||||
|
||||
if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) {
|
||||
/*
|
||||
* 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;
|
||||
pd->supply = devm_of_regulator_get_optional(scpsys->dev, node, "domain");
|
||||
if (IS_ERR(pd->supply))
|
||||
return dev_err_cast_probe(scpsys->dev, pd->supply,
|
||||
"%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[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt6735-power-controller",
|
||||
.data = &mt6735_scpsys_data,
|
||||
},
|
||||
{
|
||||
.compatible = "mediatek,mt6795-power-controller",
|
||||
.data = &mt6795_scpsys_data,
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define SPM_ISP_PWR_CON 0x0238
|
||||
#define SPM_DIS_PWR_CON 0x023c
|
||||
#define SPM_CONN_PWR_CON 0x0280
|
||||
#define SPM_MD1_PWR_CON 0x0284
|
||||
#define SPM_VEN2_PWR_CON 0x0298
|
||||
#define SPM_AUDIO_PWR_CON 0x029c
|
||||
#define SPM_MFG_2D_PWR_CON 0x02c0
|
||||
@ -30,6 +31,7 @@
|
||||
#define SPM_PWR_STATUS 0x060c
|
||||
#define SPM_PWR_STATUS_2ND 0x0610
|
||||
|
||||
#define PWR_STATUS_MD1 BIT(0)
|
||||
#define PWR_STATUS_CONN BIT(1)
|
||||
#define PWR_STATUS_DISP BIT(3)
|
||||
#define PWR_STATUS_MFG BIT(4)
|
||||
|
@ -259,6 +259,30 @@ static const struct rpmhpd_desc sa8775p_desc = {
|
||||
.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 */
|
||||
static struct rpmhpd *sdm670_rpmhpds[] = {
|
||||
[SDM670_CX] = &cx_w_mx_parent,
|
||||
@ -513,6 +537,31 @@ static const struct rpmhpd_desc sm8650_desc = {
|
||||
.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 */
|
||||
static struct rpmhpd *qdu1000_rpmhpds[] = {
|
||||
[QDU1000_CX] = &cx,
|
||||
@ -624,11 +673,48 @@ static const struct rpmhpd_desc x1e80100_desc = {
|
||||
.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[] = {
|
||||
{ .compatible = "qcom,qcs615-rpmhpd", .data = &qcs615_desc },
|
||||
{ .compatible = "qcom,qcs8300-rpmhpd", .data = &qcs8300_desc },
|
||||
{ .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc },
|
||||
{ .compatible = "qcom,sa8155p-rpmhpd", .data = &sa8155p_desc },
|
||||
{ .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc },
|
||||
{ .compatible = "qcom,sa8775p-rpmhpd", .data = &sa8775p_desc },
|
||||
{ .compatible = "qcom,sar2130p-rpmhpd", .data = &sar2130p_desc},
|
||||
{ .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc },
|
||||
{ .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_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,sm8550-rpmhpd", .data = &sm8550_desc },
|
||||
{ .compatible = "qcom,sm8650-rpmhpd", .data = &sm8650_desc },
|
||||
{ .compatible = "qcom,sm8750-rpmhpd", .data = &sm8750_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 ti_sci_genpd_provider *pd_provider;
|
||||
struct ti_sci_pm_domain *pd;
|
||||
struct device_node *np;
|
||||
struct device_node *np __free(device_node) = NULL;
|
||||
struct of_phandle_args args;
|
||||
int ret;
|
||||
u32 max_id = 0;
|
||||
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") {
|
||||
index = 0;
|
||||
|
||||
while (1) {
|
||||
ret = of_parse_phandle_with_args(np, "power-domains",
|
||||
while (!of_parse_phandle_with_args(np, "power-domains",
|
||||
"#power-domain-cells",
|
||||
index, &args);
|
||||
if (ret)
|
||||
break;
|
||||
index, &args)) {
|
||||
|
||||
if (args.args_count >= 1 && args.np == dev->of_node) {
|
||||
of_node_put(args.np);
|
||||
if (args.args[0] > max_id) {
|
||||
max_id = args.args[0];
|
||||
} else {
|
||||
@ -171,28 +168,28 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
|
||||
if (!pd) {
|
||||
of_node_put(np);
|
||||
if (!pd)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pd->pd.name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"pd:%d",
|
||||
args.args[0]);
|
||||
if (!pd->pd.name) {
|
||||
of_node_put(np);
|
||||
if (!pd->pd.name)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pd->pd.power_off = ti_sci_pd_power_off;
|
||||
pd->pd.power_on = ti_sci_pd_power_on;
|
||||
pd->pd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
|
||||
pd->idx = args.args[0];
|
||||
pd->parent = pd_provider;
|
||||
|
||||
pm_genpd_init(&pd->pd, NULL, true);
|
||||
|
||||
list_add(&pd->node, &pd_provider->pd_list);
|
||||
} else {
|
||||
of_node_put(args.np);
|
||||
}
|
||||
|
||||
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 */
|
||||
#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
|
||||
@ -238,6 +239,7 @@
|
||||
#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_SUPER_TURBO 464
|
||||
#define RPMH_REGULATOR_LEVEL_SUPER_TURBO_NO_CPR 480
|
||||
|
||||
|
@ -30,9 +30,16 @@
|
||||
* supplier and its PM domain when creating the
|
||||
* 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_DEV_LINK_ON BIT(1)
|
||||
#define PD_FLAG_REQUIRED_OPP BIT(2)
|
||||
|
||||
struct dev_pm_domain_attach_data {
|
||||
const char * const *pd_names;
|
||||
@ -43,6 +50,7 @@ struct dev_pm_domain_attach_data {
|
||||
struct dev_pm_domain_list {
|
||||
struct device **pd_devs;
|
||||
struct device_link **pd_links;
|
||||
u32 *opp_tokens;
|
||||
u32 num_pds;
|
||||
};
|
||||
|
||||
@ -250,6 +258,7 @@ struct generic_pm_domain_data {
|
||||
unsigned int performance_state;
|
||||
unsigned int default_pstate;
|
||||
unsigned int rpm_pstate;
|
||||
unsigned int opp_token;
|
||||
bool hw_mode;
|
||||
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_count: Number of elements in the array.
|
||||
* @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
|
||||
* attach. Mutually exclusive with required_devs.
|
||||
* @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.
|
||||
* @required_dev: The required OPP device.
|
||||
* @required_dev_index: The index of the required OPP for the @required_dev.
|
||||
*
|
||||
* This structure contains platform specific OPP configurations for the device.
|
||||
*/
|
||||
@ -79,9 +76,8 @@ struct dev_pm_opp_config {
|
||||
const unsigned int *supported_hw;
|
||||
unsigned int supported_hw_count;
|
||||
const char * const *regulator_names;
|
||||
const char * const *genpd_names;
|
||||
struct device ***virt_devs;
|
||||
struct device **required_devs;
|
||||
struct device *required_dev;
|
||||
unsigned int required_dev_index;
|
||||
};
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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) | \
|
||||
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_PROTECTSTA1 0x0228
|
||||
#define INFRA_TOPAXI_PROTECTEN_SET 0x0260
|
||||
|
Loading…
Reference in New Issue
Block a user