summaryrefslogtreecommitdiff
path: root/drivers/hwmon/adm1021.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-06-20 02:14:59 +0200
committerArnd Bergmann <arnd@arndb.de>2013-06-20 02:15:45 +0200
commite5051b8472c2fde91e44d906c9a2e516a10b60b2 (patch)
treeb7c27378ca981a7bcf86639db7b0cde834feb0b6 /drivers/hwmon/adm1021.c
parentc3b693d1d63444afe4fbf809d8a311b63741e503 (diff)
parent3bfbc6cd9b41f937a134ba65a4a1eefba062b9a8 (diff)
Merge tag 'imx-soc-3.11' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/soc
From Shawn Guo: imx soc changes for 3.11: * New SoCs i.MX6 Sololite and Vybrid VF610 support * imx5 and imx6 clock fixes and additions * Update clock driver to use of_clk_init() function * Refactor restart routine mxc_restart() to get it work for DT boot as well * Clean up mxc specific ulpi access ops * imx defconfig updates * tag 'imx-soc-3.11' of git://git.linaro.org/people/shawnguo/linux-2.6: (29 commits) ARM: imx_v6_v7_defconfig: Enable Vybrid VF610 ARM: imx_v6_v7_defconfig: Enable imx-wm8962 by default ARM: clk-imx6qdl: Add clko1 configuration for imx6qdl-sabresd ARM: imx_v6_v7_defconfig: Enable PWM and backlight options ARM: imx: Remove mxc specific ulpi access ops ARM: imx: add initial support for VF610 ARM: imx: add VF610 clock support ARM: imx_v6_v7_defconfig: enable parallel display ARM: imx: clk: No need to initialize phandle struct ARM: imx: irq-common: Include header to avoid sparse warning ARM: imx: Enable mx6 solo-lite support ARM: imx6: use common of_clk_init() call to initialize clocks ARM: imx6q: call of_clk_init() to register fixed rate clocks ARM: imx: imx_v6_v7_defconfig: Select CONFIG_DRM_IMX_TVE ARM: i.MX6: clk: add different DualLite MLB clock config ARM i.MX5: Add S/PDIF clocks ARM i.MX53: Add SATA clock ARM: imx6q: clk: add the eim_slow clock ARM: imx: remove MLB PLL from pllv3 ARM: imx: disable pll8_mlb in mx6q_clks ... Conflicts: arch/arm/Kconfig.debug (simple add/add conflict) Includes an update to 3.10-rc6 Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/hwmon/adm1021.c')
-rw-r--r--drivers/hwmon/adm1021.c58
1 files changed, 50 insertions, 8 deletions
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index 7e76922a4ba9..f920619cd6da 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -331,26 +331,68 @@ static int adm1021_detect(struct i2c_client *client,
man_id = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID);
dev_id = i2c_smbus_read_byte_data(client, ADM1021_REG_DEV_ID);
+ if (man_id < 0 || dev_id < 0)
+ return -ENODEV;
+
if (man_id == 0x4d && dev_id == 0x01)
type_name = "max1617a";
else if (man_id == 0x41) {
if ((dev_id & 0xF0) == 0x30)
type_name = "adm1023";
- else
+ else if ((dev_id & 0xF0) == 0x00)
type_name = "adm1021";
+ else
+ return -ENODEV;
} else if (man_id == 0x49)
type_name = "thmc10";
else if (man_id == 0x23)
type_name = "gl523sm";
else if (man_id == 0x54)
type_name = "mc1066";
- /* LM84 Mfr ID in a different place, and it has more unused bits */
- else if (conv_rate == 0x00
- && (config & 0x7F) == 0x00
- && (status & 0xAB) == 0x00)
- type_name = "lm84";
- else
- type_name = "max1617";
+ else {
+ int lte, rte, lhi, rhi, llo, rlo;
+
+ /* extra checks for LM84 and MAX1617 to avoid misdetections */
+
+ llo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(0));
+ rlo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(1));
+
+ /* fail if any of the additional register reads failed */
+ if (llo < 0 || rlo < 0)
+ return -ENODEV;
+
+ lte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(0));
+ rte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(1));
+ lhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(0));
+ rhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(1));
+
+ /*
+ * Fail for negative temperatures and negative high limits.
+ * This check also catches read errors on the tested registers.
+ */
+ if ((s8)lte < 0 || (s8)rte < 0 || (s8)lhi < 0 || (s8)rhi < 0)
+ return -ENODEV;
+
+ /* fail if all registers hold the same value */
+ if (lte == rte && lte == lhi && lte == rhi && lte == llo
+ && lte == rlo)
+ return -ENODEV;
+
+ /*
+ * LM84 Mfr ID is in a different place,
+ * and it has more unused bits.
+ */
+ if (conv_rate == 0x00
+ && (config & 0x7F) == 0x00
+ && (status & 0xAB) == 0x00) {
+ type_name = "lm84";
+ } else {
+ /* fail if low limits are larger than high limits */
+ if ((s8)llo > lhi || (s8)rlo > rhi)
+ return -ENODEV;
+ type_name = "max1617";
+ }
+ }
pr_debug("Detected chip %s at adapter %d, address 0x%02x.\n",
type_name, i2c_adapter_id(adapter), client->addr);