xref: /netbsd-src/sys/arch/arm/footbridge/isa/dsrtc.c (revision 77e75c280a6ef9de02ed9c7c1ed432312348a840)
1*77e75c28Sskrll /*	$NetBSD: dsrtc.c,v 1.13 2021/08/13 11:40:43 skrll Exp $	*/
2a73dabb4Schris 
3a73dabb4Schris /*
4a73dabb4Schris  * Copyright (c) 1998 Mark Brinicombe.
5a73dabb4Schris  * Copyright (c) 1998 Causality Limited.
6a73dabb4Schris  * All rights reserved.
7a73dabb4Schris  *
8a73dabb4Schris  * Written by Mark Brinicombe, Causality Limited
9a73dabb4Schris  *
10a73dabb4Schris  * Redistribution and use in source and binary forms, with or without
11a73dabb4Schris  * modification, are permitted provided that the following conditions
12a73dabb4Schris  * are met:
13a73dabb4Schris  * 1. Redistributions of source code must retain the above copyright
14a73dabb4Schris  *    notice, this list of conditions and the following disclaimer.
15a73dabb4Schris  * 2. Redistributions in binary form must reproduce the above copyright
16a73dabb4Schris  *    notice, this list of conditions and the following disclaimer in the
17a73dabb4Schris  *    documentation and/or other materials provided with the distribution.
18a73dabb4Schris  * 3. All advertising materials mentioning features or use of this software
19a73dabb4Schris  *    must display the following acknowledgement:
20a73dabb4Schris  *	This product includes software developed by Mark Brinicombe
21a73dabb4Schris  *	for the NetBSD Project.
22a73dabb4Schris  * 4. The name of the company nor the name of the author may be used to
23a73dabb4Schris  *    endorse or promote products derived from this software without specific
24a73dabb4Schris  *    prior written permission.
25a73dabb4Schris  *
26a73dabb4Schris  * THIS SOFTWARE IS PROVIDED BY CAUASLITY LIMITED ``AS IS'' AND ANY EXPRESS
27a73dabb4Schris  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28a73dabb4Schris  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29a73dabb4Schris  * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED OR CONTRIBUTORS BE LIABLE
30a73dabb4Schris  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31a73dabb4Schris  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32a73dabb4Schris  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33a73dabb4Schris  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34a73dabb4Schris  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35a73dabb4Schris  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36a73dabb4Schris  * SUCH DAMAGE.
37a73dabb4Schris  */
38a73dabb4Schris 
399fd86b68Schris #include <sys/cdefs.h>
40*77e75c28Sskrll __KERNEL_RCSID(0, "$NetBSD: dsrtc.c,v 1.13 2021/08/13 11:40:43 skrll Exp $");
419fd86b68Schris 
42a73dabb4Schris #include <sys/param.h>
43a73dabb4Schris #include <sys/systm.h>
44a73dabb4Schris #include <sys/kernel.h>
45a73dabb4Schris #include <sys/conf.h>
46a73dabb4Schris #include <sys/device.h>
47a73dabb4Schris 
48467eaaa9Schristos #include <dev/clock_subr.h>
49a73dabb4Schris #include <arm/footbridge/isa/ds1687reg.h>
50a73dabb4Schris 
51a73dabb4Schris #include <dev/isa/isavar.h>
52a73dabb4Schris 
53a73dabb4Schris #define NRTC_PORTS	2
54a73dabb4Schris 
55a73dabb4Schris struct dsrtc_softc {
56a73dabb4Schris 	bus_space_tag_t	sc_iot;
57a73dabb4Schris 	bus_space_handle_t sc_ioh;
58467eaaa9Schristos 	struct todr_chip_handle sc_todr;
59a73dabb4Schris };
60a73dabb4Schris 
61f037af89Sskrll void dsrtcattach(device_t parent, device_t self, void *aux);
62f037af89Sskrll int dsrtcmatch(device_t parent, cfdata_t cf, void *aux);
63f475d69bSgdamore int ds1687_read(struct dsrtc_softc *sc, int addr);
64f475d69bSgdamore void ds1687_write(struct dsrtc_softc *sc, int addr, int data);
65f475d69bSgdamore #if 0
66f475d69bSgdamore int ds1687_ram_read(struct dsrtc_softc *sc, int addr);
67f475d69bSgdamore void ds1687_ram_write(struct dsrtc_softc *sc, int addr, int data);
68f475d69bSgdamore #endif
69f475d69bSgdamore static void ds1687_bank_select(struct dsrtc_softc *, int);
70467eaaa9Schristos static int dsrtc_write(todr_chip_handle_t, struct clock_ymdhms *);
71467eaaa9Schristos static int dsrtc_read(todr_chip_handle_t, struct clock_ymdhms *);
72a73dabb4Schris 
73a73dabb4Schris int
ds1687_read(struct dsrtc_softc * sc,int addr)74f475d69bSgdamore ds1687_read(struct dsrtc_softc *sc, int addr)
75a73dabb4Schris {
76a73dabb4Schris 
77a73dabb4Schris 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr);
78a73dabb4Schris 	return(bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG));
79a73dabb4Schris }
80a73dabb4Schris 
81a73dabb4Schris void
ds1687_write(struct dsrtc_softc * sc,int addr,int data)82f475d69bSgdamore ds1687_write(struct dsrtc_softc *sc, int addr, int data)
83a73dabb4Schris {
84a73dabb4Schris 
85a73dabb4Schris 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr);
86a73dabb4Schris 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG, data);
87a73dabb4Schris }
88a73dabb4Schris 
89a73dabb4Schris static void
ds1687_bank_select(struct dsrtc_softc * sc,int bank)90f475d69bSgdamore ds1687_bank_select(struct dsrtc_softc *sc, int bank)
91a73dabb4Schris {
92a73dabb4Schris 	int data;
93a73dabb4Schris 
94a73dabb4Schris 	data = ds1687_read(sc, RTC_REG_A);
95a73dabb4Schris 	data &= ~RTC_REG_A_BANK_MASK;
96a73dabb4Schris 	if (bank)
97a73dabb4Schris 		data |= RTC_REG_A_BANK1;
98a73dabb4Schris 	ds1687_write(sc, RTC_REG_A, data);
99a73dabb4Schris }
100a73dabb4Schris 
101a73dabb4Schris #if 0
102a73dabb4Schris /* Nothing uses these yet */
103a73dabb4Schris int
104f475d69bSgdamore ds1687_ram_read(struct dsrtc_softc *sc, int addr)
105a73dabb4Schris {
106a73dabb4Schris 	if (addr < RTC_PC_RAM_SIZE)
107a73dabb4Schris 		return(ds1687_read(sc, RTC_PC_RAM_START + addr));
108a73dabb4Schris 
109a73dabb4Schris 	addr -= RTC_PC_RAM_SIZE;
110a73dabb4Schris 	if (addr < RTC_BANK0_RAM_SIZE)
111a73dabb4Schris 		return(ds1687_read(sc, RTC_BANK0_RAM_START + addr));
112a73dabb4Schris 
113a73dabb4Schris 	addr -= RTC_BANK0_RAM_SIZE;
114a73dabb4Schris 	if (addr < RTC_EXT_RAM_SIZE) {
115a73dabb4Schris 		int data;
116a73dabb4Schris 
117a73dabb4Schris 		ds1687_bank_select(sc, 1);
118a73dabb4Schris 		ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr);
119a73dabb4Schris 		data = ds1687_read(sc, RTC_EXT_RAM_DATA);
120a73dabb4Schris 		ds1687_bank_select(sc, 0);
121a73dabb4Schris 		return(data);
122a73dabb4Schris 	}
123a73dabb4Schris 	return(-1);
124a73dabb4Schris }
125a73dabb4Schris 
126a73dabb4Schris void
127f475d69bSgdamore ds1687_ram_write(struct dsrtc_softc *sc, int addr, int val)
128a73dabb4Schris {
129a73dabb4Schris 	if (addr < RTC_PC_RAM_SIZE)
130a73dabb4Schris 		return(ds1687_write(sc, RTC_PC_RAM_START + addr, val));
131a73dabb4Schris 
132a73dabb4Schris 	addr -= RTC_PC_RAM_SIZE;
133a73dabb4Schris 	if (addr < RTC_BANK0_RAM_SIZE)
134a73dabb4Schris 		return(ds1687_write(sc, RTC_BANK0_RAM_START + addr, val));
135a73dabb4Schris 
136a73dabb4Schris 	addr -= RTC_BANK0_RAM_SIZE;
137a73dabb4Schris 	if (addr < RTC_EXT_RAM_SIZE) {
138a73dabb4Schris 		ds1687_bank_select(sc, 1);
139a73dabb4Schris 		ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr);
140a73dabb4Schris 		ds1687_write(sc, RTC_EXT_RAM_DATA, val);
141a73dabb4Schris 		ds1687_bank_select(sc, 0);
142a73dabb4Schris 	}
143a73dabb4Schris }
144a73dabb4Schris #endif
145a73dabb4Schris 
146a73dabb4Schris static int
dsrtc_write(todr_chip_handle_t tc,struct clock_ymdhms * dt)147467eaaa9Schristos dsrtc_write(todr_chip_handle_t tc, struct clock_ymdhms *dt)
148a73dabb4Schris {
149467eaaa9Schristos 	struct dsrtc_softc *sc = tc->cookie;
150a73dabb4Schris 
151467eaaa9Schristos 	ds1687_write(sc, RTC_SECONDS, dt->dt_sec);
152467eaaa9Schristos 	ds1687_write(sc, RTC_MINUTES, dt->dt_min);
153467eaaa9Schristos 	ds1687_write(sc, RTC_HOURS, dt->dt_hour);
154467eaaa9Schristos 	ds1687_write(sc, RTC_DAYOFMONTH, dt->dt_day);
155467eaaa9Schristos 	ds1687_write(sc, RTC_MONTH, dt->dt_mon);
156467eaaa9Schristos 	ds1687_write(sc, RTC_YEAR, dt->dt_year % 100);
157a73dabb4Schris 	ds1687_bank_select(sc, 1);
158467eaaa9Schristos 	ds1687_write(sc, RTC_CENTURY, dt->dt_year / 100);
159a73dabb4Schris 	ds1687_bank_select(sc, 0);
160467eaaa9Schristos 	return(0);
161a73dabb4Schris }
162a73dabb4Schris 
163a73dabb4Schris static int
dsrtc_read(todr_chip_handle_t tc,struct clock_ymdhms * dt)164467eaaa9Schristos dsrtc_read(todr_chip_handle_t tc, struct clock_ymdhms *dt)
165a73dabb4Schris {
166467eaaa9Schristos 	struct dsrtc_softc *sc = tc->cookie;
167a73dabb4Schris 
168467eaaa9Schristos 	dt->dt_sec   = ds1687_read(sc, RTC_SECONDS);
169467eaaa9Schristos 	dt->dt_min   = ds1687_read(sc, RTC_MINUTES);
170467eaaa9Schristos 	dt->dt_hour  = ds1687_read(sc, RTC_HOURS);
171467eaaa9Schristos 	dt->dt_day   = ds1687_read(sc, RTC_DAYOFMONTH);
172467eaaa9Schristos 	dt->dt_mon   = ds1687_read(sc, RTC_MONTH);
173467eaaa9Schristos 	dt->dt_year  = ds1687_read(sc, RTC_YEAR);
174a73dabb4Schris 	ds1687_bank_select(sc, 1);
175467eaaa9Schristos 	dt->dt_year  += ds1687_read(sc, RTC_CENTURY) * 100;
176a73dabb4Schris 	ds1687_bank_select(sc, 0);
177a73dabb4Schris 
178467eaaa9Schristos 	return(0);
179a73dabb4Schris }
180a73dabb4Schris 
181a73dabb4Schris /* device and attach structures */
1829cbe4c86Sskrll CFATTACH_DECL_NEW(ds1687rtc, sizeof(struct dsrtc_softc),
183bd5bb465Sthorpej     dsrtcmatch, dsrtcattach, NULL, NULL);
184a73dabb4Schris 
185a73dabb4Schris /*
186a73dabb4Schris  * dsrtcmatch()
187a73dabb4Schris  *
188a73dabb4Schris  * Validate the IIC address to make sure its an RTC we understand
189a73dabb4Schris  */
190a73dabb4Schris 
191a73dabb4Schris int
dsrtcmatch(device_t parent,cfdata_t cf,void * aux)1929cbe4c86Sskrll dsrtcmatch(device_t parent, cfdata_t cf, void *aux)
193a73dabb4Schris {
194a73dabb4Schris 	struct isa_attach_args *ia = aux;
195a73dabb4Schris 
196a73dabb4Schris 	if (ia->ia_nio < 1 ||
197ea827e51Sdrochner 	    ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
198a73dabb4Schris 		return (0);
199a73dabb4Schris 
200a73dabb4Schris 	ia->ia_nio = 1;
201a73dabb4Schris 	ia->ia_io[0].ir_size = NRTC_PORTS;
202a73dabb4Schris 
203a73dabb4Schris 	ia->ia_niomem = 0;
204a73dabb4Schris 	ia->ia_nirq = 0;
205a73dabb4Schris 	ia->ia_ndrq = 0;
206a73dabb4Schris 
207a73dabb4Schris 	return(1);
208a73dabb4Schris }
209a73dabb4Schris 
210a73dabb4Schris /*
211a73dabb4Schris  * dsrtcattach()
212a73dabb4Schris  *
213a73dabb4Schris  * Attach the rtc device
214a73dabb4Schris  */
215a73dabb4Schris 
216a73dabb4Schris void
dsrtcattach(device_t parent,device_t self,void * aux)2179cbe4c86Sskrll dsrtcattach(device_t parent, device_t self, void *aux)
218a73dabb4Schris {
2199cbe4c86Sskrll 	struct dsrtc_softc *sc = device_private(self);
220a73dabb4Schris 	struct isa_attach_args *ia = aux;
221a73dabb4Schris 
222a73dabb4Schris 	sc->sc_iot = ia->ia_iot;
223a73dabb4Schris 	if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr,
224a73dabb4Schris 	    ia->ia_io[0].ir_size, 0, &sc->sc_ioh)) {
2259cbe4c86Sskrll 		aprint_error(": cannot map I/O space\n");
226a73dabb4Schris 		return;
227a73dabb4Schris 	}
228a73dabb4Schris 
229a73dabb4Schris 	ds1687_write(sc, RTC_REG_A, RTC_REG_A_DV1);
230a73dabb4Schris 	ds1687_write(sc, RTC_REG_B, RTC_REG_B_BINARY | RTC_REG_B_24_HOUR);
231a73dabb4Schris 
232a73dabb4Schris 	if (!(ds1687_read(sc, RTC_REG_D) & RTC_REG_D_VRT))
2339cbe4c86Sskrll 		aprint_error(": lithium cell is dead, RTC unreliable");
2349cbe4c86Sskrll 	aprint_normal("\n");
235a73dabb4Schris 
236467eaaa9Schristos 	sc->sc_todr.todr_gettime_ymdhms = dsrtc_read;
237467eaaa9Schristos 	sc->sc_todr.todr_settime_ymdhms = dsrtc_write;
238467eaaa9Schristos 	sc->sc_todr.cookie = sc;
239467eaaa9Schristos 	todr_attach(&sc->sc_todr);
240a73dabb4Schris }
241a73dabb4Schris 
242a73dabb4Schris /* End of dsrtc.c */
243