Home | History | Annotate | Line # | Download | only in i2c
      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, &reg, 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 			 &reg, 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