18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * f71805f.c - driver for the Fintek F71805F/FG and F71872F/FG Super-I/O
48c2ecf20Sopenharmony_ci *             chips integrated hardware monitoring features
58c2ecf20Sopenharmony_ci * Copyright (C) 2005-2006  Jean Delvare <jdelvare@suse.de>
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
88c2ecf20Sopenharmony_ci * complete hardware monitoring features: voltage, fan and temperature
98c2ecf20Sopenharmony_ci * sensors, and manual and automatic fan speed control.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * The F71872F/FG is almost the same, with two more voltages monitored,
128c2ecf20Sopenharmony_ci * and 6 VID inputs.
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci * The F71806F/FG is essentially the same as the F71872F/FG. It even has
158c2ecf20Sopenharmony_ci * the same chip ID, so the driver can't differentiate between.
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <linux/module.h>
218c2ecf20Sopenharmony_ci#include <linux/init.h>
228c2ecf20Sopenharmony_ci#include <linux/slab.h>
238c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
248c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
258c2ecf20Sopenharmony_ci#include <linux/hwmon.h>
268c2ecf20Sopenharmony_ci#include <linux/hwmon-sysfs.h>
278c2ecf20Sopenharmony_ci#include <linux/err.h>
288c2ecf20Sopenharmony_ci#include <linux/mutex.h>
298c2ecf20Sopenharmony_ci#include <linux/sysfs.h>
308c2ecf20Sopenharmony_ci#include <linux/ioport.h>
318c2ecf20Sopenharmony_ci#include <linux/acpi.h>
328c2ecf20Sopenharmony_ci#include <linux/io.h>
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic unsigned short force_id;
358c2ecf20Sopenharmony_cimodule_param(force_id, ushort, 0);
368c2ecf20Sopenharmony_ciMODULE_PARM_DESC(force_id, "Override the detected device ID");
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic struct platform_device *pdev;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#define DRVNAME "f71805f"
418c2ecf20Sopenharmony_cienum kinds { f71805f, f71872f };
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/*
448c2ecf20Sopenharmony_ci * Super-I/O constants and functions
458c2ecf20Sopenharmony_ci */
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define F71805F_LD_HWM		0x04
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define SIO_REG_LDSEL		0x07	/* Logical device select */
508c2ecf20Sopenharmony_ci#define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
518c2ecf20Sopenharmony_ci#define SIO_REG_DEVREV		0x22	/* Device revision */
528c2ecf20Sopenharmony_ci#define SIO_REG_MANID		0x23	/* Fintek ID (2 bytes) */
538c2ecf20Sopenharmony_ci#define SIO_REG_FNSEL1		0x29	/* Multi Function Select 1 (F71872F) */
548c2ecf20Sopenharmony_ci#define SIO_REG_ENABLE		0x30	/* Logical device enable */
558c2ecf20Sopenharmony_ci#define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define SIO_FINTEK_ID		0x1934
588c2ecf20Sopenharmony_ci#define SIO_F71805F_ID		0x0406
598c2ecf20Sopenharmony_ci#define SIO_F71872F_ID		0x0341
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic inline int
628c2ecf20Sopenharmony_cisuperio_inb(int base, int reg)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	outb(reg, base);
658c2ecf20Sopenharmony_ci	return inb(base + 1);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic int
698c2ecf20Sopenharmony_cisuperio_inw(int base, int reg)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	int val;
728c2ecf20Sopenharmony_ci	outb(reg++, base);
738c2ecf20Sopenharmony_ci	val = inb(base + 1) << 8;
748c2ecf20Sopenharmony_ci	outb(reg, base);
758c2ecf20Sopenharmony_ci	val |= inb(base + 1);
768c2ecf20Sopenharmony_ci	return val;
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic inline void
808c2ecf20Sopenharmony_cisuperio_select(int base, int ld)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	outb(SIO_REG_LDSEL, base);
838c2ecf20Sopenharmony_ci	outb(ld, base + 1);
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic inline int
878c2ecf20Sopenharmony_cisuperio_enter(int base)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	if (!request_muxed_region(base, 2, DRVNAME))
908c2ecf20Sopenharmony_ci		return -EBUSY;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	outb(0x87, base);
938c2ecf20Sopenharmony_ci	outb(0x87, base);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	return 0;
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic inline void
998c2ecf20Sopenharmony_cisuperio_exit(int base)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	outb(0xaa, base);
1028c2ecf20Sopenharmony_ci	release_region(base, 2);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/*
1068c2ecf20Sopenharmony_ci * ISA constants
1078c2ecf20Sopenharmony_ci */
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci#define REGION_LENGTH		8
1108c2ecf20Sopenharmony_ci#define ADDR_REG_OFFSET		5
1118c2ecf20Sopenharmony_ci#define DATA_REG_OFFSET		6
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci/*
1148c2ecf20Sopenharmony_ci * Registers
1158c2ecf20Sopenharmony_ci */
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci/* in nr from 0 to 10 (8-bit values) */
1188c2ecf20Sopenharmony_ci#define F71805F_REG_IN(nr)		(0x10 + (nr))
1198c2ecf20Sopenharmony_ci#define F71805F_REG_IN_HIGH(nr)		((nr) < 10 ? 0x40 + 2 * (nr) : 0x2E)
1208c2ecf20Sopenharmony_ci#define F71805F_REG_IN_LOW(nr)		((nr) < 10 ? 0x41 + 2 * (nr) : 0x2F)
1218c2ecf20Sopenharmony_ci/* fan nr from 0 to 2 (12-bit values, two registers) */
1228c2ecf20Sopenharmony_ci#define F71805F_REG_FAN(nr)		(0x20 + 2 * (nr))
1238c2ecf20Sopenharmony_ci#define F71805F_REG_FAN_LOW(nr)		(0x28 + 2 * (nr))
1248c2ecf20Sopenharmony_ci#define F71805F_REG_FAN_TARGET(nr)	(0x69 + 16 * (nr))
1258c2ecf20Sopenharmony_ci#define F71805F_REG_FAN_CTRL(nr)	(0x60 + 16 * (nr))
1268c2ecf20Sopenharmony_ci#define F71805F_REG_PWM_FREQ(nr)	(0x63 + 16 * (nr))
1278c2ecf20Sopenharmony_ci#define F71805F_REG_PWM_DUTY(nr)	(0x6B + 16 * (nr))
1288c2ecf20Sopenharmony_ci/* temp nr from 0 to 2 (8-bit values) */
1298c2ecf20Sopenharmony_ci#define F71805F_REG_TEMP(nr)		(0x1B + (nr))
1308c2ecf20Sopenharmony_ci#define F71805F_REG_TEMP_HIGH(nr)	(0x54 + 2 * (nr))
1318c2ecf20Sopenharmony_ci#define F71805F_REG_TEMP_HYST(nr)	(0x55 + 2 * (nr))
1328c2ecf20Sopenharmony_ci#define F71805F_REG_TEMP_MODE		0x01
1338c2ecf20Sopenharmony_ci/* pwm/fan pwmnr from 0 to 2, auto point apnr from 0 to 2 */
1348c2ecf20Sopenharmony_ci/* map Fintek numbers to our numbers as follows: 9->0, 5->1, 1->2 */
1358c2ecf20Sopenharmony_ci#define F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr) \
1368c2ecf20Sopenharmony_ci					(0xA0 + 0x10 * (pwmnr) + (2 - (apnr)))
1378c2ecf20Sopenharmony_ci#define F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr) \
1388c2ecf20Sopenharmony_ci					(0xA4 + 0x10 * (pwmnr) + \
1398c2ecf20Sopenharmony_ci						2 * (2 - (apnr)))
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci#define F71805F_REG_START		0x00
1428c2ecf20Sopenharmony_ci/* status nr from 0 to 2 */
1438c2ecf20Sopenharmony_ci#define F71805F_REG_STATUS(nr)		(0x36 + (nr))
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci/* individual register bits */
1468c2ecf20Sopenharmony_ci#define FAN_CTRL_DC_MODE		0x10
1478c2ecf20Sopenharmony_ci#define FAN_CTRL_LATCH_FULL		0x08
1488c2ecf20Sopenharmony_ci#define FAN_CTRL_MODE_MASK		0x03
1498c2ecf20Sopenharmony_ci#define FAN_CTRL_MODE_SPEED		0x00
1508c2ecf20Sopenharmony_ci#define FAN_CTRL_MODE_TEMPERATURE	0x01
1518c2ecf20Sopenharmony_ci#define FAN_CTRL_MODE_MANUAL		0x02
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci/*
1548c2ecf20Sopenharmony_ci * Data structures and manipulation thereof
1558c2ecf20Sopenharmony_ci */
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistruct f71805f_auto_point {
1588c2ecf20Sopenharmony_ci	u8 temp[3];
1598c2ecf20Sopenharmony_ci	u16 fan[3];
1608c2ecf20Sopenharmony_ci};
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistruct f71805f_data {
1638c2ecf20Sopenharmony_ci	unsigned short addr;
1648c2ecf20Sopenharmony_ci	const char *name;
1658c2ecf20Sopenharmony_ci	struct device *hwmon_dev;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	struct mutex update_lock;
1688c2ecf20Sopenharmony_ci	char valid;		/* !=0 if following fields are valid */
1698c2ecf20Sopenharmony_ci	unsigned long last_updated;	/* In jiffies */
1708c2ecf20Sopenharmony_ci	unsigned long last_limits;	/* In jiffies */
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	/* Register values */
1738c2ecf20Sopenharmony_ci	u8 in[11];
1748c2ecf20Sopenharmony_ci	u8 in_high[11];
1758c2ecf20Sopenharmony_ci	u8 in_low[11];
1768c2ecf20Sopenharmony_ci	u16 has_in;
1778c2ecf20Sopenharmony_ci	u16 fan[3];
1788c2ecf20Sopenharmony_ci	u16 fan_low[3];
1798c2ecf20Sopenharmony_ci	u16 fan_target[3];
1808c2ecf20Sopenharmony_ci	u8 fan_ctrl[3];
1818c2ecf20Sopenharmony_ci	u8 pwm[3];
1828c2ecf20Sopenharmony_ci	u8 pwm_freq[3];
1838c2ecf20Sopenharmony_ci	u8 temp[3];
1848c2ecf20Sopenharmony_ci	u8 temp_high[3];
1858c2ecf20Sopenharmony_ci	u8 temp_hyst[3];
1868c2ecf20Sopenharmony_ci	u8 temp_mode;
1878c2ecf20Sopenharmony_ci	unsigned long alarms;
1888c2ecf20Sopenharmony_ci	struct f71805f_auto_point auto_points[3];
1898c2ecf20Sopenharmony_ci};
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistruct f71805f_sio_data {
1928c2ecf20Sopenharmony_ci	enum kinds kind;
1938c2ecf20Sopenharmony_ci	u8 fnsel1;
1948c2ecf20Sopenharmony_ci};
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic inline long in_from_reg(u8 reg)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	return reg * 8;
1998c2ecf20Sopenharmony_ci}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci/* The 2 least significant bits are not used */
2028c2ecf20Sopenharmony_cistatic inline u8 in_to_reg(long val)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	if (val <= 0)
2058c2ecf20Sopenharmony_ci		return 0;
2068c2ecf20Sopenharmony_ci	if (val >= 2016)
2078c2ecf20Sopenharmony_ci		return 0xfc;
2088c2ecf20Sopenharmony_ci	return ((val + 16) / 32) << 2;
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci/* in0 is downscaled by a factor 2 internally */
2128c2ecf20Sopenharmony_cistatic inline long in0_from_reg(u8 reg)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	return reg * 16;
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic inline u8 in0_to_reg(long val)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	if (val <= 0)
2208c2ecf20Sopenharmony_ci		return 0;
2218c2ecf20Sopenharmony_ci	if (val >= 4032)
2228c2ecf20Sopenharmony_ci		return 0xfc;
2238c2ecf20Sopenharmony_ci	return ((val + 32) / 64) << 2;
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci/* The 4 most significant bits are not used */
2278c2ecf20Sopenharmony_cistatic inline long fan_from_reg(u16 reg)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	reg &= 0xfff;
2308c2ecf20Sopenharmony_ci	if (!reg || reg == 0xfff)
2318c2ecf20Sopenharmony_ci		return 0;
2328c2ecf20Sopenharmony_ci	return 1500000 / reg;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic inline u16 fan_to_reg(long rpm)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	/*
2388c2ecf20Sopenharmony_ci	 * If the low limit is set below what the chip can measure,
2398c2ecf20Sopenharmony_ci	 * store the largest possible 12-bit value in the registers,
2408c2ecf20Sopenharmony_ci	 * so that no alarm will ever trigger.
2418c2ecf20Sopenharmony_ci	 */
2428c2ecf20Sopenharmony_ci	if (rpm < 367)
2438c2ecf20Sopenharmony_ci		return 0xfff;
2448c2ecf20Sopenharmony_ci	return 1500000 / rpm;
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistatic inline unsigned long pwm_freq_from_reg(u8 reg)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	unsigned long clock = (reg & 0x80) ? 48000000UL : 1000000UL;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	reg &= 0x7f;
2528c2ecf20Sopenharmony_ci	if (reg == 0)
2538c2ecf20Sopenharmony_ci		reg++;
2548c2ecf20Sopenharmony_ci	return clock / (reg << 8);
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic inline u8 pwm_freq_to_reg(unsigned long val)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	if (val >= 187500)	/* The highest we can do */
2608c2ecf20Sopenharmony_ci		return 0x80;
2618c2ecf20Sopenharmony_ci	if (val >= 1475)	/* Use 48 MHz clock */
2628c2ecf20Sopenharmony_ci		return 0x80 | (48000000UL / (val << 8));
2638c2ecf20Sopenharmony_ci	if (val < 31)		/* The lowest we can do */
2648c2ecf20Sopenharmony_ci		return 0x7f;
2658c2ecf20Sopenharmony_ci	else			/* Use 1 MHz clock */
2668c2ecf20Sopenharmony_ci		return 1000000UL / (val << 8);
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistatic inline int pwm_mode_from_reg(u8 reg)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	return !(reg & FAN_CTRL_DC_MODE);
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_cistatic inline long temp_from_reg(u8 reg)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	return reg * 1000;
2778c2ecf20Sopenharmony_ci}
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_cistatic inline u8 temp_to_reg(long val)
2808c2ecf20Sopenharmony_ci{
2818c2ecf20Sopenharmony_ci	if (val <= 0)
2828c2ecf20Sopenharmony_ci		return 0;
2838c2ecf20Sopenharmony_ci	if (val >= 1000 * 0xff)
2848c2ecf20Sopenharmony_ci		return 0xff;
2858c2ecf20Sopenharmony_ci	return (val + 500) / 1000;
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci/*
2898c2ecf20Sopenharmony_ci * Device I/O access
2908c2ecf20Sopenharmony_ci */
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci/* Must be called with data->update_lock held, except during initialization */
2938c2ecf20Sopenharmony_cistatic u8 f71805f_read8(struct f71805f_data *data, u8 reg)
2948c2ecf20Sopenharmony_ci{
2958c2ecf20Sopenharmony_ci	outb(reg, data->addr + ADDR_REG_OFFSET);
2968c2ecf20Sopenharmony_ci	return inb(data->addr + DATA_REG_OFFSET);
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci/* Must be called with data->update_lock held, except during initialization */
3008c2ecf20Sopenharmony_cistatic void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	outb(reg, data->addr + ADDR_REG_OFFSET);
3038c2ecf20Sopenharmony_ci	outb(val, data->addr + DATA_REG_OFFSET);
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci/*
3078c2ecf20Sopenharmony_ci * It is important to read the MSB first, because doing so latches the
3088c2ecf20Sopenharmony_ci * value of the LSB, so we are sure both bytes belong to the same value.
3098c2ecf20Sopenharmony_ci * Must be called with data->update_lock held, except during initialization
3108c2ecf20Sopenharmony_ci */
3118c2ecf20Sopenharmony_cistatic u16 f71805f_read16(struct f71805f_data *data, u8 reg)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	u16 val;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	outb(reg, data->addr + ADDR_REG_OFFSET);
3168c2ecf20Sopenharmony_ci	val = inb(data->addr + DATA_REG_OFFSET) << 8;
3178c2ecf20Sopenharmony_ci	outb(++reg, data->addr + ADDR_REG_OFFSET);
3188c2ecf20Sopenharmony_ci	val |= inb(data->addr + DATA_REG_OFFSET);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	return val;
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci/* Must be called with data->update_lock held, except during initialization */
3248c2ecf20Sopenharmony_cistatic void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	outb(reg, data->addr + ADDR_REG_OFFSET);
3278c2ecf20Sopenharmony_ci	outb(val >> 8, data->addr + DATA_REG_OFFSET);
3288c2ecf20Sopenharmony_ci	outb(++reg, data->addr + ADDR_REG_OFFSET);
3298c2ecf20Sopenharmony_ci	outb(val & 0xff, data->addr + DATA_REG_OFFSET);
3308c2ecf20Sopenharmony_ci}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_cistatic struct f71805f_data *f71805f_update_device(struct device *dev)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
3358c2ecf20Sopenharmony_ci	int nr, apnr;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	/* Limit registers cache is refreshed after 60 seconds */
3408c2ecf20Sopenharmony_ci	if (time_after(jiffies, data->last_updated + 60 * HZ)
3418c2ecf20Sopenharmony_ci	 || !data->valid) {
3428c2ecf20Sopenharmony_ci		for (nr = 0; nr < 11; nr++) {
3438c2ecf20Sopenharmony_ci			if (!(data->has_in & (1 << nr)))
3448c2ecf20Sopenharmony_ci				continue;
3458c2ecf20Sopenharmony_ci			data->in_high[nr] = f71805f_read8(data,
3468c2ecf20Sopenharmony_ci					    F71805F_REG_IN_HIGH(nr));
3478c2ecf20Sopenharmony_ci			data->in_low[nr] = f71805f_read8(data,
3488c2ecf20Sopenharmony_ci					   F71805F_REG_IN_LOW(nr));
3498c2ecf20Sopenharmony_ci		}
3508c2ecf20Sopenharmony_ci		for (nr = 0; nr < 3; nr++) {
3518c2ecf20Sopenharmony_ci			data->fan_low[nr] = f71805f_read16(data,
3528c2ecf20Sopenharmony_ci					    F71805F_REG_FAN_LOW(nr));
3538c2ecf20Sopenharmony_ci			data->fan_target[nr] = f71805f_read16(data,
3548c2ecf20Sopenharmony_ci					       F71805F_REG_FAN_TARGET(nr));
3558c2ecf20Sopenharmony_ci			data->pwm_freq[nr] = f71805f_read8(data,
3568c2ecf20Sopenharmony_ci					     F71805F_REG_PWM_FREQ(nr));
3578c2ecf20Sopenharmony_ci		}
3588c2ecf20Sopenharmony_ci		for (nr = 0; nr < 3; nr++) {
3598c2ecf20Sopenharmony_ci			data->temp_high[nr] = f71805f_read8(data,
3608c2ecf20Sopenharmony_ci					      F71805F_REG_TEMP_HIGH(nr));
3618c2ecf20Sopenharmony_ci			data->temp_hyst[nr] = f71805f_read8(data,
3628c2ecf20Sopenharmony_ci					      F71805F_REG_TEMP_HYST(nr));
3638c2ecf20Sopenharmony_ci		}
3648c2ecf20Sopenharmony_ci		data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE);
3658c2ecf20Sopenharmony_ci		for (nr = 0; nr < 3; nr++) {
3668c2ecf20Sopenharmony_ci			for (apnr = 0; apnr < 3; apnr++) {
3678c2ecf20Sopenharmony_ci				data->auto_points[nr].temp[apnr] =
3688c2ecf20Sopenharmony_ci					f71805f_read8(data,
3698c2ecf20Sopenharmony_ci					F71805F_REG_PWM_AUTO_POINT_TEMP(nr,
3708c2ecf20Sopenharmony_ci									apnr));
3718c2ecf20Sopenharmony_ci				data->auto_points[nr].fan[apnr] =
3728c2ecf20Sopenharmony_ci					f71805f_read16(data,
3738c2ecf20Sopenharmony_ci					F71805F_REG_PWM_AUTO_POINT_FAN(nr,
3748c2ecf20Sopenharmony_ci								       apnr));
3758c2ecf20Sopenharmony_ci			}
3768c2ecf20Sopenharmony_ci		}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci		data->last_limits = jiffies;
3798c2ecf20Sopenharmony_ci	}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	/* Measurement registers cache is refreshed after 1 second */
3828c2ecf20Sopenharmony_ci	if (time_after(jiffies, data->last_updated + HZ)
3838c2ecf20Sopenharmony_ci	 || !data->valid) {
3848c2ecf20Sopenharmony_ci		for (nr = 0; nr < 11; nr++) {
3858c2ecf20Sopenharmony_ci			if (!(data->has_in & (1 << nr)))
3868c2ecf20Sopenharmony_ci				continue;
3878c2ecf20Sopenharmony_ci			data->in[nr] = f71805f_read8(data,
3888c2ecf20Sopenharmony_ci				       F71805F_REG_IN(nr));
3898c2ecf20Sopenharmony_ci		}
3908c2ecf20Sopenharmony_ci		for (nr = 0; nr < 3; nr++) {
3918c2ecf20Sopenharmony_ci			data->fan[nr] = f71805f_read16(data,
3928c2ecf20Sopenharmony_ci					F71805F_REG_FAN(nr));
3938c2ecf20Sopenharmony_ci			data->fan_ctrl[nr] = f71805f_read8(data,
3948c2ecf20Sopenharmony_ci					     F71805F_REG_FAN_CTRL(nr));
3958c2ecf20Sopenharmony_ci			data->pwm[nr] = f71805f_read8(data,
3968c2ecf20Sopenharmony_ci					F71805F_REG_PWM_DUTY(nr));
3978c2ecf20Sopenharmony_ci		}
3988c2ecf20Sopenharmony_ci		for (nr = 0; nr < 3; nr++) {
3998c2ecf20Sopenharmony_ci			data->temp[nr] = f71805f_read8(data,
4008c2ecf20Sopenharmony_ci					 F71805F_REG_TEMP(nr));
4018c2ecf20Sopenharmony_ci		}
4028c2ecf20Sopenharmony_ci		data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0))
4038c2ecf20Sopenharmony_ci			+ (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8)
4048c2ecf20Sopenharmony_ci			+ (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16);
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci		data->last_updated = jiffies;
4078c2ecf20Sopenharmony_ci		data->valid = 1;
4088c2ecf20Sopenharmony_ci	}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	return data;
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci/*
4168c2ecf20Sopenharmony_ci * Sysfs interface
4178c2ecf20Sopenharmony_ci */
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_cistatic ssize_t show_in0(struct device *dev, struct device_attribute *devattr,
4208c2ecf20Sopenharmony_ci			char *buf)
4218c2ecf20Sopenharmony_ci{
4228c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
4238c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
4248c2ecf20Sopenharmony_ci	int nr = attr->index;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", in0_from_reg(data->in[nr]));
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_cistatic ssize_t show_in0_max(struct device *dev, struct device_attribute
4308c2ecf20Sopenharmony_ci			    *devattr, char *buf)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
4338c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
4348c2ecf20Sopenharmony_ci	int nr = attr->index;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[nr]));
4378c2ecf20Sopenharmony_ci}
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_cistatic ssize_t show_in0_min(struct device *dev, struct device_attribute
4408c2ecf20Sopenharmony_ci			    *devattr, char *buf)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
4438c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
4448c2ecf20Sopenharmony_ci	int nr = attr->index;
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[nr]));
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic ssize_t set_in0_max(struct device *dev, struct device_attribute
4508c2ecf20Sopenharmony_ci			   *devattr, const char *buf, size_t count)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
4538c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
4548c2ecf20Sopenharmony_ci	int nr = attr->index;
4558c2ecf20Sopenharmony_ci	long val;
4568c2ecf20Sopenharmony_ci	int err;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
4598c2ecf20Sopenharmony_ci	if (err)
4608c2ecf20Sopenharmony_ci		return err;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
4638c2ecf20Sopenharmony_ci	data->in_high[nr] = in0_to_reg(val);
4648c2ecf20Sopenharmony_ci	f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
4658c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	return count;
4688c2ecf20Sopenharmony_ci}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_cistatic ssize_t set_in0_min(struct device *dev, struct device_attribute
4718c2ecf20Sopenharmony_ci			   *devattr, const char *buf, size_t count)
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
4748c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
4758c2ecf20Sopenharmony_ci	int nr = attr->index;
4768c2ecf20Sopenharmony_ci	long val;
4778c2ecf20Sopenharmony_ci	int err;
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
4808c2ecf20Sopenharmony_ci	if (err)
4818c2ecf20Sopenharmony_ci		return err;
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
4848c2ecf20Sopenharmony_ci	data->in_low[nr] = in0_to_reg(val);
4858c2ecf20Sopenharmony_ci	f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
4868c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	return count;
4898c2ecf20Sopenharmony_ci}
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_cistatic ssize_t show_in(struct device *dev, struct device_attribute *devattr,
4928c2ecf20Sopenharmony_ci		       char *buf)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
4958c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
4968c2ecf20Sopenharmony_ci	int nr = attr->index;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", in_from_reg(data->in[nr]));
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic ssize_t show_in_max(struct device *dev, struct device_attribute
5028c2ecf20Sopenharmony_ci			   *devattr, char *buf)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
5058c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5068c2ecf20Sopenharmony_ci	int nr = attr->index;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr]));
5098c2ecf20Sopenharmony_ci}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_cistatic ssize_t show_in_min(struct device *dev, struct device_attribute
5128c2ecf20Sopenharmony_ci			   *devattr, char *buf)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
5158c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5168c2ecf20Sopenharmony_ci	int nr = attr->index;
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr]));
5198c2ecf20Sopenharmony_ci}
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_cistatic ssize_t set_in_max(struct device *dev, struct device_attribute
5228c2ecf20Sopenharmony_ci			  *devattr, const char *buf, size_t count)
5238c2ecf20Sopenharmony_ci{
5248c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
5258c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5268c2ecf20Sopenharmony_ci	int nr = attr->index;
5278c2ecf20Sopenharmony_ci	long val;
5288c2ecf20Sopenharmony_ci	int err;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
5318c2ecf20Sopenharmony_ci	if (err)
5328c2ecf20Sopenharmony_ci		return err;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
5358c2ecf20Sopenharmony_ci	data->in_high[nr] = in_to_reg(val);
5368c2ecf20Sopenharmony_ci	f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
5378c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	return count;
5408c2ecf20Sopenharmony_ci}
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_cistatic ssize_t set_in_min(struct device *dev, struct device_attribute
5438c2ecf20Sopenharmony_ci			  *devattr, const char *buf, size_t count)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
5468c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5478c2ecf20Sopenharmony_ci	int nr = attr->index;
5488c2ecf20Sopenharmony_ci	long val;
5498c2ecf20Sopenharmony_ci	int err;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
5528c2ecf20Sopenharmony_ci	if (err)
5538c2ecf20Sopenharmony_ci		return err;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
5568c2ecf20Sopenharmony_ci	data->in_low[nr] = in_to_reg(val);
5578c2ecf20Sopenharmony_ci	f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
5588c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	return count;
5618c2ecf20Sopenharmony_ci}
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_cistatic ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
5648c2ecf20Sopenharmony_ci			char *buf)
5658c2ecf20Sopenharmony_ci{
5668c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
5678c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5688c2ecf20Sopenharmony_ci	int nr = attr->index;
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr]));
5718c2ecf20Sopenharmony_ci}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_cistatic ssize_t show_fan_min(struct device *dev, struct device_attribute
5748c2ecf20Sopenharmony_ci			    *devattr, char *buf)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
5778c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5788c2ecf20Sopenharmony_ci	int nr = attr->index;
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
5818c2ecf20Sopenharmony_ci}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_cistatic ssize_t show_fan_target(struct device *dev, struct device_attribute
5848c2ecf20Sopenharmony_ci			       *devattr, char *buf)
5858c2ecf20Sopenharmony_ci{
5868c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
5878c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5888c2ecf20Sopenharmony_ci	int nr = attr->index;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", fan_from_reg(data->fan_target[nr]));
5918c2ecf20Sopenharmony_ci}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_cistatic ssize_t set_fan_min(struct device *dev, struct device_attribute
5948c2ecf20Sopenharmony_ci			   *devattr, const char *buf, size_t count)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
5978c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
5988c2ecf20Sopenharmony_ci	int nr = attr->index;
5998c2ecf20Sopenharmony_ci	long val;
6008c2ecf20Sopenharmony_ci	int err;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
6038c2ecf20Sopenharmony_ci	if (err)
6048c2ecf20Sopenharmony_ci		return err;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
6078c2ecf20Sopenharmony_ci	data->fan_low[nr] = fan_to_reg(val);
6088c2ecf20Sopenharmony_ci	f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]);
6098c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci	return count;
6128c2ecf20Sopenharmony_ci}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_cistatic ssize_t set_fan_target(struct device *dev, struct device_attribute
6158c2ecf20Sopenharmony_ci			      *devattr, const char *buf, size_t count)
6168c2ecf20Sopenharmony_ci{
6178c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
6188c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
6198c2ecf20Sopenharmony_ci	int nr = attr->index;
6208c2ecf20Sopenharmony_ci	long val;
6218c2ecf20Sopenharmony_ci	int err;
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
6248c2ecf20Sopenharmony_ci	if (err)
6258c2ecf20Sopenharmony_ci		return err;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
6288c2ecf20Sopenharmony_ci	data->fan_target[nr] = fan_to_reg(val);
6298c2ecf20Sopenharmony_ci	f71805f_write16(data, F71805F_REG_FAN_TARGET(nr),
6308c2ecf20Sopenharmony_ci			data->fan_target[nr]);
6318c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	return count;
6348c2ecf20Sopenharmony_ci}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_cistatic ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
6378c2ecf20Sopenharmony_ci			char *buf)
6388c2ecf20Sopenharmony_ci{
6398c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
6408c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
6418c2ecf20Sopenharmony_ci	int nr = attr->index;
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", (int)data->pwm[nr]);
6448c2ecf20Sopenharmony_ci}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_cistatic ssize_t show_pwm_enable(struct device *dev, struct device_attribute
6478c2ecf20Sopenharmony_ci			       *devattr, char *buf)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
6508c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
6518c2ecf20Sopenharmony_ci	int nr = attr->index;
6528c2ecf20Sopenharmony_ci	int mode;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	switch (data->fan_ctrl[nr] & FAN_CTRL_MODE_MASK) {
6558c2ecf20Sopenharmony_ci	case FAN_CTRL_MODE_SPEED:
6568c2ecf20Sopenharmony_ci		mode = 3;
6578c2ecf20Sopenharmony_ci		break;
6588c2ecf20Sopenharmony_ci	case FAN_CTRL_MODE_TEMPERATURE:
6598c2ecf20Sopenharmony_ci		mode = 2;
6608c2ecf20Sopenharmony_ci		break;
6618c2ecf20Sopenharmony_ci	default: /* MANUAL */
6628c2ecf20Sopenharmony_ci		mode = 1;
6638c2ecf20Sopenharmony_ci	}
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", mode);
6668c2ecf20Sopenharmony_ci}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_cistatic ssize_t show_pwm_freq(struct device *dev, struct device_attribute
6698c2ecf20Sopenharmony_ci			     *devattr, char *buf)
6708c2ecf20Sopenharmony_ci{
6718c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
6728c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
6738c2ecf20Sopenharmony_ci	int nr = attr->index;
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	return sprintf(buf, "%lu\n", pwm_freq_from_reg(data->pwm_freq[nr]));
6768c2ecf20Sopenharmony_ci}
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_cistatic ssize_t show_pwm_mode(struct device *dev, struct device_attribute
6798c2ecf20Sopenharmony_ci			     *devattr, char *buf)
6808c2ecf20Sopenharmony_ci{
6818c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
6828c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
6838c2ecf20Sopenharmony_ci	int nr = attr->index;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", pwm_mode_from_reg(data->fan_ctrl[nr]));
6868c2ecf20Sopenharmony_ci}
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_cistatic ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
6898c2ecf20Sopenharmony_ci		       const char *buf, size_t count)
6908c2ecf20Sopenharmony_ci{
6918c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
6928c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
6938c2ecf20Sopenharmony_ci	int nr = attr->index;
6948c2ecf20Sopenharmony_ci	unsigned long val;
6958c2ecf20Sopenharmony_ci	int err;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	err = kstrtoul(buf, 10, &val);
6988c2ecf20Sopenharmony_ci	if (err)
6998c2ecf20Sopenharmony_ci		return err;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	if (val > 255)
7028c2ecf20Sopenharmony_ci		return -EINVAL;
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
7058c2ecf20Sopenharmony_ci	data->pwm[nr] = val;
7068c2ecf20Sopenharmony_ci	f71805f_write8(data, F71805F_REG_PWM_DUTY(nr), data->pwm[nr]);
7078c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	return count;
7108c2ecf20Sopenharmony_ci}
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_cistatic struct attribute *f71805f_attr_pwm[];
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_cistatic ssize_t set_pwm_enable(struct device *dev, struct device_attribute
7158c2ecf20Sopenharmony_ci			      *devattr, const char *buf, size_t count)
7168c2ecf20Sopenharmony_ci{
7178c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
7188c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
7198c2ecf20Sopenharmony_ci	int nr = attr->index;
7208c2ecf20Sopenharmony_ci	u8 reg;
7218c2ecf20Sopenharmony_ci	unsigned long val;
7228c2ecf20Sopenharmony_ci	int err;
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	err = kstrtoul(buf, 10, &val);
7258c2ecf20Sopenharmony_ci	if (err)
7268c2ecf20Sopenharmony_ci		return err;
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	if (val < 1 || val > 3)
7298c2ecf20Sopenharmony_ci		return -EINVAL;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	if (val > 1) { /* Automatic mode, user can't set PWM value */
7328c2ecf20Sopenharmony_ci		if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
7338c2ecf20Sopenharmony_ci				     S_IRUGO))
7348c2ecf20Sopenharmony_ci			dev_dbg(dev, "chmod -w pwm%d failed\n", nr + 1);
7358c2ecf20Sopenharmony_ci	}
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
7388c2ecf20Sopenharmony_ci	reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(nr))
7398c2ecf20Sopenharmony_ci	    & ~FAN_CTRL_MODE_MASK;
7408c2ecf20Sopenharmony_ci	switch (val) {
7418c2ecf20Sopenharmony_ci	case 1:
7428c2ecf20Sopenharmony_ci		reg |= FAN_CTRL_MODE_MANUAL;
7438c2ecf20Sopenharmony_ci		break;
7448c2ecf20Sopenharmony_ci	case 2:
7458c2ecf20Sopenharmony_ci		reg |= FAN_CTRL_MODE_TEMPERATURE;
7468c2ecf20Sopenharmony_ci		break;
7478c2ecf20Sopenharmony_ci	case 3:
7488c2ecf20Sopenharmony_ci		reg |= FAN_CTRL_MODE_SPEED;
7498c2ecf20Sopenharmony_ci		break;
7508c2ecf20Sopenharmony_ci	}
7518c2ecf20Sopenharmony_ci	data->fan_ctrl[nr] = reg;
7528c2ecf20Sopenharmony_ci	f71805f_write8(data, F71805F_REG_FAN_CTRL(nr), reg);
7538c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	if (val == 1) { /* Manual mode, user can set PWM value */
7568c2ecf20Sopenharmony_ci		if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
7578c2ecf20Sopenharmony_ci				     S_IRUGO | S_IWUSR))
7588c2ecf20Sopenharmony_ci			dev_dbg(dev, "chmod +w pwm%d failed\n", nr + 1);
7598c2ecf20Sopenharmony_ci	}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	return count;
7628c2ecf20Sopenharmony_ci}
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_cistatic ssize_t set_pwm_freq(struct device *dev, struct device_attribute
7658c2ecf20Sopenharmony_ci			    *devattr, const char *buf, size_t count)
7668c2ecf20Sopenharmony_ci{
7678c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
7688c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
7698c2ecf20Sopenharmony_ci	int nr = attr->index;
7708c2ecf20Sopenharmony_ci	unsigned long val;
7718c2ecf20Sopenharmony_ci	int err;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	err = kstrtoul(buf, 10, &val);
7748c2ecf20Sopenharmony_ci	if (err)
7758c2ecf20Sopenharmony_ci		return err;
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
7788c2ecf20Sopenharmony_ci	data->pwm_freq[nr] = pwm_freq_to_reg(val);
7798c2ecf20Sopenharmony_ci	f71805f_write8(data, F71805F_REG_PWM_FREQ(nr), data->pwm_freq[nr]);
7808c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	return count;
7838c2ecf20Sopenharmony_ci}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_cistatic ssize_t show_pwm_auto_point_temp(struct device *dev,
7868c2ecf20Sopenharmony_ci					struct device_attribute *devattr,
7878c2ecf20Sopenharmony_ci					char *buf)
7888c2ecf20Sopenharmony_ci{
7898c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
7908c2ecf20Sopenharmony_ci	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
7918c2ecf20Sopenharmony_ci	int pwmnr = attr->nr;
7928c2ecf20Sopenharmony_ci	int apnr = attr->index;
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n",
7958c2ecf20Sopenharmony_ci		       temp_from_reg(data->auto_points[pwmnr].temp[apnr]));
7968c2ecf20Sopenharmony_ci}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_cistatic ssize_t set_pwm_auto_point_temp(struct device *dev,
7998c2ecf20Sopenharmony_ci				       struct device_attribute *devattr,
8008c2ecf20Sopenharmony_ci				       const char *buf, size_t count)
8018c2ecf20Sopenharmony_ci{
8028c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
8038c2ecf20Sopenharmony_ci	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
8048c2ecf20Sopenharmony_ci	int pwmnr = attr->nr;
8058c2ecf20Sopenharmony_ci	int apnr = attr->index;
8068c2ecf20Sopenharmony_ci	unsigned long val;
8078c2ecf20Sopenharmony_ci	int err;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	err = kstrtoul(buf, 10, &val);
8108c2ecf20Sopenharmony_ci	if (err)
8118c2ecf20Sopenharmony_ci		return err;
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
8148c2ecf20Sopenharmony_ci	data->auto_points[pwmnr].temp[apnr] = temp_to_reg(val);
8158c2ecf20Sopenharmony_ci	f71805f_write8(data, F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr),
8168c2ecf20Sopenharmony_ci		       data->auto_points[pwmnr].temp[apnr]);
8178c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	return count;
8208c2ecf20Sopenharmony_ci}
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_cistatic ssize_t show_pwm_auto_point_fan(struct device *dev,
8238c2ecf20Sopenharmony_ci				       struct device_attribute *devattr,
8248c2ecf20Sopenharmony_ci				       char *buf)
8258c2ecf20Sopenharmony_ci{
8268c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
8278c2ecf20Sopenharmony_ci	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
8288c2ecf20Sopenharmony_ci	int pwmnr = attr->nr;
8298c2ecf20Sopenharmony_ci	int apnr = attr->index;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n",
8328c2ecf20Sopenharmony_ci		       fan_from_reg(data->auto_points[pwmnr].fan[apnr]));
8338c2ecf20Sopenharmony_ci}
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_cistatic ssize_t set_pwm_auto_point_fan(struct device *dev,
8368c2ecf20Sopenharmony_ci				      struct device_attribute *devattr,
8378c2ecf20Sopenharmony_ci				      const char *buf, size_t count)
8388c2ecf20Sopenharmony_ci{
8398c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
8408c2ecf20Sopenharmony_ci	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
8418c2ecf20Sopenharmony_ci	int pwmnr = attr->nr;
8428c2ecf20Sopenharmony_ci	int apnr = attr->index;
8438c2ecf20Sopenharmony_ci	unsigned long val;
8448c2ecf20Sopenharmony_ci	int err;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	err = kstrtoul(buf, 10, &val);
8478c2ecf20Sopenharmony_ci	if (err)
8488c2ecf20Sopenharmony_ci		return err;
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
8518c2ecf20Sopenharmony_ci	data->auto_points[pwmnr].fan[apnr] = fan_to_reg(val);
8528c2ecf20Sopenharmony_ci	f71805f_write16(data, F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr),
8538c2ecf20Sopenharmony_ci			data->auto_points[pwmnr].fan[apnr]);
8548c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	return count;
8578c2ecf20Sopenharmony_ci}
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_cistatic ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
8608c2ecf20Sopenharmony_ci			 char *buf)
8618c2ecf20Sopenharmony_ci{
8628c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
8638c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
8648c2ecf20Sopenharmony_ci	int nr = attr->index;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
8678c2ecf20Sopenharmony_ci}
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_cistatic ssize_t show_temp_max(struct device *dev, struct device_attribute
8708c2ecf20Sopenharmony_ci			     *devattr, char *buf)
8718c2ecf20Sopenharmony_ci{
8728c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
8738c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
8748c2ecf20Sopenharmony_ci	int nr = attr->index;
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr]));
8778c2ecf20Sopenharmony_ci}
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_cistatic ssize_t show_temp_hyst(struct device *dev, struct device_attribute
8808c2ecf20Sopenharmony_ci			      *devattr, char *buf)
8818c2ecf20Sopenharmony_ci{
8828c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
8838c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
8848c2ecf20Sopenharmony_ci	int nr = attr->index;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr]));
8878c2ecf20Sopenharmony_ci}
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_cistatic ssize_t show_temp_type(struct device *dev, struct device_attribute
8908c2ecf20Sopenharmony_ci			      *devattr, char *buf)
8918c2ecf20Sopenharmony_ci{
8928c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
8938c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
8948c2ecf20Sopenharmony_ci	int nr = attr->index;
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	/* 3 is diode, 4 is thermistor */
8978c2ecf20Sopenharmony_ci	return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4);
8988c2ecf20Sopenharmony_ci}
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_cistatic ssize_t set_temp_max(struct device *dev, struct device_attribute
9018c2ecf20Sopenharmony_ci			    *devattr, const char *buf, size_t count)
9028c2ecf20Sopenharmony_ci{
9038c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
9048c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
9058c2ecf20Sopenharmony_ci	int nr = attr->index;
9068c2ecf20Sopenharmony_ci	long val;
9078c2ecf20Sopenharmony_ci	int err;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
9108c2ecf20Sopenharmony_ci	if (err)
9118c2ecf20Sopenharmony_ci		return err;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
9148c2ecf20Sopenharmony_ci	data->temp_high[nr] = temp_to_reg(val);
9158c2ecf20Sopenharmony_ci	f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]);
9168c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	return count;
9198c2ecf20Sopenharmony_ci}
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_cistatic ssize_t set_temp_hyst(struct device *dev, struct device_attribute
9228c2ecf20Sopenharmony_ci			     *devattr, const char *buf, size_t count)
9238c2ecf20Sopenharmony_ci{
9248c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
9258c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
9268c2ecf20Sopenharmony_ci	int nr = attr->index;
9278c2ecf20Sopenharmony_ci	long val;
9288c2ecf20Sopenharmony_ci	int err;
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
9318c2ecf20Sopenharmony_ci	if (err)
9328c2ecf20Sopenharmony_ci		return err;
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
9358c2ecf20Sopenharmony_ci	data->temp_hyst[nr] = temp_to_reg(val);
9368c2ecf20Sopenharmony_ci	f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
9378c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	return count;
9408c2ecf20Sopenharmony_ci}
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_cistatic ssize_t alarms_in_show(struct device *dev, struct device_attribute
9438c2ecf20Sopenharmony_ci			      *devattr, char *buf)
9448c2ecf20Sopenharmony_ci{
9458c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	return sprintf(buf, "%lu\n", data->alarms & 0x7ff);
9488c2ecf20Sopenharmony_ci}
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_cistatic ssize_t alarms_fan_show(struct device *dev, struct device_attribute
9518c2ecf20Sopenharmony_ci			       *devattr, char *buf)
9528c2ecf20Sopenharmony_ci{
9538c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07);
9568c2ecf20Sopenharmony_ci}
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_cistatic ssize_t alarms_temp_show(struct device *dev, struct device_attribute
9598c2ecf20Sopenharmony_ci				*devattr, char *buf)
9608c2ecf20Sopenharmony_ci{
9618c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07);
9648c2ecf20Sopenharmony_ci}
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_cistatic ssize_t show_alarm(struct device *dev, struct device_attribute
9678c2ecf20Sopenharmony_ci			  *devattr, char *buf)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	struct f71805f_data *data = f71805f_update_device(dev);
9708c2ecf20Sopenharmony_ci	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
9718c2ecf20Sopenharmony_ci	int bitnr = attr->index;
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	return sprintf(buf, "%lu\n", (data->alarms >> bitnr) & 1);
9748c2ecf20Sopenharmony_ci}
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_cistatic ssize_t name_show(struct device *dev, struct device_attribute
9778c2ecf20Sopenharmony_ci			 *devattr, char *buf)
9788c2ecf20Sopenharmony_ci{
9798c2ecf20Sopenharmony_ci	struct f71805f_data *data = dev_get_drvdata(dev);
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", data->name);
9828c2ecf20Sopenharmony_ci}
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL, 0);
9858c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
9868c2ecf20Sopenharmony_ci			  show_in0_max, set_in0_max, 0);
9878c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
9888c2ecf20Sopenharmony_ci			  show_in0_min, set_in0_min, 0);
9898c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
9908c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
9918c2ecf20Sopenharmony_ci			  show_in_max, set_in_max, 1);
9928c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR,
9938c2ecf20Sopenharmony_ci			  show_in_min, set_in_min, 1);
9948c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
9958c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR,
9968c2ecf20Sopenharmony_ci			  show_in_max, set_in_max, 2);
9978c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR,
9988c2ecf20Sopenharmony_ci			  show_in_min, set_in_min, 2);
9998c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
10008c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR,
10018c2ecf20Sopenharmony_ci			  show_in_max, set_in_max, 3);
10028c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR,
10038c2ecf20Sopenharmony_ci			  show_in_min, set_in_min, 3);
10048c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
10058c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
10068c2ecf20Sopenharmony_ci			  show_in_max, set_in_max, 4);
10078c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR,
10088c2ecf20Sopenharmony_ci			  show_in_min, set_in_min, 4);
10098c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5);
10108c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR,
10118c2ecf20Sopenharmony_ci			  show_in_max, set_in_max, 5);
10128c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR,
10138c2ecf20Sopenharmony_ci			  show_in_min, set_in_min, 5);
10148c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6);
10158c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in6_max, S_IRUGO | S_IWUSR,
10168c2ecf20Sopenharmony_ci			  show_in_max, set_in_max, 6);
10178c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in6_min, S_IRUGO | S_IWUSR,
10188c2ecf20Sopenharmony_ci			  show_in_min, set_in_min, 6);
10198c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7);
10208c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in7_max, S_IRUGO | S_IWUSR,
10218c2ecf20Sopenharmony_ci			  show_in_max, set_in_max, 7);
10228c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in7_min, S_IRUGO | S_IWUSR,
10238c2ecf20Sopenharmony_ci			  show_in_min, set_in_min, 7);
10248c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8);
10258c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in8_max, S_IRUGO | S_IWUSR,
10268c2ecf20Sopenharmony_ci			  show_in_max, set_in_max, 8);
10278c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR,
10288c2ecf20Sopenharmony_ci			  show_in_min, set_in_min, 8);
10298c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in0, NULL, 9);
10308c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in9_max, S_IRUGO | S_IWUSR,
10318c2ecf20Sopenharmony_ci			  show_in0_max, set_in0_max, 9);
10328c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in9_min, S_IRUGO | S_IWUSR,
10338c2ecf20Sopenharmony_ci			  show_in0_min, set_in0_min, 9);
10348c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in0, NULL, 10);
10358c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in10_max, S_IRUGO | S_IWUSR,
10368c2ecf20Sopenharmony_ci			  show_in0_max, set_in0_max, 10);
10378c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in10_min, S_IRUGO | S_IWUSR,
10388c2ecf20Sopenharmony_ci			  show_in0_min, set_in0_min, 10);
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
10418c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
10428c2ecf20Sopenharmony_ci			  show_fan_min, set_fan_min, 0);
10438c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR,
10448c2ecf20Sopenharmony_ci			  show_fan_target, set_fan_target, 0);
10458c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
10468c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
10478c2ecf20Sopenharmony_ci			  show_fan_min, set_fan_min, 1);
10488c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO | S_IWUSR,
10498c2ecf20Sopenharmony_ci			  show_fan_target, set_fan_target, 1);
10508c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
10518c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
10528c2ecf20Sopenharmony_ci			  show_fan_min, set_fan_min, 2);
10538c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan3_target, S_IRUGO | S_IWUSR,
10548c2ecf20Sopenharmony_ci			  show_fan_target, set_fan_target, 2);
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
10578c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
10588c2ecf20Sopenharmony_ci		    show_temp_max, set_temp_max, 0);
10598c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
10608c2ecf20Sopenharmony_ci		    show_temp_hyst, set_temp_hyst, 0);
10618c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0);
10628c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
10638c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR,
10648c2ecf20Sopenharmony_ci		    show_temp_max, set_temp_max, 1);
10658c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
10668c2ecf20Sopenharmony_ci		    show_temp_hyst, set_temp_hyst, 1);
10678c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1);
10688c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
10698c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR,
10708c2ecf20Sopenharmony_ci		    show_temp_max, set_temp_max, 2);
10718c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
10728c2ecf20Sopenharmony_ci		    show_temp_hyst, set_temp_hyst, 2);
10738c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci/*
10768c2ecf20Sopenharmony_ci * pwm (value) files are created read-only, write permission is
10778c2ecf20Sopenharmony_ci * then added or removed dynamically as needed
10788c2ecf20Sopenharmony_ci */
10798c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, show_pwm, set_pwm, 0);
10808c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
10818c2ecf20Sopenharmony_ci			  show_pwm_enable, set_pwm_enable, 0);
10828c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR,
10838c2ecf20Sopenharmony_ci			  show_pwm_freq, set_pwm_freq, 0);
10848c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0);
10858c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm2, S_IRUGO, show_pwm, set_pwm, 1);
10868c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
10878c2ecf20Sopenharmony_ci			  show_pwm_enable, set_pwm_enable, 1);
10888c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO | S_IWUSR,
10898c2ecf20Sopenharmony_ci			  show_pwm_freq, set_pwm_freq, 1);
10908c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, NULL, 1);
10918c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm3, S_IRUGO, show_pwm, set_pwm, 2);
10928c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR,
10938c2ecf20Sopenharmony_ci			  show_pwm_enable, set_pwm_enable, 2);
10948c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR,
10958c2ecf20Sopenharmony_ci			  show_pwm_freq, set_pwm_freq, 2);
10968c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2);
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR,
10998c2ecf20Sopenharmony_ci			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
11008c2ecf20Sopenharmony_ci			    0, 0);
11018c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_fan, S_IRUGO | S_IWUSR,
11028c2ecf20Sopenharmony_ci			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
11038c2ecf20Sopenharmony_ci			    0, 0);
11048c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR,
11058c2ecf20Sopenharmony_ci			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
11068c2ecf20Sopenharmony_ci			    0, 1);
11078c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_fan, S_IRUGO | S_IWUSR,
11088c2ecf20Sopenharmony_ci			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
11098c2ecf20Sopenharmony_ci			    0, 1);
11108c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR,
11118c2ecf20Sopenharmony_ci			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
11128c2ecf20Sopenharmony_ci			    0, 2);
11138c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_fan, S_IRUGO | S_IWUSR,
11148c2ecf20Sopenharmony_ci			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
11158c2ecf20Sopenharmony_ci			    0, 2);
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR,
11188c2ecf20Sopenharmony_ci			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
11198c2ecf20Sopenharmony_ci			    1, 0);
11208c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_fan, S_IRUGO | S_IWUSR,
11218c2ecf20Sopenharmony_ci			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
11228c2ecf20Sopenharmony_ci			    1, 0);
11238c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR,
11248c2ecf20Sopenharmony_ci			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
11258c2ecf20Sopenharmony_ci			    1, 1);
11268c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_fan, S_IRUGO | S_IWUSR,
11278c2ecf20Sopenharmony_ci			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
11288c2ecf20Sopenharmony_ci			    1, 1);
11298c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR,
11308c2ecf20Sopenharmony_ci			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
11318c2ecf20Sopenharmony_ci			    1, 2);
11328c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_fan, S_IRUGO | S_IWUSR,
11338c2ecf20Sopenharmony_ci			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
11348c2ecf20Sopenharmony_ci			    1, 2);
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR,
11378c2ecf20Sopenharmony_ci			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
11388c2ecf20Sopenharmony_ci			    2, 0);
11398c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_fan, S_IRUGO | S_IWUSR,
11408c2ecf20Sopenharmony_ci			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
11418c2ecf20Sopenharmony_ci			    2, 0);
11428c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR,
11438c2ecf20Sopenharmony_ci			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
11448c2ecf20Sopenharmony_ci			    2, 1);
11458c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_fan, S_IRUGO | S_IWUSR,
11468c2ecf20Sopenharmony_ci			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
11478c2ecf20Sopenharmony_ci			    2, 1);
11488c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR,
11498c2ecf20Sopenharmony_ci			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
11508c2ecf20Sopenharmony_ci			    2, 2);
11518c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_fan, S_IRUGO | S_IWUSR,
11528c2ecf20Sopenharmony_ci			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
11538c2ecf20Sopenharmony_ci			    2, 2);
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
11568c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
11578c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
11588c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
11598c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
11608c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
11618c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
11628c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
11638c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
11648c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9);
11658c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10);
11668c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11);
11678c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12);
11688c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
11698c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
11708c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
11718c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
11728c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(alarms_in);
11738c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(alarms_fan);
11748c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(alarms_temp);
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(name);
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_cistatic struct attribute *f71805f_attributes[] = {
11798c2ecf20Sopenharmony_ci	&sensor_dev_attr_in0_input.dev_attr.attr,
11808c2ecf20Sopenharmony_ci	&sensor_dev_attr_in0_max.dev_attr.attr,
11818c2ecf20Sopenharmony_ci	&sensor_dev_attr_in0_min.dev_attr.attr,
11828c2ecf20Sopenharmony_ci	&sensor_dev_attr_in1_input.dev_attr.attr,
11838c2ecf20Sopenharmony_ci	&sensor_dev_attr_in1_max.dev_attr.attr,
11848c2ecf20Sopenharmony_ci	&sensor_dev_attr_in1_min.dev_attr.attr,
11858c2ecf20Sopenharmony_ci	&sensor_dev_attr_in2_input.dev_attr.attr,
11868c2ecf20Sopenharmony_ci	&sensor_dev_attr_in2_max.dev_attr.attr,
11878c2ecf20Sopenharmony_ci	&sensor_dev_attr_in2_min.dev_attr.attr,
11888c2ecf20Sopenharmony_ci	&sensor_dev_attr_in3_input.dev_attr.attr,
11898c2ecf20Sopenharmony_ci	&sensor_dev_attr_in3_max.dev_attr.attr,
11908c2ecf20Sopenharmony_ci	&sensor_dev_attr_in3_min.dev_attr.attr,
11918c2ecf20Sopenharmony_ci	&sensor_dev_attr_in5_input.dev_attr.attr,
11928c2ecf20Sopenharmony_ci	&sensor_dev_attr_in5_max.dev_attr.attr,
11938c2ecf20Sopenharmony_ci	&sensor_dev_attr_in5_min.dev_attr.attr,
11948c2ecf20Sopenharmony_ci	&sensor_dev_attr_in6_input.dev_attr.attr,
11958c2ecf20Sopenharmony_ci	&sensor_dev_attr_in6_max.dev_attr.attr,
11968c2ecf20Sopenharmony_ci	&sensor_dev_attr_in6_min.dev_attr.attr,
11978c2ecf20Sopenharmony_ci	&sensor_dev_attr_in7_input.dev_attr.attr,
11988c2ecf20Sopenharmony_ci	&sensor_dev_attr_in7_max.dev_attr.attr,
11998c2ecf20Sopenharmony_ci	&sensor_dev_attr_in7_min.dev_attr.attr,
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_input.dev_attr.attr,
12028c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_min.dev_attr.attr,
12038c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
12048c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_target.dev_attr.attr,
12058c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_input.dev_attr.attr,
12068c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_min.dev_attr.attr,
12078c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
12088c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_target.dev_attr.attr,
12098c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_input.dev_attr.attr,
12108c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_min.dev_attr.attr,
12118c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
12128c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_target.dev_attr.attr,
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1.dev_attr.attr,
12158c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
12168c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_mode.dev_attr.attr,
12178c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2.dev_attr.attr,
12188c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
12198c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_mode.dev_attr.attr,
12208c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3.dev_attr.attr,
12218c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
12228c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_mode.dev_attr.attr,
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_input.dev_attr.attr,
12258c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_max.dev_attr.attr,
12268c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
12278c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_type.dev_attr.attr,
12288c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_input.dev_attr.attr,
12298c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_max.dev_attr.attr,
12308c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
12318c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_type.dev_attr.attr,
12328c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_input.dev_attr.attr,
12338c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_max.dev_attr.attr,
12348c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
12358c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_type.dev_attr.attr,
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
12388c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point1_fan.dev_attr.attr,
12398c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
12408c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point2_fan.dev_attr.attr,
12418c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
12428c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_auto_point3_fan.dev_attr.attr,
12438c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
12448c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point1_fan.dev_attr.attr,
12458c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
12468c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point2_fan.dev_attr.attr,
12478c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
12488c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_auto_point3_fan.dev_attr.attr,
12498c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,
12508c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point1_fan.dev_attr.attr,
12518c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
12528c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point2_fan.dev_attr.attr,
12538c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,
12548c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_auto_point3_fan.dev_attr.attr,
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	&sensor_dev_attr_in0_alarm.dev_attr.attr,
12578c2ecf20Sopenharmony_ci	&sensor_dev_attr_in1_alarm.dev_attr.attr,
12588c2ecf20Sopenharmony_ci	&sensor_dev_attr_in2_alarm.dev_attr.attr,
12598c2ecf20Sopenharmony_ci	&sensor_dev_attr_in3_alarm.dev_attr.attr,
12608c2ecf20Sopenharmony_ci	&sensor_dev_attr_in5_alarm.dev_attr.attr,
12618c2ecf20Sopenharmony_ci	&sensor_dev_attr_in6_alarm.dev_attr.attr,
12628c2ecf20Sopenharmony_ci	&sensor_dev_attr_in7_alarm.dev_attr.attr,
12638c2ecf20Sopenharmony_ci	&dev_attr_alarms_in.attr,
12648c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
12658c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
12668c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
12678c2ecf20Sopenharmony_ci	&dev_attr_alarms_temp.attr,
12688c2ecf20Sopenharmony_ci	&dev_attr_alarms_fan.attr,
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	&dev_attr_name.attr,
12718c2ecf20Sopenharmony_ci	NULL
12728c2ecf20Sopenharmony_ci};
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_cistatic const struct attribute_group f71805f_group = {
12758c2ecf20Sopenharmony_ci	.attrs = f71805f_attributes,
12768c2ecf20Sopenharmony_ci};
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_cistatic struct attribute *f71805f_attributes_optin[4][5] = {
12798c2ecf20Sopenharmony_ci	{
12808c2ecf20Sopenharmony_ci		&sensor_dev_attr_in4_input.dev_attr.attr,
12818c2ecf20Sopenharmony_ci		&sensor_dev_attr_in4_max.dev_attr.attr,
12828c2ecf20Sopenharmony_ci		&sensor_dev_attr_in4_min.dev_attr.attr,
12838c2ecf20Sopenharmony_ci		&sensor_dev_attr_in4_alarm.dev_attr.attr,
12848c2ecf20Sopenharmony_ci		NULL
12858c2ecf20Sopenharmony_ci	}, {
12868c2ecf20Sopenharmony_ci		&sensor_dev_attr_in8_input.dev_attr.attr,
12878c2ecf20Sopenharmony_ci		&sensor_dev_attr_in8_max.dev_attr.attr,
12888c2ecf20Sopenharmony_ci		&sensor_dev_attr_in8_min.dev_attr.attr,
12898c2ecf20Sopenharmony_ci		&sensor_dev_attr_in8_alarm.dev_attr.attr,
12908c2ecf20Sopenharmony_ci		NULL
12918c2ecf20Sopenharmony_ci	}, {
12928c2ecf20Sopenharmony_ci		&sensor_dev_attr_in9_input.dev_attr.attr,
12938c2ecf20Sopenharmony_ci		&sensor_dev_attr_in9_max.dev_attr.attr,
12948c2ecf20Sopenharmony_ci		&sensor_dev_attr_in9_min.dev_attr.attr,
12958c2ecf20Sopenharmony_ci		&sensor_dev_attr_in9_alarm.dev_attr.attr,
12968c2ecf20Sopenharmony_ci		NULL
12978c2ecf20Sopenharmony_ci	}, {
12988c2ecf20Sopenharmony_ci		&sensor_dev_attr_in10_input.dev_attr.attr,
12998c2ecf20Sopenharmony_ci		&sensor_dev_attr_in10_max.dev_attr.attr,
13008c2ecf20Sopenharmony_ci		&sensor_dev_attr_in10_min.dev_attr.attr,
13018c2ecf20Sopenharmony_ci		&sensor_dev_attr_in10_alarm.dev_attr.attr,
13028c2ecf20Sopenharmony_ci		NULL
13038c2ecf20Sopenharmony_ci	}
13048c2ecf20Sopenharmony_ci};
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_cistatic const struct attribute_group f71805f_group_optin[4] = {
13078c2ecf20Sopenharmony_ci	{ .attrs = f71805f_attributes_optin[0] },
13088c2ecf20Sopenharmony_ci	{ .attrs = f71805f_attributes_optin[1] },
13098c2ecf20Sopenharmony_ci	{ .attrs = f71805f_attributes_optin[2] },
13108c2ecf20Sopenharmony_ci	{ .attrs = f71805f_attributes_optin[3] },
13118c2ecf20Sopenharmony_ci};
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci/*
13148c2ecf20Sopenharmony_ci * We don't include pwm_freq files in the arrays above, because they must be
13158c2ecf20Sopenharmony_ci * created conditionally (only if pwm_mode is 1 == PWM)
13168c2ecf20Sopenharmony_ci */
13178c2ecf20Sopenharmony_cistatic struct attribute *f71805f_attributes_pwm_freq[] = {
13188c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
13198c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
13208c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3_freq.dev_attr.attr,
13218c2ecf20Sopenharmony_ci	NULL
13228c2ecf20Sopenharmony_ci};
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_cistatic const struct attribute_group f71805f_group_pwm_freq = {
13258c2ecf20Sopenharmony_ci	.attrs = f71805f_attributes_pwm_freq,
13268c2ecf20Sopenharmony_ci};
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci/* We also need an indexed access to pwmN files to toggle writability */
13298c2ecf20Sopenharmony_cistatic struct attribute *f71805f_attr_pwm[] = {
13308c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm1.dev_attr.attr,
13318c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm2.dev_attr.attr,
13328c2ecf20Sopenharmony_ci	&sensor_dev_attr_pwm3.dev_attr.attr,
13338c2ecf20Sopenharmony_ci};
13348c2ecf20Sopenharmony_ci
13358c2ecf20Sopenharmony_ci/*
13368c2ecf20Sopenharmony_ci * Device registration and initialization
13378c2ecf20Sopenharmony_ci */
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_cistatic void f71805f_init_device(struct f71805f_data *data)
13408c2ecf20Sopenharmony_ci{
13418c2ecf20Sopenharmony_ci	u8 reg;
13428c2ecf20Sopenharmony_ci	int i;
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	reg = f71805f_read8(data, F71805F_REG_START);
13458c2ecf20Sopenharmony_ci	if ((reg & 0x41) != 0x01) {
13468c2ecf20Sopenharmony_ci		pr_debug("Starting monitoring operations\n");
13478c2ecf20Sopenharmony_ci		f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40);
13488c2ecf20Sopenharmony_ci	}
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	/*
13518c2ecf20Sopenharmony_ci	 * Fan monitoring can be disabled. If it is, we won't be polling
13528c2ecf20Sopenharmony_ci	 * the register values, and won't create the related sysfs files.
13538c2ecf20Sopenharmony_ci	 */
13548c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++) {
13558c2ecf20Sopenharmony_ci		data->fan_ctrl[i] = f71805f_read8(data,
13568c2ecf20Sopenharmony_ci						  F71805F_REG_FAN_CTRL(i));
13578c2ecf20Sopenharmony_ci		/*
13588c2ecf20Sopenharmony_ci		 * Clear latch full bit, else "speed mode" fan speed control
13598c2ecf20Sopenharmony_ci		 * doesn't work
13608c2ecf20Sopenharmony_ci		 */
13618c2ecf20Sopenharmony_ci		if (data->fan_ctrl[i] & FAN_CTRL_LATCH_FULL) {
13628c2ecf20Sopenharmony_ci			data->fan_ctrl[i] &= ~FAN_CTRL_LATCH_FULL;
13638c2ecf20Sopenharmony_ci			f71805f_write8(data, F71805F_REG_FAN_CTRL(i),
13648c2ecf20Sopenharmony_ci				       data->fan_ctrl[i]);
13658c2ecf20Sopenharmony_ci		}
13668c2ecf20Sopenharmony_ci	}
13678c2ecf20Sopenharmony_ci}
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_cistatic int f71805f_probe(struct platform_device *pdev)
13708c2ecf20Sopenharmony_ci{
13718c2ecf20Sopenharmony_ci	struct f71805f_sio_data *sio_data = dev_get_platdata(&pdev->dev);
13728c2ecf20Sopenharmony_ci	struct f71805f_data *data;
13738c2ecf20Sopenharmony_ci	struct resource *res;
13748c2ecf20Sopenharmony_ci	int i, err;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	static const char * const names[] = {
13778c2ecf20Sopenharmony_ci		"f71805f",
13788c2ecf20Sopenharmony_ci		"f71872f",
13798c2ecf20Sopenharmony_ci	};
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	data = devm_kzalloc(&pdev->dev, sizeof(struct f71805f_data),
13828c2ecf20Sopenharmony_ci			    GFP_KERNEL);
13838c2ecf20Sopenharmony_ci	if (!data)
13848c2ecf20Sopenharmony_ci		return -ENOMEM;
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
13878c2ecf20Sopenharmony_ci	if (!devm_request_region(&pdev->dev, res->start + ADDR_REG_OFFSET, 2,
13888c2ecf20Sopenharmony_ci				 DRVNAME)) {
13898c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
13908c2ecf20Sopenharmony_ci			(unsigned long)(res->start + ADDR_REG_OFFSET),
13918c2ecf20Sopenharmony_ci			(unsigned long)(res->start + ADDR_REG_OFFSET + 1));
13928c2ecf20Sopenharmony_ci		return -EBUSY;
13938c2ecf20Sopenharmony_ci	}
13948c2ecf20Sopenharmony_ci	data->addr = res->start;
13958c2ecf20Sopenharmony_ci	data->name = names[sio_data->kind];
13968c2ecf20Sopenharmony_ci	mutex_init(&data->update_lock);
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, data);
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_ci	/* Some voltage inputs depend on chip model and configuration */
14018c2ecf20Sopenharmony_ci	switch (sio_data->kind) {
14028c2ecf20Sopenharmony_ci	case f71805f:
14038c2ecf20Sopenharmony_ci		data->has_in = 0x1ff;
14048c2ecf20Sopenharmony_ci		break;
14058c2ecf20Sopenharmony_ci	case f71872f:
14068c2ecf20Sopenharmony_ci		data->has_in = 0x6ef;
14078c2ecf20Sopenharmony_ci		if (sio_data->fnsel1 & 0x01)
14088c2ecf20Sopenharmony_ci			data->has_in |= (1 << 4); /* in4 */
14098c2ecf20Sopenharmony_ci		if (sio_data->fnsel1 & 0x02)
14108c2ecf20Sopenharmony_ci			data->has_in |= (1 << 8); /* in8 */
14118c2ecf20Sopenharmony_ci		break;
14128c2ecf20Sopenharmony_ci	}
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ci	/* Initialize the F71805F chip */
14158c2ecf20Sopenharmony_ci	f71805f_init_device(data);
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_ci	/* Register sysfs interface files */
14188c2ecf20Sopenharmony_ci	err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group);
14198c2ecf20Sopenharmony_ci	if (err)
14208c2ecf20Sopenharmony_ci		return err;
14218c2ecf20Sopenharmony_ci	if (data->has_in & (1 << 4)) { /* in4 */
14228c2ecf20Sopenharmony_ci		err = sysfs_create_group(&pdev->dev.kobj,
14238c2ecf20Sopenharmony_ci					 &f71805f_group_optin[0]);
14248c2ecf20Sopenharmony_ci		if (err)
14258c2ecf20Sopenharmony_ci			goto exit_remove_files;
14268c2ecf20Sopenharmony_ci	}
14278c2ecf20Sopenharmony_ci	if (data->has_in & (1 << 8)) { /* in8 */
14288c2ecf20Sopenharmony_ci		err = sysfs_create_group(&pdev->dev.kobj,
14298c2ecf20Sopenharmony_ci					 &f71805f_group_optin[1]);
14308c2ecf20Sopenharmony_ci		if (err)
14318c2ecf20Sopenharmony_ci			goto exit_remove_files;
14328c2ecf20Sopenharmony_ci	}
14338c2ecf20Sopenharmony_ci	if (data->has_in & (1 << 9)) { /* in9 (F71872F/FG only) */
14348c2ecf20Sopenharmony_ci		err = sysfs_create_group(&pdev->dev.kobj,
14358c2ecf20Sopenharmony_ci					 &f71805f_group_optin[2]);
14368c2ecf20Sopenharmony_ci		if (err)
14378c2ecf20Sopenharmony_ci			goto exit_remove_files;
14388c2ecf20Sopenharmony_ci	}
14398c2ecf20Sopenharmony_ci	if (data->has_in & (1 << 10)) { /* in9 (F71872F/FG only) */
14408c2ecf20Sopenharmony_ci		err = sysfs_create_group(&pdev->dev.kobj,
14418c2ecf20Sopenharmony_ci					 &f71805f_group_optin[3]);
14428c2ecf20Sopenharmony_ci		if (err)
14438c2ecf20Sopenharmony_ci			goto exit_remove_files;
14448c2ecf20Sopenharmony_ci	}
14458c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++) {
14468c2ecf20Sopenharmony_ci		/* If control mode is PWM, create pwm_freq file */
14478c2ecf20Sopenharmony_ci		if (!(data->fan_ctrl[i] & FAN_CTRL_DC_MODE)) {
14488c2ecf20Sopenharmony_ci			err = sysfs_create_file(&pdev->dev.kobj,
14498c2ecf20Sopenharmony_ci						f71805f_attributes_pwm_freq[i]);
14508c2ecf20Sopenharmony_ci			if (err)
14518c2ecf20Sopenharmony_ci				goto exit_remove_files;
14528c2ecf20Sopenharmony_ci		}
14538c2ecf20Sopenharmony_ci		/* If PWM is in manual mode, add write permission */
14548c2ecf20Sopenharmony_ci		if (data->fan_ctrl[i] & FAN_CTRL_MODE_MANUAL) {
14558c2ecf20Sopenharmony_ci			err = sysfs_chmod_file(&pdev->dev.kobj,
14568c2ecf20Sopenharmony_ci					       f71805f_attr_pwm[i],
14578c2ecf20Sopenharmony_ci					       S_IRUGO | S_IWUSR);
14588c2ecf20Sopenharmony_ci			if (err) {
14598c2ecf20Sopenharmony_ci				dev_err(&pdev->dev, "chmod +w pwm%d failed\n",
14608c2ecf20Sopenharmony_ci					i + 1);
14618c2ecf20Sopenharmony_ci				goto exit_remove_files;
14628c2ecf20Sopenharmony_ci			}
14638c2ecf20Sopenharmony_ci		}
14648c2ecf20Sopenharmony_ci	}
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci	data->hwmon_dev = hwmon_device_register(&pdev->dev);
14678c2ecf20Sopenharmony_ci	if (IS_ERR(data->hwmon_dev)) {
14688c2ecf20Sopenharmony_ci		err = PTR_ERR(data->hwmon_dev);
14698c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
14708c2ecf20Sopenharmony_ci		goto exit_remove_files;
14718c2ecf20Sopenharmony_ci	}
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci	return 0;
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ciexit_remove_files:
14768c2ecf20Sopenharmony_ci	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
14778c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++)
14788c2ecf20Sopenharmony_ci		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
14798c2ecf20Sopenharmony_ci	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
14808c2ecf20Sopenharmony_ci	return err;
14818c2ecf20Sopenharmony_ci}
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_cistatic int f71805f_remove(struct platform_device *pdev)
14848c2ecf20Sopenharmony_ci{
14858c2ecf20Sopenharmony_ci	struct f71805f_data *data = platform_get_drvdata(pdev);
14868c2ecf20Sopenharmony_ci	int i;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	hwmon_device_unregister(data->hwmon_dev);
14898c2ecf20Sopenharmony_ci	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
14908c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++)
14918c2ecf20Sopenharmony_ci		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
14928c2ecf20Sopenharmony_ci	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci	return 0;
14958c2ecf20Sopenharmony_ci}
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_cistatic struct platform_driver f71805f_driver = {
14988c2ecf20Sopenharmony_ci	.driver = {
14998c2ecf20Sopenharmony_ci		.name	= DRVNAME,
15008c2ecf20Sopenharmony_ci	},
15018c2ecf20Sopenharmony_ci	.probe		= f71805f_probe,
15028c2ecf20Sopenharmony_ci	.remove		= f71805f_remove,
15038c2ecf20Sopenharmony_ci};
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_cistatic int __init f71805f_device_add(unsigned short address,
15068c2ecf20Sopenharmony_ci				     const struct f71805f_sio_data *sio_data)
15078c2ecf20Sopenharmony_ci{
15088c2ecf20Sopenharmony_ci	struct resource res = {
15098c2ecf20Sopenharmony_ci		.start	= address,
15108c2ecf20Sopenharmony_ci		.end	= address + REGION_LENGTH - 1,
15118c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IO,
15128c2ecf20Sopenharmony_ci	};
15138c2ecf20Sopenharmony_ci	int err;
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_ci	pdev = platform_device_alloc(DRVNAME, address);
15168c2ecf20Sopenharmony_ci	if (!pdev) {
15178c2ecf20Sopenharmony_ci		err = -ENOMEM;
15188c2ecf20Sopenharmony_ci		pr_err("Device allocation failed\n");
15198c2ecf20Sopenharmony_ci		goto exit;
15208c2ecf20Sopenharmony_ci	}
15218c2ecf20Sopenharmony_ci
15228c2ecf20Sopenharmony_ci	res.name = pdev->name;
15238c2ecf20Sopenharmony_ci	err = acpi_check_resource_conflict(&res);
15248c2ecf20Sopenharmony_ci	if (err)
15258c2ecf20Sopenharmony_ci		goto exit_device_put;
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	err = platform_device_add_resources(pdev, &res, 1);
15288c2ecf20Sopenharmony_ci	if (err) {
15298c2ecf20Sopenharmony_ci		pr_err("Device resource addition failed (%d)\n", err);
15308c2ecf20Sopenharmony_ci		goto exit_device_put;
15318c2ecf20Sopenharmony_ci	}
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ci	err = platform_device_add_data(pdev, sio_data,
15348c2ecf20Sopenharmony_ci				       sizeof(struct f71805f_sio_data));
15358c2ecf20Sopenharmony_ci	if (err) {
15368c2ecf20Sopenharmony_ci		pr_err("Platform data allocation failed\n");
15378c2ecf20Sopenharmony_ci		goto exit_device_put;
15388c2ecf20Sopenharmony_ci	}
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	err = platform_device_add(pdev);
15418c2ecf20Sopenharmony_ci	if (err) {
15428c2ecf20Sopenharmony_ci		pr_err("Device addition failed (%d)\n", err);
15438c2ecf20Sopenharmony_ci		goto exit_device_put;
15448c2ecf20Sopenharmony_ci	}
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	return 0;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ciexit_device_put:
15498c2ecf20Sopenharmony_ci	platform_device_put(pdev);
15508c2ecf20Sopenharmony_ciexit:
15518c2ecf20Sopenharmony_ci	return err;
15528c2ecf20Sopenharmony_ci}
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_cistatic int __init f71805f_find(int sioaddr, unsigned short *address,
15558c2ecf20Sopenharmony_ci			       struct f71805f_sio_data *sio_data)
15568c2ecf20Sopenharmony_ci{
15578c2ecf20Sopenharmony_ci	int err;
15588c2ecf20Sopenharmony_ci	u16 devid;
15598c2ecf20Sopenharmony_ci
15608c2ecf20Sopenharmony_ci	static const char * const names[] = {
15618c2ecf20Sopenharmony_ci		"F71805F/FG",
15628c2ecf20Sopenharmony_ci		"F71872F/FG or F71806F/FG",
15638c2ecf20Sopenharmony_ci	};
15648c2ecf20Sopenharmony_ci
15658c2ecf20Sopenharmony_ci	err = superio_enter(sioaddr);
15668c2ecf20Sopenharmony_ci	if (err)
15678c2ecf20Sopenharmony_ci		return err;
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_ci	err = -ENODEV;
15708c2ecf20Sopenharmony_ci	devid = superio_inw(sioaddr, SIO_REG_MANID);
15718c2ecf20Sopenharmony_ci	if (devid != SIO_FINTEK_ID)
15728c2ecf20Sopenharmony_ci		goto exit;
15738c2ecf20Sopenharmony_ci
15748c2ecf20Sopenharmony_ci	devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
15758c2ecf20Sopenharmony_ci	switch (devid) {
15768c2ecf20Sopenharmony_ci	case SIO_F71805F_ID:
15778c2ecf20Sopenharmony_ci		sio_data->kind = f71805f;
15788c2ecf20Sopenharmony_ci		break;
15798c2ecf20Sopenharmony_ci	case SIO_F71872F_ID:
15808c2ecf20Sopenharmony_ci		sio_data->kind = f71872f;
15818c2ecf20Sopenharmony_ci		sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
15828c2ecf20Sopenharmony_ci		break;
15838c2ecf20Sopenharmony_ci	default:
15848c2ecf20Sopenharmony_ci		pr_info("Unsupported Fintek device, skipping\n");
15858c2ecf20Sopenharmony_ci		goto exit;
15868c2ecf20Sopenharmony_ci	}
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci	superio_select(sioaddr, F71805F_LD_HWM);
15898c2ecf20Sopenharmony_ci	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
15908c2ecf20Sopenharmony_ci		pr_warn("Device not activated, skipping\n");
15918c2ecf20Sopenharmony_ci		goto exit;
15928c2ecf20Sopenharmony_ci	}
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci	*address = superio_inw(sioaddr, SIO_REG_ADDR);
15958c2ecf20Sopenharmony_ci	if (*address == 0) {
15968c2ecf20Sopenharmony_ci		pr_warn("Base address not set, skipping\n");
15978c2ecf20Sopenharmony_ci		goto exit;
15988c2ecf20Sopenharmony_ci	}
15998c2ecf20Sopenharmony_ci	*address &= ~(REGION_LENGTH - 1);	/* Ignore 3 LSB */
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	err = 0;
16028c2ecf20Sopenharmony_ci	pr_info("Found %s chip at %#x, revision %u\n",
16038c2ecf20Sopenharmony_ci		names[sio_data->kind], *address,
16048c2ecf20Sopenharmony_ci		superio_inb(sioaddr, SIO_REG_DEVREV));
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ciexit:
16078c2ecf20Sopenharmony_ci	superio_exit(sioaddr);
16088c2ecf20Sopenharmony_ci	return err;
16098c2ecf20Sopenharmony_ci}
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_cistatic int __init f71805f_init(void)
16128c2ecf20Sopenharmony_ci{
16138c2ecf20Sopenharmony_ci	int err;
16148c2ecf20Sopenharmony_ci	unsigned short address;
16158c2ecf20Sopenharmony_ci	struct f71805f_sio_data sio_data;
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	if (f71805f_find(0x2e, &address, &sio_data)
16188c2ecf20Sopenharmony_ci	 && f71805f_find(0x4e, &address, &sio_data))
16198c2ecf20Sopenharmony_ci		return -ENODEV;
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	err = platform_driver_register(&f71805f_driver);
16228c2ecf20Sopenharmony_ci	if (err)
16238c2ecf20Sopenharmony_ci		goto exit;
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci	/* Sets global pdev as a side effect */
16268c2ecf20Sopenharmony_ci	err = f71805f_device_add(address, &sio_data);
16278c2ecf20Sopenharmony_ci	if (err)
16288c2ecf20Sopenharmony_ci		goto exit_driver;
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	return 0;
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_ciexit_driver:
16338c2ecf20Sopenharmony_ci	platform_driver_unregister(&f71805f_driver);
16348c2ecf20Sopenharmony_ciexit:
16358c2ecf20Sopenharmony_ci	return err;
16368c2ecf20Sopenharmony_ci}
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_cistatic void __exit f71805f_exit(void)
16398c2ecf20Sopenharmony_ci{
16408c2ecf20Sopenharmony_ci	platform_device_unregister(pdev);
16418c2ecf20Sopenharmony_ci	platform_driver_unregister(&f71805f_driver);
16428c2ecf20Sopenharmony_ci}
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
16458c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
16468c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("F71805F/F71872F hardware monitoring driver");
16478c2ecf20Sopenharmony_ci
16488c2ecf20Sopenharmony_cimodule_init(f71805f_init);
16498c2ecf20Sopenharmony_cimodule_exit(f71805f_exit);
1650