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