174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29873964dSCharles Spirakis /*
3ec1c3194SGuenter Roeck * w83791d.c - Part of lm_sensors, Linux kernel modules for hardware
4ec1c3194SGuenter Roeck * monitoring
5ec1c3194SGuenter Roeck *
6ec1c3194SGuenter Roeck * Copyright (C) 2006-2007 Charles Spirakis <bezaur@gmail.com>
79873964dSCharles Spirakis */
89873964dSCharles Spirakis
99873964dSCharles Spirakis /*
10ec1c3194SGuenter Roeck * Supports following chips:
11ec1c3194SGuenter Roeck *
12ec1c3194SGuenter Roeck * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
13ec1c3194SGuenter Roeck * w83791d 10 5 5 3 0x71 0x5ca3 yes no
14ec1c3194SGuenter Roeck *
15ec1c3194SGuenter Roeck * The w83791d chip appears to be part way between the 83781d and the
16ec1c3194SGuenter Roeck * 83792d. Thus, this file is derived from both the w83792d.c and
17ec1c3194SGuenter Roeck * w83781d.c files.
18ec1c3194SGuenter Roeck *
19ec1c3194SGuenter Roeck * The w83791g chip is the same as the w83791d but lead-free.
209873964dSCharles Spirakis */
219873964dSCharles Spirakis
229873964dSCharles Spirakis #include <linux/module.h>
239873964dSCharles Spirakis #include <linux/init.h>
249873964dSCharles Spirakis #include <linux/slab.h>
259873964dSCharles Spirakis #include <linux/i2c.h>
269873964dSCharles Spirakis #include <linux/hwmon.h>
279873964dSCharles Spirakis #include <linux/hwmon-vid.h>
289873964dSCharles Spirakis #include <linux/hwmon-sysfs.h>
299873964dSCharles Spirakis #include <linux/err.h>
309873964dSCharles Spirakis #include <linux/mutex.h>
31dcd8f392SJean Delvare #include <linux/jiffies.h>
329873964dSCharles Spirakis
339873964dSCharles Spirakis #define NUMBER_OF_VIN 10
349873964dSCharles Spirakis #define NUMBER_OF_FANIN 5
359873964dSCharles Spirakis #define NUMBER_OF_TEMPIN 3
366495ce18SMarc Hulsman #define NUMBER_OF_PWM 5
379873964dSCharles Spirakis
389873964dSCharles Spirakis /* Addresses to scan */
3925e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
4025e9c86dSMark M. Hoffman I2C_CLIENT_END };
419873964dSCharles Spirakis
429873964dSCharles Spirakis /* Insmod parameters */
433aed198cSJean Delvare
443aed198cSJean Delvare static unsigned short force_subclients[4];
453aed198cSJean Delvare module_param_array(force_subclients, short, NULL, 0);
46b55f3757SGuenter Roeck MODULE_PARM_DESC(force_subclients,
47b55f3757SGuenter Roeck "List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
489873964dSCharles Spirakis
4990ab5ee9SRusty Russell static bool reset;
509873964dSCharles Spirakis module_param(reset, bool, 0);
519873964dSCharles Spirakis MODULE_PARM_DESC(reset, "Set to one to force a hardware chip reset");
529873964dSCharles Spirakis
5390ab5ee9SRusty Russell static bool init;
549873964dSCharles Spirakis module_param(init, bool, 0);
559873964dSCharles Spirakis MODULE_PARM_DESC(init, "Set to one to force extra software initialization");
569873964dSCharles Spirakis
579873964dSCharles Spirakis /* The W83791D registers */
589873964dSCharles Spirakis static const u8 W83791D_REG_IN[NUMBER_OF_VIN] = {
599873964dSCharles Spirakis 0x20, /* VCOREA in DataSheet */
609873964dSCharles Spirakis 0x21, /* VINR0 in DataSheet */
619873964dSCharles Spirakis 0x22, /* +3.3VIN in DataSheet */
629873964dSCharles Spirakis 0x23, /* VDD5V in DataSheet */
639873964dSCharles Spirakis 0x24, /* +12VIN in DataSheet */
649873964dSCharles Spirakis 0x25, /* -12VIN in DataSheet */
659873964dSCharles Spirakis 0x26, /* -5VIN in DataSheet */
669873964dSCharles Spirakis 0xB0, /* 5VSB in DataSheet */
679873964dSCharles Spirakis 0xB1, /* VBAT in DataSheet */
689873964dSCharles Spirakis 0xB2 /* VINR1 in DataSheet */
699873964dSCharles Spirakis };
709873964dSCharles Spirakis
719873964dSCharles Spirakis static const u8 W83791D_REG_IN_MAX[NUMBER_OF_VIN] = {
729873964dSCharles Spirakis 0x2B, /* VCOREA High Limit in DataSheet */
739873964dSCharles Spirakis 0x2D, /* VINR0 High Limit in DataSheet */
749873964dSCharles Spirakis 0x2F, /* +3.3VIN High Limit in DataSheet */
759873964dSCharles Spirakis 0x31, /* VDD5V High Limit in DataSheet */
769873964dSCharles Spirakis 0x33, /* +12VIN High Limit in DataSheet */
779873964dSCharles Spirakis 0x35, /* -12VIN High Limit in DataSheet */
789873964dSCharles Spirakis 0x37, /* -5VIN High Limit in DataSheet */
799873964dSCharles Spirakis 0xB4, /* 5VSB High Limit in DataSheet */
809873964dSCharles Spirakis 0xB6, /* VBAT High Limit in DataSheet */
819873964dSCharles Spirakis 0xB8 /* VINR1 High Limit in DataSheet */
829873964dSCharles Spirakis };
839873964dSCharles Spirakis static const u8 W83791D_REG_IN_MIN[NUMBER_OF_VIN] = {
849873964dSCharles Spirakis 0x2C, /* VCOREA Low Limit in DataSheet */
859873964dSCharles Spirakis 0x2E, /* VINR0 Low Limit in DataSheet */
869873964dSCharles Spirakis 0x30, /* +3.3VIN Low Limit in DataSheet */
879873964dSCharles Spirakis 0x32, /* VDD5V Low Limit in DataSheet */
889873964dSCharles Spirakis 0x34, /* +12VIN Low Limit in DataSheet */
899873964dSCharles Spirakis 0x36, /* -12VIN Low Limit in DataSheet */
909873964dSCharles Spirakis 0x38, /* -5VIN Low Limit in DataSheet */
919873964dSCharles Spirakis 0xB5, /* 5VSB Low Limit in DataSheet */
929873964dSCharles Spirakis 0xB7, /* VBAT Low Limit in DataSheet */
939873964dSCharles Spirakis 0xB9 /* VINR1 Low Limit in DataSheet */
949873964dSCharles Spirakis };
959873964dSCharles Spirakis static const u8 W83791D_REG_FAN[NUMBER_OF_FANIN] = {
969873964dSCharles Spirakis 0x28, /* FAN 1 Count in DataSheet */
979873964dSCharles Spirakis 0x29, /* FAN 2 Count in DataSheet */
989873964dSCharles Spirakis 0x2A, /* FAN 3 Count in DataSheet */
999873964dSCharles Spirakis 0xBA, /* FAN 4 Count in DataSheet */
1009873964dSCharles Spirakis 0xBB, /* FAN 5 Count in DataSheet */
1019873964dSCharles Spirakis };
1029873964dSCharles Spirakis static const u8 W83791D_REG_FAN_MIN[NUMBER_OF_FANIN] = {
1039873964dSCharles Spirakis 0x3B, /* FAN 1 Count Low Limit in DataSheet */
1049873964dSCharles Spirakis 0x3C, /* FAN 2 Count Low Limit in DataSheet */
1059873964dSCharles Spirakis 0x3D, /* FAN 3 Count Low Limit in DataSheet */
1069873964dSCharles Spirakis 0xBC, /* FAN 4 Count Low Limit in DataSheet */
1079873964dSCharles Spirakis 0xBD, /* FAN 5 Count Low Limit in DataSheet */
1089873964dSCharles Spirakis };
1099873964dSCharles Spirakis
1106495ce18SMarc Hulsman static const u8 W83791D_REG_PWM[NUMBER_OF_PWM] = {
1116495ce18SMarc Hulsman 0x81, /* PWM 1 duty cycle register in DataSheet */
1126495ce18SMarc Hulsman 0x83, /* PWM 2 duty cycle register in DataSheet */
1136495ce18SMarc Hulsman 0x94, /* PWM 3 duty cycle register in DataSheet */
1146495ce18SMarc Hulsman 0xA0, /* PWM 4 duty cycle register in DataSheet */
1156495ce18SMarc Hulsman 0xA1, /* PWM 5 duty cycle register in DataSheet */
1166495ce18SMarc Hulsman };
1176495ce18SMarc Hulsman
118a5a4598cSMarc Hulsman static const u8 W83791D_REG_TEMP_TARGET[3] = {
119a5a4598cSMarc Hulsman 0x85, /* PWM 1 target temperature for temp 1 */
120a5a4598cSMarc Hulsman 0x86, /* PWM 2 target temperature for temp 2 */
121a5a4598cSMarc Hulsman 0x96, /* PWM 3 target temperature for temp 3 */
122a5a4598cSMarc Hulsman };
123a5a4598cSMarc Hulsman
124a5a4598cSMarc Hulsman static const u8 W83791D_REG_TEMP_TOL[2] = {
125a5a4598cSMarc Hulsman 0x87, /* PWM 1/2 temperature tolerance */
126a5a4598cSMarc Hulsman 0x97, /* PWM 3 temperature tolerance */
127a5a4598cSMarc Hulsman };
128a5a4598cSMarc Hulsman
1299873964dSCharles Spirakis static const u8 W83791D_REG_FAN_CFG[2] = {
1309873964dSCharles Spirakis 0x84, /* FAN 1/2 configuration */
1319873964dSCharles Spirakis 0x95, /* FAN 3 configuration */
1329873964dSCharles Spirakis };
1339873964dSCharles Spirakis
1349873964dSCharles Spirakis static const u8 W83791D_REG_FAN_DIV[3] = {
1359873964dSCharles Spirakis 0x47, /* contains FAN1 and FAN2 Divisor */
1369873964dSCharles Spirakis 0x4b, /* contains FAN3 Divisor */
1379873964dSCharles Spirakis 0x5C, /* contains FAN4 and FAN5 Divisor */
1389873964dSCharles Spirakis };
1399873964dSCharles Spirakis
1409873964dSCharles Spirakis #define W83791D_REG_BANK 0x4E
1419873964dSCharles Spirakis #define W83791D_REG_TEMP2_CONFIG 0xC2
1429873964dSCharles Spirakis #define W83791D_REG_TEMP3_CONFIG 0xCA
1439873964dSCharles Spirakis
1449873964dSCharles Spirakis static const u8 W83791D_REG_TEMP1[3] = {
1459873964dSCharles Spirakis 0x27, /* TEMP 1 in DataSheet */
1469873964dSCharles Spirakis 0x39, /* TEMP 1 Over in DataSheet */
1479873964dSCharles Spirakis 0x3A, /* TEMP 1 Hyst in DataSheet */
1489873964dSCharles Spirakis };
1499873964dSCharles Spirakis
1509873964dSCharles Spirakis static const u8 W83791D_REG_TEMP_ADD[2][6] = {
1519873964dSCharles Spirakis {0xC0, /* TEMP 2 in DataSheet */
1529873964dSCharles Spirakis 0xC1, /* TEMP 2(0.5 deg) in DataSheet */
1539873964dSCharles Spirakis 0xC5, /* TEMP 2 Over High part in DataSheet */
1549873964dSCharles Spirakis 0xC6, /* TEMP 2 Over Low part in DataSheet */
1559873964dSCharles Spirakis 0xC3, /* TEMP 2 Thyst High part in DataSheet */
1569873964dSCharles Spirakis 0xC4}, /* TEMP 2 Thyst Low part in DataSheet */
1579873964dSCharles Spirakis {0xC8, /* TEMP 3 in DataSheet */
1589873964dSCharles Spirakis 0xC9, /* TEMP 3(0.5 deg) in DataSheet */
1599873964dSCharles Spirakis 0xCD, /* TEMP 3 Over High part in DataSheet */
1609873964dSCharles Spirakis 0xCE, /* TEMP 3 Over Low part in DataSheet */
1619873964dSCharles Spirakis 0xCB, /* TEMP 3 Thyst High part in DataSheet */
1629873964dSCharles Spirakis 0xCC} /* TEMP 3 Thyst Low part in DataSheet */
1639873964dSCharles Spirakis };
1649873964dSCharles Spirakis
1659873964dSCharles Spirakis #define W83791D_REG_BEEP_CONFIG 0x4D
1669873964dSCharles Spirakis
1679873964dSCharles Spirakis static const u8 W83791D_REG_BEEP_CTRL[3] = {
1689873964dSCharles Spirakis 0x56, /* BEEP Control Register 1 */
1699873964dSCharles Spirakis 0x57, /* BEEP Control Register 2 */
1709873964dSCharles Spirakis 0xA3, /* BEEP Control Register 3 */
1719873964dSCharles Spirakis };
1729873964dSCharles Spirakis
1736e1ecd9bSMarc Hulsman #define W83791D_REG_GPIO 0x15
1749873964dSCharles Spirakis #define W83791D_REG_CONFIG 0x40
1759873964dSCharles Spirakis #define W83791D_REG_VID_FANDIV 0x47
1769873964dSCharles Spirakis #define W83791D_REG_DID_VID4 0x49
1779873964dSCharles Spirakis #define W83791D_REG_WCHIPID 0x58
1789873964dSCharles Spirakis #define W83791D_REG_CHIPMAN 0x4F
1799873964dSCharles Spirakis #define W83791D_REG_PIN 0x4B
1809873964dSCharles Spirakis #define W83791D_REG_I2C_SUBADDR 0x4A
1819873964dSCharles Spirakis
1829873964dSCharles Spirakis #define W83791D_REG_ALARM1 0xA9 /* realtime status register1 */
1839873964dSCharles Spirakis #define W83791D_REG_ALARM2 0xAA /* realtime status register2 */
1849873964dSCharles Spirakis #define W83791D_REG_ALARM3 0xAB /* realtime status register3 */
1859873964dSCharles Spirakis
1869873964dSCharles Spirakis #define W83791D_REG_VBAT 0x5D
1879873964dSCharles Spirakis #define W83791D_REG_I2C_ADDR 0x48
1889873964dSCharles Spirakis
189ec1c3194SGuenter Roeck /*
190ec1c3194SGuenter Roeck * The SMBus locks itself. The Winbond W83791D has a bank select register
191ec1c3194SGuenter Roeck * (index 0x4e), but the driver only accesses registers in bank 0. Since
192ec1c3194SGuenter Roeck * we don't switch banks, we don't need any special code to handle
193ec1c3194SGuenter Roeck * locking access between bank switches
194ec1c3194SGuenter Roeck */
w83791d_read(struct i2c_client * client,u8 reg)1959873964dSCharles Spirakis static inline int w83791d_read(struct i2c_client *client, u8 reg)
1969873964dSCharles Spirakis {
1979873964dSCharles Spirakis return i2c_smbus_read_byte_data(client, reg);
1989873964dSCharles Spirakis }
1999873964dSCharles Spirakis
w83791d_write(struct i2c_client * client,u8 reg,u8 value)2009873964dSCharles Spirakis static inline int w83791d_write(struct i2c_client *client, u8 reg, u8 value)
2019873964dSCharles Spirakis {
2029873964dSCharles Spirakis return i2c_smbus_write_byte_data(client, reg, value);
2039873964dSCharles Spirakis }
2049873964dSCharles Spirakis
205ec1c3194SGuenter Roeck /*
206ec1c3194SGuenter Roeck * The analog voltage inputs have 16mV LSB. Since the sysfs output is
207ec1c3194SGuenter Roeck * in mV as would be measured on the chip input pin, need to just
208ec1c3194SGuenter Roeck * multiply/divide by 16 to translate from/to register values.
209ec1c3194SGuenter Roeck */
2102a844c14SGuenter Roeck #define IN_TO_REG(val) (clamp_val((((val) + 8) / 16), 0, 255))
2119873964dSCharles Spirakis #define IN_FROM_REG(val) ((val) * 16)
2129873964dSCharles Spirakis
fan_to_reg(long rpm,int div)2139873964dSCharles Spirakis static u8 fan_to_reg(long rpm, int div)
2149873964dSCharles Spirakis {
2159873964dSCharles Spirakis if (rpm == 0)
2169873964dSCharles Spirakis return 255;
2172a844c14SGuenter Roeck rpm = clamp_val(rpm, 1, 1000000);
2182a844c14SGuenter Roeck return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
2199873964dSCharles Spirakis }
2209873964dSCharles Spirakis
2219873964dSCharles Spirakis #define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
2229873964dSCharles Spirakis ((val) == 255 ? 0 : \
2239873964dSCharles Spirakis 1350000 / ((val) * (div))))
2249873964dSCharles Spirakis
2259873964dSCharles Spirakis /* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */
2269873964dSCharles Spirakis #define TEMP1_FROM_REG(val) ((val) * 1000)
2279873964dSCharles Spirakis #define TEMP1_TO_REG(val) ((val) <= -128000 ? -128 : \
2289873964dSCharles Spirakis (val) >= 127000 ? 127 : \
2299873964dSCharles Spirakis (val) < 0 ? ((val) - 500) / 1000 : \
2309873964dSCharles Spirakis ((val) + 500) / 1000)
2319873964dSCharles Spirakis
232ec1c3194SGuenter Roeck /*
233ec1c3194SGuenter Roeck * for temp2 and temp3 which are 9-bit resolution, LSB = 0.5 degree Celsius
234ec1c3194SGuenter Roeck * Assumes the top 8 bits are the integral amount and the bottom 8 bits
235ec1c3194SGuenter Roeck * are the fractional amount. Since we only have 0.5 degree resolution,
236ec1c3194SGuenter Roeck * the bottom 7 bits will always be zero
237ec1c3194SGuenter Roeck */
2389873964dSCharles Spirakis #define TEMP23_FROM_REG(val) ((val) / 128 * 500)
23940ebdb92SGuenter Roeck #define TEMP23_TO_REG(val) (DIV_ROUND_CLOSEST(clamp_val((val), -128000, \
24040ebdb92SGuenter Roeck 127500), 500) * 128)
2419873964dSCharles Spirakis
242a5a4598cSMarc Hulsman /* for thermal cruise target temp, 7-bits, LSB = 1 degree Celsius */
24340ebdb92SGuenter Roeck #define TARGET_TEMP_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), 0, 127000), \
24440ebdb92SGuenter Roeck 1000)
245a5a4598cSMarc Hulsman
246a5a4598cSMarc Hulsman /* for thermal cruise temp tolerance, 4-bits, LSB = 1 degree Celsius */
24740ebdb92SGuenter Roeck #define TOL_TEMP_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), 0, 15000), \
24840ebdb92SGuenter Roeck 1000)
2499873964dSCharles Spirakis
2509873964dSCharles Spirakis #define BEEP_MASK_TO_REG(val) ((val) & 0xffffff)
2519873964dSCharles Spirakis #define BEEP_MASK_FROM_REG(val) ((val) & 0xffffff)
2529873964dSCharles Spirakis
2539873964dSCharles Spirakis #define DIV_FROM_REG(val) (1 << (val))
2549873964dSCharles Spirakis
div_to_reg(int nr,long val)2559873964dSCharles Spirakis static u8 div_to_reg(int nr, long val)
2569873964dSCharles Spirakis {
2579873964dSCharles Spirakis int i;
2589873964dSCharles Spirakis
259ad02ad85SMarc Hulsman /* fan divisors max out at 128 */
2602a844c14SGuenter Roeck val = clamp_val(val, 1, 128) >> 1;
2619873964dSCharles Spirakis for (i = 0; i < 7; i++) {
2629873964dSCharles Spirakis if (val == 0)
2639873964dSCharles Spirakis break;
2649873964dSCharles Spirakis val >>= 1;
2659873964dSCharles Spirakis }
2669873964dSCharles Spirakis return (u8) i;
2679873964dSCharles Spirakis }
2689873964dSCharles Spirakis
2699873964dSCharles Spirakis struct w83791d_data {
2701beeffe4STony Jones struct device *hwmon_dev;
2719873964dSCharles Spirakis struct mutex update_lock;
2729873964dSCharles Spirakis
273952a11caSPaul Fertser bool valid; /* true if following fields are valid */
2749873964dSCharles Spirakis unsigned long last_updated; /* In jiffies */
2759873964dSCharles Spirakis
2769873964dSCharles Spirakis /* volts */
2779873964dSCharles Spirakis u8 in[NUMBER_OF_VIN]; /* Register value */
2789873964dSCharles Spirakis u8 in_max[NUMBER_OF_VIN]; /* Register value */
2799873964dSCharles Spirakis u8 in_min[NUMBER_OF_VIN]; /* Register value */
2809873964dSCharles Spirakis
2819873964dSCharles Spirakis /* fans */
2829873964dSCharles Spirakis u8 fan[NUMBER_OF_FANIN]; /* Register value */
2839873964dSCharles Spirakis u8 fan_min[NUMBER_OF_FANIN]; /* Register value */
2849873964dSCharles Spirakis u8 fan_div[NUMBER_OF_FANIN]; /* Register encoding, shifted right */
2859873964dSCharles Spirakis
2869873964dSCharles Spirakis /* Temperature sensors */
2879873964dSCharles Spirakis
2889873964dSCharles Spirakis s8 temp1[3]; /* current, over, thyst */
2899873964dSCharles Spirakis s16 temp_add[2][3]; /* fixed point value. Top 8 bits are the
290ec1c3194SGuenter Roeck * integral part, bottom 8 bits are the
291ec1c3194SGuenter Roeck * fractional part. We only use the top
292ec1c3194SGuenter Roeck * 9 bits as the resolution is only
293ec1c3194SGuenter Roeck * to the 0.5 degree C...
294ec1c3194SGuenter Roeck * two sensors with three values
295ec1c3194SGuenter Roeck * (cur, over, hyst)
296ec1c3194SGuenter Roeck */
2979873964dSCharles Spirakis
2986495ce18SMarc Hulsman /* PWMs */
2996495ce18SMarc Hulsman u8 pwm[5]; /* pwm duty cycle */
300b5938f8cSMarc Hulsman u8 pwm_enable[3]; /* pwm enable status for fan 1-3
301ec1c3194SGuenter Roeck * (fan 4-5 only support manual mode)
302ec1c3194SGuenter Roeck */
3036495ce18SMarc Hulsman
304a5a4598cSMarc Hulsman u8 temp_target[3]; /* pwm 1-3 target temperature */
305a5a4598cSMarc Hulsman u8 temp_tolerance[3]; /* pwm 1-3 temperature tolerance */
306a5a4598cSMarc Hulsman
3079873964dSCharles Spirakis /* Misc */
3089873964dSCharles Spirakis u32 alarms; /* realtime status register encoding,combined */
3099873964dSCharles Spirakis u8 beep_enable; /* Global beep enable */
3109873964dSCharles Spirakis u32 beep_mask; /* Mask off specific beeps */
3119873964dSCharles Spirakis u8 vid; /* Register encoding, combined */
3129873964dSCharles Spirakis u8 vrm; /* hwmon-vid */
3139873964dSCharles Spirakis };
3149873964dSCharles Spirakis
31577b5b8a8SStephen Kitt static int w83791d_probe(struct i2c_client *client);
316310ec792SJean Delvare static int w83791d_detect(struct i2c_client *client,
317cb0c1af3SJean Delvare struct i2c_board_info *info);
318ed5c2f5fSUwe Kleine-König static void w83791d_remove(struct i2c_client *client);
3199873964dSCharles Spirakis
3207cbe1ceeSChris Peterson static int w83791d_read(struct i2c_client *client, u8 reg);
3217cbe1ceeSChris Peterson static int w83791d_write(struct i2c_client *client, u8 reg, u8 value);
3229873964dSCharles Spirakis static struct w83791d_data *w83791d_update_device(struct device *dev);
3239873964dSCharles Spirakis
3249873964dSCharles Spirakis #ifdef DEBUG
3259873964dSCharles Spirakis static void w83791d_print_debug(struct w83791d_data *data, struct device *dev);
3269873964dSCharles Spirakis #endif
3279873964dSCharles Spirakis
3289873964dSCharles Spirakis static void w83791d_init_client(struct i2c_client *client);
3299873964dSCharles Spirakis
330cb0c1af3SJean Delvare static const struct i2c_device_id w83791d_id[] = {
3311f86df49SJean Delvare { "w83791d", 0 },
332cb0c1af3SJean Delvare { }
333cb0c1af3SJean Delvare };
334cb0c1af3SJean Delvare MODULE_DEVICE_TABLE(i2c, w83791d_id);
335cb0c1af3SJean Delvare
3369873964dSCharles Spirakis static struct i2c_driver w83791d_driver = {
337cb0c1af3SJean Delvare .class = I2C_CLASS_HWMON,
3389873964dSCharles Spirakis .driver = {
3399873964dSCharles Spirakis .name = "w83791d",
3409873964dSCharles Spirakis },
341*1975d167SUwe Kleine-König .probe = w83791d_probe,
342cb0c1af3SJean Delvare .remove = w83791d_remove,
343cb0c1af3SJean Delvare .id_table = w83791d_id,
344cb0c1af3SJean Delvare .detect = w83791d_detect,
345c3813d6aSJean Delvare .address_list = normal_i2c,
3469873964dSCharles Spirakis };
3479873964dSCharles Spirakis
3489873964dSCharles Spirakis /* following are the sysfs callback functions */
3499873964dSCharles Spirakis #define show_in_reg(reg) \
3509873964dSCharles Spirakis static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
3519873964dSCharles Spirakis char *buf) \
3529873964dSCharles Spirakis { \
3539873964dSCharles Spirakis struct sensor_device_attribute *sensor_attr = \
3549873964dSCharles Spirakis to_sensor_dev_attr(attr); \
3559873964dSCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev); \
3569873964dSCharles Spirakis int nr = sensor_attr->index; \
3579873964dSCharles Spirakis return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \
3589873964dSCharles Spirakis }
3599873964dSCharles Spirakis
3609873964dSCharles Spirakis show_in_reg(in);
3619873964dSCharles Spirakis show_in_reg(in_min);
3629873964dSCharles Spirakis show_in_reg(in_max);
3639873964dSCharles Spirakis
3649873964dSCharles Spirakis #define store_in_reg(REG, reg) \
3659873964dSCharles Spirakis static ssize_t store_in_##reg(struct device *dev, \
3669873964dSCharles Spirakis struct device_attribute *attr, \
3679873964dSCharles Spirakis const char *buf, size_t count) \
3689873964dSCharles Spirakis { \
3699873964dSCharles Spirakis struct sensor_device_attribute *sensor_attr = \
3709873964dSCharles Spirakis to_sensor_dev_attr(attr); \
3719873964dSCharles Spirakis struct i2c_client *client = to_i2c_client(dev); \
3729873964dSCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client); \
3739873964dSCharles Spirakis int nr = sensor_attr->index; \
374ec1c3194SGuenter Roeck unsigned long val; \
375ec1c3194SGuenter Roeck int err = kstrtoul(buf, 10, &val); \
376ec1c3194SGuenter Roeck if (err) \
377ec1c3194SGuenter Roeck return err; \
3789873964dSCharles Spirakis mutex_lock(&data->update_lock); \
3799873964dSCharles Spirakis data->in_##reg[nr] = IN_TO_REG(val); \
3809873964dSCharles Spirakis w83791d_write(client, W83791D_REG_IN_##REG[nr], data->in_##reg[nr]); \
3819873964dSCharles Spirakis mutex_unlock(&data->update_lock); \
3829873964dSCharles Spirakis \
3839873964dSCharles Spirakis return count; \
3849873964dSCharles Spirakis }
3859873964dSCharles Spirakis store_in_reg(MIN, min);
3869873964dSCharles Spirakis store_in_reg(MAX, max);
3879873964dSCharles Spirakis
3889873964dSCharles Spirakis static struct sensor_device_attribute sda_in_input[] = {
3899873964dSCharles Spirakis SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
3909873964dSCharles Spirakis SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
3919873964dSCharles Spirakis SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
3929873964dSCharles Spirakis SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
3939873964dSCharles Spirakis SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
3949873964dSCharles Spirakis SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
3959873964dSCharles Spirakis SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
3969873964dSCharles Spirakis SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
3979873964dSCharles Spirakis SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
3989873964dSCharles Spirakis SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),
3999873964dSCharles Spirakis };
4009873964dSCharles Spirakis
4019873964dSCharles Spirakis static struct sensor_device_attribute sda_in_min[] = {
4029873964dSCharles Spirakis SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
4039873964dSCharles Spirakis SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
4049873964dSCharles Spirakis SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
4059873964dSCharles Spirakis SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
4069873964dSCharles Spirakis SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
4079873964dSCharles Spirakis SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
4089873964dSCharles Spirakis SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
4099873964dSCharles Spirakis SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
4109873964dSCharles Spirakis SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
4119873964dSCharles Spirakis SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
4129873964dSCharles Spirakis };
4139873964dSCharles Spirakis
4149873964dSCharles Spirakis static struct sensor_device_attribute sda_in_max[] = {
4159873964dSCharles Spirakis SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
4169873964dSCharles Spirakis SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
4179873964dSCharles Spirakis SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
4189873964dSCharles Spirakis SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
4199873964dSCharles Spirakis SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
4209873964dSCharles Spirakis SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
4219873964dSCharles Spirakis SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
4229873964dSCharles Spirakis SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
4239873964dSCharles Spirakis SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
4249873964dSCharles Spirakis SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
4259873964dSCharles Spirakis };
4269873964dSCharles Spirakis
42764383123SCharles Spirakis
show_beep(struct device * dev,struct device_attribute * attr,char * buf)42864383123SCharles Spirakis static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
42964383123SCharles Spirakis char *buf)
43064383123SCharles Spirakis {
43164383123SCharles Spirakis struct sensor_device_attribute *sensor_attr =
43264383123SCharles Spirakis to_sensor_dev_attr(attr);
43364383123SCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev);
43464383123SCharles Spirakis int bitnr = sensor_attr->index;
43564383123SCharles Spirakis
43664383123SCharles Spirakis return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1);
43764383123SCharles Spirakis }
43864383123SCharles Spirakis
store_beep(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)43964383123SCharles Spirakis static ssize_t store_beep(struct device *dev, struct device_attribute *attr,
44064383123SCharles Spirakis const char *buf, size_t count)
44164383123SCharles Spirakis {
44264383123SCharles Spirakis struct sensor_device_attribute *sensor_attr =
44364383123SCharles Spirakis to_sensor_dev_attr(attr);
44464383123SCharles Spirakis struct i2c_client *client = to_i2c_client(dev);
44564383123SCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client);
44664383123SCharles Spirakis int bitnr = sensor_attr->index;
44764383123SCharles Spirakis int bytenr = bitnr / 8;
448ec1c3194SGuenter Roeck unsigned long val;
449ec1c3194SGuenter Roeck int err;
450ec1c3194SGuenter Roeck
451ec1c3194SGuenter Roeck err = kstrtoul(buf, 10, &val);
452ec1c3194SGuenter Roeck if (err)
453ec1c3194SGuenter Roeck return err;
454ec1c3194SGuenter Roeck
455ec1c3194SGuenter Roeck val = val ? 1 : 0;
45664383123SCharles Spirakis
45764383123SCharles Spirakis mutex_lock(&data->update_lock);
45864383123SCharles Spirakis
45964383123SCharles Spirakis data->beep_mask &= ~(0xff << (bytenr * 8));
46064383123SCharles Spirakis data->beep_mask |= w83791d_read(client, W83791D_REG_BEEP_CTRL[bytenr])
46164383123SCharles Spirakis << (bytenr * 8);
46264383123SCharles Spirakis
46364383123SCharles Spirakis data->beep_mask &= ~(1 << bitnr);
46464383123SCharles Spirakis data->beep_mask |= val << bitnr;
46564383123SCharles Spirakis
46664383123SCharles Spirakis w83791d_write(client, W83791D_REG_BEEP_CTRL[bytenr],
46764383123SCharles Spirakis (data->beep_mask >> (bytenr * 8)) & 0xff);
46864383123SCharles Spirakis
46964383123SCharles Spirakis mutex_unlock(&data->update_lock);
47064383123SCharles Spirakis
47164383123SCharles Spirakis return count;
47264383123SCharles Spirakis }
47364383123SCharles Spirakis
show_alarm(struct device * dev,struct device_attribute * attr,char * buf)47464383123SCharles Spirakis static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
47564383123SCharles Spirakis char *buf)
47664383123SCharles Spirakis {
47764383123SCharles Spirakis struct sensor_device_attribute *sensor_attr =
47864383123SCharles Spirakis to_sensor_dev_attr(attr);
47964383123SCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev);
48064383123SCharles Spirakis int bitnr = sensor_attr->index;
48164383123SCharles Spirakis
48264383123SCharles Spirakis return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
48364383123SCharles Spirakis }
48464383123SCharles Spirakis
485ec1c3194SGuenter Roeck /*
486ec1c3194SGuenter Roeck * Note: The bitmask for the beep enable/disable is different than
487ec1c3194SGuenter Roeck * the bitmask for the alarm.
488ec1c3194SGuenter Roeck */
48964383123SCharles Spirakis static struct sensor_device_attribute sda_in_beep[] = {
49064383123SCharles Spirakis SENSOR_ATTR(in0_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 0),
49164383123SCharles Spirakis SENSOR_ATTR(in1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 13),
49264383123SCharles Spirakis SENSOR_ATTR(in2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 2),
49364383123SCharles Spirakis SENSOR_ATTR(in3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 3),
49464383123SCharles Spirakis SENSOR_ATTR(in4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 8),
49564383123SCharles Spirakis SENSOR_ATTR(in5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 9),
49664383123SCharles Spirakis SENSOR_ATTR(in6_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 10),
49764383123SCharles Spirakis SENSOR_ATTR(in7_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 16),
49864383123SCharles Spirakis SENSOR_ATTR(in8_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 17),
49964383123SCharles Spirakis SENSOR_ATTR(in9_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 14),
50064383123SCharles Spirakis };
50164383123SCharles Spirakis
50264383123SCharles Spirakis static struct sensor_device_attribute sda_in_alarm[] = {
50364383123SCharles Spirakis SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0),
50464383123SCharles Spirakis SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1),
50564383123SCharles Spirakis SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2),
50664383123SCharles Spirakis SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3),
50764383123SCharles Spirakis SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8),
50864383123SCharles Spirakis SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9),
50964383123SCharles Spirakis SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10),
51064383123SCharles Spirakis SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 19),
51164383123SCharles Spirakis SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20),
51264383123SCharles Spirakis SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 14),
51364383123SCharles Spirakis };
51464383123SCharles Spirakis
5159873964dSCharles Spirakis #define show_fan_reg(reg) \
5169873964dSCharles Spirakis static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
5179873964dSCharles Spirakis char *buf) \
5189873964dSCharles Spirakis { \
5199873964dSCharles Spirakis struct sensor_device_attribute *sensor_attr = \
5209873964dSCharles Spirakis to_sensor_dev_attr(attr); \
5219873964dSCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev); \
5229873964dSCharles Spirakis int nr = sensor_attr->index; \
5239873964dSCharles Spirakis return sprintf(buf, "%d\n", \
5249873964dSCharles Spirakis FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
5259873964dSCharles Spirakis }
5269873964dSCharles Spirakis
5279873964dSCharles Spirakis show_fan_reg(fan);
5289873964dSCharles Spirakis show_fan_reg(fan_min);
5299873964dSCharles Spirakis
store_fan_min(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)5309873964dSCharles Spirakis static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
5319873964dSCharles Spirakis const char *buf, size_t count)
5329873964dSCharles Spirakis {
5339873964dSCharles Spirakis struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
5349873964dSCharles Spirakis struct i2c_client *client = to_i2c_client(dev);
5359873964dSCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client);
5369873964dSCharles Spirakis int nr = sensor_attr->index;
537ec1c3194SGuenter Roeck unsigned long val;
538ec1c3194SGuenter Roeck int err;
539ec1c3194SGuenter Roeck
540ec1c3194SGuenter Roeck err = kstrtoul(buf, 10, &val);
541ec1c3194SGuenter Roeck if (err)
542ec1c3194SGuenter Roeck return err;
5439873964dSCharles Spirakis
5449873964dSCharles Spirakis mutex_lock(&data->update_lock);
5459873964dSCharles Spirakis data->fan_min[nr] = fan_to_reg(val, DIV_FROM_REG(data->fan_div[nr]));
5469873964dSCharles Spirakis w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);
5479873964dSCharles Spirakis mutex_unlock(&data->update_lock);
5489873964dSCharles Spirakis
5499873964dSCharles Spirakis return count;
5509873964dSCharles Spirakis }
5519873964dSCharles Spirakis
show_fan_div(struct device * dev,struct device_attribute * attr,char * buf)5529873964dSCharles Spirakis static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
5539873964dSCharles Spirakis char *buf)
5549873964dSCharles Spirakis {
5559873964dSCharles Spirakis struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
5569873964dSCharles Spirakis int nr = sensor_attr->index;
5579873964dSCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev);
5589873964dSCharles Spirakis return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr]));
5599873964dSCharles Spirakis }
5609873964dSCharles Spirakis
561ec1c3194SGuenter Roeck /*
562ec1c3194SGuenter Roeck * Note: we save and restore the fan minimum here, because its value is
563ec1c3194SGuenter Roeck * determined in part by the fan divisor. This follows the principle of
564ec1c3194SGuenter Roeck * least surprise; the user doesn't expect the fan minimum to change just
565ec1c3194SGuenter Roeck * because the divisor changed.
566ec1c3194SGuenter Roeck */
store_fan_div(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)5679873964dSCharles Spirakis static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
5689873964dSCharles Spirakis const char *buf, size_t count)
5699873964dSCharles Spirakis {
5709873964dSCharles Spirakis struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
5719873964dSCharles Spirakis struct i2c_client *client = to_i2c_client(dev);
5729873964dSCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client);
5739873964dSCharles Spirakis int nr = sensor_attr->index;
5749873964dSCharles Spirakis unsigned long min;
5759873964dSCharles Spirakis u8 tmp_fan_div;
5769873964dSCharles Spirakis u8 fan_div_reg;
577ad02ad85SMarc Hulsman u8 vbat_reg;
5789873964dSCharles Spirakis int indx = 0;
5799873964dSCharles Spirakis u8 keep_mask = 0;
5809873964dSCharles Spirakis u8 new_shift = 0;
581ec1c3194SGuenter Roeck unsigned long val;
582ec1c3194SGuenter Roeck int err;
583ec1c3194SGuenter Roeck
584ec1c3194SGuenter Roeck err = kstrtoul(buf, 10, &val);
585ec1c3194SGuenter Roeck if (err)
586ec1c3194SGuenter Roeck return err;
5879873964dSCharles Spirakis
5889873964dSCharles Spirakis /* Save fan_min */
5899873964dSCharles Spirakis min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
5909873964dSCharles Spirakis
5919873964dSCharles Spirakis mutex_lock(&data->update_lock);
592ec1c3194SGuenter Roeck data->fan_div[nr] = div_to_reg(nr, val);
5939873964dSCharles Spirakis
5949873964dSCharles Spirakis switch (nr) {
5959873964dSCharles Spirakis case 0:
5969873964dSCharles Spirakis indx = 0;
5979873964dSCharles Spirakis keep_mask = 0xcf;
5989873964dSCharles Spirakis new_shift = 4;
5999873964dSCharles Spirakis break;
6009873964dSCharles Spirakis case 1:
6019873964dSCharles Spirakis indx = 0;
6029873964dSCharles Spirakis keep_mask = 0x3f;
6039873964dSCharles Spirakis new_shift = 6;
6049873964dSCharles Spirakis break;
6059873964dSCharles Spirakis case 2:
6069873964dSCharles Spirakis indx = 1;
6079873964dSCharles Spirakis keep_mask = 0x3f;
6089873964dSCharles Spirakis new_shift = 6;
6099873964dSCharles Spirakis break;
6109873964dSCharles Spirakis case 3:
6119873964dSCharles Spirakis indx = 2;
6129873964dSCharles Spirakis keep_mask = 0xf8;
6139873964dSCharles Spirakis new_shift = 0;
6149873964dSCharles Spirakis break;
6159873964dSCharles Spirakis case 4:
6169873964dSCharles Spirakis indx = 2;
6179873964dSCharles Spirakis keep_mask = 0x8f;
6189873964dSCharles Spirakis new_shift = 4;
6199873964dSCharles Spirakis break;
6209873964dSCharles Spirakis #ifdef DEBUG
6219873964dSCharles Spirakis default:
6229873964dSCharles Spirakis dev_warn(dev, "store_fan_div: Unexpected nr seen: %d\n", nr);
6239873964dSCharles Spirakis count = -EINVAL;
6249873964dSCharles Spirakis goto err_exit;
6259873964dSCharles Spirakis #endif
6269873964dSCharles Spirakis }
6279873964dSCharles Spirakis
6289873964dSCharles Spirakis fan_div_reg = w83791d_read(client, W83791D_REG_FAN_DIV[indx])
6299873964dSCharles Spirakis & keep_mask;
6309873964dSCharles Spirakis tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask;
6319873964dSCharles Spirakis
6329873964dSCharles Spirakis w83791d_write(client, W83791D_REG_FAN_DIV[indx],
6339873964dSCharles Spirakis fan_div_reg | tmp_fan_div);
6349873964dSCharles Spirakis
635ad02ad85SMarc Hulsman /* Bit 2 of fans 0-2 is stored in the vbat register (bits 5-7) */
636ad02ad85SMarc Hulsman if (nr < 3) {
637ad02ad85SMarc Hulsman keep_mask = ~(1 << (nr + 5));
638ad02ad85SMarc Hulsman vbat_reg = w83791d_read(client, W83791D_REG_VBAT)
639ad02ad85SMarc Hulsman & keep_mask;
640ad02ad85SMarc Hulsman tmp_fan_div = (data->fan_div[nr] << (3 + nr)) & ~keep_mask;
641ad02ad85SMarc Hulsman w83791d_write(client, W83791D_REG_VBAT,
642ad02ad85SMarc Hulsman vbat_reg | tmp_fan_div);
643ad02ad85SMarc Hulsman }
644ad02ad85SMarc Hulsman
6459873964dSCharles Spirakis /* Restore fan_min */
6469873964dSCharles Spirakis data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr]));
6479873964dSCharles Spirakis w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);
6489873964dSCharles Spirakis
6499873964dSCharles Spirakis #ifdef DEBUG
6509873964dSCharles Spirakis err_exit:
6519873964dSCharles Spirakis #endif
6529873964dSCharles Spirakis mutex_unlock(&data->update_lock);
6539873964dSCharles Spirakis
6549873964dSCharles Spirakis return count;
6559873964dSCharles Spirakis }
6569873964dSCharles Spirakis
6579873964dSCharles Spirakis static struct sensor_device_attribute sda_fan_input[] = {
6589873964dSCharles Spirakis SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
6599873964dSCharles Spirakis SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
6609873964dSCharles Spirakis SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
6619873964dSCharles Spirakis SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
6629873964dSCharles Spirakis SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
6639873964dSCharles Spirakis };
6649873964dSCharles Spirakis
6659873964dSCharles Spirakis static struct sensor_device_attribute sda_fan_min[] = {
6669873964dSCharles Spirakis SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO,
6679873964dSCharles Spirakis show_fan_min, store_fan_min, 0),
6689873964dSCharles Spirakis SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO,
6699873964dSCharles Spirakis show_fan_min, store_fan_min, 1),
6709873964dSCharles Spirakis SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO,
6719873964dSCharles Spirakis show_fan_min, store_fan_min, 2),
6729873964dSCharles Spirakis SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO,
6739873964dSCharles Spirakis show_fan_min, store_fan_min, 3),
6749873964dSCharles Spirakis SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO,
6759873964dSCharles Spirakis show_fan_min, store_fan_min, 4),
6769873964dSCharles Spirakis };
6779873964dSCharles Spirakis
6789873964dSCharles Spirakis static struct sensor_device_attribute sda_fan_div[] = {
6799873964dSCharles Spirakis SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO,
6809873964dSCharles Spirakis show_fan_div, store_fan_div, 0),
6819873964dSCharles Spirakis SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO,
6829873964dSCharles Spirakis show_fan_div, store_fan_div, 1),
6839873964dSCharles Spirakis SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO,
6849873964dSCharles Spirakis show_fan_div, store_fan_div, 2),
6859873964dSCharles Spirakis SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO,
6869873964dSCharles Spirakis show_fan_div, store_fan_div, 3),
6879873964dSCharles Spirakis SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO,
6889873964dSCharles Spirakis show_fan_div, store_fan_div, 4),
6899873964dSCharles Spirakis };
6909873964dSCharles Spirakis
69164383123SCharles Spirakis static struct sensor_device_attribute sda_fan_beep[] = {
69264383123SCharles Spirakis SENSOR_ATTR(fan1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 6),
69364383123SCharles Spirakis SENSOR_ATTR(fan2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 7),
69464383123SCharles Spirakis SENSOR_ATTR(fan3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 11),
69564383123SCharles Spirakis SENSOR_ATTR(fan4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 21),
69664383123SCharles Spirakis SENSOR_ATTR(fan5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 22),
69764383123SCharles Spirakis };
69864383123SCharles Spirakis
69964383123SCharles Spirakis static struct sensor_device_attribute sda_fan_alarm[] = {
70064383123SCharles Spirakis SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6),
70164383123SCharles Spirakis SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7),
70264383123SCharles Spirakis SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11),
70364383123SCharles Spirakis SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21),
70464383123SCharles Spirakis SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22),
70564383123SCharles Spirakis };
70664383123SCharles Spirakis
7076495ce18SMarc Hulsman /* read/write PWMs */
show_pwm(struct device * dev,struct device_attribute * attr,char * buf)7086495ce18SMarc Hulsman static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
7096495ce18SMarc Hulsman char *buf)
7106495ce18SMarc Hulsman {
7116495ce18SMarc Hulsman struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
7126495ce18SMarc Hulsman int nr = sensor_attr->index;
7136495ce18SMarc Hulsman struct w83791d_data *data = w83791d_update_device(dev);
7146495ce18SMarc Hulsman return sprintf(buf, "%u\n", data->pwm[nr]);
7156495ce18SMarc Hulsman }
7166495ce18SMarc Hulsman
store_pwm(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)7176495ce18SMarc Hulsman static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
7186495ce18SMarc Hulsman const char *buf, size_t count)
7196495ce18SMarc Hulsman {
7206495ce18SMarc Hulsman struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
7216495ce18SMarc Hulsman struct i2c_client *client = to_i2c_client(dev);
7226495ce18SMarc Hulsman struct w83791d_data *data = i2c_get_clientdata(client);
7236495ce18SMarc Hulsman int nr = sensor_attr->index;
7246495ce18SMarc Hulsman unsigned long val;
7256495ce18SMarc Hulsman
726179c4fdbSFrans Meulenbroeks if (kstrtoul(buf, 10, &val))
7276495ce18SMarc Hulsman return -EINVAL;
7286495ce18SMarc Hulsman
7296495ce18SMarc Hulsman mutex_lock(&data->update_lock);
7302a844c14SGuenter Roeck data->pwm[nr] = clamp_val(val, 0, 255);
7316495ce18SMarc Hulsman w83791d_write(client, W83791D_REG_PWM[nr], data->pwm[nr]);
7326495ce18SMarc Hulsman mutex_unlock(&data->update_lock);
7336495ce18SMarc Hulsman return count;
7346495ce18SMarc Hulsman }
7356495ce18SMarc Hulsman
7366495ce18SMarc Hulsman static struct sensor_device_attribute sda_pwm[] = {
7376495ce18SMarc Hulsman SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO,
7386495ce18SMarc Hulsman show_pwm, store_pwm, 0),
7396495ce18SMarc Hulsman SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO,
7406495ce18SMarc Hulsman show_pwm, store_pwm, 1),
7416495ce18SMarc Hulsman SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO,
7426495ce18SMarc Hulsman show_pwm, store_pwm, 2),
7436495ce18SMarc Hulsman SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO,
7446495ce18SMarc Hulsman show_pwm, store_pwm, 3),
7456495ce18SMarc Hulsman SENSOR_ATTR(pwm5, S_IWUSR | S_IRUGO,
7466495ce18SMarc Hulsman show_pwm, store_pwm, 4),
7476495ce18SMarc Hulsman };
7486495ce18SMarc Hulsman
show_pwmenable(struct device * dev,struct device_attribute * attr,char * buf)749b5938f8cSMarc Hulsman static ssize_t show_pwmenable(struct device *dev, struct device_attribute *attr,
750b5938f8cSMarc Hulsman char *buf)
751b5938f8cSMarc Hulsman {
752b5938f8cSMarc Hulsman struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
753b5938f8cSMarc Hulsman int nr = sensor_attr->index;
754b5938f8cSMarc Hulsman struct w83791d_data *data = w83791d_update_device(dev);
755b5938f8cSMarc Hulsman return sprintf(buf, "%u\n", data->pwm_enable[nr] + 1);
756b5938f8cSMarc Hulsman }
757b5938f8cSMarc Hulsman
store_pwmenable(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)758b5938f8cSMarc Hulsman static ssize_t store_pwmenable(struct device *dev,
759b5938f8cSMarc Hulsman struct device_attribute *attr, const char *buf, size_t count)
760b5938f8cSMarc Hulsman {
761b5938f8cSMarc Hulsman struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
762b5938f8cSMarc Hulsman struct i2c_client *client = to_i2c_client(dev);
763b5938f8cSMarc Hulsman struct w83791d_data *data = i2c_get_clientdata(client);
764b5938f8cSMarc Hulsman int nr = sensor_attr->index;
765b5938f8cSMarc Hulsman unsigned long val;
766b5938f8cSMarc Hulsman u8 reg_cfg_tmp;
767b5938f8cSMarc Hulsman u8 reg_idx = 0;
768b5938f8cSMarc Hulsman u8 val_shift = 0;
769b5938f8cSMarc Hulsman u8 keep_mask = 0;
770b5938f8cSMarc Hulsman
771179c4fdbSFrans Meulenbroeks int ret = kstrtoul(buf, 10, &val);
772b5938f8cSMarc Hulsman
773b5938f8cSMarc Hulsman if (ret || val < 1 || val > 3)
774b5938f8cSMarc Hulsman return -EINVAL;
775b5938f8cSMarc Hulsman
776b5938f8cSMarc Hulsman mutex_lock(&data->update_lock);
777b5938f8cSMarc Hulsman data->pwm_enable[nr] = val - 1;
778b5938f8cSMarc Hulsman switch (nr) {
779b5938f8cSMarc Hulsman case 0:
780b5938f8cSMarc Hulsman reg_idx = 0;
781b5938f8cSMarc Hulsman val_shift = 2;
782b5938f8cSMarc Hulsman keep_mask = 0xf3;
783b5938f8cSMarc Hulsman break;
784b5938f8cSMarc Hulsman case 1:
785b5938f8cSMarc Hulsman reg_idx = 0;
786b5938f8cSMarc Hulsman val_shift = 4;
787b5938f8cSMarc Hulsman keep_mask = 0xcf;
788b5938f8cSMarc Hulsman break;
789b5938f8cSMarc Hulsman case 2:
790b5938f8cSMarc Hulsman reg_idx = 1;
791b5938f8cSMarc Hulsman val_shift = 2;
792b5938f8cSMarc Hulsman keep_mask = 0xf3;
793b5938f8cSMarc Hulsman break;
794b5938f8cSMarc Hulsman }
795b5938f8cSMarc Hulsman
796b5938f8cSMarc Hulsman reg_cfg_tmp = w83791d_read(client, W83791D_REG_FAN_CFG[reg_idx]);
797b5938f8cSMarc Hulsman reg_cfg_tmp = (reg_cfg_tmp & keep_mask) |
798b5938f8cSMarc Hulsman data->pwm_enable[nr] << val_shift;
799b5938f8cSMarc Hulsman
800b5938f8cSMarc Hulsman w83791d_write(client, W83791D_REG_FAN_CFG[reg_idx], reg_cfg_tmp);
801b5938f8cSMarc Hulsman mutex_unlock(&data->update_lock);
802b5938f8cSMarc Hulsman
803b5938f8cSMarc Hulsman return count;
804b5938f8cSMarc Hulsman }
805b5938f8cSMarc Hulsman static struct sensor_device_attribute sda_pwmenable[] = {
806b5938f8cSMarc Hulsman SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
807b5938f8cSMarc Hulsman show_pwmenable, store_pwmenable, 0),
808b5938f8cSMarc Hulsman SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
809b5938f8cSMarc Hulsman show_pwmenable, store_pwmenable, 1),
810b5938f8cSMarc Hulsman SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
811b5938f8cSMarc Hulsman show_pwmenable, store_pwmenable, 2),
812b5938f8cSMarc Hulsman };
813b5938f8cSMarc Hulsman
814a5a4598cSMarc Hulsman /* For Smart Fan I / Thermal Cruise */
show_temp_target(struct device * dev,struct device_attribute * attr,char * buf)815a5a4598cSMarc Hulsman static ssize_t show_temp_target(struct device *dev,
816a5a4598cSMarc Hulsman struct device_attribute *attr, char *buf)
817a5a4598cSMarc Hulsman {
818a5a4598cSMarc Hulsman struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
819a5a4598cSMarc Hulsman struct w83791d_data *data = w83791d_update_device(dev);
820a5a4598cSMarc Hulsman int nr = sensor_attr->index;
821a5a4598cSMarc Hulsman return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp_target[nr]));
822a5a4598cSMarc Hulsman }
823a5a4598cSMarc Hulsman
store_temp_target(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)824a5a4598cSMarc Hulsman static ssize_t store_temp_target(struct device *dev,
825a5a4598cSMarc Hulsman struct device_attribute *attr, const char *buf, size_t count)
826a5a4598cSMarc Hulsman {
827a5a4598cSMarc Hulsman struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
828a5a4598cSMarc Hulsman struct i2c_client *client = to_i2c_client(dev);
829a5a4598cSMarc Hulsman struct w83791d_data *data = i2c_get_clientdata(client);
830a5a4598cSMarc Hulsman int nr = sensor_attr->index;
831a9169813SGuenter Roeck long val;
832a5a4598cSMarc Hulsman u8 target_mask;
833a5a4598cSMarc Hulsman
834a9169813SGuenter Roeck if (kstrtol(buf, 10, &val))
835a5a4598cSMarc Hulsman return -EINVAL;
836a5a4598cSMarc Hulsman
837a5a4598cSMarc Hulsman mutex_lock(&data->update_lock);
838a5a4598cSMarc Hulsman data->temp_target[nr] = TARGET_TEMP_TO_REG(val);
839a5a4598cSMarc Hulsman target_mask = w83791d_read(client,
840a5a4598cSMarc Hulsman W83791D_REG_TEMP_TARGET[nr]) & 0x80;
841a5a4598cSMarc Hulsman w83791d_write(client, W83791D_REG_TEMP_TARGET[nr],
842a5a4598cSMarc Hulsman data->temp_target[nr] | target_mask);
843a5a4598cSMarc Hulsman mutex_unlock(&data->update_lock);
844a5a4598cSMarc Hulsman return count;
845a5a4598cSMarc Hulsman }
846a5a4598cSMarc Hulsman
847a5a4598cSMarc Hulsman static struct sensor_device_attribute sda_temp_target[] = {
848a5a4598cSMarc Hulsman SENSOR_ATTR(temp1_target, S_IWUSR | S_IRUGO,
849a5a4598cSMarc Hulsman show_temp_target, store_temp_target, 0),
850a5a4598cSMarc Hulsman SENSOR_ATTR(temp2_target, S_IWUSR | S_IRUGO,
851a5a4598cSMarc Hulsman show_temp_target, store_temp_target, 1),
852a5a4598cSMarc Hulsman SENSOR_ATTR(temp3_target, S_IWUSR | S_IRUGO,
853a5a4598cSMarc Hulsman show_temp_target, store_temp_target, 2),
854a5a4598cSMarc Hulsman };
855a5a4598cSMarc Hulsman
show_temp_tolerance(struct device * dev,struct device_attribute * attr,char * buf)856a5a4598cSMarc Hulsman static ssize_t show_temp_tolerance(struct device *dev,
857a5a4598cSMarc Hulsman struct device_attribute *attr, char *buf)
858a5a4598cSMarc Hulsman {
859a5a4598cSMarc Hulsman struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
860a5a4598cSMarc Hulsman struct w83791d_data *data = w83791d_update_device(dev);
861a5a4598cSMarc Hulsman int nr = sensor_attr->index;
862a5a4598cSMarc Hulsman return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp_tolerance[nr]));
863a5a4598cSMarc Hulsman }
864a5a4598cSMarc Hulsman
store_temp_tolerance(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)865a5a4598cSMarc Hulsman static ssize_t store_temp_tolerance(struct device *dev,
866a5a4598cSMarc Hulsman struct device_attribute *attr, const char *buf, size_t count)
867a5a4598cSMarc Hulsman {
868a5a4598cSMarc Hulsman struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
869a5a4598cSMarc Hulsman struct i2c_client *client = to_i2c_client(dev);
870a5a4598cSMarc Hulsman struct w83791d_data *data = i2c_get_clientdata(client);
871a5a4598cSMarc Hulsman int nr = sensor_attr->index;
872a5a4598cSMarc Hulsman unsigned long val;
873a5a4598cSMarc Hulsman u8 target_mask;
874a5a4598cSMarc Hulsman u8 reg_idx = 0;
875a5a4598cSMarc Hulsman u8 val_shift = 0;
876a5a4598cSMarc Hulsman u8 keep_mask = 0;
877a5a4598cSMarc Hulsman
878179c4fdbSFrans Meulenbroeks if (kstrtoul(buf, 10, &val))
879a5a4598cSMarc Hulsman return -EINVAL;
880a5a4598cSMarc Hulsman
881a5a4598cSMarc Hulsman switch (nr) {
882a5a4598cSMarc Hulsman case 0:
883a5a4598cSMarc Hulsman reg_idx = 0;
884a5a4598cSMarc Hulsman val_shift = 0;
885a5a4598cSMarc Hulsman keep_mask = 0xf0;
886a5a4598cSMarc Hulsman break;
887a5a4598cSMarc Hulsman case 1:
888a5a4598cSMarc Hulsman reg_idx = 0;
889a5a4598cSMarc Hulsman val_shift = 4;
890a5a4598cSMarc Hulsman keep_mask = 0x0f;
891a5a4598cSMarc Hulsman break;
892a5a4598cSMarc Hulsman case 2:
893a5a4598cSMarc Hulsman reg_idx = 1;
894a5a4598cSMarc Hulsman val_shift = 0;
895a5a4598cSMarc Hulsman keep_mask = 0xf0;
896a5a4598cSMarc Hulsman break;
897a5a4598cSMarc Hulsman }
898a5a4598cSMarc Hulsman
899a5a4598cSMarc Hulsman mutex_lock(&data->update_lock);
900a5a4598cSMarc Hulsman data->temp_tolerance[nr] = TOL_TEMP_TO_REG(val);
901a5a4598cSMarc Hulsman target_mask = w83791d_read(client,
902a5a4598cSMarc Hulsman W83791D_REG_TEMP_TOL[reg_idx]) & keep_mask;
903a5a4598cSMarc Hulsman w83791d_write(client, W83791D_REG_TEMP_TOL[reg_idx],
904a5a4598cSMarc Hulsman (data->temp_tolerance[nr] << val_shift) | target_mask);
905a5a4598cSMarc Hulsman mutex_unlock(&data->update_lock);
906a5a4598cSMarc Hulsman return count;
907a5a4598cSMarc Hulsman }
908a5a4598cSMarc Hulsman
909a5a4598cSMarc Hulsman static struct sensor_device_attribute sda_temp_tolerance[] = {
910a5a4598cSMarc Hulsman SENSOR_ATTR(temp1_tolerance, S_IWUSR | S_IRUGO,
911a5a4598cSMarc Hulsman show_temp_tolerance, store_temp_tolerance, 0),
912a5a4598cSMarc Hulsman SENSOR_ATTR(temp2_tolerance, S_IWUSR | S_IRUGO,
913a5a4598cSMarc Hulsman show_temp_tolerance, store_temp_tolerance, 1),
914a5a4598cSMarc Hulsman SENSOR_ATTR(temp3_tolerance, S_IWUSR | S_IRUGO,
915a5a4598cSMarc Hulsman show_temp_tolerance, store_temp_tolerance, 2),
916a5a4598cSMarc Hulsman };
917a5a4598cSMarc Hulsman
9189873964dSCharles Spirakis /* read/write the temperature1, includes measured value and limits */
show_temp1(struct device * dev,struct device_attribute * devattr,char * buf)9199873964dSCharles Spirakis static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr,
9209873964dSCharles Spirakis char *buf)
9219873964dSCharles Spirakis {
9229873964dSCharles Spirakis struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
9239873964dSCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev);
9249873964dSCharles Spirakis return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[attr->index]));
9259873964dSCharles Spirakis }
9269873964dSCharles Spirakis
store_temp1(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)9279873964dSCharles Spirakis static ssize_t store_temp1(struct device *dev, struct device_attribute *devattr,
9289873964dSCharles Spirakis const char *buf, size_t count)
9299873964dSCharles Spirakis {
9309873964dSCharles Spirakis struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
9319873964dSCharles Spirakis struct i2c_client *client = to_i2c_client(dev);
9329873964dSCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client);
9339873964dSCharles Spirakis int nr = attr->index;
934ec1c3194SGuenter Roeck long val;
935ec1c3194SGuenter Roeck int err;
936ec1c3194SGuenter Roeck
937ec1c3194SGuenter Roeck err = kstrtol(buf, 10, &val);
938ec1c3194SGuenter Roeck if (err)
939ec1c3194SGuenter Roeck return err;
9409873964dSCharles Spirakis
9419873964dSCharles Spirakis mutex_lock(&data->update_lock);
9429873964dSCharles Spirakis data->temp1[nr] = TEMP1_TO_REG(val);
9439873964dSCharles Spirakis w83791d_write(client, W83791D_REG_TEMP1[nr], data->temp1[nr]);
9449873964dSCharles Spirakis mutex_unlock(&data->update_lock);
9459873964dSCharles Spirakis return count;
9469873964dSCharles Spirakis }
9479873964dSCharles Spirakis
9489873964dSCharles Spirakis /* read/write temperature2-3, includes measured value and limits */
show_temp23(struct device * dev,struct device_attribute * devattr,char * buf)9499873964dSCharles Spirakis static ssize_t show_temp23(struct device *dev, struct device_attribute *devattr,
9509873964dSCharles Spirakis char *buf)
9519873964dSCharles Spirakis {
9529873964dSCharles Spirakis struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
9539873964dSCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev);
9549873964dSCharles Spirakis int nr = attr->nr;
9559873964dSCharles Spirakis int index = attr->index;
9569873964dSCharles Spirakis return sprintf(buf, "%d\n", TEMP23_FROM_REG(data->temp_add[nr][index]));
9579873964dSCharles Spirakis }
9589873964dSCharles Spirakis
store_temp23(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)9599873964dSCharles Spirakis static ssize_t store_temp23(struct device *dev,
9609873964dSCharles Spirakis struct device_attribute *devattr,
9619873964dSCharles Spirakis const char *buf, size_t count)
9629873964dSCharles Spirakis {
9639873964dSCharles Spirakis struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
9649873964dSCharles Spirakis struct i2c_client *client = to_i2c_client(dev);
9659873964dSCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client);
966ec1c3194SGuenter Roeck long val;
967ec1c3194SGuenter Roeck int err;
9689873964dSCharles Spirakis int nr = attr->nr;
9699873964dSCharles Spirakis int index = attr->index;
9709873964dSCharles Spirakis
971ec1c3194SGuenter Roeck err = kstrtol(buf, 10, &val);
972ec1c3194SGuenter Roeck if (err)
973ec1c3194SGuenter Roeck return err;
974ec1c3194SGuenter Roeck
9759873964dSCharles Spirakis mutex_lock(&data->update_lock);
9769873964dSCharles Spirakis data->temp_add[nr][index] = TEMP23_TO_REG(val);
9779873964dSCharles Spirakis w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2],
9789873964dSCharles Spirakis data->temp_add[nr][index] >> 8);
9799873964dSCharles Spirakis w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2 + 1],
9809873964dSCharles Spirakis data->temp_add[nr][index] & 0x80);
9819873964dSCharles Spirakis mutex_unlock(&data->update_lock);
9829873964dSCharles Spirakis
9839873964dSCharles Spirakis return count;
9849873964dSCharles Spirakis }
9859873964dSCharles Spirakis
9869873964dSCharles Spirakis static struct sensor_device_attribute_2 sda_temp_input[] = {
9879873964dSCharles Spirakis SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0),
9889873964dSCharles Spirakis SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0),
9899873964dSCharles Spirakis SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0),
9909873964dSCharles Spirakis };
9919873964dSCharles Spirakis
9929873964dSCharles Spirakis static struct sensor_device_attribute_2 sda_temp_max[] = {
9939873964dSCharles Spirakis SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR,
9949873964dSCharles Spirakis show_temp1, store_temp1, 0, 1),
9959873964dSCharles Spirakis SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR,
9969873964dSCharles Spirakis show_temp23, store_temp23, 0, 1),
9979873964dSCharles Spirakis SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR,
9989873964dSCharles Spirakis show_temp23, store_temp23, 1, 1),
9999873964dSCharles Spirakis };
10009873964dSCharles Spirakis
10019873964dSCharles Spirakis static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
10029873964dSCharles Spirakis SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR,
10039873964dSCharles Spirakis show_temp1, store_temp1, 0, 2),
10049873964dSCharles Spirakis SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR,
10059873964dSCharles Spirakis show_temp23, store_temp23, 0, 2),
10069873964dSCharles Spirakis SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR,
10079873964dSCharles Spirakis show_temp23, store_temp23, 1, 2),
10089873964dSCharles Spirakis };
10099873964dSCharles Spirakis
1010ec1c3194SGuenter Roeck /*
1011ec1c3194SGuenter Roeck * Note: The bitmask for the beep enable/disable is different than
1012ec1c3194SGuenter Roeck * the bitmask for the alarm.
1013ec1c3194SGuenter Roeck */
101464383123SCharles Spirakis static struct sensor_device_attribute sda_temp_beep[] = {
101564383123SCharles Spirakis SENSOR_ATTR(temp1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 4),
101664383123SCharles Spirakis SENSOR_ATTR(temp2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 5),
101764383123SCharles Spirakis SENSOR_ATTR(temp3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 1),
101864383123SCharles Spirakis };
101964383123SCharles Spirakis
102064383123SCharles Spirakis static struct sensor_device_attribute sda_temp_alarm[] = {
102164383123SCharles Spirakis SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4),
102264383123SCharles Spirakis SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5),
102364383123SCharles Spirakis SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
102464383123SCharles Spirakis };
10259873964dSCharles Spirakis
102684fb029fSLABBE Corentin /* get realtime status of all sensors items: voltage, temp, fan */
alarms_show(struct device * dev,struct device_attribute * attr,char * buf)10278d0ec428SJulia Lawall static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
10288d0ec428SJulia Lawall char *buf)
10299873964dSCharles Spirakis {
10309873964dSCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev);
10319873964dSCharles Spirakis return sprintf(buf, "%u\n", data->alarms);
10329873964dSCharles Spirakis }
10339873964dSCharles Spirakis
10348d0ec428SJulia Lawall static DEVICE_ATTR_RO(alarms);
10359873964dSCharles Spirakis
10369873964dSCharles Spirakis /* Beep control */
10379873964dSCharles Spirakis
10389873964dSCharles Spirakis #define GLOBAL_BEEP_ENABLE_SHIFT 15
10399873964dSCharles Spirakis #define GLOBAL_BEEP_ENABLE_MASK (1 << GLOBAL_BEEP_ENABLE_SHIFT)
10409873964dSCharles Spirakis
show_beep_enable(struct device * dev,struct device_attribute * attr,char * buf)10419873964dSCharles Spirakis static ssize_t show_beep_enable(struct device *dev,
10429873964dSCharles Spirakis struct device_attribute *attr, char *buf)
10439873964dSCharles Spirakis {
10449873964dSCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev);
10459873964dSCharles Spirakis return sprintf(buf, "%d\n", data->beep_enable);
10469873964dSCharles Spirakis }
10479873964dSCharles Spirakis
show_beep_mask(struct device * dev,struct device_attribute * attr,char * buf)10489873964dSCharles Spirakis static ssize_t show_beep_mask(struct device *dev,
10499873964dSCharles Spirakis struct device_attribute *attr, char *buf)
10509873964dSCharles Spirakis {
10519873964dSCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev);
10529873964dSCharles Spirakis return sprintf(buf, "%d\n", BEEP_MASK_FROM_REG(data->beep_mask));
10539873964dSCharles Spirakis }
10549873964dSCharles Spirakis
10559873964dSCharles Spirakis
store_beep_mask(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)10569873964dSCharles Spirakis static ssize_t store_beep_mask(struct device *dev,
10579873964dSCharles Spirakis struct device_attribute *attr,
10589873964dSCharles Spirakis const char *buf, size_t count)
10599873964dSCharles Spirakis {
10609873964dSCharles Spirakis struct i2c_client *client = to_i2c_client(dev);
10619873964dSCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client);
10629873964dSCharles Spirakis int i;
1063ec1c3194SGuenter Roeck long val;
1064ec1c3194SGuenter Roeck int err;
1065ec1c3194SGuenter Roeck
1066ec1c3194SGuenter Roeck err = kstrtol(buf, 10, &val);
1067ec1c3194SGuenter Roeck if (err)
1068ec1c3194SGuenter Roeck return err;
10699873964dSCharles Spirakis
10709873964dSCharles Spirakis mutex_lock(&data->update_lock);
10719873964dSCharles Spirakis
1072ec1c3194SGuenter Roeck /*
1073ec1c3194SGuenter Roeck * The beep_enable state overrides any enabling request from
1074ec1c3194SGuenter Roeck * the masks
1075ec1c3194SGuenter Roeck */
10769873964dSCharles Spirakis data->beep_mask = BEEP_MASK_TO_REG(val) & ~GLOBAL_BEEP_ENABLE_MASK;
10779873964dSCharles Spirakis data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT);
10789873964dSCharles Spirakis
10799873964dSCharles Spirakis val = data->beep_mask;
10809873964dSCharles Spirakis
10819873964dSCharles Spirakis for (i = 0; i < 3; i++) {
10829873964dSCharles Spirakis w83791d_write(client, W83791D_REG_BEEP_CTRL[i], (val & 0xff));
10839873964dSCharles Spirakis val >>= 8;
10849873964dSCharles Spirakis }
10859873964dSCharles Spirakis
10869873964dSCharles Spirakis mutex_unlock(&data->update_lock);
10879873964dSCharles Spirakis
10889873964dSCharles Spirakis return count;
10899873964dSCharles Spirakis }
10909873964dSCharles Spirakis
store_beep_enable(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)10919873964dSCharles Spirakis static ssize_t store_beep_enable(struct device *dev,
10929873964dSCharles Spirakis struct device_attribute *attr,
10939873964dSCharles Spirakis const char *buf, size_t count)
10949873964dSCharles Spirakis {
10959873964dSCharles Spirakis struct i2c_client *client = to_i2c_client(dev);
10969873964dSCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client);
1097ec1c3194SGuenter Roeck long val;
1098ec1c3194SGuenter Roeck int err;
1099ec1c3194SGuenter Roeck
1100ec1c3194SGuenter Roeck err = kstrtol(buf, 10, &val);
1101ec1c3194SGuenter Roeck if (err)
1102ec1c3194SGuenter Roeck return err;
11039873964dSCharles Spirakis
11049873964dSCharles Spirakis mutex_lock(&data->update_lock);
11059873964dSCharles Spirakis
11069873964dSCharles Spirakis data->beep_enable = val ? 1 : 0;
11079873964dSCharles Spirakis
11089873964dSCharles Spirakis /* Keep the full mask value in sync with the current enable */
11099873964dSCharles Spirakis data->beep_mask &= ~GLOBAL_BEEP_ENABLE_MASK;
11109873964dSCharles Spirakis data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT);
11119873964dSCharles Spirakis
1112ec1c3194SGuenter Roeck /*
1113ec1c3194SGuenter Roeck * The global control is in the second beep control register
1114ec1c3194SGuenter Roeck * so only need to update that register
1115ec1c3194SGuenter Roeck */
11169873964dSCharles Spirakis val = (data->beep_mask >> 8) & 0xff;
11179873964dSCharles Spirakis
11189873964dSCharles Spirakis w83791d_write(client, W83791D_REG_BEEP_CTRL[1], val);
11199873964dSCharles Spirakis
11209873964dSCharles Spirakis mutex_unlock(&data->update_lock);
11219873964dSCharles Spirakis
11229873964dSCharles Spirakis return count;
11239873964dSCharles Spirakis }
11249873964dSCharles Spirakis
11259873964dSCharles Spirakis static struct sensor_device_attribute sda_beep_ctrl[] = {
11269873964dSCharles Spirakis SENSOR_ATTR(beep_enable, S_IRUGO | S_IWUSR,
11279873964dSCharles Spirakis show_beep_enable, store_beep_enable, 0),
11289873964dSCharles Spirakis SENSOR_ATTR(beep_mask, S_IRUGO | S_IWUSR,
11299873964dSCharles Spirakis show_beep_mask, store_beep_mask, 1)
11309873964dSCharles Spirakis };
11319873964dSCharles Spirakis
11329873964dSCharles Spirakis /* cpu voltage regulation information */
cpu0_vid_show(struct device * dev,struct device_attribute * attr,char * buf)11338d0ec428SJulia Lawall static ssize_t cpu0_vid_show(struct device *dev,
11349873964dSCharles Spirakis struct device_attribute *attr, char *buf)
11359873964dSCharles Spirakis {
11369873964dSCharles Spirakis struct w83791d_data *data = w83791d_update_device(dev);
11379873964dSCharles Spirakis return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
11389873964dSCharles Spirakis }
11399873964dSCharles Spirakis
11408d0ec428SJulia Lawall static DEVICE_ATTR_RO(cpu0_vid);
11419873964dSCharles Spirakis
vrm_show(struct device * dev,struct device_attribute * attr,char * buf)11428d0ec428SJulia Lawall static ssize_t vrm_show(struct device *dev, struct device_attribute *attr,
11438d0ec428SJulia Lawall char *buf)
11449873964dSCharles Spirakis {
114590d6619aSJean Delvare struct w83791d_data *data = dev_get_drvdata(dev);
11469873964dSCharles Spirakis return sprintf(buf, "%d\n", data->vrm);
11479873964dSCharles Spirakis }
11489873964dSCharles Spirakis
vrm_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)11498d0ec428SJulia Lawall static ssize_t vrm_store(struct device *dev, struct device_attribute *attr,
11509873964dSCharles Spirakis const char *buf, size_t count)
11519873964dSCharles Spirakis {
11528f74efe8SJean Delvare struct w83791d_data *data = dev_get_drvdata(dev);
1153ec1c3194SGuenter Roeck unsigned long val;
1154ec1c3194SGuenter Roeck int err;
11559873964dSCharles Spirakis
1156ec1c3194SGuenter Roeck /*
1157ec1c3194SGuenter Roeck * No lock needed as vrm is internal to the driver
1158ec1c3194SGuenter Roeck * (not read from a chip register) and so is not
1159ec1c3194SGuenter Roeck * updated in w83791d_update_device()
1160ec1c3194SGuenter Roeck */
11619873964dSCharles Spirakis
1162ec1c3194SGuenter Roeck err = kstrtoul(buf, 10, &val);
1163ec1c3194SGuenter Roeck if (err)
1164ec1c3194SGuenter Roeck return err;
1165ec1c3194SGuenter Roeck
1166fe04f24bSAxel Lin if (val > 255)
1167fe04f24bSAxel Lin return -EINVAL;
1168fe04f24bSAxel Lin
1169ec1c3194SGuenter Roeck data->vrm = val;
11709873964dSCharles Spirakis return count;
11719873964dSCharles Spirakis }
11729873964dSCharles Spirakis
11738d0ec428SJulia Lawall static DEVICE_ATTR_RW(vrm);
11749873964dSCharles Spirakis
117534fc921aSJim Cromie #define IN_UNIT_ATTRS(X) \
117634fc921aSJim Cromie &sda_in_input[X].dev_attr.attr, \
117734fc921aSJim Cromie &sda_in_min[X].dev_attr.attr, \
117864383123SCharles Spirakis &sda_in_max[X].dev_attr.attr, \
117964383123SCharles Spirakis &sda_in_beep[X].dev_attr.attr, \
118064383123SCharles Spirakis &sda_in_alarm[X].dev_attr.attr
118134fc921aSJim Cromie
118234fc921aSJim Cromie #define FAN_UNIT_ATTRS(X) \
118334fc921aSJim Cromie &sda_fan_input[X].dev_attr.attr, \
118434fc921aSJim Cromie &sda_fan_min[X].dev_attr.attr, \
118564383123SCharles Spirakis &sda_fan_div[X].dev_attr.attr, \
118664383123SCharles Spirakis &sda_fan_beep[X].dev_attr.attr, \
118764383123SCharles Spirakis &sda_fan_alarm[X].dev_attr.attr
118834fc921aSJim Cromie
118934fc921aSJim Cromie #define TEMP_UNIT_ATTRS(X) \
119034fc921aSJim Cromie &sda_temp_input[X].dev_attr.attr, \
119134fc921aSJim Cromie &sda_temp_max[X].dev_attr.attr, \
119264383123SCharles Spirakis &sda_temp_max_hyst[X].dev_attr.attr, \
119364383123SCharles Spirakis &sda_temp_beep[X].dev_attr.attr, \
119464383123SCharles Spirakis &sda_temp_alarm[X].dev_attr.attr
119534fc921aSJim Cromie
119634fc921aSJim Cromie static struct attribute *w83791d_attributes[] = {
119734fc921aSJim Cromie IN_UNIT_ATTRS(0),
119834fc921aSJim Cromie IN_UNIT_ATTRS(1),
119934fc921aSJim Cromie IN_UNIT_ATTRS(2),
120034fc921aSJim Cromie IN_UNIT_ATTRS(3),
120134fc921aSJim Cromie IN_UNIT_ATTRS(4),
120234fc921aSJim Cromie IN_UNIT_ATTRS(5),
120334fc921aSJim Cromie IN_UNIT_ATTRS(6),
120434fc921aSJim Cromie IN_UNIT_ATTRS(7),
120534fc921aSJim Cromie IN_UNIT_ATTRS(8),
120634fc921aSJim Cromie IN_UNIT_ATTRS(9),
120734fc921aSJim Cromie FAN_UNIT_ATTRS(0),
120834fc921aSJim Cromie FAN_UNIT_ATTRS(1),
120934fc921aSJim Cromie FAN_UNIT_ATTRS(2),
121034fc921aSJim Cromie TEMP_UNIT_ATTRS(0),
121134fc921aSJim Cromie TEMP_UNIT_ATTRS(1),
121234fc921aSJim Cromie TEMP_UNIT_ATTRS(2),
121334fc921aSJim Cromie &dev_attr_alarms.attr,
121434fc921aSJim Cromie &sda_beep_ctrl[0].dev_attr.attr,
121534fc921aSJim Cromie &sda_beep_ctrl[1].dev_attr.attr,
121634fc921aSJim Cromie &dev_attr_cpu0_vid.attr,
121734fc921aSJim Cromie &dev_attr_vrm.attr,
12186495ce18SMarc Hulsman &sda_pwm[0].dev_attr.attr,
12196495ce18SMarc Hulsman &sda_pwm[1].dev_attr.attr,
12206495ce18SMarc Hulsman &sda_pwm[2].dev_attr.attr,
1221b5938f8cSMarc Hulsman &sda_pwmenable[0].dev_attr.attr,
1222b5938f8cSMarc Hulsman &sda_pwmenable[1].dev_attr.attr,
1223b5938f8cSMarc Hulsman &sda_pwmenable[2].dev_attr.attr,
1224a5a4598cSMarc Hulsman &sda_temp_target[0].dev_attr.attr,
1225a5a4598cSMarc Hulsman &sda_temp_target[1].dev_attr.attr,
1226a5a4598cSMarc Hulsman &sda_temp_target[2].dev_attr.attr,
1227a5a4598cSMarc Hulsman &sda_temp_tolerance[0].dev_attr.attr,
1228a5a4598cSMarc Hulsman &sda_temp_tolerance[1].dev_attr.attr,
1229a5a4598cSMarc Hulsman &sda_temp_tolerance[2].dev_attr.attr,
123034fc921aSJim Cromie NULL
123134fc921aSJim Cromie };
123234fc921aSJim Cromie
123334fc921aSJim Cromie static const struct attribute_group w83791d_group = {
123434fc921aSJim Cromie .attrs = w83791d_attributes,
123534fc921aSJim Cromie };
123634fc921aSJim Cromie
1237ec1c3194SGuenter Roeck /*
1238ec1c3194SGuenter Roeck * Separate group of attributes for fan/pwm 4-5. Their pins can also be
1239ec1c3194SGuenter Roeck * in use for GPIO in which case their sysfs-interface should not be made
1240ec1c3194SGuenter Roeck * available
1241ec1c3194SGuenter Roeck */
12426e1ecd9bSMarc Hulsman static struct attribute *w83791d_attributes_fanpwm45[] = {
12436e1ecd9bSMarc Hulsman FAN_UNIT_ATTRS(3),
12446e1ecd9bSMarc Hulsman FAN_UNIT_ATTRS(4),
12456495ce18SMarc Hulsman &sda_pwm[3].dev_attr.attr,
12466495ce18SMarc Hulsman &sda_pwm[4].dev_attr.attr,
12476e1ecd9bSMarc Hulsman NULL
12486e1ecd9bSMarc Hulsman };
12496e1ecd9bSMarc Hulsman
12506e1ecd9bSMarc Hulsman static const struct attribute_group w83791d_group_fanpwm45 = {
12516e1ecd9bSMarc Hulsman .attrs = w83791d_attributes_fanpwm45,
12526e1ecd9bSMarc Hulsman };
1253cb0c1af3SJean Delvare
w83791d_detect_subclients(struct i2c_client * client)1254cb0c1af3SJean Delvare static int w83791d_detect_subclients(struct i2c_client *client)
12559873964dSCharles Spirakis {
1256cb0c1af3SJean Delvare struct i2c_adapter *adapter = client->adapter;
1257cb0c1af3SJean Delvare int address = client->addr;
1258358d2071SWolfram Sang int i, id;
12599873964dSCharles Spirakis u8 val;
12609873964dSCharles Spirakis
12619873964dSCharles Spirakis id = i2c_adapter_id(adapter);
12629873964dSCharles Spirakis if (force_subclients[0] == id && force_subclients[1] == address) {
12639873964dSCharles Spirakis for (i = 2; i <= 3; i++) {
12649873964dSCharles Spirakis if (force_subclients[i] < 0x48 ||
12659873964dSCharles Spirakis force_subclients[i] > 0x4f) {
12669873964dSCharles Spirakis dev_err(&client->dev,
12679873964dSCharles Spirakis "invalid subclient "
12689873964dSCharles Spirakis "address %d; must be 0x48-0x4f\n",
12699873964dSCharles Spirakis force_subclients[i]);
1270358d2071SWolfram Sang return -ENODEV;
12719873964dSCharles Spirakis }
12729873964dSCharles Spirakis }
12739873964dSCharles Spirakis w83791d_write(client, W83791D_REG_I2C_SUBADDR,
12749873964dSCharles Spirakis (force_subclients[2] & 0x07) |
12759873964dSCharles Spirakis ((force_subclients[3] & 0x07) << 4));
12769873964dSCharles Spirakis }
12779873964dSCharles Spirakis
12789873964dSCharles Spirakis val = w83791d_read(client, W83791D_REG_I2C_SUBADDR);
1279943c15acSNadezda Lutovinova
1280943c15acSNadezda Lutovinova if (!(val & 0x88) && (val & 0x7) == ((val >> 4) & 0x7)) {
12819873964dSCharles Spirakis dev_err(&client->dev,
1282943c15acSNadezda Lutovinova "duplicate addresses 0x%x, use force_subclient\n", 0x48 + (val & 0x7));
1283358d2071SWolfram Sang return -ENODEV;
12849873964dSCharles Spirakis }
1285943c15acSNadezda Lutovinova
1286943c15acSNadezda Lutovinova if (!(val & 0x08))
1287943c15acSNadezda Lutovinova devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + (val & 0x7));
1288943c15acSNadezda Lutovinova
1289943c15acSNadezda Lutovinova if (!(val & 0x80))
1290943c15acSNadezda Lutovinova devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + ((val >> 4) & 0x7));
12919873964dSCharles Spirakis
12929873964dSCharles Spirakis return 0;
12939873964dSCharles Spirakis }
12949873964dSCharles Spirakis
12959873964dSCharles Spirakis
1296cb0c1af3SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
w83791d_detect(struct i2c_client * client,struct i2c_board_info * info)1297310ec792SJean Delvare static int w83791d_detect(struct i2c_client *client,
1298cb0c1af3SJean Delvare struct i2c_board_info *info)
12999873964dSCharles Spirakis {
1300cb0c1af3SJean Delvare struct i2c_adapter *adapter = client->adapter;
1301cb0c1af3SJean Delvare int val1, val2;
1302cb0c1af3SJean Delvare unsigned short address = client->addr;
13039873964dSCharles Spirakis
1304ec1c3194SGuenter Roeck if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1305cb0c1af3SJean Delvare return -ENODEV;
13069873964dSCharles Spirakis
13073f8b8459SJean Delvare if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80)
1308cb0c1af3SJean Delvare return -ENODEV;
13093f8b8459SJean Delvare
13109873964dSCharles Spirakis val1 = w83791d_read(client, W83791D_REG_BANK);
13119873964dSCharles Spirakis val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
13129873964dSCharles Spirakis /* Check for Winbond ID if in bank 0 */
13139873964dSCharles Spirakis if (!(val1 & 0x07)) {
13143f8b8459SJean Delvare if ((!(val1 & 0x80) && val2 != 0xa3) ||
13153f8b8459SJean Delvare ((val1 & 0x80) && val2 != 0x5c)) {
1316cb0c1af3SJean Delvare return -ENODEV;
13179873964dSCharles Spirakis }
13189873964dSCharles Spirakis }
1319ec1c3194SGuenter Roeck /*
1320ec1c3194SGuenter Roeck * If Winbond chip, address of chip and W83791D_REG_I2C_ADDR
1321ec1c3194SGuenter Roeck * should match
1322ec1c3194SGuenter Roeck */
13233f8b8459SJean Delvare if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address)
1324cb0c1af3SJean Delvare return -ENODEV;
13259873964dSCharles Spirakis
13263f8b8459SJean Delvare /* We want bank 0 and Vendor ID high byte */
13279873964dSCharles Spirakis val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78;
13289873964dSCharles Spirakis w83791d_write(client, W83791D_REG_BANK, val1 | 0x80);
13299873964dSCharles Spirakis
13309873964dSCharles Spirakis /* Verify it is a Winbond w83791d */
13319873964dSCharles Spirakis val1 = w83791d_read(client, W83791D_REG_WCHIPID);
13323f8b8459SJean Delvare val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
13333f8b8459SJean Delvare if (val1 != 0x71 || val2 != 0x5c)
1334cb0c1af3SJean Delvare return -ENODEV;
13359873964dSCharles Spirakis
1336f2f394dbSWolfram Sang strscpy(info->type, "w83791d", I2C_NAME_SIZE);
1337cb0c1af3SJean Delvare
1338cb0c1af3SJean Delvare return 0;
13399873964dSCharles Spirakis }
13409873964dSCharles Spirakis
w83791d_probe(struct i2c_client * client)134177b5b8a8SStephen Kitt static int w83791d_probe(struct i2c_client *client)
1342cb0c1af3SJean Delvare {
1343cb0c1af3SJean Delvare struct w83791d_data *data;
1344cb0c1af3SJean Delvare struct device *dev = &client->dev;
134516a515fdSMichael Borisov int i, err;
13466e1ecd9bSMarc Hulsman u8 has_fanpwm45;
1347cb0c1af3SJean Delvare
13489873964dSCharles Spirakis #ifdef DEBUG
134916a515fdSMichael Borisov int val1;
13509873964dSCharles Spirakis val1 = w83791d_read(client, W83791D_REG_DID_VID4);
13519873964dSCharles Spirakis dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n",
13529873964dSCharles Spirakis (val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1);
13539873964dSCharles Spirakis #endif
13549873964dSCharles Spirakis
13556e13bb06SGuenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct w83791d_data),
13566e13bb06SGuenter Roeck GFP_KERNEL);
13576e13bb06SGuenter Roeck if (!data)
13586e13bb06SGuenter Roeck return -ENOMEM;
13599873964dSCharles Spirakis
1360cb0c1af3SJean Delvare i2c_set_clientdata(client, data);
1361cb0c1af3SJean Delvare mutex_init(&data->update_lock);
1362cb0c1af3SJean Delvare
1363cb0c1af3SJean Delvare err = w83791d_detect_subclients(client);
1364cb0c1af3SJean Delvare if (err)
13656e13bb06SGuenter Roeck return err;
13669873964dSCharles Spirakis
13679873964dSCharles Spirakis /* Initialize the chip */
13689873964dSCharles Spirakis w83791d_init_client(client);
13699873964dSCharles Spirakis
1370ec1c3194SGuenter Roeck /*
1371ec1c3194SGuenter Roeck * If the fan_div is changed, make sure there is a rational
1372ec1c3194SGuenter Roeck * fan_min in place
1373ec1c3194SGuenter Roeck */
1374ec1c3194SGuenter Roeck for (i = 0; i < NUMBER_OF_FANIN; i++)
13759873964dSCharles Spirakis data->fan_min[i] = w83791d_read(client, W83791D_REG_FAN_MIN[i]);
13769873964dSCharles Spirakis
13779873964dSCharles Spirakis /* Register sysfs hooks */
1378ec1c3194SGuenter Roeck err = sysfs_create_group(&client->dev.kobj, &w83791d_group);
1379ec1c3194SGuenter Roeck if (err)
1380358d2071SWolfram Sang return err;
138134fc921aSJim Cromie
13826e1ecd9bSMarc Hulsman /* Check if pins of fan/pwm 4-5 are in use as GPIO */
13836e1ecd9bSMarc Hulsman has_fanpwm45 = w83791d_read(client, W83791D_REG_GPIO) & 0x10;
13846e1ecd9bSMarc Hulsman if (has_fanpwm45) {
13856e1ecd9bSMarc Hulsman err = sysfs_create_group(&client->dev.kobj,
13866e1ecd9bSMarc Hulsman &w83791d_group_fanpwm45);
13876e1ecd9bSMarc Hulsman if (err)
13886e1ecd9bSMarc Hulsman goto error4;
13896e1ecd9bSMarc Hulsman }
13906e1ecd9bSMarc Hulsman
139134fc921aSJim Cromie /* Everything is ready, now register the working device */
13921beeffe4STony Jones data->hwmon_dev = hwmon_device_register(dev);
13931beeffe4STony Jones if (IS_ERR(data->hwmon_dev)) {
13941beeffe4STony Jones err = PTR_ERR(data->hwmon_dev);
13956e1ecd9bSMarc Hulsman goto error5;
13969873964dSCharles Spirakis }
13979873964dSCharles Spirakis
13989873964dSCharles Spirakis return 0;
13999873964dSCharles Spirakis
14006e1ecd9bSMarc Hulsman error5:
14016e1ecd9bSMarc Hulsman if (has_fanpwm45)
14026e1ecd9bSMarc Hulsman sysfs_remove_group(&client->dev.kobj, &w83791d_group_fanpwm45);
140334fc921aSJim Cromie error4:
140434fc921aSJim Cromie sysfs_remove_group(&client->dev.kobj, &w83791d_group);
14059873964dSCharles Spirakis return err;
14069873964dSCharles Spirakis }
14079873964dSCharles Spirakis
w83791d_remove(struct i2c_client * client)1408ed5c2f5fSUwe Kleine-König static void w83791d_remove(struct i2c_client *client)
14099873964dSCharles Spirakis {
14109873964dSCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client);
14119873964dSCharles Spirakis
14121beeffe4STony Jones hwmon_device_unregister(data->hwmon_dev);
141334fc921aSJim Cromie sysfs_remove_group(&client->dev.kobj, &w83791d_group);
14149873964dSCharles Spirakis }
14159873964dSCharles Spirakis
w83791d_init_client(struct i2c_client * client)14169873964dSCharles Spirakis static void w83791d_init_client(struct i2c_client *client)
14179873964dSCharles Spirakis {
14189873964dSCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client);
14199873964dSCharles Spirakis u8 tmp;
14209873964dSCharles Spirakis u8 old_beep;
14219873964dSCharles Spirakis
1422ec1c3194SGuenter Roeck /*
1423ec1c3194SGuenter Roeck * The difference between reset and init is that reset
1424ec1c3194SGuenter Roeck * does a hard reset of the chip via index 0x40, bit 7,
1425ec1c3194SGuenter Roeck * but init simply forces certain registers to have "sane"
1426ec1c3194SGuenter Roeck * values. The hope is that the BIOS has done the right
1427ec1c3194SGuenter Roeck * thing (which is why the default is reset=0, init=0),
1428ec1c3194SGuenter Roeck * but if not, reset is the hard hammer and init
1429ec1c3194SGuenter Roeck * is the soft mallet both of which are trying to whack
1430ec1c3194SGuenter Roeck * things into place...
1431ec1c3194SGuenter Roeck * NOTE: The data sheet makes a distinction between
1432ec1c3194SGuenter Roeck * "power on defaults" and "reset by MR". As far as I can tell,
1433ec1c3194SGuenter Roeck * the hard reset puts everything into a power-on state so I'm
1434ec1c3194SGuenter Roeck * not sure what "reset by MR" means or how it can happen.
14359873964dSCharles Spirakis */
14369873964dSCharles Spirakis if (reset || init) {
14379873964dSCharles Spirakis /* keep some BIOS settings when we... */
14389873964dSCharles Spirakis old_beep = w83791d_read(client, W83791D_REG_BEEP_CONFIG);
14399873964dSCharles Spirakis
14409873964dSCharles Spirakis if (reset) {
14419873964dSCharles Spirakis /* ... reset the chip and ... */
14429873964dSCharles Spirakis w83791d_write(client, W83791D_REG_CONFIG, 0x80);
14439873964dSCharles Spirakis }
14449873964dSCharles Spirakis
14459873964dSCharles Spirakis /* ... disable power-on abnormal beep */
14469873964dSCharles Spirakis w83791d_write(client, W83791D_REG_BEEP_CONFIG, old_beep | 0x80);
14479873964dSCharles Spirakis
14489873964dSCharles Spirakis /* disable the global beep (not done by hard reset) */
14499873964dSCharles Spirakis tmp = w83791d_read(client, W83791D_REG_BEEP_CTRL[1]);
14509873964dSCharles Spirakis w83791d_write(client, W83791D_REG_BEEP_CTRL[1], tmp & 0xef);
14519873964dSCharles Spirakis
14529873964dSCharles Spirakis if (init) {
14539873964dSCharles Spirakis /* Make sure monitoring is turned on for add-ons */
14549873964dSCharles Spirakis tmp = w83791d_read(client, W83791D_REG_TEMP2_CONFIG);
14559873964dSCharles Spirakis if (tmp & 1) {
14569873964dSCharles Spirakis w83791d_write(client, W83791D_REG_TEMP2_CONFIG,
14579873964dSCharles Spirakis tmp & 0xfe);
14589873964dSCharles Spirakis }
14599873964dSCharles Spirakis
14609873964dSCharles Spirakis tmp = w83791d_read(client, W83791D_REG_TEMP3_CONFIG);
14619873964dSCharles Spirakis if (tmp & 1) {
14629873964dSCharles Spirakis w83791d_write(client, W83791D_REG_TEMP3_CONFIG,
14639873964dSCharles Spirakis tmp & 0xfe);
14649873964dSCharles Spirakis }
14659873964dSCharles Spirakis
14669873964dSCharles Spirakis /* Start monitoring */
14679873964dSCharles Spirakis tmp = w83791d_read(client, W83791D_REG_CONFIG) & 0xf7;
14689873964dSCharles Spirakis w83791d_write(client, W83791D_REG_CONFIG, tmp | 0x01);
14699873964dSCharles Spirakis }
14709873964dSCharles Spirakis }
14719873964dSCharles Spirakis
14729873964dSCharles Spirakis data->vrm = vid_which_vrm();
14739873964dSCharles Spirakis }
14749873964dSCharles Spirakis
w83791d_update_device(struct device * dev)14759873964dSCharles Spirakis static struct w83791d_data *w83791d_update_device(struct device *dev)
14769873964dSCharles Spirakis {
14779873964dSCharles Spirakis struct i2c_client *client = to_i2c_client(dev);
14789873964dSCharles Spirakis struct w83791d_data *data = i2c_get_clientdata(client);
14799873964dSCharles Spirakis int i, j;
14809873964dSCharles Spirakis u8 reg_array_tmp[3];
1481ad02ad85SMarc Hulsman u8 vbat_reg;
14829873964dSCharles Spirakis
14839873964dSCharles Spirakis mutex_lock(&data->update_lock);
14849873964dSCharles Spirakis
14859873964dSCharles Spirakis if (time_after(jiffies, data->last_updated + (HZ * 3))
14869873964dSCharles Spirakis || !data->valid) {
14879873964dSCharles Spirakis dev_dbg(dev, "Starting w83791d device update\n");
14889873964dSCharles Spirakis
14899873964dSCharles Spirakis /* Update the voltages measured value and limits */
14909873964dSCharles Spirakis for (i = 0; i < NUMBER_OF_VIN; i++) {
14919873964dSCharles Spirakis data->in[i] = w83791d_read(client,
14929873964dSCharles Spirakis W83791D_REG_IN[i]);
14939873964dSCharles Spirakis data->in_max[i] = w83791d_read(client,
14949873964dSCharles Spirakis W83791D_REG_IN_MAX[i]);
14959873964dSCharles Spirakis data->in_min[i] = w83791d_read(client,
14969873964dSCharles Spirakis W83791D_REG_IN_MIN[i]);
14979873964dSCharles Spirakis }
14989873964dSCharles Spirakis
14999873964dSCharles Spirakis /* Update the fan counts and limits */
15009873964dSCharles Spirakis for (i = 0; i < NUMBER_OF_FANIN; i++) {
15019873964dSCharles Spirakis /* Update the Fan measured value and limits */
15029873964dSCharles Spirakis data->fan[i] = w83791d_read(client,
15039873964dSCharles Spirakis W83791D_REG_FAN[i]);
15049873964dSCharles Spirakis data->fan_min[i] = w83791d_read(client,
15059873964dSCharles Spirakis W83791D_REG_FAN_MIN[i]);
15069873964dSCharles Spirakis }
15079873964dSCharles Spirakis
15089873964dSCharles Spirakis /* Update the fan divisor */
15099873964dSCharles Spirakis for (i = 0; i < 3; i++) {
15109873964dSCharles Spirakis reg_array_tmp[i] = w83791d_read(client,
15119873964dSCharles Spirakis W83791D_REG_FAN_DIV[i]);
15129873964dSCharles Spirakis }
15139873964dSCharles Spirakis data->fan_div[0] = (reg_array_tmp[0] >> 4) & 0x03;
15149873964dSCharles Spirakis data->fan_div[1] = (reg_array_tmp[0] >> 6) & 0x03;
15159873964dSCharles Spirakis data->fan_div[2] = (reg_array_tmp[1] >> 6) & 0x03;
15169873964dSCharles Spirakis data->fan_div[3] = reg_array_tmp[2] & 0x07;
15179873964dSCharles Spirakis data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07;
15189873964dSCharles Spirakis
1519ec1c3194SGuenter Roeck /*
1520ec1c3194SGuenter Roeck * The fan divisor for fans 0-2 get bit 2 from
1521ec1c3194SGuenter Roeck * bits 5-7 respectively of vbat register
1522ec1c3194SGuenter Roeck */
1523ad02ad85SMarc Hulsman vbat_reg = w83791d_read(client, W83791D_REG_VBAT);
1524ad02ad85SMarc Hulsman for (i = 0; i < 3; i++)
1525ad02ad85SMarc Hulsman data->fan_div[i] |= (vbat_reg >> (3 + i)) & 0x04;
1526ad02ad85SMarc Hulsman
15276495ce18SMarc Hulsman /* Update PWM duty cycle */
15286495ce18SMarc Hulsman for (i = 0; i < NUMBER_OF_PWM; i++) {
15296495ce18SMarc Hulsman data->pwm[i] = w83791d_read(client,
15306495ce18SMarc Hulsman W83791D_REG_PWM[i]);
15316495ce18SMarc Hulsman }
15326495ce18SMarc Hulsman
1533b5938f8cSMarc Hulsman /* Update PWM enable status */
1534b5938f8cSMarc Hulsman for (i = 0; i < 2; i++) {
1535b5938f8cSMarc Hulsman reg_array_tmp[i] = w83791d_read(client,
1536b5938f8cSMarc Hulsman W83791D_REG_FAN_CFG[i]);
1537b5938f8cSMarc Hulsman }
1538b5938f8cSMarc Hulsman data->pwm_enable[0] = (reg_array_tmp[0] >> 2) & 0x03;
1539b5938f8cSMarc Hulsman data->pwm_enable[1] = (reg_array_tmp[0] >> 4) & 0x03;
1540b5938f8cSMarc Hulsman data->pwm_enable[2] = (reg_array_tmp[1] >> 2) & 0x03;
1541b5938f8cSMarc Hulsman
1542a5a4598cSMarc Hulsman /* Update PWM target temperature */
1543a5a4598cSMarc Hulsman for (i = 0; i < 3; i++) {
1544a5a4598cSMarc Hulsman data->temp_target[i] = w83791d_read(client,
1545a5a4598cSMarc Hulsman W83791D_REG_TEMP_TARGET[i]) & 0x7f;
1546a5a4598cSMarc Hulsman }
1547a5a4598cSMarc Hulsman
1548a5a4598cSMarc Hulsman /* Update PWM temperature tolerance */
1549a5a4598cSMarc Hulsman for (i = 0; i < 2; i++) {
1550a5a4598cSMarc Hulsman reg_array_tmp[i] = w83791d_read(client,
1551a5a4598cSMarc Hulsman W83791D_REG_TEMP_TOL[i]);
1552a5a4598cSMarc Hulsman }
1553a5a4598cSMarc Hulsman data->temp_tolerance[0] = reg_array_tmp[0] & 0x0f;
1554a5a4598cSMarc Hulsman data->temp_tolerance[1] = (reg_array_tmp[0] >> 4) & 0x0f;
1555a5a4598cSMarc Hulsman data->temp_tolerance[2] = reg_array_tmp[1] & 0x0f;
1556a5a4598cSMarc Hulsman
15579873964dSCharles Spirakis /* Update the first temperature sensor */
15589873964dSCharles Spirakis for (i = 0; i < 3; i++) {
15599873964dSCharles Spirakis data->temp1[i] = w83791d_read(client,
15609873964dSCharles Spirakis W83791D_REG_TEMP1[i]);
15619873964dSCharles Spirakis }
15629873964dSCharles Spirakis
15639873964dSCharles Spirakis /* Update the rest of the temperature sensors */
15649873964dSCharles Spirakis for (i = 0; i < 2; i++) {
15659873964dSCharles Spirakis for (j = 0; j < 3; j++) {
15669873964dSCharles Spirakis data->temp_add[i][j] =
15679873964dSCharles Spirakis (w83791d_read(client,
15689873964dSCharles Spirakis W83791D_REG_TEMP_ADD[i][j * 2]) << 8) |
15699873964dSCharles Spirakis w83791d_read(client,
15709873964dSCharles Spirakis W83791D_REG_TEMP_ADD[i][j * 2 + 1]);
15719873964dSCharles Spirakis }
15729873964dSCharles Spirakis }
15739873964dSCharles Spirakis
15749873964dSCharles Spirakis /* Update the realtime status */
15759873964dSCharles Spirakis data->alarms =
15769873964dSCharles Spirakis w83791d_read(client, W83791D_REG_ALARM1) +
15779873964dSCharles Spirakis (w83791d_read(client, W83791D_REG_ALARM2) << 8) +
15789873964dSCharles Spirakis (w83791d_read(client, W83791D_REG_ALARM3) << 16);
15799873964dSCharles Spirakis
15809873964dSCharles Spirakis /* Update the beep configuration information */
15819873964dSCharles Spirakis data->beep_mask =
15829873964dSCharles Spirakis w83791d_read(client, W83791D_REG_BEEP_CTRL[0]) +
15839873964dSCharles Spirakis (w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) +
15849873964dSCharles Spirakis (w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16);
15859873964dSCharles Spirakis
1586125751cbSCharles Spirakis /* Extract global beep enable flag */
15879873964dSCharles Spirakis data->beep_enable =
15889873964dSCharles Spirakis (data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01;
15899873964dSCharles Spirakis
15909873964dSCharles Spirakis /* Update the cpu voltage information */
15919873964dSCharles Spirakis i = w83791d_read(client, W83791D_REG_VID_FANDIV);
15929873964dSCharles Spirakis data->vid = i & 0x0f;
15939873964dSCharles Spirakis data->vid |= (w83791d_read(client, W83791D_REG_DID_VID4) & 0x01)
15949873964dSCharles Spirakis << 4;
15959873964dSCharles Spirakis
15969873964dSCharles Spirakis data->last_updated = jiffies;
1597952a11caSPaul Fertser data->valid = true;
15989873964dSCharles Spirakis }
15999873964dSCharles Spirakis
16009873964dSCharles Spirakis mutex_unlock(&data->update_lock);
16019873964dSCharles Spirakis
16029873964dSCharles Spirakis #ifdef DEBUG
16039873964dSCharles Spirakis w83791d_print_debug(data, dev);
16049873964dSCharles Spirakis #endif
16059873964dSCharles Spirakis
16069873964dSCharles Spirakis return data;
16079873964dSCharles Spirakis }
16089873964dSCharles Spirakis
16099873964dSCharles Spirakis #ifdef DEBUG
w83791d_print_debug(struct w83791d_data * data,struct device * dev)16109873964dSCharles Spirakis static void w83791d_print_debug(struct w83791d_data *data, struct device *dev)
16119873964dSCharles Spirakis {
16129873964dSCharles Spirakis int i = 0, j = 0;
16139873964dSCharles Spirakis
16149873964dSCharles Spirakis dev_dbg(dev, "======Start of w83791d debug values======\n");
16159873964dSCharles Spirakis dev_dbg(dev, "%d set of Voltages: ===>\n", NUMBER_OF_VIN);
16169873964dSCharles Spirakis for (i = 0; i < NUMBER_OF_VIN; i++) {
16179873964dSCharles Spirakis dev_dbg(dev, "vin[%d] is: 0x%02x\n", i, data->in[i]);
16189873964dSCharles Spirakis dev_dbg(dev, "vin[%d] min is: 0x%02x\n", i, data->in_min[i]);
16199873964dSCharles Spirakis dev_dbg(dev, "vin[%d] max is: 0x%02x\n", i, data->in_max[i]);
16209873964dSCharles Spirakis }
16219873964dSCharles Spirakis dev_dbg(dev, "%d set of Fan Counts/Divisors: ===>\n", NUMBER_OF_FANIN);
16229873964dSCharles Spirakis for (i = 0; i < NUMBER_OF_FANIN; i++) {
16239873964dSCharles Spirakis dev_dbg(dev, "fan[%d] is: 0x%02x\n", i, data->fan[i]);
16249873964dSCharles Spirakis dev_dbg(dev, "fan[%d] min is: 0x%02x\n", i, data->fan_min[i]);
16259873964dSCharles Spirakis dev_dbg(dev, "fan_div[%d] is: 0x%02x\n", i, data->fan_div[i]);
16269873964dSCharles Spirakis }
16279873964dSCharles Spirakis
1628ec1c3194SGuenter Roeck /*
1629ec1c3194SGuenter Roeck * temperature math is signed, but only print out the
1630ec1c3194SGuenter Roeck * bits that matter
1631ec1c3194SGuenter Roeck */
16329873964dSCharles Spirakis dev_dbg(dev, "%d set of Temperatures: ===>\n", NUMBER_OF_TEMPIN);
1633ec1c3194SGuenter Roeck for (i = 0; i < 3; i++)
16349873964dSCharles Spirakis dev_dbg(dev, "temp1[%d] is: 0x%02x\n", i, (u8) data->temp1[i]);
16359873964dSCharles Spirakis for (i = 0; i < 2; i++) {
16369873964dSCharles Spirakis for (j = 0; j < 3; j++) {
16379873964dSCharles Spirakis dev_dbg(dev, "temp_add[%d][%d] is: 0x%04x\n", i, j,
16389873964dSCharles Spirakis (u16) data->temp_add[i][j]);
16399873964dSCharles Spirakis }
16409873964dSCharles Spirakis }
16419873964dSCharles Spirakis
16429873964dSCharles Spirakis dev_dbg(dev, "Misc Information: ===>\n");
16439873964dSCharles Spirakis dev_dbg(dev, "alarm is: 0x%08x\n", data->alarms);
16449873964dSCharles Spirakis dev_dbg(dev, "beep_mask is: 0x%08x\n", data->beep_mask);
16459873964dSCharles Spirakis dev_dbg(dev, "beep_enable is: %d\n", data->beep_enable);
16469873964dSCharles Spirakis dev_dbg(dev, "vid is: 0x%02x\n", data->vid);
16479873964dSCharles Spirakis dev_dbg(dev, "vrm is: 0x%02x\n", data->vrm);
16489873964dSCharles Spirakis dev_dbg(dev, "=======End of w83791d debug values========\n");
16499873964dSCharles Spirakis dev_dbg(dev, "\n");
16509873964dSCharles Spirakis }
16519873964dSCharles Spirakis #endif
16529873964dSCharles Spirakis
1653f0967eeaSAxel Lin module_i2c_driver(w83791d_driver);
16549873964dSCharles Spirakis
16559873964dSCharles Spirakis MODULE_AUTHOR("Charles Spirakis <bezaur@gmail.com>");
16569873964dSCharles Spirakis MODULE_DESCRIPTION("W83791D driver");
16579873964dSCharles Spirakis MODULE_LICENSE("GPL");
1658