18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/module.h> 78c2ecf20Sopenharmony_ci#include <linux/delay.h> 88c2ecf20Sopenharmony_ci#include <linux/err.h> 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 118c2ecf20Sopenharmony_ci#include <linux/bitops.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <linux/of.h> 148c2ecf20Sopenharmony_ci#include <linux/of_device.h> 158c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 168c2ecf20Sopenharmony_ci#include <linux/ktime.h> 178c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h> 188c2ecf20Sopenharmony_ci#include <linux/regmap.h> 198c2ecf20Sopenharmony_ci#include <linux/list.h> 208c2ecf20Sopenharmony_ci#include <linux/mfd/syscon.h> 218c2ecf20Sopenharmony_ci#include <linux/io.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* Pin control enable input pins. */ 248c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_NONE 0x00 258c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN0 0x01 268c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN1 0x02 278c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN2 0x04 288c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN3 0x08 298c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT 0x10 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* Pin control high power mode input pins. */ 328c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_NONE 0x00 338c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_EN0 0x01 348c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_EN1 0x02 358c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_EN2 0x04 368c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_EN3 0x08 378c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_SLEEP_B 0x10 388c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT 0x20 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * Used with enable parameters to specify that hardware default register values 428c2ecf20Sopenharmony_ci * should be left unaltered. 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci#define SPMI_REGULATOR_USE_HW_DEFAULT 2 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* Soft start strength of a voltage switch type regulator */ 478c2ecf20Sopenharmony_cienum spmi_vs_soft_start_str { 488c2ecf20Sopenharmony_ci SPMI_VS_SOFT_START_STR_0P05_UA = 0, 498c2ecf20Sopenharmony_ci SPMI_VS_SOFT_START_STR_0P25_UA, 508c2ecf20Sopenharmony_ci SPMI_VS_SOFT_START_STR_0P55_UA, 518c2ecf20Sopenharmony_ci SPMI_VS_SOFT_START_STR_0P75_UA, 528c2ecf20Sopenharmony_ci SPMI_VS_SOFT_START_STR_HW_DEFAULT, 538c2ecf20Sopenharmony_ci}; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/** 568c2ecf20Sopenharmony_ci * struct spmi_regulator_init_data - spmi-regulator initialization data 578c2ecf20Sopenharmony_ci * @pin_ctrl_enable: Bit mask specifying which hardware pins should be 588c2ecf20Sopenharmony_ci * used to enable the regulator, if any 598c2ecf20Sopenharmony_ci * Value should be an ORing of 608c2ecf20Sopenharmony_ci * SPMI_REGULATOR_PIN_CTRL_ENABLE_* constants. If 618c2ecf20Sopenharmony_ci * the bit specified by 628c2ecf20Sopenharmony_ci * SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT is 638c2ecf20Sopenharmony_ci * set, then pin control enable hardware registers 648c2ecf20Sopenharmony_ci * will not be modified. 658c2ecf20Sopenharmony_ci * @pin_ctrl_hpm: Bit mask specifying which hardware pins should be 668c2ecf20Sopenharmony_ci * used to force the regulator into high power 678c2ecf20Sopenharmony_ci * mode, if any 688c2ecf20Sopenharmony_ci * Value should be an ORing of 698c2ecf20Sopenharmony_ci * SPMI_REGULATOR_PIN_CTRL_HPM_* constants. If 708c2ecf20Sopenharmony_ci * the bit specified by 718c2ecf20Sopenharmony_ci * SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT is 728c2ecf20Sopenharmony_ci * set, then pin control mode hardware registers 738c2ecf20Sopenharmony_ci * will not be modified. 748c2ecf20Sopenharmony_ci * @vs_soft_start_strength: This parameter sets the soft start strength for 758c2ecf20Sopenharmony_ci * voltage switch type regulators. Its value 768c2ecf20Sopenharmony_ci * should be one of SPMI_VS_SOFT_START_STR_*. If 778c2ecf20Sopenharmony_ci * its value is SPMI_VS_SOFT_START_STR_HW_DEFAULT, 788c2ecf20Sopenharmony_ci * then the soft start strength will be left at its 798c2ecf20Sopenharmony_ci * default hardware value. 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_cistruct spmi_regulator_init_data { 828c2ecf20Sopenharmony_ci unsigned pin_ctrl_enable; 838c2ecf20Sopenharmony_ci unsigned pin_ctrl_hpm; 848c2ecf20Sopenharmony_ci enum spmi_vs_soft_start_str vs_soft_start_strength; 858c2ecf20Sopenharmony_ci}; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* These types correspond to unique register layouts. */ 888c2ecf20Sopenharmony_cienum spmi_regulator_logical_type { 898c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_SMPS, 908c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_LDO, 918c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_VS, 928c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_BOOST, 938c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS, 948c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_BOOST_BYP, 958c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_LN_LDO, 968c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS, 978c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS, 988c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO, 998c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426, 1008c2ecf20Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_HFS430, 1018c2ecf20Sopenharmony_ci}; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cienum spmi_regulator_type { 1048c2ecf20Sopenharmony_ci SPMI_REGULATOR_TYPE_BUCK = 0x03, 1058c2ecf20Sopenharmony_ci SPMI_REGULATOR_TYPE_LDO = 0x04, 1068c2ecf20Sopenharmony_ci SPMI_REGULATOR_TYPE_VS = 0x05, 1078c2ecf20Sopenharmony_ci SPMI_REGULATOR_TYPE_BOOST = 0x1b, 1088c2ecf20Sopenharmony_ci SPMI_REGULATOR_TYPE_FTS = 0x1c, 1098c2ecf20Sopenharmony_ci SPMI_REGULATOR_TYPE_BOOST_BYP = 0x1f, 1108c2ecf20Sopenharmony_ci SPMI_REGULATOR_TYPE_ULT_LDO = 0x21, 1118c2ecf20Sopenharmony_ci SPMI_REGULATOR_TYPE_ULT_BUCK = 0x22, 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cienum spmi_regulator_subtype { 1158c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_GP_CTL = 0x08, 1168c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_RF_CTL = 0x09, 1178c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N50 = 0x01, 1188c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N150 = 0x02, 1198c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N300 = 0x03, 1208c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N600 = 0x04, 1218c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N1200 = 0x05, 1228c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N600_ST = 0x06, 1238c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N1200_ST = 0x07, 1248c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N900_ST = 0x14, 1258c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N300_ST = 0x15, 1268c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_P50 = 0x08, 1278c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_P150 = 0x09, 1288c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_P300 = 0x0a, 1298c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_P600 = 0x0b, 1308c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_P1200 = 0x0c, 1318c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LN = 0x10, 1328c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P50 = 0x28, 1338c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P150 = 0x29, 1348c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P300 = 0x2a, 1358c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P600 = 0x2b, 1368c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P1200 = 0x2c, 1378c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P450 = 0x2d, 1388c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_N300_ST = 0x30, 1398c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_N600_ST = 0x31, 1408c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_N1200_ST = 0x32, 1418c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_LVP150 = 0x3b, 1428c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_LVP300 = 0x3c, 1438c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_N300_ST = 0x42, 1448c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_N600_ST = 0x43, 1458c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_P50 = 0x46, 1468c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_P150 = 0x47, 1478c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_P600 = 0x49, 1488c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_LVP150 = 0x4d, 1498c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_LVP600 = 0x4f, 1508c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV100 = 0x01, 1518c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV300 = 0x02, 1528c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_MV300 = 0x08, 1538c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_MV500 = 0x09, 1548c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HDMI = 0x10, 1558c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_OTG = 0x11, 1568c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_5V_BOOST = 0x01, 1578c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_FTS_CTL = 0x08, 1588c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_FTS2p5_CTL = 0x09, 1598c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_FTS426_CTL = 0x0a, 1608c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_BB_2A = 0x01, 1618c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL1 = 0x0d, 1628c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL2 = 0x0e, 1638c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL3 = 0x0f, 1648c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10, 1658c2ecf20Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HFS430 = 0x0a, 1668c2ecf20Sopenharmony_ci}; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cienum spmi_common_regulator_registers { 1698c2ecf20Sopenharmony_ci SPMI_COMMON_REG_DIG_MAJOR_REV = 0x01, 1708c2ecf20Sopenharmony_ci SPMI_COMMON_REG_TYPE = 0x04, 1718c2ecf20Sopenharmony_ci SPMI_COMMON_REG_SUBTYPE = 0x05, 1728c2ecf20Sopenharmony_ci SPMI_COMMON_REG_VOLTAGE_RANGE = 0x40, 1738c2ecf20Sopenharmony_ci SPMI_COMMON_REG_VOLTAGE_SET = 0x41, 1748c2ecf20Sopenharmony_ci SPMI_COMMON_REG_MODE = 0x45, 1758c2ecf20Sopenharmony_ci SPMI_COMMON_REG_ENABLE = 0x46, 1768c2ecf20Sopenharmony_ci SPMI_COMMON_REG_PULL_DOWN = 0x48, 1778c2ecf20Sopenharmony_ci SPMI_COMMON_REG_SOFT_START = 0x4c, 1788c2ecf20Sopenharmony_ci SPMI_COMMON_REG_STEP_CTRL = 0x61, 1798c2ecf20Sopenharmony_ci}; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci/* 1828c2ecf20Sopenharmony_ci * Second common register layout used by newer devices starting with ftsmps426 1838c2ecf20Sopenharmony_ci * Note that some of the registers from the first common layout remain 1848c2ecf20Sopenharmony_ci * unchanged and their definition is not duplicated. 1858c2ecf20Sopenharmony_ci */ 1868c2ecf20Sopenharmony_cienum spmi_ftsmps426_regulator_registers { 1878c2ecf20Sopenharmony_ci SPMI_FTSMPS426_REG_VOLTAGE_LSB = 0x40, 1888c2ecf20Sopenharmony_ci SPMI_FTSMPS426_REG_VOLTAGE_MSB = 0x41, 1898c2ecf20Sopenharmony_ci SPMI_FTSMPS426_REG_VOLTAGE_ULS_LSB = 0x68, 1908c2ecf20Sopenharmony_ci SPMI_FTSMPS426_REG_VOLTAGE_ULS_MSB = 0x69, 1918c2ecf20Sopenharmony_ci}; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cienum spmi_vs_registers { 1948c2ecf20Sopenharmony_ci SPMI_VS_REG_OCP = 0x4a, 1958c2ecf20Sopenharmony_ci SPMI_VS_REG_SOFT_START = 0x4c, 1968c2ecf20Sopenharmony_ci}; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cienum spmi_boost_registers { 1998c2ecf20Sopenharmony_ci SPMI_BOOST_REG_CURRENT_LIMIT = 0x4a, 2008c2ecf20Sopenharmony_ci}; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cienum spmi_boost_byp_registers { 2038c2ecf20Sopenharmony_ci SPMI_BOOST_BYP_REG_CURRENT_LIMIT = 0x4b, 2048c2ecf20Sopenharmony_ci}; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cienum spmi_saw3_registers { 2078c2ecf20Sopenharmony_ci SAW3_SECURE = 0x00, 2088c2ecf20Sopenharmony_ci SAW3_ID = 0x04, 2098c2ecf20Sopenharmony_ci SAW3_SPM_STS = 0x0C, 2108c2ecf20Sopenharmony_ci SAW3_AVS_STS = 0x10, 2118c2ecf20Sopenharmony_ci SAW3_PMIC_STS = 0x14, 2128c2ecf20Sopenharmony_ci SAW3_RST = 0x18, 2138c2ecf20Sopenharmony_ci SAW3_VCTL = 0x1C, 2148c2ecf20Sopenharmony_ci SAW3_AVS_CTL = 0x20, 2158c2ecf20Sopenharmony_ci SAW3_AVS_LIMIT = 0x24, 2168c2ecf20Sopenharmony_ci SAW3_AVS_DLY = 0x28, 2178c2ecf20Sopenharmony_ci SAW3_AVS_HYSTERESIS = 0x2C, 2188c2ecf20Sopenharmony_ci SAW3_SPM_STS2 = 0x38, 2198c2ecf20Sopenharmony_ci SAW3_SPM_PMIC_DATA_3 = 0x4C, 2208c2ecf20Sopenharmony_ci SAW3_VERSION = 0xFD0, 2218c2ecf20Sopenharmony_ci}; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci/* Used for indexing into ctrl_reg. These are offets from 0x40 */ 2248c2ecf20Sopenharmony_cienum spmi_common_control_register_index { 2258c2ecf20Sopenharmony_ci SPMI_COMMON_IDX_VOLTAGE_RANGE = 0, 2268c2ecf20Sopenharmony_ci SPMI_COMMON_IDX_VOLTAGE_SET = 1, 2278c2ecf20Sopenharmony_ci SPMI_COMMON_IDX_MODE = 5, 2288c2ecf20Sopenharmony_ci SPMI_COMMON_IDX_ENABLE = 6, 2298c2ecf20Sopenharmony_ci}; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci/* Common regulator control register layout */ 2328c2ecf20Sopenharmony_ci#define SPMI_COMMON_ENABLE_MASK 0x80 2338c2ecf20Sopenharmony_ci#define SPMI_COMMON_ENABLE 0x80 2348c2ecf20Sopenharmony_ci#define SPMI_COMMON_DISABLE 0x00 2358c2ecf20Sopenharmony_ci#define SPMI_COMMON_ENABLE_FOLLOW_HW_EN3_MASK 0x08 2368c2ecf20Sopenharmony_ci#define SPMI_COMMON_ENABLE_FOLLOW_HW_EN2_MASK 0x04 2378c2ecf20Sopenharmony_ci#define SPMI_COMMON_ENABLE_FOLLOW_HW_EN1_MASK 0x02 2388c2ecf20Sopenharmony_ci#define SPMI_COMMON_ENABLE_FOLLOW_HW_EN0_MASK 0x01 2398c2ecf20Sopenharmony_ci#define SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK 0x0f 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci/* Common regulator mode register layout */ 2428c2ecf20Sopenharmony_ci#define SPMI_COMMON_MODE_HPM_MASK 0x80 2438c2ecf20Sopenharmony_ci#define SPMI_COMMON_MODE_AUTO_MASK 0x40 2448c2ecf20Sopenharmony_ci#define SPMI_COMMON_MODE_BYPASS_MASK 0x20 2458c2ecf20Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK 0x10 2468c2ecf20Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_HW_EN3_MASK 0x08 2478c2ecf20Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_HW_EN2_MASK 0x04 2488c2ecf20Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_HW_EN1_MASK 0x02 2498c2ecf20Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_HW_EN0_MASK 0x01 2508c2ecf20Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_ALL_MASK 0x1f 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_MODE_BYPASS_MASK 3 2538c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_MODE_RETENTION_MASK 4 2548c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_MODE_LPM_MASK 5 2558c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_MODE_AUTO_MASK 6 2568c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_MODE_HPM_MASK 7 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_MODE_MASK 0x07 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci/* Common regulator pull down control register layout */ 2618c2ecf20Sopenharmony_ci#define SPMI_COMMON_PULL_DOWN_ENABLE_MASK 0x80 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci/* LDO regulator current limit control register layout */ 2648c2ecf20Sopenharmony_ci#define SPMI_LDO_CURRENT_LIMIT_ENABLE_MASK 0x80 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci/* LDO regulator soft start control register layout */ 2678c2ecf20Sopenharmony_ci#define SPMI_LDO_SOFT_START_ENABLE_MASK 0x80 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci/* VS regulator over current protection control register layout */ 2708c2ecf20Sopenharmony_ci#define SPMI_VS_OCP_OVERRIDE 0x01 2718c2ecf20Sopenharmony_ci#define SPMI_VS_OCP_NO_OVERRIDE 0x00 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci/* VS regulator soft start control register layout */ 2748c2ecf20Sopenharmony_ci#define SPMI_VS_SOFT_START_ENABLE_MASK 0x80 2758c2ecf20Sopenharmony_ci#define SPMI_VS_SOFT_START_SEL_MASK 0x03 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci/* Boost regulator current limit control register layout */ 2788c2ecf20Sopenharmony_ci#define SPMI_BOOST_CURRENT_LIMIT_ENABLE_MASK 0x80 2798c2ecf20Sopenharmony_ci#define SPMI_BOOST_CURRENT_LIMIT_MASK 0x07 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci#define SPMI_VS_OCP_DEFAULT_MAX_RETRIES 10 2828c2ecf20Sopenharmony_ci#define SPMI_VS_OCP_DEFAULT_RETRY_DELAY_MS 30 2838c2ecf20Sopenharmony_ci#define SPMI_VS_OCP_FALL_DELAY_US 90 2848c2ecf20Sopenharmony_ci#define SPMI_VS_OCP_FAULT_DELAY_US 20000 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci#define SPMI_FTSMPS_STEP_CTRL_STEP_MASK 0x18 2878c2ecf20Sopenharmony_ci#define SPMI_FTSMPS_STEP_CTRL_STEP_SHIFT 3 2888c2ecf20Sopenharmony_ci#define SPMI_FTSMPS_STEP_CTRL_DELAY_MASK 0x07 2898c2ecf20Sopenharmony_ci#define SPMI_FTSMPS_STEP_CTRL_DELAY_SHIFT 0 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci/* Clock rate in kHz of the FTSMPS regulator reference clock. */ 2928c2ecf20Sopenharmony_ci#define SPMI_FTSMPS_CLOCK_RATE 19200 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci/* Minimum voltage stepper delay for each step. */ 2958c2ecf20Sopenharmony_ci#define SPMI_FTSMPS_STEP_DELAY 8 2968c2ecf20Sopenharmony_ci#define SPMI_DEFAULT_STEP_DELAY 20 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci/* 2998c2ecf20Sopenharmony_ci * The ratio SPMI_FTSMPS_STEP_MARGIN_NUM/SPMI_FTSMPS_STEP_MARGIN_DEN is used to 3008c2ecf20Sopenharmony_ci * adjust the step rate in order to account for oscillator variance. 3018c2ecf20Sopenharmony_ci */ 3028c2ecf20Sopenharmony_ci#define SPMI_FTSMPS_STEP_MARGIN_NUM 4 3038c2ecf20Sopenharmony_ci#define SPMI_FTSMPS_STEP_MARGIN_DEN 5 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_STEP_CTRL_DELAY_MASK 0x03 3068c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT 0 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci/* Clock rate in kHz of the FTSMPS426 regulator reference clock. */ 3098c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_CLOCK_RATE 4800 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci#define SPMI_HFS430_CLOCK_RATE 1600 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci/* Minimum voltage stepper delay for each step. */ 3148c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_STEP_DELAY 2 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci/* 3178c2ecf20Sopenharmony_ci * The ratio SPMI_FTSMPS426_STEP_MARGIN_NUM/SPMI_FTSMPS426_STEP_MARGIN_DEN is 3188c2ecf20Sopenharmony_ci * used to adjust the step rate in order to account for oscillator variance. 3198c2ecf20Sopenharmony_ci */ 3208c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_STEP_MARGIN_NUM 10 3218c2ecf20Sopenharmony_ci#define SPMI_FTSMPS426_STEP_MARGIN_DEN 11 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci/* VSET value to decide the range of ULT SMPS */ 3258c2ecf20Sopenharmony_ci#define ULT_SMPS_RANGE_SPLIT 0x60 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci/** 3288c2ecf20Sopenharmony_ci * struct spmi_voltage_range - regulator set point voltage mapping description 3298c2ecf20Sopenharmony_ci * @min_uV: Minimum programmable output voltage resulting from 3308c2ecf20Sopenharmony_ci * set point register value 0x00 3318c2ecf20Sopenharmony_ci * @max_uV: Maximum programmable output voltage 3328c2ecf20Sopenharmony_ci * @step_uV: Output voltage increase resulting from the set point 3338c2ecf20Sopenharmony_ci * register value increasing by 1 3348c2ecf20Sopenharmony_ci * @set_point_min_uV: Minimum allowed voltage 3358c2ecf20Sopenharmony_ci * @set_point_max_uV: Maximum allowed voltage. This may be tweaked in order 3368c2ecf20Sopenharmony_ci * to pick which range should be used in the case of 3378c2ecf20Sopenharmony_ci * overlapping set points. 3388c2ecf20Sopenharmony_ci * @n_voltages: Number of preferred voltage set points present in this 3398c2ecf20Sopenharmony_ci * range 3408c2ecf20Sopenharmony_ci * @range_sel: Voltage range register value corresponding to this range 3418c2ecf20Sopenharmony_ci * 3428c2ecf20Sopenharmony_ci * The following relationships must be true for the values used in this struct: 3438c2ecf20Sopenharmony_ci * (max_uV - min_uV) % step_uV == 0 3448c2ecf20Sopenharmony_ci * (set_point_min_uV - min_uV) % step_uV == 0* 3458c2ecf20Sopenharmony_ci * (set_point_max_uV - min_uV) % step_uV == 0* 3468c2ecf20Sopenharmony_ci * n_voltages = (set_point_max_uV - set_point_min_uV) / step_uV + 1 3478c2ecf20Sopenharmony_ci * 3488c2ecf20Sopenharmony_ci * *Note, set_point_min_uV == set_point_max_uV == 0 is allowed in order to 3498c2ecf20Sopenharmony_ci * specify that the voltage range has meaning, but is not preferred. 3508c2ecf20Sopenharmony_ci */ 3518c2ecf20Sopenharmony_cistruct spmi_voltage_range { 3528c2ecf20Sopenharmony_ci int min_uV; 3538c2ecf20Sopenharmony_ci int max_uV; 3548c2ecf20Sopenharmony_ci int step_uV; 3558c2ecf20Sopenharmony_ci int set_point_min_uV; 3568c2ecf20Sopenharmony_ci int set_point_max_uV; 3578c2ecf20Sopenharmony_ci unsigned n_voltages; 3588c2ecf20Sopenharmony_ci u8 range_sel; 3598c2ecf20Sopenharmony_ci}; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci/* 3628c2ecf20Sopenharmony_ci * The ranges specified in the spmi_voltage_set_points struct must be listed 3638c2ecf20Sopenharmony_ci * so that range[i].set_point_max_uV < range[i+1].set_point_min_uV. 3648c2ecf20Sopenharmony_ci */ 3658c2ecf20Sopenharmony_cistruct spmi_voltage_set_points { 3668c2ecf20Sopenharmony_ci struct spmi_voltage_range *range; 3678c2ecf20Sopenharmony_ci int count; 3688c2ecf20Sopenharmony_ci unsigned n_voltages; 3698c2ecf20Sopenharmony_ci}; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistruct spmi_regulator { 3728c2ecf20Sopenharmony_ci struct regulator_desc desc; 3738c2ecf20Sopenharmony_ci struct device *dev; 3748c2ecf20Sopenharmony_ci struct delayed_work ocp_work; 3758c2ecf20Sopenharmony_ci struct regmap *regmap; 3768c2ecf20Sopenharmony_ci struct spmi_voltage_set_points *set_points; 3778c2ecf20Sopenharmony_ci enum spmi_regulator_logical_type logical_type; 3788c2ecf20Sopenharmony_ci int ocp_irq; 3798c2ecf20Sopenharmony_ci int ocp_count; 3808c2ecf20Sopenharmony_ci int ocp_max_retries; 3818c2ecf20Sopenharmony_ci int ocp_retry_delay_ms; 3828c2ecf20Sopenharmony_ci int hpm_min_load; 3838c2ecf20Sopenharmony_ci int slew_rate; 3848c2ecf20Sopenharmony_ci ktime_t vs_enable_time; 3858c2ecf20Sopenharmony_ci u16 base; 3868c2ecf20Sopenharmony_ci struct list_head node; 3878c2ecf20Sopenharmony_ci}; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistruct spmi_regulator_mapping { 3908c2ecf20Sopenharmony_ci enum spmi_regulator_type type; 3918c2ecf20Sopenharmony_ci enum spmi_regulator_subtype subtype; 3928c2ecf20Sopenharmony_ci enum spmi_regulator_logical_type logical_type; 3938c2ecf20Sopenharmony_ci u32 revision_min; 3948c2ecf20Sopenharmony_ci u32 revision_max; 3958c2ecf20Sopenharmony_ci const struct regulator_ops *ops; 3968c2ecf20Sopenharmony_ci struct spmi_voltage_set_points *set_points; 3978c2ecf20Sopenharmony_ci int hpm_min_load; 3988c2ecf20Sopenharmony_ci}; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistruct spmi_regulator_data { 4018c2ecf20Sopenharmony_ci const char *name; 4028c2ecf20Sopenharmony_ci u16 base; 4038c2ecf20Sopenharmony_ci const char *supply; 4048c2ecf20Sopenharmony_ci const char *ocp; 4058c2ecf20Sopenharmony_ci u16 force_type; 4068c2ecf20Sopenharmony_ci}; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci#define SPMI_VREG(_type, _subtype, _dig_major_min, _dig_major_max, \ 4098c2ecf20Sopenharmony_ci _logical_type, _ops_val, _set_points_val, _hpm_min_load) \ 4108c2ecf20Sopenharmony_ci { \ 4118c2ecf20Sopenharmony_ci .type = SPMI_REGULATOR_TYPE_##_type, \ 4128c2ecf20Sopenharmony_ci .subtype = SPMI_REGULATOR_SUBTYPE_##_subtype, \ 4138c2ecf20Sopenharmony_ci .revision_min = _dig_major_min, \ 4148c2ecf20Sopenharmony_ci .revision_max = _dig_major_max, \ 4158c2ecf20Sopenharmony_ci .logical_type = SPMI_REGULATOR_LOGICAL_TYPE_##_logical_type, \ 4168c2ecf20Sopenharmony_ci .ops = &spmi_##_ops_val##_ops, \ 4178c2ecf20Sopenharmony_ci .set_points = &_set_points_val##_set_points, \ 4188c2ecf20Sopenharmony_ci .hpm_min_load = _hpm_min_load, \ 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci#define SPMI_VREG_VS(_subtype, _dig_major_min, _dig_major_max) \ 4228c2ecf20Sopenharmony_ci { \ 4238c2ecf20Sopenharmony_ci .type = SPMI_REGULATOR_TYPE_VS, \ 4248c2ecf20Sopenharmony_ci .subtype = SPMI_REGULATOR_SUBTYPE_##_subtype, \ 4258c2ecf20Sopenharmony_ci .revision_min = _dig_major_min, \ 4268c2ecf20Sopenharmony_ci .revision_max = _dig_major_max, \ 4278c2ecf20Sopenharmony_ci .logical_type = SPMI_REGULATOR_LOGICAL_TYPE_VS, \ 4288c2ecf20Sopenharmony_ci .ops = &spmi_vs_ops, \ 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci#define SPMI_VOLTAGE_RANGE(_range_sel, _min_uV, _set_point_min_uV, \ 4328c2ecf20Sopenharmony_ci _set_point_max_uV, _max_uV, _step_uV) \ 4338c2ecf20Sopenharmony_ci { \ 4348c2ecf20Sopenharmony_ci .min_uV = _min_uV, \ 4358c2ecf20Sopenharmony_ci .max_uV = _max_uV, \ 4368c2ecf20Sopenharmony_ci .set_point_min_uV = _set_point_min_uV, \ 4378c2ecf20Sopenharmony_ci .set_point_max_uV = _set_point_max_uV, \ 4388c2ecf20Sopenharmony_ci .step_uV = _step_uV, \ 4398c2ecf20Sopenharmony_ci .range_sel = _range_sel, \ 4408c2ecf20Sopenharmony_ci } 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci#define DEFINE_SPMI_SET_POINTS(name) \ 4438c2ecf20Sopenharmony_cistruct spmi_voltage_set_points name##_set_points = { \ 4448c2ecf20Sopenharmony_ci .range = name##_ranges, \ 4458c2ecf20Sopenharmony_ci .count = ARRAY_SIZE(name##_ranges), \ 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci/* 4498c2ecf20Sopenharmony_ci * These tables contain the physically available PMIC regulator voltage setpoint 4508c2ecf20Sopenharmony_ci * ranges. Where two ranges overlap in hardware, one of the ranges is trimmed 4518c2ecf20Sopenharmony_ci * to ensure that the setpoints available to software are monotonically 4528c2ecf20Sopenharmony_ci * increasing and unique. The set_voltage callback functions expect these 4538c2ecf20Sopenharmony_ci * properties to hold. 4548c2ecf20Sopenharmony_ci */ 4558c2ecf20Sopenharmony_cistatic struct spmi_voltage_range pldo_ranges[] = { 4568c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(2, 750000, 750000, 1537500, 1537500, 12500), 4578c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(3, 1500000, 1550000, 3075000, 3075000, 25000), 4588c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(4, 1750000, 3100000, 4900000, 4900000, 50000), 4598c2ecf20Sopenharmony_ci}; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cistatic struct spmi_voltage_range nldo1_ranges[] = { 4628c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(2, 750000, 750000, 1537500, 1537500, 12500), 4638c2ecf20Sopenharmony_ci}; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_cistatic struct spmi_voltage_range nldo2_ranges[] = { 4668c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 375000, 0, 0, 1537500, 12500), 4678c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 375000, 375000, 768750, 768750, 6250), 4688c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(2, 750000, 775000, 1537500, 1537500, 12500), 4698c2ecf20Sopenharmony_ci}; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_cistatic struct spmi_voltage_range nldo3_ranges[] = { 4728c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1537500, 1537500, 12500), 4738c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 375000, 0, 0, 1537500, 12500), 4748c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(2, 750000, 0, 0, 1537500, 12500), 4758c2ecf20Sopenharmony_ci}; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_cistatic struct spmi_voltage_range ln_ldo_ranges[] = { 4788c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 690000, 690000, 1110000, 1110000, 60000), 4798c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1380000, 1380000, 2220000, 2220000, 120000), 4808c2ecf20Sopenharmony_ci}; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_cistatic struct spmi_voltage_range smps_ranges[] = { 4838c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1562500, 1562500, 12500), 4848c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 1550000, 1575000, 3125000, 3125000, 25000), 4858c2ecf20Sopenharmony_ci}; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_cistatic struct spmi_voltage_range ftsmps_ranges[] = { 4888c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 0, 350000, 1275000, 1275000, 5000), 4898c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 0, 1280000, 2040000, 2040000, 10000), 4908c2ecf20Sopenharmony_ci}; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_cistatic struct spmi_voltage_range ftsmps2p5_ranges[] = { 4938c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 80000, 350000, 1355000, 1355000, 5000), 4948c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 160000, 1360000, 2200000, 2200000, 10000), 4958c2ecf20Sopenharmony_ci}; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cistatic struct spmi_voltage_range ftsmps426_ranges[] = { 4988c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 0, 320000, 1352000, 1352000, 4000), 4998c2ecf20Sopenharmony_ci}; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cistatic struct spmi_voltage_range boost_ranges[] = { 5028c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 4000000, 4000000, 5550000, 5550000, 50000), 5038c2ecf20Sopenharmony_ci}; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_cistatic struct spmi_voltage_range boost_byp_ranges[] = { 5068c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 2500000, 2500000, 5200000, 5650000, 50000), 5078c2ecf20Sopenharmony_ci}; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_cistatic struct spmi_voltage_range ult_lo_smps_ranges[] = { 5108c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1562500, 1562500, 12500), 5118c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 750000, 0, 0, 1525000, 25000), 5128c2ecf20Sopenharmony_ci}; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_cistatic struct spmi_voltage_range ult_ho_smps_ranges[] = { 5158c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1550000, 1550000, 2325000, 2325000, 25000), 5168c2ecf20Sopenharmony_ci}; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_cistatic struct spmi_voltage_range ult_nldo_ranges[] = { 5198c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1537500, 1537500, 12500), 5208c2ecf20Sopenharmony_ci}; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_cistatic struct spmi_voltage_range ult_pldo_ranges[] = { 5238c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1750000, 1750000, 3337500, 3337500, 12500), 5248c2ecf20Sopenharmony_ci}; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic struct spmi_voltage_range pldo660_ranges[] = { 5278c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1504000, 1504000, 3544000, 3544000, 8000), 5288c2ecf20Sopenharmony_ci}; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic struct spmi_voltage_range nldo660_ranges[] = { 5318c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000), 5328c2ecf20Sopenharmony_ci}; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic struct spmi_voltage_range ht_lvpldo_ranges[] = { 5358c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1504000, 1504000, 2000000, 2000000, 8000), 5368c2ecf20Sopenharmony_ci}; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_cistatic struct spmi_voltage_range ht_nldo_ranges[] = { 5398c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 312000, 312000, 1304000, 1304000, 8000), 5408c2ecf20Sopenharmony_ci}; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_cistatic struct spmi_voltage_range hfs430_ranges[] = { 5438c2ecf20Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000), 5448c2ecf20Sopenharmony_ci}; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(pldo); 5478c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(nldo1); 5488c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(nldo2); 5498c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(nldo3); 5508c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ln_ldo); 5518c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(smps); 5528c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ftsmps); 5538c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ftsmps2p5); 5548c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ftsmps426); 5558c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(boost); 5568c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(boost_byp); 5578c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ult_lo_smps); 5588c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ult_ho_smps); 5598c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ult_nldo); 5608c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ult_pldo); 5618c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(pldo660); 5628c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(nldo660); 5638c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ht_lvpldo); 5648c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ht_nldo); 5658c2ecf20Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(hfs430); 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_cistatic inline int spmi_vreg_read(struct spmi_regulator *vreg, u16 addr, u8 *buf, 5688c2ecf20Sopenharmony_ci int len) 5698c2ecf20Sopenharmony_ci{ 5708c2ecf20Sopenharmony_ci return regmap_bulk_read(vreg->regmap, vreg->base + addr, buf, len); 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_cistatic inline int spmi_vreg_write(struct spmi_regulator *vreg, u16 addr, 5748c2ecf20Sopenharmony_ci u8 *buf, int len) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci return regmap_bulk_write(vreg->regmap, vreg->base + addr, buf, len); 5778c2ecf20Sopenharmony_ci} 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_cistatic int spmi_vreg_update_bits(struct spmi_regulator *vreg, u16 addr, u8 val, 5808c2ecf20Sopenharmony_ci u8 mask) 5818c2ecf20Sopenharmony_ci{ 5828c2ecf20Sopenharmony_ci return regmap_update_bits(vreg->regmap, vreg->base + addr, mask, val); 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic int spmi_regulator_vs_enable(struct regulator_dev *rdev) 5868c2ecf20Sopenharmony_ci{ 5878c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci if (vreg->ocp_irq) { 5908c2ecf20Sopenharmony_ci vreg->ocp_count = 0; 5918c2ecf20Sopenharmony_ci vreg->vs_enable_time = ktime_get(); 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci return regulator_enable_regmap(rdev); 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic int spmi_regulator_vs_ocp(struct regulator_dev *rdev) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 6008c2ecf20Sopenharmony_ci u8 reg = SPMI_VS_OCP_OVERRIDE; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci return spmi_vreg_write(vreg, SPMI_VS_REG_OCP, ®, 1); 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_cistatic int spmi_regulator_select_voltage(struct spmi_regulator *vreg, 6068c2ecf20Sopenharmony_ci int min_uV, int max_uV) 6078c2ecf20Sopenharmony_ci{ 6088c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range; 6098c2ecf20Sopenharmony_ci int uV = min_uV; 6108c2ecf20Sopenharmony_ci int lim_min_uV, lim_max_uV, i, range_id, range_max_uV; 6118c2ecf20Sopenharmony_ci int selector, voltage_sel; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci /* Check if request voltage is outside of physically settable range. */ 6148c2ecf20Sopenharmony_ci lim_min_uV = vreg->set_points->range[0].set_point_min_uV; 6158c2ecf20Sopenharmony_ci lim_max_uV = 6168c2ecf20Sopenharmony_ci vreg->set_points->range[vreg->set_points->count - 1].set_point_max_uV; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci if (uV < lim_min_uV && max_uV >= lim_min_uV) 6198c2ecf20Sopenharmony_ci uV = lim_min_uV; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci if (uV < lim_min_uV || uV > lim_max_uV) { 6228c2ecf20Sopenharmony_ci dev_err(vreg->dev, 6238c2ecf20Sopenharmony_ci "request v=[%d, %d] is outside possible v=[%d, %d]\n", 6248c2ecf20Sopenharmony_ci min_uV, max_uV, lim_min_uV, lim_max_uV); 6258c2ecf20Sopenharmony_ci return -EINVAL; 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci /* Find the range which uV is inside of. */ 6298c2ecf20Sopenharmony_ci for (i = vreg->set_points->count - 1; i > 0; i--) { 6308c2ecf20Sopenharmony_ci range_max_uV = vreg->set_points->range[i - 1].set_point_max_uV; 6318c2ecf20Sopenharmony_ci if (uV > range_max_uV && range_max_uV > 0) 6328c2ecf20Sopenharmony_ci break; 6338c2ecf20Sopenharmony_ci } 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci range_id = i; 6368c2ecf20Sopenharmony_ci range = &vreg->set_points->range[range_id]; 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /* 6398c2ecf20Sopenharmony_ci * Force uV to be an allowed set point by applying a ceiling function to 6408c2ecf20Sopenharmony_ci * the uV value. 6418c2ecf20Sopenharmony_ci */ 6428c2ecf20Sopenharmony_ci voltage_sel = DIV_ROUND_UP(uV - range->min_uV, range->step_uV); 6438c2ecf20Sopenharmony_ci uV = voltage_sel * range->step_uV + range->min_uV; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci if (uV > max_uV) { 6468c2ecf20Sopenharmony_ci dev_err(vreg->dev, 6478c2ecf20Sopenharmony_ci "request v=[%d, %d] cannot be met by any set point; " 6488c2ecf20Sopenharmony_ci "next set point: %d\n", 6498c2ecf20Sopenharmony_ci min_uV, max_uV, uV); 6508c2ecf20Sopenharmony_ci return -EINVAL; 6518c2ecf20Sopenharmony_ci } 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci selector = 0; 6548c2ecf20Sopenharmony_ci for (i = 0; i < range_id; i++) 6558c2ecf20Sopenharmony_ci selector += vreg->set_points->range[i].n_voltages; 6568c2ecf20Sopenharmony_ci selector += (uV - range->set_point_min_uV) / range->step_uV; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci return selector; 6598c2ecf20Sopenharmony_ci} 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_cistatic int spmi_sw_selector_to_hw(struct spmi_regulator *vreg, 6628c2ecf20Sopenharmony_ci unsigned selector, u8 *range_sel, 6638c2ecf20Sopenharmony_ci u8 *voltage_sel) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range, *end; 6668c2ecf20Sopenharmony_ci unsigned offset; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci range = vreg->set_points->range; 6698c2ecf20Sopenharmony_ci end = range + vreg->set_points->count; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci for (; range < end; range++) { 6728c2ecf20Sopenharmony_ci if (selector < range->n_voltages) { 6738c2ecf20Sopenharmony_ci /* 6748c2ecf20Sopenharmony_ci * hardware selectors between set point min and real 6758c2ecf20Sopenharmony_ci * min are invalid so we ignore them 6768c2ecf20Sopenharmony_ci */ 6778c2ecf20Sopenharmony_ci offset = range->set_point_min_uV - range->min_uV; 6788c2ecf20Sopenharmony_ci offset /= range->step_uV; 6798c2ecf20Sopenharmony_ci *voltage_sel = selector + offset; 6808c2ecf20Sopenharmony_ci *range_sel = range->range_sel; 6818c2ecf20Sopenharmony_ci return 0; 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci selector -= range->n_voltages; 6858c2ecf20Sopenharmony_ci } 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci return -EINVAL; 6888c2ecf20Sopenharmony_ci} 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_cistatic int spmi_hw_selector_to_sw(struct spmi_regulator *vreg, u8 hw_sel, 6918c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range) 6928c2ecf20Sopenharmony_ci{ 6938c2ecf20Sopenharmony_ci unsigned sw_sel = 0; 6948c2ecf20Sopenharmony_ci unsigned offset, max_hw_sel; 6958c2ecf20Sopenharmony_ci const struct spmi_voltage_range *r = vreg->set_points->range; 6968c2ecf20Sopenharmony_ci const struct spmi_voltage_range *end = r + vreg->set_points->count; 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci for (; r < end; r++) { 6998c2ecf20Sopenharmony_ci if (r == range && range->n_voltages) { 7008c2ecf20Sopenharmony_ci /* 7018c2ecf20Sopenharmony_ci * hardware selectors between set point min and real 7028c2ecf20Sopenharmony_ci * min and between set point max and real max are 7038c2ecf20Sopenharmony_ci * invalid so we return an error if they're 7048c2ecf20Sopenharmony_ci * programmed into the hardware 7058c2ecf20Sopenharmony_ci */ 7068c2ecf20Sopenharmony_ci offset = range->set_point_min_uV - range->min_uV; 7078c2ecf20Sopenharmony_ci offset /= range->step_uV; 7088c2ecf20Sopenharmony_ci if (hw_sel < offset) 7098c2ecf20Sopenharmony_ci return -EINVAL; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci max_hw_sel = range->set_point_max_uV - range->min_uV; 7128c2ecf20Sopenharmony_ci max_hw_sel /= range->step_uV; 7138c2ecf20Sopenharmony_ci if (hw_sel > max_hw_sel) 7148c2ecf20Sopenharmony_ci return -EINVAL; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci return sw_sel + hw_sel - offset; 7178c2ecf20Sopenharmony_ci } 7188c2ecf20Sopenharmony_ci sw_sel += r->n_voltages; 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci return -EINVAL; 7228c2ecf20Sopenharmony_ci} 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_cistatic const struct spmi_voltage_range * 7258c2ecf20Sopenharmony_cispmi_regulator_find_range(struct spmi_regulator *vreg) 7268c2ecf20Sopenharmony_ci{ 7278c2ecf20Sopenharmony_ci u8 range_sel; 7288c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range, *end; 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci range = vreg->set_points->range; 7318c2ecf20Sopenharmony_ci end = range + vreg->set_points->count; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, &range_sel, 1); 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci for (; range < end; range++) 7368c2ecf20Sopenharmony_ci if (range->range_sel == range_sel) 7378c2ecf20Sopenharmony_ci return range; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci return NULL; 7408c2ecf20Sopenharmony_ci} 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_cistatic int spmi_regulator_select_voltage_same_range(struct spmi_regulator *vreg, 7438c2ecf20Sopenharmony_ci int min_uV, int max_uV) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range; 7468c2ecf20Sopenharmony_ci int uV = min_uV; 7478c2ecf20Sopenharmony_ci int i, selector; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci range = spmi_regulator_find_range(vreg); 7508c2ecf20Sopenharmony_ci if (!range) 7518c2ecf20Sopenharmony_ci goto different_range; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci if (uV < range->min_uV && max_uV >= range->min_uV) 7548c2ecf20Sopenharmony_ci uV = range->min_uV; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci if (uV < range->min_uV || uV > range->max_uV) { 7578c2ecf20Sopenharmony_ci /* Current range doesn't support the requested voltage. */ 7588c2ecf20Sopenharmony_ci goto different_range; 7598c2ecf20Sopenharmony_ci } 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci /* 7628c2ecf20Sopenharmony_ci * Force uV to be an allowed set point by applying a ceiling function to 7638c2ecf20Sopenharmony_ci * the uV value. 7648c2ecf20Sopenharmony_ci */ 7658c2ecf20Sopenharmony_ci uV = DIV_ROUND_UP(uV - range->min_uV, range->step_uV); 7668c2ecf20Sopenharmony_ci uV = uV * range->step_uV + range->min_uV; 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci if (uV > max_uV) { 7698c2ecf20Sopenharmony_ci /* 7708c2ecf20Sopenharmony_ci * No set point in the current voltage range is within the 7718c2ecf20Sopenharmony_ci * requested min_uV to max_uV range. 7728c2ecf20Sopenharmony_ci */ 7738c2ecf20Sopenharmony_ci goto different_range; 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci selector = 0; 7778c2ecf20Sopenharmony_ci for (i = 0; i < vreg->set_points->count; i++) { 7788c2ecf20Sopenharmony_ci if (uV >= vreg->set_points->range[i].set_point_min_uV 7798c2ecf20Sopenharmony_ci && uV <= vreg->set_points->range[i].set_point_max_uV) { 7808c2ecf20Sopenharmony_ci selector += 7818c2ecf20Sopenharmony_ci (uV - vreg->set_points->range[i].set_point_min_uV) 7828c2ecf20Sopenharmony_ci / vreg->set_points->range[i].step_uV; 7838c2ecf20Sopenharmony_ci break; 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci selector += vreg->set_points->range[i].n_voltages; 7878c2ecf20Sopenharmony_ci } 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci if (selector >= vreg->set_points->n_voltages) 7908c2ecf20Sopenharmony_ci goto different_range; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci return selector; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_cidifferent_range: 7958c2ecf20Sopenharmony_ci return spmi_regulator_select_voltage(vreg, min_uV, max_uV); 7968c2ecf20Sopenharmony_ci} 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_cistatic int spmi_regulator_common_map_voltage(struct regulator_dev *rdev, 7998c2ecf20Sopenharmony_ci int min_uV, int max_uV) 8008c2ecf20Sopenharmony_ci{ 8018c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci /* 8048c2ecf20Sopenharmony_ci * Favor staying in the current voltage range if possible. This avoids 8058c2ecf20Sopenharmony_ci * voltage spikes that occur when changing the voltage range. 8068c2ecf20Sopenharmony_ci */ 8078c2ecf20Sopenharmony_ci return spmi_regulator_select_voltage_same_range(vreg, min_uV, max_uV); 8088c2ecf20Sopenharmony_ci} 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_cistatic int 8118c2ecf20Sopenharmony_cispmi_regulator_common_set_voltage(struct regulator_dev *rdev, unsigned selector) 8128c2ecf20Sopenharmony_ci{ 8138c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 8148c2ecf20Sopenharmony_ci int ret; 8158c2ecf20Sopenharmony_ci u8 buf[2]; 8168c2ecf20Sopenharmony_ci u8 range_sel, voltage_sel; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel); 8198c2ecf20Sopenharmony_ci if (ret) 8208c2ecf20Sopenharmony_ci return ret; 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci buf[0] = range_sel; 8238c2ecf20Sopenharmony_ci buf[1] = voltage_sel; 8248c2ecf20Sopenharmony_ci return spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, buf, 2); 8258c2ecf20Sopenharmony_ci} 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_cistatic int spmi_regulator_common_list_voltage(struct regulator_dev *rdev, 8288c2ecf20Sopenharmony_ci unsigned selector); 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_cistatic int spmi_regulator_ftsmps426_set_voltage(struct regulator_dev *rdev, 8318c2ecf20Sopenharmony_ci unsigned selector) 8328c2ecf20Sopenharmony_ci{ 8338c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 8348c2ecf20Sopenharmony_ci u8 buf[2]; 8358c2ecf20Sopenharmony_ci int mV; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci mV = spmi_regulator_common_list_voltage(rdev, selector) / 1000; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci buf[0] = mV & 0xff; 8408c2ecf20Sopenharmony_ci buf[1] = mV >> 8; 8418c2ecf20Sopenharmony_ci return spmi_vreg_write(vreg, SPMI_FTSMPS426_REG_VOLTAGE_LSB, buf, 2); 8428c2ecf20Sopenharmony_ci} 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_cistatic int spmi_regulator_set_voltage_time_sel(struct regulator_dev *rdev, 8458c2ecf20Sopenharmony_ci unsigned int old_selector, unsigned int new_selector) 8468c2ecf20Sopenharmony_ci{ 8478c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 8488c2ecf20Sopenharmony_ci int diff_uV; 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci diff_uV = abs(spmi_regulator_common_list_voltage(rdev, new_selector) - 8518c2ecf20Sopenharmony_ci spmi_regulator_common_list_voltage(rdev, old_selector)); 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci return DIV_ROUND_UP(diff_uV, vreg->slew_rate); 8548c2ecf20Sopenharmony_ci} 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_cistatic int spmi_regulator_common_get_voltage(struct regulator_dev *rdev) 8578c2ecf20Sopenharmony_ci{ 8588c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 8598c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range; 8608c2ecf20Sopenharmony_ci u8 voltage_sel; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_SET, &voltage_sel, 1); 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci range = spmi_regulator_find_range(vreg); 8658c2ecf20Sopenharmony_ci if (!range) 8668c2ecf20Sopenharmony_ci return -EINVAL; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci return spmi_hw_selector_to_sw(vreg, voltage_sel, range); 8698c2ecf20Sopenharmony_ci} 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_cistatic int spmi_regulator_ftsmps426_get_voltage(struct regulator_dev *rdev) 8728c2ecf20Sopenharmony_ci{ 8738c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 8748c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range; 8758c2ecf20Sopenharmony_ci u8 buf[2]; 8768c2ecf20Sopenharmony_ci int uV; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci spmi_vreg_read(vreg, SPMI_FTSMPS426_REG_VOLTAGE_LSB, buf, 2); 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci uV = (((unsigned int)buf[1] << 8) | (unsigned int)buf[0]) * 1000; 8818c2ecf20Sopenharmony_ci range = vreg->set_points->range; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci return (uV - range->set_point_min_uV) / range->step_uV; 8848c2ecf20Sopenharmony_ci} 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_cistatic int spmi_regulator_single_map_voltage(struct regulator_dev *rdev, 8878c2ecf20Sopenharmony_ci int min_uV, int max_uV) 8888c2ecf20Sopenharmony_ci{ 8898c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci return spmi_regulator_select_voltage(vreg, min_uV, max_uV); 8928c2ecf20Sopenharmony_ci} 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_cistatic int spmi_regulator_single_range_set_voltage(struct regulator_dev *rdev, 8958c2ecf20Sopenharmony_ci unsigned selector) 8968c2ecf20Sopenharmony_ci{ 8978c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 8988c2ecf20Sopenharmony_ci u8 sel = selector; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci /* 9018c2ecf20Sopenharmony_ci * Certain types of regulators do not have a range select register so 9028c2ecf20Sopenharmony_ci * only voltage set register needs to be written. 9038c2ecf20Sopenharmony_ci */ 9048c2ecf20Sopenharmony_ci return spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_SET, &sel, 1); 9058c2ecf20Sopenharmony_ci} 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_cistatic int spmi_regulator_single_range_get_voltage(struct regulator_dev *rdev) 9088c2ecf20Sopenharmony_ci{ 9098c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 9108c2ecf20Sopenharmony_ci u8 selector; 9118c2ecf20Sopenharmony_ci int ret; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_SET, &selector, 1); 9148c2ecf20Sopenharmony_ci if (ret) 9158c2ecf20Sopenharmony_ci return ret; 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci return selector; 9188c2ecf20Sopenharmony_ci} 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_cistatic int spmi_regulator_ult_lo_smps_set_voltage(struct regulator_dev *rdev, 9218c2ecf20Sopenharmony_ci unsigned selector) 9228c2ecf20Sopenharmony_ci{ 9238c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 9248c2ecf20Sopenharmony_ci int ret; 9258c2ecf20Sopenharmony_ci u8 range_sel, voltage_sel; 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel); 9288c2ecf20Sopenharmony_ci if (ret) 9298c2ecf20Sopenharmony_ci return ret; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci /* 9328c2ecf20Sopenharmony_ci * Calculate VSET based on range 9338c2ecf20Sopenharmony_ci * In case of range 0: voltage_sel is a 7 bit value, can be written 9348c2ecf20Sopenharmony_ci * witout any modification. 9358c2ecf20Sopenharmony_ci * In case of range 1: voltage_sel is a 5 bit value, bits[7-5] set to 9368c2ecf20Sopenharmony_ci * [011]. 9378c2ecf20Sopenharmony_ci */ 9388c2ecf20Sopenharmony_ci if (range_sel == 1) 9398c2ecf20Sopenharmony_ci voltage_sel |= ULT_SMPS_RANGE_SPLIT; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_VOLTAGE_SET, 9428c2ecf20Sopenharmony_ci voltage_sel, 0xff); 9438c2ecf20Sopenharmony_ci} 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_cistatic int spmi_regulator_ult_lo_smps_get_voltage(struct regulator_dev *rdev) 9468c2ecf20Sopenharmony_ci{ 9478c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 9488c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range; 9498c2ecf20Sopenharmony_ci u8 voltage_sel; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_SET, &voltage_sel, 1); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci range = spmi_regulator_find_range(vreg); 9548c2ecf20Sopenharmony_ci if (!range) 9558c2ecf20Sopenharmony_ci return -EINVAL; 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci if (range->range_sel == 1) 9588c2ecf20Sopenharmony_ci voltage_sel &= ~ULT_SMPS_RANGE_SPLIT; 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci return spmi_hw_selector_to_sw(vreg, voltage_sel, range); 9618c2ecf20Sopenharmony_ci} 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_cistatic int spmi_regulator_common_list_voltage(struct regulator_dev *rdev, 9648c2ecf20Sopenharmony_ci unsigned selector) 9658c2ecf20Sopenharmony_ci{ 9668c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 9678c2ecf20Sopenharmony_ci int uV = 0; 9688c2ecf20Sopenharmony_ci int i; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci if (selector >= vreg->set_points->n_voltages) 9718c2ecf20Sopenharmony_ci return 0; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci for (i = 0; i < vreg->set_points->count; i++) { 9748c2ecf20Sopenharmony_ci if (selector < vreg->set_points->range[i].n_voltages) { 9758c2ecf20Sopenharmony_ci uV = selector * vreg->set_points->range[i].step_uV 9768c2ecf20Sopenharmony_ci + vreg->set_points->range[i].set_point_min_uV; 9778c2ecf20Sopenharmony_ci break; 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci selector -= vreg->set_points->range[i].n_voltages; 9818c2ecf20Sopenharmony_ci } 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci return uV; 9848c2ecf20Sopenharmony_ci} 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_cistatic int 9878c2ecf20Sopenharmony_cispmi_regulator_common_set_bypass(struct regulator_dev *rdev, bool enable) 9888c2ecf20Sopenharmony_ci{ 9898c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 9908c2ecf20Sopenharmony_ci u8 mask = SPMI_COMMON_MODE_BYPASS_MASK; 9918c2ecf20Sopenharmony_ci u8 val = 0; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci if (enable) 9948c2ecf20Sopenharmony_ci val = mask; 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); 9978c2ecf20Sopenharmony_ci} 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_cistatic int 10008c2ecf20Sopenharmony_cispmi_regulator_common_get_bypass(struct regulator_dev *rdev, bool *enable) 10018c2ecf20Sopenharmony_ci{ 10028c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 10038c2ecf20Sopenharmony_ci u8 val; 10048c2ecf20Sopenharmony_ci int ret; 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, &val, 1); 10078c2ecf20Sopenharmony_ci *enable = val & SPMI_COMMON_MODE_BYPASS_MASK; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci return ret; 10108c2ecf20Sopenharmony_ci} 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_cistatic unsigned int spmi_regulator_common_get_mode(struct regulator_dev *rdev) 10138c2ecf20Sopenharmony_ci{ 10148c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 10158c2ecf20Sopenharmony_ci u8 reg; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, ®, 1); 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci reg &= SPMI_COMMON_MODE_HPM_MASK | SPMI_COMMON_MODE_AUTO_MASK; 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci switch (reg) { 10228c2ecf20Sopenharmony_ci case SPMI_COMMON_MODE_HPM_MASK: 10238c2ecf20Sopenharmony_ci return REGULATOR_MODE_NORMAL; 10248c2ecf20Sopenharmony_ci case SPMI_COMMON_MODE_AUTO_MASK: 10258c2ecf20Sopenharmony_ci return REGULATOR_MODE_FAST; 10268c2ecf20Sopenharmony_ci default: 10278c2ecf20Sopenharmony_ci return REGULATOR_MODE_IDLE; 10288c2ecf20Sopenharmony_ci } 10298c2ecf20Sopenharmony_ci} 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_cistatic unsigned int spmi_regulator_ftsmps426_get_mode(struct regulator_dev *rdev) 10328c2ecf20Sopenharmony_ci{ 10338c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 10348c2ecf20Sopenharmony_ci u8 reg; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, ®, 1); 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci switch (reg) { 10398c2ecf20Sopenharmony_ci case SPMI_FTSMPS426_MODE_HPM_MASK: 10408c2ecf20Sopenharmony_ci return REGULATOR_MODE_NORMAL; 10418c2ecf20Sopenharmony_ci case SPMI_FTSMPS426_MODE_AUTO_MASK: 10428c2ecf20Sopenharmony_ci return REGULATOR_MODE_FAST; 10438c2ecf20Sopenharmony_ci default: 10448c2ecf20Sopenharmony_ci return REGULATOR_MODE_IDLE; 10458c2ecf20Sopenharmony_ci } 10468c2ecf20Sopenharmony_ci} 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cistatic int 10498c2ecf20Sopenharmony_cispmi_regulator_common_set_mode(struct regulator_dev *rdev, unsigned int mode) 10508c2ecf20Sopenharmony_ci{ 10518c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 10528c2ecf20Sopenharmony_ci u8 mask = SPMI_COMMON_MODE_HPM_MASK | SPMI_COMMON_MODE_AUTO_MASK; 10538c2ecf20Sopenharmony_ci u8 val; 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci switch (mode) { 10568c2ecf20Sopenharmony_ci case REGULATOR_MODE_NORMAL: 10578c2ecf20Sopenharmony_ci val = SPMI_COMMON_MODE_HPM_MASK; 10588c2ecf20Sopenharmony_ci break; 10598c2ecf20Sopenharmony_ci case REGULATOR_MODE_FAST: 10608c2ecf20Sopenharmony_ci val = SPMI_COMMON_MODE_AUTO_MASK; 10618c2ecf20Sopenharmony_ci break; 10628c2ecf20Sopenharmony_ci default: 10638c2ecf20Sopenharmony_ci val = 0; 10648c2ecf20Sopenharmony_ci break; 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); 10688c2ecf20Sopenharmony_ci} 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_cistatic int 10718c2ecf20Sopenharmony_cispmi_regulator_ftsmps426_set_mode(struct regulator_dev *rdev, unsigned int mode) 10728c2ecf20Sopenharmony_ci{ 10738c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 10748c2ecf20Sopenharmony_ci u8 mask = SPMI_FTSMPS426_MODE_MASK; 10758c2ecf20Sopenharmony_ci u8 val; 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci switch (mode) { 10788c2ecf20Sopenharmony_ci case REGULATOR_MODE_NORMAL: 10798c2ecf20Sopenharmony_ci val = SPMI_FTSMPS426_MODE_HPM_MASK; 10808c2ecf20Sopenharmony_ci break; 10818c2ecf20Sopenharmony_ci case REGULATOR_MODE_FAST: 10828c2ecf20Sopenharmony_ci val = SPMI_FTSMPS426_MODE_AUTO_MASK; 10838c2ecf20Sopenharmony_ci break; 10848c2ecf20Sopenharmony_ci case REGULATOR_MODE_IDLE: 10858c2ecf20Sopenharmony_ci val = SPMI_FTSMPS426_MODE_LPM_MASK; 10868c2ecf20Sopenharmony_ci break; 10878c2ecf20Sopenharmony_ci default: 10888c2ecf20Sopenharmony_ci return -EINVAL; 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); 10928c2ecf20Sopenharmony_ci} 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_cistatic int 10958c2ecf20Sopenharmony_cispmi_regulator_common_set_load(struct regulator_dev *rdev, int load_uA) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 10988c2ecf20Sopenharmony_ci unsigned int mode; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci if (load_uA >= vreg->hpm_min_load) 11018c2ecf20Sopenharmony_ci mode = REGULATOR_MODE_NORMAL; 11028c2ecf20Sopenharmony_ci else 11038c2ecf20Sopenharmony_ci mode = REGULATOR_MODE_IDLE; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci return spmi_regulator_common_set_mode(rdev, mode); 11068c2ecf20Sopenharmony_ci} 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_cistatic int spmi_regulator_common_set_pull_down(struct regulator_dev *rdev) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 11118c2ecf20Sopenharmony_ci unsigned int mask = SPMI_COMMON_PULL_DOWN_ENABLE_MASK; 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_PULL_DOWN, 11148c2ecf20Sopenharmony_ci mask, mask); 11158c2ecf20Sopenharmony_ci} 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_cistatic int spmi_regulator_common_set_soft_start(struct regulator_dev *rdev) 11188c2ecf20Sopenharmony_ci{ 11198c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 11208c2ecf20Sopenharmony_ci unsigned int mask = SPMI_LDO_SOFT_START_ENABLE_MASK; 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_SOFT_START, 11238c2ecf20Sopenharmony_ci mask, mask); 11248c2ecf20Sopenharmony_ci} 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_cistatic int spmi_regulator_set_ilim(struct regulator_dev *rdev, int ilim_uA) 11278c2ecf20Sopenharmony_ci{ 11288c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 11298c2ecf20Sopenharmony_ci enum spmi_regulator_logical_type type = vreg->logical_type; 11308c2ecf20Sopenharmony_ci unsigned int current_reg; 11318c2ecf20Sopenharmony_ci u8 reg; 11328c2ecf20Sopenharmony_ci u8 mask = SPMI_BOOST_CURRENT_LIMIT_MASK | 11338c2ecf20Sopenharmony_ci SPMI_BOOST_CURRENT_LIMIT_ENABLE_MASK; 11348c2ecf20Sopenharmony_ci int max = (SPMI_BOOST_CURRENT_LIMIT_MASK + 1) * 500; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (type == SPMI_REGULATOR_LOGICAL_TYPE_BOOST) 11378c2ecf20Sopenharmony_ci current_reg = SPMI_BOOST_REG_CURRENT_LIMIT; 11388c2ecf20Sopenharmony_ci else 11398c2ecf20Sopenharmony_ci current_reg = SPMI_BOOST_BYP_REG_CURRENT_LIMIT; 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci if (ilim_uA > max || ilim_uA <= 0) 11428c2ecf20Sopenharmony_ci return -EINVAL; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci reg = (ilim_uA - 1) / 500; 11458c2ecf20Sopenharmony_ci reg |= SPMI_BOOST_CURRENT_LIMIT_ENABLE_MASK; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci return spmi_vreg_update_bits(vreg, current_reg, reg, mask); 11488c2ecf20Sopenharmony_ci} 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_cistatic int spmi_regulator_vs_clear_ocp(struct spmi_regulator *vreg) 11518c2ecf20Sopenharmony_ci{ 11528c2ecf20Sopenharmony_ci int ret; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci ret = spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_ENABLE, 11558c2ecf20Sopenharmony_ci SPMI_COMMON_DISABLE, SPMI_COMMON_ENABLE_MASK); 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci vreg->vs_enable_time = ktime_get(); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci ret = spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_ENABLE, 11608c2ecf20Sopenharmony_ci SPMI_COMMON_ENABLE, SPMI_COMMON_ENABLE_MASK); 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci return ret; 11638c2ecf20Sopenharmony_ci} 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_cistatic void spmi_regulator_vs_ocp_work(struct work_struct *work) 11668c2ecf20Sopenharmony_ci{ 11678c2ecf20Sopenharmony_ci struct delayed_work *dwork = to_delayed_work(work); 11688c2ecf20Sopenharmony_ci struct spmi_regulator *vreg 11698c2ecf20Sopenharmony_ci = container_of(dwork, struct spmi_regulator, ocp_work); 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci spmi_regulator_vs_clear_ocp(vreg); 11728c2ecf20Sopenharmony_ci} 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_cistatic irqreturn_t spmi_regulator_vs_ocp_isr(int irq, void *data) 11758c2ecf20Sopenharmony_ci{ 11768c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = data; 11778c2ecf20Sopenharmony_ci ktime_t ocp_irq_time; 11788c2ecf20Sopenharmony_ci s64 ocp_trigger_delay_us; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci ocp_irq_time = ktime_get(); 11818c2ecf20Sopenharmony_ci ocp_trigger_delay_us = ktime_us_delta(ocp_irq_time, 11828c2ecf20Sopenharmony_ci vreg->vs_enable_time); 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci /* 11858c2ecf20Sopenharmony_ci * Reset the OCP count if there is a large delay between switch enable 11868c2ecf20Sopenharmony_ci * and when OCP triggers. This is indicative of a hotplug event as 11878c2ecf20Sopenharmony_ci * opposed to a fault. 11888c2ecf20Sopenharmony_ci */ 11898c2ecf20Sopenharmony_ci if (ocp_trigger_delay_us > SPMI_VS_OCP_FAULT_DELAY_US) 11908c2ecf20Sopenharmony_ci vreg->ocp_count = 0; 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci /* Wait for switch output to settle back to 0 V after OCP triggered. */ 11938c2ecf20Sopenharmony_ci udelay(SPMI_VS_OCP_FALL_DELAY_US); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci vreg->ocp_count++; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci if (vreg->ocp_count == 1) { 11988c2ecf20Sopenharmony_ci /* Immediately clear the over current condition. */ 11998c2ecf20Sopenharmony_ci spmi_regulator_vs_clear_ocp(vreg); 12008c2ecf20Sopenharmony_ci } else if (vreg->ocp_count <= vreg->ocp_max_retries) { 12018c2ecf20Sopenharmony_ci /* Schedule the over current clear task to run later. */ 12028c2ecf20Sopenharmony_ci schedule_delayed_work(&vreg->ocp_work, 12038c2ecf20Sopenharmony_ci msecs_to_jiffies(vreg->ocp_retry_delay_ms) + 1); 12048c2ecf20Sopenharmony_ci } else { 12058c2ecf20Sopenharmony_ci dev_err(vreg->dev, 12068c2ecf20Sopenharmony_ci "OCP triggered %d times; no further retries\n", 12078c2ecf20Sopenharmony_ci vreg->ocp_count); 12088c2ecf20Sopenharmony_ci } 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci return IRQ_HANDLED; 12118c2ecf20Sopenharmony_ci} 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci#define SAW3_VCTL_DATA_MASK 0xFF 12148c2ecf20Sopenharmony_ci#define SAW3_VCTL_CLEAR_MASK 0x700FF 12158c2ecf20Sopenharmony_ci#define SAW3_AVS_CTL_EN_MASK 0x1 12168c2ecf20Sopenharmony_ci#define SAW3_AVS_CTL_TGGL_MASK 0x8000000 12178c2ecf20Sopenharmony_ci#define SAW3_AVS_CTL_CLEAR_MASK 0x7efc00 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_cistatic struct regmap *saw_regmap; 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_cistatic void spmi_saw_set_vdd(void *data) 12228c2ecf20Sopenharmony_ci{ 12238c2ecf20Sopenharmony_ci u32 vctl, data3, avs_ctl, pmic_sts; 12248c2ecf20Sopenharmony_ci bool avs_enabled = false; 12258c2ecf20Sopenharmony_ci unsigned long timeout; 12268c2ecf20Sopenharmony_ci u8 voltage_sel = *(u8 *)data; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci regmap_read(saw_regmap, SAW3_AVS_CTL, &avs_ctl); 12298c2ecf20Sopenharmony_ci regmap_read(saw_regmap, SAW3_VCTL, &vctl); 12308c2ecf20Sopenharmony_ci regmap_read(saw_regmap, SAW3_SPM_PMIC_DATA_3, &data3); 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci /* select the band */ 12338c2ecf20Sopenharmony_ci vctl &= ~SAW3_VCTL_CLEAR_MASK; 12348c2ecf20Sopenharmony_ci vctl |= (u32)voltage_sel; 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci data3 &= ~SAW3_VCTL_CLEAR_MASK; 12378c2ecf20Sopenharmony_ci data3 |= (u32)voltage_sel; 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci /* If AVS is enabled, switch it off during the voltage change */ 12408c2ecf20Sopenharmony_ci avs_enabled = SAW3_AVS_CTL_EN_MASK & avs_ctl; 12418c2ecf20Sopenharmony_ci if (avs_enabled) { 12428c2ecf20Sopenharmony_ci avs_ctl &= ~SAW3_AVS_CTL_TGGL_MASK; 12438c2ecf20Sopenharmony_ci regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl); 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci regmap_write(saw_regmap, SAW3_RST, 1); 12478c2ecf20Sopenharmony_ci regmap_write(saw_regmap, SAW3_VCTL, vctl); 12488c2ecf20Sopenharmony_ci regmap_write(saw_regmap, SAW3_SPM_PMIC_DATA_3, data3); 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci timeout = jiffies + usecs_to_jiffies(100); 12518c2ecf20Sopenharmony_ci do { 12528c2ecf20Sopenharmony_ci regmap_read(saw_regmap, SAW3_PMIC_STS, &pmic_sts); 12538c2ecf20Sopenharmony_ci pmic_sts &= SAW3_VCTL_DATA_MASK; 12548c2ecf20Sopenharmony_ci if (pmic_sts == (u32)voltage_sel) 12558c2ecf20Sopenharmony_ci break; 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci cpu_relax(); 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci } while (time_before(jiffies, timeout)); 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci /* After successful voltage change, switch the AVS back on */ 12628c2ecf20Sopenharmony_ci if (avs_enabled) { 12638c2ecf20Sopenharmony_ci pmic_sts &= 0x3f; 12648c2ecf20Sopenharmony_ci avs_ctl &= ~SAW3_AVS_CTL_CLEAR_MASK; 12658c2ecf20Sopenharmony_ci avs_ctl |= ((pmic_sts - 4) << 10); 12668c2ecf20Sopenharmony_ci avs_ctl |= (pmic_sts << 17); 12678c2ecf20Sopenharmony_ci avs_ctl |= SAW3_AVS_CTL_TGGL_MASK; 12688c2ecf20Sopenharmony_ci regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl); 12698c2ecf20Sopenharmony_ci } 12708c2ecf20Sopenharmony_ci} 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_cistatic int 12738c2ecf20Sopenharmony_cispmi_regulator_saw_set_voltage(struct regulator_dev *rdev, unsigned selector) 12748c2ecf20Sopenharmony_ci{ 12758c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 12768c2ecf20Sopenharmony_ci int ret; 12778c2ecf20Sopenharmony_ci u8 range_sel, voltage_sel; 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel); 12808c2ecf20Sopenharmony_ci if (ret) 12818c2ecf20Sopenharmony_ci return ret; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci if (0 != range_sel) { 12848c2ecf20Sopenharmony_ci dev_dbg(&rdev->dev, "range_sel = %02X voltage_sel = %02X", \ 12858c2ecf20Sopenharmony_ci range_sel, voltage_sel); 12868c2ecf20Sopenharmony_ci return -EINVAL; 12878c2ecf20Sopenharmony_ci } 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci /* Always do the SAW register writes on the first CPU */ 12908c2ecf20Sopenharmony_ci return smp_call_function_single(0, spmi_saw_set_vdd, \ 12918c2ecf20Sopenharmony_ci &voltage_sel, true); 12928c2ecf20Sopenharmony_ci} 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_cistatic struct regulator_ops spmi_saw_ops = {}; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_smps_ops = { 12978c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 12988c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 12998c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 13008c2ecf20Sopenharmony_ci .set_voltage_sel = spmi_regulator_common_set_voltage, 13018c2ecf20Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 13028c2ecf20Sopenharmony_ci .get_voltage_sel = spmi_regulator_common_get_voltage, 13038c2ecf20Sopenharmony_ci .map_voltage = spmi_regulator_common_map_voltage, 13048c2ecf20Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 13058c2ecf20Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 13068c2ecf20Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 13078c2ecf20Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 13088c2ecf20Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 13098c2ecf20Sopenharmony_ci}; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_ldo_ops = { 13128c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 13138c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 13148c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 13158c2ecf20Sopenharmony_ci .set_voltage_sel = spmi_regulator_common_set_voltage, 13168c2ecf20Sopenharmony_ci .get_voltage_sel = spmi_regulator_common_get_voltage, 13178c2ecf20Sopenharmony_ci .map_voltage = spmi_regulator_common_map_voltage, 13188c2ecf20Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 13198c2ecf20Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 13208c2ecf20Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 13218c2ecf20Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 13228c2ecf20Sopenharmony_ci .set_bypass = spmi_regulator_common_set_bypass, 13238c2ecf20Sopenharmony_ci .get_bypass = spmi_regulator_common_get_bypass, 13248c2ecf20Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 13258c2ecf20Sopenharmony_ci .set_soft_start = spmi_regulator_common_set_soft_start, 13268c2ecf20Sopenharmony_ci}; 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_ln_ldo_ops = { 13298c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 13308c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 13318c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 13328c2ecf20Sopenharmony_ci .set_voltage_sel = spmi_regulator_common_set_voltage, 13338c2ecf20Sopenharmony_ci .get_voltage_sel = spmi_regulator_common_get_voltage, 13348c2ecf20Sopenharmony_ci .map_voltage = spmi_regulator_common_map_voltage, 13358c2ecf20Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 13368c2ecf20Sopenharmony_ci .set_bypass = spmi_regulator_common_set_bypass, 13378c2ecf20Sopenharmony_ci .get_bypass = spmi_regulator_common_get_bypass, 13388c2ecf20Sopenharmony_ci}; 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_vs_ops = { 13418c2ecf20Sopenharmony_ci .enable = spmi_regulator_vs_enable, 13428c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 13438c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 13448c2ecf20Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 13458c2ecf20Sopenharmony_ci .set_soft_start = spmi_regulator_common_set_soft_start, 13468c2ecf20Sopenharmony_ci .set_over_current_protection = spmi_regulator_vs_ocp, 13478c2ecf20Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 13488c2ecf20Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 13498c2ecf20Sopenharmony_ci}; 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_boost_ops = { 13528c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 13538c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 13548c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 13558c2ecf20Sopenharmony_ci .set_voltage_sel = spmi_regulator_single_range_set_voltage, 13568c2ecf20Sopenharmony_ci .get_voltage_sel = spmi_regulator_single_range_get_voltage, 13578c2ecf20Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 13588c2ecf20Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 13598c2ecf20Sopenharmony_ci .set_input_current_limit = spmi_regulator_set_ilim, 13608c2ecf20Sopenharmony_ci}; 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_ftsmps_ops = { 13638c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 13648c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 13658c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 13668c2ecf20Sopenharmony_ci .set_voltage_sel = spmi_regulator_common_set_voltage, 13678c2ecf20Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 13688c2ecf20Sopenharmony_ci .get_voltage_sel = spmi_regulator_common_get_voltage, 13698c2ecf20Sopenharmony_ci .map_voltage = spmi_regulator_common_map_voltage, 13708c2ecf20Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 13718c2ecf20Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 13728c2ecf20Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 13738c2ecf20Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 13748c2ecf20Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 13758c2ecf20Sopenharmony_ci}; 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_ult_lo_smps_ops = { 13788c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 13798c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 13808c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 13818c2ecf20Sopenharmony_ci .set_voltage_sel = spmi_regulator_ult_lo_smps_set_voltage, 13828c2ecf20Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 13838c2ecf20Sopenharmony_ci .get_voltage_sel = spmi_regulator_ult_lo_smps_get_voltage, 13848c2ecf20Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 13858c2ecf20Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 13868c2ecf20Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 13878c2ecf20Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 13888c2ecf20Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 13898c2ecf20Sopenharmony_ci}; 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_ult_ho_smps_ops = { 13928c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 13938c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 13948c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 13958c2ecf20Sopenharmony_ci .set_voltage_sel = spmi_regulator_single_range_set_voltage, 13968c2ecf20Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 13978c2ecf20Sopenharmony_ci .get_voltage_sel = spmi_regulator_single_range_get_voltage, 13988c2ecf20Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 13998c2ecf20Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 14008c2ecf20Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 14018c2ecf20Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 14028c2ecf20Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 14038c2ecf20Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 14048c2ecf20Sopenharmony_ci}; 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_ult_ldo_ops = { 14078c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 14088c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 14098c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 14108c2ecf20Sopenharmony_ci .set_voltage_sel = spmi_regulator_single_range_set_voltage, 14118c2ecf20Sopenharmony_ci .get_voltage_sel = spmi_regulator_single_range_get_voltage, 14128c2ecf20Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 14138c2ecf20Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 14148c2ecf20Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 14158c2ecf20Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 14168c2ecf20Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 14178c2ecf20Sopenharmony_ci .set_bypass = spmi_regulator_common_set_bypass, 14188c2ecf20Sopenharmony_ci .get_bypass = spmi_regulator_common_get_bypass, 14198c2ecf20Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 14208c2ecf20Sopenharmony_ci .set_soft_start = spmi_regulator_common_set_soft_start, 14218c2ecf20Sopenharmony_ci}; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_ftsmps426_ops = { 14248c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 14258c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 14268c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 14278c2ecf20Sopenharmony_ci .set_voltage_sel = spmi_regulator_ftsmps426_set_voltage, 14288c2ecf20Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 14298c2ecf20Sopenharmony_ci .get_voltage_sel = spmi_regulator_ftsmps426_get_voltage, 14308c2ecf20Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 14318c2ecf20Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 14328c2ecf20Sopenharmony_ci .set_mode = spmi_regulator_ftsmps426_set_mode, 14338c2ecf20Sopenharmony_ci .get_mode = spmi_regulator_ftsmps426_get_mode, 14348c2ecf20Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 14358c2ecf20Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 14368c2ecf20Sopenharmony_ci}; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_cistatic const struct regulator_ops spmi_hfs430_ops = { 14398c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 14408c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 14418c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 14428c2ecf20Sopenharmony_ci .set_voltage_sel = spmi_regulator_ftsmps426_set_voltage, 14438c2ecf20Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 14448c2ecf20Sopenharmony_ci .get_voltage_sel = spmi_regulator_ftsmps426_get_voltage, 14458c2ecf20Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 14468c2ecf20Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 14478c2ecf20Sopenharmony_ci .set_mode = spmi_regulator_ftsmps426_set_mode, 14488c2ecf20Sopenharmony_ci .get_mode = spmi_regulator_ftsmps426_get_mode, 14498c2ecf20Sopenharmony_ci}; 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci/* Maximum possible digital major revision value */ 14528c2ecf20Sopenharmony_ci#define INF 0xFF 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_cistatic const struct spmi_regulator_mapping supported_regulators[] = { 14558c2ecf20Sopenharmony_ci /* type subtype dig_min dig_max ltype ops setpoints hpm_min */ 14568c2ecf20Sopenharmony_ci SPMI_VREG(BUCK, GP_CTL, 0, INF, SMPS, smps, smps, 100000), 14578c2ecf20Sopenharmony_ci SPMI_VREG(BUCK, HFS430, 0, INF, HFS430, hfs430, hfs430, 10000), 14588c2ecf20Sopenharmony_ci SPMI_VREG(LDO, N300, 0, INF, LDO, ldo, nldo1, 10000), 14598c2ecf20Sopenharmony_ci SPMI_VREG(LDO, N600, 0, 0, LDO, ldo, nldo2, 10000), 14608c2ecf20Sopenharmony_ci SPMI_VREG(LDO, N1200, 0, 0, LDO, ldo, nldo2, 10000), 14618c2ecf20Sopenharmony_ci SPMI_VREG(LDO, N600, 1, INF, LDO, ldo, nldo3, 10000), 14628c2ecf20Sopenharmony_ci SPMI_VREG(LDO, N1200, 1, INF, LDO, ldo, nldo3, 10000), 14638c2ecf20Sopenharmony_ci SPMI_VREG(LDO, N600_ST, 0, 0, LDO, ldo, nldo2, 10000), 14648c2ecf20Sopenharmony_ci SPMI_VREG(LDO, N1200_ST, 0, 0, LDO, ldo, nldo2, 10000), 14658c2ecf20Sopenharmony_ci SPMI_VREG(LDO, N600_ST, 1, INF, LDO, ldo, nldo3, 10000), 14668c2ecf20Sopenharmony_ci SPMI_VREG(LDO, N1200_ST, 1, INF, LDO, ldo, nldo3, 10000), 14678c2ecf20Sopenharmony_ci SPMI_VREG(LDO, P50, 0, INF, LDO, ldo, pldo, 5000), 14688c2ecf20Sopenharmony_ci SPMI_VREG(LDO, P150, 0, INF, LDO, ldo, pldo, 10000), 14698c2ecf20Sopenharmony_ci SPMI_VREG(LDO, P300, 0, INF, LDO, ldo, pldo, 10000), 14708c2ecf20Sopenharmony_ci SPMI_VREG(LDO, P600, 0, INF, LDO, ldo, pldo, 10000), 14718c2ecf20Sopenharmony_ci SPMI_VREG(LDO, P1200, 0, INF, LDO, ldo, pldo, 10000), 14728c2ecf20Sopenharmony_ci SPMI_VREG(LDO, LN, 0, INF, LN_LDO, ln_ldo, ln_ldo, 0), 14738c2ecf20Sopenharmony_ci SPMI_VREG(LDO, LV_P50, 0, INF, LDO, ldo, pldo, 5000), 14748c2ecf20Sopenharmony_ci SPMI_VREG(LDO, LV_P150, 0, INF, LDO, ldo, pldo, 10000), 14758c2ecf20Sopenharmony_ci SPMI_VREG(LDO, LV_P300, 0, INF, LDO, ldo, pldo, 10000), 14768c2ecf20Sopenharmony_ci SPMI_VREG(LDO, LV_P600, 0, INF, LDO, ldo, pldo, 10000), 14778c2ecf20Sopenharmony_ci SPMI_VREG(LDO, LV_P1200, 0, INF, LDO, ldo, pldo, 10000), 14788c2ecf20Sopenharmony_ci SPMI_VREG(LDO, HT_N300_ST, 0, INF, FTSMPS426, ftsmps426, 14798c2ecf20Sopenharmony_ci ht_nldo, 30000), 14808c2ecf20Sopenharmony_ci SPMI_VREG(LDO, HT_N600_ST, 0, INF, FTSMPS426, ftsmps426, 14818c2ecf20Sopenharmony_ci ht_nldo, 30000), 14828c2ecf20Sopenharmony_ci SPMI_VREG(LDO, HT_N1200_ST, 0, INF, FTSMPS426, ftsmps426, 14838c2ecf20Sopenharmony_ci ht_nldo, 30000), 14848c2ecf20Sopenharmony_ci SPMI_VREG(LDO, HT_LVP150, 0, INF, FTSMPS426, ftsmps426, 14858c2ecf20Sopenharmony_ci ht_lvpldo, 10000), 14868c2ecf20Sopenharmony_ci SPMI_VREG(LDO, HT_LVP300, 0, INF, FTSMPS426, ftsmps426, 14878c2ecf20Sopenharmony_ci ht_lvpldo, 10000), 14888c2ecf20Sopenharmony_ci SPMI_VREG(LDO, L660_N300_ST, 0, INF, FTSMPS426, ftsmps426, 14898c2ecf20Sopenharmony_ci nldo660, 10000), 14908c2ecf20Sopenharmony_ci SPMI_VREG(LDO, L660_N600_ST, 0, INF, FTSMPS426, ftsmps426, 14918c2ecf20Sopenharmony_ci nldo660, 10000), 14928c2ecf20Sopenharmony_ci SPMI_VREG(LDO, L660_P50, 0, INF, FTSMPS426, ftsmps426, 14938c2ecf20Sopenharmony_ci pldo660, 10000), 14948c2ecf20Sopenharmony_ci SPMI_VREG(LDO, L660_P150, 0, INF, FTSMPS426, ftsmps426, 14958c2ecf20Sopenharmony_ci pldo660, 10000), 14968c2ecf20Sopenharmony_ci SPMI_VREG(LDO, L660_P600, 0, INF, FTSMPS426, ftsmps426, 14978c2ecf20Sopenharmony_ci pldo660, 10000), 14988c2ecf20Sopenharmony_ci SPMI_VREG(LDO, L660_LVP150, 0, INF, FTSMPS426, ftsmps426, 14998c2ecf20Sopenharmony_ci ht_lvpldo, 10000), 15008c2ecf20Sopenharmony_ci SPMI_VREG(LDO, L660_LVP600, 0, INF, FTSMPS426, ftsmps426, 15018c2ecf20Sopenharmony_ci ht_lvpldo, 10000), 15028c2ecf20Sopenharmony_ci SPMI_VREG_VS(LV100, 0, INF), 15038c2ecf20Sopenharmony_ci SPMI_VREG_VS(LV300, 0, INF), 15048c2ecf20Sopenharmony_ci SPMI_VREG_VS(MV300, 0, INF), 15058c2ecf20Sopenharmony_ci SPMI_VREG_VS(MV500, 0, INF), 15068c2ecf20Sopenharmony_ci SPMI_VREG_VS(HDMI, 0, INF), 15078c2ecf20Sopenharmony_ci SPMI_VREG_VS(OTG, 0, INF), 15088c2ecf20Sopenharmony_ci SPMI_VREG(BOOST, 5V_BOOST, 0, INF, BOOST, boost, boost, 0), 15098c2ecf20Sopenharmony_ci SPMI_VREG(FTS, FTS_CTL, 0, INF, FTSMPS, ftsmps, ftsmps, 100000), 15108c2ecf20Sopenharmony_ci SPMI_VREG(FTS, FTS2p5_CTL, 0, INF, FTSMPS, ftsmps, ftsmps2p5, 100000), 15118c2ecf20Sopenharmony_ci SPMI_VREG(FTS, FTS426_CTL, 0, INF, FTSMPS426, ftsmps426, ftsmps426, 100000), 15128c2ecf20Sopenharmony_ci SPMI_VREG(BOOST_BYP, BB_2A, 0, INF, BOOST_BYP, boost, boost_byp, 0), 15138c2ecf20Sopenharmony_ci SPMI_VREG(ULT_BUCK, ULT_HF_CTL1, 0, INF, ULT_LO_SMPS, ult_lo_smps, 15148c2ecf20Sopenharmony_ci ult_lo_smps, 100000), 15158c2ecf20Sopenharmony_ci SPMI_VREG(ULT_BUCK, ULT_HF_CTL2, 0, INF, ULT_LO_SMPS, ult_lo_smps, 15168c2ecf20Sopenharmony_ci ult_lo_smps, 100000), 15178c2ecf20Sopenharmony_ci SPMI_VREG(ULT_BUCK, ULT_HF_CTL3, 0, INF, ULT_LO_SMPS, ult_lo_smps, 15188c2ecf20Sopenharmony_ci ult_lo_smps, 100000), 15198c2ecf20Sopenharmony_ci SPMI_VREG(ULT_BUCK, ULT_HF_CTL4, 0, INF, ULT_HO_SMPS, ult_ho_smps, 15208c2ecf20Sopenharmony_ci ult_ho_smps, 100000), 15218c2ecf20Sopenharmony_ci SPMI_VREG(ULT_LDO, N300_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000), 15228c2ecf20Sopenharmony_ci SPMI_VREG(ULT_LDO, N600_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000), 15238c2ecf20Sopenharmony_ci SPMI_VREG(ULT_LDO, N900_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000), 15248c2ecf20Sopenharmony_ci SPMI_VREG(ULT_LDO, N1200_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000), 15258c2ecf20Sopenharmony_ci SPMI_VREG(ULT_LDO, LV_P150, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 15268c2ecf20Sopenharmony_ci SPMI_VREG(ULT_LDO, LV_P300, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 15278c2ecf20Sopenharmony_ci SPMI_VREG(ULT_LDO, LV_P450, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 15288c2ecf20Sopenharmony_ci SPMI_VREG(ULT_LDO, P600, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 15298c2ecf20Sopenharmony_ci SPMI_VREG(ULT_LDO, P150, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 15308c2ecf20Sopenharmony_ci SPMI_VREG(ULT_LDO, P50, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 5000), 15318c2ecf20Sopenharmony_ci}; 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_cistatic void spmi_calculate_num_voltages(struct spmi_voltage_set_points *points) 15348c2ecf20Sopenharmony_ci{ 15358c2ecf20Sopenharmony_ci unsigned int n; 15368c2ecf20Sopenharmony_ci struct spmi_voltage_range *range = points->range; 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci for (; range < points->range + points->count; range++) { 15398c2ecf20Sopenharmony_ci n = 0; 15408c2ecf20Sopenharmony_ci if (range->set_point_max_uV) { 15418c2ecf20Sopenharmony_ci n = range->set_point_max_uV - range->set_point_min_uV; 15428c2ecf20Sopenharmony_ci n = (n / range->step_uV) + 1; 15438c2ecf20Sopenharmony_ci } 15448c2ecf20Sopenharmony_ci range->n_voltages = n; 15458c2ecf20Sopenharmony_ci points->n_voltages += n; 15468c2ecf20Sopenharmony_ci } 15478c2ecf20Sopenharmony_ci} 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_cistatic int spmi_regulator_match(struct spmi_regulator *vreg, u16 force_type) 15508c2ecf20Sopenharmony_ci{ 15518c2ecf20Sopenharmony_ci const struct spmi_regulator_mapping *mapping; 15528c2ecf20Sopenharmony_ci int ret, i; 15538c2ecf20Sopenharmony_ci u32 dig_major_rev; 15548c2ecf20Sopenharmony_ci u8 version[SPMI_COMMON_REG_SUBTYPE - SPMI_COMMON_REG_DIG_MAJOR_REV + 1]; 15558c2ecf20Sopenharmony_ci u8 type, subtype; 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_DIG_MAJOR_REV, version, 15588c2ecf20Sopenharmony_ci ARRAY_SIZE(version)); 15598c2ecf20Sopenharmony_ci if (ret) { 15608c2ecf20Sopenharmony_ci dev_dbg(vreg->dev, "could not read version registers\n"); 15618c2ecf20Sopenharmony_ci return ret; 15628c2ecf20Sopenharmony_ci } 15638c2ecf20Sopenharmony_ci dig_major_rev = version[SPMI_COMMON_REG_DIG_MAJOR_REV 15648c2ecf20Sopenharmony_ci - SPMI_COMMON_REG_DIG_MAJOR_REV]; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci if (!force_type) { 15678c2ecf20Sopenharmony_ci type = version[SPMI_COMMON_REG_TYPE - 15688c2ecf20Sopenharmony_ci SPMI_COMMON_REG_DIG_MAJOR_REV]; 15698c2ecf20Sopenharmony_ci subtype = version[SPMI_COMMON_REG_SUBTYPE - 15708c2ecf20Sopenharmony_ci SPMI_COMMON_REG_DIG_MAJOR_REV]; 15718c2ecf20Sopenharmony_ci } else { 15728c2ecf20Sopenharmony_ci type = force_type >> 8; 15738c2ecf20Sopenharmony_ci subtype = force_type; 15748c2ecf20Sopenharmony_ci } 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(supported_regulators); i++) { 15778c2ecf20Sopenharmony_ci mapping = &supported_regulators[i]; 15788c2ecf20Sopenharmony_ci if (mapping->type == type && mapping->subtype == subtype 15798c2ecf20Sopenharmony_ci && mapping->revision_min <= dig_major_rev 15808c2ecf20Sopenharmony_ci && mapping->revision_max >= dig_major_rev) 15818c2ecf20Sopenharmony_ci goto found; 15828c2ecf20Sopenharmony_ci } 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci dev_err(vreg->dev, 15858c2ecf20Sopenharmony_ci "unsupported regulator: name=%s type=0x%02X, subtype=0x%02X, dig major rev=0x%02X\n", 15868c2ecf20Sopenharmony_ci vreg->desc.name, type, subtype, dig_major_rev); 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci return -ENODEV; 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_cifound: 15918c2ecf20Sopenharmony_ci vreg->logical_type = mapping->logical_type; 15928c2ecf20Sopenharmony_ci vreg->set_points = mapping->set_points; 15938c2ecf20Sopenharmony_ci vreg->hpm_min_load = mapping->hpm_min_load; 15948c2ecf20Sopenharmony_ci vreg->desc.ops = mapping->ops; 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci if (mapping->set_points) { 15978c2ecf20Sopenharmony_ci if (!mapping->set_points->n_voltages) 15988c2ecf20Sopenharmony_ci spmi_calculate_num_voltages(mapping->set_points); 15998c2ecf20Sopenharmony_ci vreg->desc.n_voltages = mapping->set_points->n_voltages; 16008c2ecf20Sopenharmony_ci } 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci return 0; 16038c2ecf20Sopenharmony_ci} 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_cistatic int spmi_regulator_init_slew_rate(struct spmi_regulator *vreg) 16068c2ecf20Sopenharmony_ci{ 16078c2ecf20Sopenharmony_ci int ret; 16088c2ecf20Sopenharmony_ci u8 reg = 0; 16098c2ecf20Sopenharmony_ci int step, delay, slew_rate, step_delay; 16108c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range; 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_STEP_CTRL, ®, 1); 16138c2ecf20Sopenharmony_ci if (ret) { 16148c2ecf20Sopenharmony_ci dev_err(vreg->dev, "spmi read failed, ret=%d\n", ret); 16158c2ecf20Sopenharmony_ci return ret; 16168c2ecf20Sopenharmony_ci } 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci range = spmi_regulator_find_range(vreg); 16198c2ecf20Sopenharmony_ci if (!range) 16208c2ecf20Sopenharmony_ci return -EINVAL; 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci switch (vreg->logical_type) { 16238c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS: 16248c2ecf20Sopenharmony_ci step_delay = SPMI_FTSMPS_STEP_DELAY; 16258c2ecf20Sopenharmony_ci break; 16268c2ecf20Sopenharmony_ci default: 16278c2ecf20Sopenharmony_ci step_delay = SPMI_DEFAULT_STEP_DELAY; 16288c2ecf20Sopenharmony_ci break; 16298c2ecf20Sopenharmony_ci } 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci step = reg & SPMI_FTSMPS_STEP_CTRL_STEP_MASK; 16328c2ecf20Sopenharmony_ci step >>= SPMI_FTSMPS_STEP_CTRL_STEP_SHIFT; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci delay = reg & SPMI_FTSMPS_STEP_CTRL_DELAY_MASK; 16358c2ecf20Sopenharmony_ci delay >>= SPMI_FTSMPS_STEP_CTRL_DELAY_SHIFT; 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci /* slew_rate has units of uV/us */ 16388c2ecf20Sopenharmony_ci slew_rate = SPMI_FTSMPS_CLOCK_RATE * range->step_uV * (1 << step); 16398c2ecf20Sopenharmony_ci slew_rate /= 1000 * (step_delay << delay); 16408c2ecf20Sopenharmony_ci slew_rate *= SPMI_FTSMPS_STEP_MARGIN_NUM; 16418c2ecf20Sopenharmony_ci slew_rate /= SPMI_FTSMPS_STEP_MARGIN_DEN; 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci /* Ensure that the slew rate is greater than 0 */ 16448c2ecf20Sopenharmony_ci vreg->slew_rate = max(slew_rate, 1); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci return ret; 16478c2ecf20Sopenharmony_ci} 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_cistatic int spmi_regulator_init_slew_rate_ftsmps426(struct spmi_regulator *vreg, 16508c2ecf20Sopenharmony_ci int clock_rate) 16518c2ecf20Sopenharmony_ci{ 16528c2ecf20Sopenharmony_ci int ret; 16538c2ecf20Sopenharmony_ci u8 reg = 0; 16548c2ecf20Sopenharmony_ci int delay, slew_rate; 16558c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range = &vreg->set_points->range[0]; 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_STEP_CTRL, ®, 1); 16588c2ecf20Sopenharmony_ci if (ret) { 16598c2ecf20Sopenharmony_ci dev_err(vreg->dev, "spmi read failed, ret=%d\n", ret); 16608c2ecf20Sopenharmony_ci return ret; 16618c2ecf20Sopenharmony_ci } 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci delay = reg & SPMI_FTSMPS426_STEP_CTRL_DELAY_MASK; 16648c2ecf20Sopenharmony_ci delay >>= SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci /* slew_rate has units of uV/us */ 16678c2ecf20Sopenharmony_ci slew_rate = clock_rate * range->step_uV; 16688c2ecf20Sopenharmony_ci slew_rate /= 1000 * (SPMI_FTSMPS426_STEP_DELAY << delay); 16698c2ecf20Sopenharmony_ci slew_rate *= SPMI_FTSMPS426_STEP_MARGIN_NUM; 16708c2ecf20Sopenharmony_ci slew_rate /= SPMI_FTSMPS426_STEP_MARGIN_DEN; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci /* Ensure that the slew rate is greater than 0 */ 16738c2ecf20Sopenharmony_ci vreg->slew_rate = max(slew_rate, 1); 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci return ret; 16768c2ecf20Sopenharmony_ci} 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_cistatic int spmi_regulator_init_registers(struct spmi_regulator *vreg, 16798c2ecf20Sopenharmony_ci const struct spmi_regulator_init_data *data) 16808c2ecf20Sopenharmony_ci{ 16818c2ecf20Sopenharmony_ci int ret; 16828c2ecf20Sopenharmony_ci enum spmi_regulator_logical_type type; 16838c2ecf20Sopenharmony_ci u8 ctrl_reg[8], reg, mask; 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci type = vreg->logical_type; 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, ctrl_reg, 8); 16888c2ecf20Sopenharmony_ci if (ret) 16898c2ecf20Sopenharmony_ci return ret; 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci /* Set up enable pin control. */ 16928c2ecf20Sopenharmony_ci if (!(data->pin_ctrl_enable & SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT)) { 16938c2ecf20Sopenharmony_ci switch (type) { 16948c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_SMPS: 16958c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_LDO: 16968c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_VS: 16978c2ecf20Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_ENABLE] &= 16988c2ecf20Sopenharmony_ci ~SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK; 16998c2ecf20Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_ENABLE] |= 17008c2ecf20Sopenharmony_ci data->pin_ctrl_enable & SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK; 17018c2ecf20Sopenharmony_ci break; 17028c2ecf20Sopenharmony_ci default: 17038c2ecf20Sopenharmony_ci break; 17048c2ecf20Sopenharmony_ci } 17058c2ecf20Sopenharmony_ci } 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci /* Set up mode pin control. */ 17088c2ecf20Sopenharmony_ci if (!(data->pin_ctrl_hpm & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) { 17098c2ecf20Sopenharmony_ci switch (type) { 17108c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_SMPS: 17118c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_LDO: 17128c2ecf20Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_MODE] &= 17138c2ecf20Sopenharmony_ci ~SPMI_COMMON_MODE_FOLLOW_ALL_MASK; 17148c2ecf20Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_MODE] |= 17158c2ecf20Sopenharmony_ci data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_ALL_MASK; 17168c2ecf20Sopenharmony_ci break; 17178c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_VS: 17188c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS: 17198c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS: 17208c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO: 17218c2ecf20Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_MODE] &= 17228c2ecf20Sopenharmony_ci ~SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK; 17238c2ecf20Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_MODE] |= 17248c2ecf20Sopenharmony_ci data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK; 17258c2ecf20Sopenharmony_ci break; 17268c2ecf20Sopenharmony_ci default: 17278c2ecf20Sopenharmony_ci break; 17288c2ecf20Sopenharmony_ci } 17298c2ecf20Sopenharmony_ci } 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci /* Write back any control register values that were modified. */ 17328c2ecf20Sopenharmony_ci ret = spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, ctrl_reg, 8); 17338c2ecf20Sopenharmony_ci if (ret) 17348c2ecf20Sopenharmony_ci return ret; 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci /* Set soft start strength and over current protection for VS. */ 17378c2ecf20Sopenharmony_ci if (type == SPMI_REGULATOR_LOGICAL_TYPE_VS) { 17388c2ecf20Sopenharmony_ci if (data->vs_soft_start_strength 17398c2ecf20Sopenharmony_ci != SPMI_VS_SOFT_START_STR_HW_DEFAULT) { 17408c2ecf20Sopenharmony_ci reg = data->vs_soft_start_strength 17418c2ecf20Sopenharmony_ci & SPMI_VS_SOFT_START_SEL_MASK; 17428c2ecf20Sopenharmony_ci mask = SPMI_VS_SOFT_START_SEL_MASK; 17438c2ecf20Sopenharmony_ci return spmi_vreg_update_bits(vreg, 17448c2ecf20Sopenharmony_ci SPMI_VS_REG_SOFT_START, 17458c2ecf20Sopenharmony_ci reg, mask); 17468c2ecf20Sopenharmony_ci } 17478c2ecf20Sopenharmony_ci } 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci return 0; 17508c2ecf20Sopenharmony_ci} 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_cistatic void spmi_regulator_get_dt_config(struct spmi_regulator *vreg, 17538c2ecf20Sopenharmony_ci struct device_node *node, struct spmi_regulator_init_data *data) 17548c2ecf20Sopenharmony_ci{ 17558c2ecf20Sopenharmony_ci /* 17568c2ecf20Sopenharmony_ci * Initialize configuration parameters to use hardware default in case 17578c2ecf20Sopenharmony_ci * no value is specified via device tree. 17588c2ecf20Sopenharmony_ci */ 17598c2ecf20Sopenharmony_ci data->pin_ctrl_enable = SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT; 17608c2ecf20Sopenharmony_ci data->pin_ctrl_hpm = SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT; 17618c2ecf20Sopenharmony_ci data->vs_soft_start_strength = SPMI_VS_SOFT_START_STR_HW_DEFAULT; 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci /* These bindings are optional, so it is okay if they aren't found. */ 17648c2ecf20Sopenharmony_ci of_property_read_u32(node, "qcom,ocp-max-retries", 17658c2ecf20Sopenharmony_ci &vreg->ocp_max_retries); 17668c2ecf20Sopenharmony_ci of_property_read_u32(node, "qcom,ocp-retry-delay", 17678c2ecf20Sopenharmony_ci &vreg->ocp_retry_delay_ms); 17688c2ecf20Sopenharmony_ci of_property_read_u32(node, "qcom,pin-ctrl-enable", 17698c2ecf20Sopenharmony_ci &data->pin_ctrl_enable); 17708c2ecf20Sopenharmony_ci of_property_read_u32(node, "qcom,pin-ctrl-hpm", &data->pin_ctrl_hpm); 17718c2ecf20Sopenharmony_ci of_property_read_u32(node, "qcom,vs-soft-start-strength", 17728c2ecf20Sopenharmony_ci &data->vs_soft_start_strength); 17738c2ecf20Sopenharmony_ci} 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_cistatic unsigned int spmi_regulator_of_map_mode(unsigned int mode) 17768c2ecf20Sopenharmony_ci{ 17778c2ecf20Sopenharmony_ci if (mode == 1) 17788c2ecf20Sopenharmony_ci return REGULATOR_MODE_NORMAL; 17798c2ecf20Sopenharmony_ci if (mode == 2) 17808c2ecf20Sopenharmony_ci return REGULATOR_MODE_FAST; 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci return REGULATOR_MODE_IDLE; 17838c2ecf20Sopenharmony_ci} 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_cistatic int spmi_regulator_of_parse(struct device_node *node, 17868c2ecf20Sopenharmony_ci const struct regulator_desc *desc, 17878c2ecf20Sopenharmony_ci struct regulator_config *config) 17888c2ecf20Sopenharmony_ci{ 17898c2ecf20Sopenharmony_ci struct spmi_regulator_init_data data = { }; 17908c2ecf20Sopenharmony_ci struct spmi_regulator *vreg = config->driver_data; 17918c2ecf20Sopenharmony_ci struct device *dev = config->dev; 17928c2ecf20Sopenharmony_ci int ret; 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci spmi_regulator_get_dt_config(vreg, node, &data); 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci if (!vreg->ocp_max_retries) 17978c2ecf20Sopenharmony_ci vreg->ocp_max_retries = SPMI_VS_OCP_DEFAULT_MAX_RETRIES; 17988c2ecf20Sopenharmony_ci if (!vreg->ocp_retry_delay_ms) 17998c2ecf20Sopenharmony_ci vreg->ocp_retry_delay_ms = SPMI_VS_OCP_DEFAULT_RETRY_DELAY_MS; 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci ret = spmi_regulator_init_registers(vreg, &data); 18028c2ecf20Sopenharmony_ci if (ret) { 18038c2ecf20Sopenharmony_ci dev_err(dev, "common initialization failed, ret=%d\n", ret); 18048c2ecf20Sopenharmony_ci return ret; 18058c2ecf20Sopenharmony_ci } 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci switch (vreg->logical_type) { 18088c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS: 18098c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS: 18108c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS: 18118c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_SMPS: 18128c2ecf20Sopenharmony_ci ret = spmi_regulator_init_slew_rate(vreg); 18138c2ecf20Sopenharmony_ci if (ret) 18148c2ecf20Sopenharmony_ci return ret; 18158c2ecf20Sopenharmony_ci break; 18168c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426: 18178c2ecf20Sopenharmony_ci ret = spmi_regulator_init_slew_rate_ftsmps426(vreg, 18188c2ecf20Sopenharmony_ci SPMI_FTSMPS426_CLOCK_RATE); 18198c2ecf20Sopenharmony_ci if (ret) 18208c2ecf20Sopenharmony_ci return ret; 18218c2ecf20Sopenharmony_ci break; 18228c2ecf20Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_HFS430: 18238c2ecf20Sopenharmony_ci ret = spmi_regulator_init_slew_rate_ftsmps426(vreg, 18248c2ecf20Sopenharmony_ci SPMI_HFS430_CLOCK_RATE); 18258c2ecf20Sopenharmony_ci if (ret) 18268c2ecf20Sopenharmony_ci return ret; 18278c2ecf20Sopenharmony_ci break; 18288c2ecf20Sopenharmony_ci default: 18298c2ecf20Sopenharmony_ci break; 18308c2ecf20Sopenharmony_ci } 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci if (vreg->logical_type != SPMI_REGULATOR_LOGICAL_TYPE_VS) 18338c2ecf20Sopenharmony_ci vreg->ocp_irq = 0; 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci if (vreg->ocp_irq) { 18368c2ecf20Sopenharmony_ci ret = devm_request_irq(dev, vreg->ocp_irq, 18378c2ecf20Sopenharmony_ci spmi_regulator_vs_ocp_isr, IRQF_TRIGGER_RISING, "ocp", 18388c2ecf20Sopenharmony_ci vreg); 18398c2ecf20Sopenharmony_ci if (ret < 0) { 18408c2ecf20Sopenharmony_ci dev_err(dev, "failed to request irq %d, ret=%d\n", 18418c2ecf20Sopenharmony_ci vreg->ocp_irq, ret); 18428c2ecf20Sopenharmony_ci return ret; 18438c2ecf20Sopenharmony_ci } 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&vreg->ocp_work, spmi_regulator_vs_ocp_work); 18468c2ecf20Sopenharmony_ci } 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci return 0; 18498c2ecf20Sopenharmony_ci} 18508c2ecf20Sopenharmony_ci 18518c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pm8941_regulators[] = { 18528c2ecf20Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 18538c2ecf20Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 18548c2ecf20Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 18558c2ecf20Sopenharmony_ci { "s4", 0xa000, }, 18568c2ecf20Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l3", }, 18578c2ecf20Sopenharmony_ci { "l2", 0x4100, "vdd_l2_lvs_1_2_3", }, 18588c2ecf20Sopenharmony_ci { "l3", 0x4200, "vdd_l1_l3", }, 18598c2ecf20Sopenharmony_ci { "l4", 0x4300, "vdd_l4_l11", }, 18608c2ecf20Sopenharmony_ci { "l5", 0x4400, "vdd_l5_l7", NULL, 0x0410 }, 18618c2ecf20Sopenharmony_ci { "l6", 0x4500, "vdd_l6_l12_l14_l15", }, 18628c2ecf20Sopenharmony_ci { "l7", 0x4600, "vdd_l5_l7", NULL, 0x0410 }, 18638c2ecf20Sopenharmony_ci { "l8", 0x4700, "vdd_l8_l16_l18_19", }, 18648c2ecf20Sopenharmony_ci { "l9", 0x4800, "vdd_l9_l10_l17_l22", }, 18658c2ecf20Sopenharmony_ci { "l10", 0x4900, "vdd_l9_l10_l17_l22", }, 18668c2ecf20Sopenharmony_ci { "l11", 0x4a00, "vdd_l4_l11", }, 18678c2ecf20Sopenharmony_ci { "l12", 0x4b00, "vdd_l6_l12_l14_l15", }, 18688c2ecf20Sopenharmony_ci { "l13", 0x4c00, "vdd_l13_l20_l23_l24", }, 18698c2ecf20Sopenharmony_ci { "l14", 0x4d00, "vdd_l6_l12_l14_l15", }, 18708c2ecf20Sopenharmony_ci { "l15", 0x4e00, "vdd_l6_l12_l14_l15", }, 18718c2ecf20Sopenharmony_ci { "l16", 0x4f00, "vdd_l8_l16_l18_19", }, 18728c2ecf20Sopenharmony_ci { "l17", 0x5000, "vdd_l9_l10_l17_l22", }, 18738c2ecf20Sopenharmony_ci { "l18", 0x5100, "vdd_l8_l16_l18_19", }, 18748c2ecf20Sopenharmony_ci { "l19", 0x5200, "vdd_l8_l16_l18_19", }, 18758c2ecf20Sopenharmony_ci { "l20", 0x5300, "vdd_l13_l20_l23_l24", }, 18768c2ecf20Sopenharmony_ci { "l21", 0x5400, "vdd_l21", }, 18778c2ecf20Sopenharmony_ci { "l22", 0x5500, "vdd_l9_l10_l17_l22", }, 18788c2ecf20Sopenharmony_ci { "l23", 0x5600, "vdd_l13_l20_l23_l24", }, 18798c2ecf20Sopenharmony_ci { "l24", 0x5700, "vdd_l13_l20_l23_l24", }, 18808c2ecf20Sopenharmony_ci { "lvs1", 0x8000, "vdd_l2_lvs_1_2_3", }, 18818c2ecf20Sopenharmony_ci { "lvs2", 0x8100, "vdd_l2_lvs_1_2_3", }, 18828c2ecf20Sopenharmony_ci { "lvs3", 0x8200, "vdd_l2_lvs_1_2_3", }, 18838c2ecf20Sopenharmony_ci { "5vs1", 0x8300, "vin_5vs", "ocp-5vs1", }, 18848c2ecf20Sopenharmony_ci { "5vs2", 0x8400, "vin_5vs", "ocp-5vs2", }, 18858c2ecf20Sopenharmony_ci { } 18868c2ecf20Sopenharmony_ci}; 18878c2ecf20Sopenharmony_ci 18888c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pm8841_regulators[] = { 18898c2ecf20Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 18908c2ecf20Sopenharmony_ci { "s2", 0x1700, "vdd_s2", NULL, 0x1c08 }, 18918c2ecf20Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 18928c2ecf20Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", NULL, 0x1c08 }, 18938c2ecf20Sopenharmony_ci { "s5", 0x2000, "vdd_s5", NULL, 0x1c08 }, 18948c2ecf20Sopenharmony_ci { "s6", 0x2300, "vdd_s6", NULL, 0x1c08 }, 18958c2ecf20Sopenharmony_ci { "s7", 0x2600, "vdd_s7", NULL, 0x1c08 }, 18968c2ecf20Sopenharmony_ci { "s8", 0x2900, "vdd_s8", NULL, 0x1c08 }, 18978c2ecf20Sopenharmony_ci { } 18988c2ecf20Sopenharmony_ci}; 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pm8916_regulators[] = { 19018c2ecf20Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 19028c2ecf20Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 19038c2ecf20Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 19048c2ecf20Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 19058c2ecf20Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l3", }, 19068c2ecf20Sopenharmony_ci { "l2", 0x4100, "vdd_l2", }, 19078c2ecf20Sopenharmony_ci { "l3", 0x4200, "vdd_l1_l3", }, 19088c2ecf20Sopenharmony_ci { "l4", 0x4300, "vdd_l4_l5_l6", }, 19098c2ecf20Sopenharmony_ci { "l5", 0x4400, "vdd_l4_l5_l6", }, 19108c2ecf20Sopenharmony_ci { "l6", 0x4500, "vdd_l4_l5_l6", }, 19118c2ecf20Sopenharmony_ci { "l7", 0x4600, "vdd_l7", }, 19128c2ecf20Sopenharmony_ci { "l8", 0x4700, "vdd_l8_l11_l14_l15_l16", }, 19138c2ecf20Sopenharmony_ci { "l9", 0x4800, "vdd_l9_l10_l12_l13_l17_l18", }, 19148c2ecf20Sopenharmony_ci { "l10", 0x4900, "vdd_l9_l10_l12_l13_l17_l18", }, 19158c2ecf20Sopenharmony_ci { "l11", 0x4a00, "vdd_l8_l11_l14_l15_l16", }, 19168c2ecf20Sopenharmony_ci { "l12", 0x4b00, "vdd_l9_l10_l12_l13_l17_l18", }, 19178c2ecf20Sopenharmony_ci { "l13", 0x4c00, "vdd_l9_l10_l12_l13_l17_l18", }, 19188c2ecf20Sopenharmony_ci { "l14", 0x4d00, "vdd_l8_l11_l14_l15_l16", }, 19198c2ecf20Sopenharmony_ci { "l15", 0x4e00, "vdd_l8_l11_l14_l15_l16", }, 19208c2ecf20Sopenharmony_ci { "l16", 0x4f00, "vdd_l8_l11_l14_l15_l16", }, 19218c2ecf20Sopenharmony_ci { "l17", 0x5000, "vdd_l9_l10_l12_l13_l17_l18", }, 19228c2ecf20Sopenharmony_ci { "l18", 0x5100, "vdd_l9_l10_l12_l13_l17_l18", }, 19238c2ecf20Sopenharmony_ci { } 19248c2ecf20Sopenharmony_ci}; 19258c2ecf20Sopenharmony_ci 19268c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pm8950_regulators[] = { 19278c2ecf20Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 19288c2ecf20Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 19298c2ecf20Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 19308c2ecf20Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 19318c2ecf20Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 19328c2ecf20Sopenharmony_ci { "s6", 0x2300, "vdd_s6", }, 19338c2ecf20Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l19", }, 19348c2ecf20Sopenharmony_ci { "l2", 0x4100, "vdd_l2_l23", }, 19358c2ecf20Sopenharmony_ci { "l3", 0x4200, "vdd_l3", }, 19368c2ecf20Sopenharmony_ci { "l4", 0x4300, "vdd_l4_l5_l6_l7_l16", }, 19378c2ecf20Sopenharmony_ci { "l5", 0x4400, "vdd_l4_l5_l6_l7_l16", }, 19388c2ecf20Sopenharmony_ci { "l6", 0x4500, "vdd_l4_l5_l6_l7_l16", }, 19398c2ecf20Sopenharmony_ci { "l7", 0x4600, "vdd_l4_l5_l6_l7_l16", }, 19408c2ecf20Sopenharmony_ci { "l8", 0x4700, "vdd_l8_l11_l12_l17_l22", }, 19418c2ecf20Sopenharmony_ci { "l9", 0x4800, "vdd_l9_l10_l13_l14_l15_l18", }, 19428c2ecf20Sopenharmony_ci { "l10", 0x4900, "vdd_l9_l10_l13_l14_l15_l18", }, 19438c2ecf20Sopenharmony_ci { "l11", 0x4a00, "vdd_l8_l11_l12_l17_l22", }, 19448c2ecf20Sopenharmony_ci { "l12", 0x4b00, "vdd_l8_l11_l12_l17_l22", }, 19458c2ecf20Sopenharmony_ci { "l13", 0x4c00, "vdd_l9_l10_l13_l14_l15_l18", }, 19468c2ecf20Sopenharmony_ci { "l14", 0x4d00, "vdd_l9_l10_l13_l14_l15_l18", }, 19478c2ecf20Sopenharmony_ci { "l15", 0x4e00, "vdd_l9_l10_l13_l14_l15_l18", }, 19488c2ecf20Sopenharmony_ci { "l16", 0x4f00, "vdd_l4_l5_l6_l7_l16", }, 19498c2ecf20Sopenharmony_ci { "l17", 0x5000, "vdd_l8_l11_l12_l17_l22", }, 19508c2ecf20Sopenharmony_ci { "l18", 0x5100, "vdd_l9_l10_l13_l14_l15_l18", }, 19518c2ecf20Sopenharmony_ci { "l19", 0x5200, "vdd_l1_l19", }, 19528c2ecf20Sopenharmony_ci { "l20", 0x5300, "vdd_l20", }, 19538c2ecf20Sopenharmony_ci { "l21", 0x5400, "vdd_l21", }, 19548c2ecf20Sopenharmony_ci { "l22", 0x5500, "vdd_l8_l11_l12_l17_l22", }, 19558c2ecf20Sopenharmony_ci { "l23", 0x5600, "vdd_l2_l23", }, 19568c2ecf20Sopenharmony_ci { } 19578c2ecf20Sopenharmony_ci}; 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pm8994_regulators[] = { 19608c2ecf20Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 19618c2ecf20Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 19628c2ecf20Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 19638c2ecf20Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 19648c2ecf20Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 19658c2ecf20Sopenharmony_ci { "s6", 0x2300, "vdd_s6", }, 19668c2ecf20Sopenharmony_ci { "s7", 0x2600, "vdd_s7", }, 19678c2ecf20Sopenharmony_ci { "s8", 0x2900, "vdd_s8", }, 19688c2ecf20Sopenharmony_ci { "s9", 0x2c00, "vdd_s9", }, 19698c2ecf20Sopenharmony_ci { "s10", 0x2f00, "vdd_s10", }, 19708c2ecf20Sopenharmony_ci { "s11", 0x3200, "vdd_s11", }, 19718c2ecf20Sopenharmony_ci { "s12", 0x3500, "vdd_s12", }, 19728c2ecf20Sopenharmony_ci { "l1", 0x4000, "vdd_l1", }, 19738c2ecf20Sopenharmony_ci { "l2", 0x4100, "vdd_l2_l26_l28", }, 19748c2ecf20Sopenharmony_ci { "l3", 0x4200, "vdd_l3_l11", }, 19758c2ecf20Sopenharmony_ci { "l4", 0x4300, "vdd_l4_l27_l31", }, 19768c2ecf20Sopenharmony_ci { "l5", 0x4400, "vdd_l5_l7", }, 19778c2ecf20Sopenharmony_ci { "l6", 0x4500, "vdd_l6_l12_l32", }, 19788c2ecf20Sopenharmony_ci { "l7", 0x4600, "vdd_l5_l7", }, 19798c2ecf20Sopenharmony_ci { "l8", 0x4700, "vdd_l8_l16_l30", }, 19808c2ecf20Sopenharmony_ci { "l9", 0x4800, "vdd_l9_l10_l18_l22", }, 19818c2ecf20Sopenharmony_ci { "l10", 0x4900, "vdd_l9_l10_l18_l22", }, 19828c2ecf20Sopenharmony_ci { "l11", 0x4a00, "vdd_l3_l11", }, 19838c2ecf20Sopenharmony_ci { "l12", 0x4b00, "vdd_l6_l12_l32", }, 19848c2ecf20Sopenharmony_ci { "l13", 0x4c00, "vdd_l13_l19_l23_l24", }, 19858c2ecf20Sopenharmony_ci { "l14", 0x4d00, "vdd_l14_l15", }, 19868c2ecf20Sopenharmony_ci { "l15", 0x4e00, "vdd_l14_l15", }, 19878c2ecf20Sopenharmony_ci { "l16", 0x4f00, "vdd_l8_l16_l30", }, 19888c2ecf20Sopenharmony_ci { "l17", 0x5000, "vdd_l17_l29", }, 19898c2ecf20Sopenharmony_ci { "l18", 0x5100, "vdd_l9_l10_l18_l22", }, 19908c2ecf20Sopenharmony_ci { "l19", 0x5200, "vdd_l13_l19_l23_l24", }, 19918c2ecf20Sopenharmony_ci { "l20", 0x5300, "vdd_l20_l21", }, 19928c2ecf20Sopenharmony_ci { "l21", 0x5400, "vdd_l20_l21", }, 19938c2ecf20Sopenharmony_ci { "l22", 0x5500, "vdd_l9_l10_l18_l22", }, 19948c2ecf20Sopenharmony_ci { "l23", 0x5600, "vdd_l13_l19_l23_l24", }, 19958c2ecf20Sopenharmony_ci { "l24", 0x5700, "vdd_l13_l19_l23_l24", }, 19968c2ecf20Sopenharmony_ci { "l25", 0x5800, "vdd_l25", }, 19978c2ecf20Sopenharmony_ci { "l26", 0x5900, "vdd_l2_l26_l28", }, 19988c2ecf20Sopenharmony_ci { "l27", 0x5a00, "vdd_l4_l27_l31", }, 19998c2ecf20Sopenharmony_ci { "l28", 0x5b00, "vdd_l2_l26_l28", }, 20008c2ecf20Sopenharmony_ci { "l29", 0x5c00, "vdd_l17_l29", }, 20018c2ecf20Sopenharmony_ci { "l30", 0x5d00, "vdd_l8_l16_l30", }, 20028c2ecf20Sopenharmony_ci { "l31", 0x5e00, "vdd_l4_l27_l31", }, 20038c2ecf20Sopenharmony_ci { "l32", 0x5f00, "vdd_l6_l12_l32", }, 20048c2ecf20Sopenharmony_ci { "lvs1", 0x8000, "vdd_lvs_1_2", }, 20058c2ecf20Sopenharmony_ci { "lvs2", 0x8100, "vdd_lvs_1_2", }, 20068c2ecf20Sopenharmony_ci { } 20078c2ecf20Sopenharmony_ci}; 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pmi8994_regulators[] = { 20108c2ecf20Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 20118c2ecf20Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 20128c2ecf20Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 20138c2ecf20Sopenharmony_ci { "l1", 0x4000, "vdd_l1", }, 20148c2ecf20Sopenharmony_ci { } 20158c2ecf20Sopenharmony_ci}; 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pm660_regulators[] = { 20188c2ecf20Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 20198c2ecf20Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 20208c2ecf20Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 20218c2ecf20Sopenharmony_ci { "s4", 0x1d00, "vdd_s3", }, 20228c2ecf20Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 20238c2ecf20Sopenharmony_ci { "s6", 0x2300, "vdd_s6", }, 20248c2ecf20Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l6_l7", }, 20258c2ecf20Sopenharmony_ci { "l2", 0x4100, "vdd_l2_l3", }, 20268c2ecf20Sopenharmony_ci { "l3", 0x4200, "vdd_l2_l3", }, 20278c2ecf20Sopenharmony_ci /* l4 is unaccessible on PM660 */ 20288c2ecf20Sopenharmony_ci { "l5", 0x4400, "vdd_l5", }, 20298c2ecf20Sopenharmony_ci { "l6", 0x4500, "vdd_l1_l6_l7", }, 20308c2ecf20Sopenharmony_ci { "l7", 0x4600, "vdd_l1_l6_l7", }, 20318c2ecf20Sopenharmony_ci { "l8", 0x4700, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 20328c2ecf20Sopenharmony_ci { "l9", 0x4800, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 20338c2ecf20Sopenharmony_ci { "l10", 0x4900, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 20348c2ecf20Sopenharmony_ci { "l11", 0x4a00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 20358c2ecf20Sopenharmony_ci { "l12", 0x4b00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 20368c2ecf20Sopenharmony_ci { "l13", 0x4c00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 20378c2ecf20Sopenharmony_ci { "l14", 0x4d00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 20388c2ecf20Sopenharmony_ci { "l15", 0x4e00, "vdd_l15_l16_l17_l18_l19", }, 20398c2ecf20Sopenharmony_ci { "l16", 0x4f00, "vdd_l15_l16_l17_l18_l19", }, 20408c2ecf20Sopenharmony_ci { "l17", 0x5000, "vdd_l15_l16_l17_l18_l19", }, 20418c2ecf20Sopenharmony_ci { "l18", 0x5100, "vdd_l15_l16_l17_l18_l19", }, 20428c2ecf20Sopenharmony_ci { "l19", 0x5200, "vdd_l15_l16_l17_l18_l19", }, 20438c2ecf20Sopenharmony_ci { } 20448c2ecf20Sopenharmony_ci}; 20458c2ecf20Sopenharmony_ci 20468c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pm660l_regulators[] = { 20478c2ecf20Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 20488c2ecf20Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 20498c2ecf20Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 20508c2ecf20Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 20518c2ecf20Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 20528c2ecf20Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l9_l10", }, 20538c2ecf20Sopenharmony_ci { "l2", 0x4100, "vdd_l2", }, 20548c2ecf20Sopenharmony_ci { "l3", 0x4200, "vdd_l3_l5_l7_l8", }, 20558c2ecf20Sopenharmony_ci { "l4", 0x4300, "vdd_l4_l6", }, 20568c2ecf20Sopenharmony_ci { "l5", 0x4400, "vdd_l3_l5_l7_l8", }, 20578c2ecf20Sopenharmony_ci { "l6", 0x4500, "vdd_l4_l6", }, 20588c2ecf20Sopenharmony_ci { "l7", 0x4600, "vdd_l3_l5_l7_l8", }, 20598c2ecf20Sopenharmony_ci { "l8", 0x4700, "vdd_l3_l5_l7_l8", }, 20608c2ecf20Sopenharmony_ci { "l9", 0x4800, "vdd_l1_l9_l10", }, 20618c2ecf20Sopenharmony_ci { "l10", 0x4900, "vdd_l1_l9_l10", }, 20628c2ecf20Sopenharmony_ci { } 20638c2ecf20Sopenharmony_ci}; 20648c2ecf20Sopenharmony_ci 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pm8004_regulators[] = { 20678c2ecf20Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 20688c2ecf20Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 20698c2ecf20Sopenharmony_ci { } 20708c2ecf20Sopenharmony_ci}; 20718c2ecf20Sopenharmony_ci 20728c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pm8005_regulators[] = { 20738c2ecf20Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 20748c2ecf20Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 20758c2ecf20Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 20768c2ecf20Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 20778c2ecf20Sopenharmony_ci { } 20788c2ecf20Sopenharmony_ci}; 20798c2ecf20Sopenharmony_ci 20808c2ecf20Sopenharmony_cistatic const struct spmi_regulator_data pms405_regulators[] = { 20818c2ecf20Sopenharmony_ci { "s3", 0x1a00, "vdd_s3"}, 20828c2ecf20Sopenharmony_ci { } 20838c2ecf20Sopenharmony_ci}; 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_cistatic const struct of_device_id qcom_spmi_regulator_match[] = { 20868c2ecf20Sopenharmony_ci { .compatible = "qcom,pm8004-regulators", .data = &pm8004_regulators }, 20878c2ecf20Sopenharmony_ci { .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators }, 20888c2ecf20Sopenharmony_ci { .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators }, 20898c2ecf20Sopenharmony_ci { .compatible = "qcom,pm8916-regulators", .data = &pm8916_regulators }, 20908c2ecf20Sopenharmony_ci { .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators }, 20918c2ecf20Sopenharmony_ci { .compatible = "qcom,pm8950-regulators", .data = &pm8950_regulators }, 20928c2ecf20Sopenharmony_ci { .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators }, 20938c2ecf20Sopenharmony_ci { .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators }, 20948c2ecf20Sopenharmony_ci { .compatible = "qcom,pm660-regulators", .data = &pm660_regulators }, 20958c2ecf20Sopenharmony_ci { .compatible = "qcom,pm660l-regulators", .data = &pm660l_regulators }, 20968c2ecf20Sopenharmony_ci { .compatible = "qcom,pms405-regulators", .data = &pms405_regulators }, 20978c2ecf20Sopenharmony_ci { } 20988c2ecf20Sopenharmony_ci}; 20998c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, qcom_spmi_regulator_match); 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_cistatic int qcom_spmi_regulator_probe(struct platform_device *pdev) 21028c2ecf20Sopenharmony_ci{ 21038c2ecf20Sopenharmony_ci const struct spmi_regulator_data *reg; 21048c2ecf20Sopenharmony_ci const struct spmi_voltage_range *range; 21058c2ecf20Sopenharmony_ci const struct of_device_id *match; 21068c2ecf20Sopenharmony_ci struct regulator_config config = { }; 21078c2ecf20Sopenharmony_ci struct regulator_dev *rdev; 21088c2ecf20Sopenharmony_ci struct spmi_regulator *vreg; 21098c2ecf20Sopenharmony_ci struct regmap *regmap; 21108c2ecf20Sopenharmony_ci const char *name; 21118c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 21128c2ecf20Sopenharmony_ci struct device_node *node = pdev->dev.of_node; 21138c2ecf20Sopenharmony_ci struct device_node *syscon, *reg_node; 21148c2ecf20Sopenharmony_ci struct property *reg_prop; 21158c2ecf20Sopenharmony_ci int ret, lenp; 21168c2ecf20Sopenharmony_ci struct list_head *vreg_list; 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci vreg_list = devm_kzalloc(dev, sizeof(*vreg_list), GFP_KERNEL); 21198c2ecf20Sopenharmony_ci if (!vreg_list) 21208c2ecf20Sopenharmony_ci return -ENOMEM; 21218c2ecf20Sopenharmony_ci INIT_LIST_HEAD(vreg_list); 21228c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, vreg_list); 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci regmap = dev_get_regmap(dev->parent, NULL); 21258c2ecf20Sopenharmony_ci if (!regmap) 21268c2ecf20Sopenharmony_ci return -ENODEV; 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci match = of_match_device(qcom_spmi_regulator_match, &pdev->dev); 21298c2ecf20Sopenharmony_ci if (!match) 21308c2ecf20Sopenharmony_ci return -ENODEV; 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_ci if (of_find_property(node, "qcom,saw-reg", &lenp)) { 21338c2ecf20Sopenharmony_ci syscon = of_parse_phandle(node, "qcom,saw-reg", 0); 21348c2ecf20Sopenharmony_ci saw_regmap = syscon_node_to_regmap(syscon); 21358c2ecf20Sopenharmony_ci of_node_put(syscon); 21368c2ecf20Sopenharmony_ci if (IS_ERR(saw_regmap)) 21378c2ecf20Sopenharmony_ci dev_err(dev, "ERROR reading SAW regmap\n"); 21388c2ecf20Sopenharmony_ci } 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_ci for (reg = match->data; reg->name; reg++) { 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci if (saw_regmap) { 21438c2ecf20Sopenharmony_ci reg_node = of_get_child_by_name(node, reg->name); 21448c2ecf20Sopenharmony_ci reg_prop = of_find_property(reg_node, "qcom,saw-slave", 21458c2ecf20Sopenharmony_ci &lenp); 21468c2ecf20Sopenharmony_ci of_node_put(reg_node); 21478c2ecf20Sopenharmony_ci if (reg_prop) 21488c2ecf20Sopenharmony_ci continue; 21498c2ecf20Sopenharmony_ci } 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); 21528c2ecf20Sopenharmony_ci if (!vreg) 21538c2ecf20Sopenharmony_ci return -ENOMEM; 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ci vreg->dev = dev; 21568c2ecf20Sopenharmony_ci vreg->base = reg->base; 21578c2ecf20Sopenharmony_ci vreg->regmap = regmap; 21588c2ecf20Sopenharmony_ci if (reg->ocp) { 21598c2ecf20Sopenharmony_ci vreg->ocp_irq = platform_get_irq_byname(pdev, reg->ocp); 21608c2ecf20Sopenharmony_ci if (vreg->ocp_irq < 0) { 21618c2ecf20Sopenharmony_ci ret = vreg->ocp_irq; 21628c2ecf20Sopenharmony_ci goto err; 21638c2ecf20Sopenharmony_ci } 21648c2ecf20Sopenharmony_ci } 21658c2ecf20Sopenharmony_ci vreg->desc.id = -1; 21668c2ecf20Sopenharmony_ci vreg->desc.owner = THIS_MODULE; 21678c2ecf20Sopenharmony_ci vreg->desc.type = REGULATOR_VOLTAGE; 21688c2ecf20Sopenharmony_ci vreg->desc.enable_reg = reg->base + SPMI_COMMON_REG_ENABLE; 21698c2ecf20Sopenharmony_ci vreg->desc.enable_mask = SPMI_COMMON_ENABLE_MASK; 21708c2ecf20Sopenharmony_ci vreg->desc.enable_val = SPMI_COMMON_ENABLE; 21718c2ecf20Sopenharmony_ci vreg->desc.name = name = reg->name; 21728c2ecf20Sopenharmony_ci vreg->desc.supply_name = reg->supply; 21738c2ecf20Sopenharmony_ci vreg->desc.of_match = reg->name; 21748c2ecf20Sopenharmony_ci vreg->desc.of_parse_cb = spmi_regulator_of_parse; 21758c2ecf20Sopenharmony_ci vreg->desc.of_map_mode = spmi_regulator_of_map_mode; 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_ci ret = spmi_regulator_match(vreg, reg->force_type); 21788c2ecf20Sopenharmony_ci if (ret) 21798c2ecf20Sopenharmony_ci continue; 21808c2ecf20Sopenharmony_ci 21818c2ecf20Sopenharmony_ci if (saw_regmap) { 21828c2ecf20Sopenharmony_ci reg_node = of_get_child_by_name(node, reg->name); 21838c2ecf20Sopenharmony_ci reg_prop = of_find_property(reg_node, "qcom,saw-leader", 21848c2ecf20Sopenharmony_ci &lenp); 21858c2ecf20Sopenharmony_ci of_node_put(reg_node); 21868c2ecf20Sopenharmony_ci if (reg_prop) { 21878c2ecf20Sopenharmony_ci spmi_saw_ops = *(vreg->desc.ops); 21888c2ecf20Sopenharmony_ci spmi_saw_ops.set_voltage_sel = 21898c2ecf20Sopenharmony_ci spmi_regulator_saw_set_voltage; 21908c2ecf20Sopenharmony_ci vreg->desc.ops = &spmi_saw_ops; 21918c2ecf20Sopenharmony_ci } 21928c2ecf20Sopenharmony_ci } 21938c2ecf20Sopenharmony_ci 21948c2ecf20Sopenharmony_ci if (vreg->set_points && vreg->set_points->count == 1) { 21958c2ecf20Sopenharmony_ci /* since there is only one range */ 21968c2ecf20Sopenharmony_ci range = vreg->set_points->range; 21978c2ecf20Sopenharmony_ci vreg->desc.uV_step = range->step_uV; 21988c2ecf20Sopenharmony_ci } 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_ci config.dev = dev; 22018c2ecf20Sopenharmony_ci config.driver_data = vreg; 22028c2ecf20Sopenharmony_ci config.regmap = regmap; 22038c2ecf20Sopenharmony_ci rdev = devm_regulator_register(dev, &vreg->desc, &config); 22048c2ecf20Sopenharmony_ci if (IS_ERR(rdev)) { 22058c2ecf20Sopenharmony_ci dev_err(dev, "failed to register %s\n", name); 22068c2ecf20Sopenharmony_ci ret = PTR_ERR(rdev); 22078c2ecf20Sopenharmony_ci goto err; 22088c2ecf20Sopenharmony_ci } 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vreg->node); 22118c2ecf20Sopenharmony_ci list_add(&vreg->node, vreg_list); 22128c2ecf20Sopenharmony_ci } 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ci return 0; 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_cierr: 22178c2ecf20Sopenharmony_ci list_for_each_entry(vreg, vreg_list, node) 22188c2ecf20Sopenharmony_ci if (vreg->ocp_irq) 22198c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&vreg->ocp_work); 22208c2ecf20Sopenharmony_ci return ret; 22218c2ecf20Sopenharmony_ci} 22228c2ecf20Sopenharmony_ci 22238c2ecf20Sopenharmony_cistatic int qcom_spmi_regulator_remove(struct platform_device *pdev) 22248c2ecf20Sopenharmony_ci{ 22258c2ecf20Sopenharmony_ci struct spmi_regulator *vreg; 22268c2ecf20Sopenharmony_ci struct list_head *vreg_list = platform_get_drvdata(pdev); 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci list_for_each_entry(vreg, vreg_list, node) 22298c2ecf20Sopenharmony_ci if (vreg->ocp_irq) 22308c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&vreg->ocp_work); 22318c2ecf20Sopenharmony_ci 22328c2ecf20Sopenharmony_ci return 0; 22338c2ecf20Sopenharmony_ci} 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_cistatic struct platform_driver qcom_spmi_regulator_driver = { 22368c2ecf20Sopenharmony_ci .driver = { 22378c2ecf20Sopenharmony_ci .name = "qcom-spmi-regulator", 22388c2ecf20Sopenharmony_ci .of_match_table = qcom_spmi_regulator_match, 22398c2ecf20Sopenharmony_ci }, 22408c2ecf20Sopenharmony_ci .probe = qcom_spmi_regulator_probe, 22418c2ecf20Sopenharmony_ci .remove = qcom_spmi_regulator_remove, 22428c2ecf20Sopenharmony_ci}; 22438c2ecf20Sopenharmony_cimodule_platform_driver(qcom_spmi_regulator_driver); 22448c2ecf20Sopenharmony_ci 22458c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Qualcomm SPMI PMIC regulator driver"); 22468c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 22478c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:qcom-spmi-regulator"); 2248