Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
10818 views
1
/*
2
* pmi backend for the cbe_cpufreq driver
3
*
4
* (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
5
*
6
* Author: Christian Krafft <[email protected]>
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2, or (at your option)
11
* any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
*/
22
23
#include <linux/kernel.h>
24
#include <linux/types.h>
25
#include <linux/timer.h>
26
#include <linux/of_platform.h>
27
28
#include <asm/processor.h>
29
#include <asm/prom.h>
30
#include <asm/pmi.h>
31
#include <asm/cell-regs.h>
32
33
#ifdef DEBUG
34
#include <asm/time.h>
35
#endif
36
37
#include "cbe_cpufreq.h"
38
39
static u8 pmi_slow_mode_limit[MAX_CBE];
40
41
bool cbe_cpufreq_has_pmi = false;
42
EXPORT_SYMBOL_GPL(cbe_cpufreq_has_pmi);
43
44
/*
45
* hardware specific functions
46
*/
47
48
int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode)
49
{
50
int ret;
51
pmi_message_t pmi_msg;
52
#ifdef DEBUG
53
long time;
54
#endif
55
pmi_msg.type = PMI_TYPE_FREQ_CHANGE;
56
pmi_msg.data1 = cbe_cpu_to_node(cpu);
57
pmi_msg.data2 = pmode;
58
59
#ifdef DEBUG
60
time = jiffies;
61
#endif
62
pmi_send_message(pmi_msg);
63
64
#ifdef DEBUG
65
time = jiffies - time;
66
time = jiffies_to_msecs(time);
67
pr_debug("had to wait %lu ms for a transition using " \
68
"PMI\n", time);
69
#endif
70
ret = pmi_msg.data2;
71
pr_debug("PMI returned slow mode %d\n", ret);
72
73
return ret;
74
}
75
EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi);
76
77
78
static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg)
79
{
80
u8 node, slow_mode;
81
82
BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE);
83
84
node = pmi_msg.data1;
85
slow_mode = pmi_msg.data2;
86
87
pmi_slow_mode_limit[node] = slow_mode;
88
89
pr_debug("cbe_handle_pmi: node: %d max_freq: %d\n", node, slow_mode);
90
}
91
92
static int pmi_notifier(struct notifier_block *nb,
93
unsigned long event, void *data)
94
{
95
struct cpufreq_policy *policy = data;
96
struct cpufreq_frequency_table *cbe_freqs;
97
u8 node;
98
99
/* Should this really be called for CPUFREQ_ADJUST, CPUFREQ_INCOMPATIBLE
100
* and CPUFREQ_NOTIFY policy events?)
101
*/
102
if (event == CPUFREQ_START)
103
return 0;
104
105
cbe_freqs = cpufreq_frequency_get_table(policy->cpu);
106
node = cbe_cpu_to_node(policy->cpu);
107
108
pr_debug("got notified, event=%lu, node=%u\n", event, node);
109
110
if (pmi_slow_mode_limit[node] != 0) {
111
pr_debug("limiting node %d to slow mode %d\n",
112
node, pmi_slow_mode_limit[node]);
113
114
cpufreq_verify_within_limits(policy, 0,
115
116
cbe_freqs[pmi_slow_mode_limit[node]].frequency);
117
}
118
119
return 0;
120
}
121
122
static struct notifier_block pmi_notifier_block = {
123
.notifier_call = pmi_notifier,
124
};
125
126
static struct pmi_handler cbe_pmi_handler = {
127
.type = PMI_TYPE_FREQ_CHANGE,
128
.handle_pmi_message = cbe_cpufreq_handle_pmi,
129
};
130
131
132
133
static int __init cbe_cpufreq_pmi_init(void)
134
{
135
cbe_cpufreq_has_pmi = pmi_register_handler(&cbe_pmi_handler) == 0;
136
137
if (!cbe_cpufreq_has_pmi)
138
return -ENODEV;
139
140
cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
141
142
return 0;
143
}
144
145
static void __exit cbe_cpufreq_pmi_exit(void)
146
{
147
cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
148
pmi_unregister_handler(&cbe_pmi_handler);
149
}
150
151
module_init(cbe_cpufreq_pmi_init);
152
module_exit(cbe_cpufreq_pmi_exit);
153
154
MODULE_LICENSE("GPL");
155
MODULE_AUTHOR("Christian Krafft <[email protected]>");
156
157