| // SPDX-License-Identifier: GPL-2.0-or-later | 
 | /* | 
 |  * lm83.c - Part of lm_sensors, Linux kernel modules for hardware | 
 |  *          monitoring | 
 |  * Copyright (C) 2003-2009  Jean Delvare <jdelvare@suse.de> | 
 |  * | 
 |  * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is | 
 |  * a sensor chip made by National Semiconductor. It reports up to four | 
 |  * temperatures (its own plus up to three external ones) with a 1 deg | 
 |  * resolution and a 3-4 deg accuracy. Complete datasheet can be obtained | 
 |  * from National's website at: | 
 |  *   http://www.national.com/pf/LM/LM83.html | 
 |  * Since the datasheet omits to give the chip stepping code, I give it | 
 |  * here: 0x03 (at register 0xff). | 
 |  * | 
 |  * Also supports the LM82 temp sensor, which is basically a stripped down | 
 |  * model of the LM83.  Datasheet is here: | 
 |  * http://www.national.com/pf/LM/LM82.html | 
 |  */ | 
 |  | 
 | #include <linux/bits.h> | 
 | #include <linux/err.h> | 
 | #include <linux/i2c.h> | 
 | #include <linux/init.h> | 
 | #include <linux/hwmon.h> | 
 | #include <linux/module.h> | 
 | #include <linux/regmap.h> | 
 | #include <linux/slab.h> | 
 |  | 
 | /* | 
 |  * Addresses to scan | 
 |  * Address is selected using 2 three-level pins, resulting in 9 possible | 
 |  * addresses. | 
 |  */ | 
 |  | 
 | static const unsigned short normal_i2c[] = { | 
 | 	0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; | 
 |  | 
 | enum chips { lm83, lm82 }; | 
 |  | 
 | /* | 
 |  * The LM83 registers | 
 |  * Manufacturer ID is 0x01 for National Semiconductor. | 
 |  */ | 
 |  | 
 | #define LM83_REG_R_MAN_ID		0xFE | 
 | #define LM83_REG_R_CHIP_ID		0xFF | 
 | #define LM83_REG_R_CONFIG		0x03 | 
 | #define LM83_REG_W_CONFIG		0x09 | 
 | #define LM83_REG_R_STATUS1		0x02 | 
 | #define LM83_REG_R_STATUS2		0x35 | 
 | #define LM83_REG_R_LOCAL_TEMP		0x00 | 
 | #define LM83_REG_R_LOCAL_HIGH		0x05 | 
 | #define LM83_REG_W_LOCAL_HIGH		0x0B | 
 | #define LM83_REG_R_REMOTE1_TEMP		0x30 | 
 | #define LM83_REG_R_REMOTE1_HIGH		0x38 | 
 | #define LM83_REG_W_REMOTE1_HIGH		0x50 | 
 | #define LM83_REG_R_REMOTE2_TEMP		0x01 | 
 | #define LM83_REG_R_REMOTE2_HIGH		0x07 | 
 | #define LM83_REG_W_REMOTE2_HIGH		0x0D | 
 | #define LM83_REG_R_REMOTE3_TEMP		0x31 | 
 | #define LM83_REG_R_REMOTE3_HIGH		0x3A | 
 | #define LM83_REG_W_REMOTE3_HIGH		0x52 | 
 | #define LM83_REG_R_TCRIT		0x42 | 
 | #define LM83_REG_W_TCRIT		0x5A | 
 |  | 
 | static const u8 LM83_REG_TEMP[] = { | 
 | 	LM83_REG_R_LOCAL_TEMP, | 
 | 	LM83_REG_R_REMOTE1_TEMP, | 
 | 	LM83_REG_R_REMOTE2_TEMP, | 
 | 	LM83_REG_R_REMOTE3_TEMP, | 
 | }; | 
 |  | 
 | static const u8 LM83_REG_MAX[] = { | 
 | 	LM83_REG_R_LOCAL_HIGH, | 
 | 	LM83_REG_R_REMOTE1_HIGH, | 
 | 	LM83_REG_R_REMOTE2_HIGH, | 
 | 	LM83_REG_R_REMOTE3_HIGH, | 
 | }; | 
 |  | 
 | /* alarm and fault registers and bits, indexed by channel */ | 
 | static const u8 LM83_ALARM_REG[] = { | 
 | 	LM83_REG_R_STATUS1, LM83_REG_R_STATUS2, LM83_REG_R_STATUS1, LM83_REG_R_STATUS2 | 
 | }; | 
 |  | 
 | static const u8 LM83_MAX_ALARM_BIT[] = { | 
 | 	BIT(6), BIT(7), BIT(4), BIT(4) | 
 | }; | 
 |  | 
 | static const u8 LM83_CRIT_ALARM_BIT[] = { | 
 | 	BIT(0), BIT(0), BIT(1), BIT(1) | 
 | }; | 
 |  | 
 | static const u8 LM83_FAULT_BIT[] = { | 
 | 	0, BIT(5), BIT(2), BIT(2) | 
 | }; | 
 |  | 
 | /* | 
 |  * Client data (each client gets its own) | 
 |  */ | 
 |  | 
 | struct lm83_data { | 
 | 	struct regmap *regmap; | 
 | 	enum chips type; | 
 | }; | 
 |  | 
 | /* regmap code */ | 
 |  | 
 | static int lm83_regmap_reg_read(void *context, unsigned int reg, unsigned int *val) | 
 | { | 
 | 	struct i2c_client *client = context; | 
 | 	int ret; | 
 |  | 
 | 	ret = i2c_smbus_read_byte_data(client, reg); | 
 | 	if (ret < 0) | 
 | 		return ret; | 
 |  | 
 | 	*val = ret; | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* | 
 |  * The regmap write function maps read register addresses to write register | 
 |  * addresses. This is necessary for regmap register caching to work. | 
 |  * An alternative would be to clear the regmap cache whenever a register is | 
 |  * written, but that would be much more expensive. | 
 |  */ | 
 | static int lm83_regmap_reg_write(void *context, unsigned int reg, unsigned int val) | 
 | { | 
 | 	struct i2c_client *client = context; | 
 |  | 
 | 	switch (reg) { | 
 | 	case LM83_REG_R_CONFIG: | 
 | 	case LM83_REG_R_LOCAL_HIGH: | 
 | 	case LM83_REG_R_REMOTE2_HIGH: | 
 | 		reg += 0x06; | 
 | 		break; | 
 | 	case LM83_REG_R_REMOTE1_HIGH: | 
 | 	case LM83_REG_R_REMOTE3_HIGH: | 
 | 	case LM83_REG_R_TCRIT: | 
 | 		reg += 0x18; | 
 | 		break; | 
 | 	default: | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	return i2c_smbus_write_byte_data(client, reg, val); | 
 | } | 
 |  | 
 | static bool lm83_regmap_is_volatile(struct device *dev, unsigned int reg) | 
 | { | 
 | 	switch (reg) { | 
 | 	case LM83_REG_R_LOCAL_TEMP: | 
 | 	case LM83_REG_R_REMOTE1_TEMP: | 
 | 	case LM83_REG_R_REMOTE2_TEMP: | 
 | 	case LM83_REG_R_REMOTE3_TEMP: | 
 | 	case LM83_REG_R_STATUS1: | 
 | 	case LM83_REG_R_STATUS2: | 
 | 		return true; | 
 | 	default: | 
 | 		return false; | 
 | 	} | 
 | } | 
 |  | 
 | static const struct regmap_config lm83_regmap_config = { | 
 | 	.reg_bits = 8, | 
 | 	.val_bits = 8, | 
 | 	.cache_type = REGCACHE_MAPLE, | 
 | 	.volatile_reg = lm83_regmap_is_volatile, | 
 | 	.reg_read = lm83_regmap_reg_read, | 
 | 	.reg_write = lm83_regmap_reg_write, | 
 | }; | 
 |  | 
 | /* hwmon API */ | 
 |  | 
 | static int lm83_temp_read(struct device *dev, u32 attr, int channel, long *val) | 
 | { | 
 | 	struct lm83_data *data = dev_get_drvdata(dev); | 
 | 	unsigned int regval; | 
 | 	int err; | 
 |  | 
 | 	switch (attr) { | 
 | 	case hwmon_temp_input: | 
 | 		err = regmap_read(data->regmap, LM83_REG_TEMP[channel], ®val); | 
 | 		if (err < 0) | 
 | 			return err; | 
 | 		*val = (s8)regval * 1000; | 
 | 		break; | 
 | 	case hwmon_temp_max: | 
 | 		err = regmap_read(data->regmap, LM83_REG_MAX[channel], ®val); | 
 | 		if (err < 0) | 
 | 			return err; | 
 | 		*val = (s8)regval * 1000; | 
 | 		break; | 
 | 	case hwmon_temp_crit: | 
 | 		err = regmap_read(data->regmap, LM83_REG_R_TCRIT, ®val); | 
 | 		if (err < 0) | 
 | 			return err; | 
 | 		*val = (s8)regval * 1000; | 
 | 		break; | 
 | 	case hwmon_temp_max_alarm: | 
 | 		err = regmap_read(data->regmap, LM83_ALARM_REG[channel], ®val); | 
 | 		if (err < 0) | 
 | 			return err; | 
 | 		*val = !!(regval & LM83_MAX_ALARM_BIT[channel]); | 
 | 		break; | 
 | 	case hwmon_temp_crit_alarm: | 
 | 		err = regmap_read(data->regmap, LM83_ALARM_REG[channel], ®val); | 
 | 		if (err < 0) | 
 | 			return err; | 
 | 		*val = !!(regval & LM83_CRIT_ALARM_BIT[channel]); | 
 | 		break; | 
 | 	case hwmon_temp_fault: | 
 | 		err = regmap_read(data->regmap, LM83_ALARM_REG[channel], ®val); | 
 | 		if (err < 0) | 
 | 			return err; | 
 | 		*val = !!(regval & LM83_FAULT_BIT[channel]); | 
 | 		break; | 
 | 	default: | 
 | 		return -EOPNOTSUPP; | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int lm83_temp_write(struct device *dev, u32 attr, int channel, long val) | 
 | { | 
 | 	struct lm83_data *data = dev_get_drvdata(dev); | 
 | 	unsigned int regval; | 
 | 	int err; | 
 |  | 
 | 	regval = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000); | 
 |  | 
 | 	switch (attr) { | 
 | 	case hwmon_temp_max: | 
 | 		err = regmap_write(data->regmap, LM83_REG_MAX[channel], regval); | 
 | 		if (err < 0) | 
 | 			return err; | 
 | 		break; | 
 | 	case hwmon_temp_crit: | 
 | 		err = regmap_write(data->regmap, LM83_REG_R_TCRIT, regval); | 
 | 		if (err < 0) | 
 | 			return err; | 
 | 		break; | 
 | 	default: | 
 | 		return -EOPNOTSUPP; | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int lm83_chip_read(struct device *dev, u32 attr, int channel, long *val) | 
 | { | 
 | 	struct lm83_data *data = dev_get_drvdata(dev); | 
 | 	unsigned int regval; | 
 | 	int err; | 
 |  | 
 | 	switch (attr) { | 
 | 	case hwmon_chip_alarms: | 
 | 		err = regmap_read(data->regmap, LM83_REG_R_STATUS1, ®val); | 
 | 		if (err < 0) | 
 | 			return err; | 
 | 		*val = regval; | 
 | 		err = regmap_read(data->regmap, LM83_REG_R_STATUS2, ®val); | 
 | 		if (err < 0) | 
 | 			return err; | 
 | 		*val |= regval << 8; | 
 | 		return 0; | 
 | 	default: | 
 | 		return -EOPNOTSUPP; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int lm83_read(struct device *dev, enum hwmon_sensor_types type, | 
 | 		     u32 attr, int channel, long *val) | 
 | { | 
 | 	switch (type) { | 
 | 	case hwmon_chip: | 
 | 		return lm83_chip_read(dev, attr, channel, val); | 
 | 	case hwmon_temp: | 
 | 		return lm83_temp_read(dev, attr, channel, val); | 
 | 	default: | 
 | 		return -EOPNOTSUPP; | 
 | 	} | 
 | } | 
 |  | 
 | static int lm83_write(struct device *dev, enum hwmon_sensor_types type, | 
 | 		      u32 attr, int channel, long val) | 
 | { | 
 | 	switch (type) { | 
 | 	case hwmon_temp: | 
 | 		return lm83_temp_write(dev, attr, channel, val); | 
 | 	default: | 
 | 		return -EOPNOTSUPP; | 
 | 	} | 
 | } | 
 |  | 
 | static umode_t lm83_is_visible(const void *_data, enum hwmon_sensor_types type, | 
 | 			       u32 attr, int channel) | 
 | { | 
 | 	const struct lm83_data *data = _data; | 
 |  | 
 | 	/* | 
 | 	 * LM82 only supports a single external channel, modeled as channel 2. | 
 | 	 */ | 
 | 	if (data->type == lm82 && (channel == 1 || channel == 3)) | 
 | 		return 0; | 
 |  | 
 | 	switch (type) { | 
 | 	case hwmon_chip: | 
 | 		if (attr == hwmon_chip_alarms) | 
 | 			return 0444; | 
 | 		break; | 
 | 	case hwmon_temp: | 
 | 		switch (attr) { | 
 | 		case hwmon_temp_input: | 
 | 		case hwmon_temp_max_alarm: | 
 | 		case hwmon_temp_crit_alarm: | 
 | 			return 0444; | 
 | 		case hwmon_temp_fault: | 
 | 			if (channel) | 
 | 				return 0444; | 
 | 			break; | 
 | 		case hwmon_temp_max: | 
 | 			return 0644; | 
 | 		case hwmon_temp_crit: | 
 | 			if (channel == 2) | 
 | 				return 0644; | 
 | 			return 0444; | 
 | 		default: | 
 | 			break; | 
 | 		} | 
 | 		break; | 
 | 	default: | 
 | 		break; | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 | static const struct hwmon_channel_info * const lm83_info[] = { | 
 | 	HWMON_CHANNEL_INFO(chip, HWMON_C_ALARMS), | 
 | 	HWMON_CHANNEL_INFO(temp, | 
 | 			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | | 
 | 			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM, | 
 | 			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | | 
 | 			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT, | 
 | 			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | | 
 | 			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT, | 
 | 			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | | 
 | 			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT | 
 | 			   ), | 
 | 	NULL | 
 | }; | 
 |  | 
 | static const struct hwmon_ops lm83_hwmon_ops = { | 
 | 	.is_visible = lm83_is_visible, | 
 | 	.read = lm83_read, | 
 | 	.write = lm83_write, | 
 | }; | 
 |  | 
 | static const struct hwmon_chip_info lm83_chip_info = { | 
 | 	.ops = &lm83_hwmon_ops, | 
 | 	.info = lm83_info, | 
 | }; | 
 |  | 
 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 
 | static int lm83_detect(struct i2c_client *client, | 
 | 		       struct i2c_board_info *info) | 
 | { | 
 | 	struct i2c_adapter *adapter = client->adapter; | 
 | 	const char *name; | 
 | 	u8 man_id, chip_id; | 
 |  | 
 | 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 
 | 		return -ENODEV; | 
 |  | 
 | 	/* Detection */ | 
 | 	if ((i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1) & 0xA8) || | 
 | 	    (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2) & 0x48) || | 
 | 	    (i2c_smbus_read_byte_data(client, LM83_REG_R_CONFIG) & 0x41)) { | 
 | 		dev_dbg(&adapter->dev, "LM83 detection failed at 0x%02x\n", | 
 | 			client->addr); | 
 | 		return -ENODEV; | 
 | 	} | 
 |  | 
 | 	/* Identification */ | 
 | 	man_id = i2c_smbus_read_byte_data(client, LM83_REG_R_MAN_ID); | 
 | 	if (man_id != 0x01)	/* National Semiconductor */ | 
 | 		return -ENODEV; | 
 |  | 
 | 	chip_id = i2c_smbus_read_byte_data(client, LM83_REG_R_CHIP_ID); | 
 | 	switch (chip_id) { | 
 | 	case 0x03: | 
 | 		/* | 
 | 		 * According to the LM82 datasheet dated March 2013, recent | 
 | 		 * revisions of LM82 have a die revision of 0x03. This was | 
 | 		 * confirmed with a real chip. Further details in this revision | 
 | 		 * of the LM82 datasheet strongly suggest that LM82 is just a | 
 | 		 * repackaged LM83. It is therefore impossible to distinguish | 
 | 		 * those chips from LM83, and they will be misdetected as LM83. | 
 | 		 */ | 
 | 		name = "lm83"; | 
 | 		break; | 
 | 	case 0x01: | 
 | 		name = "lm82"; | 
 | 		break; | 
 | 	default: | 
 | 		/* identification failed */ | 
 | 		dev_dbg(&adapter->dev, | 
 | 			"Unsupported chip (man_id=0x%02X, chip_id=0x%02X)\n", | 
 | 			man_id, chip_id); | 
 | 		return -ENODEV; | 
 | 	} | 
 |  | 
 | 	strscpy(info->type, name, I2C_NAME_SIZE); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int lm83_probe(struct i2c_client *client) | 
 | { | 
 | 	struct device *dev = &client->dev; | 
 | 	struct device *hwmon_dev; | 
 | 	struct lm83_data *data; | 
 |  | 
 | 	data = devm_kzalloc(dev, sizeof(struct lm83_data), GFP_KERNEL); | 
 | 	if (!data) | 
 | 		return -ENOMEM; | 
 |  | 
 | 	data->regmap = devm_regmap_init(dev, NULL, client, &lm83_regmap_config); | 
 | 	if (IS_ERR(data->regmap)) | 
 | 		return PTR_ERR(data->regmap); | 
 |  | 
 | 	data->type = (uintptr_t)i2c_get_match_data(client); | 
 |  | 
 | 	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, | 
 | 							 data, &lm83_chip_info, NULL); | 
 | 	return PTR_ERR_OR_ZERO(hwmon_dev); | 
 | } | 
 |  | 
 | /* | 
 |  * Driver data (common to all clients) | 
 |  */ | 
 |  | 
 | static const struct i2c_device_id lm83_id[] = { | 
 | 	{ "lm83", lm83 }, | 
 | 	{ "lm82", lm82 }, | 
 | 	{ } | 
 | }; | 
 | MODULE_DEVICE_TABLE(i2c, lm83_id); | 
 |  | 
 | static struct i2c_driver lm83_driver = { | 
 | 	.class		= I2C_CLASS_HWMON, | 
 | 	.driver = { | 
 | 		.name	= "lm83", | 
 | 	}, | 
 | 	.probe		= lm83_probe, | 
 | 	.id_table	= lm83_id, | 
 | 	.detect		= lm83_detect, | 
 | 	.address_list	= normal_i2c, | 
 | }; | 
 |  | 
 | module_i2c_driver(lm83_driver); | 
 |  | 
 | MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); | 
 | MODULE_DESCRIPTION("LM83 driver"); | 
 | MODULE_LICENSE("GPL"); |