dsrtc.c revision 1.4 1 /* $NetBSD: dsrtc.c,v 1.4 2002/10/02 15:45:10 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1998 Mark Brinicombe.
5 * Copyright (c) 1998 Causality Limited.
6 * All rights reserved.
7 *
8 * Written by Mark Brinicombe, Causality Limited
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
25 *
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
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/conf.h>
43 #include <sys/device.h>
44
45 #include <machine/rtc.h>
46
47 #include <arm/footbridge/todclockvar.h>
48 #include <arm/footbridge/isa/ds1687reg.h>
49
50 #include <dev/isa/isavar.h>
51
52 #define NRTC_PORTS 2
53
54 struct dsrtc_softc {
55 struct device sc_dev;
56 bus_space_tag_t sc_iot;
57 bus_space_handle_t sc_ioh;
58 };
59
60 void dsrtcattach __P((struct device *parent, struct device *self, void *aux));
61 int dsrtcmatch __P((struct device *parent, struct cfdata *cf, void *aux));
62 int ds1687_read __P((struct dsrtc_softc *sc, int addr));
63 void ds1687_write __P((struct dsrtc_softc *sc, int addr, int data));
64 int ds1687_ram_read __P((struct dsrtc_softc *sc, int addr));
65 void ds1687_ram_write __P((struct dsrtc_softc *sc, int addr, int data));
66 static void ds1687_bank_select __P((struct dsrtc_softc *, int));
67 static int dsrtc_write __P((void *, rtc_t *));
68 static int dsrtc_read __P((void *, rtc_t *));
69
70 int
71 ds1687_read(sc, addr)
72 struct dsrtc_softc *sc;
73 int addr;
74 {
75
76 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr);
77 return(bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG));
78 }
79
80 void
81 ds1687_write(sc, addr, data)
82 struct dsrtc_softc *sc;
83 int addr;
84 int data;
85 {
86
87 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr);
88 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG, data);
89 }
90
91 static void
92 ds1687_bank_select(sc, bank)
93 struct dsrtc_softc *sc;
94 int bank;
95 {
96 int data;
97
98 data = ds1687_read(sc, RTC_REG_A);
99 data &= ~RTC_REG_A_BANK_MASK;
100 if (bank)
101 data |= RTC_REG_A_BANK1;
102 ds1687_write(sc, RTC_REG_A, data);
103 }
104
105 #if 0
106 /* Nothing uses these yet */
107 int
108 ds1687_ram_read(sc, addr)
109 struct dsrtc_softc *sc;
110 int addr;
111 {
112 if (addr < RTC_PC_RAM_SIZE)
113 return(ds1687_read(sc, RTC_PC_RAM_START + addr));
114
115 addr -= RTC_PC_RAM_SIZE;
116 if (addr < RTC_BANK0_RAM_SIZE)
117 return(ds1687_read(sc, RTC_BANK0_RAM_START + addr));
118
119 addr -= RTC_BANK0_RAM_SIZE;
120 if (addr < RTC_EXT_RAM_SIZE) {
121 int data;
122
123 ds1687_bank_select(sc, 1);
124 ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr);
125 data = ds1687_read(sc, RTC_EXT_RAM_DATA);
126 ds1687_bank_select(sc, 0);
127 return(data);
128 }
129 return(-1);
130 }
131
132 void
133 ds1687_ram_write(sc, addr, val)
134 struct dsrtc_softc *sc;
135 int addr;
136 int val;
137 {
138 if (addr < RTC_PC_RAM_SIZE)
139 return(ds1687_write(sc, RTC_PC_RAM_START + addr, val));
140
141 addr -= RTC_PC_RAM_SIZE;
142 if (addr < RTC_BANK0_RAM_SIZE)
143 return(ds1687_write(sc, RTC_BANK0_RAM_START + addr, val));
144
145 addr -= RTC_BANK0_RAM_SIZE;
146 if (addr < RTC_EXT_RAM_SIZE) {
147 ds1687_bank_select(sc, 1);
148 ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr);
149 ds1687_write(sc, RTC_EXT_RAM_DATA, val);
150 ds1687_bank_select(sc, 0);
151 }
152 }
153 #endif
154
155 static int
156 dsrtc_write(arg, rtc)
157 void *arg;
158 rtc_t *rtc;
159 {
160 struct dsrtc_softc *sc = arg;
161
162 ds1687_write(sc, RTC_SECONDS, rtc->rtc_sec);
163 ds1687_write(sc, RTC_MINUTES, rtc->rtc_min);
164 ds1687_write(sc, RTC_HOURS, rtc->rtc_hour);
165 ds1687_write(sc, RTC_DAYOFMONTH, rtc->rtc_day);
166 ds1687_write(sc, RTC_MONTH, rtc->rtc_mon);
167 ds1687_write(sc, RTC_YEAR, rtc->rtc_year);
168 ds1687_bank_select(sc, 1);
169 ds1687_write(sc, RTC_CENTURY, rtc->rtc_cen);
170 ds1687_bank_select(sc, 0);
171 return(1);
172 }
173
174 static int
175 dsrtc_read(arg, rtc)
176 void *arg;
177 rtc_t *rtc;
178 {
179 struct dsrtc_softc *sc = arg;
180
181 rtc->rtc_micro = 0;
182 rtc->rtc_centi = 0;
183 rtc->rtc_sec = ds1687_read(sc, RTC_SECONDS);
184 rtc->rtc_min = ds1687_read(sc, RTC_MINUTES);
185 rtc->rtc_hour = ds1687_read(sc, RTC_HOURS);
186 rtc->rtc_day = ds1687_read(sc, RTC_DAYOFMONTH);
187 rtc->rtc_mon = ds1687_read(sc, RTC_MONTH);
188 rtc->rtc_year = ds1687_read(sc, RTC_YEAR);
189 ds1687_bank_select(sc, 1);
190 rtc->rtc_cen = ds1687_read(sc, RTC_CENTURY);
191 ds1687_bank_select(sc, 0);
192
193 return(1);
194 }
195
196 /* device and attach structures */
197 CFATTACH_DECL(dsrtc, sizeof(struct dsrtc_softc),
198 dsrtcmatch, dsrtcattach, NULL, NULL);
199
200 /*
201 * dsrtcmatch()
202 *
203 * Validate the IIC address to make sure its an RTC we understand
204 */
205
206 int
207 dsrtcmatch(parent, cf, aux)
208 struct device *parent;
209 struct cfdata *cf;
210 void *aux;
211 {
212 struct isa_attach_args *ia = aux;
213
214 if (ia->ia_nio < 1 ||
215 ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT)
216 return (0);
217
218 ia->ia_nio = 1;
219 ia->ia_io[0].ir_size = NRTC_PORTS;
220
221 ia->ia_niomem = 0;
222 ia->ia_nirq = 0;
223 ia->ia_ndrq = 0;
224
225 return(1);
226 }
227
228 /*
229 * dsrtcattach()
230 *
231 * Attach the rtc device
232 */
233
234 void
235 dsrtcattach(parent, self, aux)
236 struct device *parent;
237 struct device *self;
238 void *aux;
239 {
240 struct dsrtc_softc *sc = (struct dsrtc_softc *)self;
241 struct isa_attach_args *ia = aux;
242 struct todclock_attach_args ta;
243
244 sc->sc_iot = ia->ia_iot;
245 if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr,
246 ia->ia_io[0].ir_size, 0, &sc->sc_ioh)) {
247 printf(": cannot map I/O space\n");
248 return;
249 }
250
251 ds1687_write(sc, RTC_REG_A, RTC_REG_A_DV1);
252 ds1687_write(sc, RTC_REG_B, RTC_REG_B_BINARY | RTC_REG_B_24_HOUR);
253
254 if (!(ds1687_read(sc, RTC_REG_D) & RTC_REG_D_VRT))
255 printf(": lithium cell is dead, RTC unreliable");
256 printf("\n");
257
258 ta.ta_name = "todclock";
259 ta.ta_rtc_arg = sc;
260 ta.ta_rtc_write = dsrtc_write;
261 ta.ta_rtc_read = dsrtc_read;
262 ta.ta_flags = 0;
263 config_found(self, &ta, NULL);
264 }
265
266 /* End of dsrtc.c */
267