162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Voltage regulator support for AMS AS3722 PMIC 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2013 ams 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Florian Lobmaier <florian.lobmaier@ams.com> 862306a36Sopenharmony_ci * Author: Laxman Dewangan <ldewangan@nvidia.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/err.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/mfd/as3722.h> 1562306a36Sopenharmony_ci#include <linux/of.h> 1662306a36Sopenharmony_ci#include <linux/of_platform.h> 1762306a36Sopenharmony_ci#include <linux/platform_device.h> 1862306a36Sopenharmony_ci#include <linux/regulator/driver.h> 1962306a36Sopenharmony_ci#include <linux/regulator/machine.h> 2062306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h> 2162306a36Sopenharmony_ci#include <linux/slab.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* Regulator IDs */ 2462306a36Sopenharmony_cienum as3722_regulators_id { 2562306a36Sopenharmony_ci AS3722_REGULATOR_ID_SD0, 2662306a36Sopenharmony_ci AS3722_REGULATOR_ID_SD1, 2762306a36Sopenharmony_ci AS3722_REGULATOR_ID_SD2, 2862306a36Sopenharmony_ci AS3722_REGULATOR_ID_SD3, 2962306a36Sopenharmony_ci AS3722_REGULATOR_ID_SD4, 3062306a36Sopenharmony_ci AS3722_REGULATOR_ID_SD5, 3162306a36Sopenharmony_ci AS3722_REGULATOR_ID_SD6, 3262306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO0, 3362306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO1, 3462306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO2, 3562306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO3, 3662306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO4, 3762306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO5, 3862306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO6, 3962306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO7, 4062306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO9, 4162306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO10, 4262306a36Sopenharmony_ci AS3722_REGULATOR_ID_LDO11, 4362306a36Sopenharmony_ci AS3722_REGULATOR_ID_MAX, 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct as3722_register_mapping { 4762306a36Sopenharmony_ci u8 regulator_id; 4862306a36Sopenharmony_ci const char *name; 4962306a36Sopenharmony_ci const char *sname; 5062306a36Sopenharmony_ci u8 vsel_reg; 5162306a36Sopenharmony_ci u8 vsel_mask; 5262306a36Sopenharmony_ci int n_voltages; 5362306a36Sopenharmony_ci u32 enable_reg; 5462306a36Sopenharmony_ci u8 enable_mask; 5562306a36Sopenharmony_ci u32 control_reg; 5662306a36Sopenharmony_ci u8 mode_mask; 5762306a36Sopenharmony_ci u32 sleep_ctrl_reg; 5862306a36Sopenharmony_ci u8 sleep_ctrl_mask; 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistruct as3722_regulator_config_data { 6262306a36Sopenharmony_ci struct regulator_init_data *reg_init; 6362306a36Sopenharmony_ci bool enable_tracking; 6462306a36Sopenharmony_ci int ext_control; 6562306a36Sopenharmony_ci}; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistruct as3722_regulators { 6862306a36Sopenharmony_ci struct device *dev; 6962306a36Sopenharmony_ci struct as3722 *as3722; 7062306a36Sopenharmony_ci struct regulator_desc desc[AS3722_REGULATOR_ID_MAX]; 7162306a36Sopenharmony_ci struct as3722_regulator_config_data 7262306a36Sopenharmony_ci reg_config_data[AS3722_REGULATOR_ID_MAX]; 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic const struct as3722_register_mapping as3722_reg_lookup[] = { 7662306a36Sopenharmony_ci { 7762306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD0, 7862306a36Sopenharmony_ci .name = "as3722-sd0", 7962306a36Sopenharmony_ci .vsel_reg = AS3722_SD0_VOLTAGE_REG, 8062306a36Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 8162306a36Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 8262306a36Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(0), 8362306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG, 8462306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK, 8562306a36Sopenharmony_ci .control_reg = AS3722_SD0_CONTROL_REG, 8662306a36Sopenharmony_ci .mode_mask = AS3722_SD0_MODE_FAST, 8762306a36Sopenharmony_ci }, 8862306a36Sopenharmony_ci { 8962306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD1, 9062306a36Sopenharmony_ci .name = "as3722-sd1", 9162306a36Sopenharmony_ci .vsel_reg = AS3722_SD1_VOLTAGE_REG, 9262306a36Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 9362306a36Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 9462306a36Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(1), 9562306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG, 9662306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK, 9762306a36Sopenharmony_ci .control_reg = AS3722_SD1_CONTROL_REG, 9862306a36Sopenharmony_ci .mode_mask = AS3722_SD1_MODE_FAST, 9962306a36Sopenharmony_ci }, 10062306a36Sopenharmony_ci { 10162306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD2, 10262306a36Sopenharmony_ci .name = "as3722-sd2", 10362306a36Sopenharmony_ci .sname = "vsup-sd2", 10462306a36Sopenharmony_ci .vsel_reg = AS3722_SD2_VOLTAGE_REG, 10562306a36Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 10662306a36Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 10762306a36Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(2), 10862306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG, 10962306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD2_EXT_ENABLE_MASK, 11062306a36Sopenharmony_ci .control_reg = AS3722_SD23_CONTROL_REG, 11162306a36Sopenharmony_ci .mode_mask = AS3722_SD2_MODE_FAST, 11262306a36Sopenharmony_ci .n_voltages = AS3722_SD2_VSEL_MAX + 1, 11362306a36Sopenharmony_ci }, 11462306a36Sopenharmony_ci { 11562306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD3, 11662306a36Sopenharmony_ci .name = "as3722-sd3", 11762306a36Sopenharmony_ci .sname = "vsup-sd3", 11862306a36Sopenharmony_ci .vsel_reg = AS3722_SD3_VOLTAGE_REG, 11962306a36Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 12062306a36Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 12162306a36Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(3), 12262306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG, 12362306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD3_EXT_ENABLE_MASK, 12462306a36Sopenharmony_ci .control_reg = AS3722_SD23_CONTROL_REG, 12562306a36Sopenharmony_ci .mode_mask = AS3722_SD3_MODE_FAST, 12662306a36Sopenharmony_ci .n_voltages = AS3722_SD2_VSEL_MAX + 1, 12762306a36Sopenharmony_ci }, 12862306a36Sopenharmony_ci { 12962306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD4, 13062306a36Sopenharmony_ci .name = "as3722-sd4", 13162306a36Sopenharmony_ci .sname = "vsup-sd4", 13262306a36Sopenharmony_ci .vsel_reg = AS3722_SD4_VOLTAGE_REG, 13362306a36Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 13462306a36Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 13562306a36Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(4), 13662306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG, 13762306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD4_EXT_ENABLE_MASK, 13862306a36Sopenharmony_ci .control_reg = AS3722_SD4_CONTROL_REG, 13962306a36Sopenharmony_ci .mode_mask = AS3722_SD4_MODE_FAST, 14062306a36Sopenharmony_ci .n_voltages = AS3722_SD2_VSEL_MAX + 1, 14162306a36Sopenharmony_ci }, 14262306a36Sopenharmony_ci { 14362306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD5, 14462306a36Sopenharmony_ci .name = "as3722-sd5", 14562306a36Sopenharmony_ci .sname = "vsup-sd5", 14662306a36Sopenharmony_ci .vsel_reg = AS3722_SD5_VOLTAGE_REG, 14762306a36Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 14862306a36Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 14962306a36Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(5), 15062306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG, 15162306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD5_EXT_ENABLE_MASK, 15262306a36Sopenharmony_ci .control_reg = AS3722_SD5_CONTROL_REG, 15362306a36Sopenharmony_ci .mode_mask = AS3722_SD5_MODE_FAST, 15462306a36Sopenharmony_ci .n_voltages = AS3722_SD2_VSEL_MAX + 1, 15562306a36Sopenharmony_ci }, 15662306a36Sopenharmony_ci { 15762306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_SD6, 15862306a36Sopenharmony_ci .name = "as3722-sd6", 15962306a36Sopenharmony_ci .vsel_reg = AS3722_SD6_VOLTAGE_REG, 16062306a36Sopenharmony_ci .vsel_mask = AS3722_SD_VSEL_MASK, 16162306a36Sopenharmony_ci .enable_reg = AS3722_SD_CONTROL_REG, 16262306a36Sopenharmony_ci .enable_mask = AS3722_SDn_CTRL(6), 16362306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG, 16462306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK, 16562306a36Sopenharmony_ci .control_reg = AS3722_SD6_CONTROL_REG, 16662306a36Sopenharmony_ci .mode_mask = AS3722_SD6_MODE_FAST, 16762306a36Sopenharmony_ci }, 16862306a36Sopenharmony_ci { 16962306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO0, 17062306a36Sopenharmony_ci .name = "as3722-ldo0", 17162306a36Sopenharmony_ci .sname = "vin-ldo0", 17262306a36Sopenharmony_ci .vsel_reg = AS3722_LDO0_VOLTAGE_REG, 17362306a36Sopenharmony_ci .vsel_mask = AS3722_LDO0_VSEL_MASK, 17462306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 17562306a36Sopenharmony_ci .enable_mask = AS3722_LDO0_CTRL, 17662306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG, 17762306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO0_EXT_ENABLE_MASK, 17862306a36Sopenharmony_ci .n_voltages = AS3722_LDO0_NUM_VOLT, 17962306a36Sopenharmony_ci }, 18062306a36Sopenharmony_ci { 18162306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO1, 18262306a36Sopenharmony_ci .name = "as3722-ldo1", 18362306a36Sopenharmony_ci .sname = "vin-ldo1-6", 18462306a36Sopenharmony_ci .vsel_reg = AS3722_LDO1_VOLTAGE_REG, 18562306a36Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 18662306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 18762306a36Sopenharmony_ci .enable_mask = AS3722_LDO1_CTRL, 18862306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG, 18962306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO1_EXT_ENABLE_MASK, 19062306a36Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 19162306a36Sopenharmony_ci }, 19262306a36Sopenharmony_ci { 19362306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO2, 19462306a36Sopenharmony_ci .name = "as3722-ldo2", 19562306a36Sopenharmony_ci .sname = "vin-ldo2-5-7", 19662306a36Sopenharmony_ci .vsel_reg = AS3722_LDO2_VOLTAGE_REG, 19762306a36Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 19862306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 19962306a36Sopenharmony_ci .enable_mask = AS3722_LDO2_CTRL, 20062306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG, 20162306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO2_EXT_ENABLE_MASK, 20262306a36Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 20362306a36Sopenharmony_ci }, 20462306a36Sopenharmony_ci { 20562306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO3, 20662306a36Sopenharmony_ci .name = "as3722-ldo3", 20762306a36Sopenharmony_ci .sname = "vin-ldo3-4", 20862306a36Sopenharmony_ci .vsel_reg = AS3722_LDO3_VOLTAGE_REG, 20962306a36Sopenharmony_ci .vsel_mask = AS3722_LDO3_VSEL_MASK, 21062306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 21162306a36Sopenharmony_ci .enable_mask = AS3722_LDO3_CTRL, 21262306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG, 21362306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO3_EXT_ENABLE_MASK, 21462306a36Sopenharmony_ci .n_voltages = AS3722_LDO3_NUM_VOLT, 21562306a36Sopenharmony_ci }, 21662306a36Sopenharmony_ci { 21762306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO4, 21862306a36Sopenharmony_ci .name = "as3722-ldo4", 21962306a36Sopenharmony_ci .sname = "vin-ldo3-4", 22062306a36Sopenharmony_ci .vsel_reg = AS3722_LDO4_VOLTAGE_REG, 22162306a36Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 22262306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 22362306a36Sopenharmony_ci .enable_mask = AS3722_LDO4_CTRL, 22462306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG, 22562306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO4_EXT_ENABLE_MASK, 22662306a36Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 22762306a36Sopenharmony_ci }, 22862306a36Sopenharmony_ci { 22962306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO5, 23062306a36Sopenharmony_ci .name = "as3722-ldo5", 23162306a36Sopenharmony_ci .sname = "vin-ldo2-5-7", 23262306a36Sopenharmony_ci .vsel_reg = AS3722_LDO5_VOLTAGE_REG, 23362306a36Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 23462306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 23562306a36Sopenharmony_ci .enable_mask = AS3722_LDO5_CTRL, 23662306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG, 23762306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO5_EXT_ENABLE_MASK, 23862306a36Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 23962306a36Sopenharmony_ci }, 24062306a36Sopenharmony_ci { 24162306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO6, 24262306a36Sopenharmony_ci .name = "as3722-ldo6", 24362306a36Sopenharmony_ci .sname = "vin-ldo1-6", 24462306a36Sopenharmony_ci .vsel_reg = AS3722_LDO6_VOLTAGE_REG, 24562306a36Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 24662306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 24762306a36Sopenharmony_ci .enable_mask = AS3722_LDO6_CTRL, 24862306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG, 24962306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO6_EXT_ENABLE_MASK, 25062306a36Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 25162306a36Sopenharmony_ci }, 25262306a36Sopenharmony_ci { 25362306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO7, 25462306a36Sopenharmony_ci .name = "as3722-ldo7", 25562306a36Sopenharmony_ci .sname = "vin-ldo2-5-7", 25662306a36Sopenharmony_ci .vsel_reg = AS3722_LDO7_VOLTAGE_REG, 25762306a36Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 25862306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL0_REG, 25962306a36Sopenharmony_ci .enable_mask = AS3722_LDO7_CTRL, 26062306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG, 26162306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO7_EXT_ENABLE_MASK, 26262306a36Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 26362306a36Sopenharmony_ci }, 26462306a36Sopenharmony_ci { 26562306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO9, 26662306a36Sopenharmony_ci .name = "as3722-ldo9", 26762306a36Sopenharmony_ci .sname = "vin-ldo9-10", 26862306a36Sopenharmony_ci .vsel_reg = AS3722_LDO9_VOLTAGE_REG, 26962306a36Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 27062306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL1_REG, 27162306a36Sopenharmony_ci .enable_mask = AS3722_LDO9_CTRL, 27262306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG, 27362306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO9_EXT_ENABLE_MASK, 27462306a36Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 27562306a36Sopenharmony_ci }, 27662306a36Sopenharmony_ci { 27762306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO10, 27862306a36Sopenharmony_ci .name = "as3722-ldo10", 27962306a36Sopenharmony_ci .sname = "vin-ldo9-10", 28062306a36Sopenharmony_ci .vsel_reg = AS3722_LDO10_VOLTAGE_REG, 28162306a36Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 28262306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL1_REG, 28362306a36Sopenharmony_ci .enable_mask = AS3722_LDO10_CTRL, 28462306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG, 28562306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO10_EXT_ENABLE_MASK, 28662306a36Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 28762306a36Sopenharmony_ci }, 28862306a36Sopenharmony_ci { 28962306a36Sopenharmony_ci .regulator_id = AS3722_REGULATOR_ID_LDO11, 29062306a36Sopenharmony_ci .name = "as3722-ldo11", 29162306a36Sopenharmony_ci .sname = "vin-ldo11", 29262306a36Sopenharmony_ci .vsel_reg = AS3722_LDO11_VOLTAGE_REG, 29362306a36Sopenharmony_ci .vsel_mask = AS3722_LDO_VSEL_MASK, 29462306a36Sopenharmony_ci .enable_reg = AS3722_LDOCONTROL1_REG, 29562306a36Sopenharmony_ci .enable_mask = AS3722_LDO11_CTRL, 29662306a36Sopenharmony_ci .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG, 29762306a36Sopenharmony_ci .sleep_ctrl_mask = AS3722_LDO11_EXT_ENABLE_MASK, 29862306a36Sopenharmony_ci .n_voltages = AS3722_LDO_NUM_VOLT, 29962306a36Sopenharmony_ci }, 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic const unsigned int as3722_ldo_current[] = { 150000, 300000 }; 30362306a36Sopenharmony_cistatic const unsigned int as3722_sd016_current[] = { 30462306a36Sopenharmony_ci 2500000, 3000000, 3500000 30562306a36Sopenharmony_ci}; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic const struct regulator_ops as3722_ldo0_ops = { 30862306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 30962306a36Sopenharmony_ci .enable = regulator_enable_regmap, 31062306a36Sopenharmony_ci .disable = regulator_disable_regmap, 31162306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 31262306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 31362306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 31462306a36Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 31562306a36Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 31662306a36Sopenharmony_ci}; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic const struct regulator_ops as3722_ldo0_extcntrl_ops = { 31962306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 32062306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 32162306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 32262306a36Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 32362306a36Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 32462306a36Sopenharmony_ci}; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic int as3722_ldo3_set_tracking_mode(struct as3722_regulators *as3722_reg, 32762306a36Sopenharmony_ci int id, u8 mode) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci struct as3722 *as3722 = as3722_reg->as3722; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci switch (mode) { 33262306a36Sopenharmony_ci case AS3722_LDO3_MODE_PMOS: 33362306a36Sopenharmony_ci case AS3722_LDO3_MODE_PMOS_TRACKING: 33462306a36Sopenharmony_ci case AS3722_LDO3_MODE_NMOS: 33562306a36Sopenharmony_ci case AS3722_LDO3_MODE_SWITCH: 33662306a36Sopenharmony_ci return as3722_update_bits(as3722, 33762306a36Sopenharmony_ci as3722_reg_lookup[id].vsel_reg, 33862306a36Sopenharmony_ci AS3722_LDO3_MODE_MASK, mode); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci default: 34162306a36Sopenharmony_ci return -EINVAL; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci} 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic int as3722_ldo3_get_current_limit(struct regulator_dev *rdev) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci return 150000; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic const struct regulator_ops as3722_ldo3_ops = { 35162306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 35262306a36Sopenharmony_ci .enable = regulator_enable_regmap, 35362306a36Sopenharmony_ci .disable = regulator_disable_regmap, 35462306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 35562306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 35662306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 35762306a36Sopenharmony_ci .get_current_limit = as3722_ldo3_get_current_limit, 35862306a36Sopenharmony_ci}; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic const struct regulator_ops as3722_ldo3_extcntrl_ops = { 36162306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 36262306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 36362306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 36462306a36Sopenharmony_ci .get_current_limit = as3722_ldo3_get_current_limit, 36562306a36Sopenharmony_ci}; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic const struct regulator_ops as3722_ldo6_ops = { 36862306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 36962306a36Sopenharmony_ci .enable = regulator_enable_regmap, 37062306a36Sopenharmony_ci .disable = regulator_disable_regmap, 37162306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 37262306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 37362306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 37462306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 37562306a36Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 37662306a36Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 37762306a36Sopenharmony_ci .get_bypass = regulator_get_bypass_regmap, 37862306a36Sopenharmony_ci .set_bypass = regulator_set_bypass_regmap, 37962306a36Sopenharmony_ci}; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_cistatic const struct regulator_ops as3722_ldo6_extcntrl_ops = { 38262306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 38362306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 38462306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 38562306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 38662306a36Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 38762306a36Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 38862306a36Sopenharmony_ci .get_bypass = regulator_get_bypass_regmap, 38962306a36Sopenharmony_ci .set_bypass = regulator_set_bypass_regmap, 39062306a36Sopenharmony_ci}; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic const struct linear_range as3722_ldo_ranges[] = { 39362306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0), 39462306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(825000, 0x01, 0x24, 25000), 39562306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(1725000, 0x40, 0x7F, 25000), 39662306a36Sopenharmony_ci}; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistatic const struct regulator_ops as3722_ldo_ops = { 39962306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 40062306a36Sopenharmony_ci .enable = regulator_enable_regmap, 40162306a36Sopenharmony_ci .disable = regulator_disable_regmap, 40262306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 40362306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 40462306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 40562306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 40662306a36Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 40762306a36Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 40862306a36Sopenharmony_ci}; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistatic const struct regulator_ops as3722_ldo_extcntrl_ops = { 41162306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 41262306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 41362306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 41462306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 41562306a36Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 41662306a36Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 41762306a36Sopenharmony_ci}; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic unsigned int as3722_sd_get_mode(struct regulator_dev *rdev) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev); 42262306a36Sopenharmony_ci struct as3722 *as3722 = as3722_regs->as3722; 42362306a36Sopenharmony_ci int id = rdev_get_id(rdev); 42462306a36Sopenharmony_ci u32 val; 42562306a36Sopenharmony_ci int ret; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci if (!as3722_reg_lookup[id].control_reg) 42862306a36Sopenharmony_ci return -ENOTSUPP; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci ret = as3722_read(as3722, as3722_reg_lookup[id].control_reg, &val); 43162306a36Sopenharmony_ci if (ret < 0) { 43262306a36Sopenharmony_ci dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n", 43362306a36Sopenharmony_ci as3722_reg_lookup[id].control_reg, ret); 43462306a36Sopenharmony_ci return ret; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (val & as3722_reg_lookup[id].mode_mask) 43862306a36Sopenharmony_ci return REGULATOR_MODE_FAST; 43962306a36Sopenharmony_ci else 44062306a36Sopenharmony_ci return REGULATOR_MODE_NORMAL; 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cistatic int as3722_sd_set_mode(struct regulator_dev *rdev, 44462306a36Sopenharmony_ci unsigned int mode) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev); 44762306a36Sopenharmony_ci struct as3722 *as3722 = as3722_regs->as3722; 44862306a36Sopenharmony_ci u8 id = rdev_get_id(rdev); 44962306a36Sopenharmony_ci u8 val = 0; 45062306a36Sopenharmony_ci int ret; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci if (!as3722_reg_lookup[id].control_reg) 45362306a36Sopenharmony_ci return -ERANGE; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci switch (mode) { 45662306a36Sopenharmony_ci case REGULATOR_MODE_FAST: 45762306a36Sopenharmony_ci val = as3722_reg_lookup[id].mode_mask; 45862306a36Sopenharmony_ci fallthrough; 45962306a36Sopenharmony_ci case REGULATOR_MODE_NORMAL: 46062306a36Sopenharmony_ci break; 46162306a36Sopenharmony_ci default: 46262306a36Sopenharmony_ci return -EINVAL; 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci ret = as3722_update_bits(as3722, as3722_reg_lookup[id].control_reg, 46662306a36Sopenharmony_ci as3722_reg_lookup[id].mode_mask, val); 46762306a36Sopenharmony_ci if (ret < 0) { 46862306a36Sopenharmony_ci dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n", 46962306a36Sopenharmony_ci as3722_reg_lookup[id].control_reg, ret); 47062306a36Sopenharmony_ci return ret; 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci return ret; 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic bool as3722_sd0_is_low_voltage(struct as3722_regulators *as3722_regs) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci int err; 47862306a36Sopenharmony_ci unsigned val; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci err = as3722_read(as3722_regs->as3722, AS3722_FUSE7_REG, &val); 48162306a36Sopenharmony_ci if (err < 0) { 48262306a36Sopenharmony_ci dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n", 48362306a36Sopenharmony_ci AS3722_FUSE7_REG, err); 48462306a36Sopenharmony_ci return false; 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci if (val & AS3722_FUSE7_SD0_LOW_VOLTAGE) 48762306a36Sopenharmony_ci return true; 48862306a36Sopenharmony_ci return false; 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_cistatic const struct linear_range as3722_sd2345_ranges[] = { 49262306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0), 49362306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500), 49462306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000), 49562306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7F, 50000), 49662306a36Sopenharmony_ci}; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_cistatic const struct regulator_ops as3722_sd016_ops = { 49962306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 50062306a36Sopenharmony_ci .enable = regulator_enable_regmap, 50162306a36Sopenharmony_ci .disable = regulator_disable_regmap, 50262306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 50362306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_linear, 50462306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 50562306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 50662306a36Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 50762306a36Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 50862306a36Sopenharmony_ci .get_mode = as3722_sd_get_mode, 50962306a36Sopenharmony_ci .set_mode = as3722_sd_set_mode, 51062306a36Sopenharmony_ci}; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_cistatic const struct regulator_ops as3722_sd016_extcntrl_ops = { 51362306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 51462306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_linear, 51562306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 51662306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 51762306a36Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 51862306a36Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 51962306a36Sopenharmony_ci .get_mode = as3722_sd_get_mode, 52062306a36Sopenharmony_ci .set_mode = as3722_sd_set_mode, 52162306a36Sopenharmony_ci}; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic const struct regulator_ops as3722_sd2345_ops = { 52462306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 52562306a36Sopenharmony_ci .enable = regulator_enable_regmap, 52662306a36Sopenharmony_ci .disable = regulator_disable_regmap, 52762306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 52862306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 52962306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 53062306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 53162306a36Sopenharmony_ci .get_mode = as3722_sd_get_mode, 53262306a36Sopenharmony_ci .set_mode = as3722_sd_set_mode, 53362306a36Sopenharmony_ci}; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_cistatic const struct regulator_ops as3722_sd2345_extcntrl_ops = { 53662306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 53762306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 53862306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 53962306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 54062306a36Sopenharmony_ci .get_mode = as3722_sd_get_mode, 54162306a36Sopenharmony_ci .set_mode = as3722_sd_set_mode, 54262306a36Sopenharmony_ci}; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_cistatic int as3722_extreg_init(struct as3722_regulators *as3722_regs, int id, 54562306a36Sopenharmony_ci int ext_pwr_ctrl) 54662306a36Sopenharmony_ci{ 54762306a36Sopenharmony_ci int ret; 54862306a36Sopenharmony_ci unsigned int val; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci if ((ext_pwr_ctrl < AS3722_EXT_CONTROL_ENABLE1) || 55162306a36Sopenharmony_ci (ext_pwr_ctrl > AS3722_EXT_CONTROL_ENABLE3)) 55262306a36Sopenharmony_ci return -EINVAL; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci val = ext_pwr_ctrl << (ffs(as3722_reg_lookup[id].sleep_ctrl_mask) - 1); 55562306a36Sopenharmony_ci ret = as3722_update_bits(as3722_regs->as3722, 55662306a36Sopenharmony_ci as3722_reg_lookup[id].sleep_ctrl_reg, 55762306a36Sopenharmony_ci as3722_reg_lookup[id].sleep_ctrl_mask, val); 55862306a36Sopenharmony_ci if (ret < 0) 55962306a36Sopenharmony_ci dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n", 56062306a36Sopenharmony_ci as3722_reg_lookup[id].sleep_ctrl_reg, ret); 56162306a36Sopenharmony_ci return ret; 56262306a36Sopenharmony_ci} 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_cistatic struct of_regulator_match as3722_regulator_matches[] = { 56562306a36Sopenharmony_ci { .name = "sd0", }, 56662306a36Sopenharmony_ci { .name = "sd1", }, 56762306a36Sopenharmony_ci { .name = "sd2", }, 56862306a36Sopenharmony_ci { .name = "sd3", }, 56962306a36Sopenharmony_ci { .name = "sd4", }, 57062306a36Sopenharmony_ci { .name = "sd5", }, 57162306a36Sopenharmony_ci { .name = "sd6", }, 57262306a36Sopenharmony_ci { .name = "ldo0", }, 57362306a36Sopenharmony_ci { .name = "ldo1", }, 57462306a36Sopenharmony_ci { .name = "ldo2", }, 57562306a36Sopenharmony_ci { .name = "ldo3", }, 57662306a36Sopenharmony_ci { .name = "ldo4", }, 57762306a36Sopenharmony_ci { .name = "ldo5", }, 57862306a36Sopenharmony_ci { .name = "ldo6", }, 57962306a36Sopenharmony_ci { .name = "ldo7", }, 58062306a36Sopenharmony_ci { .name = "ldo9", }, 58162306a36Sopenharmony_ci { .name = "ldo10", }, 58262306a36Sopenharmony_ci { .name = "ldo11", }, 58362306a36Sopenharmony_ci}; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_cistatic int as3722_get_regulator_dt_data(struct platform_device *pdev, 58662306a36Sopenharmony_ci struct as3722_regulators *as3722_regs) 58762306a36Sopenharmony_ci{ 58862306a36Sopenharmony_ci struct device_node *np; 58962306a36Sopenharmony_ci struct as3722_regulator_config_data *reg_config; 59062306a36Sopenharmony_ci u32 prop; 59162306a36Sopenharmony_ci int id; 59262306a36Sopenharmony_ci int ret; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators"); 59562306a36Sopenharmony_ci if (!np) { 59662306a36Sopenharmony_ci dev_err(&pdev->dev, "Device is not having regulators node\n"); 59762306a36Sopenharmony_ci return -ENODEV; 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci pdev->dev.of_node = np; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches, 60262306a36Sopenharmony_ci ARRAY_SIZE(as3722_regulator_matches)); 60362306a36Sopenharmony_ci of_node_put(np); 60462306a36Sopenharmony_ci if (ret < 0) { 60562306a36Sopenharmony_ci dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n", 60662306a36Sopenharmony_ci ret); 60762306a36Sopenharmony_ci return ret; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci for (id = 0; id < ARRAY_SIZE(as3722_regulator_matches); ++id) { 61162306a36Sopenharmony_ci struct device_node *reg_node; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci reg_config = &as3722_regs->reg_config_data[id]; 61462306a36Sopenharmony_ci reg_config->reg_init = as3722_regulator_matches[id].init_data; 61562306a36Sopenharmony_ci reg_node = as3722_regulator_matches[id].of_node; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci if (!reg_config->reg_init || !reg_node) 61862306a36Sopenharmony_ci continue; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci ret = of_property_read_u32(reg_node, "ams,ext-control", &prop); 62162306a36Sopenharmony_ci if (!ret) { 62262306a36Sopenharmony_ci if (prop < 3) 62362306a36Sopenharmony_ci reg_config->ext_control = prop; 62462306a36Sopenharmony_ci else 62562306a36Sopenharmony_ci dev_warn(&pdev->dev, 62662306a36Sopenharmony_ci "ext-control have invalid option: %u\n", 62762306a36Sopenharmony_ci prop); 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci reg_config->enable_tracking = 63062306a36Sopenharmony_ci of_property_read_bool(reg_node, "ams,enable-tracking"); 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci return 0; 63362306a36Sopenharmony_ci} 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_cistatic int as3722_regulator_probe(struct platform_device *pdev) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent); 63862306a36Sopenharmony_ci struct as3722_regulators *as3722_regs; 63962306a36Sopenharmony_ci struct as3722_regulator_config_data *reg_config; 64062306a36Sopenharmony_ci struct regulator_dev *rdev; 64162306a36Sopenharmony_ci struct regulator_config config = { }; 64262306a36Sopenharmony_ci const struct regulator_ops *ops; 64362306a36Sopenharmony_ci int id; 64462306a36Sopenharmony_ci int ret; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci as3722_regs = devm_kzalloc(&pdev->dev, sizeof(*as3722_regs), 64762306a36Sopenharmony_ci GFP_KERNEL); 64862306a36Sopenharmony_ci if (!as3722_regs) 64962306a36Sopenharmony_ci return -ENOMEM; 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci as3722_regs->dev = &pdev->dev; 65262306a36Sopenharmony_ci as3722_regs->as3722 = as3722; 65362306a36Sopenharmony_ci platform_set_drvdata(pdev, as3722_regs); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci ret = as3722_get_regulator_dt_data(pdev, as3722_regs); 65662306a36Sopenharmony_ci if (ret < 0) 65762306a36Sopenharmony_ci return ret; 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci config.dev = &pdev->dev; 66062306a36Sopenharmony_ci config.driver_data = as3722_regs; 66162306a36Sopenharmony_ci config.regmap = as3722->regmap; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci for (id = 0; id < AS3722_REGULATOR_ID_MAX; id++) { 66462306a36Sopenharmony_ci struct regulator_desc *desc; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci desc = &as3722_regs->desc[id]; 66762306a36Sopenharmony_ci reg_config = &as3722_regs->reg_config_data[id]; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci desc->name = as3722_reg_lookup[id].name; 67062306a36Sopenharmony_ci desc->supply_name = as3722_reg_lookup[id].sname; 67162306a36Sopenharmony_ci desc->id = as3722_reg_lookup[id].regulator_id; 67262306a36Sopenharmony_ci desc->n_voltages = as3722_reg_lookup[id].n_voltages; 67362306a36Sopenharmony_ci desc->type = REGULATOR_VOLTAGE; 67462306a36Sopenharmony_ci desc->owner = THIS_MODULE; 67562306a36Sopenharmony_ci desc->enable_reg = as3722_reg_lookup[id].enable_reg; 67662306a36Sopenharmony_ci desc->enable_mask = as3722_reg_lookup[id].enable_mask; 67762306a36Sopenharmony_ci desc->vsel_reg = as3722_reg_lookup[id].vsel_reg; 67862306a36Sopenharmony_ci desc->vsel_mask = as3722_reg_lookup[id].vsel_mask; 67962306a36Sopenharmony_ci switch (id) { 68062306a36Sopenharmony_ci case AS3722_REGULATOR_ID_LDO0: 68162306a36Sopenharmony_ci if (reg_config->ext_control) 68262306a36Sopenharmony_ci ops = &as3722_ldo0_extcntrl_ops; 68362306a36Sopenharmony_ci else 68462306a36Sopenharmony_ci ops = &as3722_ldo0_ops; 68562306a36Sopenharmony_ci desc->min_uV = 825000; 68662306a36Sopenharmony_ci desc->uV_step = 25000; 68762306a36Sopenharmony_ci desc->linear_min_sel = 1; 68862306a36Sopenharmony_ci desc->enable_time = 500; 68962306a36Sopenharmony_ci desc->curr_table = as3722_ldo_current; 69062306a36Sopenharmony_ci desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current); 69162306a36Sopenharmony_ci desc->csel_reg = as3722_reg_lookup[id].vsel_reg; 69262306a36Sopenharmony_ci desc->csel_mask = AS3722_LDO_ILIMIT_MASK; 69362306a36Sopenharmony_ci break; 69462306a36Sopenharmony_ci case AS3722_REGULATOR_ID_LDO3: 69562306a36Sopenharmony_ci if (reg_config->ext_control) 69662306a36Sopenharmony_ci ops = &as3722_ldo3_extcntrl_ops; 69762306a36Sopenharmony_ci else 69862306a36Sopenharmony_ci ops = &as3722_ldo3_ops; 69962306a36Sopenharmony_ci desc->min_uV = 620000; 70062306a36Sopenharmony_ci desc->uV_step = 20000; 70162306a36Sopenharmony_ci desc->linear_min_sel = 1; 70262306a36Sopenharmony_ci desc->enable_time = 500; 70362306a36Sopenharmony_ci if (reg_config->enable_tracking) { 70462306a36Sopenharmony_ci ret = as3722_ldo3_set_tracking_mode(as3722_regs, 70562306a36Sopenharmony_ci id, AS3722_LDO3_MODE_PMOS_TRACKING); 70662306a36Sopenharmony_ci if (ret < 0) { 70762306a36Sopenharmony_ci dev_err(&pdev->dev, 70862306a36Sopenharmony_ci "LDO3 tracking failed: %d\n", 70962306a36Sopenharmony_ci ret); 71062306a36Sopenharmony_ci return ret; 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci break; 71462306a36Sopenharmony_ci case AS3722_REGULATOR_ID_LDO6: 71562306a36Sopenharmony_ci if (reg_config->ext_control) 71662306a36Sopenharmony_ci ops = &as3722_ldo6_extcntrl_ops; 71762306a36Sopenharmony_ci else 71862306a36Sopenharmony_ci ops = &as3722_ldo6_ops; 71962306a36Sopenharmony_ci desc->enable_time = 500; 72062306a36Sopenharmony_ci desc->bypass_reg = AS3722_LDO6_VOLTAGE_REG; 72162306a36Sopenharmony_ci desc->bypass_mask = AS3722_LDO_VSEL_MASK; 72262306a36Sopenharmony_ci desc->bypass_val_on = AS3722_LDO6_VSEL_BYPASS; 72362306a36Sopenharmony_ci desc->bypass_val_off = AS3722_LDO6_VSEL_BYPASS; 72462306a36Sopenharmony_ci desc->linear_ranges = as3722_ldo_ranges; 72562306a36Sopenharmony_ci desc->n_linear_ranges = ARRAY_SIZE(as3722_ldo_ranges); 72662306a36Sopenharmony_ci desc->curr_table = as3722_ldo_current; 72762306a36Sopenharmony_ci desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current); 72862306a36Sopenharmony_ci desc->csel_reg = as3722_reg_lookup[id].vsel_reg; 72962306a36Sopenharmony_ci desc->csel_mask = AS3722_LDO_ILIMIT_MASK; 73062306a36Sopenharmony_ci break; 73162306a36Sopenharmony_ci case AS3722_REGULATOR_ID_SD0: 73262306a36Sopenharmony_ci case AS3722_REGULATOR_ID_SD1: 73362306a36Sopenharmony_ci case AS3722_REGULATOR_ID_SD6: 73462306a36Sopenharmony_ci if (reg_config->ext_control) 73562306a36Sopenharmony_ci ops = &as3722_sd016_extcntrl_ops; 73662306a36Sopenharmony_ci else 73762306a36Sopenharmony_ci ops = &as3722_sd016_ops; 73862306a36Sopenharmony_ci if (id == AS3722_REGULATOR_ID_SD0 && 73962306a36Sopenharmony_ci as3722_sd0_is_low_voltage(as3722_regs)) { 74062306a36Sopenharmony_ci as3722_regs->desc[id].n_voltages = 74162306a36Sopenharmony_ci AS3722_SD0_VSEL_LOW_VOL_MAX + 1; 74262306a36Sopenharmony_ci as3722_regs->desc[id].min_uV = 410000; 74362306a36Sopenharmony_ci } else { 74462306a36Sopenharmony_ci as3722_regs->desc[id].n_voltages = 74562306a36Sopenharmony_ci AS3722_SD0_VSEL_MAX + 1; 74662306a36Sopenharmony_ci as3722_regs->desc[id].min_uV = 610000; 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci desc->uV_step = 10000; 74962306a36Sopenharmony_ci desc->linear_min_sel = 1; 75062306a36Sopenharmony_ci desc->enable_time = 600; 75162306a36Sopenharmony_ci desc->curr_table = as3722_sd016_current; 75262306a36Sopenharmony_ci desc->n_current_limits = 75362306a36Sopenharmony_ci ARRAY_SIZE(as3722_sd016_current); 75462306a36Sopenharmony_ci if (id == AS3722_REGULATOR_ID_SD0) { 75562306a36Sopenharmony_ci desc->csel_reg = AS3722_OVCURRENT_REG; 75662306a36Sopenharmony_ci desc->csel_mask = 75762306a36Sopenharmony_ci AS3722_OVCURRENT_SD0_TRIP_MASK; 75862306a36Sopenharmony_ci } else if (id == AS3722_REGULATOR_ID_SD1) { 75962306a36Sopenharmony_ci desc->csel_reg = AS3722_OVCURRENT_REG; 76062306a36Sopenharmony_ci desc->csel_mask = 76162306a36Sopenharmony_ci AS3722_OVCURRENT_SD1_TRIP_MASK; 76262306a36Sopenharmony_ci } else if (id == AS3722_REGULATOR_ID_SD6) { 76362306a36Sopenharmony_ci desc->csel_reg = AS3722_OVCURRENT_DEB_REG; 76462306a36Sopenharmony_ci desc->csel_mask = 76562306a36Sopenharmony_ci AS3722_OVCURRENT_SD6_TRIP_MASK; 76662306a36Sopenharmony_ci } 76762306a36Sopenharmony_ci break; 76862306a36Sopenharmony_ci case AS3722_REGULATOR_ID_SD2: 76962306a36Sopenharmony_ci case AS3722_REGULATOR_ID_SD3: 77062306a36Sopenharmony_ci case AS3722_REGULATOR_ID_SD4: 77162306a36Sopenharmony_ci case AS3722_REGULATOR_ID_SD5: 77262306a36Sopenharmony_ci if (reg_config->ext_control) 77362306a36Sopenharmony_ci ops = &as3722_sd2345_extcntrl_ops; 77462306a36Sopenharmony_ci else 77562306a36Sopenharmony_ci ops = &as3722_sd2345_ops; 77662306a36Sopenharmony_ci desc->linear_ranges = as3722_sd2345_ranges; 77762306a36Sopenharmony_ci desc->n_linear_ranges = 77862306a36Sopenharmony_ci ARRAY_SIZE(as3722_sd2345_ranges); 77962306a36Sopenharmony_ci break; 78062306a36Sopenharmony_ci default: 78162306a36Sopenharmony_ci if (reg_config->ext_control) 78262306a36Sopenharmony_ci ops = &as3722_ldo_extcntrl_ops; 78362306a36Sopenharmony_ci else 78462306a36Sopenharmony_ci ops = &as3722_ldo_ops; 78562306a36Sopenharmony_ci desc->enable_time = 500; 78662306a36Sopenharmony_ci desc->linear_ranges = as3722_ldo_ranges; 78762306a36Sopenharmony_ci desc->n_linear_ranges = ARRAY_SIZE(as3722_ldo_ranges); 78862306a36Sopenharmony_ci desc->curr_table = as3722_ldo_current; 78962306a36Sopenharmony_ci desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current); 79062306a36Sopenharmony_ci desc->csel_reg = as3722_reg_lookup[id].vsel_reg; 79162306a36Sopenharmony_ci desc->csel_mask = AS3722_LDO_ILIMIT_MASK; 79262306a36Sopenharmony_ci break; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci desc->ops = ops; 79562306a36Sopenharmony_ci config.init_data = reg_config->reg_init; 79662306a36Sopenharmony_ci config.of_node = as3722_regulator_matches[id].of_node; 79762306a36Sopenharmony_ci rdev = devm_regulator_register(&pdev->dev, desc, &config); 79862306a36Sopenharmony_ci if (IS_ERR(rdev)) { 79962306a36Sopenharmony_ci ret = PTR_ERR(rdev); 80062306a36Sopenharmony_ci dev_err(&pdev->dev, "regulator %d register failed %d\n", 80162306a36Sopenharmony_ci id, ret); 80262306a36Sopenharmony_ci return ret; 80362306a36Sopenharmony_ci } 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci if (reg_config->ext_control) { 80662306a36Sopenharmony_ci ret = regulator_enable_regmap(rdev); 80762306a36Sopenharmony_ci if (ret < 0) { 80862306a36Sopenharmony_ci dev_err(&pdev->dev, 80962306a36Sopenharmony_ci "Regulator %d enable failed: %d\n", 81062306a36Sopenharmony_ci id, ret); 81162306a36Sopenharmony_ci return ret; 81262306a36Sopenharmony_ci } 81362306a36Sopenharmony_ci ret = as3722_extreg_init(as3722_regs, id, 81462306a36Sopenharmony_ci reg_config->ext_control); 81562306a36Sopenharmony_ci if (ret < 0) { 81662306a36Sopenharmony_ci dev_err(&pdev->dev, 81762306a36Sopenharmony_ci "AS3722 ext control failed: %d", ret); 81862306a36Sopenharmony_ci return ret; 81962306a36Sopenharmony_ci } 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci } 82262306a36Sopenharmony_ci return 0; 82362306a36Sopenharmony_ci} 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_cistatic const struct of_device_id of_as3722_regulator_match[] = { 82662306a36Sopenharmony_ci { .compatible = "ams,as3722-regulator", }, 82762306a36Sopenharmony_ci {}, 82862306a36Sopenharmony_ci}; 82962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_as3722_regulator_match); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_cistatic struct platform_driver as3722_regulator_driver = { 83262306a36Sopenharmony_ci .driver = { 83362306a36Sopenharmony_ci .name = "as3722-regulator", 83462306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 83562306a36Sopenharmony_ci .of_match_table = of_as3722_regulator_match, 83662306a36Sopenharmony_ci }, 83762306a36Sopenharmony_ci .probe = as3722_regulator_probe, 83862306a36Sopenharmony_ci}; 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_cimodule_platform_driver(as3722_regulator_driver); 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ciMODULE_ALIAS("platform:as3722-regulator"); 84362306a36Sopenharmony_ciMODULE_DESCRIPTION("AS3722 regulator driver"); 84462306a36Sopenharmony_ciMODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>"); 84562306a36Sopenharmony_ciMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 84662306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 847