2705 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/***************************************************************************3 * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> *4 * Copyright (C) 2007-2011 Hans de Goede <hdegoede@redhat.com> *5 * *6 ***************************************************************************/7 8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt9 10#include <linux/module.h>11#include <linux/init.h>12#include <linux/slab.h>13#include <linux/jiffies.h>14#include <linux/platform_device.h>15#include <linux/hwmon.h>16#include <linux/hwmon-sysfs.h>17#include <linux/err.h>18#include <linux/mutex.h>19#include <linux/io.h>20#include <linux/acpi.h>21 22#define DRVNAME "f71882fg"23 24#define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */25#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */26#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */27#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */28 29#define SIO_REG_LDSEL 0x07 /* Logical device select */30#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */31#define SIO_REG_DEVREV 0x22 /* Device revision */32#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */33#define SIO_REG_ENABLE 0x30 /* Logical device enable */34#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */35 36#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */37#define SIO_F71808E_ID 0x0901 /* Chipset ID */38#define SIO_F71808A_ID 0x1001 /* Chipset ID */39#define SIO_F71858_ID 0x0507 /* Chipset ID */40#define SIO_F71862_ID 0x0601 /* Chipset ID */41#define SIO_F71868_ID 0x1106 /* Chipset ID */42#define SIO_F71869_ID 0x0814 /* Chipset ID */43#define SIO_F71869A_ID 0x1007 /* Chipset ID */44#define SIO_F71882_ID 0x0541 /* Chipset ID */45#define SIO_F71889_ID 0x0723 /* Chipset ID */46#define SIO_F71889E_ID 0x0909 /* Chipset ID */47#define SIO_F71889A_ID 0x1005 /* Chipset ID */48#define SIO_F8000_ID 0x0581 /* Chipset ID */49#define SIO_F81768D_ID 0x1210 /* Chipset ID */50#define SIO_F81865_ID 0x0704 /* Chipset ID */51#define SIO_F81866_ID 0x1010 /* Chipset ID */52#define SIO_F71858AD_ID 0x0903 /* Chipset ID */53#define SIO_F81966_ID 0x1502 /* Chipset ID */54 55#define REGION_LENGTH 856#define ADDR_REG_OFFSET 557#define DATA_REG_OFFSET 658 59#define F71882FG_REG_IN_STATUS 0x12 /* f7188x only */60#define F71882FG_REG_IN_BEEP 0x13 /* f7188x only */61#define F71882FG_REG_IN(nr) (0x20 + (nr))62#define F71882FG_REG_IN1_HIGH 0x32 /* f7188x only */63 64#define F81866_REG_IN_STATUS 0x16 /* F81866 only */65#define F81866_REG_IN_BEEP 0x17 /* F81866 only */66#define F81866_REG_IN1_HIGH 0x3a /* F81866 only */67 68#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))69#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))70#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))71#define F71882FG_REG_FAN_STATUS 0x9272#define F71882FG_REG_FAN_BEEP 0x9373 74#define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr))75#define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr))76#define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr))77#define F71882FG_REG_TEMP_STATUS 0x6278#define F71882FG_REG_TEMP_BEEP 0x6379#define F71882FG_REG_TEMP_CONFIG 0x6980#define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr))81#define F71882FG_REG_TEMP_TYPE 0x6B82#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F83 84#define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr)))85#define F71882FG_REG_PWM_TYPE 0x9486#define F71882FG_REG_PWM_ENABLE 0x9687 88#define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr))89 90#define F71882FG_REG_FAN_FAULT_T 0x9F91#define F71882FG_FAN_NEG_TEMP_EN 0x2092#define F71882FG_FAN_PROG_SEL 0x8093 94#define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm)))95#define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm)))96#define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr))97 98#define F71882FG_REG_START 0x0199 100#define F71882FG_MAX_INS 11101 102#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */103 104static unsigned short force_id;105module_param(force_id, ushort, 0);106MODULE_PARM_DESC(force_id, "Override the detected device ID");107 108enum chips { f71808e, f71808a, f71858fg, f71862fg, f71868a, f71869, f71869a,109 f71882fg, f71889fg, f71889ed, f71889a, f8000, f81768d, f81865f,110 f81866a};111 112static const char *const f71882fg_names[] = {113 "f71808e",114 "f71808a",115 "f71858fg",116 "f71862fg",117 "f71868a",118 "f71869", /* Both f71869f and f71869e, reg. compatible and same id */119 "f71869a",120 "f71882fg",121 "f71889fg", /* f81801u too, same id */122 "f71889ed",123 "f71889a",124 "f8000",125 "f81768d",126 "f81865f",127 "f81866a",128};129 130static const char f71882fg_has_in[][F71882FG_MAX_INS] = {131 [f71808e] = { 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0 },132 [f71808a] = { 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0 },133 [f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },134 [f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },135 [f71868a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },136 [f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },137 [f71869a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },138 [f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },139 [f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },140 [f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },141 [f71889a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },142 [f8000] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },143 [f81768d] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },144 [f81865f] = { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },145 [f81866a] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },146};147 148static const char f71882fg_has_in1_alarm[] = {149 [f71808e] = 0,150 [f71808a] = 0,151 [f71858fg] = 0,152 [f71862fg] = 0,153 [f71868a] = 0,154 [f71869] = 0,155 [f71869a] = 0,156 [f71882fg] = 1,157 [f71889fg] = 1,158 [f71889ed] = 1,159 [f71889a] = 1,160 [f8000] = 0,161 [f81768d] = 1,162 [f81865f] = 1,163 [f81866a] = 1,164};165 166static const char f71882fg_fan_has_beep[] = {167 [f71808e] = 0,168 [f71808a] = 0,169 [f71858fg] = 0,170 [f71862fg] = 1,171 [f71868a] = 1,172 [f71869] = 1,173 [f71869a] = 1,174 [f71882fg] = 1,175 [f71889fg] = 1,176 [f71889ed] = 1,177 [f71889a] = 1,178 [f8000] = 0,179 [f81768d] = 1,180 [f81865f] = 1,181 [f81866a] = 1,182};183 184static const char f71882fg_nr_fans[] = {185 [f71808e] = 3,186 [f71808a] = 2, /* +1 fan which is monitor + simple pwm only */187 [f71858fg] = 3,188 [f71862fg] = 3,189 [f71868a] = 3,190 [f71869] = 3,191 [f71869a] = 3,192 [f71882fg] = 4,193 [f71889fg] = 3,194 [f71889ed] = 3,195 [f71889a] = 3,196 [f8000] = 3, /* +1 fan which is monitor only */197 [f81768d] = 3,198 [f81865f] = 2,199 [f81866a] = 3,200};201 202static const char f71882fg_temp_has_beep[] = {203 [f71808e] = 0,204 [f71808a] = 1,205 [f71858fg] = 0,206 [f71862fg] = 1,207 [f71868a] = 1,208 [f71869] = 1,209 [f71869a] = 1,210 [f71882fg] = 1,211 [f71889fg] = 1,212 [f71889ed] = 1,213 [f71889a] = 1,214 [f8000] = 0,215 [f81768d] = 1,216 [f81865f] = 1,217 [f81866a] = 1,218};219 220static const char f71882fg_nr_temps[] = {221 [f71808e] = 2,222 [f71808a] = 2,223 [f71858fg] = 3,224 [f71862fg] = 3,225 [f71868a] = 3,226 [f71869] = 3,227 [f71869a] = 3,228 [f71882fg] = 3,229 [f71889fg] = 3,230 [f71889ed] = 3,231 [f71889a] = 3,232 [f8000] = 3,233 [f81768d] = 3,234 [f81865f] = 2,235 [f81866a] = 3,236};237 238static struct platform_device *f71882fg_pdev;239 240struct f71882fg_sio_data {241 enum chips type;242};243 244struct f71882fg_data {245 unsigned short addr;246 enum chips type;247 struct device *hwmon_dev;248 249 struct mutex update_lock;250 int temp_start; /* temp numbering start (0 or 1) */251 bool valid; /* true if following fields are valid */252 char auto_point_temp_signed;253 unsigned long last_updated; /* In jiffies */254 unsigned long last_limits; /* In jiffies */255 256 /* Register Values */257 u8 in[F71882FG_MAX_INS];258 u8 in1_max;259 u8 in_status;260 u8 in_beep;261 u16 fan[4];262 u16 fan_target[4];263 u16 fan_full_speed[4];264 u8 fan_status;265 u8 fan_beep;266 /*267 * Note: all models have max 3 temperature channels, but on some268 * they are addressed as 0-2 and on others as 1-3, so for coding269 * convenience we reserve space for 4 channels270 */271 u16 temp[4];272 u8 temp_ovt[4];273 u8 temp_high[4];274 u8 temp_hyst[2]; /* 2 hysts stored per reg */275 u8 temp_type[4];276 u8 temp_status;277 u8 temp_beep;278 u8 temp_diode_open;279 u8 temp_config;280 u8 pwm[4];281 u8 pwm_enable;282 u8 pwm_auto_point_hyst[2];283 u8 pwm_auto_point_mapping[4];284 u8 pwm_auto_point_pwm[4][5];285 s8 pwm_auto_point_temp[4][4];286};287 288static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)289{290 u8 val;291 292 outb(reg, data->addr + ADDR_REG_OFFSET);293 val = inb(data->addr + DATA_REG_OFFSET);294 295 return val;296}297 298static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg)299{300 u16 val;301 302 val = f71882fg_read8(data, reg) << 8;303 val |= f71882fg_read8(data, reg + 1);304 305 return val;306}307 308static inline int fan_from_reg(u16 reg)309{310 return reg ? (1500000 / reg) : 0;311}312 313static inline u16 fan_to_reg(int fan)314{315 return fan ? (1500000 / fan) : 0;316}317 318static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)319{320 outb(reg, data->addr + ADDR_REG_OFFSET);321 outb(val, data->addr + DATA_REG_OFFSET);322}323 324static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)325{326 f71882fg_write8(data, reg, val >> 8);327 f71882fg_write8(data, reg + 1, val & 0xff);328}329 330static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)331{332 if (data->type == f71858fg)333 return f71882fg_read16(data, F71882FG_REG_TEMP(nr));334 else335 return f71882fg_read8(data, F71882FG_REG_TEMP(nr));336}337 338static struct f71882fg_data *f71882fg_update_device(struct device *dev)339{340 struct f71882fg_data *data = dev_get_drvdata(dev);341 int nr_fans = f71882fg_nr_fans[data->type];342 int nr_temps = f71882fg_nr_temps[data->type];343 int nr, reg, point;344 345 mutex_lock(&data->update_lock);346 347 /* Update once every 60 seconds */348 if (time_after(jiffies, data->last_limits + 60 * HZ) ||349 !data->valid) {350 if (f71882fg_has_in1_alarm[data->type]) {351 if (data->type == f81866a) {352 data->in1_max =353 f71882fg_read8(data,354 F81866_REG_IN1_HIGH);355 data->in_beep =356 f71882fg_read8(data,357 F81866_REG_IN_BEEP);358 } else {359 data->in1_max =360 f71882fg_read8(data,361 F71882FG_REG_IN1_HIGH);362 data->in_beep =363 f71882fg_read8(data,364 F71882FG_REG_IN_BEEP);365 }366 }367 368 /* Get High & boundary temps*/369 for (nr = data->temp_start; nr < nr_temps + data->temp_start;370 nr++) {371 data->temp_ovt[nr] = f71882fg_read8(data,372 F71882FG_REG_TEMP_OVT(nr));373 data->temp_high[nr] = f71882fg_read8(data,374 F71882FG_REG_TEMP_HIGH(nr));375 }376 377 if (data->type != f8000) {378 data->temp_hyst[0] = f71882fg_read8(data,379 F71882FG_REG_TEMP_HYST(0));380 data->temp_hyst[1] = f71882fg_read8(data,381 F71882FG_REG_TEMP_HYST(1));382 }383 /* All but the f71858fg / f8000 have this register */384 if ((data->type != f71858fg) && (data->type != f8000)) {385 reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);386 data->temp_type[1] = (reg & 0x02) ? 2 : 4;387 data->temp_type[2] = (reg & 0x04) ? 2 : 4;388 data->temp_type[3] = (reg & 0x08) ? 2 : 4;389 }390 391 if (f71882fg_fan_has_beep[data->type])392 data->fan_beep = f71882fg_read8(data,393 F71882FG_REG_FAN_BEEP);394 395 if (f71882fg_temp_has_beep[data->type])396 data->temp_beep = f71882fg_read8(data,397 F71882FG_REG_TEMP_BEEP);398 399 data->pwm_enable = f71882fg_read8(data,400 F71882FG_REG_PWM_ENABLE);401 data->pwm_auto_point_hyst[0] =402 f71882fg_read8(data, F71882FG_REG_FAN_HYST(0));403 data->pwm_auto_point_hyst[1] =404 f71882fg_read8(data, F71882FG_REG_FAN_HYST(1));405 406 for (nr = 0; nr < nr_fans; nr++) {407 data->pwm_auto_point_mapping[nr] =408 f71882fg_read8(data,409 F71882FG_REG_POINT_MAPPING(nr));410 411 switch (data->type) {412 default:413 for (point = 0; point < 5; point++) {414 data->pwm_auto_point_pwm[nr][point] =415 f71882fg_read8(data,416 F71882FG_REG_POINT_PWM417 (nr, point));418 }419 for (point = 0; point < 4; point++) {420 data->pwm_auto_point_temp[nr][point] =421 f71882fg_read8(data,422 F71882FG_REG_POINT_TEMP423 (nr, point));424 }425 break;426 case f71808e:427 case f71869:428 data->pwm_auto_point_pwm[nr][0] =429 f71882fg_read8(data,430 F71882FG_REG_POINT_PWM(nr, 0));431 fallthrough;432 case f71862fg:433 data->pwm_auto_point_pwm[nr][1] =434 f71882fg_read8(data,435 F71882FG_REG_POINT_PWM436 (nr, 1));437 data->pwm_auto_point_pwm[nr][4] =438 f71882fg_read8(data,439 F71882FG_REG_POINT_PWM440 (nr, 4));441 data->pwm_auto_point_temp[nr][0] =442 f71882fg_read8(data,443 F71882FG_REG_POINT_TEMP444 (nr, 0));445 data->pwm_auto_point_temp[nr][3] =446 f71882fg_read8(data,447 F71882FG_REG_POINT_TEMP448 (nr, 3));449 break;450 }451 }452 data->last_limits = jiffies;453 }454 455 /* Update every second */456 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {457 data->temp_status = f71882fg_read8(data,458 F71882FG_REG_TEMP_STATUS);459 data->temp_diode_open = f71882fg_read8(data,460 F71882FG_REG_TEMP_DIODE_OPEN);461 for (nr = data->temp_start; nr < nr_temps + data->temp_start;462 nr++)463 data->temp[nr] = f71882fg_read_temp(data, nr);464 465 data->fan_status = f71882fg_read8(data,466 F71882FG_REG_FAN_STATUS);467 for (nr = 0; nr < nr_fans; nr++) {468 data->fan[nr] = f71882fg_read16(data,469 F71882FG_REG_FAN(nr));470 data->fan_target[nr] =471 f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));472 data->fan_full_speed[nr] =473 f71882fg_read16(data,474 F71882FG_REG_FAN_FULL_SPEED(nr));475 data->pwm[nr] =476 f71882fg_read8(data, F71882FG_REG_PWM(nr));477 }478 /* Some models have 1 more fan with limited capabilities */479 if (data->type == f71808a) {480 data->fan[2] = f71882fg_read16(data,481 F71882FG_REG_FAN(2));482 data->pwm[2] = f71882fg_read8(data,483 F71882FG_REG_PWM(2));484 }485 if (data->type == f8000)486 data->fan[3] = f71882fg_read16(data,487 F71882FG_REG_FAN(3));488 489 if (f71882fg_has_in1_alarm[data->type]) {490 if (data->type == f81866a)491 data->in_status = f71882fg_read8(data,492 F81866_REG_IN_STATUS);493 494 else495 data->in_status = f71882fg_read8(data,496 F71882FG_REG_IN_STATUS);497 }498 499 for (nr = 0; nr < F71882FG_MAX_INS; nr++)500 if (f71882fg_has_in[data->type][nr])501 data->in[nr] = f71882fg_read8(data,502 F71882FG_REG_IN(nr));503 504 data->last_updated = jiffies;505 data->valid = true;506 }507 508 mutex_unlock(&data->update_lock);509 510 return data;511}512 513static ssize_t name_show(struct device *dev, struct device_attribute *devattr,514 char *buf)515{516 struct f71882fg_data *data = dev_get_drvdata(dev);517 return sprintf(buf, "%s\n", f71882fg_names[data->type]);518}519 520static DEVICE_ATTR_RO(name);521 522static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,523 char *buf)524{525 struct f71882fg_data *data = f71882fg_update_device(dev);526 int nr = to_sensor_dev_attr_2(devattr)->index;527 int sign, temp;528 529 if (data->type == f71858fg) {530 /* TEMP_TABLE_SEL 1 or 3 ? */531 if (data->temp_config & 1) {532 sign = data->temp[nr] & 0x0001;533 temp = (data->temp[nr] >> 5) & 0x7ff;534 } else {535 sign = data->temp[nr] & 0x8000;536 temp = (data->temp[nr] >> 5) & 0x3ff;537 }538 temp *= 125;539 if (sign)540 temp -= 128000;541 } else {542 temp = ((s8)data->temp[nr]) * 1000;543 }544 545 return sprintf(buf, "%d\n", temp);546}547 548static ssize_t show_temp_max(struct device *dev, struct device_attribute549 *devattr, char *buf)550{551 struct f71882fg_data *data = f71882fg_update_device(dev);552 int nr = to_sensor_dev_attr_2(devattr)->index;553 554 return sprintf(buf, "%d\n", data->temp_high[nr] * 1000);555}556 557static ssize_t store_temp_max(struct device *dev, struct device_attribute558 *devattr, const char *buf, size_t count)559{560 struct f71882fg_data *data = dev_get_drvdata(dev);561 int err, nr = to_sensor_dev_attr_2(devattr)->index;562 long val;563 564 err = kstrtol(buf, 10, &val);565 if (err)566 return err;567 568 val /= 1000;569 val = clamp_val(val, 0, 255);570 571 mutex_lock(&data->update_lock);572 f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);573 data->temp_high[nr] = val;574 mutex_unlock(&data->update_lock);575 576 return count;577}578 579static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute580 *devattr, char *buf)581{582 struct f71882fg_data *data = f71882fg_update_device(dev);583 int nr = to_sensor_dev_attr_2(devattr)->index;584 int temp_max_hyst;585 586 mutex_lock(&data->update_lock);587 if (nr & 1)588 temp_max_hyst = data->temp_hyst[nr / 2] >> 4;589 else590 temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f;591 temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000;592 mutex_unlock(&data->update_lock);593 594 return sprintf(buf, "%d\n", temp_max_hyst);595}596 597static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute598 *devattr, const char *buf, size_t count)599{600 struct f71882fg_data *data = dev_get_drvdata(dev);601 int err, nr = to_sensor_dev_attr_2(devattr)->index;602 ssize_t ret = count;603 u8 reg;604 long val;605 606 err = kstrtol(buf, 10, &val);607 if (err)608 return err;609 610 val /= 1000;611 612 mutex_lock(&data->update_lock);613 614 /* convert abs to relative and check */615 data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr));616 val = clamp_val(val, data->temp_high[nr] - 15, data->temp_high[nr]);617 val = data->temp_high[nr] - val;618 619 /* convert value to register contents */620 reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2));621 if (nr & 1)622 reg = (reg & 0x0f) | (val << 4);623 else624 reg = (reg & 0xf0) | val;625 f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg);626 data->temp_hyst[nr / 2] = reg;627 628 mutex_unlock(&data->update_lock);629 return ret;630}631 632static ssize_t show_temp_alarm(struct device *dev, struct device_attribute633 *devattr, char *buf)634{635 struct f71882fg_data *data = f71882fg_update_device(dev);636 int nr = to_sensor_dev_attr_2(devattr)->index;637 638 if (data->temp_status & (1 << nr))639 return sprintf(buf, "1\n");640 else641 return sprintf(buf, "0\n");642}643 644static ssize_t show_temp_crit(struct device *dev, struct device_attribute645 *devattr, char *buf)646{647 struct f71882fg_data *data = f71882fg_update_device(dev);648 int nr = to_sensor_dev_attr_2(devattr)->index;649 650 return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000);651}652 653static ssize_t store_temp_crit(struct device *dev, struct device_attribute654 *devattr, const char *buf, size_t count)655{656 struct f71882fg_data *data = dev_get_drvdata(dev);657 int err, nr = to_sensor_dev_attr_2(devattr)->index;658 long val;659 660 err = kstrtol(buf, 10, &val);661 if (err)662 return err;663 664 val /= 1000;665 val = clamp_val(val, 0, 255);666 667 mutex_lock(&data->update_lock);668 f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);669 data->temp_ovt[nr] = val;670 mutex_unlock(&data->update_lock);671 672 return count;673}674 675static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute676 *devattr, char *buf)677{678 struct f71882fg_data *data = f71882fg_update_device(dev);679 int nr = to_sensor_dev_attr_2(devattr)->index;680 int temp_crit_hyst;681 682 mutex_lock(&data->update_lock);683 if (nr & 1)684 temp_crit_hyst = data->temp_hyst[nr / 2] >> 4;685 else686 temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f;687 temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000;688 mutex_unlock(&data->update_lock);689 690 return sprintf(buf, "%d\n", temp_crit_hyst);691}692 693static ssize_t show_temp_fault(struct device *dev, struct device_attribute694 *devattr, char *buf)695{696 struct f71882fg_data *data = f71882fg_update_device(dev);697 int nr = to_sensor_dev_attr_2(devattr)->index;698 699 if (data->temp_diode_open & (1 << nr))700 return sprintf(buf, "1\n");701 else702 return sprintf(buf, "0\n");703}704 705/*706 * Temp attr for the f71858fg, the f71858fg is special as it has its707 * temperature indexes start at 0 (the others start at 1)708 */709static struct sensor_device_attribute_2 f71858fg_temp_attr[] = {710 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),711 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,712 store_temp_max, 0, 0),713 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,714 store_temp_max_hyst, 0, 0),715 SENSOR_ATTR_2(temp1_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0),716 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,717 store_temp_crit, 0, 0),718 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,719 0, 0),720 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),721 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),722 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),723 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,724 store_temp_max, 0, 1),725 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,726 store_temp_max_hyst, 0, 1),727 SENSOR_ATTR_2(temp2_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),728 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,729 store_temp_crit, 0, 1),730 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,731 0, 1),732 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),733 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),734 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),735 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,736 store_temp_max, 0, 2),737 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,738 store_temp_max_hyst, 0, 2),739 SENSOR_ATTR_2(temp3_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),740 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,741 store_temp_crit, 0, 2),742 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,743 0, 2),744 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),745 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),746};747 748static ssize_t show_temp_type(struct device *dev, struct device_attribute749 *devattr, char *buf)750{751 struct f71882fg_data *data = f71882fg_update_device(dev);752 int nr = to_sensor_dev_attr_2(devattr)->index;753 754 return sprintf(buf, "%d\n", data->temp_type[nr]);755}756 757/* Temp attr for the standard models */758static struct sensor_device_attribute_2 fxxxx_temp_attr[3][9] = { {759 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),760 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,761 store_temp_max, 0, 1),762 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,763 store_temp_max_hyst, 0, 1),764 /*765 * Should really be temp1_max_alarm, but older versions did not handle766 * the max and crit alarms separately and lm_sensors v2 depends on the767 * presence of temp#_alarm files. The same goes for temp2/3 _alarm.768 */769 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),770 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,771 store_temp_crit, 0, 1),772 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,773 0, 1),774 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),775 SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),776 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),777}, {778 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),779 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,780 store_temp_max, 0, 2),781 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,782 store_temp_max_hyst, 0, 2),783 /* Should be temp2_max_alarm, see temp1_alarm note */784 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),785 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,786 store_temp_crit, 0, 2),787 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,788 0, 2),789 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),790 SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),791 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),792}, {793 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),794 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,795 store_temp_max, 0, 3),796 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,797 store_temp_max_hyst, 0, 3),798 /* Should be temp3_max_alarm, see temp1_alarm note */799 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),800 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,801 store_temp_crit, 0, 3),802 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,803 0, 3),804 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),805 SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),806 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),807} };808 809static ssize_t show_temp_beep(struct device *dev, struct device_attribute810 *devattr, char *buf)811{812 struct f71882fg_data *data = f71882fg_update_device(dev);813 int nr = to_sensor_dev_attr_2(devattr)->index;814 815 if (data->temp_beep & (1 << nr))816 return sprintf(buf, "1\n");817 else818 return sprintf(buf, "0\n");819}820 821static ssize_t store_temp_beep(struct device *dev, struct device_attribute822 *devattr, const char *buf, size_t count)823{824 struct f71882fg_data *data = dev_get_drvdata(dev);825 int err, nr = to_sensor_dev_attr_2(devattr)->index;826 unsigned long val;827 828 err = kstrtoul(buf, 10, &val);829 if (err)830 return err;831 832 mutex_lock(&data->update_lock);833 data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);834 if (val)835 data->temp_beep |= 1 << nr;836 else837 data->temp_beep &= ~(1 << nr);838 839 f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep);840 mutex_unlock(&data->update_lock);841 842 return count;843}844 845/* Temp attr for models which can beep on temp alarm */846static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {847 SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,848 store_temp_beep, 0, 1),849 SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,850 store_temp_beep, 0, 5),851}, {852 SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,853 store_temp_beep, 0, 2),854 SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,855 store_temp_beep, 0, 6),856}, {857 SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,858 store_temp_beep, 0, 3),859 SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,860 store_temp_beep, 0, 7),861} };862 863static struct sensor_device_attribute_2 f81866_temp_beep_attr[3][2] = { {864 SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,865 store_temp_beep, 0, 0),866 SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,867 store_temp_beep, 0, 4),868}, {869 SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,870 store_temp_beep, 0, 1),871 SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,872 store_temp_beep, 0, 5),873}, {874 SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,875 store_temp_beep, 0, 2),876 SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,877 store_temp_beep, 0, 6),878} };879 880/*881 * Temp attr for the f8000882 * Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)883 * is used as hysteresis value to clear alarms884 * Also like the f71858fg its temperature indexes start at 0885 */886static struct sensor_device_attribute_2 f8000_temp_attr[] = {887 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),888 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,889 store_temp_crit, 0, 0),890 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,891 store_temp_max, 0, 0),892 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),893 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),894 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),895 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit,896 store_temp_crit, 0, 1),897 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,898 store_temp_max, 0, 1),899 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),900 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),901 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),902 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,903 store_temp_crit, 0, 2),904 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,905 store_temp_max, 0, 2),906 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),907 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),908};909 910static ssize_t show_in(struct device *dev, struct device_attribute *devattr,911 char *buf)912{913 struct f71882fg_data *data = f71882fg_update_device(dev);914 int nr = to_sensor_dev_attr_2(devattr)->index;915 916 return sprintf(buf, "%d\n", data->in[nr] * 8);917}918 919/* in attr for all models */920static struct sensor_device_attribute_2 fxxxx_in_attr[] = {921 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),922 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),923 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),924 SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),925 SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),926 SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),927 SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),928 SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),929 SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),930 SENSOR_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 0, 9),931 SENSOR_ATTR_2(in10_input, S_IRUGO, show_in, NULL, 0, 10),932};933 934static ssize_t show_in_max(struct device *dev, struct device_attribute935 *devattr, char *buf)936{937 struct f71882fg_data *data = f71882fg_update_device(dev);938 939 return sprintf(buf, "%d\n", data->in1_max * 8);940}941 942static ssize_t store_in_max(struct device *dev, struct device_attribute943 *devattr, const char *buf, size_t count)944{945 struct f71882fg_data *data = dev_get_drvdata(dev);946 int err;947 long val;948 949 err = kstrtol(buf, 10, &val);950 if (err)951 return err;952 953 val /= 8;954 val = clamp_val(val, 0, 255);955 956 mutex_lock(&data->update_lock);957 if (data->type == f81866a)958 f71882fg_write8(data, F81866_REG_IN1_HIGH, val);959 else960 f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);961 data->in1_max = val;962 mutex_unlock(&data->update_lock);963 964 return count;965}966 967static ssize_t show_in_beep(struct device *dev, struct device_attribute968 *devattr, char *buf)969{970 struct f71882fg_data *data = f71882fg_update_device(dev);971 int nr = to_sensor_dev_attr_2(devattr)->index;972 973 if (data->in_beep & (1 << nr))974 return sprintf(buf, "1\n");975 else976 return sprintf(buf, "0\n");977}978 979static ssize_t store_in_beep(struct device *dev, struct device_attribute980 *devattr, const char *buf, size_t count)981{982 struct f71882fg_data *data = dev_get_drvdata(dev);983 int err, nr = to_sensor_dev_attr_2(devattr)->index;984 unsigned long val;985 986 err = kstrtoul(buf, 10, &val);987 if (err)988 return err;989 990 mutex_lock(&data->update_lock);991 if (data->type == f81866a)992 data->in_beep = f71882fg_read8(data, F81866_REG_IN_BEEP);993 else994 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);995 996 if (val)997 data->in_beep |= 1 << nr;998 else999 data->in_beep &= ~(1 << nr);1000 1001 if (data->type == f81866a)1002 f71882fg_write8(data, F81866_REG_IN_BEEP, data->in_beep);1003 else1004 f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);1005 mutex_unlock(&data->update_lock);1006 1007 return count;1008}1009 1010static ssize_t show_in_alarm(struct device *dev, struct device_attribute1011 *devattr, char *buf)1012{1013 struct f71882fg_data *data = f71882fg_update_device(dev);1014 int nr = to_sensor_dev_attr_2(devattr)->index;1015 1016 if (data->in_status & (1 << nr))1017 return sprintf(buf, "1\n");1018 else1019 return sprintf(buf, "0\n");1020}1021 1022/* For models with in1 alarm capability */1023static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {1024 SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,1025 0, 1),1026 SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,1027 0, 1),1028 SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),1029};1030 1031static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,1032 char *buf)1033{1034 struct f71882fg_data *data = f71882fg_update_device(dev);1035 int nr = to_sensor_dev_attr_2(devattr)->index;1036 int speed = fan_from_reg(data->fan[nr]);1037 1038 if (speed == FAN_MIN_DETECT)1039 speed = 0;1040 1041 return sprintf(buf, "%d\n", speed);1042}1043 1044static ssize_t show_fan_full_speed(struct device *dev,1045 struct device_attribute *devattr, char *buf)1046{1047 struct f71882fg_data *data = f71882fg_update_device(dev);1048 int nr = to_sensor_dev_attr_2(devattr)->index;1049 int speed = fan_from_reg(data->fan_full_speed[nr]);1050 return sprintf(buf, "%d\n", speed);1051}1052 1053static ssize_t store_fan_full_speed(struct device *dev,1054 struct device_attribute *devattr,1055 const char *buf, size_t count)1056{1057 struct f71882fg_data *data = dev_get_drvdata(dev);1058 int err, nr = to_sensor_dev_attr_2(devattr)->index;1059 long val;1060 1061 err = kstrtol(buf, 10, &val);1062 if (err)1063 return err;1064 1065 val = clamp_val(val, 23, 1500000);1066 val = fan_to_reg(val);1067 1068 mutex_lock(&data->update_lock);1069 f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);1070 data->fan_full_speed[nr] = val;1071 mutex_unlock(&data->update_lock);1072 1073 return count;1074}1075 1076static ssize_t show_fan_alarm(struct device *dev, struct device_attribute1077 *devattr, char *buf)1078{1079 struct f71882fg_data *data = f71882fg_update_device(dev);1080 int nr = to_sensor_dev_attr_2(devattr)->index;1081 1082 if (data->fan_status & (1 << nr))1083 return sprintf(buf, "1\n");1084 else1085 return sprintf(buf, "0\n");1086}1087 1088static ssize_t show_pwm(struct device *dev,1089 struct device_attribute *devattr, char *buf)1090{1091 struct f71882fg_data *data = f71882fg_update_device(dev);1092 int val, nr = to_sensor_dev_attr_2(devattr)->index;1093 mutex_lock(&data->update_lock);1094 if (data->pwm_enable & (1 << (2 * nr)))1095 /* PWM mode */1096 val = data->pwm[nr];1097 else {1098 /* RPM mode */1099 if (fan_from_reg(data->fan_full_speed[nr]))1100 val = 255 * fan_from_reg(data->fan_target[nr])1101 / fan_from_reg(data->fan_full_speed[nr]);1102 else1103 val = 0;1104 }1105 mutex_unlock(&data->update_lock);1106 return sprintf(buf, "%d\n", val);1107}1108 1109static ssize_t store_pwm(struct device *dev,1110 struct device_attribute *devattr, const char *buf,1111 size_t count)1112{1113 struct f71882fg_data *data = dev_get_drvdata(dev);1114 int err, nr = to_sensor_dev_attr_2(devattr)->index;1115 long val;1116 1117 err = kstrtol(buf, 10, &val);1118 if (err)1119 return err;1120 1121 val = clamp_val(val, 0, 255);1122 1123 mutex_lock(&data->update_lock);1124 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);1125 if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) ||1126 (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) {1127 count = -EROFS;1128 goto leave;1129 }1130 if (data->pwm_enable & (1 << (2 * nr))) {1131 /* PWM mode */1132 f71882fg_write8(data, F71882FG_REG_PWM(nr), val);1133 data->pwm[nr] = val;1134 } else {1135 /* RPM mode */1136 int target, full_speed;1137 full_speed = f71882fg_read16(data,1138 F71882FG_REG_FAN_FULL_SPEED(nr));1139 target = fan_to_reg(val * fan_from_reg(full_speed) / 255);1140 f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target);1141 data->fan_target[nr] = target;1142 data->fan_full_speed[nr] = full_speed;1143 }1144leave:1145 mutex_unlock(&data->update_lock);1146 1147 return count;1148}1149 1150static ssize_t show_pwm_enable(struct device *dev,1151 struct device_attribute *devattr, char *buf)1152{1153 int result = 0;1154 struct f71882fg_data *data = f71882fg_update_device(dev);1155 int nr = to_sensor_dev_attr_2(devattr)->index;1156 1157 switch ((data->pwm_enable >> 2 * nr) & 3) {1158 case 0:1159 case 1:1160 result = 2; /* Normal auto mode */1161 break;1162 case 2:1163 result = 1; /* Manual mode */1164 break;1165 case 3:1166 if (data->type == f8000)1167 result = 3; /* Thermostat mode */1168 else1169 result = 1; /* Manual mode */1170 break;1171 }1172 1173 return sprintf(buf, "%d\n", result);1174}1175 1176static ssize_t store_pwm_enable(struct device *dev, struct device_attribute1177 *devattr, const char *buf, size_t count)1178{1179 struct f71882fg_data *data = dev_get_drvdata(dev);1180 int err, nr = to_sensor_dev_attr_2(devattr)->index;1181 long val;1182 1183 err = kstrtol(buf, 10, &val);1184 if (err)1185 return err;1186 1187 /* Special case for F8000 pwm channel 3 which only does auto mode */1188 if (data->type == f8000 && nr == 2 && val != 2)1189 return -EINVAL;1190 1191 mutex_lock(&data->update_lock);1192 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);1193 /* Special case for F8000 auto PWM mode / Thermostat mode */1194 if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) {1195 switch (val) {1196 case 2:1197 data->pwm_enable &= ~(2 << (2 * nr));1198 break; /* Normal auto mode */1199 case 3:1200 data->pwm_enable |= 2 << (2 * nr);1201 break; /* Thermostat mode */1202 default:1203 count = -EINVAL;1204 goto leave;1205 }1206 } else {1207 switch (val) {1208 case 1:1209 /* The f71858fg does not support manual RPM mode */1210 if (data->type == f71858fg &&1211 ((data->pwm_enable >> (2 * nr)) & 1)) {1212 count = -EINVAL;1213 goto leave;1214 }1215 data->pwm_enable |= 2 << (2 * nr);1216 break; /* Manual */1217 case 2:1218 data->pwm_enable &= ~(2 << (2 * nr));1219 break; /* Normal auto mode */1220 default:1221 count = -EINVAL;1222 goto leave;1223 }1224 }1225 f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);1226leave:1227 mutex_unlock(&data->update_lock);1228 1229 return count;1230}1231 1232static ssize_t show_pwm_interpolate(struct device *dev,1233 struct device_attribute *devattr, char *buf)1234{1235 int result;1236 struct f71882fg_data *data = f71882fg_update_device(dev);1237 int nr = to_sensor_dev_attr_2(devattr)->index;1238 1239 result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;1240 1241 return sprintf(buf, "%d\n", result);1242}1243 1244static ssize_t store_pwm_interpolate(struct device *dev,1245 struct device_attribute *devattr,1246 const char *buf, size_t count)1247{1248 struct f71882fg_data *data = dev_get_drvdata(dev);1249 int err, nr = to_sensor_dev_attr_2(devattr)->index;1250 unsigned long val;1251 1252 err = kstrtoul(buf, 10, &val);1253 if (err)1254 return err;1255 1256 mutex_lock(&data->update_lock);1257 data->pwm_auto_point_mapping[nr] =1258 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));1259 if (val)1260 val = data->pwm_auto_point_mapping[nr] | (1 << 4);1261 else1262 val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));1263 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);1264 data->pwm_auto_point_mapping[nr] = val;1265 mutex_unlock(&data->update_lock);1266 1267 return count;1268}1269 1270/* Fan / PWM attr common to all models */1271static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { {1272 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),1273 SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,1274 show_fan_full_speed,1275 store_fan_full_speed, 0, 0),1276 SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),1277 SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),1278 SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,1279 store_pwm_enable, 0, 0),1280 SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,1281 show_pwm_interpolate, store_pwm_interpolate, 0, 0),1282}, {1283 SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),1284 SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,1285 show_fan_full_speed,1286 store_fan_full_speed, 0, 1),1287 SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),1288 SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),1289 SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,1290 store_pwm_enable, 0, 1),1291 SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,1292 show_pwm_interpolate, store_pwm_interpolate, 0, 1),1293}, {1294 SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),1295 SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,1296 show_fan_full_speed,1297 store_fan_full_speed, 0, 2),1298 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),1299 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),1300 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,1301 store_pwm_enable, 0, 2),1302 SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,1303 show_pwm_interpolate, store_pwm_interpolate, 0, 2),1304}, {1305 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),1306 SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,1307 show_fan_full_speed,1308 store_fan_full_speed, 0, 3),1309 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),1310 SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),1311 SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,1312 store_pwm_enable, 0, 3),1313 SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,1314 show_pwm_interpolate, store_pwm_interpolate, 0, 3),1315} };1316 1317static ssize_t show_simple_pwm(struct device *dev,1318 struct device_attribute *devattr, char *buf)1319{1320 struct f71882fg_data *data = f71882fg_update_device(dev);1321 int val, nr = to_sensor_dev_attr_2(devattr)->index;1322 1323 val = data->pwm[nr];1324 return sprintf(buf, "%d\n", val);1325}1326 1327static ssize_t store_simple_pwm(struct device *dev,1328 struct device_attribute *devattr,1329 const char *buf, size_t count)1330{1331 struct f71882fg_data *data = dev_get_drvdata(dev);1332 int err, nr = to_sensor_dev_attr_2(devattr)->index;1333 long val;1334 1335 err = kstrtol(buf, 10, &val);1336 if (err)1337 return err;1338 1339 val = clamp_val(val, 0, 255);1340 1341 mutex_lock(&data->update_lock);1342 f71882fg_write8(data, F71882FG_REG_PWM(nr), val);1343 data->pwm[nr] = val;1344 mutex_unlock(&data->update_lock);1345 1346 return count;1347}1348 1349/* Attr for the third fan of the f71808a, which only has manual pwm */1350static struct sensor_device_attribute_2 f71808a_fan3_attr[] = {1351 SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),1352 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),1353 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR,1354 show_simple_pwm, store_simple_pwm, 0, 2),1355};1356 1357static ssize_t show_fan_beep(struct device *dev, struct device_attribute1358 *devattr, char *buf)1359{1360 struct f71882fg_data *data = f71882fg_update_device(dev);1361 int nr = to_sensor_dev_attr_2(devattr)->index;1362 1363 if (data->fan_beep & (1 << nr))1364 return sprintf(buf, "1\n");1365 else1366 return sprintf(buf, "0\n");1367}1368 1369static ssize_t store_fan_beep(struct device *dev, struct device_attribute1370 *devattr, const char *buf, size_t count)1371{1372 struct f71882fg_data *data = dev_get_drvdata(dev);1373 int err, nr = to_sensor_dev_attr_2(devattr)->index;1374 unsigned long val;1375 1376 err = kstrtoul(buf, 10, &val);1377 if (err)1378 return err;1379 1380 mutex_lock(&data->update_lock);1381 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);1382 if (val)1383 data->fan_beep |= 1 << nr;1384 else1385 data->fan_beep &= ~(1 << nr);1386 1387 f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep);1388 mutex_unlock(&data->update_lock);1389 1390 return count;1391}1392 1393/* Attr for models which can beep on Fan alarm */1394static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {1395 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,1396 store_fan_beep, 0, 0),1397 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,1398 store_fan_beep, 0, 1),1399 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,1400 store_fan_beep, 0, 2),1401 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,1402 store_fan_beep, 0, 3),1403};1404 1405static ssize_t show_pwm_auto_point_channel(struct device *dev,1406 struct device_attribute *devattr,1407 char *buf)1408{1409 int result;1410 struct f71882fg_data *data = f71882fg_update_device(dev);1411 int nr = to_sensor_dev_attr_2(devattr)->index;1412 1413 result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) -1414 data->temp_start);1415 1416 return sprintf(buf, "%d\n", result);1417}1418 1419static ssize_t store_pwm_auto_point_channel(struct device *dev,1420 struct device_attribute *devattr,1421 const char *buf, size_t count)1422{1423 struct f71882fg_data *data = dev_get_drvdata(dev);1424 int err, nr = to_sensor_dev_attr_2(devattr)->index;1425 long val;1426 1427 err = kstrtol(buf, 10, &val);1428 if (err)1429 return err;1430 1431 switch (val) {1432 case 1:1433 val = 0;1434 break;1435 case 2:1436 val = 1;1437 break;1438 case 4:1439 val = 2;1440 break;1441 default:1442 return -EINVAL;1443 }1444 val += data->temp_start;1445 mutex_lock(&data->update_lock);1446 data->pwm_auto_point_mapping[nr] =1447 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));1448 val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;1449 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);1450 data->pwm_auto_point_mapping[nr] = val;1451 mutex_unlock(&data->update_lock);1452 1453 return count;1454}1455 1456static ssize_t show_pwm_auto_point_pwm(struct device *dev,1457 struct device_attribute *devattr,1458 char *buf)1459{1460 int result;1461 struct f71882fg_data *data = f71882fg_update_device(dev);1462 int pwm = to_sensor_dev_attr_2(devattr)->index;1463 int point = to_sensor_dev_attr_2(devattr)->nr;1464 1465 mutex_lock(&data->update_lock);1466 if (data->pwm_enable & (1 << (2 * pwm))) {1467 /* PWM mode */1468 result = data->pwm_auto_point_pwm[pwm][point];1469 } else {1470 /* RPM mode */1471 result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);1472 }1473 mutex_unlock(&data->update_lock);1474 1475 return sprintf(buf, "%d\n", result);1476}1477 1478static ssize_t store_pwm_auto_point_pwm(struct device *dev,1479 struct device_attribute *devattr,1480 const char *buf, size_t count)1481{1482 struct f71882fg_data *data = dev_get_drvdata(dev);1483 int err, pwm = to_sensor_dev_attr_2(devattr)->index;1484 int point = to_sensor_dev_attr_2(devattr)->nr;1485 long val;1486 1487 err = kstrtol(buf, 10, &val);1488 if (err)1489 return err;1490 1491 val = clamp_val(val, 0, 255);1492 1493 mutex_lock(&data->update_lock);1494 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);1495 if (data->pwm_enable & (1 << (2 * pwm))) {1496 /* PWM mode */1497 } else {1498 /* RPM mode */1499 if (val < 29) /* Prevent negative numbers */1500 val = 255;1501 else1502 val = (255 - val) * 32 / val;1503 }1504 f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);1505 data->pwm_auto_point_pwm[pwm][point] = val;1506 mutex_unlock(&data->update_lock);1507 1508 return count;1509}1510 1511static ssize_t show_pwm_auto_point_temp(struct device *dev,1512 struct device_attribute *devattr,1513 char *buf)1514{1515 int result;1516 struct f71882fg_data *data = f71882fg_update_device(dev);1517 int pwm = to_sensor_dev_attr_2(devattr)->index;1518 int point = to_sensor_dev_attr_2(devattr)->nr;1519 1520 result = data->pwm_auto_point_temp[pwm][point];1521 return sprintf(buf, "%d\n", 1000 * result);1522}1523 1524static ssize_t store_pwm_auto_point_temp(struct device *dev,1525 struct device_attribute *devattr,1526 const char *buf, size_t count)1527{1528 struct f71882fg_data *data = dev_get_drvdata(dev);1529 int err, pwm = to_sensor_dev_attr_2(devattr)->index;1530 int point = to_sensor_dev_attr_2(devattr)->nr;1531 long val;1532 1533 err = kstrtol(buf, 10, &val);1534 if (err)1535 return err;1536 1537 val /= 1000;1538 1539 if (data->auto_point_temp_signed)1540 val = clamp_val(val, -128, 127);1541 else1542 val = clamp_val(val, 0, 127);1543 1544 mutex_lock(&data->update_lock);1545 f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);1546 data->pwm_auto_point_temp[pwm][point] = val;1547 mutex_unlock(&data->update_lock);1548 1549 return count;1550}1551 1552static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,1553 struct device_attribute *devattr,1554 char *buf)1555{1556 int result = 0;1557 struct f71882fg_data *data = f71882fg_update_device(dev);1558 int nr = to_sensor_dev_attr_2(devattr)->index;1559 int point = to_sensor_dev_attr_2(devattr)->nr;1560 1561 mutex_lock(&data->update_lock);1562 if (nr & 1)1563 result = data->pwm_auto_point_hyst[nr / 2] >> 4;1564 else1565 result = data->pwm_auto_point_hyst[nr / 2] & 0x0f;1566 result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);1567 mutex_unlock(&data->update_lock);1568 1569 return sprintf(buf, "%d\n", result);1570}1571 1572static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,1573 struct device_attribute *devattr,1574 const char *buf, size_t count)1575{1576 struct f71882fg_data *data = dev_get_drvdata(dev);1577 int err, nr = to_sensor_dev_attr_2(devattr)->index;1578 int point = to_sensor_dev_attr_2(devattr)->nr;1579 u8 reg;1580 long val;1581 1582 err = kstrtol(buf, 10, &val);1583 if (err)1584 return err;1585 1586 val /= 1000;1587 1588 mutex_lock(&data->update_lock);1589 data->pwm_auto_point_temp[nr][point] =1590 f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point));1591 val = clamp_val(val, data->pwm_auto_point_temp[nr][point] - 15,1592 data->pwm_auto_point_temp[nr][point]);1593 val = data->pwm_auto_point_temp[nr][point] - val;1594 1595 reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2));1596 if (nr & 1)1597 reg = (reg & 0x0f) | (val << 4);1598 else1599 reg = (reg & 0xf0) | val;1600 1601 f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg);1602 data->pwm_auto_point_hyst[nr / 2] = reg;1603 mutex_unlock(&data->update_lock);1604 1605 return count;1606}1607 1608/*1609 * PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the1610 * standard models1611 */1612static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[3][7] = { {1613 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,1614 show_pwm_auto_point_channel,1615 store_pwm_auto_point_channel, 0, 0),1616 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,1617 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1618 1, 0),1619 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,1620 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1621 4, 0),1622 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,1623 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1624 0, 0),1625 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,1626 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1627 3, 0),1628 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1629 show_pwm_auto_point_temp_hyst,1630 store_pwm_auto_point_temp_hyst,1631 0, 0),1632 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,1633 show_pwm_auto_point_temp_hyst, NULL, 3, 0),1634}, {1635 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,1636 show_pwm_auto_point_channel,1637 store_pwm_auto_point_channel, 0, 1),1638 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,1639 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1640 1, 1),1641 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,1642 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1643 4, 1),1644 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,1645 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1646 0, 1),1647 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,1648 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1649 3, 1),1650 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1651 show_pwm_auto_point_temp_hyst,1652 store_pwm_auto_point_temp_hyst,1653 0, 1),1654 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,1655 show_pwm_auto_point_temp_hyst, NULL, 3, 1),1656}, {1657 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,1658 show_pwm_auto_point_channel,1659 store_pwm_auto_point_channel, 0, 2),1660 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,1661 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1662 1, 2),1663 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,1664 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1665 4, 2),1666 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,1667 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1668 0, 2),1669 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,1670 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1671 3, 2),1672 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1673 show_pwm_auto_point_temp_hyst,1674 store_pwm_auto_point_temp_hyst,1675 0, 2),1676 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,1677 show_pwm_auto_point_temp_hyst, NULL, 3, 2),1678} };1679 1680/*1681 * PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the1682 * pwm setting when the temperature is above the pwmX_auto_point1_temp can be1683 * programmed instead of being hardcoded to 0xff1684 */1685static struct sensor_device_attribute_2 f71869_auto_pwm_attr[3][8] = { {1686 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,1687 show_pwm_auto_point_channel,1688 store_pwm_auto_point_channel, 0, 0),1689 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,1690 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1691 0, 0),1692 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,1693 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1694 1, 0),1695 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,1696 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1697 4, 0),1698 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,1699 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1700 0, 0),1701 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,1702 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1703 3, 0),1704 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1705 show_pwm_auto_point_temp_hyst,1706 store_pwm_auto_point_temp_hyst,1707 0, 0),1708 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,1709 show_pwm_auto_point_temp_hyst, NULL, 3, 0),1710}, {1711 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,1712 show_pwm_auto_point_channel,1713 store_pwm_auto_point_channel, 0, 1),1714 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,1715 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1716 0, 1),1717 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,1718 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1719 1, 1),1720 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,1721 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1722 4, 1),1723 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,1724 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1725 0, 1),1726 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,1727 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1728 3, 1),1729 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1730 show_pwm_auto_point_temp_hyst,1731 store_pwm_auto_point_temp_hyst,1732 0, 1),1733 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,1734 show_pwm_auto_point_temp_hyst, NULL, 3, 1),1735}, {1736 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,1737 show_pwm_auto_point_channel,1738 store_pwm_auto_point_channel, 0, 2),1739 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,1740 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1741 0, 2),1742 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,1743 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1744 1, 2),1745 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,1746 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1747 4, 2),1748 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,1749 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1750 0, 2),1751 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,1752 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1753 3, 2),1754 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1755 show_pwm_auto_point_temp_hyst,1756 store_pwm_auto_point_temp_hyst,1757 0, 2),1758 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,1759 show_pwm_auto_point_temp_hyst, NULL, 3, 2),1760} };1761 1762/* PWM attr for the standard models */1763static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {1764 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,1765 show_pwm_auto_point_channel,1766 store_pwm_auto_point_channel, 0, 0),1767 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,1768 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1769 0, 0),1770 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,1771 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1772 1, 0),1773 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,1774 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1775 2, 0),1776 SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,1777 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1778 3, 0),1779 SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,1780 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1781 4, 0),1782 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,1783 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1784 0, 0),1785 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,1786 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1787 1, 0),1788 SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,1789 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1790 2, 0),1791 SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,1792 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1793 3, 0),1794 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1795 show_pwm_auto_point_temp_hyst,1796 store_pwm_auto_point_temp_hyst,1797 0, 0),1798 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,1799 show_pwm_auto_point_temp_hyst, NULL, 1, 0),1800 SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,1801 show_pwm_auto_point_temp_hyst, NULL, 2, 0),1802 SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,1803 show_pwm_auto_point_temp_hyst, NULL, 3, 0),1804}, {1805 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,1806 show_pwm_auto_point_channel,1807 store_pwm_auto_point_channel, 0, 1),1808 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,1809 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1810 0, 1),1811 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,1812 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1813 1, 1),1814 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,1815 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1816 2, 1),1817 SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,1818 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1819 3, 1),1820 SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,1821 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1822 4, 1),1823 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,1824 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1825 0, 1),1826 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,1827 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1828 1, 1),1829 SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,1830 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1831 2, 1),1832 SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,1833 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1834 3, 1),1835 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1836 show_pwm_auto_point_temp_hyst,1837 store_pwm_auto_point_temp_hyst,1838 0, 1),1839 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,1840 show_pwm_auto_point_temp_hyst, NULL, 1, 1),1841 SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,1842 show_pwm_auto_point_temp_hyst, NULL, 2, 1),1843 SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,1844 show_pwm_auto_point_temp_hyst, NULL, 3, 1),1845}, {1846 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,1847 show_pwm_auto_point_channel,1848 store_pwm_auto_point_channel, 0, 2),1849 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,1850 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1851 0, 2),1852 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,1853 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1854 1, 2),1855 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,1856 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1857 2, 2),1858 SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,1859 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1860 3, 2),1861 SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,1862 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1863 4, 2),1864 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,1865 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1866 0, 2),1867 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,1868 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1869 1, 2),1870 SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,1871 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1872 2, 2),1873 SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,1874 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1875 3, 2),1876 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1877 show_pwm_auto_point_temp_hyst,1878 store_pwm_auto_point_temp_hyst,1879 0, 2),1880 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,1881 show_pwm_auto_point_temp_hyst, NULL, 1, 2),1882 SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,1883 show_pwm_auto_point_temp_hyst, NULL, 2, 2),1884 SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,1885 show_pwm_auto_point_temp_hyst, NULL, 3, 2),1886}, {1887 SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,1888 show_pwm_auto_point_channel,1889 store_pwm_auto_point_channel, 0, 3),1890 SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,1891 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1892 0, 3),1893 SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,1894 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1895 1, 3),1896 SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,1897 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1898 2, 3),1899 SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,1900 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1901 3, 3),1902 SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,1903 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1904 4, 3),1905 SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,1906 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1907 0, 3),1908 SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,1909 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1910 1, 3),1911 SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,1912 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1913 2, 3),1914 SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,1915 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1916 3, 3),1917 SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1918 show_pwm_auto_point_temp_hyst,1919 store_pwm_auto_point_temp_hyst,1920 0, 3),1921 SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,1922 show_pwm_auto_point_temp_hyst, NULL, 1, 3),1923 SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,1924 show_pwm_auto_point_temp_hyst, NULL, 2, 3),1925 SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,1926 show_pwm_auto_point_temp_hyst, NULL, 3, 3),1927} };1928 1929/* Fan attr specific to the f8000 (4th fan input can only measure speed) */1930static struct sensor_device_attribute_2 f8000_fan_attr[] = {1931 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),1932};1933 1934/*1935 * PWM attr for the f8000, zones mapped to temp instead of to pwm!1936 * Also the register block at offset A0 maps to TEMP1 (so our temp2, as the1937 * F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP01938 */1939static struct sensor_device_attribute_2 f8000_auto_pwm_attr[3][14] = { {1940 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,1941 show_pwm_auto_point_channel,1942 store_pwm_auto_point_channel, 0, 0),1943 SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,1944 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1945 0, 2),1946 SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR,1947 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1948 1, 2),1949 SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR,1950 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1951 2, 2),1952 SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR,1953 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1954 3, 2),1955 SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR,1956 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1957 4, 2),1958 SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR,1959 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1960 0, 2),1961 SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR,1962 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1963 1, 2),1964 SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR,1965 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1966 2, 2),1967 SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR,1968 show_pwm_auto_point_temp, store_pwm_auto_point_temp,1969 3, 2),1970 SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,1971 show_pwm_auto_point_temp_hyst,1972 store_pwm_auto_point_temp_hyst,1973 0, 2),1974 SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO,1975 show_pwm_auto_point_temp_hyst, NULL, 1, 2),1976 SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO,1977 show_pwm_auto_point_temp_hyst, NULL, 2, 2),1978 SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,1979 show_pwm_auto_point_temp_hyst, NULL, 3, 2),1980}, {1981 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,1982 show_pwm_auto_point_channel,1983 store_pwm_auto_point_channel, 0, 1),1984 SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR,1985 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1986 0, 0),1987 SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR,1988 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1989 1, 0),1990 SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR,1991 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1992 2, 0),1993 SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR,1994 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1995 3, 0),1996 SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR,1997 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,1998 4, 0),1999 SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR,2000 show_pwm_auto_point_temp, store_pwm_auto_point_temp,2001 0, 0),2002 SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR,2003 show_pwm_auto_point_temp, store_pwm_auto_point_temp,2004 1, 0),2005 SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR,2006 show_pwm_auto_point_temp, store_pwm_auto_point_temp,2007 2, 0),2008 SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR,2009 show_pwm_auto_point_temp, store_pwm_auto_point_temp,2010 3, 0),2011 SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,2012 show_pwm_auto_point_temp_hyst,2013 store_pwm_auto_point_temp_hyst,2014 0, 0),2015 SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO,2016 show_pwm_auto_point_temp_hyst, NULL, 1, 0),2017 SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO,2018 show_pwm_auto_point_temp_hyst, NULL, 2, 0),2019 SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,2020 show_pwm_auto_point_temp_hyst, NULL, 3, 0),2021}, {2022 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,2023 show_pwm_auto_point_channel,2024 store_pwm_auto_point_channel, 0, 2),2025 SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR,2026 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,2027 0, 1),2028 SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR,2029 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,2030 1, 1),2031 SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR,2032 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,2033 2, 1),2034 SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR,2035 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,2036 3, 1),2037 SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR,2038 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,2039 4, 1),2040 SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR,2041 show_pwm_auto_point_temp, store_pwm_auto_point_temp,2042 0, 1),2043 SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR,2044 show_pwm_auto_point_temp, store_pwm_auto_point_temp,2045 1, 1),2046 SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR,2047 show_pwm_auto_point_temp, store_pwm_auto_point_temp,2048 2, 1),2049 SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR,2050 show_pwm_auto_point_temp, store_pwm_auto_point_temp,2051 3, 1),2052 SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,2053 show_pwm_auto_point_temp_hyst,2054 store_pwm_auto_point_temp_hyst,2055 0, 1),2056 SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO,2057 show_pwm_auto_point_temp_hyst, NULL, 1, 1),2058 SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO,2059 show_pwm_auto_point_temp_hyst, NULL, 2, 1),2060 SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,2061 show_pwm_auto_point_temp_hyst, NULL, 3, 1),2062} };2063 2064/* Super I/O functions */2065static inline int superio_inb(int base, int reg)2066{2067 outb(reg, base);2068 return inb(base + 1);2069}2070 2071static int superio_inw(int base, int reg)2072{2073 int val;2074 val = superio_inb(base, reg) << 8;2075 val |= superio_inb(base, reg + 1);2076 return val;2077}2078 2079static inline int superio_enter(int base)2080{2081 /* Don't step on other drivers' I/O space by accident */2082 if (!request_muxed_region(base, 2, DRVNAME)) {2083 pr_err("I/O address 0x%04x already in use\n", base);2084 return -EBUSY;2085 }2086 2087 /* according to the datasheet the key must be send twice! */2088 outb(SIO_UNLOCK_KEY, base);2089 outb(SIO_UNLOCK_KEY, base);2090 2091 return 0;2092}2093 2094static inline void superio_select(int base, int ld)2095{2096 outb(SIO_REG_LDSEL, base);2097 outb(ld, base + 1);2098}2099 2100static inline void superio_exit(int base)2101{2102 outb(SIO_LOCK_KEY, base);2103 release_region(base, 2);2104}2105 2106static int f71882fg_create_sysfs_files(struct platform_device *pdev,2107 struct sensor_device_attribute_2 *attr, int count)2108{2109 int err, i;2110 2111 for (i = 0; i < count; i++) {2112 err = device_create_file(&pdev->dev, &attr[i].dev_attr);2113 if (err)2114 return err;2115 }2116 return 0;2117}2118 2119static void f71882fg_remove_sysfs_files(struct platform_device *pdev,2120 struct sensor_device_attribute_2 *attr, int count)2121{2122 int i;2123 2124 for (i = 0; i < count; i++)2125 device_remove_file(&pdev->dev, &attr[i].dev_attr);2126}2127 2128static int f71882fg_create_fan_sysfs_files(2129 struct platform_device *pdev, int idx)2130{2131 struct f71882fg_data *data = platform_get_drvdata(pdev);2132 int err;2133 2134 /* Sanity check the pwm setting */2135 err = 0;2136 switch (data->type) {2137 case f71858fg:2138 if (((data->pwm_enable >> (idx * 2)) & 3) == 3)2139 err = 1;2140 break;2141 case f71862fg:2142 if (((data->pwm_enable >> (idx * 2)) & 1) != 1)2143 err = 1;2144 break;2145 case f8000:2146 if (idx == 2)2147 err = data->pwm_enable & 0x20;2148 break;2149 default:2150 break;2151 }2152 if (err) {2153 dev_err(&pdev->dev,2154 "Invalid (reserved) pwm settings: 0x%02x, "2155 "skipping fan %d\n",2156 (data->pwm_enable >> (idx * 2)) & 3, idx + 1);2157 return 0; /* This is a non fatal condition */2158 }2159 2160 err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[idx][0],2161 ARRAY_SIZE(fxxxx_fan_attr[0]));2162 if (err)2163 return err;2164 2165 if (f71882fg_fan_has_beep[data->type]) {2166 err = f71882fg_create_sysfs_files(pdev,2167 &fxxxx_fan_beep_attr[idx],2168 1);2169 if (err)2170 return err;2171 }2172 2173 dev_info(&pdev->dev, "Fan: %d is in %s mode\n", idx + 1,2174 (data->pwm_enable & (1 << (2 * idx))) ? "duty-cycle" : "RPM");2175 2176 /* Check for unsupported auto pwm settings */2177 switch (data->type) {2178 case f71808e:2179 case f71808a:2180 case f71869:2181 case f71869a:2182 case f71889fg:2183 case f71889ed:2184 case f71889a:2185 data->pwm_auto_point_mapping[idx] =2186 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(idx));2187 if ((data->pwm_auto_point_mapping[idx] & 0x80) ||2188 (data->pwm_auto_point_mapping[idx] & 3) == 0) {2189 dev_warn(&pdev->dev,2190 "Auto pwm controlled by raw digital "2191 "data, disabling pwm auto_point "2192 "sysfs attributes for fan %d\n", idx + 1);2193 return 0; /* This is a non fatal condition */2194 }2195 break;2196 default:2197 break;2198 }2199 2200 switch (data->type) {2201 case f71862fg:2202 err = f71882fg_create_sysfs_files(pdev,2203 &f71862fg_auto_pwm_attr[idx][0],2204 ARRAY_SIZE(f71862fg_auto_pwm_attr[0]));2205 break;2206 case f71808e:2207 case f71869:2208 err = f71882fg_create_sysfs_files(pdev,2209 &f71869_auto_pwm_attr[idx][0],2210 ARRAY_SIZE(f71869_auto_pwm_attr[0]));2211 break;2212 case f8000:2213 err = f71882fg_create_sysfs_files(pdev,2214 &f8000_auto_pwm_attr[idx][0],2215 ARRAY_SIZE(f8000_auto_pwm_attr[0]));2216 break;2217 default:2218 err = f71882fg_create_sysfs_files(pdev,2219 &fxxxx_auto_pwm_attr[idx][0],2220 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]));2221 }2222 2223 return err;2224}2225 2226static void f71882fg_remove(struct platform_device *pdev)2227{2228 struct f71882fg_data *data = platform_get_drvdata(pdev);2229 int nr_fans = f71882fg_nr_fans[data->type];2230 int nr_temps = f71882fg_nr_temps[data->type];2231 int i;2232 u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);2233 2234 if (data->hwmon_dev)2235 hwmon_device_unregister(data->hwmon_dev);2236 2237 device_remove_file(&pdev->dev, &dev_attr_name);2238 2239 if (start_reg & 0x01) {2240 switch (data->type) {2241 case f71858fg:2242 if (data->temp_config & 0x10)2243 f71882fg_remove_sysfs_files(pdev,2244 f8000_temp_attr,2245 ARRAY_SIZE(f8000_temp_attr));2246 else2247 f71882fg_remove_sysfs_files(pdev,2248 f71858fg_temp_attr,2249 ARRAY_SIZE(f71858fg_temp_attr));2250 break;2251 case f8000:2252 f71882fg_remove_sysfs_files(pdev,2253 f8000_temp_attr,2254 ARRAY_SIZE(f8000_temp_attr));2255 break;2256 case f81866a:2257 f71882fg_remove_sysfs_files(pdev,2258 f71858fg_temp_attr,2259 ARRAY_SIZE(f71858fg_temp_attr));2260 break;2261 default:2262 f71882fg_remove_sysfs_files(pdev,2263 &fxxxx_temp_attr[0][0],2264 ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);2265 }2266 if (f71882fg_temp_has_beep[data->type]) {2267 if (data->type == f81866a)2268 f71882fg_remove_sysfs_files(pdev,2269 &f81866_temp_beep_attr[0][0],2270 ARRAY_SIZE(f81866_temp_beep_attr[0])2271 * nr_temps);2272 else2273 f71882fg_remove_sysfs_files(pdev,2274 &fxxxx_temp_beep_attr[0][0],2275 ARRAY_SIZE(fxxxx_temp_beep_attr[0])2276 * nr_temps);2277 }2278 2279 for (i = 0; i < F71882FG_MAX_INS; i++) {2280 if (f71882fg_has_in[data->type][i]) {2281 device_remove_file(&pdev->dev,2282 &fxxxx_in_attr[i].dev_attr);2283 }2284 }2285 if (f71882fg_has_in1_alarm[data->type]) {2286 f71882fg_remove_sysfs_files(pdev,2287 fxxxx_in1_alarm_attr,2288 ARRAY_SIZE(fxxxx_in1_alarm_attr));2289 }2290 }2291 2292 if (start_reg & 0x02) {2293 f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0],2294 ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);2295 2296 if (f71882fg_fan_has_beep[data->type]) {2297 f71882fg_remove_sysfs_files(pdev,2298 fxxxx_fan_beep_attr, nr_fans);2299 }2300 2301 switch (data->type) {2302 case f71808a:2303 f71882fg_remove_sysfs_files(pdev,2304 &fxxxx_auto_pwm_attr[0][0],2305 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);2306 f71882fg_remove_sysfs_files(pdev,2307 f71808a_fan3_attr,2308 ARRAY_SIZE(f71808a_fan3_attr));2309 break;2310 case f71862fg:2311 f71882fg_remove_sysfs_files(pdev,2312 &f71862fg_auto_pwm_attr[0][0],2313 ARRAY_SIZE(f71862fg_auto_pwm_attr[0]) *2314 nr_fans);2315 break;2316 case f71808e:2317 case f71869:2318 f71882fg_remove_sysfs_files(pdev,2319 &f71869_auto_pwm_attr[0][0],2320 ARRAY_SIZE(f71869_auto_pwm_attr[0]) * nr_fans);2321 break;2322 case f8000:2323 f71882fg_remove_sysfs_files(pdev,2324 f8000_fan_attr,2325 ARRAY_SIZE(f8000_fan_attr));2326 f71882fg_remove_sysfs_files(pdev,2327 &f8000_auto_pwm_attr[0][0],2328 ARRAY_SIZE(f8000_auto_pwm_attr[0]) * nr_fans);2329 break;2330 default:2331 f71882fg_remove_sysfs_files(pdev,2332 &fxxxx_auto_pwm_attr[0][0],2333 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);2334 }2335 }2336}2337 2338static int f71882fg_probe(struct platform_device *pdev)2339{2340 struct f71882fg_data *data;2341 struct f71882fg_sio_data *sio_data = dev_get_platdata(&pdev->dev);2342 int nr_fans = f71882fg_nr_fans[sio_data->type];2343 int nr_temps = f71882fg_nr_temps[sio_data->type];2344 int err, i;2345 int size;2346 u8 start_reg, reg;2347 2348 data = devm_kzalloc(&pdev->dev, sizeof(struct f71882fg_data),2349 GFP_KERNEL);2350 if (!data)2351 return -ENOMEM;2352 2353 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;2354 data->type = sio_data->type;2355 data->temp_start =2356 (data->type == f71858fg || data->type == f8000 ||2357 data->type == f81866a) ? 0 : 1;2358 mutex_init(&data->update_lock);2359 platform_set_drvdata(pdev, data);2360 2361 start_reg = f71882fg_read8(data, F71882FG_REG_START);2362 if (start_reg & 0x04) {2363 dev_warn(&pdev->dev, "Hardware monitor is powered down\n");2364 return -ENODEV;2365 }2366 if (!(start_reg & 0x03)) {2367 dev_warn(&pdev->dev, "Hardware monitoring not activated\n");2368 return -ENODEV;2369 }2370 2371 /* Register sysfs interface files */2372 err = device_create_file(&pdev->dev, &dev_attr_name);2373 if (err)2374 goto exit_unregister_sysfs;2375 2376 if (start_reg & 0x01) {2377 switch (data->type) {2378 case f71858fg:2379 data->temp_config =2380 f71882fg_read8(data, F71882FG_REG_TEMP_CONFIG);2381 if (data->temp_config & 0x10)2382 /*2383 * The f71858fg temperature alarms behave as2384 * the f8000 alarms in this mode2385 */2386 err = f71882fg_create_sysfs_files(pdev,2387 f8000_temp_attr,2388 ARRAY_SIZE(f8000_temp_attr));2389 else2390 err = f71882fg_create_sysfs_files(pdev,2391 f71858fg_temp_attr,2392 ARRAY_SIZE(f71858fg_temp_attr));2393 break;2394 case f8000:2395 err = f71882fg_create_sysfs_files(pdev,2396 f8000_temp_attr,2397 ARRAY_SIZE(f8000_temp_attr));2398 break;2399 case f81866a:2400 err = f71882fg_create_sysfs_files(pdev,2401 f71858fg_temp_attr,2402 ARRAY_SIZE(f71858fg_temp_attr));2403 break;2404 default:2405 err = f71882fg_create_sysfs_files(pdev,2406 &fxxxx_temp_attr[0][0],2407 ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);2408 }2409 if (err)2410 goto exit_unregister_sysfs;2411 2412 if (f71882fg_temp_has_beep[data->type]) {2413 if (data->type == f81866a) {2414 size = ARRAY_SIZE(f81866_temp_beep_attr[0]);2415 err = f71882fg_create_sysfs_files(pdev,2416 &f81866_temp_beep_attr[0][0],2417 size * nr_temps);2418 2419 } else {2420 size = ARRAY_SIZE(fxxxx_temp_beep_attr[0]);2421 err = f71882fg_create_sysfs_files(pdev,2422 &fxxxx_temp_beep_attr[0][0],2423 size * nr_temps);2424 }2425 if (err)2426 goto exit_unregister_sysfs;2427 }2428 2429 for (i = 0; i < F71882FG_MAX_INS; i++) {2430 if (f71882fg_has_in[data->type][i]) {2431 err = device_create_file(&pdev->dev,2432 &fxxxx_in_attr[i].dev_attr);2433 if (err)2434 goto exit_unregister_sysfs;2435 }2436 }2437 if (f71882fg_has_in1_alarm[data->type]) {2438 err = f71882fg_create_sysfs_files(pdev,2439 fxxxx_in1_alarm_attr,2440 ARRAY_SIZE(fxxxx_in1_alarm_attr));2441 if (err)2442 goto exit_unregister_sysfs;2443 }2444 }2445 2446 if (start_reg & 0x02) {2447 switch (data->type) {2448 case f71808e:2449 case f71808a:2450 case f71869:2451 case f71869a:2452 /* These always have signed auto point temps */2453 data->auto_point_temp_signed = 1;2454 fallthrough; /* to select correct fan/pwm reg bank! */2455 case f71889fg:2456 case f71889ed:2457 case f71889a:2458 reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);2459 if (reg & F71882FG_FAN_NEG_TEMP_EN)2460 data->auto_point_temp_signed = 1;2461 /* Ensure banked pwm registers point to right bank */2462 reg &= ~F71882FG_FAN_PROG_SEL;2463 f71882fg_write8(data, F71882FG_REG_FAN_FAULT_T, reg);2464 break;2465 default:2466 break;2467 }2468 2469 data->pwm_enable =2470 f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);2471 2472 for (i = 0; i < nr_fans; i++) {2473 err = f71882fg_create_fan_sysfs_files(pdev, i);2474 if (err)2475 goto exit_unregister_sysfs;2476 }2477 2478 /* Some types have 1 extra fan with limited functionality */2479 switch (data->type) {2480 case f71808a:2481 err = f71882fg_create_sysfs_files(pdev,2482 f71808a_fan3_attr,2483 ARRAY_SIZE(f71808a_fan3_attr));2484 break;2485 case f8000:2486 err = f71882fg_create_sysfs_files(pdev,2487 f8000_fan_attr,2488 ARRAY_SIZE(f8000_fan_attr));2489 break;2490 default:2491 break;2492 }2493 if (err)2494 goto exit_unregister_sysfs;2495 }2496 2497 data->hwmon_dev = hwmon_device_register(&pdev->dev);2498 if (IS_ERR(data->hwmon_dev)) {2499 err = PTR_ERR(data->hwmon_dev);2500 data->hwmon_dev = NULL;2501 goto exit_unregister_sysfs;2502 }2503 2504 return 0;2505 2506exit_unregister_sysfs:2507 f71882fg_remove(pdev); /* Will unregister the sysfs files for us */2508 return err; /* f71882fg_remove() also frees our data */2509}2510 2511static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)2512{2513 u16 devid;2514 unsigned short address;2515 int err = superio_enter(sioaddr);2516 if (err)2517 return err;2518 2519 devid = superio_inw(sioaddr, SIO_REG_MANID);2520 if (devid != SIO_FINTEK_ID) {2521 pr_debug("Not a Fintek device\n");2522 err = -ENODEV;2523 goto exit;2524 }2525 2526 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);2527 switch (devid) {2528 case SIO_F71808E_ID:2529 sio_data->type = f71808e;2530 break;2531 case SIO_F71808A_ID:2532 sio_data->type = f71808a;2533 break;2534 case SIO_F71858_ID:2535 case SIO_F71858AD_ID:2536 sio_data->type = f71858fg;2537 break;2538 case SIO_F71862_ID:2539 sio_data->type = f71862fg;2540 break;2541 case SIO_F71868_ID:2542 sio_data->type = f71868a;2543 break;2544 case SIO_F71869_ID:2545 sio_data->type = f71869;2546 break;2547 case SIO_F71869A_ID:2548 sio_data->type = f71869a;2549 break;2550 case SIO_F71882_ID:2551 sio_data->type = f71882fg;2552 break;2553 case SIO_F71889_ID:2554 sio_data->type = f71889fg;2555 break;2556 case SIO_F71889E_ID:2557 sio_data->type = f71889ed;2558 break;2559 case SIO_F71889A_ID:2560 sio_data->type = f71889a;2561 break;2562 case SIO_F8000_ID:2563 sio_data->type = f8000;2564 break;2565 case SIO_F81768D_ID:2566 sio_data->type = f81768d;2567 break;2568 case SIO_F81865_ID:2569 sio_data->type = f81865f;2570 break;2571 case SIO_F81866_ID:2572 case SIO_F81966_ID:2573 sio_data->type = f81866a;2574 break;2575 default:2576 pr_info("Unsupported Fintek device: %04x\n",2577 (unsigned int)devid);2578 err = -ENODEV;2579 goto exit;2580 }2581 2582 if (sio_data->type == f71858fg)2583 superio_select(sioaddr, SIO_F71858FG_LD_HWM);2584 else2585 superio_select(sioaddr, SIO_F71882FG_LD_HWM);2586 2587 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {2588 pr_warn("Device not activated\n");2589 err = -ENODEV;2590 goto exit;2591 }2592 2593 address = superio_inw(sioaddr, SIO_REG_ADDR);2594 if (address == 0) {2595 pr_warn("Base address not set\n");2596 err = -ENODEV;2597 goto exit;2598 }2599 address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */2600 2601 err = address;2602 pr_info("Found %s chip at %#x, revision %d\n",2603 f71882fg_names[sio_data->type], (unsigned int)address,2604 (int)superio_inb(sioaddr, SIO_REG_DEVREV));2605exit:2606 superio_exit(sioaddr);2607 return err;2608}2609 2610static int __init f71882fg_device_add(int address,2611 const struct f71882fg_sio_data *sio_data)2612{2613 struct resource res = {2614 .start = address,2615 .end = address + REGION_LENGTH - 1,2616 .flags = IORESOURCE_IO,2617 };2618 int err;2619 2620 f71882fg_pdev = platform_device_alloc(DRVNAME, address);2621 if (!f71882fg_pdev)2622 return -ENOMEM;2623 2624 res.name = f71882fg_pdev->name;2625 err = acpi_check_resource_conflict(&res);2626 if (err)2627 goto exit_device_put;2628 2629 err = platform_device_add_resources(f71882fg_pdev, &res, 1);2630 if (err) {2631 pr_err("Device resource addition failed\n");2632 goto exit_device_put;2633 }2634 2635 err = platform_device_add_data(f71882fg_pdev, sio_data,2636 sizeof(struct f71882fg_sio_data));2637 if (err) {2638 pr_err("Platform data allocation failed\n");2639 goto exit_device_put;2640 }2641 2642 err = platform_device_add(f71882fg_pdev);2643 if (err) {2644 pr_err("Device addition failed\n");2645 goto exit_device_put;2646 }2647 2648 return 0;2649 2650exit_device_put:2651 platform_device_put(f71882fg_pdev);2652 2653 return err;2654}2655 2656static struct platform_driver f71882fg_driver = {2657 .driver = {2658 .name = DRVNAME,2659 },2660 .probe = f71882fg_probe,2661 .remove_new = f71882fg_remove,2662};2663 2664static int __init f71882fg_init(void)2665{2666 int err;2667 int address;2668 struct f71882fg_sio_data sio_data;2669 2670 memset(&sio_data, 0, sizeof(sio_data));2671 2672 address = f71882fg_find(0x2e, &sio_data);2673 if (address < 0)2674 address = f71882fg_find(0x4e, &sio_data);2675 if (address < 0)2676 return address;2677 2678 err = platform_driver_register(&f71882fg_driver);2679 if (err)2680 return err;2681 2682 err = f71882fg_device_add(address, &sio_data);2683 if (err)2684 goto exit_driver;2685 2686 return 0;2687 2688exit_driver:2689 platform_driver_unregister(&f71882fg_driver);2690 return err;2691}2692 2693static void __exit f71882fg_exit(void)2694{2695 platform_device_unregister(f71882fg_pdev);2696 platform_driver_unregister(&f71882fg_driver);2697}2698 2699MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");2700MODULE_AUTHOR("Hans Edgington, Hans de Goede <hdegoede@redhat.com>");2701MODULE_LICENSE("GPL");2702 2703module_init(f71882fg_init);2704module_exit(f71882fg_exit);2705