diff options
Diffstat (limited to 'drivers/acpi/pmic/intel_pmic_xpower.c')
| -rw-r--r-- | drivers/acpi/pmic/intel_pmic_xpower.c | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c index e7c0006e6602..49bda5e0c8aa 100644 --- a/drivers/acpi/pmic/intel_pmic_xpower.c +++ b/drivers/acpi/pmic/intel_pmic_xpower.c @@ -26,7 +26,7 @@ #define AXP288_ADC_TS_CURRENT_ON_ONDEMAND (2 << 0) #define AXP288_ADC_TS_CURRENT_ON (3 << 0) -static struct pmic_table power_table[] = { +static const struct pmic_table power_table[] = { { .address = 0x00, .reg = 0x13, @@ -129,7 +129,7 @@ static struct pmic_table power_table[] = { }; /* TMP0 - TMP5 are the same, all from GPADC */ -static struct pmic_table thermal_table[] = { +static const struct pmic_table thermal_table[] = { { .address = 0x00, .reg = XPOWER_GPADC_LOW @@ -178,15 +178,17 @@ static int intel_xpower_pmic_update_power(struct regmap *regmap, int reg, { int data, ret; - /* GPIO1 LDO regulator needs special handling */ - if (reg == XPOWER_GPI1_CTRL) - return regmap_update_bits(regmap, reg, GPI1_LDO_MASK, - on ? GPI1_LDO_ON : GPI1_LDO_OFF); - ret = iosf_mbi_block_punit_i2c_access(); if (ret) return ret; + /* GPIO1 LDO regulator needs special handling */ + if (reg == XPOWER_GPI1_CTRL) { + ret = regmap_update_bits(regmap, reg, GPI1_LDO_MASK, + on ? GPI1_LDO_ON : GPI1_LDO_OFF); + goto out; + } + if (regmap_read(regmap, reg, &data)) { ret = -EIO; goto out; @@ -234,6 +236,11 @@ static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) return ret; if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) { + /* + * AXP288_ADC_TS_PIN_CTRL reads are cached by the regmap, so + * this does to a single I2C-transfer, and thus there is no + * need to explicitly call iosf_mbi_block_punit_i2c_access(). + */ ret = regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_CURRENT_ON_OFF_MASK, AXP288_ADC_TS_CURRENT_ON_ONDEMAND); @@ -244,7 +251,11 @@ static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) usleep_range(6000, 10000); } - ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2); + ret = iosf_mbi_block_punit_i2c_access(); + if (ret) + return ret; + + ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, sizeof(buf)); if (ret == 0) ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f); @@ -254,17 +265,67 @@ static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) AXP288_ADC_TS_CURRENT_ON); } + iosf_mbi_unblock_punit_i2c_access(); + + return ret; +} + +static int intel_xpower_exec_mipi_pmic_seq_element(struct regmap *regmap, + u16 i2c_address, u32 reg_address, + u32 value, u32 mask) +{ + struct device *dev = regmap_get_device(regmap); + int ret; + + if (i2c_address != 0x34) { + dev_err(dev, "Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n", + i2c_address, reg_address, value, mask); + return -ENXIO; + } + + ret = iosf_mbi_block_punit_i2c_access(); + if (ret) + return ret; + + ret = regmap_update_bits(regmap, reg_address, mask, value); + + iosf_mbi_unblock_punit_i2c_access(); + return ret; } -static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { +static int intel_xpower_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table, + int raw) +{ + struct acpi_lpat first = lpat_table->lpat[0]; + struct acpi_lpat last = lpat_table->lpat[lpat_table->lpat_count - 1]; + + /* + * Some LPAT tables in the ACPI Device for the AXP288 PMIC for some + * reason only describe a small temperature range, e.g. 27° - 37° + * Celcius. Resulting in errors when the tablet is idle in a cool room. + * + * To avoid these errors clamp the raw value to be inside the LPAT. + */ + if (first.raw < last.raw) + raw = clamp(raw, first.raw, last.raw); + else + raw = clamp(raw, last.raw, first.raw); + + return acpi_lpat_raw_to_temp(lpat_table, raw); +} + +static const struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { .get_power = intel_xpower_pmic_get_power, .update_power = intel_xpower_pmic_update_power, .get_raw_temp = intel_xpower_pmic_get_raw_temp, + .exec_mipi_pmic_seq_element = intel_xpower_exec_mipi_pmic_seq_element, + .lpat_raw_to_temp = intel_xpower_lpat_raw_to_temp, .power_table = power_table, .power_table_count = ARRAY_SIZE(power_table), .thermal_table = thermal_table, .thermal_table_count = ARRAY_SIZE(thermal_table), + .pmic_i2c_address = 0x34, }; static acpi_status intel_xpower_pmic_gpio_handler(u32 function, |
