xref: /netbsd-src/sys/arch/arm/footbridge/isa/dsrtc.c (revision 77e75c280a6ef9de02ed9c7c1ed432312348a840)
1 /*	$NetBSD: dsrtc.c,v 1.13 2021/08/13 11:40:43 skrll 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.13 2021/08/13 11:40:43 skrll 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 <dev/clock_subr.h>
49 #include <arm/footbridge/isa/ds1687reg.h>
50 
51 #include <dev/isa/isavar.h>
52 
53 #define NRTC_PORTS	2
54 
55 struct dsrtc_softc {
56 	bus_space_tag_t	sc_iot;
57 	bus_space_handle_t sc_ioh;
58 	struct todr_chip_handle sc_todr;
59 };
60 
61 void dsrtcattach(device_t parent, device_t self, void *aux);
62 int dsrtcmatch(device_t parent, cfdata_t cf, void *aux);
63 int ds1687_read(struct dsrtc_softc *sc, int addr);
64 void ds1687_write(struct dsrtc_softc *sc, int addr, int data);
65 #if 0
66 int ds1687_ram_read(struct dsrtc_softc *sc, int addr);
67 void ds1687_ram_write(struct dsrtc_softc *sc, int addr, int data);
68 #endif
69 static void ds1687_bank_select(struct dsrtc_softc *, int);
70 static int dsrtc_write(todr_chip_handle_t, struct clock_ymdhms *);
71 static int dsrtc_read(todr_chip_handle_t, struct clock_ymdhms *);
72 
73 int
ds1687_read(struct dsrtc_softc * sc,int addr)74 ds1687_read(struct dsrtc_softc *sc, int addr)
75 {
76 
77 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr);
78 	return(bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG));
79 }
80 
81 void
ds1687_write(struct dsrtc_softc * sc,int addr,int data)82 ds1687_write(struct dsrtc_softc *sc, int addr, int data)
83 {
84 
85 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr);
86 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG, data);
87 }
88 
89 static void
ds1687_bank_select(struct dsrtc_softc * sc,int bank)90 ds1687_bank_select(struct dsrtc_softc *sc, int bank)
91 {
92 	int data;
93 
94 	data = ds1687_read(sc, RTC_REG_A);
95 	data &= ~RTC_REG_A_BANK_MASK;
96 	if (bank)
97 		data |= RTC_REG_A_BANK1;
98 	ds1687_write(sc, RTC_REG_A, data);
99 }
100 
101 #if 0
102 /* Nothing uses these yet */
103 int
104 ds1687_ram_read(struct dsrtc_softc *sc, int addr)
105 {
106 	if (addr < RTC_PC_RAM_SIZE)
107 		return(ds1687_read(sc, RTC_PC_RAM_START + addr));
108 
109 	addr -= RTC_PC_RAM_SIZE;
110 	if (addr < RTC_BANK0_RAM_SIZE)
111 		return(ds1687_read(sc, RTC_BANK0_RAM_START + addr));
112 
113 	addr -= RTC_BANK0_RAM_SIZE;
114 	if (addr < RTC_EXT_RAM_SIZE) {
115 		int data;
116 
117 		ds1687_bank_select(sc, 1);
118 		ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr);
119 		data = ds1687_read(sc, RTC_EXT_RAM_DATA);
120 		ds1687_bank_select(sc, 0);
121 		return(data);
122 	}
123 	return(-1);
124 }
125 
126 void
127 ds1687_ram_write(struct dsrtc_softc *sc, int addr, int val)
128 {
129 	if (addr < RTC_PC_RAM_SIZE)
130 		return(ds1687_write(sc, RTC_PC_RAM_START + addr, val));
131 
132 	addr -= RTC_PC_RAM_SIZE;
133 	if (addr < RTC_BANK0_RAM_SIZE)
134 		return(ds1687_write(sc, RTC_BANK0_RAM_START + addr, val));
135 
136 	addr -= RTC_BANK0_RAM_SIZE;
137 	if (addr < RTC_EXT_RAM_SIZE) {
138 		ds1687_bank_select(sc, 1);
139 		ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr);
140 		ds1687_write(sc, RTC_EXT_RAM_DATA, val);
141 		ds1687_bank_select(sc, 0);
142 	}
143 }
144 #endif
145 
146 static int
dsrtc_write(todr_chip_handle_t tc,struct clock_ymdhms * dt)147 dsrtc_write(todr_chip_handle_t tc, struct clock_ymdhms *dt)
148 {
149 	struct dsrtc_softc *sc = tc->cookie;
150 
151 	ds1687_write(sc, RTC_SECONDS, dt->dt_sec);
152 	ds1687_write(sc, RTC_MINUTES, dt->dt_min);
153 	ds1687_write(sc, RTC_HOURS, dt->dt_hour);
154 	ds1687_write(sc, RTC_DAYOFMONTH, dt->dt_day);
155 	ds1687_write(sc, RTC_MONTH, dt->dt_mon);
156 	ds1687_write(sc, RTC_YEAR, dt->dt_year % 100);
157 	ds1687_bank_select(sc, 1);
158 	ds1687_write(sc, RTC_CENTURY, dt->dt_year / 100);
159 	ds1687_bank_select(sc, 0);
160 	return(0);
161 }
162 
163 static int
dsrtc_read(todr_chip_handle_t tc,struct clock_ymdhms * dt)164 dsrtc_read(todr_chip_handle_t tc, struct clock_ymdhms *dt)
165 {
166 	struct dsrtc_softc *sc = tc->cookie;
167 
168 	dt->dt_sec   = ds1687_read(sc, RTC_SECONDS);
169 	dt->dt_min   = ds1687_read(sc, RTC_MINUTES);
170 	dt->dt_hour  = ds1687_read(sc, RTC_HOURS);
171 	dt->dt_day   = ds1687_read(sc, RTC_DAYOFMONTH);
172 	dt->dt_mon   = ds1687_read(sc, RTC_MONTH);
173 	dt->dt_year  = ds1687_read(sc, RTC_YEAR);
174 	ds1687_bank_select(sc, 1);
175 	dt->dt_year  += ds1687_read(sc, RTC_CENTURY) * 100;
176 	ds1687_bank_select(sc, 0);
177 
178 	return(0);
179 }
180 
181 /* device and attach structures */
182 CFATTACH_DECL_NEW(ds1687rtc, sizeof(struct dsrtc_softc),
183     dsrtcmatch, dsrtcattach, NULL, NULL);
184 
185 /*
186  * dsrtcmatch()
187  *
188  * Validate the IIC address to make sure its an RTC we understand
189  */
190 
191 int
dsrtcmatch(device_t parent,cfdata_t cf,void * aux)192 dsrtcmatch(device_t parent, cfdata_t cf, void *aux)
193 {
194 	struct isa_attach_args *ia = aux;
195 
196 	if (ia->ia_nio < 1 ||
197 	    ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
198 		return (0);
199 
200 	ia->ia_nio = 1;
201 	ia->ia_io[0].ir_size = NRTC_PORTS;
202 
203 	ia->ia_niomem = 0;
204 	ia->ia_nirq = 0;
205 	ia->ia_ndrq = 0;
206 
207 	return(1);
208 }
209 
210 /*
211  * dsrtcattach()
212  *
213  * Attach the rtc device
214  */
215 
216 void
dsrtcattach(device_t parent,device_t self,void * aux)217 dsrtcattach(device_t parent, device_t self, void *aux)
218 {
219 	struct dsrtc_softc *sc = device_private(self);
220 	struct isa_attach_args *ia = aux;
221 
222 	sc->sc_iot = ia->ia_iot;
223 	if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr,
224 	    ia->ia_io[0].ir_size, 0, &sc->sc_ioh)) {
225 		aprint_error(": cannot map I/O space\n");
226 		return;
227 	}
228 
229 	ds1687_write(sc, RTC_REG_A, RTC_REG_A_DV1);
230 	ds1687_write(sc, RTC_REG_B, RTC_REG_B_BINARY | RTC_REG_B_24_HOUR);
231 
232 	if (!(ds1687_read(sc, RTC_REG_D) & RTC_REG_D_VRT))
233 		aprint_error(": lithium cell is dead, RTC unreliable");
234 	aprint_normal("\n");
235 
236 	sc->sc_todr.todr_gettime_ymdhms = dsrtc_read;
237 	sc->sc_todr.todr_settime_ymdhms = dsrtc_write;
238 	sc->sc_todr.cookie = sc;
239 	todr_attach(&sc->sc_todr);
240 }
241 
242 /* End of dsrtc.c */
243