1 1.3 thorpej /* $NetBSD: rtc.c,v 1.3 2025/09/07 21:45:13 thorpej Exp $ */ 2 1.1 mrg 3 1.1 mrg /* 4 1.1 mrg * Copyright 2002 Wasabi Systems, Inc. 5 1.1 mrg * All rights reserved. 6 1.1 mrg * 7 1.1 mrg * Written by Simon Burge for Wasabi Systems, Inc. 8 1.1 mrg * 9 1.1 mrg * Redistribution and use in source and binary forms, with or without 10 1.1 mrg * modification, are permitted provided that the following conditions 11 1.1 mrg * are met: 12 1.1 mrg * 1. Redistributions of source code must retain the above copyright 13 1.1 mrg * notice, this list of conditions and the following disclaimer. 14 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 mrg * notice, this list of conditions and the following disclaimer in the 16 1.1 mrg * documentation and/or other materials provided with the distribution. 17 1.1 mrg * 3. All advertising materials mentioning features or use of this software 18 1.1 mrg * must display the following acknowledgement: 19 1.1 mrg * This product includes software developed for the NetBSD Project by 20 1.1 mrg * Wasabi Systems, Inc. 21 1.1 mrg * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 1.1 mrg * or promote products derived from this software without specific prior 23 1.1 mrg * written permission. 24 1.1 mrg * 25 1.1 mrg * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 1.1 mrg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 1.1 mrg * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 1.1 mrg * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 1.1 mrg * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 1.1 mrg * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 1.1 mrg * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 1.1 mrg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 1.1 mrg * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 1.1 mrg * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 1.1 mrg * POSSIBILITY OF SUCH DAMAGE. 36 1.1 mrg */ 37 1.1 mrg 38 1.1 mrg #include <sys/cdefs.h> 39 1.3 thorpej __KERNEL_RCSID(0, "$NetBSD: rtc.c,v 1.3 2025/09/07 21:45:13 thorpej Exp $"); 40 1.1 mrg 41 1.1 mrg #include <sys/param.h> 42 1.1 mrg #include <sys/device.h> 43 1.1 mrg #include <sys/kernel.h> 44 1.1 mrg #include <sys/systm.h> 45 1.1 mrg #include <sys/cpu.h> 46 1.1 mrg 47 1.1 mrg #include <dev/clock_subr.h> 48 1.1 mrg 49 1.2 mrg #include <evbmips/sbmips/swarm.h> 50 1.2 mrg #include <evbmips/sbmips/systemsw.h> 51 1.1 mrg 52 1.1 mrg #include <mips/locore.h> 53 1.1 mrg #include <mips/sibyte/dev/sbsmbusvar.h> 54 1.1 mrg 55 1.1 mrg #include <dev/smbus/m41t81reg.h> 56 1.1 mrg #include <dev/smbus/x1241reg.h> 57 1.1 mrg 58 1.1 mrg struct rtc_softc { 59 1.1 mrg device_t sc_dev; 60 1.1 mrg int sc_smbus_chan; 61 1.1 mrg int sc_smbus_addr; 62 1.1 mrg int sc_type; 63 1.1 mrg struct todr_chip_handle sc_ct; 64 1.1 mrg }; 65 1.1 mrg 66 1.1 mrg /* "types" for RTCs we support */ 67 1.1 mrg #define SMB_1BYTE_ADDR 1 68 1.1 mrg #define SMB_2BYTE_ADDR 2 69 1.1 mrg 70 1.1 mrg static int xirtc_match(device_t, cfdata_t , void *); 71 1.1 mrg static void xirtc_attach(device_t, device_t, void *); 72 1.1 mrg static int xirtc_gettime(todr_chip_handle_t, struct clock_ymdhms *); 73 1.1 mrg static int xirtc_settime(todr_chip_handle_t, struct clock_ymdhms *); 74 1.1 mrg 75 1.1 mrg static int strtc_match(device_t, cfdata_t , void *); 76 1.1 mrg static void strtc_attach(device_t, device_t, void *); 77 1.1 mrg static int strtc_gettime(todr_chip_handle_t, struct clock_ymdhms *); 78 1.1 mrg static int strtc_settime(todr_chip_handle_t, struct clock_ymdhms *); 79 1.1 mrg 80 1.1 mrg static void rtc_cal_timer(void); 81 1.1 mrg 82 1.1 mrg static void time_smbus_init(int); 83 1.1 mrg static int time_waitready(int); 84 1.1 mrg static int time_readrtc(int, int, int, int); 85 1.1 mrg static int time_writertc(int, int, int, int, int); 86 1.1 mrg 87 1.1 mrg #define WRITERTC(sc, dev, val) \ 88 1.1 mrg time_writertc((sc)->sc_smbus_chan, (sc)->sc_smbus_addr, (dev), (sc)->sc_type, (val)) 89 1.1 mrg #define READRTC(sc, dev) \ 90 1.1 mrg time_readrtc((sc)->sc_smbus_chan, (sc)->sc_smbus_addr, (dev), (sc)->sc_type) 91 1.1 mrg 92 1.1 mrg 93 1.1 mrg CFATTACH_DECL_NEW(xirtc, sizeof(struct rtc_softc), 94 1.1 mrg xirtc_match, xirtc_attach, NULL, NULL); 95 1.1 mrg 96 1.1 mrg CFATTACH_DECL_NEW(m41t81rtc, sizeof(struct rtc_softc), 97 1.1 mrg strtc_match, strtc_attach, NULL, NULL); 98 1.1 mrg 99 1.1 mrg static int rtcfound = 0; 100 1.1 mrg struct rtc_softc *the_rtc; 101 1.1 mrg 102 1.1 mrg /* 103 1.1 mrg * Xicor X1241 RTC support. 104 1.1 mrg */ 105 1.1 mrg static int 106 1.1 mrg xirtc_match(device_t parent, cfdata_t cf, void *aux) 107 1.1 mrg { 108 1.1 mrg struct smbus_attach_args *sa = aux; 109 1.1 mrg int ret; 110 1.1 mrg 111 1.1 mrg time_smbus_init(sa->sa_interface); 112 1.1 mrg 113 1.1 mrg if ((sa->sa_interface != X1241_SMBUS_CHAN) || 114 1.1 mrg (sa->sa_device != X1241_RTC_SLAVEADDR)) 115 1.1 mrg return (0); 116 1.1 mrg 117 1.1 mrg ret = time_readrtc(sa->sa_interface, sa->sa_device, SMB_2BYTE_ADDR, X1241REG_SC); 118 1.1 mrg if (ret < 0) 119 1.1 mrg return (0); 120 1.1 mrg 121 1.1 mrg return (!rtcfound); 122 1.1 mrg } 123 1.1 mrg 124 1.1 mrg static void 125 1.1 mrg xirtc_attach(device_t parent, device_t self, void *aux) 126 1.1 mrg { 127 1.1 mrg struct smbus_attach_args *sa = aux; 128 1.1 mrg struct rtc_softc *sc = device_private(self); 129 1.1 mrg 130 1.1 mrg rtcfound = 1; 131 1.1 mrg the_rtc = sc; 132 1.1 mrg 133 1.1 mrg sc->sc_dev = self; 134 1.1 mrg sc->sc_smbus_chan = sa->sa_interface; 135 1.1 mrg sc->sc_smbus_addr = sa->sa_device; 136 1.1 mrg sc->sc_type = SMB_2BYTE_ADDR; /* Two-byte register addresses on the Xicor */ 137 1.1 mrg 138 1.1 mrg 139 1.1 mrg /* Set up MI todr(9) stuff */ 140 1.3 thorpej sc->sc_ct.todr_dev = self; 141 1.1 mrg sc->sc_ct.todr_settime_ymdhms = xirtc_settime; 142 1.1 mrg sc->sc_ct.todr_gettime_ymdhms = xirtc_gettime; 143 1.1 mrg 144 1.1 mrg todr_attach(&sc->sc_ct); 145 1.1 mrg 146 1.1 mrg aprint_normal("\n"); 147 1.1 mrg rtc_cal_timer(); /* XXX */ 148 1.1 mrg } 149 1.1 mrg 150 1.1 mrg static int 151 1.1 mrg xirtc_settime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) 152 1.1 mrg { 153 1.3 thorpej struct rtc_softc *sc = device_private(handle->todr_dev); 154 1.1 mrg uint8_t year, y2k; 155 1.1 mrg 156 1.1 mrg time_smbus_init(sc->sc_smbus_chan); 157 1.1 mrg 158 1.1 mrg /* unlock writes to the CCR */ 159 1.1 mrg WRITERTC(sc, X1241REG_SR, X1241REG_SR_WEL); 160 1.1 mrg WRITERTC(sc, X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); 161 1.1 mrg 162 1.1 mrg /* set the time */ 163 1.1 mrg WRITERTC(sc, X1241REG_HR, bintobcd(ymdhms->dt_hour) | X1241REG_HR_MIL); 164 1.1 mrg WRITERTC(sc, X1241REG_MN, bintobcd(ymdhms->dt_min)); 165 1.1 mrg WRITERTC(sc, X1241REG_SC, bintobcd(ymdhms->dt_sec)); 166 1.1 mrg 167 1.1 mrg /* set the date */ 168 1.1 mrg y2k = (ymdhms->dt_year >= 2000) ? 0x20 : 0x19; 169 1.1 mrg year = ymdhms->dt_year % 100; 170 1.1 mrg 171 1.1 mrg WRITERTC(sc, X1241REG_MO, bintobcd(ymdhms->dt_mon)); 172 1.1 mrg WRITERTC(sc, X1241REG_DT, bintobcd(ymdhms->dt_day)); 173 1.1 mrg WRITERTC(sc, X1241REG_YR, bintobcd(year)); 174 1.1 mrg WRITERTC(sc, X1241REG_Y2K, bintobcd(y2k)); 175 1.1 mrg 176 1.1 mrg /* lock writes again */ 177 1.1 mrg WRITERTC(sc, X1241REG_SR, 0); 178 1.1 mrg 179 1.1 mrg return (0); 180 1.1 mrg } 181 1.1 mrg 182 1.1 mrg static int 183 1.1 mrg xirtc_gettime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) 184 1.1 mrg { 185 1.3 thorpej struct rtc_softc *sc = device_private(handle->todr_dev); 186 1.1 mrg uint8_t hour, year, y2k; 187 1.1 mrg uint8_t status; 188 1.1 mrg 189 1.1 mrg time_smbus_init(sc->sc_smbus_chan); 190 1.1 mrg ymdhms->dt_day = bcdtobin(READRTC(sc, X1241REG_DT)); 191 1.1 mrg ymdhms->dt_mon = bcdtobin(READRTC(sc, X1241REG_MO)); 192 1.1 mrg year = READRTC(sc, X1241REG_YR); 193 1.1 mrg y2k = READRTC(sc, X1241REG_Y2K); 194 1.1 mrg ymdhms->dt_year = bcdtobin(y2k) * 100 + bcdtobin(year); 195 1.1 mrg 196 1.1 mrg 197 1.1 mrg ymdhms->dt_sec = bcdtobin(READRTC(sc, X1241REG_SC)); 198 1.1 mrg ymdhms->dt_min = bcdtobin(READRTC(sc, X1241REG_MN)); 199 1.1 mrg hour = READRTC(sc, X1241REG_HR); 200 1.1 mrg ymdhms->dt_hour = bcdtobin(hour & ~X1241REG_HR_MIL); 201 1.1 mrg 202 1.1 mrg status = READRTC(sc, X1241REG_SR); 203 1.1 mrg 204 1.1 mrg if (status & X1241REG_SR_RTCF) { 205 1.1 mrg printf("%s: battery has failed, clock setting is not accurate\n", 206 1.1 mrg device_xname(sc->sc_dev)); 207 1.1 mrg return (EIO); 208 1.1 mrg } 209 1.1 mrg 210 1.1 mrg return (0); 211 1.1 mrg } 212 1.1 mrg 213 1.1 mrg /* 214 1.1 mrg * ST M41T81 RTC support. 215 1.1 mrg */ 216 1.1 mrg static int 217 1.1 mrg strtc_match(device_t parent, cfdata_t cf, void *aux) 218 1.1 mrg { 219 1.1 mrg struct smbus_attach_args *sa = aux; 220 1.1 mrg int ret; 221 1.1 mrg 222 1.1 mrg if ((sa->sa_interface != M41T81_SMBUS_CHAN) || 223 1.1 mrg (sa->sa_device != M41T81_SLAVEADDR)) 224 1.1 mrg return (0); 225 1.1 mrg 226 1.1 mrg time_smbus_init(sa->sa_interface); 227 1.1 mrg 228 1.1 mrg ret = time_readrtc(sa->sa_interface, sa->sa_device, SMB_1BYTE_ADDR, M41T81_SEC); 229 1.1 mrg if (ret < 0) 230 1.1 mrg return (0); 231 1.1 mrg 232 1.1 mrg return (!rtcfound); 233 1.1 mrg } 234 1.1 mrg 235 1.1 mrg static void 236 1.1 mrg strtc_attach(device_t parent, device_t self, void *aux) 237 1.1 mrg { 238 1.1 mrg struct smbus_attach_args *sa = aux; 239 1.1 mrg struct rtc_softc *sc = device_private(self); 240 1.1 mrg 241 1.1 mrg rtcfound = 1; 242 1.1 mrg the_rtc = sc; 243 1.1 mrg 244 1.1 mrg sc->sc_dev = self; 245 1.1 mrg sc->sc_smbus_chan = sa->sa_interface; 246 1.1 mrg sc->sc_smbus_addr = sa->sa_device; 247 1.1 mrg sc->sc_type = SMB_1BYTE_ADDR; /* One-byte register addresses on the ST */ 248 1.1 mrg 249 1.1 mrg /* Set up MI todr(9) stuff */ 250 1.3 thorpej sc->sc_ct.todr_dev = self; 251 1.1 mrg sc->sc_ct.todr_settime_ymdhms = strtc_settime; 252 1.1 mrg sc->sc_ct.todr_gettime_ymdhms = strtc_gettime; 253 1.1 mrg 254 1.1 mrg todr_attach(&sc->sc_ct); 255 1.1 mrg 256 1.1 mrg aprint_normal("\n"); 257 1.1 mrg rtc_cal_timer(); /* XXX */ 258 1.1 mrg } 259 1.1 mrg 260 1.1 mrg static int 261 1.1 mrg strtc_settime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) 262 1.1 mrg { 263 1.3 thorpej struct rtc_softc *sc = device_private(handle->todr_dev); 264 1.1 mrg uint8_t hour; 265 1.1 mrg 266 1.1 mrg time_smbus_init(sc->sc_smbus_chan); 267 1.1 mrg 268 1.1 mrg hour = bintobcd(ymdhms->dt_hour); 269 1.1 mrg if (ymdhms->dt_year >= 2000) /* Should be always true! */ 270 1.1 mrg hour |= M41T81_HOUR_CB | M41T81_HOUR_CEB; 271 1.1 mrg 272 1.1 mrg /* set the time */ 273 1.1 mrg WRITERTC(sc, M41T81_SEC, bintobcd(ymdhms->dt_sec)); 274 1.1 mrg WRITERTC(sc, M41T81_MIN, bintobcd(ymdhms->dt_min)); 275 1.1 mrg WRITERTC(sc, M41T81_HOUR, hour); 276 1.1 mrg 277 1.1 mrg /* set the date */ 278 1.1 mrg WRITERTC(sc, M41T81_DATE, bintobcd(ymdhms->dt_day)); 279 1.1 mrg WRITERTC(sc, M41T81_MON, bintobcd(ymdhms->dt_mon)); 280 1.1 mrg WRITERTC(sc, M41T81_YEAR, bintobcd(ymdhms->dt_year % 100)); 281 1.1 mrg 282 1.1 mrg return (0); 283 1.1 mrg } 284 1.1 mrg 285 1.1 mrg static int 286 1.1 mrg strtc_gettime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) 287 1.1 mrg { 288 1.3 thorpej struct rtc_softc *sc = device_private(handle->todr_dev); 289 1.1 mrg uint8_t hour; 290 1.1 mrg 291 1.1 mrg time_smbus_init(sc->sc_smbus_chan); 292 1.1 mrg 293 1.1 mrg ymdhms->dt_sec = bcdtobin(READRTC(sc, M41T81_SEC)); 294 1.1 mrg ymdhms->dt_min = bcdtobin(READRTC(sc, M41T81_MIN)); 295 1.1 mrg hour = READRTC(sc, M41T81_HOUR & M41T81_HOUR_MASK); 296 1.1 mrg ymdhms->dt_hour = bcdtobin(hour & M41T81_HOUR_MASK); 297 1.1 mrg 298 1.1 mrg ymdhms->dt_day = bcdtobin(READRTC(sc, M41T81_DATE)); 299 1.1 mrg ymdhms->dt_mon = bcdtobin(READRTC(sc, M41T81_MON)); 300 1.1 mrg ymdhms->dt_year = 1900 + bcdtobin(READRTC(sc, M41T81_YEAR)); 301 1.1 mrg if (hour & M41T81_HOUR_CB) 302 1.1 mrg ymdhms->dt_year += 100; 303 1.1 mrg 304 1.1 mrg return (0); 305 1.1 mrg } 306 1.1 mrg 307 1.1 mrg #define NITERS 3 308 1.1 mrg #define RTC_SECONDS(rtc) bcdtobin(READRTC((rtc), X1241REG_SC)) 309 1.1 mrg 310 1.1 mrg /* 311 1.1 mrg * Since it takes so long to read the complete time/date values from 312 1.1 mrg * the RTC over the SMBus, we only read the seconds value. 313 1.1 mrg * Later versions of the SWARM will hopefully have the RTC interrupt 314 1.1 mrg * attached so we can do the clock calibration much more quickly and 315 1.1 mrg * with a higher resolution. 316 1.1 mrg */ 317 1.1 mrg static void 318 1.1 mrg rtc_cal_timer(void) 319 1.1 mrg { 320 1.1 mrg uint32_t ctrdiff[NITERS], startctr, endctr; 321 1.1 mrg int sec, lastsec, i; 322 1.1 mrg 323 1.1 mrg if (rtcfound == 0) { 324 1.1 mrg printf("rtc_cal_timer before rtc attached\n"); 325 1.1 mrg return; 326 1.1 mrg } 327 1.1 mrg return; /* XXX XXX */ 328 1.1 mrg 329 1.1 mrg printf("%s: calibrating CPU clock", device_xname(the_rtc->sc_dev)); 330 1.1 mrg 331 1.1 mrg /* 332 1.1 mrg * Run the loop an extra time to wait for the second to tick over 333 1.1 mrg * and to prime the cache. 334 1.1 mrg */ 335 1.1 mrg time_smbus_init(the_rtc->sc_smbus_chan); 336 1.1 mrg sec = RTC_SECONDS(the_rtc); 337 1.1 mrg endctr = mips3_cp0_count_read(); 338 1.1 mrg 339 1.1 mrg for (i = 0; i < NITERS; i++) { 340 1.1 mrg int diff; 341 1.1 mrg 342 1.1 mrg again: 343 1.1 mrg lastsec = sec; 344 1.1 mrg startctr = endctr; 345 1.1 mrg 346 1.1 mrg /* Wait for the timer to tick over. */ 347 1.1 mrg do { 348 1.1 mrg // time_smbus_init(the_rtc->sc_smbus_chan); 349 1.1 mrg sec = RTC_SECONDS(the_rtc); 350 1.1 mrg } while (lastsec == sec); 351 1.1 mrg endctr = mips3_cp0_count_read(); 352 1.1 mrg 353 1.1 mrg diff = sec - lastsec; 354 1.1 mrg if (diff < 0) 355 1.1 mrg diff += 60; 356 1.1 mrg 357 1.1 mrg /* Sometimes we appear to skip a second. Clock jitter? */ 358 1.1 mrg if (diff > 1) 359 1.1 mrg goto again; 360 1.1 mrg 361 1.1 mrg if (endctr < startctr) 362 1.1 mrg ctrdiff[i] = 0xffffffff - startctr + endctr; 363 1.1 mrg else 364 1.1 mrg ctrdiff[i] = endctr - startctr; 365 1.1 mrg } 366 1.1 mrg printf("\n"); 367 1.1 mrg 368 1.1 mrg /* Compute the number of cycles per second. */ 369 1.1 mrg curcpu()->ci_cpu_freq = ((ctrdiff[1] + ctrdiff[2]) / 2); 370 1.1 mrg 371 1.1 mrg /* Compute the delay divisor. */ 372 1.1 mrg curcpu()->ci_divisor_delay = curcpu()->ci_cpu_freq / 1000000; 373 1.1 mrg 374 1.1 mrg /* Compute clock cycles per hz */ 375 1.1 mrg curcpu()->ci_cycles_per_hz = curcpu()->ci_cpu_freq / hz; 376 1.1 mrg 377 1.1 mrg printf("%s: timer calibration: %lu cycles/sec [(%u, %u)]\n", 378 1.1 mrg device_xname(the_rtc->sc_dev), curcpu()->ci_cpu_freq, 379 1.1 mrg ctrdiff[1], ctrdiff[2]); 380 1.1 mrg } 381 1.1 mrg #undef RTC_SECONDS 382 1.1 mrg 383 1.1 mrg /* XXX eville direct-access-to-the-device code follows... */ 384 1.1 mrg 385 1.1 mrg /* 386 1.1 mrg * Copyright 2000,2001 387 1.1 mrg * Broadcom Corporation. All rights reserved. 388 1.1 mrg * 389 1.1 mrg * This software is furnished under license and may be used and copied only 390 1.1 mrg * in accordance with the following terms and conditions. Subject to these 391 1.1 mrg * conditions, you may download, copy, install, use, modify and distribute 392 1.1 mrg * modified or unmodified copies of this software in source and/or binary 393 1.1 mrg * form. No title or ownership is transferred hereby. 394 1.1 mrg * 395 1.1 mrg * 1) Any source code used, modified or distributed must reproduce and 396 1.1 mrg * retain this copyright notice and list of conditions as they appear in 397 1.1 mrg * the source file. 398 1.1 mrg * 399 1.1 mrg * 2) No right is granted to use any trade name, trademark, or logo of 400 1.1 mrg * Broadcom Corporation. The "Broadcom Corporation" name may not be 401 1.1 mrg * used to endorse or promote products derived from this software 402 1.1 mrg * without the prior written permission of Broadcom Corporation. 403 1.1 mrg * 404 1.1 mrg * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 405 1.1 mrg * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 406 1.1 mrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 407 1.1 mrg * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 408 1.1 mrg * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 409 1.1 mrg * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 410 1.1 mrg * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 411 1.1 mrg * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 412 1.1 mrg * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 413 1.1 mrg * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 414 1.1 mrg * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 415 1.1 mrg */ 416 1.1 mrg 417 1.1 mrg #include <mips/sibyte/include/sb1250_regs.h> 418 1.1 mrg #include <mips/sibyte/include/sb1250_smbus.h> 419 1.1 mrg 420 1.1 mrg #define READ_REG(rp) mips3_ld((register_t)(MIPS_PHYS_TO_KSEG1(rp))) 421 1.1 mrg #define WRITE_REG(rp, val) mips3_sd((register_t)(MIPS_PHYS_TO_KSEG1(rp)), (val)) 422 1.1 mrg 423 1.1 mrg static void 424 1.1 mrg time_smbus_init(int chan) 425 1.1 mrg { 426 1.1 mrg uint32_t reg; 427 1.1 mrg 428 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_FREQ); 429 1.1 mrg WRITE_REG(reg, K_SMB_FREQ_100KHZ); 430 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_CONTROL); 431 1.1 mrg WRITE_REG(reg, 0); /* not in direct mode, no interrupts, will poll */ 432 1.1 mrg } 433 1.1 mrg 434 1.1 mrg static int 435 1.1 mrg time_waitready(int chan) 436 1.1 mrg { 437 1.1 mrg uint32_t reg; 438 1.1 mrg uint64_t status; 439 1.1 mrg 440 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_STATUS); 441 1.1 mrg 442 1.1 mrg for (;;) { 443 1.1 mrg status = READ_REG(reg); 444 1.1 mrg if (status & M_SMB_BUSY) 445 1.1 mrg continue; 446 1.1 mrg break; 447 1.1 mrg } 448 1.1 mrg 449 1.1 mrg if (status & M_SMB_ERROR) { 450 1.1 mrg WRITE_REG(reg, (status & M_SMB_ERROR)); 451 1.1 mrg return (-1); 452 1.1 mrg } 453 1.1 mrg return (0); 454 1.1 mrg } 455 1.1 mrg 456 1.1 mrg static int 457 1.1 mrg time_readrtc(int chan, int slaveaddr, int devaddr, int type) 458 1.1 mrg { 459 1.1 mrg uint32_t reg; 460 1.1 mrg int err; 461 1.1 mrg 462 1.1 mrg /* 463 1.1 mrg * Make sure the bus is idle (probably should 464 1.1 mrg * ignore error here) 465 1.1 mrg */ 466 1.1 mrg 467 1.1 mrg if (time_waitready(chan) < 0) 468 1.1 mrg return (-1); 469 1.1 mrg 470 1.1 mrg if (type == SMB_2BYTE_ADDR) { 471 1.1 mrg /* 472 1.1 mrg * Write the device address to the controller. There are two 473 1.1 mrg * parts, the high part goes in the "CMD" field, and the 474 1.1 mrg * low part is the data field. 475 1.1 mrg */ 476 1.1 mrg 477 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_CMD); 478 1.1 mrg WRITE_REG(reg, (devaddr >> 8) & 0x7); 479 1.1 mrg 480 1.1 mrg /* 481 1.1 mrg * Write the data to the controller 482 1.1 mrg */ 483 1.1 mrg 484 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_DATA); 485 1.1 mrg WRITE_REG(reg, (devaddr & 0xff) & 0xff); 486 1.1 mrg } else { /* SMB_1BYTE_ADDR */ 487 1.1 mrg /* 488 1.1 mrg * Write the device address to the controller. 489 1.1 mrg */ 490 1.1 mrg 491 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_CMD); 492 1.1 mrg WRITE_REG(reg, devaddr & 0xff); 493 1.1 mrg } 494 1.1 mrg 495 1.1 mrg /* 496 1.1 mrg * Start the command 497 1.1 mrg */ 498 1.1 mrg 499 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_START); 500 1.1 mrg if (type == SMB_2BYTE_ADDR) 501 1.1 mrg WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR2BYTE) | V_SMB_ADDR(slaveaddr)); 502 1.1 mrg else /* SMB_1BYTE_ADDR */ 503 1.1 mrg WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR1BYTE) | V_SMB_ADDR(slaveaddr)); 504 1.1 mrg 505 1.1 mrg /* 506 1.1 mrg * Wait till done 507 1.1 mrg */ 508 1.1 mrg 509 1.1 mrg err = time_waitready(chan); 510 1.1 mrg if (err < 0) 511 1.1 mrg return (err); 512 1.1 mrg 513 1.1 mrg /* 514 1.1 mrg * Read the data byte 515 1.1 mrg */ 516 1.1 mrg 517 1.1 mrg WRITE_REG(reg, V_SMB_TT(K_SMB_TT_RD1BYTE) | V_SMB_ADDR(slaveaddr)); 518 1.1 mrg 519 1.1 mrg err = time_waitready(chan); 520 1.1 mrg if (err < 0) 521 1.1 mrg return (err); 522 1.1 mrg 523 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_DATA); 524 1.1 mrg err = READ_REG(reg); 525 1.1 mrg 526 1.1 mrg return (err & 0xff); 527 1.1 mrg } 528 1.1 mrg 529 1.1 mrg static int 530 1.1 mrg time_writertc(int chan, int slaveaddr, int devaddr, int type, int b) 531 1.1 mrg { 532 1.1 mrg uint32_t reg; 533 1.1 mrg int err, timer; 534 1.1 mrg 535 1.1 mrg /* 536 1.1 mrg * Make sure the bus is idle (probably should 537 1.1 mrg * ignore error here) 538 1.1 mrg */ 539 1.1 mrg 540 1.1 mrg if (time_waitready(chan) < 0) 541 1.1 mrg return (-1); 542 1.1 mrg 543 1.1 mrg /* 544 1.1 mrg * Write the device address to the controller. There are two 545 1.1 mrg * parts, the high part goes in the "CMD" field, and the 546 1.1 mrg * low part is the data field. 547 1.1 mrg */ 548 1.1 mrg 549 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_CMD); 550 1.1 mrg if (type == SMB_2BYTE_ADDR) 551 1.1 mrg WRITE_REG(reg, (devaddr >> 8) & 0x7); 552 1.1 mrg else /* SMB_1BYTE_ADDR */ 553 1.1 mrg WRITE_REG(reg, devaddr & 0xff); 554 1.1 mrg 555 1.1 mrg /* 556 1.1 mrg * Write the data to the controller 557 1.1 mrg */ 558 1.1 mrg 559 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_DATA); 560 1.1 mrg if (type == SMB_2BYTE_ADDR) 561 1.1 mrg WRITE_REG(reg, (devaddr & 0xff) | ((b & 0xff) << 8)); 562 1.1 mrg else /* SMB_1BYTE_ADDR */ 563 1.1 mrg WRITE_REG(reg, b & 0xff); 564 1.1 mrg 565 1.1 mrg /* 566 1.1 mrg * Start the command. Keep pounding on the device until it 567 1.1 mrg * submits or the timer expires, whichever comes first. The 568 1.1 mrg * datasheet says writes can take up to 10ms, so we'll give it 500. 569 1.1 mrg */ 570 1.1 mrg 571 1.1 mrg reg = A_SMB_REGISTER(chan, R_SMB_START); 572 1.1 mrg if (type == SMB_2BYTE_ADDR) 573 1.1 mrg WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR3BYTE) | V_SMB_ADDR(slaveaddr)); 574 1.1 mrg else /* SMB_1BYTE_ADDR */ 575 1.1 mrg WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR2BYTE) | V_SMB_ADDR(slaveaddr)); 576 1.1 mrg 577 1.1 mrg /* 578 1.1 mrg * Wait till the SMBus interface is done 579 1.1 mrg */ 580 1.1 mrg 581 1.1 mrg err = time_waitready(chan); 582 1.1 mrg if (err < 0) 583 1.1 mrg return (err); 584 1.1 mrg 585 1.1 mrg /* 586 1.1 mrg * Pound on the device with a current address read 587 1.1 mrg * to poll for the write complete 588 1.1 mrg */ 589 1.1 mrg 590 1.1 mrg err = -1; 591 1.1 mrg timer = 100000000; /* XXX */ 592 1.1 mrg 593 1.1 mrg while (timer-- > 0) { 594 1.1 mrg WRITE_REG(reg, V_SMB_TT(K_SMB_TT_RD1BYTE) | V_SMB_ADDR(slaveaddr)); 595 1.1 mrg 596 1.1 mrg err = time_waitready(chan); 597 1.1 mrg if (err == 0) 598 1.1 mrg break; 599 1.1 mrg } 600 1.1 mrg 601 1.1 mrg return (err); 602 1.1 mrg } 603