18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * A hwmon driver for the Analog Devices ADT7470
48c2ecf20Sopenharmony_ci * Copyright (C) 2007 IBM
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Author: Darrick J. Wong <darrick.wong@oracle.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
138c2ecf20Sopenharmony_ci#include <linux/i2c.h>
148c2ecf20Sopenharmony_ci#include <linux/hwmon.h>
158c2ecf20Sopenharmony_ci#include <linux/hwmon-sysfs.h>
168c2ecf20Sopenharmony_ci#include <linux/err.h>
178c2ecf20Sopenharmony_ci#include <linux/mutex.h>
188c2ecf20Sopenharmony_ci#include <linux/delay.h>
198c2ecf20Sopenharmony_ci#include <linux/log2.h>
208c2ecf20Sopenharmony_ci#include <linux/kthread.h>
218c2ecf20Sopenharmony_ci#include <linux/slab.h>
228c2ecf20Sopenharmony_ci#include <linux/util_macros.h>
238c2ecf20Sopenharmony_ci#include <linux/sched.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/* Addresses to scan */
268c2ecf20Sopenharmony_cistatic const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END };
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* ADT7470 registers */
298c2ecf20Sopenharmony_ci#define ADT7470_REG_BASE_ADDR			0x20
308c2ecf20Sopenharmony_ci#define ADT7470_REG_TEMP_BASE_ADDR		0x20
318c2ecf20Sopenharmony_ci#define ADT7470_REG_TEMP_MAX_ADDR		0x29
328c2ecf20Sopenharmony_ci#define ADT7470_REG_FAN_BASE_ADDR		0x2A
338c2ecf20Sopenharmony_ci#define ADT7470_REG_FAN_MAX_ADDR		0x31
348c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_BASE_ADDR		0x32
358c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_MAX_ADDR		0x35
368c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_MAX_BASE_ADDR		0x38
378c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_MAX_MAX_ADDR		0x3B
388c2ecf20Sopenharmony_ci#define ADT7470_REG_CFG				0x40
398c2ecf20Sopenharmony_ci#define		ADT7470_FSPD_MASK		0x04
408c2ecf20Sopenharmony_ci#define ADT7470_REG_ALARM1			0x41
418c2ecf20Sopenharmony_ci#define		ADT7470_R1T_ALARM		0x01
428c2ecf20Sopenharmony_ci#define		ADT7470_R2T_ALARM		0x02
438c2ecf20Sopenharmony_ci#define		ADT7470_R3T_ALARM		0x04
448c2ecf20Sopenharmony_ci#define		ADT7470_R4T_ALARM		0x08
458c2ecf20Sopenharmony_ci#define		ADT7470_R5T_ALARM		0x10
468c2ecf20Sopenharmony_ci#define		ADT7470_R6T_ALARM		0x20
478c2ecf20Sopenharmony_ci#define		ADT7470_R7T_ALARM		0x40
488c2ecf20Sopenharmony_ci#define		ADT7470_OOL_ALARM		0x80
498c2ecf20Sopenharmony_ci#define ADT7470_REG_ALARM2			0x42
508c2ecf20Sopenharmony_ci#define		ADT7470_R8T_ALARM		0x01
518c2ecf20Sopenharmony_ci#define		ADT7470_R9T_ALARM		0x02
528c2ecf20Sopenharmony_ci#define		ADT7470_R10T_ALARM		0x04
538c2ecf20Sopenharmony_ci#define		ADT7470_FAN1_ALARM		0x10
548c2ecf20Sopenharmony_ci#define		ADT7470_FAN2_ALARM		0x20
558c2ecf20Sopenharmony_ci#define		ADT7470_FAN3_ALARM		0x40
568c2ecf20Sopenharmony_ci#define		ADT7470_FAN4_ALARM		0x80
578c2ecf20Sopenharmony_ci#define ADT7470_REG_TEMP_LIMITS_BASE_ADDR	0x44
588c2ecf20Sopenharmony_ci#define ADT7470_REG_TEMP_LIMITS_MAX_ADDR	0x57
598c2ecf20Sopenharmony_ci#define ADT7470_REG_FAN_MIN_BASE_ADDR		0x58
608c2ecf20Sopenharmony_ci#define ADT7470_REG_FAN_MIN_MAX_ADDR		0x5F
618c2ecf20Sopenharmony_ci#define ADT7470_REG_FAN_MAX_BASE_ADDR		0x60
628c2ecf20Sopenharmony_ci#define ADT7470_REG_FAN_MAX_MAX_ADDR		0x67
638c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_CFG_BASE_ADDR		0x68
648c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM12_CFG			0x68
658c2ecf20Sopenharmony_ci#define		ADT7470_PWM2_AUTO_MASK		0x40
668c2ecf20Sopenharmony_ci#define		ADT7470_PWM1_AUTO_MASK		0x80
678c2ecf20Sopenharmony_ci#define		ADT7470_PWM_AUTO_MASK		0xC0
688c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM34_CFG			0x69
698c2ecf20Sopenharmony_ci#define		ADT7470_PWM3_AUTO_MASK		0x40
708c2ecf20Sopenharmony_ci#define		ADT7470_PWM4_AUTO_MASK		0x80
718c2ecf20Sopenharmony_ci#define	ADT7470_REG_PWM_MIN_BASE_ADDR		0x6A
728c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_MIN_MAX_ADDR		0x6D
738c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_TEMP_MIN_BASE_ADDR	0x6E
748c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_TEMP_MIN_MAX_ADDR	0x71
758c2ecf20Sopenharmony_ci#define ADT7470_REG_CFG_2			0x74
768c2ecf20Sopenharmony_ci#define ADT7470_REG_ACOUSTICS12			0x75
778c2ecf20Sopenharmony_ci#define ADT7470_REG_ACOUSTICS34			0x76
788c2ecf20Sopenharmony_ci#define ADT7470_REG_DEVICE			0x3D
798c2ecf20Sopenharmony_ci#define ADT7470_REG_VENDOR			0x3E
808c2ecf20Sopenharmony_ci#define ADT7470_REG_REVISION			0x3F
818c2ecf20Sopenharmony_ci#define ADT7470_REG_ALARM1_MASK			0x72
828c2ecf20Sopenharmony_ci#define ADT7470_REG_ALARM2_MASK			0x73
838c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_AUTO_TEMP_BASE_ADDR	0x7C
848c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_AUTO_TEMP_MAX_ADDR	0x7D
858c2ecf20Sopenharmony_ci#define ADT7470_REG_MAX_ADDR			0x81
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#define ADT7470_TEMP_COUNT	10
888c2ecf20Sopenharmony_ci#define ADT7470_TEMP_REG(x)	(ADT7470_REG_TEMP_BASE_ADDR + (x))
898c2ecf20Sopenharmony_ci#define ADT7470_TEMP_MIN_REG(x) (ADT7470_REG_TEMP_LIMITS_BASE_ADDR + ((x) * 2))
908c2ecf20Sopenharmony_ci#define ADT7470_TEMP_MAX_REG(x) (ADT7470_REG_TEMP_LIMITS_BASE_ADDR + \
918c2ecf20Sopenharmony_ci				((x) * 2) + 1)
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci#define ADT7470_FAN_COUNT	4
948c2ecf20Sopenharmony_ci#define ADT7470_REG_FAN(x)	(ADT7470_REG_FAN_BASE_ADDR + ((x) * 2))
958c2ecf20Sopenharmony_ci#define ADT7470_REG_FAN_MIN(x)	(ADT7470_REG_FAN_MIN_BASE_ADDR + ((x) * 2))
968c2ecf20Sopenharmony_ci#define ADT7470_REG_FAN_MAX(x)	(ADT7470_REG_FAN_MAX_BASE_ADDR + ((x) * 2))
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci#define ADT7470_PWM_COUNT	4
998c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM(x)	(ADT7470_REG_PWM_BASE_ADDR + (x))
1008c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_MAX(x)	(ADT7470_REG_PWM_MAX_BASE_ADDR + (x))
1018c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_MIN(x)	(ADT7470_REG_PWM_MIN_BASE_ADDR + (x))
1028c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_TMIN(x)	(ADT7470_REG_PWM_TEMP_MIN_BASE_ADDR + (x))
1038c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_CFG(x)	(ADT7470_REG_PWM_CFG_BASE_ADDR + ((x) / 2))
1048c2ecf20Sopenharmony_ci#define ADT7470_REG_PWM_AUTO_TEMP(x)	(ADT7470_REG_PWM_AUTO_TEMP_BASE_ADDR + \
1058c2ecf20Sopenharmony_ci					((x) / 2))
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci#define ALARM2(x)		((x) << 8)
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci#define ADT7470_VENDOR		0x41
1108c2ecf20Sopenharmony_ci#define ADT7470_DEVICE		0x70
1118c2ecf20Sopenharmony_ci/* datasheet only mentions a revision 2 */
1128c2ecf20Sopenharmony_ci#define ADT7470_REVISION	0x02
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci/* "all temps" according to hwmon sysfs interface spec */
1158c2ecf20Sopenharmony_ci#define ADT7470_PWM_ALL_TEMPS	0x3FF
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci/* How often do we reread sensors values? (In jiffies) */
1188c2ecf20Sopenharmony_ci#define SENSOR_REFRESH_INTERVAL	(5 * HZ)
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci/* How often do we reread sensor limit values? (In jiffies) */
1218c2ecf20Sopenharmony_ci#define LIMIT_REFRESH_INTERVAL	(60 * HZ)
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci/* Wait at least 200ms per sensor for 10 sensors */
1248c2ecf20Sopenharmony_ci#define TEMP_COLLECTION_TIME	2000
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci/* auto update thing won't fire more than every 2s */
1278c2ecf20Sopenharmony_ci#define AUTO_UPDATE_INTERVAL	2000
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci/* datasheet says to divide this number by the fan reading to get fan rpm */
1308c2ecf20Sopenharmony_ci#define FAN_PERIOD_TO_RPM(x)	((90000 * 60) / (x))
1318c2ecf20Sopenharmony_ci#define FAN_RPM_TO_PERIOD	FAN_PERIOD_TO_RPM
1328c2ecf20Sopenharmony_ci#define FAN_PERIOD_INVALID	65535
1338c2ecf20Sopenharmony_ci#define FAN_DATA_VALID(x)	((x) && (x) != FAN_PERIOD_INVALID)
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci/* Config registers 1 and 2 include fields for selecting the PWM frequency */
1368c2ecf20Sopenharmony_ci#define ADT7470_CFG_LF		0x40
1378c2ecf20Sopenharmony_ci#define ADT7470_FREQ_MASK	0x70
1388c2ecf20Sopenharmony_ci#define ADT7470_FREQ_SHIFT	4
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistruct adt7470_data {
1418c2ecf20Sopenharmony_ci	struct i2c_client	*client;
1428c2ecf20Sopenharmony_ci	struct mutex		lock;
1438c2ecf20Sopenharmony_ci	char			sensors_valid;
1448c2ecf20Sopenharmony_ci	char			limits_valid;
1458c2ecf20Sopenharmony_ci	unsigned long		sensors_last_updated;	/* In jiffies */
1468c2ecf20Sopenharmony_ci	unsigned long		limits_last_updated;	/* In jiffies */
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	int			num_temp_sensors;	/* -1 = probe */
1498c2ecf20Sopenharmony_ci	int			temperatures_probed;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	s8			temp[ADT7470_TEMP_COUNT];
1528c2ecf20Sopenharmony_ci	s8			temp_min[ADT7470_TEMP_COUNT];
1538c2ecf20Sopenharmony_ci	s8			temp_max[ADT7470_TEMP_COUNT];
1548c2ecf20Sopenharmony_ci	u16			fan[ADT7470_FAN_COUNT];
1558c2ecf20Sopenharmony_ci	u16			fan_min[ADT7470_FAN_COUNT];
1568c2ecf20Sopenharmony_ci	u16			fan_max[ADT7470_FAN_COUNT];
1578c2ecf20Sopenharmony_ci	u16			alarm;
1588c2ecf20Sopenharmony_ci	u16			alarms_mask;
1598c2ecf20Sopenharmony_ci	u8			force_pwm_max;
1608c2ecf20Sopenharmony_ci	u8			pwm[ADT7470_PWM_COUNT];
1618c2ecf20Sopenharmony_ci	u8			pwm_max[ADT7470_PWM_COUNT];
1628c2ecf20Sopenharmony_ci	u8			pwm_automatic[ADT7470_PWM_COUNT];
1638c2ecf20Sopenharmony_ci	u8			pwm_min[ADT7470_PWM_COUNT];
1648c2ecf20Sopenharmony_ci	s8			pwm_tmin[ADT7470_PWM_COUNT];
1658c2ecf20Sopenharmony_ci	u8			pwm_auto_temp[ADT7470_PWM_COUNT];
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	struct task_struct	*auto_update;
1688c2ecf20Sopenharmony_ci	unsigned int		auto_update_interval;
1698c2ecf20Sopenharmony_ci};
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci/*
1728c2ecf20Sopenharmony_ci * 16-bit registers on the ADT7470 are low-byte first.  The data sheet says
1738c2ecf20Sopenharmony_ci * that the low byte must be read before the high byte.
1748c2ecf20Sopenharmony_ci */
1758c2ecf20Sopenharmony_cistatic inline int adt7470_read_word_data(struct i2c_client *client, u8 reg)
1768c2ecf20Sopenharmony_ci{
1778c2ecf20Sopenharmony_ci	u16 foo;
1788c2ecf20Sopenharmony_ci	foo = i2c_smbus_read_byte_data(client, reg);
1798c2ecf20Sopenharmony_ci	foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8);
1808c2ecf20Sopenharmony_ci	return foo;
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic inline int adt7470_write_word_data(struct i2c_client *client, u8 reg,
1848c2ecf20Sopenharmony_ci					  u16 value)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	return i2c_smbus_write_byte_data(client, reg, value & 0xFF)
1878c2ecf20Sopenharmony_ci	       || i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci/* Probe for temperature sensors.  Assumes lock is held */
1918c2ecf20Sopenharmony_cistatic int adt7470_read_temperatures(struct i2c_client *client,
1928c2ecf20Sopenharmony_ci				     struct adt7470_data *data)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	unsigned long res;
1958c2ecf20Sopenharmony_ci	int i;
1968c2ecf20Sopenharmony_ci	u8 cfg, pwm[4], pwm_cfg[2];
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	/* save pwm[1-4] config register */
1998c2ecf20Sopenharmony_ci	pwm_cfg[0] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(0));
2008c2ecf20Sopenharmony_ci	pwm_cfg[1] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(2));
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	/* set manual pwm to whatever it is set to now */
2038c2ecf20Sopenharmony_ci	for (i = 0; i < ADT7470_FAN_COUNT; i++)
2048c2ecf20Sopenharmony_ci		pwm[i] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM(i));
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	/* put pwm in manual mode */
2078c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0),
2088c2ecf20Sopenharmony_ci		pwm_cfg[0] & ~(ADT7470_PWM_AUTO_MASK));
2098c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2),
2108c2ecf20Sopenharmony_ci		pwm_cfg[1] & ~(ADT7470_PWM_AUTO_MASK));
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	/* write pwm control to whatever it was */
2138c2ecf20Sopenharmony_ci	for (i = 0; i < ADT7470_FAN_COUNT; i++)
2148c2ecf20Sopenharmony_ci		i2c_smbus_write_byte_data(client, ADT7470_REG_PWM(i), pwm[i]);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	/* start reading temperature sensors */
2178c2ecf20Sopenharmony_ci	cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
2188c2ecf20Sopenharmony_ci	cfg |= 0x80;
2198c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	/* Delay is 200ms * number of temp sensors. */
2228c2ecf20Sopenharmony_ci	res = msleep_interruptible((data->num_temp_sensors >= 0 ?
2238c2ecf20Sopenharmony_ci				    data->num_temp_sensors * 200 :
2248c2ecf20Sopenharmony_ci				    TEMP_COLLECTION_TIME));
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	/* done reading temperature sensors */
2278c2ecf20Sopenharmony_ci	cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
2288c2ecf20Sopenharmony_ci	cfg &= ~0x80;
2298c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* restore pwm[1-4] config registers */
2328c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]);
2338c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (res) {
2368c2ecf20Sopenharmony_ci		pr_err("ha ha, interrupted\n");
2378c2ecf20Sopenharmony_ci		return -EAGAIN;
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	/* Only count fans if we have to */
2418c2ecf20Sopenharmony_ci	if (data->num_temp_sensors >= 0)
2428c2ecf20Sopenharmony_ci		return 0;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	for (i = 0; i < ADT7470_TEMP_COUNT; i++) {
2458c2ecf20Sopenharmony_ci		data->temp[i] = i2c_smbus_read_byte_data(client,
2468c2ecf20Sopenharmony_ci						ADT7470_TEMP_REG(i));
2478c2ecf20Sopenharmony_ci		if (data->temp[i])
2488c2ecf20Sopenharmony_ci			data->num_temp_sensors = i + 1;
2498c2ecf20Sopenharmony_ci	}
2508c2ecf20Sopenharmony_ci	data->temperatures_probed = 1;
2518c2ecf20Sopenharmony_ci	return 0;
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic int adt7470_update_thread(void *p)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	struct i2c_client *client = p;
2578c2ecf20Sopenharmony_ci	struct adt7470_data *data = i2c_get_clientdata(client);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	while (!kthread_should_stop()) {
2608c2ecf20Sopenharmony_ci		mutex_lock(&data->lock);
2618c2ecf20Sopenharmony_ci		adt7470_read_temperatures(client, data);
2628c2ecf20Sopenharmony_ci		mutex_unlock(&data->lock);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci		if (kthread_should_stop())
2658c2ecf20Sopenharmony_ci			break;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci		schedule_timeout_interruptible(msecs_to_jiffies(data->auto_update_interval));
2688c2ecf20Sopenharmony_ci	}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	return 0;
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_cistatic struct adt7470_data *adt7470_update_device(struct device *dev)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
2768c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
2778c2ecf20Sopenharmony_ci	unsigned long local_jiffies = jiffies;
2788c2ecf20Sopenharmony_ci	u8 cfg;
2798c2ecf20Sopenharmony_ci	int i;
2808c2ecf20Sopenharmony_ci	int need_sensors = 1;
2818c2ecf20Sopenharmony_ci	int need_limits = 1;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	/*
2848c2ecf20Sopenharmony_ci	 * Figure out if we need to update the shadow registers.
2858c2ecf20Sopenharmony_ci	 * Lockless means that we may occasionally report out of
2868c2ecf20Sopenharmony_ci	 * date data.
2878c2ecf20Sopenharmony_ci	 */
2888c2ecf20Sopenharmony_ci	if (time_before(local_jiffies, data->sensors_last_updated +
2898c2ecf20Sopenharmony_ci			SENSOR_REFRESH_INTERVAL) &&
2908c2ecf20Sopenharmony_ci	    data->sensors_valid)
2918c2ecf20Sopenharmony_ci		need_sensors = 0;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	if (time_before(local_jiffies, data->limits_last_updated +
2948c2ecf20Sopenharmony_ci			LIMIT_REFRESH_INTERVAL) &&
2958c2ecf20Sopenharmony_ci	    data->limits_valid)
2968c2ecf20Sopenharmony_ci		need_limits = 0;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	if (!need_sensors && !need_limits)
2998c2ecf20Sopenharmony_ci		return data;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
3028c2ecf20Sopenharmony_ci	if (!need_sensors)
3038c2ecf20Sopenharmony_ci		goto no_sensor_update;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	if (!data->temperatures_probed)
3068c2ecf20Sopenharmony_ci		adt7470_read_temperatures(client, data);
3078c2ecf20Sopenharmony_ci	else
3088c2ecf20Sopenharmony_ci		for (i = 0; i < ADT7470_TEMP_COUNT; i++)
3098c2ecf20Sopenharmony_ci			data->temp[i] = i2c_smbus_read_byte_data(client,
3108c2ecf20Sopenharmony_ci						ADT7470_TEMP_REG(i));
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	for (i = 0; i < ADT7470_FAN_COUNT; i++)
3138c2ecf20Sopenharmony_ci		data->fan[i] = adt7470_read_word_data(client,
3148c2ecf20Sopenharmony_ci						ADT7470_REG_FAN(i));
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	for (i = 0; i < ADT7470_PWM_COUNT; i++) {
3178c2ecf20Sopenharmony_ci		int reg;
3188c2ecf20Sopenharmony_ci		int reg_mask;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci		data->pwm[i] = i2c_smbus_read_byte_data(client,
3218c2ecf20Sopenharmony_ci						ADT7470_REG_PWM(i));
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci		if (i % 2)
3248c2ecf20Sopenharmony_ci			reg_mask = ADT7470_PWM2_AUTO_MASK;
3258c2ecf20Sopenharmony_ci		else
3268c2ecf20Sopenharmony_ci			reg_mask = ADT7470_PWM1_AUTO_MASK;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci		reg = ADT7470_REG_PWM_CFG(i);
3298c2ecf20Sopenharmony_ci		if (i2c_smbus_read_byte_data(client, reg) & reg_mask)
3308c2ecf20Sopenharmony_ci			data->pwm_automatic[i] = 1;
3318c2ecf20Sopenharmony_ci		else
3328c2ecf20Sopenharmony_ci			data->pwm_automatic[i] = 0;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci		reg = ADT7470_REG_PWM_AUTO_TEMP(i);
3358c2ecf20Sopenharmony_ci		cfg = i2c_smbus_read_byte_data(client, reg);
3368c2ecf20Sopenharmony_ci		if (!(i % 2))
3378c2ecf20Sopenharmony_ci			data->pwm_auto_temp[i] = cfg >> 4;
3388c2ecf20Sopenharmony_ci		else
3398c2ecf20Sopenharmony_ci			data->pwm_auto_temp[i] = cfg & 0xF;
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (i2c_smbus_read_byte_data(client, ADT7470_REG_CFG) &
3438c2ecf20Sopenharmony_ci	    ADT7470_FSPD_MASK)
3448c2ecf20Sopenharmony_ci		data->force_pwm_max = 1;
3458c2ecf20Sopenharmony_ci	else
3468c2ecf20Sopenharmony_ci		data->force_pwm_max = 0;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	data->alarm = i2c_smbus_read_byte_data(client, ADT7470_REG_ALARM1);
3498c2ecf20Sopenharmony_ci	if (data->alarm & ADT7470_OOL_ALARM)
3508c2ecf20Sopenharmony_ci		data->alarm |= ALARM2(i2c_smbus_read_byte_data(client,
3518c2ecf20Sopenharmony_ci							ADT7470_REG_ALARM2));
3528c2ecf20Sopenharmony_ci	data->alarms_mask = adt7470_read_word_data(client,
3538c2ecf20Sopenharmony_ci						   ADT7470_REG_ALARM1_MASK);
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	data->sensors_last_updated = local_jiffies;
3568c2ecf20Sopenharmony_ci	data->sensors_valid = 1;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cino_sensor_update:
3598c2ecf20Sopenharmony_ci	if (!need_limits)
3608c2ecf20Sopenharmony_ci		goto out;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	for (i = 0; i < ADT7470_TEMP_COUNT; i++) {
3638c2ecf20Sopenharmony_ci		data->temp_min[i] = i2c_smbus_read_byte_data(client,
3648c2ecf20Sopenharmony_ci						ADT7470_TEMP_MIN_REG(i));
3658c2ecf20Sopenharmony_ci		data->temp_max[i] = i2c_smbus_read_byte_data(client,
3668c2ecf20Sopenharmony_ci						ADT7470_TEMP_MAX_REG(i));
3678c2ecf20Sopenharmony_ci	}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	for (i = 0; i < ADT7470_FAN_COUNT; i++) {
3708c2ecf20Sopenharmony_ci		data->fan_min[i] = adt7470_read_word_data(client,
3718c2ecf20Sopenharmony_ci						ADT7470_REG_FAN_MIN(i));
3728c2ecf20Sopenharmony_ci		data->fan_max[i] = adt7470_read_word_data(client,
3738c2ecf20Sopenharmony_ci						ADT7470_REG_FAN_MAX(i));
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	for (i = 0; i < ADT7470_PWM_COUNT; i++) {
3778c2ecf20Sopenharmony_ci		data->pwm_max[i] = i2c_smbus_read_byte_data(client,
3788c2ecf20Sopenharmony_ci						ADT7470_REG_PWM_MAX(i));
3798c2ecf20Sopenharmony_ci		data->pwm_min[i] = i2c_smbus_read_byte_data(client,
3808c2ecf20Sopenharmony_ci						ADT7470_REG_PWM_MIN(i));
3818c2ecf20Sopenharmony_ci		data->pwm_tmin[i] = i2c_smbus_read_byte_data(client,
3828c2ecf20Sopenharmony_ci						ADT7470_REG_PWM_TMIN(i));
3838c2ecf20Sopenharmony_ci	}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	data->limits_last_updated = local_jiffies;
3868c2ecf20Sopenharmony_ci	data->limits_valid = 1;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ciout:
3898c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
3908c2ecf20Sopenharmony_ci	return data;
3918c2ecf20Sopenharmony_ci}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cistatic ssize_t auto_update_interval_show(struct device *dev,
3948c2ecf20Sopenharmony_ci					 struct device_attribute *devattr,
3958c2ecf20Sopenharmony_ci					 char *buf)
3968c2ecf20Sopenharmony_ci{
3978c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
3988c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", data->auto_update_interval);
3998c2ecf20Sopenharmony_ci}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_cistatic ssize_t auto_update_interval_store(struct device *dev,
4028c2ecf20Sopenharmony_ci					  struct device_attribute *devattr,
4038c2ecf20Sopenharmony_ci					  const char *buf, size_t count)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
4068c2ecf20Sopenharmony_ci	long temp;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
4098c2ecf20Sopenharmony_ci		return -EINVAL;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	temp = clamp_val(temp, 0, 60000);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
4148c2ecf20Sopenharmony_ci	data->auto_update_interval = temp;
4158c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	return count;
4188c2ecf20Sopenharmony_ci}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_cistatic ssize_t num_temp_sensors_show(struct device *dev,
4218c2ecf20Sopenharmony_ci				     struct device_attribute *devattr,
4228c2ecf20Sopenharmony_ci				     char *buf)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
4258c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", data->num_temp_sensors);
4268c2ecf20Sopenharmony_ci}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_cistatic ssize_t num_temp_sensors_store(struct device *dev,
4298c2ecf20Sopenharmony_ci				      struct device_attribute *devattr,
4308c2ecf20Sopenharmony_ci				      const char *buf, size_t count)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
4338c2ecf20Sopenharmony_ci	long temp;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
4368c2ecf20Sopenharmony_ci		return -EINVAL;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	temp = clamp_val(temp, -1, 10);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
4418c2ecf20Sopenharmony_ci	data->num_temp_sensors = temp;
4428c2ecf20Sopenharmony_ci	if (temp < 0)
4438c2ecf20Sopenharmony_ci		data->temperatures_probed = 0;
4448c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	return count;
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic ssize_t temp_min_show(struct device *dev,
4508c2ecf20Sopenharmony_ci			     struct device_attribute *devattr, char *buf)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
4538c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
4548c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", 1000 * data->temp_min[attr->index]);
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic ssize_t temp_min_store(struct device *dev,
4588c2ecf20Sopenharmony_ci			      struct device_attribute *devattr,
4598c2ecf20Sopenharmony_ci			      const char *buf, size_t count)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
4628c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
4638c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
4648c2ecf20Sopenharmony_ci	long temp;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
4678c2ecf20Sopenharmony_ci		return -EINVAL;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	temp = clamp_val(temp, -128000, 127000);
4708c2ecf20Sopenharmony_ci	temp = DIV_ROUND_CLOSEST(temp, 1000);
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
4738c2ecf20Sopenharmony_ci	data->temp_min[attr->index] = temp;
4748c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_TEMP_MIN_REG(attr->index),
4758c2ecf20Sopenharmony_ci				  temp);
4768c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	return count;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic ssize_t temp_max_show(struct device *dev,
4828c2ecf20Sopenharmony_ci			     struct device_attribute *devattr, char *buf)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
4858c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
4868c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", 1000 * data->temp_max[attr->index]);
4878c2ecf20Sopenharmony_ci}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_cistatic ssize_t temp_max_store(struct device *dev,
4908c2ecf20Sopenharmony_ci			      struct device_attribute *devattr,
4918c2ecf20Sopenharmony_ci			      const char *buf, size_t count)
4928c2ecf20Sopenharmony_ci{
4938c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
4948c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
4958c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
4968c2ecf20Sopenharmony_ci	long temp;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
4998c2ecf20Sopenharmony_ci		return -EINVAL;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	temp = clamp_val(temp, -128000, 127000);
5028c2ecf20Sopenharmony_ci	temp = DIV_ROUND_CLOSEST(temp, 1000);
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
5058c2ecf20Sopenharmony_ci	data->temp_max[attr->index] = temp;
5068c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_TEMP_MAX_REG(attr->index),
5078c2ecf20Sopenharmony_ci				  temp);
5088c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	return count;
5118c2ecf20Sopenharmony_ci}
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_cistatic ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
5148c2ecf20Sopenharmony_ci			 char *buf)
5158c2ecf20Sopenharmony_ci{
5168c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5178c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
5188c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", 1000 * data->temp[attr->index]);
5198c2ecf20Sopenharmony_ci}
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_cistatic ssize_t alarm_mask_show(struct device *dev,
5228c2ecf20Sopenharmony_ci			   struct device_attribute *devattr,
5238c2ecf20Sopenharmony_ci			   char *buf)
5248c2ecf20Sopenharmony_ci{
5258c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	return sprintf(buf, "%x\n", data->alarms_mask);
5288c2ecf20Sopenharmony_ci}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_cistatic ssize_t alarm_mask_store(struct device *dev,
5318c2ecf20Sopenharmony_ci				struct device_attribute *devattr,
5328c2ecf20Sopenharmony_ci				const char *buf, size_t count)
5338c2ecf20Sopenharmony_ci{
5348c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
5358c2ecf20Sopenharmony_ci	long mask;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	if (kstrtoul(buf, 0, &mask))
5388c2ecf20Sopenharmony_ci		return -EINVAL;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	if (mask & ~0xffff)
5418c2ecf20Sopenharmony_ci		return -EINVAL;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
5448c2ecf20Sopenharmony_ci	data->alarms_mask = mask;
5458c2ecf20Sopenharmony_ci	adt7470_write_word_data(data->client, ADT7470_REG_ALARM1_MASK, mask);
5468c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	return count;
5498c2ecf20Sopenharmony_ci}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_cistatic ssize_t fan_max_show(struct device *dev,
5528c2ecf20Sopenharmony_ci			    struct device_attribute *devattr, char *buf)
5538c2ecf20Sopenharmony_ci{
5548c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5558c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	if (FAN_DATA_VALID(data->fan_max[attr->index]))
5588c2ecf20Sopenharmony_ci		return sprintf(buf, "%d\n",
5598c2ecf20Sopenharmony_ci			       FAN_PERIOD_TO_RPM(data->fan_max[attr->index]));
5608c2ecf20Sopenharmony_ci	else
5618c2ecf20Sopenharmony_ci		return sprintf(buf, "0\n");
5628c2ecf20Sopenharmony_ci}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_cistatic ssize_t fan_max_store(struct device *dev,
5658c2ecf20Sopenharmony_ci			     struct device_attribute *devattr,
5668c2ecf20Sopenharmony_ci			     const char *buf, size_t count)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5698c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
5708c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
5718c2ecf20Sopenharmony_ci	long temp;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp) || !temp)
5748c2ecf20Sopenharmony_ci		return -EINVAL;
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	temp = FAN_RPM_TO_PERIOD(temp);
5778c2ecf20Sopenharmony_ci	temp = clamp_val(temp, 1, 65534);
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
5808c2ecf20Sopenharmony_ci	data->fan_max[attr->index] = temp;
5818c2ecf20Sopenharmony_ci	adt7470_write_word_data(client, ADT7470_REG_FAN_MAX(attr->index), temp);
5828c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	return count;
5858c2ecf20Sopenharmony_ci}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_cistatic ssize_t fan_min_show(struct device *dev,
5888c2ecf20Sopenharmony_ci			    struct device_attribute *devattr, char *buf)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5918c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	if (FAN_DATA_VALID(data->fan_min[attr->index]))
5948c2ecf20Sopenharmony_ci		return sprintf(buf, "%d\n",
5958c2ecf20Sopenharmony_ci			       FAN_PERIOD_TO_RPM(data->fan_min[attr->index]));
5968c2ecf20Sopenharmony_ci	else
5978c2ecf20Sopenharmony_ci		return sprintf(buf, "0\n");
5988c2ecf20Sopenharmony_ci}
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_cistatic ssize_t fan_min_store(struct device *dev,
6018c2ecf20Sopenharmony_ci			     struct device_attribute *devattr,
6028c2ecf20Sopenharmony_ci			     const char *buf, size_t count)
6038c2ecf20Sopenharmony_ci{
6048c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
6058c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
6068c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
6078c2ecf20Sopenharmony_ci	long temp;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp) || !temp)
6108c2ecf20Sopenharmony_ci		return -EINVAL;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	temp = FAN_RPM_TO_PERIOD(temp);
6138c2ecf20Sopenharmony_ci	temp = clamp_val(temp, 1, 65534);
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
6168c2ecf20Sopenharmony_ci	data->fan_min[attr->index] = temp;
6178c2ecf20Sopenharmony_ci	adt7470_write_word_data(client, ADT7470_REG_FAN_MIN(attr->index), temp);
6188c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	return count;
6218c2ecf20Sopenharmony_ci}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_cistatic ssize_t fan_show(struct device *dev, struct device_attribute *devattr,
6248c2ecf20Sopenharmony_ci			char *buf)
6258c2ecf20Sopenharmony_ci{
6268c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
6278c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	if (FAN_DATA_VALID(data->fan[attr->index]))
6308c2ecf20Sopenharmony_ci		return sprintf(buf, "%d\n",
6318c2ecf20Sopenharmony_ci			       FAN_PERIOD_TO_RPM(data->fan[attr->index]));
6328c2ecf20Sopenharmony_ci	else
6338c2ecf20Sopenharmony_ci		return sprintf(buf, "0\n");
6348c2ecf20Sopenharmony_ci}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_cistatic ssize_t force_pwm_max_show(struct device *dev,
6378c2ecf20Sopenharmony_ci				  struct device_attribute *devattr, char *buf)
6388c2ecf20Sopenharmony_ci{
6398c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
6408c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", data->force_pwm_max);
6418c2ecf20Sopenharmony_ci}
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_cistatic ssize_t force_pwm_max_store(struct device *dev,
6448c2ecf20Sopenharmony_ci				   struct device_attribute *devattr,
6458c2ecf20Sopenharmony_ci				   const char *buf, size_t count)
6468c2ecf20Sopenharmony_ci{
6478c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
6488c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
6498c2ecf20Sopenharmony_ci	long temp;
6508c2ecf20Sopenharmony_ci	u8 reg;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
6538c2ecf20Sopenharmony_ci		return -EINVAL;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
6568c2ecf20Sopenharmony_ci	data->force_pwm_max = temp;
6578c2ecf20Sopenharmony_ci	reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
6588c2ecf20Sopenharmony_ci	if (temp)
6598c2ecf20Sopenharmony_ci		reg |= ADT7470_FSPD_MASK;
6608c2ecf20Sopenharmony_ci	else
6618c2ecf20Sopenharmony_ci		reg &= ~ADT7470_FSPD_MASK;
6628c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg);
6638c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	return count;
6668c2ecf20Sopenharmony_ci}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_cistatic ssize_t pwm_show(struct device *dev, struct device_attribute *devattr,
6698c2ecf20Sopenharmony_ci			char *buf)
6708c2ecf20Sopenharmony_ci{
6718c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
6728c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
6738c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", data->pwm[attr->index]);
6748c2ecf20Sopenharmony_ci}
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_cistatic ssize_t pwm_store(struct device *dev, struct device_attribute *devattr,
6778c2ecf20Sopenharmony_ci			 const char *buf, size_t count)
6788c2ecf20Sopenharmony_ci{
6798c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
6808c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
6818c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
6828c2ecf20Sopenharmony_ci	long temp;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
6858c2ecf20Sopenharmony_ci		return -EINVAL;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	temp = clamp_val(temp, 0, 255);
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
6908c2ecf20Sopenharmony_ci	data->pwm[attr->index] = temp;
6918c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_PWM(attr->index), temp);
6928c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	return count;
6958c2ecf20Sopenharmony_ci}
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci/* These are the valid PWM frequencies to the nearest Hz */
6988c2ecf20Sopenharmony_cistatic const int adt7470_freq_map[] = {
6998c2ecf20Sopenharmony_ci	11, 15, 22, 29, 35, 44, 59, 88, 1400, 22500
7008c2ecf20Sopenharmony_ci};
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_cistatic ssize_t pwm1_freq_show(struct device *dev,
7038c2ecf20Sopenharmony_ci			      struct device_attribute *devattr, char *buf)
7048c2ecf20Sopenharmony_ci{
7058c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
7068c2ecf20Sopenharmony_ci	unsigned char cfg_reg_1;
7078c2ecf20Sopenharmony_ci	unsigned char cfg_reg_2;
7088c2ecf20Sopenharmony_ci	int index;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
7118c2ecf20Sopenharmony_ci	cfg_reg_1 = i2c_smbus_read_byte_data(data->client, ADT7470_REG_CFG);
7128c2ecf20Sopenharmony_ci	cfg_reg_2 = i2c_smbus_read_byte_data(data->client, ADT7470_REG_CFG_2);
7138c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	index = (cfg_reg_2 & ADT7470_FREQ_MASK) >> ADT7470_FREQ_SHIFT;
7168c2ecf20Sopenharmony_ci	if (!(cfg_reg_1 & ADT7470_CFG_LF))
7178c2ecf20Sopenharmony_ci		index += 8;
7188c2ecf20Sopenharmony_ci	if (index >= ARRAY_SIZE(adt7470_freq_map))
7198c2ecf20Sopenharmony_ci		index = ARRAY_SIZE(adt7470_freq_map) - 1;
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	return scnprintf(buf, PAGE_SIZE, "%d\n", adt7470_freq_map[index]);
7228c2ecf20Sopenharmony_ci}
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_cistatic ssize_t pwm1_freq_store(struct device *dev,
7258c2ecf20Sopenharmony_ci			       struct device_attribute *devattr,
7268c2ecf20Sopenharmony_ci			       const char *buf, size_t count)
7278c2ecf20Sopenharmony_ci{
7288c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
7298c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
7308c2ecf20Sopenharmony_ci	long freq;
7318c2ecf20Sopenharmony_ci	int index;
7328c2ecf20Sopenharmony_ci	int low_freq = ADT7470_CFG_LF;
7338c2ecf20Sopenharmony_ci	unsigned char val;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &freq))
7368c2ecf20Sopenharmony_ci		return -EINVAL;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	/* Round the user value given to the closest available frequency */
7398c2ecf20Sopenharmony_ci	index = find_closest(freq, adt7470_freq_map,
7408c2ecf20Sopenharmony_ci			     ARRAY_SIZE(adt7470_freq_map));
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	if (index >= 8) {
7438c2ecf20Sopenharmony_ci		index -= 8;
7448c2ecf20Sopenharmony_ci		low_freq = 0;
7458c2ecf20Sopenharmony_ci	}
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
7488c2ecf20Sopenharmony_ci	/* Configuration Register 1 */
7498c2ecf20Sopenharmony_ci	val = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
7508c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_CFG,
7518c2ecf20Sopenharmony_ci				  (val & ~ADT7470_CFG_LF) | low_freq);
7528c2ecf20Sopenharmony_ci	/* Configuration Register 2 */
7538c2ecf20Sopenharmony_ci	val = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG_2);
7548c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_CFG_2,
7558c2ecf20Sopenharmony_ci		(val & ~ADT7470_FREQ_MASK) | (index << ADT7470_FREQ_SHIFT));
7568c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	return count;
7598c2ecf20Sopenharmony_ci}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_cistatic ssize_t pwm_max_show(struct device *dev,
7628c2ecf20Sopenharmony_ci			    struct device_attribute *devattr, char *buf)
7638c2ecf20Sopenharmony_ci{
7648c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
7658c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
7668c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", data->pwm_max[attr->index]);
7678c2ecf20Sopenharmony_ci}
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_cistatic ssize_t pwm_max_store(struct device *dev,
7708c2ecf20Sopenharmony_ci			     struct device_attribute *devattr,
7718c2ecf20Sopenharmony_ci			     const char *buf, size_t count)
7728c2ecf20Sopenharmony_ci{
7738c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
7748c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
7758c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
7768c2ecf20Sopenharmony_ci	long temp;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
7798c2ecf20Sopenharmony_ci		return -EINVAL;
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	temp = clamp_val(temp, 0, 255);
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
7848c2ecf20Sopenharmony_ci	data->pwm_max[attr->index] = temp;
7858c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_MAX(attr->index),
7868c2ecf20Sopenharmony_ci				  temp);
7878c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	return count;
7908c2ecf20Sopenharmony_ci}
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_cistatic ssize_t pwm_min_show(struct device *dev,
7938c2ecf20Sopenharmony_ci			    struct device_attribute *devattr, char *buf)
7948c2ecf20Sopenharmony_ci{
7958c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
7968c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
7978c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", data->pwm_min[attr->index]);
7988c2ecf20Sopenharmony_ci}
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_cistatic ssize_t pwm_min_store(struct device *dev,
8018c2ecf20Sopenharmony_ci			     struct device_attribute *devattr,
8028c2ecf20Sopenharmony_ci			     const char *buf, size_t count)
8038c2ecf20Sopenharmony_ci{
8048c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
8058c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
8068c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
8078c2ecf20Sopenharmony_ci	long temp;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
8108c2ecf20Sopenharmony_ci		return -EINVAL;
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	temp = clamp_val(temp, 0, 255);
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
8158c2ecf20Sopenharmony_ci	data->pwm_min[attr->index] = temp;
8168c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_MIN(attr->index),
8178c2ecf20Sopenharmony_ci				  temp);
8188c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	return count;
8218c2ecf20Sopenharmony_ci}
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_cistatic ssize_t pwm_tmax_show(struct device *dev,
8248c2ecf20Sopenharmony_ci			     struct device_attribute *devattr, char *buf)
8258c2ecf20Sopenharmony_ci{
8268c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
8278c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
8288c2ecf20Sopenharmony_ci	/* the datasheet says that tmax = tmin + 20C */
8298c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", 1000 * (20 + data->pwm_tmin[attr->index]));
8308c2ecf20Sopenharmony_ci}
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_cistatic ssize_t pwm_tmin_show(struct device *dev,
8338c2ecf20Sopenharmony_ci			     struct device_attribute *devattr, char *buf)
8348c2ecf20Sopenharmony_ci{
8358c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
8368c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
8378c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", 1000 * data->pwm_tmin[attr->index]);
8388c2ecf20Sopenharmony_ci}
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_cistatic ssize_t pwm_tmin_store(struct device *dev,
8418c2ecf20Sopenharmony_ci			      struct device_attribute *devattr,
8428c2ecf20Sopenharmony_ci			      const char *buf, size_t count)
8438c2ecf20Sopenharmony_ci{
8448c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
8458c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
8468c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
8478c2ecf20Sopenharmony_ci	long temp;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
8508c2ecf20Sopenharmony_ci		return -EINVAL;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	temp = clamp_val(temp, -128000, 127000);
8538c2ecf20Sopenharmony_ci	temp = DIV_ROUND_CLOSEST(temp, 1000);
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
8568c2ecf20Sopenharmony_ci	data->pwm_tmin[attr->index] = temp;
8578c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_TMIN(attr->index),
8588c2ecf20Sopenharmony_ci				  temp);
8598c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	return count;
8628c2ecf20Sopenharmony_ci}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_cistatic ssize_t pwm_auto_show(struct device *dev,
8658c2ecf20Sopenharmony_ci			     struct device_attribute *devattr, char *buf)
8668c2ecf20Sopenharmony_ci{
8678c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
8688c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
8698c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", 1 + data->pwm_automatic[attr->index]);
8708c2ecf20Sopenharmony_ci}
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_cistatic ssize_t pwm_auto_store(struct device *dev,
8738c2ecf20Sopenharmony_ci			      struct device_attribute *devattr,
8748c2ecf20Sopenharmony_ci			      const char *buf, size_t count)
8758c2ecf20Sopenharmony_ci{
8768c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
8778c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
8788c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
8798c2ecf20Sopenharmony_ci	int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index);
8808c2ecf20Sopenharmony_ci	int pwm_auto_reg_mask;
8818c2ecf20Sopenharmony_ci	long temp;
8828c2ecf20Sopenharmony_ci	u8 reg;
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
8858c2ecf20Sopenharmony_ci		return -EINVAL;
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	if (attr->index % 2)
8888c2ecf20Sopenharmony_ci		pwm_auto_reg_mask = ADT7470_PWM2_AUTO_MASK;
8898c2ecf20Sopenharmony_ci	else
8908c2ecf20Sopenharmony_ci		pwm_auto_reg_mask = ADT7470_PWM1_AUTO_MASK;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	if (temp != 2 && temp != 1)
8938c2ecf20Sopenharmony_ci		return -EINVAL;
8948c2ecf20Sopenharmony_ci	temp--;
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
8978c2ecf20Sopenharmony_ci	data->pwm_automatic[attr->index] = temp;
8988c2ecf20Sopenharmony_ci	reg = i2c_smbus_read_byte_data(client, pwm_auto_reg);
8998c2ecf20Sopenharmony_ci	if (temp)
9008c2ecf20Sopenharmony_ci		reg |= pwm_auto_reg_mask;
9018c2ecf20Sopenharmony_ci	else
9028c2ecf20Sopenharmony_ci		reg &= ~pwm_auto_reg_mask;
9038c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, pwm_auto_reg, reg);
9048c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	return count;
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_cistatic ssize_t pwm_auto_temp_show(struct device *dev,
9108c2ecf20Sopenharmony_ci				  struct device_attribute *devattr, char *buf)
9118c2ecf20Sopenharmony_ci{
9128c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
9138c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
9148c2ecf20Sopenharmony_ci	u8 ctrl = data->pwm_auto_temp[attr->index];
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	if (ctrl)
9178c2ecf20Sopenharmony_ci		return sprintf(buf, "%d\n", 1 << (ctrl - 1));
9188c2ecf20Sopenharmony_ci	else
9198c2ecf20Sopenharmony_ci		return sprintf(buf, "%d\n", ADT7470_PWM_ALL_TEMPS);
9208c2ecf20Sopenharmony_ci}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_cistatic int cvt_auto_temp(int input)
9238c2ecf20Sopenharmony_ci{
9248c2ecf20Sopenharmony_ci	if (input == ADT7470_PWM_ALL_TEMPS)
9258c2ecf20Sopenharmony_ci		return 0;
9268c2ecf20Sopenharmony_ci	if (input < 1 || !is_power_of_2(input))
9278c2ecf20Sopenharmony_ci		return -EINVAL;
9288c2ecf20Sopenharmony_ci	return ilog2(input) + 1;
9298c2ecf20Sopenharmony_ci}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_cistatic ssize_t pwm_auto_temp_store(struct device *dev,
9328c2ecf20Sopenharmony_ci				   struct device_attribute *devattr,
9338c2ecf20Sopenharmony_ci				   const char *buf, size_t count)
9348c2ecf20Sopenharmony_ci{
9358c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
9368c2ecf20Sopenharmony_ci	struct adt7470_data *data = dev_get_drvdata(dev);
9378c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
9388c2ecf20Sopenharmony_ci	int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index);
9398c2ecf20Sopenharmony_ci	long temp;
9408c2ecf20Sopenharmony_ci	u8 reg;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	if (kstrtol(buf, 10, &temp))
9438c2ecf20Sopenharmony_ci		return -EINVAL;
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	temp = cvt_auto_temp(temp);
9468c2ecf20Sopenharmony_ci	if (temp < 0)
9478c2ecf20Sopenharmony_ci		return temp;
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	mutex_lock(&data->lock);
9508c2ecf20Sopenharmony_ci	data->pwm_automatic[attr->index] = temp;
9518c2ecf20Sopenharmony_ci	reg = i2c_smbus_read_byte_data(client, pwm_auto_reg);
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	if (!(attr->index % 2)) {
9548c2ecf20Sopenharmony_ci		reg &= 0xF;
9558c2ecf20Sopenharmony_ci		reg |= (temp << 4) & 0xF0;
9568c2ecf20Sopenharmony_ci	} else {
9578c2ecf20Sopenharmony_ci		reg &= 0xF0;
9588c2ecf20Sopenharmony_ci		reg |= temp & 0xF;
9598c2ecf20Sopenharmony_ci	}
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	i2c_smbus_write_byte_data(client, pwm_auto_reg, reg);
9628c2ecf20Sopenharmony_ci	mutex_unlock(&data->lock);
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	return count;
9658c2ecf20Sopenharmony_ci}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_cistatic ssize_t alarm_show(struct device *dev,
9688c2ecf20Sopenharmony_ci			  struct device_attribute *devattr, char *buf)
9698c2ecf20Sopenharmony_ci{
9708c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
9718c2ecf20Sopenharmony_ci	struct adt7470_data *data = adt7470_update_device(dev);
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	if (data->alarm & attr->index)
9748c2ecf20Sopenharmony_ci		return sprintf(buf, "1\n");
9758c2ecf20Sopenharmony_ci	else
9768c2ecf20Sopenharmony_ci		return sprintf(buf, "0\n");
9778c2ecf20Sopenharmony_ci}
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(alarm_mask);
9808c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(num_temp_sensors);
9818c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(auto_update_interval);
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
9848c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
9858c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2);
9868c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp4_max, temp_max, 3);
9878c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp5_max, temp_max, 4);
9888c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp6_max, temp_max, 5);
9898c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp7_max, temp_max, 6);
9908c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp8_max, temp_max, 7);
9918c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp9_max, temp_max, 8);
9928c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp10_max, temp_max, 9);
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0);
9958c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1);
9968c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2);
9978c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp4_min, temp_min, 3);
9988c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp5_min, temp_min, 4);
9998c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp6_min, temp_min, 5);
10008c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp7_min, temp_min, 6);
10018c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp8_min, temp_min, 7);
10028c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp9_min, temp_min, 8);
10038c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp10_min, temp_min, 9);
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
10068c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
10078c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
10088c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp4_input, temp, 3);
10098c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp5_input, temp, 4);
10108c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp6_input, temp, 5);
10118c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp7_input, temp, 6);
10128c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp8_input, temp, 7);
10138c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp9_input, temp, 8);
10148c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp10_input, temp, 9);
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, ADT7470_R1T_ALARM);
10178c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, ADT7470_R2T_ALARM);
10188c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp3_alarm, alarm, ADT7470_R3T_ALARM);
10198c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp4_alarm, alarm, ADT7470_R4T_ALARM);
10208c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp5_alarm, alarm, ADT7470_R5T_ALARM);
10218c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp6_alarm, alarm, ADT7470_R6T_ALARM);
10228c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp7_alarm, alarm, ADT7470_R7T_ALARM);
10238c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp8_alarm, alarm, ALARM2(ADT7470_R8T_ALARM));
10248c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp9_alarm, alarm, ALARM2(ADT7470_R9T_ALARM));
10258c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp10_alarm, alarm, ALARM2(ADT7470_R10T_ALARM));
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan1_max, fan_max, 0);
10288c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan2_max, fan_max, 1);
10298c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan3_max, fan_max, 2);
10308c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan4_max, fan_max, 3);
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
10338c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
10348c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2);
10358c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan4_min, fan_min, 3);
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
10388c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
10398c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan3_input, fan, 2);
10408c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan4_input, fan, 3);
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, ALARM2(ADT7470_FAN1_ALARM));
10438c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, ALARM2(ADT7470_FAN2_ALARM));
10448c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan3_alarm, alarm, ALARM2(ADT7470_FAN3_ALARM));
10458c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan4_alarm, alarm, ALARM2(ADT7470_FAN4_ALARM));
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(force_pwm_max, force_pwm_max, 0);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
10508c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
10518c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm3, pwm, 2);
10528c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm4, pwm, 3);
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(pwm1_freq);
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_pwm, pwm_min, 0);
10578c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm2_auto_point1_pwm, pwm_min, 1);
10588c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm3_auto_point1_pwm, pwm_min, 2);
10598c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm4_auto_point1_pwm, pwm_min, 3);
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_pwm, pwm_max, 0);
10628c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm2_auto_point2_pwm, pwm_max, 1);
10638c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm3_auto_point2_pwm, pwm_max, 2);
10648c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm4_auto_point2_pwm, pwm_max, 3);
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp, pwm_tmin, 0);
10678c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm2_auto_point1_temp, pwm_tmin, 1);
10688c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm3_auto_point1_temp, pwm_tmin, 2);
10698c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm4_auto_point1_temp, pwm_tmin, 3);
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(pwm1_auto_point2_temp, pwm_tmax, 0);
10728c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(pwm2_auto_point2_temp, pwm_tmax, 1);
10738c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(pwm3_auto_point2_temp, pwm_tmax, 2);
10748c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(pwm4_auto_point2_temp, pwm_tmax, 3);
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm1_enable, pwm_auto, 0);
10778c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm2_enable, pwm_auto, 1);
10788c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm3_enable, pwm_auto, 2);
10798c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm4_enable, pwm_auto, 3);
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm1_auto_channels_temp, pwm_auto_temp, 0);
10828c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm2_auto_channels_temp, pwm_auto_temp, 1);
10838c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm3_auto_channels_temp, pwm_auto_temp, 2);
10848c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(pwm4_auto_channels_temp, pwm_auto_temp, 3);
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_cistatic struct attribute *adt7470_attrs[] = {
10878c2ecf20Sopenharmony_ci	&dev_attr_alarm_mask.attr,
10888c2ecf20Sopenharmony_ci	&dev_attr_num_temp_sensors.attr,
10898c2ecf20Sopenharmony_ci	&dev_attr_auto_update_interval.attr,
10908c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_max.dev_attr.attr,
10918c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_max.dev_attr.attr,
10928c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_max.dev_attr.attr,
10938c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp4_max.dev_attr.attr,
10948c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp5_max.dev_attr.attr,
10958c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp6_max.dev_attr.attr,
10968c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp7_max.dev_attr.attr,
10978c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp8_max.dev_attr.attr,
10988c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp9_max.dev_attr.attr,
10998c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp10_max.dev_attr.attr,
11008c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_min.dev_attr.attr,
11018c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_min.dev_attr.attr,
11028c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_min.dev_attr.attr,
11038c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp4_min.dev_attr.attr,
11048c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp5_min.dev_attr.attr,
11058c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp6_min.dev_attr.attr,
11068c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp7_min.dev_attr.attr,
11078c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp8_min.dev_attr.attr,
11088c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp9_min.dev_attr.attr,
11098c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp10_min.dev_attr.attr,
11108c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_input.dev_attr.attr,
11118c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_input.dev_attr.attr,
11128c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_input.dev_attr.attr,
11138c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp4_input.dev_attr.attr,
11148c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp5_input.dev_attr.attr,
11158c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp6_input.dev_attr.attr,
11168c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp7_input.dev_attr.attr,
11178c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp8_input.dev_attr.attr,
11188c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp9_input.dev_attr.attr,
11198c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp10_input.dev_attr.attr,
11208c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
11218c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
11228c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
11238c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp4_alarm.dev_attr.attr,
11248c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp5_alarm.dev_attr.attr,
11258c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp6_alarm.dev_attr.attr,
11268c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp7_alarm.dev_attr.attr,
11278c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp8_alarm.dev_attr.attr,
11288c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp9_alarm.dev_attr.attr,
11298c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp10_alarm.dev_attr.attr,
11308c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_max.dev_attr.attr,
11318c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_max.dev_attr.attr,
11328c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_max.dev_attr.attr,
11338c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan4_max.dev_attr.attr,
11348c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_min.dev_attr.attr,
11358c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_min.dev_attr.attr,
11368c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_min.dev_attr.attr,
11378c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan4_min.dev_attr.attr,
11388c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_input.dev_attr.attr,
11398c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_input.dev_attr.attr,
11408c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_input.dev_attr.attr,
11418c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan4_input.dev_attr.attr,
11428c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
11438c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
11448c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
11458c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
11468c2ecf20Sopenharmony_ci	&sensor_dev_attr_force_pwm_max.dev_attr.attr,
11478c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1.dev_attr.attr,
11488c2ecf20Sopenharmony_ci	&dev_attr_pwm1_freq.attr,
11498c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2.dev_attr.attr,
11508c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3.dev_attr.attr,
11518c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm4.dev_attr.attr,
11528c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
11538c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
11548c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
11558c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm4_auto_point1_pwm.dev_attr.attr,
11568c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
11578c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
11588c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
11598c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm4_auto_point2_pwm.dev_attr.attr,
11608c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
11618c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
11628c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,
11638c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm4_auto_point1_temp.dev_attr.attr,
11648c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
11658c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
11668c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
11678c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm4_auto_point2_temp.dev_attr.attr,
11688c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
11698c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
11708c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
11718c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm4_enable.dev_attr.attr,
11728c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
11738c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
11748c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
11758c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr,
11768c2ecf20Sopenharmony_ci	NULL
11778c2ecf20Sopenharmony_ci};
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(adt7470);
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_ci/* Return 0 if detection is successful, -ENODEV otherwise */
11828c2ecf20Sopenharmony_cistatic int adt7470_detect(struct i2c_client *client,
11838c2ecf20Sopenharmony_ci			  struct i2c_board_info *info)
11848c2ecf20Sopenharmony_ci{
11858c2ecf20Sopenharmony_ci	struct i2c_adapter *adapter = client->adapter;
11868c2ecf20Sopenharmony_ci	int vendor, device, revision;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
11898c2ecf20Sopenharmony_ci		return -ENODEV;
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci	vendor = i2c_smbus_read_byte_data(client, ADT7470_REG_VENDOR);
11928c2ecf20Sopenharmony_ci	if (vendor != ADT7470_VENDOR)
11938c2ecf20Sopenharmony_ci		return -ENODEV;
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	device = i2c_smbus_read_byte_data(client, ADT7470_REG_DEVICE);
11968c2ecf20Sopenharmony_ci	if (device != ADT7470_DEVICE)
11978c2ecf20Sopenharmony_ci		return -ENODEV;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	revision = i2c_smbus_read_byte_data(client, ADT7470_REG_REVISION);
12008c2ecf20Sopenharmony_ci	if (revision != ADT7470_REVISION)
12018c2ecf20Sopenharmony_ci		return -ENODEV;
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	strlcpy(info->type, "adt7470", I2C_NAME_SIZE);
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	return 0;
12068c2ecf20Sopenharmony_ci}
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_cistatic void adt7470_init_client(struct i2c_client *client)
12098c2ecf20Sopenharmony_ci{
12108c2ecf20Sopenharmony_ci	int reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	if (reg < 0) {
12138c2ecf20Sopenharmony_ci		dev_err(&client->dev, "cannot read configuration register\n");
12148c2ecf20Sopenharmony_ci	} else {
12158c2ecf20Sopenharmony_ci		/* start monitoring (and do a self-test) */
12168c2ecf20Sopenharmony_ci		i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3);
12178c2ecf20Sopenharmony_ci	}
12188c2ecf20Sopenharmony_ci}
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_cistatic int adt7470_probe(struct i2c_client *client)
12218c2ecf20Sopenharmony_ci{
12228c2ecf20Sopenharmony_ci	struct device *dev = &client->dev;
12238c2ecf20Sopenharmony_ci	struct adt7470_data *data;
12248c2ecf20Sopenharmony_ci	struct device *hwmon_dev;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	data = devm_kzalloc(dev, sizeof(struct adt7470_data), GFP_KERNEL);
12278c2ecf20Sopenharmony_ci	if (!data)
12288c2ecf20Sopenharmony_ci		return -ENOMEM;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	data->num_temp_sensors = -1;
12318c2ecf20Sopenharmony_ci	data->auto_update_interval = AUTO_UPDATE_INTERVAL;
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, data);
12348c2ecf20Sopenharmony_ci	data->client = client;
12358c2ecf20Sopenharmony_ci	mutex_init(&data->lock);
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	dev_info(&client->dev, "%s chip found\n", client->name);
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	/* Initialize the ADT7470 chip */
12408c2ecf20Sopenharmony_ci	adt7470_init_client(client);
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	/* Register sysfs hooks */
12438c2ecf20Sopenharmony_ci	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
12448c2ecf20Sopenharmony_ci							   data,
12458c2ecf20Sopenharmony_ci							   adt7470_groups);
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	if (IS_ERR(hwmon_dev))
12488c2ecf20Sopenharmony_ci		return PTR_ERR(hwmon_dev);
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci	data->auto_update = kthread_run(adt7470_update_thread, client, "%s",
12518c2ecf20Sopenharmony_ci					dev_name(hwmon_dev));
12528c2ecf20Sopenharmony_ci	if (IS_ERR(data->auto_update)) {
12538c2ecf20Sopenharmony_ci		return PTR_ERR(data->auto_update);
12548c2ecf20Sopenharmony_ci	}
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	return 0;
12578c2ecf20Sopenharmony_ci}
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_cistatic int adt7470_remove(struct i2c_client *client)
12608c2ecf20Sopenharmony_ci{
12618c2ecf20Sopenharmony_ci	struct adt7470_data *data = i2c_get_clientdata(client);
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	kthread_stop(data->auto_update);
12648c2ecf20Sopenharmony_ci	return 0;
12658c2ecf20Sopenharmony_ci}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_cistatic const struct i2c_device_id adt7470_id[] = {
12688c2ecf20Sopenharmony_ci	{ "adt7470", 0 },
12698c2ecf20Sopenharmony_ci	{ }
12708c2ecf20Sopenharmony_ci};
12718c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, adt7470_id);
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_cistatic struct i2c_driver adt7470_driver = {
12748c2ecf20Sopenharmony_ci	.class		= I2C_CLASS_HWMON,
12758c2ecf20Sopenharmony_ci	.driver = {
12768c2ecf20Sopenharmony_ci		.name	= "adt7470",
12778c2ecf20Sopenharmony_ci	},
12788c2ecf20Sopenharmony_ci	.probe_new	= adt7470_probe,
12798c2ecf20Sopenharmony_ci	.remove		= adt7470_remove,
12808c2ecf20Sopenharmony_ci	.id_table	= adt7470_id,
12818c2ecf20Sopenharmony_ci	.detect		= adt7470_detect,
12828c2ecf20Sopenharmony_ci	.address_list	= normal_i2c,
12838c2ecf20Sopenharmony_ci};
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_cimodule_i2c_driver(adt7470_driver);
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ciMODULE_AUTHOR("Darrick J. Wong <darrick.wong@oracle.com>");
12888c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ADT7470 driver");
12898c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1290