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