Home | History | Annotate | Line # | Download | only in isa
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