162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * adt7475 - Thermal sensor driver for the ADT7475 chip and derivatives
462306a36Sopenharmony_ci * Copyright (C) 2007-2008, Advanced Micro Devices, Inc.
562306a36Sopenharmony_ci * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
662306a36Sopenharmony_ci * Copyright (C) 2008 Hans de Goede <hdegoede@redhat.com>
762306a36Sopenharmony_ci * Copyright (C) 2009 Jean Delvare <jdelvare@suse.de>
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Derived from the lm83 driver by Jean Delvare
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/slab.h>
1562306a36Sopenharmony_ci#include <linux/i2c.h>
1662306a36Sopenharmony_ci#include <linux/hwmon.h>
1762306a36Sopenharmony_ci#include <linux/hwmon-sysfs.h>
1862306a36Sopenharmony_ci#include <linux/hwmon-vid.h>
1962306a36Sopenharmony_ci#include <linux/err.h>
2062306a36Sopenharmony_ci#include <linux/jiffies.h>
2162306a36Sopenharmony_ci#include <linux/of.h>
2262306a36Sopenharmony_ci#include <linux/util_macros.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/* Indexes for the sysfs hooks */
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define INPUT		0
2762306a36Sopenharmony_ci#define MIN		1
2862306a36Sopenharmony_ci#define MAX		2
2962306a36Sopenharmony_ci#define CONTROL		3
3062306a36Sopenharmony_ci#define OFFSET		3
3162306a36Sopenharmony_ci#define AUTOMIN		4
3262306a36Sopenharmony_ci#define THERM		5
3362306a36Sopenharmony_ci#define HYSTERSIS	6
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/*
3662306a36Sopenharmony_ci * These are unique identifiers for the sysfs functions - unlike the
3762306a36Sopenharmony_ci * numbers above, these are not also indexes into an array
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define ALARM		9
4162306a36Sopenharmony_ci#define FAULT		10
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/* 7475 Common Registers */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define REG_DEVREV2		0x12	/* ADT7490 only */
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define REG_VTT			0x1E	/* ADT7490 only */
4862306a36Sopenharmony_ci#define REG_EXTEND3		0x1F	/* ADT7490 only */
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#define REG_VOLTAGE_BASE	0x20
5162306a36Sopenharmony_ci#define REG_TEMP_BASE		0x25
5262306a36Sopenharmony_ci#define REG_TACH_BASE		0x28
5362306a36Sopenharmony_ci#define REG_PWM_BASE		0x30
5462306a36Sopenharmony_ci#define REG_PWM_MAX_BASE	0x38
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#define REG_DEVID		0x3D
5762306a36Sopenharmony_ci#define REG_VENDID		0x3E
5862306a36Sopenharmony_ci#define REG_DEVID2		0x3F
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define REG_CONFIG1		0x40
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#define REG_STATUS1		0x41
6362306a36Sopenharmony_ci#define REG_STATUS2		0x42
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#define REG_VID			0x43	/* ADT7476 only */
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci#define REG_VOLTAGE_MIN_BASE	0x44
6862306a36Sopenharmony_ci#define REG_VOLTAGE_MAX_BASE	0x45
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#define REG_TEMP_MIN_BASE	0x4E
7162306a36Sopenharmony_ci#define REG_TEMP_MAX_BASE	0x4F
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define REG_TACH_MIN_BASE	0x54
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci#define REG_PWM_CONFIG_BASE	0x5C
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci#define REG_TEMP_TRANGE_BASE	0x5F
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci#define REG_ENHANCE_ACOUSTICS1	0x62
8062306a36Sopenharmony_ci#define REG_ENHANCE_ACOUSTICS2	0x63
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci#define REG_PWM_MIN_BASE	0x64
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci#define REG_TEMP_TMIN_BASE	0x67
8562306a36Sopenharmony_ci#define REG_TEMP_THERM_BASE	0x6A
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#define REG_REMOTE1_HYSTERSIS	0x6D
8862306a36Sopenharmony_ci#define REG_REMOTE2_HYSTERSIS	0x6E
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define REG_TEMP_OFFSET_BASE	0x70
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#define REG_CONFIG2		0x73
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci#define REG_EXTEND1		0x76
9562306a36Sopenharmony_ci#define REG_EXTEND2		0x77
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci#define REG_CONFIG3		0x78
9862306a36Sopenharmony_ci#define REG_CONFIG5		0x7C
9962306a36Sopenharmony_ci#define REG_CONFIG4		0x7D
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci#define REG_STATUS4		0x81	/* ADT7490 only */
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci#define REG_VTT_MIN		0x84	/* ADT7490 only */
10462306a36Sopenharmony_ci#define REG_VTT_MAX		0x86	/* ADT7490 only */
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci#define VID_VIDSEL		0x80	/* ADT7476 only */
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci#define CONFIG2_ATTN		0x20
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci#define CONFIG3_SMBALERT	0x01
11162306a36Sopenharmony_ci#define CONFIG3_THERM		0x02
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci#define CONFIG4_PINFUNC		0x03
11462306a36Sopenharmony_ci#define CONFIG4_THERM		0x01
11562306a36Sopenharmony_ci#define CONFIG4_SMBALERT	0x02
11662306a36Sopenharmony_ci#define CONFIG4_MAXDUTY		0x08
11762306a36Sopenharmony_ci#define CONFIG4_ATTN_IN10	0x30
11862306a36Sopenharmony_ci#define CONFIG4_ATTN_IN43	0xC0
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#define CONFIG5_TWOSCOMP	0x01
12162306a36Sopenharmony_ci#define CONFIG5_TEMPOFFSET	0x02
12262306a36Sopenharmony_ci#define CONFIG5_VIDGPIO		0x10	/* ADT7476 only */
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci/* ADT7475 Settings */
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci#define ADT7475_VOLTAGE_COUNT	5	/* Not counting Vtt */
12762306a36Sopenharmony_ci#define ADT7475_TEMP_COUNT	3
12862306a36Sopenharmony_ci#define ADT7475_TACH_COUNT	4
12962306a36Sopenharmony_ci#define ADT7475_PWM_COUNT	3
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci/* Macro to read the registers */
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci#define adt7475_read(reg) i2c_smbus_read_byte_data(client, (reg))
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/* Macros to easily index the registers */
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci#define TACH_REG(idx) (REG_TACH_BASE + ((idx) * 2))
13862306a36Sopenharmony_ci#define TACH_MIN_REG(idx) (REG_TACH_MIN_BASE + ((idx) * 2))
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci#define PWM_REG(idx) (REG_PWM_BASE + (idx))
14162306a36Sopenharmony_ci#define PWM_MAX_REG(idx) (REG_PWM_MAX_BASE + (idx))
14262306a36Sopenharmony_ci#define PWM_MIN_REG(idx) (REG_PWM_MIN_BASE + (idx))
14362306a36Sopenharmony_ci#define PWM_CONFIG_REG(idx) (REG_PWM_CONFIG_BASE + (idx))
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci#define VOLTAGE_REG(idx) (REG_VOLTAGE_BASE + (idx))
14662306a36Sopenharmony_ci#define VOLTAGE_MIN_REG(idx) (REG_VOLTAGE_MIN_BASE + ((idx) * 2))
14762306a36Sopenharmony_ci#define VOLTAGE_MAX_REG(idx) (REG_VOLTAGE_MAX_BASE + ((idx) * 2))
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci#define TEMP_REG(idx) (REG_TEMP_BASE + (idx))
15062306a36Sopenharmony_ci#define TEMP_MIN_REG(idx) (REG_TEMP_MIN_BASE + ((idx) * 2))
15162306a36Sopenharmony_ci#define TEMP_MAX_REG(idx) (REG_TEMP_MAX_BASE + ((idx) * 2))
15262306a36Sopenharmony_ci#define TEMP_TMIN_REG(idx) (REG_TEMP_TMIN_BASE + (idx))
15362306a36Sopenharmony_ci#define TEMP_THERM_REG(idx) (REG_TEMP_THERM_BASE + (idx))
15462306a36Sopenharmony_ci#define TEMP_OFFSET_REG(idx) (REG_TEMP_OFFSET_BASE + (idx))
15562306a36Sopenharmony_ci#define TEMP_TRANGE_REG(idx) (REG_TEMP_TRANGE_BASE + (idx))
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cienum chips { adt7473, adt7475, adt7476, adt7490 };
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic const struct i2c_device_id adt7475_id[] = {
16262306a36Sopenharmony_ci	{ "adt7473", adt7473 },
16362306a36Sopenharmony_ci	{ "adt7475", adt7475 },
16462306a36Sopenharmony_ci	{ "adt7476", adt7476 },
16562306a36Sopenharmony_ci	{ "adt7490", adt7490 },
16662306a36Sopenharmony_ci	{ }
16762306a36Sopenharmony_ci};
16862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, adt7475_id);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic const struct of_device_id __maybe_unused adt7475_of_match[] = {
17162306a36Sopenharmony_ci	{
17262306a36Sopenharmony_ci		.compatible = "adi,adt7473",
17362306a36Sopenharmony_ci		.data = (void *)adt7473
17462306a36Sopenharmony_ci	},
17562306a36Sopenharmony_ci	{
17662306a36Sopenharmony_ci		.compatible = "adi,adt7475",
17762306a36Sopenharmony_ci		.data = (void *)adt7475
17862306a36Sopenharmony_ci	},
17962306a36Sopenharmony_ci	{
18062306a36Sopenharmony_ci		.compatible = "adi,adt7476",
18162306a36Sopenharmony_ci		.data = (void *)adt7476
18262306a36Sopenharmony_ci	},
18362306a36Sopenharmony_ci	{
18462306a36Sopenharmony_ci		.compatible = "adi,adt7490",
18562306a36Sopenharmony_ci		.data = (void *)adt7490
18662306a36Sopenharmony_ci	},
18762306a36Sopenharmony_ci	{ },
18862306a36Sopenharmony_ci};
18962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, adt7475_of_match);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistruct adt7475_data {
19262306a36Sopenharmony_ci	struct i2c_client *client;
19362306a36Sopenharmony_ci	struct mutex lock;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	unsigned long measure_updated;
19662306a36Sopenharmony_ci	bool valid;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	u8 config2;
19962306a36Sopenharmony_ci	u8 config4;
20062306a36Sopenharmony_ci	u8 config5;
20162306a36Sopenharmony_ci	u8 has_voltage;
20262306a36Sopenharmony_ci	u8 bypass_attn;		/* Bypass voltage attenuator */
20362306a36Sopenharmony_ci	u8 has_pwm2:1;
20462306a36Sopenharmony_ci	u8 has_fan4:1;
20562306a36Sopenharmony_ci	u8 has_vid:1;
20662306a36Sopenharmony_ci	u32 alarms;
20762306a36Sopenharmony_ci	u16 voltage[3][6];
20862306a36Sopenharmony_ci	u16 temp[7][3];
20962306a36Sopenharmony_ci	u16 tach[2][4];
21062306a36Sopenharmony_ci	u8 pwm[4][3];
21162306a36Sopenharmony_ci	u8 range[3];
21262306a36Sopenharmony_ci	u8 pwmctl[3];
21362306a36Sopenharmony_ci	u8 pwmchan[3];
21462306a36Sopenharmony_ci	u8 enh_acoustics[2];
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	u8 vid;
21762306a36Sopenharmony_ci	u8 vrm;
21862306a36Sopenharmony_ci	const struct attribute_group *groups[9];
21962306a36Sopenharmony_ci};
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic struct i2c_driver adt7475_driver;
22262306a36Sopenharmony_cistatic struct adt7475_data *adt7475_update_device(struct device *dev);
22362306a36Sopenharmony_cistatic void adt7475_read_hystersis(struct i2c_client *client);
22462306a36Sopenharmony_cistatic void adt7475_read_pwm(struct i2c_client *client, int index);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci/* Given a temp value, convert it to register value */
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic inline u16 temp2reg(struct adt7475_data *data, long val)
22962306a36Sopenharmony_ci{
23062306a36Sopenharmony_ci	u16 ret;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	if (!(data->config5 & CONFIG5_TWOSCOMP)) {
23362306a36Sopenharmony_ci		val = clamp_val(val, -64000, 191000);
23462306a36Sopenharmony_ci		ret = (val + 64500) / 1000;
23562306a36Sopenharmony_ci	} else {
23662306a36Sopenharmony_ci		val = clamp_val(val, -128000, 127000);
23762306a36Sopenharmony_ci		if (val < -500)
23862306a36Sopenharmony_ci			ret = (256500 + val) / 1000;
23962306a36Sopenharmony_ci		else
24062306a36Sopenharmony_ci			ret = (val + 500) / 1000;
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	return ret << 2;
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci/* Given a register value, convert it to a real temp value */
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic inline int reg2temp(struct adt7475_data *data, u16 reg)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	if (data->config5 & CONFIG5_TWOSCOMP) {
25162306a36Sopenharmony_ci		if (reg >= 512)
25262306a36Sopenharmony_ci			return (reg - 1024) * 250;
25362306a36Sopenharmony_ci		else
25462306a36Sopenharmony_ci			return reg * 250;
25562306a36Sopenharmony_ci	} else
25662306a36Sopenharmony_ci		return (reg - 256) * 250;
25762306a36Sopenharmony_ci}
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_cistatic inline int tach2rpm(u16 tach)
26062306a36Sopenharmony_ci{
26162306a36Sopenharmony_ci	if (tach == 0 || tach == 0xFFFF)
26262306a36Sopenharmony_ci		return 0;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	return (90000 * 60) / tach;
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic inline u16 rpm2tach(unsigned long rpm)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	if (rpm == 0)
27062306a36Sopenharmony_ci		return 0;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	return clamp_val((90000 * 60) / rpm, 1, 0xFFFF);
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci/* Scaling factors for voltage inputs, taken from the ADT7490 datasheet */
27662306a36Sopenharmony_cistatic const int adt7473_in_scaling[ADT7475_VOLTAGE_COUNT + 1][2] = {
27762306a36Sopenharmony_ci	{ 45, 94 },	/* +2.5V */
27862306a36Sopenharmony_ci	{ 175, 525 },	/* Vccp */
27962306a36Sopenharmony_ci	{ 68, 71 },	/* Vcc */
28062306a36Sopenharmony_ci	{ 93, 47 },	/* +5V */
28162306a36Sopenharmony_ci	{ 120, 20 },	/* +12V */
28262306a36Sopenharmony_ci	{ 45, 45 },	/* Vtt */
28362306a36Sopenharmony_ci};
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_cistatic inline int reg2volt(int channel, u16 reg, u8 bypass_attn)
28662306a36Sopenharmony_ci{
28762306a36Sopenharmony_ci	const int *r = adt7473_in_scaling[channel];
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	if (bypass_attn & (1 << channel))
29062306a36Sopenharmony_ci		return DIV_ROUND_CLOSEST(reg * 2250, 1024);
29162306a36Sopenharmony_ci	return DIV_ROUND_CLOSEST(reg * (r[0] + r[1]) * 2250, r[1] * 1024);
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_cistatic inline u16 volt2reg(int channel, long volt, u8 bypass_attn)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	const int *r = adt7473_in_scaling[channel];
29762306a36Sopenharmony_ci	long reg;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	if (bypass_attn & (1 << channel))
30062306a36Sopenharmony_ci		reg = DIV_ROUND_CLOSEST(volt * 1024, 2250);
30162306a36Sopenharmony_ci	else
30262306a36Sopenharmony_ci		reg = DIV_ROUND_CLOSEST(volt * r[1] * 1024,
30362306a36Sopenharmony_ci					(r[0] + r[1]) * 2250);
30462306a36Sopenharmony_ci	return clamp_val(reg, 0, 1023) & (0xff << 2);
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_cistatic int adt7475_read_word(struct i2c_client *client, int reg)
30862306a36Sopenharmony_ci{
30962306a36Sopenharmony_ci	int val1, val2;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	val1 = i2c_smbus_read_byte_data(client, reg);
31262306a36Sopenharmony_ci	if (val1 < 0)
31362306a36Sopenharmony_ci		return val1;
31462306a36Sopenharmony_ci	val2 = i2c_smbus_read_byte_data(client, reg + 1);
31562306a36Sopenharmony_ci	if (val2 < 0)
31662306a36Sopenharmony_ci		return val2;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	return val1 | (val2 << 8);
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic void adt7475_write_word(struct i2c_client *client, int reg, u16 val)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, reg + 1, val >> 8);
32462306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, reg, val & 0xFF);
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic ssize_t voltage_show(struct device *dev, struct device_attribute *attr,
32862306a36Sopenharmony_ci			    char *buf)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	struct adt7475_data *data = adt7475_update_device(dev);
33162306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
33262306a36Sopenharmony_ci	unsigned short val;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	if (IS_ERR(data))
33562306a36Sopenharmony_ci		return PTR_ERR(data);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	switch (sattr->nr) {
33862306a36Sopenharmony_ci	case ALARM:
33962306a36Sopenharmony_ci		return sprintf(buf, "%d\n",
34062306a36Sopenharmony_ci			       (data->alarms >> sattr->index) & 1);
34162306a36Sopenharmony_ci	default:
34262306a36Sopenharmony_ci		val = data->voltage[sattr->nr][sattr->index];
34362306a36Sopenharmony_ci		return sprintf(buf, "%d\n",
34462306a36Sopenharmony_ci			       reg2volt(sattr->index, val, data->bypass_attn));
34562306a36Sopenharmony_ci	}
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_cistatic ssize_t voltage_store(struct device *dev,
34962306a36Sopenharmony_ci			     struct device_attribute *attr, const char *buf,
35062306a36Sopenharmony_ci			     size_t count)
35162306a36Sopenharmony_ci{
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
35462306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
35562306a36Sopenharmony_ci	struct i2c_client *client = data->client;
35662306a36Sopenharmony_ci	unsigned char reg;
35762306a36Sopenharmony_ci	long val;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	if (kstrtol(buf, 10, &val))
36062306a36Sopenharmony_ci		return -EINVAL;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	mutex_lock(&data->lock);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	data->voltage[sattr->nr][sattr->index] =
36562306a36Sopenharmony_ci				volt2reg(sattr->index, val, data->bypass_attn);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	if (sattr->index < ADT7475_VOLTAGE_COUNT) {
36862306a36Sopenharmony_ci		if (sattr->nr == MIN)
36962306a36Sopenharmony_ci			reg = VOLTAGE_MIN_REG(sattr->index);
37062306a36Sopenharmony_ci		else
37162306a36Sopenharmony_ci			reg = VOLTAGE_MAX_REG(sattr->index);
37262306a36Sopenharmony_ci	} else {
37362306a36Sopenharmony_ci		if (sattr->nr == MIN)
37462306a36Sopenharmony_ci			reg = REG_VTT_MIN;
37562306a36Sopenharmony_ci		else
37662306a36Sopenharmony_ci			reg = REG_VTT_MAX;
37762306a36Sopenharmony_ci	}
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, reg,
38062306a36Sopenharmony_ci				  data->voltage[sattr->nr][sattr->index] >> 2);
38162306a36Sopenharmony_ci	mutex_unlock(&data->lock);
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	return count;
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic ssize_t temp_show(struct device *dev, struct device_attribute *attr,
38762306a36Sopenharmony_ci			 char *buf)
38862306a36Sopenharmony_ci{
38962306a36Sopenharmony_ci	struct adt7475_data *data = adt7475_update_device(dev);
39062306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
39162306a36Sopenharmony_ci	int out;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	if (IS_ERR(data))
39462306a36Sopenharmony_ci		return PTR_ERR(data);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	switch (sattr->nr) {
39762306a36Sopenharmony_ci	case HYSTERSIS:
39862306a36Sopenharmony_ci		mutex_lock(&data->lock);
39962306a36Sopenharmony_ci		out = data->temp[sattr->nr][sattr->index];
40062306a36Sopenharmony_ci		if (sattr->index != 1)
40162306a36Sopenharmony_ci			out = (out >> 4) & 0xF;
40262306a36Sopenharmony_ci		else
40362306a36Sopenharmony_ci			out = (out & 0xF);
40462306a36Sopenharmony_ci		/*
40562306a36Sopenharmony_ci		 * Show the value as an absolute number tied to
40662306a36Sopenharmony_ci		 * THERM
40762306a36Sopenharmony_ci		 */
40862306a36Sopenharmony_ci		out = reg2temp(data, data->temp[THERM][sattr->index]) -
40962306a36Sopenharmony_ci			out * 1000;
41062306a36Sopenharmony_ci		mutex_unlock(&data->lock);
41162306a36Sopenharmony_ci		break;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	case OFFSET:
41462306a36Sopenharmony_ci		/*
41562306a36Sopenharmony_ci		 * Offset is always 2's complement, regardless of the
41662306a36Sopenharmony_ci		 * setting in CONFIG5
41762306a36Sopenharmony_ci		 */
41862306a36Sopenharmony_ci		mutex_lock(&data->lock);
41962306a36Sopenharmony_ci		out = (s8)data->temp[sattr->nr][sattr->index];
42062306a36Sopenharmony_ci		if (data->config5 & CONFIG5_TEMPOFFSET)
42162306a36Sopenharmony_ci			out *= 1000;
42262306a36Sopenharmony_ci		else
42362306a36Sopenharmony_ci			out *= 500;
42462306a36Sopenharmony_ci		mutex_unlock(&data->lock);
42562306a36Sopenharmony_ci		break;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	case ALARM:
42862306a36Sopenharmony_ci		out = (data->alarms >> (sattr->index + 4)) & 1;
42962306a36Sopenharmony_ci		break;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	case FAULT:
43262306a36Sopenharmony_ci		/* Note - only for remote1 and remote2 */
43362306a36Sopenharmony_ci		out = !!(data->alarms & (sattr->index ? 0x8000 : 0x4000));
43462306a36Sopenharmony_ci		break;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	default:
43762306a36Sopenharmony_ci		/* All other temp values are in the configured format */
43862306a36Sopenharmony_ci		out = reg2temp(data, data->temp[sattr->nr][sattr->index]);
43962306a36Sopenharmony_ci	}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	return sprintf(buf, "%d\n", out);
44262306a36Sopenharmony_ci}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_cistatic ssize_t temp_store(struct device *dev, struct device_attribute *attr,
44562306a36Sopenharmony_ci			  const char *buf, size_t count)
44662306a36Sopenharmony_ci{
44762306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
44862306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
44962306a36Sopenharmony_ci	struct i2c_client *client = data->client;
45062306a36Sopenharmony_ci	unsigned char reg = 0;
45162306a36Sopenharmony_ci	u8 out;
45262306a36Sopenharmony_ci	int temp;
45362306a36Sopenharmony_ci	long val;
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	if (kstrtol(buf, 10, &val))
45662306a36Sopenharmony_ci		return -EINVAL;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	mutex_lock(&data->lock);
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	/* We need the config register in all cases for temp <-> reg conv. */
46162306a36Sopenharmony_ci	data->config5 = adt7475_read(REG_CONFIG5);
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	switch (sattr->nr) {
46462306a36Sopenharmony_ci	case OFFSET:
46562306a36Sopenharmony_ci		if (data->config5 & CONFIG5_TEMPOFFSET) {
46662306a36Sopenharmony_ci			val = clamp_val(val, -63000, 127000);
46762306a36Sopenharmony_ci			out = data->temp[OFFSET][sattr->index] = val / 1000;
46862306a36Sopenharmony_ci		} else {
46962306a36Sopenharmony_ci			val = clamp_val(val, -63000, 64000);
47062306a36Sopenharmony_ci			out = data->temp[OFFSET][sattr->index] = val / 500;
47162306a36Sopenharmony_ci		}
47262306a36Sopenharmony_ci		break;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	case HYSTERSIS:
47562306a36Sopenharmony_ci		/*
47662306a36Sopenharmony_ci		 * The value will be given as an absolute value, turn it
47762306a36Sopenharmony_ci		 * into an offset based on THERM
47862306a36Sopenharmony_ci		 */
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci		/* Read fresh THERM and HYSTERSIS values from the chip */
48162306a36Sopenharmony_ci		data->temp[THERM][sattr->index] =
48262306a36Sopenharmony_ci			adt7475_read(TEMP_THERM_REG(sattr->index)) << 2;
48362306a36Sopenharmony_ci		adt7475_read_hystersis(client);
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci		temp = reg2temp(data, data->temp[THERM][sattr->index]);
48662306a36Sopenharmony_ci		val = clamp_val(val, temp - 15000, temp);
48762306a36Sopenharmony_ci		val = (temp - val) / 1000;
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci		if (sattr->index != 1) {
49062306a36Sopenharmony_ci			data->temp[HYSTERSIS][sattr->index] &= 0x0F;
49162306a36Sopenharmony_ci			data->temp[HYSTERSIS][sattr->index] |= (val & 0xF) << 4;
49262306a36Sopenharmony_ci		} else {
49362306a36Sopenharmony_ci			data->temp[HYSTERSIS][sattr->index] &= 0xF0;
49462306a36Sopenharmony_ci			data->temp[HYSTERSIS][sattr->index] |= (val & 0xF);
49562306a36Sopenharmony_ci		}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci		out = data->temp[HYSTERSIS][sattr->index];
49862306a36Sopenharmony_ci		break;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	default:
50162306a36Sopenharmony_ci		data->temp[sattr->nr][sattr->index] = temp2reg(data, val);
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci		/*
50462306a36Sopenharmony_ci		 * We maintain an extra 2 digits of precision for simplicity
50562306a36Sopenharmony_ci		 * - shift those back off before writing the value
50662306a36Sopenharmony_ci		 */
50762306a36Sopenharmony_ci		out = (u8) (data->temp[sattr->nr][sattr->index] >> 2);
50862306a36Sopenharmony_ci	}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	switch (sattr->nr) {
51162306a36Sopenharmony_ci	case MIN:
51262306a36Sopenharmony_ci		reg = TEMP_MIN_REG(sattr->index);
51362306a36Sopenharmony_ci		break;
51462306a36Sopenharmony_ci	case MAX:
51562306a36Sopenharmony_ci		reg = TEMP_MAX_REG(sattr->index);
51662306a36Sopenharmony_ci		break;
51762306a36Sopenharmony_ci	case OFFSET:
51862306a36Sopenharmony_ci		reg = TEMP_OFFSET_REG(sattr->index);
51962306a36Sopenharmony_ci		break;
52062306a36Sopenharmony_ci	case AUTOMIN:
52162306a36Sopenharmony_ci		reg = TEMP_TMIN_REG(sattr->index);
52262306a36Sopenharmony_ci		break;
52362306a36Sopenharmony_ci	case THERM:
52462306a36Sopenharmony_ci		reg = TEMP_THERM_REG(sattr->index);
52562306a36Sopenharmony_ci		break;
52662306a36Sopenharmony_ci	case HYSTERSIS:
52762306a36Sopenharmony_ci		if (sattr->index != 2)
52862306a36Sopenharmony_ci			reg = REG_REMOTE1_HYSTERSIS;
52962306a36Sopenharmony_ci		else
53062306a36Sopenharmony_ci			reg = REG_REMOTE2_HYSTERSIS;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci		break;
53362306a36Sopenharmony_ci	}
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, reg, out);
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci	mutex_unlock(&data->lock);
53862306a36Sopenharmony_ci	return count;
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci/* Assuming CONFIG6[SLOW] is 0 */
54262306a36Sopenharmony_cistatic const int ad7475_st_map[] = {
54362306a36Sopenharmony_ci	37500, 18800, 12500, 7500, 4700, 3100, 1600, 800,
54462306a36Sopenharmony_ci};
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_cistatic ssize_t temp_st_show(struct device *dev, struct device_attribute *attr,
54762306a36Sopenharmony_ci			    char *buf)
54862306a36Sopenharmony_ci{
54962306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
55062306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
55162306a36Sopenharmony_ci	long val;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	switch (sattr->index) {
55462306a36Sopenharmony_ci	case 0:
55562306a36Sopenharmony_ci		val = data->enh_acoustics[0] & 0xf;
55662306a36Sopenharmony_ci		break;
55762306a36Sopenharmony_ci	case 1:
55862306a36Sopenharmony_ci		val = data->enh_acoustics[1] & 0xf;
55962306a36Sopenharmony_ci		break;
56062306a36Sopenharmony_ci	case 2:
56162306a36Sopenharmony_ci	default:
56262306a36Sopenharmony_ci		val = (data->enh_acoustics[1] >> 4) & 0xf;
56362306a36Sopenharmony_ci		break;
56462306a36Sopenharmony_ci	}
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	if (val & 0x8)
56762306a36Sopenharmony_ci		return sprintf(buf, "%d\n", ad7475_st_map[val & 0x7]);
56862306a36Sopenharmony_ci	else
56962306a36Sopenharmony_ci		return sprintf(buf, "0\n");
57062306a36Sopenharmony_ci}
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_cistatic ssize_t temp_st_store(struct device *dev,
57362306a36Sopenharmony_ci			     struct device_attribute *attr, const char *buf,
57462306a36Sopenharmony_ci			     size_t count)
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
57762306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
57862306a36Sopenharmony_ci	struct i2c_client *client = data->client;
57962306a36Sopenharmony_ci	unsigned char reg;
58062306a36Sopenharmony_ci	int shift, idx;
58162306a36Sopenharmony_ci	ulong val;
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	if (kstrtoul(buf, 10, &val))
58462306a36Sopenharmony_ci		return -EINVAL;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	switch (sattr->index) {
58762306a36Sopenharmony_ci	case 0:
58862306a36Sopenharmony_ci		reg = REG_ENHANCE_ACOUSTICS1;
58962306a36Sopenharmony_ci		shift = 0;
59062306a36Sopenharmony_ci		idx = 0;
59162306a36Sopenharmony_ci		break;
59262306a36Sopenharmony_ci	case 1:
59362306a36Sopenharmony_ci		reg = REG_ENHANCE_ACOUSTICS2;
59462306a36Sopenharmony_ci		shift = 0;
59562306a36Sopenharmony_ci		idx = 1;
59662306a36Sopenharmony_ci		break;
59762306a36Sopenharmony_ci	case 2:
59862306a36Sopenharmony_ci	default:
59962306a36Sopenharmony_ci		reg = REG_ENHANCE_ACOUSTICS2;
60062306a36Sopenharmony_ci		shift = 4;
60162306a36Sopenharmony_ci		idx = 1;
60262306a36Sopenharmony_ci		break;
60362306a36Sopenharmony_ci	}
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	if (val > 0) {
60662306a36Sopenharmony_ci		val = find_closest_descending(val, ad7475_st_map,
60762306a36Sopenharmony_ci					      ARRAY_SIZE(ad7475_st_map));
60862306a36Sopenharmony_ci		val |= 0x8;
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	mutex_lock(&data->lock);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	data->enh_acoustics[idx] &= ~(0xf << shift);
61462306a36Sopenharmony_ci	data->enh_acoustics[idx] |= (val << shift);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, reg, data->enh_acoustics[idx]);
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	mutex_unlock(&data->lock);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	return count;
62162306a36Sopenharmony_ci}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci/*
62462306a36Sopenharmony_ci * Table of autorange values - the user will write the value in millidegrees,
62562306a36Sopenharmony_ci * and we'll convert it
62662306a36Sopenharmony_ci */
62762306a36Sopenharmony_cistatic const int autorange_table[] = {
62862306a36Sopenharmony_ci	2000, 2500, 3330, 4000, 5000, 6670, 8000,
62962306a36Sopenharmony_ci	10000, 13330, 16000, 20000, 26670, 32000, 40000,
63062306a36Sopenharmony_ci	53330, 80000
63162306a36Sopenharmony_ci};
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_cistatic ssize_t point2_show(struct device *dev, struct device_attribute *attr,
63462306a36Sopenharmony_ci			   char *buf)
63562306a36Sopenharmony_ci{
63662306a36Sopenharmony_ci	struct adt7475_data *data = adt7475_update_device(dev);
63762306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
63862306a36Sopenharmony_ci	int out, val;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	if (IS_ERR(data))
64162306a36Sopenharmony_ci		return PTR_ERR(data);
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	mutex_lock(&data->lock);
64462306a36Sopenharmony_ci	out = (data->range[sattr->index] >> 4) & 0x0F;
64562306a36Sopenharmony_ci	val = reg2temp(data, data->temp[AUTOMIN][sattr->index]);
64662306a36Sopenharmony_ci	mutex_unlock(&data->lock);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	return sprintf(buf, "%d\n", val + autorange_table[out]);
64962306a36Sopenharmony_ci}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_cistatic ssize_t point2_store(struct device *dev, struct device_attribute *attr,
65262306a36Sopenharmony_ci			    const char *buf, size_t count)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
65562306a36Sopenharmony_ci	struct i2c_client *client = data->client;
65662306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
65762306a36Sopenharmony_ci	int temp;
65862306a36Sopenharmony_ci	long val;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	if (kstrtol(buf, 10, &val))
66162306a36Sopenharmony_ci		return -EINVAL;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	mutex_lock(&data->lock);
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	/* Get a fresh copy of the needed registers */
66662306a36Sopenharmony_ci	data->config5 = adt7475_read(REG_CONFIG5);
66762306a36Sopenharmony_ci	data->temp[AUTOMIN][sattr->index] =
66862306a36Sopenharmony_ci		adt7475_read(TEMP_TMIN_REG(sattr->index)) << 2;
66962306a36Sopenharmony_ci	data->range[sattr->index] =
67062306a36Sopenharmony_ci		adt7475_read(TEMP_TRANGE_REG(sattr->index));
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	/*
67362306a36Sopenharmony_ci	 * The user will write an absolute value, so subtract the start point
67462306a36Sopenharmony_ci	 * to figure the range
67562306a36Sopenharmony_ci	 */
67662306a36Sopenharmony_ci	temp = reg2temp(data, data->temp[AUTOMIN][sattr->index]);
67762306a36Sopenharmony_ci	val = clamp_val(val, temp + autorange_table[0],
67862306a36Sopenharmony_ci		temp + autorange_table[ARRAY_SIZE(autorange_table) - 1]);
67962306a36Sopenharmony_ci	val -= temp;
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	/* Find the nearest table entry to what the user wrote */
68262306a36Sopenharmony_ci	val = find_closest(val, autorange_table, ARRAY_SIZE(autorange_table));
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	data->range[sattr->index] &= ~0xF0;
68562306a36Sopenharmony_ci	data->range[sattr->index] |= val << 4;
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index),
68862306a36Sopenharmony_ci				  data->range[sattr->index]);
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	mutex_unlock(&data->lock);
69162306a36Sopenharmony_ci	return count;
69262306a36Sopenharmony_ci}
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_cistatic ssize_t tach_show(struct device *dev, struct device_attribute *attr,
69562306a36Sopenharmony_ci			 char *buf)
69662306a36Sopenharmony_ci{
69762306a36Sopenharmony_ci	struct adt7475_data *data = adt7475_update_device(dev);
69862306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
69962306a36Sopenharmony_ci	int out;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	if (IS_ERR(data))
70262306a36Sopenharmony_ci		return PTR_ERR(data);
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	if (sattr->nr == ALARM)
70562306a36Sopenharmony_ci		out = (data->alarms >> (sattr->index + 10)) & 1;
70662306a36Sopenharmony_ci	else
70762306a36Sopenharmony_ci		out = tach2rpm(data->tach[sattr->nr][sattr->index]);
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	return sprintf(buf, "%d\n", out);
71062306a36Sopenharmony_ci}
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_cistatic ssize_t tach_store(struct device *dev, struct device_attribute *attr,
71362306a36Sopenharmony_ci			  const char *buf, size_t count)
71462306a36Sopenharmony_ci{
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
71762306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
71862306a36Sopenharmony_ci	struct i2c_client *client = data->client;
71962306a36Sopenharmony_ci	unsigned long val;
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	if (kstrtoul(buf, 10, &val))
72262306a36Sopenharmony_ci		return -EINVAL;
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	mutex_lock(&data->lock);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	data->tach[MIN][sattr->index] = rpm2tach(val);
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	adt7475_write_word(client, TACH_MIN_REG(sattr->index),
72962306a36Sopenharmony_ci			   data->tach[MIN][sattr->index]);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	mutex_unlock(&data->lock);
73262306a36Sopenharmony_ci	return count;
73362306a36Sopenharmony_ci}
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_cistatic ssize_t pwm_show(struct device *dev, struct device_attribute *attr,
73662306a36Sopenharmony_ci			char *buf)
73762306a36Sopenharmony_ci{
73862306a36Sopenharmony_ci	struct adt7475_data *data = adt7475_update_device(dev);
73962306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	if (IS_ERR(data))
74262306a36Sopenharmony_ci		return PTR_ERR(data);
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	return sprintf(buf, "%d\n", data->pwm[sattr->nr][sattr->index]);
74562306a36Sopenharmony_ci}
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_cistatic ssize_t pwmchan_show(struct device *dev, struct device_attribute *attr,
74862306a36Sopenharmony_ci			    char *buf)
74962306a36Sopenharmony_ci{
75062306a36Sopenharmony_ci	struct adt7475_data *data = adt7475_update_device(dev);
75162306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	if (IS_ERR(data))
75462306a36Sopenharmony_ci		return PTR_ERR(data);
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	return sprintf(buf, "%d\n", data->pwmchan[sattr->index]);
75762306a36Sopenharmony_ci}
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_cistatic ssize_t pwmctrl_show(struct device *dev, struct device_attribute *attr,
76062306a36Sopenharmony_ci			    char *buf)
76162306a36Sopenharmony_ci{
76262306a36Sopenharmony_ci	struct adt7475_data *data = adt7475_update_device(dev);
76362306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	if (IS_ERR(data))
76662306a36Sopenharmony_ci		return PTR_ERR(data);
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	return sprintf(buf, "%d\n", data->pwmctl[sattr->index]);
76962306a36Sopenharmony_ci}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_cistatic ssize_t pwm_store(struct device *dev, struct device_attribute *attr,
77262306a36Sopenharmony_ci			 const char *buf, size_t count)
77362306a36Sopenharmony_ci{
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
77662306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
77762306a36Sopenharmony_ci	struct i2c_client *client = data->client;
77862306a36Sopenharmony_ci	unsigned char reg = 0;
77962306a36Sopenharmony_ci	long val;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	if (kstrtol(buf, 10, &val))
78262306a36Sopenharmony_ci		return -EINVAL;
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci	mutex_lock(&data->lock);
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	switch (sattr->nr) {
78762306a36Sopenharmony_ci	case INPUT:
78862306a36Sopenharmony_ci		/* Get a fresh value for CONTROL */
78962306a36Sopenharmony_ci		data->pwm[CONTROL][sattr->index] =
79062306a36Sopenharmony_ci			adt7475_read(PWM_CONFIG_REG(sattr->index));
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci		/*
79362306a36Sopenharmony_ci		 * If we are not in manual mode, then we shouldn't allow
79462306a36Sopenharmony_ci		 * the user to set the pwm speed
79562306a36Sopenharmony_ci		 */
79662306a36Sopenharmony_ci		if (((data->pwm[CONTROL][sattr->index] >> 5) & 7) != 7) {
79762306a36Sopenharmony_ci			mutex_unlock(&data->lock);
79862306a36Sopenharmony_ci			return count;
79962306a36Sopenharmony_ci		}
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci		reg = PWM_REG(sattr->index);
80262306a36Sopenharmony_ci		break;
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	case MIN:
80562306a36Sopenharmony_ci		reg = PWM_MIN_REG(sattr->index);
80662306a36Sopenharmony_ci		break;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	case MAX:
80962306a36Sopenharmony_ci		reg = PWM_MAX_REG(sattr->index);
81062306a36Sopenharmony_ci		break;
81162306a36Sopenharmony_ci	}
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci	data->pwm[sattr->nr][sattr->index] = clamp_val(val, 0, 0xFF);
81462306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, reg,
81562306a36Sopenharmony_ci				  data->pwm[sattr->nr][sattr->index]);
81662306a36Sopenharmony_ci	mutex_unlock(&data->lock);
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	return count;
81962306a36Sopenharmony_ci}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_cistatic ssize_t stall_disable_show(struct device *dev,
82262306a36Sopenharmony_ci				  struct device_attribute *attr, char *buf)
82362306a36Sopenharmony_ci{
82462306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
82562306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	u8 mask = BIT(5 + sattr->index);
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	return sprintf(buf, "%d\n", !!(data->enh_acoustics[0] & mask));
83062306a36Sopenharmony_ci}
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_cistatic ssize_t stall_disable_store(struct device *dev,
83362306a36Sopenharmony_ci				   struct device_attribute *attr,
83462306a36Sopenharmony_ci				   const char *buf, size_t count)
83562306a36Sopenharmony_ci{
83662306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
83762306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
83862306a36Sopenharmony_ci	struct i2c_client *client = data->client;
83962306a36Sopenharmony_ci	long val;
84062306a36Sopenharmony_ci	u8 mask = BIT(5 + sattr->index);
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	if (kstrtol(buf, 10, &val))
84362306a36Sopenharmony_ci		return -EINVAL;
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci	mutex_lock(&data->lock);
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	data->enh_acoustics[0] &= ~mask;
84862306a36Sopenharmony_ci	if (val)
84962306a36Sopenharmony_ci		data->enh_acoustics[0] |= mask;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, REG_ENHANCE_ACOUSTICS1,
85262306a36Sopenharmony_ci				  data->enh_acoustics[0]);
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	mutex_unlock(&data->lock);
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	return count;
85762306a36Sopenharmony_ci}
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci/* Called by set_pwmctrl and set_pwmchan */
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_cistatic int hw_set_pwm(struct i2c_client *client, int index,
86262306a36Sopenharmony_ci		      unsigned int pwmctl, unsigned int pwmchan)
86362306a36Sopenharmony_ci{
86462306a36Sopenharmony_ci	struct adt7475_data *data = i2c_get_clientdata(client);
86562306a36Sopenharmony_ci	long val = 0;
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	switch (pwmctl) {
86862306a36Sopenharmony_ci	case 0:
86962306a36Sopenharmony_ci		val = 0x03;	/* Run at full speed */
87062306a36Sopenharmony_ci		break;
87162306a36Sopenharmony_ci	case 1:
87262306a36Sopenharmony_ci		val = 0x07;	/* Manual mode */
87362306a36Sopenharmony_ci		break;
87462306a36Sopenharmony_ci	case 2:
87562306a36Sopenharmony_ci		switch (pwmchan) {
87662306a36Sopenharmony_ci		case 1:
87762306a36Sopenharmony_ci			/* Remote1 controls PWM */
87862306a36Sopenharmony_ci			val = 0x00;
87962306a36Sopenharmony_ci			break;
88062306a36Sopenharmony_ci		case 2:
88162306a36Sopenharmony_ci			/* local controls PWM */
88262306a36Sopenharmony_ci			val = 0x01;
88362306a36Sopenharmony_ci			break;
88462306a36Sopenharmony_ci		case 4:
88562306a36Sopenharmony_ci			/* remote2 controls PWM */
88662306a36Sopenharmony_ci			val = 0x02;
88762306a36Sopenharmony_ci			break;
88862306a36Sopenharmony_ci		case 6:
88962306a36Sopenharmony_ci			/* local/remote2 control PWM */
89062306a36Sopenharmony_ci			val = 0x05;
89162306a36Sopenharmony_ci			break;
89262306a36Sopenharmony_ci		case 7:
89362306a36Sopenharmony_ci			/* All three control PWM */
89462306a36Sopenharmony_ci			val = 0x06;
89562306a36Sopenharmony_ci			break;
89662306a36Sopenharmony_ci		default:
89762306a36Sopenharmony_ci			return -EINVAL;
89862306a36Sopenharmony_ci		}
89962306a36Sopenharmony_ci		break;
90062306a36Sopenharmony_ci	default:
90162306a36Sopenharmony_ci		return -EINVAL;
90262306a36Sopenharmony_ci	}
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	data->pwmctl[index] = pwmctl;
90562306a36Sopenharmony_ci	data->pwmchan[index] = pwmchan;
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	data->pwm[CONTROL][index] &= ~0xE0;
90862306a36Sopenharmony_ci	data->pwm[CONTROL][index] |= (val & 7) << 5;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
91162306a36Sopenharmony_ci				  data->pwm[CONTROL][index]);
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	return 0;
91462306a36Sopenharmony_ci}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_cistatic ssize_t pwmchan_store(struct device *dev,
91762306a36Sopenharmony_ci			     struct device_attribute *attr, const char *buf,
91862306a36Sopenharmony_ci			     size_t count)
91962306a36Sopenharmony_ci{
92062306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
92162306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
92262306a36Sopenharmony_ci	struct i2c_client *client = data->client;
92362306a36Sopenharmony_ci	int r;
92462306a36Sopenharmony_ci	long val;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	if (kstrtol(buf, 10, &val))
92762306a36Sopenharmony_ci		return -EINVAL;
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	mutex_lock(&data->lock);
93062306a36Sopenharmony_ci	/* Read Modify Write PWM values */
93162306a36Sopenharmony_ci	adt7475_read_pwm(client, sattr->index);
93262306a36Sopenharmony_ci	r = hw_set_pwm(client, sattr->index, data->pwmctl[sattr->index], val);
93362306a36Sopenharmony_ci	if (r)
93462306a36Sopenharmony_ci		count = r;
93562306a36Sopenharmony_ci	mutex_unlock(&data->lock);
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	return count;
93862306a36Sopenharmony_ci}
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_cistatic ssize_t pwmctrl_store(struct device *dev,
94162306a36Sopenharmony_ci			     struct device_attribute *attr, const char *buf,
94262306a36Sopenharmony_ci			     size_t count)
94362306a36Sopenharmony_ci{
94462306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
94562306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
94662306a36Sopenharmony_ci	struct i2c_client *client = data->client;
94762306a36Sopenharmony_ci	int r;
94862306a36Sopenharmony_ci	long val;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	if (kstrtol(buf, 10, &val))
95162306a36Sopenharmony_ci		return -EINVAL;
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	mutex_lock(&data->lock);
95462306a36Sopenharmony_ci	/* Read Modify Write PWM values */
95562306a36Sopenharmony_ci	adt7475_read_pwm(client, sattr->index);
95662306a36Sopenharmony_ci	r = hw_set_pwm(client, sattr->index, val, data->pwmchan[sattr->index]);
95762306a36Sopenharmony_ci	if (r)
95862306a36Sopenharmony_ci		count = r;
95962306a36Sopenharmony_ci	mutex_unlock(&data->lock);
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	return count;
96262306a36Sopenharmony_ci}
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci/* List of frequencies for the PWM */
96562306a36Sopenharmony_cistatic const int pwmfreq_table[] = {
96662306a36Sopenharmony_ci	11, 14, 22, 29, 35, 44, 58, 88, 22500
96762306a36Sopenharmony_ci};
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_cistatic ssize_t pwmfreq_show(struct device *dev, struct device_attribute *attr,
97062306a36Sopenharmony_ci			    char *buf)
97162306a36Sopenharmony_ci{
97262306a36Sopenharmony_ci	struct adt7475_data *data = adt7475_update_device(dev);
97362306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
97462306a36Sopenharmony_ci	int idx;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	if (IS_ERR(data))
97762306a36Sopenharmony_ci		return PTR_ERR(data);
97862306a36Sopenharmony_ci	idx = clamp_val(data->range[sattr->index] & 0xf, 0,
97962306a36Sopenharmony_ci			ARRAY_SIZE(pwmfreq_table) - 1);
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	return sprintf(buf, "%d\n", pwmfreq_table[idx]);
98262306a36Sopenharmony_ci}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_cistatic ssize_t pwmfreq_store(struct device *dev,
98562306a36Sopenharmony_ci			     struct device_attribute *attr, const char *buf,
98662306a36Sopenharmony_ci			     size_t count)
98762306a36Sopenharmony_ci{
98862306a36Sopenharmony_ci	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
98962306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
99062306a36Sopenharmony_ci	struct i2c_client *client = data->client;
99162306a36Sopenharmony_ci	int out;
99262306a36Sopenharmony_ci	long val;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	if (kstrtol(buf, 10, &val))
99562306a36Sopenharmony_ci		return -EINVAL;
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	out = find_closest(val, pwmfreq_table, ARRAY_SIZE(pwmfreq_table));
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci	mutex_lock(&data->lock);
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	data->range[sattr->index] =
100262306a36Sopenharmony_ci		adt7475_read(TEMP_TRANGE_REG(sattr->index));
100362306a36Sopenharmony_ci	data->range[sattr->index] &= ~0xf;
100462306a36Sopenharmony_ci	data->range[sattr->index] |= out;
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index),
100762306a36Sopenharmony_ci				  data->range[sattr->index]);
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	mutex_unlock(&data->lock);
101062306a36Sopenharmony_ci	return count;
101162306a36Sopenharmony_ci}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_cistatic ssize_t pwm_use_point2_pwm_at_crit_show(struct device *dev,
101462306a36Sopenharmony_ci					struct device_attribute *devattr,
101562306a36Sopenharmony_ci					char *buf)
101662306a36Sopenharmony_ci{
101762306a36Sopenharmony_ci	struct adt7475_data *data = adt7475_update_device(dev);
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	if (IS_ERR(data))
102062306a36Sopenharmony_ci		return PTR_ERR(data);
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	return sprintf(buf, "%d\n", !!(data->config4 & CONFIG4_MAXDUTY));
102362306a36Sopenharmony_ci}
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_cistatic ssize_t pwm_use_point2_pwm_at_crit_store(struct device *dev,
102662306a36Sopenharmony_ci					struct device_attribute *devattr,
102762306a36Sopenharmony_ci					const char *buf, size_t count)
102862306a36Sopenharmony_ci{
102962306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
103062306a36Sopenharmony_ci	struct i2c_client *client = data->client;
103162306a36Sopenharmony_ci	long val;
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	if (kstrtol(buf, 10, &val))
103462306a36Sopenharmony_ci		return -EINVAL;
103562306a36Sopenharmony_ci	if (val != 0 && val != 1)
103662306a36Sopenharmony_ci		return -EINVAL;
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	mutex_lock(&data->lock);
103962306a36Sopenharmony_ci	data->config4 = i2c_smbus_read_byte_data(client, REG_CONFIG4);
104062306a36Sopenharmony_ci	if (val)
104162306a36Sopenharmony_ci		data->config4 |= CONFIG4_MAXDUTY;
104262306a36Sopenharmony_ci	else
104362306a36Sopenharmony_ci		data->config4 &= ~CONFIG4_MAXDUTY;
104462306a36Sopenharmony_ci	i2c_smbus_write_byte_data(client, REG_CONFIG4, data->config4);
104562306a36Sopenharmony_ci	mutex_unlock(&data->lock);
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	return count;
104862306a36Sopenharmony_ci}
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_cistatic ssize_t vrm_show(struct device *dev, struct device_attribute *devattr,
105162306a36Sopenharmony_ci			char *buf)
105262306a36Sopenharmony_ci{
105362306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
105462306a36Sopenharmony_ci	return sprintf(buf, "%d\n", (int)data->vrm);
105562306a36Sopenharmony_ci}
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_cistatic ssize_t vrm_store(struct device *dev, struct device_attribute *devattr,
105862306a36Sopenharmony_ci			 const char *buf, size_t count)
105962306a36Sopenharmony_ci{
106062306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
106162306a36Sopenharmony_ci	long val;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	if (kstrtol(buf, 10, &val))
106462306a36Sopenharmony_ci		return -EINVAL;
106562306a36Sopenharmony_ci	if (val < 0 || val > 255)
106662306a36Sopenharmony_ci		return -EINVAL;
106762306a36Sopenharmony_ci	data->vrm = val;
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	return count;
107062306a36Sopenharmony_ci}
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_cistatic ssize_t cpu0_vid_show(struct device *dev,
107362306a36Sopenharmony_ci			     struct device_attribute *devattr, char *buf)
107462306a36Sopenharmony_ci{
107562306a36Sopenharmony_ci	struct adt7475_data *data = adt7475_update_device(dev);
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	if (IS_ERR(data))
107862306a36Sopenharmony_ci		return PTR_ERR(data);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
108162306a36Sopenharmony_ci}
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in0_input, voltage, INPUT, 0);
108462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in0_max, voltage, MAX, 0);
108562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in0_min, voltage, MIN, 0);
108662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in0_alarm, voltage, ALARM, 0);
108762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in1_input, voltage, INPUT, 1);
108862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in1_max, voltage, MAX, 1);
108962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in1_min, voltage, MIN, 1);
109062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in1_alarm, voltage, ALARM, 1);
109162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in2_input, voltage, INPUT, 2);
109262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in2_max, voltage, MAX, 2);
109362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in2_min, voltage, MIN, 2);
109462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in2_alarm, voltage, ALARM, 2);
109562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in3_input, voltage, INPUT, 3);
109662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in3_max, voltage, MAX, 3);
109762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in3_min, voltage, MIN, 3);
109862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in3_alarm, voltage, ALARM, 3);
109962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in4_input, voltage, INPUT, 4);
110062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in4_max, voltage, MAX, 4);
110162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in4_min, voltage, MIN, 4);
110262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in4_alarm, voltage, ALARM, 8);
110362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in5_input, voltage, INPUT, 5);
110462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in5_max, voltage, MAX, 5);
110562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(in5_min, voltage, MIN, 5);
110662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(in5_alarm, voltage, ALARM, 31);
110762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(temp1_input, temp, INPUT, 0);
110862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(temp1_alarm, temp, ALARM, 0);
110962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(temp1_fault, temp, FAULT, 0);
111062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp, MAX, 0);
111162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp1_min, temp, MIN, 0);
111262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp1_offset, temp, OFFSET, 0);
111362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp1_auto_point1_temp, temp, AUTOMIN, 0);
111462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp1_auto_point2_temp, point2, 0, 0);
111562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp1_crit, temp, THERM, 0);
111662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp1_crit_hyst, temp, HYSTERSIS, 0);
111762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp1_smoothing, temp_st, 0, 0);
111862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(temp2_input, temp, INPUT, 1);
111962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(temp2_alarm, temp, ALARM, 1);
112062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp, MAX, 1);
112162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp2_min, temp, MIN, 1);
112262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp2_offset, temp, OFFSET, 1);
112362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp2_auto_point1_temp, temp, AUTOMIN, 1);
112462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp2_auto_point2_temp, point2, 0, 1);
112562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp2_crit, temp, THERM, 1);
112662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp2_crit_hyst, temp, HYSTERSIS, 1);
112762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp2_smoothing, temp_st, 0, 1);
112862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(temp3_input, temp, INPUT, 2);
112962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(temp3_alarm, temp, ALARM, 2);
113062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(temp3_fault, temp, FAULT, 2);
113162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp3_max, temp, MAX, 2);
113262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp3_min, temp, MIN, 2);
113362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp3_offset, temp, OFFSET, 2);
113462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp3_auto_point1_temp, temp, AUTOMIN, 2);
113562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp3_auto_point2_temp, point2, 0, 2);
113662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp3_crit, temp, THERM, 2);
113762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp3_crit_hyst, temp, HYSTERSIS, 2);
113862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(temp3_smoothing, temp_st, 0, 2);
113962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(fan1_input, tach, INPUT, 0);
114062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(fan1_min, tach, MIN, 0);
114162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(fan1_alarm, tach, ALARM, 0);
114262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(fan2_input, tach, INPUT, 1);
114362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(fan2_min, tach, MIN, 1);
114462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(fan2_alarm, tach, ALARM, 1);
114562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(fan3_input, tach, INPUT, 2);
114662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(fan3_min, tach, MIN, 2);
114762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(fan3_alarm, tach, ALARM, 2);
114862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(fan4_input, tach, INPUT, 3);
114962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(fan4_min, tach, MIN, 3);
115062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RO(fan4_alarm, tach, ALARM, 3);
115162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm1, pwm, INPUT, 0);
115262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm1_freq, pwmfreq, INPUT, 0);
115362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm1_enable, pwmctrl, INPUT, 0);
115462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_channels_temp, pwmchan, INPUT, 0);
115562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point1_pwm, pwm, MIN, 0);
115662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point2_pwm, pwm, MAX, 0);
115762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm1_stall_disable, stall_disable, 0, 0);
115862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm2, pwm, INPUT, 1);
115962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm2_freq, pwmfreq, INPUT, 1);
116062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm2_enable, pwmctrl, INPUT, 1);
116162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_channels_temp, pwmchan, INPUT, 1);
116262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point1_pwm, pwm, MIN, 1);
116362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point2_pwm, pwm, MAX, 1);
116462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm2_stall_disable, stall_disable, 0, 1);
116562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm3, pwm, INPUT, 2);
116662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm3_freq, pwmfreq, INPUT, 2);
116762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm3_enable, pwmctrl, INPUT, 2);
116862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_channels_temp, pwmchan, INPUT, 2);
116962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point1_pwm, pwm, MIN, 2);
117062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point2_pwm, pwm, MAX, 2);
117162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2_RW(pwm3_stall_disable, stall_disable, 0, 2);
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci/* Non-standard name, might need revisiting */
117462306a36Sopenharmony_cistatic DEVICE_ATTR_RW(pwm_use_point2_pwm_at_crit);
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_cistatic DEVICE_ATTR_RW(vrm);
117762306a36Sopenharmony_cistatic DEVICE_ATTR_RO(cpu0_vid);
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_cistatic struct attribute *adt7475_attrs[] = {
118062306a36Sopenharmony_ci	&sensor_dev_attr_in1_input.dev_attr.attr,
118162306a36Sopenharmony_ci	&sensor_dev_attr_in1_max.dev_attr.attr,
118262306a36Sopenharmony_ci	&sensor_dev_attr_in1_min.dev_attr.attr,
118362306a36Sopenharmony_ci	&sensor_dev_attr_in1_alarm.dev_attr.attr,
118462306a36Sopenharmony_ci	&sensor_dev_attr_in2_input.dev_attr.attr,
118562306a36Sopenharmony_ci	&sensor_dev_attr_in2_max.dev_attr.attr,
118662306a36Sopenharmony_ci	&sensor_dev_attr_in2_min.dev_attr.attr,
118762306a36Sopenharmony_ci	&sensor_dev_attr_in2_alarm.dev_attr.attr,
118862306a36Sopenharmony_ci	&sensor_dev_attr_temp1_input.dev_attr.attr,
118962306a36Sopenharmony_ci	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
119062306a36Sopenharmony_ci	&sensor_dev_attr_temp1_fault.dev_attr.attr,
119162306a36Sopenharmony_ci	&sensor_dev_attr_temp1_max.dev_attr.attr,
119262306a36Sopenharmony_ci	&sensor_dev_attr_temp1_min.dev_attr.attr,
119362306a36Sopenharmony_ci	&sensor_dev_attr_temp1_offset.dev_attr.attr,
119462306a36Sopenharmony_ci	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
119562306a36Sopenharmony_ci	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
119662306a36Sopenharmony_ci	&sensor_dev_attr_temp1_crit.dev_attr.attr,
119762306a36Sopenharmony_ci	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
119862306a36Sopenharmony_ci	&sensor_dev_attr_temp1_smoothing.dev_attr.attr,
119962306a36Sopenharmony_ci	&sensor_dev_attr_temp2_input.dev_attr.attr,
120062306a36Sopenharmony_ci	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
120162306a36Sopenharmony_ci	&sensor_dev_attr_temp2_max.dev_attr.attr,
120262306a36Sopenharmony_ci	&sensor_dev_attr_temp2_min.dev_attr.attr,
120362306a36Sopenharmony_ci	&sensor_dev_attr_temp2_offset.dev_attr.attr,
120462306a36Sopenharmony_ci	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
120562306a36Sopenharmony_ci	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
120662306a36Sopenharmony_ci	&sensor_dev_attr_temp2_crit.dev_attr.attr,
120762306a36Sopenharmony_ci	&sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
120862306a36Sopenharmony_ci	&sensor_dev_attr_temp2_smoothing.dev_attr.attr,
120962306a36Sopenharmony_ci	&sensor_dev_attr_temp3_input.dev_attr.attr,
121062306a36Sopenharmony_ci	&sensor_dev_attr_temp3_fault.dev_attr.attr,
121162306a36Sopenharmony_ci	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
121262306a36Sopenharmony_ci	&sensor_dev_attr_temp3_max.dev_attr.attr,
121362306a36Sopenharmony_ci	&sensor_dev_attr_temp3_min.dev_attr.attr,
121462306a36Sopenharmony_ci	&sensor_dev_attr_temp3_offset.dev_attr.attr,
121562306a36Sopenharmony_ci	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
121662306a36Sopenharmony_ci	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
121762306a36Sopenharmony_ci	&sensor_dev_attr_temp3_crit.dev_attr.attr,
121862306a36Sopenharmony_ci	&sensor_dev_attr_temp3_crit_hyst.dev_attr.attr,
121962306a36Sopenharmony_ci	&sensor_dev_attr_temp3_smoothing.dev_attr.attr,
122062306a36Sopenharmony_ci	&sensor_dev_attr_fan1_input.dev_attr.attr,
122162306a36Sopenharmony_ci	&sensor_dev_attr_fan1_min.dev_attr.attr,
122262306a36Sopenharmony_ci	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
122362306a36Sopenharmony_ci	&sensor_dev_attr_fan2_input.dev_attr.attr,
122462306a36Sopenharmony_ci	&sensor_dev_attr_fan2_min.dev_attr.attr,
122562306a36Sopenharmony_ci	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
122662306a36Sopenharmony_ci	&sensor_dev_attr_fan3_input.dev_attr.attr,
122762306a36Sopenharmony_ci	&sensor_dev_attr_fan3_min.dev_attr.attr,
122862306a36Sopenharmony_ci	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
122962306a36Sopenharmony_ci	&sensor_dev_attr_pwm1.dev_attr.attr,
123062306a36Sopenharmony_ci	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
123162306a36Sopenharmony_ci	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
123262306a36Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
123362306a36Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
123462306a36Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
123562306a36Sopenharmony_ci	&sensor_dev_attr_pwm1_stall_disable.dev_attr.attr,
123662306a36Sopenharmony_ci	&sensor_dev_attr_pwm3.dev_attr.attr,
123762306a36Sopenharmony_ci	&sensor_dev_attr_pwm3_freq.dev_attr.attr,
123862306a36Sopenharmony_ci	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
123962306a36Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
124062306a36Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
124162306a36Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
124262306a36Sopenharmony_ci	&sensor_dev_attr_pwm3_stall_disable.dev_attr.attr,
124362306a36Sopenharmony_ci	&dev_attr_pwm_use_point2_pwm_at_crit.attr,
124462306a36Sopenharmony_ci	NULL,
124562306a36Sopenharmony_ci};
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_cistatic struct attribute *fan4_attrs[] = {
124862306a36Sopenharmony_ci	&sensor_dev_attr_fan4_input.dev_attr.attr,
124962306a36Sopenharmony_ci	&sensor_dev_attr_fan4_min.dev_attr.attr,
125062306a36Sopenharmony_ci	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
125162306a36Sopenharmony_ci	NULL
125262306a36Sopenharmony_ci};
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_cistatic struct attribute *pwm2_attrs[] = {
125562306a36Sopenharmony_ci	&sensor_dev_attr_pwm2.dev_attr.attr,
125662306a36Sopenharmony_ci	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
125762306a36Sopenharmony_ci	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
125862306a36Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
125962306a36Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
126062306a36Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
126162306a36Sopenharmony_ci	&sensor_dev_attr_pwm2_stall_disable.dev_attr.attr,
126262306a36Sopenharmony_ci	NULL
126362306a36Sopenharmony_ci};
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_cistatic struct attribute *in0_attrs[] = {
126662306a36Sopenharmony_ci	&sensor_dev_attr_in0_input.dev_attr.attr,
126762306a36Sopenharmony_ci	&sensor_dev_attr_in0_max.dev_attr.attr,
126862306a36Sopenharmony_ci	&sensor_dev_attr_in0_min.dev_attr.attr,
126962306a36Sopenharmony_ci	&sensor_dev_attr_in0_alarm.dev_attr.attr,
127062306a36Sopenharmony_ci	NULL
127162306a36Sopenharmony_ci};
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_cistatic struct attribute *in3_attrs[] = {
127462306a36Sopenharmony_ci	&sensor_dev_attr_in3_input.dev_attr.attr,
127562306a36Sopenharmony_ci	&sensor_dev_attr_in3_max.dev_attr.attr,
127662306a36Sopenharmony_ci	&sensor_dev_attr_in3_min.dev_attr.attr,
127762306a36Sopenharmony_ci	&sensor_dev_attr_in3_alarm.dev_attr.attr,
127862306a36Sopenharmony_ci	NULL
127962306a36Sopenharmony_ci};
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_cistatic struct attribute *in4_attrs[] = {
128262306a36Sopenharmony_ci	&sensor_dev_attr_in4_input.dev_attr.attr,
128362306a36Sopenharmony_ci	&sensor_dev_attr_in4_max.dev_attr.attr,
128462306a36Sopenharmony_ci	&sensor_dev_attr_in4_min.dev_attr.attr,
128562306a36Sopenharmony_ci	&sensor_dev_attr_in4_alarm.dev_attr.attr,
128662306a36Sopenharmony_ci	NULL
128762306a36Sopenharmony_ci};
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_cistatic struct attribute *in5_attrs[] = {
129062306a36Sopenharmony_ci	&sensor_dev_attr_in5_input.dev_attr.attr,
129162306a36Sopenharmony_ci	&sensor_dev_attr_in5_max.dev_attr.attr,
129262306a36Sopenharmony_ci	&sensor_dev_attr_in5_min.dev_attr.attr,
129362306a36Sopenharmony_ci	&sensor_dev_attr_in5_alarm.dev_attr.attr,
129462306a36Sopenharmony_ci	NULL
129562306a36Sopenharmony_ci};
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_cistatic struct attribute *vid_attrs[] = {
129862306a36Sopenharmony_ci	&dev_attr_cpu0_vid.attr,
129962306a36Sopenharmony_ci	&dev_attr_vrm.attr,
130062306a36Sopenharmony_ci	NULL
130162306a36Sopenharmony_ci};
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_cistatic const struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs };
130462306a36Sopenharmony_cistatic const struct attribute_group fan4_attr_group = { .attrs = fan4_attrs };
130562306a36Sopenharmony_cistatic const struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs };
130662306a36Sopenharmony_cistatic const struct attribute_group in0_attr_group = { .attrs = in0_attrs };
130762306a36Sopenharmony_cistatic const struct attribute_group in3_attr_group = { .attrs = in3_attrs };
130862306a36Sopenharmony_cistatic const struct attribute_group in4_attr_group = { .attrs = in4_attrs };
130962306a36Sopenharmony_cistatic const struct attribute_group in5_attr_group = { .attrs = in5_attrs };
131062306a36Sopenharmony_cistatic const struct attribute_group vid_attr_group = { .attrs = vid_attrs };
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_cistatic int adt7475_detect(struct i2c_client *client,
131362306a36Sopenharmony_ci			  struct i2c_board_info *info)
131462306a36Sopenharmony_ci{
131562306a36Sopenharmony_ci	struct i2c_adapter *adapter = client->adapter;
131662306a36Sopenharmony_ci	int vendid, devid, devid2;
131762306a36Sopenharmony_ci	const char *name;
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
132062306a36Sopenharmony_ci		return -ENODEV;
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	vendid = adt7475_read(REG_VENDID);
132362306a36Sopenharmony_ci	devid2 = adt7475_read(REG_DEVID2);
132462306a36Sopenharmony_ci	if (vendid != 0x41 ||		/* Analog Devices */
132562306a36Sopenharmony_ci	    (devid2 & 0xf8) != 0x68)
132662306a36Sopenharmony_ci		return -ENODEV;
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	devid = adt7475_read(REG_DEVID);
132962306a36Sopenharmony_ci	if (devid == 0x73)
133062306a36Sopenharmony_ci		name = "adt7473";
133162306a36Sopenharmony_ci	else if (devid == 0x75 && client->addr == 0x2e)
133262306a36Sopenharmony_ci		name = "adt7475";
133362306a36Sopenharmony_ci	else if (devid == 0x76)
133462306a36Sopenharmony_ci		name = "adt7476";
133562306a36Sopenharmony_ci	else if ((devid2 & 0xfc) == 0x6c)
133662306a36Sopenharmony_ci		name = "adt7490";
133762306a36Sopenharmony_ci	else {
133862306a36Sopenharmony_ci		dev_dbg(&adapter->dev,
133962306a36Sopenharmony_ci			"Couldn't detect an ADT7473/75/76/90 part at "
134062306a36Sopenharmony_ci			"0x%02x\n", (unsigned int)client->addr);
134162306a36Sopenharmony_ci		return -ENODEV;
134262306a36Sopenharmony_ci	}
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	strscpy(info->type, name, I2C_NAME_SIZE);
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	return 0;
134762306a36Sopenharmony_ci}
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_cistatic int adt7475_update_limits(struct i2c_client *client)
135062306a36Sopenharmony_ci{
135162306a36Sopenharmony_ci	struct adt7475_data *data = i2c_get_clientdata(client);
135262306a36Sopenharmony_ci	int i;
135362306a36Sopenharmony_ci	int ret;
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	ret = adt7475_read(REG_CONFIG4);
135662306a36Sopenharmony_ci	if (ret < 0)
135762306a36Sopenharmony_ci		return ret;
135862306a36Sopenharmony_ci	data->config4 = ret;
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	ret = adt7475_read(REG_CONFIG5);
136162306a36Sopenharmony_ci	if (ret < 0)
136262306a36Sopenharmony_ci		return ret;
136362306a36Sopenharmony_ci	data->config5 = ret;
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci	for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) {
136662306a36Sopenharmony_ci		if (!(data->has_voltage & (1 << i)))
136762306a36Sopenharmony_ci			continue;
136862306a36Sopenharmony_ci		/* Adjust values so they match the input precision */
136962306a36Sopenharmony_ci		ret = adt7475_read(VOLTAGE_MIN_REG(i));
137062306a36Sopenharmony_ci		if (ret < 0)
137162306a36Sopenharmony_ci			return ret;
137262306a36Sopenharmony_ci		data->voltage[MIN][i] = ret << 2;
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci		ret = adt7475_read(VOLTAGE_MAX_REG(i));
137562306a36Sopenharmony_ci		if (ret < 0)
137662306a36Sopenharmony_ci			return ret;
137762306a36Sopenharmony_ci		data->voltage[MAX][i] = ret << 2;
137862306a36Sopenharmony_ci	}
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	if (data->has_voltage & (1 << 5)) {
138162306a36Sopenharmony_ci		ret = adt7475_read(REG_VTT_MIN);
138262306a36Sopenharmony_ci		if (ret < 0)
138362306a36Sopenharmony_ci			return ret;
138462306a36Sopenharmony_ci		data->voltage[MIN][5] = ret << 2;
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci		ret = adt7475_read(REG_VTT_MAX);
138762306a36Sopenharmony_ci		if (ret < 0)
138862306a36Sopenharmony_ci			return ret;
138962306a36Sopenharmony_ci		data->voltage[MAX][5] = ret << 2;
139062306a36Sopenharmony_ci	}
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	for (i = 0; i < ADT7475_TEMP_COUNT; i++) {
139362306a36Sopenharmony_ci		/* Adjust values so they match the input precision */
139462306a36Sopenharmony_ci		ret = adt7475_read(TEMP_MIN_REG(i));
139562306a36Sopenharmony_ci		if (ret < 0)
139662306a36Sopenharmony_ci			return ret;
139762306a36Sopenharmony_ci		data->temp[MIN][i] = ret << 2;
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ci		ret = adt7475_read(TEMP_MAX_REG(i));
140062306a36Sopenharmony_ci		if (ret < 0)
140162306a36Sopenharmony_ci			return ret;
140262306a36Sopenharmony_ci		data->temp[MAX][i] = ret << 2;
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci		ret = adt7475_read(TEMP_TMIN_REG(i));
140562306a36Sopenharmony_ci		if (ret < 0)
140662306a36Sopenharmony_ci			return ret;
140762306a36Sopenharmony_ci		data->temp[AUTOMIN][i] = ret << 2;
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci		ret = adt7475_read(TEMP_THERM_REG(i));
141062306a36Sopenharmony_ci		if (ret < 0)
141162306a36Sopenharmony_ci			return ret;
141262306a36Sopenharmony_ci		data->temp[THERM][i] = ret << 2;
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci		ret = adt7475_read(TEMP_OFFSET_REG(i));
141562306a36Sopenharmony_ci		if (ret < 0)
141662306a36Sopenharmony_ci			return ret;
141762306a36Sopenharmony_ci		data->temp[OFFSET][i] = ret;
141862306a36Sopenharmony_ci	}
141962306a36Sopenharmony_ci	adt7475_read_hystersis(client);
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	for (i = 0; i < ADT7475_TACH_COUNT; i++) {
142262306a36Sopenharmony_ci		if (i == 3 && !data->has_fan4)
142362306a36Sopenharmony_ci			continue;
142462306a36Sopenharmony_ci		ret = adt7475_read_word(client, TACH_MIN_REG(i));
142562306a36Sopenharmony_ci		if (ret < 0)
142662306a36Sopenharmony_ci			return ret;
142762306a36Sopenharmony_ci		data->tach[MIN][i] = ret;
142862306a36Sopenharmony_ci	}
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci	for (i = 0; i < ADT7475_PWM_COUNT; i++) {
143162306a36Sopenharmony_ci		if (i == 1 && !data->has_pwm2)
143262306a36Sopenharmony_ci			continue;
143362306a36Sopenharmony_ci		ret = adt7475_read(PWM_MAX_REG(i));
143462306a36Sopenharmony_ci		if (ret < 0)
143562306a36Sopenharmony_ci			return ret;
143662306a36Sopenharmony_ci		data->pwm[MAX][i] = ret;
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci		ret = adt7475_read(PWM_MIN_REG(i));
143962306a36Sopenharmony_ci		if (ret < 0)
144062306a36Sopenharmony_ci			return ret;
144162306a36Sopenharmony_ci		data->pwm[MIN][i] = ret;
144262306a36Sopenharmony_ci		/* Set the channel and control information */
144362306a36Sopenharmony_ci		adt7475_read_pwm(client, i);
144462306a36Sopenharmony_ci	}
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	ret = adt7475_read(TEMP_TRANGE_REG(0));
144762306a36Sopenharmony_ci	if (ret < 0)
144862306a36Sopenharmony_ci		return ret;
144962306a36Sopenharmony_ci	data->range[0] = ret;
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci	ret = adt7475_read(TEMP_TRANGE_REG(1));
145262306a36Sopenharmony_ci	if (ret < 0)
145362306a36Sopenharmony_ci		return ret;
145462306a36Sopenharmony_ci	data->range[1] = ret;
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci	ret = adt7475_read(TEMP_TRANGE_REG(2));
145762306a36Sopenharmony_ci	if (ret < 0)
145862306a36Sopenharmony_ci		return ret;
145962306a36Sopenharmony_ci	data->range[2] = ret;
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	return 0;
146262306a36Sopenharmony_ci}
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_cistatic int load_config3(const struct i2c_client *client, const char *propname)
146562306a36Sopenharmony_ci{
146662306a36Sopenharmony_ci	const char *function;
146762306a36Sopenharmony_ci	u8 config3;
146862306a36Sopenharmony_ci	int ret;
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	ret = device_property_read_string(&client->dev, propname, &function);
147162306a36Sopenharmony_ci	if (!ret) {
147262306a36Sopenharmony_ci		ret = adt7475_read(REG_CONFIG3);
147362306a36Sopenharmony_ci		if (ret < 0)
147462306a36Sopenharmony_ci			return ret;
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci		config3 = ret & ~CONFIG3_SMBALERT;
147762306a36Sopenharmony_ci		if (!strcmp("pwm2", function))
147862306a36Sopenharmony_ci			;
147962306a36Sopenharmony_ci		else if (!strcmp("smbalert#", function))
148062306a36Sopenharmony_ci			config3 |= CONFIG3_SMBALERT;
148162306a36Sopenharmony_ci		else
148262306a36Sopenharmony_ci			return -EINVAL;
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci		return i2c_smbus_write_byte_data(client, REG_CONFIG3, config3);
148562306a36Sopenharmony_ci	}
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	return 0;
148862306a36Sopenharmony_ci}
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_cistatic int load_config4(const struct i2c_client *client, const char *propname)
149162306a36Sopenharmony_ci{
149262306a36Sopenharmony_ci	const char *function;
149362306a36Sopenharmony_ci	u8 config4;
149462306a36Sopenharmony_ci	int ret;
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	ret = device_property_read_string(&client->dev, propname, &function);
149762306a36Sopenharmony_ci	if (!ret) {
149862306a36Sopenharmony_ci		ret = adt7475_read(REG_CONFIG4);
149962306a36Sopenharmony_ci		if (ret < 0)
150062306a36Sopenharmony_ci			return ret;
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci		config4 = ret & ~CONFIG4_PINFUNC;
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ci		if (!strcmp("tach4", function))
150562306a36Sopenharmony_ci			;
150662306a36Sopenharmony_ci		else if (!strcmp("therm#", function))
150762306a36Sopenharmony_ci			config4 |= CONFIG4_THERM;
150862306a36Sopenharmony_ci		else if (!strcmp("smbalert#", function))
150962306a36Sopenharmony_ci			config4 |= CONFIG4_SMBALERT;
151062306a36Sopenharmony_ci		else if (!strcmp("gpio", function))
151162306a36Sopenharmony_ci			config4 |= CONFIG4_PINFUNC;
151262306a36Sopenharmony_ci		else
151362306a36Sopenharmony_ci			return -EINVAL;
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci		return i2c_smbus_write_byte_data(client, REG_CONFIG4, config4);
151662306a36Sopenharmony_ci	}
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ci	return 0;
151962306a36Sopenharmony_ci}
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_cistatic int load_config(const struct i2c_client *client, enum chips chip)
152262306a36Sopenharmony_ci{
152362306a36Sopenharmony_ci	int err;
152462306a36Sopenharmony_ci	const char *prop1, *prop2;
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	switch (chip) {
152762306a36Sopenharmony_ci	case adt7473:
152862306a36Sopenharmony_ci	case adt7475:
152962306a36Sopenharmony_ci		prop1 = "adi,pin5-function";
153062306a36Sopenharmony_ci		prop2 = "adi,pin9-function";
153162306a36Sopenharmony_ci		break;
153262306a36Sopenharmony_ci	case adt7476:
153362306a36Sopenharmony_ci	case adt7490:
153462306a36Sopenharmony_ci		prop1 = "adi,pin10-function";
153562306a36Sopenharmony_ci		prop2 = "adi,pin14-function";
153662306a36Sopenharmony_ci		break;
153762306a36Sopenharmony_ci	}
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci	err = load_config3(client, prop1);
154062306a36Sopenharmony_ci	if (err) {
154162306a36Sopenharmony_ci		dev_err(&client->dev, "failed to configure %s\n", prop1);
154262306a36Sopenharmony_ci		return err;
154362306a36Sopenharmony_ci	}
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_ci	err = load_config4(client, prop2);
154662306a36Sopenharmony_ci	if (err) {
154762306a36Sopenharmony_ci		dev_err(&client->dev, "failed to configure %s\n", prop2);
154862306a36Sopenharmony_ci		return err;
154962306a36Sopenharmony_ci	}
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	return 0;
155262306a36Sopenharmony_ci}
155362306a36Sopenharmony_ci
155462306a36Sopenharmony_cistatic int set_property_bit(const struct i2c_client *client, char *property,
155562306a36Sopenharmony_ci			    u8 *config, u8 bit_index)
155662306a36Sopenharmony_ci{
155762306a36Sopenharmony_ci	u32 prop_value = 0;
155862306a36Sopenharmony_ci	int ret = device_property_read_u32(&client->dev, property,
155962306a36Sopenharmony_ci					   &prop_value);
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci	if (!ret) {
156262306a36Sopenharmony_ci		if (prop_value)
156362306a36Sopenharmony_ci			*config |= (1 << bit_index);
156462306a36Sopenharmony_ci		else
156562306a36Sopenharmony_ci			*config &= ~(1 << bit_index);
156662306a36Sopenharmony_ci	}
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_ci	return ret;
156962306a36Sopenharmony_ci}
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_cistatic int load_attenuators(const struct i2c_client *client, enum chips chip,
157262306a36Sopenharmony_ci			    struct adt7475_data *data)
157362306a36Sopenharmony_ci{
157462306a36Sopenharmony_ci	switch (chip) {
157562306a36Sopenharmony_ci	case adt7476:
157662306a36Sopenharmony_ci	case adt7490:
157762306a36Sopenharmony_ci		set_property_bit(client, "adi,bypass-attenuator-in0",
157862306a36Sopenharmony_ci				 &data->config4, 4);
157962306a36Sopenharmony_ci		set_property_bit(client, "adi,bypass-attenuator-in1",
158062306a36Sopenharmony_ci				 &data->config4, 5);
158162306a36Sopenharmony_ci		set_property_bit(client, "adi,bypass-attenuator-in3",
158262306a36Sopenharmony_ci				 &data->config4, 6);
158362306a36Sopenharmony_ci		set_property_bit(client, "adi,bypass-attenuator-in4",
158462306a36Sopenharmony_ci				 &data->config4, 7);
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci		return i2c_smbus_write_byte_data(client, REG_CONFIG4,
158762306a36Sopenharmony_ci						 data->config4);
158862306a36Sopenharmony_ci	case adt7473:
158962306a36Sopenharmony_ci	case adt7475:
159062306a36Sopenharmony_ci		set_property_bit(client, "adi,bypass-attenuator-in1",
159162306a36Sopenharmony_ci				 &data->config2, 5);
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci		return i2c_smbus_write_byte_data(client, REG_CONFIG2,
159462306a36Sopenharmony_ci						 data->config2);
159562306a36Sopenharmony_ci	}
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	return 0;
159862306a36Sopenharmony_ci}
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_cistatic int adt7475_set_pwm_polarity(struct i2c_client *client)
160162306a36Sopenharmony_ci{
160262306a36Sopenharmony_ci	u32 states[ADT7475_PWM_COUNT];
160362306a36Sopenharmony_ci	int ret, i;
160462306a36Sopenharmony_ci	u8 val;
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	ret = device_property_read_u32_array(&client->dev,
160762306a36Sopenharmony_ci					     "adi,pwm-active-state", states,
160862306a36Sopenharmony_ci					     ARRAY_SIZE(states));
160962306a36Sopenharmony_ci	if (ret)
161062306a36Sopenharmony_ci		return ret;
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci	for (i = 0; i < ADT7475_PWM_COUNT; i++) {
161362306a36Sopenharmony_ci		ret = adt7475_read(PWM_CONFIG_REG(i));
161462306a36Sopenharmony_ci		if (ret < 0)
161562306a36Sopenharmony_ci			return ret;
161662306a36Sopenharmony_ci		val = ret;
161762306a36Sopenharmony_ci		if (states[i])
161862306a36Sopenharmony_ci			val &= ~BIT(4);
161962306a36Sopenharmony_ci		else
162062306a36Sopenharmony_ci			val |= BIT(4);
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci		ret = i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(i), val);
162362306a36Sopenharmony_ci		if (ret)
162462306a36Sopenharmony_ci			return ret;
162562306a36Sopenharmony_ci	}
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci	return 0;
162862306a36Sopenharmony_ci}
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_cistatic int adt7475_probe(struct i2c_client *client)
163162306a36Sopenharmony_ci{
163262306a36Sopenharmony_ci	enum chips chip;
163362306a36Sopenharmony_ci	static const char * const names[] = {
163462306a36Sopenharmony_ci		[adt7473] = "ADT7473",
163562306a36Sopenharmony_ci		[adt7475] = "ADT7475",
163662306a36Sopenharmony_ci		[adt7476] = "ADT7476",
163762306a36Sopenharmony_ci		[adt7490] = "ADT7490",
163862306a36Sopenharmony_ci	};
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	struct adt7475_data *data;
164162306a36Sopenharmony_ci	struct device *hwmon_dev;
164262306a36Sopenharmony_ci	int i, ret = 0, revision, group_num = 0;
164362306a36Sopenharmony_ci	u8 config3;
164462306a36Sopenharmony_ci	const struct i2c_device_id *id = i2c_match_id(adt7475_id, client);
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
164762306a36Sopenharmony_ci	if (data == NULL)
164862306a36Sopenharmony_ci		return -ENOMEM;
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci	mutex_init(&data->lock);
165162306a36Sopenharmony_ci	data->client = client;
165262306a36Sopenharmony_ci	i2c_set_clientdata(client, data);
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	if (client->dev.of_node)
165562306a36Sopenharmony_ci		chip = (uintptr_t)of_device_get_match_data(&client->dev);
165662306a36Sopenharmony_ci	else
165762306a36Sopenharmony_ci		chip = id->driver_data;
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_ci	/* Initialize device-specific values */
166062306a36Sopenharmony_ci	switch (chip) {
166162306a36Sopenharmony_ci	case adt7476:
166262306a36Sopenharmony_ci		data->has_voltage = 0x0e;	/* in1 to in3 */
166362306a36Sopenharmony_ci		revision = adt7475_read(REG_DEVID2) & 0x07;
166462306a36Sopenharmony_ci		break;
166562306a36Sopenharmony_ci	case adt7490:
166662306a36Sopenharmony_ci		data->has_voltage = 0x3e;	/* in1 to in5 */
166762306a36Sopenharmony_ci		revision = adt7475_read(REG_DEVID2) & 0x03;
166862306a36Sopenharmony_ci		if (revision == 0x03)
166962306a36Sopenharmony_ci			revision += adt7475_read(REG_DEVREV2);
167062306a36Sopenharmony_ci		break;
167162306a36Sopenharmony_ci	default:
167262306a36Sopenharmony_ci		data->has_voltage = 0x06;	/* in1, in2 */
167362306a36Sopenharmony_ci		revision = adt7475_read(REG_DEVID2) & 0x07;
167462306a36Sopenharmony_ci	}
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci	ret = load_config(client, chip);
167762306a36Sopenharmony_ci	if (ret)
167862306a36Sopenharmony_ci		return ret;
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_ci	config3 = adt7475_read(REG_CONFIG3);
168162306a36Sopenharmony_ci	/* Pin PWM2 may alternatively be used for ALERT output */
168262306a36Sopenharmony_ci	if (!(config3 & CONFIG3_SMBALERT))
168362306a36Sopenharmony_ci		data->has_pwm2 = 1;
168462306a36Sopenharmony_ci	/* Meaning of this bit is inverted for the ADT7473-1 */
168562306a36Sopenharmony_ci	if (id->driver_data == adt7473 && revision >= 1)
168662306a36Sopenharmony_ci		data->has_pwm2 = !data->has_pwm2;
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	data->config4 = adt7475_read(REG_CONFIG4);
168962306a36Sopenharmony_ci	/* Pin TACH4 may alternatively be used for THERM */
169062306a36Sopenharmony_ci	if ((data->config4 & CONFIG4_PINFUNC) == 0x0)
169162306a36Sopenharmony_ci		data->has_fan4 = 1;
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_ci	/*
169462306a36Sopenharmony_ci	 * THERM configuration is more complex on the ADT7476 and ADT7490,
169562306a36Sopenharmony_ci	 * because 2 different pins (TACH4 and +2.5 Vin) can be used for
169662306a36Sopenharmony_ci	 * this function
169762306a36Sopenharmony_ci	 */
169862306a36Sopenharmony_ci	if (id->driver_data == adt7490) {
169962306a36Sopenharmony_ci		if ((data->config4 & CONFIG4_PINFUNC) == 0x1 &&
170062306a36Sopenharmony_ci		    !(config3 & CONFIG3_THERM))
170162306a36Sopenharmony_ci			data->has_fan4 = 1;
170262306a36Sopenharmony_ci	}
170362306a36Sopenharmony_ci	if (id->driver_data == adt7476 || id->driver_data == adt7490) {
170462306a36Sopenharmony_ci		if (!(config3 & CONFIG3_THERM) ||
170562306a36Sopenharmony_ci		    (data->config4 & CONFIG4_PINFUNC) == 0x1)
170662306a36Sopenharmony_ci			data->has_voltage |= (1 << 0);		/* in0 */
170762306a36Sopenharmony_ci	}
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	/*
171062306a36Sopenharmony_ci	 * On the ADT7476, the +12V input pin may instead be used as VID5,
171162306a36Sopenharmony_ci	 * and VID pins may alternatively be used as GPIO
171262306a36Sopenharmony_ci	 */
171362306a36Sopenharmony_ci	if (id->driver_data == adt7476) {
171462306a36Sopenharmony_ci		u8 vid = adt7475_read(REG_VID);
171562306a36Sopenharmony_ci		if (!(vid & VID_VIDSEL))
171662306a36Sopenharmony_ci			data->has_voltage |= (1 << 4);		/* in4 */
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci		data->has_vid = !(adt7475_read(REG_CONFIG5) & CONFIG5_VIDGPIO);
171962306a36Sopenharmony_ci	}
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	/* Voltage attenuators can be bypassed, globally or individually */
172262306a36Sopenharmony_ci	data->config2 = adt7475_read(REG_CONFIG2);
172362306a36Sopenharmony_ci	ret = load_attenuators(client, chip, data);
172462306a36Sopenharmony_ci	if (ret)
172562306a36Sopenharmony_ci		dev_warn(&client->dev, "Error configuring attenuator bypass\n");
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	if (data->config2 & CONFIG2_ATTN) {
172862306a36Sopenharmony_ci		data->bypass_attn = (0x3 << 3) | 0x3;
172962306a36Sopenharmony_ci	} else {
173062306a36Sopenharmony_ci		data->bypass_attn = ((data->config4 & CONFIG4_ATTN_IN10) >> 4) |
173162306a36Sopenharmony_ci				    ((data->config4 & CONFIG4_ATTN_IN43) >> 3);
173262306a36Sopenharmony_ci	}
173362306a36Sopenharmony_ci	data->bypass_attn &= data->has_voltage;
173462306a36Sopenharmony_ci
173562306a36Sopenharmony_ci	/*
173662306a36Sopenharmony_ci	 * Call adt7475_read_pwm for all pwm's as this will reprogram any
173762306a36Sopenharmony_ci	 * pwm's which are disabled to manual mode with 0% duty cycle
173862306a36Sopenharmony_ci	 */
173962306a36Sopenharmony_ci	for (i = 0; i < ADT7475_PWM_COUNT; i++)
174062306a36Sopenharmony_ci		adt7475_read_pwm(client, i);
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci	ret = adt7475_set_pwm_polarity(client);
174362306a36Sopenharmony_ci	if (ret && ret != -EINVAL)
174462306a36Sopenharmony_ci		dev_warn(&client->dev, "Error configuring pwm polarity\n");
174562306a36Sopenharmony_ci
174662306a36Sopenharmony_ci	/* Start monitoring */
174762306a36Sopenharmony_ci	switch (chip) {
174862306a36Sopenharmony_ci	case adt7475:
174962306a36Sopenharmony_ci	case adt7476:
175062306a36Sopenharmony_ci		i2c_smbus_write_byte_data(client, REG_CONFIG1,
175162306a36Sopenharmony_ci					  adt7475_read(REG_CONFIG1) | 0x01);
175262306a36Sopenharmony_ci		break;
175362306a36Sopenharmony_ci	default:
175462306a36Sopenharmony_ci		break;
175562306a36Sopenharmony_ci	}
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci	data->groups[group_num++] = &adt7475_attr_group;
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci	/* Features that can be disabled individually */
176062306a36Sopenharmony_ci	if (data->has_fan4) {
176162306a36Sopenharmony_ci		data->groups[group_num++] = &fan4_attr_group;
176262306a36Sopenharmony_ci	}
176362306a36Sopenharmony_ci	if (data->has_pwm2) {
176462306a36Sopenharmony_ci		data->groups[group_num++] = &pwm2_attr_group;
176562306a36Sopenharmony_ci	}
176662306a36Sopenharmony_ci	if (data->has_voltage & (1 << 0)) {
176762306a36Sopenharmony_ci		data->groups[group_num++] = &in0_attr_group;
176862306a36Sopenharmony_ci	}
176962306a36Sopenharmony_ci	if (data->has_voltage & (1 << 3)) {
177062306a36Sopenharmony_ci		data->groups[group_num++] = &in3_attr_group;
177162306a36Sopenharmony_ci	}
177262306a36Sopenharmony_ci	if (data->has_voltage & (1 << 4)) {
177362306a36Sopenharmony_ci		data->groups[group_num++] = &in4_attr_group;
177462306a36Sopenharmony_ci	}
177562306a36Sopenharmony_ci	if (data->has_voltage & (1 << 5)) {
177662306a36Sopenharmony_ci		data->groups[group_num++] = &in5_attr_group;
177762306a36Sopenharmony_ci	}
177862306a36Sopenharmony_ci	if (data->has_vid) {
177962306a36Sopenharmony_ci		data->vrm = vid_which_vrm();
178062306a36Sopenharmony_ci		data->groups[group_num] = &vid_attr_group;
178162306a36Sopenharmony_ci	}
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci	/* register device with all the acquired attributes */
178462306a36Sopenharmony_ci	hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
178562306a36Sopenharmony_ci							   client->name, data,
178662306a36Sopenharmony_ci							   data->groups);
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	if (IS_ERR(hwmon_dev)) {
178962306a36Sopenharmony_ci		ret = PTR_ERR(hwmon_dev);
179062306a36Sopenharmony_ci		return ret;
179162306a36Sopenharmony_ci	}
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci	dev_info(&client->dev, "%s device, revision %d\n",
179462306a36Sopenharmony_ci		 names[id->driver_data], revision);
179562306a36Sopenharmony_ci	if ((data->has_voltage & 0x11) || data->has_fan4 || data->has_pwm2)
179662306a36Sopenharmony_ci		dev_info(&client->dev, "Optional features:%s%s%s%s%s\n",
179762306a36Sopenharmony_ci			 (data->has_voltage & (1 << 0)) ? " in0" : "",
179862306a36Sopenharmony_ci			 (data->has_voltage & (1 << 4)) ? " in4" : "",
179962306a36Sopenharmony_ci			 data->has_fan4 ? " fan4" : "",
180062306a36Sopenharmony_ci			 data->has_pwm2 ? " pwm2" : "",
180162306a36Sopenharmony_ci			 data->has_vid ? " vid" : "");
180262306a36Sopenharmony_ci	if (data->bypass_attn)
180362306a36Sopenharmony_ci		dev_info(&client->dev, "Bypassing attenuators on:%s%s%s%s\n",
180462306a36Sopenharmony_ci			 (data->bypass_attn & (1 << 0)) ? " in0" : "",
180562306a36Sopenharmony_ci			 (data->bypass_attn & (1 << 1)) ? " in1" : "",
180662306a36Sopenharmony_ci			 (data->bypass_attn & (1 << 3)) ? " in3" : "",
180762306a36Sopenharmony_ci			 (data->bypass_attn & (1 << 4)) ? " in4" : "");
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_ci	/* Limits and settings, should never change update more than once */
181062306a36Sopenharmony_ci	ret = adt7475_update_limits(client);
181162306a36Sopenharmony_ci	if (ret)
181262306a36Sopenharmony_ci		return ret;
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	return 0;
181562306a36Sopenharmony_ci}
181662306a36Sopenharmony_ci
181762306a36Sopenharmony_cistatic struct i2c_driver adt7475_driver = {
181862306a36Sopenharmony_ci	.class		= I2C_CLASS_HWMON,
181962306a36Sopenharmony_ci	.driver = {
182062306a36Sopenharmony_ci		.name	= "adt7475",
182162306a36Sopenharmony_ci		.of_match_table = of_match_ptr(adt7475_of_match),
182262306a36Sopenharmony_ci	},
182362306a36Sopenharmony_ci	.probe		= adt7475_probe,
182462306a36Sopenharmony_ci	.id_table	= adt7475_id,
182562306a36Sopenharmony_ci	.detect		= adt7475_detect,
182662306a36Sopenharmony_ci	.address_list	= normal_i2c,
182762306a36Sopenharmony_ci};
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_cistatic void adt7475_read_hystersis(struct i2c_client *client)
183062306a36Sopenharmony_ci{
183162306a36Sopenharmony_ci	struct adt7475_data *data = i2c_get_clientdata(client);
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ci	data->temp[HYSTERSIS][0] = (u16) adt7475_read(REG_REMOTE1_HYSTERSIS);
183462306a36Sopenharmony_ci	data->temp[HYSTERSIS][1] = data->temp[HYSTERSIS][0];
183562306a36Sopenharmony_ci	data->temp[HYSTERSIS][2] = (u16) adt7475_read(REG_REMOTE2_HYSTERSIS);
183662306a36Sopenharmony_ci}
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_cistatic void adt7475_read_pwm(struct i2c_client *client, int index)
183962306a36Sopenharmony_ci{
184062306a36Sopenharmony_ci	struct adt7475_data *data = i2c_get_clientdata(client);
184162306a36Sopenharmony_ci	unsigned int v;
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_ci	data->pwm[CONTROL][index] = adt7475_read(PWM_CONFIG_REG(index));
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci	/*
184662306a36Sopenharmony_ci	 * Figure out the internal value for pwmctrl and pwmchan
184762306a36Sopenharmony_ci	 * based on the current settings
184862306a36Sopenharmony_ci	 */
184962306a36Sopenharmony_ci	v = (data->pwm[CONTROL][index] >> 5) & 7;
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_ci	if (v == 3)
185262306a36Sopenharmony_ci		data->pwmctl[index] = 0;
185362306a36Sopenharmony_ci	else if (v == 7)
185462306a36Sopenharmony_ci		data->pwmctl[index] = 1;
185562306a36Sopenharmony_ci	else if (v == 4) {
185662306a36Sopenharmony_ci		/*
185762306a36Sopenharmony_ci		 * The fan is disabled - we don't want to
185862306a36Sopenharmony_ci		 * support that, so change to manual mode and
185962306a36Sopenharmony_ci		 * set the duty cycle to 0 instead
186062306a36Sopenharmony_ci		 */
186162306a36Sopenharmony_ci		data->pwm[INPUT][index] = 0;
186262306a36Sopenharmony_ci		data->pwm[CONTROL][index] &= ~0xE0;
186362306a36Sopenharmony_ci		data->pwm[CONTROL][index] |= (7 << 5);
186462306a36Sopenharmony_ci
186562306a36Sopenharmony_ci		i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
186662306a36Sopenharmony_ci					  data->pwm[INPUT][index]);
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci		i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
186962306a36Sopenharmony_ci					  data->pwm[CONTROL][index]);
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci		data->pwmctl[index] = 1;
187262306a36Sopenharmony_ci	} else {
187362306a36Sopenharmony_ci		data->pwmctl[index] = 2;
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci		switch (v) {
187662306a36Sopenharmony_ci		case 0:
187762306a36Sopenharmony_ci			data->pwmchan[index] = 1;
187862306a36Sopenharmony_ci			break;
187962306a36Sopenharmony_ci		case 1:
188062306a36Sopenharmony_ci			data->pwmchan[index] = 2;
188162306a36Sopenharmony_ci			break;
188262306a36Sopenharmony_ci		case 2:
188362306a36Sopenharmony_ci			data->pwmchan[index] = 4;
188462306a36Sopenharmony_ci			break;
188562306a36Sopenharmony_ci		case 5:
188662306a36Sopenharmony_ci			data->pwmchan[index] = 6;
188762306a36Sopenharmony_ci			break;
188862306a36Sopenharmony_ci		case 6:
188962306a36Sopenharmony_ci			data->pwmchan[index] = 7;
189062306a36Sopenharmony_ci			break;
189162306a36Sopenharmony_ci		}
189262306a36Sopenharmony_ci	}
189362306a36Sopenharmony_ci}
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_cistatic int adt7475_update_measure(struct device *dev)
189662306a36Sopenharmony_ci{
189762306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
189862306a36Sopenharmony_ci	struct i2c_client *client = data->client;
189962306a36Sopenharmony_ci	u16 ext;
190062306a36Sopenharmony_ci	int i;
190162306a36Sopenharmony_ci	int ret;
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	ret = adt7475_read(REG_STATUS2);
190462306a36Sopenharmony_ci	if (ret < 0)
190562306a36Sopenharmony_ci		return ret;
190662306a36Sopenharmony_ci	data->alarms = ret << 8;
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_ci	ret = adt7475_read(REG_STATUS1);
190962306a36Sopenharmony_ci	if (ret < 0)
191062306a36Sopenharmony_ci		return ret;
191162306a36Sopenharmony_ci	data->alarms |= ret;
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	ret = adt7475_read(REG_EXTEND2);
191462306a36Sopenharmony_ci	if (ret < 0)
191562306a36Sopenharmony_ci		return ret;
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci	ext = (ret << 8);
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci	ret = adt7475_read(REG_EXTEND1);
192062306a36Sopenharmony_ci	if (ret < 0)
192162306a36Sopenharmony_ci		return ret;
192262306a36Sopenharmony_ci
192362306a36Sopenharmony_ci	ext |= ret;
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_ci	for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) {
192662306a36Sopenharmony_ci		if (!(data->has_voltage & (1 << i)))
192762306a36Sopenharmony_ci			continue;
192862306a36Sopenharmony_ci		ret = adt7475_read(VOLTAGE_REG(i));
192962306a36Sopenharmony_ci		if (ret < 0)
193062306a36Sopenharmony_ci			return ret;
193162306a36Sopenharmony_ci		data->voltage[INPUT][i] =
193262306a36Sopenharmony_ci			(ret << 2) |
193362306a36Sopenharmony_ci			((ext >> (i * 2)) & 3);
193462306a36Sopenharmony_ci	}
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	for (i = 0; i < ADT7475_TEMP_COUNT; i++) {
193762306a36Sopenharmony_ci		ret = adt7475_read(TEMP_REG(i));
193862306a36Sopenharmony_ci		if (ret < 0)
193962306a36Sopenharmony_ci			return ret;
194062306a36Sopenharmony_ci		data->temp[INPUT][i] =
194162306a36Sopenharmony_ci			(ret << 2) |
194262306a36Sopenharmony_ci			((ext >> ((i + 5) * 2)) & 3);
194362306a36Sopenharmony_ci	}
194462306a36Sopenharmony_ci
194562306a36Sopenharmony_ci	if (data->has_voltage & (1 << 5)) {
194662306a36Sopenharmony_ci		ret = adt7475_read(REG_STATUS4);
194762306a36Sopenharmony_ci		if (ret < 0)
194862306a36Sopenharmony_ci			return ret;
194962306a36Sopenharmony_ci		data->alarms |= ret << 24;
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_ci		ret = adt7475_read(REG_EXTEND3);
195262306a36Sopenharmony_ci		if (ret < 0)
195362306a36Sopenharmony_ci			return ret;
195462306a36Sopenharmony_ci		ext = ret;
195562306a36Sopenharmony_ci
195662306a36Sopenharmony_ci		ret = adt7475_read(REG_VTT);
195762306a36Sopenharmony_ci		if (ret < 0)
195862306a36Sopenharmony_ci			return ret;
195962306a36Sopenharmony_ci		data->voltage[INPUT][5] = ret << 2 |
196062306a36Sopenharmony_ci			((ext >> 4) & 3);
196162306a36Sopenharmony_ci	}
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci	for (i = 0; i < ADT7475_TACH_COUNT; i++) {
196462306a36Sopenharmony_ci		if (i == 3 && !data->has_fan4)
196562306a36Sopenharmony_ci			continue;
196662306a36Sopenharmony_ci		ret = adt7475_read_word(client, TACH_REG(i));
196762306a36Sopenharmony_ci		if (ret < 0)
196862306a36Sopenharmony_ci			return ret;
196962306a36Sopenharmony_ci		data->tach[INPUT][i] = ret;
197062306a36Sopenharmony_ci	}
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	/* Updated by hw when in auto mode */
197362306a36Sopenharmony_ci	for (i = 0; i < ADT7475_PWM_COUNT; i++) {
197462306a36Sopenharmony_ci		if (i == 1 && !data->has_pwm2)
197562306a36Sopenharmony_ci			continue;
197662306a36Sopenharmony_ci		ret = adt7475_read(PWM_REG(i));
197762306a36Sopenharmony_ci		if (ret < 0)
197862306a36Sopenharmony_ci			return ret;
197962306a36Sopenharmony_ci		data->pwm[INPUT][i] = ret;
198062306a36Sopenharmony_ci	}
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci	if (data->has_vid) {
198362306a36Sopenharmony_ci		ret = adt7475_read(REG_VID);
198462306a36Sopenharmony_ci		if (ret < 0)
198562306a36Sopenharmony_ci			return ret;
198662306a36Sopenharmony_ci		data->vid = ret & 0x3f;
198762306a36Sopenharmony_ci	}
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci	return 0;
199062306a36Sopenharmony_ci}
199162306a36Sopenharmony_ci
199262306a36Sopenharmony_cistatic struct adt7475_data *adt7475_update_device(struct device *dev)
199362306a36Sopenharmony_ci{
199462306a36Sopenharmony_ci	struct adt7475_data *data = dev_get_drvdata(dev);
199562306a36Sopenharmony_ci	int ret;
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_ci	mutex_lock(&data->lock);
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci	/* Measurement values update every 2 seconds */
200062306a36Sopenharmony_ci	if (time_after(jiffies, data->measure_updated + HZ * 2) ||
200162306a36Sopenharmony_ci	    !data->valid) {
200262306a36Sopenharmony_ci		ret = adt7475_update_measure(dev);
200362306a36Sopenharmony_ci		if (ret) {
200462306a36Sopenharmony_ci			data->valid = false;
200562306a36Sopenharmony_ci			mutex_unlock(&data->lock);
200662306a36Sopenharmony_ci			return ERR_PTR(ret);
200762306a36Sopenharmony_ci		}
200862306a36Sopenharmony_ci		data->measure_updated = jiffies;
200962306a36Sopenharmony_ci		data->valid = true;
201062306a36Sopenharmony_ci	}
201162306a36Sopenharmony_ci
201262306a36Sopenharmony_ci	mutex_unlock(&data->lock);
201362306a36Sopenharmony_ci
201462306a36Sopenharmony_ci	return data;
201562306a36Sopenharmony_ci}
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_cimodule_i2c_driver(adt7475_driver);
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ciMODULE_AUTHOR("Advanced Micro Devices, Inc");
202062306a36Sopenharmony_ciMODULE_DESCRIPTION("adt7475 driver");
202162306a36Sopenharmony_ciMODULE_LICENSE("GPL");
2022