18d5d45fbSJean Delvare /* 2fbb6670dSGuenter Roeck * adm1031.c - Part of lm_sensors, Linux kernel modules for hardware 3fbb6670dSGuenter Roeck * monitoring 4fbb6670dSGuenter Roeck * Based on lm75.c and lm85.c 5fbb6670dSGuenter Roeck * Supports adm1030 / adm1031 6fbb6670dSGuenter Roeck * Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org> 77c81c60fSJean Delvare * Reworked by Jean Delvare <jdelvare@suse.de> 8fbb6670dSGuenter Roeck * 9fbb6670dSGuenter Roeck * This program is free software; you can redistribute it and/or modify 10fbb6670dSGuenter Roeck * it under the terms of the GNU General Public License as published by 11fbb6670dSGuenter Roeck * the Free Software Foundation; either version 2 of the License, or 12fbb6670dSGuenter Roeck * (at your option) any later version. 13fbb6670dSGuenter Roeck * 14fbb6670dSGuenter Roeck * This program is distributed in the hope that it will be useful, 15fbb6670dSGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 16fbb6670dSGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17fbb6670dSGuenter Roeck * GNU General Public License for more details. 18fbb6670dSGuenter Roeck * 19fbb6670dSGuenter Roeck * You should have received a copy of the GNU General Public License 20fbb6670dSGuenter Roeck * along with this program; if not, write to the Free Software 21fbb6670dSGuenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 228d5d45fbSJean Delvare */ 238d5d45fbSJean Delvare 248d5d45fbSJean Delvare #include <linux/module.h> 258d5d45fbSJean Delvare #include <linux/init.h> 268d5d45fbSJean Delvare #include <linux/slab.h> 278d5d45fbSJean Delvare #include <linux/jiffies.h> 288d5d45fbSJean Delvare #include <linux/i2c.h> 29943b0830SMark M. Hoffman #include <linux/hwmon.h> 30c801082dSJean Delvare #include <linux/hwmon-sysfs.h> 31943b0830SMark M. Hoffman #include <linux/err.h> 329a61bf63SIngo Molnar #include <linux/mutex.h> 338d5d45fbSJean Delvare 348d5d45fbSJean Delvare /* Following macros takes channel parameter starting from 0 to 2 */ 358d5d45fbSJean Delvare #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) 368d5d45fbSJean Delvare #define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) 378d5d45fbSJean Delvare #define ADM1031_REG_PWM (0x22) 388d5d45fbSJean Delvare #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) 3987c33daaSJean Delvare #define ADM1031_REG_FAN_FILTER (0x23) 408d5d45fbSJean Delvare 4149dc9efeSIra Snyder #define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) 428d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) 438d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) 448d5d45fbSJean Delvare #define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) 458d5d45fbSJean Delvare 466d6006b8SJean Delvare #define ADM1031_REG_TEMP(nr) (0x0a + (nr)) 478d5d45fbSJean Delvare #define ADM1031_REG_AUTO_TEMP(nr) (0x24 + (nr)) 488d5d45fbSJean Delvare 498d5d45fbSJean Delvare #define ADM1031_REG_STATUS(nr) (0x2 + (nr)) 508d5d45fbSJean Delvare 516d6006b8SJean Delvare #define ADM1031_REG_CONF1 0x00 526d6006b8SJean Delvare #define ADM1031_REG_CONF2 0x01 536d6006b8SJean Delvare #define ADM1031_REG_EXT_TEMP 0x06 548d5d45fbSJean Delvare 558d5d45fbSJean Delvare #define ADM1031_CONF1_MONITOR_ENABLE 0x01 /* Monitoring enable */ 568d5d45fbSJean Delvare #define ADM1031_CONF1_PWM_INVERT 0x08 /* PWM Invert */ 578d5d45fbSJean Delvare #define ADM1031_CONF1_AUTO_MODE 0x80 /* Auto FAN */ 588d5d45fbSJean Delvare 598d5d45fbSJean Delvare #define ADM1031_CONF2_PWM1_ENABLE 0x01 608d5d45fbSJean Delvare #define ADM1031_CONF2_PWM2_ENABLE 0x02 618d5d45fbSJean Delvare #define ADM1031_CONF2_TACH1_ENABLE 0x04 628d5d45fbSJean Delvare #define ADM1031_CONF2_TACH2_ENABLE 0x08 638d5d45fbSJean Delvare #define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan)) 648d5d45fbSJean Delvare 6587c33daaSJean Delvare #define ADM1031_UPDATE_RATE_MASK 0x1c 6687c33daaSJean Delvare #define ADM1031_UPDATE_RATE_SHIFT 2 6787c33daaSJean Delvare 688d5d45fbSJean Delvare /* Addresses to scan */ 6925e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; 708d5d45fbSJean Delvare 71e5e9f44cSJean Delvare enum chips { adm1030, adm1031 }; 728d5d45fbSJean Delvare 738d5d45fbSJean Delvare typedef u8 auto_chan_table_t[8][2]; 748d5d45fbSJean Delvare 758d5d45fbSJean Delvare /* Each client has this additional data */ 768d5d45fbSJean Delvare struct adm1031_data { 77*b060f3c4SAxel Lin struct i2c_client *client; 78*b060f3c4SAxel Lin const struct attribute_group *groups[3]; 799a61bf63SIngo Molnar struct mutex update_lock; 808d5d45fbSJean Delvare int chip_type; 818d5d45fbSJean Delvare char valid; /* !=0 if following fields are valid */ 828d5d45fbSJean Delvare unsigned long last_updated; /* In jiffies */ 83a51b9944SGuenter Roeck unsigned int update_interval; /* In milliseconds */ 84fbb6670dSGuenter Roeck /* 85fbb6670dSGuenter Roeck * The chan_select_table contains the possible configurations for 868d5d45fbSJean Delvare * auto fan control. 878d5d45fbSJean Delvare */ 886d6006b8SJean Delvare const auto_chan_table_t *chan_select_table; 898d5d45fbSJean Delvare u16 alarm; 908d5d45fbSJean Delvare u8 conf1; 918d5d45fbSJean Delvare u8 conf2; 928d5d45fbSJean Delvare u8 fan[2]; 938d5d45fbSJean Delvare u8 fan_div[2]; 948d5d45fbSJean Delvare u8 fan_min[2]; 958d5d45fbSJean Delvare u8 pwm[2]; 968d5d45fbSJean Delvare u8 old_pwm[2]; 978d5d45fbSJean Delvare s8 temp[3]; 988d5d45fbSJean Delvare u8 ext_temp[3]; 998d5d45fbSJean Delvare u8 auto_temp[3]; 1008d5d45fbSJean Delvare u8 auto_temp_min[3]; 1018d5d45fbSJean Delvare u8 auto_temp_off[3]; 1028d5d45fbSJean Delvare u8 auto_temp_max[3]; 10349dc9efeSIra Snyder s8 temp_offset[3]; 1048d5d45fbSJean Delvare s8 temp_min[3]; 1058d5d45fbSJean Delvare s8 temp_max[3]; 1068d5d45fbSJean Delvare s8 temp_crit[3]; 1078d5d45fbSJean Delvare }; 1088d5d45fbSJean Delvare 1098d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) 1108d5d45fbSJean Delvare { 1118d5d45fbSJean Delvare return i2c_smbus_read_byte_data(client, reg); 1128d5d45fbSJean Delvare } 1138d5d45fbSJean Delvare 1148d5d45fbSJean Delvare static inline int 1158d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value) 1168d5d45fbSJean Delvare { 1178d5d45fbSJean Delvare return i2c_smbus_write_byte_data(client, reg, value); 1188d5d45fbSJean Delvare } 1198d5d45fbSJean Delvare 120278ee1c8SAxel Lin static struct adm1031_data *adm1031_update_device(struct device *dev) 121278ee1c8SAxel Lin { 122*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 123*b060f3c4SAxel Lin struct i2c_client *client = data->client; 124278ee1c8SAxel Lin unsigned long next_update; 125278ee1c8SAxel Lin int chan; 126278ee1c8SAxel Lin 127278ee1c8SAxel Lin mutex_lock(&data->update_lock); 128278ee1c8SAxel Lin 129278ee1c8SAxel Lin next_update = data->last_updated 130278ee1c8SAxel Lin + msecs_to_jiffies(data->update_interval); 131278ee1c8SAxel Lin if (time_after(jiffies, next_update) || !data->valid) { 132278ee1c8SAxel Lin 133278ee1c8SAxel Lin dev_dbg(&client->dev, "Starting adm1031 update\n"); 134278ee1c8SAxel Lin for (chan = 0; 135278ee1c8SAxel Lin chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) { 136278ee1c8SAxel Lin u8 oldh, newh; 137278ee1c8SAxel Lin 138278ee1c8SAxel Lin oldh = 139278ee1c8SAxel Lin adm1031_read_value(client, ADM1031_REG_TEMP(chan)); 140278ee1c8SAxel Lin data->ext_temp[chan] = 141278ee1c8SAxel Lin adm1031_read_value(client, ADM1031_REG_EXT_TEMP); 142278ee1c8SAxel Lin newh = 143278ee1c8SAxel Lin adm1031_read_value(client, ADM1031_REG_TEMP(chan)); 144278ee1c8SAxel Lin if (newh != oldh) { 145278ee1c8SAxel Lin data->ext_temp[chan] = 146278ee1c8SAxel Lin adm1031_read_value(client, 147278ee1c8SAxel Lin ADM1031_REG_EXT_TEMP); 148278ee1c8SAxel Lin #ifdef DEBUG 149278ee1c8SAxel Lin oldh = 150278ee1c8SAxel Lin adm1031_read_value(client, 151278ee1c8SAxel Lin ADM1031_REG_TEMP(chan)); 152278ee1c8SAxel Lin 153278ee1c8SAxel Lin /* oldh is actually newer */ 154278ee1c8SAxel Lin if (newh != oldh) 155278ee1c8SAxel Lin dev_warn(&client->dev, 156278ee1c8SAxel Lin "Remote temperature may be wrong.\n"); 157278ee1c8SAxel Lin #endif 158278ee1c8SAxel Lin } 159278ee1c8SAxel Lin data->temp[chan] = newh; 160278ee1c8SAxel Lin 161278ee1c8SAxel Lin data->temp_offset[chan] = 162278ee1c8SAxel Lin adm1031_read_value(client, 163278ee1c8SAxel Lin ADM1031_REG_TEMP_OFFSET(chan)); 164278ee1c8SAxel Lin data->temp_min[chan] = 165278ee1c8SAxel Lin adm1031_read_value(client, 166278ee1c8SAxel Lin ADM1031_REG_TEMP_MIN(chan)); 167278ee1c8SAxel Lin data->temp_max[chan] = 168278ee1c8SAxel Lin adm1031_read_value(client, 169278ee1c8SAxel Lin ADM1031_REG_TEMP_MAX(chan)); 170278ee1c8SAxel Lin data->temp_crit[chan] = 171278ee1c8SAxel Lin adm1031_read_value(client, 172278ee1c8SAxel Lin ADM1031_REG_TEMP_CRIT(chan)); 173278ee1c8SAxel Lin data->auto_temp[chan] = 174278ee1c8SAxel Lin adm1031_read_value(client, 175278ee1c8SAxel Lin ADM1031_REG_AUTO_TEMP(chan)); 176278ee1c8SAxel Lin 177278ee1c8SAxel Lin } 178278ee1c8SAxel Lin 179278ee1c8SAxel Lin data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1); 180278ee1c8SAxel Lin data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2); 181278ee1c8SAxel Lin 182278ee1c8SAxel Lin data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0)) 183278ee1c8SAxel Lin | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8); 184278ee1c8SAxel Lin if (data->chip_type == adm1030) 185278ee1c8SAxel Lin data->alarm &= 0xc0ff; 186278ee1c8SAxel Lin 187278ee1c8SAxel Lin for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2); 188278ee1c8SAxel Lin chan++) { 189278ee1c8SAxel Lin data->fan_div[chan] = 190278ee1c8SAxel Lin adm1031_read_value(client, 191278ee1c8SAxel Lin ADM1031_REG_FAN_DIV(chan)); 192278ee1c8SAxel Lin data->fan_min[chan] = 193278ee1c8SAxel Lin adm1031_read_value(client, 194278ee1c8SAxel Lin ADM1031_REG_FAN_MIN(chan)); 195278ee1c8SAxel Lin data->fan[chan] = 196278ee1c8SAxel Lin adm1031_read_value(client, 197278ee1c8SAxel Lin ADM1031_REG_FAN_SPEED(chan)); 198278ee1c8SAxel Lin data->pwm[chan] = 199278ee1c8SAxel Lin (adm1031_read_value(client, 200278ee1c8SAxel Lin ADM1031_REG_PWM) >> (4 * chan)) & 0x0f; 201278ee1c8SAxel Lin } 202278ee1c8SAxel Lin data->last_updated = jiffies; 203278ee1c8SAxel Lin data->valid = 1; 204278ee1c8SAxel Lin } 205278ee1c8SAxel Lin 206278ee1c8SAxel Lin mutex_unlock(&data->update_lock); 207278ee1c8SAxel Lin 208278ee1c8SAxel Lin return data; 209278ee1c8SAxel Lin } 2108d5d45fbSJean Delvare 2118d5d45fbSJean Delvare #define TEMP_TO_REG(val) (((val) < 0 ? ((val - 500) / 1000) : \ 2128d5d45fbSJean Delvare ((val + 500) / 1000))) 2138d5d45fbSJean Delvare 2148d5d45fbSJean Delvare #define TEMP_FROM_REG(val) ((val) * 1000) 2158d5d45fbSJean Delvare 2168d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) 2178d5d45fbSJean Delvare 21849dc9efeSIra Snyder #define TEMP_OFFSET_TO_REG(val) (TEMP_TO_REG(val) & 0x8f) 21949dc9efeSIra Snyder #define TEMP_OFFSET_FROM_REG(val) TEMP_FROM_REG((val) < 0 ? \ 22049dc9efeSIra Snyder (val) | 0x70 : (val)) 22149dc9efeSIra Snyder 2221c720093SGuenter Roeck #define FAN_FROM_REG(reg, div) ((reg) ? \ 2231c720093SGuenter Roeck (11250 * 60) / ((reg) * (div)) : 0) 2248d5d45fbSJean Delvare 2258d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div) 2268d5d45fbSJean Delvare { 2278d5d45fbSJean Delvare int tmp; 2282a844c14SGuenter Roeck tmp = FAN_FROM_REG(clamp_val(reg, 0, 65535), div); 2298d5d45fbSJean Delvare return tmp > 255 ? 255 : tmp; 2308d5d45fbSJean Delvare } 2318d5d45fbSJean Delvare 2328d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg) (1<<(((reg)&0xc0)>>6)) 2338d5d45fbSJean Delvare 2342a844c14SGuenter Roeck #define PWM_TO_REG(val) (clamp_val((val), 0, 255) >> 4) 2358d5d45fbSJean Delvare #define PWM_FROM_REG(val) ((val) << 4) 2368d5d45fbSJean Delvare 2378d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg) (((reg) >> 5) & 7) 2388d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg) \ 2398d5d45fbSJean Delvare (((reg) & 0x1F) | (((val) << 5) & 0xe0)) 2408d5d45fbSJean Delvare 2418d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg) \ 2428d5d45fbSJean Delvare ((((val) / 500) & 0xf8) | ((reg) & 0x7)) 2438d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg) (5000 * (1 << ((reg) & 0x7))) 2448d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg) (1000 * ((((reg) >> 3) & 0x1f) << 2)) 2458d5d45fbSJean Delvare 2468d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg) ((((reg) >> 3) & 0x1f) << 2) 2478d5d45fbSJean Delvare 2488d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg) \ 2498d5d45fbSJean Delvare (AUTO_TEMP_MIN_FROM_REG(reg) - 5000) 2508d5d45fbSJean Delvare 2518d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg) \ 2528d5d45fbSJean Delvare (AUTO_TEMP_RANGE_FROM_REG(reg) + \ 2538d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG(reg)) 2548d5d45fbSJean Delvare 2558d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm) 2568d5d45fbSJean Delvare { 2578d5d45fbSJean Delvare int ret; 2588d5d45fbSJean Delvare int range = val - AUTO_TEMP_MIN_FROM_REG(reg); 2598d5d45fbSJean Delvare 2608d5d45fbSJean Delvare range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm); 2618d5d45fbSJean Delvare ret = ((reg & 0xf8) | 2628d5d45fbSJean Delvare (range < 10000 ? 0 : 2638d5d45fbSJean Delvare range < 20000 ? 1 : 2648d5d45fbSJean Delvare range < 40000 ? 2 : range < 80000 ? 3 : 4)); 2658d5d45fbSJean Delvare return ret; 2668d5d45fbSJean Delvare } 2678d5d45fbSJean Delvare 2688d5d45fbSJean Delvare /* FAN auto control */ 2698d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx) \ 2708d5d45fbSJean Delvare (*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2] 2718d5d45fbSJean Delvare 272fbb6670dSGuenter Roeck /* 273fbb6670dSGuenter Roeck * The tables below contains the possible values for the auto fan 2748d5d45fbSJean Delvare * control bitfields. the index in the table is the register value. 2758d5d45fbSJean Delvare * MSb is the auto fan control enable bit, so the four first entries 2768d5d45fbSJean Delvare * in the table disables auto fan control when both bitfields are zero. 2778d5d45fbSJean Delvare */ 2786d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = { 2798d5d45fbSJean Delvare { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2808d5d45fbSJean Delvare { 2 /* 0b010 */ , 4 /* 0b100 */ }, 2818d5d45fbSJean Delvare { 2 /* 0b010 */ , 2 /* 0b010 */ }, 2828d5d45fbSJean Delvare { 4 /* 0b100 */ , 4 /* 0b100 */ }, 2838d5d45fbSJean Delvare { 7 /* 0b111 */ , 7 /* 0b111 */ }, 2848d5d45fbSJean Delvare }; 2858d5d45fbSJean Delvare 2866d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = { 2878d5d45fbSJean Delvare { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2888d5d45fbSJean Delvare { 2 /* 0b10 */ , 0 }, 2898d5d45fbSJean Delvare { 0xff /* invalid */ , 0 }, 2908d5d45fbSJean Delvare { 0xff /* invalid */ , 0 }, 2918d5d45fbSJean Delvare { 3 /* 0b11 */ , 0 }, 2928d5d45fbSJean Delvare }; 2938d5d45fbSJean Delvare 294fbb6670dSGuenter Roeck /* 295fbb6670dSGuenter Roeck * That function checks if a bitfield is valid and returns the other bitfield 2968d5d45fbSJean Delvare * nearest match if no exact match where found. 2978d5d45fbSJean Delvare */ 2988d5d45fbSJean Delvare static int 299ce15a81dSGuenter Roeck get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg) 3008d5d45fbSJean Delvare { 3018d5d45fbSJean Delvare int i; 3028d5d45fbSJean Delvare int first_match = -1, exact_match = -1; 3038d5d45fbSJean Delvare u8 other_reg_val = 3048d5d45fbSJean Delvare (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1]; 3058d5d45fbSJean Delvare 306ce15a81dSGuenter Roeck if (val == 0) 3078d5d45fbSJean Delvare return 0; 3088d5d45fbSJean Delvare 3098d5d45fbSJean Delvare for (i = 0; i < 8; i++) { 3108d5d45fbSJean Delvare if ((val == (*data->chan_select_table)[i][chan]) && 3118d5d45fbSJean Delvare ((*data->chan_select_table)[i][chan ? 0 : 1] == 3128d5d45fbSJean Delvare other_reg_val)) { 3138d5d45fbSJean Delvare /* We found an exact match */ 3148d5d45fbSJean Delvare exact_match = i; 3158d5d45fbSJean Delvare break; 3168d5d45fbSJean Delvare } else if (val == (*data->chan_select_table)[i][chan] && 3178d5d45fbSJean Delvare first_match == -1) { 318fbb6670dSGuenter Roeck /* 319fbb6670dSGuenter Roeck * Save the first match in case of an exact match has 3206d6006b8SJean Delvare * not been found 3218d5d45fbSJean Delvare */ 3228d5d45fbSJean Delvare first_match = i; 3238d5d45fbSJean Delvare } 3248d5d45fbSJean Delvare } 3258d5d45fbSJean Delvare 3261c720093SGuenter Roeck if (exact_match >= 0) 327ce15a81dSGuenter Roeck return exact_match; 3281c720093SGuenter Roeck else if (first_match >= 0) 329ce15a81dSGuenter Roeck return first_match; 3301c720093SGuenter Roeck 331ce15a81dSGuenter Roeck return -EINVAL; 3328d5d45fbSJean Delvare } 3338d5d45fbSJean Delvare 334c801082dSJean Delvare static ssize_t show_fan_auto_channel(struct device *dev, 335c801082dSJean Delvare struct device_attribute *attr, char *buf) 3368d5d45fbSJean Delvare { 337c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3388d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 3398d5d45fbSJean Delvare return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr)); 3408d5d45fbSJean Delvare } 3418d5d45fbSJean Delvare 3428d5d45fbSJean Delvare static ssize_t 343c801082dSJean Delvare set_fan_auto_channel(struct device *dev, struct device_attribute *attr, 344c801082dSJean Delvare const char *buf, size_t count) 3458d5d45fbSJean Delvare { 346*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 347*b060f3c4SAxel Lin struct i2c_client *client = data->client; 348c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3491c720093SGuenter Roeck long val; 3508d5d45fbSJean Delvare u8 reg; 3518d5d45fbSJean Delvare int ret; 3528d5d45fbSJean Delvare u8 old_fan_mode; 3538d5d45fbSJean Delvare 3541c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 3551c720093SGuenter Roeck if (ret) 3561c720093SGuenter Roeck return ret; 3571c720093SGuenter Roeck 3588d5d45fbSJean Delvare old_fan_mode = data->conf1; 3598d5d45fbSJean Delvare 3609a61bf63SIngo Molnar mutex_lock(&data->update_lock); 3618d5d45fbSJean Delvare 362ce15a81dSGuenter Roeck ret = get_fan_auto_nearest(data, nr, val, data->conf1); 363ce15a81dSGuenter Roeck if (ret < 0) { 3649a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 3658d5d45fbSJean Delvare return ret; 3668d5d45fbSJean Delvare } 367ce15a81dSGuenter Roeck reg = ret; 3686d6006b8SJean Delvare data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); 3696d6006b8SJean Delvare if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^ 3708d5d45fbSJean Delvare (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) { 3718d5d45fbSJean Delvare if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { 372fbb6670dSGuenter Roeck /* 373fbb6670dSGuenter Roeck * Switch to Auto Fan Mode 3748d5d45fbSJean Delvare * Save PWM registers 375fbb6670dSGuenter Roeck * Set PWM registers to 33% Both 376fbb6670dSGuenter Roeck */ 3778d5d45fbSJean Delvare data->old_pwm[0] = data->pwm[0]; 3788d5d45fbSJean Delvare data->old_pwm[1] = data->pwm[1]; 3798d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_PWM, 0x55); 3808d5d45fbSJean Delvare } else { 3818d5d45fbSJean Delvare /* Switch to Manual Mode */ 3828d5d45fbSJean Delvare data->pwm[0] = data->old_pwm[0]; 3838d5d45fbSJean Delvare data->pwm[1] = data->old_pwm[1]; 3848d5d45fbSJean Delvare /* Restore PWM registers */ 3858d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_PWM, 3868d5d45fbSJean Delvare data->pwm[0] | (data->pwm[1] << 4)); 3878d5d45fbSJean Delvare } 3888d5d45fbSJean Delvare } 3898d5d45fbSJean Delvare data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); 3908d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); 3919a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 3928d5d45fbSJean Delvare return count; 3938d5d45fbSJean Delvare } 3948d5d45fbSJean Delvare 395c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_channel, S_IRUGO | S_IWUSR, 396c801082dSJean Delvare show_fan_auto_channel, set_fan_auto_channel, 0); 397c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_channel, S_IRUGO | S_IWUSR, 398c801082dSJean Delvare show_fan_auto_channel, set_fan_auto_channel, 1); 3998d5d45fbSJean Delvare 4008d5d45fbSJean Delvare /* Auto Temps */ 401c801082dSJean Delvare static ssize_t show_auto_temp_off(struct device *dev, 402c801082dSJean Delvare struct device_attribute *attr, char *buf) 4038d5d45fbSJean Delvare { 404c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4058d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 4068d5d45fbSJean Delvare return sprintf(buf, "%d\n", 4078d5d45fbSJean Delvare AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr])); 4088d5d45fbSJean Delvare } 409c801082dSJean Delvare static ssize_t show_auto_temp_min(struct device *dev, 410c801082dSJean Delvare struct device_attribute *attr, char *buf) 4118d5d45fbSJean Delvare { 412c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4138d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 4148d5d45fbSJean Delvare return sprintf(buf, "%d\n", 4158d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr])); 4168d5d45fbSJean Delvare } 4178d5d45fbSJean Delvare static ssize_t 418c801082dSJean Delvare set_auto_temp_min(struct device *dev, struct device_attribute *attr, 419c801082dSJean Delvare const char *buf, size_t count) 4208d5d45fbSJean Delvare { 421*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 422*b060f3c4SAxel Lin struct i2c_client *client = data->client; 423c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4241c720093SGuenter Roeck long val; 4251c720093SGuenter Roeck int ret; 4261c720093SGuenter Roeck 4271c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 4281c720093SGuenter Roeck if (ret) 4291c720093SGuenter Roeck return ret; 4308d5d45fbSJean Delvare 431145e74a4SGuenter Roeck val = clamp_val(val, 0, 127000); 4329a61bf63SIngo Molnar mutex_lock(&data->update_lock); 4338d5d45fbSJean Delvare data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); 4348d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), 4358d5d45fbSJean Delvare data->auto_temp[nr]); 4369a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 4378d5d45fbSJean Delvare return count; 4388d5d45fbSJean Delvare } 439c801082dSJean Delvare static ssize_t show_auto_temp_max(struct device *dev, 440c801082dSJean Delvare struct device_attribute *attr, char *buf) 4418d5d45fbSJean Delvare { 442c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4438d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 4448d5d45fbSJean Delvare return sprintf(buf, "%d\n", 4458d5d45fbSJean Delvare AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr])); 4468d5d45fbSJean Delvare } 4478d5d45fbSJean Delvare static ssize_t 448c801082dSJean Delvare set_auto_temp_max(struct device *dev, struct device_attribute *attr, 449c801082dSJean Delvare const char *buf, size_t count) 4508d5d45fbSJean Delvare { 451*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 452*b060f3c4SAxel Lin struct i2c_client *client = data->client; 453c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4541c720093SGuenter Roeck long val; 4551c720093SGuenter Roeck int ret; 4561c720093SGuenter Roeck 4571c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 4581c720093SGuenter Roeck if (ret) 4591c720093SGuenter Roeck return ret; 4608d5d45fbSJean Delvare 461145e74a4SGuenter Roeck val = clamp_val(val, 0, 127000); 4629a61bf63SIngo Molnar mutex_lock(&data->update_lock); 4631c720093SGuenter Roeck data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], 4641c720093SGuenter Roeck data->pwm[nr]); 4658d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), 4668d5d45fbSJean Delvare data->temp_max[nr]); 4679a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 4688d5d45fbSJean Delvare return count; 4698d5d45fbSJean Delvare } 4708d5d45fbSJean Delvare 4718d5d45fbSJean Delvare #define auto_temp_reg(offset) \ 472c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO, \ 473c801082dSJean Delvare show_auto_temp_off, NULL, offset - 1); \ 474c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR, \ 475c801082dSJean Delvare show_auto_temp_min, set_auto_temp_min, offset - 1); \ 476c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR, \ 477c801082dSJean Delvare show_auto_temp_max, set_auto_temp_max, offset - 1) 4788d5d45fbSJean Delvare 4798d5d45fbSJean Delvare auto_temp_reg(1); 4808d5d45fbSJean Delvare auto_temp_reg(2); 4818d5d45fbSJean Delvare auto_temp_reg(3); 4828d5d45fbSJean Delvare 4838d5d45fbSJean Delvare /* pwm */ 484c801082dSJean Delvare static ssize_t show_pwm(struct device *dev, 485c801082dSJean Delvare struct device_attribute *attr, char *buf) 4868d5d45fbSJean Delvare { 487c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4888d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 4898d5d45fbSJean Delvare return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); 4908d5d45fbSJean Delvare } 491c801082dSJean Delvare static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, 492c801082dSJean Delvare const char *buf, size_t count) 4938d5d45fbSJean Delvare { 494*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 495*b060f3c4SAxel Lin struct i2c_client *client = data->client; 496c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4971c720093SGuenter Roeck long val; 4981c720093SGuenter Roeck int ret, reg; 4991c720093SGuenter Roeck 5001c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 5011c720093SGuenter Roeck if (ret) 5021c720093SGuenter Roeck return ret; 5038d5d45fbSJean Delvare 5049a61bf63SIngo Molnar mutex_lock(&data->update_lock); 5058d5d45fbSJean Delvare if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && 5068d5d45fbSJean Delvare (((val>>4) & 0xf) != 5)) { 5078d5d45fbSJean Delvare /* In automatic mode, the only PWM accepted is 33% */ 5089a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 5098d5d45fbSJean Delvare return -EINVAL; 5108d5d45fbSJean Delvare } 5118d5d45fbSJean Delvare data->pwm[nr] = PWM_TO_REG(val); 5128d5d45fbSJean Delvare reg = adm1031_read_value(client, ADM1031_REG_PWM); 5138d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_PWM, 5148d5d45fbSJean Delvare nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) 5158d5d45fbSJean Delvare : (data->pwm[nr] & 0xf) | (reg & 0xf0)); 5169a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 5178d5d45fbSJean Delvare return count; 5188d5d45fbSJean Delvare } 5198d5d45fbSJean Delvare 520c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0); 521c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1); 522c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_min_pwm, S_IRUGO | S_IWUSR, 523c801082dSJean Delvare show_pwm, set_pwm, 0); 524c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_min_pwm, S_IRUGO | S_IWUSR, 525c801082dSJean Delvare show_pwm, set_pwm, 1); 5268d5d45fbSJean Delvare 5278d5d45fbSJean Delvare /* Fans */ 5288d5d45fbSJean Delvare 5298d5d45fbSJean Delvare /* 5308d5d45fbSJean Delvare * That function checks the cases where the fan reading is not 5318d5d45fbSJean Delvare * relevant. It is used to provide 0 as fan reading when the fan is 5328d5d45fbSJean Delvare * not supposed to run 5338d5d45fbSJean Delvare */ 5348d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan) 5358d5d45fbSJean Delvare { 5368d5d45fbSJean Delvare int res = 0; 5378d5d45fbSJean Delvare 5388d5d45fbSJean Delvare if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { 5398d5d45fbSJean Delvare switch (data->conf1 & 0x60) { 5401c720093SGuenter Roeck case 0x00: 5411c720093SGuenter Roeck /* 5421c720093SGuenter Roeck * remote temp1 controls fan1, 5431c720093SGuenter Roeck * remote temp2 controls fan2 5441c720093SGuenter Roeck */ 5458d5d45fbSJean Delvare res = data->temp[chan+1] >= 5468d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]); 5478d5d45fbSJean Delvare break; 5488d5d45fbSJean Delvare case 0x20: /* remote temp1 controls both fans */ 5498d5d45fbSJean Delvare res = 5508d5d45fbSJean Delvare data->temp[1] >= 5518d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]); 5528d5d45fbSJean Delvare break; 5538d5d45fbSJean Delvare case 0x40: /* remote temp2 controls both fans */ 5548d5d45fbSJean Delvare res = 5558d5d45fbSJean Delvare data->temp[2] >= 5568d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]); 5578d5d45fbSJean Delvare break; 5588d5d45fbSJean Delvare case 0x60: /* max controls both fans */ 5598d5d45fbSJean Delvare res = 5608d5d45fbSJean Delvare data->temp[0] >= 5618d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0]) 5628d5d45fbSJean Delvare || data->temp[1] >= 5638d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]) 5648d5d45fbSJean Delvare || (data->chip_type == adm1031 5658d5d45fbSJean Delvare && data->temp[2] >= 5668d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2])); 5678d5d45fbSJean Delvare break; 5688d5d45fbSJean Delvare } 5698d5d45fbSJean Delvare } else { 5708d5d45fbSJean Delvare res = data->pwm[chan] > 0; 5718d5d45fbSJean Delvare } 5728d5d45fbSJean Delvare return res; 5738d5d45fbSJean Delvare } 5748d5d45fbSJean Delvare 5758d5d45fbSJean Delvare 576c801082dSJean Delvare static ssize_t show_fan(struct device *dev, 577c801082dSJean Delvare struct device_attribute *attr, char *buf) 5788d5d45fbSJean Delvare { 579c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5808d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 5818d5d45fbSJean Delvare int value; 5828d5d45fbSJean Delvare 5838d5d45fbSJean Delvare value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr], 5848d5d45fbSJean Delvare FAN_DIV_FROM_REG(data->fan_div[nr])) : 0; 5858d5d45fbSJean Delvare return sprintf(buf, "%d\n", value); 5868d5d45fbSJean Delvare } 5878d5d45fbSJean Delvare 588c801082dSJean Delvare static ssize_t show_fan_div(struct device *dev, 589c801082dSJean Delvare struct device_attribute *attr, char *buf) 5908d5d45fbSJean Delvare { 591c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5928d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 5938d5d45fbSJean Delvare return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr])); 5948d5d45fbSJean Delvare } 595c801082dSJean Delvare static ssize_t show_fan_min(struct device *dev, 596c801082dSJean Delvare struct device_attribute *attr, char *buf) 5978d5d45fbSJean Delvare { 598c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5998d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 6008d5d45fbSJean Delvare return sprintf(buf, "%d\n", 6018d5d45fbSJean Delvare FAN_FROM_REG(data->fan_min[nr], 6028d5d45fbSJean Delvare FAN_DIV_FROM_REG(data->fan_div[nr]))); 6038d5d45fbSJean Delvare } 604c801082dSJean Delvare static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, 605c801082dSJean Delvare const char *buf, size_t count) 6068d5d45fbSJean Delvare { 607*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 608*b060f3c4SAxel Lin struct i2c_client *client = data->client; 609c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6101c720093SGuenter Roeck long val; 6111c720093SGuenter Roeck int ret; 6121c720093SGuenter Roeck 6131c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 6141c720093SGuenter Roeck if (ret) 6151c720093SGuenter Roeck return ret; 6168d5d45fbSJean Delvare 6179a61bf63SIngo Molnar mutex_lock(&data->update_lock); 6188d5d45fbSJean Delvare if (val) { 6198d5d45fbSJean Delvare data->fan_min[nr] = 6208d5d45fbSJean Delvare FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); 6218d5d45fbSJean Delvare } else { 6228d5d45fbSJean Delvare data->fan_min[nr] = 0xff; 6238d5d45fbSJean Delvare } 6248d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); 6259a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 6268d5d45fbSJean Delvare return count; 6278d5d45fbSJean Delvare } 628c801082dSJean Delvare static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, 629c801082dSJean Delvare const char *buf, size_t count) 6308d5d45fbSJean Delvare { 631*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 632*b060f3c4SAxel Lin struct i2c_client *client = data->client; 633c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6341c720093SGuenter Roeck long val; 6358d5d45fbSJean Delvare u8 tmp; 6368d5d45fbSJean Delvare int old_div; 6378d5d45fbSJean Delvare int new_min; 6381c720093SGuenter Roeck int ret; 6391c720093SGuenter Roeck 6401c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 6411c720093SGuenter Roeck if (ret) 6421c720093SGuenter Roeck return ret; 6438d5d45fbSJean Delvare 6448d5d45fbSJean Delvare tmp = val == 8 ? 0xc0 : 6458d5d45fbSJean Delvare val == 4 ? 0x80 : 6468d5d45fbSJean Delvare val == 2 ? 0x40 : 6478d5d45fbSJean Delvare val == 1 ? 0x00 : 6488d5d45fbSJean Delvare 0xff; 6498d5d45fbSJean Delvare if (tmp == 0xff) 6508d5d45fbSJean Delvare return -EINVAL; 6518d5d45fbSJean Delvare 6529a61bf63SIngo Molnar mutex_lock(&data->update_lock); 65338a1f0e9SJean Delvare /* Get fresh readings */ 65438a1f0e9SJean Delvare data->fan_div[nr] = adm1031_read_value(client, 65538a1f0e9SJean Delvare ADM1031_REG_FAN_DIV(nr)); 65638a1f0e9SJean Delvare data->fan_min[nr] = adm1031_read_value(client, 65738a1f0e9SJean Delvare ADM1031_REG_FAN_MIN(nr)); 65838a1f0e9SJean Delvare 65938a1f0e9SJean Delvare /* Write the new clock divider and fan min */ 6608d5d45fbSJean Delvare old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); 6616d6006b8SJean Delvare data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]); 6626d6006b8SJean Delvare new_min = data->fan_min[nr] * old_div / val; 6638d5d45fbSJean Delvare data->fan_min[nr] = new_min > 0xff ? 0xff : new_min; 6648d5d45fbSJean Delvare 6658d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr), 6668d5d45fbSJean Delvare data->fan_div[nr]); 6678d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), 6688d5d45fbSJean Delvare data->fan_min[nr]); 66938a1f0e9SJean Delvare 67038a1f0e9SJean Delvare /* Invalidate the cache: fan speed is no longer valid */ 67138a1f0e9SJean Delvare data->valid = 0; 6729a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 6738d5d45fbSJean Delvare return count; 6748d5d45fbSJean Delvare } 6758d5d45fbSJean Delvare 6768d5d45fbSJean Delvare #define fan_offset(offset) \ 677c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ 678c801082dSJean Delvare show_fan, NULL, offset - 1); \ 679c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ 680c801082dSJean Delvare show_fan_min, set_fan_min, offset - 1); \ 681c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ 682c801082dSJean Delvare show_fan_div, set_fan_div, offset - 1) 6838d5d45fbSJean Delvare 6848d5d45fbSJean Delvare fan_offset(1); 6858d5d45fbSJean Delvare fan_offset(2); 6868d5d45fbSJean Delvare 6878d5d45fbSJean Delvare 6888d5d45fbSJean Delvare /* Temps */ 689c801082dSJean Delvare static ssize_t show_temp(struct device *dev, 690c801082dSJean Delvare struct device_attribute *attr, char *buf) 6918d5d45fbSJean Delvare { 692c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6938d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 6948d5d45fbSJean Delvare int ext; 6958d5d45fbSJean Delvare ext = nr == 0 ? 6968d5d45fbSJean Delvare ((data->ext_temp[nr] >> 6) & 0x3) * 2 : 6978d5d45fbSJean Delvare (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); 6988d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); 6998d5d45fbSJean Delvare } 70049dc9efeSIra Snyder static ssize_t show_temp_offset(struct device *dev, 70149dc9efeSIra Snyder struct device_attribute *attr, char *buf) 70249dc9efeSIra Snyder { 70349dc9efeSIra Snyder int nr = to_sensor_dev_attr(attr)->index; 70449dc9efeSIra Snyder struct adm1031_data *data = adm1031_update_device(dev); 70549dc9efeSIra Snyder return sprintf(buf, "%d\n", 70649dc9efeSIra Snyder TEMP_OFFSET_FROM_REG(data->temp_offset[nr])); 70749dc9efeSIra Snyder } 708c801082dSJean Delvare static ssize_t show_temp_min(struct device *dev, 709c801082dSJean Delvare struct device_attribute *attr, char *buf) 7108d5d45fbSJean Delvare { 711c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7128d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 7138d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); 7148d5d45fbSJean Delvare } 715c801082dSJean Delvare static ssize_t show_temp_max(struct device *dev, 716c801082dSJean Delvare struct device_attribute *attr, char *buf) 7178d5d45fbSJean Delvare { 718c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7198d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 7208d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); 7218d5d45fbSJean Delvare } 722c801082dSJean Delvare static ssize_t show_temp_crit(struct device *dev, 723c801082dSJean Delvare struct device_attribute *attr, char *buf) 7248d5d45fbSJean Delvare { 725c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7268d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 7278d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); 7288d5d45fbSJean Delvare } 72949dc9efeSIra Snyder static ssize_t set_temp_offset(struct device *dev, 73049dc9efeSIra Snyder struct device_attribute *attr, const char *buf, 73149dc9efeSIra Snyder size_t count) 73249dc9efeSIra Snyder { 733*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 734*b060f3c4SAxel Lin struct i2c_client *client = data->client; 73549dc9efeSIra Snyder int nr = to_sensor_dev_attr(attr)->index; 7361c720093SGuenter Roeck long val; 7371c720093SGuenter Roeck int ret; 73849dc9efeSIra Snyder 7391c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 7401c720093SGuenter Roeck if (ret) 7411c720093SGuenter Roeck return ret; 7421c720093SGuenter Roeck 7432a844c14SGuenter Roeck val = clamp_val(val, -15000, 15000); 74449dc9efeSIra Snyder mutex_lock(&data->update_lock); 74549dc9efeSIra Snyder data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val); 74649dc9efeSIra Snyder adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr), 74749dc9efeSIra Snyder data->temp_offset[nr]); 74849dc9efeSIra Snyder mutex_unlock(&data->update_lock); 74949dc9efeSIra Snyder return count; 75049dc9efeSIra Snyder } 751c801082dSJean Delvare static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, 752c801082dSJean Delvare const char *buf, size_t count) 7538d5d45fbSJean Delvare { 754*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 755*b060f3c4SAxel 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_min[nr] = TEMP_TO_REG(val); 7678d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), 7688d5d45fbSJean Delvare data->temp_min[nr]); 7699a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7708d5d45fbSJean Delvare return count; 7718d5d45fbSJean Delvare } 772c801082dSJean Delvare static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, 773c801082dSJean Delvare const char *buf, size_t count) 7748d5d45fbSJean Delvare { 775*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 776*b060f3c4SAxel Lin struct i2c_client *client = data->client; 777c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7781c720093SGuenter Roeck long val; 7791c720093SGuenter Roeck int ret; 7808d5d45fbSJean Delvare 7811c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 7821c720093SGuenter Roeck if (ret) 7831c720093SGuenter Roeck return ret; 7841c720093SGuenter Roeck 785145e74a4SGuenter Roeck val = clamp_val(val, -55000, 127000); 7869a61bf63SIngo Molnar mutex_lock(&data->update_lock); 7878d5d45fbSJean Delvare data->temp_max[nr] = TEMP_TO_REG(val); 7888d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), 7898d5d45fbSJean Delvare data->temp_max[nr]); 7909a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7918d5d45fbSJean Delvare return count; 7928d5d45fbSJean Delvare } 793c801082dSJean Delvare static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, 794c801082dSJean Delvare const char *buf, size_t count) 7958d5d45fbSJean Delvare { 796*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 797*b060f3c4SAxel Lin struct i2c_client *client = data->client; 798c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7991c720093SGuenter Roeck long val; 8001c720093SGuenter Roeck int ret; 8018d5d45fbSJean Delvare 8021c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 8031c720093SGuenter Roeck if (ret) 8041c720093SGuenter Roeck return ret; 8051c720093SGuenter Roeck 806145e74a4SGuenter Roeck val = clamp_val(val, -55000, 127000); 8079a61bf63SIngo Molnar mutex_lock(&data->update_lock); 8088d5d45fbSJean Delvare data->temp_crit[nr] = TEMP_TO_REG(val); 8098d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), 8108d5d45fbSJean Delvare data->temp_crit[nr]); 8119a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 8128d5d45fbSJean Delvare return count; 8138d5d45fbSJean Delvare } 8148d5d45fbSJean Delvare 8158d5d45fbSJean Delvare #define temp_reg(offset) \ 816c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ 817c801082dSJean Delvare show_temp, NULL, offset - 1); \ 81849dc9efeSIra Snyder static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \ 81949dc9efeSIra Snyder show_temp_offset, set_temp_offset, offset - 1); \ 820c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ 821c801082dSJean Delvare show_temp_min, set_temp_min, offset - 1); \ 822c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ 823c801082dSJean Delvare show_temp_max, set_temp_max, offset - 1); \ 824c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \ 825c801082dSJean Delvare show_temp_crit, set_temp_crit, offset - 1) 8268d5d45fbSJean Delvare 8278d5d45fbSJean Delvare temp_reg(1); 8288d5d45fbSJean Delvare temp_reg(2); 8298d5d45fbSJean Delvare temp_reg(3); 8308d5d45fbSJean Delvare 8318d5d45fbSJean Delvare /* Alarms */ 8321c720093SGuenter Roeck static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, 8331c720093SGuenter Roeck char *buf) 8348d5d45fbSJean Delvare { 8358d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 8368d5d45fbSJean Delvare return sprintf(buf, "%d\n", data->alarm); 8378d5d45fbSJean Delvare } 8388d5d45fbSJean Delvare 8398d5d45fbSJean Delvare static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 8408d5d45fbSJean Delvare 841050ab878SJean Delvare static ssize_t show_alarm(struct device *dev, 842050ab878SJean Delvare struct device_attribute *attr, char *buf) 843050ab878SJean Delvare { 844050ab878SJean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 845050ab878SJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 846050ab878SJean Delvare return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1); 847050ab878SJean Delvare } 848050ab878SJean Delvare 849050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0); 850050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1); 851050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2); 852050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); 853050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 4); 854050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 5); 855050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); 856050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 7); 857050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 8); 858050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 9); 859050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 10); 860050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11); 861050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12); 862050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); 863050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); 8648d5d45fbSJean Delvare 865a51b9944SGuenter Roeck /* Update Interval */ 866a51b9944SGuenter Roeck static const unsigned int update_intervals[] = { 86787c33daaSJean Delvare 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 86887c33daaSJean Delvare }; 86987c33daaSJean Delvare 870a51b9944SGuenter Roeck static ssize_t show_update_interval(struct device *dev, 87187c33daaSJean Delvare struct device_attribute *attr, char *buf) 87287c33daaSJean Delvare { 873*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 87487c33daaSJean Delvare 875a51b9944SGuenter Roeck return sprintf(buf, "%u\n", data->update_interval); 87687c33daaSJean Delvare } 87787c33daaSJean Delvare 878a51b9944SGuenter Roeck static ssize_t set_update_interval(struct device *dev, 87987c33daaSJean Delvare struct device_attribute *attr, 88087c33daaSJean Delvare const char *buf, size_t count) 88187c33daaSJean Delvare { 882*b060f3c4SAxel Lin struct adm1031_data *data = dev_get_drvdata(dev); 883*b060f3c4SAxel Lin struct i2c_client *client = data->client; 88487c33daaSJean Delvare unsigned long val; 88587c33daaSJean Delvare int i, err; 88687c33daaSJean Delvare u8 reg; 88787c33daaSJean Delvare 888179c4fdbSFrans Meulenbroeks err = kstrtoul(buf, 10, &val); 88987c33daaSJean Delvare if (err) 89087c33daaSJean Delvare return err; 89187c33daaSJean Delvare 892a51b9944SGuenter Roeck /* 893a51b9944SGuenter Roeck * Find the nearest update interval from the table. 894a51b9944SGuenter Roeck * Use it to determine the matching update rate. 895a51b9944SGuenter Roeck */ 896a51b9944SGuenter Roeck for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) { 897a51b9944SGuenter Roeck if (val >= update_intervals[i]) 89887c33daaSJean Delvare break; 89987c33daaSJean Delvare } 900a51b9944SGuenter Roeck /* if not found, we point to the last entry (lowest update interval) */ 90187c33daaSJean Delvare 90287c33daaSJean Delvare /* set the new update rate while preserving other settings */ 90387c33daaSJean Delvare reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); 90487c33daaSJean Delvare reg &= ~ADM1031_UPDATE_RATE_MASK; 90587c33daaSJean Delvare reg |= i << ADM1031_UPDATE_RATE_SHIFT; 90687c33daaSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg); 90787c33daaSJean Delvare 90887c33daaSJean Delvare mutex_lock(&data->update_lock); 909a51b9944SGuenter Roeck data->update_interval = update_intervals[i]; 91087c33daaSJean Delvare mutex_unlock(&data->update_lock); 91187c33daaSJean Delvare 91287c33daaSJean Delvare return count; 91387c33daaSJean Delvare } 91487c33daaSJean Delvare 915a51b9944SGuenter Roeck static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval, 916a51b9944SGuenter Roeck set_update_interval); 91787c33daaSJean Delvare 918681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = { 919c801082dSJean Delvare &sensor_dev_attr_fan1_input.dev_attr.attr, 920c801082dSJean Delvare &sensor_dev_attr_fan1_div.dev_attr.attr, 921c801082dSJean Delvare &sensor_dev_attr_fan1_min.dev_attr.attr, 922050ab878SJean Delvare &sensor_dev_attr_fan1_alarm.dev_attr.attr, 923050ab878SJean Delvare &sensor_dev_attr_fan1_fault.dev_attr.attr, 924c801082dSJean Delvare &sensor_dev_attr_pwm1.dev_attr.attr, 925c801082dSJean Delvare &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, 926c801082dSJean Delvare &sensor_dev_attr_temp1_input.dev_attr.attr, 92749dc9efeSIra Snyder &sensor_dev_attr_temp1_offset.dev_attr.attr, 928c801082dSJean Delvare &sensor_dev_attr_temp1_min.dev_attr.attr, 929050ab878SJean Delvare &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 930c801082dSJean Delvare &sensor_dev_attr_temp1_max.dev_attr.attr, 931050ab878SJean Delvare &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 932c801082dSJean Delvare &sensor_dev_attr_temp1_crit.dev_attr.attr, 933050ab878SJean Delvare &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 934c801082dSJean Delvare &sensor_dev_attr_temp2_input.dev_attr.attr, 93549dc9efeSIra Snyder &sensor_dev_attr_temp2_offset.dev_attr.attr, 936c801082dSJean Delvare &sensor_dev_attr_temp2_min.dev_attr.attr, 937050ab878SJean Delvare &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, 938c801082dSJean Delvare &sensor_dev_attr_temp2_max.dev_attr.attr, 939050ab878SJean Delvare &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, 940c801082dSJean Delvare &sensor_dev_attr_temp2_crit.dev_attr.attr, 941050ab878SJean Delvare &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, 942050ab878SJean Delvare &sensor_dev_attr_temp2_fault.dev_attr.attr, 943681c6f7aSMark M. Hoffman 944c801082dSJean Delvare &sensor_dev_attr_auto_temp1_off.dev_attr.attr, 945c801082dSJean Delvare &sensor_dev_attr_auto_temp1_min.dev_attr.attr, 946c801082dSJean Delvare &sensor_dev_attr_auto_temp1_max.dev_attr.attr, 947681c6f7aSMark M. Hoffman 948c801082dSJean Delvare &sensor_dev_attr_auto_temp2_off.dev_attr.attr, 949c801082dSJean Delvare &sensor_dev_attr_auto_temp2_min.dev_attr.attr, 950c801082dSJean Delvare &sensor_dev_attr_auto_temp2_max.dev_attr.attr, 951681c6f7aSMark M. Hoffman 952c801082dSJean Delvare &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, 953681c6f7aSMark M. Hoffman 954a51b9944SGuenter Roeck &dev_attr_update_interval.attr, 955681c6f7aSMark M. Hoffman &dev_attr_alarms.attr, 956681c6f7aSMark M. Hoffman 957681c6f7aSMark M. Hoffman NULL 958681c6f7aSMark M. Hoffman }; 959681c6f7aSMark M. Hoffman 960681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = { 961681c6f7aSMark M. Hoffman .attrs = adm1031_attributes, 962681c6f7aSMark M. Hoffman }; 963681c6f7aSMark M. Hoffman 964681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = { 965c801082dSJean Delvare &sensor_dev_attr_fan2_input.dev_attr.attr, 966c801082dSJean Delvare &sensor_dev_attr_fan2_div.dev_attr.attr, 967c801082dSJean Delvare &sensor_dev_attr_fan2_min.dev_attr.attr, 968050ab878SJean Delvare &sensor_dev_attr_fan2_alarm.dev_attr.attr, 969050ab878SJean Delvare &sensor_dev_attr_fan2_fault.dev_attr.attr, 970c801082dSJean Delvare &sensor_dev_attr_pwm2.dev_attr.attr, 971c801082dSJean Delvare &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, 972c801082dSJean Delvare &sensor_dev_attr_temp3_input.dev_attr.attr, 97349dc9efeSIra Snyder &sensor_dev_attr_temp3_offset.dev_attr.attr, 974c801082dSJean Delvare &sensor_dev_attr_temp3_min.dev_attr.attr, 975050ab878SJean Delvare &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, 976c801082dSJean Delvare &sensor_dev_attr_temp3_max.dev_attr.attr, 977050ab878SJean Delvare &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, 978c801082dSJean Delvare &sensor_dev_attr_temp3_crit.dev_attr.attr, 979050ab878SJean Delvare &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, 980050ab878SJean Delvare &sensor_dev_attr_temp3_fault.dev_attr.attr, 981c801082dSJean Delvare &sensor_dev_attr_auto_temp3_off.dev_attr.attr, 982c801082dSJean Delvare &sensor_dev_attr_auto_temp3_min.dev_attr.attr, 983c801082dSJean Delvare &sensor_dev_attr_auto_temp3_max.dev_attr.attr, 984c801082dSJean Delvare &sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr, 985681c6f7aSMark M. Hoffman NULL 986681c6f7aSMark M. Hoffman }; 987681c6f7aSMark M. Hoffman 988681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = { 989681c6f7aSMark M. Hoffman .attrs = adm1031_attributes_opt, 990681c6f7aSMark M. Hoffman }; 991681c6f7aSMark M. Hoffman 992af200f88SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */ 993310ec792SJean Delvare static int adm1031_detect(struct i2c_client *client, 994af200f88SJean Delvare struct i2c_board_info *info) 9958d5d45fbSJean Delvare { 996af200f88SJean Delvare struct i2c_adapter *adapter = client->adapter; 99752df6440SJean Delvare const char *name; 99852df6440SJean Delvare int id, co; 9998d5d45fbSJean Delvare 10008d5d45fbSJean Delvare if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 1001af200f88SJean Delvare return -ENODEV; 10028d5d45fbSJean Delvare 10036d6006b8SJean Delvare id = i2c_smbus_read_byte_data(client, 0x3d); 10046d6006b8SJean Delvare co = i2c_smbus_read_byte_data(client, 0x3e); 10058d5d45fbSJean Delvare 10068d5d45fbSJean Delvare if (!((id == 0x31 || id == 0x30) && co == 0x41)) 1007af200f88SJean Delvare return -ENODEV; 100852df6440SJean Delvare name = (id == 0x30) ? "adm1030" : "adm1031"; 10098d5d45fbSJean Delvare 1010af200f88SJean Delvare strlcpy(info->type, name, I2C_NAME_SIZE); 10118d5d45fbSJean Delvare 1012af200f88SJean Delvare return 0; 1013af200f88SJean Delvare } 1014af200f88SJean Delvare 1015278ee1c8SAxel Lin static void adm1031_init_client(struct i2c_client *client) 1016278ee1c8SAxel Lin { 1017278ee1c8SAxel Lin unsigned int read_val; 1018278ee1c8SAxel Lin unsigned int mask; 1019278ee1c8SAxel Lin int i; 1020278ee1c8SAxel Lin struct adm1031_data *data = i2c_get_clientdata(client); 1021278ee1c8SAxel Lin 1022278ee1c8SAxel Lin mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE); 1023278ee1c8SAxel Lin if (data->chip_type == adm1031) { 1024278ee1c8SAxel Lin mask |= (ADM1031_CONF2_PWM2_ENABLE | 1025278ee1c8SAxel Lin ADM1031_CONF2_TACH2_ENABLE); 1026278ee1c8SAxel Lin } 1027278ee1c8SAxel Lin /* Initialize the ADM1031 chip (enables fan speed reading ) */ 1028278ee1c8SAxel Lin read_val = adm1031_read_value(client, ADM1031_REG_CONF2); 1029278ee1c8SAxel Lin if ((read_val | mask) != read_val) 1030278ee1c8SAxel Lin adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask); 1031278ee1c8SAxel Lin 1032278ee1c8SAxel Lin read_val = adm1031_read_value(client, ADM1031_REG_CONF1); 1033278ee1c8SAxel Lin if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) { 1034278ee1c8SAxel Lin adm1031_write_value(client, ADM1031_REG_CONF1, 1035278ee1c8SAxel Lin read_val | ADM1031_CONF1_MONITOR_ENABLE); 1036278ee1c8SAxel Lin } 1037278ee1c8SAxel Lin 1038278ee1c8SAxel Lin /* Read the chip's update rate */ 1039278ee1c8SAxel Lin mask = ADM1031_UPDATE_RATE_MASK; 1040278ee1c8SAxel Lin read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); 1041278ee1c8SAxel Lin i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT; 1042278ee1c8SAxel Lin /* Save it as update interval */ 1043278ee1c8SAxel Lin data->update_interval = update_intervals[i]; 1044278ee1c8SAxel Lin } 1045278ee1c8SAxel Lin 1046af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client, 1047af200f88SJean Delvare const struct i2c_device_id *id) 1048af200f88SJean Delvare { 1049*b060f3c4SAxel Lin struct device *dev = &client->dev; 1050*b060f3c4SAxel Lin struct device *hwmon_dev; 1051af200f88SJean Delvare struct adm1031_data *data; 1052af200f88SJean Delvare 1053*b060f3c4SAxel Lin data = devm_kzalloc(dev, sizeof(struct adm1031_data), GFP_KERNEL); 1054dc2fd663SGuenter Roeck if (!data) 1055dc2fd663SGuenter Roeck return -ENOMEM; 1056af200f88SJean Delvare 1057af200f88SJean Delvare i2c_set_clientdata(client, data); 1058*b060f3c4SAxel Lin data->client = client; 1059af200f88SJean Delvare data->chip_type = id->driver_data; 10609a61bf63SIngo Molnar mutex_init(&data->update_lock); 10618d5d45fbSJean Delvare 1062af200f88SJean Delvare if (data->chip_type == adm1030) 1063af200f88SJean Delvare data->chan_select_table = &auto_channel_select_table_adm1030; 1064af200f88SJean Delvare else 1065af200f88SJean Delvare data->chan_select_table = &auto_channel_select_table_adm1031; 10668d5d45fbSJean Delvare 10678d5d45fbSJean Delvare /* Initialize the ADM1031 chip */ 10686d6006b8SJean Delvare adm1031_init_client(client); 10698d5d45fbSJean Delvare 1070*b060f3c4SAxel Lin /* sysfs hooks */ 1071*b060f3c4SAxel Lin data->groups[0] = &adm1031_group; 1072*b060f3c4SAxel Lin if (data->chip_type == adm1031) 1073*b060f3c4SAxel Lin data->groups[1] = &adm1031_group_opt; 1074681c6f7aSMark M. Hoffman 1075*b060f3c4SAxel Lin hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 1076*b060f3c4SAxel Lin data, data->groups); 1077*b060f3c4SAxel Lin return PTR_ERR_OR_ZERO(hwmon_dev); 10788d5d45fbSJean Delvare } 10798d5d45fbSJean Delvare 1080278ee1c8SAxel Lin static const struct i2c_device_id adm1031_id[] = { 1081278ee1c8SAxel Lin { "adm1030", adm1030 }, 1082278ee1c8SAxel Lin { "adm1031", adm1031 }, 1083278ee1c8SAxel Lin { } 1084278ee1c8SAxel Lin }; 1085278ee1c8SAxel Lin MODULE_DEVICE_TABLE(i2c, adm1031_id); 10868d5d45fbSJean Delvare 1087278ee1c8SAxel Lin static struct i2c_driver adm1031_driver = { 1088278ee1c8SAxel Lin .class = I2C_CLASS_HWMON, 1089278ee1c8SAxel Lin .driver = { 1090278ee1c8SAxel Lin .name = "adm1031", 1091278ee1c8SAxel Lin }, 1092278ee1c8SAxel Lin .probe = adm1031_probe, 1093278ee1c8SAxel Lin .id_table = adm1031_id, 1094278ee1c8SAxel Lin .detect = adm1031_detect, 1095278ee1c8SAxel Lin .address_list = normal_i2c, 1096278ee1c8SAxel Lin }; 10978d5d45fbSJean Delvare 1098f0967eeaSAxel Lin module_i2c_driver(adm1031_driver); 10998d5d45fbSJean Delvare 11008d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>"); 11018d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver"); 11028d5d45fbSJean Delvare MODULE_LICENSE("GPL"); 1103