Skip to content

Commit 68732c0

Browse files
committed
Merge tag 'pmdomain-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm
Pull pmdomain updates from Ulf Hansson: "pmdomain core: - Add support for naming idlestates through DT pmdomain providers: - arm: Explicitly request the current state at init for the SCMI PM domain - mediatek: Add Airoha CPU PM Domain support for CPU frequency scaling - ti: Add per-device latency constraint management to the ti_sci PM domain cpuidle-psci: - Enable system-wakeup through GENPD_FLAG_ACTIVE_WAKEUP" * tag 'pmdomain-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm: pmdomain: airoha: Fix compilation error with Clang-20 and Thumb2 mode pmdomain: arm: scmi_pm_domain: Send an explicit request to set the current state pmdomain: airoha: Add Airoha CPU PM Domain support pmdomain: ti_sci: handle wake IRQs for IO daisy chain wakeups pmdomain: ti_sci: add wakeup constraint management pmdomain: ti_sci: add per-device latency constraint management pmdomain: imx-gpcv2: Suppress bind attrs pmdomain: imx8m[p]-blk-ctrl: Suppress bind attrs pmdomain: core: Support naming idle states dt-bindings: power: domain-idle-state: Allow idle-state-name cpuidle: psci: Activate GENPD_FLAG_ACTIVE_WAKEUP with OSI
2 parents b746043 + 885f566 commit 68732c0

File tree

12 files changed

+276
-3
lines changed

12 files changed

+276
-3
lines changed

Documentation/devicetree/bindings/power/domain-idle-state.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ patternProperties:
5454
(i.e. idle states node with entry-method property is set to "psci")
5555
must specify this property.
5656
57+
idle-state-name:
58+
$ref: /schemas/types.yaml#/definitions/string
59+
description:
60+
A string used as a descriptive name for the idle state.
61+
5762
required:
5863
- compatible
5964
- entry-latency-us

drivers/cpuidle/cpuidle-psci-domain.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ static int psci_pd_init(struct device_node *np, bool use_osi)
7272
*/
7373
if (use_osi) {
7474
pd->power_off = psci_pd_power_off;
75+
pd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
7576
if (IS_ENABLED(CONFIG_PREEMPT_RT))
7677
pd->flags |= GENPD_FLAG_RPM_ALWAYS_ON;
7778
} else {

drivers/pmdomain/arm/scmi_pm_domain.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
9696
continue;
9797
}
9898

99+
/*
100+
* Register the explicit power on request to the firmware so
101+
* that it is tracked as used by OSPM agent and not
102+
* accidentally turned off with OSPM's knowledge
103+
*/
104+
if (state == SCMI_POWER_STATE_GENERIC_ON)
105+
power_ops->state_set(ph, i, state);
106+
99107
scmi_pd->domain = i;
100108
scmi_pd->ph = ph;
101109
scmi_pd->name = power_ops->name_get(ph, i);

drivers/pmdomain/core.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3180,6 +3180,8 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state,
31803180
if (!err)
31813181
genpd_state->residency_ns = 1000LL * residency;
31823182

3183+
of_property_read_string(state_node, "idle-state-name", &genpd_state->name);
3184+
31833185
genpd_state->power_on_latency_ns = 1000LL * exit_latency;
31843186
genpd_state->power_off_latency_ns = 1000LL * entry_latency;
31853187
genpd_state->fwnode = &state_node->fwnode;
@@ -3458,7 +3460,10 @@ static int idle_states_show(struct seq_file *s, void *data)
34583460
seq_puts(s, "State Time Spent(ms) Usage Rejected\n");
34593461

34603462
for (i = 0; i < genpd->state_count; i++) {
3461-
idle_time += genpd->states[i].idle_time;
3463+
struct genpd_power_state *state = &genpd->states[i];
3464+
char state_name[15];
3465+
3466+
idle_time += state->idle_time;
34623467

34633468
if (genpd->status == GENPD_STATE_OFF && genpd->state_idx == i) {
34643469
now = ktime_get_mono_fast_ns();
@@ -3468,9 +3473,13 @@ static int idle_states_show(struct seq_file *s, void *data)
34683473
}
34693474
}
34703475

3476+
if (!state->name)
3477+
snprintf(state_name, ARRAY_SIZE(state_name), "S%-13d", i);
3478+
34713479
do_div(idle_time, NSEC_PER_MSEC);
3472-
seq_printf(s, "S%-13i %-14llu %-14llu %llu\n", i, idle_time,
3473-
genpd->states[i].usage, genpd->states[i].rejected);
3480+
seq_printf(s, "%-14s %-14llu %-14llu %llu\n",
3481+
state->name ?: state_name, idle_time,
3482+
state->usage, state->rejected);
34743483
}
34753484

