1 /* $NetBSD: em3027.c,v 1.10 2025/09/07 21:45:15 thorpej Exp $ */ 2 /* 3 * Copyright (c) 2018 Valery Ushakov 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 /* 28 * EM Microelectronic EM3027 RTC 29 */ 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: em3027.c,v 1.10 2025/09/07 21:45:15 thorpej Exp $"); 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/device.h> 36 #include <sys/kernel.h> 37 38 #include <dev/clock_subr.h> 39 40 #include <dev/i2c/i2cvar.h> 41 #include <dev/i2c/em3027reg.h> 42 #include <dev/sysmon/sysmonvar.h> 43 44 #if 0 45 #define aprint_verbose_dev aprint_normal_dev 46 #define aprint_debug_dev aprint_normal_dev 47 #endif 48 49 50 struct em3027rtc_softc { 51 device_t sc_dev; 52 53 i2c_tag_t sc_tag; 54 i2c_addr_t sc_addr; 55 56 bool sc_vlow; 57 58 struct todr_chip_handle sc_todr; 59 60 struct sysmon_envsys *sc_sme; 61 envsys_data_t sc_sensor; 62 }; 63 64 65 #define EM3027_CONTROL_BASE EM3027_ONOFF 66 #define EM3027_WATCH_BASE EM3027_WATCH_SEC 67 68 struct em3027rtc_watch { 69 uint8_t sec; 70 uint8_t min; 71 uint8_t hour; 72 uint8_t day; 73 uint8_t wday; 74 uint8_t mon; 75 uint8_t year; 76 }; 77 78 #define EM3027_WATCH_SIZE (EM3027_WATCH_YEAR - EM3027_WATCH_BASE + 1) 79 __CTASSERT(sizeof(struct em3027rtc_watch) == EM3027_WATCH_SIZE); 80 81 #define EM3027_BASE_YEAR 1980 82 83 84 static int em3027rtc_match(device_t, cfdata_t, void *); 85 static void em3027rtc_attach(device_t, device_t, void *); 86 87 CFATTACH_DECL_NEW(em3027rtc, sizeof(struct em3027rtc_softc), 88 em3027rtc_match, em3027rtc_attach, NULL, NULL); 89 90 91 static bool em3027rtc_enable_thermometer(struct em3027rtc_softc *); 92 static void em3027rtc_envsys_attach(struct em3027rtc_softc *); 93 94 static int em3027rtc_gettime(struct todr_chip_handle *, struct clock_ymdhms *); 95 static int em3027rtc_settime(struct todr_chip_handle *, struct clock_ymdhms *); 96 97 static void em3027rtc_sme_refresh(struct sysmon_envsys *, envsys_data_t *); 98 99 static int em3027rtc_iic_exec(struct em3027rtc_softc *, i2c_op_t, uint8_t, 100 void *, size_t); 101 102 static int em3027rtc_read(struct em3027rtc_softc *, uint8_t, void *, size_t); 103 static int em3027rtc_write(struct em3027rtc_softc *, uint8_t, void *, size_t); 104 105 static int em3027rtc_read_byte(struct em3027rtc_softc *, uint8_t, uint8_t *); 106 static int em3027rtc_write_byte(struct em3027rtc_softc *, uint8_t, uint8_t); 107 108 static const struct device_compatible_entry compat_data[] = { 109 { .compat = "emmicro,em3027" }, 110 DEVICE_COMPAT_EOL 111 }; 112 113 static int 114 em3027rtc_match(device_t parent, cfdata_t cf, void *aux) 115 { 116 const struct i2c_attach_args *ia = aux; 117 uint8_t reg; 118 int error; 119 int match_result; 120 121 if (iic_use_direct_match(ia, cf, compat_data, &match_result)) 122 return match_result; 123 124 if (ia->ia_addr != EM3027_ADDR) 125 return 0; 126 127 /* check if the device is there */ 128 error = iic_acquire_bus(ia->ia_tag, 0); 129 if (error) 130 return 0; 131 132 error = iic_smbus_read_byte(ia->ia_tag, ia->ia_addr, 133 EM3027_ONOFF, ®, 0); 134 iic_release_bus(ia->ia_tag, 0); 135 if (error) 136 return 0; 137 138 return I2C_MATCH_ADDRESS_AND_PROBE; 139 } 140 141 142 static void 143 em3027rtc_attach(device_t parent, device_t self, void *aux) 144 { 145 struct em3027rtc_softc *sc = device_private(self); 146 const struct i2c_attach_args *ia = aux; 147 struct ctl { 148 uint8_t onoff; 149 uint8_t irq_ctl; 150 uint8_t irq_flags; 151 uint8_t status; 152 } ctl; 153 int error; 154 155 aprint_naive(": Real-time Clock and Temperature Sensor\n"); 156 aprint_normal(": Real-time Clock and Temperature Sensor\n"); 157 158 sc->sc_dev = self; 159 160 sc->sc_tag = ia->ia_tag; 161 sc->sc_addr = ia->ia_addr; 162 163 164 /* 165 * Control Page registers 166 */ 167 error = em3027rtc_read(sc, EM3027_CONTROL_BASE, &ctl, sizeof(ctl)); 168 if (error) { 169 aprint_error_dev(sc->sc_dev, 170 "failed to read control page (error %d)\n", error); 171 return; 172 } 173 174 175 /* Status */ 176 aprint_debug_dev(sc->sc_dev, "status=0x%02x\n", ctl.status); 177 178 /* Complain about low voltage but continue anyway */ 179 if (ctl.status & EM3027_STATUS_VLOW2) { 180 aprint_error_dev(sc->sc_dev, "voltage low (VLow2)\n"); 181 sc->sc_vlow = true; 182 } 183 else if (ctl.status & EM3027_STATUS_VLOW1) { 184 aprint_error_dev(sc->sc_dev, "voltage low (VLow1)\n"); 185 sc->sc_vlow = true; 186 } 187 188 ctl.status = EM3027_STATUS_POWER_ON; 189 190 191 /* On/Off */ 192 aprint_debug_dev(sc->sc_dev, "on/off=0x%02x\n", ctl.onoff); 193 194 if ((ctl.onoff & EM3027_ONOFF_SR) == 0) { 195 aprint_verbose_dev(sc->sc_dev, "enabling self-recovery\n"); 196 ctl.onoff |= EM3027_ONOFF_SR; 197 } 198 199 if ((ctl.onoff & EM3027_ONOFF_EEREF) == 0) { 200 aprint_verbose_dev(sc->sc_dev, "enabling EEPROM self-refresh\n"); 201 ctl.onoff |= EM3027_ONOFF_EEREF; 202 } 203 204 ctl.onoff &= ~EM3027_ONOFF_TR; 205 206 if (ctl.onoff & EM3027_ONOFF_TI) { 207 aprint_verbose_dev(sc->sc_dev, "disabling timer\n"); 208 ctl.onoff &= ~EM3027_ONOFF_TI; 209 } 210 211 if ((ctl.onoff & EM3027_ONOFF_WA) == 0) { 212 aprint_verbose_dev(sc->sc_dev, "enabling watch\n"); 213 ctl.onoff |= EM3027_ONOFF_WA; 214 } 215 216 217 /* IRQ Control/Flags */ 218 if (ctl.irq_ctl != 0) 219 aprint_debug_dev(sc->sc_dev, 220 "irq=0x%02x - disabling all\n", ctl.irq_ctl); 221 ctl.irq_ctl = 0; 222 ctl.irq_flags = 0; 223 224 225 /* Write them back */ 226 error = em3027rtc_write(sc, EM3027_CONTROL_BASE, &ctl, sizeof(ctl)); 227 if (error) { 228 aprint_error_dev(sc->sc_dev, 229 "failed to write control page (error %d)\n", error); 230 return; 231 } 232 233 234 /* 235 * Attach RTC 236 */ 237 sc->sc_todr.todr_dev = self; 238 sc->sc_todr.todr_gettime_ymdhms = em3027rtc_gettime; 239 sc->sc_todr.todr_settime_ymdhms = em3027rtc_settime; 240 241 todr_attach(&sc->sc_todr); 242 243 244 /* 245 * Attach thermometer 246 */ 247 em3027rtc_envsys_attach(sc); 248 } 249 250 251 static bool 252 em3027rtc_enable_thermometer(struct em3027rtc_softc *sc) 253 { 254 uint8_t eeprom_ctl; 255 int error; 256 257 error = em3027rtc_read_byte(sc, EM3027_EEPROM_CTL, &eeprom_ctl); 258 if (error) { 259 aprint_error_dev(sc->sc_dev, 260 "failed to read eeprom control (error %d)\n", error); 261 return false; 262 } 263 264 aprint_debug_dev(sc->sc_dev, "eeprom ctl=0x%02x\n", eeprom_ctl); 265 if (eeprom_ctl & EM3027_EEPROM_THERM_ENABLE) 266 return true; 267 268 eeprom_ctl |= EM3027_EEPROM_THERM_ENABLE; 269 error = em3027rtc_write_byte(sc, EM3027_EEPROM_CTL, eeprom_ctl); 270 if (error) { 271 aprint_error_dev(sc->sc_dev, 272 "failed to write eeprom control (error %d)\n", error); 273 return false; 274 } 275 276 return true; 277 } 278 279 280 static void 281 em3027rtc_envsys_attach(struct em3027rtc_softc *sc) 282 { 283 int error; 284 285 if (!em3027rtc_enable_thermometer(sc)) { 286 aprint_error_dev(sc->sc_dev, "thermometer not enabled\n"); 287 return; 288 } 289 290 sc->sc_sme = sysmon_envsys_create(); 291 292 sc->sc_sme->sme_name = device_xname(sc->sc_dev); 293 sc->sc_sme->sme_cookie = sc; 294 sc->sc_sme->sme_refresh = em3027rtc_sme_refresh; 295 296 sc->sc_sensor.units = ENVSYS_STEMP; 297 sc->sc_sensor.state = ENVSYS_SINVALID; 298 sc->sc_sensor.flags = 0; 299 strlcpy(sc->sc_sensor.desc, "temperature", sizeof(sc->sc_sensor.desc)); 300 301 error = sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor); 302 if (error) { 303 aprint_error_dev(sc->sc_dev, 304 "unable to attach sensor (error %d)\n", error); 305 goto out; 306 } 307 308 error = sysmon_envsys_register(sc->sc_sme); 309 if (error) { 310 aprint_error_dev(sc->sc_dev, 311 "unable to register with sysmon (error %d)\n", error); 312 goto out; 313 } 314 315 return; 316 317 out: 318 if (error) { 319 sysmon_envsys_destroy(sc->sc_sme); 320 sc->sc_sme = NULL; 321 } 322 } 323 324 325 static int 326 em3027rtc_iic_exec(struct em3027rtc_softc *sc, i2c_op_t op, uint8_t reg, 327 void *buf, size_t len) 328 { 329 const int flags = 0; 330 int error; 331 332 error = iic_acquire_bus(sc->sc_tag, flags); 333 if (error) 334 return error; 335 336 error = iic_exec(sc->sc_tag, op, sc->sc_addr, 337 ®, 1, 338 (uint8_t *)buf, len, 339 flags); 340 341 /* XXX: horrible hack that seems to be needed on utilite */ 342 if (reg == EM3027_WATCH_BASE) 343 DELAY(1); 344 345 iic_release_bus(sc->sc_tag, flags); 346 return error; 347 } 348 349 350 static int 351 em3027rtc_read(struct em3027rtc_softc *sc, uint8_t reg, void *buf, size_t len) 352 { 353 354 return em3027rtc_iic_exec(sc, I2C_OP_READ_WITH_STOP, reg, buf, len); 355 } 356 357 358 static int 359 em3027rtc_read_byte(struct em3027rtc_softc *sc, uint8_t reg, uint8_t *valp) 360 { 361 362 return em3027rtc_read(sc, reg, valp, 1); 363 } 364 365 366 static int 367 em3027rtc_write(struct em3027rtc_softc *sc, uint8_t reg, void *buf, size_t len) 368 { 369 370 return em3027rtc_iic_exec(sc, I2C_OP_WRITE_WITH_STOP, reg, buf, len); 371 } 372 373 374 static int 375 em3027rtc_write_byte(struct em3027rtc_softc *sc, uint8_t reg, uint8_t val) 376 { 377 378 return em3027rtc_write(sc, reg, &val, 1); 379 } 380 381 382 static int 383 em3027rtc_gettime(struct todr_chip_handle *todr, struct clock_ymdhms *dt) 384 { 385 struct em3027rtc_softc *sc = device_private(todr->todr_dev); 386 struct em3027rtc_watch w; 387 int error; 388 389 error = em3027rtc_read(sc, EM3027_WATCH_BASE, &w, sizeof(w)); 390 if (error) { 391 aprint_error_dev(sc->sc_dev, 392 "failed to read watch (error %d)\n", error); 393 return error; 394 } 395 396 dt->dt_sec = bcdtobin(w.sec); 397 dt->dt_min = bcdtobin(w.min); 398 399 if (w.hour & EM3027_WATCH_HOUR_S12) { 400 const int pm = w.hour & EM3027_WATCH_HOUR_PM; 401 int hr; 402 403 w.hour &= ~(EM3027_WATCH_HOUR_S12 | EM3027_WATCH_HOUR_PM); 404 hr = bcdtobin(w.hour); 405 if (hr == 12) 406 hr = pm ? 12 : 0; 407 else if (pm) 408 hr += 12; 409 410 dt->dt_hour = hr; 411 } 412 else { 413 dt->dt_hour = bcdtobin(w.hour); 414 } 415 416 dt->dt_day = bcdtobin(w.day); 417 dt->dt_wday = bcdtobin(w.wday) - 1; 418 dt->dt_mon = bcdtobin(w.mon); 419 dt->dt_year = bcdtobin(w.year) + EM3027_BASE_YEAR; 420 421 return 0; 422 } 423 424 425 static int 426 em3027rtc_settime(struct todr_chip_handle *todr, struct clock_ymdhms *dt) 427 { 428 struct em3027rtc_softc *sc = device_private(todr->todr_dev); 429 struct em3027rtc_watch w; 430 int error; 431 432 w.sec = bintobcd(dt->dt_sec); 433 w.min = bintobcd(dt->dt_min); 434 w.hour = bintobcd(dt->dt_hour); 435 w.day = bintobcd(dt->dt_day); 436 w.wday = bintobcd(dt->dt_wday + 1); 437 w.mon = bintobcd(dt->dt_mon); 438 w.year = bintobcd(dt->dt_year - EM3027_BASE_YEAR); 439 440 error = em3027rtc_write(sc, EM3027_WATCH_BASE, &w, sizeof(w)); 441 return error; 442 } 443 444 445 static void 446 em3027rtc_sme_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 447 { 448 struct em3027rtc_softc *sc = sme->sme_cookie; 449 uint8_t status, t_raw; 450 uint32_t t_uk; 451 int error; 452 453 edata->state = ENVSYS_SINVALID; 454 455 error = em3027rtc_read_byte(sc, EM3027_STATUS, &status); 456 if (error) { 457 aprint_debug_dev(sc->sc_dev, 458 "failed to read status (error %d)\n", error); 459 return; 460 } 461 462 if (status & (EM3027_STATUS_VLOW2 | EM3027_STATUS_VLOW1)) { 463 if (!sc->sc_vlow) { 464 sc->sc_vlow = true; 465 aprint_error_dev(sc->sc_dev, 466 "voltage low, thermometer is disabled\n"); 467 } 468 return; 469 } 470 else 471 sc->sc_vlow = false; 472 473 error = em3027rtc_read_byte(sc, EM3027_TEMP, &t_raw); 474 if (error) { 475 aprint_debug_dev(sc->sc_dev, 476 "failed to read temperature (error %d)\n", error); 477 return; 478 } 479 480 481 /* convert to microkelvin */ 482 t_uk = ((int)t_raw + EM3027_TEMP_BASE) * 1000000 + 273150000; 483 484 edata->value_cur = t_uk; 485 edata->state = ENVSYS_SVALID; 486 } 487