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 25 static struct pmic_table power_table[] = { 26 { 27 .address = 0x00, 28 .reg = 0x13, 29 .bit = 0x05, 30 }, /* ALD1 */ 31 { 32 .address = 0x04, 33 .reg = 0x13, 34 .bit = 0x06, 35 }, /* ALD2 */ 36 { 37 .address = 0x08, 38 .reg = 0x13, 39 .bit = 0x07, 40 }, /* ALD3 */ 41 { 42 .address = 0x0c, 43 .reg = 0x12, 44 .bit = 0x03, 45 }, /* DLD1 */ 46 { 47 .address = 0x10, 48 .reg = 0x12, 49 .bit = 0x04, 50 }, /* DLD2 */ 51 { 52 .address = 0x14, 53 .reg = 0x12, 54 .bit = 0x05, 55 }, /* DLD3 */ 56 { 57 .address = 0x18, 58 .reg = 0x12, 59 .bit = 0x06, 60 }, /* DLD4 */ 61 { 62 .address = 0x1c, 63 .reg = 0x12, 64 .bit = 0x00, 65 }, /* ELD1 */ 66 { 67 .address = 0x20, 68 .reg = 0x12, 69 .bit = 0x01, 70 }, /* ELD2 */ 71 { 72 .address = 0x24, 73 .reg = 0x12, 74 .bit = 0x02, 75 }, /* ELD3 */ 76 { 77 .address = 0x28, 78 .reg = 0x13, 79 .bit = 0x02, 80 }, /* FLD1 */ 81 { 82 .address = 0x2c, 83 .reg = 0x13, 84 .bit = 0x03, 85 }, /* FLD2 */ 86 { 87 .address = 0x30, 88 .reg = 0x13, 89 .bit = 0x04, 90 }, /* FLD3 */ 91 { 92 .address = 0x34, 93 .reg = 0x10, 94 .bit = 0x03, 95 }, /* BUC1 */ 96 { 97 .address = 0x38, 98 .reg = 0x10, 99 .bit = 0x06, 100 }, /* BUC2 */ 101 { 102 .address = 0x3c, 103 .reg = 0x10, 104 .bit = 0x05, 105 }, /* BUC3 */ 106 { 107 .address = 0x40, 108 .reg = 0x10, 109 .bit = 0x04, 110 }, /* BUC4 */ 111 { 112 .address = 0x44, 113 .reg = 0x10, 114 .bit = 0x01, 115 }, /* BUC5 */ 116 { 117 .address = 0x48, 118 .reg = 0x10, 119 .bit = 0x00 120 }, /* BUC6 */ 121 }; 122 123 /* TMP0 - TMP5 are the same, all from GPADC */ 124 static struct pmic_table thermal_table[] = { 125 { 126 .address = 0x00, 127 .reg = XPOWER_GPADC_LOW 128 }, 129 { 130 .address = 0x0c, 131 .reg = XPOWER_GPADC_LOW 132 }, 133 { 134 .address = 0x18, 135 .reg = XPOWER_GPADC_LOW 136 }, 137 { 138 .address = 0x24, 139 .reg = XPOWER_GPADC_LOW 140 }, 141 { 142 .address = 0x30, 143 .reg = XPOWER_GPADC_LOW 144 }, 145 { 146 .address = 0x3c, 147 .reg = XPOWER_GPADC_LOW 148 }, 149 }; 150 151 static int intel_xpower_pmic_get_power(struct regmap *regmap, int reg, 152 int bit, u64 *value) 153 { 154 int data; 155 156 if (regmap_read(regmap, reg, &data)) 157 return -EIO; 158 159 *value = (data & BIT(bit)) ? 1 : 0; 160 return 0; 161 } 162 163 static int intel_xpower_pmic_update_power(struct regmap *regmap, int reg, 164 int bit, bool on) 165 { 166 int data; 167 168 if (regmap_read(regmap, reg, &data)) 169 return -EIO; 170 171 if (on) 172 data |= BIT(bit); 173 else 174 data &= ~BIT(bit); 175 176 if (regmap_write(regmap, reg, data)) 177 return -EIO; 178 179 return 0; 180 } 181 182 /** 183 * intel_xpower_pmic_get_raw_temp(): Get raw temperature reading from the PMIC 184 * 185 * @regmap: regmap of the PMIC device 186 * @reg: register to get the reading 187 * 188 * Return a positive value on success, errno on failure. 189 */ 190 static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) 191 { 192 u8 buf[2]; 193 194 if (regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2)) 195 return -EIO; 196 197 return (buf[0] << 4) + ((buf[1] >> 4) & 0x0F); 198 } 199 200 static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { 201 .get_power = intel_xpower_pmic_get_power, 202 .update_power = intel_xpower_pmic_update_power, 203 .get_raw_temp = intel_xpower_pmic_get_raw_temp, 204 .power_table = power_table, 205 .power_table_count = ARRAY_SIZE(power_table), 206 .thermal_table = thermal_table, 207 .thermal_table_count = ARRAY_SIZE(thermal_table), 208 }; 209 210 static acpi_status intel_xpower_pmic_gpio_handler(u32 function, 211 acpi_physical_address address, u32 bit_width, u64 *value, 212 void *handler_context, void *region_context) 213 { 214 return AE_OK; 215 } 216 217 static int intel_xpower_pmic_opregion_probe(struct platform_device *pdev) 218 { 219 struct device *parent = pdev->dev.parent; 220 struct axp20x_dev *axp20x = dev_get_drvdata(parent); 221 acpi_status status; 222 int result; 223 224 status = acpi_install_address_space_handler(ACPI_HANDLE(parent), 225 ACPI_ADR_SPACE_GPIO, intel_xpower_pmic_gpio_handler, 226 NULL, NULL); 227 if (ACPI_FAILURE(status)) 228 return -ENODEV; 229 230 result = intel_pmic_install_opregion_handler(&pdev->dev, 231 ACPI_HANDLE(parent), axp20x->regmap, 232 &intel_xpower_pmic_opregion_data); 233 if (result) 234 acpi_remove_address_space_handler(ACPI_HANDLE(parent), 235 ACPI_ADR_SPACE_GPIO, 236 intel_xpower_pmic_gpio_handler); 237 238 return result; 239 } 240 241 static struct platform_driver intel_xpower_pmic_opregion_driver = { 242 .probe = intel_xpower_pmic_opregion_probe, 243 .driver = { 244 .name = "axp288_pmic_acpi", 245 }, 246 }; 247 248 static int __init intel_xpower_pmic_opregion_driver_init(void) 249 { 250 return platform_driver_register(&intel_xpower_pmic_opregion_driver); 251 } 252 device_initcall(intel_xpower_pmic_opregion_driver_init); 253