162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/module.h> 762306a36Sopenharmony_ci#include <linux/delay.h> 862306a36Sopenharmony_ci#include <linux/devm-helpers.h> 962306a36Sopenharmony_ci#include <linux/err.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/interrupt.h> 1262306a36Sopenharmony_ci#include <linux/bitops.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/of.h> 1562306a36Sopenharmony_ci#include <linux/of_device.h> 1662306a36Sopenharmony_ci#include <linux/platform_device.h> 1762306a36Sopenharmony_ci#include <linux/ktime.h> 1862306a36Sopenharmony_ci#include <linux/regulator/driver.h> 1962306a36Sopenharmony_ci#include <linux/regmap.h> 2062306a36Sopenharmony_ci#include <linux/list.h> 2162306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 2262306a36Sopenharmony_ci#include <linux/io.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* Pin control enable input pins. */ 2562306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_NONE 0x00 2662306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN0 0x01 2762306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN1 0x02 2862306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN2 0x04 2962306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN3 0x08 3062306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT 0x10 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* Pin control high power mode input pins. */ 3362306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_NONE 0x00 3462306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_EN0 0x01 3562306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_EN1 0x02 3662306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_EN2 0x04 3762306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_EN3 0x08 3862306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_SLEEP_B 0x10 3962306a36Sopenharmony_ci#define SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT 0x20 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* 4262306a36Sopenharmony_ci * Used with enable parameters to specify that hardware default register values 4362306a36Sopenharmony_ci * should be left unaltered. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ci#define SPMI_REGULATOR_USE_HW_DEFAULT 2 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* Soft start strength of a voltage switch type regulator */ 4862306a36Sopenharmony_cienum spmi_vs_soft_start_str { 4962306a36Sopenharmony_ci SPMI_VS_SOFT_START_STR_0P05_UA = 0, 5062306a36Sopenharmony_ci SPMI_VS_SOFT_START_STR_0P25_UA, 5162306a36Sopenharmony_ci SPMI_VS_SOFT_START_STR_0P55_UA, 5262306a36Sopenharmony_ci SPMI_VS_SOFT_START_STR_0P75_UA, 5362306a36Sopenharmony_ci SPMI_VS_SOFT_START_STR_HW_DEFAULT, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/** 5762306a36Sopenharmony_ci * struct spmi_regulator_init_data - spmi-regulator initialization data 5862306a36Sopenharmony_ci * @pin_ctrl_enable: Bit mask specifying which hardware pins should be 5962306a36Sopenharmony_ci * used to enable the regulator, if any 6062306a36Sopenharmony_ci * Value should be an ORing of 6162306a36Sopenharmony_ci * SPMI_REGULATOR_PIN_CTRL_ENABLE_* constants. If 6262306a36Sopenharmony_ci * the bit specified by 6362306a36Sopenharmony_ci * SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT is 6462306a36Sopenharmony_ci * set, then pin control enable hardware registers 6562306a36Sopenharmony_ci * will not be modified. 6662306a36Sopenharmony_ci * @pin_ctrl_hpm: Bit mask specifying which hardware pins should be 6762306a36Sopenharmony_ci * used to force the regulator into high power 6862306a36Sopenharmony_ci * mode, if any 6962306a36Sopenharmony_ci * Value should be an ORing of 7062306a36Sopenharmony_ci * SPMI_REGULATOR_PIN_CTRL_HPM_* constants. If 7162306a36Sopenharmony_ci * the bit specified by 7262306a36Sopenharmony_ci * SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT is 7362306a36Sopenharmony_ci * set, then pin control mode hardware registers 7462306a36Sopenharmony_ci * will not be modified. 7562306a36Sopenharmony_ci * @vs_soft_start_strength: This parameter sets the soft start strength for 7662306a36Sopenharmony_ci * voltage switch type regulators. Its value 7762306a36Sopenharmony_ci * should be one of SPMI_VS_SOFT_START_STR_*. If 7862306a36Sopenharmony_ci * its value is SPMI_VS_SOFT_START_STR_HW_DEFAULT, 7962306a36Sopenharmony_ci * then the soft start strength will be left at its 8062306a36Sopenharmony_ci * default hardware value. 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_cistruct spmi_regulator_init_data { 8362306a36Sopenharmony_ci unsigned pin_ctrl_enable; 8462306a36Sopenharmony_ci unsigned pin_ctrl_hpm; 8562306a36Sopenharmony_ci enum spmi_vs_soft_start_str vs_soft_start_strength; 8662306a36Sopenharmony_ci}; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/* These types correspond to unique register layouts. */ 8962306a36Sopenharmony_cienum spmi_regulator_logical_type { 9062306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_SMPS, 9162306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_LDO, 9262306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_VS, 9362306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_BOOST, 9462306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS, 9562306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_BOOST_BYP, 9662306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_LN_LDO, 9762306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS, 9862306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS, 9962306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO, 10062306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426, 10162306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_HFS430, 10262306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS3, 10362306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_LDO_510, 10462306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_HFSMPS, 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cienum spmi_regulator_type { 10862306a36Sopenharmony_ci SPMI_REGULATOR_TYPE_BUCK = 0x03, 10962306a36Sopenharmony_ci SPMI_REGULATOR_TYPE_LDO = 0x04, 11062306a36Sopenharmony_ci SPMI_REGULATOR_TYPE_VS = 0x05, 11162306a36Sopenharmony_ci SPMI_REGULATOR_TYPE_BOOST = 0x1b, 11262306a36Sopenharmony_ci SPMI_REGULATOR_TYPE_FTS = 0x1c, 11362306a36Sopenharmony_ci SPMI_REGULATOR_TYPE_BOOST_BYP = 0x1f, 11462306a36Sopenharmony_ci SPMI_REGULATOR_TYPE_ULT_LDO = 0x21, 11562306a36Sopenharmony_ci SPMI_REGULATOR_TYPE_ULT_BUCK = 0x22, 11662306a36Sopenharmony_ci}; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cienum spmi_regulator_subtype { 11962306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_GP_CTL = 0x08, 12062306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_RF_CTL = 0x09, 12162306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N50 = 0x01, 12262306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N150 = 0x02, 12362306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N300 = 0x03, 12462306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N600 = 0x04, 12562306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N1200 = 0x05, 12662306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N600_ST = 0x06, 12762306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N1200_ST = 0x07, 12862306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N900_ST = 0x14, 12962306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N300_ST = 0x15, 13062306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_P50 = 0x08, 13162306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_P150 = 0x09, 13262306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_P300 = 0x0a, 13362306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_P600 = 0x0b, 13462306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_P1200 = 0x0c, 13562306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LN = 0x10, 13662306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P50 = 0x28, 13762306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P150 = 0x29, 13862306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P300 = 0x2a, 13962306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P600 = 0x2b, 14062306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P1200 = 0x2c, 14162306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P450 = 0x2d, 14262306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_N300_ST = 0x30, 14362306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_N600_ST = 0x31, 14462306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_N1200_ST = 0x32, 14562306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_LVP150 = 0x3b, 14662306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_LVP300 = 0x3c, 14762306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_N300_ST = 0x42, 14862306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_N600_ST = 0x43, 14962306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_P50 = 0x46, 15062306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_P150 = 0x47, 15162306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_P600 = 0x49, 15262306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_LVP150 = 0x4d, 15362306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_L660_LVP600 = 0x4f, 15462306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV100 = 0x01, 15562306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV300 = 0x02, 15662306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_MV300 = 0x08, 15762306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_MV500 = 0x09, 15862306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HDMI = 0x10, 15962306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_OTG = 0x11, 16062306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_5V_BOOST = 0x01, 16162306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_FTS_CTL = 0x08, 16262306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_FTS2p5_CTL = 0x09, 16362306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_FTS426_CTL = 0x0a, 16462306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_BB_2A = 0x01, 16562306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL1 = 0x0d, 16662306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL2 = 0x0e, 16762306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL3 = 0x0f, 16862306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10, 16962306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HFS430 = 0x0a, 17062306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_P150 = 0x35, 17162306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HT_P600 = 0x3d, 17262306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_HFSMPS_510 = 0x0a, 17362306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_FTSMPS_510 = 0x0b, 17462306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P150_510 = 0x71, 17562306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P300_510 = 0x72, 17662306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_LV_P600_510 = 0x73, 17762306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N300_510 = 0x6a, 17862306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N600_510 = 0x6b, 17962306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_N1200_510 = 0x6c, 18062306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_MV_P50_510 = 0x7a, 18162306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_MV_P150_510 = 0x7b, 18262306a36Sopenharmony_ci SPMI_REGULATOR_SUBTYPE_MV_P600_510 = 0x7d, 18362306a36Sopenharmony_ci}; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cienum spmi_common_regulator_registers { 18662306a36Sopenharmony_ci SPMI_COMMON_REG_DIG_MAJOR_REV = 0x01, 18762306a36Sopenharmony_ci SPMI_COMMON_REG_TYPE = 0x04, 18862306a36Sopenharmony_ci SPMI_COMMON_REG_SUBTYPE = 0x05, 18962306a36Sopenharmony_ci SPMI_COMMON_REG_VOLTAGE_RANGE = 0x40, 19062306a36Sopenharmony_ci SPMI_COMMON_REG_VOLTAGE_SET = 0x41, 19162306a36Sopenharmony_ci SPMI_COMMON_REG_MODE = 0x45, 19262306a36Sopenharmony_ci SPMI_COMMON_REG_ENABLE = 0x46, 19362306a36Sopenharmony_ci SPMI_COMMON_REG_PULL_DOWN = 0x48, 19462306a36Sopenharmony_ci SPMI_COMMON_REG_SOFT_START = 0x4c, 19562306a36Sopenharmony_ci SPMI_COMMON_REG_STEP_CTRL = 0x61, 19662306a36Sopenharmony_ci}; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci/* 19962306a36Sopenharmony_ci * Second common register layout used by newer devices starting with ftsmps426 20062306a36Sopenharmony_ci * Note that some of the registers from the first common layout remain 20162306a36Sopenharmony_ci * unchanged and their definition is not duplicated. 20262306a36Sopenharmony_ci */ 20362306a36Sopenharmony_cienum spmi_ftsmps426_regulator_registers { 20462306a36Sopenharmony_ci SPMI_FTSMPS426_REG_VOLTAGE_LSB = 0x40, 20562306a36Sopenharmony_ci SPMI_FTSMPS426_REG_VOLTAGE_MSB = 0x41, 20662306a36Sopenharmony_ci SPMI_FTSMPS426_REG_VOLTAGE_ULS_LSB = 0x68, 20762306a36Sopenharmony_ci SPMI_FTSMPS426_REG_VOLTAGE_ULS_MSB = 0x69, 20862306a36Sopenharmony_ci}; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci/* 21162306a36Sopenharmony_ci * Third common register layout 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_cienum spmi_hfsmps_regulator_registers { 21462306a36Sopenharmony_ci SPMI_HFSMPS_REG_STEP_CTRL = 0x3c, 21562306a36Sopenharmony_ci SPMI_HFSMPS_REG_PULL_DOWN = 0xa0, 21662306a36Sopenharmony_ci}; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cienum spmi_vs_registers { 21962306a36Sopenharmony_ci SPMI_VS_REG_OCP = 0x4a, 22062306a36Sopenharmony_ci SPMI_VS_REG_SOFT_START = 0x4c, 22162306a36Sopenharmony_ci}; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_cienum spmi_boost_registers { 22462306a36Sopenharmony_ci SPMI_BOOST_REG_CURRENT_LIMIT = 0x4a, 22562306a36Sopenharmony_ci}; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cienum spmi_boost_byp_registers { 22862306a36Sopenharmony_ci SPMI_BOOST_BYP_REG_CURRENT_LIMIT = 0x4b, 22962306a36Sopenharmony_ci}; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cienum spmi_saw3_registers { 23262306a36Sopenharmony_ci SAW3_SECURE = 0x00, 23362306a36Sopenharmony_ci SAW3_ID = 0x04, 23462306a36Sopenharmony_ci SAW3_SPM_STS = 0x0C, 23562306a36Sopenharmony_ci SAW3_AVS_STS = 0x10, 23662306a36Sopenharmony_ci SAW3_PMIC_STS = 0x14, 23762306a36Sopenharmony_ci SAW3_RST = 0x18, 23862306a36Sopenharmony_ci SAW3_VCTL = 0x1C, 23962306a36Sopenharmony_ci SAW3_AVS_CTL = 0x20, 24062306a36Sopenharmony_ci SAW3_AVS_LIMIT = 0x24, 24162306a36Sopenharmony_ci SAW3_AVS_DLY = 0x28, 24262306a36Sopenharmony_ci SAW3_AVS_HYSTERESIS = 0x2C, 24362306a36Sopenharmony_ci SAW3_SPM_STS2 = 0x38, 24462306a36Sopenharmony_ci SAW3_SPM_PMIC_DATA_3 = 0x4C, 24562306a36Sopenharmony_ci SAW3_VERSION = 0xFD0, 24662306a36Sopenharmony_ci}; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci/* Used for indexing into ctrl_reg. These are offets from 0x40 */ 24962306a36Sopenharmony_cienum spmi_common_control_register_index { 25062306a36Sopenharmony_ci SPMI_COMMON_IDX_VOLTAGE_RANGE = 0, 25162306a36Sopenharmony_ci SPMI_COMMON_IDX_VOLTAGE_SET = 1, 25262306a36Sopenharmony_ci SPMI_COMMON_IDX_MODE = 5, 25362306a36Sopenharmony_ci SPMI_COMMON_IDX_ENABLE = 6, 25462306a36Sopenharmony_ci}; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci/* Common regulator control register layout */ 25762306a36Sopenharmony_ci#define SPMI_COMMON_ENABLE_MASK 0x80 25862306a36Sopenharmony_ci#define SPMI_COMMON_ENABLE 0x80 25962306a36Sopenharmony_ci#define SPMI_COMMON_DISABLE 0x00 26062306a36Sopenharmony_ci#define SPMI_COMMON_ENABLE_FOLLOW_HW_EN3_MASK 0x08 26162306a36Sopenharmony_ci#define SPMI_COMMON_ENABLE_FOLLOW_HW_EN2_MASK 0x04 26262306a36Sopenharmony_ci#define SPMI_COMMON_ENABLE_FOLLOW_HW_EN1_MASK 0x02 26362306a36Sopenharmony_ci#define SPMI_COMMON_ENABLE_FOLLOW_HW_EN0_MASK 0x01 26462306a36Sopenharmony_ci#define SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK 0x0f 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci/* Common regulator mode register layout */ 26762306a36Sopenharmony_ci#define SPMI_COMMON_MODE_HPM_MASK 0x80 26862306a36Sopenharmony_ci#define SPMI_COMMON_MODE_AUTO_MASK 0x40 26962306a36Sopenharmony_ci#define SPMI_COMMON_MODE_BYPASS_MASK 0x20 27062306a36Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK 0x10 27162306a36Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_HW_EN3_MASK 0x08 27262306a36Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_HW_EN2_MASK 0x04 27362306a36Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_HW_EN1_MASK 0x02 27462306a36Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_HW_EN0_MASK 0x01 27562306a36Sopenharmony_ci#define SPMI_COMMON_MODE_FOLLOW_ALL_MASK 0x1f 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci#define SPMI_FTSMPS426_MODE_BYPASS_MASK 3 27862306a36Sopenharmony_ci#define SPMI_FTSMPS426_MODE_RETENTION_MASK 4 27962306a36Sopenharmony_ci#define SPMI_FTSMPS426_MODE_LPM_MASK 5 28062306a36Sopenharmony_ci#define SPMI_FTSMPS426_MODE_AUTO_MASK 6 28162306a36Sopenharmony_ci#define SPMI_FTSMPS426_MODE_HPM_MASK 7 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci#define SPMI_FTSMPS426_MODE_MASK 0x07 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci/* Third common regulator mode register values */ 28662306a36Sopenharmony_ci#define SPMI_HFSMPS_MODE_BYPASS_MASK 2 28762306a36Sopenharmony_ci#define SPMI_HFSMPS_MODE_RETENTION_MASK 3 28862306a36Sopenharmony_ci#define SPMI_HFSMPS_MODE_LPM_MASK 4 28962306a36Sopenharmony_ci#define SPMI_HFSMPS_MODE_AUTO_MASK 6 29062306a36Sopenharmony_ci#define SPMI_HFSMPS_MODE_HPM_MASK 7 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci#define SPMI_HFSMPS_MODE_MASK 0x07 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci/* Common regulator pull down control register layout */ 29562306a36Sopenharmony_ci#define SPMI_COMMON_PULL_DOWN_ENABLE_MASK 0x80 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci/* LDO regulator current limit control register layout */ 29862306a36Sopenharmony_ci#define SPMI_LDO_CURRENT_LIMIT_ENABLE_MASK 0x80 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci/* LDO regulator soft start control register layout */ 30162306a36Sopenharmony_ci#define SPMI_LDO_SOFT_START_ENABLE_MASK 0x80 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci/* VS regulator over current protection control register layout */ 30462306a36Sopenharmony_ci#define SPMI_VS_OCP_OVERRIDE 0x01 30562306a36Sopenharmony_ci#define SPMI_VS_OCP_NO_OVERRIDE 0x00 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci/* VS regulator soft start control register layout */ 30862306a36Sopenharmony_ci#define SPMI_VS_SOFT_START_ENABLE_MASK 0x80 30962306a36Sopenharmony_ci#define SPMI_VS_SOFT_START_SEL_MASK 0x03 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/* Boost regulator current limit control register layout */ 31262306a36Sopenharmony_ci#define SPMI_BOOST_CURRENT_LIMIT_ENABLE_MASK 0x80 31362306a36Sopenharmony_ci#define SPMI_BOOST_CURRENT_LIMIT_MASK 0x07 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci#define SPMI_VS_OCP_DEFAULT_MAX_RETRIES 10 31662306a36Sopenharmony_ci#define SPMI_VS_OCP_DEFAULT_RETRY_DELAY_MS 30 31762306a36Sopenharmony_ci#define SPMI_VS_OCP_FALL_DELAY_US 90 31862306a36Sopenharmony_ci#define SPMI_VS_OCP_FAULT_DELAY_US 20000 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci#define SPMI_FTSMPS_STEP_CTRL_STEP_MASK 0x18 32162306a36Sopenharmony_ci#define SPMI_FTSMPS_STEP_CTRL_STEP_SHIFT 3 32262306a36Sopenharmony_ci#define SPMI_FTSMPS_STEP_CTRL_DELAY_MASK 0x07 32362306a36Sopenharmony_ci#define SPMI_FTSMPS_STEP_CTRL_DELAY_SHIFT 0 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci/* Clock rate in kHz of the FTSMPS regulator reference clock. */ 32662306a36Sopenharmony_ci#define SPMI_FTSMPS_CLOCK_RATE 19200 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci/* Minimum voltage stepper delay for each step. */ 32962306a36Sopenharmony_ci#define SPMI_FTSMPS_STEP_DELAY 8 33062306a36Sopenharmony_ci#define SPMI_DEFAULT_STEP_DELAY 20 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci/* 33362306a36Sopenharmony_ci * The ratio SPMI_FTSMPS_STEP_MARGIN_NUM/SPMI_FTSMPS_STEP_MARGIN_DEN is used to 33462306a36Sopenharmony_ci * adjust the step rate in order to account for oscillator variance. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci#define SPMI_FTSMPS_STEP_MARGIN_NUM 4 33762306a36Sopenharmony_ci#define SPMI_FTSMPS_STEP_MARGIN_DEN 5 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci/* slew_rate has units of uV/us. */ 34062306a36Sopenharmony_ci#define SPMI_HFSMPS_SLEW_RATE_38p4 38400 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci#define SPMI_FTSMPS426_STEP_CTRL_DELAY_MASK 0x03 34362306a36Sopenharmony_ci#define SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT 0 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci/* Clock rate in kHz of the FTSMPS426 regulator reference clock. */ 34662306a36Sopenharmony_ci#define SPMI_FTSMPS426_CLOCK_RATE 4800 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci#define SPMI_HFS430_CLOCK_RATE 1600 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci/* Minimum voltage stepper delay for each step. */ 35162306a36Sopenharmony_ci#define SPMI_FTSMPS426_STEP_DELAY 2 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci/* 35462306a36Sopenharmony_ci * The ratio SPMI_FTSMPS426_STEP_MARGIN_NUM/SPMI_FTSMPS426_STEP_MARGIN_DEN is 35562306a36Sopenharmony_ci * used to adjust the step rate in order to account for oscillator variance. 35662306a36Sopenharmony_ci */ 35762306a36Sopenharmony_ci#define SPMI_FTSMPS426_STEP_MARGIN_NUM 10 35862306a36Sopenharmony_ci#define SPMI_FTSMPS426_STEP_MARGIN_DEN 11 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci/* VSET value to decide the range of ULT SMPS */ 36262306a36Sopenharmony_ci#define ULT_SMPS_RANGE_SPLIT 0x60 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci/** 36562306a36Sopenharmony_ci * struct spmi_voltage_range - regulator set point voltage mapping description 36662306a36Sopenharmony_ci * @min_uV: Minimum programmable output voltage resulting from 36762306a36Sopenharmony_ci * set point register value 0x00 36862306a36Sopenharmony_ci * @max_uV: Maximum programmable output voltage 36962306a36Sopenharmony_ci * @step_uV: Output voltage increase resulting from the set point 37062306a36Sopenharmony_ci * register value increasing by 1 37162306a36Sopenharmony_ci * @set_point_min_uV: Minimum allowed voltage 37262306a36Sopenharmony_ci * @set_point_max_uV: Maximum allowed voltage. This may be tweaked in order 37362306a36Sopenharmony_ci * to pick which range should be used in the case of 37462306a36Sopenharmony_ci * overlapping set points. 37562306a36Sopenharmony_ci * @n_voltages: Number of preferred voltage set points present in this 37662306a36Sopenharmony_ci * range 37762306a36Sopenharmony_ci * @range_sel: Voltage range register value corresponding to this range 37862306a36Sopenharmony_ci * 37962306a36Sopenharmony_ci * The following relationships must be true for the values used in this struct: 38062306a36Sopenharmony_ci * (max_uV - min_uV) % step_uV == 0 38162306a36Sopenharmony_ci * (set_point_min_uV - min_uV) % step_uV == 0* 38262306a36Sopenharmony_ci * (set_point_max_uV - min_uV) % step_uV == 0* 38362306a36Sopenharmony_ci * n_voltages = (set_point_max_uV - set_point_min_uV) / step_uV + 1 38462306a36Sopenharmony_ci * 38562306a36Sopenharmony_ci * *Note, set_point_min_uV == set_point_max_uV == 0 is allowed in order to 38662306a36Sopenharmony_ci * specify that the voltage range has meaning, but is not preferred. 38762306a36Sopenharmony_ci */ 38862306a36Sopenharmony_cistruct spmi_voltage_range { 38962306a36Sopenharmony_ci int min_uV; 39062306a36Sopenharmony_ci int max_uV; 39162306a36Sopenharmony_ci int step_uV; 39262306a36Sopenharmony_ci int set_point_min_uV; 39362306a36Sopenharmony_ci int set_point_max_uV; 39462306a36Sopenharmony_ci unsigned n_voltages; 39562306a36Sopenharmony_ci u8 range_sel; 39662306a36Sopenharmony_ci}; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci/* 39962306a36Sopenharmony_ci * The ranges specified in the spmi_voltage_set_points struct must be listed 40062306a36Sopenharmony_ci * so that range[i].set_point_max_uV < range[i+1].set_point_min_uV. 40162306a36Sopenharmony_ci */ 40262306a36Sopenharmony_cistruct spmi_voltage_set_points { 40362306a36Sopenharmony_ci struct spmi_voltage_range *range; 40462306a36Sopenharmony_ci int count; 40562306a36Sopenharmony_ci unsigned n_voltages; 40662306a36Sopenharmony_ci}; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistruct spmi_regulator { 40962306a36Sopenharmony_ci struct regulator_desc desc; 41062306a36Sopenharmony_ci struct device *dev; 41162306a36Sopenharmony_ci struct delayed_work ocp_work; 41262306a36Sopenharmony_ci struct regmap *regmap; 41362306a36Sopenharmony_ci struct spmi_voltage_set_points *set_points; 41462306a36Sopenharmony_ci enum spmi_regulator_logical_type logical_type; 41562306a36Sopenharmony_ci int ocp_irq; 41662306a36Sopenharmony_ci int ocp_count; 41762306a36Sopenharmony_ci int ocp_max_retries; 41862306a36Sopenharmony_ci int ocp_retry_delay_ms; 41962306a36Sopenharmony_ci int hpm_min_load; 42062306a36Sopenharmony_ci int slew_rate; 42162306a36Sopenharmony_ci ktime_t vs_enable_time; 42262306a36Sopenharmony_ci u16 base; 42362306a36Sopenharmony_ci struct list_head node; 42462306a36Sopenharmony_ci}; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistruct spmi_regulator_mapping { 42762306a36Sopenharmony_ci enum spmi_regulator_type type; 42862306a36Sopenharmony_ci enum spmi_regulator_subtype subtype; 42962306a36Sopenharmony_ci enum spmi_regulator_logical_type logical_type; 43062306a36Sopenharmony_ci u32 revision_min; 43162306a36Sopenharmony_ci u32 revision_max; 43262306a36Sopenharmony_ci const struct regulator_ops *ops; 43362306a36Sopenharmony_ci struct spmi_voltage_set_points *set_points; 43462306a36Sopenharmony_ci int hpm_min_load; 43562306a36Sopenharmony_ci}; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistruct spmi_regulator_data { 43862306a36Sopenharmony_ci const char *name; 43962306a36Sopenharmony_ci u16 base; 44062306a36Sopenharmony_ci const char *supply; 44162306a36Sopenharmony_ci const char *ocp; 44262306a36Sopenharmony_ci u16 force_type; 44362306a36Sopenharmony_ci}; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci#define SPMI_VREG(_type, _subtype, _dig_major_min, _dig_major_max, \ 44662306a36Sopenharmony_ci _logical_type, _ops_val, _set_points_val, _hpm_min_load) \ 44762306a36Sopenharmony_ci { \ 44862306a36Sopenharmony_ci .type = SPMI_REGULATOR_TYPE_##_type, \ 44962306a36Sopenharmony_ci .subtype = SPMI_REGULATOR_SUBTYPE_##_subtype, \ 45062306a36Sopenharmony_ci .revision_min = _dig_major_min, \ 45162306a36Sopenharmony_ci .revision_max = _dig_major_max, \ 45262306a36Sopenharmony_ci .logical_type = SPMI_REGULATOR_LOGICAL_TYPE_##_logical_type, \ 45362306a36Sopenharmony_ci .ops = &spmi_##_ops_val##_ops, \ 45462306a36Sopenharmony_ci .set_points = &_set_points_val##_set_points, \ 45562306a36Sopenharmony_ci .hpm_min_load = _hpm_min_load, \ 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci#define SPMI_VREG_VS(_subtype, _dig_major_min, _dig_major_max) \ 45962306a36Sopenharmony_ci { \ 46062306a36Sopenharmony_ci .type = SPMI_REGULATOR_TYPE_VS, \ 46162306a36Sopenharmony_ci .subtype = SPMI_REGULATOR_SUBTYPE_##_subtype, \ 46262306a36Sopenharmony_ci .revision_min = _dig_major_min, \ 46362306a36Sopenharmony_ci .revision_max = _dig_major_max, \ 46462306a36Sopenharmony_ci .logical_type = SPMI_REGULATOR_LOGICAL_TYPE_VS, \ 46562306a36Sopenharmony_ci .ops = &spmi_vs_ops, \ 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci#define SPMI_VOLTAGE_RANGE(_range_sel, _min_uV, _set_point_min_uV, \ 46962306a36Sopenharmony_ci _set_point_max_uV, _max_uV, _step_uV) \ 47062306a36Sopenharmony_ci { \ 47162306a36Sopenharmony_ci .min_uV = _min_uV, \ 47262306a36Sopenharmony_ci .max_uV = _max_uV, \ 47362306a36Sopenharmony_ci .set_point_min_uV = _set_point_min_uV, \ 47462306a36Sopenharmony_ci .set_point_max_uV = _set_point_max_uV, \ 47562306a36Sopenharmony_ci .step_uV = _step_uV, \ 47662306a36Sopenharmony_ci .range_sel = _range_sel, \ 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci#define DEFINE_SPMI_SET_POINTS(name) \ 48062306a36Sopenharmony_cistruct spmi_voltage_set_points name##_set_points = { \ 48162306a36Sopenharmony_ci .range = name##_ranges, \ 48262306a36Sopenharmony_ci .count = ARRAY_SIZE(name##_ranges), \ 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci/* 48662306a36Sopenharmony_ci * These tables contain the physically available PMIC regulator voltage setpoint 48762306a36Sopenharmony_ci * ranges. Where two ranges overlap in hardware, one of the ranges is trimmed 48862306a36Sopenharmony_ci * to ensure that the setpoints available to software are monotonically 48962306a36Sopenharmony_ci * increasing and unique. The set_voltage callback functions expect these 49062306a36Sopenharmony_ci * properties to hold. 49162306a36Sopenharmony_ci */ 49262306a36Sopenharmony_cistatic struct spmi_voltage_range pldo_ranges[] = { 49362306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(2, 750000, 750000, 1537500, 1537500, 12500), 49462306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(3, 1500000, 1550000, 3075000, 3075000, 25000), 49562306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(4, 1750000, 3100000, 4900000, 4900000, 50000), 49662306a36Sopenharmony_ci}; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_cistatic struct spmi_voltage_range nldo1_ranges[] = { 49962306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(2, 750000, 750000, 1537500, 1537500, 12500), 50062306a36Sopenharmony_ci}; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_cistatic struct spmi_voltage_range nldo2_ranges[] = { 50362306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 375000, 0, 0, 1537500, 12500), 50462306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 375000, 375000, 768750, 768750, 6250), 50562306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(2, 750000, 775000, 1537500, 1537500, 12500), 50662306a36Sopenharmony_ci}; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_cistatic struct spmi_voltage_range nldo3_ranges[] = { 50962306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1537500, 1537500, 12500), 51062306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 375000, 0, 0, 1537500, 12500), 51162306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(2, 750000, 0, 0, 1537500, 12500), 51262306a36Sopenharmony_ci}; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic struct spmi_voltage_range ln_ldo_ranges[] = { 51562306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 690000, 690000, 1110000, 1110000, 60000), 51662306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1380000, 1380000, 2220000, 2220000, 120000), 51762306a36Sopenharmony_ci}; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_cistatic struct spmi_voltage_range smps_ranges[] = { 52062306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1562500, 1562500, 12500), 52162306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 1550000, 1575000, 3125000, 3125000, 25000), 52262306a36Sopenharmony_ci}; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_cistatic struct spmi_voltage_range ftsmps_ranges[] = { 52562306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 0, 350000, 1275000, 1275000, 5000), 52662306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 0, 1280000, 2040000, 2040000, 10000), 52762306a36Sopenharmony_ci}; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic struct spmi_voltage_range ftsmps2p5_ranges[] = { 53062306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 80000, 350000, 1355000, 1355000, 5000), 53162306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 160000, 1360000, 2200000, 2200000, 10000), 53262306a36Sopenharmony_ci}; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_cistatic struct spmi_voltage_range ftsmps426_ranges[] = { 53562306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 0, 320000, 1352000, 1352000, 4000), 53662306a36Sopenharmony_ci}; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_cistatic struct spmi_voltage_range boost_ranges[] = { 53962306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 4000000, 4000000, 5550000, 5550000, 50000), 54062306a36Sopenharmony_ci}; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic struct spmi_voltage_range boost_byp_ranges[] = { 54362306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 2500000, 2500000, 5200000, 5650000, 50000), 54462306a36Sopenharmony_ci}; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic struct spmi_voltage_range ult_lo_smps_ranges[] = { 54762306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1562500, 1562500, 12500), 54862306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(1, 750000, 0, 0, 1525000, 25000), 54962306a36Sopenharmony_ci}; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_cistatic struct spmi_voltage_range ult_ho_smps_ranges[] = { 55262306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1550000, 1550000, 2325000, 2325000, 25000), 55362306a36Sopenharmony_ci}; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_cistatic struct spmi_voltage_range ult_nldo_ranges[] = { 55662306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1537500, 1537500, 12500), 55762306a36Sopenharmony_ci}; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_cistatic struct spmi_voltage_range ult_pldo_ranges[] = { 56062306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1750000, 1750000, 3337500, 3337500, 12500), 56162306a36Sopenharmony_ci}; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_cistatic struct spmi_voltage_range pldo660_ranges[] = { 56462306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1504000, 1504000, 3544000, 3544000, 8000), 56562306a36Sopenharmony_ci}; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_cistatic struct spmi_voltage_range nldo660_ranges[] = { 56862306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000), 56962306a36Sopenharmony_ci}; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic struct spmi_voltage_range ht_lvpldo_ranges[] = { 57262306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1504000, 1504000, 2000000, 2000000, 8000), 57362306a36Sopenharmony_ci}; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_cistatic struct spmi_voltage_range ht_nldo_ranges[] = { 57662306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 312000, 312000, 1304000, 1304000, 8000), 57762306a36Sopenharmony_ci}; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_cistatic struct spmi_voltage_range hfs430_ranges[] = { 58062306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000), 58162306a36Sopenharmony_ci}; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic struct spmi_voltage_range ht_p150_ranges[] = { 58462306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1616000, 1616000, 3304000, 3304000, 8000), 58562306a36Sopenharmony_ci}; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_cistatic struct spmi_voltage_range ht_p600_ranges[] = { 58862306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 1704000, 1704000, 1896000, 1896000, 8000), 58962306a36Sopenharmony_ci}; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_cistatic struct spmi_voltage_range nldo_510_ranges[] = { 59262306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000), 59362306a36Sopenharmony_ci}; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_cistatic struct spmi_voltage_range ftsmps510_ranges[] = { 59662306a36Sopenharmony_ci SPMI_VOLTAGE_RANGE(0, 300000, 300000, 1372000, 1372000, 4000), 59762306a36Sopenharmony_ci}; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(pldo); 60062306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(nldo1); 60162306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(nldo2); 60262306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(nldo3); 60362306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ln_ldo); 60462306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(smps); 60562306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ftsmps); 60662306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ftsmps2p5); 60762306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ftsmps426); 60862306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(boost); 60962306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(boost_byp); 61062306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ult_lo_smps); 61162306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ult_ho_smps); 61262306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ult_nldo); 61362306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ult_pldo); 61462306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(pldo660); 61562306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(nldo660); 61662306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ht_lvpldo); 61762306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ht_nldo); 61862306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(hfs430); 61962306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ht_p150); 62062306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ht_p600); 62162306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(nldo_510); 62262306a36Sopenharmony_cistatic DEFINE_SPMI_SET_POINTS(ftsmps510); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_cistatic inline int spmi_vreg_read(struct spmi_regulator *vreg, u16 addr, u8 *buf, 62562306a36Sopenharmony_ci int len) 62662306a36Sopenharmony_ci{ 62762306a36Sopenharmony_ci return regmap_bulk_read(vreg->regmap, vreg->base + addr, buf, len); 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic inline int spmi_vreg_write(struct spmi_regulator *vreg, u16 addr, 63162306a36Sopenharmony_ci u8 *buf, int len) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci return regmap_bulk_write(vreg->regmap, vreg->base + addr, buf, len); 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic int spmi_vreg_update_bits(struct spmi_regulator *vreg, u16 addr, u8 val, 63762306a36Sopenharmony_ci u8 mask) 63862306a36Sopenharmony_ci{ 63962306a36Sopenharmony_ci return regmap_update_bits(vreg->regmap, vreg->base + addr, mask, val); 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_cistatic int spmi_regulator_vs_enable(struct regulator_dev *rdev) 64362306a36Sopenharmony_ci{ 64462306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci if (vreg->ocp_irq) { 64762306a36Sopenharmony_ci vreg->ocp_count = 0; 64862306a36Sopenharmony_ci vreg->vs_enable_time = ktime_get(); 64962306a36Sopenharmony_ci } 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci return regulator_enable_regmap(rdev); 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_cistatic int spmi_regulator_vs_ocp(struct regulator_dev *rdev, int lim_uA, 65562306a36Sopenharmony_ci int severity, bool enable) 65662306a36Sopenharmony_ci{ 65762306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 65862306a36Sopenharmony_ci u8 reg = SPMI_VS_OCP_OVERRIDE; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci if (lim_uA || !enable || severity != REGULATOR_SEVERITY_PROT) 66162306a36Sopenharmony_ci return -EINVAL; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci return spmi_vreg_write(vreg, SPMI_VS_REG_OCP, ®, 1); 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_cistatic int spmi_regulator_select_voltage(struct spmi_regulator *vreg, 66762306a36Sopenharmony_ci int min_uV, int max_uV) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci const struct spmi_voltage_range *range; 67062306a36Sopenharmony_ci int uV = min_uV; 67162306a36Sopenharmony_ci int lim_min_uV, lim_max_uV, i, range_id, range_max_uV; 67262306a36Sopenharmony_ci int selector, voltage_sel; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci /* Check if request voltage is outside of physically settable range. */ 67562306a36Sopenharmony_ci lim_min_uV = vreg->set_points->range[0].set_point_min_uV; 67662306a36Sopenharmony_ci lim_max_uV = 67762306a36Sopenharmony_ci vreg->set_points->range[vreg->set_points->count - 1].set_point_max_uV; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci if (uV < lim_min_uV && max_uV >= lim_min_uV) 68062306a36Sopenharmony_ci uV = lim_min_uV; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci if (uV < lim_min_uV || uV > lim_max_uV) { 68362306a36Sopenharmony_ci dev_err(vreg->dev, 68462306a36Sopenharmony_ci "request v=[%d, %d] is outside possible v=[%d, %d]\n", 68562306a36Sopenharmony_ci min_uV, max_uV, lim_min_uV, lim_max_uV); 68662306a36Sopenharmony_ci return -EINVAL; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci /* Find the range which uV is inside of. */ 69062306a36Sopenharmony_ci for (i = vreg->set_points->count - 1; i > 0; i--) { 69162306a36Sopenharmony_ci range_max_uV = vreg->set_points->range[i - 1].set_point_max_uV; 69262306a36Sopenharmony_ci if (uV > range_max_uV && range_max_uV > 0) 69362306a36Sopenharmony_ci break; 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci range_id = i; 69762306a36Sopenharmony_ci range = &vreg->set_points->range[range_id]; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci /* 70062306a36Sopenharmony_ci * Force uV to be an allowed set point by applying a ceiling function to 70162306a36Sopenharmony_ci * the uV value. 70262306a36Sopenharmony_ci */ 70362306a36Sopenharmony_ci voltage_sel = DIV_ROUND_UP(uV - range->min_uV, range->step_uV); 70462306a36Sopenharmony_ci uV = voltage_sel * range->step_uV + range->min_uV; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci if (uV > max_uV) { 70762306a36Sopenharmony_ci dev_err(vreg->dev, 70862306a36Sopenharmony_ci "request v=[%d, %d] cannot be met by any set point; " 70962306a36Sopenharmony_ci "next set point: %d\n", 71062306a36Sopenharmony_ci min_uV, max_uV, uV); 71162306a36Sopenharmony_ci return -EINVAL; 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci selector = 0; 71562306a36Sopenharmony_ci for (i = 0; i < range_id; i++) 71662306a36Sopenharmony_ci selector += vreg->set_points->range[i].n_voltages; 71762306a36Sopenharmony_ci selector += (uV - range->set_point_min_uV) / range->step_uV; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci return selector; 72062306a36Sopenharmony_ci} 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_cistatic int spmi_sw_selector_to_hw(struct spmi_regulator *vreg, 72362306a36Sopenharmony_ci unsigned selector, u8 *range_sel, 72462306a36Sopenharmony_ci u8 *voltage_sel) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci const struct spmi_voltage_range *range, *end; 72762306a36Sopenharmony_ci unsigned offset; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci range = vreg->set_points->range; 73062306a36Sopenharmony_ci end = range + vreg->set_points->count; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci for (; range < end; range++) { 73362306a36Sopenharmony_ci if (selector < range->n_voltages) { 73462306a36Sopenharmony_ci /* 73562306a36Sopenharmony_ci * hardware selectors between set point min and real 73662306a36Sopenharmony_ci * min are invalid so we ignore them 73762306a36Sopenharmony_ci */ 73862306a36Sopenharmony_ci offset = range->set_point_min_uV - range->min_uV; 73962306a36Sopenharmony_ci offset /= range->step_uV; 74062306a36Sopenharmony_ci *voltage_sel = selector + offset; 74162306a36Sopenharmony_ci *range_sel = range->range_sel; 74262306a36Sopenharmony_ci return 0; 74362306a36Sopenharmony_ci } 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci selector -= range->n_voltages; 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci return -EINVAL; 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_cistatic int spmi_hw_selector_to_sw(struct spmi_regulator *vreg, u8 hw_sel, 75262306a36Sopenharmony_ci const struct spmi_voltage_range *range) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci unsigned sw_sel = 0; 75562306a36Sopenharmony_ci unsigned offset, max_hw_sel; 75662306a36Sopenharmony_ci const struct spmi_voltage_range *r = vreg->set_points->range; 75762306a36Sopenharmony_ci const struct spmi_voltage_range *end = r + vreg->set_points->count; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci for (; r < end; r++) { 76062306a36Sopenharmony_ci if (r == range && range->n_voltages) { 76162306a36Sopenharmony_ci /* 76262306a36Sopenharmony_ci * hardware selectors between set point min and real 76362306a36Sopenharmony_ci * min and between set point max and real max are 76462306a36Sopenharmony_ci * invalid so we return an error if they're 76562306a36Sopenharmony_ci * programmed into the hardware 76662306a36Sopenharmony_ci */ 76762306a36Sopenharmony_ci offset = range->set_point_min_uV - range->min_uV; 76862306a36Sopenharmony_ci offset /= range->step_uV; 76962306a36Sopenharmony_ci if (hw_sel < offset) 77062306a36Sopenharmony_ci return -EINVAL; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci max_hw_sel = range->set_point_max_uV - range->min_uV; 77362306a36Sopenharmony_ci max_hw_sel /= range->step_uV; 77462306a36Sopenharmony_ci if (hw_sel > max_hw_sel) 77562306a36Sopenharmony_ci return -EINVAL; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci return sw_sel + hw_sel - offset; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci sw_sel += r->n_voltages; 78062306a36Sopenharmony_ci } 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci return -EINVAL; 78362306a36Sopenharmony_ci} 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_cistatic const struct spmi_voltage_range * 78662306a36Sopenharmony_cispmi_regulator_find_range(struct spmi_regulator *vreg) 78762306a36Sopenharmony_ci{ 78862306a36Sopenharmony_ci u8 range_sel; 78962306a36Sopenharmony_ci const struct spmi_voltage_range *range, *end; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci range = vreg->set_points->range; 79262306a36Sopenharmony_ci end = range + vreg->set_points->count; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, &range_sel, 1); 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci for (; range < end; range++) 79762306a36Sopenharmony_ci if (range->range_sel == range_sel) 79862306a36Sopenharmony_ci return range; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci return NULL; 80162306a36Sopenharmony_ci} 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_cistatic int spmi_regulator_select_voltage_same_range(struct spmi_regulator *vreg, 80462306a36Sopenharmony_ci int min_uV, int max_uV) 80562306a36Sopenharmony_ci{ 80662306a36Sopenharmony_ci const struct spmi_voltage_range *range; 80762306a36Sopenharmony_ci int uV = min_uV; 80862306a36Sopenharmony_ci int i, selector; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci range = spmi_regulator_find_range(vreg); 81162306a36Sopenharmony_ci if (!range) 81262306a36Sopenharmony_ci goto different_range; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci if (uV < range->min_uV && max_uV >= range->min_uV) 81562306a36Sopenharmony_ci uV = range->min_uV; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci if (uV < range->min_uV || uV > range->max_uV) { 81862306a36Sopenharmony_ci /* Current range doesn't support the requested voltage. */ 81962306a36Sopenharmony_ci goto different_range; 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci /* 82362306a36Sopenharmony_ci * Force uV to be an allowed set point by applying a ceiling function to 82462306a36Sopenharmony_ci * the uV value. 82562306a36Sopenharmony_ci */ 82662306a36Sopenharmony_ci uV = DIV_ROUND_UP(uV - range->min_uV, range->step_uV); 82762306a36Sopenharmony_ci uV = uV * range->step_uV + range->min_uV; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci if (uV > max_uV) { 83062306a36Sopenharmony_ci /* 83162306a36Sopenharmony_ci * No set point in the current voltage range is within the 83262306a36Sopenharmony_ci * requested min_uV to max_uV range. 83362306a36Sopenharmony_ci */ 83462306a36Sopenharmony_ci goto different_range; 83562306a36Sopenharmony_ci } 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci selector = 0; 83862306a36Sopenharmony_ci for (i = 0; i < vreg->set_points->count; i++) { 83962306a36Sopenharmony_ci if (uV >= vreg->set_points->range[i].set_point_min_uV 84062306a36Sopenharmony_ci && uV <= vreg->set_points->range[i].set_point_max_uV) { 84162306a36Sopenharmony_ci selector += 84262306a36Sopenharmony_ci (uV - vreg->set_points->range[i].set_point_min_uV) 84362306a36Sopenharmony_ci / vreg->set_points->range[i].step_uV; 84462306a36Sopenharmony_ci break; 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci selector += vreg->set_points->range[i].n_voltages; 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci if (selector >= vreg->set_points->n_voltages) 85162306a36Sopenharmony_ci goto different_range; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci return selector; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_cidifferent_range: 85662306a36Sopenharmony_ci return spmi_regulator_select_voltage(vreg, min_uV, max_uV); 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_cistatic int spmi_regulator_common_map_voltage(struct regulator_dev *rdev, 86062306a36Sopenharmony_ci int min_uV, int max_uV) 86162306a36Sopenharmony_ci{ 86262306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci /* 86562306a36Sopenharmony_ci * Favor staying in the current voltage range if possible. This avoids 86662306a36Sopenharmony_ci * voltage spikes that occur when changing the voltage range. 86762306a36Sopenharmony_ci */ 86862306a36Sopenharmony_ci return spmi_regulator_select_voltage_same_range(vreg, min_uV, max_uV); 86962306a36Sopenharmony_ci} 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_cistatic int 87262306a36Sopenharmony_cispmi_regulator_common_set_voltage(struct regulator_dev *rdev, unsigned selector) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 87562306a36Sopenharmony_ci int ret; 87662306a36Sopenharmony_ci u8 buf[2]; 87762306a36Sopenharmony_ci u8 range_sel, voltage_sel; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel); 88062306a36Sopenharmony_ci if (ret) 88162306a36Sopenharmony_ci return ret; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci buf[0] = range_sel; 88462306a36Sopenharmony_ci buf[1] = voltage_sel; 88562306a36Sopenharmony_ci return spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, buf, 2); 88662306a36Sopenharmony_ci} 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_cistatic int spmi_regulator_common_list_voltage(struct regulator_dev *rdev, 88962306a36Sopenharmony_ci unsigned selector); 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_cistatic int spmi_regulator_ftsmps426_set_voltage(struct regulator_dev *rdev, 89262306a36Sopenharmony_ci unsigned selector) 89362306a36Sopenharmony_ci{ 89462306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 89562306a36Sopenharmony_ci u8 buf[2]; 89662306a36Sopenharmony_ci int mV; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci mV = spmi_regulator_common_list_voltage(rdev, selector) / 1000; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci buf[0] = mV & 0xff; 90162306a36Sopenharmony_ci buf[1] = mV >> 8; 90262306a36Sopenharmony_ci return spmi_vreg_write(vreg, SPMI_FTSMPS426_REG_VOLTAGE_LSB, buf, 2); 90362306a36Sopenharmony_ci} 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_cistatic int spmi_regulator_set_voltage_time_sel(struct regulator_dev *rdev, 90662306a36Sopenharmony_ci unsigned int old_selector, unsigned int new_selector) 90762306a36Sopenharmony_ci{ 90862306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 90962306a36Sopenharmony_ci int diff_uV; 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci diff_uV = abs(spmi_regulator_common_list_voltage(rdev, new_selector) - 91262306a36Sopenharmony_ci spmi_regulator_common_list_voltage(rdev, old_selector)); 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci return DIV_ROUND_UP(diff_uV, vreg->slew_rate); 91562306a36Sopenharmony_ci} 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_cistatic int spmi_regulator_common_get_voltage(struct regulator_dev *rdev) 91862306a36Sopenharmony_ci{ 91962306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 92062306a36Sopenharmony_ci const struct spmi_voltage_range *range; 92162306a36Sopenharmony_ci u8 voltage_sel; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_SET, &voltage_sel, 1); 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci range = spmi_regulator_find_range(vreg); 92662306a36Sopenharmony_ci if (!range) 92762306a36Sopenharmony_ci return -EINVAL; 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci return spmi_hw_selector_to_sw(vreg, voltage_sel, range); 93062306a36Sopenharmony_ci} 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_cistatic int spmi_regulator_ftsmps426_get_voltage(struct regulator_dev *rdev) 93362306a36Sopenharmony_ci{ 93462306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 93562306a36Sopenharmony_ci const struct spmi_voltage_range *range; 93662306a36Sopenharmony_ci u8 buf[2]; 93762306a36Sopenharmony_ci int uV; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci spmi_vreg_read(vreg, SPMI_FTSMPS426_REG_VOLTAGE_LSB, buf, 2); 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci uV = (((unsigned int)buf[1] << 8) | (unsigned int)buf[0]) * 1000; 94262306a36Sopenharmony_ci range = vreg->set_points->range; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci return (uV - range->set_point_min_uV) / range->step_uV; 94562306a36Sopenharmony_ci} 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_cistatic int spmi_regulator_single_map_voltage(struct regulator_dev *rdev, 94862306a36Sopenharmony_ci int min_uV, int max_uV) 94962306a36Sopenharmony_ci{ 95062306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci return spmi_regulator_select_voltage(vreg, min_uV, max_uV); 95362306a36Sopenharmony_ci} 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_cistatic int spmi_regulator_single_range_set_voltage(struct regulator_dev *rdev, 95662306a36Sopenharmony_ci unsigned selector) 95762306a36Sopenharmony_ci{ 95862306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 95962306a36Sopenharmony_ci u8 sel = selector; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci /* 96262306a36Sopenharmony_ci * Certain types of regulators do not have a range select register so 96362306a36Sopenharmony_ci * only voltage set register needs to be written. 96462306a36Sopenharmony_ci */ 96562306a36Sopenharmony_ci return spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_SET, &sel, 1); 96662306a36Sopenharmony_ci} 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_cistatic int spmi_regulator_single_range_get_voltage(struct regulator_dev *rdev) 96962306a36Sopenharmony_ci{ 97062306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 97162306a36Sopenharmony_ci u8 selector; 97262306a36Sopenharmony_ci int ret; 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_SET, &selector, 1); 97562306a36Sopenharmony_ci if (ret) 97662306a36Sopenharmony_ci return ret; 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci return selector; 97962306a36Sopenharmony_ci} 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_cistatic int spmi_regulator_ult_lo_smps_set_voltage(struct regulator_dev *rdev, 98262306a36Sopenharmony_ci unsigned selector) 98362306a36Sopenharmony_ci{ 98462306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 98562306a36Sopenharmony_ci int ret; 98662306a36Sopenharmony_ci u8 range_sel, voltage_sel; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel); 98962306a36Sopenharmony_ci if (ret) 99062306a36Sopenharmony_ci return ret; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci /* 99362306a36Sopenharmony_ci * Calculate VSET based on range 99462306a36Sopenharmony_ci * In case of range 0: voltage_sel is a 7 bit value, can be written 99562306a36Sopenharmony_ci * witout any modification. 99662306a36Sopenharmony_ci * In case of range 1: voltage_sel is a 5 bit value, bits[7-5] set to 99762306a36Sopenharmony_ci * [011]. 99862306a36Sopenharmony_ci */ 99962306a36Sopenharmony_ci if (range_sel == 1) 100062306a36Sopenharmony_ci voltage_sel |= ULT_SMPS_RANGE_SPLIT; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_VOLTAGE_SET, 100362306a36Sopenharmony_ci voltage_sel, 0xff); 100462306a36Sopenharmony_ci} 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_cistatic int spmi_regulator_ult_lo_smps_get_voltage(struct regulator_dev *rdev) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 100962306a36Sopenharmony_ci const struct spmi_voltage_range *range; 101062306a36Sopenharmony_ci u8 voltage_sel; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_SET, &voltage_sel, 1); 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci range = spmi_regulator_find_range(vreg); 101562306a36Sopenharmony_ci if (!range) 101662306a36Sopenharmony_ci return -EINVAL; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci if (range->range_sel == 1) 101962306a36Sopenharmony_ci voltage_sel &= ~ULT_SMPS_RANGE_SPLIT; 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci return spmi_hw_selector_to_sw(vreg, voltage_sel, range); 102262306a36Sopenharmony_ci} 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_cistatic int spmi_regulator_common_list_voltage(struct regulator_dev *rdev, 102562306a36Sopenharmony_ci unsigned selector) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 102862306a36Sopenharmony_ci int uV = 0; 102962306a36Sopenharmony_ci int i; 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci if (selector >= vreg->set_points->n_voltages) 103262306a36Sopenharmony_ci return 0; 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci for (i = 0; i < vreg->set_points->count; i++) { 103562306a36Sopenharmony_ci if (selector < vreg->set_points->range[i].n_voltages) { 103662306a36Sopenharmony_ci uV = selector * vreg->set_points->range[i].step_uV 103762306a36Sopenharmony_ci + vreg->set_points->range[i].set_point_min_uV; 103862306a36Sopenharmony_ci break; 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci selector -= vreg->set_points->range[i].n_voltages; 104262306a36Sopenharmony_ci } 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci return uV; 104562306a36Sopenharmony_ci} 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_cistatic int 104862306a36Sopenharmony_cispmi_regulator_common_set_bypass(struct regulator_dev *rdev, bool enable) 104962306a36Sopenharmony_ci{ 105062306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 105162306a36Sopenharmony_ci u8 mask = SPMI_COMMON_MODE_BYPASS_MASK; 105262306a36Sopenharmony_ci u8 val = 0; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci if (enable) 105562306a36Sopenharmony_ci val = mask; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); 105862306a36Sopenharmony_ci} 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_cistatic int 106162306a36Sopenharmony_cispmi_regulator_common_get_bypass(struct regulator_dev *rdev, bool *enable) 106262306a36Sopenharmony_ci{ 106362306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 106462306a36Sopenharmony_ci u8 val; 106562306a36Sopenharmony_ci int ret; 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, &val, 1); 106862306a36Sopenharmony_ci *enable = val & SPMI_COMMON_MODE_BYPASS_MASK; 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_ci return ret; 107162306a36Sopenharmony_ci} 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_cistatic unsigned int spmi_regulator_common_get_mode(struct regulator_dev *rdev) 107462306a36Sopenharmony_ci{ 107562306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 107662306a36Sopenharmony_ci u8 reg; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, ®, 1); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci reg &= SPMI_COMMON_MODE_HPM_MASK | SPMI_COMMON_MODE_AUTO_MASK; 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci switch (reg) { 108362306a36Sopenharmony_ci case SPMI_COMMON_MODE_HPM_MASK: 108462306a36Sopenharmony_ci return REGULATOR_MODE_NORMAL; 108562306a36Sopenharmony_ci case SPMI_COMMON_MODE_AUTO_MASK: 108662306a36Sopenharmony_ci return REGULATOR_MODE_FAST; 108762306a36Sopenharmony_ci default: 108862306a36Sopenharmony_ci return REGULATOR_MODE_IDLE; 108962306a36Sopenharmony_ci } 109062306a36Sopenharmony_ci} 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_cistatic unsigned int spmi_regulator_ftsmps426_get_mode(struct regulator_dev *rdev) 109362306a36Sopenharmony_ci{ 109462306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 109562306a36Sopenharmony_ci u8 reg; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, ®, 1); 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci switch (reg) { 110062306a36Sopenharmony_ci case SPMI_FTSMPS426_MODE_HPM_MASK: 110162306a36Sopenharmony_ci return REGULATOR_MODE_NORMAL; 110262306a36Sopenharmony_ci case SPMI_FTSMPS426_MODE_AUTO_MASK: 110362306a36Sopenharmony_ci return REGULATOR_MODE_FAST; 110462306a36Sopenharmony_ci default: 110562306a36Sopenharmony_ci return REGULATOR_MODE_IDLE; 110662306a36Sopenharmony_ci } 110762306a36Sopenharmony_ci} 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_cistatic unsigned int spmi_regulator_hfsmps_get_mode(struct regulator_dev *rdev) 111062306a36Sopenharmony_ci{ 111162306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 111262306a36Sopenharmony_ci u8 reg; 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, ®, 1); 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci switch (reg) { 111762306a36Sopenharmony_ci case SPMI_HFSMPS_MODE_HPM_MASK: 111862306a36Sopenharmony_ci return REGULATOR_MODE_NORMAL; 111962306a36Sopenharmony_ci case SPMI_HFSMPS_MODE_AUTO_MASK: 112062306a36Sopenharmony_ci return REGULATOR_MODE_FAST; 112162306a36Sopenharmony_ci default: 112262306a36Sopenharmony_ci return REGULATOR_MODE_IDLE; 112362306a36Sopenharmony_ci } 112462306a36Sopenharmony_ci} 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_cistatic int 112762306a36Sopenharmony_cispmi_regulator_common_set_mode(struct regulator_dev *rdev, unsigned int mode) 112862306a36Sopenharmony_ci{ 112962306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 113062306a36Sopenharmony_ci u8 mask = SPMI_COMMON_MODE_HPM_MASK | SPMI_COMMON_MODE_AUTO_MASK; 113162306a36Sopenharmony_ci u8 val; 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci switch (mode) { 113462306a36Sopenharmony_ci case REGULATOR_MODE_NORMAL: 113562306a36Sopenharmony_ci val = SPMI_COMMON_MODE_HPM_MASK; 113662306a36Sopenharmony_ci break; 113762306a36Sopenharmony_ci case REGULATOR_MODE_FAST: 113862306a36Sopenharmony_ci val = SPMI_COMMON_MODE_AUTO_MASK; 113962306a36Sopenharmony_ci break; 114062306a36Sopenharmony_ci default: 114162306a36Sopenharmony_ci val = 0; 114262306a36Sopenharmony_ci break; 114362306a36Sopenharmony_ci } 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); 114662306a36Sopenharmony_ci} 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_cistatic int 114962306a36Sopenharmony_cispmi_regulator_ftsmps426_set_mode(struct regulator_dev *rdev, unsigned int mode) 115062306a36Sopenharmony_ci{ 115162306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 115262306a36Sopenharmony_ci u8 mask = SPMI_FTSMPS426_MODE_MASK; 115362306a36Sopenharmony_ci u8 val; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci switch (mode) { 115662306a36Sopenharmony_ci case REGULATOR_MODE_NORMAL: 115762306a36Sopenharmony_ci val = SPMI_FTSMPS426_MODE_HPM_MASK; 115862306a36Sopenharmony_ci break; 115962306a36Sopenharmony_ci case REGULATOR_MODE_FAST: 116062306a36Sopenharmony_ci val = SPMI_FTSMPS426_MODE_AUTO_MASK; 116162306a36Sopenharmony_ci break; 116262306a36Sopenharmony_ci case REGULATOR_MODE_IDLE: 116362306a36Sopenharmony_ci val = SPMI_FTSMPS426_MODE_LPM_MASK; 116462306a36Sopenharmony_ci break; 116562306a36Sopenharmony_ci default: 116662306a36Sopenharmony_ci return -EINVAL; 116762306a36Sopenharmony_ci } 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); 117062306a36Sopenharmony_ci} 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_cistatic int 117362306a36Sopenharmony_cispmi_regulator_hfsmps_set_mode(struct regulator_dev *rdev, unsigned int mode) 117462306a36Sopenharmony_ci{ 117562306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 117662306a36Sopenharmony_ci u8 mask = SPMI_HFSMPS_MODE_MASK; 117762306a36Sopenharmony_ci u8 val; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci switch (mode) { 118062306a36Sopenharmony_ci case REGULATOR_MODE_NORMAL: 118162306a36Sopenharmony_ci val = SPMI_HFSMPS_MODE_HPM_MASK; 118262306a36Sopenharmony_ci break; 118362306a36Sopenharmony_ci case REGULATOR_MODE_FAST: 118462306a36Sopenharmony_ci val = SPMI_HFSMPS_MODE_AUTO_MASK; 118562306a36Sopenharmony_ci break; 118662306a36Sopenharmony_ci case REGULATOR_MODE_IDLE: 118762306a36Sopenharmony_ci val = vreg->logical_type == 118862306a36Sopenharmony_ci SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS3 ? 118962306a36Sopenharmony_ci SPMI_HFSMPS_MODE_RETENTION_MASK : 119062306a36Sopenharmony_ci SPMI_HFSMPS_MODE_LPM_MASK; 119162306a36Sopenharmony_ci break; 119262306a36Sopenharmony_ci default: 119362306a36Sopenharmony_ci return -EINVAL; 119462306a36Sopenharmony_ci } 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); 119762306a36Sopenharmony_ci} 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_cistatic int 120062306a36Sopenharmony_cispmi_regulator_common_set_load(struct regulator_dev *rdev, int load_uA) 120162306a36Sopenharmony_ci{ 120262306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 120362306a36Sopenharmony_ci unsigned int mode; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci if (load_uA >= vreg->hpm_min_load) 120662306a36Sopenharmony_ci mode = REGULATOR_MODE_NORMAL; 120762306a36Sopenharmony_ci else 120862306a36Sopenharmony_ci mode = REGULATOR_MODE_IDLE; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci return spmi_regulator_common_set_mode(rdev, mode); 121162306a36Sopenharmony_ci} 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_cistatic int spmi_regulator_common_set_pull_down(struct regulator_dev *rdev) 121462306a36Sopenharmony_ci{ 121562306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 121662306a36Sopenharmony_ci unsigned int mask = SPMI_COMMON_PULL_DOWN_ENABLE_MASK; 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_PULL_DOWN, 121962306a36Sopenharmony_ci mask, mask); 122062306a36Sopenharmony_ci} 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_cistatic int spmi_regulator_hfsmps_set_pull_down(struct regulator_dev *rdev) 122362306a36Sopenharmony_ci{ 122462306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 122562306a36Sopenharmony_ci unsigned int mask = SPMI_COMMON_PULL_DOWN_ENABLE_MASK; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_HFSMPS_REG_PULL_DOWN, 122862306a36Sopenharmony_ci mask, mask); 122962306a36Sopenharmony_ci} 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_cistatic int spmi_regulator_common_set_soft_start(struct regulator_dev *rdev) 123262306a36Sopenharmony_ci{ 123362306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 123462306a36Sopenharmony_ci unsigned int mask = SPMI_LDO_SOFT_START_ENABLE_MASK; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_SOFT_START, 123762306a36Sopenharmony_ci mask, mask); 123862306a36Sopenharmony_ci} 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_cistatic int spmi_regulator_set_ilim(struct regulator_dev *rdev, int ilim_uA) 124162306a36Sopenharmony_ci{ 124262306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 124362306a36Sopenharmony_ci enum spmi_regulator_logical_type type = vreg->logical_type; 124462306a36Sopenharmony_ci unsigned int current_reg; 124562306a36Sopenharmony_ci u8 reg; 124662306a36Sopenharmony_ci u8 mask = SPMI_BOOST_CURRENT_LIMIT_MASK | 124762306a36Sopenharmony_ci SPMI_BOOST_CURRENT_LIMIT_ENABLE_MASK; 124862306a36Sopenharmony_ci int max = (SPMI_BOOST_CURRENT_LIMIT_MASK + 1) * 500; 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci if (type == SPMI_REGULATOR_LOGICAL_TYPE_BOOST) 125162306a36Sopenharmony_ci current_reg = SPMI_BOOST_REG_CURRENT_LIMIT; 125262306a36Sopenharmony_ci else 125362306a36Sopenharmony_ci current_reg = SPMI_BOOST_BYP_REG_CURRENT_LIMIT; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci if (ilim_uA > max || ilim_uA <= 0) 125662306a36Sopenharmony_ci return -EINVAL; 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci reg = (ilim_uA - 1) / 500; 125962306a36Sopenharmony_ci reg |= SPMI_BOOST_CURRENT_LIMIT_ENABLE_MASK; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci return spmi_vreg_update_bits(vreg, current_reg, reg, mask); 126262306a36Sopenharmony_ci} 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_cistatic int spmi_regulator_vs_clear_ocp(struct spmi_regulator *vreg) 126562306a36Sopenharmony_ci{ 126662306a36Sopenharmony_ci int ret; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci ret = spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_ENABLE, 126962306a36Sopenharmony_ci SPMI_COMMON_DISABLE, SPMI_COMMON_ENABLE_MASK); 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci vreg->vs_enable_time = ktime_get(); 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci ret = spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_ENABLE, 127462306a36Sopenharmony_ci SPMI_COMMON_ENABLE, SPMI_COMMON_ENABLE_MASK); 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci return ret; 127762306a36Sopenharmony_ci} 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_cistatic void spmi_regulator_vs_ocp_work(struct work_struct *work) 128062306a36Sopenharmony_ci{ 128162306a36Sopenharmony_ci struct delayed_work *dwork = to_delayed_work(work); 128262306a36Sopenharmony_ci struct spmi_regulator *vreg 128362306a36Sopenharmony_ci = container_of(dwork, struct spmi_regulator, ocp_work); 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci spmi_regulator_vs_clear_ocp(vreg); 128662306a36Sopenharmony_ci} 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_cistatic irqreturn_t spmi_regulator_vs_ocp_isr(int irq, void *data) 128962306a36Sopenharmony_ci{ 129062306a36Sopenharmony_ci struct spmi_regulator *vreg = data; 129162306a36Sopenharmony_ci ktime_t ocp_irq_time; 129262306a36Sopenharmony_ci s64 ocp_trigger_delay_us; 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci ocp_irq_time = ktime_get(); 129562306a36Sopenharmony_ci ocp_trigger_delay_us = ktime_us_delta(ocp_irq_time, 129662306a36Sopenharmony_ci vreg->vs_enable_time); 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci /* 129962306a36Sopenharmony_ci * Reset the OCP count if there is a large delay between switch enable 130062306a36Sopenharmony_ci * and when OCP triggers. This is indicative of a hotplug event as 130162306a36Sopenharmony_ci * opposed to a fault. 130262306a36Sopenharmony_ci */ 130362306a36Sopenharmony_ci if (ocp_trigger_delay_us > SPMI_VS_OCP_FAULT_DELAY_US) 130462306a36Sopenharmony_ci vreg->ocp_count = 0; 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci /* Wait for switch output to settle back to 0 V after OCP triggered. */ 130762306a36Sopenharmony_ci udelay(SPMI_VS_OCP_FALL_DELAY_US); 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci vreg->ocp_count++; 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci if (vreg->ocp_count == 1) { 131262306a36Sopenharmony_ci /* Immediately clear the over current condition. */ 131362306a36Sopenharmony_ci spmi_regulator_vs_clear_ocp(vreg); 131462306a36Sopenharmony_ci } else if (vreg->ocp_count <= vreg->ocp_max_retries) { 131562306a36Sopenharmony_ci /* Schedule the over current clear task to run later. */ 131662306a36Sopenharmony_ci schedule_delayed_work(&vreg->ocp_work, 131762306a36Sopenharmony_ci msecs_to_jiffies(vreg->ocp_retry_delay_ms) + 1); 131862306a36Sopenharmony_ci } else { 131962306a36Sopenharmony_ci dev_err(vreg->dev, 132062306a36Sopenharmony_ci "OCP triggered %d times; no further retries\n", 132162306a36Sopenharmony_ci vreg->ocp_count); 132262306a36Sopenharmony_ci } 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci return IRQ_HANDLED; 132562306a36Sopenharmony_ci} 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci#define SAW3_VCTL_DATA_MASK 0xFF 132862306a36Sopenharmony_ci#define SAW3_VCTL_CLEAR_MASK 0x700FF 132962306a36Sopenharmony_ci#define SAW3_AVS_CTL_EN_MASK 0x1 133062306a36Sopenharmony_ci#define SAW3_AVS_CTL_TGGL_MASK 0x8000000 133162306a36Sopenharmony_ci#define SAW3_AVS_CTL_CLEAR_MASK 0x7efc00 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_cistatic struct regmap *saw_regmap; 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_cistatic void spmi_saw_set_vdd(void *data) 133662306a36Sopenharmony_ci{ 133762306a36Sopenharmony_ci u32 vctl, data3, avs_ctl, pmic_sts; 133862306a36Sopenharmony_ci bool avs_enabled = false; 133962306a36Sopenharmony_ci unsigned long timeout; 134062306a36Sopenharmony_ci u8 voltage_sel = *(u8 *)data; 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci regmap_read(saw_regmap, SAW3_AVS_CTL, &avs_ctl); 134362306a36Sopenharmony_ci regmap_read(saw_regmap, SAW3_VCTL, &vctl); 134462306a36Sopenharmony_ci regmap_read(saw_regmap, SAW3_SPM_PMIC_DATA_3, &data3); 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci /* select the band */ 134762306a36Sopenharmony_ci vctl &= ~SAW3_VCTL_CLEAR_MASK; 134862306a36Sopenharmony_ci vctl |= (u32)voltage_sel; 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci data3 &= ~SAW3_VCTL_CLEAR_MASK; 135162306a36Sopenharmony_ci data3 |= (u32)voltage_sel; 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci /* If AVS is enabled, switch it off during the voltage change */ 135462306a36Sopenharmony_ci avs_enabled = SAW3_AVS_CTL_EN_MASK & avs_ctl; 135562306a36Sopenharmony_ci if (avs_enabled) { 135662306a36Sopenharmony_ci avs_ctl &= ~SAW3_AVS_CTL_TGGL_MASK; 135762306a36Sopenharmony_ci regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl); 135862306a36Sopenharmony_ci } 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci regmap_write(saw_regmap, SAW3_RST, 1); 136162306a36Sopenharmony_ci regmap_write(saw_regmap, SAW3_VCTL, vctl); 136262306a36Sopenharmony_ci regmap_write(saw_regmap, SAW3_SPM_PMIC_DATA_3, data3); 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci timeout = jiffies + usecs_to_jiffies(100); 136562306a36Sopenharmony_ci do { 136662306a36Sopenharmony_ci regmap_read(saw_regmap, SAW3_PMIC_STS, &pmic_sts); 136762306a36Sopenharmony_ci pmic_sts &= SAW3_VCTL_DATA_MASK; 136862306a36Sopenharmony_ci if (pmic_sts == (u32)voltage_sel) 136962306a36Sopenharmony_ci break; 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci cpu_relax(); 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci } while (time_before(jiffies, timeout)); 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci /* After successful voltage change, switch the AVS back on */ 137662306a36Sopenharmony_ci if (avs_enabled) { 137762306a36Sopenharmony_ci pmic_sts &= 0x3f; 137862306a36Sopenharmony_ci avs_ctl &= ~SAW3_AVS_CTL_CLEAR_MASK; 137962306a36Sopenharmony_ci avs_ctl |= ((pmic_sts - 4) << 10); 138062306a36Sopenharmony_ci avs_ctl |= (pmic_sts << 17); 138162306a36Sopenharmony_ci avs_ctl |= SAW3_AVS_CTL_TGGL_MASK; 138262306a36Sopenharmony_ci regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl); 138362306a36Sopenharmony_ci } 138462306a36Sopenharmony_ci} 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_cistatic int 138762306a36Sopenharmony_cispmi_regulator_saw_set_voltage(struct regulator_dev *rdev, unsigned selector) 138862306a36Sopenharmony_ci{ 138962306a36Sopenharmony_ci struct spmi_regulator *vreg = rdev_get_drvdata(rdev); 139062306a36Sopenharmony_ci int ret; 139162306a36Sopenharmony_ci u8 range_sel, voltage_sel; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel); 139462306a36Sopenharmony_ci if (ret) 139562306a36Sopenharmony_ci return ret; 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci if (0 != range_sel) { 139862306a36Sopenharmony_ci dev_dbg(&rdev->dev, "range_sel = %02X voltage_sel = %02X", \ 139962306a36Sopenharmony_ci range_sel, voltage_sel); 140062306a36Sopenharmony_ci return -EINVAL; 140162306a36Sopenharmony_ci } 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci /* Always do the SAW register writes on the first CPU */ 140462306a36Sopenharmony_ci return smp_call_function_single(0, spmi_saw_set_vdd, \ 140562306a36Sopenharmony_ci &voltage_sel, true); 140662306a36Sopenharmony_ci} 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_cistatic struct regulator_ops spmi_saw_ops = {}; 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_cistatic const struct regulator_ops spmi_smps_ops = { 141162306a36Sopenharmony_ci .enable = regulator_enable_regmap, 141262306a36Sopenharmony_ci .disable = regulator_disable_regmap, 141362306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 141462306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_common_set_voltage, 141562306a36Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 141662306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_common_get_voltage, 141762306a36Sopenharmony_ci .map_voltage = spmi_regulator_common_map_voltage, 141862306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 141962306a36Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 142062306a36Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 142162306a36Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 142262306a36Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 142362306a36Sopenharmony_ci}; 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_cistatic const struct regulator_ops spmi_ldo_ops = { 142662306a36Sopenharmony_ci .enable = regulator_enable_regmap, 142762306a36Sopenharmony_ci .disable = regulator_disable_regmap, 142862306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 142962306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_common_set_voltage, 143062306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_common_get_voltage, 143162306a36Sopenharmony_ci .map_voltage = spmi_regulator_common_map_voltage, 143262306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 143362306a36Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 143462306a36Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 143562306a36Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 143662306a36Sopenharmony_ci .set_bypass = spmi_regulator_common_set_bypass, 143762306a36Sopenharmony_ci .get_bypass = spmi_regulator_common_get_bypass, 143862306a36Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 143962306a36Sopenharmony_ci .set_soft_start = spmi_regulator_common_set_soft_start, 144062306a36Sopenharmony_ci}; 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_cistatic const struct regulator_ops spmi_ln_ldo_ops = { 144362306a36Sopenharmony_ci .enable = regulator_enable_regmap, 144462306a36Sopenharmony_ci .disable = regulator_disable_regmap, 144562306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 144662306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_common_set_voltage, 144762306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_common_get_voltage, 144862306a36Sopenharmony_ci .map_voltage = spmi_regulator_common_map_voltage, 144962306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 145062306a36Sopenharmony_ci .set_bypass = spmi_regulator_common_set_bypass, 145162306a36Sopenharmony_ci .get_bypass = spmi_regulator_common_get_bypass, 145262306a36Sopenharmony_ci}; 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_cistatic const struct regulator_ops spmi_vs_ops = { 145562306a36Sopenharmony_ci .enable = spmi_regulator_vs_enable, 145662306a36Sopenharmony_ci .disable = regulator_disable_regmap, 145762306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 145862306a36Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 145962306a36Sopenharmony_ci .set_soft_start = spmi_regulator_common_set_soft_start, 146062306a36Sopenharmony_ci .set_over_current_protection = spmi_regulator_vs_ocp, 146162306a36Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 146262306a36Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 146362306a36Sopenharmony_ci}; 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_cistatic const struct regulator_ops spmi_boost_ops = { 146662306a36Sopenharmony_ci .enable = regulator_enable_regmap, 146762306a36Sopenharmony_ci .disable = regulator_disable_regmap, 146862306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 146962306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_single_range_set_voltage, 147062306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_single_range_get_voltage, 147162306a36Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 147262306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 147362306a36Sopenharmony_ci .set_input_current_limit = spmi_regulator_set_ilim, 147462306a36Sopenharmony_ci}; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_cistatic const struct regulator_ops spmi_ftsmps_ops = { 147762306a36Sopenharmony_ci .enable = regulator_enable_regmap, 147862306a36Sopenharmony_ci .disable = regulator_disable_regmap, 147962306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 148062306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_common_set_voltage, 148162306a36Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 148262306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_common_get_voltage, 148362306a36Sopenharmony_ci .map_voltage = spmi_regulator_common_map_voltage, 148462306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 148562306a36Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 148662306a36Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 148762306a36Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 148862306a36Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 148962306a36Sopenharmony_ci}; 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_cistatic const struct regulator_ops spmi_ult_lo_smps_ops = { 149262306a36Sopenharmony_ci .enable = regulator_enable_regmap, 149362306a36Sopenharmony_ci .disable = regulator_disable_regmap, 149462306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 149562306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_ult_lo_smps_set_voltage, 149662306a36Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 149762306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_ult_lo_smps_get_voltage, 149862306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 149962306a36Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 150062306a36Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 150162306a36Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 150262306a36Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 150362306a36Sopenharmony_ci}; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_cistatic const struct regulator_ops spmi_ult_ho_smps_ops = { 150662306a36Sopenharmony_ci .enable = regulator_enable_regmap, 150762306a36Sopenharmony_ci .disable = regulator_disable_regmap, 150862306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 150962306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_single_range_set_voltage, 151062306a36Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 151162306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_single_range_get_voltage, 151262306a36Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 151362306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 151462306a36Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 151562306a36Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 151662306a36Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 151762306a36Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 151862306a36Sopenharmony_ci}; 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_cistatic const struct regulator_ops spmi_ult_ldo_ops = { 152162306a36Sopenharmony_ci .enable = regulator_enable_regmap, 152262306a36Sopenharmony_ci .disable = regulator_disable_regmap, 152362306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 152462306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_single_range_set_voltage, 152562306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_single_range_get_voltage, 152662306a36Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 152762306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 152862306a36Sopenharmony_ci .set_mode = spmi_regulator_common_set_mode, 152962306a36Sopenharmony_ci .get_mode = spmi_regulator_common_get_mode, 153062306a36Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 153162306a36Sopenharmony_ci .set_bypass = spmi_regulator_common_set_bypass, 153262306a36Sopenharmony_ci .get_bypass = spmi_regulator_common_get_bypass, 153362306a36Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 153462306a36Sopenharmony_ci .set_soft_start = spmi_regulator_common_set_soft_start, 153562306a36Sopenharmony_ci}; 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_cistatic const struct regulator_ops spmi_ftsmps426_ops = { 153862306a36Sopenharmony_ci .enable = regulator_enable_regmap, 153962306a36Sopenharmony_ci .disable = regulator_disable_regmap, 154062306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 154162306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_ftsmps426_set_voltage, 154262306a36Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 154362306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_ftsmps426_get_voltage, 154462306a36Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 154562306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 154662306a36Sopenharmony_ci .set_mode = spmi_regulator_ftsmps426_set_mode, 154762306a36Sopenharmony_ci .get_mode = spmi_regulator_ftsmps426_get_mode, 154862306a36Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 154962306a36Sopenharmony_ci .set_pull_down = spmi_regulator_common_set_pull_down, 155062306a36Sopenharmony_ci}; 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_cistatic const struct regulator_ops spmi_hfs430_ops = { 155362306a36Sopenharmony_ci .enable = regulator_enable_regmap, 155462306a36Sopenharmony_ci .disable = regulator_disable_regmap, 155562306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 155662306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_ftsmps426_set_voltage, 155762306a36Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 155862306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_ftsmps426_get_voltage, 155962306a36Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 156062306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 156162306a36Sopenharmony_ci .set_mode = spmi_regulator_ftsmps426_set_mode, 156262306a36Sopenharmony_ci .get_mode = spmi_regulator_ftsmps426_get_mode, 156362306a36Sopenharmony_ci}; 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_cistatic const struct regulator_ops spmi_hfsmps_ops = { 156662306a36Sopenharmony_ci .enable = regulator_enable_regmap, 156762306a36Sopenharmony_ci .disable = regulator_disable_regmap, 156862306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 156962306a36Sopenharmony_ci .set_voltage_sel = spmi_regulator_ftsmps426_set_voltage, 157062306a36Sopenharmony_ci .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, 157162306a36Sopenharmony_ci .get_voltage_sel = spmi_regulator_ftsmps426_get_voltage, 157262306a36Sopenharmony_ci .map_voltage = spmi_regulator_single_map_voltage, 157362306a36Sopenharmony_ci .list_voltage = spmi_regulator_common_list_voltage, 157462306a36Sopenharmony_ci .set_mode = spmi_regulator_hfsmps_set_mode, 157562306a36Sopenharmony_ci .get_mode = spmi_regulator_hfsmps_get_mode, 157662306a36Sopenharmony_ci .set_load = spmi_regulator_common_set_load, 157762306a36Sopenharmony_ci .set_pull_down = spmi_regulator_hfsmps_set_pull_down, 157862306a36Sopenharmony_ci}; 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci/* Maximum possible digital major revision value */ 158162306a36Sopenharmony_ci#define INF 0xFF 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_cistatic const struct spmi_regulator_mapping supported_regulators[] = { 158462306a36Sopenharmony_ci /* type subtype dig_min dig_max ltype ops setpoints hpm_min */ 158562306a36Sopenharmony_ci SPMI_VREG(LDO, HT_P600, 0, INF, HFS430, hfs430, ht_p600, 10000), 158662306a36Sopenharmony_ci SPMI_VREG(LDO, HT_P150, 0, INF, HFS430, hfs430, ht_p150, 10000), 158762306a36Sopenharmony_ci SPMI_VREG(BUCK, GP_CTL, 0, INF, SMPS, smps, smps, 100000), 158862306a36Sopenharmony_ci SPMI_VREG(BUCK, HFS430, 0, 3, HFS430, hfs430, hfs430, 10000), 158962306a36Sopenharmony_ci SPMI_VREG(BUCK, HFSMPS_510, 4, INF, HFSMPS, hfsmps, hfs430, 100000), 159062306a36Sopenharmony_ci SPMI_VREG(LDO, N300, 0, INF, LDO, ldo, nldo1, 10000), 159162306a36Sopenharmony_ci SPMI_VREG(LDO, N600, 0, 0, LDO, ldo, nldo2, 10000), 159262306a36Sopenharmony_ci SPMI_VREG(LDO, N1200, 0, 0, LDO, ldo, nldo2, 10000), 159362306a36Sopenharmony_ci SPMI_VREG(LDO, N600, 1, INF, LDO, ldo, nldo3, 10000), 159462306a36Sopenharmony_ci SPMI_VREG(LDO, N1200, 1, INF, LDO, ldo, nldo3, 10000), 159562306a36Sopenharmony_ci SPMI_VREG(LDO, N600_ST, 0, 0, LDO, ldo, nldo2, 10000), 159662306a36Sopenharmony_ci SPMI_VREG(LDO, N1200_ST, 0, 0, LDO, ldo, nldo2, 10000), 159762306a36Sopenharmony_ci SPMI_VREG(LDO, N600_ST, 1, INF, LDO, ldo, nldo3, 10000), 159862306a36Sopenharmony_ci SPMI_VREG(LDO, N1200_ST, 1, INF, LDO, ldo, nldo3, 10000), 159962306a36Sopenharmony_ci SPMI_VREG(LDO, P50, 0, INF, LDO, ldo, pldo, 5000), 160062306a36Sopenharmony_ci SPMI_VREG(LDO, P150, 0, INF, LDO, ldo, pldo, 10000), 160162306a36Sopenharmony_ci SPMI_VREG(LDO, P300, 0, INF, LDO, ldo, pldo, 10000), 160262306a36Sopenharmony_ci SPMI_VREG(LDO, P600, 0, INF, LDO, ldo, pldo, 10000), 160362306a36Sopenharmony_ci SPMI_VREG(LDO, P1200, 0, INF, LDO, ldo, pldo, 10000), 160462306a36Sopenharmony_ci SPMI_VREG(LDO, LN, 0, INF, LN_LDO, ln_ldo, ln_ldo, 0), 160562306a36Sopenharmony_ci SPMI_VREG(LDO, LV_P50, 0, INF, LDO, ldo, pldo, 5000), 160662306a36Sopenharmony_ci SPMI_VREG(LDO, LV_P150, 0, INF, LDO, ldo, pldo, 10000), 160762306a36Sopenharmony_ci SPMI_VREG(LDO, LV_P300, 0, INF, LDO, ldo, pldo, 10000), 160862306a36Sopenharmony_ci SPMI_VREG(LDO, LV_P600, 0, INF, LDO, ldo, pldo, 10000), 160962306a36Sopenharmony_ci SPMI_VREG(LDO, LV_P1200, 0, INF, LDO, ldo, pldo, 10000), 161062306a36Sopenharmony_ci SPMI_VREG(LDO, HT_N300_ST, 0, INF, FTSMPS426, ftsmps426, 161162306a36Sopenharmony_ci ht_nldo, 30000), 161262306a36Sopenharmony_ci SPMI_VREG(LDO, HT_N600_ST, 0, INF, FTSMPS426, ftsmps426, 161362306a36Sopenharmony_ci ht_nldo, 30000), 161462306a36Sopenharmony_ci SPMI_VREG(LDO, HT_N1200_ST, 0, INF, FTSMPS426, ftsmps426, 161562306a36Sopenharmony_ci ht_nldo, 30000), 161662306a36Sopenharmony_ci SPMI_VREG(LDO, HT_LVP150, 0, INF, FTSMPS426, ftsmps426, 161762306a36Sopenharmony_ci ht_lvpldo, 10000), 161862306a36Sopenharmony_ci SPMI_VREG(LDO, HT_LVP300, 0, INF, FTSMPS426, ftsmps426, 161962306a36Sopenharmony_ci ht_lvpldo, 10000), 162062306a36Sopenharmony_ci SPMI_VREG(LDO, L660_N300_ST, 0, INF, FTSMPS426, ftsmps426, 162162306a36Sopenharmony_ci nldo660, 10000), 162262306a36Sopenharmony_ci SPMI_VREG(LDO, L660_N600_ST, 0, INF, FTSMPS426, ftsmps426, 162362306a36Sopenharmony_ci nldo660, 10000), 162462306a36Sopenharmony_ci SPMI_VREG(LDO, L660_P50, 0, INF, FTSMPS426, ftsmps426, 162562306a36Sopenharmony_ci pldo660, 10000), 162662306a36Sopenharmony_ci SPMI_VREG(LDO, L660_P150, 0, INF, FTSMPS426, ftsmps426, 162762306a36Sopenharmony_ci pldo660, 10000), 162862306a36Sopenharmony_ci SPMI_VREG(LDO, L660_P600, 0, INF, FTSMPS426, ftsmps426, 162962306a36Sopenharmony_ci pldo660, 10000), 163062306a36Sopenharmony_ci SPMI_VREG(LDO, L660_LVP150, 0, INF, FTSMPS426, ftsmps426, 163162306a36Sopenharmony_ci ht_lvpldo, 10000), 163262306a36Sopenharmony_ci SPMI_VREG(LDO, L660_LVP600, 0, INF, FTSMPS426, ftsmps426, 163362306a36Sopenharmony_ci ht_lvpldo, 10000), 163462306a36Sopenharmony_ci SPMI_VREG_VS(LV100, 0, INF), 163562306a36Sopenharmony_ci SPMI_VREG_VS(LV300, 0, INF), 163662306a36Sopenharmony_ci SPMI_VREG_VS(MV300, 0, INF), 163762306a36Sopenharmony_ci SPMI_VREG_VS(MV500, 0, INF), 163862306a36Sopenharmony_ci SPMI_VREG_VS(HDMI, 0, INF), 163962306a36Sopenharmony_ci SPMI_VREG_VS(OTG, 0, INF), 164062306a36Sopenharmony_ci SPMI_VREG(BOOST, 5V_BOOST, 0, INF, BOOST, boost, boost, 0), 164162306a36Sopenharmony_ci SPMI_VREG(FTS, FTS_CTL, 0, INF, FTSMPS, ftsmps, ftsmps, 100000), 164262306a36Sopenharmony_ci SPMI_VREG(FTS, FTS2p5_CTL, 0, INF, FTSMPS, ftsmps, ftsmps2p5, 100000), 164362306a36Sopenharmony_ci SPMI_VREG(FTS, FTS426_CTL, 0, INF, FTSMPS426, ftsmps426, ftsmps426, 100000), 164462306a36Sopenharmony_ci SPMI_VREG(BOOST_BYP, BB_2A, 0, INF, BOOST_BYP, boost, boost_byp, 0), 164562306a36Sopenharmony_ci SPMI_VREG(ULT_BUCK, ULT_HF_CTL1, 0, INF, ULT_LO_SMPS, ult_lo_smps, 164662306a36Sopenharmony_ci ult_lo_smps, 100000), 164762306a36Sopenharmony_ci SPMI_VREG(ULT_BUCK, ULT_HF_CTL2, 0, INF, ULT_LO_SMPS, ult_lo_smps, 164862306a36Sopenharmony_ci ult_lo_smps, 100000), 164962306a36Sopenharmony_ci SPMI_VREG(ULT_BUCK, ULT_HF_CTL3, 0, INF, ULT_LO_SMPS, ult_lo_smps, 165062306a36Sopenharmony_ci ult_lo_smps, 100000), 165162306a36Sopenharmony_ci SPMI_VREG(ULT_BUCK, ULT_HF_CTL4, 0, INF, ULT_HO_SMPS, ult_ho_smps, 165262306a36Sopenharmony_ci ult_ho_smps, 100000), 165362306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, N300_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000), 165462306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, N600_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000), 165562306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, N900_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000), 165662306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, N1200_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000), 165762306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, LV_P50, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 165862306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, LV_P150, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 165962306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, LV_P300, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 166062306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, LV_P450, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 166162306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, P600, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 166262306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, P300, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 166362306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, P150, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), 166462306a36Sopenharmony_ci SPMI_VREG(ULT_LDO, P50, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 5000), 166562306a36Sopenharmony_ci SPMI_VREG(LDO, LV_P150_510, 0, INF, LDO_510, hfsmps, ht_lvpldo, 10000), 166662306a36Sopenharmony_ci SPMI_VREG(LDO, LV_P300_510, 0, INF, LDO_510, hfsmps, ht_lvpldo, 10000), 166762306a36Sopenharmony_ci SPMI_VREG(LDO, LV_P600_510, 0, INF, LDO_510, hfsmps, ht_lvpldo, 10000), 166862306a36Sopenharmony_ci SPMI_VREG(LDO, MV_P50_510, 0, INF, LDO_510, hfsmps, pldo660, 10000), 166962306a36Sopenharmony_ci SPMI_VREG(LDO, MV_P150_510, 0, INF, LDO_510, hfsmps, pldo660, 10000), 167062306a36Sopenharmony_ci SPMI_VREG(LDO, MV_P600_510, 0, INF, LDO_510, hfsmps, pldo660, 10000), 167162306a36Sopenharmony_ci SPMI_VREG(LDO, N300_510, 0, INF, LDO_510, hfsmps, nldo_510, 10000), 167262306a36Sopenharmony_ci SPMI_VREG(LDO, N600_510, 0, INF, LDO_510, hfsmps, nldo_510, 10000), 167362306a36Sopenharmony_ci SPMI_VREG(LDO, N1200_510, 0, INF, LDO_510, hfsmps, nldo_510, 10000), 167462306a36Sopenharmony_ci SPMI_VREG(FTS, FTSMPS_510, 0, INF, FTSMPS3, hfsmps, ftsmps510, 100000), 167562306a36Sopenharmony_ci}; 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_cistatic void spmi_calculate_num_voltages(struct spmi_voltage_set_points *points) 167862306a36Sopenharmony_ci{ 167962306a36Sopenharmony_ci unsigned int n; 168062306a36Sopenharmony_ci struct spmi_voltage_range *range = points->range; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci for (; range < points->range + points->count; range++) { 168362306a36Sopenharmony_ci n = 0; 168462306a36Sopenharmony_ci if (range->set_point_max_uV) { 168562306a36Sopenharmony_ci n = range->set_point_max_uV - range->set_point_min_uV; 168662306a36Sopenharmony_ci n = (n / range->step_uV) + 1; 168762306a36Sopenharmony_ci } 168862306a36Sopenharmony_ci range->n_voltages = n; 168962306a36Sopenharmony_ci points->n_voltages += n; 169062306a36Sopenharmony_ci } 169162306a36Sopenharmony_ci} 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_cistatic int spmi_regulator_match(struct spmi_regulator *vreg, u16 force_type) 169462306a36Sopenharmony_ci{ 169562306a36Sopenharmony_ci const struct spmi_regulator_mapping *mapping; 169662306a36Sopenharmony_ci int ret, i; 169762306a36Sopenharmony_ci u32 dig_major_rev; 169862306a36Sopenharmony_ci u8 version[SPMI_COMMON_REG_SUBTYPE - SPMI_COMMON_REG_DIG_MAJOR_REV + 1]; 169962306a36Sopenharmony_ci u8 type, subtype; 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_DIG_MAJOR_REV, version, 170262306a36Sopenharmony_ci ARRAY_SIZE(version)); 170362306a36Sopenharmony_ci if (ret) { 170462306a36Sopenharmony_ci dev_dbg(vreg->dev, "could not read version registers\n"); 170562306a36Sopenharmony_ci return ret; 170662306a36Sopenharmony_ci } 170762306a36Sopenharmony_ci dig_major_rev = version[SPMI_COMMON_REG_DIG_MAJOR_REV 170862306a36Sopenharmony_ci - SPMI_COMMON_REG_DIG_MAJOR_REV]; 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci if (!force_type) { 171162306a36Sopenharmony_ci type = version[SPMI_COMMON_REG_TYPE - 171262306a36Sopenharmony_ci SPMI_COMMON_REG_DIG_MAJOR_REV]; 171362306a36Sopenharmony_ci subtype = version[SPMI_COMMON_REG_SUBTYPE - 171462306a36Sopenharmony_ci SPMI_COMMON_REG_DIG_MAJOR_REV]; 171562306a36Sopenharmony_ci } else { 171662306a36Sopenharmony_ci type = force_type >> 8; 171762306a36Sopenharmony_ci subtype = force_type; 171862306a36Sopenharmony_ci } 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(supported_regulators); i++) { 172162306a36Sopenharmony_ci mapping = &supported_regulators[i]; 172262306a36Sopenharmony_ci if (mapping->type == type && mapping->subtype == subtype 172362306a36Sopenharmony_ci && mapping->revision_min <= dig_major_rev 172462306a36Sopenharmony_ci && mapping->revision_max >= dig_major_rev) 172562306a36Sopenharmony_ci goto found; 172662306a36Sopenharmony_ci } 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci dev_err(vreg->dev, 172962306a36Sopenharmony_ci "unsupported regulator: name=%s type=0x%02X, subtype=0x%02X, dig major rev=0x%02X\n", 173062306a36Sopenharmony_ci vreg->desc.name, type, subtype, dig_major_rev); 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci return -ENODEV; 173362306a36Sopenharmony_ci 173462306a36Sopenharmony_cifound: 173562306a36Sopenharmony_ci vreg->logical_type = mapping->logical_type; 173662306a36Sopenharmony_ci vreg->set_points = mapping->set_points; 173762306a36Sopenharmony_ci vreg->hpm_min_load = mapping->hpm_min_load; 173862306a36Sopenharmony_ci vreg->desc.ops = mapping->ops; 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci if (mapping->set_points) { 174162306a36Sopenharmony_ci if (!mapping->set_points->n_voltages) 174262306a36Sopenharmony_ci spmi_calculate_num_voltages(mapping->set_points); 174362306a36Sopenharmony_ci vreg->desc.n_voltages = mapping->set_points->n_voltages; 174462306a36Sopenharmony_ci } 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci return 0; 174762306a36Sopenharmony_ci} 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_cistatic int spmi_regulator_init_slew_rate(struct spmi_regulator *vreg) 175062306a36Sopenharmony_ci{ 175162306a36Sopenharmony_ci int ret; 175262306a36Sopenharmony_ci u8 reg = 0; 175362306a36Sopenharmony_ci int step, delay, slew_rate, step_delay; 175462306a36Sopenharmony_ci const struct spmi_voltage_range *range; 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_STEP_CTRL, ®, 1); 175762306a36Sopenharmony_ci if (ret) { 175862306a36Sopenharmony_ci dev_err(vreg->dev, "spmi read failed, ret=%d\n", ret); 175962306a36Sopenharmony_ci return ret; 176062306a36Sopenharmony_ci } 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci range = spmi_regulator_find_range(vreg); 176362306a36Sopenharmony_ci if (!range) 176462306a36Sopenharmony_ci return -EINVAL; 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci switch (vreg->logical_type) { 176762306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS: 176862306a36Sopenharmony_ci step_delay = SPMI_FTSMPS_STEP_DELAY; 176962306a36Sopenharmony_ci break; 177062306a36Sopenharmony_ci default: 177162306a36Sopenharmony_ci step_delay = SPMI_DEFAULT_STEP_DELAY; 177262306a36Sopenharmony_ci break; 177362306a36Sopenharmony_ci } 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci step = reg & SPMI_FTSMPS_STEP_CTRL_STEP_MASK; 177662306a36Sopenharmony_ci step >>= SPMI_FTSMPS_STEP_CTRL_STEP_SHIFT; 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci delay = reg & SPMI_FTSMPS_STEP_CTRL_DELAY_MASK; 177962306a36Sopenharmony_ci delay >>= SPMI_FTSMPS_STEP_CTRL_DELAY_SHIFT; 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci /* slew_rate has units of uV/us */ 178262306a36Sopenharmony_ci slew_rate = SPMI_FTSMPS_CLOCK_RATE * range->step_uV * (1 << step); 178362306a36Sopenharmony_ci slew_rate /= 1000 * (step_delay << delay); 178462306a36Sopenharmony_ci slew_rate *= SPMI_FTSMPS_STEP_MARGIN_NUM; 178562306a36Sopenharmony_ci slew_rate /= SPMI_FTSMPS_STEP_MARGIN_DEN; 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci /* Ensure that the slew rate is greater than 0 */ 178862306a36Sopenharmony_ci vreg->slew_rate = max(slew_rate, 1); 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci return ret; 179162306a36Sopenharmony_ci} 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_cistatic int spmi_regulator_init_slew_rate_ftsmps426(struct spmi_regulator *vreg, 179462306a36Sopenharmony_ci int clock_rate) 179562306a36Sopenharmony_ci{ 179662306a36Sopenharmony_ci int ret; 179762306a36Sopenharmony_ci u8 reg = 0; 179862306a36Sopenharmony_ci int delay, slew_rate; 179962306a36Sopenharmony_ci const struct spmi_voltage_range *range = &vreg->set_points->range[0]; 180062306a36Sopenharmony_ci 180162306a36Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_STEP_CTRL, ®, 1); 180262306a36Sopenharmony_ci if (ret) { 180362306a36Sopenharmony_ci dev_err(vreg->dev, "spmi read failed, ret=%d\n", ret); 180462306a36Sopenharmony_ci return ret; 180562306a36Sopenharmony_ci } 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci delay = reg & SPMI_FTSMPS426_STEP_CTRL_DELAY_MASK; 180862306a36Sopenharmony_ci delay >>= SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT; 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci /* slew_rate has units of uV/us */ 181162306a36Sopenharmony_ci slew_rate = clock_rate * range->step_uV; 181262306a36Sopenharmony_ci slew_rate /= 1000 * (SPMI_FTSMPS426_STEP_DELAY << delay); 181362306a36Sopenharmony_ci slew_rate *= SPMI_FTSMPS426_STEP_MARGIN_NUM; 181462306a36Sopenharmony_ci slew_rate /= SPMI_FTSMPS426_STEP_MARGIN_DEN; 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci /* Ensure that the slew rate is greater than 0 */ 181762306a36Sopenharmony_ci vreg->slew_rate = max(slew_rate, 1); 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci return ret; 182062306a36Sopenharmony_ci} 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_cistatic int spmi_regulator_init_slew_rate_hfsmps(struct spmi_regulator *vreg) 182362306a36Sopenharmony_ci{ 182462306a36Sopenharmony_ci int ret; 182562306a36Sopenharmony_ci u8 reg = 0; 182662306a36Sopenharmony_ci int delay; 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_HFSMPS_REG_STEP_CTRL, ®, 1); 182962306a36Sopenharmony_ci if (ret) { 183062306a36Sopenharmony_ci dev_err(vreg->dev, "spmi read failed, ret=%d\n", ret); 183162306a36Sopenharmony_ci return ret; 183262306a36Sopenharmony_ci } 183362306a36Sopenharmony_ci 183462306a36Sopenharmony_ci delay = reg & SPMI_FTSMPS426_STEP_CTRL_DELAY_MASK; 183562306a36Sopenharmony_ci delay >>= SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT; 183662306a36Sopenharmony_ci 183762306a36Sopenharmony_ci vreg->slew_rate = SPMI_HFSMPS_SLEW_RATE_38p4 >> delay; 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci return ret; 184062306a36Sopenharmony_ci} 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_cistatic int spmi_regulator_init_registers(struct spmi_regulator *vreg, 184362306a36Sopenharmony_ci const struct spmi_regulator_init_data *data) 184462306a36Sopenharmony_ci{ 184562306a36Sopenharmony_ci int ret; 184662306a36Sopenharmony_ci enum spmi_regulator_logical_type type; 184762306a36Sopenharmony_ci u8 ctrl_reg[8], reg, mask; 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci type = vreg->logical_type; 185062306a36Sopenharmony_ci 185162306a36Sopenharmony_ci ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, ctrl_reg, 8); 185262306a36Sopenharmony_ci if (ret) 185362306a36Sopenharmony_ci return ret; 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci /* Set up enable pin control. */ 185662306a36Sopenharmony_ci if (!(data->pin_ctrl_enable & SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT)) { 185762306a36Sopenharmony_ci switch (type) { 185862306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_SMPS: 185962306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_LDO: 186062306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_VS: 186162306a36Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_ENABLE] &= 186262306a36Sopenharmony_ci ~SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK; 186362306a36Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_ENABLE] |= 186462306a36Sopenharmony_ci data->pin_ctrl_enable & SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK; 186562306a36Sopenharmony_ci break; 186662306a36Sopenharmony_ci default: 186762306a36Sopenharmony_ci break; 186862306a36Sopenharmony_ci } 186962306a36Sopenharmony_ci } 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci /* Set up mode pin control. */ 187262306a36Sopenharmony_ci if (!(data->pin_ctrl_hpm & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) { 187362306a36Sopenharmony_ci switch (type) { 187462306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_SMPS: 187562306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_LDO: 187662306a36Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_MODE] &= 187762306a36Sopenharmony_ci ~SPMI_COMMON_MODE_FOLLOW_ALL_MASK; 187862306a36Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_MODE] |= 187962306a36Sopenharmony_ci data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_ALL_MASK; 188062306a36Sopenharmony_ci break; 188162306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_VS: 188262306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS: 188362306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS: 188462306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO: 188562306a36Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_MODE] &= 188662306a36Sopenharmony_ci ~SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK; 188762306a36Sopenharmony_ci ctrl_reg[SPMI_COMMON_IDX_MODE] |= 188862306a36Sopenharmony_ci data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK; 188962306a36Sopenharmony_ci break; 189062306a36Sopenharmony_ci default: 189162306a36Sopenharmony_ci break; 189262306a36Sopenharmony_ci } 189362306a36Sopenharmony_ci } 189462306a36Sopenharmony_ci 189562306a36Sopenharmony_ci /* Write back any control register values that were modified. */ 189662306a36Sopenharmony_ci ret = spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, ctrl_reg, 8); 189762306a36Sopenharmony_ci if (ret) 189862306a36Sopenharmony_ci return ret; 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci /* Set soft start strength and over current protection for VS. */ 190162306a36Sopenharmony_ci if (type == SPMI_REGULATOR_LOGICAL_TYPE_VS) { 190262306a36Sopenharmony_ci if (data->vs_soft_start_strength 190362306a36Sopenharmony_ci != SPMI_VS_SOFT_START_STR_HW_DEFAULT) { 190462306a36Sopenharmony_ci reg = data->vs_soft_start_strength 190562306a36Sopenharmony_ci & SPMI_VS_SOFT_START_SEL_MASK; 190662306a36Sopenharmony_ci mask = SPMI_VS_SOFT_START_SEL_MASK; 190762306a36Sopenharmony_ci return spmi_vreg_update_bits(vreg, 190862306a36Sopenharmony_ci SPMI_VS_REG_SOFT_START, 190962306a36Sopenharmony_ci reg, mask); 191062306a36Sopenharmony_ci } 191162306a36Sopenharmony_ci } 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci return 0; 191462306a36Sopenharmony_ci} 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_cistatic void spmi_regulator_get_dt_config(struct spmi_regulator *vreg, 191762306a36Sopenharmony_ci struct device_node *node, struct spmi_regulator_init_data *data) 191862306a36Sopenharmony_ci{ 191962306a36Sopenharmony_ci /* 192062306a36Sopenharmony_ci * Initialize configuration parameters to use hardware default in case 192162306a36Sopenharmony_ci * no value is specified via device tree. 192262306a36Sopenharmony_ci */ 192362306a36Sopenharmony_ci data->pin_ctrl_enable = SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT; 192462306a36Sopenharmony_ci data->pin_ctrl_hpm = SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT; 192562306a36Sopenharmony_ci data->vs_soft_start_strength = SPMI_VS_SOFT_START_STR_HW_DEFAULT; 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci /* These bindings are optional, so it is okay if they aren't found. */ 192862306a36Sopenharmony_ci of_property_read_u32(node, "qcom,ocp-max-retries", 192962306a36Sopenharmony_ci &vreg->ocp_max_retries); 193062306a36Sopenharmony_ci of_property_read_u32(node, "qcom,ocp-retry-delay", 193162306a36Sopenharmony_ci &vreg->ocp_retry_delay_ms); 193262306a36Sopenharmony_ci of_property_read_u32(node, "qcom,pin-ctrl-enable", 193362306a36Sopenharmony_ci &data->pin_ctrl_enable); 193462306a36Sopenharmony_ci of_property_read_u32(node, "qcom,pin-ctrl-hpm", &data->pin_ctrl_hpm); 193562306a36Sopenharmony_ci of_property_read_u32(node, "qcom,vs-soft-start-strength", 193662306a36Sopenharmony_ci &data->vs_soft_start_strength); 193762306a36Sopenharmony_ci} 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_cistatic unsigned int spmi_regulator_of_map_mode(unsigned int mode) 194062306a36Sopenharmony_ci{ 194162306a36Sopenharmony_ci if (mode == 1) 194262306a36Sopenharmony_ci return REGULATOR_MODE_NORMAL; 194362306a36Sopenharmony_ci if (mode == 2) 194462306a36Sopenharmony_ci return REGULATOR_MODE_FAST; 194562306a36Sopenharmony_ci 194662306a36Sopenharmony_ci return REGULATOR_MODE_IDLE; 194762306a36Sopenharmony_ci} 194862306a36Sopenharmony_ci 194962306a36Sopenharmony_cistatic int spmi_regulator_of_parse(struct device_node *node, 195062306a36Sopenharmony_ci const struct regulator_desc *desc, 195162306a36Sopenharmony_ci struct regulator_config *config) 195262306a36Sopenharmony_ci{ 195362306a36Sopenharmony_ci struct spmi_regulator_init_data data = { }; 195462306a36Sopenharmony_ci struct spmi_regulator *vreg = config->driver_data; 195562306a36Sopenharmony_ci struct device *dev = config->dev; 195662306a36Sopenharmony_ci int ret; 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci spmi_regulator_get_dt_config(vreg, node, &data); 195962306a36Sopenharmony_ci 196062306a36Sopenharmony_ci if (!vreg->ocp_max_retries) 196162306a36Sopenharmony_ci vreg->ocp_max_retries = SPMI_VS_OCP_DEFAULT_MAX_RETRIES; 196262306a36Sopenharmony_ci if (!vreg->ocp_retry_delay_ms) 196362306a36Sopenharmony_ci vreg->ocp_retry_delay_ms = SPMI_VS_OCP_DEFAULT_RETRY_DELAY_MS; 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci ret = spmi_regulator_init_registers(vreg, &data); 196662306a36Sopenharmony_ci if (ret) { 196762306a36Sopenharmony_ci dev_err(dev, "common initialization failed, ret=%d\n", ret); 196862306a36Sopenharmony_ci return ret; 196962306a36Sopenharmony_ci } 197062306a36Sopenharmony_ci 197162306a36Sopenharmony_ci switch (vreg->logical_type) { 197262306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS: 197362306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS: 197462306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS: 197562306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_SMPS: 197662306a36Sopenharmony_ci ret = spmi_regulator_init_slew_rate(vreg); 197762306a36Sopenharmony_ci if (ret) 197862306a36Sopenharmony_ci return ret; 197962306a36Sopenharmony_ci break; 198062306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426: 198162306a36Sopenharmony_ci ret = spmi_regulator_init_slew_rate_ftsmps426(vreg, 198262306a36Sopenharmony_ci SPMI_FTSMPS426_CLOCK_RATE); 198362306a36Sopenharmony_ci if (ret) 198462306a36Sopenharmony_ci return ret; 198562306a36Sopenharmony_ci break; 198662306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_HFS430: 198762306a36Sopenharmony_ci ret = spmi_regulator_init_slew_rate_ftsmps426(vreg, 198862306a36Sopenharmony_ci SPMI_HFS430_CLOCK_RATE); 198962306a36Sopenharmony_ci if (ret) 199062306a36Sopenharmony_ci return ret; 199162306a36Sopenharmony_ci break; 199262306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_HFSMPS: 199362306a36Sopenharmony_ci case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS3: 199462306a36Sopenharmony_ci ret = spmi_regulator_init_slew_rate_hfsmps(vreg); 199562306a36Sopenharmony_ci if (ret) 199662306a36Sopenharmony_ci return ret; 199762306a36Sopenharmony_ci break; 199862306a36Sopenharmony_ci default: 199962306a36Sopenharmony_ci break; 200062306a36Sopenharmony_ci } 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci if (vreg->logical_type != SPMI_REGULATOR_LOGICAL_TYPE_VS) 200362306a36Sopenharmony_ci vreg->ocp_irq = 0; 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci if (vreg->ocp_irq) { 200662306a36Sopenharmony_ci ret = devm_request_irq(dev, vreg->ocp_irq, 200762306a36Sopenharmony_ci spmi_regulator_vs_ocp_isr, IRQF_TRIGGER_RISING, "ocp", 200862306a36Sopenharmony_ci vreg); 200962306a36Sopenharmony_ci if (ret < 0) { 201062306a36Sopenharmony_ci dev_err(dev, "failed to request irq %d, ret=%d\n", 201162306a36Sopenharmony_ci vreg->ocp_irq, ret); 201262306a36Sopenharmony_ci return ret; 201362306a36Sopenharmony_ci } 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci ret = devm_delayed_work_autocancel(dev, &vreg->ocp_work, 201662306a36Sopenharmony_ci spmi_regulator_vs_ocp_work); 201762306a36Sopenharmony_ci if (ret) 201862306a36Sopenharmony_ci return ret; 201962306a36Sopenharmony_ci } 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_ci return 0; 202262306a36Sopenharmony_ci} 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_cistatic const struct spmi_regulator_data pm6125_regulators[] = { 202562306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1" }, 202662306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2" }, 202762306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3" }, 202862306a36Sopenharmony_ci { "s4", 0x1d00, "vdd_s4" }, 202962306a36Sopenharmony_ci { "s5", 0x2000, "vdd_s5" }, 203062306a36Sopenharmony_ci { "s6", 0x2300, "vdd_s6" }, 203162306a36Sopenharmony_ci { "s7", 0x2600, "vdd_s7" }, 203262306a36Sopenharmony_ci { "s8", 0x2900, "vdd_s8" }, 203362306a36Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l7_l17_l18" }, 203462306a36Sopenharmony_ci { "l2", 0x4100, "vdd_l2_l3_l4" }, 203562306a36Sopenharmony_ci { "l3", 0x4200, "vdd_l2_l3_l4" }, 203662306a36Sopenharmony_ci { "l4", 0x4300, "vdd_l2_l3_l4" }, 203762306a36Sopenharmony_ci { "l5", 0x4400, "vdd_l5_l15_l19_l20_l21_l22" }, 203862306a36Sopenharmony_ci { "l6", 0x4500, "vdd_l6_l8" }, 203962306a36Sopenharmony_ci { "l7", 0x4600, "vdd_l1_l7_l17_l18" }, 204062306a36Sopenharmony_ci { "l8", 0x4700, "vdd_l6_l8" }, 204162306a36Sopenharmony_ci { "l9", 0x4800, "vdd_l9_l11" }, 204262306a36Sopenharmony_ci { "l10", 0x4900, "vdd_l10_l13_l14" }, 204362306a36Sopenharmony_ci { "l11", 0x4a00, "vdd_l9_l11" }, 204462306a36Sopenharmony_ci { "l12", 0x4b00, "vdd_l12_l16" }, 204562306a36Sopenharmony_ci { "l13", 0x4c00, "vdd_l10_l13_l14" }, 204662306a36Sopenharmony_ci { "l14", 0x4d00, "vdd_l10_l13_l14" }, 204762306a36Sopenharmony_ci { "l15", 0x4e00, "vdd_l5_l15_l19_l20_l21_l22" }, 204862306a36Sopenharmony_ci { "l16", 0x4f00, "vdd_l12_l16" }, 204962306a36Sopenharmony_ci { "l17", 0x5000, "vdd_l1_l7_l17_l18" }, 205062306a36Sopenharmony_ci { "l18", 0x5100, "vdd_l1_l7_l17_l18" }, 205162306a36Sopenharmony_ci { "l19", 0x5200, "vdd_l5_l15_l19_l20_l21_l22" }, 205262306a36Sopenharmony_ci { "l20", 0x5300, "vdd_l5_l15_l19_l20_l21_l22" }, 205362306a36Sopenharmony_ci { "l21", 0x5400, "vdd_l5_l15_l19_l20_l21_l22" }, 205462306a36Sopenharmony_ci { "l22", 0x5500, "vdd_l5_l15_l19_l20_l21_l22" }, 205562306a36Sopenharmony_ci { "l23", 0x5600, "vdd_l23_l24" }, 205662306a36Sopenharmony_ci { "l24", 0x5700, "vdd_l23_l24" }, 205762306a36Sopenharmony_ci}; 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_cistatic const struct spmi_regulator_data pm660_regulators[] = { 206062306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 206162306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 206262306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 206362306a36Sopenharmony_ci { "s4", 0x1d00, "vdd_s3", }, 206462306a36Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 206562306a36Sopenharmony_ci { "s6", 0x2300, "vdd_s6", }, 206662306a36Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l6_l7", }, 206762306a36Sopenharmony_ci { "l2", 0x4100, "vdd_l2_l3", }, 206862306a36Sopenharmony_ci { "l3", 0x4200, "vdd_l2_l3", }, 206962306a36Sopenharmony_ci /* l4 is unaccessible on PM660 */ 207062306a36Sopenharmony_ci { "l5", 0x4400, "vdd_l5", }, 207162306a36Sopenharmony_ci { "l6", 0x4500, "vdd_l1_l6_l7", }, 207262306a36Sopenharmony_ci { "l7", 0x4600, "vdd_l1_l6_l7", }, 207362306a36Sopenharmony_ci { "l8", 0x4700, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 207462306a36Sopenharmony_ci { "l9", 0x4800, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 207562306a36Sopenharmony_ci { "l10", 0x4900, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 207662306a36Sopenharmony_ci { "l11", 0x4a00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 207762306a36Sopenharmony_ci { "l12", 0x4b00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 207862306a36Sopenharmony_ci { "l13", 0x4c00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 207962306a36Sopenharmony_ci { "l14", 0x4d00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, 208062306a36Sopenharmony_ci { "l15", 0x4e00, "vdd_l15_l16_l17_l18_l19", }, 208162306a36Sopenharmony_ci { "l16", 0x4f00, "vdd_l15_l16_l17_l18_l19", }, 208262306a36Sopenharmony_ci { "l17", 0x5000, "vdd_l15_l16_l17_l18_l19", }, 208362306a36Sopenharmony_ci { "l18", 0x5100, "vdd_l15_l16_l17_l18_l19", }, 208462306a36Sopenharmony_ci { "l19", 0x5200, "vdd_l15_l16_l17_l18_l19", }, 208562306a36Sopenharmony_ci { } 208662306a36Sopenharmony_ci}; 208762306a36Sopenharmony_ci 208862306a36Sopenharmony_cistatic const struct spmi_regulator_data pm660l_regulators[] = { 208962306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 209062306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 209162306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 209262306a36Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 209362306a36Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 209462306a36Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l9_l10", }, 209562306a36Sopenharmony_ci { "l2", 0x4100, "vdd_l2", }, 209662306a36Sopenharmony_ci { "l3", 0x4200, "vdd_l3_l5_l7_l8", }, 209762306a36Sopenharmony_ci { "l4", 0x4300, "vdd_l4_l6", }, 209862306a36Sopenharmony_ci { "l5", 0x4400, "vdd_l3_l5_l7_l8", }, 209962306a36Sopenharmony_ci { "l6", 0x4500, "vdd_l4_l6", }, 210062306a36Sopenharmony_ci { "l7", 0x4600, "vdd_l3_l5_l7_l8", }, 210162306a36Sopenharmony_ci { "l8", 0x4700, "vdd_l3_l5_l7_l8", }, 210262306a36Sopenharmony_ci { "l9", 0x4800, "vdd_l1_l9_l10", }, 210362306a36Sopenharmony_ci { "l10", 0x4900, "vdd_l1_l9_l10", }, 210462306a36Sopenharmony_ci { } 210562306a36Sopenharmony_ci}; 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_cistatic const struct spmi_regulator_data pm8004_regulators[] = { 210862306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 210962306a36Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 211062306a36Sopenharmony_ci { } 211162306a36Sopenharmony_ci}; 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_cistatic const struct spmi_regulator_data pm8005_regulators[] = { 211462306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 211562306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 211662306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 211762306a36Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 211862306a36Sopenharmony_ci { } 211962306a36Sopenharmony_ci}; 212062306a36Sopenharmony_ci 212162306a36Sopenharmony_cistatic const struct spmi_regulator_data pm8226_regulators[] = { 212262306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 212362306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 212462306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 212562306a36Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 212662306a36Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 212762306a36Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l2_l4_l5", }, 212862306a36Sopenharmony_ci { "l2", 0x4100, "vdd_l1_l2_l4_l5", }, 212962306a36Sopenharmony_ci { "l3", 0x4200, "vdd_l3_l24_l26", }, 213062306a36Sopenharmony_ci { "l4", 0x4300, "vdd_l1_l2_l4_l5", }, 213162306a36Sopenharmony_ci { "l5", 0x4400, "vdd_l1_l2_l4_l5", }, 213262306a36Sopenharmony_ci { "l6", 0x4500, "vdd_l6_l7_l8_l9_l27", }, 213362306a36Sopenharmony_ci { "l7", 0x4600, "vdd_l6_l7_l8_l9_l27", }, 213462306a36Sopenharmony_ci { "l8", 0x4700, "vdd_l6_l7_l8_l9_l27", }, 213562306a36Sopenharmony_ci { "l9", 0x4800, "vdd_l6_l7_l8_l9_l27", }, 213662306a36Sopenharmony_ci { "l10", 0x4900, "vdd_l10_l11_l13", }, 213762306a36Sopenharmony_ci { "l11", 0x4a00, "vdd_l10_l11_l13", }, 213862306a36Sopenharmony_ci { "l12", 0x4b00, "vdd_l12_l14", }, 213962306a36Sopenharmony_ci { "l13", 0x4c00, "vdd_l10_l11_l13", }, 214062306a36Sopenharmony_ci { "l14", 0x4d00, "vdd_l12_l14", }, 214162306a36Sopenharmony_ci { "l15", 0x4e00, "vdd_l15_l16_l17_l18", }, 214262306a36Sopenharmony_ci { "l16", 0x4f00, "vdd_l15_l16_l17_l18", }, 214362306a36Sopenharmony_ci { "l17", 0x5000, "vdd_l15_l16_l17_l18", }, 214462306a36Sopenharmony_ci { "l18", 0x5100, "vdd_l15_l16_l17_l18", }, 214562306a36Sopenharmony_ci { "l19", 0x5200, "vdd_l19_l20_l21_l22_l23_l28", }, 214662306a36Sopenharmony_ci { "l20", 0x5300, "vdd_l19_l20_l21_l22_l23_l28", }, 214762306a36Sopenharmony_ci { "l21", 0x5400, "vdd_l19_l20_l21_l22_l23_l28", }, 214862306a36Sopenharmony_ci { "l22", 0x5500, "vdd_l19_l20_l21_l22_l23_l28", }, 214962306a36Sopenharmony_ci { "l23", 0x5600, "vdd_l19_l20_l21_l22_l23_l28", }, 215062306a36Sopenharmony_ci { "l24", 0x5700, "vdd_l3_l24_l26", }, 215162306a36Sopenharmony_ci { "l25", 0x5800, "vdd_l25", }, 215262306a36Sopenharmony_ci { "l26", 0x5900, "vdd_l3_l24_l26", }, 215362306a36Sopenharmony_ci { "l27", 0x5a00, "vdd_l6_l7_l8_l9_l27", }, 215462306a36Sopenharmony_ci { "l28", 0x5b00, "vdd_l19_l20_l21_l22_l23_l28", }, 215562306a36Sopenharmony_ci { "lvs1", 0x8000, "vdd_lvs1", }, 215662306a36Sopenharmony_ci { } 215762306a36Sopenharmony_ci}; 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_cistatic const struct spmi_regulator_data pm8841_regulators[] = { 216062306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 216162306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", NULL, 0x1c08 }, 216262306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 216362306a36Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", NULL, 0x1c08 }, 216462306a36Sopenharmony_ci { "s5", 0x2000, "vdd_s5", NULL, 0x1c08 }, 216562306a36Sopenharmony_ci { "s6", 0x2300, "vdd_s6", NULL, 0x1c08 }, 216662306a36Sopenharmony_ci { "s7", 0x2600, "vdd_s7", NULL, 0x1c08 }, 216762306a36Sopenharmony_ci { "s8", 0x2900, "vdd_s8", NULL, 0x1c08 }, 216862306a36Sopenharmony_ci { } 216962306a36Sopenharmony_ci}; 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_cistatic const struct spmi_regulator_data pm8916_regulators[] = { 217262306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 217362306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 217462306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 217562306a36Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 217662306a36Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l3", }, 217762306a36Sopenharmony_ci { "l2", 0x4100, "vdd_l2", }, 217862306a36Sopenharmony_ci { "l3", 0x4200, "vdd_l1_l3", }, 217962306a36Sopenharmony_ci { "l4", 0x4300, "vdd_l4_l5_l6", }, 218062306a36Sopenharmony_ci { "l5", 0x4400, "vdd_l4_l5_l6", }, 218162306a36Sopenharmony_ci { "l6", 0x4500, "vdd_l4_l5_l6", }, 218262306a36Sopenharmony_ci { "l7", 0x4600, "vdd_l7", }, 218362306a36Sopenharmony_ci { "l8", 0x4700, "vdd_l8_l11_l14_l15_l16", }, 218462306a36Sopenharmony_ci { "l9", 0x4800, "vdd_l9_l10_l12_l13_l17_l18", }, 218562306a36Sopenharmony_ci { "l10", 0x4900, "vdd_l9_l10_l12_l13_l17_l18", }, 218662306a36Sopenharmony_ci { "l11", 0x4a00, "vdd_l8_l11_l14_l15_l16", }, 218762306a36Sopenharmony_ci { "l12", 0x4b00, "vdd_l9_l10_l12_l13_l17_l18", }, 218862306a36Sopenharmony_ci { "l13", 0x4c00, "vdd_l9_l10_l12_l13_l17_l18", }, 218962306a36Sopenharmony_ci { "l14", 0x4d00, "vdd_l8_l11_l14_l15_l16", }, 219062306a36Sopenharmony_ci { "l15", 0x4e00, "vdd_l8_l11_l14_l15_l16", }, 219162306a36Sopenharmony_ci { "l16", 0x4f00, "vdd_l8_l11_l14_l15_l16", }, 219262306a36Sopenharmony_ci { "l17", 0x5000, "vdd_l9_l10_l12_l13_l17_l18", }, 219362306a36Sopenharmony_ci { "l18", 0x5100, "vdd_l9_l10_l12_l13_l17_l18", }, 219462306a36Sopenharmony_ci { } 219562306a36Sopenharmony_ci}; 219662306a36Sopenharmony_ci 219762306a36Sopenharmony_cistatic const struct spmi_regulator_data pm8941_regulators[] = { 219862306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 219962306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 220062306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 220162306a36Sopenharmony_ci { "s4", 0xa000, }, 220262306a36Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l3", }, 220362306a36Sopenharmony_ci { "l2", 0x4100, "vdd_l2_lvs_1_2_3", }, 220462306a36Sopenharmony_ci { "l3", 0x4200, "vdd_l1_l3", }, 220562306a36Sopenharmony_ci { "l4", 0x4300, "vdd_l4_l11", }, 220662306a36Sopenharmony_ci { "l5", 0x4400, "vdd_l5_l7", NULL, 0x0410 }, 220762306a36Sopenharmony_ci { "l6", 0x4500, "vdd_l6_l12_l14_l15", }, 220862306a36Sopenharmony_ci { "l7", 0x4600, "vdd_l5_l7", NULL, 0x0410 }, 220962306a36Sopenharmony_ci { "l8", 0x4700, "vdd_l8_l16_l18_19", }, 221062306a36Sopenharmony_ci { "l9", 0x4800, "vdd_l9_l10_l17_l22", }, 221162306a36Sopenharmony_ci { "l10", 0x4900, "vdd_l9_l10_l17_l22", }, 221262306a36Sopenharmony_ci { "l11", 0x4a00, "vdd_l4_l11", }, 221362306a36Sopenharmony_ci { "l12", 0x4b00, "vdd_l6_l12_l14_l15", }, 221462306a36Sopenharmony_ci { "l13", 0x4c00, "vdd_l13_l20_l23_l24", }, 221562306a36Sopenharmony_ci { "l14", 0x4d00, "vdd_l6_l12_l14_l15", }, 221662306a36Sopenharmony_ci { "l15", 0x4e00, "vdd_l6_l12_l14_l15", }, 221762306a36Sopenharmony_ci { "l16", 0x4f00, "vdd_l8_l16_l18_19", }, 221862306a36Sopenharmony_ci { "l17", 0x5000, "vdd_l9_l10_l17_l22", }, 221962306a36Sopenharmony_ci { "l18", 0x5100, "vdd_l8_l16_l18_19", }, 222062306a36Sopenharmony_ci { "l19", 0x5200, "vdd_l8_l16_l18_19", }, 222162306a36Sopenharmony_ci { "l20", 0x5300, "vdd_l13_l20_l23_l24", }, 222262306a36Sopenharmony_ci { "l21", 0x5400, "vdd_l21", }, 222362306a36Sopenharmony_ci { "l22", 0x5500, "vdd_l9_l10_l17_l22", }, 222462306a36Sopenharmony_ci { "l23", 0x5600, "vdd_l13_l20_l23_l24", }, 222562306a36Sopenharmony_ci { "l24", 0x5700, "vdd_l13_l20_l23_l24", }, 222662306a36Sopenharmony_ci { "lvs1", 0x8000, "vdd_l2_lvs_1_2_3", }, 222762306a36Sopenharmony_ci { "lvs2", 0x8100, "vdd_l2_lvs_1_2_3", }, 222862306a36Sopenharmony_ci { "lvs3", 0x8200, "vdd_l2_lvs_1_2_3", }, 222962306a36Sopenharmony_ci { "5vs1", 0x8300, "vin_5vs", "ocp-5vs1", }, 223062306a36Sopenharmony_ci { "5vs2", 0x8400, "vin_5vs", "ocp-5vs2", }, 223162306a36Sopenharmony_ci { } 223262306a36Sopenharmony_ci}; 223362306a36Sopenharmony_ci 223462306a36Sopenharmony_cistatic const struct spmi_regulator_data pm8950_regulators[] = { 223562306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 223662306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 223762306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 223862306a36Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 223962306a36Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 224062306a36Sopenharmony_ci { "s6", 0x2300, "vdd_s6", }, 224162306a36Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l19", }, 224262306a36Sopenharmony_ci { "l2", 0x4100, "vdd_l2_l23", }, 224362306a36Sopenharmony_ci { "l3", 0x4200, "vdd_l3", }, 224462306a36Sopenharmony_ci { "l4", 0x4300, "vdd_l4_l5_l6_l7_l16", }, 224562306a36Sopenharmony_ci { "l5", 0x4400, "vdd_l4_l5_l6_l7_l16", }, 224662306a36Sopenharmony_ci { "l6", 0x4500, "vdd_l4_l5_l6_l7_l16", }, 224762306a36Sopenharmony_ci { "l7", 0x4600, "vdd_l4_l5_l6_l7_l16", }, 224862306a36Sopenharmony_ci { "l8", 0x4700, "vdd_l8_l11_l12_l17_l22", }, 224962306a36Sopenharmony_ci { "l9", 0x4800, "vdd_l9_l10_l13_l14_l15_l18", }, 225062306a36Sopenharmony_ci { "l10", 0x4900, "vdd_l9_l10_l13_l14_l15_l18", }, 225162306a36Sopenharmony_ci { "l11", 0x4a00, "vdd_l8_l11_l12_l17_l22", }, 225262306a36Sopenharmony_ci { "l12", 0x4b00, "vdd_l8_l11_l12_l17_l22", }, 225362306a36Sopenharmony_ci { "l13", 0x4c00, "vdd_l9_l10_l13_l14_l15_l18", }, 225462306a36Sopenharmony_ci { "l14", 0x4d00, "vdd_l9_l10_l13_l14_l15_l18", }, 225562306a36Sopenharmony_ci { "l15", 0x4e00, "vdd_l9_l10_l13_l14_l15_l18", }, 225662306a36Sopenharmony_ci { "l16", 0x4f00, "vdd_l4_l5_l6_l7_l16", }, 225762306a36Sopenharmony_ci { "l17", 0x5000, "vdd_l8_l11_l12_l17_l22", }, 225862306a36Sopenharmony_ci { "l18", 0x5100, "vdd_l9_l10_l13_l14_l15_l18", }, 225962306a36Sopenharmony_ci { "l19", 0x5200, "vdd_l1_l19", }, 226062306a36Sopenharmony_ci { "l20", 0x5300, "vdd_l20", }, 226162306a36Sopenharmony_ci { "l21", 0x5400, "vdd_l21", }, 226262306a36Sopenharmony_ci { "l22", 0x5500, "vdd_l8_l11_l12_l17_l22", }, 226362306a36Sopenharmony_ci { "l23", 0x5600, "vdd_l2_l23", }, 226462306a36Sopenharmony_ci { } 226562306a36Sopenharmony_ci}; 226662306a36Sopenharmony_ci 226762306a36Sopenharmony_cistatic const struct spmi_regulator_data pm8994_regulators[] = { 226862306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 226962306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 227062306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 227162306a36Sopenharmony_ci { "s4", 0x1d00, "vdd_s4", }, 227262306a36Sopenharmony_ci { "s5", 0x2000, "vdd_s5", }, 227362306a36Sopenharmony_ci { "s6", 0x2300, "vdd_s6", }, 227462306a36Sopenharmony_ci { "s7", 0x2600, "vdd_s7", }, 227562306a36Sopenharmony_ci { "s8", 0x2900, "vdd_s8", }, 227662306a36Sopenharmony_ci { "s9", 0x2c00, "vdd_s9", }, 227762306a36Sopenharmony_ci { "s10", 0x2f00, "vdd_s10", }, 227862306a36Sopenharmony_ci { "s11", 0x3200, "vdd_s11", }, 227962306a36Sopenharmony_ci { "s12", 0x3500, "vdd_s12", }, 228062306a36Sopenharmony_ci { "l1", 0x4000, "vdd_l1", }, 228162306a36Sopenharmony_ci { "l2", 0x4100, "vdd_l2_l26_l28", }, 228262306a36Sopenharmony_ci { "l3", 0x4200, "vdd_l3_l11", }, 228362306a36Sopenharmony_ci { "l4", 0x4300, "vdd_l4_l27_l31", }, 228462306a36Sopenharmony_ci { "l5", 0x4400, "vdd_l5_l7", }, 228562306a36Sopenharmony_ci { "l6", 0x4500, "vdd_l6_l12_l32", }, 228662306a36Sopenharmony_ci { "l7", 0x4600, "vdd_l5_l7", }, 228762306a36Sopenharmony_ci { "l8", 0x4700, "vdd_l8_l16_l30", }, 228862306a36Sopenharmony_ci { "l9", 0x4800, "vdd_l9_l10_l18_l22", }, 228962306a36Sopenharmony_ci { "l10", 0x4900, "vdd_l9_l10_l18_l22", }, 229062306a36Sopenharmony_ci { "l11", 0x4a00, "vdd_l3_l11", }, 229162306a36Sopenharmony_ci { "l12", 0x4b00, "vdd_l6_l12_l32", }, 229262306a36Sopenharmony_ci { "l13", 0x4c00, "vdd_l13_l19_l23_l24", }, 229362306a36Sopenharmony_ci { "l14", 0x4d00, "vdd_l14_l15", }, 229462306a36Sopenharmony_ci { "l15", 0x4e00, "vdd_l14_l15", }, 229562306a36Sopenharmony_ci { "l16", 0x4f00, "vdd_l8_l16_l30", }, 229662306a36Sopenharmony_ci { "l17", 0x5000, "vdd_l17_l29", }, 229762306a36Sopenharmony_ci { "l18", 0x5100, "vdd_l9_l10_l18_l22", }, 229862306a36Sopenharmony_ci { "l19", 0x5200, "vdd_l13_l19_l23_l24", }, 229962306a36Sopenharmony_ci { "l20", 0x5300, "vdd_l20_l21", }, 230062306a36Sopenharmony_ci { "l21", 0x5400, "vdd_l20_l21", }, 230162306a36Sopenharmony_ci { "l22", 0x5500, "vdd_l9_l10_l18_l22", }, 230262306a36Sopenharmony_ci { "l23", 0x5600, "vdd_l13_l19_l23_l24", }, 230362306a36Sopenharmony_ci { "l24", 0x5700, "vdd_l13_l19_l23_l24", }, 230462306a36Sopenharmony_ci { "l25", 0x5800, "vdd_l25", }, 230562306a36Sopenharmony_ci { "l26", 0x5900, "vdd_l2_l26_l28", }, 230662306a36Sopenharmony_ci { "l27", 0x5a00, "vdd_l4_l27_l31", }, 230762306a36Sopenharmony_ci { "l28", 0x5b00, "vdd_l2_l26_l28", }, 230862306a36Sopenharmony_ci { "l29", 0x5c00, "vdd_l17_l29", }, 230962306a36Sopenharmony_ci { "l30", 0x5d00, "vdd_l8_l16_l30", }, 231062306a36Sopenharmony_ci { "l31", 0x5e00, "vdd_l4_l27_l31", }, 231162306a36Sopenharmony_ci { "l32", 0x5f00, "vdd_l6_l12_l32", }, 231262306a36Sopenharmony_ci { "lvs1", 0x8000, "vdd_lvs_1_2", }, 231362306a36Sopenharmony_ci { "lvs2", 0x8100, "vdd_lvs_1_2", }, 231462306a36Sopenharmony_ci { } 231562306a36Sopenharmony_ci}; 231662306a36Sopenharmony_ci 231762306a36Sopenharmony_cistatic const struct spmi_regulator_data pmi8994_regulators[] = { 231862306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1", }, 231962306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2", }, 232062306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3", }, 232162306a36Sopenharmony_ci { "l1", 0x4000, "vdd_l1", }, 232262306a36Sopenharmony_ci { } 232362306a36Sopenharmony_ci}; 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_cistatic const struct spmi_regulator_data pmp8074_regulators[] = { 232662306a36Sopenharmony_ci { "s1", 0x1400, "vdd_s1"}, 232762306a36Sopenharmony_ci { "s2", 0x1700, "vdd_s2"}, 232862306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3"}, 232962306a36Sopenharmony_ci { "s4", 0x1d00, "vdd_s4"}, 233062306a36Sopenharmony_ci { "s5", 0x2000, "vdd_s5"}, 233162306a36Sopenharmony_ci { "l1", 0x4000, "vdd_l1_l2"}, 233262306a36Sopenharmony_ci { "l2", 0x4100, "vdd_l1_l2"}, 233362306a36Sopenharmony_ci { "l3", 0x4200, "vdd_l3_l8"}, 233462306a36Sopenharmony_ci { "l4", 0x4300, "vdd_l4"}, 233562306a36Sopenharmony_ci { "l5", 0x4400, "vdd_l5_l6_l15"}, 233662306a36Sopenharmony_ci { "l6", 0x4500, "vdd_l5_l6_l15"}, 233762306a36Sopenharmony_ci { "l7", 0x4600, "vdd_l7"}, 233862306a36Sopenharmony_ci { "l8", 0x4700, "vdd_l3_l8"}, 233962306a36Sopenharmony_ci { "l9", 0x4800, "vdd_l9"}, 234062306a36Sopenharmony_ci /* l10 is currently unsupported HT_P50 */ 234162306a36Sopenharmony_ci { "l11", 0x4a00, "vdd_l10_l11_l12_l13"}, 234262306a36Sopenharmony_ci { "l12", 0x4b00, "vdd_l10_l11_l12_l13"}, 234362306a36Sopenharmony_ci { "l13", 0x4c00, "vdd_l10_l11_l12_l13"}, 234462306a36Sopenharmony_ci { } 234562306a36Sopenharmony_ci}; 234662306a36Sopenharmony_ci 234762306a36Sopenharmony_cistatic const struct spmi_regulator_data pms405_regulators[] = { 234862306a36Sopenharmony_ci { "s3", 0x1a00, "vdd_s3"}, 234962306a36Sopenharmony_ci { } 235062306a36Sopenharmony_ci}; 235162306a36Sopenharmony_ci 235262306a36Sopenharmony_cistatic const struct of_device_id qcom_spmi_regulator_match[] = { 235362306a36Sopenharmony_ci { .compatible = "qcom,pm6125-regulators", .data = &pm6125_regulators }, 235462306a36Sopenharmony_ci { .compatible = "qcom,pm660-regulators", .data = &pm660_regulators }, 235562306a36Sopenharmony_ci { .compatible = "qcom,pm660l-regulators", .data = &pm660l_regulators }, 235662306a36Sopenharmony_ci { .compatible = "qcom,pm8004-regulators", .data = &pm8004_regulators }, 235762306a36Sopenharmony_ci { .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators }, 235862306a36Sopenharmony_ci { .compatible = "qcom,pm8226-regulators", .data = &pm8226_regulators }, 235962306a36Sopenharmony_ci { .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators }, 236062306a36Sopenharmony_ci { .compatible = "qcom,pm8916-regulators", .data = &pm8916_regulators }, 236162306a36Sopenharmony_ci { .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators }, 236262306a36Sopenharmony_ci { .compatible = "qcom,pm8950-regulators", .data = &pm8950_regulators }, 236362306a36Sopenharmony_ci { .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators }, 236462306a36Sopenharmony_ci { .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators }, 236562306a36Sopenharmony_ci { .compatible = "qcom,pmp8074-regulators", .data = &pmp8074_regulators }, 236662306a36Sopenharmony_ci { .compatible = "qcom,pms405-regulators", .data = &pms405_regulators }, 236762306a36Sopenharmony_ci { } 236862306a36Sopenharmony_ci}; 236962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, qcom_spmi_regulator_match); 237062306a36Sopenharmony_ci 237162306a36Sopenharmony_cistatic int qcom_spmi_regulator_probe(struct platform_device *pdev) 237262306a36Sopenharmony_ci{ 237362306a36Sopenharmony_ci const struct spmi_regulator_data *reg; 237462306a36Sopenharmony_ci const struct spmi_voltage_range *range; 237562306a36Sopenharmony_ci const struct of_device_id *match; 237662306a36Sopenharmony_ci struct regulator_config config = { }; 237762306a36Sopenharmony_ci struct regulator_dev *rdev; 237862306a36Sopenharmony_ci struct spmi_regulator *vreg; 237962306a36Sopenharmony_ci struct regmap *regmap; 238062306a36Sopenharmony_ci const char *name; 238162306a36Sopenharmony_ci struct device *dev = &pdev->dev; 238262306a36Sopenharmony_ci struct device_node *node = pdev->dev.of_node; 238362306a36Sopenharmony_ci struct device_node *syscon, *reg_node; 238462306a36Sopenharmony_ci struct property *reg_prop; 238562306a36Sopenharmony_ci int ret, lenp; 238662306a36Sopenharmony_ci struct list_head *vreg_list; 238762306a36Sopenharmony_ci 238862306a36Sopenharmony_ci vreg_list = devm_kzalloc(dev, sizeof(*vreg_list), GFP_KERNEL); 238962306a36Sopenharmony_ci if (!vreg_list) 239062306a36Sopenharmony_ci return -ENOMEM; 239162306a36Sopenharmony_ci INIT_LIST_HEAD(vreg_list); 239262306a36Sopenharmony_ci platform_set_drvdata(pdev, vreg_list); 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_ci regmap = dev_get_regmap(dev->parent, NULL); 239562306a36Sopenharmony_ci if (!regmap) 239662306a36Sopenharmony_ci return -ENODEV; 239762306a36Sopenharmony_ci 239862306a36Sopenharmony_ci match = of_match_device(qcom_spmi_regulator_match, &pdev->dev); 239962306a36Sopenharmony_ci if (!match) 240062306a36Sopenharmony_ci return -ENODEV; 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci if (of_find_property(node, "qcom,saw-reg", &lenp)) { 240362306a36Sopenharmony_ci syscon = of_parse_phandle(node, "qcom,saw-reg", 0); 240462306a36Sopenharmony_ci saw_regmap = syscon_node_to_regmap(syscon); 240562306a36Sopenharmony_ci of_node_put(syscon); 240662306a36Sopenharmony_ci if (IS_ERR(saw_regmap)) 240762306a36Sopenharmony_ci dev_err(dev, "ERROR reading SAW regmap\n"); 240862306a36Sopenharmony_ci } 240962306a36Sopenharmony_ci 241062306a36Sopenharmony_ci for (reg = match->data; reg->name; reg++) { 241162306a36Sopenharmony_ci 241262306a36Sopenharmony_ci if (saw_regmap) { 241362306a36Sopenharmony_ci reg_node = of_get_child_by_name(node, reg->name); 241462306a36Sopenharmony_ci reg_prop = of_find_property(reg_node, "qcom,saw-slave", 241562306a36Sopenharmony_ci &lenp); 241662306a36Sopenharmony_ci of_node_put(reg_node); 241762306a36Sopenharmony_ci if (reg_prop) 241862306a36Sopenharmony_ci continue; 241962306a36Sopenharmony_ci } 242062306a36Sopenharmony_ci 242162306a36Sopenharmony_ci vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); 242262306a36Sopenharmony_ci if (!vreg) 242362306a36Sopenharmony_ci return -ENOMEM; 242462306a36Sopenharmony_ci 242562306a36Sopenharmony_ci vreg->dev = dev; 242662306a36Sopenharmony_ci vreg->base = reg->base; 242762306a36Sopenharmony_ci vreg->regmap = regmap; 242862306a36Sopenharmony_ci if (reg->ocp) { 242962306a36Sopenharmony_ci vreg->ocp_irq = platform_get_irq_byname(pdev, reg->ocp); 243062306a36Sopenharmony_ci if (vreg->ocp_irq < 0) 243162306a36Sopenharmony_ci return vreg->ocp_irq; 243262306a36Sopenharmony_ci } 243362306a36Sopenharmony_ci vreg->desc.id = -1; 243462306a36Sopenharmony_ci vreg->desc.owner = THIS_MODULE; 243562306a36Sopenharmony_ci vreg->desc.type = REGULATOR_VOLTAGE; 243662306a36Sopenharmony_ci vreg->desc.enable_reg = reg->base + SPMI_COMMON_REG_ENABLE; 243762306a36Sopenharmony_ci vreg->desc.enable_mask = SPMI_COMMON_ENABLE_MASK; 243862306a36Sopenharmony_ci vreg->desc.enable_val = SPMI_COMMON_ENABLE; 243962306a36Sopenharmony_ci vreg->desc.name = name = reg->name; 244062306a36Sopenharmony_ci vreg->desc.supply_name = reg->supply; 244162306a36Sopenharmony_ci vreg->desc.of_match = reg->name; 244262306a36Sopenharmony_ci vreg->desc.of_parse_cb = spmi_regulator_of_parse; 244362306a36Sopenharmony_ci vreg->desc.of_map_mode = spmi_regulator_of_map_mode; 244462306a36Sopenharmony_ci 244562306a36Sopenharmony_ci ret = spmi_regulator_match(vreg, reg->force_type); 244662306a36Sopenharmony_ci if (ret) 244762306a36Sopenharmony_ci continue; 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci if (saw_regmap) { 245062306a36Sopenharmony_ci reg_node = of_get_child_by_name(node, reg->name); 245162306a36Sopenharmony_ci reg_prop = of_find_property(reg_node, "qcom,saw-leader", 245262306a36Sopenharmony_ci &lenp); 245362306a36Sopenharmony_ci of_node_put(reg_node); 245462306a36Sopenharmony_ci if (reg_prop) { 245562306a36Sopenharmony_ci spmi_saw_ops = *(vreg->desc.ops); 245662306a36Sopenharmony_ci spmi_saw_ops.set_voltage_sel = 245762306a36Sopenharmony_ci spmi_regulator_saw_set_voltage; 245862306a36Sopenharmony_ci vreg->desc.ops = &spmi_saw_ops; 245962306a36Sopenharmony_ci } 246062306a36Sopenharmony_ci } 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_ci if (vreg->set_points && vreg->set_points->count == 1) { 246362306a36Sopenharmony_ci /* since there is only one range */ 246462306a36Sopenharmony_ci range = vreg->set_points->range; 246562306a36Sopenharmony_ci vreg->desc.uV_step = range->step_uV; 246662306a36Sopenharmony_ci } 246762306a36Sopenharmony_ci 246862306a36Sopenharmony_ci config.dev = dev; 246962306a36Sopenharmony_ci config.driver_data = vreg; 247062306a36Sopenharmony_ci config.regmap = regmap; 247162306a36Sopenharmony_ci rdev = devm_regulator_register(dev, &vreg->desc, &config); 247262306a36Sopenharmony_ci if (IS_ERR(rdev)) { 247362306a36Sopenharmony_ci dev_err(dev, "failed to register %s\n", name); 247462306a36Sopenharmony_ci return PTR_ERR(rdev); 247562306a36Sopenharmony_ci } 247662306a36Sopenharmony_ci 247762306a36Sopenharmony_ci INIT_LIST_HEAD(&vreg->node); 247862306a36Sopenharmony_ci list_add(&vreg->node, vreg_list); 247962306a36Sopenharmony_ci } 248062306a36Sopenharmony_ci 248162306a36Sopenharmony_ci return 0; 248262306a36Sopenharmony_ci} 248362306a36Sopenharmony_ci 248462306a36Sopenharmony_cistatic struct platform_driver qcom_spmi_regulator_driver = { 248562306a36Sopenharmony_ci .driver = { 248662306a36Sopenharmony_ci .name = "qcom-spmi-regulator", 248762306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 248862306a36Sopenharmony_ci .of_match_table = qcom_spmi_regulator_match, 248962306a36Sopenharmony_ci }, 249062306a36Sopenharmony_ci .probe = qcom_spmi_regulator_probe, 249162306a36Sopenharmony_ci}; 249262306a36Sopenharmony_cimodule_platform_driver(qcom_spmi_regulator_driver); 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_ciMODULE_DESCRIPTION("Qualcomm SPMI PMIC regulator driver"); 249562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 249662306a36Sopenharmony_ciMODULE_ALIAS("platform:qcom-spmi-regulator"); 2497