Subject: LM77 temperature
To: None <tech-kern@netbsd.org>
From: KIYOHARA Takashi <kiyohara@kk.iij4u.or.jp>
List: tech-kern
Date: 04/30/2006 02:01:43
----Next_Part(Sun_Apr_30_02:01:44_2006_187)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi! all,


LM77 can be supported with this patch.  ;-)

The address is the same though LM77 uses a mask different from LM75.
Some registers are added. 


Besides, is there an idea?

Thanks,
--
kiyohara


----Next_Part(Sun_Apr_30_02:01:44_2006_187)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="lmtemp.diff"

Index: lm75.c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/lm75.c,v
retrieving revision 1.7
diff -u -r1.7 lm75.c
--- lm75.c	4 Apr 2006 19:38:38 -0000	1.7
+++ lm75.c	29 Apr 2006 16:56:42 -0000
@@ -49,12 +49,13 @@
 	struct device sc_dev;
 	i2c_tag_t sc_tag;
 	int sc_address;
-	int sc_is_ds75;
 
 	struct envsys_tre_data sc_sensor[1];
 	struct envsys_basic_info sc_info[1];
 
 	struct sysmon_envsys sc_sysmon;
+
+	uint32_t (*sc_lmtemp_decode)(const uint8_t *);
 };
 
 static int  lmtemp_match(struct device *, struct cfdata *, void *);
@@ -76,13 +77,45 @@
 static int lmtemp_config_write(struct lmtemp_softc *, uint8_t);
 static uint32_t lmtemp_decode_lm75(const uint8_t *);
 static uint32_t lmtemp_decode_ds75(const uint8_t *);
+static uint32_t lmtemp_decode_lm77(const uint8_t *);
+
+enum {
+	lmtemp_lm75 = 0,
+	lmtemp_ds75,
+	lmtemp_lm77,
+};
+static const struct {
+	int lmtemp_type;
+	const char *lmtemp_name;
+	int lmtemp_addrmask;
+	int lmtemp_addr;
+	uint32_t (*lmtemp_decode)(const uint8_t *);
+} lmtemptbl[] = {
+	{ lmtemp_lm75,	"LM75",
+	    LM75_ADDRMASK,	LM75_ADDR,	lmtemp_decode_lm75 },
+	{ lmtemp_ds75,	"DS75",
+	    LM75_ADDRMASK,	LM75_ADDR,	lmtemp_decode_ds75 },
+	{ lmtemp_lm77,	"LM77",
+	    LM77_ADDRMASK,	LM77_ADDR,	lmtemp_decode_lm77 },
+
+	{ -1,		NULL,
+	    0,			0,		NULL }
+};
 
 static int
 lmtemp_match(struct device *parent, struct cfdata *cf, void *aux)
 {
 	struct i2c_attach_args *ia = aux;
+	int i;
+
+	for (i = 0; lmtemptbl[i].lmtemp_type != -1 ; i++)
+		if (lmtemptbl[i].lmtemp_type == cf->cf_flags)
+			break;
+	if (lmtemptbl[i].lmtemp_type == -1)
+		return (0);
 
-	if ((ia->ia_addr & LM75_ADDRMASK) == LM75_ADDR)
+	if ((ia->ia_addr & lmtemptbl[i].lmtemp_addrmask) ==
+	    lmtemptbl[i].lmtemp_addr)
 		return (1);
 
 	return (0);
@@ -93,15 +126,18 @@
 {
 	struct lmtemp_softc *sc = device_private(self);
 	struct i2c_attach_args *ia = aux;
-	int ptype;
+	int ptype, i;
+
+	for (i = 0; lmtemptbl[i].lmtemp_type != -1 ; i++)
+		if (lmtemptbl[i].lmtemp_type ==
+		    device_cfdata(&sc->sc_dev)->cf_flags)
+			break;
 
 	sc->sc_tag = ia->ia_tag;
 	sc->sc_address = ia->ia_addr;
-	sc->sc_is_ds75 = device_cfdata(&sc->sc_dev)->cf_flags & 1;
 
 	aprint_naive(": Temperature Sensor\n");
-	aprint_normal(": %s Temperature Sensor\n",
-	    (sc->sc_is_ds75) ? "DS75" : "LM75");
+	aprint_normal(": %s Temperature Sensor\n", lmtemptbl[i].lmtemp_name);
 
 	/* Set the configuration of the LM75 to defaults. */
 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
@@ -126,6 +162,8 @@
 	    ptype != PROP_STRING)
 		strcpy(sc->sc_info[0].desc, sc->sc_dev.dv_xname);
 
+	sc->sc_lmtemp_decode = lmtemptbl[i].lmtemp_decode;
+
 	/* Hook into system monitor. */
 	sc->sc_sysmon.sme_ranges = lmtemp_ranges;
 	sc->sc_sysmon.sme_sensor_info = sc->sc_info;
@@ -169,11 +207,7 @@
 	if (error)
 		return (error);
 
-	if (sc->sc_is_ds75)
-		*valp = lmtemp_decode_ds75(buf);
-	else
-		*valp = lmtemp_decode_lm75(buf);
-
+	*valp = sc->sc_lmtemp_decode(buf);
 	return (0);
 }
 
@@ -276,3 +310,23 @@
 	return (temp * 62500 + 273150000);
 }
 
+static uint32_t
+lmtemp_decode_lm77(const uint8_t *buf)
+{
+	int temp;
+	uint32_t val;
+
+	/*
+	 * Describe each bits of temperature registers on LM77.
+	 *   D15 - D12:	Sign
+	 *   D11 - D3 :	Bit8(MSB) - Bit0
+	 */
+	temp = (int8_t)buf[0];
+	temp = (temp << 5) | (buf[1] >> 3);
+
+	/* Temp is given in 1/2 deg. C, we convert to uK. */
+	val = temp * 500000 + 273150000;
+
+	return (val);
+}
+
Index: lm75reg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/lm75reg.h,v
retrieving revision 1.2
diff -u -r1.2 lm75reg.h
--- lm75reg.h	11 Dec 2005 12:21:22 -0000	1.2
+++ lm75reg.h	29 Apr 2006 16:56:42 -0000
@@ -45,6 +45,8 @@
  */
 #define	LM75_ADDRMASK		0x78
 #define	LM75_ADDR		0x48
+#define	LM77_ADDRMASK		0x7c
+#define	LM77_ADDR		0x48
 
 /*
  * Temperature on the LM75 is represented by a 9-bit two's complement
@@ -65,6 +67,11 @@
 #define	LM75_REG_THYST_SET_POINT	0x02
 #define	LM75_REG_TOS_SET_POINT		0x03
 
+#define	LM77_REG_TCRIT_SET_POINT	0x03
+#define	LM77_REG_TLOW_SET_POINT		0x04
+#define	LM77_REG_THIGH_SET_POINT	0x05
+
+
 #define	LM75_TEMP_LEN			2	/* 2 data bytes */
 
 #define	LM75_CONFIG_SHUTDOWN		0x01
@@ -75,4 +82,8 @@
 #define	LM75_CONFIG_FAULT_QUEUE_4	(2 << 3)
 #define	LM75_CONFIG_FAULT_QUEUE_6	(3 << 3)
 
+#define	LM77_CONFIG_TCRITAPOLARITY	0x04
+#define	LM77_CONFIG_INTPOLARITY		0x08
+#define	LM77_CONFIG_FAULT_QUEUE		LM75_CONFIG_FAULT_QUEUE_4
+
 #endif /* _DEV_I2C_LM75REG_H_ */

----Next_Part(Sun_Apr_30_02:01:44_2006_187)----