xref: /linux/drivers/hwmon/lm95241.c (revision c942fddf8793b2013be8c901b47d0a8dc02bf99f)
1*c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
206160327SDavide Rizzo /*
30f1deb4bSDavide Rizzo  * Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@gmail.com>
406160327SDavide Rizzo  *
50f1deb4bSDavide Rizzo  * The LM95241 is a sensor chip made by National Semiconductors.
60f1deb4bSDavide Rizzo  * It reports up to three temperatures (its own plus up to two external ones).
70f1deb4bSDavide Rizzo  * Complete datasheet can be obtained from National's website at:
806160327SDavide Rizzo  *   http://www.national.com/ds.cgi/LM/LM95241.pdf
906160327SDavide Rizzo  */
1006160327SDavide Rizzo 
11e8172a93SGuenter Roeck #include <linux/bitops.h>
124b2ea08bSGuenter Roeck #include <linux/err.h>
1306160327SDavide Rizzo #include <linux/i2c.h>
144b2ea08bSGuenter Roeck #include <linux/init.h>
154b2ea08bSGuenter Roeck #include <linux/jiffies.h>
1606160327SDavide Rizzo #include <linux/hwmon.h>
174b2ea08bSGuenter Roeck #include <linux/module.h>
1806160327SDavide Rizzo #include <linux/mutex.h>
194b2ea08bSGuenter Roeck #include <linux/slab.h>
2006160327SDavide Rizzo 
210f1deb4bSDavide Rizzo #define DEVNAME "lm95241"
220f1deb4bSDavide Rizzo 
2306160327SDavide Rizzo static const unsigned short normal_i2c[] = {
2406160327SDavide Rizzo 	0x19, 0x2a, 0x2b, I2C_CLIENT_END };
2506160327SDavide Rizzo 
2606160327SDavide Rizzo /* LM95241 registers */
2706160327SDavide Rizzo #define LM95241_REG_R_MAN_ID		0xFE
2806160327SDavide Rizzo #define LM95241_REG_R_CHIP_ID		0xFF
2906160327SDavide Rizzo #define LM95241_REG_R_STATUS		0x02
3006160327SDavide Rizzo #define LM95241_REG_RW_CONFIG		0x03
3106160327SDavide Rizzo #define LM95241_REG_RW_REM_FILTER	0x06
3206160327SDavide Rizzo #define LM95241_REG_RW_TRUTHERM		0x07
3306160327SDavide Rizzo #define LM95241_REG_W_ONE_SHOT		0x0F
3406160327SDavide Rizzo #define LM95241_REG_R_LOCAL_TEMPH	0x10
3506160327SDavide Rizzo #define LM95241_REG_R_REMOTE1_TEMPH	0x11
3606160327SDavide Rizzo #define LM95241_REG_R_REMOTE2_TEMPH	0x12
3706160327SDavide Rizzo #define LM95241_REG_R_LOCAL_TEMPL	0x20
3806160327SDavide Rizzo #define LM95241_REG_R_REMOTE1_TEMPL	0x21
3906160327SDavide Rizzo #define LM95241_REG_R_REMOTE2_TEMPL	0x22
4006160327SDavide Rizzo #define LM95241_REG_RW_REMOTE_MODEL	0x30
4106160327SDavide Rizzo 
4206160327SDavide Rizzo /* LM95241 specific bitfields */
43e8172a93SGuenter Roeck #define CFG_STOP	BIT(6)
4406160327SDavide Rizzo #define CFG_CR0076	0x00
45e8172a93SGuenter Roeck #define CFG_CR0182	BIT(4)
46e8172a93SGuenter Roeck #define CFG_CR1000	BIT(5)
47e8172a93SGuenter Roeck #define CFG_CR2700	(BIT(4) | BIT(5))
48e8172a93SGuenter Roeck #define CFG_CRMASK	(BIT(4) | BIT(5))
49e8172a93SGuenter Roeck #define R1MS_MASK	BIT(0)
50e8172a93SGuenter Roeck #define R2MS_MASK	BIT(2)
51e8172a93SGuenter Roeck #define R1DF_MASK	BIT(1)
52e8172a93SGuenter Roeck #define R2DF_MASK	BIT(2)
53e8172a93SGuenter Roeck #define R1FE_MASK	BIT(0)
54e8172a93SGuenter Roeck #define R2FE_MASK	BIT(2)
55e8172a93SGuenter Roeck #define R1DM		BIT(0)
56e8172a93SGuenter Roeck #define R2DM		BIT(1)
5706160327SDavide Rizzo #define TT1_SHIFT	0
5806160327SDavide Rizzo #define TT2_SHIFT	4
5906160327SDavide Rizzo #define TT_OFF		0
6006160327SDavide Rizzo #define TT_ON		1
6106160327SDavide Rizzo #define TT_MASK		7
628c1d0419SGuenter Roeck #define NATSEMI_MAN_ID	0x01
638c1d0419SGuenter Roeck #define LM95231_CHIP_ID	0xA1
648c1d0419SGuenter Roeck #define LM95241_CHIP_ID	0xA4
6506160327SDavide Rizzo 
660f1deb4bSDavide Rizzo static const u8 lm95241_reg_address[] = {
670f1deb4bSDavide Rizzo 	LM95241_REG_R_LOCAL_TEMPH,
680f1deb4bSDavide Rizzo 	LM95241_REG_R_LOCAL_TEMPL,
690f1deb4bSDavide Rizzo 	LM95241_REG_R_REMOTE1_TEMPH,
700f1deb4bSDavide Rizzo 	LM95241_REG_R_REMOTE1_TEMPL,
710f1deb4bSDavide Rizzo 	LM95241_REG_R_REMOTE2_TEMPH,
720f1deb4bSDavide Rizzo 	LM95241_REG_R_REMOTE2_TEMPL
730f1deb4bSDavide Rizzo };
7406160327SDavide Rizzo 
7506160327SDavide Rizzo /* Client data (each client gets its own) */
7606160327SDavide Rizzo struct lm95241_data {
77f809621eSGuenter Roeck 	struct i2c_client *client;
7806160327SDavide Rizzo 	struct mutex update_lock;
79f48ccb26SGuenter Roeck 	unsigned long last_updated;	/* in jiffies */
80f48ccb26SGuenter Roeck 	unsigned long interval;		/* in milli-seconds */
8106160327SDavide Rizzo 	char valid;		/* zero until following fields are valid */
8206160327SDavide Rizzo 	/* registers values */
830f1deb4bSDavide Rizzo 	u8 temp[ARRAY_SIZE(lm95241_reg_address)];
84090a7f8eSGuenter Roeck 	u8 status, config, model, trutherm;
8506160327SDavide Rizzo };
8606160327SDavide Rizzo 
870f1deb4bSDavide Rizzo /* Conversions */
880c2a40e2SGuenter Roeck static int temp_from_reg_signed(u8 val_h, u8 val_l)
890f1deb4bSDavide Rizzo {
900c2a40e2SGuenter Roeck 	s16 val_hl = (val_h << 8) | val_l;
910c2a40e2SGuenter Roeck 	return val_hl * 1000 / 256;
920c2a40e2SGuenter Roeck }
930c2a40e2SGuenter Roeck 
940c2a40e2SGuenter Roeck static int temp_from_reg_unsigned(u8 val_h, u8 val_l)
950c2a40e2SGuenter Roeck {
960c2a40e2SGuenter Roeck 	u16 val_hl = (val_h << 8) | val_l;
970c2a40e2SGuenter Roeck 	return val_hl * 1000 / 256;
9806160327SDavide Rizzo }
990f1deb4bSDavide Rizzo 
1000f1deb4bSDavide Rizzo static struct lm95241_data *lm95241_update_device(struct device *dev)
1010f1deb4bSDavide Rizzo {
102f809621eSGuenter Roeck 	struct lm95241_data *data = dev_get_drvdata(dev);
103f809621eSGuenter Roeck 	struct i2c_client *client = data->client;
1040f1deb4bSDavide Rizzo 
1050f1deb4bSDavide Rizzo 	mutex_lock(&data->update_lock);
1060f1deb4bSDavide Rizzo 
107f48ccb26SGuenter Roeck 	if (time_after(jiffies, data->last_updated
108f48ccb26SGuenter Roeck 		       + msecs_to_jiffies(data->interval)) ||
1090f1deb4bSDavide Rizzo 	    !data->valid) {
1100f1deb4bSDavide Rizzo 		int i;
1110f1deb4bSDavide Rizzo 
112f809621eSGuenter Roeck 		dev_dbg(dev, "Updating lm95241 data.\n");
1130f1deb4bSDavide Rizzo 		for (i = 0; i < ARRAY_SIZE(lm95241_reg_address); i++)
1140f1deb4bSDavide Rizzo 			data->temp[i]
1150f1deb4bSDavide Rizzo 			  = i2c_smbus_read_byte_data(client,
1160f1deb4bSDavide Rizzo 						     lm95241_reg_address[i]);
117090a7f8eSGuenter Roeck 
118090a7f8eSGuenter Roeck 		data->status = i2c_smbus_read_byte_data(client,
119090a7f8eSGuenter Roeck 							LM95241_REG_R_STATUS);
1200f1deb4bSDavide Rizzo 		data->last_updated = jiffies;
1210f1deb4bSDavide Rizzo 		data->valid = 1;
1220f1deb4bSDavide Rizzo 	}
1230f1deb4bSDavide Rizzo 
1240f1deb4bSDavide Rizzo 	mutex_unlock(&data->update_lock);
1250f1deb4bSDavide Rizzo 
1260f1deb4bSDavide Rizzo 	return data;
1270f1deb4bSDavide Rizzo }
1280f1deb4bSDavide Rizzo 
1293e904628SGuenter Roeck static int lm95241_read_chip(struct device *dev, u32 attr, int channel,
1303e904628SGuenter Roeck 			     long *val)
1313e904628SGuenter Roeck {
1323e904628SGuenter Roeck 	struct lm95241_data *data = dev_get_drvdata(dev);
1333e904628SGuenter Roeck 
1343e904628SGuenter Roeck 	switch (attr) {
1353e904628SGuenter Roeck 	case hwmon_chip_update_interval:
1363e904628SGuenter Roeck 		*val = data->interval;
1373e904628SGuenter Roeck 		return 0;
1383e904628SGuenter Roeck 	default:
1393e904628SGuenter Roeck 		return -EOPNOTSUPP;
1403e904628SGuenter Roeck 	}
1413e904628SGuenter Roeck }
1423e904628SGuenter Roeck 
1433e904628SGuenter Roeck static int lm95241_read_temp(struct device *dev, u32 attr, int channel,
1443e904628SGuenter Roeck 			     long *val)
1450f1deb4bSDavide Rizzo {
1460f1deb4bSDavide Rizzo 	struct lm95241_data *data = lm95241_update_device(dev);
1470f1deb4bSDavide Rizzo 
1483e904628SGuenter Roeck 	switch (attr) {
1493e904628SGuenter Roeck 	case hwmon_temp_input:
1503e904628SGuenter Roeck 		if (!channel || (data->config & BIT(channel - 1)))
1513e904628SGuenter Roeck 			*val = temp_from_reg_signed(data->temp[channel * 2],
1523e904628SGuenter Roeck 						data->temp[channel * 2 + 1]);
1530f1deb4bSDavide Rizzo 		else
1543e904628SGuenter Roeck 			*val = temp_from_reg_unsigned(data->temp[channel * 2],
1553e904628SGuenter Roeck 						data->temp[channel * 2 + 1]);
1563e904628SGuenter Roeck 		return 0;
1573e904628SGuenter Roeck 	case hwmon_temp_min:
1583e904628SGuenter Roeck 		if (channel == 1)
1593e904628SGuenter Roeck 			*val = (data->config & R1DF_MASK) ? -128000 : 0;
1600f1deb4bSDavide Rizzo 		else
1613e904628SGuenter Roeck 			*val = (data->config & R2DF_MASK) ? -128000 : 0;
1623e904628SGuenter Roeck 		return 0;
1633e904628SGuenter Roeck 	case hwmon_temp_max:
1643e904628SGuenter Roeck 		if (channel == 1)
1653e904628SGuenter Roeck 			*val = (data->config & R1DF_MASK) ? 127875 : 255875;
1663e904628SGuenter Roeck 		else
1673e904628SGuenter Roeck 			*val = (data->config & R2DF_MASK) ? 127875 : 255875;
1683e904628SGuenter Roeck 		return 0;
1693e904628SGuenter Roeck 	case hwmon_temp_type:
1703e904628SGuenter Roeck 		if (channel == 1)
1713e904628SGuenter Roeck 			*val = (data->model & R1MS_MASK) ? 1 : 2;
1723e904628SGuenter Roeck 		else
1733e904628SGuenter Roeck 			*val = (data->model & R2MS_MASK) ? 1 : 2;
1743e904628SGuenter Roeck 		return 0;
1753e904628SGuenter Roeck 	case hwmon_temp_fault:
1763e904628SGuenter Roeck 		if (channel == 1)
1773e904628SGuenter Roeck 			*val = !!(data->status & R1DM);
1783e904628SGuenter Roeck 		else
1793e904628SGuenter Roeck 			*val = !!(data->status & R2DM);
1803e904628SGuenter Roeck 		return 0;
1813e904628SGuenter Roeck 	default:
1823e904628SGuenter Roeck 		return -EOPNOTSUPP;
1833e904628SGuenter Roeck 	}
1840f1deb4bSDavide Rizzo }
18506160327SDavide Rizzo 
1863e904628SGuenter Roeck static int lm95241_read(struct device *dev, enum hwmon_sensor_types type,
1873e904628SGuenter Roeck 			u32 attr, int channel, long *val)
188090a7f8eSGuenter Roeck {
1893e904628SGuenter Roeck 	switch (type) {
1903e904628SGuenter Roeck 	case hwmon_chip:
1913e904628SGuenter Roeck 		return lm95241_read_chip(dev, attr, channel, val);
1923e904628SGuenter Roeck 	case hwmon_temp:
1933e904628SGuenter Roeck 		return lm95241_read_temp(dev, attr, channel, val);
1943e904628SGuenter Roeck 	default:
1953e904628SGuenter Roeck 		return -EOPNOTSUPP;
1963e904628SGuenter Roeck 	}
197090a7f8eSGuenter Roeck }
198090a7f8eSGuenter Roeck 
1993e904628SGuenter Roeck static int lm95241_write_chip(struct device *dev, u32 attr, int channel,
2003e904628SGuenter Roeck 			      long val)
20106160327SDavide Rizzo {
202f809621eSGuenter Roeck 	struct lm95241_data *data = dev_get_drvdata(dev);
203f48ccb26SGuenter Roeck 	int convrate;
204f48ccb26SGuenter Roeck 	u8 config;
2053e904628SGuenter Roeck 	int ret;
20661ec2da5SJean Delvare 
207f48ccb26SGuenter Roeck 	mutex_lock(&data->update_lock);
208f48ccb26SGuenter Roeck 
2093e904628SGuenter Roeck 	switch (attr) {
2103e904628SGuenter Roeck 	case hwmon_chip_update_interval:
211f48ccb26SGuenter Roeck 		config = data->config & ~CFG_CRMASK;
212f48ccb26SGuenter Roeck 		if (val < 130) {
213f48ccb26SGuenter Roeck 			convrate = 76;
214f48ccb26SGuenter Roeck 			config |= CFG_CR0076;
215f48ccb26SGuenter Roeck 		} else if (val < 590) {
216f48ccb26SGuenter Roeck 			convrate = 182;
217f48ccb26SGuenter Roeck 			config |= CFG_CR0182;
218f48ccb26SGuenter Roeck 		} else if (val < 1850) {
219f48ccb26SGuenter Roeck 			convrate = 1000;
220f48ccb26SGuenter Roeck 			config |= CFG_CR1000;
221f48ccb26SGuenter Roeck 		} else {
222f48ccb26SGuenter Roeck 			convrate = 2700;
223f48ccb26SGuenter Roeck 			config |= CFG_CR2700;
224f48ccb26SGuenter Roeck 		}
225f48ccb26SGuenter Roeck 		data->interval = convrate;
226f48ccb26SGuenter Roeck 		data->config = config;
2273e904628SGuenter Roeck 		ret = i2c_smbus_write_byte_data(data->client,
2283e904628SGuenter Roeck 						LM95241_REG_RW_CONFIG, config);
2293e904628SGuenter Roeck 		break;
2303e904628SGuenter Roeck 	default:
2313e904628SGuenter Roeck 		ret = -EOPNOTSUPP;
2323e904628SGuenter Roeck 		break;
2333e904628SGuenter Roeck 	}
234f48ccb26SGuenter Roeck 	mutex_unlock(&data->update_lock);
2353e904628SGuenter Roeck 	return ret;
23606160327SDavide Rizzo }
23706160327SDavide Rizzo 
2383e904628SGuenter Roeck static int lm95241_write_temp(struct device *dev, u32 attr, int channel,
2393e904628SGuenter Roeck 			      long val)
2403e904628SGuenter Roeck {
2413e904628SGuenter Roeck 	struct lm95241_data *data = dev_get_drvdata(dev);
2423e904628SGuenter Roeck 	struct i2c_client *client = data->client;
2433e904628SGuenter Roeck 	int ret;
24406160327SDavide Rizzo 
2453e904628SGuenter Roeck 	mutex_lock(&data->update_lock);
2463e904628SGuenter Roeck 
2473e904628SGuenter Roeck 	switch (attr) {
2483e904628SGuenter Roeck 	case hwmon_temp_min:
2493e904628SGuenter Roeck 		if (channel == 1) {
2503e904628SGuenter Roeck 			if (val < 0)
2513e904628SGuenter Roeck 				data->config |= R1DF_MASK;
2523e904628SGuenter Roeck 			else
2533e904628SGuenter Roeck 				data->config &= ~R1DF_MASK;
2543e904628SGuenter Roeck 		} else {
2553e904628SGuenter Roeck 			if (val < 0)
2563e904628SGuenter Roeck 				data->config |= R2DF_MASK;
2573e904628SGuenter Roeck 			else
2583e904628SGuenter Roeck 				data->config &= ~R2DF_MASK;
2593e904628SGuenter Roeck 		}
2603e904628SGuenter Roeck 		data->valid = 0;
2613e904628SGuenter Roeck 		ret = i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG,
2623e904628SGuenter Roeck 						data->config);
2633e904628SGuenter Roeck 		break;
2643e904628SGuenter Roeck 	case hwmon_temp_max:
2653e904628SGuenter Roeck 		if (channel == 1) {
2663e904628SGuenter Roeck 			if (val <= 127875)
2673e904628SGuenter Roeck 				data->config |= R1DF_MASK;
2683e904628SGuenter Roeck 			else
2693e904628SGuenter Roeck 				data->config &= ~R1DF_MASK;
2703e904628SGuenter Roeck 		} else {
2713e904628SGuenter Roeck 			if (val <= 127875)
2723e904628SGuenter Roeck 				data->config |= R2DF_MASK;
2733e904628SGuenter Roeck 			else
2743e904628SGuenter Roeck 				data->config &= ~R2DF_MASK;
2753e904628SGuenter Roeck 		}
2763e904628SGuenter Roeck 		data->valid = 0;
2773e904628SGuenter Roeck 		ret = i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG,
2783e904628SGuenter Roeck 						data->config);
2793e904628SGuenter Roeck 		break;
2803e904628SGuenter Roeck 	case hwmon_temp_type:
2813e904628SGuenter Roeck 		if (val != 1 && val != 2) {
2823e904628SGuenter Roeck 			ret = -EINVAL;
2833e904628SGuenter Roeck 			break;
2843e904628SGuenter Roeck 		}
2853e904628SGuenter Roeck 		if (channel == 1) {
2863e904628SGuenter Roeck 			data->trutherm &= ~(TT_MASK << TT1_SHIFT);
2873e904628SGuenter Roeck 			if (val == 1) {
2883e904628SGuenter Roeck 				data->model |= R1MS_MASK;
2893e904628SGuenter Roeck 				data->trutherm |= (TT_ON << TT1_SHIFT);
2903e904628SGuenter Roeck 			} else {
2913e904628SGuenter Roeck 				data->model &= ~R1MS_MASK;
2923e904628SGuenter Roeck 				data->trutherm |= (TT_OFF << TT1_SHIFT);
2933e904628SGuenter Roeck 			}
2943e904628SGuenter Roeck 		} else {
2953e904628SGuenter Roeck 			data->trutherm &= ~(TT_MASK << TT2_SHIFT);
2963e904628SGuenter Roeck 			if (val == 1) {
2973e904628SGuenter Roeck 				data->model |= R2MS_MASK;
2983e904628SGuenter Roeck 				data->trutherm |= (TT_ON << TT2_SHIFT);
2993e904628SGuenter Roeck 			} else {
3003e904628SGuenter Roeck 				data->model &= ~R2MS_MASK;
3013e904628SGuenter Roeck 				data->trutherm |= (TT_OFF << TT2_SHIFT);
3023e904628SGuenter Roeck 			}
3033e904628SGuenter Roeck 		}
3043e904628SGuenter Roeck 		ret = i2c_smbus_write_byte_data(client,
3053e904628SGuenter Roeck 						LM95241_REG_RW_REMOTE_MODEL,
3063e904628SGuenter Roeck 						data->model);
3073e904628SGuenter Roeck 		if (ret < 0)
3083e904628SGuenter Roeck 			break;
3093e904628SGuenter Roeck 		ret = i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM,
3103e904628SGuenter Roeck 						data->trutherm);
3113e904628SGuenter Roeck 		break;
3123e904628SGuenter Roeck 	default:
3133e904628SGuenter Roeck 		ret = -EOPNOTSUPP;
3143e904628SGuenter Roeck 		break;
3153e904628SGuenter Roeck 	}
3163e904628SGuenter Roeck 
3173e904628SGuenter Roeck 	mutex_unlock(&data->update_lock);
3183e904628SGuenter Roeck 
3193e904628SGuenter Roeck 	return ret;
3203e904628SGuenter Roeck }
3213e904628SGuenter Roeck 
3223e904628SGuenter Roeck static int lm95241_write(struct device *dev, enum hwmon_sensor_types type,
3233e904628SGuenter Roeck 			 u32 attr, int channel, long val)
3243e904628SGuenter Roeck {
3253e904628SGuenter Roeck 	switch (type) {
3263e904628SGuenter Roeck 	case hwmon_chip:
3273e904628SGuenter Roeck 		return lm95241_write_chip(dev, attr, channel, val);
3283e904628SGuenter Roeck 	case hwmon_temp:
3293e904628SGuenter Roeck 		return lm95241_write_temp(dev, attr, channel, val);
3303e904628SGuenter Roeck 	default:
3313e904628SGuenter Roeck 		return -EOPNOTSUPP;
3323e904628SGuenter Roeck 	}
3333e904628SGuenter Roeck }
3343e904628SGuenter Roeck 
3353e904628SGuenter Roeck static umode_t lm95241_is_visible(const void *data,
3363e904628SGuenter Roeck 				  enum hwmon_sensor_types type,
3373e904628SGuenter Roeck 				  u32 attr, int channel)
3383e904628SGuenter Roeck {
3393e904628SGuenter Roeck 	switch (type) {
3403e904628SGuenter Roeck 	case hwmon_chip:
3413e904628SGuenter Roeck 		switch (attr) {
3423e904628SGuenter Roeck 		case hwmon_chip_update_interval:
3435c06d568SGuenter Roeck 			return 0644;
3443e904628SGuenter Roeck 		}
3453e904628SGuenter Roeck 		break;
3463e904628SGuenter Roeck 	case hwmon_temp:
3473e904628SGuenter Roeck 		switch (attr) {
3483e904628SGuenter Roeck 		case hwmon_temp_input:
3495c06d568SGuenter Roeck 			return 0444;
3503e904628SGuenter Roeck 		case hwmon_temp_fault:
3515c06d568SGuenter Roeck 			return 0444;
3523e904628SGuenter Roeck 		case hwmon_temp_min:
3533e904628SGuenter Roeck 		case hwmon_temp_max:
3543e904628SGuenter Roeck 		case hwmon_temp_type:
3555c06d568SGuenter Roeck 			return 0644;
3563e904628SGuenter Roeck 		}
3573e904628SGuenter Roeck 		break;
3583e904628SGuenter Roeck 	default:
3593e904628SGuenter Roeck 		break;
3603e904628SGuenter Roeck 	}
3613e904628SGuenter Roeck 	return 0;
3623e904628SGuenter Roeck }
36306160327SDavide Rizzo 
364797eaa4bSJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
365310ec792SJean Delvare static int lm95241_detect(struct i2c_client *new_client,
366797eaa4bSJean Delvare 			  struct i2c_board_info *info)
36706160327SDavide Rizzo {
368797eaa4bSJean Delvare 	struct i2c_adapter *adapter = new_client->adapter;
36952df6440SJean Delvare 	const char *name;
3708c1d0419SGuenter Roeck 	int mfg_id, chip_id;
37106160327SDavide Rizzo 
37206160327SDavide Rizzo 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
373797eaa4bSJean Delvare 		return -ENODEV;
37406160327SDavide Rizzo 
3758c1d0419SGuenter Roeck 	mfg_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID);
3768c1d0419SGuenter Roeck 	if (mfg_id != NATSEMI_MAN_ID)
3778c1d0419SGuenter Roeck 		return -ENODEV;
3788c1d0419SGuenter Roeck 
3798c1d0419SGuenter Roeck 	chip_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID);
3808c1d0419SGuenter Roeck 	switch (chip_id) {
3818c1d0419SGuenter Roeck 	case LM95231_CHIP_ID:
3828c1d0419SGuenter Roeck 		name = "lm95231";
3838c1d0419SGuenter Roeck 		break;
3848c1d0419SGuenter Roeck 	case LM95241_CHIP_ID:
3858c1d0419SGuenter Roeck 		name = "lm95241";
3868c1d0419SGuenter Roeck 		break;
3878c1d0419SGuenter Roeck 	default:
388797eaa4bSJean Delvare 		return -ENODEV;
38906160327SDavide Rizzo 	}
39006160327SDavide Rizzo 
391797eaa4bSJean Delvare 	/* Fill the i2c board info */
392797eaa4bSJean Delvare 	strlcpy(info->type, name, I2C_NAME_SIZE);
393797eaa4bSJean Delvare 	return 0;
394797eaa4bSJean Delvare }
39506160327SDavide Rizzo 
396f809621eSGuenter Roeck static void lm95241_init_client(struct i2c_client *client,
397f809621eSGuenter Roeck 				struct lm95241_data *data)
3980f1deb4bSDavide Rizzo {
399f48ccb26SGuenter Roeck 	data->interval = 1000;
400f48ccb26SGuenter Roeck 	data->config = CFG_CR1000;
4010f1deb4bSDavide Rizzo 	data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT);
4020f1deb4bSDavide Rizzo 
4030f1deb4bSDavide Rizzo 	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);
4040f1deb4bSDavide Rizzo 	i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER,
4050f1deb4bSDavide Rizzo 				  R1FE_MASK | R2FE_MASK);
4060f1deb4bSDavide Rizzo 	i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM,
4070f1deb4bSDavide Rizzo 				  data->trutherm);
4080f1deb4bSDavide Rizzo 	i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL,
4090f1deb4bSDavide Rizzo 				  data->model);
4100f1deb4bSDavide Rizzo }
4110f1deb4bSDavide Rizzo 
4123e904628SGuenter Roeck static const struct hwmon_channel_info *lm95241_info[] = {
413f5011f9fSGuenter Roeck 	HWMON_CHANNEL_INFO(chip,
414f5011f9fSGuenter Roeck 			   HWMON_C_UPDATE_INTERVAL),
415f5011f9fSGuenter Roeck 	HWMON_CHANNEL_INFO(temp,
416f5011f9fSGuenter Roeck 			   HWMON_T_INPUT,
417f5011f9fSGuenter Roeck 			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN |
418f5011f9fSGuenter Roeck 			   HWMON_T_TYPE | HWMON_T_FAULT,
419f5011f9fSGuenter Roeck 			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN |
420f5011f9fSGuenter Roeck 			   HWMON_T_TYPE | HWMON_T_FAULT),
4213e904628SGuenter Roeck 	NULL
4223e904628SGuenter Roeck };
4233e904628SGuenter Roeck 
4243e904628SGuenter Roeck static const struct hwmon_ops lm95241_hwmon_ops = {
4253e904628SGuenter Roeck 	.is_visible = lm95241_is_visible,
4263e904628SGuenter Roeck 	.read = lm95241_read,
4273e904628SGuenter Roeck 	.write = lm95241_write,
4283e904628SGuenter Roeck };
4293e904628SGuenter Roeck 
4303e904628SGuenter Roeck static const struct hwmon_chip_info lm95241_chip_info = {
4313e904628SGuenter Roeck 	.ops = &lm95241_hwmon_ops,
4323e904628SGuenter Roeck 	.info = lm95241_info,
4333e904628SGuenter Roeck };
4343e904628SGuenter Roeck 
435f809621eSGuenter Roeck static int lm95241_probe(struct i2c_client *client,
436797eaa4bSJean Delvare 			 const struct i2c_device_id *id)
437797eaa4bSJean Delvare {
438f809621eSGuenter Roeck 	struct device *dev = &client->dev;
439797eaa4bSJean Delvare 	struct lm95241_data *data;
440f809621eSGuenter Roeck 	struct device *hwmon_dev;
441797eaa4bSJean Delvare 
442f809621eSGuenter Roeck 	data = devm_kzalloc(dev, sizeof(struct lm95241_data), GFP_KERNEL);
4431487bf70SGuenter Roeck 	if (!data)
4441487bf70SGuenter Roeck 		return -ENOMEM;
445797eaa4bSJean Delvare 
446f809621eSGuenter Roeck 	data->client = client;
44706160327SDavide Rizzo 	mutex_init(&data->update_lock);
44806160327SDavide Rizzo 
44906160327SDavide Rizzo 	/* Initialize the LM95241 chip */
450f809621eSGuenter Roeck 	lm95241_init_client(client, data);
45106160327SDavide Rizzo 
4523e904628SGuenter Roeck 	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
453f809621eSGuenter Roeck 							   data,
4543e904628SGuenter Roeck 							   &lm95241_chip_info,
4553e904628SGuenter Roeck 							   NULL);
456f809621eSGuenter Roeck 	return PTR_ERR_OR_ZERO(hwmon_dev);
45706160327SDavide Rizzo }
45806160327SDavide Rizzo 
459797eaa4bSJean Delvare /* Driver data (common to all clients) */
460797eaa4bSJean Delvare static const struct i2c_device_id lm95241_id[] = {
4618c1d0419SGuenter Roeck 	{ "lm95231", 0 },
4628c1d0419SGuenter Roeck 	{ "lm95241", 0 },
463797eaa4bSJean Delvare 	{ }
464797eaa4bSJean Delvare };
465797eaa4bSJean Delvare MODULE_DEVICE_TABLE(i2c, lm95241_id);
466797eaa4bSJean Delvare 
467797eaa4bSJean Delvare static struct i2c_driver lm95241_driver = {
468797eaa4bSJean Delvare 	.class		= I2C_CLASS_HWMON,
469797eaa4bSJean Delvare 	.driver = {
4700f1deb4bSDavide Rizzo 		.name	= DEVNAME,
471797eaa4bSJean Delvare 	},
472797eaa4bSJean Delvare 	.probe		= lm95241_probe,
473797eaa4bSJean Delvare 	.id_table	= lm95241_id,
474797eaa4bSJean Delvare 	.detect		= lm95241_detect,
475c3813d6aSJean Delvare 	.address_list	= normal_i2c,
476797eaa4bSJean Delvare };
477797eaa4bSJean Delvare 
478f0967eeaSAxel Lin module_i2c_driver(lm95241_driver);
47906160327SDavide Rizzo 
4800f1deb4bSDavide Rizzo MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
4810a8784e7SAxel Lin MODULE_DESCRIPTION("LM95231/LM95241 sensor driver");
48206160327SDavide Rizzo MODULE_LICENSE("GPL");
483