Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
d037e053
Commit
d037e053
authored
May 11, 2007
by
David S. Miller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SPARC64]: Add support for bq4802 TOD chip, as found on ultra45.
Signed-off-by:
David S. Miller
<
davem@davemloft.net
>
parent
95d71e66
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
210 additions
and
20 deletions
+210
-20
arch/sparc64/kernel/time.c
arch/sparc64/kernel/time.c
+210
-20
No files found.
arch/sparc64/kernel/time.c
View file @
d037e053
...
@@ -55,6 +55,7 @@ DEFINE_SPINLOCK(rtc_lock);
...
@@ -55,6 +55,7 @@ DEFINE_SPINLOCK(rtc_lock);
void
__iomem
*
mstk48t02_regs
=
NULL
;
void
__iomem
*
mstk48t02_regs
=
NULL
;
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
unsigned
long
ds1287_regs
=
0UL
;
unsigned
long
ds1287_regs
=
0UL
;
static
void
__iomem
*
bq4802_regs
;
#endif
#endif
static
void
__iomem
*
mstk48t08_regs
;
static
void
__iomem
*
mstk48t08_regs
;
...
@@ -565,12 +566,14 @@ static void __init set_system_time(void)
...
@@ -565,12 +566,14 @@ static void __init set_system_time(void)
void
__iomem
*
mregs
=
mstk48t02_regs
;
void
__iomem
*
mregs
=
mstk48t02_regs
;
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
unsigned
long
dregs
=
ds1287_regs
;
unsigned
long
dregs
=
ds1287_regs
;
void
__iomem
*
bregs
=
bq4802_regs
;
#else
#else
unsigned
long
dregs
=
0UL
;
unsigned
long
dregs
=
0UL
;
void
__iomem
*
bregs
=
0UL
;
#endif
#endif
u8
tmp
;
u8
tmp
;
if
(
!
mregs
&&
!
dregs
)
{
if
(
!
mregs
&&
!
dregs
&&
!
bregs
)
{
prom_printf
(
"Something wrong, clock regs not mapped yet.
\n
"
);
prom_printf
(
"Something wrong, clock regs not mapped yet.
\n
"
);
prom_halt
();
prom_halt
();
}
}
...
@@ -589,6 +592,33 @@ static void __init set_system_time(void)
...
@@ -589,6 +592,33 @@ static void __init set_system_time(void)
day
=
MSTK_REG_DOM
(
mregs
);
day
=
MSTK_REG_DOM
(
mregs
);
mon
=
MSTK_REG_MONTH
(
mregs
);
mon
=
MSTK_REG_MONTH
(
mregs
);
year
=
MSTK_CVT_YEAR
(
MSTK_REG_YEAR
(
mregs
)
);
year
=
MSTK_CVT_YEAR
(
MSTK_REG_YEAR
(
mregs
)
);
}
else
if
(
bregs
)
{
unsigned
char
val
=
readb
(
bregs
+
0x0e
);
unsigned
int
century
;
/* BQ4802 RTC chip. */
writeb
(
val
|
0x08
,
bregs
+
0x0e
);
sec
=
readb
(
bregs
+
0x00
);
min
=
readb
(
bregs
+
0x02
);
hour
=
readb
(
bregs
+
0x04
);
day
=
readb
(
bregs
+
0x06
);
mon
=
readb
(
bregs
+
0x09
);
year
=
readb
(
bregs
+
0x0a
);
century
=
readb
(
bregs
+
0x0f
);
writeb
(
val
,
bregs
+
0x0e
);
BCD_TO_BIN
(
sec
);
BCD_TO_BIN
(
min
);
BCD_TO_BIN
(
hour
);
BCD_TO_BIN
(
day
);
BCD_TO_BIN
(
mon
);
BCD_TO_BIN
(
year
);
BCD_TO_BIN
(
century
);
year
+=
(
century
*
100
);
}
else
{
}
else
{
/* Dallas 12887 RTC chip. */
/* Dallas 12887 RTC chip. */
...
@@ -712,7 +742,8 @@ static int __init clock_model_matches(const char *model)
...
@@ -712,7 +742,8 @@ static int __init clock_model_matches(const char *model)
strcmp
(
model
,
"m5819"
)
&&
strcmp
(
model
,
"m5819"
)
&&
strcmp
(
model
,
"m5819p"
)
&&
strcmp
(
model
,
"m5819p"
)
&&
strcmp
(
model
,
"m5823"
)
&&
strcmp
(
model
,
"m5823"
)
&&
strcmp
(
model
,
"ds1287"
))
strcmp
(
model
,
"ds1287"
)
&&
strcmp
(
model
,
"bq4802"
))
return
0
;
return
0
;
return
1
;
return
1
;
...
@@ -722,9 +753,13 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id
...
@@ -722,9 +753,13 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id
{
{
struct
device_node
*
dp
=
op
->
node
;
struct
device_node
*
dp
=
op
->
node
;
const
char
*
model
=
of_get_property
(
dp
,
"model"
,
NULL
);
const
char
*
model
=
of_get_property
(
dp
,
"model"
,
NULL
);
const
char
*
compat
=
of_get_property
(
dp
,
"compatible"
,
NULL
);
unsigned
long
size
,
flags
;
unsigned
long
size
,
flags
;
void
__iomem
*
regs
;
void
__iomem
*
regs
;
if
(
!
model
)
model
=
compat
;
if
(
!
model
||
!
clock_model_matches
(
model
))
if
(
!
model
||
!
clock_model_matches
(
model
))
return
-
ENODEV
;
return
-
ENODEV
;
...
@@ -746,6 +781,8 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id
...
@@ -746,6 +781,8 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id
!
strcmp
(
model
,
"m5819p"
)
||
!
strcmp
(
model
,
"m5819p"
)
||
!
strcmp
(
model
,
"m5823"
))
{
!
strcmp
(
model
,
"m5823"
))
{
ds1287_regs
=
(
unsigned
long
)
regs
;
ds1287_regs
=
(
unsigned
long
)
regs
;
}
else
if
(
!
strcmp
(
model
,
"bq4802"
))
{
bq4802_regs
=
regs
;
}
else
}
else
#endif
#endif
if
(
model
[
5
]
==
'0'
&&
model
[
6
]
==
'2'
)
{
if
(
model
[
5
]
==
'0'
&&
model
[
6
]
==
'2'
)
{
...
@@ -1070,8 +1107,10 @@ static int set_rtc_mmss(unsigned long nowtime)
...
@@ -1070,8 +1107,10 @@ static int set_rtc_mmss(unsigned long nowtime)
void
__iomem
*
mregs
=
mstk48t02_regs
;
void
__iomem
*
mregs
=
mstk48t02_regs
;
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
unsigned
long
dregs
=
ds1287_regs
;
unsigned
long
dregs
=
ds1287_regs
;
void
__iomem
*
bregs
=
bq4802_regs
;
#else
#else
unsigned
long
dregs
=
0UL
;
unsigned
long
dregs
=
0UL
;
void
__iomem
*
bregs
=
0UL
;
#endif
#endif
unsigned
long
flags
;
unsigned
long
flags
;
u8
tmp
;
u8
tmp
;
...
@@ -1080,7 +1119,7 @@ static int set_rtc_mmss(unsigned long nowtime)
...
@@ -1080,7 +1119,7 @@ static int set_rtc_mmss(unsigned long nowtime)
* Not having a register set can lead to trouble.
* Not having a register set can lead to trouble.
* Also starfire doesn't have a tod clock.
* Also starfire doesn't have a tod clock.
*/
*/
if
(
!
mregs
&&
!
dregs
)
if
(
!
mregs
&&
!
dregs
&
!
bregs
)
return
-
1
;
return
-
1
;
if
(
mregs
)
{
if
(
mregs
)
{
...
@@ -1129,6 +1168,37 @@ static int set_rtc_mmss(unsigned long nowtime)
...
@@ -1129,6 +1168,37 @@ static int set_rtc_mmss(unsigned long nowtime)
return
-
1
;
return
-
1
;
}
}
}
else
if
(
bregs
)
{
int
retval
=
0
;
unsigned
char
val
=
readb
(
bregs
+
0x0e
);
/* BQ4802 RTC chip. */
writeb
(
val
|
0x08
,
bregs
+
0x0e
);
chip_minutes
=
readb
(
bregs
+
0x02
);
BCD_TO_BIN
(
chip_minutes
);
real_seconds
=
nowtime
%
60
;
real_minutes
=
nowtime
/
60
;
if
(((
abs
(
real_minutes
-
chip_minutes
)
+
15
)
/
30
)
&
1
)
real_minutes
+=
30
;
real_minutes
%=
60
;
if
(
abs
(
real_minutes
-
chip_minutes
)
<
30
)
{
BIN_TO_BCD
(
real_seconds
);
BIN_TO_BCD
(
real_minutes
);
writeb
(
real_seconds
,
bregs
+
0x00
);
writeb
(
real_minutes
,
bregs
+
0x02
);
}
else
{
printk
(
KERN_WARNING
"set_rtc_mmss: can't update from %d to %d
\n
"
,
chip_minutes
,
real_minutes
);
retval
=
-
1
;
}
writeb
(
val
,
bregs
+
0x0e
);
return
retval
;
}
else
{
}
else
{
int
retval
=
0
;
int
retval
=
0
;
unsigned
char
save_control
,
save_freq_select
;
unsigned
char
save_control
,
save_freq_select
;
...
@@ -1259,38 +1329,152 @@ static void to_tm(int tim, struct rtc_time *tm)
...
@@ -1259,38 +1329,152 @@ static void to_tm(int tim, struct rtc_time *tm)
/* Both Starfire and SUN4V give us seconds since Jan 1st, 1970,
/* Both Starfire and SUN4V give us seconds since Jan 1st, 1970,
* aka Unix time. So we have to convert to/from rtc_time.
* aka Unix time. So we have to convert to/from rtc_time.
*/
*/
static
inline
void
mini
_get_rtc_time
(
struct
rtc_time
*
time
)
static
void
starfire
_get_rtc_time
(
struct
rtc_time
*
time
)
{
{
unsigned
long
flags
;
u32
seconds
=
starfire_get_time
();
u32
seconds
;
spin_lock_irqsave
(
&
rtc_lock
,
flags
);
to_tm
(
seconds
,
time
);
seconds
=
0
;
time
->
tm_year
-=
1900
;
if
(
this_is_starfire
)
time
->
tm_mon
-=
1
;
seconds
=
starfire_get_time
();
}
else
if
(
tlb_type
==
hypervisor
)
seconds
=
hypervisor_get_time
();
static
int
starfire_set_rtc_time
(
struct
rtc_time
*
time
)
spin_unlock_irqrestore
(
&
rtc_lock
,
flags
);
{
u32
seconds
=
mktime
(
time
->
tm_year
+
1900
,
time
->
tm_mon
+
1
,
time
->
tm_mday
,
time
->
tm_hour
,
time
->
tm_min
,
time
->
tm_sec
);
return
starfire_set_time
(
seconds
);
}
static
void
hypervisor_get_rtc_time
(
struct
rtc_time
*
time
)
{
u32
seconds
=
hypervisor_get_time
();
to_tm
(
seconds
,
time
);
to_tm
(
seconds
,
time
);
time
->
tm_year
-=
1900
;
time
->
tm_year
-=
1900
;
time
->
tm_mon
-=
1
;
time
->
tm_mon
-=
1
;
}
}
static
in
line
int
mini
_set_rtc_time
(
struct
rtc_time
*
time
)
static
in
t
hypervisor
_set_rtc_time
(
struct
rtc_time
*
time
)
{
{
u32
seconds
=
mktime
(
time
->
tm_year
+
1900
,
time
->
tm_mon
+
1
,
u32
seconds
=
mktime
(
time
->
tm_year
+
1900
,
time
->
tm_mon
+
1
,
time
->
tm_mday
,
time
->
tm_hour
,
time
->
tm_mday
,
time
->
tm_hour
,
time
->
tm_min
,
time
->
tm_sec
);
time
->
tm_min
,
time
->
tm_sec
);
return
hypervisor_set_time
(
seconds
);
}
static
void
bq4802_get_rtc_time
(
struct
rtc_time
*
time
)
{
unsigned
char
val
=
readb
(
bq4802_regs
+
0x0e
);
unsigned
int
century
;
writeb
(
val
|
0x08
,
bq4802_regs
+
0x0e
);
time
->
tm_sec
=
readb
(
bq4802_regs
+
0x00
);
time
->
tm_min
=
readb
(
bq4802_regs
+
0x02
);
time
->
tm_hour
=
readb
(
bq4802_regs
+
0x04
);
time
->
tm_mday
=
readb
(
bq4802_regs
+
0x06
);
time
->
tm_mon
=
readb
(
bq4802_regs
+
0x09
);
time
->
tm_year
=
readb
(
bq4802_regs
+
0x0a
);
time
->
tm_wday
=
readb
(
bq4802_regs
+
0x08
);
century
=
readb
(
bq4802_regs
+
0x0f
);
writeb
(
val
,
bq4802_regs
+
0x0e
);
BCD_TO_BIN
(
time
->
tm_sec
);
BCD_TO_BIN
(
time
->
tm_min
);
BCD_TO_BIN
(
time
->
tm_hour
);
BCD_TO_BIN
(
time
->
tm_mday
);
BCD_TO_BIN
(
time
->
tm_mon
);
BCD_TO_BIN
(
time
->
tm_year
);
BCD_TO_BIN
(
time
->
tm_wday
);
BCD_TO_BIN
(
century
);
time
->
tm_year
+=
(
century
*
100
);
time
->
tm_year
-=
1900
;
time
->
tm_mon
--
;
}
static
int
bq4802_set_rtc_time
(
struct
rtc_time
*
time
)
{
unsigned
char
val
=
readb
(
bq4802_regs
+
0x0e
);
unsigned
char
sec
,
min
,
hrs
,
day
,
mon
,
yrs
,
century
;
unsigned
int
year
;
year
=
time
->
tm_year
+
1900
;
century
=
year
/
100
;
yrs
=
year
%
100
;
mon
=
time
->
tm_mon
+
1
;
/* tm_mon starts at zero */
day
=
time
->
tm_mday
;
hrs
=
time
->
tm_hour
;
min
=
time
->
tm_min
;
sec
=
time
->
tm_sec
;
BIN_TO_BCD
(
sec
);
BIN_TO_BCD
(
min
);
BIN_TO_BCD
(
hrs
);
BIN_TO_BCD
(
day
);
BIN_TO_BCD
(
mon
);
BIN_TO_BCD
(
yrs
);
BIN_TO_BCD
(
century
);
writeb
(
val
|
0x08
,
bq4802_regs
+
0x0e
);
writeb
(
sec
,
bq4802_regs
+
0x00
);
writeb
(
min
,
bq4802_regs
+
0x02
);
writeb
(
hrs
,
bq4802_regs
+
0x04
);
writeb
(
day
,
bq4802_regs
+
0x06
);
writeb
(
mon
,
bq4802_regs
+
0x09
);
writeb
(
yrs
,
bq4802_regs
+
0x0a
);
writeb
(
century
,
bq4802_regs
+
0x0f
);
writeb
(
val
,
bq4802_regs
+
0x0e
);
return
0
;
}
struct
mini_rtc_ops
{
void
(
*
get_rtc_time
)(
struct
rtc_time
*
);
int
(
*
set_rtc_time
)(
struct
rtc_time
*
);
};
static
struct
mini_rtc_ops
starfire_rtc_ops
=
{
.
get_rtc_time
=
starfire_get_rtc_time
,
.
set_rtc_time
=
starfire_set_rtc_time
,
};
static
struct
mini_rtc_ops
hypervisor_rtc_ops
=
{
.
get_rtc_time
=
hypervisor_get_rtc_time
,
.
set_rtc_time
=
hypervisor_set_rtc_time
,
};
static
struct
mini_rtc_ops
bq4802_rtc_ops
=
{
.
get_rtc_time
=
bq4802_get_rtc_time
,
.
set_rtc_time
=
bq4802_set_rtc_time
,
};
static
struct
mini_rtc_ops
*
mini_rtc_ops
;
static
inline
void
mini_get_rtc_time
(
struct
rtc_time
*
time
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
rtc_lock
,
flags
);
mini_rtc_ops
->
get_rtc_time
(
time
);
spin_unlock_irqrestore
(
&
rtc_lock
,
flags
);
}
static
inline
int
mini_set_rtc_time
(
struct
rtc_time
*
time
)
{
unsigned
long
flags
;
unsigned
long
flags
;
int
err
;
int
err
;
spin_lock_irqsave
(
&
rtc_lock
,
flags
);
spin_lock_irqsave
(
&
rtc_lock
,
flags
);
err
=
-
ENODEV
;
err
=
mini_rtc_ops
->
set_rtc_time
(
time
);
if
(
this_is_starfire
)
err
=
starfire_set_time
(
seconds
);
else
if
(
tlb_type
==
hypervisor
)
err
=
hypervisor_set_time
(
seconds
);
spin_unlock_irqrestore
(
&
rtc_lock
,
flags
);
spin_unlock_irqrestore
(
&
rtc_lock
,
flags
);
return
err
;
return
err
;
...
@@ -1391,7 +1575,13 @@ static int __init rtc_mini_init(void)
...
@@ -1391,7 +1575,13 @@ static int __init rtc_mini_init(void)
{
{
int
retval
;
int
retval
;
if
(
tlb_type
!=
hypervisor
&&
!
this_is_starfire
)
if
(
tlb_type
==
hypervisor
)
mini_rtc_ops
=
&
hypervisor_rtc_ops
;
else
if
(
this_is_starfire
)
mini_rtc_ops
=
&
starfire_rtc_ops
;
else
if
(
bq4802_regs
)
mini_rtc_ops
=
&
bq4802_rtc_ops
;
else
return
-
ENODEV
;
return
-
ENODEV
;
printk
(
KERN_INFO
"Mini RTC Driver
\n
"
);
printk
(
KERN_INFO
"Mini RTC Driver
\n
"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment