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