brintos

brintos / linux-shallow public Read only

0
0
Text · 13.9 KiB · 1100c6e Raw
488 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * emc6w201.c - Hardware monitoring driver for the SMSC EMC6W2014 * Copyright (C) 2011  Jean Delvare <jdelvare@suse.de>5 */6 7#include <linux/module.h>8#include <linux/init.h>9#include <linux/slab.h>10#include <linux/jiffies.h>11#include <linux/i2c.h>12#include <linux/hwmon.h>13#include <linux/hwmon-sysfs.h>14#include <linux/err.h>15#include <linux/mutex.h>16 17/*18 * Addresses to scan19 */20 21static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };22 23/*24 * The EMC6W201 registers25 */26 27#define EMC6W201_REG_IN(nr)		(0x20 + (nr))28#define EMC6W201_REG_TEMP(nr)		(0x26 + (nr))29#define EMC6W201_REG_FAN(nr)		(0x2C + (nr) * 2)30#define EMC6W201_REG_COMPANY		0x3E31#define EMC6W201_REG_VERSTEP		0x3F32#define EMC6W201_REG_CONFIG		0x4033#define EMC6W201_REG_IN_LOW(nr)		(0x4A + (nr) * 2)34#define EMC6W201_REG_IN_HIGH(nr)	(0x4B + (nr) * 2)35#define EMC6W201_REG_TEMP_LOW(nr)	(0x56 + (nr) * 2)36#define EMC6W201_REG_TEMP_HIGH(nr)	(0x57 + (nr) * 2)37#define EMC6W201_REG_FAN_MIN(nr)	(0x62 + (nr) * 2)38 39enum subfeature { input, min, max };40 41/*42 * Per-device data43 */44 45struct emc6w201_data {46	struct i2c_client *client;47	struct mutex update_lock;48	bool valid; /* false until following fields are valid */49	unsigned long last_updated; /* in jiffies */50 51	/* registers values */52	u8 in[3][6];53	s8 temp[3][6];54	u16 fan[2][5];55};56 57/*58 * Combine LSB and MSB registers in a single value59 * Locking: must be called with data->update_lock held60 */61static u16 emc6w201_read16(struct i2c_client *client, u8 reg)62{63	int lsb, msb;64 65	lsb = i2c_smbus_read_byte_data(client, reg);66	msb = i2c_smbus_read_byte_data(client, reg + 1);67	if (unlikely(lsb < 0 || msb < 0)) {68		dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",69			16, "read", reg);70		return 0xFFFF;	/* Arbitrary value */71	}72 73	return (msb << 8) | lsb;74}75 76/*77 * Write 16-bit value to LSB and MSB registers78 * Locking: must be called with data->update_lock held79 */80static int emc6w201_write16(struct i2c_client *client, u8 reg, u16 val)81{82	int err;83 84	err = i2c_smbus_write_byte_data(client, reg, val & 0xff);85	if (likely(!err))86		err = i2c_smbus_write_byte_data(client, reg + 1, val >> 8);87	if (unlikely(err < 0))88		dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",89			16, "write", reg);90 91	return err;92}93 94/* Read 8-bit value from register */95static u8 emc6w201_read8(struct i2c_client *client, u8 reg)96{97	int val;98 99	val = i2c_smbus_read_byte_data(client, reg);100	if (unlikely(val < 0)) {101		dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",102			8, "read", reg);103		return 0x00;	/* Arbitrary value */104	}105 106	return val;107}108 109/* Write 8-bit value to register */110static int emc6w201_write8(struct i2c_client *client, u8 reg, u8 val)111{112	int err;113 114	err = i2c_smbus_write_byte_data(client, reg, val);115	if (unlikely(err < 0))116		dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",117			8, "write", reg);118 119	return err;120}121 122static struct emc6w201_data *emc6w201_update_device(struct device *dev)123{124	struct emc6w201_data *data = dev_get_drvdata(dev);125	struct i2c_client *client = data->client;126	int nr;127 128	mutex_lock(&data->update_lock);129 130	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {131		for (nr = 0; nr < 6; nr++) {132			data->in[input][nr] =133				emc6w201_read8(client,134						EMC6W201_REG_IN(nr));135			data->in[min][nr] =136				emc6w201_read8(client,137						EMC6W201_REG_IN_LOW(nr));138			data->in[max][nr] =139				emc6w201_read8(client,140						EMC6W201_REG_IN_HIGH(nr));141		}142 143		for (nr = 0; nr < 6; nr++) {144			data->temp[input][nr] =145				emc6w201_read8(client,146						EMC6W201_REG_TEMP(nr));147			data->temp[min][nr] =148				emc6w201_read8(client,149						EMC6W201_REG_TEMP_LOW(nr));150			data->temp[max][nr] =151				emc6w201_read8(client,152						EMC6W201_REG_TEMP_HIGH(nr));153		}154 155		for (nr = 0; nr < 5; nr++) {156			data->fan[input][nr] =157				emc6w201_read16(client,158						EMC6W201_REG_FAN(nr));159			data->fan[min][nr] =160				emc6w201_read16(client,161						EMC6W201_REG_FAN_MIN(nr));162		}163 164		data->last_updated = jiffies;165		data->valid = true;166	}167 168	mutex_unlock(&data->update_lock);169 170	return data;171}172 173/*174 * Sysfs callback functions175 */176 177static const s16 nominal_mv[6] = { 2500, 1500, 3300, 5000, 1500, 1500 };178 179static ssize_t in_show(struct device *dev, struct device_attribute *devattr,180		       char *buf)181{182	struct emc6w201_data *data = emc6w201_update_device(dev);183	int sf = to_sensor_dev_attr_2(devattr)->index;184	int nr = to_sensor_dev_attr_2(devattr)->nr;185 186	return sprintf(buf, "%u\n",187		       (unsigned)data->in[sf][nr] * nominal_mv[nr] / 0xC0);188}189 190static ssize_t in_store(struct device *dev, struct device_attribute *devattr,191			const char *buf, size_t count)192{193	struct emc6w201_data *data = dev_get_drvdata(dev);194	struct i2c_client *client = data->client;195	int sf = to_sensor_dev_attr_2(devattr)->index;196	int nr = to_sensor_dev_attr_2(devattr)->nr;197	int err;198	long val;199	u8 reg;200 201	err = kstrtol(buf, 10, &val);202	if (err < 0)203		return err;204 205	val = clamp_val(val, 0, 255 * nominal_mv[nr] / 192);206	val = DIV_ROUND_CLOSEST(val * 192, nominal_mv[nr]);207	reg = (sf == min) ? EMC6W201_REG_IN_LOW(nr)208			  : EMC6W201_REG_IN_HIGH(nr);209 210	mutex_lock(&data->update_lock);211	data->in[sf][nr] = val;212	err = emc6w201_write8(client, reg, data->in[sf][nr]);213	mutex_unlock(&data->update_lock);214 215	return err < 0 ? err : count;216}217 218static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,219			 char *buf)220{221	struct emc6w201_data *data = emc6w201_update_device(dev);222	int sf = to_sensor_dev_attr_2(devattr)->index;223	int nr = to_sensor_dev_attr_2(devattr)->nr;224 225	return sprintf(buf, "%d\n", (int)data->temp[sf][nr] * 1000);226}227 228static ssize_t temp_store(struct device *dev,229			  struct device_attribute *devattr, const char *buf,230			  size_t count)231{232	struct emc6w201_data *data = dev_get_drvdata(dev);233	struct i2c_client *client = data->client;234	int sf = to_sensor_dev_attr_2(devattr)->index;235	int nr = to_sensor_dev_attr_2(devattr)->nr;236	int err;237	long val;238	u8 reg;239 240	err = kstrtol(buf, 10, &val);241	if (err < 0)242		return err;243 244	val = clamp_val(val, -127000, 127000);245	val = DIV_ROUND_CLOSEST(val, 1000);246	reg = (sf == min) ? EMC6W201_REG_TEMP_LOW(nr)247			  : EMC6W201_REG_TEMP_HIGH(nr);248 249	mutex_lock(&data->update_lock);250	data->temp[sf][nr] = val;251	err = emc6w201_write8(client, reg, data->temp[sf][nr]);252	mutex_unlock(&data->update_lock);253 254	return err < 0 ? err : count;255}256 257static ssize_t fan_show(struct device *dev, struct device_attribute *devattr,258			char *buf)259{260	struct emc6w201_data *data = emc6w201_update_device(dev);261	int sf = to_sensor_dev_attr_2(devattr)->index;262	int nr = to_sensor_dev_attr_2(devattr)->nr;263	unsigned rpm;264 265	if (data->fan[sf][nr] == 0 || data->fan[sf][nr] == 0xFFFF)266		rpm = 0;267	else268		rpm = 5400000U / data->fan[sf][nr];269 270	return sprintf(buf, "%u\n", rpm);271}272 273static ssize_t fan_store(struct device *dev, struct device_attribute *devattr,274			 const char *buf, size_t count)275{276	struct emc6w201_data *data = dev_get_drvdata(dev);277	struct i2c_client *client = data->client;278	int sf = to_sensor_dev_attr_2(devattr)->index;279	int nr = to_sensor_dev_attr_2(devattr)->nr;280	int err;281	unsigned long val;282 283	err = kstrtoul(buf, 10, &val);284	if (err < 0)285		return err;286 287	if (val == 0) {288		val = 0xFFFF;289	} else {290		val = DIV_ROUND_CLOSEST(5400000U, val);291		val = clamp_val(val, 0, 0xFFFE);292	}293 294	mutex_lock(&data->update_lock);295	data->fan[sf][nr] = val;296	err = emc6w201_write16(client, EMC6W201_REG_FAN_MIN(nr),297			       data->fan[sf][nr]);298	mutex_unlock(&data->update_lock);299 300	return err < 0 ? err : count;301}302 303static SENSOR_DEVICE_ATTR_2_RO(in0_input, in, 0, input);304static SENSOR_DEVICE_ATTR_2_RW(in0_min, in, 0, min);305static SENSOR_DEVICE_ATTR_2_RW(in0_max, in, 0, max);306static SENSOR_DEVICE_ATTR_2_RO(in1_input, in, 1, input);307static SENSOR_DEVICE_ATTR_2_RW(in1_min, in, 1, min);308static SENSOR_DEVICE_ATTR_2_RW(in1_max, in, 1, max);309static SENSOR_DEVICE_ATTR_2_RO(in2_input, in, 2, input);310static SENSOR_DEVICE_ATTR_2_RW(in2_min, in, 2, min);311static SENSOR_DEVICE_ATTR_2_RW(in2_max, in, 2, max);312static SENSOR_DEVICE_ATTR_2_RO(in3_input, in, 3, input);313static SENSOR_DEVICE_ATTR_2_RW(in3_min, in, 3, min);314static SENSOR_DEVICE_ATTR_2_RW(in3_max, in, 3, max);315static SENSOR_DEVICE_ATTR_2_RO(in4_input, in, 4, input);316static SENSOR_DEVICE_ATTR_2_RW(in4_min, in, 4, min);317static SENSOR_DEVICE_ATTR_2_RW(in4_max, in, 4, max);318static SENSOR_DEVICE_ATTR_2_RO(in5_input, in, 5, input);319static SENSOR_DEVICE_ATTR_2_RW(in5_min, in, 5, min);320static SENSOR_DEVICE_ATTR_2_RW(in5_max, in, 5, max);321 322static SENSOR_DEVICE_ATTR_2_RO(temp1_input, temp, 0, input);323static SENSOR_DEVICE_ATTR_2_RW(temp1_min, temp, 0, min);324static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp, 0, max);325static SENSOR_DEVICE_ATTR_2_RO(temp2_input, temp, 1, input);326static SENSOR_DEVICE_ATTR_2_RW(temp2_min, temp, 1, min);327static SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp, 1, max);328static SENSOR_DEVICE_ATTR_2_RO(temp3_input, temp, 2, input);329static SENSOR_DEVICE_ATTR_2_RW(temp3_min, temp, 2, min);330static SENSOR_DEVICE_ATTR_2_RW(temp3_max, temp, 2, max);331static SENSOR_DEVICE_ATTR_2_RO(temp4_input, temp, 3, input);332static SENSOR_DEVICE_ATTR_2_RW(temp4_min, temp, 3, min);333static SENSOR_DEVICE_ATTR_2_RW(temp4_max, temp, 3, max);334static SENSOR_DEVICE_ATTR_2_RO(temp5_input, temp, 4, input);335static SENSOR_DEVICE_ATTR_2_RW(temp5_min, temp, 4, min);336static SENSOR_DEVICE_ATTR_2_RW(temp5_max, temp, 4, max);337static SENSOR_DEVICE_ATTR_2_RO(temp6_input, temp, 5, input);338static SENSOR_DEVICE_ATTR_2_RW(temp6_min, temp, 5, min);339static SENSOR_DEVICE_ATTR_2_RW(temp6_max, temp, 5, max);340 341static SENSOR_DEVICE_ATTR_2_RO(fan1_input, fan, 0, input);342static SENSOR_DEVICE_ATTR_2_RW(fan1_min, fan, 0, min);343static SENSOR_DEVICE_ATTR_2_RO(fan2_input, fan, 1, input);344static SENSOR_DEVICE_ATTR_2_RW(fan2_min, fan, 1, min);345static SENSOR_DEVICE_ATTR_2_RO(fan3_input, fan, 2, input);346static SENSOR_DEVICE_ATTR_2_RW(fan3_min, fan, 2, min);347static SENSOR_DEVICE_ATTR_2_RO(fan4_input, fan, 3, input);348static SENSOR_DEVICE_ATTR_2_RW(fan4_min, fan, 3, min);349static SENSOR_DEVICE_ATTR_2_RO(fan5_input, fan, 4, input);350static SENSOR_DEVICE_ATTR_2_RW(fan5_min, fan, 4, min);351 352static struct attribute *emc6w201_attrs[] = {353	&sensor_dev_attr_in0_input.dev_attr.attr,354	&sensor_dev_attr_in0_min.dev_attr.attr,355	&sensor_dev_attr_in0_max.dev_attr.attr,356	&sensor_dev_attr_in1_input.dev_attr.attr,357	&sensor_dev_attr_in1_min.dev_attr.attr,358	&sensor_dev_attr_in1_max.dev_attr.attr,359	&sensor_dev_attr_in2_input.dev_attr.attr,360	&sensor_dev_attr_in2_min.dev_attr.attr,361	&sensor_dev_attr_in2_max.dev_attr.attr,362	&sensor_dev_attr_in3_input.dev_attr.attr,363	&sensor_dev_attr_in3_min.dev_attr.attr,364	&sensor_dev_attr_in3_max.dev_attr.attr,365	&sensor_dev_attr_in4_input.dev_attr.attr,366	&sensor_dev_attr_in4_min.dev_attr.attr,367	&sensor_dev_attr_in4_max.dev_attr.attr,368	&sensor_dev_attr_in5_input.dev_attr.attr,369	&sensor_dev_attr_in5_min.dev_attr.attr,370	&sensor_dev_attr_in5_max.dev_attr.attr,371 372	&sensor_dev_attr_temp1_input.dev_attr.attr,373	&sensor_dev_attr_temp1_min.dev_attr.attr,374	&sensor_dev_attr_temp1_max.dev_attr.attr,375	&sensor_dev_attr_temp2_input.dev_attr.attr,376	&sensor_dev_attr_temp2_min.dev_attr.attr,377	&sensor_dev_attr_temp2_max.dev_attr.attr,378	&sensor_dev_attr_temp3_input.dev_attr.attr,379	&sensor_dev_attr_temp3_min.dev_attr.attr,380	&sensor_dev_attr_temp3_max.dev_attr.attr,381	&sensor_dev_attr_temp4_input.dev_attr.attr,382	&sensor_dev_attr_temp4_min.dev_attr.attr,383	&sensor_dev_attr_temp4_max.dev_attr.attr,384	&sensor_dev_attr_temp5_input.dev_attr.attr,385	&sensor_dev_attr_temp5_min.dev_attr.attr,386	&sensor_dev_attr_temp5_max.dev_attr.attr,387	&sensor_dev_attr_temp6_input.dev_attr.attr,388	&sensor_dev_attr_temp6_min.dev_attr.attr,389	&sensor_dev_attr_temp6_max.dev_attr.attr,390 391	&sensor_dev_attr_fan1_input.dev_attr.attr,392	&sensor_dev_attr_fan1_min.dev_attr.attr,393	&sensor_dev_attr_fan2_input.dev_attr.attr,394	&sensor_dev_attr_fan2_min.dev_attr.attr,395	&sensor_dev_attr_fan3_input.dev_attr.attr,396	&sensor_dev_attr_fan3_min.dev_attr.attr,397	&sensor_dev_attr_fan4_input.dev_attr.attr,398	&sensor_dev_attr_fan4_min.dev_attr.attr,399	&sensor_dev_attr_fan5_input.dev_attr.attr,400	&sensor_dev_attr_fan5_min.dev_attr.attr,401	NULL402};403 404ATTRIBUTE_GROUPS(emc6w201);405 406/*407 * Driver interface408 */409 410/* Return 0 if detection is successful, -ENODEV otherwise */411static int emc6w201_detect(struct i2c_client *client,412			   struct i2c_board_info *info)413{414	struct i2c_adapter *adapter = client->adapter;415	int company, verstep, config;416 417	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))418		return -ENODEV;419 420	/* Identification */421	company = i2c_smbus_read_byte_data(client, EMC6W201_REG_COMPANY);422	if (company != 0x5C)423		return -ENODEV;424	verstep = i2c_smbus_read_byte_data(client, EMC6W201_REG_VERSTEP);425	if (verstep < 0 || (verstep & 0xF0) != 0xB0)426		return -ENODEV;427	if ((verstep & 0x0F) > 2) {428		dev_dbg(&client->dev, "Unknown EMC6W201 stepping %d\n",429			verstep & 0x0F);430		return -ENODEV;431	}432 433	/* Check configuration */434	config = i2c_smbus_read_byte_data(client, EMC6W201_REG_CONFIG);435	if (config < 0 || (config & 0xF4) != 0x04)436		return -ENODEV;437	if (!(config & 0x01)) {438		dev_err(&client->dev, "Monitoring not enabled\n");439		return -ENODEV;440	}441 442	strscpy(info->type, "emc6w201", I2C_NAME_SIZE);443 444	return 0;445}446 447static int emc6w201_probe(struct i2c_client *client)448{449	struct device *dev = &client->dev;450	struct emc6w201_data *data;451	struct device *hwmon_dev;452 453	data = devm_kzalloc(dev, sizeof(struct emc6w201_data), GFP_KERNEL);454	if (!data)455		return -ENOMEM;456 457	data->client = client;458	mutex_init(&data->update_lock);459 460	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,461							   data,462							   emc6w201_groups);463	return PTR_ERR_OR_ZERO(hwmon_dev);464}465 466static const struct i2c_device_id emc6w201_id[] = {467	{ "emc6w201" },468	{ }469};470MODULE_DEVICE_TABLE(i2c, emc6w201_id);471 472static struct i2c_driver emc6w201_driver = {473	.class		= I2C_CLASS_HWMON,474	.driver = {475		.name	= "emc6w201",476	},477	.probe		= emc6w201_probe,478	.id_table	= emc6w201_id,479	.detect		= emc6w201_detect,480	.address_list	= normal_i2c,481};482 483module_i2c_driver(emc6w201_driver);484 485MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");486MODULE_DESCRIPTION("SMSC EMC6W201 hardware monitoring driver");487MODULE_LICENSE("GPL");488