brintos

brintos / linux-shallow public Read only

0
0
Text · 11.4 KiB · 13201fb Raw
515 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Hardware monitoring driver for Maxim MAX66204 *5 * Originally from L. Grunenberg.6 * (C) 2012 by L. Grunenberg <contact@lgrunenberg.de>7 *8 * Copyright (c) 2021 Dell Inc. or its subsidiaries. All Rights Reserved.9 *10 * based on code written by :11 * 2007 by Hans J. Koch <hjk@hansjkoch.de>12 * John Morris <john.morris@spirentcom.com>13 * Copyright (c) 2003 Spirent Communications14 * and Claus Gindhart <claus.gindhart@kontron.com>15 *16 * This module has only been tested with the MAX6620 chip.17 *18 * The datasheet was last seen at:19 *20 *        http://pdfserv.maxim-ic.com/en/ds/MAX6620.pdf21 *22 */23 24#include <linux/bits.h>25#include <linux/err.h>26#include <linux/hwmon.h>27#include <linux/i2c.h>28#include <linux/init.h>29#include <linux/jiffies.h>30#include <linux/module.h>31#include <linux/slab.h>32 33/*34 * MAX 6620 registers35 */36 37#define MAX6620_REG_CONFIG	0x0038#define MAX6620_REG_FAULT	0x0139#define MAX6620_REG_CONF_FAN0	0x0240#define MAX6620_REG_CONF_FAN1	0x0341#define MAX6620_REG_CONF_FAN2	0x0442#define MAX6620_REG_CONF_FAN3	0x0543#define MAX6620_REG_DYN_FAN0	0x0644#define MAX6620_REG_DYN_FAN1	0x0745#define MAX6620_REG_DYN_FAN2	0x0846#define MAX6620_REG_DYN_FAN3	0x0947#define MAX6620_REG_TACH0	0x1048#define MAX6620_REG_TACH1	0x1249#define MAX6620_REG_TACH2	0x1450#define MAX6620_REG_TACH3	0x1651#define MAX6620_REG_VOLT0	0x1852#define MAX6620_REG_VOLT1	0x1A53#define MAX6620_REG_VOLT2	0x1C54#define MAX6620_REG_VOLT3	0x1E55#define MAX6620_REG_TAR0	0x2056#define MAX6620_REG_TAR1	0x2257#define MAX6620_REG_TAR2	0x2458#define MAX6620_REG_TAR3	0x2659#define MAX6620_REG_DAC0	0x2860#define MAX6620_REG_DAC1	0x2A61#define MAX6620_REG_DAC2	0x2C62#define MAX6620_REG_DAC3	0x2E63 64/*65 * Config register bits66 */67 68#define MAX6620_CFG_RUN		BIT(7)69#define MAX6620_CFG_POR		BIT(6)70#define MAX6620_CFG_TIMEOUT	BIT(5)71#define MAX6620_CFG_FULLFAN	BIT(4)72#define MAX6620_CFG_OSC		BIT(3)73#define MAX6620_CFG_WD_MASK	(BIT(2) | BIT(1))74#define MAX6620_CFG_WD_2	BIT(1)75#define MAX6620_CFG_WD_6	BIT(2)76#define MAX6620_CFG_WD10	(BIT(2) | BIT(1))77#define MAX6620_CFG_WD		BIT(0)78 79/*80 * Failure status register bits81 */82 83#define MAX6620_FAIL_TACH0	BIT(4)84#define MAX6620_FAIL_TACH1	BIT(5)85#define MAX6620_FAIL_TACH2	BIT(6)86#define MAX6620_FAIL_TACH3	BIT(7)87#define MAX6620_FAIL_MASK0	BIT(0)88#define MAX6620_FAIL_MASK1	BIT(1)89#define MAX6620_FAIL_MASK2	BIT(2)90#define MAX6620_FAIL_MASK3	BIT(3)91 92#define MAX6620_CLOCK_FREQ	8192 /* Clock frequency in Hz */93#define MAX6620_PULSE_PER_REV	2 /* Tachometer pulses per revolution */94 95/* Minimum and maximum values of the FAN-RPM */96#define FAN_RPM_MIN	24097#define FAN_RPM_MAX	3000098 99static const u8 config_reg[] = {100	MAX6620_REG_CONF_FAN0,101	MAX6620_REG_CONF_FAN1,102	MAX6620_REG_CONF_FAN2,103	MAX6620_REG_CONF_FAN3,104};105 106static const u8 dyn_reg[] = {107	MAX6620_REG_DYN_FAN0,108	MAX6620_REG_DYN_FAN1,109	MAX6620_REG_DYN_FAN2,110	MAX6620_REG_DYN_FAN3,111};112 113static const u8 tach_reg[] = {114	MAX6620_REG_TACH0,115	MAX6620_REG_TACH1,116	MAX6620_REG_TACH2,117	MAX6620_REG_TACH3,118};119 120static const u8 target_reg[] = {121	MAX6620_REG_TAR0,122	MAX6620_REG_TAR1,123	MAX6620_REG_TAR2,124	MAX6620_REG_TAR3,125};126 127/*128 * Client data (each client gets its own)129 */130 131struct max6620_data {132	struct i2c_client *client;133	struct mutex update_lock;134	bool valid; /* false until following fields are valid */135	unsigned long last_updated; /* in jiffies */136 137	/* register values */138	u8 fancfg[4];139	u8 fandyn[4];140	u8 fault;141	u16 tach[4];142	u16 target[4];143};144 145static u8 max6620_fan_div_from_reg(u8 val)146{147	return BIT((val & 0xE0) >> 5);148}149 150static u16 max6620_fan_rpm_to_tach(u8 div, int rpm)151{152	return (60 * div * MAX6620_CLOCK_FREQ) / (rpm * MAX6620_PULSE_PER_REV);153}154 155static int max6620_fan_tach_to_rpm(u8 div, u16 tach)156{157	return (60 * div * MAX6620_CLOCK_FREQ) / (tach * MAX6620_PULSE_PER_REV);158}159 160static int max6620_update_device(struct device *dev)161{162	struct max6620_data *data = dev_get_drvdata(dev);163	struct i2c_client *client = data->client;164	int i;165	int ret = 0;166 167	mutex_lock(&data->update_lock);168 169	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {170		for (i = 0; i < 4; i++) {171			ret = i2c_smbus_read_byte_data(client, config_reg[i]);172			if (ret < 0)173				goto error;174			data->fancfg[i] = ret;175 176			ret = i2c_smbus_read_byte_data(client, dyn_reg[i]);177			if (ret < 0)178				goto error;179			data->fandyn[i] = ret;180 181			ret = i2c_smbus_read_byte_data(client, tach_reg[i]);182			if (ret < 0)183				goto error;184			data->tach[i] = (ret << 3) & 0x7f8;185			ret = i2c_smbus_read_byte_data(client, tach_reg[i] + 1);186			if (ret < 0)187				goto error;188			data->tach[i] |= (ret >> 5) & 0x7;189 190			ret = i2c_smbus_read_byte_data(client, target_reg[i]);191			if (ret < 0)192				goto error;193			data->target[i] = (ret << 3) & 0x7f8;194			ret = i2c_smbus_read_byte_data(client, target_reg[i] + 1);195			if (ret < 0)196				goto error;197			data->target[i] |= (ret >> 5) & 0x7;198		}199 200		/*201		 * Alarms are cleared on read in case the condition that202		 * caused the alarm is removed. Keep the value latched here203		 * for providing the register through different alarm files.204		 */205		ret = i2c_smbus_read_byte_data(client, MAX6620_REG_FAULT);206		if (ret < 0)207			goto error;208		data->fault |= (ret >> 4) & (ret & 0x0F);209 210		data->last_updated = jiffies;211		data->valid = true;212	}213 214error:215	mutex_unlock(&data->update_lock);216	return ret;217}218 219static umode_t220max6620_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,221		   int channel)222{223	switch (type) {224	case hwmon_fan:225		switch (attr) {226		case hwmon_fan_alarm:227		case hwmon_fan_input:228			return 0444;229		case hwmon_fan_div:230		case hwmon_fan_target:231			return 0644;232		default:233			break;234		}235		break;236	default:237		break;238	}239 240	return 0;241}242 243static int244max6620_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,245	     int channel, long *val)246{247	struct max6620_data *data;248	struct i2c_client *client;249	int ret;250	u8 div;251	u8 val1;252	u8 val2;253 254	ret = max6620_update_device(dev);255	if (ret < 0)256		return ret;257	data = dev_get_drvdata(dev);258	client = data->client;259 260	switch (type) {261	case hwmon_fan:262		switch (attr) {263		case hwmon_fan_alarm:264			mutex_lock(&data->update_lock);265			*val = !!(data->fault & BIT(channel));266 267			/* Setting TACH count to re-enable fan fault detection */268			if (*val == 1) {269				val1 = (data->target[channel] >> 3) & 0xff;270				val2 = (data->target[channel] << 5) & 0xe0;271				ret = i2c_smbus_write_byte_data(client,272								target_reg[channel], val1);273				if (ret < 0) {274					mutex_unlock(&data->update_lock);275					return ret;276				}277				ret = i2c_smbus_write_byte_data(client,278								target_reg[channel] + 1, val2);279				if (ret < 0) {280					mutex_unlock(&data->update_lock);281					return ret;282				}283 284				data->fault &= ~BIT(channel);285			}286			mutex_unlock(&data->update_lock);287 288			break;289		case hwmon_fan_div:290			*val = max6620_fan_div_from_reg(data->fandyn[channel]);291			break;292		case hwmon_fan_input:293			if (data->tach[channel] == 0) {294				*val = 0;295			} else {296				div = max6620_fan_div_from_reg(data->fandyn[channel]);297				*val = max6620_fan_tach_to_rpm(div, data->tach[channel]);298			}299			break;300		case hwmon_fan_target:301			if (data->target[channel] == 0) {302				*val = 0;303			} else {304				div = max6620_fan_div_from_reg(data->fandyn[channel]);305				*val = max6620_fan_tach_to_rpm(div, data->target[channel]);306			}307			break;308		default:309			return -EOPNOTSUPP;310		}311		break;312 313	default:314		return -EOPNOTSUPP;315	}316 317	return 0;318}319 320static int321max6620_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,322	      int channel, long val)323{324	struct max6620_data *data;325	struct i2c_client *client;326	int ret;327	u8 div;328	u16 tach;329	u8 val1;330	u8 val2;331 332	ret = max6620_update_device(dev);333	if (ret < 0)334		return ret;335	data = dev_get_drvdata(dev);336	client = data->client;337	mutex_lock(&data->update_lock);338 339	switch (type) {340	case hwmon_fan:341		switch (attr) {342		case hwmon_fan_div:343			switch (val) {344			case 1:345				div = 0;346				break;347			case 2:348				div = 1;349				break;350			case 4:351				div = 2;352				break;353			case 8:354				div = 3;355				break;356			case 16:357				div = 4;358				break;359			case 32:360				div = 5;361				break;362			default:363				ret = -EINVAL;364				goto error;365			}366			data->fandyn[channel] &= 0x1F;367			data->fandyn[channel] |= div << 5;368			ret = i2c_smbus_write_byte_data(client, dyn_reg[channel],369							data->fandyn[channel]);370			break;371		case hwmon_fan_target:372			val = clamp_val(val, FAN_RPM_MIN, FAN_RPM_MAX);373			div = max6620_fan_div_from_reg(data->fandyn[channel]);374			tach = max6620_fan_rpm_to_tach(div, val);375			val1 = (tach >> 3) & 0xff;376			val2 = (tach << 5) & 0xe0;377			ret = i2c_smbus_write_byte_data(client, target_reg[channel], val1);378			if (ret < 0)379				break;380			ret = i2c_smbus_write_byte_data(client, target_reg[channel] + 1, val2);381			if (ret < 0)382				break;383 384			/* Setting TACH count re-enables fan fault detection */385			data->fault &= ~BIT(channel);386 387			break;388		default:389			ret = -EOPNOTSUPP;390			break;391		}392		break;393 394	default:395		ret = -EOPNOTSUPP;396		break;397	}398 399error:400	mutex_unlock(&data->update_lock);401	return ret;402}403 404static const struct hwmon_channel_info * const max6620_info[] = {405	HWMON_CHANNEL_INFO(fan,406			   HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM,407			   HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM,408			   HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM,409			   HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM),410	NULL411};412 413static const struct hwmon_ops max6620_hwmon_ops = {414	.read = max6620_read,415	.write = max6620_write,416	.is_visible = max6620_is_visible,417};418 419static const struct hwmon_chip_info max6620_chip_info = {420	.ops = &max6620_hwmon_ops,421	.info = max6620_info,422};423 424static int max6620_init_client(struct max6620_data *data)425{426	struct i2c_client *client = data->client;427	int config;428	int err;429	int i;430	int reg;431 432	config = i2c_smbus_read_byte_data(client, MAX6620_REG_CONFIG);433	if (config < 0) {434		dev_err(&client->dev, "Error reading config, aborting.\n");435		return config;436	}437 438	/*439	 * Set bit 4, disable other fans from going full speed on a fail440	 * failure.441	 */442	err = i2c_smbus_write_byte_data(client, MAX6620_REG_CONFIG, config | 0x10);443	if (err < 0) {444		dev_err(&client->dev, "Config write error, aborting.\n");445		return err;446	}447 448	for (i = 0; i < 4; i++) {449		reg = i2c_smbus_read_byte_data(client, config_reg[i]);450		if (reg < 0)451			return reg;452		data->fancfg[i] = reg;453 454		/* Enable RPM mode */455		data->fancfg[i] |= 0xa8;456		err = i2c_smbus_write_byte_data(client, config_reg[i], data->fancfg[i]);457		if (err < 0)458			return err;459 460		/* 2 counts (001) and Rate change 100 (0.125 secs) */461		data->fandyn[i] = 0x30;462		err = i2c_smbus_write_byte_data(client, dyn_reg[i], data->fandyn[i]);463		if (err < 0)464			return err;465	}466	return 0;467}468 469static int max6620_probe(struct i2c_client *client)470{471	struct device *dev = &client->dev;472	struct max6620_data *data;473	struct device *hwmon_dev;474	int err;475 476	data = devm_kzalloc(dev, sizeof(struct max6620_data), GFP_KERNEL);477	if (!data)478		return -ENOMEM;479 480	data->client = client;481	mutex_init(&data->update_lock);482 483	err = max6620_init_client(data);484	if (err)485		return err;486 487	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,488							 data,489							 &max6620_chip_info,490							 NULL);491 492	return PTR_ERR_OR_ZERO(hwmon_dev);493}494 495static const struct i2c_device_id max6620_id[] = {496	{ "max6620" },497	{ }498};499MODULE_DEVICE_TABLE(i2c, max6620_id);500 501static struct i2c_driver max6620_driver = {502	.class		= I2C_CLASS_HWMON,503	.driver = {504		.name	= "max6620",505	},506	.probe		= max6620_probe,507	.id_table	= max6620_id,508};509 510module_i2c_driver(max6620_driver);511 512MODULE_AUTHOR("Lucas Grunenberg");513MODULE_DESCRIPTION("MAX6620 sensor driver");514MODULE_LICENSE("GPL");515