|
|
@@ -863,6 +863,73 @@ static struct vrm_model vrm_models[] = {
|
|
|
* Eden (Esther) */
|
|
|
};
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+/* Helper functions for IO access */
|
|
|
+static uint8_t hwm_read_reg(uint16_t hwm_base, uint8_t reg)
|
|
|
+{
|
|
|
+ outb(reg, hwm_base + HWM_INDEX_OFFSET);
|
|
|
+ return inb(hwm_base + HWM_DATA_OFFSET);
|
|
|
+}
|
|
|
+
|
|
|
+static void hwm_write_reg(uint16_t hwm_base, uint8_t reg, uint8_t val)
|
|
|
+{
|
|
|
+ outb(reg, hwm_base + HWM_INDEX_OFFSET);
|
|
|
+ outb(val, hwm_base + HWM_DATA_OFFSET);
|
|
|
+}
|
|
|
+
|
|
|
+static uint8_t hwm_read_reg_retry(uint16_t hwm_base, uint8_t reg)
|
|
|
+{
|
|
|
+ uint8_t v = hwm_read_reg(hwm_base, reg);
|
|
|
+ if (v == 0xFF) {
|
|
|
+ v = hwm_read_reg(hwm_base, reg);
|
|
|
+ }
|
|
|
+ return v;
|
|
|
+}
|
|
|
+
|
|
|
+static int vin_raw_to_volt(uint8_t raw, int r_top_kohm, int r_bottom_kohm)
|
|
|
+{
|
|
|
+ int vm = raw * 11;
|
|
|
+ if (r_top_kohm > 0 && r_bottom_kohm > 0) {
|
|
|
+ vm = (vm * (r_top_kohm + r_bottom_kohm)) / r_bottom_kohm;
|
|
|
+ }
|
|
|
+ return vm;
|
|
|
+}
|
|
|
+
|
|
|
+static int ec_raw_to_volt(uint8_t raw, int r_top_kohm, int r_bottom_kohm)
|
|
|
+{
|
|
|
+ int vm = raw * 12; /* EC unit: 10mV */
|
|
|
+ vm = (vm * (r_top_kohm + r_bottom_kohm)) / r_bottom_kohm;
|
|
|
+ return vm ;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int ec_wait_ibf(void)
|
|
|
+{
|
|
|
+ int i = 0;
|
|
|
+ while (inb(EC_CMD_PORT) & EC_IBF) {
|
|
|
+ if (++i > TIMEOUT_LOOPS) {
|
|
|
+ printk("Error: EC IBF Timeout!\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ udelay(1);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int ec_wait_obf(void)
|
|
|
+{
|
|
|
+ int i = 0;
|
|
|
+ while (!(inb(EC_CMD_PORT) & EC_OBF)) {
|
|
|
+ if (++i > TIMEOUT_LOOPS) {
|
|
|
+ printk("Error: EC OBF Timeout!\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ udelay(1);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Special case for VIA model D: there are two different possible
|
|
|
* VID tables, so we have to figure out first, which one must be
|
|
|
@@ -4055,6 +4122,76 @@ static ssize_t ac_power_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+static ssize_t voltage_vcore_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ int vlotage = 0;
|
|
|
+ uint8_t raw;
|
|
|
+ raw = hwm_read_reg_retry(IT8786_HWM_BASE_DEFAULT, 0x20);
|
|
|
+
|
|
|
+ vlotage = vin_raw_to_volt(raw, 0, 1);
|
|
|
+
|
|
|
+ return sprintf(buf, "%d", vlotage);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t voltage_vcore_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
+ const char *buf, size_t count)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static ssize_t voltage_5v_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ int vlotage = 0;
|
|
|
+ uint8_t raw;
|
|
|
+ raw = hwm_read_reg_retry(IT8786_HWM_BASE_DEFAULT, 0x22);
|
|
|
+
|
|
|
+ vlotage = vin_raw_to_volt(raw, 3, 2);
|
|
|
+
|
|
|
+ return sprintf(buf, "%d", vlotage);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t voltage_5v_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
+ const char *buf, size_t count)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static ssize_t voltage_12v_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ int vlotage = 0;
|
|
|
+ uint8_t raw;
|
|
|
+ if(oem_ec_read_ram(0x00, 0x6a, &raw) < 0)
|
|
|
+ {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ // raw = hwm_read_reg_retry(IT8786_HWM_BASE_DEFAULT, 0x6a);
|
|
|
+
|
|
|
+ vlotage = ec_raw_to_volt(raw, 10, 2);
|
|
|
+
|
|
|
+ return sprintf(buf, "%d", vlotage);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t voltage_12v_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
+ const char *buf, size_t count)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+static struct kobj_attribute voltage_vcore =
|
|
|
+ __ATTR(voltage_vcore, 0644, voltage_vcore_show, voltage_vcore_store);
|
|
|
+
|
|
|
+static struct kobj_attribute voltage_5v =
|
|
|
+ __ATTR(voltage_5v, 0644, voltage_5v_show, voltage_5v_store);
|
|
|
+
|
|
|
+static struct kobj_attribute voltage_12v =
|
|
|
+ __ATTR(voltage_12v, 0644, voltage_12v_show, voltage_12v_store);
|
|
|
+
|
|
|
static struct kobj_attribute power_flag =
|
|
|
__ATTR(power_flag, 0644, power_flag_show, power_flag_store);
|
|
|
|
|
|
@@ -4099,6 +4236,9 @@ static struct attribute *fan_attrs[] = {
|
|
|
&temp2_input.attr,
|
|
|
&power_flag.attr,
|
|
|
&ac_power.attr,
|
|
|
+ &voltage_vcore.attr,
|
|
|
+ &voltage_5v.attr,
|
|
|
+ &voltage_12v.attr,
|
|
|
NULL,
|
|
|
};
|
|
|
|