11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 219f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * ds1621.c - Part of lm_sensors, Linux kernel modules for hardware 319f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * monitoring 419f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * Christian W. Zuckschwerdt <zany@triq.net> 2000-11-23 519f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * based on lm75.c by Frodo Looijaard <frodol@dds.nl> 619f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with 77c81c60f3789a082e141d7a013392af5f78db16aJean Delvare * the help of Jean Delvare <jdelvare@suse.de> 819f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * 9cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * The DS1621 device is a digital temperature/thermometer with 9-bit 10cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * resolution, a thermal alarm output (Tout), and user-defined minimum 11cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * and maximum temperature thresholds (TH and TL). 12cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * 13260f81ffc1b9f09dde355caa09e4b312756666f0Robert Coulson * The DS1625, DS1631, DS1721, and DS1731 are pin compatible with the DS1621 14260f81ffc1b9f09dde355caa09e4b312756666f0Robert Coulson * and similar in operation, with slight variations as noted in the device 15cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * datasheets (please refer to www.maximintegrated.com for specific 16cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * device information). 17cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * 18cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * Since the DS1621 was the first chipset supported by this driver, 19cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * most comments will refer to this chipset, but are actually general 20cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * and concern all supported chipsets, unless mentioned otherwise. 21cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * 2219f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * This program is free software; you can redistribute it and/or modify 2319f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * it under the terms of the GNU General Public License as published by 2419f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * the Free Software Foundation; either version 2 of the License, or 2519f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * (at your option) any later version. 2619f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * 2719f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * This program is distributed in the hope that it will be useful, 2819f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 2919f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 3019f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * GNU General Public License for more details. 3119f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * 3219f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * You should have received a copy of the GNU General Public License 3319f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * along with this program; if not, write to the Free Software 3419f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 3519f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/jiffies.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h> 42943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/hwmon.h> 4346a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare#include <linux/hwmon-sysfs.h> 44943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/err.h> 459a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar#include <linux/mutex.h> 46a5ebe668add5f76ed8f01f752b37cfa164a26a30Jean Delvare#include <linux/sysfs.h> 47cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson#include <linux/kernel.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 49cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson/* Supported devices */ 50260f81ffc1b9f09dde355caa09e4b312756666f0Robert Coulsonenum chips { ds1621, ds1625, ds1631, ds1721, ds1731 }; 51cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Insmod parameters */ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int polarity = -1; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(polarity, int, 0); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low"); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 57cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson/* 58cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * The Configuration/Status register 59cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * 60cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * - DS1621: 61cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * 7 6 5 4 3 2 1 0 62cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * |Done|THF |TLF |NVB | X | X |POL |1SHOT| 63cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * 64cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * - DS1625: 65cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * 7 6 5 4 3 2 1 0 66cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * |Done|THF |TLF |NVB | 1 | 0 |POL |1SHOT| 67cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * 68260f81ffc1b9f09dde355caa09e4b312756666f0Robert Coulson * - DS1631, DS1731: 6979c1cc1c90c0ccaddd20965ea19205c54addd5f7Robert Coulson * 7 6 5 4 3 2 1 0 7079c1cc1c90c0ccaddd20965ea19205c54addd5f7Robert Coulson * |Done|THF |TLF |NVB | R1 | R0 |POL |1SHOT| 7179c1cc1c90c0ccaddd20965ea19205c54addd5f7Robert Coulson * 72cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * - DS1721: 73cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * 7 6 5 4 3 2 1 0 74cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * |Done| X | X | U | R1 | R0 |POL |1SHOT| 75cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * 76cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * Where: 77cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * - 'X' is Reserved 78cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * - 'U' is Undefined 79cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson */ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DS1621_REG_CONFIG_NVB 0x10 81cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson#define DS1621_REG_CONFIG_RESOL 0x0C 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DS1621_REG_CONFIG_POLARITY 0x02 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DS1621_REG_CONFIG_1SHOT 0x01 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DS1621_REG_CONFIG_DONE 0x80 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 86cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson#define DS1621_REG_CONFIG_RESOL_SHIFT 2 87cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 88cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson/* ds1721 conversion rates: {C/LSB, time(ms), resolution bit setting} */ 89cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulsonstatic const unsigned short ds1721_convrates[] = { 90cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 94, /* 9-bits (0.5, 93.75, RES[0..1] = 0 */ 91cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 188, /* 10-bits (0.25, 187.5, RES[0..1] = 1 */ 92cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 375, /* 11-bits (0.125, 375, RES[0..1] = 2 */ 93cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 750, /* 12-bits (0.0625, 750, RES[0..1] = 3 */ 94cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson}; 95cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 96cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson#define DS1621_CONVERSION_MAX 750 97cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson#define DS1625_CONVERSION_MAX 500 98cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 99cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson#define DS1621_TEMP_MAX 125000 100cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson#define DS1621_TEMP_MIN (-55000) 101cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 102cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson/* The DS1621 temperature registers */ 10346a2e71ced949ecf238f796c178f85f03501ce88Jean Delvarestatic const u8 DS1621_REG_TEMP[3] = { 10446a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare 0xAA, /* input, word, RO */ 10546a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare 0xA2, /* min, word, RW */ 10646a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare 0xA1, /* max, word, RW */ 10746a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare}; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DS1621_REG_CONF 0xAC /* byte, RW */ 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DS1621_COM_START 0xEE /* no data */ 110cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson#define DS1721_COM_START 0x51 /* no data */ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DS1621_COM_STOP 0x22 /* no data */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The DS1621 configuration register */ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DS1621_ALARM_TEMP_HIGH 0x40 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DS1621_ALARM_TEMP_LOW 0x20 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11775819f01af77d6d70abc7777e450a0848a9b898bJean Delvare/* Conversions */ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ALARMS_FROM_REG(val) ((val) & \ 11919f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck (DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW)) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Each client has this additional data */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ds1621_data { 1238269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck struct i2c_client *client; 1249a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar struct mutex update_lock; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char valid; /* !=0 if following fields are valid */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long last_updated; /* In jiffies */ 127cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson enum chips kind; /* device type */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12946a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare u16 temp[3]; /* Register values, word */ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 conf; /* Register encoding, combined */ 131a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck u8 zbits; /* Resolution encoded as number of 132a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck * zero bits */ 133cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson u16 update_interval; /* Conversion rate in milliseconds */ 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 136cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulsonstatic inline int DS1621_TEMP_FROM_REG(u16 reg) 137cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson{ 138cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson return DIV_ROUND_CLOSEST(((s16)reg / 16) * 625, 10); 139cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson} 140cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 141cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson/* 142cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * TEMP: 0.001C/bit (-55C to +125C) 143cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson * REG: 144a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck * - 1621, 1625: 0.5C/bit, 7 zero-bits 145a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck * - 1631, 1721, 1731: 0.0625C/bit, 4 zero-bits 146cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson */ 147a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeckstatic inline u16 DS1621_TEMP_TO_REG(long temp, u8 zbits) 148cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson{ 149a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck temp = clamp_val(temp, DS1621_TEMP_MIN, DS1621_TEMP_MAX); 150a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck temp = DIV_ROUND_CLOSEST(temp * (1 << (8 - zbits)), 1000) << zbits; 151a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck return temp; 152cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson} 153cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 1548269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeckstatic void ds1621_init_client(struct ds1621_data *data, 1558269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck struct i2c_client *client) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 157cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson u8 conf, new_conf, sreg, resol; 158e4879e28abd67b894fb9d2db0afd08f1945670baJean Delvare 159e4879e28abd67b894fb9d2db0afd08f1945670baJean Delvare new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); 16044bbe87e9017efa050bb1b506c6822f1f3bb94d7Steven Cole /* switch to continuous conversion mode */ 161e4879e28abd67b894fb9d2db0afd08f1945670baJean Delvare new_conf &= ~DS1621_REG_CONFIG_1SHOT; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup output polarity */ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (polarity == 0) 165e4879e28abd67b894fb9d2db0afd08f1945670baJean Delvare new_conf &= ~DS1621_REG_CONFIG_POLARITY; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (polarity == 1) 167e4879e28abd67b894fb9d2db0afd08f1945670baJean Delvare new_conf |= DS1621_REG_CONFIG_POLARITY; 16819f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck 169e4879e28abd67b894fb9d2db0afd08f1945670baJean Delvare if (conf != new_conf) 170e4879e28abd67b894fb9d2db0afd08f1945670baJean Delvare i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf); 17119f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck 172cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson switch (data->kind) { 173cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson case ds1625: 174cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson data->update_interval = DS1625_CONVERSION_MAX; 175a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck data->zbits = 7; 176cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson sreg = DS1621_COM_START; 177cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson break; 17879c1cc1c90c0ccaddd20965ea19205c54addd5f7Robert Coulson case ds1631: 179cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson case ds1721: 180260f81ffc1b9f09dde355caa09e4b312756666f0Robert Coulson case ds1731: 181cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson resol = (new_conf & DS1621_REG_CONFIG_RESOL) >> 182cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson DS1621_REG_CONFIG_RESOL_SHIFT; 183cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson data->update_interval = ds1721_convrates[resol]; 184a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck data->zbits = 7 - resol; 185cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson sreg = DS1721_COM_START; 186cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson break; 187cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson default: 188cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson data->update_interval = DS1621_CONVERSION_MAX; 189a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck data->zbits = 7; 190cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson sreg = DS1621_COM_START; 191cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson break; 192cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson } 193cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start conversion */ 195cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson i2c_smbus_write_byte(client, sreg); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1989202add67454c6a6f9508f41e733edce705dc56eJean Delvarestatic struct ds1621_data *ds1621_update_client(struct device *dev) 1999202add67454c6a6f9508f41e733edce705dc56eJean Delvare{ 2008269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck struct ds1621_data *data = dev_get_drvdata(dev); 2018269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck struct i2c_client *client = data->client; 2029202add67454c6a6f9508f41e733edce705dc56eJean Delvare u8 new_conf; 2039202add67454c6a6f9508f41e733edce705dc56eJean Delvare 2049202add67454c6a6f9508f41e733edce705dc56eJean Delvare mutex_lock(&data->update_lock); 2059202add67454c6a6f9508f41e733edce705dc56eJean Delvare 206cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson if (time_after(jiffies, data->last_updated + data->update_interval) || 207cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson !data->valid) { 2089202add67454c6a6f9508f41e733edce705dc56eJean Delvare int i; 2099202add67454c6a6f9508f41e733edce705dc56eJean Delvare 2109202add67454c6a6f9508f41e733edce705dc56eJean Delvare dev_dbg(&client->dev, "Starting ds1621 update\n"); 2119202add67454c6a6f9508f41e733edce705dc56eJean Delvare 212594592dc6f68356a3b7278eb4d260a50a66f0a06Jean Delvare data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); 2139202add67454c6a6f9508f41e733edce705dc56eJean Delvare 2149202add67454c6a6f9508f41e733edce705dc56eJean Delvare for (i = 0; i < ARRAY_SIZE(data->temp); i++) 21590f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare data->temp[i] = i2c_smbus_read_word_swapped(client, 216594592dc6f68356a3b7278eb4d260a50a66f0a06Jean Delvare DS1621_REG_TEMP[i]); 2179202add67454c6a6f9508f41e733edce705dc56eJean Delvare 2189202add67454c6a6f9508f41e733edce705dc56eJean Delvare /* reset alarms if necessary */ 2199202add67454c6a6f9508f41e733edce705dc56eJean Delvare new_conf = data->conf; 2209202add67454c6a6f9508f41e733edce705dc56eJean Delvare if (data->temp[0] > data->temp[1]) /* input > min */ 2219202add67454c6a6f9508f41e733edce705dc56eJean Delvare new_conf &= ~DS1621_ALARM_TEMP_LOW; 2229202add67454c6a6f9508f41e733edce705dc56eJean Delvare if (data->temp[0] < data->temp[2]) /* input < max */ 2239202add67454c6a6f9508f41e733edce705dc56eJean Delvare new_conf &= ~DS1621_ALARM_TEMP_HIGH; 2249202add67454c6a6f9508f41e733edce705dc56eJean Delvare if (data->conf != new_conf) 225594592dc6f68356a3b7278eb4d260a50a66f0a06Jean Delvare i2c_smbus_write_byte_data(client, DS1621_REG_CONF, 226594592dc6f68356a3b7278eb4d260a50a66f0a06Jean Delvare new_conf); 2279202add67454c6a6f9508f41e733edce705dc56eJean Delvare 2289202add67454c6a6f9508f41e733edce705dc56eJean Delvare data->last_updated = jiffies; 2299202add67454c6a6f9508f41e733edce705dc56eJean Delvare data->valid = 1; 2309202add67454c6a6f9508f41e733edce705dc56eJean Delvare } 2319202add67454c6a6f9508f41e733edce705dc56eJean Delvare 2329202add67454c6a6f9508f41e733edce705dc56eJean Delvare mutex_unlock(&data->update_lock); 2339202add67454c6a6f9508f41e733edce705dc56eJean Delvare 2349202add67454c6a6f9508f41e733edce705dc56eJean Delvare return data; 2359202add67454c6a6f9508f41e733edce705dc56eJean Delvare} 2369202add67454c6a6f9508f41e733edce705dc56eJean Delvare 23746a2e71ced949ecf238f796c178f85f03501ce88Jean Delvarestatic ssize_t show_temp(struct device *dev, struct device_attribute *da, 23846a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare char *buf) 23946a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare{ 24046a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 24146a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare struct ds1621_data *data = ds1621_update_client(dev); 24246a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare return sprintf(buf, "%d\n", 243cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson DS1621_TEMP_FROM_REG(data->temp[attr->index])); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24646a2e71ced949ecf238f796c178f85f03501ce88Jean Delvarestatic ssize_t set_temp(struct device *dev, struct device_attribute *da, 24746a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare const char *buf, size_t count) 24846a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare{ 24946a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 2508269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck struct ds1621_data *data = dev_get_drvdata(dev); 25119f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck long val; 25219f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck int err; 25319f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck 25419f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck err = kstrtol(buf, 10, &val); 25519f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck if (err) 25619f2c05964dc428ef639fcda1cce7c8c3075c9ccGuenter Roeck return err; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25846a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare mutex_lock(&data->update_lock); 259a50d9a4d9ad3c71341788099d733e4151b8a511bGuenter Roeck data->temp[attr->index] = DS1621_TEMP_TO_REG(val, data->zbits); 2608269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck i2c_smbus_write_word_swapped(data->client, DS1621_REG_TEMP[attr->index], 26190f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare data->temp[attr->index]); 26246a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare mutex_unlock(&data->update_lock); 26346a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare return count; 26446a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare} 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26646a2e71ced949ecf238f796c178f85f03501ce88Jean Delvarestatic ssize_t show_alarms(struct device *dev, struct device_attribute *da, 26746a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare char *buf) 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ds1621_data *data = ds1621_update_client(dev); 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->conf)); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27387f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvarestatic ssize_t show_alarm(struct device *dev, struct device_attribute *da, 27487f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare char *buf) 27587f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare{ 27687f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 27787f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare struct ds1621_data *data = ds1621_update_client(dev); 27887f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare return sprintf(buf, "%d\n", !!(data->conf & attr->index)); 27987f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare} 28087f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare 2813a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulsonstatic ssize_t show_convrate(struct device *dev, struct device_attribute *da, 2823a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson char *buf) 2833a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson{ 2848269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck struct ds1621_data *data = dev_get_drvdata(dev); 2853a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson return scnprintf(buf, PAGE_SIZE, "%hu\n", data->update_interval); 2863a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson} 2873a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson 2883a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulsonstatic ssize_t set_convrate(struct device *dev, struct device_attribute *da, 2893a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson const char *buf, size_t count) 2903a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson{ 2918269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck struct ds1621_data *data = dev_get_drvdata(dev); 2928269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck struct i2c_client *client = data->client; 2933a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson unsigned long convrate; 2943a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson s32 err; 2953a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson int resol = 0; 2963a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson 2973a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson err = kstrtoul(buf, 10, &convrate); 2983a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson if (err) 2993a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson return err; 3003a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson 3013a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson /* Convert rate into resolution bits */ 3023a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson while (resol < (ARRAY_SIZE(ds1721_convrates) - 1) && 3033a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson convrate > ds1721_convrates[resol]) 3043a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson resol++; 3053a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson 3063a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson mutex_lock(&data->update_lock); 3073a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); 3083a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson data->conf &= ~DS1621_REG_CONFIG_RESOL; 3093a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson data->conf |= (resol << DS1621_REG_CONFIG_RESOL_SHIFT); 3103a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson i2c_smbus_write_byte_data(client, DS1621_REG_CONF, data->conf); 3113a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson data->update_interval = ds1721_convrates[resol]; 31239c627a084475e8a690a4a9e7601410ca173ddd2Robert Coulson data->zbits = 7 - resol; 3133a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson mutex_unlock(&data->update_lock); 3143a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson 3153a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson return count; 3163a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson} 3173a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 3193a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulsonstatic DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_convrate, 3203a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson set_convrate); 3213a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson 32246a2e71ced949ecf238f796c178f85f03501ce88Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); 32346a2e71ced949ecf238f796c178f85f03501ce88Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1); 32446a2e71ced949ecf238f796c178f85f03501ce88Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2); 32587f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 32687f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare DS1621_ALARM_TEMP_LOW); 32787f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 32887f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare DS1621_ALARM_TEMP_HIGH); 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 330a5ebe668add5f76ed8f01f752b37cfa164a26a30Jean Delvarestatic struct attribute *ds1621_attributes[] = { 33146a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare &sensor_dev_attr_temp1_input.dev_attr.attr, 33246a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare &sensor_dev_attr_temp1_min.dev_attr.attr, 33346a2e71ced949ecf238f796c178f85f03501ce88Jean Delvare &sensor_dev_attr_temp1_max.dev_attr.attr, 33487f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 33587f0f31baf9ea2cb273d7fb56b3ebf9df5096884Jean Delvare &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 336a5ebe668add5f76ed8f01f752b37cfa164a26a30Jean Delvare &dev_attr_alarms.attr, 3373a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson &dev_attr_update_interval.attr, 338a5ebe668add5f76ed8f01f752b37cfa164a26a30Jean Delvare NULL 339a5ebe668add5f76ed8f01f752b37cfa164a26a30Jean Delvare}; 340a5ebe668add5f76ed8f01f752b37cfa164a26a30Jean Delvare 3413a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulsonstatic umode_t ds1621_attribute_visible(struct kobject *kobj, 3423a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson struct attribute *attr, int index) 3433a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson{ 3443a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson struct device *dev = container_of(kobj, struct device, kobj); 3458269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck struct ds1621_data *data = dev_get_drvdata(dev); 3463a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson 3473a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson if (attr == &dev_attr_update_interval.attr) 34879c1cc1c90c0ccaddd20965ea19205c54addd5f7Robert Coulson if (data->kind == ds1621 || data->kind == ds1625) 3493a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson /* shhh, we're hiding update_interval */ 3503a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson return 0; 3513a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson return attr->mode; 3523a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson} 3533a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson 354a5ebe668add5f76ed8f01f752b37cfa164a26a30Jean Delvarestatic const struct attribute_group ds1621_group = { 355a5ebe668add5f76ed8f01f752b37cfa164a26a30Jean Delvare .attrs = ds1621_attributes, 3563a8fe3315571e896489d2e271ffe7f935bfc5ce8Robert Coulson .is_visible = ds1621_attribute_visible 357a5ebe668add5f76ed8f01f752b37cfa164a26a30Jean Delvare}; 3580d36dce0f1d15a9ca55f893b3aa5ce7c297e11c8Guenter Roeck__ATTRIBUTE_GROUPS(ds1621); 3598269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck 36070313eabfc63ce6aa89b9fa3074129e5c521568aJean Delvarestatic int ds1621_probe(struct i2c_client *client, 36170313eabfc63ce6aa89b9fa3074129e5c521568aJean Delvare const struct i2c_device_id *id) 36270313eabfc63ce6aa89b9fa3074129e5c521568aJean Delvare{ 36370313eabfc63ce6aa89b9fa3074129e5c521568aJean Delvare struct ds1621_data *data; 3648269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck struct device *hwmon_dev; 36570313eabfc63ce6aa89b9fa3074129e5c521568aJean Delvare 366e20b4b38cdf1622d1577ae5e402ded2bd63bf616Guenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct ds1621_data), 367e20b4b38cdf1622d1577ae5e402ded2bd63bf616Guenter Roeck GFP_KERNEL); 368e20b4b38cdf1622d1577ae5e402ded2bd63bf616Guenter Roeck if (!data) 369e20b4b38cdf1622d1577ae5e402ded2bd63bf616Guenter Roeck return -ENOMEM; 37070313eabfc63ce6aa89b9fa3074129e5c521568aJean Delvare 37170313eabfc63ce6aa89b9fa3074129e5c521568aJean Delvare mutex_init(&data->update_lock); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 373cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson data->kind = id->driver_data; 3748269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck data->client = client; 375cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the DS1621 chip */ 3778269b75ae72c4501df7caf93d053526cef7e8a8aGuenter Roeck ds1621_init_client(data, client); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3790d36dce0f1d15a9ca55f893b3aa5ce7c297e11c8Guenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, 3800d36dce0f1d15a9ca55f893b3aa5ce7c297e11c8Guenter Roeck client->name, data, 3810d36dce0f1d15a9ca55f893b3aa5ce7c297e11c8Guenter Roeck ds1621_groups); 38231ab1ad70b25f4e19f6442e8f6d68025ba43b942Fengguang Wu return PTR_ERR_OR_ZERO(hwmon_dev); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3859202add67454c6a6f9508f41e733edce705dc56eJean Delvarestatic const struct i2c_device_id ds1621_id[] = { 386cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson { "ds1621", ds1621 }, 387cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson { "ds1625", ds1625 }, 38879c1cc1c90c0ccaddd20965ea19205c54addd5f7Robert Coulson { "ds1631", ds1631 }, 389cd6c8a4297ad036a155966db49982d6807e23ef8Robert Coulson { "ds1721", ds1721 }, 390260f81ffc1b9f09dde355caa09e4b312756666f0Robert Coulson { "ds1731", ds1731 }, 3919202add67454c6a6f9508f41e733edce705dc56eJean Delvare { } 3929202add67454c6a6f9508f41e733edce705dc56eJean Delvare}; 3939202add67454c6a6f9508f41e733edce705dc56eJean DelvareMODULE_DEVICE_TABLE(i2c, ds1621_id); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3959202add67454c6a6f9508f41e733edce705dc56eJean Delvare/* This is the driver that will be inserted */ 3969202add67454c6a6f9508f41e733edce705dc56eJean Delvarestatic struct i2c_driver ds1621_driver = { 3979202add67454c6a6f9508f41e733edce705dc56eJean Delvare .class = I2C_CLASS_HWMON, 3989202add67454c6a6f9508f41e733edce705dc56eJean Delvare .driver = { 3999202add67454c6a6f9508f41e733edce705dc56eJean Delvare .name = "ds1621", 4009202add67454c6a6f9508f41e733edce705dc56eJean Delvare }, 4019202add67454c6a6f9508f41e733edce705dc56eJean Delvare .probe = ds1621_probe, 4029202add67454c6a6f9508f41e733edce705dc56eJean Delvare .id_table = ds1621_id, 4039202add67454c6a6f9508f41e733edce705dc56eJean Delvare}; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 405f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(ds1621_driver); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Christian W. Zuckschwerdt <zany@triq.net>"); 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("DS1621 driver"); 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 410