1 /* $NetBSD: m41st84.c,v 1.35 2026/06/23 21:59:18 rkujawa Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Steve C. Woodford and Jason R. Thorpe 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: m41st84.c,v 1.35 2026/06/23 21:59:18 rkujawa Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/device.h> 44 #include <sys/kernel.h> 45 #include <sys/fcntl.h> 46 #include <sys/uio.h> 47 #include <sys/conf.h> 48 #include <sys/event.h> 49 50 #include <dev/clock_subr.h> 51 52 #include <dev/i2c/i2cvar.h> 53 #include <dev/i2c/m41st84reg.h> 54 #include <dev/i2c/m41st84var.h> 55 56 #include "ioconf.h" 57 58 struct strtc_model { 59 uint16_t sm_model; 60 uint8_t sm_nvram_start; 61 uint8_t sm_nvram_size; 62 uint32_t sm_flags; 63 }; 64 65 #define STRTC_F_HAS_WDOG __BIT(0) /* watchdog register present */ 66 #define STRTC_F_YEAR_2000 __BIT(1) /* year epoch is 2000, not 1970 */ 67 #define STRTC_F_OSC_FAIL_OF __BIT(2) /* M41T6x: OF flag, no HT bit */ 68 69 static const struct strtc_model m41t62_model = { 70 .sm_model = 62, 71 .sm_flags = STRTC_F_YEAR_2000 | STRTC_F_OSC_FAIL_OF, 72 }; 73 74 static const struct strtc_model m41t80_model = { 75 .sm_model = 80, 76 }; 77 78 static const struct strtc_model m41t81_model = { 79 .sm_model = 81, 80 .sm_flags = STRTC_F_HAS_WDOG, 81 }; 82 83 static const struct strtc_model m48t84_model = { 84 .sm_model = 84, 85 .sm_nvram_start = M41ST84_USER_RAM, 86 .sm_nvram_size = M41ST84_USER_RAM_SIZE, 87 .sm_flags = STRTC_F_HAS_WDOG, 88 }; 89 90 static const struct device_compatible_entry compat_data[] = { 91 { .compat = "st,m41t62", .data = &m41t62_model }, 92 { .compat = "st,m41t80", .data = &m41t80_model }, 93 { .compat = "st,m41t81", .data = &m41t81_model }, 94 { .compat = "st,m41t84", .data = &m48t84_model }, 95 DEVICE_COMPAT_EOL 96 }; 97 98 struct strtc_softc { 99 device_t sc_dev; 100 i2c_tag_t sc_tag; 101 int sc_address; 102 int sc_open; 103 const struct strtc_model *sc_model; 104 struct todr_chip_handle sc_todr; 105 }; 106 107 static void strtc_attach(device_t, device_t, void *); 108 static int strtc_match(device_t, cfdata_t, void *); 109 110 CFATTACH_DECL_NEW(strtc, sizeof(struct strtc_softc), 111 strtc_match, strtc_attach, NULL, NULL); 112 113 dev_type_open(strtc_open); 114 dev_type_close(strtc_close); 115 dev_type_read(strtc_read); 116 dev_type_write(strtc_write); 117 118 const struct cdevsw strtc_cdevsw = { 119 .d_open = strtc_open, 120 .d_close = strtc_close, 121 .d_read = strtc_read, 122 .d_write = strtc_write, 123 .d_ioctl = noioctl, 124 .d_stop = nostop, 125 .d_tty = notty, 126 .d_poll = nopoll, 127 .d_mmap = nommap, 128 .d_kqfilter = nokqfilter, 129 .d_discard = nodiscard, 130 .d_flag = D_OTHER 131 }; 132 133 static int strtc_clock_read(struct strtc_softc *sc, struct clock_ymdhms *); 134 static int strtc_clock_write_m41t6x(struct strtc_softc *sc, 135 struct clock_ymdhms *); 136 static int strtc_check_osc_fail(struct strtc_softc *sc, int *); 137 static int strtc_gettime_ymdhms(struct todr_chip_handle *, 138 struct clock_ymdhms *); 139 static int strtc_settime_ymdhms(struct todr_chip_handle *, 140 struct clock_ymdhms *); 141 142 static int 143 strtc_epoch(const struct strtc_softc *sc) 144 { 145 146 return (sc->sc_model->sm_flags & STRTC_F_YEAR_2000) ? 147 2000 : POSIX_BASE_YEAR; 148 } 149 150 static const struct strtc_model * 151 strtc_model_by_number(u_int model) 152 { 153 const struct device_compatible_entry *dce; 154 const struct strtc_model *sm; 155 156 /* no model given; assume it's a 41T80 */ 157 if (model == 0) 158 return &m41t80_model; 159 160 for (dce = compat_data; dce->compat != NULL; dce++) { 161 sm = dce->data; 162 if (sm->sm_model == model) 163 return sm; 164 } 165 return NULL; 166 } 167 168 static const struct strtc_model * 169 strtc_model_by_compat(const struct i2c_attach_args *ia) 170 { 171 const struct device_compatible_entry *dce; 172 const struct strtc_model *sm = NULL; 173 174 if ((dce = iic_compatible_lookup(ia, compat_data)) != NULL) 175 sm = dce->data; 176 177 return sm; 178 } 179 180 static int 181 strtc_match(device_t parent, cfdata_t cf, void *arg) 182 { 183 struct i2c_attach_args *ia = arg; 184 int match_result; 185 186 if (iic_use_direct_match(ia, cf, compat_data, &match_result)) 187 return match_result; 188 189 if (strtc_model_by_number(cf->cf_flags & 0xffff) == NULL) 190 return 0; 191 192 /* indirect config - check typical address */ 193 if (ia->ia_addr == M41ST84_ADDR) 194 return I2C_MATCH_ADDRESS_ONLY; 195 196 return 0; 197 } 198 199 static void 200 strtc_attach(device_t parent, device_t self, void *arg) 201 { 202 struct strtc_softc *sc = device_private(self); 203 struct i2c_attach_args *ia = arg; 204 const struct strtc_model *sm; 205 206 if ((sm = strtc_model_by_compat(ia)) == NULL) 207 sm = strtc_model_by_number(device_cfdata(self)->cf_flags); 208 209 if (sm == NULL) { 210 aprint_error(": unable to determine model!\n"); 211 return; 212 } 213 214 aprint_naive(": Real-time Clock%s\n", 215 sm->sm_nvram_size ? "/NVRAM" : ""); 216 aprint_normal(": M41T%d Real-time Clock%s\n", sm->sm_model, 217 sm->sm_nvram_size ? "/NVRAM" : ""); 218 219 sc->sc_tag = ia->ia_tag; 220 sc->sc_address = ia->ia_addr; 221 sc->sc_model = sm; 222 sc->sc_dev = self; 223 sc->sc_open = 0; 224 sc->sc_todr.todr_dev = self; 225 sc->sc_todr.todr_gettime_ymdhms = strtc_gettime_ymdhms; 226 sc->sc_todr.todr_settime_ymdhms = strtc_settime_ymdhms; 227 228 todr_attach(&sc->sc_todr); 229 } 230 231 /*ARGSUSED*/ 232 int 233 strtc_open(dev_t dev, int flag, int fmt, struct lwp *l) 234 { 235 struct strtc_softc *sc; 236 237 if ((sc = device_lookup_private(&strtc_cd, minor(dev))) == NULL) 238 return (ENXIO); 239 240 /* XXX: Locking */ 241 242 if (sc->sc_open) 243 return (EBUSY); 244 245 sc->sc_open = 1; 246 return (0); 247 } 248 249 /*ARGSUSED*/ 250 int 251 strtc_close(dev_t dev, int flag, int fmt, struct lwp *l) 252 { 253 struct strtc_softc *sc; 254 255 if ((sc = device_lookup_private(&strtc_cd, minor(dev))) == NULL) 256 return (ENXIO); 257 258 sc->sc_open = 0; 259 return (0); 260 } 261 262 /*ARGSUSED*/ 263 int 264 strtc_read(dev_t dev, struct uio *uio, int flags) 265 { 266 struct strtc_softc *sc; 267 u_int8_t ch, cmdbuf[1]; 268 int a, error; 269 270 if ((sc = device_lookup_private(&strtc_cd, minor(dev))) == NULL) 271 return (ENXIO); 272 273 const struct strtc_model * const sm = sc->sc_model; 274 275 if (uio->uio_offset >= sm->sm_nvram_size) 276 return (EINVAL); 277 278 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) 279 return (error); 280 281 while (uio->uio_resid && uio->uio_offset < sm->sm_nvram_size) { 282 a = (int)uio->uio_offset; 283 cmdbuf[0] = a + sm->sm_nvram_start; 284 if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 285 sc->sc_address, cmdbuf, 1, 286 &ch, 1, 0)) != 0) { 287 iic_release_bus(sc->sc_tag, 0); 288 aprint_error_dev(sc->sc_dev, 289 "strtc_read: read failed at 0x%x\n", a); 290 return (error); 291 } 292 if ((error = uiomove(&ch, 1, uio)) != 0) { 293 iic_release_bus(sc->sc_tag, 0); 294 return (error); 295 } 296 } 297 298 iic_release_bus(sc->sc_tag, 0); 299 300 return (0); 301 } 302 303 /*ARGSUSED*/ 304 int 305 strtc_write(dev_t dev, struct uio *uio, int flags) 306 { 307 struct strtc_softc *sc; 308 u_int8_t cmdbuf[2]; 309 int a, error; 310 311 if ((sc = device_lookup_private(&strtc_cd, minor(dev))) == NULL) 312 return (ENXIO); 313 314 const struct strtc_model * const sm = sc->sc_model; 315 316 if (uio->uio_offset >= sm->sm_nvram_size) 317 return (EINVAL); 318 319 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) 320 return (error); 321 322 while (uio->uio_resid && uio->uio_offset < sm->sm_nvram_size) { 323 a = (int)uio->uio_offset; 324 cmdbuf[0] = a + sm->sm_nvram_start; 325 if ((error = uiomove(&cmdbuf[1], 1, uio)) != 0) 326 break; 327 328 if ((error = iic_exec(sc->sc_tag, 329 uio->uio_resid ? I2C_OP_WRITE : I2C_OP_WRITE_WITH_STOP, 330 sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, 0)) != 0) { 331 aprint_error_dev(sc->sc_dev, 332 "strtc_write: write failed at 0x%x\n", a); 333 break; 334 } 335 } 336 337 iic_release_bus(sc->sc_tag, 0); 338 339 return (error); 340 } 341 342 static int 343 strtc_gettime_ymdhms(struct todr_chip_handle *ch, struct clock_ymdhms *dt) 344 { 345 struct strtc_softc *sc = device_private(ch->todr_dev); 346 struct clock_ymdhms check; 347 int retries, error; 348 349 memset(dt, 0, sizeof(*dt)); 350 memset(&check, 0, sizeof(check)); 351 352 if (sc->sc_model->sm_flags & STRTC_F_OSC_FAIL_OF) { 353 int failed; 354 355 if ((error = strtc_check_osc_fail(sc, &failed)) != 0) 356 return error; 357 if (failed) { 358 aprint_error_dev(sc->sc_dev, 359 "oscillator failure, time is not valid\n"); 360 return EIO; 361 } 362 } 363 364 /* 365 * Since we don't support Burst Read, we have to read the clock twice 366 * until we get two consecutive identical results. 367 */ 368 retries = 5; 369 do { 370 if ((error = strtc_clock_read(sc, dt)) == 0) 371 error = strtc_clock_read(sc, &check); 372 if (error) 373 return error; 374 } while (memcmp(dt, &check, sizeof(check)) != 0 && --retries); 375 376 return (0); 377 } 378 379 static int 380 strtc_clock_read(struct strtc_softc *sc, struct clock_ymdhms *dt) 381 { 382 u_int8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[2]; 383 int i, error; 384 385 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) { 386 aprint_error_dev(sc->sc_dev, 387 "strtc_clock_read: failed to acquire I2C bus\n"); 388 return (error); 389 } 390 391 /* 392 * Check for the HT bit -- if set, then clock lost power & stopped 393 * If that happened, then clear the bit so that the clock will have 394 * a chance to run again. The M41T6x has no HT bit (the register 395 * holds an alarm value there), it reports stopped clock via OF. 396 */ 397 if ((sc->sc_model->sm_flags & STRTC_F_OSC_FAIL_OF) == 0) { 398 cmdbuf[0] = M41ST84_REG_AL_HOUR; 399 if ((error = iic_exec(sc->sc_tag, I2C_OP_READ, sc->sc_address, 400 cmdbuf, 1, &cmdbuf[1], 1, 0)) != 0) { 401 iic_release_bus(sc->sc_tag, 0); 402 aprint_error_dev(sc->sc_dev, 403 "strtc_clock_read: failed to read HT\n"); 404 return (error); 405 } 406 if (cmdbuf[1] & M41ST84_AL_HOUR_HT) { 407 cmdbuf[1] &= ~M41ST84_AL_HOUR_HT; 408 if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE, 409 sc->sc_address, cmdbuf, 1, &cmdbuf[1], 410 1, 0)) != 0) { 411 iic_release_bus(sc->sc_tag, 0); 412 aprint_error_dev(sc->sc_dev, 413 "strtc_clock_read: failed to reset HT\n"); 414 return (error); 415 } 416 } 417 } 418 419 /* Read each RTC register in order. */ 420 for (i = M41ST84_REG_CSEC; i < M41ST84_REG_DATE_BYTES; i++) { 421 cmdbuf[0] = i; 422 423 if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 424 sc->sc_address, cmdbuf, 1, 425 &bcd[i], 1, 0)) != 0) { 426 iic_release_bus(sc->sc_tag, 0); 427 aprint_error_dev(sc->sc_dev, 428 "strtc_clock_read: failed to read rtc " 429 "at 0x%x\n", i); 430 return (error); 431 } 432 } 433 434 /* Done with I2C */ 435 iic_release_bus(sc->sc_tag, 0); 436 437 /* 438 * Convert the M41ST84's register values into something useable 439 */ 440 dt->dt_sec = bcdtobin(bcd[M41ST84_REG_SEC] & M41ST84_SEC_MASK); 441 dt->dt_min = bcdtobin(bcd[M41ST84_REG_MIN] & M41ST84_MIN_MASK); 442 dt->dt_hour = bcdtobin(bcd[M41ST84_REG_CENHR] & M41ST84_HOUR_MASK); 443 dt->dt_day = bcdtobin(bcd[M41ST84_REG_DATE] & M41ST84_DATE_MASK); 444 dt->dt_mon = bcdtobin(bcd[M41ST84_REG_MONTH] & M41ST84_MONTH_MASK); 445 446 /* XXX: Should be an MD way to specify EPOCH used by BIOS/Firmware */ 447 /* XXX: Wait, isn't that what rtc_offset in todr_gettime() is for? */ 448 dt->dt_year = bcdtobin(bcd[M41ST84_REG_YEAR]) + strtc_epoch(sc); 449 450 return (0); 451 } 452 453 /* 454 * Check for oscillator fail - M41T6x only 455 */ 456 static int 457 strtc_check_osc_fail(struct strtc_softc *sc, int *failedp) 458 { 459 uint8_t cmdbuf[2]; 460 int error; 461 462 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) { 463 aprint_error_dev(sc->sc_dev, 464 "%s: failed to acquire I2C bus\n", __func__); 465 return error; 466 } 467 468 cmdbuf[0] = M41ST84_REG_FLAGS; 469 error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, 470 cmdbuf, 1, &cmdbuf[1], 1, 0); 471 iic_release_bus(sc->sc_tag, 0); 472 473 if (error) 474 aprint_error_dev(sc->sc_dev, "%s: failed to read flags\n", 475 __func__); 476 else 477 *failedp = (cmdbuf[1] & M41ST84_FLAGS_OF) != 0; 478 479 return error; 480 } 481 482 static int 483 strtc_settime_ymdhms(struct todr_chip_handle *ch, struct clock_ymdhms *dt) 484 { 485 struct strtc_softc *sc = device_private(ch->todr_dev); 486 uint8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[2]; 487 int i, error; 488 489 if (sc->sc_model->sm_flags & STRTC_F_OSC_FAIL_OF) 490 return strtc_clock_write_m41t6x(sc, dt); 491 492 /* 493 * Convert our time representation into something the M41ST84 494 * can understand. 495 */ 496 bcd[M41ST84_REG_CSEC] = bintobcd(0); /* must always write as 0 */ 497 bcd[M41ST84_REG_SEC] = bintobcd(dt->dt_sec); 498 bcd[M41ST84_REG_MIN] = bintobcd(dt->dt_min); 499 bcd[M41ST84_REG_CENHR] = bintobcd(dt->dt_hour); 500 bcd[M41ST84_REG_DATE] = bintobcd(dt->dt_day); 501 bcd[M41ST84_REG_DAY] = bintobcd(dt->dt_wday); 502 bcd[M41ST84_REG_MONTH] = bintobcd(dt->dt_mon); 503 bcd[M41ST84_REG_YEAR] = bintobcd((dt->dt_year - strtc_epoch(sc)) % 100); 504 505 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) { 506 aprint_error_dev(sc->sc_dev, 507 "strtc_clock_write: failed to acquire I2C bus\n"); 508 return (error); 509 } 510 511 /* Stop the clock */ 512 cmdbuf[0] = M41ST84_REG_SEC; 513 cmdbuf[1] = M41ST84_SEC_ST; 514 515 if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, 516 cmdbuf, 1, &cmdbuf[1], 1, 0)) != 0) { 517 iic_release_bus(sc->sc_tag, 0); 518 aprint_error_dev(sc->sc_dev, 519 "strtc_clock_write: failed to Hold Clock\n"); 520 return (error); 521 } 522 523 /* 524 * Check for the HT bit -- if set, then clock lost power & stopped 525 * If that happened, then clear the bit so that the clock will have 526 * a chance to run again. 527 */ 528 cmdbuf[0] = M41ST84_REG_AL_HOUR; 529 if ((error = iic_exec(sc->sc_tag, I2C_OP_READ, sc->sc_address, 530 cmdbuf, 1, &cmdbuf[1], 1, 0)) != 0) { 531 iic_release_bus(sc->sc_tag, 0); 532 aprint_error_dev(sc->sc_dev, 533 "strtc_clock_write: failed to read HT\n"); 534 return (error); 535 } 536 if (cmdbuf[1] & M41ST84_AL_HOUR_HT) { 537 cmdbuf[1] &= ~M41ST84_AL_HOUR_HT; 538 if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, 539 cmdbuf, 1, &cmdbuf[1], 1, 0)) != 0) { 540 iic_release_bus(sc->sc_tag, 0); 541 aprint_error_dev(sc->sc_dev, 542 "strtc_clock_write: failed to reset HT\n"); 543 return (error); 544 } 545 } 546 547 /* 548 * Write registers in reverse order. The last write (to the Seconds 549 * register) will undo the Clock Hold, above. 550 */ 551 for (i = M41ST84_REG_DATE_BYTES - 1; i >= 0; i--) { 552 cmdbuf[0] = i; 553 if ((error = iic_exec(sc->sc_tag, 554 i ? I2C_OP_WRITE : I2C_OP_WRITE_WITH_STOP, 555 sc->sc_address, cmdbuf, 1, &bcd[i], 1, 0)) != 0) { 556 iic_release_bus(sc->sc_tag, 0); 557 aprint_error_dev(sc->sc_dev, 558 "strtc_clock_write: failed to write rtc " 559 " at 0x%x\n", i); 560 /* XXX: Clock Hold is likely still asserted! */ 561 return (error); 562 } 563 } 564 565 iic_release_bus(sc->sc_tag, 0); 566 567 return (0); 568 } 569 570 /* 571 * Set the clock on an M41T6x. Timekeeping registers are buffered. 572 */ 573 static int 574 strtc_clock_write_m41t6x(struct strtc_softc *sc, struct clock_ymdhms *dt) 575 { 576 uint8_t bcd[M41ST84_REG_DATE_BYTES], cur[M41ST84_REG_DATE_BYTES]; 577 uint8_t cmdbuf[1]; 578 int error; 579 580 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) { 581 aprint_error_dev(sc->sc_dev, 582 "%s: failed to acquire I2C bus\n", __func__); 583 return error; 584 } 585 586 cmdbuf[0] = M41ST84_REG_CSEC; 587 if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, 588 cmdbuf, 1, cur, sizeof(cur), 0)) != 0) 589 goto out; 590 591 bcd[M41ST84_REG_CSEC] = 0; /* must always write as 0 */ 592 bcd[M41ST84_REG_SEC] = bintobcd(dt->dt_sec) | 593 (cur[M41ST84_REG_SEC] & M41ST84_SEC_ST); 594 bcd[M41ST84_REG_MIN] = bintobcd(dt->dt_min) | 595 (cur[M41ST84_REG_MIN] & M41ST84_MIN_OFIE); 596 bcd[M41ST84_REG_CENHR] = bintobcd(dt->dt_hour); 597 bcd[M41ST84_REG_DAY] = bintobcd(dt->dt_wday) | 598 (cur[M41ST84_REG_DAY] & M41ST84_DAY_SQW_MASK); 599 bcd[M41ST84_REG_DATE] = bintobcd(dt->dt_day); 600 bcd[M41ST84_REG_MONTH] = bintobcd(dt->dt_mon) | 601 (cur[M41ST84_REG_MONTH] & M41ST84_MONTH_CB_MASK); 602 bcd[M41ST84_REG_YEAR] = bintobcd((dt->dt_year - strtc_epoch(sc)) % 100); 603 604 cmdbuf[0] = M41ST84_REG_CSEC; 605 if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 606 sc->sc_address, cmdbuf, 1, bcd, sizeof(bcd), 0)) != 0) 607 goto out; 608 609 /* 610 * A valid time is now running 611 */ 612 cmdbuf[0] = M41ST84_REG_FLAGS; 613 if ((error = iic_exec(sc->sc_tag, I2C_OP_READ, sc->sc_address, 614 cmdbuf, 1, &bcd[0], 1, 0)) != 0) 615 goto out; 616 if (bcd[0] & M41ST84_FLAGS_OF) { 617 bcd[0] &= ~M41ST84_FLAGS_OF; 618 error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 619 sc->sc_address, cmdbuf, 1, &bcd[0], 1, 0); 620 } 621 622 out: 623 if (error) 624 aprint_error_dev(sc->sc_dev, "%s: failed to set clock\n", 625 __func__); 626 iic_release_bus(sc->sc_tag, 0); 627 return error; 628 } 629 630 void 631 strtc_wdog_config(void *arg, uint8_t wd) 632 { 633 struct strtc_softc *sc = arg; 634 uint8_t cmdbuf[2]; 635 636 if ((sc->sc_model->sm_flags & STRTC_F_HAS_WDOG) == 0) { 637 aprint_error_dev(sc->sc_dev, 638 "strtc_wdog_config: watchdog timer not present\n"); 639 return; 640 } 641 642 if (iic_acquire_bus(sc->sc_tag, 0)) { 643 aprint_error_dev(sc->sc_dev, 644 "strtc_wdog_config: failed to acquire I2C bus\n"); 645 return; 646 } 647 648 cmdbuf[0] = M41ST84_REG_WATCHDOG; 649 cmdbuf[1] = wd; 650 651 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address, 652 cmdbuf, 1, &cmdbuf[1], 1, 0)) { 653 aprint_error_dev(sc->sc_dev, 654 "strtc_wdog_config: failed to write watchdog\n"); 655 return; 656 } 657 658 iic_release_bus(sc->sc_tag, 0); 659 } 660