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