174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 28d5d45fbSJean Delvare /* 3fbb6670dSGuenter Roeck * adm1031.c - Part of lm_sensors, Linux kernel modules for hardware 4fbb6670dSGuenter Roeck * monitoring 5fbb6670dSGuenter Roeck * Based on lm75.c and lm85.c 6fbb6670dSGuenter Roeck * Supports adm1030 / adm1031 7fbb6670dSGuenter Roeck * Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org> 87c81c60fSJean Delvare * Reworked by Jean Delvare <jdelvare@suse.de> 98d5d45fbSJean Delvare */ 108d5d45fbSJean Delvare 118d5d45fbSJean Delvare #include <linux/module.h> 128d5d45fbSJean Delvare #include <linux/init.h> 138d5d45fbSJean Delvare #include <linux/slab.h> 148d5d45fbSJean Delvare #include <linux/jiffies.h> 158d5d45fbSJean Delvare #include <linux/i2c.h> 16943b0830SMark M. Hoffman #include <linux/hwmon.h> 17c801082dSJean Delvare #include <linux/hwmon-sysfs.h> 18943b0830SMark M. Hoffman #include <linux/err.h> 199a61bf63SIngo Molnar #include <linux/mutex.h> 208d5d45fbSJean Delvare 218d5d45fbSJean Delvare /* Following macros takes channel parameter starting from 0 to 2 */ 228d5d45fbSJean Delvare #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) 238d5d45fbSJean Delvare #define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) 248d5d45fbSJean Delvare #define ADM1031_REG_PWM (0x22) 258d5d45fbSJean Delvare #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) 2687c33daaSJean Delvare #define ADM1031_REG_FAN_FILTER (0x23) 278d5d45fbSJean Delvare 2849dc9efeSIra Snyder #define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) 298d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) 308d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) 318d5d45fbSJean Delvare #define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) 328d5d45fbSJean Delvare 336d6006b8SJean Delvare #define ADM1031_REG_TEMP(nr) (0x0a + (nr)) 348d5d45fbSJean Delvare #define ADM1031_REG_AUTO_TEMP(nr) (0x24 + (nr)) 358d5d45fbSJean Delvare 368d5d45fbSJean Delvare #define ADM1031_REG_STATUS(nr) (0x2 + (nr)) 378d5d45fbSJean Delvare 386d6006b8SJean Delvare #define ADM1031_REG_CONF1 0x00 396d6006b8SJean Delvare #define ADM1031_REG_CONF2 0x01 406d6006b8SJean Delvare #define ADM1031_REG_EXT_TEMP 0x06 418d5d45fbSJean Delvare 428d5d45fbSJean Delvare #define ADM1031_CONF1_MONITOR_ENABLE 0x01 /* Monitoring enable */ 438d5d45fbSJean Delvare #define ADM1031_CONF1_PWM_INVERT 0x08 /* PWM Invert */ 448d5d45fbSJean Delvare #define ADM1031_CONF1_AUTO_MODE 0x80 /* Auto FAN */ 458d5d45fbSJean Delvare 468d5d45fbSJean Delvare #define ADM1031_CONF2_PWM1_ENABLE 0x01 478d5d45fbSJean Delvare #define ADM1031_CONF2_PWM2_ENABLE 0x02 488d5d45fbSJean Delvare #define ADM1031_CONF2_TACH1_ENABLE 0x04 498d5d45fbSJean Delvare #define ADM1031_CONF2_TACH2_ENABLE 0x08 508d5d45fbSJean Delvare #define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan)) 518d5d45fbSJean Delvare 5287c33daaSJean Delvare #define ADM1031_UPDATE_RATE_MASK 0x1c 5387c33daaSJean Delvare #define ADM1031_UPDATE_RATE_SHIFT 2 5487c33daaSJean Delvare 558d5d45fbSJean Delvare /* Addresses to scan */ 5625e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; 578d5d45fbSJean Delvare 58e5e9f44cSJean Delvare enum chips { adm1030, adm1031 }; 598d5d45fbSJean Delvare 608d5d45fbSJean Delvare typedef u8 auto_chan_table_t[8][2]; 618d5d45fbSJean Delvare 628d5d45fbSJean Delvare /* Each client has this additional data */ 638d5d45fbSJean Delvare struct adm1031_data { 64b060f3c4SAxel Lin struct i2c_client *client; 65b060f3c4SAxel Lin const struct attribute_group *groups[3]; 669a61bf63SIngo Molnar struct mutex update_lock; 678d5d45fbSJean Delvare int chip_type; 68*952a11caSPaul Fertser bool valid; /* true if following fields are valid */ 698d5d45fbSJean Delvare unsigned long last_updated; /* In jiffies */ 70a51b9944SGuenter Roeck unsigned int update_interval; /* In milliseconds */ 71fbb6670dSGuenter Roeck /* 72fbb6670dSGuenter Roeck * The chan_select_table contains the possible configurations for 738d5d45fbSJean Delvare * auto fan control. 748d5d45fbSJean Delvare */ 756d6006b8SJean Delvare const auto_chan_table_t *chan_select_table; 768d5d45fbSJean Delvare u16 alarm; 778d5d45fbSJean Delvare u8 conf1; 788d5d45fbSJean Delvare u8 conf2; 798d5d45fbSJean Delvare u8 fan[2]; 808d5d45fbSJean Delvare u8 fan_div[2]; 818d5d45fbSJean Delvare u8 fan_min[2]; 828d5d45fbSJean Delvare u8 pwm[2]; 838d5d45fbSJean Delvare u8 old_pwm[2]; 848d5d45fbSJean Delvare s8 temp[3]; 858d5d45fbSJean Delvare u8 ext_temp[3]; 868d5d45fbSJean Delvare u8 auto_temp[3]; 878d5d45fbSJean Delvare u8 auto_temp_min[3]; 888d5d45fbSJean Delvare u8 auto_temp_off[3]; 898d5d45fbSJean Delvare u8 auto_temp_max[3]; 9049dc9efeSIra Snyder s8 temp_offset[3]; 918d5d45fbSJean Delvare s8 temp_min[3]; 928d5d45fbSJean Delvare s8 temp_max[3]; 938d5d45fbSJean Delvare s8 temp_crit[3]; 948d5d45fbSJean Delvare }; 958d5d45fbSJean Delvare 968d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) 978d5d45fbSJean Delvare { 988d5d45fbSJean Delvare return i2c_smbus_read_byte_data(client, reg); 998d5d45fbSJean Delvare } 1008d5d45fbSJean Delvare 1018d5d45fbSJean Delvare static inline int 1028d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value) 1038d5d45fbSJean Delvare { 1048d5d45fbSJean Delvare return i2c_smbus_write_byte_data(client, reg, value); 1058d5d45fbSJean Delvare } 1068d5d45fbSJean Delvare 107278ee1c8SAxel Lin static struct adm1031_data *adm1031_update_device(struct device *dev) 108278ee1c8SAxel Lin { 109b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 110b060f3c4SAxel Lin struct i2c_client *client = data->client; 111278ee1c8SAxel Lin unsigned long next_update; 112278ee1c8SAxel Lin int chan; 113278ee1c8SAxel Lin 114278ee1c8SAxel Lin mutex_lock(&data->update_lock); 115278ee1c8SAxel Lin 116278ee1c8SAxel Lin next_update = data->last_updated 117278ee1c8SAxel Lin + msecs_to_jiffies(data->update_interval); 118278ee1c8SAxel Lin if (time_after(jiffies, next_update) || !data->valid) { 119278ee1c8SAxel Lin 120278ee1c8SAxel Lin dev_dbg(&client->dev, "Starting adm1031 update\n"); 121278ee1c8SAxel Lin for (chan = 0; 122278ee1c8SAxel Lin chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) { 123278ee1c8SAxel Lin u8 oldh, newh; 124278ee1c8SAxel Lin 125278ee1c8SAxel Lin oldh = 126278ee1c8SAxel Lin adm1031_read_value(client, ADM1031_REG_TEMP(chan)); 127278ee1c8SAxel Lin data->ext_temp[chan] = 128278ee1c8SAxel Lin adm1031_read_value(client, ADM1031_REG_EXT_TEMP); 129278ee1c8SAxel Lin newh = 130278ee1c8SAxel Lin adm1031_read_value(client, ADM1031_REG_TEMP(chan)); 131278ee1c8SAxel Lin if (newh != oldh) { 132278ee1c8SAxel Lin data->ext_temp[chan] = 133278ee1c8SAxel Lin adm1031_read_value(client, 134278ee1c8SAxel Lin ADM1031_REG_EXT_TEMP); 135278ee1c8SAxel Lin #ifdef DEBUG 136278ee1c8SAxel Lin oldh = 137278ee1c8SAxel Lin adm1031_read_value(client, 138278ee1c8SAxel Lin ADM1031_REG_TEMP(chan)); 139278ee1c8SAxel Lin 140278ee1c8SAxel Lin /* oldh is actually newer */ 141278ee1c8SAxel Lin if (newh != oldh) 142278ee1c8SAxel Lin dev_warn(&client->dev, 143278ee1c8SAxel Lin "Remote temperature may be wrong.\n"); 144278ee1c8SAxel Lin #endif 145278ee1c8SAxel Lin } 146278ee1c8SAxel Lin data->temp[chan] = newh; 147278ee1c8SAxel Lin 148278ee1c8SAxel Lin data->temp_offset[chan] = 149278ee1c8SAxel Lin adm1031_read_value(client, 150278ee1c8SAxel Lin ADM1031_REG_TEMP_OFFSET(chan)); 151278ee1c8SAxel Lin data->temp_min[chan] = 152278ee1c8SAxel Lin adm1031_read_value(client, 153278ee1c8SAxel Lin ADM1031_REG_TEMP_MIN(chan)); 154278ee1c8SAxel Lin data->temp_max[chan] = 155278ee1c8SAxel Lin adm1031_read_value(client, 156278ee1c8SAxel Lin ADM1031_REG_TEMP_MAX(chan)); 157278ee1c8SAxel Lin data->temp_crit[chan] = 158278ee1c8SAxel Lin adm1031_read_value(client, 159278ee1c8SAxel Lin ADM1031_REG_TEMP_CRIT(chan)); 160278ee1c8SAxel Lin data->auto_temp[chan] = 161278ee1c8SAxel Lin adm1031_read_value(client, 162278ee1c8SAxel Lin ADM1031_REG_AUTO_TEMP(chan)); 163278ee1c8SAxel Lin 164278ee1c8SAxel Lin } 165278ee1c8SAxel Lin 166278ee1c8SAxel Lin data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1); 167278ee1c8SAxel Lin data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2); 168278ee1c8SAxel Lin 169278ee1c8SAxel Lin data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0)) 170278ee1c8SAxel Lin | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8); 171278ee1c8SAxel Lin if (data->chip_type == adm1030) 172278ee1c8SAxel Lin data->alarm &= 0xc0ff; 173278ee1c8SAxel Lin 174278ee1c8SAxel Lin for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2); 175278ee1c8SAxel Lin chan++) { 176278ee1c8SAxel Lin data->fan_div[chan] = 177278ee1c8SAxel Lin adm1031_read_value(client, 178278ee1c8SAxel Lin ADM1031_REG_FAN_DIV(chan)); 179278ee1c8SAxel Lin data->fan_min[chan] = 180278ee1c8SAxel Lin adm1031_read_value(client, 181278ee1c8SAxel Lin ADM1031_REG_FAN_MIN(chan)); 182278ee1c8SAxel Lin data->fan[chan] = 183278ee1c8SAxel Lin adm1031_read_value(client, 184278ee1c8SAxel Lin ADM1031_REG_FAN_SPEED(chan)); 185278ee1c8SAxel Lin data->pwm[chan] = 186278ee1c8SAxel Lin (adm1031_read_value(client, 187278ee1c8SAxel Lin ADM1031_REG_PWM) >> (4 * chan)) & 0x0f; 188278ee1c8SAxel Lin } 189278ee1c8SAxel Lin data->last_updated = jiffies; 190*952a11caSPaul Fertser data->valid = true; 191278ee1c8SAxel Lin } 192278ee1c8SAxel Lin 193278ee1c8SAxel Lin mutex_unlock(&data->update_lock); 194278ee1c8SAxel Lin 195278ee1c8SAxel Lin return data; 196278ee1c8SAxel Lin } 1978d5d45fbSJean Delvare 1988d5d45fbSJean Delvare #define TEMP_TO_REG(val) (((val) < 0 ? ((val - 500) / 1000) : \ 1998d5d45fbSJean Delvare ((val + 500) / 1000))) 2008d5d45fbSJean Delvare 2018d5d45fbSJean Delvare #define TEMP_FROM_REG(val) ((val) * 1000) 2028d5d45fbSJean Delvare 2038d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) 2048d5d45fbSJean Delvare 20549dc9efeSIra Snyder #define TEMP_OFFSET_TO_REG(val) (TEMP_TO_REG(val) & 0x8f) 20649dc9efeSIra Snyder #define TEMP_OFFSET_FROM_REG(val) TEMP_FROM_REG((val) < 0 ? \ 20749dc9efeSIra Snyder (val) | 0x70 : (val)) 20849dc9efeSIra Snyder 2091c720093SGuenter Roeck #define FAN_FROM_REG(reg, div) ((reg) ? \ 2101c720093SGuenter Roeck (11250 * 60) / ((reg) * (div)) : 0) 2118d5d45fbSJean Delvare 2128d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div) 2138d5d45fbSJean Delvare { 2148d5d45fbSJean Delvare int tmp; 2152a844c14SGuenter Roeck tmp = FAN_FROM_REG(clamp_val(reg, 0, 65535), div); 2168d5d45fbSJean Delvare return tmp > 255 ? 255 : tmp; 2178d5d45fbSJean Delvare } 2188d5d45fbSJean Delvare 2198d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg) (1<<(((reg)&0xc0)>>6)) 2208d5d45fbSJean Delvare 2212a844c14SGuenter Roeck #define PWM_TO_REG(val) (clamp_val((val), 0, 255) >> 4) 2228d5d45fbSJean Delvare #define PWM_FROM_REG(val) ((val) << 4) 2238d5d45fbSJean Delvare 2248d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg) (((reg) >> 5) & 7) 2258d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg) \ 2268d5d45fbSJean Delvare (((reg) & 0x1F) | (((val) << 5) & 0xe0)) 2278d5d45fbSJean Delvare 2288d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg) \ 2298d5d45fbSJean Delvare ((((val) / 500) & 0xf8) | ((reg) & 0x7)) 2308d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg) (5000 * (1 << ((reg) & 0x7))) 2318d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg) (1000 * ((((reg) >> 3) & 0x1f) << 2)) 2328d5d45fbSJean Delvare 2338d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg) ((((reg) >> 3) & 0x1f) << 2) 2348d5d45fbSJean Delvare 2358d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg) \ 2368d5d45fbSJean Delvare (AUTO_TEMP_MIN_FROM_REG(reg) - 5000) 2378d5d45fbSJean Delvare 2388d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg) \ 2398d5d45fbSJean Delvare (AUTO_TEMP_RANGE_FROM_REG(reg) + \ 2408d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG(reg)) 2418d5d45fbSJean Delvare 2428d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm) 2438d5d45fbSJean Delvare { 2448d5d45fbSJean Delvare int ret; 2458d5d45fbSJean Delvare int range = val - AUTO_TEMP_MIN_FROM_REG(reg); 2468d5d45fbSJean Delvare 2478d5d45fbSJean Delvare range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm); 2488d5d45fbSJean Delvare ret = ((reg & 0xf8) | 2498d5d45fbSJean Delvare (range < 10000 ? 0 : 2508d5d45fbSJean Delvare range < 20000 ? 1 : 2518d5d45fbSJean Delvare range < 40000 ? 2 : range < 80000 ? 3 : 4)); 2528d5d45fbSJean Delvare return ret; 2538d5d45fbSJean Delvare } 2548d5d45fbSJean Delvare 2558d5d45fbSJean Delvare /* FAN auto control */ 2568d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx) \ 2578d5d45fbSJean Delvare (*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2] 2588d5d45fbSJean Delvare 259fbb6670dSGuenter Roeck /* 260fbb6670dSGuenter Roeck * The tables below contains the possible values for the auto fan 2618d5d45fbSJean Delvare * control bitfields. the index in the table is the register value. 2628d5d45fbSJean Delvare * MSb is the auto fan control enable bit, so the four first entries 2638d5d45fbSJean Delvare * in the table disables auto fan control when both bitfields are zero. 2648d5d45fbSJean Delvare */ 2656d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = { 2668d5d45fbSJean Delvare { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2678d5d45fbSJean Delvare { 2 /* 0b010 */ , 4 /* 0b100 */ }, 2688d5d45fbSJean Delvare { 2 /* 0b010 */ , 2 /* 0b010 */ }, 2698d5d45fbSJean Delvare { 4 /* 0b100 */ , 4 /* 0b100 */ }, 2708d5d45fbSJean Delvare { 7 /* 0b111 */ , 7 /* 0b111 */ }, 2718d5d45fbSJean Delvare }; 2728d5d45fbSJean Delvare 2736d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = { 2748d5d45fbSJean Delvare { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2758d5d45fbSJean Delvare { 2 /* 0b10 */ , 0 }, 2768d5d45fbSJean Delvare { 0xff /* invalid */ , 0 }, 2778d5d45fbSJean Delvare { 0xff /* invalid */ , 0 }, 2788d5d45fbSJean Delvare { 3 /* 0b11 */ , 0 }, 2798d5d45fbSJean Delvare }; 2808d5d45fbSJean Delvare 281fbb6670dSGuenter Roeck /* 282fbb6670dSGuenter Roeck * That function checks if a bitfield is valid and returns the other bitfield 2838d5d45fbSJean Delvare * nearest match if no exact match where found. 2848d5d45fbSJean Delvare */ 2858d5d45fbSJean Delvare static int 286ce15a81dSGuenter Roeck get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg) 2878d5d45fbSJean Delvare { 2888d5d45fbSJean Delvare int i; 2898d5d45fbSJean Delvare int first_match = -1, exact_match = -1; 2908d5d45fbSJean Delvare u8 other_reg_val = 2918d5d45fbSJean Delvare (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1]; 2928d5d45fbSJean Delvare 293ce15a81dSGuenter Roeck if (val == 0) 2948d5d45fbSJean Delvare return 0; 2958d5d45fbSJean Delvare 2968d5d45fbSJean Delvare for (i = 0; i < 8; i++) { 2978d5d45fbSJean Delvare if ((val == (*data->chan_select_table)[i][chan]) && 2988d5d45fbSJean Delvare ((*data->chan_select_table)[i][chan ? 0 : 1] == 2998d5d45fbSJean Delvare other_reg_val)) { 3008d5d45fbSJean Delvare /* We found an exact match */ 3018d5d45fbSJean Delvare exact_match = i; 3028d5d45fbSJean Delvare break; 3038d5d45fbSJean Delvare } else if (val == (*data->chan_select_table)[i][chan] && 3048d5d45fbSJean Delvare first_match == -1) { 305fbb6670dSGuenter Roeck /* 306fbb6670dSGuenter Roeck * Save the first match in case of an exact match has 3076d6006b8SJean Delvare * not been found 3088d5d45fbSJean Delvare */ 3098d5d45fbSJean Delvare first_match = i; 3108d5d45fbSJean Delvare } 3118d5d45fbSJean Delvare } 3128d5d45fbSJean Delvare 3131c720093SGuenter Roeck if (exact_match >= 0) 314ce15a81dSGuenter Roeck return exact_match; 3151c720093SGuenter Roeck else if (first_match >= 0) 316ce15a81dSGuenter Roeck return first_match; 3171c720093SGuenter Roeck 318ce15a81dSGuenter Roeck return -EINVAL; 3198d5d45fbSJean Delvare } 3208d5d45fbSJean Delvare 3218e757e15SGuenter Roeck static ssize_t fan_auto_channel_show(struct device *dev, 322c801082dSJean Delvare struct device_attribute *attr, char *buf) 3238d5d45fbSJean Delvare { 324c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3258d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 3268d5d45fbSJean Delvare return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr)); 3278d5d45fbSJean Delvare } 3288d5d45fbSJean Delvare 3298d5d45fbSJean Delvare static ssize_t 3308e757e15SGuenter Roeck fan_auto_channel_store(struct device *dev, struct device_attribute *attr, 331c801082dSJean Delvare const char *buf, size_t count) 3328d5d45fbSJean Delvare { 333b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 334b060f3c4SAxel Lin struct i2c_client *client = data->client; 335c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3361c720093SGuenter Roeck long val; 3378d5d45fbSJean Delvare u8 reg; 3388d5d45fbSJean Delvare int ret; 3398d5d45fbSJean Delvare u8 old_fan_mode; 3408d5d45fbSJean Delvare 3411c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 3421c720093SGuenter Roeck if (ret) 3431c720093SGuenter Roeck return ret; 3441c720093SGuenter Roeck 3458d5d45fbSJean Delvare old_fan_mode = data->conf1; 3468d5d45fbSJean Delvare 3479a61bf63SIngo Molnar mutex_lock(&data->update_lock); 3488d5d45fbSJean Delvare 349ce15a81dSGuenter Roeck ret = get_fan_auto_nearest(data, nr, val, data->conf1); 350ce15a81dSGuenter Roeck if (ret < 0) { 3519a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 3528d5d45fbSJean Delvare return ret; 3538d5d45fbSJean Delvare } 354ce15a81dSGuenter Roeck reg = ret; 3556d6006b8SJean Delvare data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); 3566d6006b8SJean Delvare if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^ 3578d5d45fbSJean Delvare (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) { 3588d5d45fbSJean Delvare if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { 359fbb6670dSGuenter Roeck /* 360fbb6670dSGuenter Roeck * Switch to Auto Fan Mode 3618d5d45fbSJean Delvare * Save PWM registers 362fbb6670dSGuenter Roeck * Set PWM registers to 33% Both 363fbb6670dSGuenter Roeck */ 3648d5d45fbSJean Delvare data->old_pwm[0] = data->pwm[0]; 3658d5d45fbSJean Delvare data->old_pwm[1] = data->pwm[1]; 3668d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_PWM, 0x55); 3678d5d45fbSJean Delvare } else { 3688d5d45fbSJean Delvare /* Switch to Manual Mode */ 3698d5d45fbSJean Delvare data->pwm[0] = data->old_pwm[0]; 3708d5d45fbSJean Delvare data->pwm[1] = data->old_pwm[1]; 3718d5d45fbSJean Delvare /* Restore PWM registers */ 3728d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_PWM, 3738d5d45fbSJean Delvare data->pwm[0] | (data->pwm[1] << 4)); 3748d5d45fbSJean Delvare } 3758d5d45fbSJean Delvare } 3768d5d45fbSJean Delvare data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); 3778d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); 3789a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 3798d5d45fbSJean Delvare return count; 3808d5d45fbSJean Delvare } 3818d5d45fbSJean Delvare 3828e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan1_channel, fan_auto_channel, 0); 3838e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan2_channel, fan_auto_channel, 1); 3848d5d45fbSJean Delvare 3858d5d45fbSJean Delvare /* Auto Temps */ 3868e757e15SGuenter Roeck static ssize_t auto_temp_off_show(struct device *dev, 387c801082dSJean Delvare struct device_attribute *attr, char *buf) 3888d5d45fbSJean Delvare { 389c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3908d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 3918d5d45fbSJean Delvare return sprintf(buf, "%d\n", 3928d5d45fbSJean Delvare AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr])); 3938d5d45fbSJean Delvare } 3948e757e15SGuenter Roeck static ssize_t auto_temp_min_show(struct device *dev, 395c801082dSJean Delvare struct device_attribute *attr, char *buf) 3968d5d45fbSJean Delvare { 397c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3988d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 3998d5d45fbSJean Delvare return sprintf(buf, "%d\n", 4008d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr])); 4018d5d45fbSJean Delvare } 4028d5d45fbSJean Delvare static ssize_t 4038e757e15SGuenter Roeck auto_temp_min_store(struct device *dev, struct device_attribute *attr, 404c801082dSJean Delvare const char *buf, size_t count) 4058d5d45fbSJean Delvare { 406b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 407b060f3c4SAxel Lin struct i2c_client *client = data->client; 408c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4091c720093SGuenter Roeck long val; 4101c720093SGuenter Roeck int ret; 4111c720093SGuenter Roeck 4121c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 4131c720093SGuenter Roeck if (ret) 4141c720093SGuenter Roeck return ret; 4158d5d45fbSJean Delvare 416145e74a4SGuenter Roeck val = clamp_val(val, 0, 127000); 4179a61bf63SIngo Molnar mutex_lock(&data->update_lock); 4188d5d45fbSJean Delvare data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); 4198d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), 4208d5d45fbSJean Delvare data->auto_temp[nr]); 4219a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 4228d5d45fbSJean Delvare return count; 4238d5d45fbSJean Delvare } 4248e757e15SGuenter Roeck static ssize_t auto_temp_max_show(struct device *dev, 425c801082dSJean Delvare struct device_attribute *attr, char *buf) 4268d5d45fbSJean Delvare { 427c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4288d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 4298d5d45fbSJean Delvare return sprintf(buf, "%d\n", 4308d5d45fbSJean Delvare AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr])); 4318d5d45fbSJean Delvare } 4328d5d45fbSJean Delvare static ssize_t 4338e757e15SGuenter Roeck auto_temp_max_store(struct device *dev, struct device_attribute *attr, 434c801082dSJean Delvare const char *buf, size_t count) 4358d5d45fbSJean Delvare { 436b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 437b060f3c4SAxel Lin struct i2c_client *client = data->client; 438c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4391c720093SGuenter Roeck long val; 4401c720093SGuenter Roeck int ret; 4411c720093SGuenter Roeck 4421c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 4431c720093SGuenter Roeck if (ret) 4441c720093SGuenter Roeck return ret; 4458d5d45fbSJean Delvare 446145e74a4SGuenter Roeck val = clamp_val(val, 0, 127000); 4479a61bf63SIngo Molnar mutex_lock(&data->update_lock); 4481c720093SGuenter Roeck data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], 4491c720093SGuenter Roeck data->pwm[nr]); 4508d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), 4518d5d45fbSJean Delvare data->temp_max[nr]); 4529a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 4538d5d45fbSJean Delvare return count; 4548d5d45fbSJean Delvare } 4558d5d45fbSJean Delvare 4568e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(auto_temp1_off, auto_temp_off, 0); 4578e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp1_min, auto_temp_min, 0); 4588e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp1_max, auto_temp_max, 0); 4598e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(auto_temp2_off, auto_temp_off, 1); 4608e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp2_min, auto_temp_min, 1); 4618e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp2_max, auto_temp_max, 1); 4628e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(auto_temp3_off, auto_temp_off, 2); 4638e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp3_min, auto_temp_min, 2); 4648e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp3_max, auto_temp_max, 2); 4658d5d45fbSJean Delvare 4668d5d45fbSJean Delvare /* pwm */ 4678e757e15SGuenter Roeck static ssize_t pwm_show(struct device *dev, struct device_attribute *attr, 4688e757e15SGuenter Roeck char *buf) 4698d5d45fbSJean Delvare { 470c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4718d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 4728d5d45fbSJean Delvare return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); 4738d5d45fbSJean Delvare } 4748e757e15SGuenter Roeck static ssize_t pwm_store(struct device *dev, struct device_attribute *attr, 475c801082dSJean Delvare const char *buf, size_t count) 4768d5d45fbSJean Delvare { 477b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 478b060f3c4SAxel Lin struct i2c_client *client = data->client; 479c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4801c720093SGuenter Roeck long val; 4811c720093SGuenter Roeck int ret, reg; 4821c720093SGuenter Roeck 4831c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 4841c720093SGuenter Roeck if (ret) 4851c720093SGuenter Roeck return ret; 4868d5d45fbSJean Delvare 4879a61bf63SIngo Molnar mutex_lock(&data->update_lock); 4888d5d45fbSJean Delvare if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && 4898d5d45fbSJean Delvare (((val>>4) & 0xf) != 5)) { 4908d5d45fbSJean Delvare /* In automatic mode, the only PWM accepted is 33% */ 4919a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 4928d5d45fbSJean Delvare return -EINVAL; 4938d5d45fbSJean Delvare } 4948d5d45fbSJean Delvare data->pwm[nr] = PWM_TO_REG(val); 4958d5d45fbSJean Delvare reg = adm1031_read_value(client, ADM1031_REG_PWM); 4968d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_PWM, 4978d5d45fbSJean Delvare nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) 4988d5d45fbSJean Delvare : (data->pwm[nr] & 0xf) | (reg & 0xf0)); 4999a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 5008d5d45fbSJean Delvare return count; 5018d5d45fbSJean Delvare } 5028d5d45fbSJean Delvare 5038e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0); 5048e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1); 5058e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan1_min_pwm, pwm, 0); 5068e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan2_min_pwm, pwm, 1); 5078d5d45fbSJean Delvare 5088d5d45fbSJean Delvare /* Fans */ 5098d5d45fbSJean Delvare 5108d5d45fbSJean Delvare /* 5118d5d45fbSJean Delvare * That function checks the cases where the fan reading is not 5128d5d45fbSJean Delvare * relevant. It is used to provide 0 as fan reading when the fan is 5138d5d45fbSJean Delvare * not supposed to run 5148d5d45fbSJean Delvare */ 5158d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan) 5168d5d45fbSJean Delvare { 5178d5d45fbSJean Delvare int res = 0; 5188d5d45fbSJean Delvare 5198d5d45fbSJean Delvare if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { 5208d5d45fbSJean Delvare switch (data->conf1 & 0x60) { 5211c720093SGuenter Roeck case 0x00: 5221c720093SGuenter Roeck /* 5231c720093SGuenter Roeck * remote temp1 controls fan1, 5241c720093SGuenter Roeck * remote temp2 controls fan2 5251c720093SGuenter Roeck */ 5268d5d45fbSJean Delvare res = data->temp[chan+1] >= 5278d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]); 5288d5d45fbSJean Delvare break; 5298d5d45fbSJean Delvare case 0x20: /* remote temp1 controls both fans */ 5308d5d45fbSJean Delvare res = 5318d5d45fbSJean Delvare data->temp[1] >= 5328d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]); 5338d5d45fbSJean Delvare break; 5348d5d45fbSJean Delvare case 0x40: /* remote temp2 controls both fans */ 5358d5d45fbSJean Delvare res = 5368d5d45fbSJean Delvare data->temp[2] >= 5378d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]); 5388d5d45fbSJean Delvare break; 5398d5d45fbSJean Delvare case 0x60: /* max controls both fans */ 5408d5d45fbSJean Delvare res = 5418d5d45fbSJean Delvare data->temp[0] >= 5428d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0]) 5438d5d45fbSJean Delvare || data->temp[1] >= 5448d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]) 5458d5d45fbSJean Delvare || (data->chip_type == adm1031 5468d5d45fbSJean Delvare && data->temp[2] >= 5478d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2])); 5488d5d45fbSJean Delvare break; 5498d5d45fbSJean Delvare } 5508d5d45fbSJean Delvare } else { 5518d5d45fbSJean Delvare res = data->pwm[chan] > 0; 5528d5d45fbSJean Delvare } 5538d5d45fbSJean Delvare return res; 5548d5d45fbSJean Delvare } 5558d5d45fbSJean Delvare 5568e757e15SGuenter Roeck static ssize_t fan_show(struct device *dev, struct device_attribute *attr, 5578e757e15SGuenter Roeck char *buf) 5588d5d45fbSJean Delvare { 559c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5608d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 5618d5d45fbSJean Delvare int value; 5628d5d45fbSJean Delvare 5638d5d45fbSJean Delvare value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr], 5648d5d45fbSJean Delvare FAN_DIV_FROM_REG(data->fan_div[nr])) : 0; 5658d5d45fbSJean Delvare return sprintf(buf, "%d\n", value); 5668d5d45fbSJean Delvare } 5678d5d45fbSJean Delvare 5688e757e15SGuenter Roeck static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr, 5698e757e15SGuenter Roeck char *buf) 5708d5d45fbSJean Delvare { 571c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5728d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 5738d5d45fbSJean Delvare return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr])); 5748d5d45fbSJean Delvare } 5758e757e15SGuenter Roeck static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr, 5768e757e15SGuenter Roeck char *buf) 5778d5d45fbSJean Delvare { 578c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5798d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 5808d5d45fbSJean Delvare return sprintf(buf, "%d\n", 5818d5d45fbSJean Delvare FAN_FROM_REG(data->fan_min[nr], 5828d5d45fbSJean Delvare FAN_DIV_FROM_REG(data->fan_div[nr]))); 5838d5d45fbSJean Delvare } 5848e757e15SGuenter Roeck static ssize_t fan_min_store(struct device *dev, 5858e757e15SGuenter Roeck struct device_attribute *attr, const char *buf, 5868e757e15SGuenter Roeck size_t count) 5878d5d45fbSJean Delvare { 588b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 589b060f3c4SAxel Lin struct i2c_client *client = data->client; 590c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5911c720093SGuenter Roeck long val; 5921c720093SGuenter Roeck int ret; 5931c720093SGuenter Roeck 5941c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 5951c720093SGuenter Roeck if (ret) 5961c720093SGuenter Roeck return ret; 5978d5d45fbSJean Delvare 5989a61bf63SIngo Molnar mutex_lock(&data->update_lock); 5998d5d45fbSJean Delvare if (val) { 6008d5d45fbSJean Delvare data->fan_min[nr] = 6018d5d45fbSJean Delvare FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); 6028d5d45fbSJean Delvare } else { 6038d5d45fbSJean Delvare data->fan_min[nr] = 0xff; 6048d5d45fbSJean Delvare } 6058d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); 6069a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 6078d5d45fbSJean Delvare return count; 6088d5d45fbSJean Delvare } 6098e757e15SGuenter Roeck static ssize_t fan_div_store(struct device *dev, 6108e757e15SGuenter Roeck struct device_attribute *attr, const char *buf, 6118e757e15SGuenter Roeck size_t count) 6128d5d45fbSJean Delvare { 613b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 614b060f3c4SAxel Lin struct i2c_client *client = data->client; 615c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6161c720093SGuenter Roeck long val; 6178d5d45fbSJean Delvare u8 tmp; 6188d5d45fbSJean Delvare int old_div; 6198d5d45fbSJean Delvare int new_min; 6201c720093SGuenter Roeck int ret; 6211c720093SGuenter Roeck 6221c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 6231c720093SGuenter Roeck if (ret) 6241c720093SGuenter Roeck return ret; 6258d5d45fbSJean Delvare 6268d5d45fbSJean Delvare tmp = val == 8 ? 0xc0 : 6278d5d45fbSJean Delvare val == 4 ? 0x80 : 6288d5d45fbSJean Delvare val == 2 ? 0x40 : 6298d5d45fbSJean Delvare val == 1 ? 0x00 : 6308d5d45fbSJean Delvare 0xff; 6318d5d45fbSJean Delvare if (tmp == 0xff) 6328d5d45fbSJean Delvare return -EINVAL; 6338d5d45fbSJean Delvare 6349a61bf63SIngo Molnar mutex_lock(&data->update_lock); 63538a1f0e9SJean Delvare /* Get fresh readings */ 63638a1f0e9SJean Delvare data->fan_div[nr] = adm1031_read_value(client, 63738a1f0e9SJean Delvare ADM1031_REG_FAN_DIV(nr)); 63838a1f0e9SJean Delvare data->fan_min[nr] = adm1031_read_value(client, 63938a1f0e9SJean Delvare ADM1031_REG_FAN_MIN(nr)); 64038a1f0e9SJean Delvare 64138a1f0e9SJean Delvare /* Write the new clock divider and fan min */ 6428d5d45fbSJean Delvare old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); 6436d6006b8SJean Delvare data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]); 6446d6006b8SJean Delvare new_min = data->fan_min[nr] * old_div / val; 6458d5d45fbSJean Delvare data->fan_min[nr] = new_min > 0xff ? 0xff : new_min; 6468d5d45fbSJean Delvare 6478d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr), 6488d5d45fbSJean Delvare data->fan_div[nr]); 6498d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), 6508d5d45fbSJean Delvare data->fan_min[nr]); 65138a1f0e9SJean Delvare 65238a1f0e9SJean Delvare /* Invalidate the cache: fan speed is no longer valid */ 653*952a11caSPaul Fertser data->valid = false; 6549a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 6558d5d45fbSJean Delvare return count; 6568d5d45fbSJean Delvare } 6578d5d45fbSJean Delvare 6588e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0); 6598e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); 6608e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0); 6618e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1); 6628e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1); 6638e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1); 6648d5d45fbSJean Delvare 6658d5d45fbSJean Delvare /* Temps */ 6668e757e15SGuenter Roeck static ssize_t temp_show(struct device *dev, struct device_attribute *attr, 6678e757e15SGuenter Roeck char *buf) 6688d5d45fbSJean Delvare { 669c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6708d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 6718d5d45fbSJean Delvare int ext; 6728d5d45fbSJean Delvare ext = nr == 0 ? 6738d5d45fbSJean Delvare ((data->ext_temp[nr] >> 6) & 0x3) * 2 : 6748d5d45fbSJean Delvare (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); 6758d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); 6768d5d45fbSJean Delvare } 6778e757e15SGuenter Roeck static ssize_t temp_offset_show(struct device *dev, 67849dc9efeSIra Snyder struct device_attribute *attr, char *buf) 67949dc9efeSIra Snyder { 68049dc9efeSIra Snyder int nr = to_sensor_dev_attr(attr)->index; 68149dc9efeSIra Snyder struct adm1031_data *data = adm1031_update_device(dev); 68249dc9efeSIra Snyder return sprintf(buf, "%d\n", 68349dc9efeSIra Snyder TEMP_OFFSET_FROM_REG(data->temp_offset[nr])); 68449dc9efeSIra Snyder } 6858e757e15SGuenter Roeck static ssize_t temp_min_show(struct device *dev, 686c801082dSJean Delvare struct device_attribute *attr, char *buf) 6878d5d45fbSJean Delvare { 688c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6898d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 6908d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); 6918d5d45fbSJean Delvare } 6928e757e15SGuenter Roeck static ssize_t temp_max_show(struct device *dev, 693c801082dSJean Delvare struct device_attribute *attr, char *buf) 6948d5d45fbSJean Delvare { 695c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6968d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 6978d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); 6988d5d45fbSJean Delvare } 6998e757e15SGuenter Roeck static ssize_t temp_crit_show(struct device *dev, 700c801082dSJean Delvare struct device_attribute *attr, char *buf) 7018d5d45fbSJean Delvare { 702c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7038d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 7048d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); 7058d5d45fbSJean Delvare } 7068e757e15SGuenter Roeck static ssize_t temp_offset_store(struct device *dev, 7078e757e15SGuenter Roeck struct device_attribute *attr, 7088e757e15SGuenter Roeck const char *buf, size_t count) 70949dc9efeSIra Snyder { 710b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 711b060f3c4SAxel Lin struct i2c_client *client = data->client; 71249dc9efeSIra Snyder int nr = to_sensor_dev_attr(attr)->index; 7131c720093SGuenter Roeck long val; 7141c720093SGuenter Roeck int ret; 71549dc9efeSIra Snyder 7161c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 7171c720093SGuenter Roeck if (ret) 7181c720093SGuenter Roeck return ret; 7191c720093SGuenter Roeck 7202a844c14SGuenter Roeck val = clamp_val(val, -15000, 15000); 72149dc9efeSIra Snyder mutex_lock(&data->update_lock); 72249dc9efeSIra Snyder data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val); 72349dc9efeSIra Snyder adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr), 72449dc9efeSIra Snyder data->temp_offset[nr]); 72549dc9efeSIra Snyder mutex_unlock(&data->update_lock); 72649dc9efeSIra Snyder return count; 72749dc9efeSIra Snyder } 7288e757e15SGuenter Roeck static ssize_t temp_min_store(struct device *dev, 7298e757e15SGuenter Roeck struct device_attribute *attr, const char *buf, 7308e757e15SGuenter Roeck size_t count) 7318d5d45fbSJean Delvare { 732b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 733b060f3c4SAxel Lin struct i2c_client *client = data->client; 734c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7351c720093SGuenter Roeck long val; 7361c720093SGuenter Roeck int ret; 7378d5d45fbSJean Delvare 7381c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 7391c720093SGuenter Roeck if (ret) 7401c720093SGuenter Roeck return ret; 7411c720093SGuenter Roeck 742145e74a4SGuenter Roeck val = clamp_val(val, -55000, 127000); 7439a61bf63SIngo Molnar mutex_lock(&data->update_lock); 7448d5d45fbSJean Delvare data->temp_min[nr] = TEMP_TO_REG(val); 7458d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), 7468d5d45fbSJean Delvare data->temp_min[nr]); 7479a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7488d5d45fbSJean Delvare return count; 7498d5d45fbSJean Delvare } 7508e757e15SGuenter Roeck static ssize_t temp_max_store(struct device *dev, 7518e757e15SGuenter Roeck struct device_attribute *attr, const char *buf, 7528e757e15SGuenter Roeck size_t count) 7538d5d45fbSJean Delvare { 754b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 755b060f3c4SAxel Lin struct i2c_client *client = data->client; 756c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7571c720093SGuenter Roeck long val; 7581c720093SGuenter Roeck int ret; 7598d5d45fbSJean Delvare 7601c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 7611c720093SGuenter Roeck if (ret) 7621c720093SGuenter Roeck return ret; 7631c720093SGuenter Roeck 764145e74a4SGuenter Roeck val = clamp_val(val, -55000, 127000); 7659a61bf63SIngo Molnar mutex_lock(&data->update_lock); 7668d5d45fbSJean Delvare data->temp_max[nr] = TEMP_TO_REG(val); 7678d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), 7688d5d45fbSJean Delvare data->temp_max[nr]); 7699a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7708d5d45fbSJean Delvare return count; 7718d5d45fbSJean Delvare } 7728e757e15SGuenter Roeck static ssize_t temp_crit_store(struct device *dev, 7738e757e15SGuenter Roeck struct device_attribute *attr, const char *buf, 7748e757e15SGuenter Roeck size_t count) 7758d5d45fbSJean Delvare { 776b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 777b060f3c4SAxel Lin struct i2c_client *client = data->client; 778c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7791c720093SGuenter Roeck long val; 7801c720093SGuenter Roeck int ret; 7818d5d45fbSJean Delvare 7821c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 7831c720093SGuenter Roeck if (ret) 7841c720093SGuenter Roeck return ret; 7851c720093SGuenter Roeck 786145e74a4SGuenter Roeck val = clamp_val(val, -55000, 127000); 7879a61bf63SIngo Molnar mutex_lock(&data->update_lock); 7888d5d45fbSJean Delvare data->temp_crit[nr] = TEMP_TO_REG(val); 7898d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), 7908d5d45fbSJean Delvare data->temp_crit[nr]); 7919a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7928d5d45fbSJean Delvare return count; 7938d5d45fbSJean Delvare } 7948d5d45fbSJean Delvare 7958e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0); 7968e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_offset, temp_offset, 0); 7978e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0); 7988e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0); 7998e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp_crit, 0); 8008e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1); 8018e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_offset, temp_offset, 1); 8028e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1); 8038e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1); 8048e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp_crit, 1); 8058e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2); 8068e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_offset, temp_offset, 2); 8078e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2); 8088e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2); 8098e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_crit, temp_crit, 2); 8108d5d45fbSJean Delvare 8118d5d45fbSJean Delvare /* Alarms */ 812bfb6b173SJulia Lawall static ssize_t alarms_show(struct device *dev, struct device_attribute *attr, 8131c720093SGuenter Roeck char *buf) 8148d5d45fbSJean Delvare { 8158d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 8168d5d45fbSJean Delvare return sprintf(buf, "%d\n", data->alarm); 8178d5d45fbSJean Delvare } 8188d5d45fbSJean Delvare 819bfb6b173SJulia Lawall static DEVICE_ATTR_RO(alarms); 8208d5d45fbSJean Delvare 8218e757e15SGuenter Roeck static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, 8228e757e15SGuenter Roeck char *buf) 823050ab878SJean Delvare { 824050ab878SJean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 825050ab878SJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 826050ab878SJean Delvare return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1); 827050ab878SJean Delvare } 828050ab878SJean Delvare 8298e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 0); 8308e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_fault, alarm, 1); 8318e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 2); 8328e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, alarm, 3); 8338e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 4); 8348e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 5); 8358e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6); 8368e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 7); 8378e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 8); 8388e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_fault, alarm, 9); 8398e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, alarm, 10); 8408e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_min_alarm, alarm, 11); 8418e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 12); 8428e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 13); 8438e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 14); 8448d5d45fbSJean Delvare 845a51b9944SGuenter Roeck /* Update Interval */ 846a51b9944SGuenter Roeck static const unsigned int update_intervals[] = { 84787c33daaSJean Delvare 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 84887c33daaSJean Delvare }; 84987c33daaSJean Delvare 850bfb6b173SJulia Lawall static ssize_t update_interval_show(struct device *dev, 85187c33daaSJean Delvare struct device_attribute *attr, char *buf) 85287c33daaSJean Delvare { 853b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 85487c33daaSJean Delvare 855a51b9944SGuenter Roeck return sprintf(buf, "%u\n", data->update_interval); 85687c33daaSJean Delvare } 85787c33daaSJean Delvare 858bfb6b173SJulia Lawall static ssize_t update_interval_store(struct device *dev, 85987c33daaSJean Delvare struct device_attribute *attr, 86087c33daaSJean Delvare const char *buf, size_t count) 86187c33daaSJean Delvare { 862b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 863b060f3c4SAxel Lin struct i2c_client *client = data->client; 86487c33daaSJean Delvare unsigned long val; 86587c33daaSJean Delvare int i, err; 86687c33daaSJean Delvare u8 reg; 86787c33daaSJean Delvare 868179c4fdbSFrans Meulenbroeks err = kstrtoul(buf, 10, &val); 86987c33daaSJean Delvare if (err) 87087c33daaSJean Delvare return err; 87187c33daaSJean Delvare 872a51b9944SGuenter Roeck /* 873a51b9944SGuenter Roeck * Find the nearest update interval from the table. 874a51b9944SGuenter Roeck * Use it to determine the matching update rate. 875a51b9944SGuenter Roeck */ 876a51b9944SGuenter Roeck for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) { 877a51b9944SGuenter Roeck if (val >= update_intervals[i]) 87887c33daaSJean Delvare break; 87987c33daaSJean Delvare } 880a51b9944SGuenter Roeck /* if not found, we point to the last entry (lowest update interval) */ 88187c33daaSJean Delvare 88287c33daaSJean Delvare /* set the new update rate while preserving other settings */ 88387c33daaSJean Delvare reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); 88487c33daaSJean Delvare reg &= ~ADM1031_UPDATE_RATE_MASK; 88587c33daaSJean Delvare reg |= i << ADM1031_UPDATE_RATE_SHIFT; 88687c33daaSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg); 88787c33daaSJean Delvare 88887c33daaSJean Delvare mutex_lock(&data->update_lock); 889a51b9944SGuenter Roeck data->update_interval = update_intervals[i]; 89087c33daaSJean Delvare mutex_unlock(&data->update_lock); 89187c33daaSJean Delvare 89287c33daaSJean Delvare return count; 89387c33daaSJean Delvare } 89487c33daaSJean Delvare 895bfb6b173SJulia Lawall static DEVICE_ATTR_RW(update_interval); 89687c33daaSJean Delvare 897681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = { 898c801082dSJean Delvare &sensor_dev_attr_fan1_input.dev_attr.attr, 899c801082dSJean Delvare &sensor_dev_attr_fan1_div.dev_attr.attr, 900c801082dSJean Delvare &sensor_dev_attr_fan1_min.dev_attr.attr, 901050ab878SJean Delvare &sensor_dev_attr_fan1_alarm.dev_attr.attr, 902050ab878SJean Delvare &sensor_dev_attr_fan1_fault.dev_attr.attr, 903c801082dSJean Delvare &sensor_dev_attr_pwm1.dev_attr.attr, 904c801082dSJean Delvare &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, 905c801082dSJean Delvare &sensor_dev_attr_temp1_input.dev_attr.attr, 90649dc9efeSIra Snyder &sensor_dev_attr_temp1_offset.dev_attr.attr, 907c801082dSJean Delvare &sensor_dev_attr_temp1_min.dev_attr.attr, 908050ab878SJean Delvare &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 909c801082dSJean Delvare &sensor_dev_attr_temp1_max.dev_attr.attr, 910050ab878SJean Delvare &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 911c801082dSJean Delvare &sensor_dev_attr_temp1_crit.dev_attr.attr, 912050ab878SJean Delvare &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 913c801082dSJean Delvare &sensor_dev_attr_temp2_input.dev_attr.attr, 91449dc9efeSIra Snyder &sensor_dev_attr_temp2_offset.dev_attr.attr, 915c801082dSJean Delvare &sensor_dev_attr_temp2_min.dev_attr.attr, 916050ab878SJean Delvare &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, 917c801082dSJean Delvare &sensor_dev_attr_temp2_max.dev_attr.attr, 918050ab878SJean Delvare &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, 919c801082dSJean Delvare &sensor_dev_attr_temp2_crit.dev_attr.attr, 920050ab878SJean Delvare &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, 921050ab878SJean Delvare &sensor_dev_attr_temp2_fault.dev_attr.attr, 922681c6f7aSMark M. Hoffman 923c801082dSJean Delvare &sensor_dev_attr_auto_temp1_off.dev_attr.attr, 924c801082dSJean Delvare &sensor_dev_attr_auto_temp1_min.dev_attr.attr, 925c801082dSJean Delvare &sensor_dev_attr_auto_temp1_max.dev_attr.attr, 926681c6f7aSMark M. Hoffman 927c801082dSJean Delvare &sensor_dev_attr_auto_temp2_off.dev_attr.attr, 928c801082dSJean Delvare &sensor_dev_attr_auto_temp2_min.dev_attr.attr, 929c801082dSJean Delvare &sensor_dev_attr_auto_temp2_max.dev_attr.attr, 930681c6f7aSMark M. Hoffman 931c801082dSJean Delvare &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, 932681c6f7aSMark M. Hoffman 933a51b9944SGuenter Roeck &dev_attr_update_interval.attr, 934681c6f7aSMark M. Hoffman &dev_attr_alarms.attr, 935681c6f7aSMark M. Hoffman 936681c6f7aSMark M. Hoffman NULL 937681c6f7aSMark M. Hoffman }; 938681c6f7aSMark M. Hoffman 939681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = { 940681c6f7aSMark M. Hoffman .attrs = adm1031_attributes, 941681c6f7aSMark M. Hoffman }; 942681c6f7aSMark M. Hoffman 943681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = { 944c801082dSJean Delvare &sensor_dev_attr_fan2_input.dev_attr.attr, 945c801082dSJean Delvare &sensor_dev_attr_fan2_div.dev_attr.attr, 946c801082dSJean Delvare &sensor_dev_attr_fan2_min.dev_attr.attr, 947050ab878SJean Delvare &sensor_dev_attr_fan2_alarm.dev_attr.attr, 948050ab878SJean Delvare &sensor_dev_attr_fan2_fault.dev_attr.attr, 949c801082dSJean Delvare &sensor_dev_attr_pwm2.dev_attr.attr, 950c801082dSJean Delvare &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, 951c801082dSJean Delvare &sensor_dev_attr_temp3_input.dev_attr.attr, 95249dc9efeSIra Snyder &sensor_dev_attr_temp3_offset.dev_attr.attr, 953c801082dSJean Delvare &sensor_dev_attr_temp3_min.dev_attr.attr, 954050ab878SJean Delvare &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, 955c801082dSJean Delvare &sensor_dev_attr_temp3_max.dev_attr.attr, 956050ab878SJean Delvare &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, 957c801082dSJean Delvare &sensor_dev_attr_temp3_crit.dev_attr.attr, 958050ab878SJean Delvare &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, 959050ab878SJean Delvare &sensor_dev_attr_temp3_fault.dev_attr.attr, 960c801082dSJean Delvare &sensor_dev_attr_auto_temp3_off.dev_attr.attr, 961c801082dSJean Delvare &sensor_dev_attr_auto_temp3_min.dev_attr.attr, 962c801082dSJean Delvare &sensor_dev_attr_auto_temp3_max.dev_attr.attr, 963c801082dSJean Delvare &sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr, 964681c6f7aSMark M. Hoffman NULL 965681c6f7aSMark M. Hoffman }; 966681c6f7aSMark M. Hoffman 967681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = { 968681c6f7aSMark M. Hoffman .attrs = adm1031_attributes_opt, 969681c6f7aSMark M. Hoffman }; 970681c6f7aSMark M. Hoffman 971af200f88SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */ 972310ec792SJean Delvare static int adm1031_detect(struct i2c_client *client, 973af200f88SJean Delvare struct i2c_board_info *info) 9748d5d45fbSJean Delvare { 975af200f88SJean Delvare struct i2c_adapter *adapter = client->adapter; 97652df6440SJean Delvare const char *name; 97752df6440SJean Delvare int id, co; 9788d5d45fbSJean Delvare 9798d5d45fbSJean Delvare if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 980af200f88SJean Delvare return -ENODEV; 9818d5d45fbSJean Delvare 9826d6006b8SJean Delvare id = i2c_smbus_read_byte_data(client, 0x3d); 9836d6006b8SJean Delvare co = i2c_smbus_read_byte_data(client, 0x3e); 9848d5d45fbSJean Delvare 9858d5d45fbSJean Delvare if (!((id == 0x31 || id == 0x30) && co == 0x41)) 986af200f88SJean Delvare return -ENODEV; 98752df6440SJean Delvare name = (id == 0x30) ? "adm1030" : "adm1031"; 9888d5d45fbSJean Delvare 989af200f88SJean Delvare strlcpy(info->type, name, I2C_NAME_SIZE); 9908d5d45fbSJean Delvare 991af200f88SJean Delvare return 0; 992af200f88SJean Delvare } 993af200f88SJean Delvare 994278ee1c8SAxel Lin static void adm1031_init_client(struct i2c_client *client) 995278ee1c8SAxel Lin { 996278ee1c8SAxel Lin unsigned int read_val; 997278ee1c8SAxel Lin unsigned int mask; 998278ee1c8SAxel Lin int i; 999278ee1c8SAxel Lin struct adm1031_data *data = i2c_get_clientdata(client); 1000278ee1c8SAxel Lin 1001278ee1c8SAxel Lin mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE); 1002278ee1c8SAxel Lin if (data->chip_type == adm1031) { 1003278ee1c8SAxel Lin mask |= (ADM1031_CONF2_PWM2_ENABLE | 1004278ee1c8SAxel Lin ADM1031_CONF2_TACH2_ENABLE); 1005278ee1c8SAxel Lin } 1006278ee1c8SAxel Lin /* Initialize the ADM1031 chip (enables fan speed reading ) */ 1007278ee1c8SAxel Lin read_val = adm1031_read_value(client, ADM1031_REG_CONF2); 1008278ee1c8SAxel Lin if ((read_val | mask) != read_val) 1009278ee1c8SAxel Lin adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask); 1010278ee1c8SAxel Lin 1011278ee1c8SAxel Lin read_val = adm1031_read_value(client, ADM1031_REG_CONF1); 1012278ee1c8SAxel Lin if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) { 1013278ee1c8SAxel Lin adm1031_write_value(client, ADM1031_REG_CONF1, 1014278ee1c8SAxel Lin read_val | ADM1031_CONF1_MONITOR_ENABLE); 1015278ee1c8SAxel Lin } 1016278ee1c8SAxel Lin 1017278ee1c8SAxel Lin /* Read the chip's update rate */ 1018278ee1c8SAxel Lin mask = ADM1031_UPDATE_RATE_MASK; 1019278ee1c8SAxel Lin read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); 1020278ee1c8SAxel Lin i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT; 1021278ee1c8SAxel Lin /* Save it as update interval */ 1022278ee1c8SAxel Lin data->update_interval = update_intervals[i]; 1023278ee1c8SAxel Lin } 1024278ee1c8SAxel Lin 102567487038SStephen Kitt static const struct i2c_device_id adm1031_id[]; 102667487038SStephen Kitt 102767487038SStephen Kitt static int adm1031_probe(struct i2c_client *client) 1028af200f88SJean Delvare { 1029b060f3c4SAxel Lin struct device *dev = &client->dev; 1030b060f3c4SAxel Lin struct device *hwmon_dev; 1031af200f88SJean Delvare struct adm1031_data *data; 1032af200f88SJean Delvare 1033b060f3c4SAxel Lin data = devm_kzalloc(dev, sizeof(struct adm1031_data), GFP_KERNEL); 1034dc2fd663SGuenter Roeck if (!data) 1035dc2fd663SGuenter Roeck return -ENOMEM; 1036af200f88SJean Delvare 1037af200f88SJean Delvare i2c_set_clientdata(client, data); 1038b060f3c4SAxel Lin data->client = client; 103967487038SStephen Kitt data->chip_type = i2c_match_id(adm1031_id, client)->driver_data; 10409a61bf63SIngo Molnar mutex_init(&data->update_lock); 10418d5d45fbSJean Delvare 1042af200f88SJean Delvare if (data->chip_type == adm1030) 1043af200f88SJean Delvare data->chan_select_table = &auto_channel_select_table_adm1030; 1044af200f88SJean Delvare else 1045af200f88SJean Delvare data->chan_select_table = &auto_channel_select_table_adm1031; 10468d5d45fbSJean Delvare 10478d5d45fbSJean Delvare /* Initialize the ADM1031 chip */ 10486d6006b8SJean Delvare adm1031_init_client(client); 10498d5d45fbSJean Delvare 1050b060f3c4SAxel Lin /* sysfs hooks */ 1051b060f3c4SAxel Lin data->groups[0] = &adm1031_group; 1052b060f3c4SAxel Lin if (data->chip_type == adm1031) 1053b060f3c4SAxel Lin data->groups[1] = &adm1031_group_opt; 1054681c6f7aSMark M. Hoffman 1055b060f3c4SAxel Lin hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 1056b060f3c4SAxel Lin data, data->groups); 1057b060f3c4SAxel Lin return PTR_ERR_OR_ZERO(hwmon_dev); 10588d5d45fbSJean Delvare } 10598d5d45fbSJean Delvare 1060278ee1c8SAxel Lin static const struct i2c_device_id adm1031_id[] = { 1061278ee1c8SAxel Lin { "adm1030", adm1030 }, 1062278ee1c8SAxel Lin { "adm1031", adm1031 }, 1063278ee1c8SAxel Lin { } 1064278ee1c8SAxel Lin }; 1065278ee1c8SAxel Lin MODULE_DEVICE_TABLE(i2c, adm1031_id); 10668d5d45fbSJean Delvare 1067278ee1c8SAxel Lin static struct i2c_driver adm1031_driver = { 1068278ee1c8SAxel Lin .class = I2C_CLASS_HWMON, 1069278ee1c8SAxel Lin .driver = { 1070278ee1c8SAxel Lin .name = "adm1031", 1071278ee1c8SAxel Lin }, 107267487038SStephen Kitt .probe_new = adm1031_probe, 1073278ee1c8SAxel Lin .id_table = adm1031_id, 1074278ee1c8SAxel Lin .detect = adm1031_detect, 1075278ee1c8SAxel Lin .address_list = normal_i2c, 1076278ee1c8SAxel Lin }; 10778d5d45fbSJean Delvare 1078f0967eeaSAxel Lin module_i2c_driver(adm1031_driver); 10798d5d45fbSJean Delvare 10808d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>"); 10818d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver"); 10828d5d45fbSJean Delvare MODULE_LICENSE("GPL"); 1083