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