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 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <sys/conf.h>
28 #include <sys/devops.h>
29 #include <sys/kmem.h>
30 #include <sys/open.h>
31 #include <sys/file.h>
32 #include <sys/note.h>
33 #include <sys/ddi.h>
34 #include <sys/sunddi.h>
35
36 #include <sys/modctl.h>
37 #include <sys/stat.h>
38 #include <sys/clock.h>
39 #include <sys/reboot.h>
40 #include <sys/machsystm.h>
41 #include <sys/poll.h>
42 #include <sys/pbio.h>
43 #include <sys/sysmacros.h>
44
45 /* Added for prom interface */
46 #include <sys/promif.h>
47 #include <sys/promimpl.h>
48
49 #include <sys/i2c/misc/i2c_svc.h>
50 #include <sys/todds1337.h>
51
52 #define DS1337_DEVICE_TYPE "rtc"
53
54 /*
55 * Driver entry routines
56 */
57 static int todds1337_attach(dev_info_t *, ddi_attach_cmd_t);
58 static int todds1337_detach(dev_info_t *, ddi_detach_cmd_t);
59 static int todds1337_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
60
61 /*
62 * tod_ops entry routines
63 */
64 static timestruc_t todds1337_get(void);
65 static void todds1337_set(timestruc_t);
66 static uint_t todds1337_set_watchdog_timer(uint_t);
67 static uint_t todds1337_clear_watchdog_timer(void);
68 static void todds1337_set_power_alarm(timestruc_t);
69 static void todds1337_clear_power_alarm(void);
70 static int todds1337_setup_prom();
71 static void todds1337_rele_prom();
72 static int todds1337_prom_getdate(struct rtc_t *rtc);
73 static int todds1337_prom_setdate(struct rtc_t *rtc);
74
75 /*
76 * Local functions
77 */
78 static int todds1337_read_rtc(struct rtc_t *);
79 static int todds1337_write_rtc(struct rtc_t *);
80
81 /* Anchor for soft state structure */
82 static void *ds1337_statep;
83 static int instance = -1;
84 static int todds1337_attach_done = 0;
85 static kmutex_t todds1337_rd_lock;
86 static kmutex_t todds1337_alarm_lock;
87 static ihandle_t todds1337_ihandle = 0;
88
89 /* one second time out */
90 #define I2C_CYCLIC_TIMEOUT 1000000000
91 uint_t i2c_cyclic_timeout = I2C_CYCLIC_TIMEOUT;
92 static int sync_clock_once = 1;
93 static struct rtc_t soft_rtc;
94
95 /*
96 * cp_ops structure
97 */
98 static struct cb_ops ds1337_cbops = {
99 nodev, /* open */
100 nodev, /* close */
101 nodev, /* strategy */
102 nodev, /* print */
103 nodev, /* dump */
104 nodev, /* read */
105 nodev, /* write */
106 nodev, /* ioctl */
107 nodev, /* devmap */
108 nodev, /* mmap */
109 nodev, /* segmap */
110 NULL, /* poll */
111 ddi_prop_op, /* cb_prop_op */
112 NULL, /* streamtab */
113 D_NEW | D_MP, /* Driver compatibility flag */
114 CB_REV, /* rev */
115 nodev, /* int (*cb_aread)() */
116 nodev /* int (*cb_awrite)() */
117 };
118
119 /*
120 * dev_ops structure
121 */
122 static struct dev_ops ds1337_ops = {
123 DEVO_REV, /* devo_rev */
124 0, /* refcnt - reference cnt always set to 0 */
125 todds1337_getinfo, /* getinfo - Maybe requred */
126 nulldev, /* identify */
127 nulldev, /* probe */
128 todds1337_attach, /* attach */
129 todds1337_detach, /* detach */
130 nodev, /* reset */
131 &ds1337_cbops, /* cb_ops - ds1337 does not need this(?) */
132 NULL, /* bus_ops */
133 NULL, /* power */
134 ddi_quiesce_not_needed, /* quiesce */
135 };
136
137 static struct modldrv todds1337_modldrv = {
138 &mod_driverops, /* Type of module. This one is a driver */
139 "tod driver for DS1337", /* Name of the module. */
140 &ds1337_ops, /* Pointer to dev_ops */
141 };
142
143 /*
144 * Module linkage structure
145 */
146 static struct modlinkage todds1337_modlinkage = {
147 MODREV_1,
148 &todds1337_modldrv,
149 0
150 };
151
152 int
_init(void)153 _init(void)
154 {
155 int error;
156
157 if (strcmp(tod_module_name, "todds1337") == 0) {
158 if ((error = ddi_soft_state_init(&ds1337_statep,
159 sizeof (ds1337_state_t), 0)) != DDI_SUCCESS) {
160 return (error);
161 }
162
163 tod_ops.tod_get = todds1337_get;
164 tod_ops.tod_set = todds1337_set;
165 tod_ops.tod_set_watchdog_timer = todds1337_set_watchdog_timer;
166 tod_ops.tod_clear_watchdog_timer =
167 todds1337_clear_watchdog_timer;
168 tod_ops.tod_set_power_alarm = todds1337_set_power_alarm;
169 tod_ops.tod_clear_power_alarm = todds1337_clear_power_alarm;
170 }
171
172 (void) todds1337_setup_prom();
173
174 /*
175 * Install the module
176 */
177 if ((error = mod_install(&todds1337_modlinkage)) != 0) {
178 if (strcmp(tod_module_name, "todds1337") == 0) {
179 ddi_soft_state_fini(&ds1337_statep);
180 }
181 todds1337_rele_prom();
182 return (error);
183 }
184 mutex_init(&todds1337_rd_lock, NULL, MUTEX_DEFAULT, NULL);
185 mutex_init(&todds1337_alarm_lock, NULL, MUTEX_DEFAULT, NULL);
186
187 return (0);
188 }
189
190 int
_fini(void)191 _fini(void)
192 {
193 int error = 0;
194
195 if (strcmp(tod_module_name, "todds1337") == 0) {
196 error = EBUSY;
197 } else {
198 if ((error = mod_remove(&todds1337_modlinkage)) == 0) {
199 mutex_destroy(&todds1337_rd_lock);
200 mutex_destroy(&todds1337_alarm_lock);
201 todds1337_rele_prom();
202 }
203 }
204
205 return (error);
206 }
207
208 int
_info(struct modinfo * modinfop)209 _info(struct modinfo *modinfop)
210 {
211 return (mod_info(&todds1337_modlinkage, modinfop));
212 }
213
214 /*
215 * cyclical call to get tod.
216 */
217 static void
todds1337_cyclic(void * arg)218 todds1337_cyclic(void *arg)
219 {
220
221 (void) todds1337_read_rtc((struct rtc_t *)arg);
222
223 }
224
225 /*
226 * register ds1337 client device with i2c services, and
227 * allocate & initialize soft state structure.
228 */
229 static int
todds1337_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)230 todds1337_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
231 {
232 static ds1337_state_t *statep = NULL;
233 i2c_transfer_t *i2c_tp = NULL;
234 uint8_t tempVal = (uint8_t)0;
235 switch (cmd) {
236 case DDI_ATTACH:
237 break;
238 case DDI_RESUME:
239 return (DDI_SUCCESS);
240 default:
241 return (DDI_FAILURE);
242 }
243
244 if (instance != -1) {
245 cmn_err(CE_WARN, "todds1337_attach: wrong instance");
246 return (DDI_FAILURE);
247 }
248
249 instance = ddi_get_instance(dip);
250
251 /*
252 * Allocate soft state structure
253 */
254 if (ddi_soft_state_zalloc(ds1337_statep, instance) != DDI_SUCCESS) {
255 cmn_err(CE_WARN, "todds1337_attach: cannot allocate soft "
256 "state");
257 instance = -1;
258 return (DDI_FAILURE);
259 }
260
261 statep = ddi_get_soft_state(ds1337_statep, instance);
262 if (statep == NULL) {
263 cmn_err(CE_WARN, "todds1337_attach: cannot acquire soft "
264 "state");
265 instance = -1;
266 return (DDI_FAILURE);
267 }
268
269 statep->dip = dip;
270
271 if (i2c_client_register(dip, &statep->ds1337_i2c_hdl) != I2C_SUCCESS) {
272 ddi_soft_state_free(ds1337_statep, instance);
273 cmn_err(CE_WARN, "todds1337_attach: cannot register i2c "
274 "client");
275 instance = -1;
276 return (DDI_FAILURE);
277 }
278
279 /* check and initialize the oscillator */
280
281 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl,
282 &i2c_tp, 1, 1, I2C_SLEEP);
283 i2c_tp->i2c_version = I2C_XFER_REV;
284 i2c_tp->i2c_flags = I2C_WR_RD;
285 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_STATUS; /* Read Status register */
286 i2c_tp->i2c_wlen = 1;
287 i2c_tp->i2c_rlen = 1;
288
289 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp)) != I2C_SUCCESS) {
290 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
291 i2c_client_unregister(statep->ds1337_i2c_hdl);
292 ddi_soft_state_free(ds1337_statep, instance);
293 cmn_err(CE_WARN, "todds1337_attach: failed to read DS1337 "
294 "status register");
295 instance = -1;
296 return (DDI_FAILURE);
297 }
298
299 tempVal = i2c_tp->i2c_rbuf[0];
300
301 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
302
303 /*
304 * Check Oscillator and initialize chip if OBP failed to do it
305 */
306
307 if (tempVal & RTC_CTL_EOSC) {
308 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl, &i2c_tp,
309 2, 0, I2C_SLEEP);
310 i2c_tp->i2c_version = I2C_XFER_REV;
311 i2c_tp->i2c_flags = I2C_WR;
312 i2c_tp->i2c_wbuf[0] = RTC_CTL; /* Write Control register */
313 i2c_tp->i2c_wbuf[1] = (uchar_t)(RTC_CTL_RS2 | RTC_CTL_RS1 |
314 RTC_CTL_INTCN);
315 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp))
316 != I2C_SUCCESS) {
317 (void) i2c_transfer_free(statep->ds1337_i2c_hdl,
318 i2c_tp);
319 i2c_client_unregister(statep->ds1337_i2c_hdl);
320 ddi_soft_state_free(ds1337_statep, instance);
321 cmn_err(CE_WARN, "todds1337_attach: failed to write "
322 "DS1337 control register");
323 instance = -1;
324 return (DDI_FAILURE);
325 }
326
327 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
328
329 /*
330 * Now reset the OSF flag in the Status register
331 */
332 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl, &i2c_tp,
333 2, 0, I2C_SLEEP);
334 i2c_tp->i2c_version = I2C_XFER_REV;
335 i2c_tp->i2c_flags = I2C_WR;
336 i2c_tp->i2c_wbuf[0] = RTC_STATUS;
337 i2c_tp->i2c_wbuf[1] = (uchar_t)0;
338 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp))
339 != I2C_SUCCESS) {
340 (void) i2c_transfer_free(statep->ds1337_i2c_hdl,
341 i2c_tp);
342 i2c_client_unregister(statep->ds1337_i2c_hdl);
343 ddi_soft_state_free(ds1337_statep, instance);
344 cmn_err(CE_WARN, "todds1337_attach: failed to write "
345 "DS1337 status register");
346 instance = -1;
347 return (DDI_FAILURE);
348 }
349
350 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
351 }
352
353 /*
354 * Create a periodical handler to read TOD.
355 */
356 ASSERT(statep->cycid == NULL);
357 statep->cycid = ddi_periodic_add(todds1337_cyclic, &soft_rtc,
358 i2c_cyclic_timeout, DDI_IPL_1);
359 statep->state = TOD_ATTACHED;
360 todds1337_attach_done = 1;
361 ddi_report_dev(dip);
362
363 return (DDI_SUCCESS);
364 }
365
366 /*ARGSUSED*/
367 static int
todds1337_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)368 todds1337_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
369 {
370 /*
371 * Once attached, do not allow detach because the system constantly
372 * calling todds1337_get() to get the time. If the driver is detached
373 * and the system try to get the time, the system will have memory
374 * problem.
375 *
376 */
377 switch (cmd) {
378 case DDI_SUSPEND:
379 return (DDI_SUCCESS);
380 default:
381 return (DDI_FAILURE);
382 }
383 }
384
385 /* *********************** tod_ops entry points ******************** */
386
387 /*
388 * Read the current time from the DS1337 chip and convert to UNIX form.
389 * Should be called with tod_lock held.
390 */
391
392 static timestruc_t
todds1337_get(void)393 todds1337_get(void)
394 {
395 timestruc_t ts;
396 todinfo_t tod;
397 struct rtc_t rtc;
398
399 ASSERT(MUTEX_HELD(&tod_lock));
400
401 if (sync_clock_once) {
402 (void) todds1337_read_rtc(&soft_rtc);
403 sync_clock_once = 0;
404 } else {
405 tod_status_set(TOD_GET_FAILED);
406 return (hrestime);
407 }
408
409 bcopy(&soft_rtc, &rtc, sizeof (rtc));
410
411 /*
412 * 00 - 68 = 2000 thru 2068
413 * 69-99 = 1969 thru 1999
414 */
415 tod.tod_year = rtc.rtc_year;
416 if (rtc.rtc_year <= 68)
417 tod.tod_year += 100;
418 tod.tod_month = rtc.rtc_mon;
419 tod.tod_day = rtc.rtc_dom;
420 tod.tod_dow = rtc.rtc_dow;
421 tod.tod_hour = rtc.rtc_hrs;
422 tod.tod_min = rtc.rtc_min;
423 tod.tod_sec = rtc.rtc_sec;
424
425 /* read was successful so ensure failure flag is clear */
426 tod_status_clear(TOD_GET_FAILED);
427
428 ts.tv_sec = tod_to_utc(tod);
429 ts.tv_nsec = 0;
430 return (ts);
431 }
432
433 /*
434 * Program DS1337 with the specified time.
435 * Must be called with tod_lock held. The TOD
436 * chip supports date from 1969-2068 only. We must
437 * reject requests to set date below 1969.
438 */
439 static void
todds1337_set(timestruc_t ts)440 todds1337_set(timestruc_t ts)
441 {
442 struct rtc_t rtc;
443 todinfo_t tod = utc_to_tod(ts.tv_sec);
444 int year;
445
446
447 ASSERT(MUTEX_HELD(&tod_lock));
448
449 /*
450 * Year is base 1900, valid year range 1969-2068
451 */
452 if ((tod.tod_year < 69) || (tod.tod_year > 168))
453 return;
454
455 year = tod.tod_year;
456 if (year >= 100)
457 year -= 100;
458
459 rtc.rtc_year = (uint8_t)year;
460 rtc.rtc_mon = (uint8_t)tod.tod_month;
461 rtc.rtc_dom = (uint8_t)tod.tod_day;
462 rtc.rtc_dow = (uint8_t)tod.tod_dow;
463 rtc.rtc_hrs = (uint8_t)tod.tod_hour;
464 rtc.rtc_min = (uint8_t)tod.tod_min;
465 rtc.rtc_sec = (uint8_t)tod.tod_sec;
466
467 (void) todds1337_write_rtc(&rtc);
468 }
469
470 /*
471 * Program ds1337 registers for alarm to go off at the specified time.
472 * Alarm #1 is used (Alarm #2 stays idle)
473 */
474 /* ARGSUSED */
475 static void
todds1337_set_power_alarm(timestruc_t ts)476 todds1337_set_power_alarm(timestruc_t ts)
477 {
478 todinfo_t tod;
479 ds1337_state_t *statep = NULL;
480 i2c_transfer_t *i2c_tp = NULL;
481 uint8_t tmpval;
482
483 ASSERT(MUTEX_HELD(&tod_lock));
484
485 if (!todds1337_attach_done) {
486 cmn_err(CE_WARN, "todds1337: driver not attached");
487 return;
488 }
489
490 statep = ddi_get_soft_state(ds1337_statep, instance);
491 if (statep == NULL) {
492 cmn_err(CE_WARN, "todds1337: ddi_get_soft_state failed");
493 return;
494 }
495
496 tod = utc_to_tod(ts.tv_sec);
497
498 /*
499 * i2c_transfe() may block; to avoid locking clock() which
500 * is running in interrupt context at PIL10 we temporarely exit
501 * the tod_mutex and enter alarm lock. Time/date and alarm hardware
502 * have non-interlsecting registers, it is safe to use different locks.
503 */
504 mutex_exit(&tod_lock);
505 mutex_enter(&todds1337_alarm_lock);
506
507 /*
508 * Disable Power Alarm (A1IE)
509 */
510 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl,
511 &i2c_tp, 1, 1, I2C_SLEEP);
512 i2c_tp->i2c_version = I2C_XFER_REV;
513 i2c_tp->i2c_flags = I2C_WR_RD;
514 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_CTL; /* Read Control register */
515
516 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp)) != I2C_SUCCESS) {
517 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
518 cmn_err(CE_WARN, "todds1337_set_power_alarm: failed to read "
519 "DS1337 control register");
520 mutex_exit(&todds1337_alarm_lock);
521 mutex_enter(&tod_lock);
522 return;
523 }
524
525 tmpval = i2c_tp->i2c_rbuf[0];
526
527 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
528
529 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl,
530 &i2c_tp, 2, 0, I2C_SLEEP);
531 i2c_tp->i2c_version = I2C_XFER_REV;
532 i2c_tp->i2c_flags = I2C_WR;
533 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_CTL; /* Write Control register */
534 i2c_tp->i2c_wbuf[1] = tmpval & ~RTC_CTL_A1IE;
535
536 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp)) != I2C_SUCCESS) {
537 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
538 cmn_err(CE_WARN, "todds1337_set_power_alarm: failed to write "
539 "DS1337control register");
540 mutex_exit(&todds1337_alarm_lock);
541 mutex_enter(&tod_lock);
542 return;
543 }
544
545 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
546
547
548 /*
549 * Write Alarm #1 registers
550 */
551
552 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl,
553 &i2c_tp, 5, 0, I2C_SLEEP);
554 i2c_tp->i2c_version = I2C_XFER_REV;
555 i2c_tp->i2c_flags = I2C_WR;
556 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_ALARM_SEC; /* Alarm #1 Seconds */
557 i2c_tp->i2c_wbuf[1] = BYTE_TO_BCD(tod.tod_sec);
558 i2c_tp->i2c_wbuf[2] = BYTE_TO_BCD(tod.tod_min);
559 i2c_tp->i2c_wbuf[3] = BYTE_TO_BCD(tod.tod_hour);
560 i2c_tp->i2c_wbuf[4] = BYTE_TO_BCD(tod.tod_day);
561
562 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp)) != I2C_SUCCESS) {
563 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
564 cmn_err(CE_WARN, "todds1337_set_power_alarm: failed to write "
565 "DS1337 alarm registers");
566 mutex_exit(&todds1337_alarm_lock);
567 mutex_enter(&tod_lock);
568 return;
569 }
570
571 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
572
573
574 /*
575 * Enable Power Alarm
576 */
577 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl,
578 &i2c_tp, 2, 0, I2C_SLEEP);
579 i2c_tp->i2c_version = I2C_XFER_REV;
580 i2c_tp->i2c_flags = I2C_WR;
581 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_CTL; /* Write Control register */
582 i2c_tp->i2c_wbuf[1] = tmpval | RTC_CTL_A1IE;
583
584 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp)) != I2C_SUCCESS) {
585 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
586 cmn_err(CE_WARN, "todds1337_set_power_alarm: failed to enable "
587 "DS1337 alarm");
588 mutex_exit(&todds1337_alarm_lock);
589 mutex_enter(&tod_lock);
590 return;
591 }
592
593 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
594
595 mutex_exit(&todds1337_alarm_lock);
596 mutex_enter(&tod_lock);
597 }
598
599 /* ARGSUSED */
600 static void
todds1337_clear_power_alarm(void)601 todds1337_clear_power_alarm(void)
602 {
603 ds1337_state_t *statep = NULL;
604 i2c_transfer_t *i2c_tp = NULL;
605 uint8_t tmpval;
606
607 ASSERT(MUTEX_HELD(&tod_lock));
608
609 if (!todds1337_attach_done) {
610 cmn_err(CE_WARN, "todds1337: driver was not attached");
611 return;
612 }
613
614 statep = ddi_get_soft_state(ds1337_statep, instance);
615 if (statep == NULL) {
616 cmn_err(CE_WARN, "todds1337: ddi_get_soft_state has failed");
617 return;
618 }
619
620 /*
621 * i2c_transfe() may block; to avoid locking clock() which
622 * is running in interrupt context at PIL10 we temporarely exit
623 * the tod_mutex and enter alarm lock. Time/date and alarm hardware
624 * have non-interlsecting registers, it is safe to use different locks.
625 */
626 mutex_exit(&tod_lock);
627 mutex_enter(&todds1337_alarm_lock);
628
629 /*
630 * Disable Alarm #1 Interrupt
631 */
632 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl,
633 &i2c_tp, 1, 1, I2C_SLEEP);
634 i2c_tp->i2c_version = I2C_XFER_REV;
635 i2c_tp->i2c_flags = I2C_WR_RD;
636 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_CTL; /* Read Control register */
637
638 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp)) != I2C_SUCCESS) {
639 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
640 cmn_err(CE_WARN, "todds1337_clear_power_alarm: failed to read "
641 "DS1337 control register");
642 mutex_exit(&todds1337_alarm_lock);
643 mutex_enter(&tod_lock);
644 return;
645 }
646
647 tmpval = i2c_tp->i2c_rbuf[0];
648
649 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
650
651 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl,
652 &i2c_tp, 2, 0, I2C_SLEEP);
653 i2c_tp->i2c_version = I2C_XFER_REV;
654 i2c_tp->i2c_flags = I2C_WR;
655 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_CTL; /* Write Control register */
656 i2c_tp->i2c_wbuf[1] = tmpval & ~RTC_CTL_A1IE;
657
658 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp)) != I2C_SUCCESS) {
659 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
660 cmn_err(CE_WARN, "todds1337_clear_power_alarm: failed to write "
661 "DS1337 control register");
662 mutex_exit(&todds1337_alarm_lock);
663 mutex_enter(&tod_lock);
664 return;
665 }
666
667 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
668
669 /*
670 * Reset Alarm #1 Flag
671 */
672 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl,
673 &i2c_tp, 1, 1, I2C_SLEEP);
674 i2c_tp->i2c_version = I2C_XFER_REV;
675 i2c_tp->i2c_flags = I2C_WR_RD;
676 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_STATUS; /* Read Status register */
677
678 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp)) != I2C_SUCCESS) {
679 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
680 cmn_err(CE_WARN, "todds1337_clear_power_alarm: failed to read "
681 "DS1337 status register");
682 mutex_exit(&todds1337_alarm_lock);
683 mutex_enter(&tod_lock);
684 return;
685 }
686
687 tmpval = i2c_tp->i2c_rbuf[0];
688
689 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
690
691 (void) i2c_transfer_alloc(statep->ds1337_i2c_hdl,
692 &i2c_tp, 2, 0, I2C_SLEEP);
693 i2c_tp->i2c_version = I2C_XFER_REV;
694 i2c_tp->i2c_flags = I2C_WR;
695 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_STATUS; /* Write Status register */
696 i2c_tp->i2c_wbuf[1] = tmpval & ~RTC_STATUS_A1F;
697
698 if ((i2c_transfer(statep->ds1337_i2c_hdl, i2c_tp)) != I2C_SUCCESS) {
699 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
700 cmn_err(CE_WARN, "todds1337_clear_power_alarm: failed to write "
701 "DS1337 status register");
702 mutex_exit(&todds1337_alarm_lock);
703 mutex_enter(&tod_lock);
704 return;
705 }
706
707 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
708
709 mutex_exit(&todds1337_alarm_lock);
710 mutex_enter(&tod_lock);
711 }
712
713 /* ARGSUSED */
714 static uint_t
todds1337_set_watchdog_timer(uint_t timeoutval)715 todds1337_set_watchdog_timer(uint_t timeoutval)
716 {
717 ASSERT(MUTEX_HELD(&tod_lock));
718 return (0);
719 }
720
721 /* ARGSUSED */
722 static uint_t
todds1337_clear_watchdog_timer(void)723 todds1337_clear_watchdog_timer(void)
724 {
725 ASSERT(MUTEX_HELD(&tod_lock));
726 return (0);
727 }
728
729 /* ********************** Local functions ***************************** */
730
731 static char tod_read[7] = {-1, -1, -1, -1, -1, -1, -1};
732 static int
todds1337_read_rtc(struct rtc_t * rtc)733 todds1337_read_rtc(struct rtc_t *rtc)
734 {
735 static ds1337_state_t *statep = NULL;
736 i2c_transfer_t *i2c_tp = NULL;
737 int i2c_cmd_status = I2C_FAILURE;
738 int counter = 4;
739
740 if (!todds1337_attach_done) {
741 return (todds1337_prom_getdate(rtc));
742 }
743
744 statep = ddi_get_soft_state(ds1337_statep, instance);
745 if (statep == NULL) {
746 cmn_err(CE_WARN, "todds1337: ddi_get_soft_state failing");
747 return (DDI_FAILURE);
748 }
749
750 mutex_enter(&todds1337_rd_lock);
751
752 /*
753 * Allocate 1 byte for write buffer and 7 bytes for read buffer to
754 * to accomodate sec, min, hrs, dayOfWeek, dayOfMonth, year
755 */
756 if ((i2c_transfer_alloc(statep->ds1337_i2c_hdl, &i2c_tp, 1,
757 7, I2C_SLEEP)) != I2C_SUCCESS) {
758 mutex_exit(&todds1337_rd_lock);
759 return (DDI_FAILURE);
760 }
761
762 do {
763 i2c_tp->i2c_version = I2C_XFER_REV;
764 i2c_tp->i2c_flags = I2C_WR_RD;
765 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_SEC; /* Start from 0x00 */
766 i2c_tp->i2c_wlen = 1; /* Write one byte address */
767 i2c_tp->i2c_rlen = 7; /* Read 7 regs */
768
769 if ((i2c_cmd_status = i2c_transfer(statep->ds1337_i2c_hdl,
770 i2c_tp)) != I2C_SUCCESS) {
771 goto done;
772 }
773 /* for first read, need to get valid data */
774 while (tod_read[0] == -1 && counter > 0) {
775 /* move data to static buffer */
776 bcopy(i2c_tp->i2c_rbuf, tod_read, 7);
777
778 /* now read again */
779 /* Start reading reg from 0x00 */
780 i2c_tp->i2c_wbuf[0] = (uchar_t)0x00;
781 i2c_tp->i2c_wlen = 1; /* Write one byte address */
782 i2c_tp->i2c_rlen = 7; /* Read 7 regs */
783 if ((i2c_cmd_status = i2c_transfer(statep->ds1337_i2c_hdl,
784 i2c_tp)) != I2C_SUCCESS) {
785 goto done;
786 }
787 /* if they are not the same, then read again */
788 if (bcmp(tod_read, i2c_tp->i2c_rbuf, 7) != 0) {
789 tod_read[0] = -1;
790 counter--;
791 }
792 }
793
794 } while (i2c_tp->i2c_rbuf[0] == 0x59 &&
795 /* if seconds register is 0x59 (BCD), add data should match */
796 bcmp(&tod_read[1], &i2c_tp->i2c_rbuf[1], 6) != 0 &&
797 counter-- > 0);
798
799 if (counter < 0)
800 cmn_err(CE_WARN, "i2ctod: TOD Chip failed ??");
801
802 /* move data to static buffer */
803 bcopy(i2c_tp->i2c_rbuf, tod_read, 7);
804
805
806 rtc->rtc_year = BCD_TO_BYTE(i2c_tp->i2c_rbuf[6]);
807 rtc->rtc_mon = BCD_TO_BYTE(i2c_tp->i2c_rbuf[5]);
808 rtc->rtc_dom = BCD_TO_BYTE(i2c_tp->i2c_rbuf[4]);
809 rtc->rtc_dow = BCD_TO_BYTE(i2c_tp->i2c_rbuf[3]);
810 rtc->rtc_hrs = BCD_TO_BYTE(i2c_tp->i2c_rbuf[2]);
811 rtc->rtc_min = BCD_TO_BYTE(i2c_tp->i2c_rbuf[1]);
812 rtc->rtc_sec = BCD_TO_BYTE(i2c_tp->i2c_rbuf[0]);
813
814 done:
815 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
816
817 mutex_exit(&todds1337_rd_lock);
818 return (i2c_cmd_status);
819 }
820
821
822 static int
todds1337_write_rtc(struct rtc_t * rtc)823 todds1337_write_rtc(struct rtc_t *rtc)
824 {
825 ds1337_state_t *statep = NULL;
826 i2c_transfer_t *i2c_tp = NULL;
827 int i2c_cmd_status = I2C_SUCCESS;
828
829
830 if (!todds1337_attach_done) {
831 return (todds1337_prom_setdate(rtc));
832 }
833
834 statep = ddi_get_soft_state(ds1337_statep, instance);
835 if (statep == NULL) {
836 return (DDI_FAILURE);
837 }
838
839 if ((i2c_cmd_status = i2c_transfer_alloc(statep->ds1337_i2c_hdl,
840 &i2c_tp, 8, 0, I2C_SLEEP)) != I2C_SUCCESS) {
841 return (i2c_cmd_status);
842 }
843
844 i2c_tp->i2c_version = I2C_XFER_REV;
845 i2c_tp->i2c_flags = I2C_WR;
846 i2c_tp->i2c_wbuf[0] = (uchar_t)RTC_SEC;
847 i2c_tp->i2c_wbuf[1] = BYTE_TO_BCD(rtc->rtc_sec);
848 i2c_tp->i2c_wbuf[2] = BYTE_TO_BCD(rtc->rtc_min);
849 i2c_tp->i2c_wbuf[3] = BYTE_TO_BCD(rtc->rtc_hrs);
850 i2c_tp->i2c_wbuf[4] = BYTE_TO_BCD(rtc->rtc_dow);
851 i2c_tp->i2c_wbuf[5] = BYTE_TO_BCD(rtc->rtc_dom);
852 i2c_tp->i2c_wbuf[6] = BYTE_TO_BCD(rtc->rtc_mon);
853 i2c_tp->i2c_wbuf[7] = BYTE_TO_BCD(rtc->rtc_year);
854 i2c_tp->i2c_wlen = 8;
855
856 if ((i2c_cmd_status = i2c_transfer(statep->ds1337_i2c_hdl,
857 i2c_tp)) != I2C_SUCCESS) {
858 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
859 return (i2c_cmd_status);
860 }
861
862 tod_read[0] = -1; /* invalidate saved data from read routine */
863
864 (void) i2c_transfer_free(statep->ds1337_i2c_hdl, i2c_tp);
865
866 return (i2c_cmd_status);
867 }
868
869
870 /*ARGSUSED*/
871 static int
todds1337_getinfo(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)872 todds1337_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
873 void **result)
874 {
875 ds1337_state_t *softsp;
876
877 if (instance == -1) {
878 return (DDI_FAILURE);
879 }
880
881 switch (infocmd) {
882 case DDI_INFO_DEVT2DEVINFO:
883 if ((softsp = ddi_get_soft_state(ds1337_statep, instance)) ==
884 NULL)
885 return (DDI_FAILURE);
886 *result = (void *)softsp->dip;
887 return (DDI_SUCCESS);
888 case DDI_INFO_DEVT2INSTANCE:
889 *result = (void *)(uintptr_t)instance;
890 return (DDI_SUCCESS);
891 default:
892 return (DDI_FAILURE);
893 }
894 }
895
896 /*
897 * Finds the device node with device_type "rtc" and opens it to
898 * execute the get-time method
899 */
900 static int
todds1337_setup_prom()901 todds1337_setup_prom()
902 {
903 pnode_t todnode;
904 char tod1337_devpath[MAXNAMELEN];
905
906 if ((todnode = prom_findnode_bydevtype(prom_rootnode(),
907 DS1337_DEVICE_TYPE)) == OBP_NONODE)
908 return (DDI_FAILURE);
909
910 /*
911 * We now have the phandle of the rtc node, we need to open the
912 * node and get the ihandle
913 */
914 if (prom_phandle_to_path(todnode, tod1337_devpath,
915 sizeof (tod1337_devpath)) < 0) {
916 cmn_err(CE_WARN, "prom_phandle_to_path failed");
917 return (DDI_FAILURE);
918 }
919
920 /*
921 * Now open the node and store it's ihandle
922 */
923 if ((todds1337_ihandle = prom_open(tod1337_devpath)) == NULL) {
924 cmn_err(CE_WARN, "prom_open failed");
925 return (DDI_FAILURE);
926 }
927
928 return (DDI_SUCCESS);
929 }
930
931 /*
932 * Closes the prom interface
933 */
934 static void
todds1337_rele_prom()935 todds1337_rele_prom()
936 {
937 (void) prom_close(todds1337_ihandle);
938 }
939
940 /*
941 * Read the date using "get-time" method in rtc node
942 * PROM returns 1969-1999 when reading 69-99 and
943 * 2000-2068 when reading 00-68
944 */
945 static int
todds1337_prom_getdate(struct rtc_t * rtc)946 todds1337_prom_getdate(struct rtc_t *rtc)
947 {
948 int year;
949 cell_t ci[12];
950
951 ci[0] = p1275_ptr2cell("call-method"); /* Service name */
952 ci[1] = 2; /* # of arguments */
953 ci[2] = 7; /* # of result cells */
954 ci[3] = p1275_ptr2cell("get-time");
955 ci[4] = p1275_ihandle2cell(todds1337_ihandle);
956
957 promif_preprom();
958 (void) p1275_cif_handler(&ci);
959 promif_postprom();
960
961 year = p1275_cell2int(ci[6]);
962 rtc->rtc_mon = p1275_cell2int(ci[7]);
963 rtc->rtc_dom = p1275_cell2int(ci[8]);
964 rtc->rtc_dow = 0;
965 rtc->rtc_hrs = p1275_cell2int(ci[9]);
966 rtc->rtc_min = p1275_cell2int(ci[10]);
967 rtc->rtc_sec = p1275_cell2int(ci[11]);
968 if (year >= 2000)
969 year -= 2000;
970 else
971 year -= 1900;
972 rtc->rtc_year = year;
973
974 return (DDI_SUCCESS);
975 }
976
977 /*
978 * Read the date using "set-time" method in rtc node
979 * For values 00 - 68, write 2000-2068, and for 69-99,
980 * write 1969-1999
981 */
982 static int
todds1337_prom_setdate(struct rtc_t * rtc)983 todds1337_prom_setdate(struct rtc_t *rtc)
984 {
985 int year;
986 cell_t ci[12];
987
988 year = rtc->rtc_year;
989
990 if ((year < 0) || (year > 99))
991 return (DDI_FAILURE);
992
993 if (year <= 68)
994 year = rtc->rtc_year + 2000;
995 else
996 year = rtc->rtc_year + 1900;
997
998 ci[0] = p1275_ptr2cell("call-method"); /* Service name */
999 ci[1] = 8; /* # of arguments */
1000 ci[2] = 0; /* # of result cells */
1001 ci[3] = p1275_ptr2cell("set-time");
1002 ci[4] = p1275_ihandle2cell(todds1337_ihandle);
1003 ci[5] = p1275_int2cell(year);
1004 ci[6] = p1275_int2cell(rtc->rtc_mon);
1005 ci[7] = p1275_int2cell(rtc->rtc_dom);
1006 ci[8] = p1275_int2cell(rtc->rtc_hrs);
1007 ci[9] = p1275_int2cell(rtc->rtc_min);
1008 ci[10] = p1275_int2cell(rtc->rtc_sec);
1009
1010 promif_preprom();
1011 (void) p1275_cif_handler(&ci);
1012 promif_postprom();
1013
1014 return (DDI_SUCCESS);
1015 }
1016