Skip to content

Commit

Permalink
Merge tag 'pmdomain-v6.9' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/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
  ...
  • Loading branch information
Linus Torvalds committed Mar 13, 2024
2 parents 15223fd + ccabbb6 commit a070a08
Show file tree
Hide file tree
Showing 30 changed files with 594 additions and 409 deletions.
2 changes: 2 additions & 0 deletions Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ properties:
const: 1

power-domains:
minItems: 8
maxItems: 8
minItems: 10
maxItems: 10

power-domain-names:
items:
Expand All @@ -40,17 +40,20 @@ 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:
- const: apb
- const: axi
- const: ref_266m
- const: ref_24m
- const: fdcc

interconnects:
maxItems: 3
Expand Down Expand Up @@ -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>;
};
134 changes: 134 additions & 0 deletions drivers/base/power/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand Down
12 changes: 7 additions & 5 deletions drivers/media/platform/qcom/venus/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
7 changes: 3 additions & 4 deletions drivers/media/platform/qcom/venus/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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];
Expand Down
Loading

0 comments on commit a070a08

Please sign in to comment.