linux/drivers/hwmon/via686a.c
<<
>>
Prefs
   1/*
   2    via686a.c - Part of lm_sensors, Linux kernel modules
   3                for hardware monitoring
   4
   5    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
   6                        Kyösti Mälkki <kmalkki@cc.hut.fi>,
   7                        Mark Studebaker <mdsxyz123@yahoo.com>,
   8                        and Bob Dougherty <bobd@stanford.edu>
   9    (Some conversion-factor data were contributed by Jonathan Teh Soon Yew
  10    <j.teh@iname.com> and Alex van Kaam <darkside@chello.nl>.)
  11
  12    This program is free software; you can redistribute it and/or modify
  13    it under the terms of the GNU General Public License as published by
  14    the Free Software Foundation; either version 2 of the License, or
  15    (at your option) any later version.
  16
  17    This program is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21
  22    You should have received a copy of the GNU General Public License
  23    along with this program; if not, write to the Free Software
  24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25*/
  26
  27/*
  28    Supports the Via VT82C686A, VT82C686B south bridges.
  29    Reports all as a 686A.
  30    Warning - only supports a single device.
  31*/
  32
  33#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  34
  35#include <linux/module.h>
  36#include <linux/slab.h>
  37#include <linux/pci.h>
  38#include <linux/jiffies.h>
  39#include <linux/platform_device.h>
  40#include <linux/hwmon.h>
  41#include <linux/hwmon-sysfs.h>
  42#include <linux/err.h>
  43#include <linux/init.h>
  44#include <linux/mutex.h>
  45#include <linux/sysfs.h>
  46#include <linux/acpi.h>
  47#include <linux/io.h>
  48
  49
  50/* If force_addr is set to anything different from 0, we forcibly enable
  51   the device at the given address. */
  52static unsigned short force_addr;
  53module_param(force_addr, ushort, 0);
  54MODULE_PARM_DESC(force_addr,
  55                 "Initialize the base address of the sensors");
  56
  57static struct platform_device *pdev;
  58
  59/*
  60   The Via 686a southbridge has a LM78-like chip integrated on the same IC.
  61   This driver is a customized copy of lm78.c
  62*/
  63
  64/* Many VIA686A constants specified below */
  65
  66/* Length of ISA address segment */
  67#define VIA686A_EXTENT          0x80
  68#define VIA686A_BASE_REG        0x70
  69#define VIA686A_ENABLE_REG      0x74
  70
  71/* The VIA686A registers */
  72/* ins numbered 0-4 */
  73#define VIA686A_REG_IN_MAX(nr)  (0x2b + ((nr) * 2))
  74#define VIA686A_REG_IN_MIN(nr)  (0x2c + ((nr) * 2))
  75#define VIA686A_REG_IN(nr)      (0x22 + (nr))
  76
  77/* fans numbered 1-2 */
  78#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
  79#define VIA686A_REG_FAN(nr)     (0x28 + (nr))
  80
  81/* temps numbered 1-3 */
  82static const u8 VIA686A_REG_TEMP[]      = { 0x20, 0x21, 0x1f };
  83static const u8 VIA686A_REG_TEMP_OVER[] = { 0x39, 0x3d, 0x1d };
  84static const u8 VIA686A_REG_TEMP_HYST[] = { 0x3a, 0x3e, 0x1e };
  85/* bits 7-6 */
  86#define VIA686A_REG_TEMP_LOW1   0x4b
  87/* 2 = bits 5-4, 3 = bits 7-6 */
  88#define VIA686A_REG_TEMP_LOW23  0x49
  89
  90#define VIA686A_REG_ALARM1      0x41
  91#define VIA686A_REG_ALARM2      0x42
  92#define VIA686A_REG_FANDIV      0x47
  93#define VIA686A_REG_CONFIG      0x40
  94/* The following register sets temp interrupt mode (bits 1-0 for temp1,
  95 3-2 for temp2, 5-4 for temp3).  Modes are:
  96    00 interrupt stays as long as value is out-of-range
  97    01 interrupt is cleared once register is read (default)
  98    10 comparator mode- like 00, but ignores hysteresis
  99    11 same as 00 */
 100#define VIA686A_REG_TEMP_MODE           0x4b
 101/* We'll just assume that you want to set all 3 simultaneously: */
 102#define VIA686A_TEMP_MODE_MASK          0x3F
 103#define VIA686A_TEMP_MODE_CONTINUOUS    0x00
 104
 105/* Conversions. Limit checking is only done on the TO_REG
 106   variants.
 107
 108********* VOLTAGE CONVERSIONS (Bob Dougherty) ********
 109 From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
 110 voltagefactor[0]=1.25/2628; (2628/1.25=2102.4)   // Vccp
 111 voltagefactor[1]=1.25/2628; (2628/1.25=2102.4)   // +2.5V
 112 voltagefactor[2]=1.67/2628; (2628/1.67=1573.7)   // +3.3V
 113 voltagefactor[3]=2.6/2628;  (2628/2.60=1010.8)   // +5V
 114 voltagefactor[4]=6.3/2628;  (2628/6.30=417.14)   // +12V
 115 in[i]=(data[i+2]*25.0+133)*voltagefactor[i];
 116 That is:
 117 volts = (25*regVal+133)*factor
 118 regVal = (volts/factor-133)/25
 119 (These conversions were contributed by Jonathan Teh Soon Yew
 120 <j.teh@iname.com>) */
 121static inline u8 IN_TO_REG(long val, int inNum)
 122{
 123        /* To avoid floating point, we multiply constants by 10 (100 for +12V).
 124           Rounding is done (120500 is actually 133000 - 12500).
 125           Remember that val is expressed in 0.001V/bit, which is why we divide
 126           by an additional 10000 (100000 for +12V): 1000 for val and 10 (100)
 127           for the constants. */
 128        if (inNum <= 1)
 129                return (u8)
 130                    SENSORS_LIMIT((val * 21024 - 1205000) / 250000, 0, 255);
 131        else if (inNum == 2)
 132                return (u8)
 133                    SENSORS_LIMIT((val * 15737 - 1205000) / 250000, 0, 255);
 134        else if (inNum == 3)
 135                return (u8)
 136                    SENSORS_LIMIT((val * 10108 - 1205000) / 250000, 0, 255);
 137        else
 138                return (u8)
 139                    SENSORS_LIMIT((val * 41714 - 12050000) / 2500000, 0, 255);
 140}
 141
 142static inline long IN_FROM_REG(u8 val, int inNum)
 143{
 144        /* To avoid floating point, we multiply constants by 10 (100 for +12V).
 145           We also multiply them by 1000 because we want 0.001V/bit for the
 146           output value. Rounding is done. */
 147        if (inNum <= 1)
 148                return (long) ((250000 * val + 1330000 + 21024 / 2) / 21024);
 149        else if (inNum == 2)
 150                return (long) ((250000 * val + 1330000 + 15737 / 2) / 15737);
 151        else if (inNum == 3)
 152                return (long) ((250000 * val + 1330000 + 10108 / 2) / 10108);
 153        else
 154                return (long) ((2500000 * val + 13300000 + 41714 / 2) / 41714);
 155}
 156
 157/********* FAN RPM CONVERSIONS ********/
 158/* Higher register values = slower fans (the fan's strobe gates a counter).
 159 But this chip saturates back at 0, not at 255 like all the other chips.
 160 So, 0 means 0 RPM */
 161static inline u8 FAN_TO_REG(long rpm, int div)
 162{
 163        if (rpm == 0)
 164                return 0;
 165        rpm = SENSORS_LIMIT(rpm, 1, 1000000);
 166        return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
 167}
 168
 169#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1350000/((val)*(div)))
 170
 171/******** TEMP CONVERSIONS (Bob Dougherty) *********/
 172/* linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
 173      if(temp<169)
 174              return double(temp)*0.427-32.08;
 175      else if(temp>=169 && temp<=202)
 176              return double(temp)*0.582-58.16;
 177      else
 178              return double(temp)*0.924-127.33;
 179
 180 A fifth-order polynomial fits the unofficial data (provided by Alex van
 181 Kaam <darkside@chello.nl>) a bit better.  It also give more reasonable
 182 numbers on my machine (ie. they agree with what my BIOS tells me).
 183 Here's the fifth-order fit to the 8-bit data:
 184 temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
 185        2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
 186
 187 (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
 188 finding my typos in this formula!)
 189
 190 Alas, none of the elegant function-fit solutions will work because we
 191 aren't allowed to use floating point in the kernel and doing it with
 192 integers doesn't provide enough precision.  So we'll do boring old
 193 look-up table stuff.  The unofficial data (see below) have effectively
 194 7-bit resolution (they are rounded to the nearest degree).  I'm assuming
 195 that the transfer function of the device is monotonic and smooth, so a
 196 smooth function fit to the data will allow us to get better precision.
 197 I used the 5th-order poly fit described above and solved for
 198 VIA register values 0-255.  I *10 before rounding, so we get tenth-degree
 199 precision.  (I could have done all 1024 values for our 10-bit readings,
 200 but the function is very linear in the useful range (0-80 deg C), so
 201 we'll just use linear interpolation for 10-bit readings.)  So, tempLUT
 202 is the temp at via register values 0-255: */
 203static const s16 tempLUT[] =
 204{ -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
 205        -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
 206        -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
 207        -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
 208        -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
 209        -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
 210        -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
 211        20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
 212        88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
 213        142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
 214        193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
 215        245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
 216        299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
 217        353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
 218        409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
 219        469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
 220        538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
 221        621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
 222        728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
 223        870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
 224        1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
 225        1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
 226};
 227
 228/* the original LUT values from Alex van Kaam <darkside@chello.nl>
 229   (for via register values 12-240):
 230{-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
 231-30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
 232-15,-14,-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,
 233-3,-2,-2,-1,-1,0,0,1,1,1,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,9,10,10,11,11,12,
 23412,12,13,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,21,21,21,22,22,
 23522,23,23,24,24,25,25,26,26,26,27,27,27,28,28,29,29,30,30,30,31,31,32,32,33,
 23633,34,34,35,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,
 23745,46,46,47,48,48,49,49,50,51,51,52,52,53,53,54,55,55,56,57,57,58,59,59,60,
 23861,62,62,63,64,65,66,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,83,84,
 23985,86,88,89,91,92,94,96,97,99,101,103,105,107,109,110};
 240
 241
 242 Here's the reverse LUT.  I got it by doing a 6-th order poly fit (needed
 243 an extra term for a good fit to these inverse data!) and then
 244 solving for each temp value from -50 to 110 (the useable range for
 245 this chip).  Here's the fit:
 246 viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
 247 - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
 248 Note that n=161: */
 249static const u8 viaLUT[] =
 250{ 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
 251        23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
 252        41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
 253        69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
 254        103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
 255        131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
 256        158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
 257        182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
 258        200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
 259        214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
 260        225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
 261        233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
 262        239, 240
 263};
 264
 265/* Converting temps to (8-bit) hyst and over registers
 266   No interpolation here.
 267   The +50 is because the temps start at -50 */
 268static inline u8 TEMP_TO_REG(long val)
 269{
 270        return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 :
 271                      (val < 0 ? val - 500 : val + 500) / 1000 + 50];
 272}
 273
 274/* for 8-bit temperature hyst and over registers */
 275#define TEMP_FROM_REG(val)      ((long)tempLUT[val] * 100)
 276
 277/* for 10-bit temperature readings */
 278static inline long TEMP_FROM_REG10(u16 val)
 279{
 280        u16 eightBits = val >> 2;
 281        u16 twoBits = val & 3;
 282
 283        /* no interpolation for these */
 284        if (twoBits == 0 || eightBits == 255)
 285                return TEMP_FROM_REG(eightBits);
 286
 287        /* do some linear interpolation */
 288        return (tempLUT[eightBits] * (4 - twoBits) +
 289                tempLUT[eightBits + 1] * twoBits) * 25;
 290}
 291
 292#define DIV_FROM_REG(val) (1 << (val))
 293#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
 294
 295/* For each registered chip, we need to keep some data in memory.
 296   The structure is dynamically allocated. */
 297struct via686a_data {
 298        unsigned short addr;
 299        const char *name;
 300        struct device *hwmon_dev;
 301        struct mutex update_lock;
 302        char valid;             /* !=0 if following fields are valid */
 303        unsigned long last_updated;     /* In jiffies */
 304
 305        u8 in[5];               /* Register value */
 306        u8 in_max[5];           /* Register value */
 307        u8 in_min[5];           /* Register value */
 308        u8 fan[2];              /* Register value */
 309        u8 fan_min[2];          /* Register value */
 310        u16 temp[3];            /* Register value 10 bit */
 311        u8 temp_over[3];        /* Register value */
 312        u8 temp_hyst[3];        /* Register value */
 313        u8 fan_div[2];          /* Register encoding, shifted right */
 314        u16 alarms;             /* Register encoding, combined */
 315};
 316
 317static struct pci_dev *s_bridge;        /* pointer to the (only) via686a */
 318
 319static int via686a_probe(struct platform_device *pdev);
 320static int __devexit via686a_remove(struct platform_device *pdev);
 321
 322static inline int via686a_read_value(struct via686a_data *data, u8 reg)
 323{
 324        return inb_p(data->addr + reg);
 325}
 326
 327static inline void via686a_write_value(struct via686a_data *data, u8 reg,
 328                                       u8 value)
 329{
 330        outb_p(value, data->addr + reg);
 331}
 332
 333static struct via686a_data *via686a_update_device(struct device *dev);
 334static void via686a_init_device(struct via686a_data *data);
 335
 336/* following are the sysfs callback functions */
 337
 338/* 7 voltage sensors */
 339static ssize_t show_in(struct device *dev, struct device_attribute *da,
 340                char *buf) {
 341        struct via686a_data *data = via686a_update_device(dev);
 342        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 343        int nr = attr->index;
 344        return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr));
 345}
 346
 347static ssize_t show_in_min(struct device *dev, struct device_attribute *da,
 348                char *buf) {
 349        struct via686a_data *data = via686a_update_device(dev);
 350        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 351        int nr = attr->index;
 352        return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr));
 353}
 354
 355static ssize_t show_in_max(struct device *dev, struct device_attribute *da,
 356                char *buf) {
 357        struct via686a_data *data = via686a_update_device(dev);
 358        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 359        int nr = attr->index;
 360        return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr));
 361}
 362
 363static ssize_t set_in_min(struct device *dev, struct device_attribute *da,
 364                const char *buf, size_t count) {
 365        struct via686a_data *data = dev_get_drvdata(dev);
 366        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 367        int nr = attr->index;
 368        unsigned long val = simple_strtoul(buf, NULL, 10);
 369
 370        mutex_lock(&data->update_lock);
 371        data->in_min[nr] = IN_TO_REG(val, nr);
 372        via686a_write_value(data, VIA686A_REG_IN_MIN(nr),
 373                        data->in_min[nr]);
 374        mutex_unlock(&data->update_lock);
 375        return count;
 376}
 377static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
 378                const char *buf, size_t count) {
 379        struct via686a_data *data = dev_get_drvdata(dev);
 380        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 381        int nr = attr->index;
 382        unsigned long val = simple_strtoul(buf, NULL, 10);
 383
 384        mutex_lock(&data->update_lock);
 385        data->in_max[nr] = IN_TO_REG(val, nr);
 386        via686a_write_value(data, VIA686A_REG_IN_MAX(nr),
 387                        data->in_max[nr]);
 388        mutex_unlock(&data->update_lock);
 389        return count;
 390}
 391#define show_in_offset(offset)                                  \
 392static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,          \
 393                show_in, NULL, offset);                         \
 394static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,  \
 395                show_in_min, set_in_min, offset);               \
 396static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,  \
 397                show_in_max, set_in_max, offset);
 398
 399show_in_offset(0);
 400show_in_offset(1);
 401show_in_offset(2);
 402show_in_offset(3);
 403show_in_offset(4);
 404
 405/* 3 temperatures */
 406static ssize_t show_temp(struct device *dev, struct device_attribute *da,
 407                char *buf) {
 408        struct via686a_data *data = via686a_update_device(dev);
 409        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 410        int nr = attr->index;
 411        return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr]));
 412}
 413static ssize_t show_temp_over(struct device *dev, struct device_attribute *da,
 414                char *buf) {
 415        struct via686a_data *data = via686a_update_device(dev);
 416        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 417        int nr = attr->index;
 418        return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr]));
 419}
 420static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da,
 421                char *buf) {
 422        struct via686a_data *data = via686a_update_device(dev);
 423        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 424        int nr = attr->index;
 425        return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr]));
 426}
 427static ssize_t set_temp_over(struct device *dev, struct device_attribute *da,
 428                const char *buf, size_t count) {
 429        struct via686a_data *data = dev_get_drvdata(dev);
 430        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 431        int nr = attr->index;
 432        int val = simple_strtol(buf, NULL, 10);
 433
 434        mutex_lock(&data->update_lock);
 435        data->temp_over[nr] = TEMP_TO_REG(val);
 436        via686a_write_value(data, VIA686A_REG_TEMP_OVER[nr],
 437                            data->temp_over[nr]);
 438        mutex_unlock(&data->update_lock);
 439        return count;
 440}
 441static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da,
 442                const char *buf, size_t count) {
 443        struct via686a_data *data = dev_get_drvdata(dev);
 444        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 445        int nr = attr->index;
 446        int val = simple_strtol(buf, NULL, 10);
 447
 448        mutex_lock(&data->update_lock);
 449        data->temp_hyst[nr] = TEMP_TO_REG(val);
 450        via686a_write_value(data, VIA686A_REG_TEMP_HYST[nr],
 451                            data->temp_hyst[nr]);
 452        mutex_unlock(&data->update_lock);
 453        return count;
 454}
 455#define show_temp_offset(offset)                                        \
 456static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,                \
 457                show_temp, NULL, offset - 1);                           \
 458static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,        \
 459                show_temp_over, set_temp_over, offset - 1);             \
 460static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR,   \
 461                show_temp_hyst, set_temp_hyst, offset - 1);
 462
 463show_temp_offset(1);
 464show_temp_offset(2);
 465show_temp_offset(3);
 466
 467/* 2 Fans */
 468static ssize_t show_fan(struct device *dev, struct device_attribute *da,
 469                char *buf) {
 470        struct via686a_data *data = via686a_update_device(dev);
 471        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 472        int nr = attr->index;
 473        return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
 474                                DIV_FROM_REG(data->fan_div[nr])) );
 475}
 476static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
 477                char *buf) {
 478        struct via686a_data *data = via686a_update_device(dev);
 479        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 480        int nr = attr->index;
 481        return sprintf(buf, "%d\n",
 482                FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
 483}
 484static ssize_t show_fan_div(struct device *dev, struct device_attribute *da,
 485                char *buf) {
 486        struct via686a_data *data = via686a_update_device(dev);
 487        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 488        int nr = attr->index;
 489        return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
 490}
 491static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
 492                const char *buf, size_t count) {
 493        struct via686a_data *data = dev_get_drvdata(dev);
 494        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 495        int nr = attr->index;
 496        int val = simple_strtol(buf, NULL, 10);
 497
 498        mutex_lock(&data->update_lock);
 499        data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
 500        via686a_write_value(data, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]);
 501        mutex_unlock(&data->update_lock);
 502        return count;
 503}
 504static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
 505                const char *buf, size_t count) {
 506        struct via686a_data *data = dev_get_drvdata(dev);
 507        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 508        int nr = attr->index;
 509        int val = simple_strtol(buf, NULL, 10);
 510        int old;
 511
 512        mutex_lock(&data->update_lock);
 513        old = via686a_read_value(data, VIA686A_REG_FANDIV);
 514        data->fan_div[nr] = DIV_TO_REG(val);
 515        old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
 516        via686a_write_value(data, VIA686A_REG_FANDIV, old);
 517        mutex_unlock(&data->update_lock);
 518        return count;
 519}
 520
 521#define show_fan_offset(offset)                                         \
 522static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,                 \
 523                show_fan, NULL, offset - 1);                            \
 524static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,         \
 525                show_fan_min, set_fan_min, offset - 1);                 \
 526static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,         \
 527                show_fan_div, set_fan_div, offset - 1);
 528
 529show_fan_offset(1);
 530show_fan_offset(2);
 531
 532/* Alarms */
 533static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) {
 534        struct via686a_data *data = via686a_update_device(dev);
 535        return sprintf(buf, "%u\n", data->alarms);
 536}
 537static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 538
 539static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
 540                          char *buf)
 541{
 542        int bitnr = to_sensor_dev_attr(attr)->index;
 543        struct via686a_data *data = via686a_update_device(dev);
 544        return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
 545}
 546static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
 547static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
 548static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
 549static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
 550static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
 551static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
 552static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 11);
 553static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 15);
 554static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
 555static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
 556
 557static ssize_t show_name(struct device *dev, struct device_attribute
 558                         *devattr, char *buf)
 559{
 560        struct via686a_data *data = dev_get_drvdata(dev);
 561        return sprintf(buf, "%s\n", data->name);
 562}
 563static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 564
 565static struct attribute *via686a_attributes[] = {
 566        &sensor_dev_attr_in0_input.dev_attr.attr,
 567        &sensor_dev_attr_in1_input.dev_attr.attr,
 568        &sensor_dev_attr_in2_input.dev_attr.attr,
 569        &sensor_dev_attr_in3_input.dev_attr.attr,
 570        &sensor_dev_attr_in4_input.dev_attr.attr,
 571        &sensor_dev_attr_in0_min.dev_attr.attr,
 572        &sensor_dev_attr_in1_min.dev_attr.attr,
 573        &sensor_dev_attr_in2_min.dev_attr.attr,
 574        &sensor_dev_attr_in3_min.dev_attr.attr,
 575        &sensor_dev_attr_in4_min.dev_attr.attr,
 576        &sensor_dev_attr_in0_max.dev_attr.attr,
 577        &sensor_dev_attr_in1_max.dev_attr.attr,
 578        &sensor_dev_attr_in2_max.dev_attr.attr,
 579        &sensor_dev_attr_in3_max.dev_attr.attr,
 580        &sensor_dev_attr_in4_max.dev_attr.attr,
 581        &sensor_dev_attr_in0_alarm.dev_attr.attr,
 582        &sensor_dev_attr_in1_alarm.dev_attr.attr,
 583        &sensor_dev_attr_in2_alarm.dev_attr.attr,
 584        &sensor_dev_attr_in3_alarm.dev_attr.attr,
 585        &sensor_dev_attr_in4_alarm.dev_attr.attr,
 586
 587        &sensor_dev_attr_temp1_input.dev_attr.attr,
 588        &sensor_dev_attr_temp2_input.dev_attr.attr,
 589        &sensor_dev_attr_temp3_input.dev_attr.attr,
 590        &sensor_dev_attr_temp1_max.dev_attr.attr,
 591        &sensor_dev_attr_temp2_max.dev_attr.attr,
 592        &sensor_dev_attr_temp3_max.dev_attr.attr,
 593        &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 594        &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
 595        &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
 596        &sensor_dev_attr_temp1_alarm.dev_attr.attr,
 597        &sensor_dev_attr_temp2_alarm.dev_attr.attr,
 598        &sensor_dev_attr_temp3_alarm.dev_attr.attr,
 599
 600        &sensor_dev_attr_fan1_input.dev_attr.attr,
 601        &sensor_dev_attr_fan2_input.dev_attr.attr,
 602        &sensor_dev_attr_fan1_min.dev_attr.attr,
 603        &sensor_dev_attr_fan2_min.dev_attr.attr,
 604        &sensor_dev_attr_fan1_div.dev_attr.attr,
 605        &sensor_dev_attr_fan2_div.dev_attr.attr,
 606        &sensor_dev_attr_fan1_alarm.dev_attr.attr,
 607        &sensor_dev_attr_fan2_alarm.dev_attr.attr,
 608
 609        &dev_attr_alarms.attr,
 610        &dev_attr_name.attr,
 611        NULL
 612};
 613
 614static const struct attribute_group via686a_group = {
 615        .attrs = via686a_attributes,
 616};
 617
 618static struct platform_driver via686a_driver = {
 619        .driver = {
 620                .owner  = THIS_MODULE,
 621                .name   = "via686a",
 622        },
 623        .probe          = via686a_probe,
 624        .remove         = __devexit_p(via686a_remove),
 625};
 626
 627
 628/* This is called when the module is loaded */
 629static int __devinit via686a_probe(struct platform_device *pdev)
 630{
 631        struct via686a_data *data;
 632        struct resource *res;
 633        int err;
 634
 635        /* Reserve the ISA region */
 636        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 637        if (!request_region(res->start, VIA686A_EXTENT,
 638                            via686a_driver.driver.name)) {
 639                dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n",
 640                        (unsigned long)res->start, (unsigned long)res->end);
 641                return -ENODEV;
 642        }
 643
 644        if (!(data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
 645                err = -ENOMEM;
 646                goto exit_release;
 647        }
 648
 649        platform_set_drvdata(pdev, data);
 650        data->addr = res->start;
 651        data->name = "via686a";
 652        mutex_init(&data->update_lock);
 653
 654        /* Initialize the VIA686A chip */
 655        via686a_init_device(data);
 656
 657        /* Register sysfs hooks */
 658        if ((err = sysfs_create_group(&pdev->dev.kobj, &via686a_group)))
 659                goto exit_free;
 660
 661        data->hwmon_dev = hwmon_device_register(&pdev->dev);
 662        if (IS_ERR(data->hwmon_dev)) {
 663                err = PTR_ERR(data->hwmon_dev);
 664                goto exit_remove_files;
 665        }
 666
 667        return 0;
 668
 669exit_remove_files:
 670        sysfs_remove_group(&pdev->dev.kobj, &via686a_group);
 671exit_free:
 672        kfree(data);
 673exit_release:
 674        release_region(res->start, VIA686A_EXTENT);
 675        return err;
 676}
 677
 678static int __devexit via686a_remove(struct platform_device *pdev)
 679{
 680        struct via686a_data *data = platform_get_drvdata(pdev);
 681
 682        hwmon_device_unregister(data->hwmon_dev);
 683        sysfs_remove_group(&pdev->dev.kobj, &via686a_group);
 684
 685        release_region(data->addr, VIA686A_EXTENT);
 686        platform_set_drvdata(pdev, NULL);
 687        kfree(data);
 688
 689        return 0;
 690}
 691
 692static void via686a_update_fan_div(struct via686a_data *data)
 693{
 694        int reg = via686a_read_value(data, VIA686A_REG_FANDIV);
 695        data->fan_div[0] = (reg >> 4) & 0x03;
 696        data->fan_div[1] = reg >> 6;
 697}
 698
 699static void __devinit via686a_init_device(struct via686a_data *data)
 700{
 701        u8 reg;
 702
 703        /* Start monitoring */
 704        reg = via686a_read_value(data, VIA686A_REG_CONFIG);
 705        via686a_write_value(data, VIA686A_REG_CONFIG, (reg | 0x01) & 0x7F);
 706
 707        /* Configure temp interrupt mode for continuous-interrupt operation */
 708        reg = via686a_read_value(data, VIA686A_REG_TEMP_MODE);
 709        via686a_write_value(data, VIA686A_REG_TEMP_MODE,
 710                            (reg & ~VIA686A_TEMP_MODE_MASK)
 711                            | VIA686A_TEMP_MODE_CONTINUOUS);
 712
 713        /* Pre-read fan clock divisor values */
 714        via686a_update_fan_div(data);
 715}
 716
 717static struct via686a_data *via686a_update_device(struct device *dev)
 718{
 719        struct via686a_data *data = dev_get_drvdata(dev);
 720        int i;
 721
 722        mutex_lock(&data->update_lock);
 723
 724        if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
 725            || !data->valid) {
 726                for (i = 0; i <= 4; i++) {
 727                        data->in[i] =
 728                            via686a_read_value(data, VIA686A_REG_IN(i));
 729                        data->in_min[i] = via686a_read_value(data,
 730                                                             VIA686A_REG_IN_MIN
 731                                                             (i));
 732                        data->in_max[i] =
 733                            via686a_read_value(data, VIA686A_REG_IN_MAX(i));
 734                }
 735                for (i = 1; i <= 2; i++) {
 736                        data->fan[i - 1] =
 737                            via686a_read_value(data, VIA686A_REG_FAN(i));
 738                        data->fan_min[i - 1] = via686a_read_value(data,
 739                                                     VIA686A_REG_FAN_MIN(i));
 740                }
 741                for (i = 0; i <= 2; i++) {
 742                        data->temp[i] = via686a_read_value(data,
 743                                                 VIA686A_REG_TEMP[i]) << 2;
 744                        data->temp_over[i] =
 745                            via686a_read_value(data,
 746                                               VIA686A_REG_TEMP_OVER[i]);
 747                        data->temp_hyst[i] =
 748                            via686a_read_value(data,
 749                                               VIA686A_REG_TEMP_HYST[i]);
 750                }
 751                /* add in lower 2 bits
 752                   temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
 753                   temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
 754                   temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
 755                 */
 756                data->temp[0] |= (via686a_read_value(data,
 757                                                     VIA686A_REG_TEMP_LOW1)
 758                                  & 0xc0) >> 6;
 759                data->temp[1] |=
 760                    (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
 761                     0x30) >> 4;
 762                data->temp[2] |=
 763                    (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
 764                     0xc0) >> 6;
 765
 766                via686a_update_fan_div(data);
 767                data->alarms =
 768                    via686a_read_value(data,
 769                                       VIA686A_REG_ALARM1) |
 770                    (via686a_read_value(data, VIA686A_REG_ALARM2) << 8);
 771                data->last_updated = jiffies;
 772                data->valid = 1;
 773        }
 774
 775        mutex_unlock(&data->update_lock);
 776
 777        return data;
 778}
 779
 780static const struct pci_device_id via686a_pci_ids[] = {
 781        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
 782        { 0, }
 783};
 784
 785MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
 786
 787static int __devinit via686a_device_add(unsigned short address)
 788{
 789        struct resource res = {
 790                .start  = address,
 791                .end    = address + VIA686A_EXTENT - 1,
 792                .name   = "via686a",
 793                .flags  = IORESOURCE_IO,
 794        };
 795        int err;
 796
 797        err = acpi_check_resource_conflict(&res);
 798        if (err)
 799                goto exit;
 800
 801        pdev = platform_device_alloc("via686a", address);
 802        if (!pdev) {
 803                err = -ENOMEM;
 804                pr_err("Device allocation failed\n");
 805                goto exit;
 806        }
 807
 808        err = platform_device_add_resources(pdev, &res, 1);
 809        if (err) {
 810                pr_err("Device resource addition failed (%d)\n", err);
 811                goto exit_device_put;
 812        }
 813
 814        err = platform_device_add(pdev);
 815        if (err) {
 816                pr_err("Device addition failed (%d)\n", err);
 817                goto exit_device_put;
 818        }
 819
 820        return 0;
 821
 822exit_device_put:
 823        platform_device_put(pdev);
 824exit:
 825        return err;
 826}
 827
 828static int __devinit via686a_pci_probe(struct pci_dev *dev,
 829                                       const struct pci_device_id *id)
 830{
 831        u16 address, val;
 832
 833        if (force_addr) {
 834                address = force_addr & ~(VIA686A_EXTENT - 1);
 835                dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address);
 836                if (PCIBIOS_SUCCESSFUL !=
 837                    pci_write_config_word(dev, VIA686A_BASE_REG, address | 1))
 838                        return -ENODEV;
 839        }
 840        if (PCIBIOS_SUCCESSFUL !=
 841            pci_read_config_word(dev, VIA686A_BASE_REG, &val))
 842                return -ENODEV;
 843
 844        address = val & ~(VIA686A_EXTENT - 1);
 845        if (address == 0) {
 846                dev_err(&dev->dev, "base address not set - upgrade BIOS "
 847                        "or use force_addr=0xaddr\n");
 848                return -ENODEV;
 849        }
 850
 851        if (PCIBIOS_SUCCESSFUL !=
 852            pci_read_config_word(dev, VIA686A_ENABLE_REG, &val))
 853                return -ENODEV;
 854        if (!(val & 0x0001)) {
 855                if (!force_addr) {
 856                        dev_warn(&dev->dev, "Sensors disabled, enable "
 857                                 "with force_addr=0x%x\n", address);
 858                        return -ENODEV;
 859                }
 860
 861                dev_warn(&dev->dev, "Enabling sensors\n");
 862                if (PCIBIOS_SUCCESSFUL !=
 863                    pci_write_config_word(dev, VIA686A_ENABLE_REG,
 864                                          val | 0x0001))
 865                        return -ENODEV;
 866        }
 867
 868        if (platform_driver_register(&via686a_driver))
 869                goto exit;
 870
 871        /* Sets global pdev as a side effect */
 872        if (via686a_device_add(address))
 873                goto exit_unregister;
 874
 875        /* Always return failure here.  This is to allow other drivers to bind
 876         * to this pci device.  We don't really want to have control over the
 877         * pci device, we only wanted to read as few register values from it.
 878         */
 879        s_bridge = pci_dev_get(dev);
 880        return -ENODEV;
 881
 882exit_unregister:
 883        platform_driver_unregister(&via686a_driver);
 884exit:
 885        return -ENODEV;
 886}
 887
 888static struct pci_driver via686a_pci_driver = {
 889        .name           = "via686a",
 890        .id_table       = via686a_pci_ids,
 891        .probe          = via686a_pci_probe,
 892};
 893
 894static int __init sm_via686a_init(void)
 895{
 896        return pci_register_driver(&via686a_pci_driver);
 897}
 898
 899static void __exit sm_via686a_exit(void)
 900{
 901        pci_unregister_driver(&via686a_pci_driver);
 902        if (s_bridge != NULL) {
 903                platform_device_unregister(pdev);
 904                platform_driver_unregister(&via686a_driver);
 905                pci_dev_put(s_bridge);
 906                s_bridge = NULL;
 907        }
 908}
 909
 910MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
 911              "Mark Studebaker <mdsxyz123@yahoo.com> "
 912              "and Bob Dougherty <bobd@stanford.edu>");
 913MODULE_DESCRIPTION("VIA 686A Sensor device");
 914MODULE_LICENSE("GPL");
 915
 916module_init(sm_via686a_init);
 917module_exit(sm_via686a_exit);
 918
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.