/* * The following are undocumented in the data sheets however we * received the information in an email from Winbond tech support
*/ /* Sensor selection - not on 781d */ #define W83781D_REG_SCFG1 0x5D staticconst u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
/* * Note: we save and restore the fan minimum here, because its value is * determined in part by the fan divisor. This follows the principle of * least surprise; the user doesn't expect the fan minimum to change just * because the divisor changed.
*/ static ssize_t
store_fan_div(struct device *dev, struct device_attribute *da, constchar *buf, size_t count)
{ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct w83781d_data *data = dev_get_drvdata(dev); unsignedlong min; int nr = attr->index;
u8 reg; unsignedlong val; int err;
err = kstrtoul(buf, 10, &val); if (err) return err;
mutex_lock(&data->update_lock);
/* Save fan_min */
min = FAN_FROM_REG(data->fan_min[nr],
DIV_FROM_REG(data->fan_div[nr]));
/* * Assumes that adapter is of I2C, not ISA variety. * OTHERWISE DON'T CALL THIS
*/ staticint
w83781d_detect_subclients(struct i2c_client *new_client)
{ int i, val1 = 0, id; int err; int address = new_client->addr; unsignedshort sc_addr[2]; struct i2c_adapter *adapter = new_client->adapter; struct w83781d_data *data = i2c_get_clientdata(new_client); enum chips kind = data->type; int num_sc = 1;
id = i2c_adapter_id(adapter);
if (force_subclients[0] == id && force_subclients[1] == address) { for (i = 2; i <= 3; i++) { if (force_subclients[i] < 0x48 ||
force_subclients[i] > 0x4f) {
dev_err(&new_client->dev, "Invalid subclient address %d; must be 0x48-0x4f\n",
force_subclients[i]);
err = -EINVAL; goto ERROR_SC_1;
}
}
w83781d_write_value(data, W83781D_REG_I2C_SUBADDR,
(force_subclients[2] & 0x07) |
((force_subclients[3] & 0x07) << 4));
sc_addr[0] = force_subclients[2];
} else {
val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR);
sc_addr[0] = 0x48 + (val1 & 0x07);
}
for (i = 0; i < num_sc; i++) {
data->lm75[i] = i2c_new_dummy_device(adapter, sc_addr[i]); if (IS_ERR(data->lm75[i])) {
dev_err(&new_client->dev, "Subclient %d registration at address 0x%x failed.\n",
i, sc_addr[i]);
err = PTR_ERR(data->lm75[i]); if (i == 1) goto ERROR_SC_3; goto ERROR_SC_2;
}
}
return 0;
/* Undo inits in case of errors */
ERROR_SC_3:
i2c_unregister_device(data->lm75[0]);
ERROR_SC_2:
ERROR_SC_1: return err;
}
/* No clean up is done on error, it's up to the caller */ staticint
w83781d_create_files(struct device *dev, int kind, int is_isa)
{ int err;
err = sysfs_create_group(&dev->kobj, &w83781d_group); if (err) return err;
if (kind != w83783s) {
err = sysfs_create_group(&dev->kobj, &w83781d_group_in1); if (err) return err;
} if (kind != as99127f && kind != w83781d && kind != w83783s) {
err = sysfs_create_group(&dev->kobj, &w83781d_group_in78); if (err) return err;
} if (kind != w83783s) {
err = sysfs_create_group(&dev->kobj, &w83781d_group_temp3); if (err) return err;
if (kind != w83781d) {
err = sysfs_chmod_file(&dev->kobj,
&sensor_dev_attr_temp3_alarm.dev_attr.attr,
S_IRUGO | S_IWUSR); if (err) return err;
}
}
if (kind != w83781d && kind != as99127f) {
err = sysfs_create_group(&dev->kobj, &w83781d_group_pwm12); if (err) return err;
} if (kind == w83782d && !is_isa) {
err = sysfs_create_group(&dev->kobj, &w83781d_group_pwm34); if (err) return err;
}
if (kind != as99127f && kind != w83781d) {
err = device_create_file(dev,
&sensor_dev_attr_temp1_type.dev_attr); if (err) return err;
err = device_create_file(dev,
&sensor_dev_attr_temp2_type.dev_attr); if (err) return err; if (kind != w83783s) {
err = device_create_file(dev,
&sensor_dev_attr_temp3_type.dev_attr); if (err) return err;
}
}
return 0;
}
/* Return 0 if detection is successful, -ENODEV otherwise */ staticint
w83781d_detect(struct i2c_client *client, struct i2c_board_info *info)
{ int val1, val2; struct w83781d_data *isa = w83781d_data_if_isa(); struct i2c_adapter *adapter = client->adapter; int address = client->addr; constchar *client_name; enum vendor { winbond, asus } vendid;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV;
/* * We block updates of the ISA device to minimize the risk of * concurrent access to the same W83781D chip through different * interfaces.
*/ if (isa)
mutex_lock(&isa->update_lock);
if (i2c_smbus_read_byte_data(client, W83781D_REG_CONFIG) & 0x80) {
dev_dbg(&adapter->dev, "Detection of w83781d chip failed at step 3\n"); goto err_nodev;
}
val1 = i2c_smbus_read_byte_data(client, W83781D_REG_BANK);
val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN); /* Check for Winbond or Asus ID if in bank 0 */ if (!(val1 & 0x07) &&
((!(val1 & 0x80) && val2 != 0xa3 && val2 != 0xc3) ||
((val1 & 0x80) && val2 != 0x5c && val2 != 0x12))) {
dev_dbg(&adapter->dev, "Detection of w83781d chip failed at step 4\n"); goto err_nodev;
} /* * If Winbond SMBus, check address at 0x48. * Asus doesn't support, except for as99127f rev.2
*/ if ((!(val1 & 0x80) && val2 == 0xa3) ||
((val1 & 0x80) && val2 == 0x5c)) { if (i2c_smbus_read_byte_data(client, W83781D_REG_I2C_ADDR)
!= address) {
dev_dbg(&adapter->dev, "Detection of w83781d chip failed at step 5\n"); goto err_nodev;
}
}
/* Put it now into bank 0 and Vendor ID High Byte */
i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
(i2c_smbus_read_byte_data(client, W83781D_REG_BANK)
& 0x78) | 0x80);
/* Get the vendor ID */
val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN); if (val2 == 0x5c)
vendid = winbond; elseif (val2 == 0x12)
vendid = asus; else {
dev_dbg(&adapter->dev, "w83781d chip vendor is neither Winbond nor Asus\n"); goto err_nodev;
}
if (val1 <= 0x30 && w83781d_alias_detect(client, val1)) {
dev_dbg(&adapter->dev, "Device at 0x%02x appears to be the same as ISA device\n",
address); goto err_nodev;
}
if (isa)
mutex_unlock(&isa->update_lock);
strscpy(info->type, client_name, I2C_NAME_SIZE);
return 0;
err_nodev: if (isa)
mutex_unlock(&isa->update_lock); return -ENODEV;
}
bank = (reg >> 8) & 0x0f; if (bank > 2) /* switch banks */
i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
bank); if (bank == 0 || bank > 2) {
i2c_smbus_write_byte_data(client, reg & 0xff,
value & 0xff);
} else { /* switch to subclient */
cl = data->lm75[bank - 1]; /* convert from ISA to LM75 I2C addresses */ switch (reg & 0xff) { case 0x52: /* CONFIG */
i2c_smbus_write_byte_data(cl, 1, value & 0xff); break; case 0x53: /* HYST */
i2c_smbus_write_word_swapped(cl, 2, value); break; case 0x55: /* OVER */
i2c_smbus_write_word_swapped(cl, 3, value); break;
}
} if (bank > 2)
i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
return 0;
}
staticvoid
w83781d_init_device(struct device *dev)
{ struct w83781d_data *data = dev_get_drvdata(dev); int i, p; int type = data->type;
u8 tmp;
if (reset && type != as99127f) { /* * this resets registers we don't have * documentation for on the as99127f
*/ /* * Resetting the chip has been the default for a long time, * but it causes the BIOS initializations (fan clock dividers, * thermal sensor types...) to be lost, so it is now optional. * It might even go away if nobody reports it as being useful, * as I see very little reason why this would be needed at * all.
*/
dev_info(dev, "If reset=1 solved a problem you were having, please report!\n");
/* save these registers */
i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
p = w83781d_read_value(data, W83781D_REG_PWMCLK12); /* * Reset all except Watchdog values and last conversion values * This sets fan-divs to 2, among others
*/
w83781d_write_value(data, W83781D_REG_CONFIG, 0x80); /* * Restore the registers and disable power-on abnormal beep. * This saves FAN 1/2/3 input/output values set by BIOS.
*/
w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
w83781d_write_value(data, W83781D_REG_PWMCLK12, p); /* * Disable master beep-enable (reset turns it on). * Individual beep_mask should be reset to off but for some * reason disabling this bit helps some people not get beeped
*/
w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 0);
}
/* * Disable power-on abnormal beep, as advised by the datasheet. * Already done if reset=1.
*/ if (init && !reset && type != as99127f) {
i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
}
data->vrm = vid_which_vrm();
if ((type != w83781d) && (type != as99127f)) {
tmp = w83781d_read_value(data, W83781D_REG_SCFG1); for (i = 1; i <= 3; i++) { if (!(tmp & BIT_SCFG1[i - 1])) {
data->sens[i - 1] = 4;
} else { if (w83781d_read_value
(data,
W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
data->sens[i - 1] = 1; else
data->sens[i - 1] = 2;
} if (type == w83783s && i == 2) break;
}
}
if (init && type != as99127f) { /* Enable temp2 */
tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG); if (tmp & 0x01) {
dev_warn(dev, "Enabling temp2, readings might not make sense\n");
w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG,
tmp & 0xfe);
}
/* Enable temp3 */ if (type != w83783s) {
tmp = w83781d_read_value(data,
W83781D_REG_TEMP3_CONFIG); if (tmp & 0x01) {
dev_warn(dev, "Enabling temp3, readings might not make sense\n");
w83781d_write_value(data,
W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
}
}
}
for (i = 0; i <= 8; i++) { if (data->type == w83783s && i == 1) continue; /* 783S has no in1 */
data->in[i] =
w83781d_read_value(data, W83781D_REG_IN(i));
data->in_min[i] =
w83781d_read_value(data, W83781D_REG_IN_MIN(i));
data->in_max[i] =
w83781d_read_value(data, W83781D_REG_IN_MAX(i)); if ((data->type != w83782d) && (i == 6)) break;
} for (i = 0; i < 3; i++) {
data->fan[i] =
w83781d_read_value(data, W83781D_REG_FAN(i));
data->fan_min[i] =
w83781d_read_value(data, W83781D_REG_FAN_MIN(i));
} if (data->type != w83781d && data->type != as99127f) { for (i = 0; i < 4; i++) {
data->pwm[i] =
w83781d_read_value(data,
W83781D_REG_PWM[i]); /* Only W83782D on SMBus has PWM3 and PWM4 */ if ((data->type != w83782d || !client)
&& i == 1) break;
} /* Only PWM2 can be disabled */
data->pwm2_enable = (w83781d_read_value(data,
W83781D_REG_PWMCLK12) & 0x08) >> 3;
}
/* ISA device, if found */ staticstruct platform_device *pdev;
staticunsignedshort isa_address = 0x290;
/* * I2C devices get this name attribute automatically, but for ISA devices * we must create it by ourselves.
*/ static ssize_t
name_show(struct device *dev, struct device_attribute *devattr, char *buf)
{ struct w83781d_data *data = dev_get_drvdata(dev); return sprintf(buf, "%s\n", data->name);
} static DEVICE_ATTR_RO(name);
/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */ staticint w83781d_alias_detect(struct i2c_client *client, u8 chipid)
{ struct w83781d_data *isa; int i;
if (!pdev) /* No ISA chip */ return 0;
isa = platform_get_drvdata(pdev);
if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr) return 0; /* Address doesn't match */ if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid) return 0; /* Chip type doesn't match */
/* * We compare all the limit registers, the config register and the * interrupt mask registers
*/ for (i = 0x2b; i <= 0x3d; i++) { if (w83781d_read_value(isa, i) !=
i2c_smbus_read_byte_data(client, i)) return 0;
} if (w83781d_read_value(isa, W83781D_REG_CONFIG) !=
i2c_smbus_read_byte_data(client, W83781D_REG_CONFIG)) return 0; for (i = 0x43; i <= 0x46; i++) { if (w83781d_read_value(isa, i) !=
i2c_smbus_read_byte_data(client, i)) return 0;
}
return 1;
}
staticint
w83781d_read_value_isa(struct w83781d_data *data, u16 reg)
{ int word_sized, res;
/* * The SMBus locks itself, usually, but nothing may access the Winbond between * bank switches. ISA access must always be locked explicitly! * We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, * would slow down the W83781D access and should not be necessary. * There are some ugly typecasts here, but the good news is - they should * nowhere else be necessary!
*/ staticint
w83781d_read_value(struct w83781d_data *data, u16 reg)
{ struct i2c_client *client = data->client; int res;
mutex_lock(&data->lock); if (client)
res = w83781d_read_value_i2c(data, reg); else
res = w83781d_read_value_isa(data, reg);
mutex_unlock(&data->lock); return res;
}
/* Reserve the ISA region */
res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!devm_request_region(&pdev->dev,
res->start + W83781D_ADDR_REG_OFFSET, 2, "w83781d")) return -EBUSY;
data = devm_kzalloc(&pdev->dev, sizeof(struct w83781d_data),
GFP_KERNEL); if (!data) return -ENOMEM;
/* return 1 if a supported chip is found, 0 otherwise */ staticint __init
w83781d_isa_found(unsignedshort address)
{ int val, save, found = 0; int port;
/* * Some boards declare base+0 to base+7 as a PNP device, some base+4 * to base+7 and some base+5 to base+6. So we better request each port * individually for the probing phase.
*/ for (port = address; port < address + W83781D_EXTENT; port++) { if (!request_region(port, 1, "w83781d")) {
pr_debug("Failed to request port 0x%x\n", port); goto release;
}
}
#define REALLY_SLOW_IO /* * We need the timeouts for at least some W83781D-like * chips. But only if we read 'undefined' registers.
*/
val = inb_p(address + 1); if (inb_p(address + 2) != val
|| inb_p(address + 3) != val
|| inb_p(address + 7) != val) {
pr_debug("Detection failed at step %d\n", 1); goto release;
} #undef REALLY_SLOW_IO
/* * We should be able to change the 7 LSB of the address port. The * MSB (busy flag) should be clear initially, set after the write.
*/
save = inb_p(address + W83781D_ADDR_REG_OFFSET); if (save & 0x80) {
pr_debug("Detection failed at step %d\n", 2); goto release;
}
val = ~save & 0x7f;
outb_p(val, address + W83781D_ADDR_REG_OFFSET); if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) {
outb_p(save, address + W83781D_ADDR_REG_OFFSET);
pr_debug("Detection failed at step %d\n", 3); goto release;
}
/* We found a device, now see if it could be a W83781D */
outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET);
val = inb_p(address + W83781D_DATA_REG_OFFSET); if (val & 0x80) {
pr_debug("Detection failed at step %d\n", 4); goto release;
}
outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
save = inb_p(address + W83781D_DATA_REG_OFFSET);
outb_p(W83781D_REG_CHIPMAN, address + W83781D_ADDR_REG_OFFSET);
val = inb_p(address + W83781D_DATA_REG_OFFSET); if ((!(save & 0x80) && (val != 0xa3))
|| ((save & 0x80) && (val != 0x5c))) {
pr_debug("Detection failed at step %d\n", 5); goto release;
}
outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET);
val = inb_p(address + W83781D_DATA_REG_OFFSET); if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */
pr_debug("Detection failed at step %d\n", 6); goto release;
}
/* The busy flag should be clear again */ if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) {
pr_debug("Detection failed at step %d\n", 7); goto release;
}
/* Determine the chip type */
outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
save = inb_p(address + W83781D_DATA_REG_OFFSET);
outb_p(save & 0xf8, address + W83781D_DATA_REG_OFFSET);
outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET);
val = inb_p(address + W83781D_DATA_REG_OFFSET); if ((val & 0xfe) == 0x10 /* W83781D */
|| val == 0x30) /* W83782D */
found = 1;
if (found)
pr_info("Found a %s chip at %#x\n",
val == 0x30 ? "W83782D" : "W83781D", (int)address);
release: for (port--; port >= address; port--)
release_region(port, 1); return found;
}
staticint __init
sensors_w83781d_init(void)
{ int res;
/* * We register the ISA device first, so that we can skip the * registration of an I2C interface to the same device.
*/
res = w83781d_isa_register(); if (res) gotoexit;
res = i2c_add_driver(&w83781d_driver); if (res) goto exit_unreg_isa;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.