1 /* $NetBSD: intersil7170.c,v 1.2 2001/11/13 13:14:38 lukem 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 2001/11/13 13:14:38 lukem 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 int s; 163 164 clock_secs_to_ymdhms(tv->tv_sec, &dt); 165 166 year = dt.dt_year - sil->sil_year0; 167 if (year > 99 && intersil7170_auto_century_adjust != 0) 168 year -= 100; 169 170 /* No interrupts while we're fiddling with the chip */ 171 s = splhigh(); 172 173 /* Enable write (stop time) */ 174 cmd = intersil_command(INTERSIL_CMD_STOP, INTERSIL_CMD_IENABLE); 175 bus_space_write_1(bt, bh, INTERSIL_ICMD, cmd); 176 177 /* The order of reading writing the clock elements is important */ 178 bus_space_write_1(bt, bh, INTERSIL_ICSEC, 0); 179 bus_space_write_1(bt, bh, INTERSIL_IHOUR, dt.dt_hour); 180 bus_space_write_1(bt, bh, INTERSIL_IMIN, dt.dt_min); 181 bus_space_write_1(bt, bh, INTERSIL_ISEC, dt.dt_sec); 182 bus_space_write_1(bt, bh, INTERSIL_IMON, dt.dt_mon); 183 bus_space_write_1(bt, bh, INTERSIL_IDAY, dt.dt_day); 184 bus_space_write_1(bt, bh, INTERSIL_IYEAR, year); 185 bus_space_write_1(bt, bh, INTERSIL_IDOW, dt.dt_wday); 186 187 /* Done writing (time wears on) */ 188 cmd = intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); 189 bus_space_write_1(bt, bh, INTERSIL_ICMD, cmd); 190 splx(s); 191 192 return (0); 193 } 194 195 int 196 intersil7170_getcal(handle, vp) 197 todr_chip_handle_t handle; 198 int *vp; 199 { 200 return (EOPNOTSUPP); 201 } 202 203 int 204 intersil7170_setcal(handle, v) 205 todr_chip_handle_t handle; 206 int v; 207 { 208 return (EOPNOTSUPP); 209 } 210