Home | History | Annotate | Line # | Download | only in i2c
lm87.c revision 1.4
      1  1.4  jdc /*	$NetBSD: lm87.c,v 1.4 2013/11/04 15:06:26 jdc Exp $	*/
      2  1.1  jdc /*	$OpenBSD: lm87.c,v 1.20 2008/11/10 05:19:48 cnst Exp $	*/
      3  1.1  jdc 
      4  1.1  jdc /*
      5  1.1  jdc  * Copyright (c) 2005 Mark Kettenis
      6  1.1  jdc  *
      7  1.1  jdc  * Permission to use, copy, modify, and distribute this software for any
      8  1.1  jdc  * purpose with or without fee is hereby granted, provided that the above
      9  1.1  jdc  * copyright notice and this permission notice appear in all copies.
     10  1.1  jdc  *
     11  1.1  jdc  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12  1.1  jdc  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13  1.1  jdc  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14  1.1  jdc  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15  1.1  jdc  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16  1.1  jdc  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17  1.1  jdc  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  1.1  jdc  */
     19  1.1  jdc 
     20  1.1  jdc #include <sys/cdefs.h>
     21  1.4  jdc __KERNEL_RCSID(0, "$NetBSD: lm87.c,v 1.4 2013/11/04 15:06:26 jdc Exp $");
     22  1.1  jdc 
     23  1.1  jdc #include <sys/param.h>
     24  1.1  jdc #include <sys/systm.h>
     25  1.1  jdc #include <sys/device.h>
     26  1.1  jdc #include <dev/sysmon/sysmonvar.h>
     27  1.1  jdc 
     28  1.1  jdc #include <dev/i2c/i2cvar.h>
     29  1.1  jdc 
     30  1.1  jdc /* LM87 registers */
     31  1.1  jdc #define LM87_2_5V	0x20
     32  1.1  jdc #define LM87_VCCP1	0x21
     33  1.1  jdc #define LM87_VCC	0x22
     34  1.1  jdc #define LM87_5V		0x23
     35  1.1  jdc #define LM87_12V	0x24
     36  1.1  jdc #define LM87_VCCP2	0x25
     37  1.1  jdc #define LM87_EXT_TEMP	0x26
     38  1.1  jdc #define LM87_INT_TEMP	0x27
     39  1.1  jdc #define LM87_FAN1	0x28
     40  1.1  jdc #define LM87_FAN2	0x29
     41  1.1  jdc #define LM87_COMPANY_ID	0x3e
     42  1.1  jdc #define LM87_REVISION	0x3f
     43  1.1  jdc #define LM87_CONFIG1	0x40
     44  1.1  jdc #define  LM87_CONFIG1_START	0x01
     45  1.1  jdc #define  LM87_CONFIG1_INTCLR	0x08
     46  1.1  jdc #define LM87_CHANNEL	0x16
     47  1.1  jdc #define  LM87_CHANNEL_AIN1	0x01
     48  1.1  jdc #define  LM87_CHANNEL_AIN2	0x02
     49  1.1  jdc #define LM87_FANDIV	0x47
     50  1.1  jdc 
     51  1.1  jdc struct lmenv_id {
     52  1.1  jdc 	u_int8_t id, family;
     53  1.1  jdc 	const char *name;
     54  1.1  jdc };
     55  1.1  jdc 
     56  1.1  jdc static const struct lmenv_id lmenv_ids[] = {
     57  1.1  jdc 	{ 0x01, 81, "LM81" },
     58  1.1  jdc 	{ 0x02, 87, "LM87" },	/* LM87 or LM87CIMT */
     59  1.1  jdc 	{ 0x23, 81, "ADM9240" },
     60  1.1  jdc 	{ 0xda, 81, "DSL780" },
     61  1.1  jdc 	{ 0x00, 0, NULL }
     62  1.1  jdc };
     63  1.1  jdc 
     64  1.1  jdc /* Sensors */
     65  1.1  jdc #define LMENV_2_5V		0
     66  1.1  jdc #define LMENV_VCCP1		1
     67  1.1  jdc #define LMENV_VCC		2
     68  1.1  jdc #define LMENV_5V		3
     69  1.1  jdc #define LMENV_12V		4
     70  1.1  jdc #define LMENV_VCCP2		5
     71  1.1  jdc #define LMENV_EXT_TEMP		6
     72  1.1  jdc #define LMENV_INT_TEMP		7
     73  1.1  jdc #define LMENV_FAN1		8
     74  1.1  jdc #define LMENV_FAN2		9
     75  1.1  jdc #define LMENV_NUM_SENSORS	10
     76  1.1  jdc 
     77  1.1  jdc struct lmenv_softc {
     78  1.1  jdc 	i2c_tag_t sc_tag;
     79  1.1  jdc 	i2c_addr_t sc_addr;
     80  1.1  jdc 
     81  1.1  jdc 	int	sc_fan1_div, sc_fan2_div;
     82  1.1  jdc 	int	sc_family;
     83  1.1  jdc 
     84  1.1  jdc 	struct sysmon_envsys *sc_sme;
     85  1.1  jdc 	envsys_data_t sc_sensor[LMENV_NUM_SENSORS];
     86  1.1  jdc };
     87  1.1  jdc 
     88  1.1  jdc int	lmenv_match(device_t, cfdata_t, void *);
     89  1.1  jdc void	lmenv_attach(device_t, device_t, void *);
     90  1.1  jdc 
     91  1.1  jdc void	lmenv_refresh(struct sysmon_envsys *, envsys_data_t *);
     92  1.1  jdc 
     93  1.1  jdc CFATTACH_DECL_NEW(lmenv, sizeof(struct lmenv_softc),
     94  1.1  jdc 	lmenv_match, lmenv_attach, NULL, NULL);
     95  1.1  jdc 
     96  1.1  jdc static const char * lmenv_compats[] = {
     97  1.1  jdc 	"lm87",
     98  1.1  jdc 	"lm87cimt",
     99  1.1  jdc 	"adm9240",
    100  1.1  jdc 	"lm81",
    101  1.1  jdc 	"ds1780",
    102  1.1  jdc 	NULL
    103  1.1  jdc };
    104  1.1  jdc 
    105  1.1  jdc int
    106  1.1  jdc lmenv_match(device_t parent, cfdata_t match, void *aux)
    107  1.1  jdc {
    108  1.1  jdc 	struct i2c_attach_args *ia = aux;
    109  1.1  jdc 	u_int8_t cmd, val;
    110  1.1  jdc 	int error, i;
    111  1.1  jdc 
    112  1.1  jdc 	if (ia->ia_name == NULL) {
    113  1.1  jdc 		/*
    114  1.1  jdc 		 * Indirect config - not much we can do!
    115  1.1  jdc 		 * Check typical addresses and read the Company ID register
    116  1.1  jdc 		 */
    117  1.1  jdc 		if ((ia->ia_addr < 0x2c) || (ia->ia_addr > 0x2f))
    118  1.1  jdc 			return 0;
    119  1.1  jdc 
    120  1.1  jdc 		cmd = LM87_COMPANY_ID;
    121  1.1  jdc 		iic_acquire_bus(ia->ia_tag, 0);
    122  1.1  jdc 		error = iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr,
    123  1.1  jdc 		    &cmd, 1, &val, 1, I2C_F_POLL);
    124  1.1  jdc 		iic_release_bus(ia->ia_tag, 0);
    125  1.1  jdc 
    126  1.1  jdc 		if (error)
    127  1.1  jdc 			return 0;
    128  1.1  jdc 
    129  1.1  jdc 		for (i = 0; lmenv_ids[i].id != 0; i++)
    130  1.1  jdc 			if (lmenv_ids[i].id == val)
    131  1.1  jdc 				return 1;
    132  1.1  jdc 	} else {
    133  1.1  jdc 		/*
    134  1.1  jdc 		 * Direct config - match via the list of compatible
    135  1.1  jdc 		 * hardware.
    136  1.1  jdc 		 */
    137  1.1  jdc 		if (iic_compat_match(ia, lmenv_compats))
    138  1.1  jdc 			return 1;
    139  1.1  jdc 	}
    140  1.1  jdc 
    141  1.1  jdc 	return 0;
    142  1.1  jdc }
    143  1.1  jdc 
    144  1.1  jdc void
    145  1.1  jdc lmenv_attach(device_t parent, device_t self, void *aux)
    146  1.1  jdc {
    147  1.1  jdc 	struct lmenv_softc *sc = device_private(self);
    148  1.1  jdc 	struct i2c_attach_args *ia = aux;
    149  1.1  jdc 	u_int8_t cmd, data, data2, channel;
    150  1.1  jdc 	int i;
    151  1.1  jdc 
    152  1.1  jdc 	sc->sc_tag = ia->ia_tag;
    153  1.1  jdc 	sc->sc_addr = ia->ia_addr;
    154  1.1  jdc 
    155  1.1  jdc 	iic_acquire_bus(sc->sc_tag, 0);
    156  1.1  jdc 
    157  1.1  jdc 	cmd = LM87_COMPANY_ID;
    158  1.1  jdc 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
    159  1.1  jdc 	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
    160  1.1  jdc 		iic_release_bus(sc->sc_tag, 0);
    161  1.1  jdc 		printf(": cannot read ID register\n");
    162  1.1  jdc 		return;
    163  1.1  jdc 	}
    164  1.1  jdc 	for (i = 0; lmenv_ids[i].id != 0; i++)
    165  1.1  jdc 		if (lmenv_ids[i].id == data)
    166  1.1  jdc 			break;
    167  1.1  jdc 
    168  1.1  jdc 	cmd = LM87_REVISION;
    169  1.1  jdc 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
    170  1.1  jdc 	    sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data, 0)) {
    171  1.1  jdc 		iic_release_bus(sc->sc_tag, 0);
    172  1.1  jdc 		printf(": cannot read revision register\n");
    173  1.1  jdc 		return;
    174  1.1  jdc 	}
    175  1.1  jdc 	printf(": %s rev %x\n", lmenv_ids[i].name, data2);
    176  1.1  jdc 	sc->sc_family = lmenv_ids[i].family;
    177  1.1  jdc 
    178  1.1  jdc 	cmd = LM87_FANDIV;
    179  1.1  jdc 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
    180  1.1  jdc 	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
    181  1.1  jdc 		iic_release_bus(sc->sc_tag, 0);
    182  1.1  jdc 		printf(", cannot read Fan Divisor register\n");
    183  1.1  jdc 		return;
    184  1.1  jdc 	}
    185  1.1  jdc 	sc->sc_fan1_div = 1 << ((data >> 4) & 0x03);
    186  1.1  jdc 	sc->sc_fan2_div = 1 << ((data >> 6) & 0x03);
    187  1.1  jdc 
    188  1.1  jdc 	if (sc->sc_family == 87) {
    189  1.1  jdc 		cmd = LM87_CHANNEL;
    190  1.1  jdc 		if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
    191  1.1  jdc 		    sc->sc_addr, &cmd, sizeof cmd, &channel,
    192  1.1  jdc 		    sizeof channel, 0)) {
    193  1.1  jdc 			iic_release_bus(sc->sc_tag, 0);
    194  1.1  jdc 			printf(", cannot read Channel register\n");
    195  1.1  jdc 			return;
    196  1.1  jdc 		}
    197  1.1  jdc 	} else
    198  1.1  jdc 		channel = 0;
    199  1.1  jdc 
    200  1.1  jdc 	cmd = LM87_CONFIG1;
    201  1.1  jdc 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
    202  1.1  jdc 	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
    203  1.1  jdc 		iic_release_bus(sc->sc_tag, 0);
    204  1.1  jdc 		printf(", cannot read Configuration Register 1\n");
    205  1.1  jdc 		return;
    206  1.1  jdc 	}
    207  1.1  jdc 
    208  1.1  jdc 	/*
    209  1.1  jdc 	 * if chip is not running, try to start it.
    210  1.1  jdc 	 * if it is stalled doing an interrupt, unstall it
    211  1.1  jdc 	 */
    212  1.1  jdc 	data2 = (data | LM87_CONFIG1_START);
    213  1.1  jdc 	data2 = data2 & ~LM87_CONFIG1_INTCLR;
    214  1.1  jdc 
    215  1.1  jdc 	if (data != data2) {
    216  1.1  jdc 		if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
    217  1.1  jdc 		    sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
    218  1.1  jdc 			iic_release_bus(sc->sc_tag, 0);
    219  1.1  jdc 			printf(", cannot write Configuration Register 1\n");
    220  1.1  jdc 			return;
    221  1.1  jdc 		}
    222  1.1  jdc 	}
    223  1.1  jdc 	iic_release_bus(sc->sc_tag, 0);
    224  1.1  jdc 
    225  1.1  jdc 	/* Initialize sensor data. */
    226  1.1  jdc 	sc->sc_sensor[LMENV_2_5V].state = ENVSYS_SINVALID;
    227  1.1  jdc 	sc->sc_sensor[LMENV_2_5V].units = ENVSYS_SVOLTS_DC;
    228  1.1  jdc 	strlcpy(sc->sc_sensor[LMENV_2_5V].desc, "+2.5Vin",
    229  1.1  jdc 	    sizeof(sc->sc_sensor[LMENV_2_5V].desc));
    230  1.1  jdc 
    231  1.1  jdc 	sc->sc_sensor[LMENV_VCCP1].state = ENVSYS_SINVALID;
    232  1.1  jdc 	sc->sc_sensor[LMENV_VCCP1].units = ENVSYS_SVOLTS_DC;
    233  1.1  jdc 	strlcpy(sc->sc_sensor[LMENV_VCCP1].desc, "Vccp1",
    234  1.1  jdc 	    sizeof(sc->sc_sensor[LMENV_VCCP1].desc));
    235  1.1  jdc 
    236  1.1  jdc 	sc->sc_sensor[LMENV_VCC].state = ENVSYS_SINVALID;
    237  1.1  jdc 	sc->sc_sensor[LMENV_VCC].units = ENVSYS_SVOLTS_DC;
    238  1.1  jdc 	strlcpy(sc->sc_sensor[LMENV_VCC].desc, "+Vcc",
    239  1.1  jdc 	    sizeof(sc->sc_sensor[LMENV_VCC].desc));
    240  1.1  jdc 
    241  1.1  jdc 	sc->sc_sensor[LMENV_5V].state = ENVSYS_SINVALID;
    242  1.1  jdc 	sc->sc_sensor[LMENV_5V].units = ENVSYS_SVOLTS_DC;
    243  1.1  jdc 	strlcpy(sc->sc_sensor[LMENV_5V].desc, "+5Vin/Vcc",
    244  1.1  jdc 	    sizeof(sc->sc_sensor[LMENV_5V].desc));
    245  1.1  jdc 
    246  1.1  jdc 	sc->sc_sensor[LMENV_12V].state = ENVSYS_SINVALID;
    247  1.1  jdc 	sc->sc_sensor[LMENV_12V].units = ENVSYS_SVOLTS_DC;
    248  1.1  jdc 	strlcpy(sc->sc_sensor[LMENV_12V].desc, "+12Vin",
    249  1.1  jdc 	    sizeof(sc->sc_sensor[LMENV_12V].desc));
    250  1.1  jdc 
    251  1.1  jdc 	sc->sc_sensor[LMENV_VCCP2].state = ENVSYS_SINVALID;
    252  1.1  jdc 	sc->sc_sensor[LMENV_VCCP2].units = ENVSYS_SVOLTS_DC;
    253  1.1  jdc 	strlcpy(sc->sc_sensor[LMENV_VCCP2].desc, "Vccp2",
    254  1.1  jdc 	    sizeof(sc->sc_sensor[LMENV_VCCP2].desc));
    255  1.1  jdc 
    256  1.1  jdc 	sc->sc_sensor[LMENV_EXT_TEMP].state = ENVSYS_SINVALID;
    257  1.1  jdc 	sc->sc_sensor[LMENV_EXT_TEMP].units = ENVSYS_STEMP;
    258  1.1  jdc 	strlcpy(sc->sc_sensor[LMENV_EXT_TEMP].desc, "External",
    259  1.1  jdc 	    sizeof(sc->sc_sensor[LMENV_EXT_TEMP].desc));
    260  1.1  jdc 	if (sc->sc_family == 81)
    261  1.1  jdc 		sc->sc_sensor[LMENV_EXT_TEMP].state = ENVSYS_SINVALID;
    262  1.1  jdc 
    263  1.1  jdc 	sc->sc_sensor[LMENV_INT_TEMP].state = ENVSYS_SINVALID;
    264  1.1  jdc 	sc->sc_sensor[LMENV_INT_TEMP].units = ENVSYS_STEMP;
    265  1.1  jdc 	strlcpy(sc->sc_sensor[LMENV_INT_TEMP].desc, "Internal",
    266  1.1  jdc 	    sizeof(sc->sc_sensor[LMENV_INT_TEMP].desc));
    267  1.1  jdc 
    268  1.1  jdc 	sc->sc_sensor[LMENV_FAN1].state = ENVSYS_SINVALID;
    269  1.1  jdc 	if (channel & LM87_CHANNEL_AIN1) {
    270  1.1  jdc 		sc->sc_sensor[LMENV_FAN1].units = ENVSYS_SVOLTS_DC;
    271  1.1  jdc 		strlcpy(sc->sc_sensor[LMENV_FAN1].desc, "AIN1",
    272  1.1  jdc 		    sizeof(sc->sc_sensor[LMENV_FAN1].desc));
    273  1.1  jdc 	} else {
    274  1.1  jdc 		sc->sc_sensor[LMENV_FAN1].units = ENVSYS_SFANRPM;
    275  1.1  jdc 		strlcpy(sc->sc_sensor[LMENV_FAN1].desc, "FAN1",
    276  1.1  jdc 		    sizeof(sc->sc_sensor[LMENV_FAN1].desc));
    277  1.1  jdc 	}
    278  1.1  jdc 
    279  1.1  jdc 	sc->sc_sensor[LMENV_FAN2].state = ENVSYS_SINVALID;
    280  1.1  jdc 	if (channel & LM87_CHANNEL_AIN2) {
    281  1.1  jdc 		sc->sc_sensor[LMENV_FAN2].units = ENVSYS_SVOLTS_DC;
    282  1.1  jdc 		strlcpy(sc->sc_sensor[LMENV_FAN2].desc, "AIN2",
    283  1.1  jdc 		    sizeof(sc->sc_sensor[LMENV_FAN2].desc));
    284  1.1  jdc 	} else {
    285  1.1  jdc 		sc->sc_sensor[LMENV_FAN2].units = ENVSYS_SFANRPM;
    286  1.1  jdc 		strlcpy(sc->sc_sensor[LMENV_FAN2].desc, "FAN2",
    287  1.1  jdc 		    sizeof(sc->sc_sensor[LMENV_FAN2].desc));
    288  1.1  jdc 	}
    289  1.1  jdc 
    290  1.1  jdc 	sc->sc_sme = sysmon_envsys_create();
    291  1.1  jdc 	for (i = 0; i < LMENV_NUM_SENSORS; i++)
    292  1.1  jdc 		if (sysmon_envsys_sensor_attach(sc->sc_sme,
    293  1.1  jdc 		    &sc->sc_sensor[i])) {
    294  1.1  jdc 			sysmon_envsys_destroy(sc->sc_sme);
    295  1.1  jdc 			aprint_error_dev(self,
    296  1.1  jdc 			    "unable to attach sensor %d at sysmon\n", i);
    297  1.1  jdc 			return;
    298  1.1  jdc 		}
    299  1.1  jdc         sc->sc_sme->sme_name = device_xname(self);
    300  1.1  jdc         sc->sc_sme->sme_cookie = sc;
    301  1.1  jdc         sc->sc_sme->sme_refresh = lmenv_refresh;
    302  1.1  jdc 	if (sysmon_envsys_register(sc->sc_sme)) {
    303  1.1  jdc 		aprint_error_dev(self,
    304  1.1  jdc 		    "unable to register with sysmon\n");
    305  1.1  jdc 		sysmon_envsys_destroy(sc->sc_sme);
    306  1.1  jdc 		return;
    307  1.1  jdc 	}
    308  1.1  jdc }
    309  1.1  jdc 
    310  1.1  jdc void
    311  1.1  jdc lmenv_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
    312  1.1  jdc {
    313  1.1  jdc 	struct lmenv_softc *sc = sme->sme_cookie;
    314  1.1  jdc 	u_int8_t cmd, data;
    315  1.1  jdc 	u_int tmp;
    316  1.1  jdc 
    317  1.1  jdc 	iic_acquire_bus(sc->sc_tag, 0);
    318  1.1  jdc 
    319  1.1  jdc 	cmd = LM87_2_5V + edata->sensor;
    320  1.1  jdc 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
    321  1.1  jdc 	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
    322  1.1  jdc 		edata->state = ENVSYS_SINVALID;
    323  1.1  jdc 		return;
    324  1.1  jdc 	}
    325  1.1  jdc 
    326  1.1  jdc 	switch (edata->sensor) {
    327  1.1  jdc 	case LMENV_2_5V:
    328  1.1  jdc 		edata->value_cur = 2500000 * data / 192;
    329  1.1  jdc 		edata->state = ENVSYS_SVALID;
    330  1.1  jdc 		break;
    331  1.1  jdc 	case LMENV_5V:
    332  1.1  jdc 		edata->value_cur = 5000000 * data / 192;
    333  1.1  jdc 		edata->state = ENVSYS_SVALID;
    334  1.1  jdc 		break;
    335  1.1  jdc 	case LMENV_12V:
    336  1.1  jdc 		edata->value_cur = 12000000 * data / 192;
    337  1.1  jdc 		edata->state = ENVSYS_SVALID;
    338  1.1  jdc 		break;
    339  1.1  jdc 	case LMENV_VCCP1:
    340  1.1  jdc 	case LMENV_VCCP2:
    341  1.1  jdc 		edata->value_cur = 2700000 * data / 192;
    342  1.1  jdc 		edata->state = ENVSYS_SVALID;
    343  1.1  jdc 		break;
    344  1.1  jdc 	case LMENV_VCC:
    345  1.1  jdc 		edata->value_cur = 3300000 * data / 192;
    346  1.1  jdc 		edata->state = ENVSYS_SVALID;
    347  1.1  jdc 		break;
    348  1.1  jdc 	case LMENV_EXT_TEMP:
    349  1.1  jdc 		if (sc->sc_family == 81) {
    350  1.1  jdc 			edata->state = ENVSYS_SINVALID;
    351  1.1  jdc 			break;		/* missing on LM81 */
    352  1.1  jdc 		}
    353  1.1  jdc 		/* FALLTHROUGH */
    354  1.1  jdc 	case LMENV_INT_TEMP:
    355  1.1  jdc 		if (data == 0x80)
    356  1.1  jdc 			edata->state = ENVSYS_SINVALID;
    357  1.4  jdc 		else {
    358  1.1  jdc 			edata->value_cur = (int8_t)data * 1000000 + 273150000;
    359  1.1  jdc 			edata->state = ENVSYS_SVALID;
    360  1.4  jdc 		}
    361  1.1  jdc 		break;
    362  1.1  jdc 	case LMENV_FAN1:
    363  1.1  jdc 		if (edata->units == ENVSYS_SVOLTS_DC) {
    364  1.1  jdc 			edata->value_cur = 1870000 * data / 192;
    365  1.1  jdc 			edata->state = ENVSYS_SVALID;
    366  1.1  jdc 			break;
    367  1.1  jdc 		}
    368  1.4  jdc 		if (data == 0xff) {
    369  1.4  jdc 			edata->state = ENVSYS_SINVALID;
    370  1.4  jdc 			break;
    371  1.4  jdc 		}
    372  1.1  jdc 		tmp = data * sc->sc_fan1_div;
    373  1.4  jdc 		if (tmp == 0)
    374  1.1  jdc 			edata->state = ENVSYS_SINVALID;
    375  1.4  jdc 		else {
    376  1.1  jdc 			edata->value_cur = 1350000 / tmp;
    377  1.1  jdc 			edata->state = ENVSYS_SVALID;
    378  1.4  jdc 		}
    379  1.1  jdc 		break;
    380  1.1  jdc 	case LMENV_FAN2:
    381  1.1  jdc 		if (edata->units == ENVSYS_SVOLTS_DC) {
    382  1.1  jdc 			edata->value_cur = 1870000 * data / 192;
    383  1.1  jdc 			edata->state = ENVSYS_SVALID;
    384  1.1  jdc 			break;
    385  1.1  jdc 		}
    386  1.4  jdc 		if (data == 0xff) {
    387  1.4  jdc 			edata->state = ENVSYS_SINVALID;
    388  1.4  jdc 			break;
    389  1.4  jdc 		}
    390  1.1  jdc 		tmp = data * sc->sc_fan2_div;
    391  1.4  jdc 		if (tmp == 0)
    392  1.1  jdc 			edata->state = ENVSYS_SINVALID;
    393  1.4  jdc 		else {
    394  1.1  jdc 			edata->value_cur = 1350000 / tmp;
    395  1.1  jdc 			edata->state = ENVSYS_SVALID;
    396  1.4  jdc 		}
    397  1.1  jdc 		break;
    398  1.1  jdc 	default:
    399  1.1  jdc 		edata->state = ENVSYS_SINVALID;
    400  1.1  jdc 		break;
    401  1.1  jdc 	}
    402  1.1  jdc 
    403  1.1  jdc 	iic_release_bus(sc->sc_tag, 0);
    404  1.1  jdc }
    405