18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Voltage regulator support for AMS AS3722 PMIC 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2013 ams 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Florian Lobmaier <florian.lobmaier@ams.com> 88c2ecf20Sopenharmony_ci * Author: Laxman Dewangan <ldewangan@nvidia.com> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/err.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/mfd/as3722.h> 158c2ecf20Sopenharmony_ci#include <linux/of.h> 168c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 178c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 188c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h> 198c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h> 208c2ecf20Sopenharmony_ci#include <linux/regulator/of_regulator.h> 218c2ecf20Sopenharmony_ci#include <linux/slab.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* Regulator IDs */ 248c2ecf20Sopenharmony_cienum as3722_regulators_id { 258c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_SD0, 268c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_SD1, 278c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_SD2, 288c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_SD3, 298c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_SD4, 308c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_SD5, 318c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_SD6, 328c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO0, 338c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO1, 348c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO2, 358c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO3, 368c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO4, 378c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO5, 388c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO6, 398c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO7, 408c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO9, 418c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO10, 428c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_LDO11, 438c2ecf20Sopenharmony_ci AS3722_REGULATOR_ID_MAX, 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistruct as3722_register_mapping { 478c2ecf20Sopenharmony_ci u8 regulator_id; 488c2ecf20Sopenharmony_ci const char *name; 498c2ecf20Sopenharmony_ci const char *sname; 508c2ecf20Sopenharmony_ci u8 vsel_reg; 518c2ecf20Sopenharmony_ci u8 vsel_mask; 528c2ecf20Sopenharmony_ci int n_voltages; 538c2ecf20Sopenharmony_ci u32 enable_reg; 548c2ecf20Sopenharmony_ci u8 enable_mask; 558c2ecf20Sopenharmony_ci u32 control_reg; 568c2ecf20Sopenharmony_ci u8 mode_mask; 578c2ecf20Sopenharmony_ci u32 sleep_ctrl_reg; 588c2ecf20Sopenharmony_ci u8 sleep_ctrl_mask; 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistruct as3722_regulator_config_data { 628c2ecf20Sopenharmony_ci struct regulator_init_data *reg_init; 638c2ecf20Sopenharmony_ci bool enable_tracking; 648c2ecf20Sopenharmony_ci int ext_control; 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistruct as3722_regulators { 688c2ecf20Sopenharmony_ci struct device *dev; 698c2ecf20Sopenharmony_ci struct as3722 *as3722; 708c2ecf20Sopenharmony_ci struct regulator_desc desc[AS3722_REGULATOR_ID_MAX]; 718c2ecf20Sopenharmony_ci struct as3722_regulator_config_data 728c2ecf20Sopenharmony_ci reg_config_data[AS3722_REGULATOR_ID_MAX]; 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic const struct as3722_register_mapping as3722_reg_lookup[] = { 768c2ecf20Sopenharmony_ci { 778c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD0, 788c2ecf20Sopenharmony_ci .name = "as3722-sd0", 798c2ecf20Sopenharmony_ci .vsel_reg = AS3722_SD0_VOLTAGE_REG, 808c2ecf20Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 818c2ecf20Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 828c2ecf20Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(0), 838c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG, 848c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK, 858c2ecf20Sopenharmony_ci .control_reg = AS3722_SD0_CONTROL_REG, 868c2ecf20Sopenharmony_ci .mode_mask = AS3722_SD0_MODE_FAST, 878c2ecf20Sopenharmony_ci }, 888c2ecf20Sopenharmony_ci { 898c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD1, 908c2ecf20Sopenharmony_ci .name = "as3722-sd1", 918c2ecf20Sopenharmony_ci .vsel_reg = AS3722_SD1_VOLTAGE_REG, 928c2ecf20Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 938c2ecf20Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 948c2ecf20Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(1), 958c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG, 968c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK, 978c2ecf20Sopenharmony_ci .control_reg = AS3722_SD1_CONTROL_REG, 988c2ecf20Sopenharmony_ci .mode_mask = AS3722_SD1_MODE_FAST, 998c2ecf20Sopenharmony_ci }, 1008c2ecf20Sopenharmony_ci { 1018c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD2, 1028c2ecf20Sopenharmony_ci .name = "as3722-sd2", 1038c2ecf20Sopenharmony_ci .sname = "vsup-sd2", 1048c2ecf20Sopenharmony_ci .vsel_reg = AS3722_SD2_VOLTAGE_REG, 1058c2ecf20Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 1068c2ecf20Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 1078c2ecf20Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(2), 1088c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG, 1098c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD2_EXT_ENABLE_MASK, 1108c2ecf20Sopenharmony_ci .control_reg = AS3722_SD23_CONTROL_REG, 1118c2ecf20Sopenharmony_ci .mode_mask = AS3722_SD2_MODE_FAST, 1128c2ecf20Sopenharmony_ci .n_voltages = AS3722_SD2_VSEL_MAX + 1, 1138c2ecf20Sopenharmony_ci }, 1148c2ecf20Sopenharmony_ci { 1158c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD3, 1168c2ecf20Sopenharmony_ci .name = "as3722-sd3", 1178c2ecf20Sopenharmony_ci .sname = "vsup-sd3", 1188c2ecf20Sopenharmony_ci .vsel_reg = AS3722_SD3_VOLTAGE_REG, 1198c2ecf20Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 1208c2ecf20Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 1218c2ecf20Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(3), 1228c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG, 1238c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD3_EXT_ENABLE_MASK, 1248c2ecf20Sopenharmony_ci .control_reg = AS3722_SD23_CONTROL_REG, 1258c2ecf20Sopenharmony_ci .mode_mask = AS3722_SD3_MODE_FAST, 1268c2ecf20Sopenharmony_ci .n_voltages = AS3722_SD2_VSEL_MAX + 1, 1278c2ecf20Sopenharmony_ci }, 1288c2ecf20Sopenharmony_ci { 1298c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD4, 1308c2ecf20Sopenharmony_ci .name = "as3722-sd4", 1318c2ecf20Sopenharmony_ci .sname = "vsup-sd4", 1328c2ecf20Sopenharmony_ci .vsel_reg = AS3722_SD4_VOLTAGE_REG, 1338c2ecf20Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 1348c2ecf20Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 1358c2ecf20Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(4), 1368c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG, 1378c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD4_EXT_ENABLE_MASK, 1388c2ecf20Sopenharmony_ci .control_reg = AS3722_SD4_CONTROL_REG, 1398c2ecf20Sopenharmony_ci .mode_mask = AS3722_SD4_MODE_FAST, 1408c2ecf20Sopenharmony_ci .n_voltages = AS3722_SD2_VSEL_MAX + 1, 1418c2ecf20Sopenharmony_ci }, 1428c2ecf20Sopenharmony_ci { 1438c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD5, 1448c2ecf20Sopenharmony_ci .name = "as3722-sd5", 1458c2ecf20Sopenharmony_ci .sname = "vsup-sd5", 1468c2ecf20Sopenharmony_ci .vsel_reg = AS3722_SD5_VOLTAGE_REG, 1478c2ecf20Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 1488c2ecf20Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 1498c2ecf20Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(5), 1508c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG, 1518c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD5_EXT_ENABLE_MASK, 1528c2ecf20Sopenharmony_ci .control_reg = AS3722_SD5_CONTROL_REG, 1538c2ecf20Sopenharmony_ci .mode_mask = AS3722_SD5_MODE_FAST, 1548c2ecf20Sopenharmony_ci .n_voltages = AS3722_SD2_VSEL_MAX + 1, 1558c2ecf20Sopenharmony_ci }, 1568c2ecf20Sopenharmony_ci { 1578c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD6, 1588c2ecf20Sopenharmony_ci .name = "as3722-sd6", 1598c2ecf20Sopenharmony_ci .vsel_reg = AS3722_SD6_VOLTAGE_REG, 1608c2ecf20Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 1618c2ecf20Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 1628c2ecf20Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(6), 1638c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG, 1648c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK, 1658c2ecf20Sopenharmony_ci .control_reg = AS3722_SD6_CONTROL_REG, 1668c2ecf20Sopenharmony_ci .mode_mask = AS3722_SD6_MODE_FAST, 1678c2ecf20Sopenharmony_ci }, 1688c2ecf20Sopenharmony_ci { 1698c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO0, 1708c2ecf20Sopenharmony_ci .name = "as3722-ldo0", 1718c2ecf20Sopenharmony_ci .sname = "vin-ldo0", 1728c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO0_VOLTAGE_REG, 1738c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO0_VSEL_MASK, 1748c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 1758c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO0_CTRL, 1768c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG, 1778c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO0_EXT_ENABLE_MASK, 1788c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO0_NUM_VOLT, 1798c2ecf20Sopenharmony_ci }, 1808c2ecf20Sopenharmony_ci { 1818c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO1, 1828c2ecf20Sopenharmony_ci .name = "as3722-ldo1", 1838c2ecf20Sopenharmony_ci .sname = "vin-ldo1-6", 1848c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO1_VOLTAGE_REG, 1858c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 1868c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 1878c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO1_CTRL, 1888c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG, 1898c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO1_EXT_ENABLE_MASK, 1908c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 1918c2ecf20Sopenharmony_ci }, 1928c2ecf20Sopenharmony_ci { 1938c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO2, 1948c2ecf20Sopenharmony_ci .name = "as3722-ldo2", 1958c2ecf20Sopenharmony_ci .sname = "vin-ldo2-5-7", 1968c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO2_VOLTAGE_REG, 1978c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 1988c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 1998c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO2_CTRL, 2008c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG, 2018c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO2_EXT_ENABLE_MASK, 2028c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 2038c2ecf20Sopenharmony_ci }, 2048c2ecf20Sopenharmony_ci { 2058c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO3, 2068c2ecf20Sopenharmony_ci .name = "as3722-ldo3", 2078c2ecf20Sopenharmony_ci .sname = "vin-ldo3-4", 2088c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO3_VOLTAGE_REG, 2098c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO3_VSEL_MASK, 2108c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 2118c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO3_CTRL, 2128c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG, 2138c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO3_EXT_ENABLE_MASK, 2148c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO3_NUM_VOLT, 2158c2ecf20Sopenharmony_ci }, 2168c2ecf20Sopenharmony_ci { 2178c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO4, 2188c2ecf20Sopenharmony_ci .name = "as3722-ldo4", 2198c2ecf20Sopenharmony_ci .sname = "vin-ldo3-4", 2208c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO4_VOLTAGE_REG, 2218c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 2228c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 2238c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO4_CTRL, 2248c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG, 2258c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO4_EXT_ENABLE_MASK, 2268c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 2278c2ecf20Sopenharmony_ci }, 2288c2ecf20Sopenharmony_ci { 2298c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO5, 2308c2ecf20Sopenharmony_ci .name = "as3722-ldo5", 2318c2ecf20Sopenharmony_ci .sname = "vin-ldo2-5-7", 2328c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO5_VOLTAGE_REG, 2338c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 2348c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 2358c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO5_CTRL, 2368c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG, 2378c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO5_EXT_ENABLE_MASK, 2388c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 2398c2ecf20Sopenharmony_ci }, 2408c2ecf20Sopenharmony_ci { 2418c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO6, 2428c2ecf20Sopenharmony_ci .name = "as3722-ldo6", 2438c2ecf20Sopenharmony_ci .sname = "vin-ldo1-6", 2448c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO6_VOLTAGE_REG, 2458c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 2468c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 2478c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO6_CTRL, 2488c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG, 2498c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO6_EXT_ENABLE_MASK, 2508c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 2518c2ecf20Sopenharmony_ci }, 2528c2ecf20Sopenharmony_ci { 2538c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO7, 2548c2ecf20Sopenharmony_ci .name = "as3722-ldo7", 2558c2ecf20Sopenharmony_ci .sname = "vin-ldo2-5-7", 2568c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO7_VOLTAGE_REG, 2578c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 2588c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 2598c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO7_CTRL, 2608c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG, 2618c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO7_EXT_ENABLE_MASK, 2628c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 2638c2ecf20Sopenharmony_ci }, 2648c2ecf20Sopenharmony_ci { 2658c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO9, 2668c2ecf20Sopenharmony_ci .name = "as3722-ldo9", 2678c2ecf20Sopenharmony_ci .sname = "vin-ldo9-10", 2688c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO9_VOLTAGE_REG, 2698c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 2708c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL1_REG, 2718c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO9_CTRL, 2728c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG, 2738c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO9_EXT_ENABLE_MASK, 2748c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 2758c2ecf20Sopenharmony_ci }, 2768c2ecf20Sopenharmony_ci { 2778c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO10, 2788c2ecf20Sopenharmony_ci .name = "as3722-ldo10", 2798c2ecf20Sopenharmony_ci .sname = "vin-ldo9-10", 2808c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO10_VOLTAGE_REG, 2818c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 2828c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL1_REG, 2838c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO10_CTRL, 2848c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG, 2858c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO10_EXT_ENABLE_MASK, 2868c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 2878c2ecf20Sopenharmony_ci }, 2888c2ecf20Sopenharmony_ci { 2898c2ecf20Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO11, 2908c2ecf20Sopenharmony_ci .name = "as3722-ldo11", 2918c2ecf20Sopenharmony_ci .sname = "vin-ldo11", 2928c2ecf20Sopenharmony_ci .vsel_reg = AS3722_LDO11_VOLTAGE_REG, 2938c2ecf20Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 2948c2ecf20Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL1_REG, 2958c2ecf20Sopenharmony_ci .enable_mask = AS3722_LDO11_CTRL, 2968c2ecf20Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG, 2978c2ecf20Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO11_EXT_ENABLE_MASK, 2988c2ecf20Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 2998c2ecf20Sopenharmony_ci }, 3008c2ecf20Sopenharmony_ci}; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic const unsigned int as3722_ldo_current[] = { 150000, 300000 }; 3038c2ecf20Sopenharmony_cistatic const unsigned int as3722_sd016_current[] = { 3048c2ecf20Sopenharmony_ci 2500000, 3000000, 3500000 3058c2ecf20Sopenharmony_ci}; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_ldo0_ops = { 3088c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 3098c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 3108c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 3118c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 3128c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 3138c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 3148c2ecf20Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 3158c2ecf20Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 3168c2ecf20Sopenharmony_ci}; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_ldo0_extcntrl_ops = { 3198c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 3208c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 3218c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 3228c2ecf20Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 3238c2ecf20Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 3248c2ecf20Sopenharmony_ci}; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic int as3722_ldo3_set_tracking_mode(struct as3722_regulators *as3722_reg, 3278c2ecf20Sopenharmony_ci int id, u8 mode) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci struct as3722 *as3722 = as3722_reg->as3722; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci switch (mode) { 3328c2ecf20Sopenharmony_ci case AS3722_LDO3_MODE_PMOS: 3338c2ecf20Sopenharmony_ci case AS3722_LDO3_MODE_PMOS_TRACKING: 3348c2ecf20Sopenharmony_ci case AS3722_LDO3_MODE_NMOS: 3358c2ecf20Sopenharmony_ci case AS3722_LDO3_MODE_SWITCH: 3368c2ecf20Sopenharmony_ci return as3722_update_bits(as3722, 3378c2ecf20Sopenharmony_ci as3722_reg_lookup[id].vsel_reg, 3388c2ecf20Sopenharmony_ci AS3722_LDO3_MODE_MASK, mode); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci default: 3418c2ecf20Sopenharmony_ci return -EINVAL; 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic int as3722_ldo3_get_current_limit(struct regulator_dev *rdev) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci return 150000; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_ldo3_ops = { 3518c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 3528c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 3538c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 3548c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 3558c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 3568c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 3578c2ecf20Sopenharmony_ci .get_current_limit = as3722_ldo3_get_current_limit, 3588c2ecf20Sopenharmony_ci}; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_ldo3_extcntrl_ops = { 3618c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 3628c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 3638c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 3648c2ecf20Sopenharmony_ci .get_current_limit = as3722_ldo3_get_current_limit, 3658c2ecf20Sopenharmony_ci}; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_ldo6_ops = { 3688c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 3698c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 3708c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 3718c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 3728c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 3738c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 3748c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 3758c2ecf20Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 3768c2ecf20Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 3778c2ecf20Sopenharmony_ci .get_bypass = regulator_get_bypass_regmap, 3788c2ecf20Sopenharmony_ci .set_bypass = regulator_set_bypass_regmap, 3798c2ecf20Sopenharmony_ci}; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_ldo6_extcntrl_ops = { 3828c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 3838c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 3848c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 3858c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 3868c2ecf20Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 3878c2ecf20Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 3888c2ecf20Sopenharmony_ci .get_bypass = regulator_get_bypass_regmap, 3898c2ecf20Sopenharmony_ci .set_bypass = regulator_set_bypass_regmap, 3908c2ecf20Sopenharmony_ci}; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic const struct linear_range as3722_ldo_ranges[] = { 3938c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0), 3948c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(825000, 0x01, 0x24, 25000), 3958c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(1725000, 0x40, 0x7F, 25000), 3968c2ecf20Sopenharmony_ci}; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_ldo_ops = { 3998c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 4008c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 4018c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 4028c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 4038c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 4048c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 4058c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 4068c2ecf20Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 4078c2ecf20Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 4088c2ecf20Sopenharmony_ci}; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_ldo_extcntrl_ops = { 4118c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 4128c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 4138c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 4148c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 4158c2ecf20Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 4168c2ecf20Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 4178c2ecf20Sopenharmony_ci}; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_cistatic unsigned int as3722_sd_get_mode(struct regulator_dev *rdev) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev); 4228c2ecf20Sopenharmony_ci struct as3722 *as3722 = as3722_regs->as3722; 4238c2ecf20Sopenharmony_ci int id = rdev_get_id(rdev); 4248c2ecf20Sopenharmony_ci u32 val; 4258c2ecf20Sopenharmony_ci int ret; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci if (!as3722_reg_lookup[id].control_reg) 4288c2ecf20Sopenharmony_ci return -ENOTSUPP; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci ret = as3722_read(as3722, as3722_reg_lookup[id].control_reg, &val); 4318c2ecf20Sopenharmony_ci if (ret < 0) { 4328c2ecf20Sopenharmony_ci dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n", 4338c2ecf20Sopenharmony_ci as3722_reg_lookup[id].control_reg, ret); 4348c2ecf20Sopenharmony_ci return ret; 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci if (val & as3722_reg_lookup[id].mode_mask) 4388c2ecf20Sopenharmony_ci return REGULATOR_MODE_FAST; 4398c2ecf20Sopenharmony_ci else 4408c2ecf20Sopenharmony_ci return REGULATOR_MODE_NORMAL; 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic int as3722_sd_set_mode(struct regulator_dev *rdev, 4448c2ecf20Sopenharmony_ci unsigned int mode) 4458c2ecf20Sopenharmony_ci{ 4468c2ecf20Sopenharmony_ci struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev); 4478c2ecf20Sopenharmony_ci struct as3722 *as3722 = as3722_regs->as3722; 4488c2ecf20Sopenharmony_ci u8 id = rdev_get_id(rdev); 4498c2ecf20Sopenharmony_ci u8 val = 0; 4508c2ecf20Sopenharmony_ci int ret; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci if (!as3722_reg_lookup[id].control_reg) 4538c2ecf20Sopenharmony_ci return -ERANGE; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci switch (mode) { 4568c2ecf20Sopenharmony_ci case REGULATOR_MODE_FAST: 4578c2ecf20Sopenharmony_ci val = as3722_reg_lookup[id].mode_mask; 4588c2ecf20Sopenharmony_ci case REGULATOR_MODE_NORMAL: /* fall down */ 4598c2ecf20Sopenharmony_ci break; 4608c2ecf20Sopenharmony_ci default: 4618c2ecf20Sopenharmony_ci return -EINVAL; 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci ret = as3722_update_bits(as3722, as3722_reg_lookup[id].control_reg, 4658c2ecf20Sopenharmony_ci as3722_reg_lookup[id].mode_mask, val); 4668c2ecf20Sopenharmony_ci if (ret < 0) { 4678c2ecf20Sopenharmony_ci dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n", 4688c2ecf20Sopenharmony_ci as3722_reg_lookup[id].control_reg, ret); 4698c2ecf20Sopenharmony_ci return ret; 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci return ret; 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_cistatic bool as3722_sd0_is_low_voltage(struct as3722_regulators *as3722_regs) 4758c2ecf20Sopenharmony_ci{ 4768c2ecf20Sopenharmony_ci int err; 4778c2ecf20Sopenharmony_ci unsigned val; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci err = as3722_read(as3722_regs->as3722, AS3722_FUSE7_REG, &val); 4808c2ecf20Sopenharmony_ci if (err < 0) { 4818c2ecf20Sopenharmony_ci dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n", 4828c2ecf20Sopenharmony_ci AS3722_FUSE7_REG, err); 4838c2ecf20Sopenharmony_ci return false; 4848c2ecf20Sopenharmony_ci } 4858c2ecf20Sopenharmony_ci if (val & AS3722_FUSE7_SD0_LOW_VOLTAGE) 4868c2ecf20Sopenharmony_ci return true; 4878c2ecf20Sopenharmony_ci return false; 4888c2ecf20Sopenharmony_ci} 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_cistatic const struct linear_range as3722_sd2345_ranges[] = { 4918c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0), 4928c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500), 4938c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000), 4948c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7F, 50000), 4958c2ecf20Sopenharmony_ci}; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_sd016_ops = { 4988c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 4998c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 5008c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 5018c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 5028c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear, 5038c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 5048c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 5058c2ecf20Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 5068c2ecf20Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 5078c2ecf20Sopenharmony_ci .get_mode = as3722_sd_get_mode, 5088c2ecf20Sopenharmony_ci .set_mode = as3722_sd_set_mode, 5098c2ecf20Sopenharmony_ci}; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_sd016_extcntrl_ops = { 5128c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 5138c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear, 5148c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 5158c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 5168c2ecf20Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 5178c2ecf20Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 5188c2ecf20Sopenharmony_ci .get_mode = as3722_sd_get_mode, 5198c2ecf20Sopenharmony_ci .set_mode = as3722_sd_set_mode, 5208c2ecf20Sopenharmony_ci}; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_sd2345_ops = { 5238c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 5248c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 5258c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 5268c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 5278c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 5288c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 5298c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 5308c2ecf20Sopenharmony_ci .get_mode = as3722_sd_get_mode, 5318c2ecf20Sopenharmony_ci .set_mode = as3722_sd_set_mode, 5328c2ecf20Sopenharmony_ci}; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic const struct regulator_ops as3722_sd2345_extcntrl_ops = { 5358c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 5368c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 5378c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 5388c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 5398c2ecf20Sopenharmony_ci .get_mode = as3722_sd_get_mode, 5408c2ecf20Sopenharmony_ci .set_mode = as3722_sd_set_mode, 5418c2ecf20Sopenharmony_ci}; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_cistatic int as3722_extreg_init(struct as3722_regulators *as3722_regs, int id, 5448c2ecf20Sopenharmony_ci int ext_pwr_ctrl) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci int ret; 5478c2ecf20Sopenharmony_ci unsigned int val; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci if ((ext_pwr_ctrl < AS3722_EXT_CONTROL_ENABLE1) || 5508c2ecf20Sopenharmony_ci (ext_pwr_ctrl > AS3722_EXT_CONTROL_ENABLE3)) 5518c2ecf20Sopenharmony_ci return -EINVAL; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci val = ext_pwr_ctrl << (ffs(as3722_reg_lookup[id].sleep_ctrl_mask) - 1); 5548c2ecf20Sopenharmony_ci ret = as3722_update_bits(as3722_regs->as3722, 5558c2ecf20Sopenharmony_ci as3722_reg_lookup[id].sleep_ctrl_reg, 5568c2ecf20Sopenharmony_ci as3722_reg_lookup[id].sleep_ctrl_mask, val); 5578c2ecf20Sopenharmony_ci if (ret < 0) 5588c2ecf20Sopenharmony_ci dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n", 5598c2ecf20Sopenharmony_ci as3722_reg_lookup[id].sleep_ctrl_reg, ret); 5608c2ecf20Sopenharmony_ci return ret; 5618c2ecf20Sopenharmony_ci} 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_cistatic struct of_regulator_match as3722_regulator_matches[] = { 5648c2ecf20Sopenharmony_ci { .name = "sd0", }, 5658c2ecf20Sopenharmony_ci { .name = "sd1", }, 5668c2ecf20Sopenharmony_ci { .name = "sd2", }, 5678c2ecf20Sopenharmony_ci { .name = "sd3", }, 5688c2ecf20Sopenharmony_ci { .name = "sd4", }, 5698c2ecf20Sopenharmony_ci { .name = "sd5", }, 5708c2ecf20Sopenharmony_ci { .name = "sd6", }, 5718c2ecf20Sopenharmony_ci { .name = "ldo0", }, 5728c2ecf20Sopenharmony_ci { .name = "ldo1", }, 5738c2ecf20Sopenharmony_ci { .name = "ldo2", }, 5748c2ecf20Sopenharmony_ci { .name = "ldo3", }, 5758c2ecf20Sopenharmony_ci { .name = "ldo4", }, 5768c2ecf20Sopenharmony_ci { .name = "ldo5", }, 5778c2ecf20Sopenharmony_ci { .name = "ldo6", }, 5788c2ecf20Sopenharmony_ci { .name = "ldo7", }, 5798c2ecf20Sopenharmony_ci { .name = "ldo9", }, 5808c2ecf20Sopenharmony_ci { .name = "ldo10", }, 5818c2ecf20Sopenharmony_ci { .name = "ldo11", }, 5828c2ecf20Sopenharmony_ci}; 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_cistatic int as3722_get_regulator_dt_data(struct platform_device *pdev, 5858c2ecf20Sopenharmony_ci struct as3722_regulators *as3722_regs) 5868c2ecf20Sopenharmony_ci{ 5878c2ecf20Sopenharmony_ci struct device_node *np; 5888c2ecf20Sopenharmony_ci struct as3722_regulator_config_data *reg_config; 5898c2ecf20Sopenharmony_ci u32 prop; 5908c2ecf20Sopenharmony_ci int id; 5918c2ecf20Sopenharmony_ci int ret; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators"); 5948c2ecf20Sopenharmony_ci if (!np) { 5958c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Device is not having regulators node\n"); 5968c2ecf20Sopenharmony_ci return -ENODEV; 5978c2ecf20Sopenharmony_ci } 5988c2ecf20Sopenharmony_ci pdev->dev.of_node = np; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches, 6018c2ecf20Sopenharmony_ci ARRAY_SIZE(as3722_regulator_matches)); 6028c2ecf20Sopenharmony_ci of_node_put(np); 6038c2ecf20Sopenharmony_ci if (ret < 0) { 6048c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n", 6058c2ecf20Sopenharmony_ci ret); 6068c2ecf20Sopenharmony_ci return ret; 6078c2ecf20Sopenharmony_ci } 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci for (id = 0; id < ARRAY_SIZE(as3722_regulator_matches); ++id) { 6108c2ecf20Sopenharmony_ci struct device_node *reg_node; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci reg_config = &as3722_regs->reg_config_data[id]; 6138c2ecf20Sopenharmony_ci reg_config->reg_init = as3722_regulator_matches[id].init_data; 6148c2ecf20Sopenharmony_ci reg_node = as3722_regulator_matches[id].of_node; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (!reg_config->reg_init || !reg_node) 6178c2ecf20Sopenharmony_ci continue; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci ret = of_property_read_u32(reg_node, "ams,ext-control", &prop); 6208c2ecf20Sopenharmony_ci if (!ret) { 6218c2ecf20Sopenharmony_ci if (prop < 3) 6228c2ecf20Sopenharmony_ci reg_config->ext_control = prop; 6238c2ecf20Sopenharmony_ci else 6248c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 6258c2ecf20Sopenharmony_ci "ext-control have invalid option: %u\n", 6268c2ecf20Sopenharmony_ci prop); 6278c2ecf20Sopenharmony_ci } 6288c2ecf20Sopenharmony_ci reg_config->enable_tracking = 6298c2ecf20Sopenharmony_ci of_property_read_bool(reg_node, "ams,enable-tracking"); 6308c2ecf20Sopenharmony_ci } 6318c2ecf20Sopenharmony_ci return 0; 6328c2ecf20Sopenharmony_ci} 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_cistatic int as3722_regulator_probe(struct platform_device *pdev) 6358c2ecf20Sopenharmony_ci{ 6368c2ecf20Sopenharmony_ci struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent); 6378c2ecf20Sopenharmony_ci struct as3722_regulators *as3722_regs; 6388c2ecf20Sopenharmony_ci struct as3722_regulator_config_data *reg_config; 6398c2ecf20Sopenharmony_ci struct regulator_dev *rdev; 6408c2ecf20Sopenharmony_ci struct regulator_config config = { }; 6418c2ecf20Sopenharmony_ci const struct regulator_ops *ops; 6428c2ecf20Sopenharmony_ci int id; 6438c2ecf20Sopenharmony_ci int ret; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci as3722_regs = devm_kzalloc(&pdev->dev, sizeof(*as3722_regs), 6468c2ecf20Sopenharmony_ci GFP_KERNEL); 6478c2ecf20Sopenharmony_ci if (!as3722_regs) 6488c2ecf20Sopenharmony_ci return -ENOMEM; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci as3722_regs->dev = &pdev->dev; 6518c2ecf20Sopenharmony_ci as3722_regs->as3722 = as3722; 6528c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, as3722_regs); 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci ret = as3722_get_regulator_dt_data(pdev, as3722_regs); 6558c2ecf20Sopenharmony_ci if (ret < 0) 6568c2ecf20Sopenharmony_ci return ret; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci config.dev = &pdev->dev; 6598c2ecf20Sopenharmony_ci config.driver_data = as3722_regs; 6608c2ecf20Sopenharmony_ci config.regmap = as3722->regmap; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci for (id = 0; id < AS3722_REGULATOR_ID_MAX; id++) { 6638c2ecf20Sopenharmony_ci struct regulator_desc *desc; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci desc = &as3722_regs->desc[id]; 6668c2ecf20Sopenharmony_ci reg_config = &as3722_regs->reg_config_data[id]; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci desc->name = as3722_reg_lookup[id].name; 6698c2ecf20Sopenharmony_ci desc->supply_name = as3722_reg_lookup[id].sname; 6708c2ecf20Sopenharmony_ci desc->id = as3722_reg_lookup[id].regulator_id; 6718c2ecf20Sopenharmony_ci desc->n_voltages = as3722_reg_lookup[id].n_voltages; 6728c2ecf20Sopenharmony_ci desc->type = REGULATOR_VOLTAGE; 6738c2ecf20Sopenharmony_ci desc->owner = THIS_MODULE; 6748c2ecf20Sopenharmony_ci desc->enable_reg = as3722_reg_lookup[id].enable_reg; 6758c2ecf20Sopenharmony_ci desc->enable_mask = as3722_reg_lookup[id].enable_mask; 6768c2ecf20Sopenharmony_ci desc->vsel_reg = as3722_reg_lookup[id].vsel_reg; 6778c2ecf20Sopenharmony_ci desc->vsel_mask = as3722_reg_lookup[id].vsel_mask; 6788c2ecf20Sopenharmony_ci switch (id) { 6798c2ecf20Sopenharmony_ci case AS3722_REGULATOR_ID_LDO0: 6808c2ecf20Sopenharmony_ci if (reg_config->ext_control) 6818c2ecf20Sopenharmony_ci ops = &as3722_ldo0_extcntrl_ops; 6828c2ecf20Sopenharmony_ci else 6838c2ecf20Sopenharmony_ci ops = &as3722_ldo0_ops; 6848c2ecf20Sopenharmony_ci desc->min_uV = 825000; 6858c2ecf20Sopenharmony_ci desc->uV_step = 25000; 6868c2ecf20Sopenharmony_ci desc->linear_min_sel = 1; 6878c2ecf20Sopenharmony_ci desc->enable_time = 500; 6888c2ecf20Sopenharmony_ci desc->curr_table = as3722_ldo_current; 6898c2ecf20Sopenharmony_ci desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current); 6908c2ecf20Sopenharmony_ci desc->csel_reg = as3722_reg_lookup[id].vsel_reg; 6918c2ecf20Sopenharmony_ci desc->csel_mask = AS3722_LDO_ILIMIT_MASK; 6928c2ecf20Sopenharmony_ci break; 6938c2ecf20Sopenharmony_ci case AS3722_REGULATOR_ID_LDO3: 6948c2ecf20Sopenharmony_ci if (reg_config->ext_control) 6958c2ecf20Sopenharmony_ci ops = &as3722_ldo3_extcntrl_ops; 6968c2ecf20Sopenharmony_ci else 6978c2ecf20Sopenharmony_ci ops = &as3722_ldo3_ops; 6988c2ecf20Sopenharmony_ci desc->min_uV = 620000; 6998c2ecf20Sopenharmony_ci desc->uV_step = 20000; 7008c2ecf20Sopenharmony_ci desc->linear_min_sel = 1; 7018c2ecf20Sopenharmony_ci desc->enable_time = 500; 7028c2ecf20Sopenharmony_ci if (reg_config->enable_tracking) { 7038c2ecf20Sopenharmony_ci ret = as3722_ldo3_set_tracking_mode(as3722_regs, 7048c2ecf20Sopenharmony_ci id, AS3722_LDO3_MODE_PMOS_TRACKING); 7058c2ecf20Sopenharmony_ci if (ret < 0) { 7068c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 7078c2ecf20Sopenharmony_ci "LDO3 tracking failed: %d\n", 7088c2ecf20Sopenharmony_ci ret); 7098c2ecf20Sopenharmony_ci return ret; 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci break; 7138c2ecf20Sopenharmony_ci case AS3722_REGULATOR_ID_LDO6: 7148c2ecf20Sopenharmony_ci if (reg_config->ext_control) 7158c2ecf20Sopenharmony_ci ops = &as3722_ldo6_extcntrl_ops; 7168c2ecf20Sopenharmony_ci else 7178c2ecf20Sopenharmony_ci ops = &as3722_ldo6_ops; 7188c2ecf20Sopenharmony_ci desc->enable_time = 500; 7198c2ecf20Sopenharmony_ci desc->bypass_reg = AS3722_LDO6_VOLTAGE_REG; 7208c2ecf20Sopenharmony_ci desc->bypass_mask = AS3722_LDO_VSEL_MASK; 7218c2ecf20Sopenharmony_ci desc->bypass_val_on = AS3722_LDO6_VSEL_BYPASS; 7228c2ecf20Sopenharmony_ci desc->bypass_val_off = AS3722_LDO6_VSEL_BYPASS; 7238c2ecf20Sopenharmony_ci desc->linear_ranges = as3722_ldo_ranges; 7248c2ecf20Sopenharmony_ci desc->n_linear_ranges = ARRAY_SIZE(as3722_ldo_ranges); 7258c2ecf20Sopenharmony_ci desc->curr_table = as3722_ldo_current; 7268c2ecf20Sopenharmony_ci desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current); 7278c2ecf20Sopenharmony_ci desc->csel_reg = as3722_reg_lookup[id].vsel_reg; 7288c2ecf20Sopenharmony_ci desc->csel_mask = AS3722_LDO_ILIMIT_MASK; 7298c2ecf20Sopenharmony_ci break; 7308c2ecf20Sopenharmony_ci case AS3722_REGULATOR_ID_SD0: 7318c2ecf20Sopenharmony_ci case AS3722_REGULATOR_ID_SD1: 7328c2ecf20Sopenharmony_ci case AS3722_REGULATOR_ID_SD6: 7338c2ecf20Sopenharmony_ci if (reg_config->ext_control) 7348c2ecf20Sopenharmony_ci ops = &as3722_sd016_extcntrl_ops; 7358c2ecf20Sopenharmony_ci else 7368c2ecf20Sopenharmony_ci ops = &as3722_sd016_ops; 7378c2ecf20Sopenharmony_ci if (id == AS3722_REGULATOR_ID_SD0 && 7388c2ecf20Sopenharmony_ci as3722_sd0_is_low_voltage(as3722_regs)) { 7398c2ecf20Sopenharmony_ci as3722_regs->desc[id].n_voltages = 7408c2ecf20Sopenharmony_ci AS3722_SD0_VSEL_LOW_VOL_MAX + 1; 7418c2ecf20Sopenharmony_ci as3722_regs->desc[id].min_uV = 410000; 7428c2ecf20Sopenharmony_ci } else { 7438c2ecf20Sopenharmony_ci as3722_regs->desc[id].n_voltages = 7448c2ecf20Sopenharmony_ci AS3722_SD0_VSEL_MAX + 1; 7458c2ecf20Sopenharmony_ci as3722_regs->desc[id].min_uV = 610000; 7468c2ecf20Sopenharmony_ci } 7478c2ecf20Sopenharmony_ci desc->uV_step = 10000; 7488c2ecf20Sopenharmony_ci desc->linear_min_sel = 1; 7498c2ecf20Sopenharmony_ci desc->enable_time = 600; 7508c2ecf20Sopenharmony_ci desc->curr_table = as3722_sd016_current; 7518c2ecf20Sopenharmony_ci desc->n_current_limits = 7528c2ecf20Sopenharmony_ci ARRAY_SIZE(as3722_sd016_current); 7538c2ecf20Sopenharmony_ci if (id == AS3722_REGULATOR_ID_SD0) { 7548c2ecf20Sopenharmony_ci desc->csel_reg = AS3722_OVCURRENT_REG; 7558c2ecf20Sopenharmony_ci desc->csel_mask = 7568c2ecf20Sopenharmony_ci AS3722_OVCURRENT_SD0_TRIP_MASK; 7578c2ecf20Sopenharmony_ci } else if (id == AS3722_REGULATOR_ID_SD1) { 7588c2ecf20Sopenharmony_ci desc->csel_reg = AS3722_OVCURRENT_REG; 7598c2ecf20Sopenharmony_ci desc->csel_mask = 7608c2ecf20Sopenharmony_ci AS3722_OVCURRENT_SD1_TRIP_MASK; 7618c2ecf20Sopenharmony_ci } else if (id == AS3722_REGULATOR_ID_SD6) { 7628c2ecf20Sopenharmony_ci desc->csel_reg = AS3722_OVCURRENT_DEB_REG; 7638c2ecf20Sopenharmony_ci desc->csel_mask = 7648c2ecf20Sopenharmony_ci AS3722_OVCURRENT_SD6_TRIP_MASK; 7658c2ecf20Sopenharmony_ci } 7668c2ecf20Sopenharmony_ci break; 7678c2ecf20Sopenharmony_ci case AS3722_REGULATOR_ID_SD2: 7688c2ecf20Sopenharmony_ci case AS3722_REGULATOR_ID_SD3: 7698c2ecf20Sopenharmony_ci case AS3722_REGULATOR_ID_SD4: 7708c2ecf20Sopenharmony_ci case AS3722_REGULATOR_ID_SD5: 7718c2ecf20Sopenharmony_ci if (reg_config->ext_control) 7728c2ecf20Sopenharmony_ci ops = &as3722_sd2345_extcntrl_ops; 7738c2ecf20Sopenharmony_ci else 7748c2ecf20Sopenharmony_ci ops = &as3722_sd2345_ops; 7758c2ecf20Sopenharmony_ci desc->linear_ranges = as3722_sd2345_ranges; 7768c2ecf20Sopenharmony_ci desc->n_linear_ranges = 7778c2ecf20Sopenharmony_ci ARRAY_SIZE(as3722_sd2345_ranges); 7788c2ecf20Sopenharmony_ci break; 7798c2ecf20Sopenharmony_ci default: 7808c2ecf20Sopenharmony_ci if (reg_config->ext_control) 7818c2ecf20Sopenharmony_ci ops = &as3722_ldo_extcntrl_ops; 7828c2ecf20Sopenharmony_ci else 7838c2ecf20Sopenharmony_ci ops = &as3722_ldo_ops; 7848c2ecf20Sopenharmony_ci desc->enable_time = 500; 7858c2ecf20Sopenharmony_ci desc->linear_ranges = as3722_ldo_ranges; 7868c2ecf20Sopenharmony_ci desc->n_linear_ranges = ARRAY_SIZE(as3722_ldo_ranges); 7878c2ecf20Sopenharmony_ci desc->curr_table = as3722_ldo_current; 7888c2ecf20Sopenharmony_ci desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current); 7898c2ecf20Sopenharmony_ci desc->csel_reg = as3722_reg_lookup[id].vsel_reg; 7908c2ecf20Sopenharmony_ci desc->csel_mask = AS3722_LDO_ILIMIT_MASK; 7918c2ecf20Sopenharmony_ci break; 7928c2ecf20Sopenharmony_ci } 7938c2ecf20Sopenharmony_ci desc->ops = ops; 7948c2ecf20Sopenharmony_ci config.init_data = reg_config->reg_init; 7958c2ecf20Sopenharmony_ci config.of_node = as3722_regulator_matches[id].of_node; 7968c2ecf20Sopenharmony_ci rdev = devm_regulator_register(&pdev->dev, desc, &config); 7978c2ecf20Sopenharmony_ci if (IS_ERR(rdev)) { 7988c2ecf20Sopenharmony_ci ret = PTR_ERR(rdev); 7998c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "regulator %d register failed %d\n", 8008c2ecf20Sopenharmony_ci id, ret); 8018c2ecf20Sopenharmony_ci return ret; 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci if (reg_config->ext_control) { 8058c2ecf20Sopenharmony_ci ret = regulator_enable_regmap(rdev); 8068c2ecf20Sopenharmony_ci if (ret < 0) { 8078c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 8088c2ecf20Sopenharmony_ci "Regulator %d enable failed: %d\n", 8098c2ecf20Sopenharmony_ci id, ret); 8108c2ecf20Sopenharmony_ci return ret; 8118c2ecf20Sopenharmony_ci } 8128c2ecf20Sopenharmony_ci ret = as3722_extreg_init(as3722_regs, id, 8138c2ecf20Sopenharmony_ci reg_config->ext_control); 8148c2ecf20Sopenharmony_ci if (ret < 0) { 8158c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 8168c2ecf20Sopenharmony_ci "AS3722 ext control failed: %d", ret); 8178c2ecf20Sopenharmony_ci return ret; 8188c2ecf20Sopenharmony_ci } 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci } 8218c2ecf20Sopenharmony_ci return 0; 8228c2ecf20Sopenharmony_ci} 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_cistatic const struct of_device_id of_as3722_regulator_match[] = { 8258c2ecf20Sopenharmony_ci { .compatible = "ams,as3722-regulator", }, 8268c2ecf20Sopenharmony_ci {}, 8278c2ecf20Sopenharmony_ci}; 8288c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_as3722_regulator_match); 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_cistatic struct platform_driver as3722_regulator_driver = { 8318c2ecf20Sopenharmony_ci .driver = { 8328c2ecf20Sopenharmony_ci .name = "as3722-regulator", 8338c2ecf20Sopenharmony_ci .of_match_table = of_as3722_regulator_match, 8348c2ecf20Sopenharmony_ci }, 8358c2ecf20Sopenharmony_ci .probe = as3722_regulator_probe, 8368c2ecf20Sopenharmony_ci}; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_cimodule_platform_driver(as3722_regulator_driver); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:as3722-regulator"); 8418c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("AS3722 regulator driver"); 8428c2ecf20Sopenharmony_ciMODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>"); 8438c2ecf20Sopenharmony_ciMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 8448c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 845