Home | History | Annotate | Line # | Download | only in ic
intersil7170.c revision 1.2.16.1
      1 /*	$NetBSD: intersil7170.c,v 1.2.16.1 2004/08/03 10:46:15 skrll Exp $ */
      2 /*-
      3  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      4  * All rights reserved.
      5  *
      6  * This code is derived from software contributed to The NetBSD Foundation
      7  * by Paul Kranenburg.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *        This product includes software developed by the NetBSD
     20  *        Foundation, Inc. and its contributors.
     21  * 4. Neither the name of The NetBSD Foundation nor the names of its
     22  *    contributors may be used to endorse or promote products derived
     23  *    from this software without specific prior written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     26  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 /*
     39  * Intersil 7170 time-of-day chip subroutines.
     40  */
     41 
     42 #include <sys/cdefs.h>
     43 __KERNEL_RCSID(0, "$NetBSD: intersil7170.c,v 1.2.16.1 2004/08/03 10:46:15 skrll Exp $");
     44 
     45 #include <sys/param.h>
     46 #include <sys/malloc.h>
     47 #include <sys/systm.h>
     48 #include <sys/errno.h>
     49 
     50 #include <machine/bus.h>
     51 #include <dev/clock_subr.h>
     52 #include <dev/ic/intersil7170.h>
     53 
     54 #define intersil_command(run, interrupt) \
     55 	(run | interrupt | INTERSIL_CMD_FREQ_32K | INTERSIL_CMD_24HR_MODE | \
     56 	 INTERSIL_CMD_NORMAL_MODE)
     57 
     58 struct intersil7170_softc {
     59 	bus_space_tag_t		sil_bt;
     60 	bus_space_handle_t	sil_bh;
     61 	int			sil_year0;
     62 };
     63 
     64 int intersil7170_gettime(todr_chip_handle_t, struct timeval *);
     65 int intersil7170_settime(todr_chip_handle_t, struct timeval *);
     66 int intersil7170_getcal(todr_chip_handle_t, int *);
     67 int intersil7170_setcal(todr_chip_handle_t, int);
     68 
     69 int intersil7170_auto_century_adjust = 1;
     70 
     71 todr_chip_handle_t
     72 intersil7170_attach(bt, bh, year0)
     73 	bus_space_tag_t bt;
     74 	bus_space_handle_t bh;
     75 	int year0;
     76 {
     77 	todr_chip_handle_t handle;
     78 	struct intersil7170_softc *sil;
     79 	int sz;
     80 
     81 	printf(": intersil7170");
     82 
     83 	sz = ALIGN(sizeof(struct todr_chip_handle)) + sizeof(struct intersil7170);
     84 	handle = malloc(sz, M_DEVBUF, M_NOWAIT);
     85 	sil = (struct intersil7170_softc *)((u_long)handle +
     86 					ALIGN(sizeof(struct todr_chip_handle)));
     87 	handle->cookie = sil;
     88 	handle->todr_gettime = intersil7170_gettime;
     89 	handle->todr_settime = intersil7170_settime;
     90 	handle->todr_getcal = intersil7170_getcal;
     91 	handle->todr_setcal = intersil7170_setcal;
     92 	sil->sil_bt = bt;
     93 	sil->sil_bh = bh;
     94 	sil->sil_year0 = year0;
     95 
     96 	return (handle);
     97 }
     98 
     99 /*
    100  * Set up the system's time, given a `reasonable' time value.
    101  */
    102 int
    103 intersil7170_gettime(handle, tv)
    104 	todr_chip_handle_t handle;
    105 	struct timeval *tv;
    106 {
    107 	struct intersil7170_softc *sil = handle->cookie;
    108 	bus_space_tag_t bt = sil->sil_bt;
    109 	bus_space_handle_t bh = sil->sil_bh;
    110 	struct clock_ymdhms dt;
    111 	u_int8_t cmd;
    112 	int year;
    113 	int s;
    114 
    115 	/* No interrupts while we're fiddling with the chip */
    116 	s = splhigh();
    117 
    118 	/* Enable read (stop time) */
    119 	cmd = intersil_command(INTERSIL_CMD_STOP, INTERSIL_CMD_IENABLE);
    120 	bus_space_write_1(bt, bh, INTERSIL_ICMD, cmd);
    121 
    122 	/* The order of reading out the clock elements is important */
    123 	bus_space_read_1(bt, bh, INTERSIL_ICSEC);	/* not used */
    124 	dt.dt_hour = bus_space_read_1(bt, bh, INTERSIL_IHOUR);
    125 	dt.dt_min = bus_space_read_1(bt, bh, INTERSIL_IMIN);
    126 	dt.dt_sec = bus_space_read_1(bt, bh, INTERSIL_ISEC);
    127 	dt.dt_mon = bus_space_read_1(bt, bh, INTERSIL_IMON);
    128 	dt.dt_day = bus_space_read_1(bt, bh, INTERSIL_IDAY);
    129 	year = bus_space_read_1(bt, bh, INTERSIL_IYEAR);
    130 	dt.dt_wday = bus_space_read_1(bt, bh, INTERSIL_IDOW);
    131 
    132 	/* Done writing (time wears on) */
    133 	cmd = intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE);
    134 	bus_space_write_1(bt, bh, INTERSIL_ICMD, cmd);
    135 	splx(s);
    136 
    137 	year += sil->sil_year0;
    138 	if (year < 1970 && intersil7170_auto_century_adjust != 0)
    139 		year += 100;
    140 
    141 	dt.dt_year = year;
    142 
    143 	tv->tv_sec = clock_ymdhms_to_secs(&dt);
    144 	tv->tv_usec = 0;
    145 	return (0);
    146 }
    147 
    148 /*
    149  * Reset the clock based on the current time.
    150  */
    151 int
    152 intersil7170_settime(handle, tv)
    153 	todr_chip_handle_t handle;
    154 	struct timeval *tv;
    155 {
    156 	struct intersil7170_softc *sil = handle->cookie;
    157 	bus_space_tag_t bt = sil->sil_bt;
    158 	bus_space_handle_t bh = sil->sil_bh;
    159 	struct clock_ymdhms dt;
    160 	u_int8_t cmd;
    161 	int year;
    162 	long sec;
    163 	int s;
    164 
    165 	sec = tv->tv_sec + ((tv->tv_usec < 500000) ? 0 : 1);
    166 	clock_secs_to_ymdhms(sec, &dt);
    167 
    168 	year = dt.dt_year - sil->sil_year0;
    169 	if (year > 99 && intersil7170_auto_century_adjust != 0)
    170 		year -= 100;
    171 
    172 	/* No interrupts while we're fiddling with the chip */
    173 	s = splhigh();
    174 
    175 	/* Enable write (stop time) */
    176 	cmd = intersil_command(INTERSIL_CMD_STOP, INTERSIL_CMD_IENABLE);
    177 	bus_space_write_1(bt, bh, INTERSIL_ICMD, cmd);
    178 
    179 	/* The order of reading writing the clock elements is important */
    180 	bus_space_write_1(bt, bh, INTERSIL_ICSEC, 0);
    181 	bus_space_write_1(bt, bh, INTERSIL_IHOUR, dt.dt_hour);
    182 	bus_space_write_1(bt, bh, INTERSIL_IMIN, dt.dt_min);
    183 	bus_space_write_1(bt, bh, INTERSIL_ISEC, dt.dt_sec);
    184 	bus_space_write_1(bt, bh, INTERSIL_IMON, dt.dt_mon);
    185 	bus_space_write_1(bt, bh, INTERSIL_IDAY, dt.dt_day);
    186 	bus_space_write_1(bt, bh, INTERSIL_IYEAR, year);
    187 	bus_space_write_1(bt, bh, INTERSIL_IDOW, dt.dt_wday);
    188 
    189 	/* Done writing (time wears on) */
    190 	cmd = intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE);
    191 	bus_space_write_1(bt, bh, INTERSIL_ICMD, cmd);
    192 	splx(s);
    193 
    194 	return (0);
    195 }
    196 
    197 int
    198 intersil7170_getcal(handle, vp)
    199 	todr_chip_handle_t handle;
    200 	int *vp;
    201 {
    202 	return (EOPNOTSUPP);
    203 }
    204 
    205 int
    206 intersil7170_setcal(handle, v)
    207 	todr_chip_handle_t handle;
    208 	int v;
    209 {
    210 	return (EOPNOTSUPP);
    211 }
    212