brintos

brintos / linux-shallow public Read only

0
0
Text · 11.0 KiB · 9537727 Raw
494 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* tmp421.c3 *4 * Copyright (C) 2009 Andre Prendel <andre.prendel@gmx.de>5 * Preliminary support by:6 * Melvin Rook, Raymond Ng7 */8 9/*10 * Driver for the Texas Instruments TMP421 SMBus temperature sensor IC.11 * Supported models: TMP421, TMP422, TMP423, TMP441, TMP44212 */13 14#include <linux/module.h>15#include <linux/init.h>16#include <linux/slab.h>17#include <linux/jiffies.h>18#include <linux/i2c.h>19#include <linux/hwmon.h>20#include <linux/hwmon-sysfs.h>21#include <linux/err.h>22#include <linux/mutex.h>23#include <linux/of.h>24#include <linux/sysfs.h>25 26/* Addresses to scan */27static const unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f,28					     I2C_CLIENT_END };29 30enum chips { tmp421, tmp422, tmp423, tmp441, tmp442 };31 32#define MAX_CHANNELS				433/* The TMP421 registers */34#define TMP421_STATUS_REG			0x0835#define TMP421_CONFIG_REG_1			0x0936#define TMP421_CONFIG_REG_2			0x0A37#define TMP421_CONFIG_REG_REN(x)		(BIT(3 + (x)))38#define TMP421_CONFIG_REG_REN_MASK		GENMASK(6, 3)39#define TMP421_CONVERSION_RATE_REG		0x0B40#define TMP421_N_FACTOR_REG_1			0x2141#define TMP421_MANUFACTURER_ID_REG		0xFE42#define TMP421_DEVICE_ID_REG			0xFF43 44static const u8 TMP421_TEMP_MSB[MAX_CHANNELS]	= { 0x00, 0x01, 0x02, 0x03 };45static const u8 TMP421_TEMP_LSB[MAX_CHANNELS]	= { 0x10, 0x11, 0x12, 0x13 };46 47/* Flags */48#define TMP421_CONFIG_SHUTDOWN			0x4049#define TMP421_CONFIG_RANGE			0x0450 51/* Manufacturer / Device ID's */52#define TMP421_MANUFACTURER_ID			0x5553#define TMP421_DEVICE_ID			0x2154#define TMP422_DEVICE_ID			0x2255#define TMP423_DEVICE_ID			0x2356#define TMP441_DEVICE_ID			0x4157#define TMP442_DEVICE_ID			0x4258 59static const struct i2c_device_id tmp421_id[] = {60	{ "tmp421", 2 },61	{ "tmp422", 3 },62	{ "tmp423", 4 },63	{ "tmp441", 2 },64	{ "tmp442", 3 },65	{ }66};67MODULE_DEVICE_TABLE(i2c, tmp421_id);68 69static const struct of_device_id __maybe_unused tmp421_of_match[] = {70	{71		.compatible = "ti,tmp421",72		.data = (void *)273	},74	{75		.compatible = "ti,tmp422",76		.data = (void *)377	},78	{79		.compatible = "ti,tmp423",80		.data = (void *)481	},82	{83		.compatible = "ti,tmp441",84		.data = (void *)285	},86	{87		.compatible = "ti,tmp442",88		.data = (void *)389	},90	{ },91};92MODULE_DEVICE_TABLE(of, tmp421_of_match);93 94struct tmp421_channel {95	const char *label;96	bool enabled;97	s16 temp;98};99 100struct tmp421_data {101	struct i2c_client *client;102	struct mutex update_lock;103	u32 temp_config[MAX_CHANNELS + 1];104	struct hwmon_channel_info temp_info;105	const struct hwmon_channel_info *info[2];106	struct hwmon_chip_info chip;107	bool valid;108	unsigned long last_updated;109	unsigned long channels;110	u8 config;111	struct tmp421_channel channel[MAX_CHANNELS];112};113 114static int temp_from_raw(u16 reg, bool extended)115{116	/* Mask out status bits */117	int temp = reg & ~0xf;118 119	if (extended)120		temp = temp - 64 * 256;121	else122		temp = (s16)temp;123 124	return DIV_ROUND_CLOSEST(temp * 1000, 256);125}126 127static int tmp421_update_device(struct tmp421_data *data)128{129	struct i2c_client *client = data->client;130	int ret = 0;131	int i;132 133	mutex_lock(&data->update_lock);134 135	if (time_after(jiffies, data->last_updated + (HZ / 2)) ||136	    !data->valid) {137		ret = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1);138		if (ret < 0)139			goto exit;140		data->config = ret;141 142		for (i = 0; i < data->channels; i++) {143			ret = i2c_smbus_read_byte_data(client, TMP421_TEMP_MSB[i]);144			if (ret < 0)145				goto exit;146			data->channel[i].temp = ret << 8;147 148			ret = i2c_smbus_read_byte_data(client, TMP421_TEMP_LSB[i]);149			if (ret < 0)150				goto exit;151			data->channel[i].temp |= ret;152		}153		data->last_updated = jiffies;154		data->valid = true;155	}156 157exit:158	mutex_unlock(&data->update_lock);159 160	if (ret < 0) {161		data->valid = false;162		return ret;163	}164 165	return 0;166}167 168static int tmp421_enable_channels(struct tmp421_data *data)169{170	int err;171	struct i2c_client *client = data->client;172	struct device *dev = &client->dev;173	int old = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_2);174	int new, i;175 176	if (old < 0) {177		dev_err(dev, "error reading register, can't disable channels\n");178		return old;179	}180 181	new = old & ~TMP421_CONFIG_REG_REN_MASK;182	for (i = 0; i < data->channels; i++)183		if (data->channel[i].enabled)184			new |= TMP421_CONFIG_REG_REN(i);185 186	if (new == old)187		return 0;188 189	err = i2c_smbus_write_byte_data(client, TMP421_CONFIG_REG_2, new);190	if (err < 0)191		dev_err(dev, "error writing register, can't disable channels\n");192 193	return err;194}195 196static int tmp421_read(struct device *dev, enum hwmon_sensor_types type,197		       u32 attr, int channel, long *val)198{199	struct tmp421_data *tmp421 = dev_get_drvdata(dev);200	int ret = 0;201 202	ret = tmp421_update_device(tmp421);203	if (ret)204		return ret;205 206	switch (attr) {207	case hwmon_temp_input:208		if (!tmp421->channel[channel].enabled)209			return -ENODATA;210		*val = temp_from_raw(tmp421->channel[channel].temp,211				     tmp421->config & TMP421_CONFIG_RANGE);212		return 0;213	case hwmon_temp_fault:214		if (!tmp421->channel[channel].enabled)215			return -ENODATA;216		/*217		 * Any of OPEN or /PVLD bits indicate a hardware mulfunction218		 * and the conversion result may be incorrect219		 */220		*val = !!(tmp421->channel[channel].temp & 0x03);221		return 0;222	case hwmon_temp_enable:223		*val = tmp421->channel[channel].enabled;224		return 0;225	default:226		return -EOPNOTSUPP;227	}228 229}230 231static int tmp421_read_string(struct device *dev, enum hwmon_sensor_types type,232			     u32 attr, int channel, const char **str)233{234	struct tmp421_data *data = dev_get_drvdata(dev);235 236	*str = data->channel[channel].label;237 238	return 0;239}240 241static int tmp421_write(struct device *dev, enum hwmon_sensor_types type,242			u32 attr, int channel, long val)243{244	struct tmp421_data *data = dev_get_drvdata(dev);245	int ret;246 247	switch (attr) {248	case hwmon_temp_enable:249		data->channel[channel].enabled = val;250		ret = tmp421_enable_channels(data);251		break;252	default:253	    ret = -EOPNOTSUPP;254	}255 256	return ret;257}258 259static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type,260				 u32 attr, int channel)261{262	switch (attr) {263	case hwmon_temp_fault:264	case hwmon_temp_input:265		return 0444;266	case hwmon_temp_label:267		return 0444;268	case hwmon_temp_enable:269		return 0644;270	default:271		return 0;272	}273}274 275static int tmp421_init_client(struct tmp421_data *data)276{277	int config, config_orig;278	struct i2c_client *client = data->client;279 280	/* Set the conversion rate to 2 Hz */281	i2c_smbus_write_byte_data(client, TMP421_CONVERSION_RATE_REG, 0x05);282 283	/* Start conversions (disable shutdown if necessary) */284	config = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1);285	if (config < 0) {286		dev_err(&client->dev,287			"Could not read configuration register (%d)\n", config);288		return config;289	}290 291	config_orig = config;292	config &= ~TMP421_CONFIG_SHUTDOWN;293 294	if (config != config_orig) {295		dev_info(&client->dev, "Enable monitoring chip\n");296		i2c_smbus_write_byte_data(client, TMP421_CONFIG_REG_1, config);297	}298 299	return tmp421_enable_channels(data);300}301 302static int tmp421_detect(struct i2c_client *client,303			 struct i2c_board_info *info)304{305	enum chips kind;306	struct i2c_adapter *adapter = client->adapter;307	static const char * const names[] = {308		"TMP421", "TMP422", "TMP423",309		"TMP441", "TMP442"310	};311	int addr = client->addr;312	u8 reg;313 314	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))315		return -ENODEV;316 317	reg = i2c_smbus_read_byte_data(client, TMP421_MANUFACTURER_ID_REG);318	if (reg != TMP421_MANUFACTURER_ID)319		return -ENODEV;320 321	reg = i2c_smbus_read_byte_data(client, TMP421_CONVERSION_RATE_REG);322	if (reg & 0xf8)323		return -ENODEV;324 325	reg = i2c_smbus_read_byte_data(client, TMP421_STATUS_REG);326	if (reg & 0x7f)327		return -ENODEV;328 329	reg = i2c_smbus_read_byte_data(client, TMP421_DEVICE_ID_REG);330	switch (reg) {331	case TMP421_DEVICE_ID:332		kind = tmp421;333		break;334	case TMP422_DEVICE_ID:335		if (addr == 0x2a)336			return -ENODEV;337		kind = tmp422;338		break;339	case TMP423_DEVICE_ID:340		if (addr != 0x4c && addr != 0x4d)341			return -ENODEV;342		kind = tmp423;343		break;344	case TMP441_DEVICE_ID:345		kind = tmp441;346		break;347	case TMP442_DEVICE_ID:348		if (addr != 0x4c && addr != 0x4d)349			return -ENODEV;350		kind = tmp442;351		break;352	default:353		return -ENODEV;354	}355 356	strscpy(info->type, tmp421_id[kind].name, I2C_NAME_SIZE);357	dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n",358		 names[kind], client->addr);359 360	return 0;361}362 363static int tmp421_probe_child_from_dt(struct i2c_client *client,364				      struct device_node *child,365				      struct tmp421_data *data)366 367{368	struct device *dev = &client->dev;369	u32 i;370	s32 val;371	int err;372 373	err = of_property_read_u32(child, "reg", &i);374	if (err) {375		dev_err(dev, "missing reg property of %pOFn\n", child);376		return err;377	}378 379	if (i >= data->channels) {380		dev_err(dev, "invalid reg %d of %pOFn\n", i, child);381		return -EINVAL;382	}383 384	of_property_read_string(child, "label", &data->channel[i].label);385	if (data->channel[i].label)386		data->temp_config[i] |= HWMON_T_LABEL;387 388	data->channel[i].enabled = of_device_is_available(child);389 390	err = of_property_read_s32(child, "ti,n-factor", &val);391	if (!err) {392		if (i == 0) {393			dev_err(dev, "n-factor can't be set for internal channel\n");394			return -EINVAL;395		}396 397		if (val > 127 || val < -128) {398			dev_err(dev, "n-factor for channel %d invalid (%d)\n",399				i, val);400			return -EINVAL;401		}402		i2c_smbus_write_byte_data(client, TMP421_N_FACTOR_REG_1 + i - 1,403					  val);404	}405 406	return 0;407}408 409static int tmp421_probe_from_dt(struct i2c_client *client, struct tmp421_data *data)410{411	struct device *dev = &client->dev;412	const struct device_node *np = dev->of_node;413	int err;414 415	for_each_child_of_node_scoped(np, child) {416		if (strcmp(child->name, "channel"))417			continue;418 419		err = tmp421_probe_child_from_dt(client, child, data);420		if (err)421			return err;422	}423 424	return 0;425}426 427static const struct hwmon_ops tmp421_ops = {428	.is_visible = tmp421_is_visible,429	.read = tmp421_read,430	.read_string = tmp421_read_string,431	.write = tmp421_write,432};433 434static int tmp421_probe(struct i2c_client *client)435{436	struct device *dev = &client->dev;437	struct device *hwmon_dev;438	struct tmp421_data *data;439	int i, err;440 441	data = devm_kzalloc(dev, sizeof(struct tmp421_data), GFP_KERNEL);442	if (!data)443		return -ENOMEM;444 445	mutex_init(&data->update_lock);446	data->channels = (unsigned long)i2c_get_match_data(client);447	data->client = client;448 449	for (i = 0; i < data->channels; i++) {450		data->temp_config[i] = HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_ENABLE;451		data->channel[i].enabled = true;452	}453 454	err = tmp421_probe_from_dt(client, data);455	if (err)456		return err;457 458	err = tmp421_init_client(data);459	if (err)460		return err;461 462	data->chip.ops = &tmp421_ops;463	data->chip.info = data->info;464 465	data->info[0] = &data->temp_info;466 467	data->temp_info.type = hwmon_temp;468	data->temp_info.config = data->temp_config;469 470	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,471							 data,472							 &data->chip,473							 NULL);474	return PTR_ERR_OR_ZERO(hwmon_dev);475}476 477static struct i2c_driver tmp421_driver = {478	.class = I2C_CLASS_HWMON,479	.driver = {480		.name	= "tmp421",481		.of_match_table = of_match_ptr(tmp421_of_match),482	},483	.probe = tmp421_probe,484	.id_table = tmp421_id,485	.detect = tmp421_detect,486	.address_list = normal_i2c,487};488 489module_i2c_driver(tmp421_driver);490 491MODULE_AUTHOR("Andre Prendel <andre.prendel@gmx.de>");492MODULE_DESCRIPTION("Texas Instruments TMP421/422/423/441/442 temperature sensor driver");493MODULE_LICENSE("GPL");494