Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
ia64
kernel
cyclone.c
Go to the documentation of this file.
1
#include <linux/module.h>
2
#include <
linux/smp.h
>
3
#include <linux/time.h>
4
#include <linux/errno.h>
5
#include <linux/timex.h>
6
#include <
linux/clocksource.h
>
7
#include <asm/io.h>
8
9
/* IBM Summit (EXA) Cyclone counter code*/
10
#define CYCLONE_CBAR_ADDR 0xFEB00CD0
11
#define CYCLONE_PMCC_OFFSET 0x51A0
12
#define CYCLONE_MPMC_OFFSET 0x51D0
13
#define CYCLONE_MPCS_OFFSET 0x51A8
14
#define CYCLONE_TIMER_FREQ 100000000
15
16
int
use_cyclone
;
17
void
__init
cyclone_setup
(
void
)
18
{
19
use_cyclone
= 1;
20
}
21
22
static
void
__iomem
*cyclone_mc;
23
24
static
cycle_t
read_cyclone(
struct
clocksource
*
cs
)
25
{
26
return
(
cycle_t
)
readq
((
void
__iomem
*)cyclone_mc);
27
}
28
29
static
struct
clocksource
clocksource_cyclone = {
30
.name =
"cyclone"
,
31
.rating = 300,
32
.read = read_cyclone,
33
.mask = (1
LL
<< 40) - 1,
34
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
35
};
36
37
int
__init
init_cyclone_clock
(
void
)
38
{
39
u64
__iomem
*
reg
;
40
u64
base
;
/* saved cyclone base address */
41
u64
offset
;
/* offset from pageaddr to cyclone_timer register */
42
int
i
;
43
u32
__iomem
*cyclone_timer;
/* Cyclone MPMC0 register */
44
45
if
(!
use_cyclone
)
46
return
0;
47
48
printk
(
KERN_INFO
"Summit chipset: Starting Cyclone Counter.\n"
);
49
50
/* find base address */
51
offset = (
CYCLONE_CBAR_ADDR
);
52
reg =
ioremap_nocache
(offset,
sizeof
(
u64
));
53
if
(!reg){
54
printk
(
KERN_ERR
"Summit chipset: Could not find valid CBAR"
55
" register.\n"
);
56
use_cyclone
= 0;
57
return
-
ENODEV
;
58
}
59
base =
readq
(reg);
60
iounmap
(reg);
61
if
(!base){
62
printk
(
KERN_ERR
"Summit chipset: Could not find valid CBAR"
63
" value.\n"
);
64
use_cyclone
= 0;
65
return
-
ENODEV
;
66
}
67
68
/* setup PMCC */
69
offset = (base +
CYCLONE_PMCC_OFFSET
);
70
reg =
ioremap_nocache
(offset,
sizeof
(
u64
));
71
if
(!reg){
72
printk
(
KERN_ERR
"Summit chipset: Could not find valid PMCC"
73
" register.\n"
);
74
use_cyclone
= 0;
75
return
-
ENODEV
;
76
}
77
writel
(0x00000001,reg);
78
iounmap
(reg);
79
80
/* setup MPCS */
81
offset = (base +
CYCLONE_MPCS_OFFSET
);
82
reg =
ioremap_nocache
(offset,
sizeof
(
u64
));
83
if
(!reg){
84
printk
(
KERN_ERR
"Summit chipset: Could not find valid MPCS"
85
" register.\n"
);
86
use_cyclone
= 0;
87
return
-
ENODEV
;
88
}
89
writel
(0x00000001,reg);
90
iounmap
(reg);
91
92
/* map in cyclone_timer */
93
offset = (base +
CYCLONE_MPMC_OFFSET
);
94
cyclone_timer =
ioremap_nocache
(offset,
sizeof
(
u32
));
95
if
(!cyclone_timer){
96
printk
(
KERN_ERR
"Summit chipset: Could not find valid MPMC"
97
" register.\n"
);
98
use_cyclone
= 0;
99
return
-
ENODEV
;
100
}
101
102
/*quick test to make sure its ticking*/
103
for
(i=0; i<3; i++){
104
u32
old =
readl
(cyclone_timer);
105
int
stall = 100;
106
while
(stall--)
barrier
();
107
if
(
readl
(cyclone_timer) == old){
108
printk
(
KERN_ERR
"Summit chipset: Counter not counting!"
109
" DISABLED\n"
);
110
iounmap
(cyclone_timer);
111
cyclone_timer =
NULL
;
112
use_cyclone
= 0;
113
return
-
ENODEV
;
114
}
115
}
116
/* initialize last tick */
117
cyclone_mc = cyclone_timer;
118
clocksource_cyclone.archdata.fsys_mmio = cyclone_timer;
119
clocksource_register_hz(&clocksource_cyclone,
CYCLONE_TIMER_FREQ
);
120
121
return
0;
122
}
123
124
__initcall
(
init_cyclone_clock
);
Generated on Thu Jan 10 2013 13:06:34 for Linux Kernel by
1.8.2