// SPDX-License-Identifier: GPL-2.0-or-later /* * w83627ehf - Driver for the hardware monitoring functionality of * the Winbond W83627EHF Super-I/O chip * 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> * Daniel J Blueman <daniel.blueman@gmail.com> * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00) * * Shamelessly ripped from the w83627hf driver * Copyright (C) 2003 Mark Studebaker * * Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help * in testing and debugging this driver. * * This driver also supports the W83627EHG, which is the lead-free * version of the W83627EHF. * * Supports the following chips: * * Chip #vin #fan #pwm #temp chip IDs man ID * w83627ehf 10 5 4 3 0x8850 0x88 0x5ca3 * 0x8860 0xa1 * w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3 * w83627dhg-p 9 5 4 3 0xb070 0xc1 0x5ca3 * w83627uhg 8 2 2 3 0xa230 0xc1 0x5ca3 * w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3 * w83667hg-b 9 5 3 4 0xb350 0xc1 0x5ca3
*/
/* * Not currently used: * REG_MAN_ID has the value 0x5ca3 for all supported chips. * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model. * REG_MAN_ID is at port 0x4f * REG_CHIP_ID is at port 0x58
*/
/* Fan clock dividers are spread over the following five registers */ #define W83627EHF_REG_FANDIV1 0x47 #define W83627EHF_REG_FANDIV2 0x4B #define W83627EHF_REG_VBAT 0x5D #define W83627EHF_REG_DIODE 0x59 #define W83627EHF_REG_SMI_OVT 0x4C
struct mutex update_lock; bool valid; /* true if following fields are valid */ unsignedlong last_updated; /* In jiffies */
/* Register values */
u8 bank; /* current register bank */
u8 in_num; /* number of in inputs we have */
u8 in[10]; /* Register value */
u8 in_max[10]; /* Register value */
u8 in_min[10]; /* Register value */ unsignedint rpm[5];
u16 fan_min[5];
u8 fan_div[5];
u8 has_fan; /* some fan inputs can be disabled */
u8 has_fan_min; /* some fans don't have min register */
u8 temp_type[3];
s8 temp_offset[3];
s16 temp[9];
s16 temp_max[9];
s16 temp_max_hyst[9];
u32 alarms;
u8 caseopen;
u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
u8 pwm_enable[4]; /* 1->manual * 2->thermal cruise mode (also called SmartFan I) * 3->fan speed cruise mode * 4->variable thermal cruise (also called * SmartFan III) * 5->enhanced variable thermal cruise (also called * SmartFan IV)
*/
u8 pwm_enable_orig[4]; /* original value of pwm_enable */
u8 pwm_num; /* number of pwm */
u8 pwm[4];
u8 target_temp[4];
u8 tolerance[4];
u8 fan_start_output[4]; /* minimum fan speed when spinning up */
u8 fan_stop_output[4]; /* minimum fan speed when spinning down */
u8 fan_stop_time[4]; /* time at minimum before disabling fan */
u8 fan_max_output[4]; /* maximum fan speed */
u8 fan_step_output[4]; /* rate of change output value */
/* Remember extra register values over suspend/resume */
u8 vbat;
u8 fandiv1;
u8 fandiv2;
};
struct w83627ehf_sio_data { int sioreg; enum kinds kind;
};
/* * On older chips, only registers 0x50-0x5f are banked. * On more recent chips, all registers are banked. * Assume that is the case and set the bank number for each access. * Cache the bank number so it only needs to be set if it changes.
*/ staticinlinevoid w83627ehf_set_bank(struct w83627ehf_data *data, u16 reg)
{
u8 bank = reg >> 8; if (data->bank != bank) {
outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET);
outb_p(bank, data->addr + DATA_REG_OFFSET);
data->bank = bank;
}
}
if (data->has_fan_min & (1 << i))
data->fan_min[i] = w83627ehf_read_value(data,
W83627EHF_REG_FAN_MIN[i]);
/* * If we failed to measure the fan speed and clock * divider can be increased, let's try that for next * time
*/ if (reg >= 0xff && data->fan_div[i] < 0x07) {
dev_dbg(dev, "Increasing fan%d clock divider from %u to %u\n",
i + 1, div_from_reg(data->fan_div[i]),
div_from_reg(data->fan_div[i] + 1));
data->fan_div[i]++;
w83627ehf_write_fan_div(data, i); /* Preserve min limit if possible */ if ((data->has_fan_min & (1 << i))
&& data->fan_min[i] >= 2
&& data->fan_min[i] != 255)
w83627ehf_write_value(data,
W83627EHF_REG_FAN_MIN[i],
(data->fan_min[i] /= 2));
}
}
w83627ehf_update_pwm(data);
for (i = 0; i < data->pwm_num; i++) { if (!(data->has_fan & (1 << i))) continue;
staticint
store_fan_min(struct device *dev, struct w83627ehf_data *data, int channel, long val)
{ unsignedint reg;
u8 new_div;
if (val < 0) return -EINVAL;
mutex_lock(&data->update_lock); if (!val) { /* No min limit, alarm disabled */
data->fan_min[channel] = 255;
new_div = data->fan_div[channel]; /* No change */
dev_info(dev, "fan%u low limit and alarm disabled\n",
channel + 1);
} elseif ((reg = 1350000U / val) >= 128 * 255) { /* * Speed below this value cannot possibly be represented, * even with the highest divider (128)
*/
data->fan_min[channel] = 254;
new_div = 7; /* 128 == (1 << 7) */
dev_warn(dev, "fan%u low limit %lu below minimum %u, set to minimum\n",
channel + 1, val, fan_from_reg8(254, 7));
} elseif (!reg) { /* * Speed above this value cannot possibly be represented, * even with the lowest divider (1)
*/
data->fan_min[channel] = 1;
new_div = 0; /* 1 == (1 << 0) */
dev_warn(dev, "fan%u low limit %lu above maximum %u, set to maximum\n",
channel + 1, val, fan_from_reg8(1, 0));
} else { /* * Automatically pick the best divider, i.e. the one such * that the min limit will correspond to a register value * in the 96..192 range
*/
new_div = 0; while (reg > 192 && new_div < 7) {
reg >>= 1;
new_div++;
}
data->fan_min[channel] = reg;
}
/* * Write both the fan clock divider (if it changed) and the new * fan min (unconditionally)
*/ if (new_div != data->fan_div[channel]) {
dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
channel + 1, div_from_reg(data->fan_div[channel]),
div_from_reg(new_div));
data->fan_div[channel] = new_div;
w83627ehf_write_fan_div(data, channel); /* Give the chip time to sample a new speed value */
data->last_updated = jiffies;
}
/* Get the monitoring functions started */ staticinlinevoid w83627ehf_init_device(struct w83627ehf_data *data, enum kinds kind)
{ int i;
u8 tmp, diode;
/* Start monitoring is needed */
tmp = w83627ehf_read_value(data, W83627EHF_REG_CONFIG); if (!(tmp & 0x01))
w83627ehf_write_value(data, W83627EHF_REG_CONFIG,
tmp | 0x01);
/* Enable temperature sensors if needed */ for (i = 0; i < NUM_REG_TEMP; i++) { if (!(data->have_temp & (1 << i))) continue; if (!data->reg_temp_config[i]) continue;
tmp = w83627ehf_read_value(data,
data->reg_temp_config[i]); if (tmp & 0x01)
w83627ehf_write_value(data,
data->reg_temp_config[i],
tmp & 0xfe);
}
/* Enable VBAT monitoring if needed */
tmp = w83627ehf_read_value(data, W83627EHF_REG_VBAT); if (!(tmp & 0x01))
w83627ehf_write_value(data, W83627EHF_REG_VBAT, tmp | 0x01);
/* Get thermal sensor types */ switch (kind) { case w83627ehf:
diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE); break; case w83627uhg:
diode = 0x00; break; default:
diode = 0x70;
} for (i = 0; i < 3; i++) { constchar *label = NULL;
if (data->temp_label)
label = data->temp_label[data->temp_src[i]];
/* The W83627UHG is simple, only two fan inputs, no config */ if (sio_data->kind == w83627uhg) {
data->has_fan = 0x03; /* fan1 and fan2 */
data->has_fan_min = 0x03; return;
}
/* fan4 and fan5 share some pins with the GPIO and serial flash */ if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
fan3pin = 1;
fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40;
fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
} else {
fan3pin = 1;
fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06);
fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
}
/* * It looks like fan4 and fan5 pins can be alternatively used * as fan on/off switches, but fan5 control is write only :/ * We assume that if the serial interface is disabled, designers * connected fan5 as input unless they are emitting log 1, which * is not the default.
*/
regval = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1); if ((regval & (1 << 2)) && fan4pin) {
data->has_fan |= (1 << 3);
data->has_fan_min |= (1 << 3);
} if (!(regval & (1 << 1)) && fan5pin) {
data->has_fan |= (1 << 4);
data->has_fan_min |= (1 << 4);
}
}
res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!devm_request_region(dev, res->start, IOREGION_LENGTH, DRVNAME)) return -EBUSY;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM;
data->addr = res->start;
mutex_init(&data->lock);
mutex_init(&data->update_lock);
data->name = w83627ehf_device_names[sio_data->kind];
data->bank = 0xff; /* Force initial bank selection */
platform_set_drvdata(pdev, data);
/* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9; /* 667HG has 3 pwms, and 627UHG has only 2 */ switch (sio_data->kind) { default:
data->pwm_num = 4; break; case w83667hg: case w83667hg_b:
data->pwm_num = 3; break; case w83627uhg:
data->pwm_num = 2; break;
}
/* Default to 3 temperature inputs, code below will adjust as needed */
data->have_temp = 0x07;
/* Deal with temperature register setup first. */ if (sio_data->kind == w83667hg_b) {
u8 reg;
w83627ehf_set_temp_reg_ehf(data, 4);
/* * Temperature sources are selected with bank 0, registers 0x49 * and 0x4a.
*/
reg = w83627ehf_read_value(data, 0x4a);
data->temp_src[0] = reg >> 5;
reg = w83627ehf_read_value(data, 0x49);
data->temp_src[1] = reg & 0x07;
data->temp_src[2] = (reg >> 4) & 0x07;
/* * W83667HG-B has another temperature register at 0x7e. * The temperature source is selected with register 0x7d. * Support it if the source differs from already reported * sources.
*/
reg = w83627ehf_read_value(data, 0x7d);
reg &= 0x07; if (reg != data->temp_src[0] && reg != data->temp_src[1]
&& reg != data->temp_src[2]) {
data->temp_src[3] = reg;
data->have_temp |= 1 << 3;
}
/* * Chip supports either AUXTIN or VIN3. Try to find out which * one.
*/
reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]); if (data->temp_src[2] == 2 && (reg & 0x01))
data->have_temp &= ~(1 << 2);
/* Setup input voltage scaling factors */ if (sio_data->kind == w83627uhg)
data->scale_in = scale_in_w83627uhg; else
data->scale_in = scale_in_common;
/* Initialize the chip */
w83627ehf_init_device(data, sio_data->kind);
data->vrm = vid_which_vrm();
err = superio_enter(sio_data->sioreg); if (err) return err;
/* Read VID value */ if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { /* * W83667HG has different pins for VID input and output, so * we can get the VID input values directly at logical device D * 0xe3.
*/
superio_select(sio_data->sioreg, W83667HG_LD_VID);
data->vid = superio_inb(sio_data->sioreg, 0xe3);
data->have_vid = true;
} elseif (sio_data->kind != w83627uhg) {
superio_select(sio_data->sioreg, W83627EHF_LD_HWM); if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) { /* * Set VID input sensibility if needed. In theory the * BIOS should have set it, but in practice it's not * always the case. We only do it for the W83627EHF/EHG * because the W83627DHG is more complex in this * respect.
*/ if (sio_data->kind == w83627ehf) {
en_vrm10 = superio_inb(sio_data->sioreg,
SIO_REG_EN_VRM10); if ((en_vrm10 & 0x08) && data->vrm == 90) {
dev_warn(dev, "Setting VID input voltage to TTL\n");
superio_outb(sio_data->sioreg,
SIO_REG_EN_VRM10,
en_vrm10 & ~0x08);
} elseif (!(en_vrm10 & 0x08)
&& data->vrm == 100) {
dev_warn(dev, "Setting VID input voltage to VRM10\n");
superio_outb(sio_data->sioreg,
SIO_REG_EN_VRM10,
en_vrm10 | 0x08);
}
}
data->vid = superio_inb(sio_data->sioreg,
SIO_REG_VID_DATA); if (sio_data->kind == w83627ehf) /* 6 VID pins only */
data->vid &= 0x3f;
data->have_vid = true;
} else {
dev_info(dev, "VID pins in output mode, CPU VID not available\n");
}
}
w83627ehf_check_fan_inputs(sio_data, data);
superio_exit(sio_data->sioreg);
/* Read fan clock dividers immediately */
w83627ehf_update_fan_div(data);
/* Read pwm data to save original values */
w83627ehf_update_pwm(data); for (i = 0; i < data->pwm_num; i++)
data->pwm_enable_orig[i] = data->pwm_enable[i];
for (i = 0; i < NUM_REG_TEMP; i++) { if (!(data->have_temp & (1 << i))) continue;
if (data->reg_temp_over[i])
w83627ehf_write_temp(data, data->reg_temp_over[i],
data->temp_max[i]); if (data->reg_temp_hyst[i])
w83627ehf_write_temp(data, data->reg_temp_hyst[i],
data->temp_max_hyst[i]); if (i > 2) continue; if (data->have_temp_offset & (1 << i))
w83627ehf_write_value(data,
W83627EHF_REG_TEMP_OFFSET[i],
data->temp_offset[i]);
}
/* Restore other settings */
w83627ehf_write_value(data, W83627EHF_REG_VBAT, data->vbat);
/* Force re-reading all values */
data->valid = false;
mutex_unlock(&data->update_lock);
err = superio_enter(sioaddr); if (err) return err;
if (force_id)
val = force_id; else
val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
| superio_inb(sioaddr, SIO_REG_DEVID + 1); switch (val & SIO_ID_MASK) { case SIO_W83627EHF_ID:
sio_data->kind = w83627ehf;
sio_name = sio_name_W83627EHF; break; case SIO_W83627EHG_ID:
sio_data->kind = w83627ehf;
sio_name = sio_name_W83627EHG; break; case SIO_W83627DHG_ID:
sio_data->kind = w83627dhg;
sio_name = sio_name_W83627DHG; break; case SIO_W83627DHG_P_ID:
sio_data->kind = w83627dhg_p;
sio_name = sio_name_W83627DHG_P; break; case SIO_W83627UHG_ID:
sio_data->kind = w83627uhg;
sio_name = sio_name_W83627UHG; break; case SIO_W83667HG_ID:
sio_data->kind = w83667hg;
sio_name = sio_name_W83667HG; break; case SIO_W83667HG_B_ID:
sio_data->kind = w83667hg_b;
sio_name = sio_name_W83667HG_B; break; default: if (val != 0xffff)
pr_debug("unsupported chip ID: 0x%04x\n", val);
superio_exit(sioaddr); return -ENODEV;
}
/* We have a known chip, find the HWM I/O address */
superio_select(sioaddr, W83627EHF_LD_HWM);
val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
| superio_inb(sioaddr, SIO_REG_ADDR + 1);
*addr = val & IOREGION_ALIGNMENT; if (*addr == 0) {
pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
superio_exit(sioaddr); return -ENODEV;
}
/* Activate logical device if needed */
val = superio_inb(sioaddr, SIO_REG_ENABLE); if (!(val & 0x01)) {
pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
}
/* * 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 w83627ehf driver.
*/ staticstruct platform_device *pdev;
/* * initialize sio_data->kind and sio_data->sioreg. * * when Super-I/O functions move to a separate file, the Super-I/O * driver will probe 0x2e and 0x4e and auto-detect the presence of a * w83627ehf hardware monitor, and call probe()
*/ if (w83627ehf_find(0x2e, &address, &sio_data) &&
w83627ehf_find(0x4e, &address, &sio_data)) return -ENODEV;
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.