Module Name: src Committed By: msaitoh Date: Tue Jul 26 07:30:16 UTC 2016
Modified Files: src/sys/dev/i2c: sdtemp.c sdtemp_reg.h Log Message: Reviewed and OK'd by pgoyette: - Add supoprt for Atmel AT30TS00, AT30TSE004, Giantec GT30TS00, GT34TS02, Microchip MCP9804, MCP98244, IDT TS3000GB[02], TS3001GB2, TSE2004GB2, and On Semiconductor CAT34TS04. Taken from OpenBSD. - Add IDT TSE2002GB2. - Check the temperature resolution field in the capability register instead of the hard coded value in the match table. With this change, some devices' temperature resolution would be fixed. - The resolution register is a vendor specific register. - All of IDT devices have the resolution register. - The address of the resolution register of Microchip MCP98244 is different from other Microchip devices. - Show accuracy, range, resolution and timeout with aprint_normal(). - Show timeout with aprint_debug(). To generate a diff of this commit: cvs rdiff -u -r1.27 -r1.28 src/sys/dev/i2c/sdtemp.c cvs rdiff -u -r1.8 -r1.9 src/sys/dev/i2c/sdtemp_reg.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/i2c/sdtemp.c diff -u src/sys/dev/i2c/sdtemp.c:1.27 src/sys/dev/i2c/sdtemp.c:1.28 --- src/sys/dev/i2c/sdtemp.c:1.27 Tue Jul 26 07:25:51 2016 +++ src/sys/dev/i2c/sdtemp.c Tue Jul 26 07:30:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: sdtemp.c,v 1.27 2016/07/26 07:25:51 msaitoh Exp $ */ +/* $NetBSD: sdtemp.c,v 1.28 2016/07/26 07:30:16 msaitoh Exp $ */ /* * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sdtemp.c,v 1.27 2016/07/26 07:25:51 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sdtemp.c,v 1.28 2016/07/26 07:30:16 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -55,6 +55,9 @@ struct sdtemp_softc { sysmon_envsys_lim_t sc_deflims; uint32_t sc_defprops; int sc_resolution; + uint16_t sc_mfgid; + uint16_t sc_devid; + uint16_t sc_devid_masked; uint16_t sc_capability; }; @@ -79,12 +82,15 @@ static int sdtemp_write_16(struct sdtemp static uint32_t sdtemp_decode_temp(struct sdtemp_softc *, uint16_t); static bool sdtemp_pmf_suspend(device_t, const pmf_qual_t *); static bool sdtemp_pmf_resume(device_t, const pmf_qual_t *); +/* Device dependent config functions */ +static void sdtemp_config_mcp(struct sdtemp_softc *); +static void sdtemp_config_idt(struct sdtemp_softc *); struct sdtemp_dev_entry { const uint16_t sdtemp_mfg_id; - const uint16_t sdtemp_devrev; - const uint16_t sdtemp_mask; - const uint8_t sdtemp_resolution; + const uint16_t sdtemp_devrev; + const uint16_t sdtemp_mask; + void (*sdtemp_config)(struct sdtemp_softc *); const char *sdtemp_desc; }; @@ -92,47 +98,78 @@ struct sdtemp_dev_entry { #define __UK2C(uk) (((uk) - 273150000) / 1000000) -/* - * List of devices known to conform to JEDEC JC42.4 - * - * NOTE: A non-negative value for resolution indicates that the sensor - * resolution is fixed at that number of fractional bits; a negative - * value indicates that the sensor needs to be configured. In either - * case, trip-point registers are fixed at two-bit (0.25C) resolution. - */ +/* List of devices known to conform to JEDEC JC42.4 */ + +#define CMCP sdtemp_config_mcp +#define CIDT sdtemp_config_idt + static const struct sdtemp_dev_entry sdtemp_dev_table[] = { - { MAXIM_MANUFACTURER_ID, MAX_6604_DEVICE_ID, MAX_6604_MASK, 3, + { AT_MANUFACTURER_ID, AT_30TS00_DEVICE_ID, AT_30TS00_MASK, NULL, + "Atmel AT30TS00" }, + { AT2_MANUFACTURER_ID, AT2_30TSE004_DEVICE_ID, AT2_30TSE004_MASK, NULL, + "Atmel AT30TSE004" }, + { GT_MANUFACTURER_ID, GT_30TS00_DEVICE_ID, GT_30TS00_MASK, NULL, + "Giantec GT30TS00" }, + { GT2_MANUFACTURER_ID, GT2_34TS02_DEVICE_ID, GT2_34TS02_MASK, NULL, + "Giantec GT34TS02" }, + { MAXIM_MANUFACTURER_ID, MAX_6604_DEVICE_ID, MAX_6604_MASK, NULL, "Maxim MAX6604" }, - { MCP_MANUFACTURER_ID, MCP_9805_DEVICE_ID, MCP_9805_MASK, 2, + { MCP_MANUFACTURER_ID, MCP_9804_DEVICE_ID, MCP_9804_MASK, CMCP, + "Microchip Tech MCP9804" }, + { MCP_MANUFACTURER_ID, MCP_9805_DEVICE_ID, MCP_9805_MASK, NULL, "Microchip Tech MCP9805/MCP9843" }, - { MCP_MANUFACTURER_ID, MCP_98243_DEVICE_ID, MCP_98243_MASK, -4, - "Microchip Tech MCP98243" }, - { MCP_MANUFACTURER_ID, MCP_98242_DEVICE_ID, MCP_98242_MASK, -4, + { MCP_MANUFACTURER_ID, MCP_98242_DEVICE_ID, MCP_98242_MASK, CMCP, "Microchip Tech MCP98242" }, - { ADT_MANUFACTURER_ID, ADT_7408_DEVICE_ID, ADT_7408_MASK, 4, + { MCP_MANUFACTURER_ID, MCP_98243_DEVICE_ID, MCP_98243_MASK, CMCP, + "Microchip Tech MCP98243" }, + { MCP_MANUFACTURER_ID, MCP_98244_DEVICE_ID, MCP_98244_MASK, CMCP, + "Microchip Tech MCP98244" }, + { ADT_MANUFACTURER_ID, ADT_7408_DEVICE_ID, ADT_7408_MASK, NULL, "Analog Devices ADT7408" }, - { NXP_MANUFACTURER_ID, NXP_SE98_DEVICE_ID, NXP_SE98_MASK, 3, + { NXP_MANUFACTURER_ID, NXP_SE98_DEVICE_ID, NXP_SE98_MASK, NULL, "NXP Semiconductors SE97B/SE98" }, - { NXP_MANUFACTURER_ID, NXP_SE97_DEVICE_ID, NXP_SE97_MASK, 3, + { NXP_MANUFACTURER_ID, NXP_SE97_DEVICE_ID, NXP_SE97_MASK, NULL, "NXP Semiconductors SE97" }, - { STTS_MANUFACTURER_ID, STTS_424E_DEVICE_ID, STTS_424E_MASK, 2, - "STmicroelectronics STTS424E" }, - { STTS_MANUFACTURER_ID, STTS_424_DEVICE_ID, STTS_424_MASK, 2, - "STmicroelectronics STTS424" }, - { STTS_MANUFACTURER_ID, STTS_2002_DEVICE_ID, STTS_2002_MASK, 2, - "STmicroelectronics STTS2002" }, - { STTS_MANUFACTURER_ID, STTS_2004_DEVICE_ID, STTS_2004_MASK, 2, - "STmicroelectronics STTS2004" }, - { STTS_MANUFACTURER_ID, STTS_3000_DEVICE_ID, STTS_3000_MASK, 2, - "STmicroelectronics STTS3000" }, - { CAT_MANUFACTURER_ID, CAT_34TS02_DEVICE_ID, CAT_34TS02_MASK, 4, + { STTS_MANUFACTURER_ID, STTS_424E_DEVICE_ID, STTS_424E_MASK, NULL, + "STmicroelectronics STTS424E" }, + { STTS_MANUFACTURER_ID, STTS_424_DEVICE_ID, STTS_424_MASK, NULL, + "STmicroelectronics STTS424" }, + { STTS_MANUFACTURER_ID, STTS_2002_DEVICE_ID, STTS_2002_MASK, NULL, + "STmicroelectronics STTS2002" }, + { STTS_MANUFACTURER_ID, STTS_2004_DEVICE_ID, STTS_2004_MASK, NULL, + "STmicroelectronics STTS2004" }, + { STTS_MANUFACTURER_ID, STTS_3000_DEVICE_ID, STTS_3000_MASK, NULL, + "STmicroelectronics STTS3000" }, + { CAT_MANUFACTURER_ID, CAT_34TS02_DEVICE_ID, CAT_34TS02_MASK, NULL, "Catalyst CAT34TS02/CAT6095" }, - { CAT_MANUFACTURER_ID, CAT_34TS02C_DEVICE_ID, CAT_34TS02C_MASK, 4, + { CAT_MANUFACTURER_ID, CAT_34TS02C_DEVICE_ID, CAT_34TS02C_MASK, NULL, "Catalyst CAT34TS02C" }, - { IDT_MANUFACTURER_ID, IDT_TS3000B3_DEVICE_ID, IDT_TS3000B3_MASK, 4, + { CAT_MANUFACTURER_ID, CAT_34TS04_DEVICE_ID, CAT_34TS04_MASK, NULL, + "Catalyst CAT34TS04" }, + { IDT_MANUFACTURER_ID, IDT_TSE2002GB2_DEVICE_ID,IDT_TSE2002GB2_MASK, CIDT, + "Integrated Device Technology TSE2002GB2" }, + { IDT_MANUFACTURER_ID, IDT_TSE2004GB2_DEVICE_ID,IDT_TSE2004GB2_MASK, NULL, + "Integrated Device Technology TSE2004GB2" }, + { IDT_MANUFACTURER_ID, IDT_TS3000B3_DEVICE_ID, IDT_TS3000B3_MASK, CIDT, "Integrated Device Technology TS3000B3/TSE2002B3" }, - { 0, 0, 0, 2, "Unknown" } + { IDT_MANUFACTURER_ID, IDT_TS3000GB0_DEVICE_ID, IDT_TS3000GB0_MASK, CIDT, + "Integrated Device Technology TS3000GB0" }, + { IDT_MANUFACTURER_ID, IDT_TS3000GB2_DEVICE_ID, IDT_TS3000GB2_MASK, CIDT, + "Integrated Device Technology TS3000GB2" }, + { IDT_MANUFACTURER_ID, IDT_TS3001GB2_DEVICE_ID, IDT_TS3001GB2_MASK, CIDT, + "Integrated Device Technology TS3001GB2" }, + { 0, 0, 0, NULL, "Unknown" } +}; + +#undef CMCP +#undef CIDT + +static const char *temp_resl[] = { + "0.5C", + "0.25C", + "0.125C", + "0.0625C" }; static int @@ -204,9 +241,10 @@ sdtemp_attach(device_t parent, device_t aprint_error(": attach error %d\n", error); return; } + sc->sc_mfgid = mfgid; + sc->sc_devid = devid; i = sdtemp_lookup(mfgid, devid); - sc->sc_resolution = - sdtemp_dev_table[i].sdtemp_resolution; + sc->sc_devid_masked = devid & sdtemp_dev_table[i].sdtemp_mask; aprint_naive(": Temp Sensor\n"); aprint_normal(": %s Temp Sensor\n", sdtemp_dev_table[i].sdtemp_desc); @@ -216,11 +254,38 @@ sdtemp_attach(device_t parent, device_t "mfg 0x%04x dev 0x%04x rev 0x%02x at addr 0x%02x\n", mfgid, devid, devid & 0xff, ia->ia_addr); + error = sdtemp_read_16(sc, SDTEMP_REG_CAPABILITY, &sc->sc_capability); + aprint_debug_dev(self, "capability reg = %04x\n", sc->sc_capability); + sc->sc_resolution + = __SHIFTOUT(sc->sc_capability, SDTEMP_CAP_RESOLUTION); + /* + * Call device dependent function here. Currently, it's used for + * the resolution. + * + * IDT's devices and some Microchip's devices have the resolution + * register in the vendor specific registers area. The devices' + * resolution bits in the capability register are not the maximum + * resolution but the current vaule of the setting. + */ + if (sdtemp_dev_table[i].sdtemp_config != NULL) + sdtemp_dev_table[i].sdtemp_config(sc); + + aprint_normal_dev(self, "%s accuracy", + (sc->sc_capability & SDTEMP_CAP_ACCURACY_1C) ? "high" : "default"); + if ((sc->sc_capability & SDTEMP_CAP_WIDER_RANGE) != 0) + aprint_normal(", wider range"); + aprint_normal(", %s resolution", temp_resl[sc->sc_resolution]); + if ((sc->sc_capability & SDTEMP_CAP_VHV) != 0) + aprint_debug(", high voltage standoff"); + aprint_debug(", %s timeout", + (sc->sc_capability & SDTEMP_CAP_TMOUT) ? "25-35ms" : "10-60ms"); + if ((sc->sc_capability & SDTEMP_CAP_EVSD) != 0) + aprint_normal(", event with shutdown"); + aprint_normal("\n"); /* * Alarm capability is required; if not present, this is likely * not a real sdtemp device. */ - error = sdtemp_read_16(sc, SDTEMP_REG_CAPABILITY, &sc->sc_capability); if (error != 0 || (sc->sc_capability & SDTEMP_CAP_HAS_ALARM) == 0) { iic_release_bus(sc->sc_tag, 0); aprint_error_dev(self, @@ -235,19 +300,6 @@ sdtemp_attach(device_t parent, device_t error); return; } - /* If variable resolution, set to max */ - if (sc->sc_resolution < 0) { - sc->sc_resolution = ~sc->sc_resolution; - error = sdtemp_write_16(sc, SDTEMP_REG_RESOLUTION, - sc->sc_resolution & 0x3); - if (error != 0) { - iic_release_bus(sc->sc_tag, 0); - aprint_error_dev(self, - "error %d writing resolution register\n", error); - return; - } else - sc->sc_resolution++; - } iic_release_bus(sc->sc_tag, 0); /* Hook us into the sysmon_envsys subsystem */ @@ -468,7 +520,7 @@ sdtemp_decode_temp(struct sdtemp_softc * temp |= SDTEMP_TEMP_SIGN_EXT; /* Mask off only bits valid within current resolution */ - temp &= ~(0xf >> sc->sc_resolution); + temp &= ~(0x7 >> sc->sc_resolution); /* Treat as signed and extend to 32-bits */ stemp = (int16_t)temp; @@ -583,3 +635,61 @@ sdtemp_modcmd(modcmd_t cmd, void *opaque return ENOTTY; } } + +/* Device dependent config functions */ + +static void +sdtemp_config_mcp(struct sdtemp_softc *sc) +{ + int rv; + uint8_t resolreg; + + /* Note that MCP9805 has no resolution register */ + switch (sc->sc_devid_masked) { + case MCP_9804_DEVICE_ID: + case MCP_98242_DEVICE_ID: + case MCP_98243_DEVICE_ID: + resolreg = SDTEMP_REG_MCP_RESOLUTION_9804; + break; + case MCP_98244_DEVICE_ID: + resolreg = SDTEMP_REG_MCP_RESOLUTION_98244; + break; + default: + aprint_error("%s: %s: unknown device ID (%04hx)\n", + device_xname(sc->sc_dev), __func__, sc->sc_devid_masked); + return; + } + + /* + * Set resolution to the max. + * + * Even if it fails, the resolution will be the default. It's not a + * fatal error. + */ + rv = sdtemp_write_16(sc, resolreg, SDTEMP_CAP_RESOLUTION_MAX); + if (rv == 0) + sc->sc_resolution = SDTEMP_CAP_RESOLUTION_MAX; + else + aprint_error("%s: error %d writing resolution register\n", + device_xname(sc->sc_dev), rv); +} + +static void +sdtemp_config_idt(struct sdtemp_softc *sc) +{ + int rv; + + /* + * Set resolution to the max. + * + * Even if it fails, the resolution will be the default. It's not a + * fatal error. + */ + rv = sdtemp_write_16(sc, SDTEMP_REG_IDT_RESOLUTION, + __SHIFTIN(SDTEMP_CAP_RESOLUTION_MAX, SDTEMP_CAP_RESOLUTION)); + if (rv == 0) + sc->sc_resolution = SDTEMP_CAP_RESOLUTION_MAX; + else + aprint_error("%s: error %d writing resolution register\n", + device_xname(sc->sc_dev), rv); +} Index: src/sys/dev/i2c/sdtemp_reg.h diff -u src/sys/dev/i2c/sdtemp_reg.h:1.8 src/sys/dev/i2c/sdtemp_reg.h:1.9 --- src/sys/dev/i2c/sdtemp_reg.h:1.8 Wed May 20 00:43:28 2015 +++ src/sys/dev/i2c/sdtemp_reg.h Tue Jul 26 07:30:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: sdtemp_reg.h,v 1.8 2015/05/20 00:43:28 msaitoh Exp $ */ +/* $NetBSD: sdtemp_reg.h,v 1.9 2016/07/26 07:30:16 msaitoh Exp $ */ /* * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -47,13 +47,16 @@ #define SDTEMP_REG_AMBIENT_TEMP 0x05 #define SDTEMP_REG_MFG_ID 0x06 #define SDTEMP_REG_DEV_REV 0x07 -#define SDTEMP_REG_RESOLUTION 0x08 #define SDTEMP_CAP_HAS_ALARM 0x0001 #define SDTEMP_CAP_ACCURACY_1C 0x0002 #define SDTEMP_CAP_WIDER_RANGE 0x0004 #define SDTEMP_CAP_RESOLUTION 0x0018 -#define SDTEMP_CAP_RES_SHIFT 3 +#define SDTEMP_CAP_RESOLUTION_MAX 0x0003 /* 0.0625C */ +#define SDTEMP_CAP_VHV 0x0020 +#define SDTEMP_CAP_TMOUT 0x0040 +#define SDTEMP_CAP_EVSD 0x0080 + #define SDTEMP_CONFIG_EVENT_MODE 0x0001 #define SDTEMP_CONFIG_EVENT_POL_AH 0x0002 @@ -91,34 +94,77 @@ /* * Devices known to conform to JEDEC JC42.4 */ + +/* Atmel */ +#define AT_MANUFACTURER_ID 0x001f +#define AT_30TS00_DEVICE_ID 0x8201 /* Also matches 002A and 002B */ +#define AT_30TS00_MASK 0xFFFF + +#define AT2_MANUFACTURER_ID 0x1114 +#define AT2_30TSE004_DEVICE_ID 0x2200 +#define AT2_30TSE004_MASK 0xFFFF + +/* Giantec Semiconductor */ +#define GT_MANUFACTURER_ID 0x1C68 +#define GT_30TS00_DEVICE_ID 0x2201 +#define GT_30TS00_MASK 0xFFFF + +#define GT2_MANUFACTURER_ID 0x132D +#define GT2_34TS02_DEVICE_ID 0x3300 +#define GT2_34TS02_MASK 0xFFFF + +/* Maxim */ #define MAXIM_MANUFACTURER_ID 0x004D #define MAX_6604_DEVICE_ID 0x3E00 #define MAX_6604_MASK 0xFFFF +/* Microchip */ #define MCP_MANUFACTURER_ID 0x0054 +#define MCP_9804_DEVICE_ID 0x0200 +#define MCP_9804_MASK 0xFFFC #define MCP_9805_DEVICE_ID 0x0000 /* Also matches MCP9843 */ #define MCP_9805_MASK 0xFFFE #define MCP_98242_DEVICE_ID 0x2000 #define MCP_98242_MASK 0xFFFC #define MCP_98243_DEVICE_ID 0x2100 #define MCP_98243_MASK 0xFFFC +#define MCP_98244_DEVICE_ID 0x2200 +#define MCP_98244_MASK 0xFFFC -/* According to datasheets, SE97 and SE98 have same ID */ +#define SDTEMP_REG_MCP_RESOLUTION_9804 0x08 /* 9804, 9824[23] */ +#define SDTEMP_REG_MCP_RESOLUTION_98244 0x09 /* 98244 */ +/* NXP Semiconductors */ +/* According to datasheets, SE97 and SE98 have same ID */ #define NXP_MANUFACTURER_ID 0x1131 #define NXP_SE98_DEVICE_ID 0xA100 #define NXP_SE98_MASK 0xFFFC #define NXP_SE97_DEVICE_ID 0xA200 #define NXP_SE97_MASK 0xFFFC +/* Analog Devices */ #define ADT_MANUFACTURER_ID 0x11D4 #define ADT_7408_DEVICE_ID 0x8001 #define ADT_7408_MASK 0xFFFF +/* IDT */ #define IDT_MANUFACTURER_ID 0x00B3 #define IDT_TS3000B3_DEVICE_ID 0x2903 /* Also matches TSE2002B3 */ #define IDT_TS3000B3_MASK 0xFFFF +#define IDT_TS3000GB0_DEVICE_ID 0x2913 +#define IDT_TS3000GB0_MASK 0xFFFF +#define IDT_TS3000GB2_DEVICE_ID 0x2912 +#define IDT_TS3000GB2_MASK 0xFFFF +#define IDT_TS3001GB2_DEVICE_ID 0x3001 +#define IDT_TS3001GB2_MASK 0xFFFF +#define IDT_TSE2002GB2_DEVICE_ID 0x2912 +#define IDT_TSE2002GB2_MASK 0xFFFF +#define IDT_TSE2004GB2_DEVICE_ID 0x2214 +#define IDT_TSE2004GB2_MASK 0xFFFF + +#define SDTEMP_REG_IDT_RESOLUTION 0x08 /* 2002 */ +/* STmicroelectronics */ #define STTS_MANUFACTURER_ID 0x104A #define STTS_424_DEVICE_ID 0x0101 #define STTS_424_MASK 0xFFFF @@ -131,12 +177,14 @@ #define STTS_2004_DEVICE_ID 0x2201 #define STTS_2004_MASK 0xFFFF +/* On Semiconductor (Catalyst) */ /* According to datasheets, both the CAT6095 and CAT34TS02 have the same ID */ - #define CAT_MANUFACTURER_ID 0x1B09 #define CAT_34TS02_DEVICE_ID 0x0800 #define CAT_34TS02_MASK 0xFFE0 #define CAT_34TS02C_DEVICE_ID 0x0a00 #define CAT_34TS02C_MASK 0xFFFF +#define CAT_34TS04_DEVICE_ID 0x2200 +#define CAT_34TS04_MASK 0xFFFF #endif /* _DEV_I2C_SDTEMPREG_H */