Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f8d374b authored by Jean-Francois Dagenais's avatar Jean-Francois Dagenais Committed by Guenter Roeck
Browse files

hwmon: (max6650) add thermal cooling device capability



This allows max6650 devices to be referenced in dts as a cooling device.

The pwm value seems duplicated in cooling_dev_state but since pwm goes
through rounding logic into data->dac, it is modified and messes with
the thermal zone state algorithms. It's also better to serve a cache
value, thus avoiding periodic actual i2c traffic.

Signed-off-by: default avatarJean-Francois Dagenais <jeff.dagenais@gmail.com>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 023912db
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -908,6 +908,7 @@ config SENSORS_MAX6642
config SENSORS_MAX6650
	tristate "Maxim MAX6650 sensor chip"
	depends on I2C
	depends on THERMAL || THERMAL=n
	help
	  If you say yes here you get support for the MAX6650 / MAX6651
	  sensor chips.
+89 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/of_device.h>
#include <linux/thermal.h>

/*
 * Insmod parameters
@@ -113,6 +114,7 @@ module_param(clock, int, 0444);
struct max6650_data {
	struct i2c_client *client;
	const struct attribute_group *groups[3];
	struct thermal_cooling_device *cooling_dev;
	struct mutex update_lock;
	int nr_fans;
	char valid; /* zero until following fields are valid */
@@ -125,6 +127,7 @@ struct max6650_data {
	u8 count;
	u8 dac;
	u8 alarm;
	unsigned long cooling_dev_state;
};

static const u8 tach_reg[] = {
@@ -694,6 +697,63 @@ static int max6650_init_client(struct max6650_data *data,
	return 0;
}

#if IS_ENABLED(CONFIG_THERMAL)

static int max6650_get_max_state(struct thermal_cooling_device *cdev,
				 unsigned long *state)
{
	*state = 255;

	return 0;
}

static int max6650_get_cur_state(struct thermal_cooling_device *cdev,
				 unsigned long *state)
{
	struct max6650_data *data = cdev->devdata;

	*state = data->cooling_dev_state;

	return 0;
}

static int max6650_set_cur_state(struct thermal_cooling_device *cdev,
				 unsigned long state)
{
	struct max6650_data *data = cdev->devdata;
	struct i2c_client *client = data->client;
	int err;

	state = clamp_val(state, 0, 255);

	mutex_lock(&data->update_lock);

	if (data->config & MAX6650_CFG_V12)
		data->dac = 180 - (180 * state)/255;
	else
		data->dac = 76 - (76 * state)/255;

	err = i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, data->dac);

	if (!err) {
		max6650_set_operating_mode(data, state ?
						   MAX6650_CFG_MODE_OPEN_LOOP :
						   MAX6650_CFG_MODE_OFF);
		data->cooling_dev_state = state;
	}

	mutex_unlock(&data->update_lock);

	return err < 0 ? err : 0;
}

static const struct thermal_cooling_device_ops max6650_cooling_ops = {
	.get_max_state = max6650_get_max_state,
	.get_cur_state = max6650_get_cur_state,
	.set_cur_state = max6650_set_cur_state,
};
#endif

static int max6650_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
@@ -709,6 +769,7 @@ static int max6650_probe(struct i2c_client *client,
		return -ENOMEM;

	data->client = client;
	i2c_set_clientdata(client, data);
	mutex_init(&data->update_lock);
	data->nr_fans = of_id ? (int)(uintptr_t)of_id->data : id->driver_data;

@@ -727,7 +788,33 @@ static int max6650_probe(struct i2c_client *client,
	hwmon_dev = devm_hwmon_device_register_with_groups(dev,
							   client->name, data,
							   data->groups);
	return PTR_ERR_OR_ZERO(hwmon_dev);
	err = PTR_ERR_OR_ZERO(hwmon_dev);
	if (err)
		return err;

#if IS_ENABLED(CONFIG_THERMAL)
	data->cooling_dev =
		thermal_of_cooling_device_register(client->dev.of_node,
						   client->name, data,
						   &max6650_cooling_ops);
	if (IS_ERR(data->cooling_dev))
		dev_warn(&client->dev,
			 "thermal cooling device register failed: %ld\n",
			 PTR_ERR(data->cooling_dev));
	else
		thermal_cdev_update(data->cooling_dev);
#endif
	return 0;
}

static int max6650_remove(struct i2c_client *client)
{
	struct max6650_data *data = i2c_get_clientdata(client);

	if (!IS_ERR(data->cooling_dev))
		thermal_cooling_device_unregister(data->cooling_dev);

	return 0;
}

static const struct i2c_device_id max6650_id[] = {
@@ -743,6 +830,7 @@ static struct i2c_driver max6650_driver = {
		.of_match_table = of_match_ptr(max6650_dt_match),
	},
	.probe		= max6650_probe,
	.remove		= max6650_remove,
	.id_table	= max6650_id,
};