18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * TI TPS68470 PMIC operation region driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2017 Intel Corporation. All rights reserved. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Rajmohan Mani <rajmohan.mani@intel.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Based on drivers/acpi/pmic/intel_pmic* drivers 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/acpi.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/mfd/tps68470.h> 158c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 168c2ecf20Sopenharmony_ci#include <linux/regmap.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistruct tps68470_pmic_table { 198c2ecf20Sopenharmony_ci u32 address; /* operation region address */ 208c2ecf20Sopenharmony_ci u32 reg; /* corresponding register */ 218c2ecf20Sopenharmony_ci u32 bitmask; /* bit mask for power, clock */ 228c2ecf20Sopenharmony_ci}; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define TI_PMIC_POWER_OPREGION_ID 0xB0 258c2ecf20Sopenharmony_ci#define TI_PMIC_VR_VAL_OPREGION_ID 0xB1 268c2ecf20Sopenharmony_ci#define TI_PMIC_CLOCK_OPREGION_ID 0xB2 278c2ecf20Sopenharmony_ci#define TI_PMIC_CLKFREQ_OPREGION_ID 0xB3 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistruct tps68470_pmic_opregion { 308c2ecf20Sopenharmony_ci struct mutex lock; 318c2ecf20Sopenharmony_ci struct regmap *regmap; 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define S_IO_I2C_EN (BIT(0) | BIT(1)) 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic const struct tps68470_pmic_table power_table[] = { 378c2ecf20Sopenharmony_ci { 388c2ecf20Sopenharmony_ci .address = 0x00, 398c2ecf20Sopenharmony_ci .reg = TPS68470_REG_S_I2C_CTL, 408c2ecf20Sopenharmony_ci .bitmask = S_IO_I2C_EN, 418c2ecf20Sopenharmony_ci /* S_I2C_CTL */ 428c2ecf20Sopenharmony_ci }, 438c2ecf20Sopenharmony_ci { 448c2ecf20Sopenharmony_ci .address = 0x04, 458c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VCMCTL, 468c2ecf20Sopenharmony_ci .bitmask = BIT(0), 478c2ecf20Sopenharmony_ci /* VCMCTL */ 488c2ecf20Sopenharmony_ci }, 498c2ecf20Sopenharmony_ci { 508c2ecf20Sopenharmony_ci .address = 0x08, 518c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VAUX1CTL, 528c2ecf20Sopenharmony_ci .bitmask = BIT(0), 538c2ecf20Sopenharmony_ci /* VAUX1_CTL */ 548c2ecf20Sopenharmony_ci }, 558c2ecf20Sopenharmony_ci { 568c2ecf20Sopenharmony_ci .address = 0x0C, 578c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VAUX2CTL, 588c2ecf20Sopenharmony_ci .bitmask = BIT(0), 598c2ecf20Sopenharmony_ci /* VAUX2CTL */ 608c2ecf20Sopenharmony_ci }, 618c2ecf20Sopenharmony_ci { 628c2ecf20Sopenharmony_ci .address = 0x10, 638c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VACTL, 648c2ecf20Sopenharmony_ci .bitmask = BIT(0), 658c2ecf20Sopenharmony_ci /* VACTL */ 668c2ecf20Sopenharmony_ci }, 678c2ecf20Sopenharmony_ci { 688c2ecf20Sopenharmony_ci .address = 0x14, 698c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VDCTL, 708c2ecf20Sopenharmony_ci .bitmask = BIT(0), 718c2ecf20Sopenharmony_ci /* VDCTL */ 728c2ecf20Sopenharmony_ci }, 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* Table to set voltage regulator value */ 768c2ecf20Sopenharmony_cistatic const struct tps68470_pmic_table vr_val_table[] = { 778c2ecf20Sopenharmony_ci { 788c2ecf20Sopenharmony_ci .address = 0x00, 798c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VSIOVAL, 808c2ecf20Sopenharmony_ci .bitmask = TPS68470_VSIOVAL_IOVOLT_MASK, 818c2ecf20Sopenharmony_ci /* TPS68470_REG_VSIOVAL */ 828c2ecf20Sopenharmony_ci }, 838c2ecf20Sopenharmony_ci { 848c2ecf20Sopenharmony_ci .address = 0x04, 858c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VIOVAL, 868c2ecf20Sopenharmony_ci .bitmask = TPS68470_VIOVAL_IOVOLT_MASK, 878c2ecf20Sopenharmony_ci /* TPS68470_REG_VIOVAL */ 888c2ecf20Sopenharmony_ci }, 898c2ecf20Sopenharmony_ci { 908c2ecf20Sopenharmony_ci .address = 0x08, 918c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VCMVAL, 928c2ecf20Sopenharmony_ci .bitmask = TPS68470_VCMVAL_VCVOLT_MASK, 938c2ecf20Sopenharmony_ci /* TPS68470_REG_VCMVAL */ 948c2ecf20Sopenharmony_ci }, 958c2ecf20Sopenharmony_ci { 968c2ecf20Sopenharmony_ci .address = 0x0C, 978c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VAUX1VAL, 988c2ecf20Sopenharmony_ci .bitmask = TPS68470_VAUX1VAL_AUX1VOLT_MASK, 998c2ecf20Sopenharmony_ci /* TPS68470_REG_VAUX1VAL */ 1008c2ecf20Sopenharmony_ci }, 1018c2ecf20Sopenharmony_ci { 1028c2ecf20Sopenharmony_ci .address = 0x10, 1038c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VAUX2VAL, 1048c2ecf20Sopenharmony_ci .bitmask = TPS68470_VAUX2VAL_AUX2VOLT_MASK, 1058c2ecf20Sopenharmony_ci /* TPS68470_REG_VAUX2VAL */ 1068c2ecf20Sopenharmony_ci }, 1078c2ecf20Sopenharmony_ci { 1088c2ecf20Sopenharmony_ci .address = 0x14, 1098c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VAVAL, 1108c2ecf20Sopenharmony_ci .bitmask = TPS68470_VAVAL_AVOLT_MASK, 1118c2ecf20Sopenharmony_ci /* TPS68470_REG_VAVAL */ 1128c2ecf20Sopenharmony_ci }, 1138c2ecf20Sopenharmony_ci { 1148c2ecf20Sopenharmony_ci .address = 0x18, 1158c2ecf20Sopenharmony_ci .reg = TPS68470_REG_VDVAL, 1168c2ecf20Sopenharmony_ci .bitmask = TPS68470_VDVAL_DVOLT_MASK, 1178c2ecf20Sopenharmony_ci /* TPS68470_REG_VDVAL */ 1188c2ecf20Sopenharmony_ci }, 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/* Table to configure clock frequency */ 1228c2ecf20Sopenharmony_cistatic const struct tps68470_pmic_table clk_freq_table[] = { 1238c2ecf20Sopenharmony_ci { 1248c2ecf20Sopenharmony_ci .address = 0x00, 1258c2ecf20Sopenharmony_ci .reg = TPS68470_REG_POSTDIV2, 1268c2ecf20Sopenharmony_ci .bitmask = BIT(0) | BIT(1), 1278c2ecf20Sopenharmony_ci /* TPS68470_REG_POSTDIV2 */ 1288c2ecf20Sopenharmony_ci }, 1298c2ecf20Sopenharmony_ci { 1308c2ecf20Sopenharmony_ci .address = 0x04, 1318c2ecf20Sopenharmony_ci .reg = TPS68470_REG_BOOSTDIV, 1328c2ecf20Sopenharmony_ci .bitmask = 0x1F, 1338c2ecf20Sopenharmony_ci /* TPS68470_REG_BOOSTDIV */ 1348c2ecf20Sopenharmony_ci }, 1358c2ecf20Sopenharmony_ci { 1368c2ecf20Sopenharmony_ci .address = 0x08, 1378c2ecf20Sopenharmony_ci .reg = TPS68470_REG_BUCKDIV, 1388c2ecf20Sopenharmony_ci .bitmask = 0x0F, 1398c2ecf20Sopenharmony_ci /* TPS68470_REG_BUCKDIV */ 1408c2ecf20Sopenharmony_ci }, 1418c2ecf20Sopenharmony_ci { 1428c2ecf20Sopenharmony_ci .address = 0x0C, 1438c2ecf20Sopenharmony_ci .reg = TPS68470_REG_PLLSWR, 1448c2ecf20Sopenharmony_ci .bitmask = 0x13, 1458c2ecf20Sopenharmony_ci /* TPS68470_REG_PLLSWR */ 1468c2ecf20Sopenharmony_ci }, 1478c2ecf20Sopenharmony_ci { 1488c2ecf20Sopenharmony_ci .address = 0x10, 1498c2ecf20Sopenharmony_ci .reg = TPS68470_REG_XTALDIV, 1508c2ecf20Sopenharmony_ci .bitmask = 0xFF, 1518c2ecf20Sopenharmony_ci /* TPS68470_REG_XTALDIV */ 1528c2ecf20Sopenharmony_ci }, 1538c2ecf20Sopenharmony_ci { 1548c2ecf20Sopenharmony_ci .address = 0x14, 1558c2ecf20Sopenharmony_ci .reg = TPS68470_REG_PLLDIV, 1568c2ecf20Sopenharmony_ci .bitmask = 0xFF, 1578c2ecf20Sopenharmony_ci /* TPS68470_REG_PLLDIV */ 1588c2ecf20Sopenharmony_ci }, 1598c2ecf20Sopenharmony_ci { 1608c2ecf20Sopenharmony_ci .address = 0x18, 1618c2ecf20Sopenharmony_ci .reg = TPS68470_REG_POSTDIV, 1628c2ecf20Sopenharmony_ci .bitmask = 0x83, 1638c2ecf20Sopenharmony_ci /* TPS68470_REG_POSTDIV */ 1648c2ecf20Sopenharmony_ci }, 1658c2ecf20Sopenharmony_ci}; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/* Table to configure and enable clocks */ 1688c2ecf20Sopenharmony_cistatic const struct tps68470_pmic_table clk_table[] = { 1698c2ecf20Sopenharmony_ci { 1708c2ecf20Sopenharmony_ci .address = 0x00, 1718c2ecf20Sopenharmony_ci .reg = TPS68470_REG_PLLCTL, 1728c2ecf20Sopenharmony_ci .bitmask = 0xF5, 1738c2ecf20Sopenharmony_ci /* TPS68470_REG_PLLCTL */ 1748c2ecf20Sopenharmony_ci }, 1758c2ecf20Sopenharmony_ci { 1768c2ecf20Sopenharmony_ci .address = 0x04, 1778c2ecf20Sopenharmony_ci .reg = TPS68470_REG_PLLCTL2, 1788c2ecf20Sopenharmony_ci .bitmask = BIT(0), 1798c2ecf20Sopenharmony_ci /* TPS68470_REG_PLLCTL2 */ 1808c2ecf20Sopenharmony_ci }, 1818c2ecf20Sopenharmony_ci { 1828c2ecf20Sopenharmony_ci .address = 0x08, 1838c2ecf20Sopenharmony_ci .reg = TPS68470_REG_CLKCFG1, 1848c2ecf20Sopenharmony_ci .bitmask = TPS68470_CLKCFG1_MODE_A_MASK | 1858c2ecf20Sopenharmony_ci TPS68470_CLKCFG1_MODE_B_MASK, 1868c2ecf20Sopenharmony_ci /* TPS68470_REG_CLKCFG1 */ 1878c2ecf20Sopenharmony_ci }, 1888c2ecf20Sopenharmony_ci { 1898c2ecf20Sopenharmony_ci .address = 0x0C, 1908c2ecf20Sopenharmony_ci .reg = TPS68470_REG_CLKCFG2, 1918c2ecf20Sopenharmony_ci .bitmask = TPS68470_CLKCFG1_MODE_A_MASK | 1928c2ecf20Sopenharmony_ci TPS68470_CLKCFG1_MODE_B_MASK, 1938c2ecf20Sopenharmony_ci /* TPS68470_REG_CLKCFG2 */ 1948c2ecf20Sopenharmony_ci }, 1958c2ecf20Sopenharmony_ci}; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int pmic_get_reg_bit(u64 address, 1988c2ecf20Sopenharmony_ci const struct tps68470_pmic_table *table, 1998c2ecf20Sopenharmony_ci const unsigned int table_size, int *reg, 2008c2ecf20Sopenharmony_ci int *bitmask) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci u64 i; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci i = address / 4; 2058c2ecf20Sopenharmony_ci if (i >= table_size) 2068c2ecf20Sopenharmony_ci return -ENOENT; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (!reg || !bitmask) 2098c2ecf20Sopenharmony_ci return -EINVAL; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci *reg = table[i].reg; 2128c2ecf20Sopenharmony_ci *bitmask = table[i].bitmask; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci return 0; 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cistatic int tps68470_pmic_get_power(struct regmap *regmap, int reg, 2188c2ecf20Sopenharmony_ci int bitmask, u64 *value) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci unsigned int data; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci if (regmap_read(regmap, reg, &data)) 2238c2ecf20Sopenharmony_ci return -EIO; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci *value = (data & bitmask) ? 1 : 0; 2268c2ecf20Sopenharmony_ci return 0; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic int tps68470_pmic_get_vr_val(struct regmap *regmap, int reg, 2308c2ecf20Sopenharmony_ci int bitmask, u64 *value) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci unsigned int data; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (regmap_read(regmap, reg, &data)) 2358c2ecf20Sopenharmony_ci return -EIO; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci *value = data & bitmask; 2388c2ecf20Sopenharmony_ci return 0; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic int tps68470_pmic_get_clk(struct regmap *regmap, int reg, 2428c2ecf20Sopenharmony_ci int bitmask, u64 *value) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci unsigned int data; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci if (regmap_read(regmap, reg, &data)) 2478c2ecf20Sopenharmony_ci return -EIO; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci *value = (data & bitmask) ? 1 : 0; 2508c2ecf20Sopenharmony_ci return 0; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic int tps68470_pmic_get_clk_freq(struct regmap *regmap, int reg, 2548c2ecf20Sopenharmony_ci int bitmask, u64 *value) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci unsigned int data; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci if (regmap_read(regmap, reg, &data)) 2598c2ecf20Sopenharmony_ci return -EIO; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci *value = data & bitmask; 2628c2ecf20Sopenharmony_ci return 0; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_cistatic int ti_tps68470_regmap_update_bits(struct regmap *regmap, int reg, 2668c2ecf20Sopenharmony_ci int bitmask, u64 value) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci return regmap_update_bits(regmap, reg, bitmask, value); 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_cistatic acpi_status tps68470_pmic_common_handler(u32 function, 2728c2ecf20Sopenharmony_ci acpi_physical_address address, 2738c2ecf20Sopenharmony_ci u32 bits, u64 *value, 2748c2ecf20Sopenharmony_ci void *region_context, 2758c2ecf20Sopenharmony_ci int (*get)(struct regmap *, 2768c2ecf20Sopenharmony_ci int, int, u64 *), 2778c2ecf20Sopenharmony_ci int (*update)(struct regmap *, 2788c2ecf20Sopenharmony_ci int, int, u64), 2798c2ecf20Sopenharmony_ci const struct tps68470_pmic_table *tbl, 2808c2ecf20Sopenharmony_ci unsigned int tbl_size) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci struct tps68470_pmic_opregion *opregion = region_context; 2838c2ecf20Sopenharmony_ci struct regmap *regmap = opregion->regmap; 2848c2ecf20Sopenharmony_ci int reg, ret, bitmask; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci if (bits != 32) 2878c2ecf20Sopenharmony_ci return AE_BAD_PARAMETER; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci ret = pmic_get_reg_bit(address, tbl, tbl_size, ®, &bitmask); 2908c2ecf20Sopenharmony_ci if (ret < 0) 2918c2ecf20Sopenharmony_ci return AE_BAD_PARAMETER; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci if (function == ACPI_WRITE && *value > bitmask) 2948c2ecf20Sopenharmony_ci return AE_BAD_PARAMETER; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci mutex_lock(&opregion->lock); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci ret = (function == ACPI_READ) ? 2998c2ecf20Sopenharmony_ci get(regmap, reg, bitmask, value) : 3008c2ecf20Sopenharmony_ci update(regmap, reg, bitmask, *value); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci mutex_unlock(&opregion->lock); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci return ret ? AE_ERROR : AE_OK; 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic acpi_status tps68470_pmic_cfreq_handler(u32 function, 3088c2ecf20Sopenharmony_ci acpi_physical_address address, 3098c2ecf20Sopenharmony_ci u32 bits, u64 *value, 3108c2ecf20Sopenharmony_ci void *handler_context, 3118c2ecf20Sopenharmony_ci void *region_context) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci return tps68470_pmic_common_handler(function, address, bits, value, 3148c2ecf20Sopenharmony_ci region_context, 3158c2ecf20Sopenharmony_ci tps68470_pmic_get_clk_freq, 3168c2ecf20Sopenharmony_ci ti_tps68470_regmap_update_bits, 3178c2ecf20Sopenharmony_ci clk_freq_table, 3188c2ecf20Sopenharmony_ci ARRAY_SIZE(clk_freq_table)); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic acpi_status tps68470_pmic_clk_handler(u32 function, 3228c2ecf20Sopenharmony_ci acpi_physical_address address, u32 bits, 3238c2ecf20Sopenharmony_ci u64 *value, void *handler_context, 3248c2ecf20Sopenharmony_ci void *region_context) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci return tps68470_pmic_common_handler(function, address, bits, value, 3278c2ecf20Sopenharmony_ci region_context, 3288c2ecf20Sopenharmony_ci tps68470_pmic_get_clk, 3298c2ecf20Sopenharmony_ci ti_tps68470_regmap_update_bits, 3308c2ecf20Sopenharmony_ci clk_table, 3318c2ecf20Sopenharmony_ci ARRAY_SIZE(clk_table)); 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic acpi_status tps68470_pmic_vrval_handler(u32 function, 3358c2ecf20Sopenharmony_ci acpi_physical_address address, 3368c2ecf20Sopenharmony_ci u32 bits, u64 *value, 3378c2ecf20Sopenharmony_ci void *handler_context, 3388c2ecf20Sopenharmony_ci void *region_context) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci return tps68470_pmic_common_handler(function, address, bits, value, 3418c2ecf20Sopenharmony_ci region_context, 3428c2ecf20Sopenharmony_ci tps68470_pmic_get_vr_val, 3438c2ecf20Sopenharmony_ci ti_tps68470_regmap_update_bits, 3448c2ecf20Sopenharmony_ci vr_val_table, 3458c2ecf20Sopenharmony_ci ARRAY_SIZE(vr_val_table)); 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic acpi_status tps68470_pmic_pwr_handler(u32 function, 3498c2ecf20Sopenharmony_ci acpi_physical_address address, 3508c2ecf20Sopenharmony_ci u32 bits, u64 *value, 3518c2ecf20Sopenharmony_ci void *handler_context, 3528c2ecf20Sopenharmony_ci void *region_context) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci if (bits != 32) 3558c2ecf20Sopenharmony_ci return AE_BAD_PARAMETER; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci /* set/clear for bit 0, bits 0 and 1 together */ 3588c2ecf20Sopenharmony_ci if (function == ACPI_WRITE && 3598c2ecf20Sopenharmony_ci !(*value == 0 || *value == 1 || *value == 3)) { 3608c2ecf20Sopenharmony_ci return AE_BAD_PARAMETER; 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci return tps68470_pmic_common_handler(function, address, bits, value, 3648c2ecf20Sopenharmony_ci region_context, 3658c2ecf20Sopenharmony_ci tps68470_pmic_get_power, 3668c2ecf20Sopenharmony_ci ti_tps68470_regmap_update_bits, 3678c2ecf20Sopenharmony_ci power_table, 3688c2ecf20Sopenharmony_ci ARRAY_SIZE(power_table)); 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic int tps68470_pmic_opregion_probe(struct platform_device *pdev) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci struct regmap *tps68470_regmap = dev_get_drvdata(pdev->dev.parent); 3748c2ecf20Sopenharmony_ci acpi_handle handle = ACPI_HANDLE(pdev->dev.parent); 3758c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 3768c2ecf20Sopenharmony_ci struct tps68470_pmic_opregion *opregion; 3778c2ecf20Sopenharmony_ci acpi_status status; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci if (!dev || !tps68470_regmap) { 3808c2ecf20Sopenharmony_ci dev_warn(dev, "dev or regmap is NULL\n"); 3818c2ecf20Sopenharmony_ci return -EINVAL; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci if (!handle) { 3858c2ecf20Sopenharmony_ci dev_warn(dev, "acpi handle is NULL\n"); 3868c2ecf20Sopenharmony_ci return -ENODEV; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci opregion = devm_kzalloc(dev, sizeof(*opregion), GFP_KERNEL); 3908c2ecf20Sopenharmony_ci if (!opregion) 3918c2ecf20Sopenharmony_ci return -ENOMEM; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci mutex_init(&opregion->lock); 3948c2ecf20Sopenharmony_ci opregion->regmap = tps68470_regmap; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci status = acpi_install_address_space_handler(handle, 3978c2ecf20Sopenharmony_ci TI_PMIC_POWER_OPREGION_ID, 3988c2ecf20Sopenharmony_ci tps68470_pmic_pwr_handler, 3998c2ecf20Sopenharmony_ci NULL, opregion); 4008c2ecf20Sopenharmony_ci if (ACPI_FAILURE(status)) 4018c2ecf20Sopenharmony_ci goto out_mutex_destroy; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci status = acpi_install_address_space_handler(handle, 4048c2ecf20Sopenharmony_ci TI_PMIC_VR_VAL_OPREGION_ID, 4058c2ecf20Sopenharmony_ci tps68470_pmic_vrval_handler, 4068c2ecf20Sopenharmony_ci NULL, opregion); 4078c2ecf20Sopenharmony_ci if (ACPI_FAILURE(status)) 4088c2ecf20Sopenharmony_ci goto out_remove_power_handler; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci status = acpi_install_address_space_handler(handle, 4118c2ecf20Sopenharmony_ci TI_PMIC_CLOCK_OPREGION_ID, 4128c2ecf20Sopenharmony_ci tps68470_pmic_clk_handler, 4138c2ecf20Sopenharmony_ci NULL, opregion); 4148c2ecf20Sopenharmony_ci if (ACPI_FAILURE(status)) 4158c2ecf20Sopenharmony_ci goto out_remove_vr_val_handler; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci status = acpi_install_address_space_handler(handle, 4188c2ecf20Sopenharmony_ci TI_PMIC_CLKFREQ_OPREGION_ID, 4198c2ecf20Sopenharmony_ci tps68470_pmic_cfreq_handler, 4208c2ecf20Sopenharmony_ci NULL, opregion); 4218c2ecf20Sopenharmony_ci if (ACPI_FAILURE(status)) 4228c2ecf20Sopenharmony_ci goto out_remove_clk_handler; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci return 0; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ciout_remove_clk_handler: 4278c2ecf20Sopenharmony_ci acpi_remove_address_space_handler(handle, TI_PMIC_CLOCK_OPREGION_ID, 4288c2ecf20Sopenharmony_ci tps68470_pmic_clk_handler); 4298c2ecf20Sopenharmony_ciout_remove_vr_val_handler: 4308c2ecf20Sopenharmony_ci acpi_remove_address_space_handler(handle, TI_PMIC_VR_VAL_OPREGION_ID, 4318c2ecf20Sopenharmony_ci tps68470_pmic_vrval_handler); 4328c2ecf20Sopenharmony_ciout_remove_power_handler: 4338c2ecf20Sopenharmony_ci acpi_remove_address_space_handler(handle, TI_PMIC_POWER_OPREGION_ID, 4348c2ecf20Sopenharmony_ci tps68470_pmic_pwr_handler); 4358c2ecf20Sopenharmony_ciout_mutex_destroy: 4368c2ecf20Sopenharmony_ci mutex_destroy(&opregion->lock); 4378c2ecf20Sopenharmony_ci return -ENODEV; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_cistatic struct platform_driver tps68470_pmic_opregion_driver = { 4418c2ecf20Sopenharmony_ci .probe = tps68470_pmic_opregion_probe, 4428c2ecf20Sopenharmony_ci .driver = { 4438c2ecf20Sopenharmony_ci .name = "tps68470_pmic_opregion", 4448c2ecf20Sopenharmony_ci }, 4458c2ecf20Sopenharmony_ci}; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cibuiltin_platform_driver(tps68470_pmic_opregion_driver) 448