34763485
genpd_unlock(genpd);

drivers/pmdomain/imx/gpcv2.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,7 @@ static struct platform_driver imx_pgc_domain_driver = {
14371437
.driver = {
14381438
.name = "imx-pgc",
14391439
.pm = &imx_pgc_domain_pm_ops,
1440+
.suppress_bind_attrs = true,
14401441
},
14411442
.probe = imx_pgc_domain_probe,
14421443
.remove = imx_pgc_domain_remove,
@@ -1549,6 +1550,7 @@ static struct platform_driver imx_gpc_driver = {
15491550
.driver = {
15501551
.name = "imx-gpcv2",
15511552
.of_match_table = imx_gpcv2_dt_ids,
1553+
.suppress_bind_attrs = true,
15521554
},
15531555
.probe = imx_gpcv2_probe,
15541556
};

drivers/pmdomain/imx/imx8m-blk-ctrl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,7 @@ static struct platform_driver imx8m_blk_ctrl_driver = {
894894
.name = "imx8m-blk-ctrl",
895895
.pm = &imx8m_blk_ctrl_pm_ops,
896896
.of_match_table = imx8m_blk_ctrl_of_match,
897+
.suppress_bind_attrs = true,
897898
},
898899
};
899900
module_platform_driver(imx8m_blk_ctrl_driver);

drivers/pmdomain/imx/imx8mp-blk-ctrl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,7 @@ static struct platform_driver imx8mp_blk_ctrl_driver = {
862862
.name = "imx8mp-blk-ctrl",
863863
.pm = &imx8mp_blk_ctrl_pm_ops,
864864
.of_match_table = imx8mp_blk_ctrl_of_match,
865+
.suppress_bind_attrs = true,
865866
},
866867
};
867868
module_platform_driver(imx8mp_blk_ctrl_driver);

drivers/pmdomain/mediatek/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,16 @@ config MTK_SCPSYS_PM_DOMAINS
2626
Control Processor System (SCPSYS) has several power management related
2727
tasks in the system.
2828

29+
config AIROHA_CPU_PM_DOMAIN
30+
tristate "Airoha CPU power domain"
31+
default ARCH_AIROHA
32+
depends on HAVE_ARM_SMCCC
33+
depends on PM
34+
select PM_GENERIC_DOMAINS
35+
help
36+
Say y here to enable CPU power domain support for Airoha SoC.
37+
38+
CPU frequency and power is controlled by ATF with SMC command to
39+
set performance states.
40+
2941
endmenu

