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
m68k
mvme16x
rtc.c
Go to the documentation of this file.
1
/*
2
* Real Time Clock interface for Linux on the MVME16x
3
*
4
* Based on the PC driver by Paul Gortmaker.
5
*/
6
7
#define RTC_VERSION "1.00"
8
9
#include <linux/types.h>
10
#include <linux/errno.h>
11
#include <
linux/miscdevice.h
>
12
#include <
linux/ioport.h
>
13
#include <linux/capability.h>
14
#include <linux/fcntl.h>
15
#include <
linux/init.h
>
16
#include <linux/poll.h>
17
#include <
linux/mc146818rtc.h
>
/* For struct rtc_time and ioctls, etc */
18
#include <
linux/bcd.h
>
19
#include <
asm/mvme16xhw.h
>
20
21
#include <asm/io.h>
22
#include <asm/uaccess.h>
23
#include <asm/setup.h>
24
25
/*
26
* We sponge a minor off of the misc major. No need slurping
27
* up another valuable major dev number for this. If you add
28
* an ioctl, make sure you don't conflict with SPARC's RTC
29
* ioctls.
30
*/
31
32
static
const
unsigned
char
days_in_mo[] =
33
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
34
35
static
atomic_t
rtc_ready =
ATOMIC_INIT
(1);
36
37
static
long
rtc_ioctl(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
38
{
39
volatile
MK48T08ptr_t
rtc
= (
MK48T08ptr_t
)
MVME_RTC_BASE
;
40
unsigned
long
flags
;
41
struct
rtc_time
wtime;
42
void
__user
*
argp
= (
void
__user
*)arg;
43
44
switch
(cmd) {
45
case
RTC_RD_TIME
:
/* Read the time/date from RTC */
46
{
47
local_irq_save
(flags);
48
/* Ensure clock and real-time-mode-register are accessible */
49
rtc->
ctrl
=
RTC_READ
;
50
memset
(&wtime, 0,
sizeof
(
struct
rtc_time
));
51
wtime.tm_sec =
bcd2bin
(rtc->
bcd_sec
);
52
wtime.tm_min =
bcd2bin
(rtc->
bcd_min
);
53
wtime.tm_hour =
bcd2bin
(rtc->
bcd_hr
);
54
wtime.tm_mday =
bcd2bin
(rtc->
bcd_dom
);
55
wtime.tm_mon =
bcd2bin
(rtc->
bcd_mth
)-1;
56
wtime.tm_year =
bcd2bin
(rtc->
bcd_year
);
57
if
(wtime.tm_year < 70)
58
wtime.tm_year += 100;
59
wtime.tm_wday =
bcd2bin
(rtc->
bcd_dow
)-1;
60
rtc->
ctrl
= 0;
61
local_irq_restore
(flags);
62
return
copy_to_user
(argp, &wtime,
sizeof
wtime) ?
63
-
EFAULT
: 0;
64
}
65
case
RTC_SET_TIME
:
/* Set the RTC */
66
{
67
struct
rtc_time
rtc_tm;
68
unsigned
char
mon,
day
, hrs,
min
,
sec
, leap_yr;
69
unsigned
int
yrs;
70
71
if
(!
capable
(
CAP_SYS_ADMIN
))
72
return
-
EACCES
;
73
74
if
(
copy_from_user
(&rtc_tm, argp,
sizeof
(
struct
rtc_time
)))
75
return
-
EFAULT
;
76
77
yrs = rtc_tm.tm_year;
78
if
(yrs < 1900)
79
yrs += 1900;
80
mon = rtc_tm.tm_mon + 1;
/* tm_mon starts at zero */
81
day = rtc_tm.tm_mday;
82
hrs = rtc_tm.tm_hour;
83
min = rtc_tm.tm_min;
84
sec = rtc_tm.tm_sec;
85
86
leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
87
88
if
((mon > 12) || (day == 0))
89
return
-
EINVAL
;
90
91
if
(day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
92
return
-
EINVAL
;
93
94
if
((hrs >= 24) || (min >= 60) || (sec >= 60))
95
return
-
EINVAL
;
96
97
if
(yrs >= 2070)
98
return
-
EINVAL
;
99
100
local_irq_save
(flags);
101
rtc->
ctrl
=
RTC_WRITE
;
102
103
rtc->
bcd_sec
=
bin2bcd
(sec);
104
rtc->
bcd_min
=
bin2bcd
(min);
105
rtc->
bcd_hr
=
bin2bcd
(hrs);
106
rtc->
bcd_dom
=
bin2bcd
(day);
107
rtc->
bcd_mth
=
bin2bcd
(mon);
108
rtc->
bcd_year
=
bin2bcd
(yrs%100);
109
110
rtc->
ctrl
= 0;
111
local_irq_restore
(flags);
112
return
0;
113
}
114
default
:
115
return
-
EINVAL
;
116
}
117
}
118
119
/*
120
* We enforce only one user at a time here with the open/close.
121
*/
122
static
int
rtc_open(
struct
inode
*
inode
,
struct
file *file)
123
{
124
if
( !
atomic_dec_and_test
(&rtc_ready) )
125
{
126
atomic_inc
( &rtc_ready );
127
return
-
EBUSY
;
128
}
129
return
0;
130
}
131
132
static
int
rtc_release(
struct
inode *inode,
struct
file *file)
133
{
134
atomic_inc
( &rtc_ready );
135
return
0;
136
}
137
138
/*
139
* The various file operations we support.
140
*/
141
142
static
const
struct
file_operations
rtc_fops = {
143
.unlocked_ioctl = rtc_ioctl,
144
.open = rtc_open,
145
.release = rtc_release,
146
.llseek =
noop_llseek
,
147
};
148
149
static
struct
miscdevice
rtc_dev=
150
{
151
.minor =
RTC_MINOR
,
152
.name =
"rtc"
,
153
.fops = &rtc_fops
154
};
155
156
static
int
__init
rtc_MK48T08_init(
void
)
157
{
158
if
(!
MACH_IS_MVME16x
)
159
return
-
ENODEV
;
160
161
printk
(
KERN_INFO
"MK48T08 Real Time Clock Driver v%s\n"
,
RTC_VERSION
);
162
return
misc_register
(&rtc_dev);
163
}
164
module_init
(rtc_MK48T08_init);
Generated on Thu Jan 10 2013 13:07:55 for Linux Kernel by
1.8.2