Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
10818 views
1
/*
2
* pervasive backend for the cbe_cpufreq driver
3
*
4
* This driver makes use of the pervasive unit to
5
* engage the desired frequency.
6
*
7
* (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
8
*
9
* Author: Christian Krafft <[email protected]>
10
*
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2, or (at your option)
14
* any later version.
15
*
16
* This program is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
20
*
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
*/
25
26
#include <linux/io.h>
27
#include <linux/kernel.h>
28
#include <linux/time.h>
29
#include <asm/machdep.h>
30
#include <asm/hw_irq.h>
31
#include <asm/cell-regs.h>
32
33
#include "cbe_cpufreq.h"
34
35
/* to write to MIC register */
36
static u64 MIC_Slow_Fast_Timer_table[] = {
37
[0 ... 7] = 0x007fc00000000000ull,
38
};
39
40
/* more values for the MIC */
41
static u64 MIC_Slow_Next_Timer_table[] = {
42
0x0000240000000000ull,
43
0x0000268000000000ull,
44
0x000029C000000000ull,
45
0x00002D0000000000ull,
46
0x0000300000000000ull,
47
0x0000334000000000ull,
48
0x000039C000000000ull,
49
0x00003FC000000000ull,
50
};
51
52
53
int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode)
54
{
55
struct cbe_pmd_regs __iomem *pmd_regs;
56
struct cbe_mic_tm_regs __iomem *mic_tm_regs;
57
unsigned long flags;
58
u64 value;
59
#ifdef DEBUG
60
long time;
61
#endif
62
63
local_irq_save(flags);
64
65
mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
66
pmd_regs = cbe_get_cpu_pmd_regs(cpu);
67
68
#ifdef DEBUG
69
time = jiffies;
70
#endif
71
72
out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
73
out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
74
75
out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);
76
out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);
77
78
value = in_be64(&pmd_regs->pmcr);
79
/* set bits to zero */
80
value &= 0xFFFFFFFFFFFFFFF8ull;
81
/* set bits to next pmode */
82
value |= pmode;
83
84
out_be64(&pmd_regs->pmcr, value);
85
86
#ifdef DEBUG
87
/* wait until new pmode appears in status register */
88
value = in_be64(&pmd_regs->pmsr) & 0x07;
89
while (value != pmode) {
90
cpu_relax();
91
value = in_be64(&pmd_regs->pmsr) & 0x07;
92
}
93
94
time = jiffies - time;
95
time = jiffies_to_msecs(time);
96
pr_debug("had to wait %lu ms for a transition using " \
97
"pervasive unit\n", time);
98
#endif
99
local_irq_restore(flags);
100
101
return 0;
102
}
103
104
105
int cbe_cpufreq_get_pmode(int cpu)
106
{
107
int ret;
108
struct cbe_pmd_regs __iomem *pmd_regs;
109
110
pmd_regs = cbe_get_cpu_pmd_regs(cpu);
111
ret = in_be64(&pmd_regs->pmsr) & 0x07;
112
113
return ret;
114
}
115
116
117