Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cbe_cpufreq_pervasive.c
Go to the documentation of this file.
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 
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