diff options
Diffstat (limited to 'drivers/hwmon/max6650.c')
| -rw-r--r-- | drivers/hwmon/max6650.c | 105 | 
1 files changed, 89 insertions, 16 deletions
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index 61135a2d0cff..6b9056f9483f 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later  /*   * max6650.c - Part of lm_sensors, Linux kernel modules for hardware   *             monitoring. @@ -15,20 +16,6 @@   * The datasheet was last seen at:   *   *        http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */  #include <linux/module.h> @@ -40,6 +27,7 @@  #include <linux/hwmon-sysfs.h>  #include <linux/err.h>  #include <linux/of_device.h> +#include <linux/thermal.h>  /*   * Insmod parameters @@ -113,6 +101,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 +114,7 @@ struct max6650_data {  	u8 count;  	u8 dac;  	u8 alarm; +	unsigned long cooling_dev_state;  };  static const u8 tach_reg[] = { @@ -134,7 +124,7 @@ static const u8 tach_reg[] = {  	MAX6650_REG_TACH3,  }; -static const struct of_device_id max6650_dt_match[] = { +static const struct of_device_id __maybe_unused max6650_dt_match[] = {  	{  		.compatible = "maxim,max6650",  		.data = (void *)1 @@ -694,6 +684,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 +756,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 +775,31 @@ 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)); +#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 +815,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,  };  |