1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * XPower AXP288 PMIC operation region driver 4 * 5 * Copyright (C) 2014 Intel Corporation. All rights reserved. 6 */ 7 8 #include <linux/acpi.h> 9 #include <linux/init.h> 10 #include <linux/mfd/axp20x.h> 11 #include <linux/regmap.h> 12 #include <linux/platform_device.h> 13 #include <asm/iosf_mbi.h> 14 #include "intel_pmic.h" 15 16 #define XPOWER_GPADC_LOW 0x5b 17 #define XPOWER_GPI1_CTRL 0x92 18 19 #define GPI1_LDO_MASK GENMASK(2, 0) 20 #define GPI1_LDO_ON (3 << 0) 21 #define GPI1_LDO_OFF (4 << 0) 22 23 #define AXP288_ADC_TS_CURRENT_ON_OFF_MASK GENMASK(1, 0) 24 #define AXP288_ADC_TS_CURRENT_OFF (0 << 0) 25 #define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING (1 << 0) 26 #define AXP288_ADC_TS_CURRENT_ON_ONDEMAND (2 << 0) 27 #define AXP288_ADC_TS_CURRENT_ON (3 << 0) 28 29 static struct pmic_table power_table[] = { 30 { 31 .address = 0x00, 32 .reg = 0x13, 33 .bit = 0x05, 34 }, /* ALD1 */ 35 { 36 .address = 0x04, 37 .reg = 0x13, 38 .bit = 0x06, 39 }, /* ALD2 */ 40 { 41 .address = 0x08, 42 .reg = 0x13, 43 .bit = 0x07, 44 }, /* ALD3 */ 45 { 46 .address = 0x0c, 47 .reg = 0x12, 48 .bit = 0x03, 49 }, /* DLD1 */ 50 { 51 .address = 0x10, 52 .reg = 0x12, 53 .bit = 0x04, 54 }, /* DLD2 */ 55 { 56 .address = 0x14, 57 .reg = 0x12, 58 .bit = 0x05, 59 }, /* DLD3 */ 60 { 61 .address = 0x18, 62 .reg = 0x12, 63 .bit = 0x06, 64 }, /* DLD4 */ 65 { 66 .address = 0x1c, 67 .reg = 0x12, 68 .bit = 0x00, 69 }, /* ELD1 */ 70 { 71 .address = 0x20, 72 .reg = 0x12, 73 .bit = 0x01, 74 }, /* ELD2 */ 75 { 76 .address = 0x24, 77 .reg = 0x12, 78 .bit = 0x02, 79 }, /* ELD3 */ 80 { 81 .address = 0x28, 82 .reg = 0x13, 83 .bit = 0x02, 84 }, /* FLD1 */ 85 { 86 .address = 0x2c, 87 .reg = 0x13, 88 .bit = 0x03, 89 }, /* FLD2 */ 90 { 91 .address = 0x30, 92 .reg = 0x13, 93 .bit = 0x04, 94 }, /* FLD3 */ 95 { 96 .address = 0x34, 97 .reg = 0x10, 98 .bit = 0x03, 99 }, /* BUC1 */ 100 { 101 .address = 0x38, 102 .reg = 0x10, 103 .bit = 0x06, 104 }, /* BUC2 */ 105 { 106 .address = 0x3c, 107 .reg = 0x10, 108 .bit = 0x05, 109 }, /* BUC3 */ 110 { 111 .address = 0x40, 112 .reg = 0x10, 113 .bit = 0x04, 114 }, /* BUC4 */ 115 { 116 .address = 0x44, 117 .reg = 0x10, 118 .bit = 0x01, 119 }, /* BUC5 */ 120 { 121 .address = 0x48, 122 .reg = 0x10, 123 .bit = 0x00 124 }, /* BUC6 */ 125 { 126 .address = 0x4c, 127 .reg = 0x92, 128 }, /* GPI1 */ 129 }; 130 131 /* TMP0 - TMP5 are the same, all from GPADC */ 132 static struct pmic_table thermal_table[] = { 133 { 134 .address = 0x00, 135 .reg = XPOWER_GPADC_LOW 136 }, 137 { 138 .address = 0x0c, 139 .reg = XPOWER_GPADC_LOW 140 }, 141 { 142 .address = 0x18, 143 .reg = XPOWER_GPADC_LOW 144 }, 145 { 146 .address = 0x24, 147 .reg = XPOWER_GPADC_LOW 148 }, 149 { 150 .address = 0x30, 151 .reg = XPOWER_GPADC_LOW 152 }, 153 { 154 .address = 0x3c, 155 .reg = XPOWER_GPADC_LOW 156 }, 157 }; 158 159 static int intel_xpower_pmic_get_power(struct regmap *regmap, int reg, 160 int bit, u64 *value) 161 { 162 int data; 163 164 if (regmap_read(regmap, reg, &data)) 165 return -EIO; 166 167 /* GPIO1 LDO regulator needs special handling */ 168 if (reg == XPOWER_GPI1_CTRL) 169 *value = ((data & GPI1_LDO_MASK) == GPI1_LDO_ON); 170 else 171 *value = (data & BIT(bit)) ? 1 : 0; 172 173 return 0; 174 } 175 176 static int intel_xpower_pmic_update_power(struct regmap *regmap, int reg, 177 int bit, bool on) 178 { 179 int data, ret; 180 181 /* GPIO1 LDO regulator needs special handling */ 182 if (reg == XPOWER_GPI1_CTRL) 183 return regmap_update_bits(regmap, reg, GPI1_LDO_MASK, 184 on ? GPI1_LDO_ON : GPI1_LDO_OFF); 185 186 ret = iosf_mbi_block_punit_i2c_access(); 187 if (ret) 188 return ret; 189 190 if (regmap_read(regmap, reg, &data)) { 191 ret = -EIO; 192 goto out; 193 } 194 195 if (on) 196 data |= BIT(bit); 197 else 198 data &= ~BIT(bit); 199 200 if (regmap_write(regmap, reg, data)) 201 ret = -EIO; 202 out: 203 iosf_mbi_unblock_punit_i2c_access(); 204 205 return ret; 206 } 207 208 /** 209 * intel_xpower_pmic_get_raw_temp(): Get raw temperature reading from the PMIC 210 * 211 * @regmap: regmap of the PMIC device 212 * @reg: register to get the reading 213 * 214 * Return a positive value on success, errno on failure. 215 */ 216 static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) 217 { 218 int ret, adc_ts_pin_ctrl; 219 u8 buf[2]; 220 221 /* 222 * The current-source used for the battery temp-sensor (TS) is shared 223 * with the GPADC. For proper fuel-gauge and charger operation the TS 224 * current-source needs to be permanently on. But to read the GPADC we 225 * need to temporary switch the TS current-source to ondemand, so that 226 * the GPADC can use it, otherwise we will always read an all 0 value. 227 * 228 * Note that the switching from on to on-ondemand is not necessary 229 * when the TS current-source is off (this happens on devices which 230 * do not use the TS-pin). 231 */ 232 ret = regmap_read(regmap, AXP288_ADC_TS_PIN_CTRL, &adc_ts_pin_ctrl); 233 if (ret) 234 return ret; 235 236 if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) { 237 ret = regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL, 238 AXP288_ADC_TS_CURRENT_ON_OFF_MASK, 239 AXP288_ADC_TS_CURRENT_ON_ONDEMAND); 240 if (ret) 241 return ret; 242 243 /* Wait a bit after switching the current-source */ 244 usleep_range(6000, 10000); 245 } 246 247 ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2); 248 if (ret == 0) 249 ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f); 250 251 if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) { 252 regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL, 253 AXP288_ADC_TS_CURRENT_ON_OFF_MASK, 254 AXP288_ADC_TS_CURRENT_ON); 255 } 256 257 return ret; 258 } 259 260 static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { 261 .get_power = intel_xpower_pmic_get_power, 262 .update_power = intel_xpower_pmic_update_power, 263 .get_raw_temp = intel_xpower_pmic_get_raw_temp, 264 .power_table = power_table, 265 .power_table_count = ARRAY_SIZE(power_table), 266 .thermal_table = thermal_table, 267 .thermal_table_count = ARRAY_SIZE(thermal_table), 268 .pmic_i2c_address = 0x34, 269 }; 270 271 static acpi_status intel_xpower_pmic_gpio_handler(u32 function, 272 acpi_physical_address address, u32 bit_width, u64 *value, 273 void *handler_context, void *region_context) 274 { 275 return AE_OK; 276 } 277 278 static int intel_xpower_pmic_opregion_probe(struct platform_device *pdev) 279 { 280 struct device *parent = pdev->dev.parent; 281 struct axp20x_dev *axp20x = dev_get_drvdata(parent); 282 acpi_status status; 283 int result; 284 285 status = acpi_install_address_space_handler(ACPI_HANDLE(parent), 286 ACPI_ADR_SPACE_GPIO, intel_xpower_pmic_gpio_handler, 287 NULL, NULL); 288 if (ACPI_FAILURE(status)) 289 return -ENODEV; 290 291 result = intel_pmic_install_opregion_handler(&pdev->dev, 292 ACPI_HANDLE(parent), axp20x->regmap, 293 &intel_xpower_pmic_opregion_data); 294 if (result) 295 acpi_remove_address_space_handler(ACPI_HANDLE(parent), 296 ACPI_ADR_SPACE_GPIO, 297 intel_xpower_pmic_gpio_handler); 298 299 return result; 300 } 301 302 static struct platform_driver intel_xpower_pmic_opregion_driver = { 303 .probe = intel_xpower_pmic_opregion_probe, 304 .driver = { 305 .name = "axp288_pmic_acpi", 306 }, 307 }; 308 builtin_platform_driver(intel_xpower_pmic_opregion_driver); 309