162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// Copyright (C) 2018 BayLibre SAS
462306a36Sopenharmony_ci// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
562306a36Sopenharmony_ci//
662306a36Sopenharmony_ci// Regulator driver for MAXIM 77650/77651 charger/power-supply.
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/of.h>
962306a36Sopenharmony_ci#include <linux/mfd/max77650.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/platform_device.h>
1262306a36Sopenharmony_ci#include <linux/regmap.h>
1362306a36Sopenharmony_ci#include <linux/regulator/driver.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define MAX77650_REGULATOR_EN_CTRL_MASK		GENMASK(3, 0)
1662306a36Sopenharmony_ci#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \
1762306a36Sopenharmony_ci		((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK)
1862306a36Sopenharmony_ci#define MAX77650_REGULATOR_ENABLED		GENMASK(2, 1)
1962306a36Sopenharmony_ci#define MAX77650_REGULATOR_DISABLED		BIT(2)
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define MAX77650_REGULATOR_V_LDO_MASK		GENMASK(6, 0)
2262306a36Sopenharmony_ci#define MAX77650_REGULATOR_V_SBB_MASK		GENMASK(5, 0)
2362306a36Sopenharmony_ci#define MAX77651_REGULATOR_V_SBB1_MASK		GENMASK(5, 2)
2462306a36Sopenharmony_ci#define MAX77651_REGULATOR_V_SBB1_RANGE_MASK	GENMASK(1, 0)
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define MAX77650_REGULATOR_AD_MASK		BIT(3)
2762306a36Sopenharmony_ci#define MAX77650_REGULATOR_AD_DISABLED		0x00
2862306a36Sopenharmony_ci#define MAX77650_REGULATOR_AD_ENABLED		BIT(3)
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define MAX77650_REGULATOR_CURR_LIM_MASK	GENMASK(7, 6)
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cienum {
3362306a36Sopenharmony_ci	MAX77650_REGULATOR_ID_LDO = 0,
3462306a36Sopenharmony_ci	MAX77650_REGULATOR_ID_SBB0,
3562306a36Sopenharmony_ci	MAX77650_REGULATOR_ID_SBB1,
3662306a36Sopenharmony_ci	MAX77650_REGULATOR_ID_SBB2,
3762306a36Sopenharmony_ci	MAX77650_REGULATOR_NUM_REGULATORS,
3862306a36Sopenharmony_ci};
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistruct max77650_regulator_desc {
4162306a36Sopenharmony_ci	struct regulator_desc desc;
4262306a36Sopenharmony_ci	unsigned int regA;
4362306a36Sopenharmony_ci	unsigned int regB;
4462306a36Sopenharmony_ci};
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic struct max77650_regulator_desc max77651_SBB1_desc;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic const unsigned int max77651_sbb1_volt_range_sel[] = {
4962306a36Sopenharmony_ci	0x0, 0x1, 0x2, 0x3
5062306a36Sopenharmony_ci};
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic const struct linear_range max77651_sbb1_volt_ranges[] = {
5362306a36Sopenharmony_ci	/* range index 0 */
5462306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000),
5562306a36Sopenharmony_ci	/* range index 1 */
5662306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(3200000, 0x00, 0x0f, 50000),
5762306a36Sopenharmony_ci	/* range index 2 */
5862306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x0f, 50000),
5962306a36Sopenharmony_ci	/* range index 3 */
6062306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(4800000, 0x00, 0x09, 50000),
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic const unsigned int max77650_current_limit_table[] = {
6462306a36Sopenharmony_ci	1000000, 866000, 707000, 500000,
6562306a36Sopenharmony_ci};
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic int max77650_regulator_is_enabled(struct regulator_dev *rdev)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	struct max77650_regulator_desc *rdesc;
7062306a36Sopenharmony_ci	struct regmap *map;
7162306a36Sopenharmony_ci	int val, rv, en;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	rdesc = rdev_get_drvdata(rdev);
7462306a36Sopenharmony_ci	map = rdev_get_regmap(rdev);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	rv = regmap_read(map, rdesc->regB, &val);
7762306a36Sopenharmony_ci	if (rv)
7862306a36Sopenharmony_ci		return rv;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	en = MAX77650_REGULATOR_EN_CTRL_BITS(val);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	return en != MAX77650_REGULATOR_DISABLED;
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic int max77650_regulator_enable(struct regulator_dev *rdev)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	struct max77650_regulator_desc *rdesc;
8862306a36Sopenharmony_ci	struct regmap *map;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	rdesc = rdev_get_drvdata(rdev);
9162306a36Sopenharmony_ci	map = rdev_get_regmap(rdev);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	return regmap_update_bits(map, rdesc->regB,
9462306a36Sopenharmony_ci				  MAX77650_REGULATOR_EN_CTRL_MASK,
9562306a36Sopenharmony_ci				  MAX77650_REGULATOR_ENABLED);
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic int max77650_regulator_disable(struct regulator_dev *rdev)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	struct max77650_regulator_desc *rdesc;
10162306a36Sopenharmony_ci	struct regmap *map;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	rdesc = rdev_get_drvdata(rdev);
10462306a36Sopenharmony_ci	map = rdev_get_regmap(rdev);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return regmap_update_bits(map, rdesc->regB,
10762306a36Sopenharmony_ci				  MAX77650_REGULATOR_EN_CTRL_MASK,
10862306a36Sopenharmony_ci				  MAX77650_REGULATOR_DISABLED);
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic const struct regulator_ops max77650_regulator_LDO_ops = {
11262306a36Sopenharmony_ci	.is_enabled		= max77650_regulator_is_enabled,
11362306a36Sopenharmony_ci	.enable			= max77650_regulator_enable,
11462306a36Sopenharmony_ci	.disable		= max77650_regulator_disable,
11562306a36Sopenharmony_ci	.list_voltage		= regulator_list_voltage_linear,
11662306a36Sopenharmony_ci	.map_voltage		= regulator_map_voltage_linear,
11762306a36Sopenharmony_ci	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
11862306a36Sopenharmony_ci	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
11962306a36Sopenharmony_ci	.set_active_discharge	= regulator_set_active_discharge_regmap,
12062306a36Sopenharmony_ci};
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic const struct regulator_ops max77650_regulator_SBB_ops = {
12362306a36Sopenharmony_ci	.is_enabled		= max77650_regulator_is_enabled,
12462306a36Sopenharmony_ci	.enable			= max77650_regulator_enable,
12562306a36Sopenharmony_ci	.disable		= max77650_regulator_disable,
12662306a36Sopenharmony_ci	.list_voltage		= regulator_list_voltage_linear,
12762306a36Sopenharmony_ci	.map_voltage		= regulator_map_voltage_linear,
12862306a36Sopenharmony_ci	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
12962306a36Sopenharmony_ci	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
13062306a36Sopenharmony_ci	.get_current_limit	= regulator_get_current_limit_regmap,
13162306a36Sopenharmony_ci	.set_current_limit	= regulator_set_current_limit_regmap,
13262306a36Sopenharmony_ci	.set_active_discharge	= regulator_set_active_discharge_regmap,
13362306a36Sopenharmony_ci};
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/* Special case for max77651 SBB1 - pickable linear-range voltage mapping. */
13662306a36Sopenharmony_cistatic const struct regulator_ops max77651_SBB1_regulator_ops = {
13762306a36Sopenharmony_ci	.is_enabled		= max77650_regulator_is_enabled,
13862306a36Sopenharmony_ci	.enable			= max77650_regulator_enable,
13962306a36Sopenharmony_ci	.disable		= max77650_regulator_disable,
14062306a36Sopenharmony_ci	.list_voltage		= regulator_list_voltage_pickable_linear_range,
14162306a36Sopenharmony_ci	.get_voltage_sel	= regulator_get_voltage_sel_pickable_regmap,
14262306a36Sopenharmony_ci	.set_voltage_sel	= regulator_set_voltage_sel_pickable_regmap,
14362306a36Sopenharmony_ci	.get_current_limit	= regulator_get_current_limit_regmap,
14462306a36Sopenharmony_ci	.set_current_limit	= regulator_set_current_limit_regmap,
14562306a36Sopenharmony_ci	.set_active_discharge	= regulator_set_active_discharge_regmap,
14662306a36Sopenharmony_ci};
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic struct max77650_regulator_desc max77650_LDO_desc = {
14962306a36Sopenharmony_ci	.desc = {
15062306a36Sopenharmony_ci		.name			= "ldo",
15162306a36Sopenharmony_ci		.of_match		= of_match_ptr("ldo"),
15262306a36Sopenharmony_ci		.regulators_node	= of_match_ptr("regulators"),
15362306a36Sopenharmony_ci		.supply_name		= "in-ldo",
15462306a36Sopenharmony_ci		.id			= MAX77650_REGULATOR_ID_LDO,
15562306a36Sopenharmony_ci		.ops			= &max77650_regulator_LDO_ops,
15662306a36Sopenharmony_ci		.min_uV			= 1350000,
15762306a36Sopenharmony_ci		.uV_step		= 12500,
15862306a36Sopenharmony_ci		.n_voltages		= 128,
15962306a36Sopenharmony_ci		.vsel_step		= 1,
16062306a36Sopenharmony_ci		.vsel_mask		= MAX77650_REGULATOR_V_LDO_MASK,
16162306a36Sopenharmony_ci		.vsel_reg		= MAX77650_REG_CNFG_LDO_A,
16262306a36Sopenharmony_ci		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
16362306a36Sopenharmony_ci		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
16462306a36Sopenharmony_ci		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
16562306a36Sopenharmony_ci		.active_discharge_reg	= MAX77650_REG_CNFG_LDO_B,
16662306a36Sopenharmony_ci		.enable_time		= 100,
16762306a36Sopenharmony_ci		.type			= REGULATOR_VOLTAGE,
16862306a36Sopenharmony_ci		.owner			= THIS_MODULE,
16962306a36Sopenharmony_ci	},
17062306a36Sopenharmony_ci	.regA		= MAX77650_REG_CNFG_LDO_A,
17162306a36Sopenharmony_ci	.regB		= MAX77650_REG_CNFG_LDO_B,
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic struct max77650_regulator_desc max77650_SBB0_desc = {
17562306a36Sopenharmony_ci	.desc = {
17662306a36Sopenharmony_ci		.name			= "sbb0",
17762306a36Sopenharmony_ci		.of_match		= of_match_ptr("sbb0"),
17862306a36Sopenharmony_ci		.regulators_node	= of_match_ptr("regulators"),
17962306a36Sopenharmony_ci		.supply_name		= "in-sbb0",
18062306a36Sopenharmony_ci		.id			= MAX77650_REGULATOR_ID_SBB0,
18162306a36Sopenharmony_ci		.ops			= &max77650_regulator_SBB_ops,
18262306a36Sopenharmony_ci		.min_uV			= 800000,
18362306a36Sopenharmony_ci		.uV_step		= 25000,
18462306a36Sopenharmony_ci		.n_voltages		= 64,
18562306a36Sopenharmony_ci		.vsel_step		= 1,
18662306a36Sopenharmony_ci		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
18762306a36Sopenharmony_ci		.vsel_reg		= MAX77650_REG_CNFG_SBB0_A,
18862306a36Sopenharmony_ci		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
18962306a36Sopenharmony_ci		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
19062306a36Sopenharmony_ci		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
19162306a36Sopenharmony_ci		.active_discharge_reg	= MAX77650_REG_CNFG_SBB0_B,
19262306a36Sopenharmony_ci		.enable_time		= 100,
19362306a36Sopenharmony_ci		.type			= REGULATOR_VOLTAGE,
19462306a36Sopenharmony_ci		.owner			= THIS_MODULE,
19562306a36Sopenharmony_ci		.csel_reg		= MAX77650_REG_CNFG_SBB0_A,
19662306a36Sopenharmony_ci		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
19762306a36Sopenharmony_ci		.curr_table		= max77650_current_limit_table,
19862306a36Sopenharmony_ci		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
19962306a36Sopenharmony_ci	},
20062306a36Sopenharmony_ci	.regA		= MAX77650_REG_CNFG_SBB0_A,
20162306a36Sopenharmony_ci	.regB		= MAX77650_REG_CNFG_SBB0_B,
20262306a36Sopenharmony_ci};
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistatic struct max77650_regulator_desc max77650_SBB1_desc = {
20562306a36Sopenharmony_ci	.desc = {
20662306a36Sopenharmony_ci		.name			= "sbb1",
20762306a36Sopenharmony_ci		.of_match		= of_match_ptr("sbb1"),
20862306a36Sopenharmony_ci		.regulators_node	= of_match_ptr("regulators"),
20962306a36Sopenharmony_ci		.supply_name		= "in-sbb1",
21062306a36Sopenharmony_ci		.id			= MAX77650_REGULATOR_ID_SBB1,
21162306a36Sopenharmony_ci		.ops			= &max77650_regulator_SBB_ops,
21262306a36Sopenharmony_ci		.min_uV			= 800000,
21362306a36Sopenharmony_ci		.uV_step		= 12500,
21462306a36Sopenharmony_ci		.n_voltages		= 64,
21562306a36Sopenharmony_ci		.vsel_step		= 1,
21662306a36Sopenharmony_ci		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
21762306a36Sopenharmony_ci		.vsel_reg		= MAX77650_REG_CNFG_SBB1_A,
21862306a36Sopenharmony_ci		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
21962306a36Sopenharmony_ci		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
22062306a36Sopenharmony_ci		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
22162306a36Sopenharmony_ci		.active_discharge_reg	= MAX77650_REG_CNFG_SBB1_B,
22262306a36Sopenharmony_ci		.enable_time		= 100,
22362306a36Sopenharmony_ci		.type			= REGULATOR_VOLTAGE,
22462306a36Sopenharmony_ci		.owner			= THIS_MODULE,
22562306a36Sopenharmony_ci		.csel_reg		= MAX77650_REG_CNFG_SBB1_A,
22662306a36Sopenharmony_ci		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
22762306a36Sopenharmony_ci		.curr_table		= max77650_current_limit_table,
22862306a36Sopenharmony_ci		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
22962306a36Sopenharmony_ci	},
23062306a36Sopenharmony_ci	.regA		= MAX77650_REG_CNFG_SBB1_A,
23162306a36Sopenharmony_ci	.regB		= MAX77650_REG_CNFG_SBB1_B,
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic struct max77650_regulator_desc max77651_SBB1_desc = {
23562306a36Sopenharmony_ci	.desc = {
23662306a36Sopenharmony_ci		.name			= "sbb1",
23762306a36Sopenharmony_ci		.of_match		= of_match_ptr("sbb1"),
23862306a36Sopenharmony_ci		.regulators_node	= of_match_ptr("regulators"),
23962306a36Sopenharmony_ci		.supply_name		= "in-sbb1",
24062306a36Sopenharmony_ci		.id			= MAX77650_REGULATOR_ID_SBB1,
24162306a36Sopenharmony_ci		.ops			= &max77651_SBB1_regulator_ops,
24262306a36Sopenharmony_ci		.linear_range_selectors_bitfield	= max77651_sbb1_volt_range_sel,
24362306a36Sopenharmony_ci		.linear_ranges		= max77651_sbb1_volt_ranges,
24462306a36Sopenharmony_ci		.n_linear_ranges	= ARRAY_SIZE(max77651_sbb1_volt_ranges),
24562306a36Sopenharmony_ci		.n_voltages		= 58,
24662306a36Sopenharmony_ci		.vsel_step		= 1,
24762306a36Sopenharmony_ci		.vsel_range_mask	= MAX77651_REGULATOR_V_SBB1_RANGE_MASK,
24862306a36Sopenharmony_ci		.vsel_range_reg		= MAX77650_REG_CNFG_SBB1_A,
24962306a36Sopenharmony_ci		.vsel_mask		= MAX77651_REGULATOR_V_SBB1_MASK,
25062306a36Sopenharmony_ci		.vsel_reg		= MAX77650_REG_CNFG_SBB1_A,
25162306a36Sopenharmony_ci		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
25262306a36Sopenharmony_ci		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
25362306a36Sopenharmony_ci		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
25462306a36Sopenharmony_ci		.active_discharge_reg	= MAX77650_REG_CNFG_SBB1_B,
25562306a36Sopenharmony_ci		.enable_time		= 100,
25662306a36Sopenharmony_ci		.type			= REGULATOR_VOLTAGE,
25762306a36Sopenharmony_ci		.owner			= THIS_MODULE,
25862306a36Sopenharmony_ci		.csel_reg		= MAX77650_REG_CNFG_SBB1_A,
25962306a36Sopenharmony_ci		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
26062306a36Sopenharmony_ci		.curr_table		= max77650_current_limit_table,
26162306a36Sopenharmony_ci		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
26262306a36Sopenharmony_ci	},
26362306a36Sopenharmony_ci	.regA		= MAX77650_REG_CNFG_SBB1_A,
26462306a36Sopenharmony_ci	.regB		= MAX77650_REG_CNFG_SBB1_B,
26562306a36Sopenharmony_ci};
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic struct max77650_regulator_desc max77650_SBB2_desc = {
26862306a36Sopenharmony_ci	.desc = {
26962306a36Sopenharmony_ci		.name			= "sbb2",
27062306a36Sopenharmony_ci		.of_match		= of_match_ptr("sbb2"),
27162306a36Sopenharmony_ci		.regulators_node	= of_match_ptr("regulators"),
27262306a36Sopenharmony_ci		.supply_name		= "in-sbb0",
27362306a36Sopenharmony_ci		.id			= MAX77650_REGULATOR_ID_SBB2,
27462306a36Sopenharmony_ci		.ops			= &max77650_regulator_SBB_ops,
27562306a36Sopenharmony_ci		.min_uV			= 800000,
27662306a36Sopenharmony_ci		.uV_step		= 50000,
27762306a36Sopenharmony_ci		.n_voltages		= 64,
27862306a36Sopenharmony_ci		.vsel_step		= 1,
27962306a36Sopenharmony_ci		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
28062306a36Sopenharmony_ci		.vsel_reg		= MAX77650_REG_CNFG_SBB2_A,
28162306a36Sopenharmony_ci		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
28262306a36Sopenharmony_ci		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
28362306a36Sopenharmony_ci		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
28462306a36Sopenharmony_ci		.active_discharge_reg	= MAX77650_REG_CNFG_SBB2_B,
28562306a36Sopenharmony_ci		.enable_time		= 100,
28662306a36Sopenharmony_ci		.type			= REGULATOR_VOLTAGE,
28762306a36Sopenharmony_ci		.owner			= THIS_MODULE,
28862306a36Sopenharmony_ci		.csel_reg		= MAX77650_REG_CNFG_SBB2_A,
28962306a36Sopenharmony_ci		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
29062306a36Sopenharmony_ci		.curr_table		= max77650_current_limit_table,
29162306a36Sopenharmony_ci		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
29262306a36Sopenharmony_ci	},
29362306a36Sopenharmony_ci	.regA		= MAX77650_REG_CNFG_SBB2_A,
29462306a36Sopenharmony_ci	.regB		= MAX77650_REG_CNFG_SBB2_B,
29562306a36Sopenharmony_ci};
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_cistatic struct max77650_regulator_desc max77651_SBB2_desc = {
29862306a36Sopenharmony_ci	.desc = {
29962306a36Sopenharmony_ci		.name			= "sbb2",
30062306a36Sopenharmony_ci		.of_match		= of_match_ptr("sbb2"),
30162306a36Sopenharmony_ci		.regulators_node	= of_match_ptr("regulators"),
30262306a36Sopenharmony_ci		.supply_name		= "in-sbb0",
30362306a36Sopenharmony_ci		.id			= MAX77650_REGULATOR_ID_SBB2,
30462306a36Sopenharmony_ci		.ops			= &max77650_regulator_SBB_ops,
30562306a36Sopenharmony_ci		.min_uV			= 2400000,
30662306a36Sopenharmony_ci		.uV_step		= 50000,
30762306a36Sopenharmony_ci		.n_voltages		= 64,
30862306a36Sopenharmony_ci		.vsel_step		= 1,
30962306a36Sopenharmony_ci		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
31062306a36Sopenharmony_ci		.vsel_reg		= MAX77650_REG_CNFG_SBB2_A,
31162306a36Sopenharmony_ci		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
31262306a36Sopenharmony_ci		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
31362306a36Sopenharmony_ci		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
31462306a36Sopenharmony_ci		.active_discharge_reg	= MAX77650_REG_CNFG_SBB2_B,
31562306a36Sopenharmony_ci		.enable_time		= 100,
31662306a36Sopenharmony_ci		.type			= REGULATOR_VOLTAGE,
31762306a36Sopenharmony_ci		.owner			= THIS_MODULE,
31862306a36Sopenharmony_ci		.csel_reg		= MAX77650_REG_CNFG_SBB2_A,
31962306a36Sopenharmony_ci		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
32062306a36Sopenharmony_ci		.curr_table		= max77650_current_limit_table,
32162306a36Sopenharmony_ci		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
32262306a36Sopenharmony_ci	},
32362306a36Sopenharmony_ci	.regA		= MAX77650_REG_CNFG_SBB2_A,
32462306a36Sopenharmony_ci	.regB		= MAX77650_REG_CNFG_SBB2_B,
32562306a36Sopenharmony_ci};
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic int max77650_regulator_probe(struct platform_device *pdev)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	struct max77650_regulator_desc **rdescs;
33062306a36Sopenharmony_ci	struct max77650_regulator_desc *rdesc;
33162306a36Sopenharmony_ci	struct regulator_config config = { };
33262306a36Sopenharmony_ci	struct device *dev, *parent;
33362306a36Sopenharmony_ci	struct regulator_dev *rdev;
33462306a36Sopenharmony_ci	struct regmap *map;
33562306a36Sopenharmony_ci	unsigned int val;
33662306a36Sopenharmony_ci	int i, rv;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	dev = &pdev->dev;
33962306a36Sopenharmony_ci	parent = dev->parent;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	if (!dev->of_node)
34262306a36Sopenharmony_ci		dev->of_node = parent->of_node;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS,
34562306a36Sopenharmony_ci			      sizeof(*rdescs), GFP_KERNEL);
34662306a36Sopenharmony_ci	if (!rdescs)
34762306a36Sopenharmony_ci		return -ENOMEM;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	map = dev_get_regmap(parent, NULL);
35062306a36Sopenharmony_ci	if (!map)
35162306a36Sopenharmony_ci		return -ENODEV;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	rv = regmap_read(map, MAX77650_REG_CID, &val);
35462306a36Sopenharmony_ci	if (rv)
35562306a36Sopenharmony_ci		return rv;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc;
35862306a36Sopenharmony_ci	rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	switch (MAX77650_CID_BITS(val)) {
36162306a36Sopenharmony_ci	case MAX77650_CID_77650A:
36262306a36Sopenharmony_ci	case MAX77650_CID_77650C:
36362306a36Sopenharmony_ci		rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc;
36462306a36Sopenharmony_ci		rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc;
36562306a36Sopenharmony_ci		break;
36662306a36Sopenharmony_ci	case MAX77650_CID_77651A:
36762306a36Sopenharmony_ci	case MAX77650_CID_77651B:
36862306a36Sopenharmony_ci		rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc;
36962306a36Sopenharmony_ci		rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc;
37062306a36Sopenharmony_ci		break;
37162306a36Sopenharmony_ci	default:
37262306a36Sopenharmony_ci		return -ENODEV;
37362306a36Sopenharmony_ci	}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	config.dev = parent;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) {
37862306a36Sopenharmony_ci		rdesc = rdescs[i];
37962306a36Sopenharmony_ci		config.driver_data = rdesc;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci		rdev = devm_regulator_register(dev, &rdesc->desc, &config);
38262306a36Sopenharmony_ci		if (IS_ERR(rdev))
38362306a36Sopenharmony_ci			return PTR_ERR(rdev);
38462306a36Sopenharmony_ci	}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	return 0;
38762306a36Sopenharmony_ci}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic const struct of_device_id max77650_regulator_of_match[] = {
39062306a36Sopenharmony_ci	{ .compatible = "maxim,max77650-regulator" },
39162306a36Sopenharmony_ci	{ }
39262306a36Sopenharmony_ci};
39362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, max77650_regulator_of_match);
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_cistatic struct platform_driver max77650_regulator_driver = {
39662306a36Sopenharmony_ci	.driver = {
39762306a36Sopenharmony_ci		.name = "max77650-regulator",
39862306a36Sopenharmony_ci		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
39962306a36Sopenharmony_ci		.of_match_table = max77650_regulator_of_match,
40062306a36Sopenharmony_ci	},
40162306a36Sopenharmony_ci	.probe = max77650_regulator_probe,
40262306a36Sopenharmony_ci};
40362306a36Sopenharmony_cimodule_platform_driver(max77650_regulator_driver);
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ciMODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");
40662306a36Sopenharmony_ciMODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
40762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
40862306a36Sopenharmony_ciMODULE_ALIAS("platform:max77650-regulator");
409