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>
16 #include <asm/processor.h>
19 #include <asm/cell-regs.h>
25 #include "ppc_cbe_cpufreq.h"
27 static u8 pmi_slow_mode_limit
[MAX_CBE
];
29 bool cbe_cpufreq_has_pmi
= false;
30 EXPORT_SYMBOL_GPL(cbe_cpufreq_has_pmi
);
33 * hardware specific functions
36 int cbe_cpufreq_set_pmode_pmi(int cpu
, unsigned int pmode
)
39 pmi_message_t pmi_msg
;
43 pmi_msg
.type
= PMI_TYPE_FREQ_CHANGE
;
44 pmi_msg
.data1
= cbe_cpu_to_node(cpu
);
45 pmi_msg
.data2
= pmode
;
50 pmi_send_message(pmi_msg
);
53 time
= jiffies
- time
;
54 time
= jiffies_to_msecs(time
);
55 pr_debug("had to wait %lu ms for a transition using " \
59 pr_debug("PMI returned slow mode %d\n", ret
);
63 EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi
);
66 static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg
)
70 BUG_ON(pmi_msg
.type
!= PMI_TYPE_FREQ_CHANGE
);
73 slow_mode
= pmi_msg
.data2
;
75 pmi_slow_mode_limit
[node
] = slow_mode
;
77 pr_debug("cbe_handle_pmi: node: %d max_freq: %d\n", node
, slow_mode
);
80 static int pmi_notifier(struct notifier_block
*nb
,
81 unsigned long event
, void *data
)
83 struct cpufreq_policy
*policy
= data
;
84 struct cpufreq_frequency_table
*cbe_freqs
= policy
->freq_table
;
87 /* Should this really be called for CPUFREQ_ADJUST and CPUFREQ_NOTIFY
90 node
= cbe_cpu_to_node(policy
->cpu
);
92 pr_debug("got notified, event=%lu, node=%u\n", event
, node
);
94 if (pmi_slow_mode_limit
[node
] != 0) {
95 pr_debug("limiting node %d to slow mode %d\n",
96 node
, pmi_slow_mode_limit
[node
]);
98 cpufreq_verify_within_limits(policy
, 0,
100 cbe_freqs
[pmi_slow_mode_limit
[node
]].frequency
);
106 static struct notifier_block pmi_notifier_block
= {
107 .notifier_call
= pmi_notifier
,
110 static struct pmi_handler cbe_pmi_handler
= {
111 .type
= PMI_TYPE_FREQ_CHANGE
,
112 .handle_pmi_message
= cbe_cpufreq_handle_pmi
,
117 static int __init
cbe_cpufreq_pmi_init(void)
119 cbe_cpufreq_has_pmi
= pmi_register_handler(&cbe_pmi_handler
) == 0;
121 if (!cbe_cpufreq_has_pmi
)
124 cpufreq_register_notifier(&pmi_notifier_block
, CPUFREQ_POLICY_NOTIFIER
);
128 device_initcall(cbe_cpufreq_pmi_init
);