1 /* $NetBSD: ds1743.c,v 1.6 2005/12/11 12:17:13 christos Exp $ */
4 * Copyright (c) 2001-2002 Wasabi Sysetms, Inc.
5 * Copyright (c) 1998 Mark Brinicombe.
6 * Copyright (c) 1998 Causality Limited.
9 * Written by Mark Brinicombe, Causality Limited
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Mark Brinicombe
22 * for the NetBSD Project.
23 * 4. The name of the company nor the name of the author may be used to
24 * endorse or promote products derived from this software without specific
25 * prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY CAUASLITY LIMITED ``AS IS'' AND ANY EXPRESS
28 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: ds1743.c,v 1.6 2005/12/11 12:17:13 christos Exp $");
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
46 #include <dev/clock_subr.h>
48 #include <machine/rtc.h>
49 #include <machine/bus.h>
51 #include <evbppc/walnut/dev/ds1743reg.h>
52 #include <evbppc/walnut/dev/pbusvar.h>
56 bus_space_tag_t sc_iot
;
57 bus_space_handle_t sc_ioh
;
58 struct todr_chip_handle sc_todr
;
61 static void dsrtcattach(struct device
*, struct device
*, void *);
62 static int dsrtcmatch(struct device
*, struct cfdata
*, void *);
63 #if 0 /* Nothing uses these yet */
64 static int ds1743_ram_read(struct dsrtc_softc
*, int);
65 static void ds1743_ram_write(struct dsrtc_softc
*, int, int);
68 static int dsrtc_read(todr_chip_handle_t
, struct clock_ymdhms
*);
69 static int dsrtc_write(todr_chip_handle_t
, struct clock_ymdhms
*);
70 static inline u_char
ds1743_read(struct dsrtc_softc
*, int);
71 static inline void ds1743_write(struct dsrtc_softc
*, int, u_char
);
72 static u_char
ds1743_lock(struct dsrtc_softc
*, u_char
);
73 static void ds1743_unlock(struct dsrtc_softc
*, u_char
);
75 /* device and attach structures */
76 CFATTACH_DECL(ds1743rtc
, sizeof(struct dsrtc_softc
),
77 dsrtcmatch
, dsrtcattach
, NULL
, NULL
);
82 * Validate the IIC address to make sure its an RTC we understand
86 #define DS_SCRATCH_ADDR 0x1FF7
89 dsrtcmatch(struct device
*parent
, struct cfdata
*cf
, void *aux
)
91 struct pbus_attach_args
*paa
= aux
;
92 int retval
= !ds1743found
;
96 /* match only RTC devices */
97 if (strcmp(paa
->pb_name
, cf
->cf_name
) != 0)
100 if (bus_space_map(paa
->pb_bt
, paa
->pb_addr
, DS_SIZE
, 0, &h
)) {
101 printf("%s: can't map i/o space\n", paa
->pb_name
);
105 /* Read one byte of what's supposed to be NVRAM */
106 x
= bus_space_read_1(paa
->pb_bt
, h
, DS_SCRATCH_ADDR
);
107 bus_space_write_1(paa
->pb_bt
, h
, DS_SCRATCH_ADDR
, 0xAA);
108 if (bus_space_read_1(paa
->pb_bt
, h
, DS_SCRATCH_ADDR
) != 0xAA) {
113 bus_space_write_1(paa
->pb_bt
, h
, DS_SCRATCH_ADDR
, 0x55);
114 if (bus_space_read_1(paa
->pb_bt
, h
, DS_SCRATCH_ADDR
) != 0x55) {
119 /* Restore scratch byte value */
120 bus_space_write_1(paa
->pb_bt
, h
, DS_SCRATCH_ADDR
, x
);
122 bus_space_unmap(paa
->pb_bt
, h
, DS_SIZE
);
130 * Attach the rtc device
134 dsrtcattach(struct device
*parent
, struct device
*self
, void *aux
)
136 struct dsrtc_softc
*sc
= (struct dsrtc_softc
*)self
;
137 struct pbus_attach_args
*paa
= aux
;
141 sc
->sc_iot
= paa
->pb_bt
;
142 if (bus_space_map(sc
->sc_iot
, paa
->pb_addr
, DS_SIZE
, 0, &sc
->sc_ioh
)) {
143 printf(": can't map i/o space\n");
147 ds1743_unlock(sc
, 0); /* Make sure the clock is running */
148 if ((ds1743_read(sc
, DS_DAY
) & DS_CTL_BF
) == 0)
149 printf(": lithium cell is dead, RTC unreliable");
155 dsrtc_read(sc
, &rtc
);
156 printf("RTC: %d/%d/%02d%02d %d:%02d:%02d\n",
157 rtc
.rtc_mon
, rtc
.rtc_day
, rtc
.rtc_cen
, rtc
.rtc_year
,
158 rtc
.rtc_hour
, rtc
.rtc_min
, rtc
.rtc_sec
);
162 sc
->sc_todr
.todr_gettime_ymdhms
= dsrtc_read
;
163 sc
->sc_todr
.todr_settime_ymdhms
= dsrtc_write
;
164 sc
->sc_todr
.cookie
= sc
;
165 todr_attach(&sc
->sc_todr
);
169 ds1743_read(struct dsrtc_softc
*sc
, int addr
)
172 return(bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, addr
));
176 ds1743_write(struct dsrtc_softc
*sc
, int addr
, u_char data
)
179 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, addr
, data
);
183 #if 0 /* Nothing uses these yet */
185 ds1743_ram_read(struct dsrtc_softc
*sc
, int addr
)
188 if (addr
>= DS_RAM_SIZE
)
190 return(ds1743_read(sc
, addr
));
194 ds1743_ram_write(struct dsrtc_softc
*sc
, int addr
, u_char val
)
197 if (addr
>= DS_RAM_SIZE
)
199 ds1743_write(sc
, addr
, val
);
203 #define BCD(x) ((((x) / 10) << 4) | (x % 10))
204 #define unBCD(v, x) v = x; v = ((v >> 4) & 0xf) * 10 + (v & 0xf)
207 ds1743_lock(struct dsrtc_softc
*sc
, u_char mode
)
211 octl
= ds1743_read(sc
, DS_CENTURY
);
212 ctl
= octl
| (mode
& DS_CTL_RW
);
213 ds1743_write(sc
, DS_CENTURY
, ctl
); /* Lock RTC for both reading and writing */
218 ds1743_unlock(struct dsrtc_softc
*sc
, u_char key
)
222 ctl
= ds1743_read(sc
, DS_CENTURY
);
223 ctl
= (ctl
& 0x3f) | (key
& DS_CTL_RW
);
224 ds1743_write(sc
, DS_CENTURY
, ctl
); /* Enable updates */
228 dsrtc_write(todr_chip_handle_t tch
, struct clock_ymdhms
*dt
)
230 struct dsrtc_softc
*sc
= tch
->cookie
;
233 key
= ds1743_lock(sc
, DS_CTL_W
);
235 ds1743_write(sc
, DS_SECONDS
, TOBCD(dt
->dt_sec
) & 0x7f);
236 ds1743_write(sc
, DS_MINUTES
, TOBCD(dt
->dt_min
) & 0x7f);
237 ds1743_write(sc
, DS_HOURS
, TOBCD(dt
->dt_hour
) & 0x3f);
238 ds1743_write(sc
, DS_DATE
, TOBCD(dt
->dt_day
) & 0x3f);
239 ds1743_write(sc
, DS_MONTH
, TOBCD(dt
->dt_mon
) & 0x1f);
240 ds1743_write(sc
, DS_YEAR
, TOBCD(dt
->dt_year
% 100));
241 ds1743_write(sc
, DS_CENTURY
, ((ds1743_read(sc
, DS_CENTURY
) & DS_CTL_RW
)
242 | TOBCD(dt
->dt_year
/ 100)));
244 ds1743_unlock(sc
, key
);
249 dsrtc_read(todr_chip_handle_t tch
, struct clock_ymdhms
*dt
)
251 struct dsrtc_softc
*sc
= tch
->cookie
;
254 key
= ds1743_lock(sc
, DS_CTL_R
);
255 dt
->dt_sec
= FROMBCD(ds1743_read(sc
, DS_SECONDS
) & 0x7f);
256 dt
->dt_min
= FROMBCD(ds1743_read(sc
, DS_MINUTES
) & 0x7f);
257 dt
->dt_hour
= FROMBCD(ds1743_read(sc
, DS_HOURS
) & 0x3f);
258 dt
->dt_day
= FROMBCD(ds1743_read(sc
, DS_DATE
) & 0x3f);
259 dt
->dt_mon
= FROMBCD(ds1743_read(sc
, DS_MONTH
) & 0x1f);
261 FROMBCD(ds1743_read(sc
, DS_YEAR
)) +
262 FROMBCD(ds1743_read(sc
, DS_CENTURY
) & ~DS_CTL_RW
) * 100;
264 ds1743_unlock(sc
, key
);