brintos

brintos / linux-shallow public Read only

0
0
Text · 17.0 KiB · 0735a1d Raw
647 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2012 Guenter Roeck <linux@roeck-us.net>4 *5 * based on max1668.c6 * Copyright (c) 2011 David George <david.george@ska.ac.za>7 */8 9#include <linux/bitfield.h>10#include <linux/bits.h>11#include <linux/err.h>12#include <linux/hwmon.h>13#include <linux/i2c.h>14#include <linux/init.h>15#include <linux/module.h>16#include <linux/mutex.h>17#include <linux/of.h>18#include <linux/regmap.h>19#include <linux/slab.h>20 21enum chips { max6581, max6602, max6622, max6636, max6689, max6693, max6694,22	     max6697, max6698, max6699 };23 24/* Report local sensor as temp1 */25 26static const u8 MAX6697_REG_TEMP[] = {27			0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08 };28static const u8 MAX6697_REG_TEMP_EXT[] = {29			0x57, 0x09, 0x52, 0x53, 0x54, 0x55, 0x56, 0 };30static const u8 MAX6697_REG_MAX[] = {31			0x17, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x18 };32static const u8 MAX6697_REG_CRIT[] = {33			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 };34 35#define MAX6697_REG_MIN			0x3036/*37 * Map device tree / internal register bit map to chip bit map.38 * Applies to alert register and over-temperature register.39 */40 41#define MAX6697_EXTERNAL_MASK_DT	GENMASK(7, 1)42#define MAX6697_LOCAL_MASK_DT		BIT(0)43#define MAX6697_EXTERNAL_MASK_CHIP	GENMASK(6, 0)44#define MAX6697_LOCAL_MASK_CHIP		BIT(7)45 46/* alert - local channel is in bit 6 */47#define MAX6697_ALERT_MAP_BITS(reg)	((((reg) & 0x7e) >> 1) | \48				 (((reg) & 0x01) << 6) | ((reg) & 0x80))49 50/* over-temperature - local channel is in bit 7 */51#define MAX6697_OVERT_MAP_BITS(reg)	\52	(FIELD_PREP(MAX6697_EXTERNAL_MASK_CHIP, FIELD_GET(MAX6697_EXTERNAL_MASK_DT, reg)) | \53	 FIELD_PREP(MAX6697_LOCAL_MASK_CHIP, FIELD_GET(MAX6697_LOCAL_MASK_DT, reg)))54 55#define MAX6697_REG_STAT_ALARM		0x4456#define MAX6697_REG_STAT_CRIT		0x4557#define MAX6697_REG_STAT_FAULT		0x4658#define MAX6697_REG_STAT_MIN_ALARM	0x4759 60#define MAX6697_REG_CONFIG		0x4161#define MAX6581_CONF_EXTENDED		BIT(1)62#define MAX6693_CONF_BETA		BIT(2)63#define MAX6697_CONF_RESISTANCE		BIT(3)64#define MAX6697_CONF_TIMEOUT		BIT(5)65#define MAX6697_REG_ALERT_MASK		0x4266#define MAX6697_REG_OVERT_MASK		0x4367 68#define MAX6581_REG_RESISTANCE		0x4a69#define MAX6581_REG_IDEALITY		0x4b70#define MAX6581_REG_IDEALITY_SELECT	0x4c71#define MAX6581_REG_OFFSET		0x4d72#define MAX6581_REG_OFFSET_SELECT	0x4e73#define MAX6581_OFFSET_MIN		-3175074#define MAX6581_OFFSET_MAX		3175075 76#define MAX6697_CONV_TIME		156	/* ms per channel, worst case */77 78struct max6697_chip_data {79	int channels;80	u32 have_ext;81	u32 have_crit;82	u32 have_fault;83	u8 valid_conf;84};85 86struct max6697_data {87	struct regmap *regmap;88 89	enum chips type;90	const struct max6697_chip_data *chip;91 92	int temp_offset;	/* in degrees C */93 94	struct mutex update_lock;95 96#define MAX6697_TEMP_INPUT	097#define MAX6697_TEMP_EXT	198#define MAX6697_TEMP_MAX	299#define MAX6697_TEMP_CRIT	3100	u32 alarms;101};102 103static const struct max6697_chip_data max6697_chip_data[] = {104	[max6581] = {105		.channels = 8,106		.have_crit = 0xff,107		.have_ext = 0x7f,108		.have_fault = 0xfe,109		.valid_conf = MAX6581_CONF_EXTENDED | MAX6697_CONF_TIMEOUT,110	},111	[max6602] = {112		.channels = 5,113		.have_crit = 0x12,114		.have_ext = 0x02,115		.have_fault = 0x1e,116		.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,117	},118	[max6622] = {119		.channels = 5,120		.have_crit = 0x12,121		.have_ext = 0x02,122		.have_fault = 0x1e,123		.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,124	},125	[max6636] = {126		.channels = 7,127		.have_crit = 0x72,128		.have_ext = 0x02,129		.have_fault = 0x7e,130		.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,131	},132	[max6689] = {133		.channels = 7,134		.have_crit = 0x72,135		.have_ext = 0x02,136		.have_fault = 0x7e,137		.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,138	},139	[max6693] = {140		.channels = 7,141		.have_crit = 0x72,142		.have_ext = 0x02,143		.have_fault = 0x7e,144		.valid_conf = MAX6697_CONF_RESISTANCE | MAX6693_CONF_BETA |145		  MAX6697_CONF_TIMEOUT,146	},147	[max6694] = {148		.channels = 5,149		.have_crit = 0x12,150		.have_ext = 0x02,151		.have_fault = 0x1e,152		.valid_conf = MAX6697_CONF_RESISTANCE | MAX6693_CONF_BETA |153		  MAX6697_CONF_TIMEOUT,154	},155	[max6697] = {156		.channels = 7,157		.have_crit = 0x72,158		.have_ext = 0x02,159		.have_fault = 0x7e,160		.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,161	},162	[max6698] = {163		.channels = 7,164		.have_crit = 0x72,165		.have_ext = 0x02,166		.have_fault = 0x0e,167		.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,168	},169	[max6699] = {170		.channels = 5,171		.have_crit = 0x12,172		.have_ext = 0x02,173		.have_fault = 0x1e,174		.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,175	},176};177 178static int max6697_alarm_channel_map(int channel)179{180	switch (channel) {181	case 0:182		return 6;183	case 7:184		return 7;185	default:186		return channel - 1;187	}188}189 190static int max6697_read(struct device *dev, enum hwmon_sensor_types type,191			u32 attr, int channel, long *val)192{193	unsigned int offset_regs[2] = { MAX6581_REG_OFFSET_SELECT, MAX6581_REG_OFFSET };194	unsigned int temp_regs[2] = { MAX6697_REG_TEMP[channel],195				      MAX6697_REG_TEMP_EXT[channel] };196	struct max6697_data *data = dev_get_drvdata(dev);197	struct regmap *regmap = data->regmap;198	u8 regdata[2] = { };199	u32 regval;200	int ret;201 202	switch (attr) {203	case hwmon_temp_input:204		ret = regmap_multi_reg_read(regmap, temp_regs, regdata,205					    data->chip->have_ext & BIT(channel) ? 2 : 1);206		if (ret)207			return ret;208		*val = (((regdata[0] - data->temp_offset) << 3) | (regdata[1] >> 5)) * 125;209		break;210	case hwmon_temp_max:211		ret = regmap_read(regmap, MAX6697_REG_MAX[channel], &regval);212		if (ret)213			return ret;214		*val = ((int)regval - data->temp_offset) * 1000;215		break;216	case hwmon_temp_crit:217		ret = regmap_read(regmap, MAX6697_REG_CRIT[channel], &regval);218		if (ret)219			return ret;220		*val = ((int)regval - data->temp_offset) * 1000;221		break;222	case hwmon_temp_min:223		ret = regmap_read(regmap, MAX6697_REG_MIN, &regval);224		if (ret)225			return ret;226		*val = ((int)regval - data->temp_offset) * 1000;227		break;228	case hwmon_temp_offset:229		ret = regmap_multi_reg_read(regmap, offset_regs, regdata, 2);230		if (ret)231			return ret;232 233		if (!(regdata[0] & BIT(channel - 1)))234			regdata[1] = 0;235 236		*val = sign_extend32(regdata[1], 7) * 250;237		break;238	case hwmon_temp_fault:239		ret = regmap_read(regmap, MAX6697_REG_STAT_FAULT, &regval);240		if (ret)241			return ret;242		if (data->type == max6581)243			*val = !!(regval & BIT(channel - 1));244		else245			*val = !!(regval & BIT(channel));246		break;247	case hwmon_temp_crit_alarm:248		ret = regmap_read(regmap, MAX6697_REG_STAT_CRIT, &regval);249		if (ret)250			return ret;251		/*252		 * In the MAX6581 datasheet revision 0 to 3, the local channel253		 * overtemperature status is reported in bit 6 of register 0x45,254		 * and the overtemperature status for remote channel 7 is255		 * reported in bit 7. In Revision 4 and later, the local channel256		 * overtemperature status is reported in bit 7, and the remote257		 * channel 7 overtemperature status is reported in bit 6. A real258		 * chip was found to match the functionality documented in259		 * Revision 4 and later.260		 */261		*val = !!(regval & BIT(channel ? channel - 1 : 7));262		break;263	case hwmon_temp_max_alarm:264		ret = regmap_read(regmap, MAX6697_REG_STAT_ALARM, &regval);265		if (ret)266			return ret;267		*val = !!(regval & BIT(max6697_alarm_channel_map(channel)));268		break;269	case hwmon_temp_min_alarm:270		ret = regmap_read(regmap, MAX6697_REG_STAT_MIN_ALARM, &regval);271		if (ret)272			return ret;273		*val = !!(regval & BIT(max6697_alarm_channel_map(channel)));274		break;275	default:276		return -EOPNOTSUPP;277	}278	return 0;279}280 281static int max6697_write(struct device *dev, enum hwmon_sensor_types type,282			 u32 attr, int channel, long val)283{284	struct max6697_data *data = dev_get_drvdata(dev);285	struct regmap *regmap = data->regmap;286	int ret;287 288	switch (attr) {289	case hwmon_temp_max:290		val = clamp_val(val, -1000000, 1000000);	/* prevent underflow */291		val = DIV_ROUND_CLOSEST(val, 1000) + data->temp_offset;292		val = clamp_val(val, 0, data->type == max6581 ? 255 : 127);293		return regmap_write(regmap, MAX6697_REG_MAX[channel], val);294	case hwmon_temp_crit:295		val = clamp_val(val, -1000000, 1000000);	/* prevent underflow */296		val = DIV_ROUND_CLOSEST(val, 1000) + data->temp_offset;297		val = clamp_val(val, 0, data->type == max6581 ? 255 : 127);298		return regmap_write(regmap, MAX6697_REG_CRIT[channel], val);299	case hwmon_temp_min:300		val = clamp_val(val, -1000000, 1000000);	/* prevent underflow */301		val = DIV_ROUND_CLOSEST(val, 1000) + data->temp_offset;302		val = clamp_val(val, 0, 255);303		return regmap_write(regmap, MAX6697_REG_MIN, val);304	case hwmon_temp_offset:305		mutex_lock(&data->update_lock);306		val = clamp_val(val, MAX6581_OFFSET_MIN, MAX6581_OFFSET_MAX);307		val = DIV_ROUND_CLOSEST(val, 250);308		if (!val) {	/* disable this (and only this) channel */309			ret = regmap_clear_bits(regmap, MAX6581_REG_OFFSET_SELECT,310						BIT(channel - 1));311		} else {312			/* enable channel and update offset */313			ret = regmap_set_bits(regmap, MAX6581_REG_OFFSET_SELECT,314					      BIT(channel - 1));315			if (ret)316				goto unlock;317			ret = regmap_write(regmap, MAX6581_REG_OFFSET, val);318		}319unlock:320		mutex_unlock(&data->update_lock);321		return ret;322	default:323		return -EOPNOTSUPP;324	}325}326 327static umode_t max6697_is_visible(const void *_data, enum hwmon_sensor_types type,328				  u32 attr, int channel)329{330	const struct max6697_data *data = _data;331	const struct max6697_chip_data *chip = data->chip;332 333	if (channel >= chip->channels)334		return 0;335 336	switch (attr) {337	case hwmon_temp_max:338		return 0644;339	case hwmon_temp_input:340	case hwmon_temp_max_alarm:341		return 0444;342	case hwmon_temp_min:343		if (data->type == max6581)344			return channel ? 0444 : 0644;345		break;346	case hwmon_temp_min_alarm:347		if (data->type == max6581)348			return 0444;349		break;350	case hwmon_temp_crit:351		if (chip->have_crit & BIT(channel))352			return 0644;353		break;354	case hwmon_temp_crit_alarm:355		if (chip->have_crit & BIT(channel))356			return 0444;357		break;358	case hwmon_temp_fault:359		if (chip->have_fault & BIT(channel))360			return 0444;361		break;362	case hwmon_temp_offset:363		if (data->type == max6581 && channel)364			return 0644;365		break;366	default:367		break;368	}369	return 0;370}371 372/* Return 0 if detection is successful, -ENODEV otherwise */373static const struct hwmon_channel_info * const max6697_info[] = {374	HWMON_CHANNEL_INFO(temp,375			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |376			   HWMON_T_MIN | HWMON_T_MIN_ALARM |377			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM,378			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |379			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM |380			   HWMON_T_MIN | HWMON_T_MIN_ALARM |381			   HWMON_T_FAULT | HWMON_T_OFFSET,382			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |383			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM |384			   HWMON_T_MIN | HWMON_T_MIN_ALARM |385			   HWMON_T_FAULT | HWMON_T_OFFSET,386			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |387			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM |388			   HWMON_T_MIN | HWMON_T_MIN_ALARM |389			   HWMON_T_FAULT | HWMON_T_OFFSET,390			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |391			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM |392			   HWMON_T_MIN | HWMON_T_MIN_ALARM |393			   HWMON_T_FAULT | HWMON_T_OFFSET,394			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |395			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM |396			   HWMON_T_MIN | HWMON_T_MIN_ALARM |397			   HWMON_T_FAULT | HWMON_T_OFFSET,398			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |399			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM |400			   HWMON_T_MIN | HWMON_T_MIN_ALARM |401			   HWMON_T_FAULT | HWMON_T_OFFSET,402			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |403			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM |404			   HWMON_T_MIN | HWMON_T_MIN_ALARM |405			   HWMON_T_FAULT | HWMON_T_OFFSET),406	NULL407};408 409static const struct hwmon_ops max6697_hwmon_ops = {410	.is_visible = max6697_is_visible,411	.read = max6697_read,412	.write = max6697_write,413};414 415static const struct hwmon_chip_info max6697_chip_info = {416	.ops = &max6697_hwmon_ops,417	.info = max6697_info,418};419 420static int max6697_config_of(struct device_node *node, struct max6697_data *data)421{422	const struct max6697_chip_data *chip = data->chip;423	struct regmap *regmap = data->regmap;424	int ret, confreg;425	u32 vals[2];426 427	confreg = 0;428	if (of_property_read_bool(node, "smbus-timeout-disable") &&429	    (chip->valid_conf & MAX6697_CONF_TIMEOUT)) {430		confreg |= MAX6697_CONF_TIMEOUT;431	}432	if (of_property_read_bool(node, "extended-range-enable") &&433	    (chip->valid_conf & MAX6581_CONF_EXTENDED)) {434		confreg |= MAX6581_CONF_EXTENDED;435		data->temp_offset = 64;436	}437	if (of_property_read_bool(node, "beta-compensation-enable") &&438	    (chip->valid_conf & MAX6693_CONF_BETA)) {439		confreg |= MAX6693_CONF_BETA;440	}441 442	if (of_property_read_u32(node, "alert-mask", vals))443		vals[0] = 0;444	ret = regmap_write(regmap, MAX6697_REG_ALERT_MASK,445			   MAX6697_ALERT_MAP_BITS(vals[0]));446	if (ret)447		return ret;448 449	if (of_property_read_u32(node, "over-temperature-mask", vals))450		vals[0] = 0;451	ret = regmap_write(regmap, MAX6697_REG_OVERT_MASK,452			   MAX6697_OVERT_MAP_BITS(vals[0]));453	if (ret)454		return ret;455 456	if (data->type != max6581) {457		if (of_property_read_bool(node, "resistance-cancellation") &&458		    chip->valid_conf & MAX6697_CONF_RESISTANCE) {459			confreg |= MAX6697_CONF_RESISTANCE;460		}461	} else {462		if (of_property_read_u32(node, "resistance-cancellation", &vals[0])) {463			if (of_property_read_bool(node, "resistance-cancellation"))464				vals[0] = 0xfe;465			else466				vals[0] = 0;467		}468 469		vals[0] &= 0xfe;470		ret = regmap_write(regmap, MAX6581_REG_RESISTANCE, vals[0] >> 1);471		if (ret < 0)472			return ret;473 474		if (of_property_read_u32_array(node, "transistor-ideality", vals, 2)) {475			vals[0] = 0;476			vals[1] = 0;477		}478 479		ret = regmap_write(regmap, MAX6581_REG_IDEALITY, vals[1]);480		if (ret < 0)481			return ret;482		ret = regmap_write(regmap, MAX6581_REG_IDEALITY_SELECT,483				   (vals[0] & 0xfe) >> 1);484		if (ret < 0)485			return ret;486	}487	return regmap_write(regmap, MAX6697_REG_CONFIG, confreg);488}489 490static int max6697_init_chip(struct device_node *np, struct max6697_data *data)491{492	unsigned int reg;493	int ret;494 495	/*496	 * Don't touch configuration if there is no devicetree configuration.497	 * If that is the case, use the current chip configuration.498	 */499	if (!np) {500		struct regmap *regmap = data->regmap;501 502		ret = regmap_read(regmap, MAX6697_REG_CONFIG, &reg);503		if (ret < 0)504			return ret;505		if (data->type == max6581) {506			if (reg & MAX6581_CONF_EXTENDED)507				data->temp_offset = 64;508			ret = regmap_read(regmap, MAX6581_REG_RESISTANCE, &reg);509		}510	} else {511		ret = max6697_config_of(np, data);512	}513 514	return ret;515}516 517static bool max6697_volatile_reg(struct device *dev, unsigned int reg)518{519	switch (reg) {520	case 0x00 ... 0x09:	/* temperature high bytes */521	case 0x44 ... 0x47:	/* status */522	case 0x51 ... 0x58:	/* temperature low bytes */523		return true;524	default:525		return false;526	}527}528 529static bool max6697_writeable_reg(struct device *dev, unsigned int reg)530{531	return reg != 0x0a && reg != 0x0f && !max6697_volatile_reg(dev, reg);532}533 534static const struct regmap_config max6697_regmap_config = {535	.reg_bits = 8,536	.val_bits = 8,537	.max_register = 0x58,538	.writeable_reg = max6697_writeable_reg,539	.volatile_reg = max6697_volatile_reg,540	.cache_type = REGCACHE_MAPLE,541};542 543static int max6697_probe(struct i2c_client *client)544{545	struct device *dev = &client->dev;546	struct max6697_data *data;547	struct device *hwmon_dev;548	struct regmap *regmap;549	int err;550 551	regmap = regmap_init_i2c(client, &max6697_regmap_config);552	if (IS_ERR(regmap))553		return PTR_ERR(regmap);554 555	data = devm_kzalloc(dev, sizeof(struct max6697_data), GFP_KERNEL);556	if (!data)557		return -ENOMEM;558 559	data->regmap = regmap;560	data->type = (uintptr_t)i2c_get_match_data(client);561	data->chip = &max6697_chip_data[data->type];562	mutex_init(&data->update_lock);563 564	err = max6697_init_chip(client->dev.of_node, data);565	if (err)566		return err;567 568	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,569							 &max6697_chip_info, NULL);570	return PTR_ERR_OR_ZERO(hwmon_dev);571}572 573static const struct i2c_device_id max6697_id[] = {574	{ "max6581", max6581 },575	{ "max6602", max6602 },576	{ "max6622", max6622 },577	{ "max6636", max6636 },578	{ "max6689", max6689 },579	{ "max6693", max6693 },580	{ "max6694", max6694 },581	{ "max6697", max6697 },582	{ "max6698", max6698 },583	{ "max6699", max6699 },584	{ }585};586MODULE_DEVICE_TABLE(i2c, max6697_id);587 588static const struct of_device_id __maybe_unused max6697_of_match[] = {589	{590		.compatible = "maxim,max6581",591		.data = (void *)max6581592	},593	{594		.compatible = "maxim,max6602",595		.data = (void *)max6602596	},597	{598		.compatible = "maxim,max6622",599		.data = (void *)max6622600	},601	{602		.compatible = "maxim,max6636",603		.data = (void *)max6636604	},605	{606		.compatible = "maxim,max6689",607		.data = (void *)max6689608	},609	{610		.compatible = "maxim,max6693",611		.data = (void *)max6693612	},613	{614		.compatible = "maxim,max6694",615		.data = (void *)max6694616	},617	{618		.compatible = "maxim,max6697",619		.data = (void *)max6697620	},621	{622		.compatible = "maxim,max6698",623		.data = (void *)max6698624	},625	{626		.compatible = "maxim,max6699",627		.data = (void *)max6699628	},629	{ },630};631MODULE_DEVICE_TABLE(of, max6697_of_match);632 633static struct i2c_driver max6697_driver = {634	.driver = {635		.name	= "max6697",636		.of_match_table = of_match_ptr(max6697_of_match),637	},638	.probe = max6697_probe,639	.id_table = max6697_id,640};641 642module_i2c_driver(max6697_driver);643 644MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");645MODULE_DESCRIPTION("MAX6697 temperature sensor driver");646MODULE_LICENSE("GPL");647