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