1 /* 2 * intel_pmic_xpower.c - XPower AXP288 PMIC operation region driver 3 * 4 * Copyright (C) 2014 Intel Corporation. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License version 8 * 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16 #include <linux/init.h> 17 #include <linux/acpi.h> 18 #include <linux/mfd/axp20x.h> 19 #include <linux/regmap.h> 20 #include <linux/platform_device.h> 21 #include "intel_pmic.h" 22 23 #define XPOWER_GPADC_LOW 0x5b 24 #define XPOWER_GPI1_CTRL 0x92 25 26 #define GPI1_LDO_MASK GENMASK(2, 0) 27 #define GPI1_LDO_ON (3 << 0) 28 #define GPI1_LDO_OFF (4 << 0) 29 30 #define AXP288_ADC_TS_PIN_GPADC 0xf2 31 #define AXP288_ADC_TS_PIN_ON 0xf3 32 33 static struct pmic_table power_table[] = { 34 { 35 .address = 0x00, 36 .reg = 0x13, 37 .bit = 0x05, 38 }, /* ALD1 */ 39 { 40 .address = 0x04, 41 .reg = 0x13, 42 .bit = 0x06, 43 }, /* ALD2 */ 44 { 45 .address = 0x08, 46 .reg = 0x13, 47 .bit = 0x07, 48 }, /* ALD3 */ 49 { 50 .address = 0x0c, 51 .reg = 0x12, 52 .bit = 0x03, 53 }, /* DLD1 */ 54 { 55 .address = 0x10, 56 .reg = 0x12, 57 .bit = 0x04, 58 }, /* DLD2 */ 59 { 60 .address = 0x14, 61 .reg = 0x12, 62 .bit = 0x05, 63 }, /* DLD3 */ 64 { 65 .address = 0x18, 66 .reg = 0x12, 67 .bit = 0x06, 68 }, /* DLD4 */ 69 { 70 .address = 0x1c, 71 .reg = 0x12, 72 .bit = 0x00, 73 }, /* ELD1 */ 74 { 75 .address = 0x20, 76 .reg = 0x12, 77 .bit = 0x01, 78 }, /* ELD2 */ 79 { 80 .address = 0x24, 81 .reg = 0x12, 82 .bit = 0x02, 83 }, /* ELD3 */ 84 { 85 .address = 0x28, 86 .reg = 0x13, 87 .bit = 0x02, 88 }, /* FLD1 */ 89 { 90 .address = 0x2c, 91 .reg = 0x13, 92 .bit = 0x03, 93 }, /* FLD2 */ 94 { 95 .address = 0x30, 96 .reg = 0x13, 97 .bit = 0x04, 98 }, /* FLD3 */ 99 { 100 .address = 0x34, 101 .reg = 0x10, 102 .bit = 0x03, 103 }, /* BUC1 */ 104 { 105 .address = 0x38, 106 .reg = 0x10, 107 .bit = 0x06, 108 }, /* BUC2 */ 109 { 110 .address = 0x3c, 111 .reg = 0x10, 112 .bit = 0x05, 113 }, /* BUC3 */ 114 { 115 .address = 0x40, 116 .reg = 0x10, 117 .bit = 0x04, 118 }, /* BUC4 */ 119 { 120 .address = 0x44, 121 .reg = 0x10, 122 .bit = 0x01, 123 }, /* BUC5 */ 124 { 125 .address = 0x48, 126 .reg = 0x10, 127 .bit = 0x00 128 }, /* BUC6 */ 129 { 130 .address = 0x4c, 131 .reg = 0x92, 132 }, /* GPI1 */ 133 }; 134 135 /* TMP0 - TMP5 are the same, all from GPADC */ 136 static struct pmic_table thermal_table[] = { 137 { 138 .address = 0x00, 139 .reg = XPOWER_GPADC_LOW 140 }, 141 { 142 .address = 0x0c, 143 .reg = XPOWER_GPADC_LOW 144 }, 145 { 146 .address = 0x18, 147 .reg = XPOWER_GPADC_LOW 148 }, 149 { 150 .address = 0x24, 151 .reg = XPOWER_GPADC_LOW 152 }, 153 { 154 .address = 0x30, 155 .reg = XPOWER_GPADC_LOW 156 }, 157 { 158 .address = 0x3c, 159 .reg = XPOWER_GPADC_LOW 160 }, 161 }; 162 163 static int intel_xpower_pmic_get_power(struct regmap *regmap, int reg, 164 int bit, u64 *value) 165 { 166 int data; 167 168 if (regmap_read(regmap, reg, &data)) 169 return -EIO; 170 171 /* GPIO1 LDO regulator needs special handling */ 172 if (reg == XPOWER_GPI1_CTRL) 173 *value = ((data & GPI1_LDO_MASK) == GPI1_LDO_ON); 174 else 175 *value = (data & BIT(bit)) ? 1 : 0; 176 177 return 0; 178 } 179 180 static int intel_xpower_pmic_update_power(struct regmap *regmap, int reg, 181 int bit, bool on) 182 { 183 int data; 184 185 /* GPIO1 LDO regulator needs special handling */ 186 if (reg == XPOWER_GPI1_CTRL) 187 return regmap_update_bits(regmap, reg, GPI1_LDO_MASK, 188 on ? GPI1_LDO_ON : GPI1_LDO_OFF); 189 190 if (regmap_read(regmap, reg, &data)) 191 return -EIO; 192 193 if (on) 194 data |= BIT(bit); 195 else 196 data &= ~BIT(bit); 197 198 if (regmap_write(regmap, reg, data)) 199 return -EIO; 200 201 return 0; 202 } 203 204 /** 205 * intel_xpower_pmic_get_raw_temp(): Get raw temperature reading from the PMIC 206 * 207 * @regmap: regmap of the PMIC device 208 * @reg: register to get the reading 209 * 210 * Return a positive value on success, errno on failure. 211 */ 212 static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) 213 { 214 u8 buf[2]; 215 int ret; 216 217 ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, 218 AXP288_ADC_TS_PIN_GPADC); 219 if (ret) 220 return ret; 221 222 /* After switching to the GPADC pin give things some time to settle */ 223 usleep_range(6000, 10000); 224 225 ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2); 226 if (ret == 0) 227 ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f); 228 229 regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON); 230 231 return ret; 232 } 233 234 static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { 235 .get_power = intel_xpower_pmic_get_power, 236 .update_power = intel_xpower_pmic_update_power, 237 .get_raw_temp = intel_xpower_pmic_get_raw_temp, 238 .power_table = power_table, 239 .power_table_count = ARRAY_SIZE(power_table), 240 .thermal_table = thermal_table, 241 .thermal_table_count = ARRAY_SIZE(thermal_table), 242 }; 243 244 static acpi_status intel_xpower_pmic_gpio_handler(u32 function, 245 acpi_physical_address address, u32 bit_width, u64 *value, 246 void *handler_context, void *region_context) 247 { 248 return AE_OK; 249 } 250 251 static int intel_xpower_pmic_opregion_probe(struct platform_device *pdev) 252 { 253 struct device *parent = pdev->dev.parent; 254 struct axp20x_dev *axp20x = dev_get_drvdata(parent); 255 acpi_status status; 256 int result; 257 258 status = acpi_install_address_space_handler(ACPI_HANDLE(parent), 259 ACPI_ADR_SPACE_GPIO, intel_xpower_pmic_gpio_handler, 260 NULL, NULL); 261 if (ACPI_FAILURE(status)) 262 return -ENODEV; 263 264 result = intel_pmic_install_opregion_handler(&pdev->dev, 265 ACPI_HANDLE(parent), axp20x->regmap, 266 &intel_xpower_pmic_opregion_data); 267 if (result) 268 acpi_remove_address_space_handler(ACPI_HANDLE(parent), 269 ACPI_ADR_SPACE_GPIO, 270 intel_xpower_pmic_gpio_handler); 271 272 return result; 273 } 274 275 static struct platform_driver intel_xpower_pmic_opregion_driver = { 276 .probe = intel_xpower_pmic_opregion_probe, 277 .driver = { 278 .name = "axp288_pmic_acpi", 279 }, 280 }; 281 builtin_platform_driver(intel_xpower_pmic_opregion_driver); 282