intel_pmic_bxtwc.c (7895B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Intel BXT WhiskeyCove PMIC operation region driver 4 * 5 * Copyright (C) 2015 Intel Corporation. All rights reserved. 6 */ 7 8#include <linux/init.h> 9#include <linux/acpi.h> 10#include <linux/mfd/intel_soc_pmic.h> 11#include <linux/regmap.h> 12#include <linux/platform_device.h> 13#include "intel_pmic.h" 14 15#define WHISKEY_COVE_ALRT_HIGH_BIT_MASK 0x0F 16#define WHISKEY_COVE_ADC_HIGH_BIT(x) (((x & 0x0F) << 8)) 17#define WHISKEY_COVE_ADC_CURSRC(x) (((x & 0xF0) >> 4)) 18#define VR_MODE_DISABLED 0 19#define VR_MODE_AUTO BIT(0) 20#define VR_MODE_NORMAL BIT(1) 21#define VR_MODE_SWITCH BIT(2) 22#define VR_MODE_ECO (BIT(0)|BIT(1)) 23#define VSWITCH2_OUTPUT BIT(5) 24#define VSWITCH1_OUTPUT BIT(4) 25#define VUSBPHY_CHARGE BIT(1) 26 27static struct pmic_table power_table[] = { 28 { 29 .address = 0x0, 30 .reg = 0x63, 31 .bit = VR_MODE_AUTO, 32 }, /* VDD1 -> VDD1CNT */ 33 { 34 .address = 0x04, 35 .reg = 0x65, 36 .bit = VR_MODE_AUTO, 37 }, /* VDD2 -> VDD2CNT */ 38 { 39 .address = 0x08, 40 .reg = 0x67, 41 .bit = VR_MODE_AUTO, 42 }, /* VDD3 -> VDD3CNT */ 43 { 44 .address = 0x0c, 45 .reg = 0x6d, 46 .bit = VR_MODE_AUTO, 47 }, /* VLFX -> VFLEXCNT */ 48 { 49 .address = 0x10, 50 .reg = 0x6f, 51 .bit = VR_MODE_NORMAL, 52 }, /* VP1A -> VPROG1ACNT */ 53 { 54 .address = 0x14, 55 .reg = 0x70, 56 .bit = VR_MODE_NORMAL, 57 }, /* VP1B -> VPROG1BCNT */ 58 { 59 .address = 0x18, 60 .reg = 0x71, 61 .bit = VR_MODE_NORMAL, 62 }, /* VP1C -> VPROG1CCNT */ 63 { 64 .address = 0x1c, 65 .reg = 0x72, 66 .bit = VR_MODE_NORMAL, 67 }, /* VP1D -> VPROG1DCNT */ 68 { 69 .address = 0x20, 70 .reg = 0x73, 71 .bit = VR_MODE_NORMAL, 72 }, /* VP2A -> VPROG2ACNT */ 73 { 74 .address = 0x24, 75 .reg = 0x74, 76 .bit = VR_MODE_NORMAL, 77 }, /* VP2B -> VPROG2BCNT */ 78 { 79 .address = 0x28, 80 .reg = 0x75, 81 .bit = VR_MODE_NORMAL, 82 }, /* VP2C -> VPROG2CCNT */ 83 { 84 .address = 0x2c, 85 .reg = 0x76, 86 .bit = VR_MODE_NORMAL, 87 }, /* VP3A -> VPROG3ACNT */ 88 { 89 .address = 0x30, 90 .reg = 0x77, 91 .bit = VR_MODE_NORMAL, 92 }, /* VP3B -> VPROG3BCNT */ 93 { 94 .address = 0x34, 95 .reg = 0x78, 96 .bit = VSWITCH2_OUTPUT, 97 }, /* VSW2 -> VLD0CNT Bit 5*/ 98 { 99 .address = 0x38, 100 .reg = 0x78, 101 .bit = VSWITCH1_OUTPUT, 102 }, /* VSW1 -> VLD0CNT Bit 4 */ 103 { 104 .address = 0x3c, 105 .reg = 0x78, 106 .bit = VUSBPHY_CHARGE, 107 }, /* VUPY -> VLDOCNT Bit 1 */ 108 { 109 .address = 0x40, 110 .reg = 0x7b, 111 .bit = VR_MODE_NORMAL, 112 }, /* VRSO -> VREFSOCCNT*/ 113 { 114 .address = 0x44, 115 .reg = 0xA0, 116 .bit = VR_MODE_NORMAL, 117 }, /* VP1E -> VPROG1ECNT */ 118 { 119 .address = 0x48, 120 .reg = 0xA1, 121 .bit = VR_MODE_NORMAL, 122 }, /* VP1F -> VPROG1FCNT */ 123 { 124 .address = 0x4c, 125 .reg = 0xA2, 126 .bit = VR_MODE_NORMAL, 127 }, /* VP2D -> VPROG2DCNT */ 128 { 129 .address = 0x50, 130 .reg = 0xA3, 131 .bit = VR_MODE_NORMAL, 132 }, /* VP4A -> VPROG4ACNT */ 133 { 134 .address = 0x54, 135 .reg = 0xA4, 136 .bit = VR_MODE_NORMAL, 137 }, /* VP4B -> VPROG4BCNT */ 138 { 139 .address = 0x58, 140 .reg = 0xA5, 141 .bit = VR_MODE_NORMAL, 142 }, /* VP4C -> VPROG4CCNT */ 143 { 144 .address = 0x5c, 145 .reg = 0xA6, 146 .bit = VR_MODE_NORMAL, 147 }, /* VP4D -> VPROG4DCNT */ 148 { 149 .address = 0x60, 150 .reg = 0xA7, 151 .bit = VR_MODE_NORMAL, 152 }, /* VP5A -> VPROG5ACNT */ 153 { 154 .address = 0x64, 155 .reg = 0xA8, 156 .bit = VR_MODE_NORMAL, 157 }, /* VP5B -> VPROG5BCNT */ 158 { 159 .address = 0x68, 160 .reg = 0xA9, 161 .bit = VR_MODE_NORMAL, 162 }, /* VP6A -> VPROG6ACNT */ 163 { 164 .address = 0x6c, 165 .reg = 0xAA, 166 .bit = VR_MODE_NORMAL, 167 }, /* VP6B -> VPROG6BCNT */ 168 { 169 .address = 0x70, 170 .reg = 0x36, 171 .bit = BIT(2), 172 }, /* SDWN_N -> MODEMCTRL Bit 2 */ 173 { 174 .address = 0x74, 175 .reg = 0x36, 176 .bit = BIT(0), 177 } /* MOFF -> MODEMCTRL Bit 0 */ 178}; 179 180static struct pmic_table thermal_table[] = { 181 { 182 .address = 0x00, 183 .reg = 0x4F39 184 }, 185 { 186 .address = 0x04, 187 .reg = 0x4F24 188 }, 189 { 190 .address = 0x08, 191 .reg = 0x4F26 192 }, 193 { 194 .address = 0x0c, 195 .reg = 0x4F3B 196 }, 197 { 198 .address = 0x10, 199 .reg = 0x4F28 200 }, 201 { 202 .address = 0x14, 203 .reg = 0x4F2A 204 }, 205 { 206 .address = 0x18, 207 .reg = 0x4F3D 208 }, 209 { 210 .address = 0x1c, 211 .reg = 0x4F2C 212 }, 213 { 214 .address = 0x20, 215 .reg = 0x4F2E 216 }, 217 { 218 .address = 0x24, 219 .reg = 0x4F3F 220 }, 221 { 222 .address = 0x28, 223 .reg = 0x4F30 224 }, 225 { 226 .address = 0x30, 227 .reg = 0x4F41 228 }, 229 { 230 .address = 0x34, 231 .reg = 0x4F32 232 }, 233 { 234 .address = 0x3c, 235 .reg = 0x4F43 236 }, 237 { 238 .address = 0x40, 239 .reg = 0x4F34 240 }, 241 { 242 .address = 0x48, 243 .reg = 0x4F6A, 244 .bit = 0, 245 }, 246 { 247 .address = 0x4C, 248 .reg = 0x4F6A, 249 .bit = 1 250 }, 251 { 252 .address = 0x50, 253 .reg = 0x4F6A, 254 .bit = 2 255 }, 256 { 257 .address = 0x54, 258 .reg = 0x4F6A, 259 .bit = 4 260 }, 261 { 262 .address = 0x58, 263 .reg = 0x4F6A, 264 .bit = 5 265 }, 266 { 267 .address = 0x5C, 268 .reg = 0x4F6A, 269 .bit = 3 270 }, 271}; 272 273static int intel_bxtwc_pmic_get_power(struct regmap *regmap, int reg, 274 int bit, u64 *value) 275{ 276 int data; 277 278 if (regmap_read(regmap, reg, &data)) 279 return -EIO; 280 281 *value = (data & bit) ? 1 : 0; 282 return 0; 283} 284 285static int intel_bxtwc_pmic_update_power(struct regmap *regmap, int reg, 286 int bit, bool on) 287{ 288 u8 val, mask = bit; 289 290 if (on) 291 val = 0xFF; 292 else 293 val = 0x0; 294 295 return regmap_update_bits(regmap, reg, mask, val); 296} 297 298static int intel_bxtwc_pmic_get_raw_temp(struct regmap *regmap, int reg) 299{ 300 unsigned int val, adc_val, reg_val; 301 u8 temp_l, temp_h, cursrc; 302 unsigned long rlsb; 303 static const unsigned long rlsb_array[] = { 304 0, 260420, 130210, 65100, 32550, 16280, 305 8140, 4070, 2030, 0, 260420, 130210 }; 306 307 if (regmap_read(regmap, reg, &val)) 308 return -EIO; 309 temp_l = (u8) val; 310 311 if (regmap_read(regmap, (reg - 1), &val)) 312 return -EIO; 313 temp_h = (u8) val; 314 315 reg_val = temp_l | WHISKEY_COVE_ADC_HIGH_BIT(temp_h); 316 cursrc = WHISKEY_COVE_ADC_CURSRC(temp_h); 317 rlsb = rlsb_array[cursrc]; 318 adc_val = reg_val * rlsb / 1000; 319 320 return adc_val; 321} 322 323static int 324intel_bxtwc_pmic_update_aux(struct regmap *regmap, int reg, int raw) 325{ 326 u32 bsr_num; 327 u16 resi_val, count = 0, thrsh = 0; 328 u8 alrt_h, alrt_l, cursel = 0; 329 330 bsr_num = raw; 331 bsr_num /= (1 << 5); 332 333 count = fls(bsr_num) - 1; 334 335 cursel = clamp_t(s8, (count - 7), 0, 7); 336 thrsh = raw / (1 << (4 + cursel)); 337 338 resi_val = (cursel << 9) | thrsh; 339 alrt_h = (resi_val >> 8) & WHISKEY_COVE_ALRT_HIGH_BIT_MASK; 340 if (regmap_update_bits(regmap, 341 reg - 1, 342 WHISKEY_COVE_ALRT_HIGH_BIT_MASK, 343 alrt_h)) 344 return -EIO; 345 346 alrt_l = (u8)resi_val; 347 return regmap_write(regmap, reg, alrt_l); 348} 349 350static int 351intel_bxtwc_pmic_get_policy(struct regmap *regmap, int reg, int bit, u64 *value) 352{ 353 u8 mask = BIT(bit); 354 unsigned int val; 355 356 if (regmap_read(regmap, reg, &val)) 357 return -EIO; 358 359 *value = (val & mask) >> bit; 360 return 0; 361} 362 363static int 364intel_bxtwc_pmic_update_policy(struct regmap *regmap, 365 int reg, int bit, int enable) 366{ 367 u8 mask = BIT(bit), val = enable << bit; 368 369 return regmap_update_bits(regmap, reg, mask, val); 370} 371 372static const struct intel_pmic_opregion_data intel_bxtwc_pmic_opregion_data = { 373 .get_power = intel_bxtwc_pmic_get_power, 374 .update_power = intel_bxtwc_pmic_update_power, 375 .get_raw_temp = intel_bxtwc_pmic_get_raw_temp, 376 .update_aux = intel_bxtwc_pmic_update_aux, 377 .get_policy = intel_bxtwc_pmic_get_policy, 378 .update_policy = intel_bxtwc_pmic_update_policy, 379 .lpat_raw_to_temp = acpi_lpat_raw_to_temp, 380 .power_table = power_table, 381 .power_table_count = ARRAY_SIZE(power_table), 382 .thermal_table = thermal_table, 383 .thermal_table_count = ARRAY_SIZE(thermal_table), 384}; 385 386static int intel_bxtwc_pmic_opregion_probe(struct platform_device *pdev) 387{ 388 struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); 389 390 return intel_pmic_install_opregion_handler(&pdev->dev, 391 ACPI_HANDLE(pdev->dev.parent), 392 pmic->regmap, 393 &intel_bxtwc_pmic_opregion_data); 394} 395 396static const struct platform_device_id bxt_wc_opregion_id_table[] = { 397 { .name = "bxt_wcove_region" }, 398 {}, 399}; 400 401static struct platform_driver intel_bxtwc_pmic_opregion_driver = { 402 .probe = intel_bxtwc_pmic_opregion_probe, 403 .driver = { 404 .name = "bxt_whiskey_cove_pmic", 405 }, 406 .id_table = bxt_wc_opregion_id_table, 407}; 408builtin_platform_driver(intel_bxtwc_pmic_opregion_driver);