* Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net>
*
* Derived from w83627ehf driver
- * Copyright (C) 2005-2012 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2005-2012 Jean Delvare <jdelvare@suse.de>
* Copyright (C) 2006 Yuan Mu (Winbond),
* Rudolf Marek <r.marek@assembler.cz>
* David Hubbard <david.c.hubbard@gmail.com>
* nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3
* nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3
* nct6791d 15 6 6 2+6 0xc800 0xc1 0x5ca3
+ * nct6792d 15 6 6 2+6 0xc911 0xc1 0x5ca3
*
* #temp lists the number of monitored temperature sources (first value) plus
* the number of directly connectable temperature sensors (second value).
#define USE_ALTERNATE
-enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791 };
+enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792 };
/* used to set data->name = nct6775_device_names[data->sio_kind] */
static const char * const nct6775_device_names[] = {
"nct6776",
"nct6779",
"nct6791",
+ "nct6792",
};
static unsigned short force_id;
#define SIO_NCT6776_ID 0xc330
#define SIO_NCT6779_ID 0xc560
#define SIO_NCT6791_ID 0xc800
+#define SIO_NCT6792_ID 0xc910
#define SIO_ID_MASK 0xFFF0
enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
4, 5, 13, -1, -1, -1, /* temp1..temp6 */
12, 9 }; /* intrusion0, intrusion1 */
+/* NCT6792 specific data */
+
+static const u16 NCT6792_REG_TEMP_MON[] = {
+ 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d };
+static const u16 NCT6792_REG_BEEP[NUM_REG_BEEP] = {
+ 0xb2, 0xb3, 0xb4, 0xb5, 0xbf };
/* NCT6102D/NCT6106D specific data */
enum kinds kind;
const char *name;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
struct device *hwmon_dev;
- struct attribute_group *group_in;
- struct attribute_group *group_fan;
- struct attribute_group *group_temp;
- struct attribute_group *group_pwm;
+#endif
+
+ const struct attribute_group *groups[6];
u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
* 3=temp_crit, 4=temp_lcrit
u16 have_temp;
u16 have_temp_fixed;
u16 have_in;
-#ifdef CONFIG_PM
+
/* Remember extra register values over suspend/resume */
u8 vbat;
u8 fandiv1;
u8 fandiv2;
-#endif
};
struct nct6775_sio_data {
struct sensor_device_attribute_2 *a2;
struct attribute **attrs;
struct sensor_device_template **t;
- int err, i, j, count;
+ int i, count;
if (repeat <= 0)
return ERR_PTR(-EINVAL);
for (i = 0; i < repeat; i++) {
t = tg->templates;
- for (j = 0; *t != NULL; j++) {
+ while (*t != NULL) {
snprintf(su->name, sizeof(su->name),
(*t)->dev_attr.attr.name, tg->base + i);
if ((*t)->s2) {
}
}
- err = sysfs_create_group(&dev->kobj, group);
- if (err)
- return ERR_PTR(-ENOMEM);
-
return group;
}
reg == 0x73 || reg == 0x75 || reg == 0x77;
case nct6779:
case nct6791:
+ case nct6792:
return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
reg == 0x402 ||
reg == 0x63a || reg == 0x63c || reg == 0x63e ||
reg == 0x640 || reg == 0x642 ||
reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
- reg == 0x7b;
+ reg == 0x7b || reg == 0x7d;
}
return false;
}
static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
{
u8 bank = reg >> 8;
+
if (data->bank != bank) {
outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
outb_p(bank, data->addr + DATA_REG_OFFSET);
if (!data->target_speed_tolerance[i] ||
data->pwm_enable[i] == speed_cruise) {
u8 t = fanmodecfg & 0x0f;
+
if (data->REG_TOLERANCE_H) {
t |= (nct6775_read_value(data,
data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
if (reg & 0x80)
data->pwm[2][i] = 0;
- if (data->REG_WEIGHT_TEMP_SEL[i]) {
- reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
- data->pwm_weight_temp_sel[i] = reg & 0x1f;
- /* If weight is disabled, report weight source as 0 */
- if (j == 1 && !(reg & 0x80))
- data->pwm_weight_temp_sel[i] = 0;
+ if (!data->REG_WEIGHT_TEMP_SEL[i])
+ continue;
- /* Weight temp data */
- for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
- data->weight_temp[j][i]
- = nct6775_read_value(data,
- data->REG_WEIGHT_TEMP[j][i]);
- }
+ reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
+ data->pwm_weight_temp_sel[i] = reg & 0x1f;
+ /* If weight is disabled, report weight source as 0 */
+ if (j == 1 && !(reg & 0x80))
+ data->pwm_weight_temp_sel[i] = 0;
+
+ /* Weight temp data */
+ for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
+ data->weight_temp[j][i]
+ = nct6775_read_value(data,
+ data->REG_WEIGHT_TEMP[j][i]);
}
}
}
case nct6106:
case nct6779:
case nct6791:
+ case nct6792:
reg = nct6775_read_value(data,
data->REG_CRITICAL_PWM_ENABLE[i]);
if (reg & data->CRITICAL_PWM_ENABLE_MASK)
= nct6775_read_temp(data,
data->reg_temp[j][i]);
}
- if (!(data->have_temp_fixed & (1 << i)))
+ if (i >= NUM_TEMP_FIXED ||
+ !(data->have_temp_fixed & (1 << i)))
continue;
data->temp_offset[i]
= nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
data->alarms = 0;
for (i = 0; i < NUM_REG_ALARM; i++) {
u8 alarm;
+
if (!data->REG_ALARM[i])
continue;
alarm = nct6775_read_value(data, data->REG_ALARM[i]);
data->beeps = 0;
for (i = 0; i < NUM_REG_BEEP; i++) {
u8 beep;
+
if (!data->REG_BEEP[i])
continue;
beep = nct6775_read_value(data, data->REG_BEEP[i]);
{
struct nct6775_data *data = nct6775_update_device(dev);
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- int nr = sattr->nr;
int index = sattr->index;
+ int nr = sattr->nr;
+
return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
}
{
struct nct6775_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- int nr = sattr->nr;
int index = sattr->index;
+ int nr = sattr->nr;
unsigned long val;
- int err = kstrtoul(buf, 10, &val);
+ int err;
+
+ err = kstrtoul(buf, 10, &val);
if (err < 0)
return err;
mutex_lock(&data->update_lock);
struct nct6775_data *data = nct6775_update_device(dev);
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
int nr = data->ALARM_BITS[sattr->index];
+
return sprintf(buf, "%u\n",
(unsigned int)((data->alarms >> nr) & 0x01));
}
if (src == source)
return nr;
}
- return -1;
+ return -ENODEV;
}
static ssize_t
nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
if (nr >= 0) {
int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
+
alarm = (data->alarms >> bit) & 0x01;
}
return sprintf(buf, "%u\n", alarm);
int nr = data->BEEP_BITS[sattr->index];
int regindex = nr >> 3;
unsigned long val;
+ int err;
- int err = kstrtoul(buf, 10, &val);
+ err = kstrtoul(buf, 10, &val);
if (err < 0)
return err;
if (val > 1)
nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
if (nr >= 0) {
int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
+
beep = (data->beeps >> bit) & 0x01;
}
return sprintf(buf, "%u\n", beep);
struct nct6775_data *data = dev_get_drvdata(dev);
int nr, bit, regindex;
unsigned long val;
+ int err;
- int err = kstrtoul(buf, 10, &val);
+ err = kstrtoul(buf, 10, &val);
if (err < 0)
return err;
if (val > 1)
nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
if (nr < 0)
- return -ENODEV;
+ return nr;
bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
regindex = bit >> 3;
struct nct6775_data *data = nct6775_update_device(dev);
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
int nr = sattr->index;
+
return sprintf(buf, "%d\n", data->rpm[nr]);
}
struct nct6775_data *data = nct6775_update_device(dev);
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
int nr = sattr->index;
+
return sprintf(buf, "%d\n",
data->fan_from_reg_min(data->fan_min[nr],
data->fan_div[nr]));
struct nct6775_data *data = nct6775_update_device(dev);
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
int nr = sattr->index;
+
return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
}
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
int nr = sattr->index;
unsigned long val;
- int err;
unsigned int reg;
u8 new_div;
+ int err;
err = kstrtoul(buf, 10, &val);
if (err < 0)
struct nct6775_data *data = nct6775_update_device(dev);
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
int nr = sattr->index;
+
return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
}
struct nct6775_data *data = nct6775_update_device(dev);
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
int nr = sattr->index;
+
return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
}
return count;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
static ssize_t
show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+#endif
static ssize_t
show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
case nct6106:
case nct6779:
case nct6791:
+ case nct6792:
nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
val);
reg = nct6775_read_value(data,
show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{
struct nct6775_data *data = dev_get_drvdata(dev);
+
return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
}
struct device *dev = container_of(kobj, struct device, kobj);
struct nct6775_data *data = dev_get_drvdata(dev);
- if (index == 1 && !data->have_vid)
+ if (index == 0 && !data->have_vid)
return 0;
- if (index == 2 || index == 3) {
- if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 2] < 0)
+ if (index == 1 || index == 2) {
+ if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)
return 0;
}
- if (index == 4 || index == 5) {
- if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 4] < 0)
+ if (index == 3 || index == 4) {
+ if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)
return 0;
}
* Any change in order or content must be matched.
*/
static struct attribute *nct6775_attributes_other[] = {
+ &dev_attr_cpu0_vid.attr, /* 0 */
+ &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 1 */
+ &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 2 */
+ &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 3 */
+ &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 4 */
+ &sensor_dev_attr_beep_enable.dev_attr.attr, /* 5 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
&dev_attr_name.attr,
- &dev_attr_cpu0_vid.attr, /* 1 */
- &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 2 */
- &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 3 */
- &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 4 */
- &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 5 */
- &sensor_dev_attr_beep_enable.dev_attr.attr, /* 6 */
-
+#endif
NULL
};
.is_visible = nct6775_other_is_visible,
};
-/*
- * Driver and device management
- */
-
-static void nct6775_device_remove_files(struct device *dev)
-{
- struct nct6775_data *data = dev_get_drvdata(dev);
-
- if (data->group_pwm)
- sysfs_remove_group(&dev->kobj, data->group_pwm);
- if (data->group_in)
- sysfs_remove_group(&dev->kobj, data->group_in);
- if (data->group_fan)
- sysfs_remove_group(&dev->kobj, data->group_fan);
- if (data->group_temp)
- sysfs_remove_group(&dev->kobj, data->group_temp);
-
- sysfs_remove_group(&dev->kobj, &nct6775_group_other);
-}
-
-/* Get the monitoring functions started */
static inline void nct6775_init_device(struct nct6775_data *data)
{
int i;
pwm4pin = false;
pwm5pin = false;
pwm6pin = false;
- } else { /* NCT6779D or NCT6791D */
+ } else { /* NCT6779D, NCT6791D, or NCT6792D */
regval = superio_inb(sioreg, 0x1c);
fan3pin = !(regval & (1 << 5));
fan4min = fan4pin;
- if (data->kind == nct6791) {
+ if (data->kind == nct6791 || data->kind == nct6792) {
regval = superio_inb(sioreg, 0x2d);
fan6pin = (regval & (1 << 1));
pwm6pin = (regval & (1 << 0));
static int nct6775_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct nct6775_sio_data *sio_data = dev->platform_data;
+ struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
struct nct6775_data *data;
struct resource *res;
int i, s, err = 0;
int num_reg_temp, num_reg_temp_mon;
u8 cr2a;
struct attribute_group *group;
+ struct device *hwmon_dev;
+ int num_attr_groups = 0;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
break;
case nct6791:
+ case nct6792:
data->in_num = 15;
data->pwm_num = 6;
data->auto_pwm_num = 4;
data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
data->REG_ALARM = NCT6791_REG_ALARM;
- data->REG_BEEP = NCT6776_REG_BEEP;
+ if (data->kind == nct6791)
+ data->REG_BEEP = NCT6776_REG_BEEP;
+ else
+ data->REG_BEEP = NCT6792_REG_BEEP;
reg_temp = NCT6779_REG_TEMP;
- reg_temp_mon = NCT6779_REG_TEMP_MON;
num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
- num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
+ if (data->kind == nct6791) {
+ reg_temp_mon = NCT6779_REG_TEMP_MON;
+ num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
+ } else {
+ reg_temp_mon = NCT6792_REG_TEMP_MON;
+ num_reg_temp_mon = ARRAY_SIZE(NCT6792_REG_TEMP_MON);
+ }
reg_temp_over = NCT6779_REG_TEMP_OVER;
reg_temp_hyst = NCT6779_REG_TEMP_HYST;
reg_temp_config = NCT6779_REG_TEMP_CONFIG;
!strlen(data->temp_label[src])) {
dev_info(dev,
"Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
- src, i, data->REG_TEMP_SEL[i], reg_temp_mon[i]);
+ src, i, data->REG_TEMP_SEL[i],
+ reg_temp_mon[i]);
continue;
}
case nct6106:
case nct6779:
case nct6791:
+ case nct6792:
break;
}
tmp |= 0x3e;
break;
case nct6791:
+ case nct6792:
tmp |= 0x7e;
break;
}
/* Register sysfs hooks */
group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
data->pwm_num);
- if (IS_ERR(group)) {
- err = PTR_ERR(group);
- goto exit_remove;
- }
- data->group_pwm = group;
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+
+ data->groups[num_attr_groups++] = group;
group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
fls(data->have_in));
- if (IS_ERR(group)) {
- err = PTR_ERR(group);
- goto exit_remove;
- }
- data->group_in = group;
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+
+ data->groups[num_attr_groups++] = group;
group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
fls(data->has_fan));
- if (IS_ERR(group)) {
- err = PTR_ERR(group);
- goto exit_remove;
- }
- data->group_fan = group;
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+
+ data->groups[num_attr_groups++] = group;
group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
fls(data->have_temp));
- if (IS_ERR(group)) {
- err = PTR_ERR(group);
- goto exit_remove;
- }
- data->group_temp = group;
+ if (IS_ERR(group))
+ return PTR_ERR(group);
- err = sysfs_create_group(&dev->kobj, &nct6775_group_other);
- if (err)
- goto exit_remove;
+ data->groups[num_attr_groups++] = group;
+ data->groups[num_attr_groups++] = &nct6775_group_other;
- data->hwmon_dev = hwmon_device_register(dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+ err = sysfs_create_groups(&dev->kobj, data->groups);
+ if (err < 0)
+ return err;
+ hwmon_dev = hwmon_device_register(dev);
+ if (IS_ERR(hwmon_dev)) {
+ sysfs_remove_groups(&dev->kobj, data->groups);
+ return PTR_ERR(hwmon_dev);
}
-
- return 0;
-
-exit_remove:
- nct6775_device_remove_files(dev);
- return err;
+ data->hwmon_dev = hwmon_dev;
+#else
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
+ data, data->groups);
+#endif
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
static int nct6775_remove(struct platform_device *pdev)
{
struct nct6775_data *data = platform_get_drvdata(pdev);
hwmon_device_unregister(data->hwmon_dev);
- nct6775_device_remove_files(&pdev->dev);
-
+ sysfs_remove_groups(&pdev->dev.kobj, data->groups);
return 0;
}
+#endif
+
+static void nct6791_enable_io_mapping(int sioaddr)
+{
+ int val;
+
+ val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
+ if (val & 0x10) {
+ pr_info("Enabling hardware monitor logical device mappings.\n");
+ superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
+ val & ~0x10);
+ }
+}
-#ifdef CONFIG_PM
-static int nct6775_suspend(struct device *dev)
+static int __maybe_unused nct6775_suspend(struct device *dev)
{
struct nct6775_data *data = nct6775_update_device(dev);
return 0;
}
-static int nct6775_resume(struct device *dev)
+static int __maybe_unused nct6775_resume(struct device *dev)
{
struct nct6775_data *data = dev_get_drvdata(dev);
int i, j, err = 0;
mutex_lock(&data->update_lock);
data->bank = 0xff; /* Force initial bank selection */
- if (data->kind == nct6791) {
- int val;
-
+ if (data->kind == nct6791 || data->kind == nct6792) {
err = superio_enter(data->sioreg);
if (err)
goto abort;
- val = superio_inb(data->sioreg,
- NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
- if (val & 0x10) {
- pr_info("Re-enabling hardware monitor logical device mappings.\n");
- superio_outb(data->sioreg,
- NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
- val & ~0x10);
- }
+ nct6791_enable_io_mapping(data->sioreg);
superio_exit(data->sioreg);
}
data->valid = false;
mutex_unlock(&data->update_lock);
- return 0;
+ return err;
}
-static const struct dev_pm_ops nct6775_dev_pm_ops = {
- .suspend = nct6775_suspend,
- .resume = nct6775_resume,
-};
-
-#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
-#else
-#define NCT6775_DEV_PM_OPS NULL
-#endif /* CONFIG_PM */
+static SIMPLE_DEV_PM_OPS(nct6775_dev_pm_ops, nct6775_suspend, nct6775_resume);
static struct platform_driver nct6775_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRVNAME,
- .pm = NCT6775_DEV_PM_OPS,
+ .pm = &nct6775_dev_pm_ops,
},
.probe = nct6775_probe,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
.remove = nct6775_remove,
+#endif
};
static const char * const nct6775_sio_names[] __initconst = {
"NCT6776D/F",
"NCT6779D",
"NCT6791D",
+ "NCT6792D",
};
/* nct6775_find() looks for a '627 in the Super-I/O config space */
case SIO_NCT6791_ID:
sio_data->kind = nct6791;
break;
+ case SIO_NCT6792_ID:
+ sio_data->kind = nct6792;
+ break;
default:
if (val != 0xffff)
pr_debug("unsupported chip ID: 0x%04x\n", val);
pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
}
- if (sio_data->kind == nct6791) {
- val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
- if (val & 0x10) {
- pr_info("Enabling hardware monitor logical device mappings.\n");
- superio_outb(sioaddr,
- NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
- val & ~0x10);
- }
- }
+
+ if (sio_data->kind == nct6791 || sio_data->kind == nct6792)
+ nct6791_enable_io_mapping(sioaddr);
superio_exit(sioaddr);
pr_info("Found %s or compatible chip at %#x:%#x\n",
/*
* when Super-I/O functions move to a separate file, the Super-I/O
* bus will manage the lifetime of the device and this module will only keep
- * track of the nct6775 driver. But since we platform_device_alloc(), we
+ * track of the nct6775 driver. But since we use platform_device_alloc(), we
* must keep track of the device
*/
static struct platform_device *pdev[2];
pdev[i] = platform_device_alloc(DRVNAME, address);
if (!pdev[i]) {
err = -ENOMEM;
- goto exit_device_put;
+ goto exit_device_unregister;
}
err = platform_device_add_data(pdev[i], &sio_data,
return 0;
exit_device_put:
- for (i = 0; i < ARRAY_SIZE(pdev); i++) {
+ platform_device_put(pdev[i]);
+exit_device_unregister:
+ while (--i >= 0) {
if (pdev[i])
- platform_device_put(pdev[i]);
+ platform_device_unregister(pdev[i]);
}
exit_unregister:
platform_driver_unregister(&nct6775_driver);
}
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
-MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
+MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D/NCT6792D driver");
MODULE_LICENSE("GPL");
module_init(sensors_nct6775_init);