1 /* $NetBSD: em3027.c,v 1.8 2021/01/27 02:29:48 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.8 2021/01/27 02:29:48 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.cookie = sc; 238 sc->sc_todr.todr_gettime_ymdhms = em3027rtc_gettime; 239 sc->sc_todr.todr_settime_ymdhms = em3027rtc_settime; 240 sc->sc_todr.todr_setwen = NULL; 241 242 todr_attach(&sc->sc_todr); 243 244 245 /* 246 * Attach thermometer 247 */ 248 em3027rtc_envsys_attach(sc); 249 } 250 251 252 static bool 253 em3027rtc_enable_thermometer(struct em3027rtc_softc *sc) 254 { 255 uint8_t eeprom_ctl; 256 int error; 257 258 error = em3027rtc_read_byte(sc, EM3027_EEPROM_CTL, &eeprom_ctl); 259 if (error) { 260 aprint_error_dev(sc->sc_dev, 261 "failed to read eeprom control (error %d)\n", error); 262 return false; 263 } 264 265 aprint_debug_dev(sc->sc_dev, "eeprom ctl=0x%02x\n", eeprom_ctl); 266 if (eeprom_ctl & EM3027_EEPROM_THERM_ENABLE) 267 return true; 268 269 eeprom_ctl |= EM3027_EEPROM_THERM_ENABLE; 270 error = em3027rtc_write_byte(sc, EM3027_EEPROM_CTL, eeprom_ctl); 271 if (error) { 272 aprint_error_dev(sc->sc_dev, 273 "failed to write eeprom control (error %d)\n", error); 274 return false; 275 } 276 277 return true; 278 } 279 280 281 static void 282 em3027rtc_envsys_attach(struct em3027rtc_softc *sc) 283 { 284 int error; 285 286 if (!em3027rtc_enable_thermometer(sc)) { 287 aprint_error_dev(sc->sc_dev, "thermometer not enabled\n"); 288 return; 289 } 290 291 sc->sc_sme = sysmon_envsys_create(); 292 293 sc->sc_sme->sme_name = device_xname(sc->sc_dev); 294 sc->sc_sme->sme_cookie = sc; 295 sc->sc_sme->sme_refresh = em3027rtc_sme_refresh; 296 297 sc->sc_sensor.units = ENVSYS_STEMP; 298 sc->sc_sensor.state = ENVSYS_SINVALID; 299 sc->sc_sensor.flags = 0; 300 strlcpy(sc->sc_sensor.desc, "temperature", sizeof(sc->sc_sensor.desc)); 301 302 error = sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor); 303 if (error) { 304 aprint_error_dev(sc->sc_dev, 305 "unable to attach sensor (error %d)\n", error); 306 goto out; 307 } 308 309 error = sysmon_envsys_register(sc->sc_sme); 310 if (error) { 311 aprint_error_dev(sc->sc_dev, 312 "unable to register with sysmon (error %d)\n", error); 313 goto out; 314 } 315 316 return; 317 318 out: 319 if (error) { 320 sysmon_envsys_destroy(sc->sc_sme); 321 sc->sc_sme = NULL; 322 } 323 } 324 325 326 static int 327 em3027rtc_iic_exec(struct em3027rtc_softc *sc, i2c_op_t op, uint8_t reg, 328 void *buf, size_t len) 329 { 330 const int flags = 0; 331 int error; 332 333 error = iic_acquire_bus(sc->sc_tag, flags); 334 if (error) 335 return error; 336 337 error = iic_exec(sc->sc_tag, op, sc->sc_addr, 338 ®, 1, 339 (uint8_t *)buf, len, 340 flags); 341 342 /* XXX: horrible hack that seems to be needed on utilite */ 343 if (reg == EM3027_WATCH_BASE) 344 DELAY(1); 345 346 iic_release_bus(sc->sc_tag, flags); 347 return error; 348 } 349 350 351 static int 352 em3027rtc_read(struct em3027rtc_softc *sc, uint8_t reg, void *buf, size_t len) 353 { 354 355 return em3027rtc_iic_exec(sc, I2C_OP_READ_WITH_STOP, reg, buf, len); 356 } 357 358 359 static int 360 em3027rtc_read_byte(struct em3027rtc_softc *sc, uint8_t reg, uint8_t *valp) 361 { 362 363 return em3027rtc_read(sc, reg, valp, 1); 364 } 365 366 367 static int 368 em3027rtc_write(struct em3027rtc_softc *sc, uint8_t reg, void *buf, size_t len) 369 { 370 371 return em3027rtc_iic_exec(sc, I2C_OP_WRITE_WITH_STOP, reg, buf, len); 372 } 373 374 375 static int 376 em3027rtc_write_byte(struct em3027rtc_softc *sc, uint8_t reg, uint8_t val) 377 { 378 379 return em3027rtc_write(sc, reg, &val, 1); 380 } 381 382 383 static int 384 em3027rtc_gettime(struct todr_chip_handle *todr, struct clock_ymdhms *dt) 385 { 386 struct em3027rtc_softc *sc = todr->cookie; 387 struct em3027rtc_watch w; 388 int error; 389 390 error = em3027rtc_read(sc, EM3027_WATCH_BASE, &w, sizeof(w)); 391 if (error) { 392 aprint_error_dev(sc->sc_dev, 393 "failed to read watch (error %d)\n", error); 394 return error; 395 } 396 397 dt->dt_sec = bcdtobin(w.sec); 398 dt->dt_min = bcdtobin(w.min); 399 400 if (w.hour & EM3027_WATCH_HOUR_S12) { 401 const int pm = w.hour & EM3027_WATCH_HOUR_PM; 402 int hr; 403 404 w.hour &= ~(EM3027_WATCH_HOUR_S12 | EM3027_WATCH_HOUR_PM); 405 hr = bcdtobin(w.hour); 406 if (hr == 12) 407 hr = pm ? 12 : 0; 408 else if (pm) 409 hr += 12; 410 411 dt->dt_hour = hr; 412 } 413 else { 414 dt->dt_hour = bcdtobin(w.hour); 415 } 416 417 dt->dt_day = bcdtobin(w.day); 418 dt->dt_wday = bcdtobin(w.wday) - 1; 419 dt->dt_mon = bcdtobin(w.mon); 420 dt->dt_year = bcdtobin(w.year) + EM3027_BASE_YEAR; 421 422 return 0; 423 } 424 425 426 static int 427 em3027rtc_settime(struct todr_chip_handle *todr, struct clock_ymdhms *dt) 428 { 429 struct em3027rtc_softc *sc = todr->cookie; 430 struct em3027rtc_watch w; 431 int error; 432 433 w.sec = bintobcd(dt->dt_sec); 434 w.min = bintobcd(dt->dt_min); 435 w.hour = bintobcd(dt->dt_hour); 436 w.day = bintobcd(dt->dt_day); 437 w.wday = bintobcd(dt->dt_wday + 1); 438 w.mon = bintobcd(dt->dt_mon); 439 w.year = bintobcd(dt->dt_year - EM3027_BASE_YEAR); 440 441 error = em3027rtc_write(sc, EM3027_WATCH_BASE, &w, sizeof(w)); 442 return error; 443 } 444 445 446 static void 447 em3027rtc_sme_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 448 { 449 struct em3027rtc_softc *sc = sme->sme_cookie; 450 uint8_t status, t_raw; 451 uint32_t t_uk; 452 int error; 453 454 edata->state = ENVSYS_SINVALID; 455 456 error = em3027rtc_read_byte(sc, EM3027_STATUS, &status); 457 if (error) { 458 aprint_debug_dev(sc->sc_dev, 459 "failed to read status (error %d)\n", error); 460 return; 461 } 462 463 if (status & (EM3027_STATUS_VLOW2 | EM3027_STATUS_VLOW1)) { 464 if (!sc->sc_vlow) { 465 sc->sc_vlow = true; 466 aprint_error_dev(sc->sc_dev, 467 "voltage low, thermometer is disabled\n"); 468 } 469 return; 470 } 471 else 472 sc->sc_vlow = false; 473 474 error = em3027rtc_read_byte(sc, EM3027_TEMP, &t_raw); 475 if (error) { 476 aprint_debug_dev(sc->sc_dev, 477 "failed to read temperature (error %d)\n", error); 478 return; 479 } 480 481 482 /* convert to microkelvin */ 483 t_uk = ((int)t_raw + EM3027_TEMP_BASE) * 1000000 + 273150000; 484 485 edata->value_cur = t_uk; 486 edata->state = ENVSYS_SVALID; 487 } 488