diff options
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/coretemp.c | 216 | ||||
-rw-r--r-- | drivers/hwmon/ds620.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/i5k_amb.c | 42 | ||||
-rw-r--r-- | drivers/hwmon/ibmaem.c | 15 | ||||
-rw-r--r-- | drivers/hwmon/max16065.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/ntc_thermistor.c | 3 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/lm25066.c | 12 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.h | 1 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c | 29 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ucd9000.c | 6 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ucd9200.c | 6 | ||||
-rw-r--r-- | drivers/hwmon/w83627ehf.c | 20 | ||||
-rw-r--r-- | drivers/hwmon/w83791d.c | 4 |
13 files changed, 140 insertions, 218 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 59d83e83da7..93238378664 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -36,17 +36,25 @@ #include <linux/cpu.h> #include <linux/pci.h> #include <linux/smp.h> +#include <linux/moduleparam.h> #include <asm/msr.h> #include <asm/processor.h> #define DRVNAME "coretemp" +/* + * force_tjmax only matters when TjMax can't be read from the CPU itself. + * When set, it replaces the driver's suboptimal heuristic. + */ +static int force_tjmax; +module_param_named(tjmax, force_tjmax, int, 0444); +MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); + #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_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 TOTAL_ATTRS (MAX_CORE_ATTRS + 1) #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) #ifdef CONFIG_SMP @@ -69,8 +77,6 @@ * 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. @@ -79,13 +85,11 @@ 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; @@ -143,19 +147,6 @@ 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) { @@ -174,83 +165,6 @@ 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) { @@ -374,7 +288,6 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) { - /* The 100C is default for both mobile and non mobile CPUs */ int err; u32 eax, edx; u32 val; @@ -385,7 +298,8 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) */ err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); if (err) { - dev_warn(dev, "Unable to read TjMax from CPU.\n"); + if (c->x86_model > 0xe && c->x86_model != 0x1c) + dev_warn(dev, "Unable to read TjMax from CPU %u\n", id); } else { val = (eax >> 16) & 0xff; /* @@ -393,11 +307,17 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) * will be used */ if (val) { - dev_info(dev, "TjMax is %d C.\n", val); + dev_dbg(dev, "TjMax is %d degrees C\n", val); return val * 1000; } } + if (force_tjmax) { + dev_notice(dev, "TjMax forced to %d degrees C by user\n", + force_tjmax); + return force_tjmax * 1000; + } + /* * An assumption is made for early CPUs and unreadable MSR. * NOTE: the calculated value may not be correct. @@ -414,21 +334,6 @@ static void __devinit get_ucode_rev_on_cpu(void *edx) rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx); } -static int get_pkg_tjmax(unsigned int cpu, struct device *dev) -{ - int err; - u32 eax, edx, val; - - err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); - if (!err) { - val = (eax >> 16) & 0xff; - if (val) - return val * 1000; - } - dev_warn(dev, "Unable to read Pkg-TjMax from CPU:%u\n", cpu); - return 100000; /* Default TjMax: 100 degree celsius */ -} - static int create_name_attr(struct platform_data *pdata, struct device *dev) { sysfs_attr_init(&pdata->name_attr.attr); @@ -442,19 +347,14 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, int attr_no) { int err, i; - static ssize_t (*rd_ptr[TOTAL_ATTRS]) (struct device *dev, + static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev, struct device_attribute *devattr, char *buf) = { 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] = { + show_ttarget }; + static const char *const names[TOTAL_ATTRS] = { "temp%d_label", "temp%d_crit_alarm", "temp%d_input", "temp%d_crit", - "temp%d_max_alarm", "temp%d_max", - "temp%d_max_hyst" }; + "temp%d_max" }; for (i = 0; i < tdata->attr_size; i++) { snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], @@ -462,10 +362,6 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, 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].index = attr_no; err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr); @@ -481,9 +377,9 @@ exit_free: } -static int __devinit chk_ucode_version(struct platform_device *pdev) +static int __cpuinit chk_ucode_version(unsigned int cpu) { - struct cpuinfo_x86 *c = &cpu_data(pdev->id); + struct cpuinfo_x86 *c = &cpu_data(cpu); int err; u32 edx; @@ -494,17 +390,15 @@ static int __devinit chk_ucode_version(struct platform_device *pdev) */ if (c->x86_model == 0xe && c->x86_mask < 0xc) { /* check for microcode update */ - err = smp_call_function_single(pdev->id, get_ucode_rev_on_cpu, + err = smp_call_function_single(cpu, get_ucode_rev_on_cpu, &edx, 1); if (err) { - dev_err(&pdev->dev, - "Cannot determine microcode revision of " - "CPU#%u (%d)!\n", pdev->id, err); + pr_err("Cannot determine microcode revision of " + "CPU#%u (%d)!\n", cpu, err); return -ENODEV; } else if (edx < 0x39) { - dev_err(&pdev->dev, - "Errata AE18 not fixed, update BIOS or " - "microcode of the CPU!\n"); + pr_err("Errata AE18 not fixed, update BIOS or " + "microcode of the CPU!\n"); return -ENODEV; } } @@ -538,8 +432,6 @@ 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); @@ -548,11 +440,11 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag) return tdata; } -static int create_core_data(struct platform_data *pdata, - struct platform_device *pdev, +static int create_core_data(struct platform_device *pdev, unsigned int cpu, int pkg_flag) { struct temp_data *tdata; + struct platform_data *pdata = platform_get_drvdata(pdev); struct cpuinfo_x86 *c = &cpu_data(cpu); u32 eax, edx; int err, attr_no; @@ -588,20 +480,21 @@ static int create_core_data(struct platform_data *pdata, goto exit_free; /* We can access status register. Get Critical Temperature */ - if (pkg_flag) - tdata->tjmax = get_pkg_tjmax(pdev->id, &pdev->dev); - else - tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); + tdata->tjmax = get_tjmax(c, cpu, &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 + * Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET. + * The target temperature is available on older CPUs but not in this + * register. Atoms don't have the register at all. */ - 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; + if (c->x86_model > 0xe && c->x86_model != 0x1c) { + err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, + &eax, &edx); + if (!err) { + tdata->ttarget + = tdata->tjmax - ((eax >> 8) & 0xff) * 1000; + tdata->attr_size++; + } } pdata->core_data[attr_no] = tdata; @@ -613,22 +506,20 @@ static int create_core_data(struct platform_data *pdata, return 0; exit_free: + pdata->core_data[attr_no] = NULL; kfree(tdata); return err; } static void coretemp_add_core(unsigned int cpu, int pkg_flag) { - struct platform_data *pdata; struct platform_device *pdev = coretemp_get_pdev(cpu); int err; if (!pdev) return; - pdata = platform_get_drvdata(pdev); - - err = create_core_data(pdata, pdev, cpu, pkg_flag); + err = create_core_data(pdev, cpu, pkg_flag); if (err) dev_err(&pdev->dev, "Adding Core %u failed\n", cpu); } @@ -652,11 +543,6 @@ static int __devinit coretemp_probe(struct platform_device *pdev) struct platform_data *pdata; int err; - /* Check the microcode version of the CPU */ - err = chk_ucode_version(pdev); - if (err) - return err; - /* Initialize the per-package data structures */ pdata = kzalloc(sizeof(struct platform_data), GFP_KERNEL); if (!pdata) @@ -666,7 +552,7 @@ static int __devinit coretemp_probe(struct platform_device *pdev) if (err) goto exit_free; - pdata->phys_proc_id = TO_PHYS_ID(pdev->id); + pdata->phys_proc_id = pdev->id; platform_set_drvdata(pdev, pdata); pdata->hwmon_dev = hwmon_device_register(&pdev->dev); @@ -718,7 +604,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) mutex_lock(&pdev_list_mutex); - pdev = platform_device_alloc(DRVNAME, cpu); + pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu)); if (!pdev) { err = -ENOMEM; pr_err("Device allocation failed\n"); @@ -738,7 +624,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) } pdev_entry->pdev = pdev; - pdev_entry->phys_proc_id = TO_PHYS_ID(cpu); + pdev_entry->phys_proc_id = pdev->id; list_add_tail(&pdev_entry->list, &pdev_list); mutex_unlock(&pdev_list_mutex); @@ -799,6 +685,10 @@ static void __cpuinit get_core_online(unsigned int cpu) return; if (!pdev) { + /* Check the microcode version of the CPU */ + if (chk_ucode_version(cpu)) + return; + /* * Alright, we have DTS support. * We are bringing the _first_ core in this pkg diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c index 257957c69d9..4f7c3fc40a8 100644 --- a/drivers/hwmon/ds620.c +++ b/drivers/hwmon/ds620.c @@ -72,7 +72,7 @@ struct ds620_data { char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ - u16 temp[3]; /* Register values, word */ + s16 temp[3]; /* Register values, word */ }; /* diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index c4c40be0edb..d22f241b6a6 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c @@ -114,7 +114,6 @@ struct i5k_amb_data { void __iomem *amb_mmio; struct i5k_device_attribute *attrs; unsigned int num_attrs; - unsigned long chipset_id; }; static ssize_t show_name(struct device *dev, struct device_attribute *devattr, @@ -444,8 +443,6 @@ static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data, goto out; } - data->chipset_id = devid; - res = 0; out: pci_dev_put(pcidev); @@ -478,23 +475,13 @@ out: return res; } -static unsigned long i5k_channel_pci_id(struct i5k_amb_data *data, - unsigned long channel) -{ - switch (data->chipset_id) { - case PCI_DEVICE_ID_INTEL_5000_ERR: - return PCI_DEVICE_ID_INTEL_5000_FBD0 + channel; - case PCI_DEVICE_ID_INTEL_5400_ERR: - return PCI_DEVICE_ID_INTEL_5400_FBD0 + channel; - default: - BUG(); - } -} - -static unsigned long chipset_ids[] = { - PCI_DEVICE_ID_INTEL_5000_ERR, - PCI_DEVICE_ID_INTEL_5400_ERR, - 0 +static struct { + unsigned long err; + unsigned long fbd0; +} chipset_ids[] __devinitdata = { + { PCI_DEVICE_ID_INTEL_5000_ERR, PCI_DEVICE_ID_INTEL_5000_FBD0 }, + { PCI_DEVICE_ID_INTEL_5400_ERR, PCI_DEVICE_ID_INTEL_5400_FBD0 }, + { 0, 0 } }; #ifdef MODULE @@ -510,8 +497,7 @@ static int __devinit i5k_amb_probe(struct platform_device *pdev) { struct i5k_amb_data *data; struct resource *reso; - int i; - int res = -ENODEV; + int i, res; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) @@ -520,22 +506,22 @@ static int __devinit i5k_amb_probe(struct platform_device *pdev) /* Figure out where the AMB registers live */ i = 0; do { - res = i5k_find_amb_registers(data, chipset_ids[i]); + res = i5k_find_amb_registers(data, chipset_ids[i].err); + if (res == 0) + break; i++; - } while (res && chipset_ids[i]); + } while (chipset_ids[i].err); if (res) goto err; /* Copy the DIMM presence map for the first two channels */ - res = i5k_channel_probe(&data->amb_present[0], - i5k_channel_pci_id(data, 0)); + res = i5k_channel_probe(&data->amb_present[0], chipset_ids[i].fbd0); if (res) goto err; /* Copy the DIMM presence map for the optional second two channels */ - i5k_channel_probe(&data->amb_present[2], - i5k_channel_pci_id(data, 1)); + i5k_channel_probe(&data->amb_present[2], chipset_ids[i].fbd0 + 1); /* Set up resource regions */ reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME); diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index 1a409c5bc9b..c316294c48b 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c @@ -432,13 +432,15 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg, aem_send_message(ipmi); res = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); - if (!res) - return -ETIMEDOUT; + if (!res) { + res = -ETIMEDOUT; + goto out; + } if (ipmi->rx_result || ipmi->rx_msg_len != rs_size || memcmp(&rs_resp->id, &system_x_id, sizeof(system_x_id))) { - kfree(rs_resp); - return -ENOENT; + res = -ENOENT; + goto out; } switch (size) { @@ -463,8 +465,11 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg, break; } } + res = 0; - return 0; +out: + kfree(rs_resp); + return res; } /* Update AEM energy registers */ diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c index d94a24fdf4b..dd2d7b9620c 100644 --- a/drivers/hwmon/max16065.c +++ b/drivers/hwmon/max16065.c @@ -124,7 +124,7 @@ static inline int MV_TO_LIMIT(int mv, int range) static inline int ADC_TO_CURR(int adc, int gain) { - return adc * 1400000 / gain * 255; + return adc * 1400000 / (gain * 255); } /* diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index d7926f4336b..eab11615dce 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -211,8 +211,7 @@ static int lookup_comp(struct ntc_data *data, if (data->comp[mid].ohm <= ohm) { *i_low = mid; *i_high = mid - 1; - } - if (data->comp[mid].ohm > ohm) { + } else { *i_low = mid + 1; *i_high = mid; } diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index d4bc114572d..ac254fba551 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c @@ -161,6 +161,17 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, return ret; } +static int lm25066_write_byte(struct i2c_client *client, int page, u8 value) +{ + if (page > 1) + return -EINVAL; + + if (page == 0) + return pmbus_write_byte(client, 0, value); + + return 0; +} + static int lm25066_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -204,6 +215,7 @@ static int lm25066_probe(struct i2c_client *client, info->read_word_data = lm25066_read_word_data; info->write_word_data = lm25066_write_word_data; + info->write_byte = lm25066_write_byte; switch (id->driver_data) { case lm25066: diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index 0808d986d75..a6ae20ffef6 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -325,6 +325,7 @@ struct pmbus_driver_info { int (*read_word_data)(struct i2c_client *client, int page, int reg); int (*write_word_data)(struct i2c_client *client, int page, int reg, u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); /* * The identify function determines supported PMBus functionality. * This function is only necessary if a chip driver supports multiple diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 5c1b6cf3170..397fc59b568 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -182,6 +182,24 @@ int pmbus_write_byte(struct i2c_client *client, int page, u8 value) } EXPORT_SYMBOL_GPL(pmbus_write_byte); +/* + * _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if + * a device specific mapping funcion exists and calls it if necessary. + */ +static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->write_byte) { + status = info->write_byte(client, page, value); + if (status != -ENODATA) + return status; + } + return pmbus_write_byte(client, page, value); +} + int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word) { int rv; @@ -281,7 +299,7 @@ static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg) static void pmbus_clear_fault_page(struct i2c_client *client, int page) { - pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); + _pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); } void pmbus_clear_faults(struct i2c_client *client) @@ -960,6 +978,8 @@ static void pmbus_find_max_attr(struct i2c_client *client, struct pmbus_limit_attr { u16 reg; /* Limit register */ bool update; /* True if register needs updates */ + bool low; /* True if low limit; for limits with compare + functions only */ const char *attr; /* Attribute name */ const char *alarm; /* Alarm attribute name */ u32 sbit; /* Alarm attribute status bit */ @@ -1011,7 +1031,8 @@ static bool pmbus_add_limit_attrs(struct i2c_client *client, if (attr->compare) { pmbus_add_boolean_cmp(data, name, l->alarm, index, - cbase, cindex, + l->low ? cindex : cbase, + l->low ? cbase : cindex, attr->sbase + page, l->sbit); } else { pmbus_add_boolean_reg(data, name, @@ -1348,11 +1369,13 @@ static const struct pmbus_sensor_attr power_attributes[] = { static const struct pmbus_limit_attr temp_limit_attrs[] = { { .reg = PMBUS_UT_WARN_LIMIT, + .low = true, .attr = "min", .alarm = "min_alarm", .sbit = PB_TEMP_UT_WARNING, }, { .reg = PMBUS_UT_FAULT_LIMIT, + .low = true, .attr = "lcrit", .alarm = "lcrit_alarm", .sbit = PB_TEMP_UT_FAULT, @@ -1381,11 +1404,13 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = { static const struct pmbus_limit_attr temp_limit_attrs23[] = { { .reg = PMBUS_UT_WARN_LIMIT, + .low = true, .attr = "min", .alarm = "min_alarm", .sbit = PB_TEMP_UT_WARNING, }, { .reg = PMBUS_UT_FAULT_LIMIT, + .low = true, .attr = "lcrit", .alarm = "lcrit_alarm", .sbit = PB_TEMP_UT_FAULT, diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index ace1c731973..d0ddb60155c 100644 --- a/drivers/hwmon/pmbus/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c @@ -141,13 +141,11 @@ static int ucd9000_probe(struct i2c_client *client, block_buffer[ret] = '\0'; dev_info(&client->dev, "Device ID %s\n", block_buffer); - mid = NULL; - for (i = 0; i < ARRAY_SIZE(ucd9000_id); i++) { - mid = &ucd9000_id[i]; + for (mid = ucd9000_id; mid->name[0]; mid++) { if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) break; } - if (!mid || !strlen(mid->name)) { + if (!mid->name[0]) { dev_err(&client->dev, "Unsupported device\n"); return -ENODEV; } diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c index ffcc1cf3609..c65e9da707c 100644 --- a/drivers/hwmon/pmbus/ucd9200.c +++ b/drivers/hwmon/pmbus/ucd9200.c @@ -68,13 +68,11 @@ static int ucd9200_probe(struct i2c_client *client, block_buffer[ret] = '\0'; dev_info(&client->dev, "Device ID %s\n", block_buffer); - mid = NULL; - for (i = 0; i < ARRAY_SIZE(ucd9200_id); i++) { - mid = &ucd9200_id[i]; + for (mid = ucd9200_id; mid->name[0]; mid++) { if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) break; } - if (!mid || !strlen(mid->name)) { + if (!mid->name[0]) { dev_err(&client->dev, "Unsupported device\n"); return -ENODEV; } diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index f2b377c56a3..36d7f270b14 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -390,7 +390,7 @@ temp_from_reg(u16 reg, s16 regval) { if (is_word_sized(reg)) return LM75_TEMP_FROM_REG(regval); - return regval * 1000; + return ((s8)regval) * 1000; } static inline u16 @@ -398,7 +398,8 @@ temp_to_reg(u16 reg, long temp) { if (is_word_sized(reg)) return LM75_TEMP_TO_REG(temp); - return DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, -127000, 128000), 1000); + return (s8)DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, -127000, 128000), + 1000); } /* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */ @@ -1715,7 +1716,8 @@ static void w83627ehf_device_remove_files(struct device *dev) } /* Get the monitoring functions started */ -static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data) +static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data, + enum kinds kind) { int i; u8 tmp, diode; @@ -1746,10 +1748,16 @@ static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data) w83627ehf_write_value(data, W83627EHF_REG_VBAT, tmp | 0x01); /* Get thermal sensor types */ - diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE); + switch (kind) { + case w83627ehf: + diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE); + break; + default: + diode = 0x70; + } for (i = 0; i < 3; i++) { if ((tmp & (0x02 << i))) - data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 2; + data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 3; else data->temp_type[i] = 4; /* thermistor */ } @@ -2016,7 +2024,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) } /* Initialize the chip */ - w83627ehf_init_device(data); + w83627ehf_init_device(data, sio_data->kind); data->vrm = vid_which_vrm(); superio_enter(sio_data->sioreg); diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 17cf1ab9552..8c2844e5691 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -329,8 +329,8 @@ static int w83791d_detect(struct i2c_client *client, struct i2c_board_info *info); static int w83791d_remove(struct i2c_client *client); -static int w83791d_read(struct i2c_client *client, u8 register); -static int w83791d_write(struct i2c_client *client, u8 register, u8 value); +static int w83791d_read(struct i2c_client *client, u8 reg); +static int w83791d_write(struct i2c_client *client, u8 reg, u8 value); static struct w83791d_data *w83791d_update_device(struct device *dev); #ifdef DEBUG |