1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * pmi backend for the cbe_cpufreq driver
5 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
7 * Author: Christian Krafft <krafft@de.ibm.com>
10 #include <linux/kernel.h>
11 #include <linux/types.h>
12 #include <linux/timer.h>
13 #include <linux/init.h>
14 #include <linux/of_platform.h>
15 #include <linux/pm_qos.h>
17 #include <asm/processor.h>
20 #include <asm/cell-regs.h>
26 #include "ppc_cbe_cpufreq.h"
28 bool cbe_cpufreq_has_pmi
= false;
29 EXPORT_SYMBOL_GPL(cbe_cpufreq_has_pmi
);
32 * hardware specific functions
35 int cbe_cpufreq_set_pmode_pmi(int cpu
, unsigned int pmode
)
38 pmi_message_t pmi_msg
;
42 pmi_msg
.type
= PMI_TYPE_FREQ_CHANGE
;
43 pmi_msg
.data1
= cbe_cpu_to_node(cpu
);
44 pmi_msg
.data2
= pmode
;
49 pmi_send_message(pmi_msg
);
52 time
= jiffies
- time
;
53 time
= jiffies_to_msecs(time
);
54 pr_debug("had to wait %lu ms for a transition using " \
58 pr_debug("PMI returned slow mode %d\n", ret
);
62 EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi
);
65 static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg
)
67 struct cpufreq_policy
*policy
;
68 struct freq_qos_request
*req
;
72 BUG_ON(pmi_msg
.type
!= PMI_TYPE_FREQ_CHANGE
);
75 slow_mode
= pmi_msg
.data2
;
77 cpu
= cbe_node_to_cpu(node
);
79 pr_debug("cbe_handle_pmi: node: %d max_freq: %d\n", node
, slow_mode
);
81 policy
= cpufreq_cpu_get(cpu
);
83 pr_warn("cpufreq policy not found cpu%d\n", cpu
);
87 req
= policy
->driver_data
;
89 ret
= freq_qos_update_request(req
,
90 policy
->freq_table
[slow_mode
].frequency
);
92 pr_warn("Failed to update freq constraint: %d\n", ret
);
94 pr_debug("limiting node %d to slow mode %d\n", node
, slow_mode
);
96 cpufreq_cpu_put(policy
);
99 static struct pmi_handler cbe_pmi_handler
= {
100 .type
= PMI_TYPE_FREQ_CHANGE
,
101 .handle_pmi_message
= cbe_cpufreq_handle_pmi
,
104 void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy
*policy
)
106 struct freq_qos_request
*req
;
109 if (!cbe_cpufreq_has_pmi
)
112 req
= kzalloc(sizeof(*req
), GFP_KERNEL
);
116 ret
= freq_qos_add_request(&policy
->constraints
, req
, FREQ_QOS_MAX
,
117 policy
->freq_table
[0].frequency
);
119 pr_err("Failed to add freq constraint (%d)\n", ret
);
124 policy
->driver_data
= req
;
126 EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_init
);
128 void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy
*policy
)
130 struct freq_qos_request
*req
= policy
->driver_data
;
132 if (cbe_cpufreq_has_pmi
) {
133 freq_qos_remove_request(req
);
137 EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_exit
);
139 void cbe_cpufreq_pmi_init(void)
141 if (!pmi_register_handler(&cbe_pmi_handler
))
142 cbe_cpufreq_has_pmi
= true;
144 EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_init
);
146 void cbe_cpufreq_pmi_exit(void)
148 pmi_unregister_handler(&cbe_pmi_handler
);
149 cbe_cpufreq_has_pmi
= false;
151 EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_exit
);