18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// tps80031-regulator.c -- TI TPS80031 regulator driver. 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// Regulator driver for TI TPS80031/TPS80032 Fully Integrated Power 68c2ecf20Sopenharmony_ci// Management with Power Path and Battery Charger. 78c2ecf20Sopenharmony_ci// 88c2ecf20Sopenharmony_ci// Copyright (c) 2012, NVIDIA Corporation. 98c2ecf20Sopenharmony_ci// 108c2ecf20Sopenharmony_ci// Author: Laxman Dewangan <ldewangan@nvidia.com> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/delay.h> 138c2ecf20Sopenharmony_ci#include <linux/err.h> 148c2ecf20Sopenharmony_ci#include <linux/init.h> 158c2ecf20Sopenharmony_ci#include <linux/kernel.h> 168c2ecf20Sopenharmony_ci#include <linux/mfd/tps80031.h> 178c2ecf20Sopenharmony_ci#include <linux/module.h> 188c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 198c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h> 208c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h> 218c2ecf20Sopenharmony_ci#include <linux/slab.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* Flags for DCDC Voltage reading */ 248c2ecf20Sopenharmony_ci#define DCDC_OFFSET_EN BIT(0) 258c2ecf20Sopenharmony_ci#define DCDC_EXTENDED_EN BIT(1) 268c2ecf20Sopenharmony_ci#define TRACK_MODE_ENABLE BIT(2) 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define SMPS_MULTOFFSET_VIO BIT(1) 298c2ecf20Sopenharmony_ci#define SMPS_MULTOFFSET_SMPS1 BIT(3) 308c2ecf20Sopenharmony_ci#define SMPS_MULTOFFSET_SMPS2 BIT(4) 318c2ecf20Sopenharmony_ci#define SMPS_MULTOFFSET_SMPS3 BIT(6) 328c2ecf20Sopenharmony_ci#define SMPS_MULTOFFSET_SMPS4 BIT(0) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define SMPS_CMD_MASK 0xC0 358c2ecf20Sopenharmony_ci#define SMPS_VSEL_MASK 0x3F 368c2ecf20Sopenharmony_ci#define LDO_VSEL_MASK 0x1F 378c2ecf20Sopenharmony_ci#define LDO_TRACK_VSEL_MASK 0x3F 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define MISC2_LDOUSB_IN_VSYS BIT(4) 408c2ecf20Sopenharmony_ci#define MISC2_LDOUSB_IN_PMID BIT(3) 418c2ecf20Sopenharmony_ci#define MISC2_LDOUSB_IN_MASK 0x18 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define MISC2_LDO3_SEL_VIB_VAL BIT(0) 448c2ecf20Sopenharmony_ci#define MISC2_LDO3_SEL_VIB_MASK 0x1 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define BOOST_HW_PWR_EN BIT(5) 478c2ecf20Sopenharmony_ci#define BOOST_HW_PWR_EN_MASK BIT(5) 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#define OPA_MODE_EN BIT(6) 508c2ecf20Sopenharmony_ci#define OPA_MODE_EN_MASK BIT(6) 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define USB_VBUS_CTRL_SET 0x04 538c2ecf20Sopenharmony_ci#define USB_VBUS_CTRL_CLR 0x05 548c2ecf20Sopenharmony_ci#define VBUS_DISCHRG 0x20 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistruct tps80031_regulator_info { 578c2ecf20Sopenharmony_ci /* Regulator register address.*/ 588c2ecf20Sopenharmony_ci u8 trans_reg; 598c2ecf20Sopenharmony_ci u8 state_reg; 608c2ecf20Sopenharmony_ci u8 force_reg; 618c2ecf20Sopenharmony_ci u8 volt_reg; 628c2ecf20Sopenharmony_ci u8 volt_id; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci /*Power request bits */ 658c2ecf20Sopenharmony_ci int preq_bit; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* used by regulator core */ 688c2ecf20Sopenharmony_ci struct regulator_desc desc; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistruct tps80031_regulator { 738c2ecf20Sopenharmony_ci struct device *dev; 748c2ecf20Sopenharmony_ci struct tps80031_regulator_info *rinfo; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci u8 device_flags; 778c2ecf20Sopenharmony_ci unsigned int config_flags; 788c2ecf20Sopenharmony_ci unsigned int ext_ctrl_flag; 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic inline struct device *to_tps80031_dev(struct regulator_dev *rdev) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci return rdev_get_dev(rdev)->parent->parent; 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic int tps80031_reg_is_enabled(struct regulator_dev *rdev) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 898c2ecf20Sopenharmony_ci struct device *parent = to_tps80031_dev(rdev); 908c2ecf20Sopenharmony_ci u8 reg_val; 918c2ecf20Sopenharmony_ci int ret; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ) 948c2ecf20Sopenharmony_ci return true; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci ret = tps80031_read(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg, 978c2ecf20Sopenharmony_ci ®_val); 988c2ecf20Sopenharmony_ci if (ret < 0) { 998c2ecf20Sopenharmony_ci dev_err(&rdev->dev, "Reg 0x%02x read failed, err = %d\n", 1008c2ecf20Sopenharmony_ci ri->rinfo->state_reg, ret); 1018c2ecf20Sopenharmony_ci return ret; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci return (reg_val & TPS80031_STATE_MASK) == TPS80031_STATE_ON; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic int tps80031_reg_enable(struct regulator_dev *rdev) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 1098c2ecf20Sopenharmony_ci struct device *parent = to_tps80031_dev(rdev); 1108c2ecf20Sopenharmony_ci int ret; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ) 1138c2ecf20Sopenharmony_ci return 0; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg, 1168c2ecf20Sopenharmony_ci TPS80031_STATE_ON, TPS80031_STATE_MASK); 1178c2ecf20Sopenharmony_ci if (ret < 0) { 1188c2ecf20Sopenharmony_ci dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n", 1198c2ecf20Sopenharmony_ci ri->rinfo->state_reg, ret); 1208c2ecf20Sopenharmony_ci return ret; 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci return ret; 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic int tps80031_reg_disable(struct regulator_dev *rdev) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 1288c2ecf20Sopenharmony_ci struct device *parent = to_tps80031_dev(rdev); 1298c2ecf20Sopenharmony_ci int ret; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ) 1328c2ecf20Sopenharmony_ci return 0; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg, 1358c2ecf20Sopenharmony_ci TPS80031_STATE_OFF, TPS80031_STATE_MASK); 1368c2ecf20Sopenharmony_ci if (ret < 0) 1378c2ecf20Sopenharmony_ci dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n", 1388c2ecf20Sopenharmony_ci ri->rinfo->state_reg, ret); 1398c2ecf20Sopenharmony_ci return ret; 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci/* DCDC voltages for the selector of 58 to 63 */ 1438c2ecf20Sopenharmony_cistatic const int tps80031_dcdc_voltages[4][5] = { 1448c2ecf20Sopenharmony_ci { 1350, 1500, 1800, 1900, 2100}, 1458c2ecf20Sopenharmony_ci { 1350, 1500, 1800, 1900, 2100}, 1468c2ecf20Sopenharmony_ci { 2084, 2315, 2778, 2932, 3241}, 1478c2ecf20Sopenharmony_ci { 4167, 2315, 2778, 2932, 3241}, 1488c2ecf20Sopenharmony_ci}; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic int tps80031_dcdc_list_voltage(struct regulator_dev *rdev, unsigned sel) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 1538c2ecf20Sopenharmony_ci int volt_index = ri->device_flags & 0x3; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci if (sel == 0) 1568c2ecf20Sopenharmony_ci return 0; 1578c2ecf20Sopenharmony_ci else if (sel < 58) 1588c2ecf20Sopenharmony_ci return regulator_list_voltage_linear(rdev, sel - 1); 1598c2ecf20Sopenharmony_ci else 1608c2ecf20Sopenharmony_ci return tps80031_dcdc_voltages[volt_index][sel - 58] * 1000; 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic int tps80031_dcdc_set_voltage_sel(struct regulator_dev *rdev, 1648c2ecf20Sopenharmony_ci unsigned vsel) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 1678c2ecf20Sopenharmony_ci struct device *parent = to_tps80031_dev(rdev); 1688c2ecf20Sopenharmony_ci int ret; 1698c2ecf20Sopenharmony_ci u8 reg_val; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci if (ri->rinfo->force_reg) { 1728c2ecf20Sopenharmony_ci ret = tps80031_read(parent, ri->rinfo->volt_id, 1738c2ecf20Sopenharmony_ci ri->rinfo->force_reg, ®_val); 1748c2ecf20Sopenharmony_ci if (ret < 0) { 1758c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", 1768c2ecf20Sopenharmony_ci ri->rinfo->force_reg, ret); 1778c2ecf20Sopenharmony_ci return ret; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci if (!(reg_val & SMPS_CMD_MASK)) { 1808c2ecf20Sopenharmony_ci ret = tps80031_update(parent, ri->rinfo->volt_id, 1818c2ecf20Sopenharmony_ci ri->rinfo->force_reg, vsel, SMPS_VSEL_MASK); 1828c2ecf20Sopenharmony_ci if (ret < 0) 1838c2ecf20Sopenharmony_ci dev_err(ri->dev, 1848c2ecf20Sopenharmony_ci "reg 0x%02x update failed, e = %d\n", 1858c2ecf20Sopenharmony_ci ri->rinfo->force_reg, ret); 1868c2ecf20Sopenharmony_ci return ret; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci ret = tps80031_update(parent, ri->rinfo->volt_id, 1908c2ecf20Sopenharmony_ci ri->rinfo->volt_reg, vsel, SMPS_VSEL_MASK); 1918c2ecf20Sopenharmony_ci if (ret < 0) 1928c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x update failed, e = %d\n", 1938c2ecf20Sopenharmony_ci ri->rinfo->volt_reg, ret); 1948c2ecf20Sopenharmony_ci return ret; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int tps80031_dcdc_get_voltage_sel(struct regulator_dev *rdev) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 2008c2ecf20Sopenharmony_ci struct device *parent = to_tps80031_dev(rdev); 2018c2ecf20Sopenharmony_ci uint8_t vsel = 0; 2028c2ecf20Sopenharmony_ci int ret; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (ri->rinfo->force_reg) { 2058c2ecf20Sopenharmony_ci ret = tps80031_read(parent, ri->rinfo->volt_id, 2068c2ecf20Sopenharmony_ci ri->rinfo->force_reg, &vsel); 2078c2ecf20Sopenharmony_ci if (ret < 0) { 2088c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", 2098c2ecf20Sopenharmony_ci ri->rinfo->force_reg, ret); 2108c2ecf20Sopenharmony_ci return ret; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci if (!(vsel & SMPS_CMD_MASK)) 2148c2ecf20Sopenharmony_ci return vsel & SMPS_VSEL_MASK; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci ret = tps80031_read(parent, ri->rinfo->volt_id, 2178c2ecf20Sopenharmony_ci ri->rinfo->volt_reg, &vsel); 2188c2ecf20Sopenharmony_ci if (ret < 0) { 2198c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", 2208c2ecf20Sopenharmony_ci ri->rinfo->volt_reg, ret); 2218c2ecf20Sopenharmony_ci return ret; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci return vsel & SMPS_VSEL_MASK; 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic int tps80031_ldo_list_voltage(struct regulator_dev *rdev, 2278c2ecf20Sopenharmony_ci unsigned int sel) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 2308c2ecf20Sopenharmony_ci struct device *parent = to_tps80031_dev(rdev); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* Check for valid setting for TPS80031 or TPS80032-ES1.0 */ 2338c2ecf20Sopenharmony_ci if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) && 2348c2ecf20Sopenharmony_ci (ri->device_flags & TRACK_MODE_ENABLE)) { 2358c2ecf20Sopenharmony_ci unsigned nvsel = (sel) & 0x1F; 2368c2ecf20Sopenharmony_ci if (((tps80031_get_chip_info(parent) == TPS80031) || 2378c2ecf20Sopenharmony_ci ((tps80031_get_chip_info(parent) == TPS80032) && 2388c2ecf20Sopenharmony_ci (tps80031_get_pmu_version(parent) == 0x0))) && 2398c2ecf20Sopenharmony_ci ((nvsel == 0x0) || (nvsel >= 0x19 && nvsel <= 0x1F))) { 2408c2ecf20Sopenharmony_ci dev_err(ri->dev, 2418c2ecf20Sopenharmony_ci "Invalid sel %d in track mode LDO2\n", 2428c2ecf20Sopenharmony_ci nvsel); 2438c2ecf20Sopenharmony_ci return -EINVAL; 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci return regulator_list_voltage_linear(rdev, sel); 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic int tps80031_ldo_map_voltage(struct regulator_dev *rdev, 2518c2ecf20Sopenharmony_ci int min_uV, int max_uV) 2528c2ecf20Sopenharmony_ci{ 2538c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 2548c2ecf20Sopenharmony_ci struct device *parent = to_tps80031_dev(rdev); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* Check for valid setting for TPS80031 or TPS80032-ES1.0 */ 2578c2ecf20Sopenharmony_ci if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) && 2588c2ecf20Sopenharmony_ci (ri->device_flags & TRACK_MODE_ENABLE)) { 2598c2ecf20Sopenharmony_ci if (((tps80031_get_chip_info(parent) == TPS80031) || 2608c2ecf20Sopenharmony_ci ((tps80031_get_chip_info(parent) == TPS80032) && 2618c2ecf20Sopenharmony_ci (tps80031_get_pmu_version(parent) == 0x0)))) { 2628c2ecf20Sopenharmony_ci return regulator_map_voltage_iterate(rdev, min_uV, 2638c2ecf20Sopenharmony_ci max_uV); 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci return regulator_map_voltage_linear(rdev, min_uV, max_uV); 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic int tps80031_vbus_is_enabled(struct regulator_dev *rdev) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 2738c2ecf20Sopenharmony_ci struct device *parent = to_tps80031_dev(rdev); 2748c2ecf20Sopenharmony_ci int ret; 2758c2ecf20Sopenharmony_ci uint8_t ctrl1 = 0; 2768c2ecf20Sopenharmony_ci uint8_t ctrl3 = 0; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci ret = tps80031_read(parent, TPS80031_SLAVE_ID2, 2798c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL1, &ctrl1); 2808c2ecf20Sopenharmony_ci if (ret < 0) { 2818c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", 2828c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL1, ret); 2838c2ecf20Sopenharmony_ci return ret; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci ret = tps80031_read(parent, TPS80031_SLAVE_ID2, 2868c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL3, &ctrl3); 2878c2ecf20Sopenharmony_ci if (ret < 0) { 2888c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", 2898c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL3, ret); 2908c2ecf20Sopenharmony_ci return ret; 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci if ((ctrl1 & OPA_MODE_EN) && (ctrl3 & BOOST_HW_PWR_EN)) 2938c2ecf20Sopenharmony_ci return 1; 2948c2ecf20Sopenharmony_ci return ret; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic int tps80031_vbus_enable(struct regulator_dev *rdev) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 3008c2ecf20Sopenharmony_ci struct device *parent = to_tps80031_dev(rdev); 3018c2ecf20Sopenharmony_ci int ret; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2, 3048c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN); 3058c2ecf20Sopenharmony_ci if (ret < 0) { 3068c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", 3078c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL1, ret); 3088c2ecf20Sopenharmony_ci return ret; 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2, 3128c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN); 3138c2ecf20Sopenharmony_ci if (ret < 0) { 3148c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", 3158c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL3, ret); 3168c2ecf20Sopenharmony_ci return ret; 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci return ret; 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic int tps80031_vbus_disable(struct regulator_dev *rdev) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci struct tps80031_regulator *ri = rdev_get_drvdata(rdev); 3248c2ecf20Sopenharmony_ci struct device *parent = to_tps80031_dev(rdev); 3258c2ecf20Sopenharmony_ci int ret; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) { 3288c2ecf20Sopenharmony_ci ret = tps80031_write(parent, TPS80031_SLAVE_ID2, 3298c2ecf20Sopenharmony_ci USB_VBUS_CTRL_SET, VBUS_DISCHRG); 3308c2ecf20Sopenharmony_ci if (ret < 0) { 3318c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n", 3328c2ecf20Sopenharmony_ci USB_VBUS_CTRL_SET, ret); 3338c2ecf20Sopenharmony_ci return ret; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2, 3388c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN); 3398c2ecf20Sopenharmony_ci if (ret < 0) { 3408c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n", 3418c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL1, ret); 3428c2ecf20Sopenharmony_ci return ret; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2, 3468c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN); 3478c2ecf20Sopenharmony_ci if (ret < 0) { 3488c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n", 3498c2ecf20Sopenharmony_ci TPS80031_CHARGERUSB_CTRL3, ret); 3508c2ecf20Sopenharmony_ci return ret; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci mdelay(DIV_ROUND_UP(ri->rinfo->desc.enable_time, 1000)); 3548c2ecf20Sopenharmony_ci if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) { 3558c2ecf20Sopenharmony_ci ret = tps80031_write(parent, TPS80031_SLAVE_ID2, 3568c2ecf20Sopenharmony_ci USB_VBUS_CTRL_CLR, VBUS_DISCHRG); 3578c2ecf20Sopenharmony_ci if (ret < 0) { 3588c2ecf20Sopenharmony_ci dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n", 3598c2ecf20Sopenharmony_ci USB_VBUS_CTRL_CLR, ret); 3608c2ecf20Sopenharmony_ci return ret; 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci return ret; 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistatic const struct regulator_ops tps80031_dcdc_ops = { 3678c2ecf20Sopenharmony_ci .list_voltage = tps80031_dcdc_list_voltage, 3688c2ecf20Sopenharmony_ci .set_voltage_sel = tps80031_dcdc_set_voltage_sel, 3698c2ecf20Sopenharmony_ci .get_voltage_sel = tps80031_dcdc_get_voltage_sel, 3708c2ecf20Sopenharmony_ci .enable = tps80031_reg_enable, 3718c2ecf20Sopenharmony_ci .disable = tps80031_reg_disable, 3728c2ecf20Sopenharmony_ci .is_enabled = tps80031_reg_is_enabled, 3738c2ecf20Sopenharmony_ci}; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic const struct regulator_ops tps80031_ldo_ops = { 3768c2ecf20Sopenharmony_ci .list_voltage = tps80031_ldo_list_voltage, 3778c2ecf20Sopenharmony_ci .map_voltage = tps80031_ldo_map_voltage, 3788c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 3798c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 3808c2ecf20Sopenharmony_ci .enable = tps80031_reg_enable, 3818c2ecf20Sopenharmony_ci .disable = tps80031_reg_disable, 3828c2ecf20Sopenharmony_ci .is_enabled = tps80031_reg_is_enabled, 3838c2ecf20Sopenharmony_ci}; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cistatic const struct regulator_ops tps80031_vbus_sw_ops = { 3868c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 3878c2ecf20Sopenharmony_ci .enable = tps80031_vbus_enable, 3888c2ecf20Sopenharmony_ci .disable = tps80031_vbus_disable, 3898c2ecf20Sopenharmony_ci .is_enabled = tps80031_vbus_is_enabled, 3908c2ecf20Sopenharmony_ci}; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic const struct regulator_ops tps80031_vbus_hw_ops = { 3938c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 3948c2ecf20Sopenharmony_ci}; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cistatic const struct regulator_ops tps80031_ext_reg_ops = { 3978c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 3988c2ecf20Sopenharmony_ci .enable = tps80031_reg_enable, 3998c2ecf20Sopenharmony_ci .disable = tps80031_reg_disable, 4008c2ecf20Sopenharmony_ci .is_enabled = tps80031_reg_is_enabled, 4018c2ecf20Sopenharmony_ci}; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci/* Non-exiting default definition for some register */ 4048c2ecf20Sopenharmony_ci#define TPS80031_SMPS3_CFG_FORCE 0 4058c2ecf20Sopenharmony_ci#define TPS80031_SMPS4_CFG_FORCE 0 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci#define TPS80031_VBUS_CFG_TRANS 0 4088c2ecf20Sopenharmony_ci#define TPS80031_VBUS_CFG_STATE 0 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci#define TPS80031_REG_SMPS(_id, _volt_id, _pbit) \ 4118c2ecf20Sopenharmony_ci{ \ 4128c2ecf20Sopenharmony_ci .trans_reg = TPS80031_##_id##_CFG_TRANS, \ 4138c2ecf20Sopenharmony_ci .state_reg = TPS80031_##_id##_CFG_STATE, \ 4148c2ecf20Sopenharmony_ci .force_reg = TPS80031_##_id##_CFG_FORCE, \ 4158c2ecf20Sopenharmony_ci .volt_reg = TPS80031_##_id##_CFG_VOLTAGE, \ 4168c2ecf20Sopenharmony_ci .volt_id = TPS80031_SLAVE_##_volt_id, \ 4178c2ecf20Sopenharmony_ci .preq_bit = _pbit, \ 4188c2ecf20Sopenharmony_ci .desc = { \ 4198c2ecf20Sopenharmony_ci .name = "tps80031_"#_id, \ 4208c2ecf20Sopenharmony_ci .id = TPS80031_REGULATOR_##_id, \ 4218c2ecf20Sopenharmony_ci .n_voltages = 63, \ 4228c2ecf20Sopenharmony_ci .ops = &tps80031_dcdc_ops, \ 4238c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 4248c2ecf20Sopenharmony_ci .owner = THIS_MODULE, \ 4258c2ecf20Sopenharmony_ci .enable_time = 500, \ 4268c2ecf20Sopenharmony_ci }, \ 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci#define TPS80031_REG_LDO(_id, _preq_bit) \ 4308c2ecf20Sopenharmony_ci{ \ 4318c2ecf20Sopenharmony_ci .trans_reg = TPS80031_##_id##_CFG_TRANS, \ 4328c2ecf20Sopenharmony_ci .state_reg = TPS80031_##_id##_CFG_STATE, \ 4338c2ecf20Sopenharmony_ci .volt_reg = TPS80031_##_id##_CFG_VOLTAGE, \ 4348c2ecf20Sopenharmony_ci .volt_id = TPS80031_SLAVE_ID1, \ 4358c2ecf20Sopenharmony_ci .preq_bit = _preq_bit, \ 4368c2ecf20Sopenharmony_ci .desc = { \ 4378c2ecf20Sopenharmony_ci .owner = THIS_MODULE, \ 4388c2ecf20Sopenharmony_ci .name = "tps80031_"#_id, \ 4398c2ecf20Sopenharmony_ci .id = TPS80031_REGULATOR_##_id, \ 4408c2ecf20Sopenharmony_ci .ops = &tps80031_ldo_ops, \ 4418c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 4428c2ecf20Sopenharmony_ci .min_uV = 1000000, \ 4438c2ecf20Sopenharmony_ci .uV_step = 100000, \ 4448c2ecf20Sopenharmony_ci .linear_min_sel = 1, \ 4458c2ecf20Sopenharmony_ci .n_voltages = 25, \ 4468c2ecf20Sopenharmony_ci .vsel_reg = TPS80031_##_id##_CFG_VOLTAGE, \ 4478c2ecf20Sopenharmony_ci .vsel_mask = LDO_VSEL_MASK, \ 4488c2ecf20Sopenharmony_ci .enable_time = 500, \ 4498c2ecf20Sopenharmony_ci }, \ 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci#define TPS80031_REG_FIXED(_id, max_mV, _ops, _delay, _pbit) \ 4538c2ecf20Sopenharmony_ci{ \ 4548c2ecf20Sopenharmony_ci .trans_reg = TPS80031_##_id##_CFG_TRANS, \ 4558c2ecf20Sopenharmony_ci .state_reg = TPS80031_##_id##_CFG_STATE, \ 4568c2ecf20Sopenharmony_ci .volt_id = TPS80031_SLAVE_ID1, \ 4578c2ecf20Sopenharmony_ci .preq_bit = _pbit, \ 4588c2ecf20Sopenharmony_ci .desc = { \ 4598c2ecf20Sopenharmony_ci .name = "tps80031_"#_id, \ 4608c2ecf20Sopenharmony_ci .id = TPS80031_REGULATOR_##_id, \ 4618c2ecf20Sopenharmony_ci .min_uV = max_mV * 1000, \ 4628c2ecf20Sopenharmony_ci .n_voltages = 1, \ 4638c2ecf20Sopenharmony_ci .ops = &_ops, \ 4648c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 4658c2ecf20Sopenharmony_ci .owner = THIS_MODULE, \ 4668c2ecf20Sopenharmony_ci .enable_time = _delay, \ 4678c2ecf20Sopenharmony_ci }, \ 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_cistatic struct tps80031_regulator_info tps80031_rinfo[TPS80031_REGULATOR_MAX] = { 4718c2ecf20Sopenharmony_ci TPS80031_REG_SMPS(VIO, ID0, 4), 4728c2ecf20Sopenharmony_ci TPS80031_REG_SMPS(SMPS1, ID0, 0), 4738c2ecf20Sopenharmony_ci TPS80031_REG_SMPS(SMPS2, ID0, 1), 4748c2ecf20Sopenharmony_ci TPS80031_REG_SMPS(SMPS3, ID1, 2), 4758c2ecf20Sopenharmony_ci TPS80031_REG_SMPS(SMPS4, ID1, 3), 4768c2ecf20Sopenharmony_ci TPS80031_REG_LDO(VANA, -1), 4778c2ecf20Sopenharmony_ci TPS80031_REG_LDO(LDO1, 8), 4788c2ecf20Sopenharmony_ci TPS80031_REG_LDO(LDO2, 9), 4798c2ecf20Sopenharmony_ci TPS80031_REG_LDO(LDO3, 10), 4808c2ecf20Sopenharmony_ci TPS80031_REG_LDO(LDO4, 11), 4818c2ecf20Sopenharmony_ci TPS80031_REG_LDO(LDO5, 12), 4828c2ecf20Sopenharmony_ci TPS80031_REG_LDO(LDO6, 13), 4838c2ecf20Sopenharmony_ci TPS80031_REG_LDO(LDO7, 14), 4848c2ecf20Sopenharmony_ci TPS80031_REG_LDO(LDOLN, 15), 4858c2ecf20Sopenharmony_ci TPS80031_REG_LDO(LDOUSB, 5), 4868c2ecf20Sopenharmony_ci TPS80031_REG_FIXED(VBUS, 5000, tps80031_vbus_hw_ops, 100000, -1), 4878c2ecf20Sopenharmony_ci TPS80031_REG_FIXED(REGEN1, 3300, tps80031_ext_reg_ops, 0, 16), 4888c2ecf20Sopenharmony_ci TPS80031_REG_FIXED(REGEN2, 3300, tps80031_ext_reg_ops, 0, 17), 4898c2ecf20Sopenharmony_ci TPS80031_REG_FIXED(SYSEN, 3300, tps80031_ext_reg_ops, 0, 18), 4908c2ecf20Sopenharmony_ci}; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_cistatic int tps80031_power_req_config(struct device *parent, 4938c2ecf20Sopenharmony_ci struct tps80031_regulator *ri, 4948c2ecf20Sopenharmony_ci struct tps80031_regulator_platform_data *tps80031_pdata) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci int ret = 0; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci if (ri->rinfo->preq_bit < 0) 4998c2ecf20Sopenharmony_ci goto skip_pwr_req_config; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag, 5028c2ecf20Sopenharmony_ci ri->rinfo->preq_bit, ri->rinfo->state_reg, 5038c2ecf20Sopenharmony_ci ri->rinfo->trans_reg); 5048c2ecf20Sopenharmony_ci if (ret < 0) { 5058c2ecf20Sopenharmony_ci dev_err(ri->dev, "ext powerreq config failed, err = %d\n", ret); 5068c2ecf20Sopenharmony_ci return ret; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ciskip_pwr_req_config: 5108c2ecf20Sopenharmony_ci if (tps80031_pdata->ext_ctrl_flag & TPS80031_PWR_ON_ON_SLEEP) { 5118c2ecf20Sopenharmony_ci ret = tps80031_update(parent, TPS80031_SLAVE_ID1, 5128c2ecf20Sopenharmony_ci ri->rinfo->trans_reg, TPS80031_TRANS_SLEEP_ON, 5138c2ecf20Sopenharmony_ci TPS80031_TRANS_SLEEP_MASK); 5148c2ecf20Sopenharmony_ci if (ret < 0) { 5158c2ecf20Sopenharmony_ci dev_err(ri->dev, "Reg 0x%02x update failed, e %d\n", 5168c2ecf20Sopenharmony_ci ri->rinfo->trans_reg, ret); 5178c2ecf20Sopenharmony_ci return ret; 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci return ret; 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_cistatic int tps80031_regulator_config(struct device *parent, 5248c2ecf20Sopenharmony_ci struct tps80031_regulator *ri, 5258c2ecf20Sopenharmony_ci struct tps80031_regulator_platform_data *tps80031_pdata) 5268c2ecf20Sopenharmony_ci{ 5278c2ecf20Sopenharmony_ci int ret = 0; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci switch (ri->rinfo->desc.id) { 5308c2ecf20Sopenharmony_ci case TPS80031_REGULATOR_LDOUSB: 5318c2ecf20Sopenharmony_ci if (ri->config_flags & (TPS80031_USBLDO_INPUT_VSYS | 5328c2ecf20Sopenharmony_ci TPS80031_USBLDO_INPUT_PMID)) { 5338c2ecf20Sopenharmony_ci unsigned val; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci if (ri->config_flags & TPS80031_USBLDO_INPUT_VSYS) 5368c2ecf20Sopenharmony_ci val = MISC2_LDOUSB_IN_VSYS; 5378c2ecf20Sopenharmony_ci else 5388c2ecf20Sopenharmony_ci val = MISC2_LDOUSB_IN_PMID; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci ret = tps80031_update(parent, TPS80031_SLAVE_ID1, 5418c2ecf20Sopenharmony_ci TPS80031_MISC2, val, 5428c2ecf20Sopenharmony_ci MISC2_LDOUSB_IN_MASK); 5438c2ecf20Sopenharmony_ci if (ret < 0) { 5448c2ecf20Sopenharmony_ci dev_err(ri->dev, 5458c2ecf20Sopenharmony_ci "LDOUSB config failed, e= %d\n", ret); 5468c2ecf20Sopenharmony_ci return ret; 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci break; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci case TPS80031_REGULATOR_LDO3: 5528c2ecf20Sopenharmony_ci if (ri->config_flags & TPS80031_LDO3_OUTPUT_VIB) { 5538c2ecf20Sopenharmony_ci ret = tps80031_update(parent, TPS80031_SLAVE_ID1, 5548c2ecf20Sopenharmony_ci TPS80031_MISC2, MISC2_LDO3_SEL_VIB_VAL, 5558c2ecf20Sopenharmony_ci MISC2_LDO3_SEL_VIB_MASK); 5568c2ecf20Sopenharmony_ci if (ret < 0) { 5578c2ecf20Sopenharmony_ci dev_err(ri->dev, 5588c2ecf20Sopenharmony_ci "LDO3 config failed, e = %d\n", ret); 5598c2ecf20Sopenharmony_ci return ret; 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci break; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci case TPS80031_REGULATOR_VBUS: 5658c2ecf20Sopenharmony_ci /* Provide SW control Ops if VBUS is SW control */ 5668c2ecf20Sopenharmony_ci if (!(ri->config_flags & TPS80031_VBUS_SW_ONLY)) 5678c2ecf20Sopenharmony_ci ri->rinfo->desc.ops = &tps80031_vbus_sw_ops; 5688c2ecf20Sopenharmony_ci break; 5698c2ecf20Sopenharmony_ci default: 5708c2ecf20Sopenharmony_ci break; 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci /* Configure Active state to ON, SLEEP to OFF and OFF_state to OFF */ 5748c2ecf20Sopenharmony_ci ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->trans_reg, 5758c2ecf20Sopenharmony_ci TPS80031_TRANS_ACTIVE_ON | TPS80031_TRANS_SLEEP_OFF | 5768c2ecf20Sopenharmony_ci TPS80031_TRANS_OFF_OFF, TPS80031_TRANS_ACTIVE_MASK | 5778c2ecf20Sopenharmony_ci TPS80031_TRANS_SLEEP_MASK | TPS80031_TRANS_OFF_MASK); 5788c2ecf20Sopenharmony_ci if (ret < 0) { 5798c2ecf20Sopenharmony_ci dev_err(ri->dev, "trans reg update failed, e %d\n", ret); 5808c2ecf20Sopenharmony_ci return ret; 5818c2ecf20Sopenharmony_ci } 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci return ret; 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic int check_smps_mode_mult(struct device *parent, 5878c2ecf20Sopenharmony_ci struct tps80031_regulator *ri) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci int mult_offset; 5908c2ecf20Sopenharmony_ci int ret; 5918c2ecf20Sopenharmony_ci u8 smps_offset; 5928c2ecf20Sopenharmony_ci u8 smps_mult; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci ret = tps80031_read(parent, TPS80031_SLAVE_ID1, 5958c2ecf20Sopenharmony_ci TPS80031_SMPS_OFFSET, &smps_offset); 5968c2ecf20Sopenharmony_ci if (ret < 0) { 5978c2ecf20Sopenharmony_ci dev_err(parent, "Error in reading smps offset register\n"); 5988c2ecf20Sopenharmony_ci return ret; 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci ret = tps80031_read(parent, TPS80031_SLAVE_ID1, 6028c2ecf20Sopenharmony_ci TPS80031_SMPS_MULT, &smps_mult); 6038c2ecf20Sopenharmony_ci if (ret < 0) { 6048c2ecf20Sopenharmony_ci dev_err(parent, "Error in reading smps mult register\n"); 6058c2ecf20Sopenharmony_ci return ret; 6068c2ecf20Sopenharmony_ci } 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci switch (ri->rinfo->desc.id) { 6098c2ecf20Sopenharmony_ci case TPS80031_REGULATOR_VIO: 6108c2ecf20Sopenharmony_ci mult_offset = SMPS_MULTOFFSET_VIO; 6118c2ecf20Sopenharmony_ci break; 6128c2ecf20Sopenharmony_ci case TPS80031_REGULATOR_SMPS1: 6138c2ecf20Sopenharmony_ci mult_offset = SMPS_MULTOFFSET_SMPS1; 6148c2ecf20Sopenharmony_ci break; 6158c2ecf20Sopenharmony_ci case TPS80031_REGULATOR_SMPS2: 6168c2ecf20Sopenharmony_ci mult_offset = SMPS_MULTOFFSET_SMPS2; 6178c2ecf20Sopenharmony_ci break; 6188c2ecf20Sopenharmony_ci case TPS80031_REGULATOR_SMPS3: 6198c2ecf20Sopenharmony_ci mult_offset = SMPS_MULTOFFSET_SMPS3; 6208c2ecf20Sopenharmony_ci break; 6218c2ecf20Sopenharmony_ci case TPS80031_REGULATOR_SMPS4: 6228c2ecf20Sopenharmony_ci mult_offset = SMPS_MULTOFFSET_SMPS4; 6238c2ecf20Sopenharmony_ci break; 6248c2ecf20Sopenharmony_ci case TPS80031_REGULATOR_LDO2: 6258c2ecf20Sopenharmony_ci ri->device_flags = smps_mult & BIT(5) ? TRACK_MODE_ENABLE : 0; 6268c2ecf20Sopenharmony_ci /* TRACK mode the ldo2 varies from 600mV to 1300mV */ 6278c2ecf20Sopenharmony_ci if (ri->device_flags & TRACK_MODE_ENABLE) { 6288c2ecf20Sopenharmony_ci ri->rinfo->desc.min_uV = 600000; 6298c2ecf20Sopenharmony_ci ri->rinfo->desc.uV_step = 12500; 6308c2ecf20Sopenharmony_ci ri->rinfo->desc.n_voltages = 57; 6318c2ecf20Sopenharmony_ci ri->rinfo->desc.vsel_mask = LDO_TRACK_VSEL_MASK; 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci return 0; 6348c2ecf20Sopenharmony_ci default: 6358c2ecf20Sopenharmony_ci return 0; 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci ri->device_flags = (smps_offset & mult_offset) ? DCDC_OFFSET_EN : 0; 6398c2ecf20Sopenharmony_ci ri->device_flags |= (smps_mult & mult_offset) ? DCDC_EXTENDED_EN : 0; 6408c2ecf20Sopenharmony_ci switch (ri->device_flags) { 6418c2ecf20Sopenharmony_ci case 0: 6428c2ecf20Sopenharmony_ci ri->rinfo->desc.min_uV = 607700; 6438c2ecf20Sopenharmony_ci ri->rinfo->desc.uV_step = 12660; 6448c2ecf20Sopenharmony_ci break; 6458c2ecf20Sopenharmony_ci case DCDC_OFFSET_EN: 6468c2ecf20Sopenharmony_ci ri->rinfo->desc.min_uV = 700000; 6478c2ecf20Sopenharmony_ci ri->rinfo->desc.uV_step = 12500; 6488c2ecf20Sopenharmony_ci break; 6498c2ecf20Sopenharmony_ci case DCDC_EXTENDED_EN: 6508c2ecf20Sopenharmony_ci ri->rinfo->desc.min_uV = 1852000; 6518c2ecf20Sopenharmony_ci ri->rinfo->desc.uV_step = 38600; 6528c2ecf20Sopenharmony_ci break; 6538c2ecf20Sopenharmony_ci case DCDC_OFFSET_EN | DCDC_EXTENDED_EN: 6548c2ecf20Sopenharmony_ci ri->rinfo->desc.min_uV = 2161000; 6558c2ecf20Sopenharmony_ci ri->rinfo->desc.uV_step = 38600; 6568c2ecf20Sopenharmony_ci break; 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci return 0; 6598c2ecf20Sopenharmony_ci} 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_cistatic int tps80031_regulator_probe(struct platform_device *pdev) 6628c2ecf20Sopenharmony_ci{ 6638c2ecf20Sopenharmony_ci struct tps80031_platform_data *pdata; 6648c2ecf20Sopenharmony_ci struct tps80031_regulator_platform_data *tps_pdata; 6658c2ecf20Sopenharmony_ci struct tps80031_regulator *ri; 6668c2ecf20Sopenharmony_ci struct tps80031_regulator *pmic; 6678c2ecf20Sopenharmony_ci struct regulator_dev *rdev; 6688c2ecf20Sopenharmony_ci struct regulator_config config = { }; 6698c2ecf20Sopenharmony_ci struct tps80031 *tps80031_mfd = dev_get_drvdata(pdev->dev.parent); 6708c2ecf20Sopenharmony_ci int ret; 6718c2ecf20Sopenharmony_ci int num; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci pdata = dev_get_platdata(pdev->dev.parent); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci if (!pdata) { 6768c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "No platform data\n"); 6778c2ecf20Sopenharmony_ci return -EINVAL; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci pmic = devm_kcalloc(&pdev->dev, 6818c2ecf20Sopenharmony_ci TPS80031_REGULATOR_MAX, sizeof(*pmic), GFP_KERNEL); 6828c2ecf20Sopenharmony_ci if (!pmic) 6838c2ecf20Sopenharmony_ci return -ENOMEM; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) { 6868c2ecf20Sopenharmony_ci tps_pdata = pdata->regulator_pdata[num]; 6878c2ecf20Sopenharmony_ci ri = &pmic[num]; 6888c2ecf20Sopenharmony_ci ri->rinfo = &tps80031_rinfo[num]; 6898c2ecf20Sopenharmony_ci ri->dev = &pdev->dev; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci check_smps_mode_mult(pdev->dev.parent, ri); 6928c2ecf20Sopenharmony_ci config.dev = &pdev->dev; 6938c2ecf20Sopenharmony_ci config.init_data = NULL; 6948c2ecf20Sopenharmony_ci config.driver_data = ri; 6958c2ecf20Sopenharmony_ci config.regmap = tps80031_mfd->regmap[ri->rinfo->volt_id]; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci if (tps_pdata) { 6988c2ecf20Sopenharmony_ci config.init_data = tps_pdata->reg_init_data; 6998c2ecf20Sopenharmony_ci ri->config_flags = tps_pdata->config_flags; 7008c2ecf20Sopenharmony_ci ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag; 7018c2ecf20Sopenharmony_ci ret = tps80031_regulator_config(pdev->dev.parent, 7028c2ecf20Sopenharmony_ci ri, tps_pdata); 7038c2ecf20Sopenharmony_ci if (ret < 0) { 7048c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 7058c2ecf20Sopenharmony_ci "regulator config failed, e %d\n", ret); 7068c2ecf20Sopenharmony_ci return ret; 7078c2ecf20Sopenharmony_ci } 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci ret = tps80031_power_req_config(pdev->dev.parent, 7108c2ecf20Sopenharmony_ci ri, tps_pdata); 7118c2ecf20Sopenharmony_ci if (ret < 0) { 7128c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 7138c2ecf20Sopenharmony_ci "pwr_req config failed, err %d\n", ret); 7148c2ecf20Sopenharmony_ci return ret; 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci } 7178c2ecf20Sopenharmony_ci rdev = devm_regulator_register(&pdev->dev, &ri->rinfo->desc, 7188c2ecf20Sopenharmony_ci &config); 7198c2ecf20Sopenharmony_ci if (IS_ERR(rdev)) { 7208c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 7218c2ecf20Sopenharmony_ci "register regulator failed %s\n", 7228c2ecf20Sopenharmony_ci ri->rinfo->desc.name); 7238c2ecf20Sopenharmony_ci return PTR_ERR(rdev); 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci } 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, pmic); 7288c2ecf20Sopenharmony_ci return 0; 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_cistatic struct platform_driver tps80031_regulator_driver = { 7328c2ecf20Sopenharmony_ci .driver = { 7338c2ecf20Sopenharmony_ci .name = "tps80031-pmic", 7348c2ecf20Sopenharmony_ci }, 7358c2ecf20Sopenharmony_ci .probe = tps80031_regulator_probe, 7368c2ecf20Sopenharmony_ci}; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_cistatic int __init tps80031_regulator_init(void) 7398c2ecf20Sopenharmony_ci{ 7408c2ecf20Sopenharmony_ci return platform_driver_register(&tps80031_regulator_driver); 7418c2ecf20Sopenharmony_ci} 7428c2ecf20Sopenharmony_cisubsys_initcall(tps80031_regulator_init); 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_cistatic void __exit tps80031_regulator_exit(void) 7458c2ecf20Sopenharmony_ci{ 7468c2ecf20Sopenharmony_ci platform_driver_unregister(&tps80031_regulator_driver); 7478c2ecf20Sopenharmony_ci} 7488c2ecf20Sopenharmony_cimodule_exit(tps80031_regulator_exit); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:tps80031-regulator"); 7518c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Regulator Driver for TI TPS80031/TPS80032 PMIC"); 7528c2ecf20Sopenharmony_ciMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 7538c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 754