1 /* $NetBSD: dsrtc.c,v 1.10 2007/01/06 16:18:18 christos Exp $ */
4 * Copyright (c) 1998 Mark Brinicombe.
5 * Copyright (c) 1998 Causality Limited.
8 * Written by Mark Brinicombe, Causality Limited
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.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by Mark Brinicombe
21 * for the NetBSD Project.
22 * 4. The name of the company nor the name of the author may be used to
23 * endorse or promote products derived from this software without specific
24 * prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY CAUASLITY LIMITED ``AS IS'' AND ANY EXPRESS
27 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: dsrtc.c,v 1.10 2007/01/06 16:18:18 christos Exp $");
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
46 #include <sys/device.h>
48 #include <dev/clock_subr.h>
49 #include <arm/footbridge/isa/ds1687reg.h>
51 #include <dev/isa/isavar.h>
57 bus_space_tag_t sc_iot
;
58 bus_space_handle_t sc_ioh
;
59 struct todr_chip_handle sc_todr
;
62 void dsrtcattach(struct device
*parent
, struct device
*self
, void *aux
);
63 int dsrtcmatch(struct device
*parent
, struct cfdata
*cf
, void *aux
);
64 int ds1687_read(struct dsrtc_softc
*sc
, int addr
);
65 void ds1687_write(struct dsrtc_softc
*sc
, int addr
, int data
);
67 int ds1687_ram_read(struct dsrtc_softc
*sc
, int addr
);
68 void ds1687_ram_write(struct dsrtc_softc
*sc
, int addr
, int data
);
70 static void ds1687_bank_select(struct dsrtc_softc
*, int);
71 static int dsrtc_write(todr_chip_handle_t
, struct clock_ymdhms
*);
72 static int dsrtc_read(todr_chip_handle_t
, struct clock_ymdhms
*);
75 ds1687_read(struct dsrtc_softc
*sc
, int addr
)
78 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, RTC_ADDR_REG
, addr
);
79 return(bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, RTC_DATA_REG
));
83 ds1687_write(struct dsrtc_softc
*sc
, int addr
, int data
)
86 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, RTC_ADDR_REG
, addr
);
87 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, RTC_DATA_REG
, data
);
91 ds1687_bank_select(struct dsrtc_softc
*sc
, int bank
)
95 data
= ds1687_read(sc
, RTC_REG_A
);
96 data
&= ~RTC_REG_A_BANK_MASK
;
98 data
|= RTC_REG_A_BANK1
;
99 ds1687_write(sc
, RTC_REG_A
, data
);
103 /* Nothing uses these yet */
105 ds1687_ram_read(struct dsrtc_softc
*sc
, int addr
)
107 if (addr
< RTC_PC_RAM_SIZE
)
108 return(ds1687_read(sc
, RTC_PC_RAM_START
+ addr
));
110 addr
-= RTC_PC_RAM_SIZE
;
111 if (addr
< RTC_BANK0_RAM_SIZE
)
112 return(ds1687_read(sc
, RTC_BANK0_RAM_START
+ addr
));
114 addr
-= RTC_BANK0_RAM_SIZE
;
115 if (addr
< RTC_EXT_RAM_SIZE
) {
118 ds1687_bank_select(sc
, 1);
119 ds1687_write(sc
, RTC_EXT_RAM_ADDRESS
, addr
);
120 data
= ds1687_read(sc
, RTC_EXT_RAM_DATA
);
121 ds1687_bank_select(sc
, 0);
128 ds1687_ram_write(struct dsrtc_softc
*sc
, int addr
, int val
)
130 if (addr
< RTC_PC_RAM_SIZE
)
131 return(ds1687_write(sc
, RTC_PC_RAM_START
+ addr
, val
));
133 addr
-= RTC_PC_RAM_SIZE
;
134 if (addr
< RTC_BANK0_RAM_SIZE
)
135 return(ds1687_write(sc
, RTC_BANK0_RAM_START
+ addr
, val
));
137 addr
-= RTC_BANK0_RAM_SIZE
;
138 if (addr
< RTC_EXT_RAM_SIZE
) {
139 ds1687_bank_select(sc
, 1);
140 ds1687_write(sc
, RTC_EXT_RAM_ADDRESS
, addr
);
141 ds1687_write(sc
, RTC_EXT_RAM_DATA
, val
);
142 ds1687_bank_select(sc
, 0);
148 dsrtc_write(todr_chip_handle_t tc
, struct clock_ymdhms
*dt
)
150 struct dsrtc_softc
*sc
= tc
->cookie
;
152 ds1687_write(sc
, RTC_SECONDS
, dt
->dt_sec
);
153 ds1687_write(sc
, RTC_MINUTES
, dt
->dt_min
);
154 ds1687_write(sc
, RTC_HOURS
, dt
->dt_hour
);
155 ds1687_write(sc
, RTC_DAYOFMONTH
, dt
->dt_day
);
156 ds1687_write(sc
, RTC_MONTH
, dt
->dt_mon
);
157 ds1687_write(sc
, RTC_YEAR
, dt
->dt_year
% 100);
158 ds1687_bank_select(sc
, 1);
159 ds1687_write(sc
, RTC_CENTURY
, dt
->dt_year
/ 100);
160 ds1687_bank_select(sc
, 0);
165 dsrtc_read(todr_chip_handle_t tc
, struct clock_ymdhms
*dt
)
167 struct dsrtc_softc
*sc
= tc
->cookie
;
169 dt
->dt_sec
= ds1687_read(sc
, RTC_SECONDS
);
170 dt
->dt_min
= ds1687_read(sc
, RTC_MINUTES
);
171 dt
->dt_hour
= ds1687_read(sc
, RTC_HOURS
);
172 dt
->dt_day
= ds1687_read(sc
, RTC_DAYOFMONTH
);
173 dt
->dt_mon
= ds1687_read(sc
, RTC_MONTH
);
174 dt
->dt_year
= ds1687_read(sc
, RTC_YEAR
);
175 ds1687_bank_select(sc
, 1);
176 dt
->dt_year
+= ds1687_read(sc
, RTC_CENTURY
) * 100;
177 ds1687_bank_select(sc
, 0);
182 /* device and attach structures */
183 CFATTACH_DECL_NEW(ds1687rtc
, sizeof(struct dsrtc_softc
),
184 dsrtcmatch
, dsrtcattach
, NULL
, NULL
);
189 * Validate the IIC address to make sure its an RTC we understand
193 dsrtcmatch(device_t parent
, cfdata_t cf
, void *aux
)
195 struct isa_attach_args
*ia
= aux
;
197 if (ia
->ia_nio
< 1 ||
198 ia
->ia_io
[0].ir_addr
== ISA_UNKNOWN_PORT
)
202 ia
->ia_io
[0].ir_size
= NRTC_PORTS
;
214 * Attach the rtc device
218 dsrtcattach(device_t parent
, device_t self
, void *aux
)
220 struct dsrtc_softc
*sc
= device_private(self
);
221 struct isa_attach_args
*ia
= aux
;
223 sc
->sc_iot
= ia
->ia_iot
;
224 if (bus_space_map(sc
->sc_iot
, ia
->ia_io
[0].ir_addr
,
225 ia
->ia_io
[0].ir_size
, 0, &sc
->sc_ioh
)) {
226 aprint_error(": cannot map I/O space\n");
230 ds1687_write(sc
, RTC_REG_A
, RTC_REG_A_DV1
);
231 ds1687_write(sc
, RTC_REG_B
, RTC_REG_B_BINARY
| RTC_REG_B_24_HOUR
);
233 if (!(ds1687_read(sc
, RTC_REG_D
) & RTC_REG_D_VRT
))
234 aprint_error(": lithium cell is dead, RTC unreliable");
237 sc
->sc_todr
.todr_gettime_ymdhms
= dsrtc_read
;
238 sc
->sc_todr
.todr_settime_ymdhms
= dsrtc_write
;
239 sc
->sc_todr
.cookie
= sc
;
240 todr_attach(&sc
->sc_todr
);