1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*
29 * tod driver module for TI BQ4802 part
30 *
31 * Note: The way to access the bq4802's RTC registers is different than
32 * the previous RTC devices (m5823, m5819p, ds1287, etc) that we used.
33 * The address returns from OBP is mapped directly to the bq4802's RTC
34 * registers. To read/write the data from/to the bq4802 registers, one
35 * just add the register offset to the base address.
36 * To access the previous RTC devices, we write the register index to
37 * the address port (v_rtc_addr_reg) then read/write the data from/to
38 * the data port (v_rtc_data_reg).
39 */
40
41 #include <sys/types.h>
42 #include <sys/conf.h>
43 #include <sys/kmem.h>
44 #include <sys/open.h>
45 #include <sys/ddi.h>
46 #include <sys/sunddi.h>
47 #include <sys/sysmacros.h>
48
49 #include <sys/todbq4802.h>
50 #include <sys/modctl.h>
51 #include <sys/stat.h>
52 #include <sys/clock.h>
53 #include <sys/reboot.h>
54 #include <sys/machsystm.h>
55
56 /*
57 * tod_ops entry routines
58 */
59 static timestruc_t todbq4802_get(void);
60 static void todbq4802_set(timestruc_t);
61 static uint_t todbq4802_set_watchdog_timer(uint_t);
62 static uint_t todbq4802_clear_watchdog_timer(void);
63 static void todbq4802_set_power_alarm(timestruc_t);
64 static void todbq4802_clear_power_alarm(void);
65 static uint64_t todbq4802_get_cpufrequency(void);
66
67 extern uint64_t find_cpufrequency(volatile uint8_t *);
68
69 /*
70 * External variables
71 */
72 extern int watchdog_enable;
73 extern int watchdog_available;
74 extern int boothowto;
75
76 /*
77 * Global variables
78 */
79 int bq4802_debug_flags;
80 uint_t bq4802_hrestime_count = 0;
81 uint_t bq4802_uip_count = 0;
82
83 /*
84 * Module linkage information for the kernel.
85 */
86 static struct modlmisc modlmisc = {
87 &mod_miscops, "tod module for TI BQ4802"
88 };
89
90 static struct modlinkage modlinkage = {
91 MODREV_1, (void *)&modlmisc, NULL
92 };
93
94 static void read_rtc(struct rtc_t *);
95 static void write_rtc_time(struct rtc_t *);
96 static void write_rtc_alarm(struct rtc_t *);
97
98 int
_init(void)99 _init(void)
100 {
101 if (strcmp(tod_module_name, "todbq4802") == 0) {
102 if (v_rtc_addr_reg == NULL)
103 cmn_err(CE_PANIC, "addr not set, cannot read RTC\n");
104
105 BQ4802_DATA_REG(RTC_CNTRL) = (RTC_HM | RTC_STOP_N);
106
107 /* Clear AF flag by reading reg Flags (D) */
108 (void) BQ4802_DATA_REG(RTC_FLAGS);
109
110 tod_ops.tod_get = todbq4802_get;
111 tod_ops.tod_set = todbq4802_set;
112 tod_ops.tod_set_watchdog_timer =
113 todbq4802_set_watchdog_timer;
114 tod_ops.tod_clear_watchdog_timer =
115 todbq4802_clear_watchdog_timer;
116 tod_ops.tod_set_power_alarm = todbq4802_set_power_alarm;
117 tod_ops.tod_clear_power_alarm = todbq4802_clear_power_alarm;
118 tod_ops.tod_get_cpufrequency = todbq4802_get_cpufrequency;
119
120 /*
121 * check if hardware watchdog timer is available and user
122 * enabled it.
123 */
124 if (watchdog_enable) {
125 if (!watchdog_available) {
126 cmn_err(CE_WARN, "bq4802: Hardware watchdog "
127 "unavailable");
128 } else if (boothowto & RB_DEBUG) {
129 cmn_err(CE_WARN, "bq4802: Hardware watchdog"
130 " disabled [debugger]");
131 }
132 }
133 }
134
135 return (mod_install(&modlinkage));
136 }
137
138 int
_fini(void)139 _fini(void)
140 {
141 if (strcmp(tod_module_name, "todbq4802") == 0)
142 return (EBUSY);
143
144 return (mod_remove(&modlinkage));
145 }
146
147 /*
148 * The loadable-module _info(9E) entry point
149 */
150 int
_info(struct modinfo * modinfop)151 _info(struct modinfo *modinfop)
152 {
153 return (mod_info(&modlinkage, modinfop));
154 }
155
156 /*
157 * Read the current time from the clock chip and convert to UNIX form.
158 * Assumes that the year in the clock chip is valid.
159 * Must be called with tod_lock held.
160 */
161 static timestruc_t
todbq4802_get(void)162 todbq4802_get(void)
163 {
164 timestruc_t ts;
165 todinfo_t tod;
166 struct rtc_t rtc;
167
168 ASSERT(MUTEX_HELD(&tod_lock));
169
170 read_rtc(&rtc);
171 DPRINTF("todbq4802_get: century=%d year=%d dom=%d hrs=%d min=%d"
172 " sec=%d\n", rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom,
173 rtc.rtc_hrs, rtc.rtc_min, rtc.rtc_sec);
174
175 /*
176 * tod_year is base 1900 so this code needs to adjust the true
177 * year retrieved from the rtc's century and year fields.
178 */
179 tod.tod_year = rtc.rtc_year + (rtc.rtc_century * 100) - 1900;
180 tod.tod_month = rtc.rtc_mon;
181 tod.tod_day = rtc.rtc_dom;
182 tod.tod_dow = rtc.rtc_dow;
183 tod.tod_hour = rtc.rtc_hrs;
184 tod.tod_min = rtc.rtc_min;
185 tod.tod_sec = rtc.rtc_sec;
186
187 ts.tv_sec = tod_to_utc(tod);
188 ts.tv_nsec = 0;
189 return (ts);
190 }
191
192 /*
193 * Once every second, the user-accessible clock/calendar
194 * locations are updated simultaneously from the internal
195 * real-time counters. To prevent reading data in transition,
196 * updates to the bq4802 clock registers should be halted.
197 * Updating is halted by setting the Update Transfer Inhibit
198 * (UTI) bit D3 of the control register E. As long as the
199 * UTI bit is 1, updates to user-accessible clock locations are
200 * inhibited. Once the frozen clock information is retrieved by
201 * reading the appropriate clock memory locations, the UTI
202 * bit should be reset to 0 in order to allow updates to occur
203 * from the internal counters. Because the internal counters
204 * are not halted by setting the UTI bit, reading the clock
205 * locations has no effect on clock accuracy. Once the UTI bit
206 * is reset to 0, the internal registers update within one
207 * second the user-accessible registers with the correct time.
208 * A halt command issued during a clock update allows the
209 * update to occur before freezing the data.
210 */
211 static void
read_rtc(struct rtc_t * rtc)212 read_rtc(struct rtc_t *rtc)
213 {
214 uint8_t reg_cntrl;
215
216 /*
217 * Freeze
218 */
219 reg_cntrl = BQ4802_DATA_REG(RTC_CNTRL);
220 BQ4802_DATA_REG(RTC_CNTRL) = (reg_cntrl | RTC_UTI);
221
222 rtc->rtc_sec = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_SEC));
223 rtc->rtc_asec = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_ASEC));
224 rtc->rtc_min = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_MIN));
225 rtc->rtc_amin = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_AMIN));
226 rtc->rtc_hrs = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_HRS));
227 rtc->rtc_ahrs = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_AHRS));
228 rtc->rtc_dom = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_DOM));
229 rtc->rtc_adom = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_ADOM));
230 rtc->rtc_dow = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_DOW));
231 rtc->rtc_mon = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_MON));
232 rtc->rtc_year = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_YEAR));
233 rtc->rtc_century = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_CENTURY));
234
235 /*
236 * Unfreeze
237 */
238 BQ4802_DATA_REG(RTC_CNTRL) = reg_cntrl;
239 }
240
241 /*
242 * Write the specified time into the clock chip.
243 * Must be called with tod_lock held.
244 */
245 static void
todbq4802_set(timestruc_t ts)246 todbq4802_set(timestruc_t ts)
247 {
248 struct rtc_t rtc;
249 todinfo_t tod = utc_to_tod(ts.tv_sec);
250 int year;
251
252 ASSERT(MUTEX_HELD(&tod_lock));
253
254 /* tod_year is base 1900 so this code needs to adjust */
255 year = 1900 + tod.tod_year;
256 rtc.rtc_year = year % 100;
257 rtc.rtc_century = year / 100;
258 rtc.rtc_mon = (uint8_t)tod.tod_month;
259 rtc.rtc_dom = (uint8_t)tod.tod_day;
260 rtc.rtc_dow = (uint8_t)tod.tod_dow;
261 rtc.rtc_hrs = (uint8_t)tod.tod_hour;
262 rtc.rtc_min = (uint8_t)tod.tod_min;
263 rtc.rtc_sec = (uint8_t)tod.tod_sec;
264 DPRINTF("todbq4802_set: year=%d dom=%d hrs=%d min=%d sec=%d\n",
265 rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs, rtc.rtc_min, rtc.rtc_sec);
266
267 write_rtc_time(&rtc);
268 }
269
270 /*
271 * The UTI bit must be used to set the bq4802 clock.
272 * Once set, the locations can be written with the desired
273 * information in BCD format. Resetting the UTI bit to 0 causes
274 * the written values to be transferred to the internal clock
275 * counters and allows updates to the user-accessible registers
276 * to resume within one second.
277 */
278 void
write_rtc_time(struct rtc_t * rtc)279 write_rtc_time(struct rtc_t *rtc)
280 {
281 uint8_t reg_cntrl;
282
283 /*
284 * Freeze
285 */
286 reg_cntrl = BQ4802_DATA_REG(RTC_CNTRL);
287 BQ4802_DATA_REG(RTC_CNTRL) = (reg_cntrl | RTC_UTI);
288
289 BQ4802_DATA_REG(RTC_SEC) = BYTE_TO_BCD(rtc->rtc_sec);
290 BQ4802_DATA_REG(RTC_MIN) = BYTE_TO_BCD(rtc->rtc_min);
291 BQ4802_DATA_REG(RTC_HRS) = BYTE_TO_BCD(rtc->rtc_hrs);
292 BQ4802_DATA_REG(RTC_DOM) = BYTE_TO_BCD(rtc->rtc_dom);
293 BQ4802_DATA_REG(RTC_DOW) = BYTE_TO_BCD(rtc->rtc_dow);
294 BQ4802_DATA_REG(RTC_MON) = BYTE_TO_BCD(rtc->rtc_mon);
295 BQ4802_DATA_REG(RTC_YEAR) = BYTE_TO_BCD(rtc->rtc_year);
296 BQ4802_DATA_REG(RTC_CENTURY) = BYTE_TO_BCD(rtc->rtc_century);
297
298 /*
299 * Unfreeze
300 */
301 BQ4802_DATA_REG(RTC_CNTRL) = reg_cntrl;
302 }
303
304 void
write_rtc_alarm(struct rtc_t * rtc)305 write_rtc_alarm(struct rtc_t *rtc)
306 {
307 BQ4802_DATA_REG(RTC_ASEC) = BYTE_TO_BCD(rtc->rtc_asec);
308 BQ4802_DATA_REG(RTC_AMIN) = BYTE_TO_BCD(rtc->rtc_amin);
309 BQ4802_DATA_REG(RTC_AHRS) = BYTE_TO_BCD(rtc->rtc_ahrs);
310 BQ4802_DATA_REG(RTC_ADOM) = BYTE_TO_BCD(rtc->rtc_adom);
311 }
312
313 /*
314 * program the rtc registers for alarm to go off at the specified time
315 */
316 static void
todbq4802_set_power_alarm(timestruc_t ts)317 todbq4802_set_power_alarm(timestruc_t ts)
318 {
319 todinfo_t tod;
320 uint8_t regc;
321 struct rtc_t rtc;
322
323 ASSERT(MUTEX_HELD(&tod_lock));
324 tod = utc_to_tod(ts.tv_sec);
325
326 /*
327 * disable alarms and clear AF flag by reading reg Flags (D)
328 */
329 regc = BQ4802_DATA_REG(RTC_ENABLES);
330 BQ4802_DATA_REG(RTC_ENABLES) = regc & ~(RTC_AIE | RTC_ABE);
331 (void) BQ4802_DATA_REG(RTC_FLAGS);
332
333 rtc.rtc_asec = (uint8_t)tod.tod_sec;
334 rtc.rtc_amin = (uint8_t)tod.tod_min;
335 rtc.rtc_ahrs = (uint8_t)tod.tod_hour;
336 rtc.rtc_adom = (uint8_t)tod.tod_day;
337 DPRINTF("todbq4802_set_alarm: dom=%d hrs=%d min=%d sec=%d\n",
338 rtc.rtc_adom, rtc.rtc_ahrs, rtc.rtc_amin, rtc.rtc_asec);
339
340 /*
341 * Write alarm values and enable alarm
342 */
343 write_rtc_alarm(&rtc);
344
345 BQ4802_DATA_REG(RTC_ENABLES) = regc | RTC_AIE | RTC_ABE;
346 }
347
348 /*
349 * clear alarm interrupt
350 */
351 static void
todbq4802_clear_power_alarm(void)352 todbq4802_clear_power_alarm(void)
353 {
354 uint8_t regc;
355
356 ASSERT(MUTEX_HELD(&tod_lock));
357
358 regc = BQ4802_DATA_REG(RTC_ENABLES);
359 BQ4802_DATA_REG(RTC_ENABLES) = regc & ~(RTC_AIE | RTC_ABE);
360 }
361
362 /*
363 * Determine the cpu frequency by watching the TOD chip rollover twice.
364 * Cpu clock rate is determined by computing the ticks added (in tick register)
365 * during one second interval on TOD.
366 */
367 uint64_t
todbq4802_get_cpufrequency(void)368 todbq4802_get_cpufrequency(void)
369 {
370 ASSERT(MUTEX_HELD(&tod_lock));
371 return (find_cpufrequency((volatile uint8_t *)v_rtc_addr_reg));
372 }
373
374 /*ARGSUSED*/
375 static uint_t
todbq4802_set_watchdog_timer(uint_t timeoutval)376 todbq4802_set_watchdog_timer(uint_t timeoutval)
377 {
378 ASSERT(MUTEX_HELD(&tod_lock));
379 return (0);
380 }
381
382 static uint_t
todbq4802_clear_watchdog_timer(void)383 todbq4802_clear_watchdog_timer(void)
384 {
385 ASSERT(MUTEX_HELD(&tod_lock));
386 return (0);
387 }
388