162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * f71805f.c - driver for the Fintek F71805F/FG and F71872F/FG Super-I/O 462306a36Sopenharmony_ci * chips integrated hardware monitoring features 562306a36Sopenharmony_ci * Copyright (C) 2005-2006 Jean Delvare <jdelvare@suse.de> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates 862306a36Sopenharmony_ci * complete hardware monitoring features: voltage, fan and temperature 962306a36Sopenharmony_ci * sensors, and manual and automatic fan speed control. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * The F71872F/FG is almost the same, with two more voltages monitored, 1262306a36Sopenharmony_ci * and 6 VID inputs. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * The F71806F/FG is essentially the same as the F71872F/FG. It even has 1562306a36Sopenharmony_ci * the same chip ID, so the driver can't differentiate between. 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/module.h> 2162306a36Sopenharmony_ci#include <linux/init.h> 2262306a36Sopenharmony_ci#include <linux/slab.h> 2362306a36Sopenharmony_ci#include <linux/jiffies.h> 2462306a36Sopenharmony_ci#include <linux/platform_device.h> 2562306a36Sopenharmony_ci#include <linux/hwmon.h> 2662306a36Sopenharmony_ci#include <linux/hwmon-sysfs.h> 2762306a36Sopenharmony_ci#include <linux/err.h> 2862306a36Sopenharmony_ci#include <linux/mutex.h> 2962306a36Sopenharmony_ci#include <linux/sysfs.h> 3062306a36Sopenharmony_ci#include <linux/ioport.h> 3162306a36Sopenharmony_ci#include <linux/acpi.h> 3262306a36Sopenharmony_ci#include <linux/io.h> 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic unsigned short force_id; 3562306a36Sopenharmony_cimodule_param(force_id, ushort, 0); 3662306a36Sopenharmony_ciMODULE_PARM_DESC(force_id, "Override the detected device ID"); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic struct platform_device *pdev; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define DRVNAME "f71805f" 4162306a36Sopenharmony_cienum kinds { f71805f, f71872f }; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* 4462306a36Sopenharmony_ci * Super-I/O constants and functions 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define F71805F_LD_HWM 0x04 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define SIO_REG_LDSEL 0x07 /* Logical device select */ 5062306a36Sopenharmony_ci#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ 5162306a36Sopenharmony_ci#define SIO_REG_DEVREV 0x22 /* Device revision */ 5262306a36Sopenharmony_ci#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ 5362306a36Sopenharmony_ci#define SIO_REG_FNSEL1 0x29 /* Multi Function Select 1 (F71872F) */ 5462306a36Sopenharmony_ci#define SIO_REG_ENABLE 0x30 /* Logical device enable */ 5562306a36Sopenharmony_ci#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define SIO_FINTEK_ID 0x1934 5862306a36Sopenharmony_ci#define SIO_F71805F_ID 0x0406 5962306a36Sopenharmony_ci#define SIO_F71872F_ID 0x0341 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic inline int 6262306a36Sopenharmony_cisuperio_inb(int base, int reg) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci outb(reg, base); 6562306a36Sopenharmony_ci return inb(base + 1); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic int 6962306a36Sopenharmony_cisuperio_inw(int base, int reg) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci int val; 7262306a36Sopenharmony_ci outb(reg++, base); 7362306a36Sopenharmony_ci val = inb(base + 1) << 8; 7462306a36Sopenharmony_ci outb(reg, base); 7562306a36Sopenharmony_ci val |= inb(base + 1); 7662306a36Sopenharmony_ci return val; 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic inline void 8062306a36Sopenharmony_cisuperio_select(int base, int ld) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci outb(SIO_REG_LDSEL, base); 8362306a36Sopenharmony_ci outb(ld, base + 1); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic inline int 8762306a36Sopenharmony_cisuperio_enter(int base) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci if (!request_muxed_region(base, 2, DRVNAME)) 9062306a36Sopenharmony_ci return -EBUSY; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci outb(0x87, base); 9362306a36Sopenharmony_ci outb(0x87, base); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci return 0; 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic inline void 9962306a36Sopenharmony_cisuperio_exit(int base) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci outb(0xaa, base); 10262306a36Sopenharmony_ci release_region(base, 2); 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* 10662306a36Sopenharmony_ci * ISA constants 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#define REGION_LENGTH 8 11062306a36Sopenharmony_ci#define ADDR_REG_OFFSET 5 11162306a36Sopenharmony_ci#define DATA_REG_OFFSET 6 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/* 11462306a36Sopenharmony_ci * Registers 11562306a36Sopenharmony_ci */ 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* in nr from 0 to 10 (8-bit values) */ 11862306a36Sopenharmony_ci#define F71805F_REG_IN(nr) (0x10 + (nr)) 11962306a36Sopenharmony_ci#define F71805F_REG_IN_HIGH(nr) ((nr) < 10 ? 0x40 + 2 * (nr) : 0x2E) 12062306a36Sopenharmony_ci#define F71805F_REG_IN_LOW(nr) ((nr) < 10 ? 0x41 + 2 * (nr) : 0x2F) 12162306a36Sopenharmony_ci/* fan nr from 0 to 2 (12-bit values, two registers) */ 12262306a36Sopenharmony_ci#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr)) 12362306a36Sopenharmony_ci#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr)) 12462306a36Sopenharmony_ci#define F71805F_REG_FAN_TARGET(nr) (0x69 + 16 * (nr)) 12562306a36Sopenharmony_ci#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr)) 12662306a36Sopenharmony_ci#define F71805F_REG_PWM_FREQ(nr) (0x63 + 16 * (nr)) 12762306a36Sopenharmony_ci#define F71805F_REG_PWM_DUTY(nr) (0x6B + 16 * (nr)) 12862306a36Sopenharmony_ci/* temp nr from 0 to 2 (8-bit values) */ 12962306a36Sopenharmony_ci#define F71805F_REG_TEMP(nr) (0x1B + (nr)) 13062306a36Sopenharmony_ci#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr)) 13162306a36Sopenharmony_ci#define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr)) 13262306a36Sopenharmony_ci#define F71805F_REG_TEMP_MODE 0x01 13362306a36Sopenharmony_ci/* pwm/fan pwmnr from 0 to 2, auto point apnr from 0 to 2 */ 13462306a36Sopenharmony_ci/* map Fintek numbers to our numbers as follows: 9->0, 5->1, 1->2 */ 13562306a36Sopenharmony_ci#define F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr) \ 13662306a36Sopenharmony_ci (0xA0 + 0x10 * (pwmnr) + (2 - (apnr))) 13762306a36Sopenharmony_ci#define F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr) \ 13862306a36Sopenharmony_ci (0xA4 + 0x10 * (pwmnr) + \ 13962306a36Sopenharmony_ci 2 * (2 - (apnr))) 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci#define F71805F_REG_START 0x00 14262306a36Sopenharmony_ci/* status nr from 0 to 2 */ 14362306a36Sopenharmony_ci#define F71805F_REG_STATUS(nr) (0x36 + (nr)) 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/* individual register bits */ 14662306a36Sopenharmony_ci#define FAN_CTRL_DC_MODE 0x10 14762306a36Sopenharmony_ci#define FAN_CTRL_LATCH_FULL 0x08 14862306a36Sopenharmony_ci#define FAN_CTRL_MODE_MASK 0x03 14962306a36Sopenharmony_ci#define FAN_CTRL_MODE_SPEED 0x00 15062306a36Sopenharmony_ci#define FAN_CTRL_MODE_TEMPERATURE 0x01 15162306a36Sopenharmony_ci#define FAN_CTRL_MODE_MANUAL 0x02 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* 15462306a36Sopenharmony_ci * Data structures and manipulation thereof 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistruct f71805f_auto_point { 15862306a36Sopenharmony_ci u8 temp[3]; 15962306a36Sopenharmony_ci u16 fan[3]; 16062306a36Sopenharmony_ci}; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistruct f71805f_data { 16362306a36Sopenharmony_ci unsigned short addr; 16462306a36Sopenharmony_ci const char *name; 16562306a36Sopenharmony_ci struct device *hwmon_dev; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci struct mutex update_lock; 16862306a36Sopenharmony_ci bool valid; /* true if following fields are valid */ 16962306a36Sopenharmony_ci unsigned long last_updated; /* In jiffies */ 17062306a36Sopenharmony_ci unsigned long last_limits; /* In jiffies */ 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci /* Register values */ 17362306a36Sopenharmony_ci u8 in[11]; 17462306a36Sopenharmony_ci u8 in_high[11]; 17562306a36Sopenharmony_ci u8 in_low[11]; 17662306a36Sopenharmony_ci u16 has_in; 17762306a36Sopenharmony_ci u16 fan[3]; 17862306a36Sopenharmony_ci u16 fan_low[3]; 17962306a36Sopenharmony_ci u16 fan_target[3]; 18062306a36Sopenharmony_ci u8 fan_ctrl[3]; 18162306a36Sopenharmony_ci u8 pwm[3]; 18262306a36Sopenharmony_ci u8 pwm_freq[3]; 18362306a36Sopenharmony_ci u8 temp[3]; 18462306a36Sopenharmony_ci u8 temp_high[3]; 18562306a36Sopenharmony_ci u8 temp_hyst[3]; 18662306a36Sopenharmony_ci u8 temp_mode; 18762306a36Sopenharmony_ci unsigned long alarms; 18862306a36Sopenharmony_ci struct f71805f_auto_point auto_points[3]; 18962306a36Sopenharmony_ci}; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistruct f71805f_sio_data { 19262306a36Sopenharmony_ci enum kinds kind; 19362306a36Sopenharmony_ci u8 fnsel1; 19462306a36Sopenharmony_ci}; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic inline long in_from_reg(u8 reg) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci return reg * 8; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/* The 2 least significant bits are not used */ 20262306a36Sopenharmony_cistatic inline u8 in_to_reg(long val) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci if (val <= 0) 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci if (val >= 2016) 20762306a36Sopenharmony_ci return 0xfc; 20862306a36Sopenharmony_ci return ((val + 16) / 32) << 2; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/* in0 is downscaled by a factor 2 internally */ 21262306a36Sopenharmony_cistatic inline long in0_from_reg(u8 reg) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci return reg * 16; 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic inline u8 in0_to_reg(long val) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci if (val <= 0) 22062306a36Sopenharmony_ci return 0; 22162306a36Sopenharmony_ci if (val >= 4032) 22262306a36Sopenharmony_ci return 0xfc; 22362306a36Sopenharmony_ci return ((val + 32) / 64) << 2; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci/* The 4 most significant bits are not used */ 22762306a36Sopenharmony_cistatic inline long fan_from_reg(u16 reg) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci reg &= 0xfff; 23062306a36Sopenharmony_ci if (!reg || reg == 0xfff) 23162306a36Sopenharmony_ci return 0; 23262306a36Sopenharmony_ci return 1500000 / reg; 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic inline u16 fan_to_reg(long rpm) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci /* 23862306a36Sopenharmony_ci * If the low limit is set below what the chip can measure, 23962306a36Sopenharmony_ci * store the largest possible 12-bit value in the registers, 24062306a36Sopenharmony_ci * so that no alarm will ever trigger. 24162306a36Sopenharmony_ci */ 24262306a36Sopenharmony_ci if (rpm < 367) 24362306a36Sopenharmony_ci return 0xfff; 24462306a36Sopenharmony_ci return 1500000 / rpm; 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic inline unsigned long pwm_freq_from_reg(u8 reg) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci unsigned long clock = (reg & 0x80) ? 48000000UL : 1000000UL; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci reg &= 0x7f; 25262306a36Sopenharmony_ci if (reg == 0) 25362306a36Sopenharmony_ci reg++; 25462306a36Sopenharmony_ci return clock / (reg << 8); 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic inline u8 pwm_freq_to_reg(unsigned long val) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci if (val >= 187500) /* The highest we can do */ 26062306a36Sopenharmony_ci return 0x80; 26162306a36Sopenharmony_ci if (val >= 1475) /* Use 48 MHz clock */ 26262306a36Sopenharmony_ci return 0x80 | (48000000UL / (val << 8)); 26362306a36Sopenharmony_ci if (val < 31) /* The lowest we can do */ 26462306a36Sopenharmony_ci return 0x7f; 26562306a36Sopenharmony_ci else /* Use 1 MHz clock */ 26662306a36Sopenharmony_ci return 1000000UL / (val << 8); 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic inline int pwm_mode_from_reg(u8 reg) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci return !(reg & FAN_CTRL_DC_MODE); 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic inline long temp_from_reg(u8 reg) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci return reg * 1000; 27762306a36Sopenharmony_ci} 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic inline u8 temp_to_reg(long val) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci if (val <= 0) 28262306a36Sopenharmony_ci return 0; 28362306a36Sopenharmony_ci if (val >= 1000 * 0xff) 28462306a36Sopenharmony_ci return 0xff; 28562306a36Sopenharmony_ci return (val + 500) / 1000; 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/* 28962306a36Sopenharmony_ci * Device I/O access 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci/* Must be called with data->update_lock held, except during initialization */ 29362306a36Sopenharmony_cistatic u8 f71805f_read8(struct f71805f_data *data, u8 reg) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci outb(reg, data->addr + ADDR_REG_OFFSET); 29662306a36Sopenharmony_ci return inb(data->addr + DATA_REG_OFFSET); 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci/* Must be called with data->update_lock held, except during initialization */ 30062306a36Sopenharmony_cistatic void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci outb(reg, data->addr + ADDR_REG_OFFSET); 30362306a36Sopenharmony_ci outb(val, data->addr + DATA_REG_OFFSET); 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci/* 30762306a36Sopenharmony_ci * It is important to read the MSB first, because doing so latches the 30862306a36Sopenharmony_ci * value of the LSB, so we are sure both bytes belong to the same value. 30962306a36Sopenharmony_ci * Must be called with data->update_lock held, except during initialization 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_cistatic u16 f71805f_read16(struct f71805f_data *data, u8 reg) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci u16 val; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci outb(reg, data->addr + ADDR_REG_OFFSET); 31662306a36Sopenharmony_ci val = inb(data->addr + DATA_REG_OFFSET) << 8; 31762306a36Sopenharmony_ci outb(++reg, data->addr + ADDR_REG_OFFSET); 31862306a36Sopenharmony_ci val |= inb(data->addr + DATA_REG_OFFSET); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci return val; 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci/* Must be called with data->update_lock held, except during initialization */ 32462306a36Sopenharmony_cistatic void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci outb(reg, data->addr + ADDR_REG_OFFSET); 32762306a36Sopenharmony_ci outb(val >> 8, data->addr + DATA_REG_OFFSET); 32862306a36Sopenharmony_ci outb(++reg, data->addr + ADDR_REG_OFFSET); 32962306a36Sopenharmony_ci outb(val & 0xff, data->addr + DATA_REG_OFFSET); 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic struct f71805f_data *f71805f_update_device(struct device *dev) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 33562306a36Sopenharmony_ci int nr, apnr; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci mutex_lock(&data->update_lock); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci /* Limit registers cache is refreshed after 60 seconds */ 34062306a36Sopenharmony_ci if (time_after(jiffies, data->last_updated + 60 * HZ) 34162306a36Sopenharmony_ci || !data->valid) { 34262306a36Sopenharmony_ci for (nr = 0; nr < 11; nr++) { 34362306a36Sopenharmony_ci if (!(data->has_in & (1 << nr))) 34462306a36Sopenharmony_ci continue; 34562306a36Sopenharmony_ci data->in_high[nr] = f71805f_read8(data, 34662306a36Sopenharmony_ci F71805F_REG_IN_HIGH(nr)); 34762306a36Sopenharmony_ci data->in_low[nr] = f71805f_read8(data, 34862306a36Sopenharmony_ci F71805F_REG_IN_LOW(nr)); 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci for (nr = 0; nr < 3; nr++) { 35162306a36Sopenharmony_ci data->fan_low[nr] = f71805f_read16(data, 35262306a36Sopenharmony_ci F71805F_REG_FAN_LOW(nr)); 35362306a36Sopenharmony_ci data->fan_target[nr] = f71805f_read16(data, 35462306a36Sopenharmony_ci F71805F_REG_FAN_TARGET(nr)); 35562306a36Sopenharmony_ci data->pwm_freq[nr] = f71805f_read8(data, 35662306a36Sopenharmony_ci F71805F_REG_PWM_FREQ(nr)); 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci for (nr = 0; nr < 3; nr++) { 35962306a36Sopenharmony_ci data->temp_high[nr] = f71805f_read8(data, 36062306a36Sopenharmony_ci F71805F_REG_TEMP_HIGH(nr)); 36162306a36Sopenharmony_ci data->temp_hyst[nr] = f71805f_read8(data, 36262306a36Sopenharmony_ci F71805F_REG_TEMP_HYST(nr)); 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE); 36562306a36Sopenharmony_ci for (nr = 0; nr < 3; nr++) { 36662306a36Sopenharmony_ci for (apnr = 0; apnr < 3; apnr++) { 36762306a36Sopenharmony_ci data->auto_points[nr].temp[apnr] = 36862306a36Sopenharmony_ci f71805f_read8(data, 36962306a36Sopenharmony_ci F71805F_REG_PWM_AUTO_POINT_TEMP(nr, 37062306a36Sopenharmony_ci apnr)); 37162306a36Sopenharmony_ci data->auto_points[nr].fan[apnr] = 37262306a36Sopenharmony_ci f71805f_read16(data, 37362306a36Sopenharmony_ci F71805F_REG_PWM_AUTO_POINT_FAN(nr, 37462306a36Sopenharmony_ci apnr)); 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci data->last_limits = jiffies; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci /* Measurement registers cache is refreshed after 1 second */ 38262306a36Sopenharmony_ci if (time_after(jiffies, data->last_updated + HZ) 38362306a36Sopenharmony_ci || !data->valid) { 38462306a36Sopenharmony_ci for (nr = 0; nr < 11; nr++) { 38562306a36Sopenharmony_ci if (!(data->has_in & (1 << nr))) 38662306a36Sopenharmony_ci continue; 38762306a36Sopenharmony_ci data->in[nr] = f71805f_read8(data, 38862306a36Sopenharmony_ci F71805F_REG_IN(nr)); 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci for (nr = 0; nr < 3; nr++) { 39162306a36Sopenharmony_ci data->fan[nr] = f71805f_read16(data, 39262306a36Sopenharmony_ci F71805F_REG_FAN(nr)); 39362306a36Sopenharmony_ci data->fan_ctrl[nr] = f71805f_read8(data, 39462306a36Sopenharmony_ci F71805F_REG_FAN_CTRL(nr)); 39562306a36Sopenharmony_ci data->pwm[nr] = f71805f_read8(data, 39662306a36Sopenharmony_ci F71805F_REG_PWM_DUTY(nr)); 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci for (nr = 0; nr < 3; nr++) { 39962306a36Sopenharmony_ci data->temp[nr] = f71805f_read8(data, 40062306a36Sopenharmony_ci F71805F_REG_TEMP(nr)); 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0)) 40362306a36Sopenharmony_ci + (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8) 40462306a36Sopenharmony_ci + (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci data->last_updated = jiffies; 40762306a36Sopenharmony_ci data->valid = true; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci return data; 41362306a36Sopenharmony_ci} 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci/* 41662306a36Sopenharmony_ci * Sysfs interface 41762306a36Sopenharmony_ci */ 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic ssize_t show_in0(struct device *dev, struct device_attribute *devattr, 42062306a36Sopenharmony_ci char *buf) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 42362306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 42462306a36Sopenharmony_ci int nr = attr->index; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci return sprintf(buf, "%ld\n", in0_from_reg(data->in[nr])); 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_cistatic ssize_t show_in0_max(struct device *dev, struct device_attribute 43062306a36Sopenharmony_ci *devattr, char *buf) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 43362306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 43462306a36Sopenharmony_ci int nr = attr->index; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[nr])); 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic ssize_t show_in0_min(struct device *dev, struct device_attribute 44062306a36Sopenharmony_ci *devattr, char *buf) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 44362306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 44462306a36Sopenharmony_ci int nr = attr->index; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[nr])); 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic ssize_t set_in0_max(struct device *dev, struct device_attribute 45062306a36Sopenharmony_ci *devattr, const char *buf, size_t count) 45162306a36Sopenharmony_ci{ 45262306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 45362306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 45462306a36Sopenharmony_ci int nr = attr->index; 45562306a36Sopenharmony_ci long val; 45662306a36Sopenharmony_ci int err; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci err = kstrtol(buf, 10, &val); 45962306a36Sopenharmony_ci if (err) 46062306a36Sopenharmony_ci return err; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci mutex_lock(&data->update_lock); 46362306a36Sopenharmony_ci data->in_high[nr] = in0_to_reg(val); 46462306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); 46562306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci return count; 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic ssize_t set_in0_min(struct device *dev, struct device_attribute 47162306a36Sopenharmony_ci *devattr, const char *buf, size_t count) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 47462306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 47562306a36Sopenharmony_ci int nr = attr->index; 47662306a36Sopenharmony_ci long val; 47762306a36Sopenharmony_ci int err; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci err = kstrtol(buf, 10, &val); 48062306a36Sopenharmony_ci if (err) 48162306a36Sopenharmony_ci return err; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci mutex_lock(&data->update_lock); 48462306a36Sopenharmony_ci data->in_low[nr] = in0_to_reg(val); 48562306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); 48662306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci return count; 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_cistatic ssize_t show_in(struct device *dev, struct device_attribute *devattr, 49262306a36Sopenharmony_ci char *buf) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 49562306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 49662306a36Sopenharmony_ci int nr = attr->index; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci return sprintf(buf, "%ld\n", in_from_reg(data->in[nr])); 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic ssize_t show_in_max(struct device *dev, struct device_attribute 50262306a36Sopenharmony_ci *devattr, char *buf) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 50562306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 50662306a36Sopenharmony_ci int nr = attr->index; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr])); 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic ssize_t show_in_min(struct device *dev, struct device_attribute 51262306a36Sopenharmony_ci *devattr, char *buf) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 51562306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 51662306a36Sopenharmony_ci int nr = attr->index; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr])); 51962306a36Sopenharmony_ci} 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_cistatic ssize_t set_in_max(struct device *dev, struct device_attribute 52262306a36Sopenharmony_ci *devattr, const char *buf, size_t count) 52362306a36Sopenharmony_ci{ 52462306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 52562306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 52662306a36Sopenharmony_ci int nr = attr->index; 52762306a36Sopenharmony_ci long val; 52862306a36Sopenharmony_ci int err; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci err = kstrtol(buf, 10, &val); 53162306a36Sopenharmony_ci if (err) 53262306a36Sopenharmony_ci return err; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci mutex_lock(&data->update_lock); 53562306a36Sopenharmony_ci data->in_high[nr] = in_to_reg(val); 53662306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); 53762306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci return count; 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic ssize_t set_in_min(struct device *dev, struct device_attribute 54362306a36Sopenharmony_ci *devattr, const char *buf, size_t count) 54462306a36Sopenharmony_ci{ 54562306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 54662306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 54762306a36Sopenharmony_ci int nr = attr->index; 54862306a36Sopenharmony_ci long val; 54962306a36Sopenharmony_ci int err; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci err = kstrtol(buf, 10, &val); 55262306a36Sopenharmony_ci if (err) 55362306a36Sopenharmony_ci return err; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci mutex_lock(&data->update_lock); 55662306a36Sopenharmony_ci data->in_low[nr] = in_to_reg(val); 55762306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); 55862306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci return count; 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_cistatic ssize_t show_fan(struct device *dev, struct device_attribute *devattr, 56462306a36Sopenharmony_ci char *buf) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 56762306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 56862306a36Sopenharmony_ci int nr = attr->index; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr])); 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_cistatic ssize_t show_fan_min(struct device *dev, struct device_attribute 57462306a36Sopenharmony_ci *devattr, char *buf) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 57762306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 57862306a36Sopenharmony_ci int nr = attr->index; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr])); 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic ssize_t show_fan_target(struct device *dev, struct device_attribute 58462306a36Sopenharmony_ci *devattr, char *buf) 58562306a36Sopenharmony_ci{ 58662306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 58762306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 58862306a36Sopenharmony_ci int nr = attr->index; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci return sprintf(buf, "%ld\n", fan_from_reg(data->fan_target[nr])); 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_cistatic ssize_t set_fan_min(struct device *dev, struct device_attribute 59462306a36Sopenharmony_ci *devattr, const char *buf, size_t count) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 59762306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 59862306a36Sopenharmony_ci int nr = attr->index; 59962306a36Sopenharmony_ci long val; 60062306a36Sopenharmony_ci int err; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci err = kstrtol(buf, 10, &val); 60362306a36Sopenharmony_ci if (err) 60462306a36Sopenharmony_ci return err; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci mutex_lock(&data->update_lock); 60762306a36Sopenharmony_ci data->fan_low[nr] = fan_to_reg(val); 60862306a36Sopenharmony_ci f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]); 60962306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci return count; 61262306a36Sopenharmony_ci} 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cistatic ssize_t set_fan_target(struct device *dev, struct device_attribute 61562306a36Sopenharmony_ci *devattr, const char *buf, size_t count) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 61862306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 61962306a36Sopenharmony_ci int nr = attr->index; 62062306a36Sopenharmony_ci long val; 62162306a36Sopenharmony_ci int err; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci err = kstrtol(buf, 10, &val); 62462306a36Sopenharmony_ci if (err) 62562306a36Sopenharmony_ci return err; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci mutex_lock(&data->update_lock); 62862306a36Sopenharmony_ci data->fan_target[nr] = fan_to_reg(val); 62962306a36Sopenharmony_ci f71805f_write16(data, F71805F_REG_FAN_TARGET(nr), 63062306a36Sopenharmony_ci data->fan_target[nr]); 63162306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci return count; 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, 63762306a36Sopenharmony_ci char *buf) 63862306a36Sopenharmony_ci{ 63962306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 64062306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 64162306a36Sopenharmony_ci int nr = attr->index; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci return sprintf(buf, "%d\n", (int)data->pwm[nr]); 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cistatic ssize_t show_pwm_enable(struct device *dev, struct device_attribute 64762306a36Sopenharmony_ci *devattr, char *buf) 64862306a36Sopenharmony_ci{ 64962306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 65062306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 65162306a36Sopenharmony_ci int nr = attr->index; 65262306a36Sopenharmony_ci int mode; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci switch (data->fan_ctrl[nr] & FAN_CTRL_MODE_MASK) { 65562306a36Sopenharmony_ci case FAN_CTRL_MODE_SPEED: 65662306a36Sopenharmony_ci mode = 3; 65762306a36Sopenharmony_ci break; 65862306a36Sopenharmony_ci case FAN_CTRL_MODE_TEMPERATURE: 65962306a36Sopenharmony_ci mode = 2; 66062306a36Sopenharmony_ci break; 66162306a36Sopenharmony_ci default: /* MANUAL */ 66262306a36Sopenharmony_ci mode = 1; 66362306a36Sopenharmony_ci } 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci return sprintf(buf, "%d\n", mode); 66662306a36Sopenharmony_ci} 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_cistatic ssize_t show_pwm_freq(struct device *dev, struct device_attribute 66962306a36Sopenharmony_ci *devattr, char *buf) 67062306a36Sopenharmony_ci{ 67162306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 67262306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 67362306a36Sopenharmony_ci int nr = attr->index; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci return sprintf(buf, "%lu\n", pwm_freq_from_reg(data->pwm_freq[nr])); 67662306a36Sopenharmony_ci} 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_cistatic ssize_t show_pwm_mode(struct device *dev, struct device_attribute 67962306a36Sopenharmony_ci *devattr, char *buf) 68062306a36Sopenharmony_ci{ 68162306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 68262306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 68362306a36Sopenharmony_ci int nr = attr->index; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci return sprintf(buf, "%d\n", pwm_mode_from_reg(data->fan_ctrl[nr])); 68662306a36Sopenharmony_ci} 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_cistatic ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, 68962306a36Sopenharmony_ci const char *buf, size_t count) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 69262306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 69362306a36Sopenharmony_ci int nr = attr->index; 69462306a36Sopenharmony_ci unsigned long val; 69562306a36Sopenharmony_ci int err; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci err = kstrtoul(buf, 10, &val); 69862306a36Sopenharmony_ci if (err) 69962306a36Sopenharmony_ci return err; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci if (val > 255) 70262306a36Sopenharmony_ci return -EINVAL; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci mutex_lock(&data->update_lock); 70562306a36Sopenharmony_ci data->pwm[nr] = val; 70662306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_PWM_DUTY(nr), data->pwm[nr]); 70762306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci return count; 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_cistatic struct attribute *f71805f_attr_pwm[]; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_cistatic ssize_t set_pwm_enable(struct device *dev, struct device_attribute 71562306a36Sopenharmony_ci *devattr, const char *buf, size_t count) 71662306a36Sopenharmony_ci{ 71762306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 71862306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 71962306a36Sopenharmony_ci int nr = attr->index; 72062306a36Sopenharmony_ci u8 reg; 72162306a36Sopenharmony_ci unsigned long val; 72262306a36Sopenharmony_ci int err; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci err = kstrtoul(buf, 10, &val); 72562306a36Sopenharmony_ci if (err) 72662306a36Sopenharmony_ci return err; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci if (val < 1 || val > 3) 72962306a36Sopenharmony_ci return -EINVAL; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci if (val > 1) { /* Automatic mode, user can't set PWM value */ 73262306a36Sopenharmony_ci if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr], 73362306a36Sopenharmony_ci S_IRUGO)) 73462306a36Sopenharmony_ci dev_dbg(dev, "chmod -w pwm%d failed\n", nr + 1); 73562306a36Sopenharmony_ci } 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci mutex_lock(&data->update_lock); 73862306a36Sopenharmony_ci reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(nr)) 73962306a36Sopenharmony_ci & ~FAN_CTRL_MODE_MASK; 74062306a36Sopenharmony_ci switch (val) { 74162306a36Sopenharmony_ci case 1: 74262306a36Sopenharmony_ci reg |= FAN_CTRL_MODE_MANUAL; 74362306a36Sopenharmony_ci break; 74462306a36Sopenharmony_ci case 2: 74562306a36Sopenharmony_ci reg |= FAN_CTRL_MODE_TEMPERATURE; 74662306a36Sopenharmony_ci break; 74762306a36Sopenharmony_ci case 3: 74862306a36Sopenharmony_ci reg |= FAN_CTRL_MODE_SPEED; 74962306a36Sopenharmony_ci break; 75062306a36Sopenharmony_ci } 75162306a36Sopenharmony_ci data->fan_ctrl[nr] = reg; 75262306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_FAN_CTRL(nr), reg); 75362306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci if (val == 1) { /* Manual mode, user can set PWM value */ 75662306a36Sopenharmony_ci if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr], 75762306a36Sopenharmony_ci S_IRUGO | S_IWUSR)) 75862306a36Sopenharmony_ci dev_dbg(dev, "chmod +w pwm%d failed\n", nr + 1); 75962306a36Sopenharmony_ci } 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci return count; 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_cistatic ssize_t set_pwm_freq(struct device *dev, struct device_attribute 76562306a36Sopenharmony_ci *devattr, const char *buf, size_t count) 76662306a36Sopenharmony_ci{ 76762306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 76862306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 76962306a36Sopenharmony_ci int nr = attr->index; 77062306a36Sopenharmony_ci unsigned long val; 77162306a36Sopenharmony_ci int err; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci err = kstrtoul(buf, 10, &val); 77462306a36Sopenharmony_ci if (err) 77562306a36Sopenharmony_ci return err; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci mutex_lock(&data->update_lock); 77862306a36Sopenharmony_ci data->pwm_freq[nr] = pwm_freq_to_reg(val); 77962306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_PWM_FREQ(nr), data->pwm_freq[nr]); 78062306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci return count; 78362306a36Sopenharmony_ci} 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_cistatic ssize_t show_pwm_auto_point_temp(struct device *dev, 78662306a36Sopenharmony_ci struct device_attribute *devattr, 78762306a36Sopenharmony_ci char *buf) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 79062306a36Sopenharmony_ci struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); 79162306a36Sopenharmony_ci int pwmnr = attr->nr; 79262306a36Sopenharmony_ci int apnr = attr->index; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci return sprintf(buf, "%ld\n", 79562306a36Sopenharmony_ci temp_from_reg(data->auto_points[pwmnr].temp[apnr])); 79662306a36Sopenharmony_ci} 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_cistatic ssize_t set_pwm_auto_point_temp(struct device *dev, 79962306a36Sopenharmony_ci struct device_attribute *devattr, 80062306a36Sopenharmony_ci const char *buf, size_t count) 80162306a36Sopenharmony_ci{ 80262306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 80362306a36Sopenharmony_ci struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); 80462306a36Sopenharmony_ci int pwmnr = attr->nr; 80562306a36Sopenharmony_ci int apnr = attr->index; 80662306a36Sopenharmony_ci unsigned long val; 80762306a36Sopenharmony_ci int err; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci err = kstrtoul(buf, 10, &val); 81062306a36Sopenharmony_ci if (err) 81162306a36Sopenharmony_ci return err; 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci mutex_lock(&data->update_lock); 81462306a36Sopenharmony_ci data->auto_points[pwmnr].temp[apnr] = temp_to_reg(val); 81562306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr), 81662306a36Sopenharmony_ci data->auto_points[pwmnr].temp[apnr]); 81762306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci return count; 82062306a36Sopenharmony_ci} 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_cistatic ssize_t show_pwm_auto_point_fan(struct device *dev, 82362306a36Sopenharmony_ci struct device_attribute *devattr, 82462306a36Sopenharmony_ci char *buf) 82562306a36Sopenharmony_ci{ 82662306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 82762306a36Sopenharmony_ci struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); 82862306a36Sopenharmony_ci int pwmnr = attr->nr; 82962306a36Sopenharmony_ci int apnr = attr->index; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci return sprintf(buf, "%ld\n", 83262306a36Sopenharmony_ci fan_from_reg(data->auto_points[pwmnr].fan[apnr])); 83362306a36Sopenharmony_ci} 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_cistatic ssize_t set_pwm_auto_point_fan(struct device *dev, 83662306a36Sopenharmony_ci struct device_attribute *devattr, 83762306a36Sopenharmony_ci const char *buf, size_t count) 83862306a36Sopenharmony_ci{ 83962306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 84062306a36Sopenharmony_ci struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); 84162306a36Sopenharmony_ci int pwmnr = attr->nr; 84262306a36Sopenharmony_ci int apnr = attr->index; 84362306a36Sopenharmony_ci unsigned long val; 84462306a36Sopenharmony_ci int err; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci err = kstrtoul(buf, 10, &val); 84762306a36Sopenharmony_ci if (err) 84862306a36Sopenharmony_ci return err; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci mutex_lock(&data->update_lock); 85162306a36Sopenharmony_ci data->auto_points[pwmnr].fan[apnr] = fan_to_reg(val); 85262306a36Sopenharmony_ci f71805f_write16(data, F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr), 85362306a36Sopenharmony_ci data->auto_points[pwmnr].fan[apnr]); 85462306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci return count; 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_cistatic ssize_t show_temp(struct device *dev, struct device_attribute *devattr, 86062306a36Sopenharmony_ci char *buf) 86162306a36Sopenharmony_ci{ 86262306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 86362306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 86462306a36Sopenharmony_ci int nr = attr->index; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr])); 86762306a36Sopenharmony_ci} 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_cistatic ssize_t show_temp_max(struct device *dev, struct device_attribute 87062306a36Sopenharmony_ci *devattr, char *buf) 87162306a36Sopenharmony_ci{ 87262306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 87362306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 87462306a36Sopenharmony_ci int nr = attr->index; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr])); 87762306a36Sopenharmony_ci} 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_cistatic ssize_t show_temp_hyst(struct device *dev, struct device_attribute 88062306a36Sopenharmony_ci *devattr, char *buf) 88162306a36Sopenharmony_ci{ 88262306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 88362306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 88462306a36Sopenharmony_ci int nr = attr->index; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr])); 88762306a36Sopenharmony_ci} 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_cistatic ssize_t show_temp_type(struct device *dev, struct device_attribute 89062306a36Sopenharmony_ci *devattr, char *buf) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 89362306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 89462306a36Sopenharmony_ci int nr = attr->index; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci /* 3 is diode, 4 is thermistor */ 89762306a36Sopenharmony_ci return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4); 89862306a36Sopenharmony_ci} 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_cistatic ssize_t set_temp_max(struct device *dev, struct device_attribute 90162306a36Sopenharmony_ci *devattr, const char *buf, size_t count) 90262306a36Sopenharmony_ci{ 90362306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 90462306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 90562306a36Sopenharmony_ci int nr = attr->index; 90662306a36Sopenharmony_ci long val; 90762306a36Sopenharmony_ci int err; 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci err = kstrtol(buf, 10, &val); 91062306a36Sopenharmony_ci if (err) 91162306a36Sopenharmony_ci return err; 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci mutex_lock(&data->update_lock); 91462306a36Sopenharmony_ci data->temp_high[nr] = temp_to_reg(val); 91562306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]); 91662306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci return count; 91962306a36Sopenharmony_ci} 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_cistatic ssize_t set_temp_hyst(struct device *dev, struct device_attribute 92262306a36Sopenharmony_ci *devattr, const char *buf, size_t count) 92362306a36Sopenharmony_ci{ 92462306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 92562306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 92662306a36Sopenharmony_ci int nr = attr->index; 92762306a36Sopenharmony_ci long val; 92862306a36Sopenharmony_ci int err; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci err = kstrtol(buf, 10, &val); 93162306a36Sopenharmony_ci if (err) 93262306a36Sopenharmony_ci return err; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci mutex_lock(&data->update_lock); 93562306a36Sopenharmony_ci data->temp_hyst[nr] = temp_to_reg(val); 93662306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]); 93762306a36Sopenharmony_ci mutex_unlock(&data->update_lock); 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci return count; 94062306a36Sopenharmony_ci} 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_cistatic ssize_t alarms_in_show(struct device *dev, struct device_attribute 94362306a36Sopenharmony_ci *devattr, char *buf) 94462306a36Sopenharmony_ci{ 94562306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci return sprintf(buf, "%lu\n", data->alarms & 0x7ff); 94862306a36Sopenharmony_ci} 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_cistatic ssize_t alarms_fan_show(struct device *dev, struct device_attribute 95162306a36Sopenharmony_ci *devattr, char *buf) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07); 95662306a36Sopenharmony_ci} 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_cistatic ssize_t alarms_temp_show(struct device *dev, struct device_attribute 95962306a36Sopenharmony_ci *devattr, char *buf) 96062306a36Sopenharmony_ci{ 96162306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07); 96462306a36Sopenharmony_ci} 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_cistatic ssize_t show_alarm(struct device *dev, struct device_attribute 96762306a36Sopenharmony_ci *devattr, char *buf) 96862306a36Sopenharmony_ci{ 96962306a36Sopenharmony_ci struct f71805f_data *data = f71805f_update_device(dev); 97062306a36Sopenharmony_ci struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 97162306a36Sopenharmony_ci int bitnr = attr->index; 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci return sprintf(buf, "%lu\n", (data->alarms >> bitnr) & 1); 97462306a36Sopenharmony_ci} 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_cistatic ssize_t name_show(struct device *dev, struct device_attribute 97762306a36Sopenharmony_ci *devattr, char *buf) 97862306a36Sopenharmony_ci{ 97962306a36Sopenharmony_ci struct f71805f_data *data = dev_get_drvdata(dev); 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci return sprintf(buf, "%s\n", data->name); 98262306a36Sopenharmony_ci} 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL, 0); 98562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, 98662306a36Sopenharmony_ci show_in0_max, set_in0_max, 0); 98762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, 98862306a36Sopenharmony_ci show_in0_min, set_in0_min, 0); 98962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1); 99062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, 99162306a36Sopenharmony_ci show_in_max, set_in_max, 1); 99262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, 99362306a36Sopenharmony_ci show_in_min, set_in_min, 1); 99462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2); 99562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR, 99662306a36Sopenharmony_ci show_in_max, set_in_max, 2); 99762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR, 99862306a36Sopenharmony_ci show_in_min, set_in_min, 2); 99962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3); 100062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR, 100162306a36Sopenharmony_ci show_in_max, set_in_max, 3); 100262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR, 100362306a36Sopenharmony_ci show_in_min, set_in_min, 3); 100462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4); 100562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, 100662306a36Sopenharmony_ci show_in_max, set_in_max, 4); 100762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR, 100862306a36Sopenharmony_ci show_in_min, set_in_min, 4); 100962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5); 101062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR, 101162306a36Sopenharmony_ci show_in_max, set_in_max, 5); 101262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR, 101362306a36Sopenharmony_ci show_in_min, set_in_min, 5); 101462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6); 101562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in6_max, S_IRUGO | S_IWUSR, 101662306a36Sopenharmony_ci show_in_max, set_in_max, 6); 101762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in6_min, S_IRUGO | S_IWUSR, 101862306a36Sopenharmony_ci show_in_min, set_in_min, 6); 101962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7); 102062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in7_max, S_IRUGO | S_IWUSR, 102162306a36Sopenharmony_ci show_in_max, set_in_max, 7); 102262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in7_min, S_IRUGO | S_IWUSR, 102362306a36Sopenharmony_ci show_in_min, set_in_min, 7); 102462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8); 102562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in8_max, S_IRUGO | S_IWUSR, 102662306a36Sopenharmony_ci show_in_max, set_in_max, 8); 102762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR, 102862306a36Sopenharmony_ci show_in_min, set_in_min, 8); 102962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in0, NULL, 9); 103062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in9_max, S_IRUGO | S_IWUSR, 103162306a36Sopenharmony_ci show_in0_max, set_in0_max, 9); 103262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in9_min, S_IRUGO | S_IWUSR, 103362306a36Sopenharmony_ci show_in0_min, set_in0_min, 9); 103462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in0, NULL, 10); 103562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in10_max, S_IRUGO | S_IWUSR, 103662306a36Sopenharmony_ci show_in0_max, set_in0_max, 10); 103762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in10_min, S_IRUGO | S_IWUSR, 103862306a36Sopenharmony_ci show_in0_min, set_in0_min, 10); 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); 104162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, 104262306a36Sopenharmony_ci show_fan_min, set_fan_min, 0); 104362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, 104462306a36Sopenharmony_ci show_fan_target, set_fan_target, 0); 104562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); 104662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, 104762306a36Sopenharmony_ci show_fan_min, set_fan_min, 1); 104862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO | S_IWUSR, 104962306a36Sopenharmony_ci show_fan_target, set_fan_target, 1); 105062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); 105162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR, 105262306a36Sopenharmony_ci show_fan_min, set_fan_min, 2); 105362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan3_target, S_IRUGO | S_IWUSR, 105462306a36Sopenharmony_ci show_fan_target, set_fan_target, 2); 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); 105762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, 105862306a36Sopenharmony_ci show_temp_max, set_temp_max, 0); 105962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, 106062306a36Sopenharmony_ci show_temp_hyst, set_temp_hyst, 0); 106162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0); 106262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); 106362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, 106462306a36Sopenharmony_ci show_temp_max, set_temp_max, 1); 106562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, 106662306a36Sopenharmony_ci show_temp_hyst, set_temp_hyst, 1); 106762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1); 106862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); 106962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR, 107062306a36Sopenharmony_ci show_temp_max, set_temp_max, 2); 107162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, 107262306a36Sopenharmony_ci show_temp_hyst, set_temp_hyst, 2); 107362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2); 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci/* 107662306a36Sopenharmony_ci * pwm (value) files are created read-only, write permission is 107762306a36Sopenharmony_ci * then added or removed dynamically as needed 107862306a36Sopenharmony_ci */ 107962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, show_pwm, set_pwm, 0); 108062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, 108162306a36Sopenharmony_ci show_pwm_enable, set_pwm_enable, 0); 108262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR, 108362306a36Sopenharmony_ci show_pwm_freq, set_pwm_freq, 0); 108462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0); 108562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm2, S_IRUGO, show_pwm, set_pwm, 1); 108662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, 108762306a36Sopenharmony_ci show_pwm_enable, set_pwm_enable, 1); 108862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO | S_IWUSR, 108962306a36Sopenharmony_ci show_pwm_freq, set_pwm_freq, 1); 109062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, NULL, 1); 109162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm3, S_IRUGO, show_pwm, set_pwm, 2); 109262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, 109362306a36Sopenharmony_ci show_pwm_enable, set_pwm_enable, 2); 109462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR, 109562306a36Sopenharmony_ci show_pwm_freq, set_pwm_freq, 2); 109662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR, 109962306a36Sopenharmony_ci show_pwm_auto_point_temp, set_pwm_auto_point_temp, 110062306a36Sopenharmony_ci 0, 0); 110162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_fan, S_IRUGO | S_IWUSR, 110262306a36Sopenharmony_ci show_pwm_auto_point_fan, set_pwm_auto_point_fan, 110362306a36Sopenharmony_ci 0, 0); 110462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR, 110562306a36Sopenharmony_ci show_pwm_auto_point_temp, set_pwm_auto_point_temp, 110662306a36Sopenharmony_ci 0, 1); 110762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_fan, S_IRUGO | S_IWUSR, 110862306a36Sopenharmony_ci show_pwm_auto_point_fan, set_pwm_auto_point_fan, 110962306a36Sopenharmony_ci 0, 1); 111062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR, 111162306a36Sopenharmony_ci show_pwm_auto_point_temp, set_pwm_auto_point_temp, 111262306a36Sopenharmony_ci 0, 2); 111362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_fan, S_IRUGO | S_IWUSR, 111462306a36Sopenharmony_ci show_pwm_auto_point_fan, set_pwm_auto_point_fan, 111562306a36Sopenharmony_ci 0, 2); 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR, 111862306a36Sopenharmony_ci show_pwm_auto_point_temp, set_pwm_auto_point_temp, 111962306a36Sopenharmony_ci 1, 0); 112062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_fan, S_IRUGO | S_IWUSR, 112162306a36Sopenharmony_ci show_pwm_auto_point_fan, set_pwm_auto_point_fan, 112262306a36Sopenharmony_ci 1, 0); 112362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR, 112462306a36Sopenharmony_ci show_pwm_auto_point_temp, set_pwm_auto_point_temp, 112562306a36Sopenharmony_ci 1, 1); 112662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_fan, S_IRUGO | S_IWUSR, 112762306a36Sopenharmony_ci show_pwm_auto_point_fan, set_pwm_auto_point_fan, 112862306a36Sopenharmony_ci 1, 1); 112962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR, 113062306a36Sopenharmony_ci show_pwm_auto_point_temp, set_pwm_auto_point_temp, 113162306a36Sopenharmony_ci 1, 2); 113262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_fan, S_IRUGO | S_IWUSR, 113362306a36Sopenharmony_ci show_pwm_auto_point_fan, set_pwm_auto_point_fan, 113462306a36Sopenharmony_ci 1, 2); 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR, 113762306a36Sopenharmony_ci show_pwm_auto_point_temp, set_pwm_auto_point_temp, 113862306a36Sopenharmony_ci 2, 0); 113962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_fan, S_IRUGO | S_IWUSR, 114062306a36Sopenharmony_ci show_pwm_auto_point_fan, set_pwm_auto_point_fan, 114162306a36Sopenharmony_ci 2, 0); 114262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR, 114362306a36Sopenharmony_ci show_pwm_auto_point_temp, set_pwm_auto_point_temp, 114462306a36Sopenharmony_ci 2, 1); 114562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_fan, S_IRUGO | S_IWUSR, 114662306a36Sopenharmony_ci show_pwm_auto_point_fan, set_pwm_auto_point_fan, 114762306a36Sopenharmony_ci 2, 1); 114862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR, 114962306a36Sopenharmony_ci show_pwm_auto_point_temp, set_pwm_auto_point_temp, 115062306a36Sopenharmony_ci 2, 2); 115162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_fan, S_IRUGO | S_IWUSR, 115262306a36Sopenharmony_ci show_pwm_auto_point_fan, set_pwm_auto_point_fan, 115362306a36Sopenharmony_ci 2, 2); 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); 115662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); 115762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); 115862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); 115962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4); 116062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5); 116162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6); 116262306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7); 116362306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8); 116462306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9); 116562306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10); 116662306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11); 116762306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12); 116862306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13); 116962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16); 117062306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17); 117162306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18); 117262306a36Sopenharmony_cistatic DEVICE_ATTR_RO(alarms_in); 117362306a36Sopenharmony_cistatic DEVICE_ATTR_RO(alarms_fan); 117462306a36Sopenharmony_cistatic DEVICE_ATTR_RO(alarms_temp); 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_cistatic DEVICE_ATTR_RO(name); 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_cistatic struct attribute *f71805f_attributes[] = { 117962306a36Sopenharmony_ci &sensor_dev_attr_in0_input.dev_attr.attr, 118062306a36Sopenharmony_ci &sensor_dev_attr_in0_max.dev_attr.attr, 118162306a36Sopenharmony_ci &sensor_dev_attr_in0_min.dev_attr.attr, 118262306a36Sopenharmony_ci &sensor_dev_attr_in1_input.dev_attr.attr, 118362306a36Sopenharmony_ci &sensor_dev_attr_in1_max.dev_attr.attr, 118462306a36Sopenharmony_ci &sensor_dev_attr_in1_min.dev_attr.attr, 118562306a36Sopenharmony_ci &sensor_dev_attr_in2_input.dev_attr.attr, 118662306a36Sopenharmony_ci &sensor_dev_attr_in2_max.dev_attr.attr, 118762306a36Sopenharmony_ci &sensor_dev_attr_in2_min.dev_attr.attr, 118862306a36Sopenharmony_ci &sensor_dev_attr_in3_input.dev_attr.attr, 118962306a36Sopenharmony_ci &sensor_dev_attr_in3_max.dev_attr.attr, 119062306a36Sopenharmony_ci &sensor_dev_attr_in3_min.dev_attr.attr, 119162306a36Sopenharmony_ci &sensor_dev_attr_in5_input.dev_attr.attr, 119262306a36Sopenharmony_ci &sensor_dev_attr_in5_max.dev_attr.attr, 119362306a36Sopenharmony_ci &sensor_dev_attr_in5_min.dev_attr.attr, 119462306a36Sopenharmony_ci &sensor_dev_attr_in6_input.dev_attr.attr, 119562306a36Sopenharmony_ci &sensor_dev_attr_in6_max.dev_attr.attr, 119662306a36Sopenharmony_ci &sensor_dev_attr_in6_min.dev_attr.attr, 119762306a36Sopenharmony_ci &sensor_dev_attr_in7_input.dev_attr.attr, 119862306a36Sopenharmony_ci &sensor_dev_attr_in7_max.dev_attr.attr, 119962306a36Sopenharmony_ci &sensor_dev_attr_in7_min.dev_attr.attr, 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci &sensor_dev_attr_fan1_input.dev_attr.attr, 120262306a36Sopenharmony_ci &sensor_dev_attr_fan1_min.dev_attr.attr, 120362306a36Sopenharmony_ci &sensor_dev_attr_fan1_alarm.dev_attr.attr, 120462306a36Sopenharmony_ci &sensor_dev_attr_fan1_target.dev_attr.attr, 120562306a36Sopenharmony_ci &sensor_dev_attr_fan2_input.dev_attr.attr, 120662306a36Sopenharmony_ci &sensor_dev_attr_fan2_min.dev_attr.attr, 120762306a36Sopenharmony_ci &sensor_dev_attr_fan2_alarm.dev_attr.attr, 120862306a36Sopenharmony_ci &sensor_dev_attr_fan2_target.dev_attr.attr, 120962306a36Sopenharmony_ci &sensor_dev_attr_fan3_input.dev_attr.attr, 121062306a36Sopenharmony_ci &sensor_dev_attr_fan3_min.dev_attr.attr, 121162306a36Sopenharmony_ci &sensor_dev_attr_fan3_alarm.dev_attr.attr, 121262306a36Sopenharmony_ci &sensor_dev_attr_fan3_target.dev_attr.attr, 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci &sensor_dev_attr_pwm1.dev_attr.attr, 121562306a36Sopenharmony_ci &sensor_dev_attr_pwm1_enable.dev_attr.attr, 121662306a36Sopenharmony_ci &sensor_dev_attr_pwm1_mode.dev_attr.attr, 121762306a36Sopenharmony_ci &sensor_dev_attr_pwm2.dev_attr.attr, 121862306a36Sopenharmony_ci &sensor_dev_attr_pwm2_enable.dev_attr.attr, 121962306a36Sopenharmony_ci &sensor_dev_attr_pwm2_mode.dev_attr.attr, 122062306a36Sopenharmony_ci &sensor_dev_attr_pwm3.dev_attr.attr, 122162306a36Sopenharmony_ci &sensor_dev_attr_pwm3_enable.dev_attr.attr, 122262306a36Sopenharmony_ci &sensor_dev_attr_pwm3_mode.dev_attr.attr, 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci &sensor_dev_attr_temp1_input.dev_attr.attr, 122562306a36Sopenharmony_ci &sensor_dev_attr_temp1_max.dev_attr.attr, 122662306a36Sopenharmony_ci &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 122762306a36Sopenharmony_ci &sensor_dev_attr_temp1_type.dev_attr.attr, 122862306a36Sopenharmony_ci &sensor_dev_attr_temp2_input.dev_attr.attr, 122962306a36Sopenharmony_ci &sensor_dev_attr_temp2_max.dev_attr.attr, 123062306a36Sopenharmony_ci &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, 123162306a36Sopenharmony_ci &sensor_dev_attr_temp2_type.dev_attr.attr, 123262306a36Sopenharmony_ci &sensor_dev_attr_temp3_input.dev_attr.attr, 123362306a36Sopenharmony_ci &sensor_dev_attr_temp3_max.dev_attr.attr, 123462306a36Sopenharmony_ci &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, 123562306a36Sopenharmony_ci &sensor_dev_attr_temp3_type.dev_attr.attr, 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, 123862306a36Sopenharmony_ci &sensor_dev_attr_pwm1_auto_point1_fan.dev_attr.attr, 123962306a36Sopenharmony_ci &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, 124062306a36Sopenharmony_ci &sensor_dev_attr_pwm1_auto_point2_fan.dev_attr.attr, 124162306a36Sopenharmony_ci &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, 124262306a36Sopenharmony_ci &sensor_dev_attr_pwm1_auto_point3_fan.dev_attr.attr, 124362306a36Sopenharmony_ci &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr, 124462306a36Sopenharmony_ci &sensor_dev_attr_pwm2_auto_point1_fan.dev_attr.attr, 124562306a36Sopenharmony_ci &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, 124662306a36Sopenharmony_ci &sensor_dev_attr_pwm2_auto_point2_fan.dev_attr.attr, 124762306a36Sopenharmony_ci &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr, 124862306a36Sopenharmony_ci &sensor_dev_attr_pwm2_auto_point3_fan.dev_attr.attr, 124962306a36Sopenharmony_ci &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, 125062306a36Sopenharmony_ci &sensor_dev_attr_pwm3_auto_point1_fan.dev_attr.attr, 125162306a36Sopenharmony_ci &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, 125262306a36Sopenharmony_ci &sensor_dev_attr_pwm3_auto_point2_fan.dev_attr.attr, 125362306a36Sopenharmony_ci &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, 125462306a36Sopenharmony_ci &sensor_dev_attr_pwm3_auto_point3_fan.dev_attr.attr, 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci &sensor_dev_attr_in0_alarm.dev_attr.attr, 125762306a36Sopenharmony_ci &sensor_dev_attr_in1_alarm.dev_attr.attr, 125862306a36Sopenharmony_ci &sensor_dev_attr_in2_alarm.dev_attr.attr, 125962306a36Sopenharmony_ci &sensor_dev_attr_in3_alarm.dev_attr.attr, 126062306a36Sopenharmony_ci &sensor_dev_attr_in5_alarm.dev_attr.attr, 126162306a36Sopenharmony_ci &sensor_dev_attr_in6_alarm.dev_attr.attr, 126262306a36Sopenharmony_ci &sensor_dev_attr_in7_alarm.dev_attr.attr, 126362306a36Sopenharmony_ci &dev_attr_alarms_in.attr, 126462306a36Sopenharmony_ci &sensor_dev_attr_temp1_alarm.dev_attr.attr, 126562306a36Sopenharmony_ci &sensor_dev_attr_temp2_alarm.dev_attr.attr, 126662306a36Sopenharmony_ci &sensor_dev_attr_temp3_alarm.dev_attr.attr, 126762306a36Sopenharmony_ci &dev_attr_alarms_temp.attr, 126862306a36Sopenharmony_ci &dev_attr_alarms_fan.attr, 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci &dev_attr_name.attr, 127162306a36Sopenharmony_ci NULL 127262306a36Sopenharmony_ci}; 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_cistatic const struct attribute_group f71805f_group = { 127562306a36Sopenharmony_ci .attrs = f71805f_attributes, 127662306a36Sopenharmony_ci}; 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_cistatic struct attribute *f71805f_attributes_optin[4][5] = { 127962306a36Sopenharmony_ci { 128062306a36Sopenharmony_ci &sensor_dev_attr_in4_input.dev_attr.attr, 128162306a36Sopenharmony_ci &sensor_dev_attr_in4_max.dev_attr.attr, 128262306a36Sopenharmony_ci &sensor_dev_attr_in4_min.dev_attr.attr, 128362306a36Sopenharmony_ci &sensor_dev_attr_in4_alarm.dev_attr.attr, 128462306a36Sopenharmony_ci NULL 128562306a36Sopenharmony_ci }, { 128662306a36Sopenharmony_ci &sensor_dev_attr_in8_input.dev_attr.attr, 128762306a36Sopenharmony_ci &sensor_dev_attr_in8_max.dev_attr.attr, 128862306a36Sopenharmony_ci &sensor_dev_attr_in8_min.dev_attr.attr, 128962306a36Sopenharmony_ci &sensor_dev_attr_in8_alarm.dev_attr.attr, 129062306a36Sopenharmony_ci NULL 129162306a36Sopenharmony_ci }, { 129262306a36Sopenharmony_ci &sensor_dev_attr_in9_input.dev_attr.attr, 129362306a36Sopenharmony_ci &sensor_dev_attr_in9_max.dev_attr.attr, 129462306a36Sopenharmony_ci &sensor_dev_attr_in9_min.dev_attr.attr, 129562306a36Sopenharmony_ci &sensor_dev_attr_in9_alarm.dev_attr.attr, 129662306a36Sopenharmony_ci NULL 129762306a36Sopenharmony_ci }, { 129862306a36Sopenharmony_ci &sensor_dev_attr_in10_input.dev_attr.attr, 129962306a36Sopenharmony_ci &sensor_dev_attr_in10_max.dev_attr.attr, 130062306a36Sopenharmony_ci &sensor_dev_attr_in10_min.dev_attr.attr, 130162306a36Sopenharmony_ci &sensor_dev_attr_in10_alarm.dev_attr.attr, 130262306a36Sopenharmony_ci NULL 130362306a36Sopenharmony_ci } 130462306a36Sopenharmony_ci}; 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_cistatic const struct attribute_group f71805f_group_optin[4] = { 130762306a36Sopenharmony_ci { .attrs = f71805f_attributes_optin[0] }, 130862306a36Sopenharmony_ci { .attrs = f71805f_attributes_optin[1] }, 130962306a36Sopenharmony_ci { .attrs = f71805f_attributes_optin[2] }, 131062306a36Sopenharmony_ci { .attrs = f71805f_attributes_optin[3] }, 131162306a36Sopenharmony_ci}; 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci/* 131462306a36Sopenharmony_ci * We don't include pwm_freq files in the arrays above, because they must be 131562306a36Sopenharmony_ci * created conditionally (only if pwm_mode is 1 == PWM) 131662306a36Sopenharmony_ci */ 131762306a36Sopenharmony_cistatic struct attribute *f71805f_attributes_pwm_freq[] = { 131862306a36Sopenharmony_ci &sensor_dev_attr_pwm1_freq.dev_attr.attr, 131962306a36Sopenharmony_ci &sensor_dev_attr_pwm2_freq.dev_attr.attr, 132062306a36Sopenharmony_ci &sensor_dev_attr_pwm3_freq.dev_attr.attr, 132162306a36Sopenharmony_ci NULL 132262306a36Sopenharmony_ci}; 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_cistatic const struct attribute_group f71805f_group_pwm_freq = { 132562306a36Sopenharmony_ci .attrs = f71805f_attributes_pwm_freq, 132662306a36Sopenharmony_ci}; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci/* We also need an indexed access to pwmN files to toggle writability */ 132962306a36Sopenharmony_cistatic struct attribute *f71805f_attr_pwm[] = { 133062306a36Sopenharmony_ci &sensor_dev_attr_pwm1.dev_attr.attr, 133162306a36Sopenharmony_ci &sensor_dev_attr_pwm2.dev_attr.attr, 133262306a36Sopenharmony_ci &sensor_dev_attr_pwm3.dev_attr.attr, 133362306a36Sopenharmony_ci}; 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci/* 133662306a36Sopenharmony_ci * Device registration and initialization 133762306a36Sopenharmony_ci */ 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_cistatic void f71805f_init_device(struct f71805f_data *data) 134062306a36Sopenharmony_ci{ 134162306a36Sopenharmony_ci u8 reg; 134262306a36Sopenharmony_ci int i; 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci reg = f71805f_read8(data, F71805F_REG_START); 134562306a36Sopenharmony_ci if ((reg & 0x41) != 0x01) { 134662306a36Sopenharmony_ci pr_debug("Starting monitoring operations\n"); 134762306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40); 134862306a36Sopenharmony_ci } 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci /* 135162306a36Sopenharmony_ci * Fan monitoring can be disabled. If it is, we won't be polling 135262306a36Sopenharmony_ci * the register values, and won't create the related sysfs files. 135362306a36Sopenharmony_ci */ 135462306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 135562306a36Sopenharmony_ci data->fan_ctrl[i] = f71805f_read8(data, 135662306a36Sopenharmony_ci F71805F_REG_FAN_CTRL(i)); 135762306a36Sopenharmony_ci /* 135862306a36Sopenharmony_ci * Clear latch full bit, else "speed mode" fan speed control 135962306a36Sopenharmony_ci * doesn't work 136062306a36Sopenharmony_ci */ 136162306a36Sopenharmony_ci if (data->fan_ctrl[i] & FAN_CTRL_LATCH_FULL) { 136262306a36Sopenharmony_ci data->fan_ctrl[i] &= ~FAN_CTRL_LATCH_FULL; 136362306a36Sopenharmony_ci f71805f_write8(data, F71805F_REG_FAN_CTRL(i), 136462306a36Sopenharmony_ci data->fan_ctrl[i]); 136562306a36Sopenharmony_ci } 136662306a36Sopenharmony_ci } 136762306a36Sopenharmony_ci} 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_cistatic int f71805f_probe(struct platform_device *pdev) 137062306a36Sopenharmony_ci{ 137162306a36Sopenharmony_ci struct f71805f_sio_data *sio_data = dev_get_platdata(&pdev->dev); 137262306a36Sopenharmony_ci struct f71805f_data *data; 137362306a36Sopenharmony_ci struct resource *res; 137462306a36Sopenharmony_ci int i, err; 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci static const char * const names[] = { 137762306a36Sopenharmony_ci "f71805f", 137862306a36Sopenharmony_ci "f71872f", 137962306a36Sopenharmony_ci }; 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci data = devm_kzalloc(&pdev->dev, sizeof(struct f71805f_data), 138262306a36Sopenharmony_ci GFP_KERNEL); 138362306a36Sopenharmony_ci if (!data) 138462306a36Sopenharmony_ci return -ENOMEM; 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_IO, 0); 138762306a36Sopenharmony_ci if (!devm_request_region(&pdev->dev, res->start + ADDR_REG_OFFSET, 2, 138862306a36Sopenharmony_ci DRVNAME)) { 138962306a36Sopenharmony_ci dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n", 139062306a36Sopenharmony_ci (unsigned long)(res->start + ADDR_REG_OFFSET), 139162306a36Sopenharmony_ci (unsigned long)(res->start + ADDR_REG_OFFSET + 1)); 139262306a36Sopenharmony_ci return -EBUSY; 139362306a36Sopenharmony_ci } 139462306a36Sopenharmony_ci data->addr = res->start; 139562306a36Sopenharmony_ci data->name = names[sio_data->kind]; 139662306a36Sopenharmony_ci mutex_init(&data->update_lock); 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci platform_set_drvdata(pdev, data); 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci /* Some voltage inputs depend on chip model and configuration */ 140162306a36Sopenharmony_ci switch (sio_data->kind) { 140262306a36Sopenharmony_ci case f71805f: 140362306a36Sopenharmony_ci data->has_in = 0x1ff; 140462306a36Sopenharmony_ci break; 140562306a36Sopenharmony_ci case f71872f: 140662306a36Sopenharmony_ci data->has_in = 0x6ef; 140762306a36Sopenharmony_ci if (sio_data->fnsel1 & 0x01) 140862306a36Sopenharmony_ci data->has_in |= (1 << 4); /* in4 */ 140962306a36Sopenharmony_ci if (sio_data->fnsel1 & 0x02) 141062306a36Sopenharmony_ci data->has_in |= (1 << 8); /* in8 */ 141162306a36Sopenharmony_ci break; 141262306a36Sopenharmony_ci } 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci /* Initialize the F71805F chip */ 141562306a36Sopenharmony_ci f71805f_init_device(data); 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci /* Register sysfs interface files */ 141862306a36Sopenharmony_ci err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group); 141962306a36Sopenharmony_ci if (err) 142062306a36Sopenharmony_ci return err; 142162306a36Sopenharmony_ci if (data->has_in & (1 << 4)) { /* in4 */ 142262306a36Sopenharmony_ci err = sysfs_create_group(&pdev->dev.kobj, 142362306a36Sopenharmony_ci &f71805f_group_optin[0]); 142462306a36Sopenharmony_ci if (err) 142562306a36Sopenharmony_ci goto exit_remove_files; 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci if (data->has_in & (1 << 8)) { /* in8 */ 142862306a36Sopenharmony_ci err = sysfs_create_group(&pdev->dev.kobj, 142962306a36Sopenharmony_ci &f71805f_group_optin[1]); 143062306a36Sopenharmony_ci if (err) 143162306a36Sopenharmony_ci goto exit_remove_files; 143262306a36Sopenharmony_ci } 143362306a36Sopenharmony_ci if (data->has_in & (1 << 9)) { /* in9 (F71872F/FG only) */ 143462306a36Sopenharmony_ci err = sysfs_create_group(&pdev->dev.kobj, 143562306a36Sopenharmony_ci &f71805f_group_optin[2]); 143662306a36Sopenharmony_ci if (err) 143762306a36Sopenharmony_ci goto exit_remove_files; 143862306a36Sopenharmony_ci } 143962306a36Sopenharmony_ci if (data->has_in & (1 << 10)) { /* in9 (F71872F/FG only) */ 144062306a36Sopenharmony_ci err = sysfs_create_group(&pdev->dev.kobj, 144162306a36Sopenharmony_ci &f71805f_group_optin[3]); 144262306a36Sopenharmony_ci if (err) 144362306a36Sopenharmony_ci goto exit_remove_files; 144462306a36Sopenharmony_ci } 144562306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 144662306a36Sopenharmony_ci /* If control mode is PWM, create pwm_freq file */ 144762306a36Sopenharmony_ci if (!(data->fan_ctrl[i] & FAN_CTRL_DC_MODE)) { 144862306a36Sopenharmony_ci err = sysfs_create_file(&pdev->dev.kobj, 144962306a36Sopenharmony_ci f71805f_attributes_pwm_freq[i]); 145062306a36Sopenharmony_ci if (err) 145162306a36Sopenharmony_ci goto exit_remove_files; 145262306a36Sopenharmony_ci } 145362306a36Sopenharmony_ci /* If PWM is in manual mode, add write permission */ 145462306a36Sopenharmony_ci if (data->fan_ctrl[i] & FAN_CTRL_MODE_MANUAL) { 145562306a36Sopenharmony_ci err = sysfs_chmod_file(&pdev->dev.kobj, 145662306a36Sopenharmony_ci f71805f_attr_pwm[i], 145762306a36Sopenharmony_ci S_IRUGO | S_IWUSR); 145862306a36Sopenharmony_ci if (err) { 145962306a36Sopenharmony_ci dev_err(&pdev->dev, "chmod +w pwm%d failed\n", 146062306a36Sopenharmony_ci i + 1); 146162306a36Sopenharmony_ci goto exit_remove_files; 146262306a36Sopenharmony_ci } 146362306a36Sopenharmony_ci } 146462306a36Sopenharmony_ci } 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci data->hwmon_dev = hwmon_device_register(&pdev->dev); 146762306a36Sopenharmony_ci if (IS_ERR(data->hwmon_dev)) { 146862306a36Sopenharmony_ci err = PTR_ERR(data->hwmon_dev); 146962306a36Sopenharmony_ci dev_err(&pdev->dev, "Class registration failed (%d)\n", err); 147062306a36Sopenharmony_ci goto exit_remove_files; 147162306a36Sopenharmony_ci } 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci return 0; 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ciexit_remove_files: 147662306a36Sopenharmony_ci sysfs_remove_group(&pdev->dev.kobj, &f71805f_group); 147762306a36Sopenharmony_ci for (i = 0; i < 4; i++) 147862306a36Sopenharmony_ci sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); 147962306a36Sopenharmony_ci sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); 148062306a36Sopenharmony_ci return err; 148162306a36Sopenharmony_ci} 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_cistatic int f71805f_remove(struct platform_device *pdev) 148462306a36Sopenharmony_ci{ 148562306a36Sopenharmony_ci struct f71805f_data *data = platform_get_drvdata(pdev); 148662306a36Sopenharmony_ci int i; 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci hwmon_device_unregister(data->hwmon_dev); 148962306a36Sopenharmony_ci sysfs_remove_group(&pdev->dev.kobj, &f71805f_group); 149062306a36Sopenharmony_ci for (i = 0; i < 4; i++) 149162306a36Sopenharmony_ci sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); 149262306a36Sopenharmony_ci sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci return 0; 149562306a36Sopenharmony_ci} 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_cistatic struct platform_driver f71805f_driver = { 149862306a36Sopenharmony_ci .driver = { 149962306a36Sopenharmony_ci .name = DRVNAME, 150062306a36Sopenharmony_ci }, 150162306a36Sopenharmony_ci .probe = f71805f_probe, 150262306a36Sopenharmony_ci .remove = f71805f_remove, 150362306a36Sopenharmony_ci}; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_cistatic int __init f71805f_device_add(unsigned short address, 150662306a36Sopenharmony_ci const struct f71805f_sio_data *sio_data) 150762306a36Sopenharmony_ci{ 150862306a36Sopenharmony_ci struct resource res = { 150962306a36Sopenharmony_ci .start = address, 151062306a36Sopenharmony_ci .end = address + REGION_LENGTH - 1, 151162306a36Sopenharmony_ci .flags = IORESOURCE_IO, 151262306a36Sopenharmony_ci }; 151362306a36Sopenharmony_ci int err; 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci pdev = platform_device_alloc(DRVNAME, address); 151662306a36Sopenharmony_ci if (!pdev) { 151762306a36Sopenharmony_ci err = -ENOMEM; 151862306a36Sopenharmony_ci pr_err("Device allocation failed\n"); 151962306a36Sopenharmony_ci goto exit; 152062306a36Sopenharmony_ci } 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci res.name = pdev->name; 152362306a36Sopenharmony_ci err = acpi_check_resource_conflict(&res); 152462306a36Sopenharmony_ci if (err) 152562306a36Sopenharmony_ci goto exit_device_put; 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci err = platform_device_add_resources(pdev, &res, 1); 152862306a36Sopenharmony_ci if (err) { 152962306a36Sopenharmony_ci pr_err("Device resource addition failed (%d)\n", err); 153062306a36Sopenharmony_ci goto exit_device_put; 153162306a36Sopenharmony_ci } 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci err = platform_device_add_data(pdev, sio_data, 153462306a36Sopenharmony_ci sizeof(struct f71805f_sio_data)); 153562306a36Sopenharmony_ci if (err) { 153662306a36Sopenharmony_ci pr_err("Platform data allocation failed\n"); 153762306a36Sopenharmony_ci goto exit_device_put; 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci err = platform_device_add(pdev); 154162306a36Sopenharmony_ci if (err) { 154262306a36Sopenharmony_ci pr_err("Device addition failed (%d)\n", err); 154362306a36Sopenharmony_ci goto exit_device_put; 154462306a36Sopenharmony_ci } 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci return 0; 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ciexit_device_put: 154962306a36Sopenharmony_ci platform_device_put(pdev); 155062306a36Sopenharmony_ciexit: 155162306a36Sopenharmony_ci return err; 155262306a36Sopenharmony_ci} 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_cistatic int __init f71805f_find(int sioaddr, unsigned short *address, 155562306a36Sopenharmony_ci struct f71805f_sio_data *sio_data) 155662306a36Sopenharmony_ci{ 155762306a36Sopenharmony_ci int err; 155862306a36Sopenharmony_ci u16 devid; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci static const char * const names[] = { 156162306a36Sopenharmony_ci "F71805F/FG", 156262306a36Sopenharmony_ci "F71872F/FG or F71806F/FG", 156362306a36Sopenharmony_ci }; 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci err = superio_enter(sioaddr); 156662306a36Sopenharmony_ci if (err) 156762306a36Sopenharmony_ci return err; 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci err = -ENODEV; 157062306a36Sopenharmony_ci devid = superio_inw(sioaddr, SIO_REG_MANID); 157162306a36Sopenharmony_ci if (devid != SIO_FINTEK_ID) 157262306a36Sopenharmony_ci goto exit; 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ci devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); 157562306a36Sopenharmony_ci switch (devid) { 157662306a36Sopenharmony_ci case SIO_F71805F_ID: 157762306a36Sopenharmony_ci sio_data->kind = f71805f; 157862306a36Sopenharmony_ci break; 157962306a36Sopenharmony_ci case SIO_F71872F_ID: 158062306a36Sopenharmony_ci sio_data->kind = f71872f; 158162306a36Sopenharmony_ci sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1); 158262306a36Sopenharmony_ci break; 158362306a36Sopenharmony_ci default: 158462306a36Sopenharmony_ci pr_info("Unsupported Fintek device, skipping\n"); 158562306a36Sopenharmony_ci goto exit; 158662306a36Sopenharmony_ci } 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci superio_select(sioaddr, F71805F_LD_HWM); 158962306a36Sopenharmony_ci if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { 159062306a36Sopenharmony_ci pr_warn("Device not activated, skipping\n"); 159162306a36Sopenharmony_ci goto exit; 159262306a36Sopenharmony_ci } 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci *address = superio_inw(sioaddr, SIO_REG_ADDR); 159562306a36Sopenharmony_ci if (*address == 0) { 159662306a36Sopenharmony_ci pr_warn("Base address not set, skipping\n"); 159762306a36Sopenharmony_ci goto exit; 159862306a36Sopenharmony_ci } 159962306a36Sopenharmony_ci *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci err = 0; 160262306a36Sopenharmony_ci pr_info("Found %s chip at %#x, revision %u\n", 160362306a36Sopenharmony_ci names[sio_data->kind], *address, 160462306a36Sopenharmony_ci superio_inb(sioaddr, SIO_REG_DEVREV)); 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_ciexit: 160762306a36Sopenharmony_ci superio_exit(sioaddr); 160862306a36Sopenharmony_ci return err; 160962306a36Sopenharmony_ci} 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_cistatic int __init f71805f_init(void) 161262306a36Sopenharmony_ci{ 161362306a36Sopenharmony_ci int err; 161462306a36Sopenharmony_ci unsigned short address; 161562306a36Sopenharmony_ci struct f71805f_sio_data sio_data; 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ci if (f71805f_find(0x2e, &address, &sio_data) 161862306a36Sopenharmony_ci && f71805f_find(0x4e, &address, &sio_data)) 161962306a36Sopenharmony_ci return -ENODEV; 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci err = platform_driver_register(&f71805f_driver); 162262306a36Sopenharmony_ci if (err) 162362306a36Sopenharmony_ci goto exit; 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci /* Sets global pdev as a side effect */ 162662306a36Sopenharmony_ci err = f71805f_device_add(address, &sio_data); 162762306a36Sopenharmony_ci if (err) 162862306a36Sopenharmony_ci goto exit_driver; 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci return 0; 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ciexit_driver: 163362306a36Sopenharmony_ci platform_driver_unregister(&f71805f_driver); 163462306a36Sopenharmony_ciexit: 163562306a36Sopenharmony_ci return err; 163662306a36Sopenharmony_ci} 163762306a36Sopenharmony_ci 163862306a36Sopenharmony_cistatic void __exit f71805f_exit(void) 163962306a36Sopenharmony_ci{ 164062306a36Sopenharmony_ci platform_device_unregister(pdev); 164162306a36Sopenharmony_ci platform_driver_unregister(&f71805f_driver); 164262306a36Sopenharmony_ci} 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ciMODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); 164562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 164662306a36Sopenharmony_ciMODULE_DESCRIPTION("F71805F/F71872F hardware monitoring driver"); 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_cimodule_init(f71805f_init); 164962306a36Sopenharmony_cimodule_exit(f71805f_exit); 1650