1 /* $NetBSD: timekeeper.c,v 1.7 2009/03/14 15:36:08 dsl Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
34 __KERNEL_RCSID(0, "$NetBSD: timekeeper.c,v 1.7 2009/03/14 15:36:08 dsl Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/kernel.h>
41 #include <machine/cpu.h>
43 #include <dev/clock_subr.h>
44 #include <luna68k/dev/timekeeper.h>
45 #include <machine/autoconf.h>
47 #define YEAR0 1970 /* year offset */
49 struct timekeeper_softc
{
51 void *sc_clock
, *sc_nvram
;
53 u_int8_t sc_image
[2040];
54 struct todr_chip_handle sc_todr
;
57 static int clock_match(struct device
*, struct cfdata
*, void *);
58 static void clock_attach(struct device
*, struct device
*, void *);
60 CFATTACH_DECL(clock
, sizeof (struct timekeeper_softc
),
61 clock_match
, clock_attach
, NULL
, NULL
);
62 extern struct cfdriver clock_cd
;
64 static int mkclock_get(todr_chip_handle_t
, struct clock_ymdhms
*);
65 static int mkclock_set(todr_chip_handle_t
, struct clock_ymdhms
*);
66 static int dsclock_get(todr_chip_handle_t
, struct clock_ymdhms
*);
67 static int dsclock_set(todr_chip_handle_t
, struct clock_ymdhms
*);
70 clock_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
72 struct mainbus_attach_args
*ma
= aux
;
74 if (strcmp(ma
->ma_name
, clock_cd
.cd_name
))
80 clock_attach(struct device
*parent
, struct device
*self
, void *aux
)
82 struct timekeeper_softc
*sc
= (void *)self
;
83 struct mainbus_attach_args
*ma
= aux
;
87 case LUNA_I
: /* Mostek MK48T02 */
88 sc
->sc_clock
= (void *)(ma
->ma_addr
+ 2040);
89 sc
->sc_nvram
= (void *)ma
->ma_addr
;
90 sc
->sc_nvramsize
= 2040;
91 sc
->sc_todr
.todr_gettime_ymdhms
= mkclock_get
;
92 sc
->sc_todr
.todr_settime_ymdhms
= mkclock_set
;
93 sc
->sc_todr
.cookie
= sc
;
94 printf(": mk48t02\n");
96 case LUNA_II
: /* Dallas DS1287A */
97 sc
->sc_clock
= (void *)ma
->ma_addr
;
98 sc
->sc_nvram
= (void *)(ma
->ma_addr
+ 50);
99 sc
->sc_nvramsize
= 50;
100 sc
->sc_todr
.todr_gettime_ymdhms
= dsclock_get
;
101 sc
->sc_todr
.todr_settime_ymdhms
= dsclock_set
;
102 sc
->sc_todr
.cookie
= sc
;
103 printf(": ds1287a\n");
106 todr_attach(&sc
->sc_todr
);
107 memcpy(sc
->sc_image
, sc
->sc_nvram
, sc
->sc_nvramsize
);
111 * Get the time of day, based on the clock's value and/or the base value.
114 mkclock_get(todr_chip_handle_t tch
, struct clock_ymdhms
*dt
)
116 struct timekeeper_softc
*sc
= (void *)tch
->cookie
;
117 volatile u_int8_t
*chiptime
= (void *)sc
->sc_clock
;
121 chiptime
[MK_CSR
] |= MK_CSR_READ
; /* enable read (stop time) */
122 dt
->dt_sec
= FROMBCD(chiptime
[MK_SEC
]);
123 dt
->dt_min
= FROMBCD(chiptime
[MK_MIN
]);
124 dt
->dt_hour
= FROMBCD(chiptime
[MK_HOUR
]);
125 dt
->dt_wday
= FROMBCD(chiptime
[MK_DOW
]);
126 dt
->dt_day
= FROMBCD(chiptime
[MK_DOM
]);
127 dt
->dt_mon
= FROMBCD(chiptime
[MK_MONTH
]);
128 dt
->dt_year
= FROMBCD(chiptime
[MK_YEAR
]) + YEAR0
;
129 chiptime
[MK_CSR
] &= ~MK_CSR_READ
; /* time wears on */
135 * Reset the TODR based on the time value.
138 mkclock_set(todr_chip_handle_t tch
, struct clock_ymdhms
*dt
)
140 struct timekeeper_softc
*sc
= (void *)tch
->cookie
;
141 volatile u_int8_t
*chiptime
= (void *)sc
->sc_clock
;
142 volatile u_int8_t
*stamp
= (u_int8_t
*)sc
->sc_nvram
+ 0x10;
146 chiptime
[MK_CSR
] |= MK_CSR_WRITE
; /* enable write */
147 chiptime
[MK_SEC
] = TOBCD(dt
->dt_sec
);
148 chiptime
[MK_MIN
] = TOBCD(dt
->dt_min
);
149 chiptime
[MK_HOUR
] = TOBCD(dt
->dt_hour
);
150 chiptime
[MK_DOW
] = TOBCD(dt
->dt_wday
);
151 chiptime
[MK_DOM
] = TOBCD(dt
->dt_day
);
152 chiptime
[MK_MONTH
] = TOBCD(dt
->dt_mon
);
153 chiptime
[MK_YEAR
] = TOBCD(dt
->dt_year
- YEAR0
);
154 chiptime
[MK_CSR
] &= ~MK_CSR_WRITE
; /* load them up */
157 stamp
[0] = 'R'; stamp
[1] = 'T'; stamp
[2] = 'C'; stamp
[3] = '\0';
162 * Get the time of day, based on the clock's value and/or the base value.
165 dsclock_get(todr_chip_handle_t tch
, struct clock_ymdhms
*dt
)
167 struct timekeeper_softc
*sc
= (void *)tch
->cookie
;
168 volatile u_int8_t
*chiptime
= (void *)sc
->sc_clock
;
172 /* update in progress; spin loop */
173 while (chiptime
[MC_REGA
] & MC_REGA_UIP
)
175 dt
->dt_sec
= chiptime
[MC_SEC
];
176 dt
->dt_min
= chiptime
[MC_MIN
];
177 dt
->dt_hour
= chiptime
[MC_HOUR
];
178 dt
->dt_wday
= chiptime
[MC_DOW
];
179 dt
->dt_day
= chiptime
[MC_DOM
];
180 dt
->dt_mon
= chiptime
[MC_MONTH
];
181 dt
->dt_year
= chiptime
[MC_YEAR
] + YEAR0
;
187 * Reset the TODR based on the time value.
190 dsclock_set(todr_chip_handle_t tch
, struct clock_ymdhms
*dt
)
192 struct timekeeper_softc
*sc
= (void *)tch
->cookie
;
193 volatile u_int8_t
*chiptime
= (void *)sc
->sc_clock
;
197 chiptime
[MC_REGB
] |= MC_REGB_SET
; /* enable write */
198 chiptime
[MC_SEC
] = dt
->dt_sec
;
199 chiptime
[MC_MIN
] = dt
->dt_min
;
200 chiptime
[MC_HOUR
] = dt
->dt_hour
;
201 chiptime
[MC_DOW
] = dt
->dt_wday
;
202 chiptime
[MC_DOM
] = dt
->dt_day
;
203 chiptime
[MC_MONTH
] = dt
->dt_mon
;
204 chiptime
[MC_YEAR
] = dt
->dt_year
- YEAR0
;
205 chiptime
[MC_REGB
] &= ~MC_REGB_SET
; /* load them up */