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