mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'pmdomain-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm
Pull pmdomain updates from Ulf Hansson:
"Core:
- Log a message when unused PM domains gets disabled
- Scale down parent/child performance states in the reverse order
Providers:
- qcom: rpmpd: Add power domains support for MSM8974, MSM8974PRO,
PMA8084 and PM8841
- renesas: rcar-gen4-sysc: Reduce atomic delays
- renesas: rcar-sysc: Adjust the waiting time to cover the worst case
- renesas: r8a779h0-sysc: Add support for the r8a779h0 PM domains
- imx: imx8mp-blk-ctrl: Add the fdcc clock to the hdmimix domains
- imx: imx8mp-blk-ctrl: Error out if domains are missing in DT
Improve support for multiple PM domains:
- Add two helper functions to attach/detach multiple PM domains
- Convert a couple of drivers to use the new helper functions"
* tag 'pmdomain-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm: (22 commits)
pmdomain: renesas: rcar-gen4-sysc: Reduce atomic delays
pmdomain: renesas: Adjust the waiting time to cover the worst case
pmdomain: qcom: rpmpd: Add MSM8974PRO+PMA8084 power domains
pmdomain: qcom: rpmpd: Add MSM8974+PM8841 power domains
pmdomain: core: constify of_phandle_args in add device and subdomain
pmdomain: core: constify of_phandle_args in xlate
media: venus: Convert to dev_pm_domain_attach|detach_list() for vcodec
remoteproc: qcom_q6v5_adsp: Convert to dev_pm_domain_attach|detach_list()
remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()
remoteproc: imx_dsp_rproc: Convert to dev_pm_domain_attach|detach_list()
PM: domains: Add helper functions to attach/detach multiple PM domains
pmdomain: imx8mp-blk-ctrl: imx8mp_blk: Add fdcc clock to hdmimix domain
pmdomain: mediatek: Use devm_platform_ioremap_resource() in init_scp()
pmdomain: renesas: r8a779h0-sysc: Add r8a779h0 support
pmdomain: imx8mp-blk-ctrl: Error out if domains are missing in DT
pmdomain: ti: Add a null pointer check to the omap_prm_domain_init
pmdomain: renesas: rcar-gen4-sysc: Remove unneeded includes
pmdomain: core: Print a message when unused power domains are disabled
pmdomain: qcom: rpmpd: Keep one RPM handle for all RPMPDs
pmdomain: core: Scale down parent/child performance states in reverse order
...
This commit is contained in:
@@ -24,6 +24,8 @@ properties:
|
||||
- qcom,msm8917-rpmpd
|
||||
- qcom,msm8939-rpmpd
|
||||
- qcom,msm8953-rpmpd
|
||||
- qcom,msm8974-rpmpd
|
||||
- qcom,msm8974pro-pma8084-rpmpd
|
||||
- qcom,msm8976-rpmpd
|
||||
- qcom,msm8994-rpmpd
|
||||
- qcom,msm8996-rpmpd
|
||||
|
||||
@@ -27,8 +27,8 @@ properties:
|
||||
const: 1
|
||||
|
||||
power-domains:
|
||||
minItems: 8
|
||||
maxItems: 8
|
||||
minItems: 10
|
||||
maxItems: 10
|
||||
|
||||
power-domain-names:
|
||||
items:
|
||||
@@ -40,10 +40,12 @@ properties:
|
||||
- const: trng
|
||||
- const: hdmi-tx
|
||||
- const: hdmi-tx-phy
|
||||
- const: hdcp
|
||||
- const: hrv
|
||||
|
||||
clocks:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
@@ -51,6 +53,7 @@ properties:
|
||||
- const: axi
|
||||
- const: ref_266m
|
||||
- const: ref_24m
|
||||
- const: fdcc
|
||||
|
||||
interconnects:
|
||||
maxItems: 3
|
||||
@@ -82,12 +85,15 @@ examples:
|
||||
clocks = <&clk IMX8MP_CLK_HDMI_APB>,
|
||||
<&clk IMX8MP_CLK_HDMI_ROOT>,
|
||||
<&clk IMX8MP_CLK_HDMI_REF_266M>,
|
||||
<&clk IMX8MP_CLK_HDMI_24M>;
|
||||
clock-names = "apb", "axi", "ref_266m", "ref_24m";
|
||||
<&clk IMX8MP_CLK_HDMI_24M>,
|
||||
<&clk IMX8MP_CLK_HDMI_FDCC_TST>;
|
||||
clock-names = "apb", "axi", "ref_266m", "ref_24m", "fdcc";
|
||||
power-domains = <&pgc_hdmimix>, <&pgc_hdmimix>, <&pgc_hdmimix>,
|
||||
<&pgc_hdmimix>, <&pgc_hdmimix>, <&pgc_hdmimix>,
|
||||
<&pgc_hdmimix>, <&pgc_hdmi_phy>;
|
||||
<&pgc_hdmimix>, <&pgc_hdmi_phy>,
|
||||
<&pgc_hdmimix>, <&pgc_hdmimix>;
|
||||
power-domain-names = "bus", "irqsteer", "lcdif", "pai", "pvi", "trng",
|
||||
"hdmi-tx", "hdmi-tx-phy";
|
||||
"hdmi-tx", "hdmi-tx-phy",
|
||||
"hdcp", "hrv";
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
|
||||
@@ -167,6 +167,115 @@ struct device *dev_pm_domain_attach_by_name(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
|
||||
|
||||
/**
|
||||
* dev_pm_domain_attach_list - Associate a device with its PM domains.
|
||||
* @dev: The device used to lookup the PM domains for.
|
||||
* @data: The data used for attaching to the PM domains.
|
||||
* @list: An out-parameter with an allocated list of attached PM domains.
|
||||
*
|
||||
* This function helps to attach a device to its multiple PM domains. The
|
||||
* caller, which is typically a driver's probe function, may provide a list of
|
||||
* names for the PM domains that we should try to attach the device to, but it
|
||||
* may also provide an empty list, in case the attach should be done for all of
|
||||
* the available PM domains.
|
||||
*
|
||||
* Callers must ensure proper synchronization of this function with power
|
||||
* management callbacks.
|
||||
*
|
||||
* Returns the number of attached PM domains or a negative error code in case of
|
||||
* a failure. Note that, to detach the list of PM domains, the driver shall call
|
||||
* dev_pm_domain_detach_list(), typically during the remove phase.
|
||||
*/
|
||||
int dev_pm_domain_attach_list(struct device *dev,
|
||||
const struct dev_pm_domain_attach_data *data,
|
||||
struct dev_pm_domain_list **list)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct dev_pm_domain_list *pds;
|
||||
struct device *pd_dev = NULL;
|
||||
int ret, i, num_pds = 0;
|
||||
bool by_id = true;
|
||||
u32 pd_flags = data ? data->pd_flags : 0;
|
||||
u32 link_flags = pd_flags & PD_FLAG_NO_DEV_LINK ? 0 :
|
||||
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
|
||||
|
||||
if (dev->pm_domain)
|
||||
return -EEXIST;
|
||||
|
||||
/* For now this is limited to OF based platforms. */
|
||||
if (!np)
|
||||
return 0;
|
||||
|
||||
if (data && data->pd_names) {
|
||||
num_pds = data->num_pd_names;
|
||||
by_id = false;
|
||||
} else {
|
||||
num_pds = of_count_phandle_with_args(np, "power-domains",
|
||||
"#power-domain-cells");
|
||||
}
|
||||
|
||||
if (num_pds <= 0)
|
||||
return 0;
|
||||
|
||||
pds = devm_kzalloc(dev, sizeof(*pds), GFP_KERNEL);
|
||||
if (!pds)
|
||||
return -ENOMEM;
|
||||
|
||||
pds->pd_devs = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_devs),
|
||||
GFP_KERNEL);
|
||||
if (!pds->pd_devs)
|
||||
return -ENOMEM;
|
||||
|
||||
pds->pd_links = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_links),
|
||||
GFP_KERNEL);
|
||||
if (!pds->pd_links)
|
||||
return -ENOMEM;
|
||||
|
||||
if (link_flags && pd_flags & PD_FLAG_DEV_LINK_ON)
|
||||
link_flags |= DL_FLAG_RPM_ACTIVE;
|
||||
|
||||
for (i = 0; i < num_pds; i++) {
|
||||
if (by_id)
|
||||
pd_dev = dev_pm_domain_attach_by_id(dev, i);
|
||||
else
|
||||
pd_dev = dev_pm_domain_attach_by_name(dev,
|
||||
data->pd_names[i]);
|
||||
if (IS_ERR_OR_NULL(pd_dev)) {
|
||||
ret = pd_dev ? PTR_ERR(pd_dev) : -ENODEV;
|
||||
goto err_attach;
|
||||
}
|
||||
|
||||
if (link_flags) {
|
||||
struct device_link *link;
|
||||
|
||||
link = device_link_add(dev, pd_dev, link_flags);
|
||||
if (!link) {
|
||||
ret = -ENODEV;
|
||||
goto err_link;
|
||||
}
|
||||
|
||||
pds->pd_links[i] = link;
|
||||
}
|
||||
|
||||
pds->pd_devs[i] = pd_dev;
|
||||
}
|
||||
|
||||
pds->num_pds = num_pds;
|
||||
*list = pds;
|
||||
return num_pds;
|
||||
|
||||
err_link:
|
||||
dev_pm_domain_detach(pd_dev, true);
|
||||
err_attach:
|
||||
while (--i >= 0) {
|
||||
if (pds->pd_links[i])
|
||||
device_link_del(pds->pd_links[i]);
|
||||
dev_pm_domain_detach(pds->pd_devs[i], true);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_domain_attach_list);
|
||||
|
||||
/**
|
||||
* dev_pm_domain_detach - Detach a device from its PM domain.
|
||||
* @dev: Device to detach.
|
||||
@@ -187,6 +296,31 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
|
||||
|
||||
/**
|
||||
* dev_pm_domain_detach_list - Detach a list of PM domains.
|
||||
* @list: The list of PM domains to detach.
|
||||
*
|
||||
* This function reverse the actions from dev_pm_domain_attach_list().
|
||||
* Typically it should be invoked during the remove phase from drivers.
|
||||
*
|
||||
* Callers must ensure proper synchronization of this function with power
|
||||
* management callbacks.
|
||||
*/
|
||||
void dev_pm_domain_detach_list(struct dev_pm_domain_list *list)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
for (i = 0; i < list->num_pds; i++) {
|
||||
if (list->pd_links[i])
|
||||
device_link_del(list->pd_links[i]);
|
||||
dev_pm_domain_detach(list->pd_devs[i], true);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_domain_detach_list);
|
||||
|
||||
/**
|
||||
* dev_pm_domain_start - Start the device through its PM domain.
|
||||
* @dev: Device to start.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <media/videobuf2-v4l2.h>
|
||||
#include <media/v4l2-mem2mem.h>
|
||||
@@ -114,7 +115,8 @@ static void venus_sys_error_handler(struct work_struct *work)
|
||||
pm_runtime_put_sync(core->dev);
|
||||
|
||||
for (i = 0; i < max_attempts; i++) {
|
||||
if (!core->pmdomains[0] || !pm_runtime_active(core->pmdomains[0]))
|
||||
if (!core->pmdomains ||
|
||||
!pm_runtime_active(core->pmdomains->pd_devs[0]))
|
||||
break;
|
||||
usleep_range(1000, 1500);
|
||||
}
|
||||
@@ -705,7 +707,7 @@ static const struct venus_resources sdm845_res_v2 = {
|
||||
.vcodec0_clks = { "vcodec0_core", "vcodec0_bus" },
|
||||
.vcodec1_clks = { "vcodec1_core", "vcodec1_bus" },
|
||||
.vcodec_clks_num = 2,
|
||||
.vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" },
|
||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0", "vcodec1" },
|
||||
.vcodec_pmdomains_num = 3,
|
||||
.opp_pmdomain = (const char *[]) { "cx", NULL },
|
||||
.vcodec_num = 2,
|
||||
@@ -754,7 +756,7 @@ static const struct venus_resources sc7180_res = {
|
||||
.clks_num = 3,
|
||||
.vcodec0_clks = { "vcodec0_core", "vcodec0_bus" },
|
||||
.vcodec_clks_num = 2,
|
||||
.vcodec_pmdomains = { "venus", "vcodec0" },
|
||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
||||
.vcodec_pmdomains_num = 2,
|
||||
.opp_pmdomain = (const char *[]) { "cx", NULL },
|
||||
.vcodec_num = 1,
|
||||
@@ -811,7 +813,7 @@ static const struct venus_resources sm8250_res = {
|
||||
.resets_num = 2,
|
||||
.vcodec0_clks = { "vcodec0_core" },
|
||||
.vcodec_clks_num = 1,
|
||||
.vcodec_pmdomains = { "venus", "vcodec0" },
|
||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
||||
.vcodec_pmdomains_num = 2,
|
||||
.opp_pmdomain = (const char *[]) { "mx", NULL },
|
||||
.vcodec_num = 1,
|
||||
@@ -870,7 +872,7 @@ static const struct venus_resources sc7280_res = {
|
||||
.clks_num = 3,
|
||||
.vcodec0_clks = {"vcodec_core", "vcodec_bus"},
|
||||
.vcodec_clks_num = 2,
|
||||
.vcodec_pmdomains = { "venus", "vcodec0" },
|
||||
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
|
||||
.vcodec_pmdomains_num = 2,
|
||||
.opp_pmdomain = (const char *[]) { "cx", NULL },
|
||||
.vcodec_num = 1,
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#define VIDC_CLKS_NUM_MAX 4
|
||||
#define VIDC_VCODEC_CLKS_NUM_MAX 2
|
||||
#define VIDC_PMDOMAINS_NUM_MAX 3
|
||||
#define VIDC_RESETS_NUM_MAX 2
|
||||
|
||||
extern int venus_fw_debug;
|
||||
@@ -72,7 +71,7 @@ struct venus_resources {
|
||||
const char * const vcodec0_clks[VIDC_VCODEC_CLKS_NUM_MAX];
|
||||
const char * const vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
|
||||
unsigned int vcodec_clks_num;
|
||||
const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX];
|
||||
const char **vcodec_pmdomains;
|
||||
unsigned int vcodec_pmdomains_num;
|
||||
const char **opp_pmdomain;
|
||||
unsigned int vcodec_num;
|
||||
@@ -134,7 +133,7 @@ struct venus_format {
|
||||
* @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: an array of pmdomains struct device pointers
|
||||
* @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
|
||||
@@ -187,7 +186,7 @@ struct venus_core {
|
||||
struct icc_path *video_path;
|
||||
struct icc_path *cpucfg_path;
|
||||
bool has_opp_table;
|
||||
struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX];
|
||||
struct dev_pm_domain_list *pmdomains;
|
||||
struct device_link *opp_dl_venus;
|
||||
struct device *opp_pmdomain;
|
||||
struct reset_control *resets[VIDC_RESETS_NUM_MAX];
|
||||
|
||||
@@ -455,7 +455,7 @@ static int poweroff_coreid(struct venus_core *core, unsigned int coreid_mask)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pm_runtime_put_sync(core->pmdomains[1]);
|
||||
ret = pm_runtime_put_sync(core->pmdomains->pd_devs[1]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -471,7 +471,7 @@ static int poweroff_coreid(struct venus_core *core, unsigned int coreid_mask)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pm_runtime_put_sync(core->pmdomains[2]);
|
||||
ret = pm_runtime_put_sync(core->pmdomains->pd_devs[2]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -484,7 +484,7 @@ static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask)
|
||||
int ret;
|
||||
|
||||
if (coreid_mask & VIDC_CORE_ID_1) {
|
||||
ret = pm_runtime_get_sync(core->pmdomains[1]);
|
||||
ret = pm_runtime_get_sync(core->pmdomains->pd_devs[1]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -502,7 +502,7 @@ static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask)
|
||||
}
|
||||
|
||||
if (coreid_mask & VIDC_CORE_ID_2) {
|
||||
ret = pm_runtime_get_sync(core->pmdomains[2]);
|
||||
ret = pm_runtime_get_sync(core->pmdomains->pd_devs[2]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -860,19 +860,18 @@ static int vcodec_domains_get(struct venus_core *core)
|
||||
struct device **opp_virt_dev;
|
||||
struct device *dev = core->dev;
|
||||
const struct venus_resources *res = core->res;
|
||||
struct device *pd;
|
||||
unsigned int i;
|
||||
struct dev_pm_domain_attach_data vcodec_data = {
|
||||
.pd_names = res->vcodec_pmdomains,
|
||||
.num_pd_names = res->vcodec_pmdomains_num,
|
||||
.pd_flags = PD_FLAG_NO_DEV_LINK,
|
||||
};
|
||||
|
||||
if (!res->vcodec_pmdomains_num)
|
||||
goto skip_pmdomains;
|
||||
|
||||
for (i = 0; i < res->vcodec_pmdomains_num; i++) {
|
||||
pd = dev_pm_domain_attach_by_name(dev,
|
||||
res->vcodec_pmdomains[i]);
|
||||
if (IS_ERR_OR_NULL(pd))
|
||||
return pd ? PTR_ERR(pd) : -ENODATA;
|
||||
core->pmdomains[i] = pd;
|
||||
}
|
||||
ret = dev_pm_domain_attach_list(dev, &vcodec_data, &core->pmdomains);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
skip_pmdomains:
|
||||
if (!core->res->opp_pmdomain)
|
||||
@@ -896,30 +895,14 @@ skip_pmdomains:
|
||||
return 0;
|
||||
|
||||
opp_attach_err:
|
||||
for (i = 0; i < res->vcodec_pmdomains_num; i++) {
|
||||
if (IS_ERR_OR_NULL(core->pmdomains[i]))
|
||||
continue;
|
||||
dev_pm_domain_detach(core->pmdomains[i], true);
|
||||
}
|
||||
|
||||
dev_pm_domain_detach_list(core->pmdomains);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vcodec_domains_put(struct venus_core *core)
|
||||
{
|
||||
const struct venus_resources *res = core->res;
|
||||
unsigned int i;
|
||||
dev_pm_domain_detach_list(core->pmdomains);
|
||||
|
||||
if (!res->vcodec_pmdomains_num)
|
||||
goto skip_pmdomains;
|
||||
|
||||
for (i = 0; i < res->vcodec_pmdomains_num; i++) {
|
||||
if (IS_ERR_OR_NULL(core->pmdomains[i]))
|
||||
continue;
|
||||
dev_pm_domain_detach(core->pmdomains[i], true);
|
||||
}
|
||||
|
||||
skip_pmdomains:
|
||||
if (!core->has_opp_table)
|
||||
return;
|
||||
|
||||
@@ -1035,7 +1018,8 @@ static void core_put_v4(struct venus_core *core)
|
||||
static int core_power_v4(struct venus_core *core, int on)
|
||||
{
|
||||
struct device *dev = core->dev;
|
||||
struct device *pmctrl = core->pmdomains[0];
|
||||
struct device *pmctrl = core->pmdomains ?
|
||||
core->pmdomains->pd_devs[0] : NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (on == POWER_ON) {
|
||||
|
||||
@@ -310,73 +310,103 @@ static int genpd_xlate_performance_state(struct generic_pm_domain *genpd,
|
||||
pstate);
|
||||
}
|
||||
|
||||
static int _genpd_set_performance_state(struct generic_pm_domain *genpd,
|
||||
unsigned int state, int depth);
|
||||
|
||||
static void _genpd_rollback_parent_state(struct gpd_link *link, int depth)
|
||||
{
|
||||
struct generic_pm_domain *parent = link->parent;
|
||||
int parent_state;
|
||||
|
||||
genpd_lock_nested(parent, depth + 1);
|
||||
|
||||
parent_state = link->prev_performance_state;
|
||||
link->performance_state = parent_state;
|
||||
|
||||
parent_state = _genpd_reeval_performance_state(parent, parent_state);
|
||||
if (_genpd_set_performance_state(parent, parent_state, depth + 1)) {
|
||||
pr_err("%s: Failed to roll back to %d performance state\n",
|
||||
parent->name, parent_state);
|
||||
}
|
||||
|
||||
genpd_unlock(parent);
|
||||
}
|
||||
|
||||
static int _genpd_set_parent_state(struct generic_pm_domain *genpd,
|
||||
struct gpd_link *link,
|
||||
unsigned int state, int depth)
|
||||
{
|
||||
struct generic_pm_domain *parent = link->parent;
|
||||
int parent_state, ret;
|
||||
|
||||
/* Find parent's performance state */
|
||||
ret = genpd_xlate_performance_state(genpd, parent, state);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
||||
parent_state = ret;
|
||||
|
||||
genpd_lock_nested(parent, depth + 1);
|
||||
|
||||
link->prev_performance_state = link->performance_state;
|
||||
link->performance_state = parent_state;
|
||||
|
||||
parent_state = _genpd_reeval_performance_state(parent, parent_state);
|
||||
ret = _genpd_set_performance_state(parent, parent_state, depth + 1);
|
||||
if (ret)
|
||||
link->performance_state = link->prev_performance_state;
|
||||
|
||||
genpd_unlock(parent);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _genpd_set_performance_state(struct generic_pm_domain *genpd,
|
||||
unsigned int state, int depth)
|
||||
{
|
||||
struct generic_pm_domain *parent;
|
||||
struct gpd_link *link;
|
||||
int parent_state, ret;
|
||||
struct gpd_link *link = NULL;
|
||||
int ret;
|
||||
|
||||
if (state == genpd->performance_state)
|
||||
return 0;
|
||||
|
||||
/* Propagate to parents of genpd */
|
||||
list_for_each_entry(link, &genpd->child_links, child_node) {
|
||||
parent = link->parent;
|
||||
|
||||
/* Find parent's performance state */
|
||||
ret = genpd_xlate_performance_state(genpd, parent, state);
|
||||
if (unlikely(ret < 0))
|
||||
goto err;
|
||||
|
||||
parent_state = ret;
|
||||
|
||||
genpd_lock_nested(parent, depth + 1);
|
||||
|
||||
link->prev_performance_state = link->performance_state;
|
||||
link->performance_state = parent_state;
|
||||
parent_state = _genpd_reeval_performance_state(parent,
|
||||
parent_state);
|
||||
ret = _genpd_set_performance_state(parent, parent_state, depth + 1);
|
||||
if (ret)
|
||||
link->performance_state = link->prev_performance_state;
|
||||
|
||||
genpd_unlock(parent);
|
||||
|
||||
if (ret)
|
||||
goto err;
|
||||
/* When scaling up, propagate to parents first in normal order */
|
||||
if (state > genpd->performance_state) {
|
||||
list_for_each_entry(link, &genpd->child_links, child_node) {
|
||||
ret = _genpd_set_parent_state(genpd, link, state, depth);
|
||||
if (ret)
|
||||
goto rollback_parents_up;
|
||||
}
|
||||
}
|
||||
|
||||
if (genpd->set_performance_state) {
|
||||
ret = genpd->set_performance_state(genpd, state);
|
||||
if (ret)
|
||||
goto err;
|
||||
if (ret) {
|
||||
if (link)
|
||||
goto rollback_parents_up;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* When scaling down, propagate to parents last in reverse order */
|
||||
if (state < genpd->performance_state) {
|
||||
list_for_each_entry_reverse(link, &genpd->child_links, child_node) {
|
||||
ret = _genpd_set_parent_state(genpd, link, state, depth);
|
||||
if (ret)
|
||||
goto rollback_parents_down;
|
||||
}
|
||||
}
|
||||
|
||||
genpd->performance_state = state;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
/* Encountered an error, lets rollback */
|
||||
list_for_each_entry_continue_reverse(link, &genpd->child_links,
|
||||
child_node) {
|
||||
parent = link->parent;
|
||||
|
||||
genpd_lock_nested(parent, depth + 1);
|
||||
|
||||
parent_state = link->prev_performance_state;
|
||||
link->performance_state = parent_state;
|
||||
|
||||
parent_state = _genpd_reeval_performance_state(parent,
|
||||
parent_state);
|
||||
if (_genpd_set_performance_state(parent, parent_state, depth + 1)) {
|
||||
pr_err("%s: Failed to roll back to %d performance state\n",
|
||||
parent->name, parent_state);
|
||||
}
|
||||
|
||||
genpd_unlock(parent);
|
||||
}
|
||||
|
||||
rollback_parents_up:
|
||||
list_for_each_entry_continue_reverse(link, &genpd->child_links, child_node)
|
||||
_genpd_rollback_parent_state(link, depth);
|
||||
return ret;
|
||||
rollback_parents_down:
|
||||
list_for_each_entry_continue(link, &genpd->child_links, child_node)
|
||||
_genpd_rollback_parent_state(link, depth);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1100,6 +1130,7 @@ static int __init genpd_power_off_unused(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_info("genpd: Disabling unused power domains\n");
|
||||
mutex_lock(&gpd_list_lock);
|
||||
|
||||
list_for_each_entry(genpd, &gpd_list, gpd_list_node)
|
||||
@@ -2235,7 +2266,7 @@ static DEFINE_MUTEX(of_genpd_mutex);
|
||||
* to be a valid pointer to struct generic_pm_domain.
|
||||
*/
|
||||
static struct generic_pm_domain *genpd_xlate_simple(
|
||||
struct of_phandle_args *genpdspec,
|
||||
const struct of_phandle_args *genpdspec,
|
||||
void *data)
|
||||
{
|
||||
return data;
|
||||
@@ -2252,7 +2283,7 @@ static struct generic_pm_domain *genpd_xlate_simple(
|
||||
* the genpd_onecell_data struct when registering the provider.
|
||||
*/
|
||||
static struct generic_pm_domain *genpd_xlate_onecell(
|
||||
struct of_phandle_args *genpdspec,
|
||||
const struct of_phandle_args *genpdspec,
|
||||
void *data)
|
||||
{
|
||||
struct genpd_onecell_data *genpd_data = data;
|
||||
@@ -2495,7 +2526,7 @@ EXPORT_SYMBOL_GPL(of_genpd_del_provider);
|
||||
* on failure.
|
||||
*/
|
||||
static struct generic_pm_domain *genpd_get_from_provider(
|
||||
struct of_phandle_args *genpdspec)
|
||||
const struct of_phandle_args *genpdspec)
|
||||
{
|
||||
struct generic_pm_domain *genpd = ERR_PTR(-ENOENT);
|
||||
struct of_genpd_provider *provider;
|
||||
@@ -2526,7 +2557,7 @@ static struct generic_pm_domain *genpd_get_from_provider(
|
||||
* Looks-up an I/O PM domain based upon phandle args provided and adds
|
||||
* the device to the PM domain. Returns a negative error code on failure.
|
||||
*/
|
||||
int of_genpd_add_device(struct of_phandle_args *genpdspec, struct device *dev)
|
||||
int of_genpd_add_device(const struct of_phandle_args *genpdspec, struct device *dev)
|
||||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
int ret;
|
||||
@@ -2560,8 +2591,8 @@ EXPORT_SYMBOL_GPL(of_genpd_add_device);
|
||||
* provided and adds the subdomain to the parent PM domain. Returns a
|
||||
* negative error code on failure.
|
||||
*/
|
||||
int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
|
||||
struct of_phandle_args *subdomain_spec)
|
||||
int of_genpd_add_subdomain(const struct of_phandle_args *parent_spec,
|
||||
const struct of_phandle_args *subdomain_spec)
|
||||
{
|
||||
struct generic_pm_domain *parent, *subdomain;
|
||||
int ret;
|
||||
@@ -2598,8 +2629,8 @@ EXPORT_SYMBOL_GPL(of_genpd_add_subdomain);
|
||||
* provided and removes the subdomain from the parent PM domain. Returns a
|
||||
* negative error code on failure.
|
||||
*/
|
||||
int of_genpd_remove_subdomain(struct of_phandle_args *parent_spec,
|
||||
struct of_phandle_args *subdomain_spec)
|
||||
int of_genpd_remove_subdomain(const struct of_phandle_args *parent_spec,
|
||||
const struct of_phandle_args *subdomain_spec)
|
||||
{
|
||||
struct generic_pm_domain *parent, *subdomain;
|
||||
int ret;
|
||||
|
||||
@@ -258,11 +258,14 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
|
||||
|
||||
domain->power_dev =
|
||||
dev_pm_domain_attach_by_name(dev, data->gpc_name);
|
||||
if (IS_ERR(domain->power_dev)) {
|
||||
dev_err_probe(dev, PTR_ERR(domain->power_dev),
|
||||
if (IS_ERR_OR_NULL(domain->power_dev)) {
|
||||
if (!domain->power_dev)
|
||||
ret = -ENODEV;
|
||||
else
|
||||
ret = PTR_ERR(domain->power_dev);
|
||||
dev_err_probe(dev, ret,
|
||||
"failed to attach power domain \"%s\"\n",
|
||||
data->gpc_name);
|
||||
ret = PTR_ERR(domain->power_dev);
|
||||
goto cleanup_pds;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ struct imx8mp_blk_ctrl_domain_data {
|
||||
const char *gpc_name;
|
||||
};
|
||||
|
||||
#define DOMAIN_MAX_CLKS 2
|
||||
#define DOMAIN_MAX_CLKS 3
|
||||
#define DOMAIN_MAX_PATHS 3
|
||||
|
||||
struct imx8mp_blk_ctrl_domain {
|
||||
@@ -457,8 +457,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
|
||||
},
|
||||
[IMX8MP_HDMIBLK_PD_LCDIF] = {
|
||||
.name = "hdmiblk-lcdif",
|
||||
.clk_names = (const char *[]){ "axi", "apb" },
|
||||
.num_clks = 2,
|
||||
.clk_names = (const char *[]){ "axi", "apb", "fdcc" },
|
||||
.num_clks = 3,
|
||||
.gpc_name = "lcdif",
|
||||
.path_names = (const char *[]){"lcdif-hdmi"},
|
||||
.num_paths = 1,
|
||||
@@ -483,8 +483,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
|
||||
},
|
||||
[IMX8MP_HDMIBLK_PD_HDMI_TX] = {
|
||||
.name = "hdmiblk-hdmi-tx",
|
||||
.clk_names = (const char *[]){ "apb", "ref_266m" },
|
||||
.num_clks = 2,
|
||||
.clk_names = (const char *[]){ "apb", "ref_266m", "fdcc" },
|
||||
.num_clks = 3,
|
||||
.gpc_name = "hdmi-tx",
|
||||
},
|
||||
[IMX8MP_HDMIBLK_PD_HDMI_TX_PHY] = {
|
||||
@@ -687,11 +687,14 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
|
||||
|
||||
domain->power_dev =
|
||||
dev_pm_domain_attach_by_name(dev, data->gpc_name);
|
||||
if (IS_ERR(domain->power_dev)) {
|
||||
dev_err_probe(dev, PTR_ERR(domain->power_dev),
|
||||
if (IS_ERR_OR_NULL(domain->power_dev)) {
|
||||
if (!domain->power_dev)
|
||||
ret = -ENODEV;
|
||||
else
|
||||
ret = PTR_ERR(domain->power_dev);
|
||||
dev_err_probe(dev, ret,
|
||||
"failed to attach power domain %s\n",
|
||||
data->gpc_name);
|
||||
ret = PTR_ERR(domain->power_dev);
|
||||
goto cleanup_pds;
|
||||
}
|
||||
|
||||
|
||||
@@ -393,7 +393,7 @@ static int imx_sc_pd_power_off(struct generic_pm_domain *domain)
|
||||
return imx_sc_pd_power(domain, false);
|
||||
}
|
||||
|
||||
static struct generic_pm_domain *imx_scu_pd_xlate(struct of_phandle_args *spec,
|
||||
static struct generic_pm_domain *imx_scu_pd_xlate(const struct of_phandle_args *spec,
|
||||
void *data)
|
||||
{
|
||||
struct generic_pm_domain *domain = ERR_PTR(-ENOENT);
|
||||
|
||||
@@ -425,7 +425,6 @@ static struct scp *init_scp(struct platform_device *pdev,
|
||||
bool bus_prot_reg_update)
|
||||
{
|
||||
struct genpd_onecell_data *pd_data;
|
||||
struct resource *res;
|
||||
int i, j;
|
||||
struct scp *scp;
|
||||
struct clk *clk[CLK_MAX];
|
||||
@@ -441,8 +440,7 @@ static struct scp *init_scp(struct platform_device *pdev,
|
||||
|
||||
scp->dev = &pdev->dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
scp->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
scp->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(scp->base))
|
||||
return ERR_CAST(scp->base);
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
|
||||
|
||||
static struct qcom_smd_rpm *rpmpd_smd_rpm;
|
||||
|
||||
/* Resource types:
|
||||
* RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */
|
||||
#define RPMPD_SMPA 0x61706d73
|
||||
@@ -54,7 +56,6 @@ struct rpmpd {
|
||||
bool enabled;
|
||||
const int res_type;
|
||||
const int res_id;
|
||||
struct qcom_smd_rpm *rpm;
|
||||
unsigned int max_state;
|
||||
__le32 key;
|
||||
bool state_synced;
|
||||
@@ -226,7 +227,46 @@ static struct rpmpd cx_s3a_vfl = {
|
||||
.key = KEY_FLOOR_LEVEL,
|
||||
};
|
||||
|
||||
static struct rpmpd cx_s2b_corner_ao;
|
||||
static struct rpmpd cx_s2b_corner = {
|
||||
.pd = { .name = "cx", },
|
||||
.peer = &cx_s2b_corner_ao,
|
||||
.res_type = RPMPD_SMPB,
|
||||
.res_id = 2,
|
||||
.key = KEY_CORNER,
|
||||
};
|
||||
|
||||
static struct rpmpd cx_s2b_corner_ao = {
|
||||
.pd = { .name = "cx_ao", },
|
||||
.peer = &cx_s2b_corner,
|
||||
.active_only = true,
|
||||
.res_type = RPMPD_SMPB,
|
||||
.res_id = 2,
|
||||
.key = KEY_CORNER,
|
||||
};
|
||||
|
||||
static struct rpmpd cx_s2b_vfc = {
|
||||
.pd = { .name = "cx_vfc", },
|
||||
.res_type = RPMPD_SMPB,
|
||||
.res_id = 2,
|
||||
.key = KEY_FLOOR_CORNER,
|
||||
};
|
||||
|
||||
/* G(F)X */
|
||||
static struct rpmpd gfx_s7a_corner = {
|
||||
.pd = { .name = "gfx", },
|
||||
.res_type = RPMPD_SMPA,
|
||||
.res_id = 7,
|
||||
.key = KEY_CORNER,
|
||||
};
|
||||
|
||||
static struct rpmpd gfx_s7a_vfc = {
|
||||
.pd = { .name = "gfx_vfc", },
|
||||
.res_type = RPMPD_SMPA,
|
||||
.res_id = 7,
|
||||
.key = KEY_FLOOR_CORNER,
|
||||
};
|
||||
|
||||
static struct rpmpd gfx_s2b_corner = {
|
||||
.pd = { .name = "gfx", },
|
||||
.res_type = RPMPD_SMPB,
|
||||
@@ -241,6 +281,20 @@ static struct rpmpd gfx_s2b_vfc = {
|
||||
.key = KEY_FLOOR_CORNER,
|
||||
};
|
||||
|
||||
static struct rpmpd gfx_s4b_corner = {
|
||||
.pd = { .name = "gfx", },
|
||||
.res_type = RPMPD_SMPB,
|
||||
.res_id = 4,
|
||||
.key = KEY_CORNER,
|
||||
};
|
||||
|
||||
static struct rpmpd gfx_s4b_vfc = {
|
||||
.pd = { .name = "gfx_vfc", },
|
||||
.res_type = RPMPD_SMPB,
|
||||
.res_id = 4,
|
||||
.key = KEY_FLOOR_CORNER,
|
||||
};
|
||||
|
||||
static struct rpmpd mx_rwmx0_lvl;
|
||||
static struct rpmpd gx_rwgx0_lvl_ao;
|
||||
static struct rpmpd gx_rwgx0_lvl = {
|
||||
@@ -663,6 +717,34 @@ static const struct rpmpd_desc msm8953_desc = {
|
||||
.max_state = RPM_SMD_LEVEL_TURBO,
|
||||
};
|
||||
|
||||
static struct rpmpd *msm8974_rpmpds[] = {
|
||||
[MSM8974_VDDCX] = &cx_s2b_corner,
|
||||
[MSM8974_VDDCX_AO] = &cx_s2b_corner_ao,
|
||||
[MSM8974_VDDCX_VFC] = &cx_s2b_vfc,
|
||||
[MSM8974_VDDGFX] = &gfx_s4b_corner,
|
||||
[MSM8974_VDDGFX_VFC] = &gfx_s4b_vfc,
|
||||
};
|
||||
|
||||
static const struct rpmpd_desc msm8974_desc = {
|
||||
.rpmpds = msm8974_rpmpds,
|
||||
.num_pds = ARRAY_SIZE(msm8974_rpmpds),
|
||||
.max_state = MAX_CORNER_RPMPD_STATE,
|
||||
};
|
||||
|
||||
static struct rpmpd *msm8974pro_pma8084_rpmpds[] = {
|
||||
[MSM8974_VDDCX] = &cx_s2a_corner,
|
||||
[MSM8974_VDDCX_AO] = &cx_s2a_corner_ao,
|
||||
[MSM8974_VDDCX_VFC] = &cx_s2a_vfc,
|
||||
[MSM8974_VDDGFX] = &gfx_s7a_corner,
|
||||
[MSM8974_VDDGFX_VFC] = &gfx_s7a_vfc,
|
||||
};
|
||||
|
||||
static const struct rpmpd_desc msm8974pro_pma8084_desc = {
|
||||
.rpmpds = msm8974pro_pma8084_rpmpds,
|
||||
.num_pds = ARRAY_SIZE(msm8974pro_pma8084_rpmpds),
|
||||
.max_state = MAX_CORNER_RPMPD_STATE,
|
||||
};
|
||||
|
||||
static struct rpmpd *msm8976_rpmpds[] = {
|
||||
[MSM8976_VDDCX] = &cx_s2a_lvl,
|
||||
[MSM8976_VDDCX_AO] = &cx_s2a_lvl_ao,
|
||||
@@ -856,6 +938,8 @@ static const struct of_device_id rpmpd_match_table[] = {
|
||||
{ .compatible = "qcom,msm8917-rpmpd", .data = &msm8917_desc },
|
||||
{ .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
|
||||
{ .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc },
|
||||
{ .compatible = "qcom,msm8974-rpmpd", .data = &msm8974_desc },
|
||||
{ .compatible = "qcom,msm8974pro-pma8084-rpmpd", .data = &msm8974pro_pma8084_desc },
|
||||
{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
|
||||
{ .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc },
|
||||
{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
|
||||
@@ -879,7 +963,7 @@ static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
|
||||
.value = cpu_to_le32(enable),
|
||||
};
|
||||
|
||||
return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
|
||||
return qcom_rpm_smd_write(rpmpd_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE,
|
||||
pd->res_type, pd->res_id, &req, sizeof(req));
|
||||
}
|
||||
|
||||
@@ -891,7 +975,7 @@ static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
|
||||
.value = cpu_to_le32(corner),
|
||||
};
|
||||
|
||||
return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
|
||||
return qcom_rpm_smd_write(rpmpd_smd_rpm, state, pd->res_type, pd->res_id,
|
||||
&req, sizeof(req));
|
||||
};
|
||||
|
||||
@@ -1004,12 +1088,11 @@ static int rpmpd_probe(struct platform_device *pdev)
|
||||
int i;
|
||||
size_t num;
|
||||
struct genpd_onecell_data *data;
|
||||
struct qcom_smd_rpm *rpm;
|
||||
struct rpmpd **rpmpds;
|
||||
const struct rpmpd_desc *desc;
|
||||
|
||||
rpm = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!rpm) {
|
||||
rpmpd_smd_rpm = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!rpmpd_smd_rpm) {
|
||||
dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -1039,7 +1122,6 @@ static int rpmpd_probe(struct platform_device *pdev)
|
||||
continue;
|
||||
}
|
||||
|
||||
rpmpds[i]->rpm = rpm;
|
||||
rpmpds[i]->max_state = desc->max_state;
|
||||
rpmpds[i]->pd.power_off = rpmpd_power_off;
|
||||
rpmpds[i]->pd.power_on = rpmpd_power_on;
|
||||
|
||||
@@ -71,6 +71,10 @@ config SYSC_R8A779G0
|
||||
bool "System Controller support for R-Car V4H" if COMPILE_TEST
|
||||
select SYSC_RCAR_GEN4
|
||||
|
||||
config SYSC_R8A779H0
|
||||
bool "System Controller support for R-Car V4M" if COMPILE_TEST
|
||||
select SYSC_RCAR_GEN4
|
||||
|
||||
config SYSC_RMOBILE
|
||||
bool "System Controller support for R-Mobile" if COMPILE_TEST
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A779A0) += r8a779a0-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A779F0) += r8a779f0-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A779G0) += r8a779g0-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A779H0) += r8a779h0-sysc.o
|
||||
# Family
|
||||
obj-$(CONFIG_SYSC_RCAR) += rcar-sysc.o
|
||||
obj-$(CONFIG_SYSC_RCAR_GEN4) += rcar-gen4-sysc.o
|
||||
|
||||
@@ -5,19 +5,7 @@
|
||||
* Copyright (C) 2020 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk/renesas.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <dt-bindings/power/r8a779a0-sysc.h>
|
||||
|
||||
|
||||
@@ -5,19 +5,7 @@
|
||||
* Copyright (C) 2021 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk/renesas.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <dt-bindings/power/r8a779f0-sysc.h>
|
||||
|
||||
|
||||
@@ -5,19 +5,7 @@
|
||||
* Copyright (C) 2022 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk/renesas.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <dt-bindings/power/r8a779g0-sysc.h>
|
||||
|
||||
|
||||
54
drivers/pmdomain/renesas/r8a779h0-sysc.c
Normal file
54
drivers/pmdomain/renesas/r8a779h0-sysc.c
Normal file
@@ -0,0 +1,54 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Renesas R-Car V4M System Controller
|
||||
*
|
||||
* Copyright (C) 2023 Renesas Electronics Corp
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <dt-bindings/power/renesas,r8a779h0-sysc.h>
|
||||
|
||||
#include "rcar-gen4-sysc.h"
|
||||
|
||||
static struct rcar_gen4_sysc_area r8a779h0_areas[] __initdata = {
|
||||
{ "always-on", R8A779H0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
|
||||
{ "c4", R8A779H0_PD_C4, R8A779H0_PD_ALWAYS_ON },
|
||||
{ "a2e0d0", R8A779H0_PD_A2E0D0, R8A779H0_PD_C4, PD_SCU },
|
||||
{ "a1e0d0c0", R8A779H0_PD_A1E0D0C0, R8A779H0_PD_A2E0D0, PD_CPU_NOCR },
|
||||
{ "a1e0d0c1", R8A779H0_PD_A1E0D0C1, R8A779H0_PD_A2E0D0, PD_CPU_NOCR },
|
||||
{ "a1e0d0c2", R8A779H0_PD_A1E0D0C2, R8A779H0_PD_A2E0D0, PD_CPU_NOCR },
|
||||
{ "a1e0d0c3", R8A779H0_PD_A1E0D0C3, R8A779H0_PD_A2E0D0, PD_CPU_NOCR },
|
||||
{ "a3cr0", R8A779H0_PD_A3CR0, R8A779H0_PD_ALWAYS_ON, PD_CPU_NOCR },
|
||||
{ "a3cr1", R8A779H0_PD_A3CR1, R8A779H0_PD_ALWAYS_ON, PD_CPU_NOCR },
|
||||
{ "a3cr2", R8A779H0_PD_A3CR2, R8A779H0_PD_ALWAYS_ON, PD_CPU_NOCR },
|
||||
{ "a33dga", R8A779H0_PD_A33DGA, R8A779H0_PD_C4 },
|
||||
{ "a23dgb", R8A779H0_PD_A23DGB, R8A779H0_PD_A33DGA },
|
||||
{ "a3vip0", R8A779H0_PD_A3VIP0, R8A779H0_PD_C4 },
|
||||
{ "a3vip2", R8A779H0_PD_A3VIP2, R8A779H0_PD_C4 },
|
||||
{ "a3dul", R8A779H0_PD_A3DUL, R8A779H0_PD_C4 },
|
||||
{ "a3isp0", R8A779H0_PD_A3ISP0, R8A779H0_PD_C4 },
|
||||
{ "a2cn0", R8A779H0_PD_A2CN0, R8A779H0_PD_C4 },
|
||||
{ "a1cn0", R8A779H0_PD_A1CN0, R8A779H0_PD_A2CN0 },
|
||||
{ "a1dsp0", R8A779H0_PD_A1DSP0, R8A779H0_PD_A2CN0 },
|
||||
{ "a1dsp1", R8A779H0_PD_A1DSP1, R8A779H0_PD_A2CN0 },
|
||||
{ "a2imp01", R8A779H0_PD_A2IMP01, R8A779H0_PD_C4 },
|
||||
{ "a2psc", R8A779H0_PD_A2PSC, R8A779H0_PD_C4 },
|
||||
{ "a2dma", R8A779H0_PD_A2DMA, R8A779H0_PD_C4 },
|
||||
{ "a2cv0", R8A779H0_PD_A2CV0, R8A779H0_PD_C4 },
|
||||
{ "a2cv1", R8A779H0_PD_A2CV1, R8A779H0_PD_C4 },
|
||||
{ "a2cv2", R8A779H0_PD_A2CV2, R8A779H0_PD_C4 },
|
||||
{ "a2cv3", R8A779H0_PD_A2CV3, R8A779H0_PD_C4 },
|
||||
{ "a3imr0", R8A779H0_PD_A3IMR0, R8A779H0_PD_C4 },
|
||||
{ "a3imr1", R8A779H0_PD_A3IMR1, R8A779H0_PD_C4 },
|
||||
{ "a3imr2", R8A779H0_PD_A3IMR2, R8A779H0_PD_C4 },
|
||||
{ "a3imr3", R8A779H0_PD_A3IMR3, R8A779H0_PD_C4 },
|
||||
{ "a3vc", R8A779H0_PD_A3VC, R8A779H0_PD_C4 },
|
||||
{ "a3pci", R8A779H0_PD_A3PCI, R8A779H0_PD_C4 },
|
||||
{ "a2pciphy", R8A779H0_PD_A2PCIPHY, R8A779H0_PD_A3PCI },
|
||||
};
|
||||
|
||||
const struct rcar_gen4_sysc_info r8a779h0_sysc_info __initconst = {
|
||||
.areas = r8a779h0_areas,
|
||||
.num_areas = ARRAY_SIZE(r8a779h0_areas),
|
||||
};
|
||||
@@ -50,13 +50,13 @@
|
||||
#define SYSCSR_BUSY GENMASK(1, 0) /* All bit sets is not busy */
|
||||
|
||||
#define SYSCSR_TIMEOUT 10000
|
||||
#define SYSCSR_DELAY_US 10
|
||||
#define SYSCSR_DELAY_US 1
|
||||
|
||||
#define PDRESR_RETRIES 1000
|
||||
#define PDRESR_DELAY_US 10
|
||||
#define PDRESR_RETRIES 10000
|
||||
#define PDRESR_DELAY_US 1
|
||||
|
||||
#define SYSCISR_TIMEOUT 10000
|
||||
#define SYSCISR_DELAY_US 10
|
||||
#define SYSCISCR_TIMEOUT 10000
|
||||
#define SYSCISCR_DELAY_US 1
|
||||
|
||||
#define RCAR_GEN4_PD_ALWAYS_ON 64
|
||||
#define NUM_DOMAINS_EACH_REG BITS_PER_TYPE(u32)
|
||||
@@ -97,7 +97,7 @@ static int clear_irq_flags(unsigned int reg_idx, unsigned int isr_mask)
|
||||
|
||||
ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx),
|
||||
val, !(val & isr_mask),
|
||||
SYSCISR_DELAY_US, SYSCISR_TIMEOUT);
|
||||
SYSCISCR_DELAY_US, SYSCISCR_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
pr_err("\n %s : Can not clear IRQ flags in SYSCISCR", __func__);
|
||||
return -EIO;
|
||||
@@ -157,7 +157,7 @@ static int rcar_gen4_sysc_power(u8 pdr, bool on)
|
||||
/* Wait until the power shutoff or resume request has completed * */
|
||||
ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx),
|
||||
val, (val & isr_mask),
|
||||
SYSCISR_DELAY_US, SYSCISR_TIMEOUT);
|
||||
SYSCISCR_DELAY_US, SYSCISCR_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
@@ -284,6 +284,9 @@ static const struct of_device_id rcar_gen4_sysc_matches[] __initconst = {
|
||||
#endif
|
||||
#ifdef CONFIG_SYSC_R8A779G0
|
||||
{ .compatible = "renesas,r8a779g0-sysc", .data = &r8a779g0_sysc_info },
|
||||
#endif
|
||||
#ifdef CONFIG_SYSC_R8A779H0
|
||||
{ .compatible = "renesas,r8a779h0-sysc", .data = &r8a779h0_sysc_info },
|
||||
#endif
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
@@ -40,5 +40,6 @@ struct rcar_gen4_sysc_info {
|
||||
extern const struct rcar_gen4_sysc_info r8a779a0_sysc_info;
|
||||
extern const struct rcar_gen4_sysc_info r8a779f0_sysc_info;
|
||||
extern const struct rcar_gen4_sysc_info r8a779g0_sysc_info;
|
||||
extern const struct rcar_gen4_sysc_info r8a779h0_sysc_info;
|
||||
|
||||
#endif /* __SOC_RENESAS_RCAR_GEN4_SYSC_H__ */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user