brintos

brintos / linux-shallow public Read only

0
0
Text · 7.5 KiB · a9aab88 Raw
351 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Hardware monitoring driver for MAX127.4 *5 * Copyright (c) 2020 Facebook Inc.6 */7 8#include <linux/err.h>9#include <linux/hwmon.h>10#include <linux/i2c.h>11#include <linux/init.h>12#include <linux/module.h>13 14/*15 * MAX127 Control Byte. Refer to MAX127 datasheet, Table 1 "Control-Byte16 * Format" for details.17 */18#define MAX127_CTRL_START	BIT(7)19#define MAX127_CTRL_SEL_SHIFT	420#define MAX127_CTRL_RNG		BIT(3)21#define MAX127_CTRL_BIP		BIT(2)22#define MAX127_CTRL_PD1		BIT(1)23#define MAX127_CTRL_PD0		BIT(0)24 25#define MAX127_NUM_CHANNELS	826#define MAX127_SET_CHANNEL(ch)	(((ch) & 7) << MAX127_CTRL_SEL_SHIFT)27 28/*29 * MAX127 channel input ranges. Refer to MAX127 datasheet, Table 3 "Range30 * and Polarity Selection" for details.31 */32#define MAX127_FULL_RANGE	10000	/* 10V */33#define MAX127_HALF_RANGE	5000	/* 5V */34 35/*36 * MAX127 returns 2 bytes at read:37 *   - the first byte contains data[11:4].38 *   - the second byte contains data[3:0] (MSB) and 4 dummy 0s (LSB).39 * Refer to MAX127 datasheet, "Read a Conversion (Read Cycle)" section40 * for details.41 */42#define MAX127_DATA_LEN		243#define MAX127_DATA_SHIFT	444 45#define MAX127_SIGN_BIT		BIT(11)46 47struct max127_data {48	struct mutex lock;49	struct i2c_client *client;50	u8 ctrl_byte[MAX127_NUM_CHANNELS];51};52 53static int max127_select_channel(struct i2c_client *client, u8 ctrl_byte)54{55	int status;56	struct i2c_msg msg = {57		.addr = client->addr,58		.flags = 0,59		.len = sizeof(ctrl_byte),60		.buf = &ctrl_byte,61	};62 63	status = i2c_transfer(client->adapter, &msg, 1);64	if (status < 0)65		return status;66	if (status != 1)67		return -EIO;68 69	return 0;70}71 72static int max127_read_channel(struct i2c_client *client, long *val)73{74	int status;75	u8 i2c_data[MAX127_DATA_LEN];76	struct i2c_msg msg = {77		.addr = client->addr,78		.flags = I2C_M_RD,79		.len = sizeof(i2c_data),80		.buf = i2c_data,81	};82 83	status = i2c_transfer(client->adapter, &msg, 1);84	if (status < 0)85		return status;86	if (status != 1)87		return -EIO;88 89	*val = (i2c_data[1] >> MAX127_DATA_SHIFT) |90		((u16)i2c_data[0] << MAX127_DATA_SHIFT);91	return 0;92}93 94static long max127_process_raw(u8 ctrl_byte, long raw)95{96	long scale, weight;97 98	/*99	 * MAX127's data coding is binary in unipolar mode with 1 LSB =100	 * (Full-Scale/4096) and two’s complement binary in bipolar mode101	 * with 1 LSB = [(2 x |FS|)/4096].102	 * Refer to MAX127 datasheet, "Transfer Function" section for103	 * details.104	 */105	scale = (ctrl_byte & MAX127_CTRL_RNG) ? MAX127_FULL_RANGE :106						MAX127_HALF_RANGE;107	if (ctrl_byte & MAX127_CTRL_BIP) {108		weight = (raw & MAX127_SIGN_BIT);109		raw &= ~MAX127_SIGN_BIT;110		raw -= weight;111		raw *= 2;112	}113 114	return raw * scale / 4096;115}116 117static int max127_read_input(struct max127_data *data, int channel, long *val)118{119	long raw;120	int status;121	struct i2c_client *client = data->client;122	u8 ctrl_byte = data->ctrl_byte[channel];123 124	mutex_lock(&data->lock);125 126	status = max127_select_channel(client, ctrl_byte);127	if (status)128		goto exit;129 130	status = max127_read_channel(client, &raw);131	if (status)132		goto exit;133 134	*val = max127_process_raw(ctrl_byte, raw);135 136exit:137	mutex_unlock(&data->lock);138	return status;139}140 141static int max127_read_min(struct max127_data *data, int channel, long *val)142{143	u8 rng_bip = (data->ctrl_byte[channel] >> 2) & 3;144	static const int min_input_map[4] = {145		0,			/* RNG=0, BIP=0 */146		-MAX127_HALF_RANGE,	/* RNG=0, BIP=1 */147		0,			/* RNG=1, BIP=0 */148		-MAX127_FULL_RANGE,	/* RNG=1, BIP=1 */149	};150 151	*val = min_input_map[rng_bip];152	return 0;153}154 155static int max127_read_max(struct max127_data *data, int channel, long *val)156{157	u8 rng_bip = (data->ctrl_byte[channel] >> 2) & 3;158	static const int max_input_map[4] = {159		MAX127_HALF_RANGE,	/* RNG=0, BIP=0 */160		MAX127_HALF_RANGE,	/* RNG=0, BIP=1 */161		MAX127_FULL_RANGE,	/* RNG=1, BIP=0 */162		MAX127_FULL_RANGE,	/* RNG=1, BIP=1 */163	};164 165	*val = max_input_map[rng_bip];166	return 0;167}168 169static int max127_write_min(struct max127_data *data, int channel, long val)170{171	u8 ctrl;172 173	mutex_lock(&data->lock);174 175	ctrl = data->ctrl_byte[channel];176	if (val <= -MAX127_FULL_RANGE) {177		ctrl |= (MAX127_CTRL_RNG | MAX127_CTRL_BIP);178	} else if (val < 0) {179		ctrl |= MAX127_CTRL_BIP;180		ctrl &= ~MAX127_CTRL_RNG;181	} else {182		ctrl &= ~MAX127_CTRL_BIP;183	}184	data->ctrl_byte[channel] = ctrl;185 186	mutex_unlock(&data->lock);187 188	return 0;189}190 191static int max127_write_max(struct max127_data *data, int channel, long val)192{193	mutex_lock(&data->lock);194 195	if (val >= MAX127_FULL_RANGE)196		data->ctrl_byte[channel] |= MAX127_CTRL_RNG;197	else198		data->ctrl_byte[channel] &= ~MAX127_CTRL_RNG;199 200	mutex_unlock(&data->lock);201 202	return 0;203}204 205static umode_t max127_is_visible(const void *_data,206				 enum hwmon_sensor_types type,207				 u32 attr, int channel)208{209	if (type == hwmon_in) {210		switch (attr) {211		case hwmon_in_input:212			return 0444;213 214		case hwmon_in_min:215		case hwmon_in_max:216			return 0644;217 218		default:219			break;220		}221	}222 223	return 0;224}225 226static int max127_read(struct device *dev, enum hwmon_sensor_types type,227			u32 attr, int channel, long *val)228{229	int status;230	struct max127_data *data = dev_get_drvdata(dev);231 232	if (type != hwmon_in)233		return -EOPNOTSUPP;234 235	switch (attr) {236	case hwmon_in_input:237		status = max127_read_input(data, channel, val);238		break;239 240	case hwmon_in_min:241		status = max127_read_min(data, channel, val);242		break;243 244	case hwmon_in_max:245		status = max127_read_max(data, channel, val);246		break;247 248	default:249		status = -EOPNOTSUPP;250		break;251	}252 253	return status;254}255 256static int max127_write(struct device *dev, enum hwmon_sensor_types type,257			u32 attr, int channel, long val)258{259	int status;260	struct max127_data *data = dev_get_drvdata(dev);261 262	if (type != hwmon_in)263		return -EOPNOTSUPP;264 265	switch (attr) {266	case hwmon_in_min:267		status = max127_write_min(data, channel, val);268		break;269 270	case hwmon_in_max:271		status = max127_write_max(data, channel, val);272		break;273 274	default:275		status = -EOPNOTSUPP;276		break;277	}278 279	return status;280}281 282static const struct hwmon_ops max127_hwmon_ops = {283	.is_visible = max127_is_visible,284	.read = max127_read,285	.write = max127_write,286};287 288static const struct hwmon_channel_info * const max127_info[] = {289	HWMON_CHANNEL_INFO(in,290			   HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX,291			   HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX,292			   HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX,293			   HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX,294			   HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX,295			   HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX,296			   HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX,297			   HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX),298	NULL,299};300 301static const struct hwmon_chip_info max127_chip_info = {302	.ops = &max127_hwmon_ops,303	.info = max127_info,304};305 306static int max127_probe(struct i2c_client *client)307{308	int i;309	struct device *hwmon_dev;310	struct max127_data *data;311	struct device *dev = &client->dev;312 313	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);314	if (!data)315		return -ENOMEM;316 317	data->client = client;318	mutex_init(&data->lock);319	for (i = 0; i < ARRAY_SIZE(data->ctrl_byte); i++)320		data->ctrl_byte[i] = (MAX127_CTRL_START |321				      MAX127_SET_CHANNEL(i));322 323	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,324							 data,325							 &max127_chip_info,326							 NULL);327 328	return PTR_ERR_OR_ZERO(hwmon_dev);329}330 331static const struct i2c_device_id max127_id[] = {332	{ "max127" },333	{ }334};335MODULE_DEVICE_TABLE(i2c, max127_id);336 337static struct i2c_driver max127_driver = {338	.driver = {339		.name	= "max127",340	},341	.probe		= max127_probe,342	.id_table	= max127_id,343};344 345module_i2c_driver(max127_driver);346 347MODULE_LICENSE("GPL");348MODULE_AUTHOR("Mike Choi <mikechoi@fb.com>");349MODULE_AUTHOR("Tao Ren <rentao.bupt@gmail.com>");350MODULE_DESCRIPTION("MAX127 Hardware Monitoring driver");351