diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-30 08:57:57 -1000 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-30 08:57:57 -1000 |
commit | 464c9098bbc17b4596aa12191a7e646a28e7587a (patch) | |
tree | 1d97f02c1f071f358f0d0b5fd8e04db3b9a7a9af /drivers | |
parent | 4c677e2eefdba9c5bfc4474e2e91b26ae8458a1d (diff) | |
parent | f90be42fb383f39aa814b8e14de138da8973e5c1 (diff) |
Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/staging
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/staging: (24 commits)
hwmon: (lm90) Refactor reading of config2 register
hwmon: (lm90) Make SA56004 detection more robust
hwmon: (lm90) Simplify handling of extended local temp register
hwmon: (pmbus) Add client driver for LM25066, LM5064, and LM5066
hwmon: (max34440) Add support for peak attributes
hwmon: (max8688) Add support for peak attributes
hwmon: (max16064) Add support for peak attributes
hwmon: (adm1275) Add support for peak attributes
hwmon: (pmbus) Add support for peak attributes
hwmon: Add new attributes to sysfs ABI
hwmon: (pmbus) Strengthen check for status register existence
hwmon: (pmbus) Add support for virtual pages
hwmon: (pmbus) Support reading and writing of word registers in device specific code
hwmon: (pmbus) Increase attribute name size
hwmon: (pmbus) Add ADP4000, NCP4200 and NCP4208 to list of supported devices
hwmon: (pmbus) Add support for VID output voltage mode
hwmon: (pmbus) Move PMBus drivers to drivers/hwmon/pmbus
hwmon: (coretemp) Add core/pkg threshold support to Coretemp
hwmon: (lm95241) Add support for LM95231
hwmon: LM95245 driver
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/Kconfig | 127 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 13 | ||||
-rw-r--r-- | drivers/hwmon/coretemp.c | 177 | ||||
-rw-r--r-- | drivers/hwmon/lm90.c | 65 | ||||
-rw-r--r-- | drivers/hwmon/lm95241.c | 31 | ||||
-rw-r--r-- | drivers/hwmon/lm95245.c | 543 | ||||
-rw-r--r-- | drivers/hwmon/max1668.c | 502 | ||||
-rw-r--r-- | drivers/hwmon/ntc_thermistor.c | 453 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/Kconfig | 100 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/Makefile | 13 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/adm1275.c (renamed from drivers/hwmon/adm1275.c) | 66 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/lm25066.c | 340 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/max16064.c (renamed from drivers/hwmon/max16064.c) | 57 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/max34440.c (renamed from drivers/hwmon/max34440.c) | 81 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/max8688.c (renamed from drivers/hwmon/max8688.c) | 69 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.c (renamed from drivers/hwmon/pmbus.c) | 37 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.h (renamed from drivers/hwmon/pmbus.h) | 48 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c (renamed from drivers/hwmon/pmbus_core.c) | 351 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ucd9000.c (renamed from drivers/hwmon/ucd9000.c) | 0 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ucd9200.c (renamed from drivers/hwmon/ucd9200.c) | 0 |
20 files changed, 2792 insertions, 281 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 0598cd22edf..0b62c3c6b7c 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -623,7 +623,7 @@ config SENSORS_LM90 LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A, Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008, - and Winbond/Nuvoton W83L771W/G/AWG/ASG sensor chips. + Winbond/Nuvoton W83L771W/G/AWG/ASG and Philips SA56004 sensor chips. This driver can also be built as a module. If so, the module will be called lm90. @@ -694,14 +694,24 @@ config SENSORS_LTC4261 be called ltc4261. config SENSORS_LM95241 - tristate "National Semiconductor LM95241 sensor chip" + tristate "National Semiconductor LM95241 and compatibles" depends on I2C help - If you say yes here you get support for LM95241 sensor chip. + If you say yes here you get support for LM95231 and LM95241 sensor + chips. This driver can also be built as a module. If so, the module will be called lm95241. +config SENSORS_LM95245 + tristate "National Semiconductor LM95245 sensor chip" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for LM95245 sensor chip. + + This driver can also be built as a module. If so, the module + will be called lm95245. + config SENSORS_MAX1111 tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" depends on SPI_MASTER @@ -736,6 +746,16 @@ config SENSORS_MAX1619 This driver can also be built as a module. If so, the module will be called max1619. +config SENSORS_MAX1668 + tristate "Maxim MAX1668 and compatibles" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for MAX1668, MAX1989 and + MAX1805 chips. + + This driver can also be built as a module. If so, the module + will be called max1668. + config SENSORS_MAX6639 tristate "Maxim MAX6639 sensor chip" depends on I2C && EXPERIMENTAL @@ -767,6 +787,20 @@ config SENSORS_MAX6650 This driver can also be built as a module. If so, the module will be called max6650. +config SENSORS_NTC_THERMISTOR + tristate "NTC thermistor support" + depends on EXPERIMENTAL + help + This driver supports NTC thermistors sensor reading and its + interpretation. The driver can also monitor the temperature and + send notifications about the temperature. + + Currently, this driver supports + NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, and NCP15WL333. + + This driver can also be built as a module. If so, the module + will be called ntc-thermistor. + config SENSORS_PC87360 tristate "National Semiconductor PC87360 family" select HWMON_VID @@ -807,92 +841,7 @@ config SENSORS_PCF8591 These devices are hard to detect and rarely found on mainstream hardware. If unsure, say N. -config PMBUS - tristate "PMBus support" - depends on I2C && EXPERIMENTAL - default n - help - Say yes here if you want to enable PMBus support. - - This driver can also be built as a module. If so, the module will - be called pmbus_core. - -if PMBUS - -config SENSORS_PMBUS - tristate "Generic PMBus devices" - default n - help - If you say yes here you get hardware monitoring support for generic - PMBus devices, including but not limited to BMR450, BMR451, BMR453, - BMR454, and LTC2978. - - This driver can also be built as a module. If so, the module will - be called pmbus. - -config SENSORS_ADM1275 - tristate "Analog Devices ADM1275" - default n - help - If you say yes here you get hardware monitoring support for Analog - Devices ADM1275 Hot-Swap Controller and Digital Power Monitor. - - This driver can also be built as a module. If so, the module will - be called adm1275. - -config SENSORS_MAX16064 - tristate "Maxim MAX16064" - default n - help - If you say yes here you get hardware monitoring support for Maxim - MAX16064. - - This driver can also be built as a module. If so, the module will - be called max16064. - -config SENSORS_MAX34440 - tristate "Maxim MAX34440/MAX34441" - default n - help - If you say yes here you get hardware monitoring support for Maxim - MAX34440 and MAX34441. - - This driver can also be built as a module. If so, the module will - be called max34440. - -config SENSORS_MAX8688 - tristate "Maxim MAX8688" - default n - help - If you say yes here you get hardware monitoring support for Maxim - MAX8688. - - This driver can also be built as a module. If so, the module will - be called max8688. - -config SENSORS_UCD9000 - tristate "TI UCD90120, UCD90124, UCD9090, UCD90910" - default n - help - If you say yes here you get hardware monitoring support for TI - UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health - Controllers. - - This driver can also be built as a module. If so, the module will - be called ucd9000. - -config SENSORS_UCD9200 - tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248" - default n - help - If you say yes here you get hardware monitoring support for TI - UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248 - Digital PWM System Controllers. - - This driver can also be built as a module. If so, the module will - be called ucd9200. - -endif # PMBUS +source drivers/hwmon/pmbus/Kconfig config SENSORS_SHT15 tristate "Sensiron humidity and temperature sensors. SHT15 and compat." diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d7995a1d078..3c9ccefea79 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -80,6 +80,7 @@ obj-$(CONFIG_SENSORS_LM90) += lm90.o obj-$(CONFIG_SENSORS_LM92) += lm92.o obj-$(CONFIG_SENSORS_LM93) += lm93.o obj-$(CONFIG_SENSORS_LM95241) += lm95241.o +obj-$(CONFIG_SENSORS_LM95245) += lm95245.o obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o @@ -87,10 +88,12 @@ obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o obj-$(CONFIG_SENSORS_MAX1111) += max1111.o obj-$(CONFIG_SENSORS_MAX16065) += max16065.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o +obj-$(CONFIG_SENSORS_MAX1668) += max1668.o obj-$(CONFIG_SENSORS_MAX6639) += max6639.o obj-$(CONFIG_SENSORS_MAX6642) += max6642.o obj-$(CONFIG_SENSORS_MAX6650) += max6650.o obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o +obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o @@ -121,15 +124,7 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o -# PMBus drivers -obj-$(CONFIG_PMBUS) += pmbus_core.o -obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o -obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o -obj-$(CONFIG_SENSORS_MAX16064) += max16064.o -obj-$(CONFIG_SENSORS_MAX34440) += max34440.o -obj-$(CONFIG_SENSORS_MAX8688) += max8688.o -obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o -obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o +obj-$(CONFIG_PMBUS) += pmbus/ ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 0070d5476dd..59d83e83da7 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -44,7 +44,9 @@ #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ #define NUM_REAL_CORES 16 /* Number of Real cores per cpu */ #define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ -#define MAX_ATTRS 5 /* Maximum no of per-core attrs */ +#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ +#define MAX_THRESH_ATTRS 3 /* Maximum no of Threshold attrs */ +#define TOTAL_ATTRS (MAX_CORE_ATTRS + MAX_THRESH_ATTRS) #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) #ifdef CONFIG_SMP @@ -67,6 +69,9 @@ * This value is passed as "id" field to rdmsr/wrmsr functions. * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS, * from where the temperature values should be read. + * @intrpt_reg: One of IA32_THERM_INTERRUPT or IA32_PACKAGE_THERM_INTERRUPT, + * from where the thresholds are read. + * @attr_size: Total number of pre-core attrs displayed in the sysfs. * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data. * Otherwise, temp_data holds coretemp data. * @valid: If this is 1, the current temperature is valid. @@ -74,15 +79,18 @@ struct temp_data { int temp; int ttarget; + int tmin; int tjmax; unsigned long last_updated; unsigned int cpu; u32 cpu_core_id; u32 status_reg; + u32 intrpt_reg; + int attr_size; bool is_pkg_data; bool valid; - struct sensor_device_attribute sd_attrs[MAX_ATTRS]; - char attr_name[MAX_ATTRS][CORETEMP_NAME_LENGTH]; + struct sensor_device_attribute sd_attrs[TOTAL_ATTRS]; + char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH]; struct mutex update_lock; }; @@ -135,6 +143,19 @@ static ssize_t show_crit_alarm(struct device *dev, return sprintf(buf, "%d\n", (eax >> 5) & 1); } +static ssize_t show_max_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + u32 eax, edx; + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct platform_data *pdata = dev_get_drvdata(dev); + struct temp_data *tdata = pdata->core_data[attr->index]; + + rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); + + return sprintf(buf, "%d\n", !!(eax & THERM_STATUS_THRESHOLD1)); +} + static ssize_t show_tjmax(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -153,6 +174,83 @@ static ssize_t show_ttarget(struct device *dev, return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget); } +static ssize_t store_ttarget(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct platform_data *pdata = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct temp_data *tdata = pdata->core_data[attr->index]; + u32 eax, edx; + unsigned long val; + int diff; + + if (strict_strtoul(buf, 10, &val)) + return -EINVAL; + + /* + * THERM_MASK_THRESHOLD1 is 7 bits wide. Values are entered in terms + * of milli degree celsius. Hence don't accept val > (127 * 1000) + */ + if (val > tdata->tjmax || val > 127000) + return -EINVAL; + + diff = (tdata->tjmax - val) / 1000; + + mutex_lock(&tdata->update_lock); + rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx); + eax = (eax & ~THERM_MASK_THRESHOLD1) | + (diff << THERM_SHIFT_THRESHOLD1); + wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx); + tdata->ttarget = val; + mutex_unlock(&tdata->update_lock); + + return count; +} + +static ssize_t show_tmin(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct platform_data *pdata = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tmin); +} + +static ssize_t store_tmin(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct platform_data *pdata = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct temp_data *tdata = pdata->core_data[attr->index]; + u32 eax, edx; + unsigned long val; + int diff; + + if (strict_strtoul(buf, 10, &val)) + return -EINVAL; + + /* + * THERM_MASK_THRESHOLD0 is 7 bits wide. Values are entered in terms + * of milli degree celsius. Hence don't accept val > (127 * 1000) + */ + if (val > tdata->tjmax || val > 127000) + return -EINVAL; + + diff = (tdata->tjmax - val) / 1000; + + mutex_lock(&tdata->update_lock); + rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx); + eax = (eax & ~THERM_MASK_THRESHOLD0) | + (diff << THERM_SHIFT_THRESHOLD0); + wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx); + tdata->tmin = val; + mutex_unlock(&tdata->update_lock); + + return count; +} + static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -344,23 +442,31 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, int attr_no) { int err, i; - static ssize_t (*rd_ptr[MAX_ATTRS]) (struct device *dev, + static ssize_t (*rd_ptr[TOTAL_ATTRS]) (struct device *dev, struct device_attribute *devattr, char *buf) = { - show_label, show_crit_alarm, show_ttarget, - show_temp, show_tjmax }; - static const char *names[MAX_ATTRS] = { + show_label, show_crit_alarm, show_temp, show_tjmax, + show_max_alarm, show_ttarget, show_tmin }; + static ssize_t (*rw_ptr[TOTAL_ATTRS]) (struct device *dev, + struct device_attribute *devattr, const char *buf, + size_t count) = { NULL, NULL, NULL, NULL, NULL, + store_ttarget, store_tmin }; + static const char *names[TOTAL_ATTRS] = { "temp%d_label", "temp%d_crit_alarm", - "temp%d_max", "temp%d_input", - "temp%d_crit" }; + "temp%d_input", "temp%d_crit", + "temp%d_max_alarm", "temp%d_max", + "temp%d_max_hyst" }; - for (i = 0; i < MAX_ATTRS; i++) { + for (i = 0; i < tdata->attr_size; i++) { snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], attr_no); sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; + if (rw_ptr[i]) { + tdata->sd_attrs[i].dev_attr.attr.mode |= S_IWUSR; + tdata->sd_attrs[i].dev_attr.store = rw_ptr[i]; + } tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; - tdata->sd_attrs[i].dev_attr.store = NULL; tdata->sd_attrs[i].index = attr_no; err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr); if (err) @@ -374,38 +480,6 @@ exit_free: return err; } -static void update_ttarget(__u8 cpu_model, struct temp_data *tdata, - struct device *dev) -{ - int err; - u32 eax, edx; - - /* - * Initialize ttarget value. Eventually this will be - * initialized with the value from MSR_IA32_THERM_INTERRUPT - * register. If IA32_TEMPERATURE_TARGET is supported, this - * value will be over written below. - * To Do: Patch to initialize ttarget from MSR_IA32_THERM_INTERRUPT - */ - tdata->ttarget = tdata->tjmax - 20000; - - /* - * Read the still undocumented IA32_TEMPERATURE_TARGET. It exists - * on older CPUs but not in this register, - * Atoms don't have it either. - */ - if (cpu_model > 0xe && cpu_model != 0x1c) { - err = rdmsr_safe_on_cpu(tdata->cpu, - MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); - if (err) { - dev_warn(dev, - "Unable to read IA32_TEMPERATURE_TARGET MSR\n"); - } else { - tdata->ttarget = tdata->tjmax - - ((eax >> 8) & 0xff) * 1000; - } - } -} static int __devinit chk_ucode_version(struct platform_device *pdev) { @@ -464,9 +538,12 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag) tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS; + tdata->intrpt_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_INTERRUPT : + MSR_IA32_THERM_INTERRUPT; tdata->is_pkg_data = pkg_flag; tdata->cpu = cpu; tdata->cpu_core_id = TO_CORE_ID(cpu); + tdata->attr_size = MAX_CORE_ATTRS; mutex_init(&tdata->update_lock); return tdata; } @@ -516,7 +593,17 @@ static int create_core_data(struct platform_data *pdata, else tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); - update_ttarget(c->x86_model, tdata, &pdev->dev); + /* + * Test if we can access the intrpt register. If so, increase the + * 'size' enough to have ttarget/tmin/max_alarm interfaces. + * Initialize ttarget with bits 16:22 of MSR_IA32_THERM_INTERRUPT + */ + err = rdmsr_safe_on_cpu(cpu, tdata->intrpt_reg, &eax, &edx); + if (!err) { + tdata->attr_size += MAX_THRESH_ATTRS; + tdata->ttarget = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000; + } + pdata->core_data[attr_no] = tdata; /* Create sysfs interfaces */ @@ -553,7 +640,7 @@ static void coretemp_remove_core(struct platform_data *pdata, struct temp_data *tdata = pdata->core_data[indx]; /* Remove the sysfs attributes */ - for (i = 0; i < MAX_ATTRS; i++) + for (i = 0; i < tdata->attr_size; i++) device_remove_file(dev, &tdata->sd_attrs[i].dev_attr); kfree(pdata->core_data[indx]); diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 2f94f950480..90ddb877421 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -54,6 +54,9 @@ * and extended mode. They are mostly compatible with LM90 except for a data * format difference for the temperature value registers. * + * This driver also supports the SA56004 from Philips. This device is + * pin-compatible with the LM86, the ED/EDP parts are also address-compatible. + * * Since the LM90 was the first chipset supported by this driver, most * comments will refer to this chipset, but are actually general and * concern all supported chipsets, unless mentioned otherwise. @@ -96,13 +99,15 @@ * MAX6659 can have address 0x4c, 0x4d or 0x4e. * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, * 0x4c, 0x4d or 0x4e. + * SA56004 can have address 0x48 through 0x4F. */ static const unsigned short normal_i2c[] = { - 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; + 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, - max6646, w83l771, max6696 }; + max6646, w83l771, max6696, sa56004 }; /* * The LM90 registers @@ -152,6 +157,10 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, #define MAX6659_REG_R_LOCAL_EMERG 0x17 #define MAX6659_REG_W_LOCAL_EMERG 0x17 +/* SA56004 registers */ + +#define SA56004_REG_R_LOCAL_TEMPL 0x22 + #define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */ #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ @@ -161,7 +170,6 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, #define LM90_FLAG_ADT7461_EXT (1 << 0) /* ADT7461 extended mode */ /* Device features */ #define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */ -#define LM90_HAVE_LOCAL_EXT (1 << 2) /* extended local temperature */ #define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */ #define LM90_HAVE_EMERGENCY (1 << 4) /* 3rd upper (emergency) limit */ #define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */ @@ -192,6 +200,7 @@ static const struct i2c_device_id lm90_id[] = { { "max6696", max6696 }, { "nct1008", adt7461 }, { "w83l771", w83l771 }, + { "sa56004", sa56004 }, { } }; MODULE_DEVICE_TABLE(i2c, lm90_id); @@ -204,6 +213,7 @@ struct lm90_params { u16 alert_alarms; /* Which alarm bits trigger ALERT# */ /* Upper 8 bits for max6695/96 */ u8 max_convrate; /* Maximum conversion rate register value */ + u8 reg_local_ext; /* Extended local temp register (optional) */ }; static const struct lm90_params lm90_params[] = { @@ -235,19 +245,20 @@ static const struct lm90_params lm90_params[] = { .max_convrate = 9, }, [max6646] = { - .flags = LM90_HAVE_LOCAL_EXT, .alert_alarms = 0x7c, .max_convrate = 6, + .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, }, [max6657] = { - .flags = LM90_HAVE_LOCAL_EXT, .alert_alarms = 0x7c, .max_convrate = 8, + .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, }, [max6659] = { - .flags = LM90_HAVE_LOCAL_EXT | LM90_HAVE_EMERGENCY, + .flags = LM90_HAVE_EMERGENCY, .alert_alarms = 0x7c, .max_convrate = 8, + .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, }, [max6680] = { .flags = LM90_HAVE_OFFSET, @@ -255,16 +266,23 @@ static const struct lm90_params lm90_params[] = { .max_convrate = 7, }, [max6696] = { - .flags = LM90_HAVE_LOCAL_EXT | LM90_HAVE_EMERGENCY + .flags = LM90_HAVE_EMERGENCY | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, .alert_alarms = 0x187c, .max_convrate = 6, + .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, }, [w83l771] = { .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, .alert_alarms = 0x7c, .max_convrate = 8, }, + [sa56004] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, + .alert_alarms = 0x7b, + .max_convrate = 9, + .reg_local_ext = SA56004_REG_R_LOCAL_TEMPL, + }, }; /* @@ -286,6 +304,7 @@ struct lm90_data { u16 alert_alarms; /* Which alarm bits trigger ALERT# */ /* Upper 8 bits for max6695/96 */ u8 max_convrate; /* Maximum conversion rate */ + u8 reg_local_ext; /* local extension register offset */ /* registers values */ s8 temp8[8]; /* 0: local low limit @@ -452,9 +471,9 @@ static struct lm90_data *lm90_update_device(struct device *dev) lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]); lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst); - if (data->flags & LM90_HAVE_LOCAL_EXT) { + if (data->reg_local_ext) { lm90_read16(client, LM90_REG_R_LOCAL_TEMP, - MAX6657_REG_R_LOCAL_TEMPL, + data->reg_local_ext, &data->temp11[4]); } else { if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, @@ -1092,7 +1111,7 @@ static int lm90_detect(struct i2c_client *new_client, struct i2c_adapter *adapter = new_client->adapter; int address = new_client->addr; const char *name = NULL; - int man_id, chip_id, reg_config1, reg_convrate; + int man_id, chip_id, reg_config1, reg_config2, reg_convrate; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; @@ -1108,15 +1127,16 @@ static int lm90_detect(struct i2c_client *new_client, LM90_REG_R_CONVRATE)) < 0) return -ENODEV; - if ((address == 0x4C || address == 0x4D) - && man_id == 0x01) { /* National Semiconductor */ - int reg_config2; - + if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) { reg_config2 = i2c_smbus_read_byte_data(new_client, LM90_REG_R_CONFIG2); if (reg_config2 < 0) return -ENODEV; + } else + reg_config2 = 0; /* Make compiler happy */ + if ((address == 0x4C || address == 0x4D) + && man_id == 0x01) { /* National Semiconductor */ if ((reg_config1 & 0x2A) == 0x00 && (reg_config2 & 0xF8) == 0x00 && reg_convrate <= 0x09) { @@ -1245,13 +1265,6 @@ static int lm90_detect(struct i2c_client *new_client, } else if (address == 0x4C && man_id == 0x5C) { /* Winbond/Nuvoton */ - int reg_config2; - - reg_config2 = i2c_smbus_read_byte_data(new_client, - LM90_REG_R_CONFIG2); - if (reg_config2 < 0) - return -ENODEV; - if ((reg_config1 & 0x2A) == 0x00 && (reg_config2 & 0xF8) == 0x00) { if (chip_id == 0x01 /* W83L771W/G */ @@ -1263,6 +1276,15 @@ static int lm90_detect(struct i2c_client *new_client, name = "w83l771"; } } + } else + if (address >= 0x48 && address <= 0x4F + && man_id == 0xA1) { /* NXP Semiconductor/Philips */ + if (chip_id == 0x00 + && (reg_config1 & 0x2A) == 0x00 + && (reg_config2 & 0xFE) == 0x00 + && reg_convrate <= 0x09) { + name = "sa56004"; + } } if (!name) { /* identification failed */ @@ -1368,6 +1390,7 @@ static int lm90_probe(struct i2c_client *new_client, /* Set chip capabilities */ data->flags = lm90_params[data->kind].flags; + data->reg_local_ext = lm90_params[data->kind].reg_local_ext; /* Set maximum conversion rate */ data->max_convrate = lm90_params[data->kind].max_convrate; diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index d3b464b74ce..513901d592a 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -74,8 +74,9 @@ static const unsigned short normal_i2c[] = { #define TT_OFF 0 #define TT_ON 1 #define TT_MASK 7 -#define MANUFACTURER_ID 0x01 -#define DEFAULT_REVISION 0xA4 +#define NATSEMI_MAN_ID 0x01 +#define LM95231_CHIP_ID 0xA1 +#define LM95241_CHIP_ID 0xA4 static const u8 lm95241_reg_address[] = { LM95241_REG_R_LOCAL_TEMPH, @@ -338,20 +339,25 @@ static int lm95241_detect(struct i2c_client *new_client, struct i2c_board_info *info) { struct i2c_adapter *adapter = new_client->adapter; - int address = new_client->addr; const char *name; + int mfg_id, chip_id; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) - == MANUFACTURER_ID) - && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) - == DEFAULT_REVISION)) { - name = DEVNAME; - } else { - dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n", - address); + mfg_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID); + if (mfg_id != NATSEMI_MAN_ID) + return -ENODEV; + + chip_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID); + switch (chip_id) { + case LM95231_CHIP_ID: + name = "lm95231"; + break; + case LM95241_CHIP_ID: + name = "lm95241"; + break; + default: return -ENODEV; } @@ -431,7 +437,8 @@ static int lm95241_remove(struct i2c_client *client) /* Driver data (common to all clients) */ static const struct i2c_device_id lm95241_id[] = { - { DEVNAME, 0 }, + { "lm95231", 0 }, + { "lm95241", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, lm95241_id); diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c new file mode 100644 index 00000000000..dce9e68241e --- /dev/null +++ b/drivers/hwmon/lm95245.c @@ -0,0 +1,543 @@ +/* + * Copyright (C) 2011 Alexander Stein <alexander.stein@systec-electronic.com> + * + * The LM95245 is a sensor chip made by National Semiconductors. + * It reports up to two temperatures (its own plus an external one). + * Complete datasheet can be obtained from National's website at: + * http://www.national.com/ds.cgi/LM/LM95245.pdf + * + * This driver is based on lm95241.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/jiffies.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/sysfs.h> + +#define DEVNAME "lm95245" + +static const unsigned short normal_i2c[] = { + 0x18, 0x19, 0x29, 0x4c, 0x4d, I2C_CLIENT_END }; + +/* LM95245 registers */ +/* general registers */ +#define LM95245_REG_RW_CONFIG1 0x03 +#define LM95245_REG_RW_CONVERS_RATE 0x04 +#define LM95245_REG_W_ONE_SHOT 0x0F + +/* diode configuration */ +#define LM95245_REG_RW_CONFIG2 0xBF +#define LM95245_REG_RW_REMOTE_OFFH 0x11 +#define LM95245_REG_RW_REMOTE_OFFL 0x12 + +/* status registers */ +#define LM95245_REG_R_STATUS1 0x02 +#define LM95245_REG_R_STATUS2 0x33 + +/* limit registers */ +#define LM95245_REG_RW_REMOTE_OS_LIMIT 0x07 +#define LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT 0x20 +#define LM95245_REG_RW_REMOTE_TCRIT_LIMIT 0x19 +#define LM95245_REG_RW_COMMON_HYSTERESIS 0x21 + +/* temperature signed */ +#define LM95245_REG_R_LOCAL_TEMPH_S 0x00 +#define LM95245_REG_R_LOCAL_TEMPL_S 0x30 +#define LM95245_REG_R_REMOTE_TEMPH_S 0x01 +#define LM95245_REG_R_REMOTE_TEMPL_S 0x10 +/* temperature unsigned */ +#define LM95245_REG_R_REMOTE_TEMPH_U 0x31 +#define LM95245_REG_R_REMOTE_TEMPL_U 0x32 + +/* id registers */ +#define LM95245_REG_R_MAN_ID 0xFE +#define LM95245_REG_R_CHIP_ID 0xFF + +/* LM95245 specific bitfields */ +#define CFG_STOP 0x40 +#define CFG_REMOTE_TCRIT_MASK 0x10 +#define CFG_REMOTE_OS_MASK 0x08 +#define CFG_LOCAL_TCRIT_MASK 0x04 +#define CFG_LOCAL_OS_MASK 0x02 + +#define CFG2_OS_A0 0x40 +#define CFG2_DIODE_FAULT_OS 0x20 +#define CFG2_DIODE_FAULT_TCRIT 0x10 +#define CFG2_REMOTE_TT 0x08 +#define CFG2_REMOTE_FILTER_DIS 0x00 +#define CFG2_REMOTE_FILTER_EN 0x06 + +/* conversation rate in ms */ +#define RATE_CR0063 0x00 +#define RATE_CR0364 0x01 +#define RATE_CR1000 0x02 +#define RATE_CR2500 0x03 + +#define STATUS1_DIODE_FAULT 0x04 +#define STATUS1_RTCRIT 0x02 +#define STATUS1_LOC 0x01 + +#define MANUFACTURER_ID 0x01 +#define DEFAULT_REV |