drivers/pmdomain/mediatek/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
33
obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS) += mtk-pm-domains.o
4+
obj-$(CONFIG_AIROHA_CPU_PM_DOMAIN) += airoha-cpu-pmdomain.o
5+
6+
ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
7+
# The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame
8+
# pointer in Thumb2 mode, which is forcibly enabled by Clang when profiling
9+
# hooks are inserted via the -pg switch.
10+
CFLAGS_REMOVE_airoha-cpu-pmdomain.o += $(CC_FLAGS_FTRACE)
11+
endif
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/arm-smccc.h>
4+
#include <linux/bitfield.h>
5+
#include <linux/clk-provider.h>
6+
#include <linux/module.h>
7+
#include <linux/platform_device.h>
8+
#include <linux/pm_domain.h>
9+
#include <linux/slab.h>
10+
11+
#define AIROHA_SIP_AVS_HANDLE 0x82000301
12+
#define AIROHA_AVS_OP_BASE 0xddddddd0
13+
#define AIROHA_AVS_OP_MASK GENMASK(1, 0)
14+
#define AIROHA_AVS_OP_FREQ_DYN_ADJ (AIROHA_AVS_OP_BASE | \
15+
FIELD_PREP(AIROHA_AVS_OP_MASK, 0x1))
16+
#define AIROHA_AVS_OP_GET_FREQ (AIROHA_AVS_OP_BASE | \
17+
FIELD_PREP(AIROHA_AVS_OP_MASK, 0x2))
18+
19+
struct airoha_cpu_pmdomain_priv {
20+
struct clk_hw hw;
21+
struct generic_pm_domain pd;
22+
};
23+
24+
static long airoha_cpu_pmdomain_clk_round(struct clk_hw *hw, unsigned long rate,
25+
unsigned long *parent_rate)
26+
{
27+
return rate;
28+
}
29+
30+
static unsigned long airoha_cpu_pmdomain_clk_get(struct clk_hw *hw,
31+
unsigned long parent_rate)
32+
{
33+
struct arm_smccc_res res;
34+
35+
arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_GET_FREQ,
36+
0, 0, 0, 0, 0, 0, &res);
37+
38+
/* SMCCC returns freq in MHz */
39+
return (int)(res.a0 * 1000 * 1000);
40+
}
41+
42+
/* Airoha CPU clk SMCC is always enabled */
43+
static int airoha_cpu_pmdomain_clk_is_enabled(struct clk_hw *hw)
44+
{
45+
return true;
46+
}
47+
48+
static const struct clk_ops airoha_cpu_pmdomain_clk_ops = {
49+
.recalc_rate = airoha_cpu_pmdomain_clk_get,
50+
.is_enabled = airoha_cpu_pmdomain_clk_is_enabled,
51+
.round_rate = airoha_cpu_pmdomain_clk_round,
52+
};
53+
54+
static int airoha_cpu_pmdomain_set_performance_state(struct generic_pm_domain *domain,
55+
unsigned int state)
56+
{
57+
struct arm_smccc_res res;
58+
59+
arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_FREQ_DYN_ADJ,
60+
0, state, 0, 0, 0, 0, &res);
61+
62+
/* SMC signal correct apply by unsetting BIT 0 */
63+
return res.a0 & BIT(0) ? -EINVAL : 0;
64+
}
65+
66+
static int airoha_cpu_pmdomain_probe(struct platform_device *pdev)
67+
{
68+
struct airoha_cpu_pmdomain_priv *priv;
69+
struct device *dev = &pdev->dev;
70+
const struct clk_init_data init = {
71+
.name = "cpu",
72+
.ops = &airoha_cpu_pmdomain_clk_ops,
73+
/* Clock with no set_rate, can't cache */
74+
.flags = CLK_GET_RATE_NOCACHE,
75+
};
76+
struct generic_pm_domain *pd;
77+
int ret;
78+
79+
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
80+
if (!priv)
81+
return -ENOMEM;
82+
83+
/* Init and register a get-only clk for Cpufreq */
84+
priv->hw.init = &init;
85+
ret = devm_clk_hw_register(dev, &priv->hw);
86+
if (ret)
87+
return ret;
88+
89+
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
90+
&priv->hw);
91+
if (ret)
92+
return ret;
93+
94+
/* Init and register a PD for CPU */
95+
pd = &priv->pd;
96+
pd->name = "cpu_pd";
97+
pd->flags = GENPD_FLAG_ALWAYS_ON;
98+
pd->set_performance_state = airoha_cpu_pmdomain_set_performance_state;
99+
100+
ret = pm_genpd_init(pd, NULL, false);
101+
if (ret)
102+
return ret;
103+
104+
ret = of_genpd_add_provider_simple(dev->of_node, pd);
105+
if (ret)
106+
goto err_add_provider;
107+
108+
platform_set_drvdata(pdev, priv);
109+
110+
return 0;
111+
112+
err_add_provider:
113+
pm_genpd_remove(pd);
114+
115+
return ret;
116+
}
117+
118+
static void airoha_cpu_pmdomain_remove(struct platform_device *pdev)
119+
{
120+
struct airoha_cpu_pmdomain_priv *priv = platform_get_drvdata(pdev);
121+
122+
of_genpd_del_provider(pdev->dev.of_node);
123+
pm_genpd_remove(&priv->pd);
124+
}
125+
126+
static const struct of_device_id airoha_cpu_pmdomain_of_match[] = {
127+
{ .compatible = "airoha,en7581-cpufreq" },
128+
{ },
129+
};
130+
MODULE_DEVICE_TABLE(of, airoha_cpu_pmdomain_of_match);
131+
132+
static struct platform_driver airoha_cpu_pmdomain_driver = {
133+
.probe = airoha_cpu_pmdomain_probe,
134+
.remove = airoha_cpu_pmdomain_remove,
135+
.driver = {
136+
.name = "airoha-cpu-pmdomain",
137+
.of_match_table = airoha_cpu_pmdomain_of_match,
138+
},
139+
};
140+
module_platform_driver(airoha_cpu_pmdomain_driver);
141+
142+
MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
143+
MODULE_DESCRIPTION("CPU PM domain driver for Airoha SoCs");
144+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)