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