Home | History | Annotate | Line # | Download | only in dev
      1 /*	$NetBSD: ds1743.c,v 1.11 2025/09/07 21:45:13 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2001-2002 Wasabi Sysetms, Inc.
      5  * Copyright (c) 1998 Mark Brinicombe.
      6  * Copyright (c) 1998 Causality Limited.
      7  * All rights reserved.
      8  *
      9  * Written by Mark Brinicombe, Causality Limited
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *	This product includes software developed by Mark Brinicombe
     22  *	for the NetBSD Project.
     23  * 4. The name of the company nor the name of the author may be used to
     24  *    endorse or promote products derived from this software without specific
     25  *    prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY CAUASLITY LIMITED ``AS IS'' AND ANY EXPRESS
     28  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     29  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     30  * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED OR CONTRIBUTORS BE LIABLE
     31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     33  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     37  * SUCH DAMAGE.
     38  */
     39 
     40 #include <sys/cdefs.h>
     41 __KERNEL_RCSID(0, "$NetBSD: ds1743.c,v 1.11 2025/09/07 21:45:13 thorpej Exp $");
     42 
     43 #include <sys/param.h>
     44 #include <sys/systm.h>
     45 #include <sys/device.h>
     46 #include <dev/clock_subr.h>
     47 
     48 #include <machine/rtc.h>
     49 #include <sys/bus.h>
     50 
     51 #include <evbppc/walnut/dev/ds1743reg.h>
     52 #include <evbppc/walnut/dev/pbusvar.h>
     53 
     54 struct dsrtc_softc {
     55 	device_t	sc_dev;
     56 	bus_space_tag_t	sc_iot;
     57 	bus_space_handle_t sc_ioh;
     58 	struct todr_chip_handle sc_todr;
     59 };
     60 
     61 static void dsrtcattach(device_t, device_t, void *);
     62 static int dsrtcmatch(device_t, cfdata_t, void *);
     63 #if 0	/* Nothing uses these yet */
     64 static int ds1743_ram_read(struct dsrtc_softc *, int);
     65 static void ds1743_ram_write(struct dsrtc_softc *, int, int);
     66 #endif
     67 
     68 static int dsrtc_read(todr_chip_handle_t, struct clock_ymdhms *);
     69 static int dsrtc_write(todr_chip_handle_t, struct clock_ymdhms *);
     70 static inline u_char ds1743_read(struct dsrtc_softc *, int);
     71 static inline void ds1743_write(struct dsrtc_softc *, int, u_char);
     72 static u_char ds1743_lock(struct dsrtc_softc *, u_char);
     73 static void ds1743_unlock(struct dsrtc_softc *, u_char);
     74 
     75 /* device and attach structures */
     76 CFATTACH_DECL_NEW(ds1743rtc, sizeof(struct dsrtc_softc),
     77     dsrtcmatch, dsrtcattach, NULL, NULL);
     78 
     79 /*
     80  * dsrtcmatch()
     81  *
     82  * Validate the IIC address to make sure its an RTC we understand
     83  */
     84 int ds1743found = 0;
     85 
     86 #define DS_SCRATCH_ADDR 0x1FF7
     87 
     88 static int
     89 dsrtcmatch(device_t parent, cfdata_t cf, void *aux)
     90 {
     91 	struct pbus_attach_args *paa = aux;
     92 	int retval = !ds1743found;
     93 	bus_space_handle_t h;
     94 	u_int8_t x;
     95 
     96 	/* match only RTC devices */
     97 	if (strcmp(paa->pb_name, cf->cf_name) != 0)
     98 		return 0;
     99 
    100 	if (bus_space_map(paa->pb_bt, paa->pb_addr, DS_SIZE, 0, &h)) {
    101 		printf("%s: can't map i/o space\n", paa->pb_name);
    102 		return 0;
    103 	}
    104 
    105 	/* Read one byte of what's supposed to be NVRAM */
    106 	x = bus_space_read_1(paa->pb_bt, h, DS_SCRATCH_ADDR);
    107 	bus_space_write_1(paa->pb_bt, h, DS_SCRATCH_ADDR, 0xAA);
    108 	if (bus_space_read_1(paa->pb_bt, h, DS_SCRATCH_ADDR) != 0xAA) {
    109 		retval = 0;
    110 		goto done;
    111 	}
    112 
    113 	bus_space_write_1(paa->pb_bt, h, DS_SCRATCH_ADDR, 0x55);
    114 	if (bus_space_read_1(paa->pb_bt, h, DS_SCRATCH_ADDR) != 0x55) {
    115 		retval = 0;
    116 		goto done;
    117 	}
    118 
    119 	/* Restore scratch byte value */
    120 	bus_space_write_1(paa->pb_bt, h, DS_SCRATCH_ADDR, x);
    121   done:
    122 	bus_space_unmap(paa->pb_bt, h, DS_SIZE);
    123 
    124 	return retval;
    125 }
    126 
    127 /*
    128  * dsrtcattach()
    129  *
    130  * Attach the rtc device
    131  */
    132 
    133 static void
    134 dsrtcattach(device_t parent, device_t self, void *aux)
    135 {
    136 	struct dsrtc_softc *sc = device_private(self);
    137 	struct pbus_attach_args *paa = aux;
    138 
    139 	ds1743found = 1;
    140 
    141 	sc->sc_dev = self;
    142 	sc->sc_iot = paa->pb_bt;
    143 	if (bus_space_map(sc->sc_iot, paa->pb_addr, DS_SIZE, 0, &sc->sc_ioh)) {
    144 		printf(": can't map i/o space\n");
    145 		return;
    146 	}
    147 
    148 	ds1743_unlock(sc, 0);	/* Make sure the clock is running */
    149 	if ((ds1743_read(sc, DS_DAY) & DS_CTL_BF) == 0)
    150 		printf(": lithium cell is dead, RTC unreliable");
    151 	printf("\n");
    152 
    153 	sc->sc_todr.todr_gettime_ymdhms = dsrtc_read;
    154 	sc->sc_todr.todr_settime_ymdhms = dsrtc_write;
    155 	sc->sc_todr.todr_dev = self;
    156 
    157 #ifdef DEBUG
    158 	{
    159 		struct clock_ymdhms dt;
    160 		dsrtc_read(&sc->sc_todr, &dt);
    161 		printf("RTC: %d/%d/%04d %d:%02d:%02d\n",
    162 			dt.dt_mon, dt.dt_day, dt.dt_year,
    163 			dt.dt_hour, dt.dt_min, dt.dt_sec);
    164 	}
    165 #endif
    166 
    167 	todr_attach(&sc->sc_todr);
    168 }
    169 
    170 static inline u_char
    171 ds1743_read(struct dsrtc_softc *sc, int addr)
    172 {
    173 
    174 	return(bus_space_read_1(sc->sc_iot, sc->sc_ioh, addr));
    175 }
    176 
    177 static inline void
    178 ds1743_write(struct dsrtc_softc *sc, int addr, u_char data)
    179 {
    180 
    181 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, addr, data);
    182 }
    183 
    184 
    185 #if 0	/* Nothing uses these yet */
    186 static u_char
    187 ds1743_ram_read(struct dsrtc_softc *sc, int addr)
    188 {
    189 
    190 	if (addr >= DS_RAM_SIZE)
    191 		return(-1);
    192 	return(ds1743_read(sc, addr));
    193 }
    194 
    195 static void
    196 ds1743_ram_write(struct dsrtc_softc *sc, int addr, u_char val)
    197 {
    198 
    199 	if (addr >= DS_RAM_SIZE)
    200 		return (-1);
    201 	ds1743_write(sc, addr, val);
    202 }
    203 #endif
    204 
    205 #define BCD(x)		((((x) / 10) << 4) | (x % 10))
    206 #define unBCD(v, x)	v = x; v = ((v >> 4) & 0xf) * 10 + (v & 0xf)
    207 
    208 static u_char
    209 ds1743_lock(struct dsrtc_softc *sc, u_char mode)
    210 {
    211 	u_char octl, ctl;
    212 
    213 	octl = ds1743_read(sc, DS_CENTURY);
    214 	ctl = octl | (mode & DS_CTL_RW);
    215 	ds1743_write(sc, DS_CENTURY, ctl);	/* Lock RTC for both reading and writing */
    216 	return octl;
    217 }
    218 
    219 static void
    220 ds1743_unlock(struct dsrtc_softc *sc, u_char key)
    221 {
    222 	int ctl;
    223 
    224 	ctl = ds1743_read(sc, DS_CENTURY);
    225 	ctl = (ctl & 0x3f) | (key & DS_CTL_RW);
    226 	ds1743_write(sc, DS_CENTURY, ctl);	/* Enable updates */
    227 }
    228 
    229 static int
    230 dsrtc_write(todr_chip_handle_t tch, struct clock_ymdhms *dt)
    231 {
    232 	struct dsrtc_softc *sc = device_private(tch->todr_dev);
    233 	u_char key;
    234 
    235 	key = ds1743_lock(sc, DS_CTL_W);
    236 
    237 	ds1743_write(sc, DS_SECONDS, bintobcd(dt->dt_sec) & 0x7f);
    238 	ds1743_write(sc, DS_MINUTES, bintobcd(dt->dt_min) & 0x7f);
    239 	ds1743_write(sc, DS_HOURS, bintobcd(dt->dt_hour)  & 0x3f);
    240 	ds1743_write(sc, DS_DATE, bintobcd(dt->dt_day)    & 0x3f);
    241 	ds1743_write(sc, DS_MONTH, bintobcd(dt->dt_mon)   & 0x1f);
    242 	ds1743_write(sc, DS_YEAR, bintobcd(dt->dt_year % 100));
    243 	ds1743_write(sc, DS_CENTURY, ((ds1743_read(sc, DS_CENTURY) & DS_CTL_RW)
    244 				      | bintobcd(dt->dt_year / 100)));
    245 
    246 	ds1743_unlock(sc, key);
    247 	return(0);
    248 }
    249 
    250 static int
    251 dsrtc_read(todr_chip_handle_t tch, struct clock_ymdhms *dt)
    252 {
    253 	struct dsrtc_softc *sc = device_private(tch->todr_dev);
    254 	u_char key;
    255 
    256 	key = ds1743_lock(sc, DS_CTL_R);
    257 	dt->dt_sec = bcdtobin(ds1743_read(sc, DS_SECONDS) & 0x7f);
    258 	dt->dt_min = bcdtobin(ds1743_read(sc, DS_MINUTES) & 0x7f);
    259 	dt->dt_hour = bcdtobin(ds1743_read(sc, DS_HOURS) & 0x3f);
    260 	dt->dt_day = bcdtobin(ds1743_read(sc, DS_DATE)   & 0x3f);
    261 	dt->dt_mon = bcdtobin(ds1743_read(sc, DS_MONTH)   & 0x1f);
    262 	dt->dt_year =
    263 	    bcdtobin(ds1743_read(sc, DS_YEAR)) +
    264 	    bcdtobin(ds1743_read(sc, DS_CENTURY) & ~DS_CTL_RW) * 100;
    265 
    266 	ds1743_unlock(sc, key);
    267 	return(0);
    268 }
    269