162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// Regulator driver for ATC260x PMICs
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright (C) 2019 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
662306a36Sopenharmony_ci// Copyright (C) 2020 Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/mfd/atc260x/core.h>
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/of.h>
1162306a36Sopenharmony_ci#include <linux/platform_device.h>
1262306a36Sopenharmony_ci#include <linux/regmap.h>
1362306a36Sopenharmony_ci#include <linux/regulator/driver.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistruct atc260x_regulator_data {
1662306a36Sopenharmony_ci	int voltage_time_dcdc;
1762306a36Sopenharmony_ci	int voltage_time_ldo;
1862306a36Sopenharmony_ci};
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic const struct linear_range atc2603c_dcdc_voltage_ranges[] = {
2162306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1300000, 0, 13, 50000),
2262306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1950000, 14, 15, 100000),
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic const struct linear_range atc2609a_dcdc_voltage_ranges[] = {
2662306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(600000, 0, 127, 6250),
2762306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1400000, 128, 232, 25000),
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic const struct linear_range atc2609a_ldo_voltage_ranges0[] = {
3162306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(700000, 0, 15, 100000),
3262306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(2100000, 0, 12, 100000),
3362306a36Sopenharmony_ci};
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic const struct linear_range atc2609a_ldo_voltage_ranges1[] = {
3662306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(850000, 0, 15, 100000),
3762306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(2100000, 0, 11, 100000),
3862306a36Sopenharmony_ci};
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic const unsigned int atc260x_ldo_voltage_range_sel[] = {
4162306a36Sopenharmony_ci	0x0, 0x1,
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic int atc260x_dcdc_set_voltage_time_sel(struct regulator_dev *rdev,
4562306a36Sopenharmony_ci					     unsigned int old_selector,
4662306a36Sopenharmony_ci					     unsigned int new_selector)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	struct atc260x_regulator_data *data = rdev_get_drvdata(rdev);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	if (new_selector > old_selector)
5162306a36Sopenharmony_ci		return data->voltage_time_dcdc;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	return 0;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic int atc260x_ldo_set_voltage_time_sel(struct regulator_dev *rdev,
5762306a36Sopenharmony_ci					    unsigned int old_selector,
5862306a36Sopenharmony_ci					    unsigned int new_selector)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	struct atc260x_regulator_data *data = rdev_get_drvdata(rdev);
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	if (new_selector > old_selector)
6362306a36Sopenharmony_ci		return data->voltage_time_ldo;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	return 0;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic const struct regulator_ops atc260x_dcdc_ops = {
6962306a36Sopenharmony_ci	.enable	= regulator_enable_regmap,
7062306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
7162306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
7262306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
7362306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_regmap,
7462306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_regmap,
7562306a36Sopenharmony_ci	.set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel,
7662306a36Sopenharmony_ci};
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic const struct regulator_ops atc260x_ldo_ops = {
7962306a36Sopenharmony_ci	.enable	= regulator_enable_regmap,
8062306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
8162306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
8262306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
8362306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_regmap,
8462306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_regmap,
8562306a36Sopenharmony_ci	.set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel,
8662306a36Sopenharmony_ci};
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic const struct regulator_ops atc260x_ldo_bypass_ops = {
8962306a36Sopenharmony_ci	.enable	= regulator_enable_regmap,
9062306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
9162306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
9262306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
9362306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_regmap,
9462306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_regmap,
9562306a36Sopenharmony_ci	.set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel,
9662306a36Sopenharmony_ci	.set_bypass = regulator_set_bypass_regmap,
9762306a36Sopenharmony_ci	.get_bypass = regulator_get_bypass_regmap,
9862306a36Sopenharmony_ci};
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic const struct regulator_ops atc260x_ldo_bypass_discharge_ops = {
10162306a36Sopenharmony_ci	.enable	= regulator_enable_regmap,
10262306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
10362306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
10462306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
10562306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_regmap,
10662306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_regmap,
10762306a36Sopenharmony_ci	.set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel,
10862306a36Sopenharmony_ci	.set_bypass = regulator_set_bypass_regmap,
10962306a36Sopenharmony_ci	.get_bypass = regulator_get_bypass_regmap,
11062306a36Sopenharmony_ci	.set_active_discharge = regulator_set_active_discharge_regmap,
11162306a36Sopenharmony_ci};
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistatic const struct regulator_ops atc260x_dcdc_range_ops = {
11462306a36Sopenharmony_ci	.enable	= regulator_enable_regmap,
11562306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
11662306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
11762306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear_range,
11862306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_regmap,
11962306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_regmap,
12062306a36Sopenharmony_ci	.set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel,
12162306a36Sopenharmony_ci};
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic const struct regulator_ops atc260x_ldo_range_pick_ops = {
12462306a36Sopenharmony_ci	.enable	= regulator_enable_regmap,
12562306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
12662306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
12762306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_pickable_linear_range,
12862306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
12962306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
13062306a36Sopenharmony_ci	.set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel,
13162306a36Sopenharmony_ci};
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic const struct regulator_ops atc260x_dcdc_fixed_ops = {
13462306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
13562306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_regmap,
13662306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_regmap,
13762306a36Sopenharmony_ci	.set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel,
13862306a36Sopenharmony_ci};
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic const struct regulator_ops atc260x_ldo_fixed_ops = {
14162306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
14262306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_regmap,
14362306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_regmap,
14462306a36Sopenharmony_ci	.set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel,
14562306a36Sopenharmony_ci};
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic const struct regulator_ops atc260x_no_ops = {
14862306a36Sopenharmony_ci};
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci/*
15162306a36Sopenharmony_ci * Note LDO8 is not documented in datasheet (v2.4), but supported
15262306a36Sopenharmony_ci * in the vendor's driver implementation (xapp-le-kernel).
15362306a36Sopenharmony_ci */
15462306a36Sopenharmony_cienum atc2603c_reg_ids {
15562306a36Sopenharmony_ci	ATC2603C_ID_DCDC1,
15662306a36Sopenharmony_ci	ATC2603C_ID_DCDC2,
15762306a36Sopenharmony_ci	ATC2603C_ID_DCDC3,
15862306a36Sopenharmony_ci	ATC2603C_ID_LDO1,
15962306a36Sopenharmony_ci	ATC2603C_ID_LDO2,
16062306a36Sopenharmony_ci	ATC2603C_ID_LDO3,
16162306a36Sopenharmony_ci	ATC2603C_ID_LDO5,
16262306a36Sopenharmony_ci	ATC2603C_ID_LDO6,
16362306a36Sopenharmony_ci	ATC2603C_ID_LDO7,
16462306a36Sopenharmony_ci	ATC2603C_ID_LDO8,
16562306a36Sopenharmony_ci	ATC2603C_ID_LDO11,
16662306a36Sopenharmony_ci	ATC2603C_ID_LDO12,
16762306a36Sopenharmony_ci	ATC2603C_ID_SWITCHLDO1,
16862306a36Sopenharmony_ci	ATC2603C_ID_MAX,
16962306a36Sopenharmony_ci};
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci#define atc2603c_reg_desc_dcdc(num, min, step, n_volt, vsel_h, vsel_l) { \
17262306a36Sopenharmony_ci	.name = "DCDC"#num, \
17362306a36Sopenharmony_ci	.supply_name = "dcdc"#num, \
17462306a36Sopenharmony_ci	.of_match = of_match_ptr("dcdc"#num), \
17562306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
17662306a36Sopenharmony_ci	.id = ATC2603C_ID_DCDC##num, \
17762306a36Sopenharmony_ci	.ops = &atc260x_dcdc_ops, \
17862306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
17962306a36Sopenharmony_ci	.min_uV = min, \
18062306a36Sopenharmony_ci	.uV_step = step, \
18162306a36Sopenharmony_ci	.n_voltages = n_volt, \
18262306a36Sopenharmony_ci	.vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \
18362306a36Sopenharmony_ci	.vsel_mask = GENMASK(vsel_h, vsel_l), \
18462306a36Sopenharmony_ci	.enable_reg = ATC2603C_PMU_DC##num##_CTL0, \
18562306a36Sopenharmony_ci	.enable_mask = BIT(15), \
18662306a36Sopenharmony_ci	.enable_time = 800, \
18762306a36Sopenharmony_ci	.owner = THIS_MODULE, \
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci#define atc2603c_reg_desc_dcdc_range(num, vsel_h, vsel_l) { \
19162306a36Sopenharmony_ci	.name = "DCDC"#num, \
19262306a36Sopenharmony_ci	.supply_name = "dcdc"#num, \
19362306a36Sopenharmony_ci	.of_match = of_match_ptr("dcdc"#num), \
19462306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
19562306a36Sopenharmony_ci	.id = ATC2603C_ID_DCDC##num, \
19662306a36Sopenharmony_ci	.ops = &atc260x_dcdc_range_ops, \
19762306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
19862306a36Sopenharmony_ci	.n_voltages = 16, \
19962306a36Sopenharmony_ci	.linear_ranges = atc2603c_dcdc_voltage_ranges, \
20062306a36Sopenharmony_ci	.n_linear_ranges = ARRAY_SIZE(atc2603c_dcdc_voltage_ranges), \
20162306a36Sopenharmony_ci	.vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \
20262306a36Sopenharmony_ci	.vsel_mask = GENMASK(vsel_h, vsel_l), \
20362306a36Sopenharmony_ci	.enable_reg = ATC2603C_PMU_DC##num##_CTL0, \
20462306a36Sopenharmony_ci	.enable_mask = BIT(15), \
20562306a36Sopenharmony_ci	.enable_time = 800, \
20662306a36Sopenharmony_ci	.owner = THIS_MODULE, \
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci#define atc2603c_reg_desc_dcdc_fixed(num, min, step, n_volt, vsel_h, vsel_l) { \
21062306a36Sopenharmony_ci	.name = "DCDC"#num, \
21162306a36Sopenharmony_ci	.supply_name = "dcdc"#num, \
21262306a36Sopenharmony_ci	.of_match = of_match_ptr("dcdc"#num), \
21362306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
21462306a36Sopenharmony_ci	.id = ATC2603C_ID_DCDC##num, \
21562306a36Sopenharmony_ci	.ops = &atc260x_dcdc_fixed_ops, \
21662306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
21762306a36Sopenharmony_ci	.min_uV = min, \
21862306a36Sopenharmony_ci	.uV_step = step, \
21962306a36Sopenharmony_ci	.n_voltages = n_volt, \
22062306a36Sopenharmony_ci	.vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \
22162306a36Sopenharmony_ci	.vsel_mask = GENMASK(vsel_h, vsel_l), \
22262306a36Sopenharmony_ci	.enable_time = 800, \
22362306a36Sopenharmony_ci	.owner = THIS_MODULE, \
22462306a36Sopenharmony_ci}
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci#define atc2603c_reg_desc_ldo(num, min, step, n_volt, vsel_h, vsel_l) { \
22762306a36Sopenharmony_ci	.name = "LDO"#num, \
22862306a36Sopenharmony_ci	.supply_name = "ldo"#num, \
22962306a36Sopenharmony_ci	.of_match = of_match_ptr("ldo"#num), \
23062306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
23162306a36Sopenharmony_ci	.id = ATC2603C_ID_LDO##num, \
23262306a36Sopenharmony_ci	.ops = &atc260x_ldo_ops, \
23362306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
23462306a36Sopenharmony_ci	.min_uV = min, \
23562306a36Sopenharmony_ci	.uV_step = step, \
23662306a36Sopenharmony_ci	.n_voltages = n_volt, \
23762306a36Sopenharmony_ci	.vsel_reg = ATC2603C_PMU_LDO##num##_CTL, \
23862306a36Sopenharmony_ci	.vsel_mask = GENMASK(vsel_h, vsel_l), \
23962306a36Sopenharmony_ci	.enable_reg = ATC2603C_PMU_LDO##num##_CTL, \
24062306a36Sopenharmony_ci	.enable_mask = BIT(0), \
24162306a36Sopenharmony_ci	.enable_time = 2000, \
24262306a36Sopenharmony_ci	.owner = THIS_MODULE, \
24362306a36Sopenharmony_ci}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci#define atc2603c_reg_desc_ldo_fixed(num, min, step, n_volt, vsel_h, vsel_l) { \
24662306a36Sopenharmony_ci	.name = "LDO"#num, \
24762306a36Sopenharmony_ci	.supply_name = "ldo"#num, \
24862306a36Sopenharmony_ci	.of_match = of_match_ptr("ldo"#num), \
24962306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
25062306a36Sopenharmony_ci	.id = ATC2603C_ID_LDO##num, \
25162306a36Sopenharmony_ci	.ops = &atc260x_ldo_fixed_ops, \
25262306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
25362306a36Sopenharmony_ci	.min_uV = min, \
25462306a36Sopenharmony_ci	.uV_step = step, \
25562306a36Sopenharmony_ci	.n_voltages = n_volt, \
25662306a36Sopenharmony_ci	.vsel_reg = ATC2603C_PMU_LDO##num##_CTL, \
25762306a36Sopenharmony_ci	.vsel_mask = GENMASK(vsel_h, vsel_l), \
25862306a36Sopenharmony_ci	.enable_time = 2000, \
25962306a36Sopenharmony_ci	.owner = THIS_MODULE, \
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci#define atc2603c_reg_desc_ldo_noops(num, vfixed) { \
26362306a36Sopenharmony_ci	.name = "LDO"#num, \
26462306a36Sopenharmony_ci	.supply_name = "ldo"#num, \
26562306a36Sopenharmony_ci	.of_match = of_match_ptr("ldo"#num), \
26662306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
26762306a36Sopenharmony_ci	.id = ATC2603C_ID_LDO##num, \
26862306a36Sopenharmony_ci	.ops = &atc260x_no_ops, \
26962306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
27062306a36Sopenharmony_ci	.fixed_uV = vfixed, \
27162306a36Sopenharmony_ci	.n_voltages = 1, \
27262306a36Sopenharmony_ci	.owner = THIS_MODULE, \
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci#define atc2603c_reg_desc_ldo_switch(num, min, step, n_volt, vsel_h, vsel_l) { \
27662306a36Sopenharmony_ci	.name = "SWITCHLDO"#num, \
27762306a36Sopenharmony_ci	.supply_name = "switchldo"#num, \
27862306a36Sopenharmony_ci	.of_match = of_match_ptr("switchldo"#num), \
27962306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
28062306a36Sopenharmony_ci	.id = ATC2603C_ID_SWITCHLDO##num, \
28162306a36Sopenharmony_ci	.ops = &atc260x_ldo_bypass_discharge_ops, \
28262306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
28362306a36Sopenharmony_ci	.min_uV = min, \
28462306a36Sopenharmony_ci	.uV_step = step, \
28562306a36Sopenharmony_ci	.n_voltages = n_volt, \
28662306a36Sopenharmony_ci	.vsel_reg = ATC2603C_PMU_SWITCH_CTL, \
28762306a36Sopenharmony_ci	.vsel_mask = GENMASK(vsel_h, vsel_l), \
28862306a36Sopenharmony_ci	.enable_reg = ATC2603C_PMU_SWITCH_CTL, \
28962306a36Sopenharmony_ci	.enable_mask = BIT(15), \
29062306a36Sopenharmony_ci	.enable_is_inverted = true, \
29162306a36Sopenharmony_ci	.enable_time = 2000, \
29262306a36Sopenharmony_ci	.bypass_reg = ATC2603C_PMU_SWITCH_CTL, \
29362306a36Sopenharmony_ci	.bypass_mask = BIT(5), \
29462306a36Sopenharmony_ci	.active_discharge_reg = ATC2603C_PMU_SWITCH_CTL, \
29562306a36Sopenharmony_ci	.active_discharge_mask = BIT(1), \
29662306a36Sopenharmony_ci	.active_discharge_on = BIT(1), \
29762306a36Sopenharmony_ci	.owner = THIS_MODULE, \
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic const struct regulator_desc atc2603c_reg[] = {
30162306a36Sopenharmony_ci	atc2603c_reg_desc_dcdc_fixed(1, 700000, 25000, 29, 11, 7),
30262306a36Sopenharmony_ci	atc2603c_reg_desc_dcdc_range(2, 12, 8),
30362306a36Sopenharmony_ci	atc2603c_reg_desc_dcdc_fixed(3, 2600000, 100000, 8, 11, 9),
30462306a36Sopenharmony_ci	atc2603c_reg_desc_ldo_fixed(1, 2600000, 100000, 8, 15, 13),
30562306a36Sopenharmony_ci	atc2603c_reg_desc_ldo_fixed(2, 2600000, 100000, 8, 15, 13),
30662306a36Sopenharmony_ci	atc2603c_reg_desc_ldo_fixed(3, 1500000, 100000, 6, 15, 13),
30762306a36Sopenharmony_ci	atc2603c_reg_desc_ldo(5, 2600000, 100000, 8, 15, 13),
30862306a36Sopenharmony_ci	atc2603c_reg_desc_ldo_fixed(6, 700000, 25000, 29, 15, 11),
30962306a36Sopenharmony_ci	atc2603c_reg_desc_ldo(7, 1500000, 100000, 6, 15, 13),
31062306a36Sopenharmony_ci	atc2603c_reg_desc_ldo(8, 2300000, 100000, 11, 15, 12),
31162306a36Sopenharmony_ci	atc2603c_reg_desc_ldo_fixed(11, 2600000, 100000, 8, 15, 13),
31262306a36Sopenharmony_ci	atc2603c_reg_desc_ldo_noops(12, 1800000),
31362306a36Sopenharmony_ci	atc2603c_reg_desc_ldo_switch(1, 3000000, 100000, 4, 4, 3),
31462306a36Sopenharmony_ci};
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_cistatic const struct regulator_desc atc2603c_reg_dcdc2_ver_b =
31762306a36Sopenharmony_ci	atc2603c_reg_desc_dcdc(2, 1000000, 50000, 18, 12, 8);
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_cienum atc2609a_reg_ids {
32062306a36Sopenharmony_ci	ATC2609A_ID_DCDC0,
32162306a36Sopenharmony_ci	ATC2609A_ID_DCDC1,
32262306a36Sopenharmony_ci	ATC2609A_ID_DCDC2,
32362306a36Sopenharmony_ci	ATC2609A_ID_DCDC3,
32462306a36Sopenharmony_ci	ATC2609A_ID_DCDC4,
32562306a36Sopenharmony_ci	ATC2609A_ID_LDO0,
32662306a36Sopenharmony_ci	ATC2609A_ID_LDO1,
32762306a36Sopenharmony_ci	ATC2609A_ID_LDO2,
32862306a36Sopenharmony_ci	ATC2609A_ID_LDO3,
32962306a36Sopenharmony_ci	ATC2609A_ID_LDO4,
33062306a36Sopenharmony_ci	ATC2609A_ID_LDO5,
33162306a36Sopenharmony_ci	ATC2609A_ID_LDO6,
33262306a36Sopenharmony_ci	ATC2609A_ID_LDO7,
33362306a36Sopenharmony_ci	ATC2609A_ID_LDO8,
33462306a36Sopenharmony_ci	ATC2609A_ID_LDO9,
33562306a36Sopenharmony_ci	ATC2609A_ID_MAX,
33662306a36Sopenharmony_ci};
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci#define atc2609a_reg_desc_dcdc(num, en_bit) { \
33962306a36Sopenharmony_ci	.name = "DCDC"#num, \
34062306a36Sopenharmony_ci	.supply_name = "dcdc"#num, \
34162306a36Sopenharmony_ci	.of_match = of_match_ptr("dcdc"#num), \
34262306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
34362306a36Sopenharmony_ci	.id = ATC2609A_ID_DCDC##num, \
34462306a36Sopenharmony_ci	.ops = &atc260x_dcdc_ops, \
34562306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
34662306a36Sopenharmony_ci	.min_uV = 600000, \
34762306a36Sopenharmony_ci	.uV_step = 6250, \
34862306a36Sopenharmony_ci	.n_voltages = 256, \
34962306a36Sopenharmony_ci	.vsel_reg = ATC2609A_PMU_DC##num##_CTL0, \
35062306a36Sopenharmony_ci	.vsel_mask = GENMASK(15, 8), \
35162306a36Sopenharmony_ci	.enable_reg = ATC2609A_PMU_DC_OSC, \
35262306a36Sopenharmony_ci	.enable_mask = BIT(en_bit), \
35362306a36Sopenharmony_ci	.enable_time = 800, \
35462306a36Sopenharmony_ci	.owner = THIS_MODULE, \
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci#define atc2609a_reg_desc_dcdc_range(num, en_bit) { \
35862306a36Sopenharmony_ci	.name = "DCDC"#num, \
35962306a36Sopenharmony_ci	.supply_name = "dcdc"#num, \
36062306a36Sopenharmony_ci	.of_match = of_match_ptr("dcdc"#num), \
36162306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
36262306a36Sopenharmony_ci	.id = ATC2609A_ID_DCDC##num, \
36362306a36Sopenharmony_ci	.ops = &atc260x_dcdc_range_ops, \
36462306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
36562306a36Sopenharmony_ci	.n_voltages = 233, \
36662306a36Sopenharmony_ci	.linear_ranges = atc2609a_dcdc_voltage_ranges, \
36762306a36Sopenharmony_ci	.n_linear_ranges = ARRAY_SIZE(atc2609a_dcdc_voltage_ranges), \
36862306a36Sopenharmony_ci	.vsel_reg = ATC2609A_PMU_DC##num##_CTL0, \
36962306a36Sopenharmony_ci	.vsel_mask = GENMASK(15, 8), \
37062306a36Sopenharmony_ci	.enable_reg = ATC2609A_PMU_DC_OSC, \
37162306a36Sopenharmony_ci	.enable_mask = BIT(en_bit), \
37262306a36Sopenharmony_ci	.enable_time = 800, \
37362306a36Sopenharmony_ci	.owner = THIS_MODULE, \
37462306a36Sopenharmony_ci}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci#define atc2609a_reg_desc_ldo(num) { \
37762306a36Sopenharmony_ci	.name = "LDO"#num, \
37862306a36Sopenharmony_ci	.supply_name = "ldo"#num, \
37962306a36Sopenharmony_ci	.of_match = of_match_ptr("ldo"#num), \
38062306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
38162306a36Sopenharmony_ci	.id = ATC2609A_ID_LDO##num, \
38262306a36Sopenharmony_ci	.ops = &atc260x_ldo_ops, \
38362306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
38462306a36Sopenharmony_ci	.min_uV = 700000, \
38562306a36Sopenharmony_ci	.uV_step = 100000, \
38662306a36Sopenharmony_ci	.n_voltages = 16, \
38762306a36Sopenharmony_ci	.vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \
38862306a36Sopenharmony_ci	.vsel_mask = GENMASK(4, 1), \
38962306a36Sopenharmony_ci	.enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \
39062306a36Sopenharmony_ci	.enable_mask = BIT(0), \
39162306a36Sopenharmony_ci	.enable_time = 2000, \
39262306a36Sopenharmony_ci	.owner = THIS_MODULE, \
39362306a36Sopenharmony_ci}
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci#define atc2609a_reg_desc_ldo_bypass(num) { \
39662306a36Sopenharmony_ci	.name = "LDO"#num, \
39762306a36Sopenharmony_ci	.supply_name = "ldo"#num, \
39862306a36Sopenharmony_ci	.of_match = of_match_ptr("ldo"#num), \
39962306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
40062306a36Sopenharmony_ci	.id = ATC2609A_ID_LDO##num, \
40162306a36Sopenharmony_ci	.ops = &atc260x_ldo_bypass_ops, \
40262306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
40362306a36Sopenharmony_ci	.min_uV = 2300000, \
40462306a36Sopenharmony_ci	.uV_step = 100000, \
40562306a36Sopenharmony_ci	.n_voltages = 12, \
40662306a36Sopenharmony_ci	.vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \
40762306a36Sopenharmony_ci	.vsel_mask = GENMASK(5, 2), \
40862306a36Sopenharmony_ci	.enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \
40962306a36Sopenharmony_ci	.enable_mask = BIT(0), \
41062306a36Sopenharmony_ci	.enable_time = 2000, \
41162306a36Sopenharmony_ci	.bypass_reg = ATC2609A_PMU_LDO##num##_CTL0, \
41262306a36Sopenharmony_ci	.bypass_mask = BIT(1), \
41362306a36Sopenharmony_ci	.owner = THIS_MODULE, \
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci#define atc2609a_reg_desc_ldo_range_pick(num, n_range, n_volt) { \
41762306a36Sopenharmony_ci	.name = "LDO"#num, \
41862306a36Sopenharmony_ci	.supply_name = "ldo"#num, \
41962306a36Sopenharmony_ci	.of_match = of_match_ptr("ldo"#num), \
42062306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
42162306a36Sopenharmony_ci	.id = ATC2609A_ID_LDO##num, \
42262306a36Sopenharmony_ci	.ops = &atc260x_ldo_range_pick_ops, \
42362306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
42462306a36Sopenharmony_ci	.linear_ranges = atc2609a_ldo_voltage_ranges##n_range, \
42562306a36Sopenharmony_ci	.n_linear_ranges = ARRAY_SIZE(atc2609a_ldo_voltage_ranges##n_range), \
42662306a36Sopenharmony_ci	.n_voltages = n_volt, \
42762306a36Sopenharmony_ci	.vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \
42862306a36Sopenharmony_ci	.vsel_mask = GENMASK(4, 1), \
42962306a36Sopenharmony_ci	.vsel_range_reg = ATC2609A_PMU_LDO##num##_CTL0, \
43062306a36Sopenharmony_ci	.vsel_range_mask = BIT(5), \
43162306a36Sopenharmony_ci	.linear_range_selectors_bitfield = atc260x_ldo_voltage_range_sel, \
43262306a36Sopenharmony_ci	.enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \
43362306a36Sopenharmony_ci	.enable_mask = BIT(0), \
43462306a36Sopenharmony_ci	.enable_time = 2000, \
43562306a36Sopenharmony_ci	.owner = THIS_MODULE, \
43662306a36Sopenharmony_ci}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci#define atc2609a_reg_desc_ldo_fixed(num) { \
43962306a36Sopenharmony_ci	.name = "LDO"#num, \
44062306a36Sopenharmony_ci	.supply_name = "ldo"#num, \
44162306a36Sopenharmony_ci	.of_match = of_match_ptr("ldo"#num), \
44262306a36Sopenharmony_ci	.regulators_node = of_match_ptr("regulators"), \
44362306a36Sopenharmony_ci	.id = ATC2609A_ID_LDO##num, \
44462306a36Sopenharmony_ci	.ops = &atc260x_ldo_fixed_ops, \
44562306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE, \
44662306a36Sopenharmony_ci	.min_uV = 2600000, \
44762306a36Sopenharmony_ci	.uV_step = 100000, \
44862306a36Sopenharmony_ci	.n_voltages = 8, \
44962306a36Sopenharmony_ci	.vsel_reg = ATC2609A_PMU_LDO##num##_CTL, \
45062306a36Sopenharmony_ci	.vsel_mask = GENMASK(15, 13), \
45162306a36Sopenharmony_ci	.enable_time = 2000, \
45262306a36Sopenharmony_ci	.owner = THIS_MODULE, \
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_cistatic const struct regulator_desc atc2609a_reg[] = {
45662306a36Sopenharmony_ci	atc2609a_reg_desc_dcdc(0, 4),
45762306a36Sopenharmony_ci	atc2609a_reg_desc_dcdc(1, 5),
45862306a36Sopenharmony_ci	atc2609a_reg_desc_dcdc(2, 6),
45962306a36Sopenharmony_ci	atc2609a_reg_desc_dcdc_range(3, 7),
46062306a36Sopenharmony_ci	atc2609a_reg_desc_dcdc(4, 8),
46162306a36Sopenharmony_ci	atc2609a_reg_desc_ldo_bypass(0),
46262306a36Sopenharmony_ci	atc2609a_reg_desc_ldo_bypass(1),
46362306a36Sopenharmony_ci	atc2609a_reg_desc_ldo_bypass(2),
46462306a36Sopenharmony_ci	atc2609a_reg_desc_ldo_range_pick(3, 0, 29),
46562306a36Sopenharmony_ci	atc2609a_reg_desc_ldo_range_pick(4, 0, 29),
46662306a36Sopenharmony_ci	atc2609a_reg_desc_ldo(5),
46762306a36Sopenharmony_ci	atc2609a_reg_desc_ldo_range_pick(6, 1, 28),
46862306a36Sopenharmony_ci	atc2609a_reg_desc_ldo_range_pick(7, 0, 29),
46962306a36Sopenharmony_ci	atc2609a_reg_desc_ldo_range_pick(8, 0, 29),
47062306a36Sopenharmony_ci	atc2609a_reg_desc_ldo_fixed(9),
47162306a36Sopenharmony_ci};
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_cistatic int atc260x_regulator_probe(struct platform_device *pdev)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	struct atc260x *atc260x = dev_get_drvdata(pdev->dev.parent);
47662306a36Sopenharmony_ci	struct device *dev = atc260x->dev;
47762306a36Sopenharmony_ci	struct atc260x_regulator_data *atc260x_data;
47862306a36Sopenharmony_ci	struct regulator_config config = {};
47962306a36Sopenharmony_ci	struct regulator_dev *atc260x_rdev;
48062306a36Sopenharmony_ci	const struct regulator_desc *regulators;
48162306a36Sopenharmony_ci	bool atc2603c_ver_b = false;
48262306a36Sopenharmony_ci	int i, nregulators;
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	atc260x_data = devm_kzalloc(&pdev->dev, sizeof(*atc260x_data), GFP_KERNEL);
48562306a36Sopenharmony_ci	if (!atc260x_data)
48662306a36Sopenharmony_ci		return -ENOMEM;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	atc260x_data->voltage_time_dcdc = 350;
48962306a36Sopenharmony_ci	atc260x_data->voltage_time_ldo = 800;
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	switch (atc260x->ic_type) {
49262306a36Sopenharmony_ci	case ATC2603C:
49362306a36Sopenharmony_ci		regulators = atc2603c_reg;
49462306a36Sopenharmony_ci		nregulators = ATC2603C_ID_MAX;
49562306a36Sopenharmony_ci		atc2603c_ver_b = atc260x->ic_ver == ATC260X_B;
49662306a36Sopenharmony_ci		break;
49762306a36Sopenharmony_ci	case ATC2609A:
49862306a36Sopenharmony_ci		atc260x_data->voltage_time_dcdc = 250;
49962306a36Sopenharmony_ci		regulators = atc2609a_reg;
50062306a36Sopenharmony_ci		nregulators = ATC2609A_ID_MAX;
50162306a36Sopenharmony_ci		break;
50262306a36Sopenharmony_ci	default:
50362306a36Sopenharmony_ci		dev_err(dev, "unsupported ATC260X ID %d\n", atc260x->ic_type);
50462306a36Sopenharmony_ci		return -EINVAL;
50562306a36Sopenharmony_ci	}
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	config.dev = dev;
50862306a36Sopenharmony_ci	config.regmap = atc260x->regmap;
50962306a36Sopenharmony_ci	config.driver_data = atc260x_data;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	/* Instantiate the regulators */
51262306a36Sopenharmony_ci	for (i = 0; i < nregulators; i++) {
51362306a36Sopenharmony_ci		if (atc2603c_ver_b && regulators[i].id == ATC2603C_ID_DCDC2)
51462306a36Sopenharmony_ci			atc260x_rdev = devm_regulator_register(&pdev->dev,
51562306a36Sopenharmony_ci							       &atc2603c_reg_dcdc2_ver_b,
51662306a36Sopenharmony_ci							       &config);
51762306a36Sopenharmony_ci		else
51862306a36Sopenharmony_ci			atc260x_rdev = devm_regulator_register(&pdev->dev,
51962306a36Sopenharmony_ci							       &regulators[i],
52062306a36Sopenharmony_ci							       &config);
52162306a36Sopenharmony_ci		if (IS_ERR(atc260x_rdev)) {
52262306a36Sopenharmony_ci			dev_err(dev, "failed to register regulator: %d\n", i);
52362306a36Sopenharmony_ci			return PTR_ERR(atc260x_rdev);
52462306a36Sopenharmony_ci		}
52562306a36Sopenharmony_ci	}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	return 0;
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_cistatic struct platform_driver atc260x_regulator_driver = {
53162306a36Sopenharmony_ci	.probe = atc260x_regulator_probe,
53262306a36Sopenharmony_ci	.driver = {
53362306a36Sopenharmony_ci		.name = "atc260x-regulator",
53462306a36Sopenharmony_ci		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
53562306a36Sopenharmony_ci	},
53662306a36Sopenharmony_ci};
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_cimodule_platform_driver(atc260x_regulator_driver);
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ciMODULE_DESCRIPTION("Regulator driver for ATC260x PMICs");
54162306a36Sopenharmony_ciMODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
54262306a36Sopenharmony_ciMODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@gmail.com>");
54362306a36Sopenharmony_ciMODULE_LICENSE("GPL");
544