1 /* $NetBSD: em3027.c,v 1.3 2019/07/27 16:02:27 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.3 2019/07/27 16:02:27 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 109 110 static int 111 em3027rtc_match(device_t parent, cfdata_t cf, void *aux) 112 { 113 const struct i2c_attach_args *ia = aux; 114 uint8_t reg; 115 int error; 116 117 if (ia->ia_addr != EM3027_ADDR) 118 return 0; 119 120 /* check if the device is there */ 121 error = iic_acquire_bus(ia->ia_tag, 0); 122 if (error) 123 return 0; 124 125 error = iic_smbus_read_byte(ia->ia_tag, ia->ia_addr, 126 EM3027_ONOFF, ®, 0); 127 iic_release_bus(ia->ia_tag, 0); 128 if (error) 129 return 0; 130 131 return I2C_MATCH_ADDRESS_AND_PROBE; 132 } 133 134 135 static void 136 em3027rtc_attach(device_t parent, device_t self, void *aux) 137 { 138 struct em3027rtc_softc *sc = device_private(self); 139 const struct i2c_attach_args *ia = aux; 140 struct ctl { 141 uint8_t onoff; 142 uint8_t irq_ctl; 143 uint8_t irq_flags; 144 uint8_t status; 145 } ctl; 146 int error; 147 148 aprint_naive(": Real-time Clock and Temperature Sensor\n"); 149 aprint_normal(": Real-time Clock and Temperature Sensor\n"); 150 151 sc->sc_dev = self; 152 153 sc->sc_tag = ia->ia_tag; 154 sc->sc_addr = ia->ia_addr; 155 156 157 /* 158 * Control Page registers 159 */ 160 error = em3027rtc_read(sc, EM3027_CONTROL_BASE, &ctl, sizeof(ctl)); 161 if (error) { 162 aprint_error_dev(sc->sc_dev, 163 "failed to read control page (error %d)\n", error); 164 return; 165 } 166 167 168 /* Status */ 169 aprint_debug_dev(sc->sc_dev, "status=0x%02x\n", ctl.status); 170 171 /* Complain about low voltage but continue anyway */ 172 if (ctl.status & EM3027_STATUS_VLOW2) { 173 aprint_error_dev(sc->sc_dev, "voltage low (VLow2)\n"); 174 sc->sc_vlow = true; 175 } 176 else if (ctl.status & EM3027_STATUS_VLOW1) { 177 aprint_error_dev(sc->sc_dev, "voltage low (VLow1)\n"); 178 sc->sc_vlow = true; 179 } 180 181 ctl.status = EM3027_STATUS_POWER_ON; 182 183 184 /* On/Off */ 185 aprint_debug_dev(sc->sc_dev, "on/off=0x%02x\n", ctl.onoff); 186 187 if ((ctl.onoff & EM3027_ONOFF_SR) == 0) { 188 aprint_verbose_dev(sc->sc_dev, "enabling self-recovery\n"); 189 ctl.onoff |= EM3027_ONOFF_SR; 190 } 191 192 if ((ctl.onoff & EM3027_ONOFF_EEREF) == 0) { 193 aprint_verbose_dev(sc->sc_dev, "enabling EEPROM self-refresh\n"); 194 ctl.onoff |= EM3027_ONOFF_EEREF; 195 } 196 197 ctl.onoff &= ~EM3027_ONOFF_TR; 198 199 if (ctl.onoff & EM3027_ONOFF_TI) { 200 aprint_verbose_dev(sc->sc_dev, "disabling timer\n"); 201 ctl.onoff &= ~EM3027_ONOFF_TI; 202 } 203 204 if ((ctl.onoff & EM3027_ONOFF_WA) == 0) { 205 aprint_verbose_dev(sc->sc_dev, "enabling watch\n"); 206 ctl.onoff |= EM3027_ONOFF_WA; 207 } 208 209 210 /* IRQ Control/Flags */ 211 if (ctl.irq_ctl != 0) 212 aprint_debug_dev(sc->sc_dev, 213 "irq=0x%02x - disabling all\n", ctl.irq_ctl); 214 ctl.irq_ctl = 0; 215 ctl.irq_flags = 0; 216 217 218 /* Write them back */ 219 error = em3027rtc_write(sc, EM3027_CONTROL_BASE, &ctl, sizeof(ctl)); 220 if (error) { 221 aprint_error_dev(sc->sc_dev, 222 "failed to write control page (error %d)\n", error); 223 return; 224 } 225 226 227 /* 228 * Attach RTC 229 */ 230 sc->sc_todr.cookie = sc; 231 sc->sc_todr.todr_gettime_ymdhms = em3027rtc_gettime; 232 sc->sc_todr.todr_settime_ymdhms = em3027rtc_settime; 233 sc->sc_todr.todr_setwen = NULL; 234 235 todr_attach(&sc->sc_todr); 236 237 238 /* 239 * Attach thermometer 240 */ 241 em3027rtc_envsys_attach(sc); 242 } 243 244 245 static bool 246 em3027rtc_enable_thermometer(struct em3027rtc_softc *sc) 247 { 248 uint8_t eeprom_ctl; 249 int error; 250 251 error = em3027rtc_read_byte(sc, EM3027_EEPROM_CTL, &eeprom_ctl); 252 if (error) { 253 aprint_error_dev(sc->sc_dev, 254 "failed to read eeprom control (error %d)\n", error); 255 return false; 256 } 257 258 aprint_debug_dev(sc->sc_dev, "eeprom ctl=0x%02x\n", eeprom_ctl); 259 if (eeprom_ctl & EM3027_EEPROM_THERM_ENABLE) 260 return true; 261 262 eeprom_ctl |= EM3027_EEPROM_THERM_ENABLE; 263 error = em3027rtc_write_byte(sc, EM3027_EEPROM_CTL, eeprom_ctl); 264 if (error) { 265 aprint_error_dev(sc->sc_dev, 266 "failed to write eeprom control (error %d)\n", error); 267 return false; 268 } 269 270 return true; 271 } 272 273 274 static void 275 em3027rtc_envsys_attach(struct em3027rtc_softc *sc) 276 { 277 int error; 278 279 if (!em3027rtc_enable_thermometer(sc)) { 280 aprint_error_dev(sc->sc_dev, "thermometer not enabled\n"); 281 return; 282 } 283 284 sc->sc_sme = sysmon_envsys_create(); 285 286 sc->sc_sme->sme_name = device_xname(sc->sc_dev); 287 sc->sc_sme->sme_cookie = sc; 288 sc->sc_sme->sme_refresh = em3027rtc_sme_refresh; 289 290 sc->sc_sensor.units = ENVSYS_STEMP; 291 sc->sc_sensor.state = ENVSYS_SINVALID; 292 sc->sc_sensor.flags = 0; 293 strlcpy(sc->sc_sensor.desc, "temperature", sizeof(sc->sc_sensor.desc)); 294 295 error = sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor); 296 if (error) { 297 aprint_error_dev(sc->sc_dev, 298 "unable to attach sensor (error %d)\n", error); 299 goto out; 300 } 301 302 error = sysmon_envsys_register(sc->sc_sme); 303 if (error) { 304 aprint_error_dev(sc->sc_dev, 305 "unable to register with sysmon (error %d)\n", error); 306 goto out; 307 } 308 309 return; 310 311 out: 312 if (error) { 313 sysmon_envsys_destroy(sc->sc_sme); 314 sc->sc_sme = NULL; 315 } 316 } 317 318 319 static int 320 em3027rtc_iic_exec(struct em3027rtc_softc *sc, i2c_op_t op, uint8_t reg, 321 void *buf, size_t len) 322 { 323 const int flags = 0; 324 int error; 325 326 error = iic_acquire_bus(sc->sc_tag, flags); 327 if (error) 328 return error; 329 330 error = iic_exec(sc->sc_tag, op, sc->sc_addr, 331 ®, 1, 332 (uint8_t *)buf, len, 333 flags); 334 335 /* XXX: horrible hack that seems to be needed on utilite */ 336 if (reg == EM3027_WATCH_BASE) 337 DELAY(1); 338 339 iic_release_bus(sc->sc_tag, flags); 340 return error; 341 } 342 343 344 static int 345 em3027rtc_read(struct em3027rtc_softc *sc, uint8_t reg, void *buf, size_t len) 346 { 347 348 return em3027rtc_iic_exec(sc, I2C_OP_READ_WITH_STOP, reg, buf, len); 349 } 350 351 352 static int 353 em3027rtc_read_byte(struct em3027rtc_softc *sc, uint8_t reg, uint8_t *valp) 354 { 355 356 return em3027rtc_read(sc, reg, valp, 1); 357 } 358 359 360 static int 361 em3027rtc_write(struct em3027rtc_softc *sc, uint8_t reg, void *buf, size_t len) 362 { 363 364 return em3027rtc_iic_exec(sc, I2C_OP_WRITE_WITH_STOP, reg, buf, len); 365 } 366 367 368 static int 369 em3027rtc_write_byte(struct em3027rtc_softc *sc, uint8_t reg, uint8_t val) 370 { 371 372 return em3027rtc_write(sc, reg, &val, 1); 373 } 374 375 376 static int 377 em3027rtc_gettime(struct todr_chip_handle *todr, struct clock_ymdhms *dt) 378 { 379 struct em3027rtc_softc *sc = todr->cookie; 380 struct em3027rtc_watch w; 381 int error; 382 383 error = em3027rtc_read(sc, EM3027_WATCH_BASE, &w, sizeof(w)); 384 if (error) { 385 aprint_error_dev(sc->sc_dev, 386 "failed to read watch (error %d)\n", error); 387 return error; 388 } 389 390 dt->dt_sec = bcdtobin(w.sec); 391 dt->dt_min = bcdtobin(w.min); 392 393 if (w.hour & EM3027_WATCH_HOUR_S12) { 394 const int pm = w.hour & EM3027_WATCH_HOUR_PM; 395 int hr; 396 397 w.hour &= ~(EM3027_WATCH_HOUR_S12 | EM3027_WATCH_HOUR_PM); 398 hr = bcdtobin(w.hour); 399 if (hr == 12) 400 hr = pm ? 12 : 0; 401 else if (pm) 402 hr += 12; 403 404 dt->dt_hour = hr; 405 } 406 else { 407 dt->dt_hour = bcdtobin(w.hour); 408 } 409 410 dt->dt_day = bcdtobin(w.day); 411 dt->dt_wday = bcdtobin(w.wday) - 1; 412 dt->dt_mon = bcdtobin(w.mon); 413 dt->dt_year = bcdtobin(w.year) + EM3027_BASE_YEAR; 414 415 return 0; 416 } 417 418 419 static int 420 em3027rtc_settime(struct todr_chip_handle *todr, struct clock_ymdhms *dt) 421 { 422 struct em3027rtc_softc *sc = todr->cookie; 423 struct em3027rtc_watch w; 424 int error; 425 426 w.sec = bintobcd(dt->dt_sec); 427 w.min = bintobcd(dt->dt_min); 428 w.hour = bintobcd(dt->dt_hour); 429 w.day = bintobcd(dt->dt_day); 430 w.wday = bintobcd(dt->dt_wday + 1); 431 w.mon = bintobcd(dt->dt_mon); 432 w.year = bintobcd(dt->dt_year - EM3027_BASE_YEAR); 433 434 error = em3027rtc_write(sc, EM3027_WATCH_BASE, &w, sizeof(w)); 435 return error; 436 } 437 438 439 static void 440 em3027rtc_sme_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 441 { 442 struct em3027rtc_softc *sc = sme->sme_cookie; 443 uint8_t status, t_raw; 444 uint32_t t_uk; 445 int error; 446 447 edata->state = ENVSYS_SINVALID; 448 449 error = em3027rtc_read_byte(sc, EM3027_STATUS, &status); 450 if (error) { 451 aprint_debug_dev(sc->sc_dev, 452 "failed to read status (error %d)\n", error); 453 return; 454 } 455 456 if (status & (EM3027_STATUS_VLOW2 | EM3027_STATUS_VLOW1)) { 457 if (!sc->sc_vlow) { 458 sc->sc_vlow = true; 459 aprint_error_dev(sc->sc_dev, 460 "voltage low, thermometer is disabled\n"); 461 } 462 return; 463 } 464 else 465 sc->sc_vlow = false; 466 467 error = em3027rtc_read_byte(sc, EM3027_TEMP, &t_raw); 468 if (error) { 469 aprint_debug_dev(sc->sc_dev, 470 "failed to read temperature (error %d)\n", error); 471 return; 472 } 473 474 475 /* convert to microkelvin */ 476 t_uk = ((int)t_raw + EM3027_TEMP_BASE) * 1000000 + 273150000; 477 478 edata->value_cur = t_uk; 479 edata->state = ENVSYS_SVALID; 480 } 481