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