162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * tps65910.c -- TI tps65910 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2010 Texas Instruments Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Graeme Gregory <gg@slimlogic.co.uk> 862306a36Sopenharmony_ci * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/err.h> 1562306a36Sopenharmony_ci#include <linux/of.h> 1662306a36Sopenharmony_ci#include <linux/platform_device.h> 1762306a36Sopenharmony_ci#include <linux/regulator/driver.h> 1862306a36Sopenharmony_ci#include <linux/regulator/machine.h> 1962306a36Sopenharmony_ci#include <linux/slab.h> 2062306a36Sopenharmony_ci#include <linux/mfd/tps65910.h> 2162306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define TPS65910_SUPPLY_STATE_ENABLED 0x1 2462306a36Sopenharmony_ci#define EXT_SLEEP_CONTROL (TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1 | \ 2562306a36Sopenharmony_ci TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2 | \ 2662306a36Sopenharmony_ci TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3 | \ 2762306a36Sopenharmony_ci TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* supported VIO voltages in microvolts */ 3062306a36Sopenharmony_cistatic const unsigned int VIO_VSEL_table[] = { 3162306a36Sopenharmony_ci 1500000, 1800000, 2500000, 3300000, 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* VSEL tables for TPS65910 specific LDOs and dcdc's */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* supported VRTC voltages in microvolts */ 3762306a36Sopenharmony_cistatic const unsigned int VRTC_VSEL_table[] = { 3862306a36Sopenharmony_ci 1800000, 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* supported VDD3 voltages in microvolts */ 4262306a36Sopenharmony_cistatic const unsigned int VDD3_VSEL_table[] = { 4362306a36Sopenharmony_ci 5000000, 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* supported VDIG1 voltages in microvolts */ 4762306a36Sopenharmony_cistatic const unsigned int VDIG1_VSEL_table[] = { 4862306a36Sopenharmony_ci 1200000, 1500000, 1800000, 2700000, 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* supported VDIG2 voltages in microvolts */ 5262306a36Sopenharmony_cistatic const unsigned int VDIG2_VSEL_table[] = { 5362306a36Sopenharmony_ci 1000000, 1100000, 1200000, 1800000, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* supported VPLL voltages in microvolts */ 5762306a36Sopenharmony_cistatic const unsigned int VPLL_VSEL_table[] = { 5862306a36Sopenharmony_ci 1000000, 1100000, 1800000, 2500000, 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* supported VDAC voltages in microvolts */ 6262306a36Sopenharmony_cistatic const unsigned int VDAC_VSEL_table[] = { 6362306a36Sopenharmony_ci 1800000, 2600000, 2800000, 2850000, 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* supported VAUX1 voltages in microvolts */ 6762306a36Sopenharmony_cistatic const unsigned int VAUX1_VSEL_table[] = { 6862306a36Sopenharmony_ci 1800000, 2500000, 2800000, 2850000, 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* supported VAUX2 voltages in microvolts */ 7262306a36Sopenharmony_cistatic const unsigned int VAUX2_VSEL_table[] = { 7362306a36Sopenharmony_ci 1800000, 2800000, 2900000, 3300000, 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* supported VAUX33 voltages in microvolts */ 7762306a36Sopenharmony_cistatic const unsigned int VAUX33_VSEL_table[] = { 7862306a36Sopenharmony_ci 1800000, 2000000, 2800000, 3300000, 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* supported VMMC voltages in microvolts */ 8262306a36Sopenharmony_cistatic const unsigned int VMMC_VSEL_table[] = { 8362306a36Sopenharmony_ci 1800000, 2800000, 3000000, 3300000, 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* supported BBCH voltages in microvolts */ 8762306a36Sopenharmony_cistatic const unsigned int VBB_VSEL_table[] = { 8862306a36Sopenharmony_ci 3000000, 2520000, 3150000, 5000000, 8962306a36Sopenharmony_ci}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistruct tps_info { 9262306a36Sopenharmony_ci const char *name; 9362306a36Sopenharmony_ci const char *vin_name; 9462306a36Sopenharmony_ci u8 n_voltages; 9562306a36Sopenharmony_ci const unsigned int *voltage_table; 9662306a36Sopenharmony_ci int enable_time_us; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic struct tps_info tps65910_regs[] = { 10062306a36Sopenharmony_ci { 10162306a36Sopenharmony_ci .name = "vrtc", 10262306a36Sopenharmony_ci .vin_name = "vcc7", 10362306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VRTC_VSEL_table), 10462306a36Sopenharmony_ci .voltage_table = VRTC_VSEL_table, 10562306a36Sopenharmony_ci .enable_time_us = 2200, 10662306a36Sopenharmony_ci }, 10762306a36Sopenharmony_ci { 10862306a36Sopenharmony_ci .name = "vio", 10962306a36Sopenharmony_ci .vin_name = "vccio", 11062306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VIO_VSEL_table), 11162306a36Sopenharmony_ci .voltage_table = VIO_VSEL_table, 11262306a36Sopenharmony_ci .enable_time_us = 350, 11362306a36Sopenharmony_ci }, 11462306a36Sopenharmony_ci { 11562306a36Sopenharmony_ci .name = "vdd1", 11662306a36Sopenharmony_ci .vin_name = "vcc1", 11762306a36Sopenharmony_ci .enable_time_us = 350, 11862306a36Sopenharmony_ci }, 11962306a36Sopenharmony_ci { 12062306a36Sopenharmony_ci .name = "vdd2", 12162306a36Sopenharmony_ci .vin_name = "vcc2", 12262306a36Sopenharmony_ci .enable_time_us = 350, 12362306a36Sopenharmony_ci }, 12462306a36Sopenharmony_ci { 12562306a36Sopenharmony_ci .name = "vdd3", 12662306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VDD3_VSEL_table), 12762306a36Sopenharmony_ci .voltage_table = VDD3_VSEL_table, 12862306a36Sopenharmony_ci .enable_time_us = 200, 12962306a36Sopenharmony_ci }, 13062306a36Sopenharmony_ci { 13162306a36Sopenharmony_ci .name = "vdig1", 13262306a36Sopenharmony_ci .vin_name = "vcc6", 13362306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VDIG1_VSEL_table), 13462306a36Sopenharmony_ci .voltage_table = VDIG1_VSEL_table, 13562306a36Sopenharmony_ci .enable_time_us = 100, 13662306a36Sopenharmony_ci }, 13762306a36Sopenharmony_ci { 13862306a36Sopenharmony_ci .name = "vdig2", 13962306a36Sopenharmony_ci .vin_name = "vcc6", 14062306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VDIG2_VSEL_table), 14162306a36Sopenharmony_ci .voltage_table = VDIG2_VSEL_table, 14262306a36Sopenharmony_ci .enable_time_us = 100, 14362306a36Sopenharmony_ci }, 14462306a36Sopenharmony_ci { 14562306a36Sopenharmony_ci .name = "vpll", 14662306a36Sopenharmony_ci .vin_name = "vcc5", 14762306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VPLL_VSEL_table), 14862306a36Sopenharmony_ci .voltage_table = VPLL_VSEL_table, 14962306a36Sopenharmony_ci .enable_time_us = 100, 15062306a36Sopenharmony_ci }, 15162306a36Sopenharmony_ci { 15262306a36Sopenharmony_ci .name = "vdac", 15362306a36Sopenharmony_ci .vin_name = "vcc5", 15462306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VDAC_VSEL_table), 15562306a36Sopenharmony_ci .voltage_table = VDAC_VSEL_table, 15662306a36Sopenharmony_ci .enable_time_us = 100, 15762306a36Sopenharmony_ci }, 15862306a36Sopenharmony_ci { 15962306a36Sopenharmony_ci .name = "vaux1", 16062306a36Sopenharmony_ci .vin_name = "vcc4", 16162306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VAUX1_VSEL_table), 16262306a36Sopenharmony_ci .voltage_table = VAUX1_VSEL_table, 16362306a36Sopenharmony_ci .enable_time_us = 100, 16462306a36Sopenharmony_ci }, 16562306a36Sopenharmony_ci { 16662306a36Sopenharmony_ci .name = "vaux2", 16762306a36Sopenharmony_ci .vin_name = "vcc4", 16862306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VAUX2_VSEL_table), 16962306a36Sopenharmony_ci .voltage_table = VAUX2_VSEL_table, 17062306a36Sopenharmony_ci .enable_time_us = 100, 17162306a36Sopenharmony_ci }, 17262306a36Sopenharmony_ci { 17362306a36Sopenharmony_ci .name = "vaux33", 17462306a36Sopenharmony_ci .vin_name = "vcc3", 17562306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VAUX33_VSEL_table), 17662306a36Sopenharmony_ci .voltage_table = VAUX33_VSEL_table, 17762306a36Sopenharmony_ci .enable_time_us = 100, 17862306a36Sopenharmony_ci }, 17962306a36Sopenharmony_ci { 18062306a36Sopenharmony_ci .name = "vmmc", 18162306a36Sopenharmony_ci .vin_name = "vcc3", 18262306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VMMC_VSEL_table), 18362306a36Sopenharmony_ci .voltage_table = VMMC_VSEL_table, 18462306a36Sopenharmony_ci .enable_time_us = 100, 18562306a36Sopenharmony_ci }, 18662306a36Sopenharmony_ci { 18762306a36Sopenharmony_ci .name = "vbb", 18862306a36Sopenharmony_ci .vin_name = "vcc7", 18962306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VBB_VSEL_table), 19062306a36Sopenharmony_ci .voltage_table = VBB_VSEL_table, 19162306a36Sopenharmony_ci }, 19262306a36Sopenharmony_ci}; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic struct tps_info tps65911_regs[] = { 19562306a36Sopenharmony_ci { 19662306a36Sopenharmony_ci .name = "vrtc", 19762306a36Sopenharmony_ci .vin_name = "vcc7", 19862306a36Sopenharmony_ci .enable_time_us = 2200, 19962306a36Sopenharmony_ci }, 20062306a36Sopenharmony_ci { 20162306a36Sopenharmony_ci .name = "vio", 20262306a36Sopenharmony_ci .vin_name = "vccio", 20362306a36Sopenharmony_ci .n_voltages = ARRAY_SIZE(VIO_VSEL_table), 20462306a36Sopenharmony_ci .voltage_table = VIO_VSEL_table, 20562306a36Sopenharmony_ci .enable_time_us = 350, 20662306a36Sopenharmony_ci }, 20762306a36Sopenharmony_ci { 20862306a36Sopenharmony_ci .name = "vdd1", 20962306a36Sopenharmony_ci .vin_name = "vcc1", 21062306a36Sopenharmony_ci .n_voltages = 0x4C, 21162306a36Sopenharmony_ci .enable_time_us = 350, 21262306a36Sopenharmony_ci }, 21362306a36Sopenharmony_ci { 21462306a36Sopenharmony_ci .name = "vdd2", 21562306a36Sopenharmony_ci .vin_name = "vcc2", 21662306a36Sopenharmony_ci .n_voltages = 0x4C, 21762306a36Sopenharmony_ci .enable_time_us = 350, 21862306a36Sopenharmony_ci }, 21962306a36Sopenharmony_ci { 22062306a36Sopenharmony_ci .name = "vddctrl", 22162306a36Sopenharmony_ci .n_voltages = 0x44, 22262306a36Sopenharmony_ci .enable_time_us = 900, 22362306a36Sopenharmony_ci }, 22462306a36Sopenharmony_ci { 22562306a36Sopenharmony_ci .name = "ldo1", 22662306a36Sopenharmony_ci .vin_name = "vcc6", 22762306a36Sopenharmony_ci .n_voltages = 0x33, 22862306a36Sopenharmony_ci .enable_time_us = 420, 22962306a36Sopenharmony_ci }, 23062306a36Sopenharmony_ci { 23162306a36Sopenharmony_ci .name = "ldo2", 23262306a36Sopenharmony_ci .vin_name = "vcc6", 23362306a36Sopenharmony_ci .n_voltages = 0x33, 23462306a36Sopenharmony_ci .enable_time_us = 420, 23562306a36Sopenharmony_ci }, 23662306a36Sopenharmony_ci { 23762306a36Sopenharmony_ci .name = "ldo3", 23862306a36Sopenharmony_ci .vin_name = "vcc5", 23962306a36Sopenharmony_ci .n_voltages = 0x1A, 24062306a36Sopenharmony_ci .enable_time_us = 230, 24162306a36Sopenharmony_ci }, 24262306a36Sopenharmony_ci { 24362306a36Sopenharmony_ci .name = "ldo4", 24462306a36Sopenharmony_ci .vin_name = "vcc5", 24562306a36Sopenharmony_ci .n_voltages = 0x33, 24662306a36Sopenharmony_ci .enable_time_us = 230, 24762306a36Sopenharmony_ci }, 24862306a36Sopenharmony_ci { 24962306a36Sopenharmony_ci .name = "ldo5", 25062306a36Sopenharmony_ci .vin_name = "vcc4", 25162306a36Sopenharmony_ci .n_voltages = 0x1A, 25262306a36Sopenharmony_ci .enable_time_us = 230, 25362306a36Sopenharmony_ci }, 25462306a36Sopenharmony_ci { 25562306a36Sopenharmony_ci .name = "ldo6", 25662306a36Sopenharmony_ci .vin_name = "vcc3", 25762306a36Sopenharmony_ci .n_voltages = 0x1A, 25862306a36Sopenharmony_ci .enable_time_us = 230, 25962306a36Sopenharmony_ci }, 26062306a36Sopenharmony_ci { 26162306a36Sopenharmony_ci .name = "ldo7", 26262306a36Sopenharmony_ci .vin_name = "vcc3", 26362306a36Sopenharmony_ci .n_voltages = 0x1A, 26462306a36Sopenharmony_ci .enable_time_us = 230, 26562306a36Sopenharmony_ci }, 26662306a36Sopenharmony_ci { 26762306a36Sopenharmony_ci .name = "ldo8", 26862306a36Sopenharmony_ci .vin_name = "vcc3", 26962306a36Sopenharmony_ci .n_voltages = 0x1A, 27062306a36Sopenharmony_ci .enable_time_us = 230, 27162306a36Sopenharmony_ci }, 27262306a36Sopenharmony_ci}; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci#define EXT_CONTROL_REG_BITS(id, regs_offs, bits) (((regs_offs) << 8) | (bits)) 27562306a36Sopenharmony_cistatic unsigned int tps65910_ext_sleep_control[] = { 27662306a36Sopenharmony_ci 0, 27762306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VIO, 1, 0), 27862306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VDD1, 1, 1), 27962306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VDD2, 1, 2), 28062306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VDD3, 1, 3), 28162306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VDIG1, 0, 1), 28262306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VDIG2, 0, 2), 28362306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VPLL, 0, 6), 28462306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VDAC, 0, 7), 28562306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VAUX1, 0, 3), 28662306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VAUX2, 0, 4), 28762306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VAUX33, 0, 5), 28862306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VMMC, 0, 0), 28962306a36Sopenharmony_ci}; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cistatic unsigned int tps65911_ext_sleep_control[] = { 29262306a36Sopenharmony_ci 0, 29362306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VIO, 1, 0), 29462306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VDD1, 1, 1), 29562306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VDD2, 1, 2), 29662306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(VDDCTRL, 1, 3), 29762306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO1, 0, 1), 29862306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO2, 0, 2), 29962306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO3, 0, 7), 30062306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO4, 0, 6), 30162306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO5, 0, 3), 30262306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO6, 0, 0), 30362306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO7, 0, 5), 30462306a36Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO8, 0, 4), 30562306a36Sopenharmony_ci}; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistruct tps65910_reg { 30862306a36Sopenharmony_ci struct regulator_desc *desc; 30962306a36Sopenharmony_ci struct tps65910 *mfd; 31062306a36Sopenharmony_ci struct regulator_dev **rdev; 31162306a36Sopenharmony_ci struct tps_info **info; 31262306a36Sopenharmony_ci int num_regulators; 31362306a36Sopenharmony_ci int mode; 31462306a36Sopenharmony_ci int (*get_ctrl_reg)(int); 31562306a36Sopenharmony_ci unsigned int *ext_sleep_control; 31662306a36Sopenharmony_ci unsigned int board_ext_control[TPS65910_NUM_REGS]; 31762306a36Sopenharmony_ci}; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistatic int tps65910_get_ctrl_register(int id) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci switch (id) { 32262306a36Sopenharmony_ci case TPS65910_REG_VRTC: 32362306a36Sopenharmony_ci return TPS65910_VRTC; 32462306a36Sopenharmony_ci case TPS65910_REG_VIO: 32562306a36Sopenharmony_ci return TPS65910_VIO; 32662306a36Sopenharmony_ci case TPS65910_REG_VDD1: 32762306a36Sopenharmony_ci return TPS65910_VDD1; 32862306a36Sopenharmony_ci case TPS65910_REG_VDD2: 32962306a36Sopenharmony_ci return TPS65910_VDD2; 33062306a36Sopenharmony_ci case TPS65910_REG_VDD3: 33162306a36Sopenharmony_ci return TPS65910_VDD3; 33262306a36Sopenharmony_ci case TPS65910_REG_VDIG1: 33362306a36Sopenharmony_ci return TPS65910_VDIG1; 33462306a36Sopenharmony_ci case TPS65910_REG_VDIG2: 33562306a36Sopenharmony_ci return TPS65910_VDIG2; 33662306a36Sopenharmony_ci case TPS65910_REG_VPLL: 33762306a36Sopenharmony_ci return TPS65910_VPLL; 33862306a36Sopenharmony_ci case TPS65910_REG_VDAC: 33962306a36Sopenharmony_ci return TPS65910_VDAC; 34062306a36Sopenharmony_ci case TPS65910_REG_VAUX1: 34162306a36Sopenharmony_ci return TPS65910_VAUX1; 34262306a36Sopenharmony_ci case TPS65910_REG_VAUX2: 34362306a36Sopenharmony_ci return TPS65910_VAUX2; 34462306a36Sopenharmony_ci case TPS65910_REG_VAUX33: 34562306a36Sopenharmony_ci return TPS65910_VAUX33; 34662306a36Sopenharmony_ci case TPS65910_REG_VMMC: 34762306a36Sopenharmony_ci return TPS65910_VMMC; 34862306a36Sopenharmony_ci case TPS65910_REG_VBB: 34962306a36Sopenharmony_ci return TPS65910_BBCH; 35062306a36Sopenharmony_ci default: 35162306a36Sopenharmony_ci return -EINVAL; 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic int tps65911_get_ctrl_register(int id) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci switch (id) { 35862306a36Sopenharmony_ci case TPS65910_REG_VRTC: 35962306a36Sopenharmony_ci return TPS65910_VRTC; 36062306a36Sopenharmony_ci case TPS65910_REG_VIO: 36162306a36Sopenharmony_ci return TPS65910_VIO; 36262306a36Sopenharmony_ci case TPS65910_REG_VDD1: 36362306a36Sopenharmony_ci return TPS65910_VDD1; 36462306a36Sopenharmony_ci case TPS65910_REG_VDD2: 36562306a36Sopenharmony_ci return TPS65910_VDD2; 36662306a36Sopenharmony_ci case TPS65911_REG_VDDCTRL: 36762306a36Sopenharmony_ci return TPS65911_VDDCTRL; 36862306a36Sopenharmony_ci case TPS65911_REG_LDO1: 36962306a36Sopenharmony_ci return TPS65911_LDO1; 37062306a36Sopenharmony_ci case TPS65911_REG_LDO2: 37162306a36Sopenharmony_ci return TPS65911_LDO2; 37262306a36Sopenharmony_ci case TPS65911_REG_LDO3: 37362306a36Sopenharmony_ci return TPS65911_LDO3; 37462306a36Sopenharmony_ci case TPS65911_REG_LDO4: 37562306a36Sopenharmony_ci return TPS65911_LDO4; 37662306a36Sopenharmony_ci case TPS65911_REG_LDO5: 37762306a36Sopenharmony_ci return TPS65911_LDO5; 37862306a36Sopenharmony_ci case TPS65911_REG_LDO6: 37962306a36Sopenharmony_ci return TPS65911_LDO6; 38062306a36Sopenharmony_ci case TPS65911_REG_LDO7: 38162306a36Sopenharmony_ci return TPS65911_LDO7; 38262306a36Sopenharmony_ci case TPS65911_REG_LDO8: 38362306a36Sopenharmony_ci return TPS65911_LDO8; 38462306a36Sopenharmony_ci default: 38562306a36Sopenharmony_ci return -EINVAL; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 39262306a36Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 39362306a36Sopenharmony_ci int reg, id = rdev_get_id(dev); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 39662306a36Sopenharmony_ci if (reg < 0) 39762306a36Sopenharmony_ci return reg; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci switch (mode) { 40062306a36Sopenharmony_ci case REGULATOR_MODE_NORMAL: 40162306a36Sopenharmony_ci return regmap_update_bits(regmap, reg, 40262306a36Sopenharmony_ci LDO_ST_MODE_BIT | LDO_ST_ON_BIT, 40362306a36Sopenharmony_ci LDO_ST_ON_BIT); 40462306a36Sopenharmony_ci case REGULATOR_MODE_IDLE: 40562306a36Sopenharmony_ci return regmap_set_bits(regmap, reg, 40662306a36Sopenharmony_ci LDO_ST_ON_BIT | LDO_ST_MODE_BIT); 40762306a36Sopenharmony_ci case REGULATOR_MODE_STANDBY: 40862306a36Sopenharmony_ci return regmap_clear_bits(regmap, reg, LDO_ST_ON_BIT); 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci return -EINVAL; 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_cistatic unsigned int tps65910_get_mode(struct regulator_dev *dev) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 41762306a36Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 41862306a36Sopenharmony_ci int ret, reg, value, id = rdev_get_id(dev); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 42162306a36Sopenharmony_ci if (reg < 0) 42262306a36Sopenharmony_ci return reg; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci ret = regmap_read(regmap, reg, &value); 42562306a36Sopenharmony_ci if (ret < 0) 42662306a36Sopenharmony_ci return ret; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci if (!(value & LDO_ST_ON_BIT)) 42962306a36Sopenharmony_ci return REGULATOR_MODE_STANDBY; 43062306a36Sopenharmony_ci else if (value & LDO_ST_MODE_BIT) 43162306a36Sopenharmony_ci return REGULATOR_MODE_IDLE; 43262306a36Sopenharmony_ci else 43362306a36Sopenharmony_ci return REGULATOR_MODE_NORMAL; 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev) 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 43962306a36Sopenharmony_ci int ret, id = rdev_get_id(dev); 44062306a36Sopenharmony_ci int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci switch (id) { 44362306a36Sopenharmony_ci case TPS65910_REG_VDD1: 44462306a36Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD1_OP, &opvsel); 44562306a36Sopenharmony_ci if (ret < 0) 44662306a36Sopenharmony_ci return ret; 44762306a36Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD1, &mult); 44862306a36Sopenharmony_ci if (ret < 0) 44962306a36Sopenharmony_ci return ret; 45062306a36Sopenharmony_ci mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT; 45162306a36Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD1_SR, &srvsel); 45262306a36Sopenharmony_ci if (ret < 0) 45362306a36Sopenharmony_ci return ret; 45462306a36Sopenharmony_ci sr = opvsel & VDD1_OP_CMD_MASK; 45562306a36Sopenharmony_ci opvsel &= VDD1_OP_SEL_MASK; 45662306a36Sopenharmony_ci srvsel &= VDD1_SR_SEL_MASK; 45762306a36Sopenharmony_ci vselmax = 75; 45862306a36Sopenharmony_ci break; 45962306a36Sopenharmony_ci case TPS65910_REG_VDD2: 46062306a36Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD2_OP, &opvsel); 46162306a36Sopenharmony_ci if (ret < 0) 46262306a36Sopenharmony_ci return ret; 46362306a36Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD2, &mult); 46462306a36Sopenharmony_ci if (ret < 0) 46562306a36Sopenharmony_ci return ret; 46662306a36Sopenharmony_ci mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT; 46762306a36Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD2_SR, &srvsel); 46862306a36Sopenharmony_ci if (ret < 0) 46962306a36Sopenharmony_ci return ret; 47062306a36Sopenharmony_ci sr = opvsel & VDD2_OP_CMD_MASK; 47162306a36Sopenharmony_ci opvsel &= VDD2_OP_SEL_MASK; 47262306a36Sopenharmony_ci srvsel &= VDD2_SR_SEL_MASK; 47362306a36Sopenharmony_ci vselmax = 75; 47462306a36Sopenharmony_ci break; 47562306a36Sopenharmony_ci case TPS65911_REG_VDDCTRL: 47662306a36Sopenharmony_ci ret = regmap_read(regmap, TPS65911_VDDCTRL_OP, &opvsel); 47762306a36Sopenharmony_ci if (ret < 0) 47862306a36Sopenharmony_ci return ret; 47962306a36Sopenharmony_ci ret = regmap_read(regmap, TPS65911_VDDCTRL_SR, &srvsel); 48062306a36Sopenharmony_ci if (ret < 0) 48162306a36Sopenharmony_ci return ret; 48262306a36Sopenharmony_ci sr = opvsel & VDDCTRL_OP_CMD_MASK; 48362306a36Sopenharmony_ci opvsel &= VDDCTRL_OP_SEL_MASK; 48462306a36Sopenharmony_ci srvsel &= VDDCTRL_SR_SEL_MASK; 48562306a36Sopenharmony_ci vselmax = 64; 48662306a36Sopenharmony_ci break; 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* multiplier 0 == 1 but 2,3 normal */ 49062306a36Sopenharmony_ci if (!mult) 49162306a36Sopenharmony_ci mult = 1; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci if (sr) { 49462306a36Sopenharmony_ci /* normalise to valid range */ 49562306a36Sopenharmony_ci if (srvsel < 3) 49662306a36Sopenharmony_ci srvsel = 3; 49762306a36Sopenharmony_ci if (srvsel > vselmax) 49862306a36Sopenharmony_ci srvsel = vselmax; 49962306a36Sopenharmony_ci return srvsel - 3; 50062306a36Sopenharmony_ci } else { 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /* normalise to valid range*/ 50362306a36Sopenharmony_ci if (opvsel < 3) 50462306a36Sopenharmony_ci opvsel = 3; 50562306a36Sopenharmony_ci if (opvsel > vselmax) 50662306a36Sopenharmony_ci opvsel = vselmax; 50762306a36Sopenharmony_ci return opvsel - 3; 50862306a36Sopenharmony_ci } 50962306a36Sopenharmony_ci return -EINVAL; 51062306a36Sopenharmony_ci} 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_cistatic int tps65910_get_voltage_sel(struct regulator_dev *dev) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 51562306a36Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 51662306a36Sopenharmony_ci int ret, reg, value, id = rdev_get_id(dev); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 51962306a36Sopenharmony_ci if (reg < 0) 52062306a36Sopenharmony_ci return reg; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci ret = regmap_read(regmap, reg, &value); 52362306a36Sopenharmony_ci if (ret < 0) 52462306a36Sopenharmony_ci return ret; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci switch (id) { 52762306a36Sopenharmony_ci case TPS65910_REG_VIO: 52862306a36Sopenharmony_ci case TPS65910_REG_VDIG1: 52962306a36Sopenharmony_ci case TPS65910_REG_VDIG2: 53062306a36Sopenharmony_ci case TPS65910_REG_VPLL: 53162306a36Sopenharmony_ci case TPS65910_REG_VDAC: 53262306a36Sopenharmony_ci case TPS65910_REG_VAUX1: 53362306a36Sopenharmony_ci case TPS65910_REG_VAUX2: 53462306a36Sopenharmony_ci case TPS65910_REG_VAUX33: 53562306a36Sopenharmony_ci case TPS65910_REG_VMMC: 53662306a36Sopenharmony_ci value &= LDO_SEL_MASK; 53762306a36Sopenharmony_ci value >>= LDO_SEL_SHIFT; 53862306a36Sopenharmony_ci break; 53962306a36Sopenharmony_ci case TPS65910_REG_VBB: 54062306a36Sopenharmony_ci value &= BBCH_BBSEL_MASK; 54162306a36Sopenharmony_ci value >>= BBCH_BBSEL_SHIFT; 54262306a36Sopenharmony_ci break; 54362306a36Sopenharmony_ci default: 54462306a36Sopenharmony_ci return -EINVAL; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci return value; 54862306a36Sopenharmony_ci} 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_cistatic int tps65910_get_voltage_vdd3(struct regulator_dev *dev) 55162306a36Sopenharmony_ci{ 55262306a36Sopenharmony_ci return dev->desc->volt_table[0]; 55362306a36Sopenharmony_ci} 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_cistatic int tps65911_get_voltage_sel(struct regulator_dev *dev) 55662306a36Sopenharmony_ci{ 55762306a36Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 55862306a36Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 55962306a36Sopenharmony_ci int ret, id = rdev_get_id(dev); 56062306a36Sopenharmony_ci unsigned int value, reg; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci ret = regmap_read(regmap, reg, &value); 56562306a36Sopenharmony_ci if (ret < 0) 56662306a36Sopenharmony_ci return ret; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci switch (id) { 56962306a36Sopenharmony_ci case TPS65911_REG_LDO1: 57062306a36Sopenharmony_ci case TPS65911_REG_LDO2: 57162306a36Sopenharmony_ci case TPS65911_REG_LDO4: 57262306a36Sopenharmony_ci value &= LDO1_SEL_MASK; 57362306a36Sopenharmony_ci value >>= LDO_SEL_SHIFT; 57462306a36Sopenharmony_ci break; 57562306a36Sopenharmony_ci case TPS65911_REG_LDO3: 57662306a36Sopenharmony_ci case TPS65911_REG_LDO5: 57762306a36Sopenharmony_ci case TPS65911_REG_LDO6: 57862306a36Sopenharmony_ci case TPS65911_REG_LDO7: 57962306a36Sopenharmony_ci case TPS65911_REG_LDO8: 58062306a36Sopenharmony_ci value &= LDO3_SEL_MASK; 58162306a36Sopenharmony_ci value >>= LDO_SEL_SHIFT; 58262306a36Sopenharmony_ci break; 58362306a36Sopenharmony_ci case TPS65910_REG_VIO: 58462306a36Sopenharmony_ci value &= LDO_SEL_MASK; 58562306a36Sopenharmony_ci value >>= LDO_SEL_SHIFT; 58662306a36Sopenharmony_ci break; 58762306a36Sopenharmony_ci default: 58862306a36Sopenharmony_ci return -EINVAL; 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci return value; 59262306a36Sopenharmony_ci} 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_cistatic int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev, 59562306a36Sopenharmony_ci unsigned selector) 59662306a36Sopenharmony_ci{ 59762306a36Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 59862306a36Sopenharmony_ci int id = rdev_get_id(dev), vsel; 59962306a36Sopenharmony_ci int dcdc_mult = 0; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci switch (id) { 60262306a36Sopenharmony_ci case TPS65910_REG_VDD1: 60362306a36Sopenharmony_ci dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; 60462306a36Sopenharmony_ci if (dcdc_mult == 1) 60562306a36Sopenharmony_ci dcdc_mult--; 60662306a36Sopenharmony_ci vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci regmap_update_bits(regmap, TPS65910_VDD1, VDD1_VGAIN_SEL_MASK, 60962306a36Sopenharmony_ci dcdc_mult << VDD1_VGAIN_SEL_SHIFT); 61062306a36Sopenharmony_ci regmap_write(regmap, TPS65910_VDD1_OP, vsel); 61162306a36Sopenharmony_ci break; 61262306a36Sopenharmony_ci case TPS65910_REG_VDD2: 61362306a36Sopenharmony_ci dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; 61462306a36Sopenharmony_ci if (dcdc_mult == 1) 61562306a36Sopenharmony_ci dcdc_mult--; 61662306a36Sopenharmony_ci vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci regmap_update_bits(regmap, TPS65910_VDD2, VDD1_VGAIN_SEL_MASK, 61962306a36Sopenharmony_ci dcdc_mult << VDD2_VGAIN_SEL_SHIFT); 62062306a36Sopenharmony_ci regmap_write(regmap, TPS65910_VDD2_OP, vsel); 62162306a36Sopenharmony_ci break; 62262306a36Sopenharmony_ci case TPS65911_REG_VDDCTRL: 62362306a36Sopenharmony_ci vsel = selector + 3; 62462306a36Sopenharmony_ci regmap_write(regmap, TPS65911_VDDCTRL_OP, vsel); 62562306a36Sopenharmony_ci break; 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci return 0; 62962306a36Sopenharmony_ci} 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_cistatic int tps65910_set_voltage_sel(struct regulator_dev *dev, 63262306a36Sopenharmony_ci unsigned selector) 63362306a36Sopenharmony_ci{ 63462306a36Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 63562306a36Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 63662306a36Sopenharmony_ci int reg, id = rdev_get_id(dev); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 63962306a36Sopenharmony_ci if (reg < 0) 64062306a36Sopenharmony_ci return reg; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci switch (id) { 64362306a36Sopenharmony_ci case TPS65910_REG_VIO: 64462306a36Sopenharmony_ci case TPS65910_REG_VDIG1: 64562306a36Sopenharmony_ci case TPS65910_REG_VDIG2: 64662306a36Sopenharmony_ci case TPS65910_REG_VPLL: 64762306a36Sopenharmony_ci case TPS65910_REG_VDAC: 64862306a36Sopenharmony_ci case TPS65910_REG_VAUX1: 64962306a36Sopenharmony_ci case TPS65910_REG_VAUX2: 65062306a36Sopenharmony_ci case TPS65910_REG_VAUX33: 65162306a36Sopenharmony_ci case TPS65910_REG_VMMC: 65262306a36Sopenharmony_ci return regmap_update_bits(regmap, reg, LDO_SEL_MASK, 65362306a36Sopenharmony_ci selector << LDO_SEL_SHIFT); 65462306a36Sopenharmony_ci case TPS65910_REG_VBB: 65562306a36Sopenharmony_ci return regmap_update_bits(regmap, reg, BBCH_BBSEL_MASK, 65662306a36Sopenharmony_ci selector << BBCH_BBSEL_SHIFT); 65762306a36Sopenharmony_ci } 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci return -EINVAL; 66062306a36Sopenharmony_ci} 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cistatic int tps65911_set_voltage_sel(struct regulator_dev *dev, 66362306a36Sopenharmony_ci unsigned selector) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 66662306a36Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 66762306a36Sopenharmony_ci int reg, id = rdev_get_id(dev); 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 67062306a36Sopenharmony_ci if (reg < 0) 67162306a36Sopenharmony_ci return reg; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci switch (id) { 67462306a36Sopenharmony_ci case TPS65911_REG_LDO1: 67562306a36Sopenharmony_ci case TPS65911_REG_LDO2: 67662306a36Sopenharmony_ci case TPS65911_REG_LDO4: 67762306a36Sopenharmony_ci return regmap_update_bits(regmap, reg, LDO1_SEL_MASK, 67862306a36Sopenharmony_ci selector << LDO_SEL_SHIFT); 67962306a36Sopenharmony_ci case TPS65911_REG_LDO3: 68062306a36Sopenharmony_ci case TPS65911_REG_LDO5: 68162306a36Sopenharmony_ci case TPS65911_REG_LDO6: 68262306a36Sopenharmony_ci case TPS65911_REG_LDO7: 68362306a36Sopenharmony_ci case TPS65911_REG_LDO8: 68462306a36Sopenharmony_ci return regmap_update_bits(regmap, reg, LDO3_SEL_MASK, 68562306a36Sopenharmony_ci selector << LDO_SEL_SHIFT); 68662306a36Sopenharmony_ci case TPS65910_REG_VIO: 68762306a36Sopenharmony_ci return regmap_update_bits(regmap, reg, LDO_SEL_MASK, 68862306a36Sopenharmony_ci selector << LDO_SEL_SHIFT); 68962306a36Sopenharmony_ci case TPS65910_REG_VBB: 69062306a36Sopenharmony_ci return regmap_update_bits(regmap, reg, BBCH_BBSEL_MASK, 69162306a36Sopenharmony_ci selector << BBCH_BBSEL_SHIFT); 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci return -EINVAL; 69562306a36Sopenharmony_ci} 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_cistatic int tps65910_list_voltage_dcdc(struct regulator_dev *dev, 69962306a36Sopenharmony_ci unsigned selector) 70062306a36Sopenharmony_ci{ 70162306a36Sopenharmony_ci int volt, mult = 1, id = rdev_get_id(dev); 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci switch (id) { 70462306a36Sopenharmony_ci case TPS65910_REG_VDD1: 70562306a36Sopenharmony_ci case TPS65910_REG_VDD2: 70662306a36Sopenharmony_ci mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; 70762306a36Sopenharmony_ci volt = VDD1_2_MIN_VOLT + 70862306a36Sopenharmony_ci (selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET; 70962306a36Sopenharmony_ci break; 71062306a36Sopenharmony_ci case TPS65911_REG_VDDCTRL: 71162306a36Sopenharmony_ci volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET); 71262306a36Sopenharmony_ci break; 71362306a36Sopenharmony_ci default: 71462306a36Sopenharmony_ci BUG(); 71562306a36Sopenharmony_ci return -EINVAL; 71662306a36Sopenharmony_ci } 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci return volt * 100 * mult; 71962306a36Sopenharmony_ci} 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_cistatic int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 72462306a36Sopenharmony_ci int step_mv = 0, id = rdev_get_id(dev); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci switch (id) { 72762306a36Sopenharmony_ci case TPS65911_REG_LDO1: 72862306a36Sopenharmony_ci case TPS65911_REG_LDO2: 72962306a36Sopenharmony_ci case TPS65911_REG_LDO4: 73062306a36Sopenharmony_ci /* The first 5 values of the selector correspond to 1V */ 73162306a36Sopenharmony_ci if (selector < 5) 73262306a36Sopenharmony_ci selector = 0; 73362306a36Sopenharmony_ci else 73462306a36Sopenharmony_ci selector -= 4; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci step_mv = 50; 73762306a36Sopenharmony_ci break; 73862306a36Sopenharmony_ci case TPS65911_REG_LDO3: 73962306a36Sopenharmony_ci case TPS65911_REG_LDO5: 74062306a36Sopenharmony_ci case TPS65911_REG_LDO6: 74162306a36Sopenharmony_ci case TPS65911_REG_LDO7: 74262306a36Sopenharmony_ci case TPS65911_REG_LDO8: 74362306a36Sopenharmony_ci /* The first 3 values of the selector correspond to 1V */ 74462306a36Sopenharmony_ci if (selector < 3) 74562306a36Sopenharmony_ci selector = 0; 74662306a36Sopenharmony_ci else 74762306a36Sopenharmony_ci selector -= 2; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci step_mv = 100; 75062306a36Sopenharmony_ci break; 75162306a36Sopenharmony_ci case TPS65910_REG_VIO: 75262306a36Sopenharmony_ci return pmic->info[id]->voltage_table[selector]; 75362306a36Sopenharmony_ci default: 75462306a36Sopenharmony_ci return -EINVAL; 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci return (LDO_MIN_VOLT + selector * step_mv) * 1000; 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci/* Regulator ops (except VRTC) */ 76162306a36Sopenharmony_cistatic const struct regulator_ops tps65910_ops_dcdc = { 76262306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 76362306a36Sopenharmony_ci .enable = regulator_enable_regmap, 76462306a36Sopenharmony_ci .disable = regulator_disable_regmap, 76562306a36Sopenharmony_ci .set_mode = tps65910_set_mode, 76662306a36Sopenharmony_ci .get_mode = tps65910_get_mode, 76762306a36Sopenharmony_ci .get_voltage_sel = tps65910_get_voltage_dcdc_sel, 76862306a36Sopenharmony_ci .set_voltage_sel = tps65910_set_voltage_dcdc_sel, 76962306a36Sopenharmony_ci .set_voltage_time_sel = regulator_set_voltage_time_sel, 77062306a36Sopenharmony_ci .list_voltage = tps65910_list_voltage_dcdc, 77162306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_ascend, 77262306a36Sopenharmony_ci}; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_cistatic const struct regulator_ops tps65910_ops_vdd3 = { 77562306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 77662306a36Sopenharmony_ci .enable = regulator_enable_regmap, 77762306a36Sopenharmony_ci .disable = regulator_disable_regmap, 77862306a36Sopenharmony_ci .set_mode = tps65910_set_mode, 77962306a36Sopenharmony_ci .get_mode = tps65910_get_mode, 78062306a36Sopenharmony_ci .get_voltage = tps65910_get_voltage_vdd3, 78162306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_table, 78262306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_ascend, 78362306a36Sopenharmony_ci}; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_cistatic const struct regulator_ops tps65910_ops_vbb = { 78662306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 78762306a36Sopenharmony_ci .enable = regulator_enable_regmap, 78862306a36Sopenharmony_ci .disable = regulator_disable_regmap, 78962306a36Sopenharmony_ci .set_mode = tps65910_set_mode, 79062306a36Sopenharmony_ci .get_mode = tps65910_get_mode, 79162306a36Sopenharmony_ci .get_voltage_sel = tps65910_get_voltage_sel, 79262306a36Sopenharmony_ci .set_voltage_sel = tps65910_set_voltage_sel, 79362306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_table, 79462306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_iterate, 79562306a36Sopenharmony_ci}; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic const struct regulator_ops tps65910_ops = { 79862306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 79962306a36Sopenharmony_ci .enable = regulator_enable_regmap, 80062306a36Sopenharmony_ci .disable = regulator_disable_regmap, 80162306a36Sopenharmony_ci .set_mode = tps65910_set_mode, 80262306a36Sopenharmony_ci .get_mode = tps65910_get_mode, 80362306a36Sopenharmony_ci .get_voltage_sel = tps65910_get_voltage_sel, 80462306a36Sopenharmony_ci .set_voltage_sel = tps65910_set_voltage_sel, 80562306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_table, 80662306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_ascend, 80762306a36Sopenharmony_ci}; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_cistatic const struct regulator_ops tps65911_ops = { 81062306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 81162306a36Sopenharmony_ci .enable = regulator_enable_regmap, 81262306a36Sopenharmony_ci .disable = regulator_disable_regmap, 81362306a36Sopenharmony_ci .set_mode = tps65910_set_mode, 81462306a36Sopenharmony_ci .get_mode = tps65910_get_mode, 81562306a36Sopenharmony_ci .get_voltage_sel = tps65911_get_voltage_sel, 81662306a36Sopenharmony_ci .set_voltage_sel = tps65911_set_voltage_sel, 81762306a36Sopenharmony_ci .list_voltage = tps65911_list_voltage, 81862306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_ascend, 81962306a36Sopenharmony_ci}; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_cistatic int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, 82262306a36Sopenharmony_ci int id, int ext_sleep_config) 82362306a36Sopenharmony_ci{ 82462306a36Sopenharmony_ci struct tps65910 *mfd = pmic->mfd; 82562306a36Sopenharmony_ci u8 regoffs = (pmic->ext_sleep_control[id] >> 8) & 0xFF; 82662306a36Sopenharmony_ci u8 bit_pos = (1 << pmic->ext_sleep_control[id] & 0xFF); 82762306a36Sopenharmony_ci int ret; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci /* 83062306a36Sopenharmony_ci * Regulator can not be control from multiple external input EN1, EN2 83162306a36Sopenharmony_ci * and EN3 together. 83262306a36Sopenharmony_ci */ 83362306a36Sopenharmony_ci if (ext_sleep_config & EXT_SLEEP_CONTROL) { 83462306a36Sopenharmony_ci int en_count; 83562306a36Sopenharmony_ci en_count = ((ext_sleep_config & 83662306a36Sopenharmony_ci TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1) != 0); 83762306a36Sopenharmony_ci en_count += ((ext_sleep_config & 83862306a36Sopenharmony_ci TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2) != 0); 83962306a36Sopenharmony_ci en_count += ((ext_sleep_config & 84062306a36Sopenharmony_ci TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3) != 0); 84162306a36Sopenharmony_ci en_count += ((ext_sleep_config & 84262306a36Sopenharmony_ci TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP) != 0); 84362306a36Sopenharmony_ci if (en_count > 1) { 84462306a36Sopenharmony_ci dev_err(mfd->dev, 84562306a36Sopenharmony_ci "External sleep control flag is not proper\n"); 84662306a36Sopenharmony_ci return -EINVAL; 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci pmic->board_ext_control[id] = ext_sleep_config; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci /* External EN1 control */ 85362306a36Sopenharmony_ci if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1) 85462306a36Sopenharmony_ci ret = regmap_set_bits(mfd->regmap, 85562306a36Sopenharmony_ci TPS65910_EN1_LDO_ASS + regoffs, bit_pos); 85662306a36Sopenharmony_ci else 85762306a36Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 85862306a36Sopenharmony_ci TPS65910_EN1_LDO_ASS + regoffs, bit_pos); 85962306a36Sopenharmony_ci if (ret < 0) { 86062306a36Sopenharmony_ci dev_err(mfd->dev, 86162306a36Sopenharmony_ci "Error in configuring external control EN1\n"); 86262306a36Sopenharmony_ci return ret; 86362306a36Sopenharmony_ci } 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci /* External EN2 control */ 86662306a36Sopenharmony_ci if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2) 86762306a36Sopenharmony_ci ret = regmap_set_bits(mfd->regmap, 86862306a36Sopenharmony_ci TPS65910_EN2_LDO_ASS + regoffs, bit_pos); 86962306a36Sopenharmony_ci else 87062306a36Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 87162306a36Sopenharmony_ci TPS65910_EN2_LDO_ASS + regoffs, bit_pos); 87262306a36Sopenharmony_ci if (ret < 0) { 87362306a36Sopenharmony_ci dev_err(mfd->dev, 87462306a36Sopenharmony_ci "Error in configuring external control EN2\n"); 87562306a36Sopenharmony_ci return ret; 87662306a36Sopenharmony_ci } 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci /* External EN3 control for TPS65910 LDO only */ 87962306a36Sopenharmony_ci if ((tps65910_chip_id(mfd) == TPS65910) && 88062306a36Sopenharmony_ci (id >= TPS65910_REG_VDIG1)) { 88162306a36Sopenharmony_ci if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3) 88262306a36Sopenharmony_ci ret = regmap_set_bits(mfd->regmap, 88362306a36Sopenharmony_ci TPS65910_EN3_LDO_ASS + regoffs, bit_pos); 88462306a36Sopenharmony_ci else 88562306a36Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 88662306a36Sopenharmony_ci TPS65910_EN3_LDO_ASS + regoffs, bit_pos); 88762306a36Sopenharmony_ci if (ret < 0) { 88862306a36Sopenharmony_ci dev_err(mfd->dev, 88962306a36Sopenharmony_ci "Error in configuring external control EN3\n"); 89062306a36Sopenharmony_ci return ret; 89162306a36Sopenharmony_ci } 89262306a36Sopenharmony_ci } 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci /* Return if no external control is selected */ 89562306a36Sopenharmony_ci if (!(ext_sleep_config & EXT_SLEEP_CONTROL)) { 89662306a36Sopenharmony_ci /* Clear all sleep controls */ 89762306a36Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 89862306a36Sopenharmony_ci TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos); 89962306a36Sopenharmony_ci if (!ret) 90062306a36Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 90162306a36Sopenharmony_ci TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); 90262306a36Sopenharmony_ci if (ret < 0) 90362306a36Sopenharmony_ci dev_err(mfd->dev, 90462306a36Sopenharmony_ci "Error in configuring SLEEP register\n"); 90562306a36Sopenharmony_ci return ret; 90662306a36Sopenharmony_ci } 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci /* 90962306a36Sopenharmony_ci * For regulator that has separate operational and sleep register make 91062306a36Sopenharmony_ci * sure that operational is used and clear sleep register to turn 91162306a36Sopenharmony_ci * regulator off when external control is inactive 91262306a36Sopenharmony_ci */ 91362306a36Sopenharmony_ci if ((id == TPS65910_REG_VDD1) || 91462306a36Sopenharmony_ci (id == TPS65910_REG_VDD2) || 91562306a36Sopenharmony_ci ((id == TPS65911_REG_VDDCTRL) && 91662306a36Sopenharmony_ci (tps65910_chip_id(mfd) == TPS65911))) { 91762306a36Sopenharmony_ci int op_reg_add = pmic->get_ctrl_reg(id) + 1; 91862306a36Sopenharmony_ci int sr_reg_add = pmic->get_ctrl_reg(id) + 2; 91962306a36Sopenharmony_ci int opvsel, srvsel; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci ret = regmap_read(mfd->regmap, op_reg_add, &opvsel); 92262306a36Sopenharmony_ci if (ret < 0) 92362306a36Sopenharmony_ci return ret; 92462306a36Sopenharmony_ci ret = regmap_read(mfd->regmap, sr_reg_add, &srvsel); 92562306a36Sopenharmony_ci if (ret < 0) 92662306a36Sopenharmony_ci return ret; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci if (opvsel & VDD1_OP_CMD_MASK) { 92962306a36Sopenharmony_ci u8 reg_val = srvsel & VDD1_OP_SEL_MASK; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci ret = regmap_write(mfd->regmap, op_reg_add, reg_val); 93262306a36Sopenharmony_ci if (ret < 0) { 93362306a36Sopenharmony_ci dev_err(mfd->dev, 93462306a36Sopenharmony_ci "Error in configuring op register\n"); 93562306a36Sopenharmony_ci return ret; 93662306a36Sopenharmony_ci } 93762306a36Sopenharmony_ci } 93862306a36Sopenharmony_ci ret = regmap_write(mfd->regmap, sr_reg_add, 0); 93962306a36Sopenharmony_ci if (ret < 0) { 94062306a36Sopenharmony_ci dev_err(mfd->dev, "Error in setting sr register\n"); 94162306a36Sopenharmony_ci return ret; 94262306a36Sopenharmony_ci } 94362306a36Sopenharmony_ci } 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 94662306a36Sopenharmony_ci TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos); 94762306a36Sopenharmony_ci if (!ret) { 94862306a36Sopenharmony_ci if (ext_sleep_config & TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP) 94962306a36Sopenharmony_ci ret = regmap_set_bits(mfd->regmap, 95062306a36Sopenharmony_ci TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); 95162306a36Sopenharmony_ci else 95262306a36Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 95362306a36Sopenharmony_ci TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); 95462306a36Sopenharmony_ci } 95562306a36Sopenharmony_ci if (ret < 0) 95662306a36Sopenharmony_ci dev_err(mfd->dev, 95762306a36Sopenharmony_ci "Error in configuring SLEEP register\n"); 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci return ret; 96062306a36Sopenharmony_ci} 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci#ifdef CONFIG_OF 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_cistatic struct of_regulator_match tps65910_matches[] = { 96562306a36Sopenharmony_ci { .name = "vrtc", .driver_data = (void *) &tps65910_regs[0] }, 96662306a36Sopenharmony_ci { .name = "vio", .driver_data = (void *) &tps65910_regs[1] }, 96762306a36Sopenharmony_ci { .name = "vdd1", .driver_data = (void *) &tps65910_regs[2] }, 96862306a36Sopenharmony_ci { .name = "vdd2", .driver_data = (void *) &tps65910_regs[3] }, 96962306a36Sopenharmony_ci { .name = "vdd3", .driver_data = (void *) &tps65910_regs[4] }, 97062306a36Sopenharmony_ci { .name = "vdig1", .driver_data = (void *) &tps65910_regs[5] }, 97162306a36Sopenharmony_ci { .name = "vdig2", .driver_data = (void *) &tps65910_regs[6] }, 97262306a36Sopenharmony_ci { .name = "vpll", .driver_data = (void *) &tps65910_regs[7] }, 97362306a36Sopenharmony_ci { .name = "vdac", .driver_data = (void *) &tps65910_regs[8] }, 97462306a36Sopenharmony_ci { .name = "vaux1", .driver_data = (void *) &tps65910_regs[9] }, 97562306a36Sopenharmony_ci { .name = "vaux2", .driver_data = (void *) &tps65910_regs[10] }, 97662306a36Sopenharmony_ci { .name = "vaux33", .driver_data = (void *) &tps65910_regs[11] }, 97762306a36Sopenharmony_ci { .name = "vmmc", .driver_data = (void *) &tps65910_regs[12] }, 97862306a36Sopenharmony_ci { .name = "vbb", .driver_data = (void *) &tps65910_regs[13] }, 97962306a36Sopenharmony_ci}; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_cistatic struct of_regulator_match tps65911_matches[] = { 98262306a36Sopenharmony_ci { .name = "vrtc", .driver_data = (void *) &tps65911_regs[0] }, 98362306a36Sopenharmony_ci { .name = "vio", .driver_data = (void *) &tps65911_regs[1] }, 98462306a36Sopenharmony_ci { .name = "vdd1", .driver_data = (void *) &tps65911_regs[2] }, 98562306a36Sopenharmony_ci { .name = "vdd2", .driver_data = (void *) &tps65911_regs[3] }, 98662306a36Sopenharmony_ci { .name = "vddctrl", .driver_data = (void *) &tps65911_regs[4] }, 98762306a36Sopenharmony_ci { .name = "ldo1", .driver_data = (void *) &tps65911_regs[5] }, 98862306a36Sopenharmony_ci { .name = "ldo2", .driver_data = (void *) &tps65911_regs[6] }, 98962306a36Sopenharmony_ci { .name = "ldo3", .driver_data = (void *) &tps65911_regs[7] }, 99062306a36Sopenharmony_ci { .name = "ldo4", .driver_data = (void *) &tps65911_regs[8] }, 99162306a36Sopenharmony_ci { .name = "ldo5", .driver_data = (void *) &tps65911_regs[9] }, 99262306a36Sopenharmony_ci { .name = "ldo6", .driver_data = (void *) &tps65911_regs[10] }, 99362306a36Sopenharmony_ci { .name = "ldo7", .driver_data = (void *) &tps65911_regs[11] }, 99462306a36Sopenharmony_ci { .name = "ldo8", .driver_data = (void *) &tps65911_regs[12] }, 99562306a36Sopenharmony_ci}; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_cistatic struct tps65910_board *tps65910_parse_dt_reg_data( 99862306a36Sopenharmony_ci struct platform_device *pdev, 99962306a36Sopenharmony_ci struct of_regulator_match **tps65910_reg_matches) 100062306a36Sopenharmony_ci{ 100162306a36Sopenharmony_ci struct tps65910_board *pmic_plat_data; 100262306a36Sopenharmony_ci struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); 100362306a36Sopenharmony_ci struct device_node *np, *regulators; 100462306a36Sopenharmony_ci struct of_regulator_match *matches; 100562306a36Sopenharmony_ci unsigned int prop; 100662306a36Sopenharmony_ci int idx = 0, ret, count; 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci pmic_plat_data = devm_kzalloc(&pdev->dev, sizeof(*pmic_plat_data), 100962306a36Sopenharmony_ci GFP_KERNEL); 101062306a36Sopenharmony_ci if (!pmic_plat_data) 101162306a36Sopenharmony_ci return NULL; 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci np = pdev->dev.parent->of_node; 101462306a36Sopenharmony_ci regulators = of_get_child_by_name(np, "regulators"); 101562306a36Sopenharmony_ci if (!regulators) { 101662306a36Sopenharmony_ci dev_err(&pdev->dev, "regulator node not found\n"); 101762306a36Sopenharmony_ci return NULL; 101862306a36Sopenharmony_ci } 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci switch (tps65910_chip_id(tps65910)) { 102162306a36Sopenharmony_ci case TPS65910: 102262306a36Sopenharmony_ci count = ARRAY_SIZE(tps65910_matches); 102362306a36Sopenharmony_ci matches = tps65910_matches; 102462306a36Sopenharmony_ci break; 102562306a36Sopenharmony_ci case TPS65911: 102662306a36Sopenharmony_ci count = ARRAY_SIZE(tps65911_matches); 102762306a36Sopenharmony_ci matches = tps65911_matches; 102862306a36Sopenharmony_ci break; 102962306a36Sopenharmony_ci default: 103062306a36Sopenharmony_ci of_node_put(regulators); 103162306a36Sopenharmony_ci dev_err(&pdev->dev, "Invalid tps chip version\n"); 103262306a36Sopenharmony_ci return NULL; 103362306a36Sopenharmony_ci } 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci ret = of_regulator_match(&pdev->dev, regulators, matches, count); 103662306a36Sopenharmony_ci of_node_put(regulators); 103762306a36Sopenharmony_ci if (ret < 0) { 103862306a36Sopenharmony_ci dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", 103962306a36Sopenharmony_ci ret); 104062306a36Sopenharmony_ci return NULL; 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci *tps65910_reg_matches = matches; 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci for (idx = 0; idx < count; idx++) { 104662306a36Sopenharmony_ci if (!matches[idx].of_node) 104762306a36Sopenharmony_ci continue; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci pmic_plat_data->tps65910_pmic_init_data[idx] = 105062306a36Sopenharmony_ci matches[idx].init_data; 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci ret = of_property_read_u32(matches[idx].of_node, 105362306a36Sopenharmony_ci "ti,regulator-ext-sleep-control", &prop); 105462306a36Sopenharmony_ci if (!ret) 105562306a36Sopenharmony_ci pmic_plat_data->regulator_ext_sleep_control[idx] = prop; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci } 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci return pmic_plat_data; 106062306a36Sopenharmony_ci} 106162306a36Sopenharmony_ci#else 106262306a36Sopenharmony_cistatic inline struct tps65910_board *tps65910_parse_dt_reg_data( 106362306a36Sopenharmony_ci struct platform_device *pdev, 106462306a36Sopenharmony_ci struct of_regulator_match **tps65910_reg_matches) 106562306a36Sopenharmony_ci{ 106662306a36Sopenharmony_ci *tps65910_reg_matches = NULL; 106762306a36Sopenharmony_ci return NULL; 106862306a36Sopenharmony_ci} 106962306a36Sopenharmony_ci#endif 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_cistatic int tps65910_probe(struct platform_device *pdev) 107262306a36Sopenharmony_ci{ 107362306a36Sopenharmony_ci struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); 107462306a36Sopenharmony_ci struct regulator_config config = { }; 107562306a36Sopenharmony_ci struct tps_info *info; 107662306a36Sopenharmony_ci struct regulator_dev *rdev; 107762306a36Sopenharmony_ci struct tps65910_reg *pmic; 107862306a36Sopenharmony_ci struct tps65910_board *pmic_plat_data; 107962306a36Sopenharmony_ci struct of_regulator_match *tps65910_reg_matches = NULL; 108062306a36Sopenharmony_ci int i, err; 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci pmic_plat_data = dev_get_platdata(tps65910->dev); 108362306a36Sopenharmony_ci if (!pmic_plat_data && tps65910->dev->of_node) 108462306a36Sopenharmony_ci pmic_plat_data = tps65910_parse_dt_reg_data(pdev, 108562306a36Sopenharmony_ci &tps65910_reg_matches); 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci if (!pmic_plat_data) { 108862306a36Sopenharmony_ci dev_err(&pdev->dev, "Platform data not found\n"); 108962306a36Sopenharmony_ci return -EINVAL; 109062306a36Sopenharmony_ci } 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); 109362306a36Sopenharmony_ci if (!pmic) 109462306a36Sopenharmony_ci return -ENOMEM; 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci pmic->mfd = tps65910; 109762306a36Sopenharmony_ci platform_set_drvdata(pdev, pmic); 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci /* Give control of all register to control port */ 110062306a36Sopenharmony_ci err = regmap_set_bits(pmic->mfd->regmap, TPS65910_DEVCTRL, 110162306a36Sopenharmony_ci DEVCTRL_SR_CTL_I2C_SEL_MASK); 110262306a36Sopenharmony_ci if (err < 0) 110362306a36Sopenharmony_ci return err; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci switch (tps65910_chip_id(tps65910)) { 110662306a36Sopenharmony_ci case TPS65910: 110762306a36Sopenharmony_ci BUILD_BUG_ON(TPS65910_NUM_REGS < ARRAY_SIZE(tps65910_regs)); 110862306a36Sopenharmony_ci pmic->get_ctrl_reg = &tps65910_get_ctrl_register; 110962306a36Sopenharmony_ci pmic->num_regulators = ARRAY_SIZE(tps65910_regs); 111062306a36Sopenharmony_ci pmic->ext_sleep_control = tps65910_ext_sleep_control; 111162306a36Sopenharmony_ci info = tps65910_regs; 111262306a36Sopenharmony_ci /* Work around silicon erratum SWCZ010: output programmed 111362306a36Sopenharmony_ci * voltage level can go higher than expected or crash 111462306a36Sopenharmony_ci * Workaround: use no synchronization of DCDC clocks 111562306a36Sopenharmony_ci */ 111662306a36Sopenharmony_ci regmap_clear_bits(pmic->mfd->regmap, TPS65910_DCDCCTRL, 111762306a36Sopenharmony_ci DCDCCTRL_DCDCCKSYNC_MASK); 111862306a36Sopenharmony_ci break; 111962306a36Sopenharmony_ci case TPS65911: 112062306a36Sopenharmony_ci BUILD_BUG_ON(TPS65910_NUM_REGS < ARRAY_SIZE(tps65911_regs)); 112162306a36Sopenharmony_ci pmic->get_ctrl_reg = &tps65911_get_ctrl_register; 112262306a36Sopenharmony_ci pmic->num_regulators = ARRAY_SIZE(tps65911_regs); 112362306a36Sopenharmony_ci pmic->ext_sleep_control = tps65911_ext_sleep_control; 112462306a36Sopenharmony_ci info = tps65911_regs; 112562306a36Sopenharmony_ci break; 112662306a36Sopenharmony_ci default: 112762306a36Sopenharmony_ci dev_err(&pdev->dev, "Invalid tps chip version\n"); 112862306a36Sopenharmony_ci return -ENODEV; 112962306a36Sopenharmony_ci } 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci pmic->desc = devm_kcalloc(&pdev->dev, 113262306a36Sopenharmony_ci pmic->num_regulators, 113362306a36Sopenharmony_ci sizeof(struct regulator_desc), 113462306a36Sopenharmony_ci GFP_KERNEL); 113562306a36Sopenharmony_ci if (!pmic->desc) 113662306a36Sopenharmony_ci return -ENOMEM; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci pmic->info = devm_kcalloc(&pdev->dev, 113962306a36Sopenharmony_ci pmic->num_regulators, 114062306a36Sopenharmony_ci sizeof(struct tps_info *), 114162306a36Sopenharmony_ci GFP_KERNEL); 114262306a36Sopenharmony_ci if (!pmic->info) 114362306a36Sopenharmony_ci return -ENOMEM; 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci pmic->rdev = devm_kcalloc(&pdev->dev, 114662306a36Sopenharmony_ci pmic->num_regulators, 114762306a36Sopenharmony_ci sizeof(struct regulator_dev *), 114862306a36Sopenharmony_ci GFP_KERNEL); 114962306a36Sopenharmony_ci if (!pmic->rdev) 115062306a36Sopenharmony_ci return -ENOMEM; 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci for (i = 0; i < pmic->num_regulators; i++, info++) { 115362306a36Sopenharmony_ci /* Register the regulators */ 115462306a36Sopenharmony_ci pmic->info[i] = info; 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci pmic->desc[i].name = info->name; 115762306a36Sopenharmony_ci pmic->desc[i].supply_name = info->vin_name; 115862306a36Sopenharmony_ci pmic->desc[i].id = i; 115962306a36Sopenharmony_ci pmic->desc[i].n_voltages = info->n_voltages; 116062306a36Sopenharmony_ci pmic->desc[i].enable_time = info->enable_time_us; 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) { 116362306a36Sopenharmony_ci pmic->desc[i].ops = &tps65910_ops_dcdc; 116462306a36Sopenharmony_ci pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE * 116562306a36Sopenharmony_ci VDD1_2_NUM_VOLT_COARSE; 116662306a36Sopenharmony_ci pmic->desc[i].ramp_delay = 12500; 116762306a36Sopenharmony_ci } else if (i == TPS65910_REG_VDD3) { 116862306a36Sopenharmony_ci if (tps65910_chip_id(tps65910) == TPS65910) { 116962306a36Sopenharmony_ci pmic->desc[i].ops = &tps65910_ops_vdd3; 117062306a36Sopenharmony_ci pmic->desc[i].volt_table = info->voltage_table; 117162306a36Sopenharmony_ci } else { 117262306a36Sopenharmony_ci pmic->desc[i].ops = &tps65910_ops_dcdc; 117362306a36Sopenharmony_ci pmic->desc[i].ramp_delay = 5000; 117462306a36Sopenharmony_ci } 117562306a36Sopenharmony_ci } else if (i == TPS65910_REG_VBB && 117662306a36Sopenharmony_ci tps65910_chip_id(tps65910) == TPS65910) { 117762306a36Sopenharmony_ci pmic->desc[i].ops = &tps65910_ops_vbb; 117862306a36Sopenharmony_ci pmic->desc[i].volt_table = info->voltage_table; 117962306a36Sopenharmony_ci } else { 118062306a36Sopenharmony_ci if (tps65910_chip_id(tps65910) == TPS65910) { 118162306a36Sopenharmony_ci pmic->desc[i].ops = &tps65910_ops; 118262306a36Sopenharmony_ci pmic->desc[i].volt_table = info->voltage_table; 118362306a36Sopenharmony_ci } else { 118462306a36Sopenharmony_ci pmic->desc[i].ops = &tps65911_ops; 118562306a36Sopenharmony_ci } 118662306a36Sopenharmony_ci } 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci err = tps65910_set_ext_sleep_config(pmic, i, 118962306a36Sopenharmony_ci pmic_plat_data->regulator_ext_sleep_control[i]); 119062306a36Sopenharmony_ci /* 119162306a36Sopenharmony_ci * Failing on regulator for configuring externally control 119262306a36Sopenharmony_ci * is not a serious issue, just throw warning. 119362306a36Sopenharmony_ci */ 119462306a36Sopenharmony_ci if (err < 0) 119562306a36Sopenharmony_ci dev_warn(tps65910->dev, 119662306a36Sopenharmony_ci "Failed to initialise ext control config\n"); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci pmic->desc[i].type = REGULATOR_VOLTAGE; 119962306a36Sopenharmony_ci pmic->desc[i].owner = THIS_MODULE; 120062306a36Sopenharmony_ci pmic->desc[i].enable_reg = pmic->get_ctrl_reg(i); 120162306a36Sopenharmony_ci pmic->desc[i].enable_mask = TPS65910_SUPPLY_STATE_ENABLED; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci config.dev = tps65910->dev; 120462306a36Sopenharmony_ci config.init_data = pmic_plat_data->tps65910_pmic_init_data[i]; 120562306a36Sopenharmony_ci config.driver_data = pmic; 120662306a36Sopenharmony_ci config.regmap = tps65910->regmap; 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci if (tps65910_reg_matches) 120962306a36Sopenharmony_ci config.of_node = tps65910_reg_matches[i].of_node; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i], 121262306a36Sopenharmony_ci &config); 121362306a36Sopenharmony_ci if (IS_ERR(rdev)) 121462306a36Sopenharmony_ci return dev_err_probe(tps65910->dev, PTR_ERR(rdev), 121562306a36Sopenharmony_ci "failed to register %s regulator\n", 121662306a36Sopenharmony_ci pdev->name); 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci /* Save regulator for cleanup */ 121962306a36Sopenharmony_ci pmic->rdev[i] = rdev; 122062306a36Sopenharmony_ci } 122162306a36Sopenharmony_ci return 0; 122262306a36Sopenharmony_ci} 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_cistatic void tps65910_shutdown(struct platform_device *pdev) 122562306a36Sopenharmony_ci{ 122662306a36Sopenharmony_ci struct tps65910_reg *pmic = platform_get_drvdata(pdev); 122762306a36Sopenharmony_ci int i; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci /* 123062306a36Sopenharmony_ci * Before bootloader jumps to kernel, it makes sure that required 123162306a36Sopenharmony_ci * external control signals are in desired state so that given rails 123262306a36Sopenharmony_ci * can be configure accordingly. 123362306a36Sopenharmony_ci * If rails are configured to be controlled from external control 123462306a36Sopenharmony_ci * then before shutting down/rebooting the system, the external 123562306a36Sopenharmony_ci * control configuration need to be remove from the rails so that 123662306a36Sopenharmony_ci * its output will be available as per register programming even 123762306a36Sopenharmony_ci * if external controls are removed. This is require when the POR 123862306a36Sopenharmony_ci * value of the control signals are not in active state and before 123962306a36Sopenharmony_ci * bootloader initializes it, the system requires the rail output 124062306a36Sopenharmony_ci * to be active for booting. 124162306a36Sopenharmony_ci */ 124262306a36Sopenharmony_ci for (i = 0; i < pmic->num_regulators; i++) { 124362306a36Sopenharmony_ci int err; 124462306a36Sopenharmony_ci if (!pmic->rdev[i]) 124562306a36Sopenharmony_ci continue; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci err = tps65910_set_ext_sleep_config(pmic, i, 0); 124862306a36Sopenharmony_ci if (err < 0) 124962306a36Sopenharmony_ci dev_err(&pdev->dev, 125062306a36Sopenharmony_ci "Error in clearing external control\n"); 125162306a36Sopenharmony_ci } 125262306a36Sopenharmony_ci} 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_cistatic struct platform_driver tps65910_driver = { 125562306a36Sopenharmony_ci .driver = { 125662306a36Sopenharmony_ci .name = "tps65910-pmic", 125762306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 125862306a36Sopenharmony_ci }, 125962306a36Sopenharmony_ci .probe = tps65910_probe, 126062306a36Sopenharmony_ci .shutdown = tps65910_shutdown, 126162306a36Sopenharmony_ci}; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_cistatic int __init tps65910_init(void) 126462306a36Sopenharmony_ci{ 126562306a36Sopenharmony_ci return platform_driver_register(&tps65910_driver); 126662306a36Sopenharmony_ci} 126762306a36Sopenharmony_cisubsys_initcall(tps65910_init); 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_cistatic void __exit tps65910_cleanup(void) 127062306a36Sopenharmony_ci{ 127162306a36Sopenharmony_ci platform_driver_unregister(&tps65910_driver); 127262306a36Sopenharmony_ci} 127362306a36Sopenharmony_cimodule_exit(tps65910_cleanup); 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ciMODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); 127662306a36Sopenharmony_ciMODULE_DESCRIPTION("TPS65910/TPS65911 voltage regulator driver"); 127762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 127862306a36Sopenharmony_ciMODULE_ALIAS("platform:tps65910-pmic"); 1279