162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci// Copyright (C) 2018 ROHM Semiconductors
362306a36Sopenharmony_ci// bd71837-regulator.c ROHM BD71837MWV/BD71847MWV regulator driver
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/delay.h>
662306a36Sopenharmony_ci#include <linux/err.h>
762306a36Sopenharmony_ci#include <linux/interrupt.h>
862306a36Sopenharmony_ci#include <linux/kernel.h>
962306a36Sopenharmony_ci#include <linux/mfd/rohm-bd718x7.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/of.h>
1262306a36Sopenharmony_ci#include <linux/platform_device.h>
1362306a36Sopenharmony_ci#include <linux/regulator/driver.h>
1462306a36Sopenharmony_ci#include <linux/regulator/machine.h>
1562306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h>
1662306a36Sopenharmony_ci#include <linux/slab.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* Typical regulator startup times as per data sheet in uS */
1962306a36Sopenharmony_ci#define BD71847_BUCK1_STARTUP_TIME 144
2062306a36Sopenharmony_ci#define BD71847_BUCK2_STARTUP_TIME 162
2162306a36Sopenharmony_ci#define BD71847_BUCK3_STARTUP_TIME 162
2262306a36Sopenharmony_ci#define BD71847_BUCK4_STARTUP_TIME 240
2362306a36Sopenharmony_ci#define BD71847_BUCK5_STARTUP_TIME 270
2462306a36Sopenharmony_ci#define BD71847_BUCK6_STARTUP_TIME 200
2562306a36Sopenharmony_ci#define BD71847_LDO1_STARTUP_TIME  440
2662306a36Sopenharmony_ci#define BD71847_LDO2_STARTUP_TIME  370
2762306a36Sopenharmony_ci#define BD71847_LDO3_STARTUP_TIME  310
2862306a36Sopenharmony_ci#define BD71847_LDO4_STARTUP_TIME  400
2962306a36Sopenharmony_ci#define BD71847_LDO5_STARTUP_TIME  530
3062306a36Sopenharmony_ci#define BD71847_LDO6_STARTUP_TIME  400
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define BD71837_BUCK1_STARTUP_TIME 160
3362306a36Sopenharmony_ci#define BD71837_BUCK2_STARTUP_TIME 180
3462306a36Sopenharmony_ci#define BD71837_BUCK3_STARTUP_TIME 180
3562306a36Sopenharmony_ci#define BD71837_BUCK4_STARTUP_TIME 180
3662306a36Sopenharmony_ci#define BD71837_BUCK5_STARTUP_TIME 160
3762306a36Sopenharmony_ci#define BD71837_BUCK6_STARTUP_TIME 240
3862306a36Sopenharmony_ci#define BD71837_BUCK7_STARTUP_TIME 220
3962306a36Sopenharmony_ci#define BD71837_BUCK8_STARTUP_TIME 200
4062306a36Sopenharmony_ci#define BD71837_LDO1_STARTUP_TIME  440
4162306a36Sopenharmony_ci#define BD71837_LDO2_STARTUP_TIME  370
4262306a36Sopenharmony_ci#define BD71837_LDO3_STARTUP_TIME  310
4362306a36Sopenharmony_ci#define BD71837_LDO4_STARTUP_TIME  400
4462306a36Sopenharmony_ci#define BD71837_LDO5_STARTUP_TIME  310
4562306a36Sopenharmony_ci#define BD71837_LDO6_STARTUP_TIME  400
4662306a36Sopenharmony_ci#define BD71837_LDO7_STARTUP_TIME  530
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/*
4962306a36Sopenharmony_ci * BD718(37/47/50) have two "enable control modes". ON/OFF can either be
5062306a36Sopenharmony_ci * controlled by software - or by PMIC internal HW state machine. Whether
5162306a36Sopenharmony_ci * regulator should be under SW or HW control can be defined from device-tree.
5262306a36Sopenharmony_ci * Let's provide separate ops for regulators to use depending on the "enable
5362306a36Sopenharmony_ci * control mode".
5462306a36Sopenharmony_ci */
5562306a36Sopenharmony_ci#define BD718XX_HWOPNAME(swopname) swopname##_hwcontrol
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define BD718XX_OPS(name, _list_voltage, _map_voltage, _set_voltage_sel, \
5862306a36Sopenharmony_ci		   _get_voltage_sel, _set_voltage_time_sel, _set_ramp_delay, \
5962306a36Sopenharmony_ci		   _set_uvp, _set_ovp)				\
6062306a36Sopenharmony_cistatic const struct regulator_ops name = {			\
6162306a36Sopenharmony_ci	.enable = regulator_enable_regmap,			\
6262306a36Sopenharmony_ci	.disable = regulator_disable_regmap,			\
6362306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,		\
6462306a36Sopenharmony_ci	.list_voltage = (_list_voltage),			\
6562306a36Sopenharmony_ci	.map_voltage = (_map_voltage),				\
6662306a36Sopenharmony_ci	.set_voltage_sel = (_set_voltage_sel),			\
6762306a36Sopenharmony_ci	.get_voltage_sel = (_get_voltage_sel),			\
6862306a36Sopenharmony_ci	.set_voltage_time_sel = (_set_voltage_time_sel),	\
6962306a36Sopenharmony_ci	.set_ramp_delay = (_set_ramp_delay),			\
7062306a36Sopenharmony_ci	.set_under_voltage_protection = (_set_uvp),		\
7162306a36Sopenharmony_ci	.set_over_voltage_protection = (_set_ovp),		\
7262306a36Sopenharmony_ci};								\
7362306a36Sopenharmony_ci								\
7462306a36Sopenharmony_cistatic const struct regulator_ops BD718XX_HWOPNAME(name) = {	\
7562306a36Sopenharmony_ci	.is_enabled = always_enabled_by_hwstate,		\
7662306a36Sopenharmony_ci	.list_voltage = (_list_voltage),			\
7762306a36Sopenharmony_ci	.map_voltage = (_map_voltage),				\
7862306a36Sopenharmony_ci	.set_voltage_sel = (_set_voltage_sel),			\
7962306a36Sopenharmony_ci	.get_voltage_sel = (_get_voltage_sel),			\
8062306a36Sopenharmony_ci	.set_voltage_time_sel = (_set_voltage_time_sel),	\
8162306a36Sopenharmony_ci	.set_ramp_delay = (_set_ramp_delay),			\
8262306a36Sopenharmony_ci	.set_under_voltage_protection = (_set_uvp),		\
8362306a36Sopenharmony_ci	.set_over_voltage_protection = (_set_ovp),		\
8462306a36Sopenharmony_ci}								\
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/*
8762306a36Sopenharmony_ci * BUCK1/2/3/4
8862306a36Sopenharmony_ci * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting
8962306a36Sopenharmony_ci * 00: 10.00mV/usec 10mV 1uS
9062306a36Sopenharmony_ci * 01: 5.00mV/usec	10mV 2uS
9162306a36Sopenharmony_ci * 10: 2.50mV/usec	10mV 4uS
9262306a36Sopenharmony_ci * 11: 1.25mV/usec	10mV 8uS
9362306a36Sopenharmony_ci */
9462306a36Sopenharmony_cistatic const unsigned int bd718xx_ramp_delay[] = { 10000, 5000, 2500, 1250 };
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* These functions are used when regulators are under HW state machine control.
9762306a36Sopenharmony_ci * We assume PMIC is in RUN state because SW running and able to query the
9862306a36Sopenharmony_ci * status. Most of the regulators have fixed ON or OFF state at RUN/IDLE so for
9962306a36Sopenharmony_ci * them we just return a constant. BD71837 BUCK3 and BUCK4 are exceptions as
10062306a36Sopenharmony_ci * they support configuring the ON/OFF state for RUN.
10162306a36Sopenharmony_ci *
10262306a36Sopenharmony_ci * Note for next hacker - these PMICs have a register where the HW state can be
10362306a36Sopenharmony_ci * read. If assuming RUN appears to be false in your use-case - you can
10462306a36Sopenharmony_ci * implement state reading (although that is not going to be atomic) before
10562306a36Sopenharmony_ci * returning the enable state.
10662306a36Sopenharmony_ci */
10762306a36Sopenharmony_cistatic int always_enabled_by_hwstate(struct regulator_dev *rdev)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	return 1;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic int never_enabled_by_hwstate(struct regulator_dev *rdev)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	return 0;
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic int bd71837_get_buck34_enable_hwctrl(struct regulator_dev *rdev)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	int ret;
12062306a36Sopenharmony_ci	unsigned int val;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
12362306a36Sopenharmony_ci	if (ret)
12462306a36Sopenharmony_ci		return ret;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	return !!(BD718XX_BUCK_RUN_ON & val);
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic void voltage_change_done(struct regulator_dev *rdev, unsigned int sel,
13062306a36Sopenharmony_ci				unsigned int *mask)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	int ret;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	if (*mask) {
13562306a36Sopenharmony_ci		/*
13662306a36Sopenharmony_ci		 * Let's allow scheduling as we use I2C anyways. We just need to
13762306a36Sopenharmony_ci		 * guarantee minimum of 1ms sleep - it shouldn't matter if we
13862306a36Sopenharmony_ci		 * exceed it due to the scheduling.
13962306a36Sopenharmony_ci		 */
14062306a36Sopenharmony_ci		msleep(1);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci		ret = regmap_clear_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2,
14362306a36Sopenharmony_ci					 *mask);
14462306a36Sopenharmony_ci		if (ret)
14562306a36Sopenharmony_ci			dev_err(&rdev->dev,
14662306a36Sopenharmony_ci				"Failed to re-enable voltage monitoring (%d)\n",
14762306a36Sopenharmony_ci				ret);
14862306a36Sopenharmony_ci	}
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic int voltage_change_prepare(struct regulator_dev *rdev, unsigned int sel,
15262306a36Sopenharmony_ci				  unsigned int *mask)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	int ret;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	*mask = 0;
15762306a36Sopenharmony_ci	if (rdev->desc->ops->is_enabled(rdev)) {
15862306a36Sopenharmony_ci		int now, new;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci		now = rdev->desc->ops->get_voltage_sel(rdev);
16162306a36Sopenharmony_ci		if (now < 0)
16262306a36Sopenharmony_ci			return now;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci		now = rdev->desc->ops->list_voltage(rdev, now);
16562306a36Sopenharmony_ci		if (now < 0)
16662306a36Sopenharmony_ci			return now;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci		new = rdev->desc->ops->list_voltage(rdev, sel);
16962306a36Sopenharmony_ci		if (new < 0)
17062306a36Sopenharmony_ci			return new;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci		/*
17362306a36Sopenharmony_ci		 * If we increase LDO voltage when LDO is enabled we need to
17462306a36Sopenharmony_ci		 * disable the power-good detection until voltage has reached
17562306a36Sopenharmony_ci		 * the new level. According to HW colleagues the maximum time
17662306a36Sopenharmony_ci		 * it takes is 1000us. I assume that on systems with light load
17762306a36Sopenharmony_ci		 * this might be less - and we could probably use DT to give
17862306a36Sopenharmony_ci		 * system specific delay value if performance matters.
17962306a36Sopenharmony_ci		 *
18062306a36Sopenharmony_ci		 * Well, knowing we use I2C here and can add scheduling delays
18162306a36Sopenharmony_ci		 * I don't think it is worth the hassle and I just add fixed
18262306a36Sopenharmony_ci		 * 1ms sleep here (and allow scheduling). If this turns out to
18362306a36Sopenharmony_ci		 * be a problem we can change it to delay and make the delay
18462306a36Sopenharmony_ci		 * time configurable.
18562306a36Sopenharmony_ci		 */
18662306a36Sopenharmony_ci		if (new > now) {
18762306a36Sopenharmony_ci			int tmp;
18862306a36Sopenharmony_ci			int prot_bit;
18962306a36Sopenharmony_ci			int ldo_offset = rdev->desc->id - BD718XX_LDO1;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci			prot_bit = BD718XX_LDO1_VRMON80 << ldo_offset;
19262306a36Sopenharmony_ci			ret = regmap_read(rdev->regmap, BD718XX_REG_MVRFLTMASK2,
19362306a36Sopenharmony_ci					  &tmp);
19462306a36Sopenharmony_ci			if (ret) {
19562306a36Sopenharmony_ci				dev_err(&rdev->dev,
19662306a36Sopenharmony_ci					"Failed to read voltage monitoring state\n");
19762306a36Sopenharmony_ci				return ret;
19862306a36Sopenharmony_ci			}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci			if (!(tmp & prot_bit)) {
20162306a36Sopenharmony_ci				/* We disable protection if it was enabled... */
20262306a36Sopenharmony_ci				ret = regmap_set_bits(rdev->regmap,
20362306a36Sopenharmony_ci						      BD718XX_REG_MVRFLTMASK2,
20462306a36Sopenharmony_ci						      prot_bit);
20562306a36Sopenharmony_ci				/* ...and we also want to re-enable it */
20662306a36Sopenharmony_ci				*mask = prot_bit;
20762306a36Sopenharmony_ci			}
20862306a36Sopenharmony_ci			if (ret) {
20962306a36Sopenharmony_ci				dev_err(&rdev->dev,
21062306a36Sopenharmony_ci					"Failed to stop voltage monitoring\n");
21162306a36Sopenharmony_ci				return ret;
21262306a36Sopenharmony_ci			}
21362306a36Sopenharmony_ci		}
21462306a36Sopenharmony_ci	}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	return 0;
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_cistatic int bd718xx_set_voltage_sel_restricted(struct regulator_dev *rdev,
22062306a36Sopenharmony_ci						    unsigned int sel)
22162306a36Sopenharmony_ci{
22262306a36Sopenharmony_ci	int ret;
22362306a36Sopenharmony_ci	int mask;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	ret = voltage_change_prepare(rdev, sel, &mask);
22662306a36Sopenharmony_ci	if (ret)
22762306a36Sopenharmony_ci		return ret;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	ret = regulator_set_voltage_sel_regmap(rdev, sel);
23062306a36Sopenharmony_ci	voltage_change_done(rdev, sel, &mask);
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	return ret;
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic int bd718xx_set_voltage_sel_pickable_restricted(
23662306a36Sopenharmony_ci		struct regulator_dev *rdev, unsigned int sel)
23762306a36Sopenharmony_ci{
23862306a36Sopenharmony_ci	int ret;
23962306a36Sopenharmony_ci	int mask;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	ret = voltage_change_prepare(rdev, sel, &mask);
24262306a36Sopenharmony_ci	if (ret)
24362306a36Sopenharmony_ci		return ret;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	ret = regulator_set_voltage_sel_pickable_regmap(rdev, sel);
24662306a36Sopenharmony_ci	voltage_change_done(rdev, sel, &mask);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	return ret;
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic int bd71837_set_voltage_sel_pickable_restricted(
25262306a36Sopenharmony_ci		struct regulator_dev *rdev, unsigned int sel)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	if (rdev->desc->ops->is_enabled(rdev))
25562306a36Sopenharmony_ci		return -EBUSY;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	return regulator_set_voltage_sel_pickable_regmap(rdev, sel);
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci/*
26162306a36Sopenharmony_ci * BD71837 BUCK1/2/3/4
26262306a36Sopenharmony_ci * BD71847 BUCK1/2
26362306a36Sopenharmony_ci * 0.70 to 1.30V (10mV step)
26462306a36Sopenharmony_ci */
26562306a36Sopenharmony_cistatic const struct linear_range bd718xx_dvs_buck_volts[] = {
26662306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(700000, 0x00, 0x3C, 10000),
26762306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1300000, 0x3D, 0x3F, 0),
26862306a36Sopenharmony_ci};
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci/*
27162306a36Sopenharmony_ci * BD71837 BUCK5
27262306a36Sopenharmony_ci * 0.7V to 1.35V  (range 0)
27362306a36Sopenharmony_ci * and
27462306a36Sopenharmony_ci * 0.675 to 1.325 (range 1)
27562306a36Sopenharmony_ci */
27662306a36Sopenharmony_cistatic const struct linear_range bd71837_buck5_volts[] = {
27762306a36Sopenharmony_ci	/* Ranges when VOLT_SEL bit is 0 */
27862306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000),
27962306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000),
28062306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1200000, 0x06, 0x07, 150000),
28162306a36Sopenharmony_ci	/* Ranges when VOLT_SEL bit is 1  */
28262306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(675000, 0x0, 0x3, 100000),
28362306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1025000, 0x4, 0x5, 50000),
28462306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1175000, 0x6, 0x7, 150000),
28562306a36Sopenharmony_ci};
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci/*
28862306a36Sopenharmony_ci * Range selector for first 3 linear ranges is 0x0
28962306a36Sopenharmony_ci * and 0x1 for last 3 ranges.
29062306a36Sopenharmony_ci */
29162306a36Sopenharmony_cistatic const unsigned int bd71837_buck5_volt_range_sel[] = {
29262306a36Sopenharmony_ci	0x0, 0x0, 0x0, 0x1, 0x1, 0x1
29362306a36Sopenharmony_ci};
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci/*
29662306a36Sopenharmony_ci * BD71847 BUCK3
29762306a36Sopenharmony_ci */
29862306a36Sopenharmony_cistatic const struct linear_range bd71847_buck3_volts[] = {
29962306a36Sopenharmony_ci	/* Ranges when VOLT_SEL bits are 00 */
30062306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000),
30162306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000),
30262306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1200000, 0x06, 0x07, 150000),
30362306a36Sopenharmony_ci	/* Ranges when VOLT_SEL bits are 01 */
30462306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(550000, 0x0, 0x7, 50000),
30562306a36Sopenharmony_ci	/* Ranges when VOLT_SEL bits are 11 */
30662306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(675000, 0x0, 0x3, 100000),
30762306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1025000, 0x4, 0x5, 50000),
30862306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1175000, 0x6, 0x7, 150000),
30962306a36Sopenharmony_ci};
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_cistatic const unsigned int bd71847_buck3_volt_range_sel[] = {
31262306a36Sopenharmony_ci	0x0, 0x0, 0x0, 0x1, 0x2, 0x2, 0x2
31362306a36Sopenharmony_ci};
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic const struct linear_range bd71847_buck4_volts[] = {
31662306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000),
31762306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(2600000, 0x00, 0x03, 100000),
31862306a36Sopenharmony_ci};
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cistatic const unsigned int bd71847_buck4_volt_range_sel[] = { 0x0, 0x1 };
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci/*
32362306a36Sopenharmony_ci * BUCK6
32462306a36Sopenharmony_ci * 3.0V to 3.3V (step 100mV)
32562306a36Sopenharmony_ci */
32662306a36Sopenharmony_cistatic const struct linear_range bd71837_buck6_volts[] = {
32762306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000),
32862306a36Sopenharmony_ci};
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci/*
33162306a36Sopenharmony_ci * BD71837 BUCK7
33262306a36Sopenharmony_ci * BD71847 BUCK5
33362306a36Sopenharmony_ci * 000 = 1.605V
33462306a36Sopenharmony_ci * 001 = 1.695V
33562306a36Sopenharmony_ci * 010 = 1.755V
33662306a36Sopenharmony_ci * 011 = 1.8V (Initial)
33762306a36Sopenharmony_ci * 100 = 1.845V
33862306a36Sopenharmony_ci * 101 = 1.905V
33962306a36Sopenharmony_ci * 110 = 1.95V
34062306a36Sopenharmony_ci * 111 = 1.995V
34162306a36Sopenharmony_ci */
34262306a36Sopenharmony_cistatic const unsigned int bd718xx_3rd_nodvs_buck_volts[] = {
34362306a36Sopenharmony_ci	1605000, 1695000, 1755000, 1800000, 1845000, 1905000, 1950000, 1995000
34462306a36Sopenharmony_ci};
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci/*
34762306a36Sopenharmony_ci * BUCK8
34862306a36Sopenharmony_ci * 0.8V to 1.40V (step 10mV)
34962306a36Sopenharmony_ci */
35062306a36Sopenharmony_cistatic const struct linear_range bd718xx_4th_nodvs_buck_volts[] = {
35162306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(800000, 0x00, 0x3C, 10000),
35262306a36Sopenharmony_ci};
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci/*
35562306a36Sopenharmony_ci * LDO1
35662306a36Sopenharmony_ci * 3.0 to 3.3V (100mV step)
35762306a36Sopenharmony_ci */
35862306a36Sopenharmony_cistatic const struct linear_range bd718xx_ldo1_volts[] = {
35962306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000),
36062306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1600000, 0x00, 0x03, 100000),
36162306a36Sopenharmony_ci};
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic const unsigned int bd718xx_ldo1_volt_range_sel[] = { 0x0, 0x1 };
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci/*
36662306a36Sopenharmony_ci * LDO2
36762306a36Sopenharmony_ci * 0.8 or 0.9V
36862306a36Sopenharmony_ci */
36962306a36Sopenharmony_cistatic const unsigned int ldo_2_volts[] = {
37062306a36Sopenharmony_ci	900000, 800000
37162306a36Sopenharmony_ci};
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci/*
37462306a36Sopenharmony_ci * LDO3
37562306a36Sopenharmony_ci * 1.8 to 3.3V (100mV step)
37662306a36Sopenharmony_ci */
37762306a36Sopenharmony_cistatic const struct linear_range bd718xx_ldo3_volts[] = {
37862306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
37962306a36Sopenharmony_ci};
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci/*
38262306a36Sopenharmony_ci * LDO4
38362306a36Sopenharmony_ci * 0.9 to 1.8V (100mV step)
38462306a36Sopenharmony_ci */
38562306a36Sopenharmony_cistatic const struct linear_range bd718xx_ldo4_volts[] = {
38662306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000),
38762306a36Sopenharmony_ci};
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci/*
39062306a36Sopenharmony_ci * LDO5 for BD71837
39162306a36Sopenharmony_ci * 1.8 to 3.3V (100mV step)
39262306a36Sopenharmony_ci */
39362306a36Sopenharmony_cistatic const struct linear_range bd71837_ldo5_volts[] = {
39462306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
39562306a36Sopenharmony_ci};
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci/*
39862306a36Sopenharmony_ci * LDO5 for BD71837
39962306a36Sopenharmony_ci * 1.8 to 3.3V (100mV step)
40062306a36Sopenharmony_ci */
40162306a36Sopenharmony_cistatic const struct linear_range bd71847_ldo5_volts[] = {
40262306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
40362306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(800000, 0x00, 0x0F, 100000),
40462306a36Sopenharmony_ci};
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_cistatic const unsigned int bd71847_ldo5_volt_range_sel[] = { 0x0, 0x1 };
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci/*
40962306a36Sopenharmony_ci * LDO6
41062306a36Sopenharmony_ci * 0.9 to 1.8V (100mV step)
41162306a36Sopenharmony_ci */
41262306a36Sopenharmony_cistatic const struct linear_range bd718xx_ldo6_volts[] = {
41362306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000),
41462306a36Sopenharmony_ci};
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci/*
41762306a36Sopenharmony_ci * LDO7
41862306a36Sopenharmony_ci * 1.8 to 3.3V (100mV step)
41962306a36Sopenharmony_ci */
42062306a36Sopenharmony_cistatic const struct linear_range bd71837_ldo7_volts[] = {
42162306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
42262306a36Sopenharmony_ci};
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_cistruct reg_init {
42562306a36Sopenharmony_ci	unsigned int reg;
42662306a36Sopenharmony_ci	unsigned int mask;
42762306a36Sopenharmony_ci	unsigned int val;
42862306a36Sopenharmony_ci};
42962306a36Sopenharmony_cistruct bd718xx_regulator_data {
43062306a36Sopenharmony_ci	struct regulator_desc desc;
43162306a36Sopenharmony_ci	const struct rohm_dvs_config dvs;
43262306a36Sopenharmony_ci	const struct reg_init init;
43362306a36Sopenharmony_ci	const struct reg_init *additional_inits;
43462306a36Sopenharmony_ci	int additional_init_amnt;
43562306a36Sopenharmony_ci};
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_cistatic int bd718x7_xvp_sanity_check(struct regulator_dev *rdev, int lim_uV,
43862306a36Sopenharmony_ci				    int severity)
43962306a36Sopenharmony_ci{
44062306a36Sopenharmony_ci	/*
44162306a36Sopenharmony_ci	 * BD71837/47/50 ... (ICs supported by this driver) do not provide
44262306a36Sopenharmony_ci	 * warnings, only protection
44362306a36Sopenharmony_ci	 */
44462306a36Sopenharmony_ci	if (severity != REGULATOR_SEVERITY_PROT) {
44562306a36Sopenharmony_ci		dev_err(&rdev->dev,
44662306a36Sopenharmony_ci			"Unsupported Under Voltage protection level\n");
44762306a36Sopenharmony_ci		return -EINVAL;
44862306a36Sopenharmony_ci	}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	/*
45162306a36Sopenharmony_ci	 * And protection limit is not changeable. It can only be enabled
45262306a36Sopenharmony_ci	 * or disabled
45362306a36Sopenharmony_ci	 */
45462306a36Sopenharmony_ci	if (lim_uV)
45562306a36Sopenharmony_ci		return -EINVAL;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	return 0;
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_cistatic int bd718x7_set_ldo_uvp(struct regulator_dev *rdev, int lim_uV,
46162306a36Sopenharmony_ci			       int severity, bool enable)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	int ldo_offset = rdev->desc->id - BD718XX_LDO1;
46462306a36Sopenharmony_ci	int prot_bit, ret;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	ret = bd718x7_xvp_sanity_check(rdev, lim_uV, severity);
46762306a36Sopenharmony_ci	if (ret)
46862306a36Sopenharmony_ci		return ret;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	prot_bit = BD718XX_LDO1_VRMON80 << ldo_offset;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	if (enable)
47362306a36Sopenharmony_ci		return regmap_clear_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2,
47462306a36Sopenharmony_ci					 prot_bit);
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	return regmap_set_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2,
47762306a36Sopenharmony_ci			       prot_bit);
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_cistatic int bd718x7_get_buck_prot_reg(int id, int *reg)
48162306a36Sopenharmony_ci{
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	if (id > BD718XX_BUCK8) {
48462306a36Sopenharmony_ci		WARN_ON(id > BD718XX_BUCK8);
48562306a36Sopenharmony_ci		return -EINVAL;
48662306a36Sopenharmony_ci	}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	if (id > BD718XX_BUCK4)
48962306a36Sopenharmony_ci		*reg = BD718XX_REG_MVRFLTMASK0;
49062306a36Sopenharmony_ci	else
49162306a36Sopenharmony_ci		*reg = BD718XX_REG_MVRFLTMASK1;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	return 0;
49462306a36Sopenharmony_ci}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_cistatic int bd718x7_get_buck_ovp_info(int id, int *reg, int *bit)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci	int ret;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	ret = bd718x7_get_buck_prot_reg(id, reg);
50162306a36Sopenharmony_ci	if (ret)
50262306a36Sopenharmony_ci		return ret;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	*bit = BIT((id % 4) * 2 + 1);
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	return 0;
50762306a36Sopenharmony_ci}
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_cistatic int bd718x7_get_buck_uvp_info(int id, int *reg, int *bit)
51062306a36Sopenharmony_ci{
51162306a36Sopenharmony_ci	int ret;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	ret = bd718x7_get_buck_prot_reg(id, reg);
51462306a36Sopenharmony_ci	if (ret)
51562306a36Sopenharmony_ci		return ret;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	*bit = BIT((id % 4) * 2);
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	return 0;
52062306a36Sopenharmony_ci}
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_cistatic int bd718x7_set_buck_uvp(struct regulator_dev *rdev, int lim_uV,
52362306a36Sopenharmony_ci				int severity, bool enable)
52462306a36Sopenharmony_ci{
52562306a36Sopenharmony_ci	int bit, reg, ret;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	ret = bd718x7_xvp_sanity_check(rdev, lim_uV, severity);
52862306a36Sopenharmony_ci	if (ret)
52962306a36Sopenharmony_ci		return ret;
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	ret = bd718x7_get_buck_uvp_info(rdev->desc->id, &reg, &bit);
53262306a36Sopenharmony_ci	if (ret)
53362306a36Sopenharmony_ci		return ret;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	if (enable)
53662306a36Sopenharmony_ci		return regmap_clear_bits(rdev->regmap, reg, bit);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	return regmap_set_bits(rdev->regmap, reg, bit);
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_cistatic int bd718x7_set_buck_ovp(struct regulator_dev *rdev, int lim_uV,
54362306a36Sopenharmony_ci				int severity,
54462306a36Sopenharmony_ci				bool enable)
54562306a36Sopenharmony_ci{
54662306a36Sopenharmony_ci	int bit, reg, ret;
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	ret = bd718x7_xvp_sanity_check(rdev, lim_uV, severity);
54962306a36Sopenharmony_ci	if (ret)
55062306a36Sopenharmony_ci		return ret;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	ret = bd718x7_get_buck_ovp_info(rdev->desc->id, &reg, &bit);
55362306a36Sopenharmony_ci	if (ret)
55462306a36Sopenharmony_ci		return ret;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	if (enable)
55762306a36Sopenharmony_ci		return regmap_clear_bits(rdev->regmap, reg, bit);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	return regmap_set_bits(rdev->regmap, reg, bit);
56062306a36Sopenharmony_ci}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci/*
56362306a36Sopenharmony_ci * OPS common for BD71847 and BD71850
56462306a36Sopenharmony_ci */
56562306a36Sopenharmony_ciBD718XX_OPS(bd718xx_pickable_range_ldo_ops,
56662306a36Sopenharmony_ci	    regulator_list_voltage_pickable_linear_range, NULL,
56762306a36Sopenharmony_ci	    bd718xx_set_voltage_sel_pickable_restricted,
56862306a36Sopenharmony_ci	    regulator_get_voltage_sel_pickable_regmap, NULL, NULL,
56962306a36Sopenharmony_ci	    bd718x7_set_ldo_uvp, NULL);
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci/* BD71847 and BD71850 LDO 5 is by default OFF at RUN state */
57262306a36Sopenharmony_cistatic const struct regulator_ops bd718xx_ldo5_ops_hwstate = {
57362306a36Sopenharmony_ci	.is_enabled = never_enabled_by_hwstate,
57462306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_pickable_linear_range,
57562306a36Sopenharmony_ci	.set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted,
57662306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
57762306a36Sopenharmony_ci	.set_under_voltage_protection = bd718x7_set_ldo_uvp,
57862306a36Sopenharmony_ci};
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ciBD718XX_OPS(bd718xx_pickable_range_buck_ops,
58162306a36Sopenharmony_ci	    regulator_list_voltage_pickable_linear_range, NULL,
58262306a36Sopenharmony_ci	    regulator_set_voltage_sel_pickable_regmap,
58362306a36Sopenharmony_ci	    regulator_get_voltage_sel_pickable_regmap,
58462306a36Sopenharmony_ci	    regulator_set_voltage_time_sel, NULL, bd718x7_set_buck_uvp,
58562306a36Sopenharmony_ci	    bd718x7_set_buck_ovp);
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ciBD718XX_OPS(bd718xx_ldo_regulator_ops, regulator_list_voltage_linear_range,
58862306a36Sopenharmony_ci	    NULL, bd718xx_set_voltage_sel_restricted,
58962306a36Sopenharmony_ci	    regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp,
59062306a36Sopenharmony_ci	    NULL);
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ciBD718XX_OPS(bd718xx_ldo_regulator_nolinear_ops, regulator_list_voltage_table,
59362306a36Sopenharmony_ci	    NULL, bd718xx_set_voltage_sel_restricted,
59462306a36Sopenharmony_ci	    regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp,
59562306a36Sopenharmony_ci	    NULL);
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ciBD718XX_OPS(bd718xx_buck_regulator_ops, regulator_list_voltage_linear_range,
59862306a36Sopenharmony_ci	    NULL, regulator_set_voltage_sel_regmap,
59962306a36Sopenharmony_ci	    regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
60062306a36Sopenharmony_ci	    NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp);
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ciBD718XX_OPS(bd718xx_buck_regulator_nolinear_ops, regulator_list_voltage_table,
60362306a36Sopenharmony_ci	    regulator_map_voltage_ascend, regulator_set_voltage_sel_regmap,
60462306a36Sopenharmony_ci	    regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
60562306a36Sopenharmony_ci	    NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp);
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci/*
60862306a36Sopenharmony_ci * OPS for BD71837
60962306a36Sopenharmony_ci */
61062306a36Sopenharmony_ciBD718XX_OPS(bd71837_pickable_range_ldo_ops,
61162306a36Sopenharmony_ci	    regulator_list_voltage_pickable_linear_range, NULL,
61262306a36Sopenharmony_ci	    bd71837_set_voltage_sel_pickable_restricted,
61362306a36Sopenharmony_ci	    regulator_get_voltage_sel_pickable_regmap, NULL, NULL,
61462306a36Sopenharmony_ci	    bd718x7_set_ldo_uvp, NULL);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ciBD718XX_OPS(bd71837_pickable_range_buck_ops,
61762306a36Sopenharmony_ci	    regulator_list_voltage_pickable_linear_range, NULL,
61862306a36Sopenharmony_ci	    bd71837_set_voltage_sel_pickable_restricted,
61962306a36Sopenharmony_ci	    regulator_get_voltage_sel_pickable_regmap,
62062306a36Sopenharmony_ci	    regulator_set_voltage_time_sel, NULL, bd718x7_set_buck_uvp,
62162306a36Sopenharmony_ci	    bd718x7_set_buck_ovp);
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ciBD718XX_OPS(bd71837_ldo_regulator_ops, regulator_list_voltage_linear_range,
62462306a36Sopenharmony_ci	    NULL, rohm_regulator_set_voltage_sel_restricted,
62562306a36Sopenharmony_ci	    regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp,
62662306a36Sopenharmony_ci	    NULL);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ciBD718XX_OPS(bd71837_ldo_regulator_nolinear_ops, regulator_list_voltage_table,
62962306a36Sopenharmony_ci	    NULL, rohm_regulator_set_voltage_sel_restricted,
63062306a36Sopenharmony_ci	    regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp,
63162306a36Sopenharmony_ci	    NULL);
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ciBD718XX_OPS(bd71837_buck_regulator_ops, regulator_list_voltage_linear_range,
63462306a36Sopenharmony_ci	    NULL, rohm_regulator_set_voltage_sel_restricted,
63562306a36Sopenharmony_ci	    regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
63662306a36Sopenharmony_ci	    NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp);
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ciBD718XX_OPS(bd71837_buck_regulator_nolinear_ops, regulator_list_voltage_table,
63962306a36Sopenharmony_ci	    regulator_map_voltage_ascend, rohm_regulator_set_voltage_sel_restricted,
64062306a36Sopenharmony_ci	    regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
64162306a36Sopenharmony_ci	    NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp);
64262306a36Sopenharmony_ci/*
64362306a36Sopenharmony_ci * BD71837 bucks 3 and 4 support defining their enable/disable state also
64462306a36Sopenharmony_ci * when buck enable state is under HW state machine control. In that case the
64562306a36Sopenharmony_ci * bit [2] in CTRL register is used to indicate if regulator should be ON.
64662306a36Sopenharmony_ci */
64762306a36Sopenharmony_cistatic const struct regulator_ops bd71837_buck34_ops_hwctrl = {
64862306a36Sopenharmony_ci	.is_enabled = bd71837_get_buck34_enable_hwctrl,
64962306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear_range,
65062306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_regmap,
65162306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_regmap,
65262306a36Sopenharmony_ci	.set_voltage_time_sel = regulator_set_voltage_time_sel,
65362306a36Sopenharmony_ci	.set_ramp_delay = regulator_set_ramp_delay_regmap,
65462306a36Sopenharmony_ci	.set_under_voltage_protection = bd718x7_set_buck_uvp,
65562306a36Sopenharmony_ci	.set_over_voltage_protection = bd718x7_set_buck_ovp,
65662306a36Sopenharmony_ci};
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci/*
65962306a36Sopenharmony_ci * OPS for all of the ICs - BD718(37/47/50)
66062306a36Sopenharmony_ci */
66162306a36Sopenharmony_ciBD718XX_OPS(bd718xx_dvs_buck_regulator_ops, regulator_list_voltage_linear_range,
66262306a36Sopenharmony_ci	    NULL, regulator_set_voltage_sel_regmap,
66362306a36Sopenharmony_ci	    regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
66462306a36Sopenharmony_ci	    regulator_set_ramp_delay_regmap, bd718x7_set_buck_uvp,
66562306a36Sopenharmony_ci	    bd718x7_set_buck_ovp);
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci/*
67062306a36Sopenharmony_ci * There is a HW quirk in BD71837. The shutdown sequence timings for
67162306a36Sopenharmony_ci * bucks/LDOs which are controlled via register interface are changed.
67262306a36Sopenharmony_ci * At PMIC poweroff the voltage for BUCK6/7 is cut immediately at the
67362306a36Sopenharmony_ci * beginning of shut-down sequence. As bucks 6 and 7 are parent
67462306a36Sopenharmony_ci * supplies for LDO5 and LDO6 - this causes LDO5/6 voltage
67562306a36Sopenharmony_ci * monitoring to errorneously detect under voltage and force PMIC to
67662306a36Sopenharmony_ci * emergency state instead of poweroff. In order to avoid this we
67762306a36Sopenharmony_ci * disable voltage monitoring for LDO5 and LDO6
67862306a36Sopenharmony_ci */
67962306a36Sopenharmony_cistatic const struct reg_init bd71837_ldo5_inits[] = {
68062306a36Sopenharmony_ci	{
68162306a36Sopenharmony_ci		.reg = BD718XX_REG_MVRFLTMASK2,
68262306a36Sopenharmony_ci		.mask = BD718XX_LDO5_VRMON80,
68362306a36Sopenharmony_ci		.val = BD718XX_LDO5_VRMON80,
68462306a36Sopenharmony_ci	},
68562306a36Sopenharmony_ci};
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_cistatic const struct reg_init bd71837_ldo6_inits[] = {
68862306a36Sopenharmony_ci	{
68962306a36Sopenharmony_ci		.reg = BD718XX_REG_MVRFLTMASK2,
69062306a36Sopenharmony_ci		.mask = BD718XX_LDO6_VRMON80,
69162306a36Sopenharmony_ci		.val = BD718XX_LDO6_VRMON80,
69262306a36Sopenharmony_ci	},
69362306a36Sopenharmony_ci};
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_cistatic int buck_set_hw_dvs_levels(struct device_node *np,
69662306a36Sopenharmony_ci			    const struct regulator_desc *desc,
69762306a36Sopenharmony_ci			    struct regulator_config *cfg)
69862306a36Sopenharmony_ci{
69962306a36Sopenharmony_ci	struct bd718xx_regulator_data *data;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	data = container_of(desc, struct bd718xx_regulator_data, desc);
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap);
70462306a36Sopenharmony_ci}
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_cistatic const struct regulator_ops *bd71847_swcontrol_ops[] = {
70762306a36Sopenharmony_ci	&bd718xx_dvs_buck_regulator_ops, &bd718xx_dvs_buck_regulator_ops,
70862306a36Sopenharmony_ci	&bd718xx_pickable_range_buck_ops, &bd718xx_pickable_range_buck_ops,
70962306a36Sopenharmony_ci	&bd718xx_buck_regulator_nolinear_ops, &bd718xx_buck_regulator_ops,
71062306a36Sopenharmony_ci	&bd718xx_pickable_range_ldo_ops, &bd718xx_ldo_regulator_nolinear_ops,
71162306a36Sopenharmony_ci	&bd718xx_ldo_regulator_ops, &bd718xx_ldo_regulator_ops,
71262306a36Sopenharmony_ci	&bd718xx_pickable_range_ldo_ops, &bd718xx_ldo_regulator_ops,
71362306a36Sopenharmony_ci};
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_cistatic const struct regulator_ops *bd71847_hwcontrol_ops[] = {
71662306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops),
71762306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops),
71862306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_pickable_range_buck_ops),
71962306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_pickable_range_buck_ops),
72062306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_buck_regulator_nolinear_ops),
72162306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_buck_regulator_ops),
72262306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_pickable_range_ldo_ops),
72362306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_ldo_regulator_nolinear_ops),
72462306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_ldo_regulator_ops),
72562306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_ldo_regulator_ops),
72662306a36Sopenharmony_ci	&bd718xx_ldo5_ops_hwstate,
72762306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_ldo_regulator_ops),
72862306a36Sopenharmony_ci};
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_cistatic struct bd718xx_regulator_data bd71847_regulators[] = {
73162306a36Sopenharmony_ci	{
73262306a36Sopenharmony_ci		.desc = {
73362306a36Sopenharmony_ci			.name = "buck1",
73462306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK1"),
73562306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
73662306a36Sopenharmony_ci			.id = BD718XX_BUCK1,
73762306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
73862306a36Sopenharmony_ci			.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
73962306a36Sopenharmony_ci			.linear_ranges = bd718xx_dvs_buck_volts,
74062306a36Sopenharmony_ci			.n_linear_ranges =
74162306a36Sopenharmony_ci				ARRAY_SIZE(bd718xx_dvs_buck_volts),
74262306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_BUCK1_VOLT_RUN,
74362306a36Sopenharmony_ci			.vsel_mask = DVS_BUCK_RUN_MASK,
74462306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_BUCK1_CTRL,
74562306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
74662306a36Sopenharmony_ci			.enable_time = BD71847_BUCK1_STARTUP_TIME,
74762306a36Sopenharmony_ci			.owner = THIS_MODULE,
74862306a36Sopenharmony_ci			.ramp_delay_table = bd718xx_ramp_delay,
74962306a36Sopenharmony_ci			.n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
75062306a36Sopenharmony_ci			.ramp_reg = BD718XX_REG_BUCK1_CTRL,
75162306a36Sopenharmony_ci			.ramp_mask = BUCK_RAMPRATE_MASK,
75262306a36Sopenharmony_ci			.of_parse_cb = buck_set_hw_dvs_levels,
75362306a36Sopenharmony_ci		},
75462306a36Sopenharmony_ci		.dvs = {
75562306a36Sopenharmony_ci			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
75662306a36Sopenharmony_ci				     ROHM_DVS_LEVEL_SUSPEND,
75762306a36Sopenharmony_ci			.run_reg = BD718XX_REG_BUCK1_VOLT_RUN,
75862306a36Sopenharmony_ci			.run_mask = DVS_BUCK_RUN_MASK,
75962306a36Sopenharmony_ci			.idle_reg = BD718XX_REG_BUCK1_VOLT_IDLE,
76062306a36Sopenharmony_ci			.idle_mask = DVS_BUCK_RUN_MASK,
76162306a36Sopenharmony_ci			.suspend_reg = BD718XX_REG_BUCK1_VOLT_SUSP,
76262306a36Sopenharmony_ci			.suspend_mask = DVS_BUCK_RUN_MASK,
76362306a36Sopenharmony_ci		},
76462306a36Sopenharmony_ci		.init = {
76562306a36Sopenharmony_ci			.reg = BD718XX_REG_BUCK1_CTRL,
76662306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
76762306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
76862306a36Sopenharmony_ci		},
76962306a36Sopenharmony_ci	},
77062306a36Sopenharmony_ci	{
77162306a36Sopenharmony_ci		.desc = {
77262306a36Sopenharmony_ci			.name = "buck2",
77362306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK2"),
77462306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
77562306a36Sopenharmony_ci			.id = BD718XX_BUCK2,
77662306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
77762306a36Sopenharmony_ci			.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
77862306a36Sopenharmony_ci			.linear_ranges = bd718xx_dvs_buck_volts,
77962306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_dvs_buck_volts),
78062306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_BUCK2_VOLT_RUN,
78162306a36Sopenharmony_ci			.vsel_mask = DVS_BUCK_RUN_MASK,
78262306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_BUCK2_CTRL,
78362306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
78462306a36Sopenharmony_ci			.enable_time = BD71847_BUCK2_STARTUP_TIME,
78562306a36Sopenharmony_ci			.ramp_delay_table = bd718xx_ramp_delay,
78662306a36Sopenharmony_ci			.n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
78762306a36Sopenharmony_ci			.ramp_reg = BD718XX_REG_BUCK2_CTRL,
78862306a36Sopenharmony_ci			.ramp_mask = BUCK_RAMPRATE_MASK,
78962306a36Sopenharmony_ci			.owner = THIS_MODULE,
79062306a36Sopenharmony_ci			.of_parse_cb = buck_set_hw_dvs_levels,
79162306a36Sopenharmony_ci		},
79262306a36Sopenharmony_ci		.dvs = {
79362306a36Sopenharmony_ci			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE,
79462306a36Sopenharmony_ci			.run_reg = BD718XX_REG_BUCK2_VOLT_RUN,
79562306a36Sopenharmony_ci			.run_mask = DVS_BUCK_RUN_MASK,
79662306a36Sopenharmony_ci			.idle_reg = BD718XX_REG_BUCK2_VOLT_IDLE,
79762306a36Sopenharmony_ci			.idle_mask = DVS_BUCK_RUN_MASK,
79862306a36Sopenharmony_ci		},
79962306a36Sopenharmony_ci		.init = {
80062306a36Sopenharmony_ci			.reg = BD718XX_REG_BUCK2_CTRL,
80162306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
80262306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
80362306a36Sopenharmony_ci		},
80462306a36Sopenharmony_ci	},
80562306a36Sopenharmony_ci	{
80662306a36Sopenharmony_ci		.desc = {
80762306a36Sopenharmony_ci			.name = "buck3",
80862306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK3"),
80962306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
81062306a36Sopenharmony_ci			.id = BD718XX_BUCK3,
81162306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
81262306a36Sopenharmony_ci			.n_voltages = BD71847_BUCK3_VOLTAGE_NUM,
81362306a36Sopenharmony_ci			.linear_ranges = bd71847_buck3_volts,
81462306a36Sopenharmony_ci			.n_linear_ranges =
81562306a36Sopenharmony_ci				ARRAY_SIZE(bd71847_buck3_volts),
81662306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT,
81762306a36Sopenharmony_ci			.vsel_mask = BD718XX_1ST_NODVS_BUCK_MASK,
81862306a36Sopenharmony_ci			.vsel_range_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT,
81962306a36Sopenharmony_ci			.vsel_range_mask = BD71847_BUCK3_RANGE_MASK,
82062306a36Sopenharmony_ci			.linear_range_selectors_bitfield = bd71847_buck3_volt_range_sel,
82162306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL,
82262306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
82362306a36Sopenharmony_ci			.enable_time = BD71847_BUCK3_STARTUP_TIME,
82462306a36Sopenharmony_ci			.owner = THIS_MODULE,
82562306a36Sopenharmony_ci		},
82662306a36Sopenharmony_ci		.init = {
82762306a36Sopenharmony_ci			.reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL,
82862306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
82962306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
83062306a36Sopenharmony_ci		},
83162306a36Sopenharmony_ci	},
83262306a36Sopenharmony_ci	{
83362306a36Sopenharmony_ci		.desc = {
83462306a36Sopenharmony_ci			.name = "buck4",
83562306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK4"),
83662306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
83762306a36Sopenharmony_ci			.id = BD718XX_BUCK4,
83862306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
83962306a36Sopenharmony_ci			.n_voltages = BD71847_BUCK4_VOLTAGE_NUM,
84062306a36Sopenharmony_ci			.linear_ranges = bd71847_buck4_volts,
84162306a36Sopenharmony_ci			.n_linear_ranges =
84262306a36Sopenharmony_ci				ARRAY_SIZE(bd71847_buck4_volts),
84362306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL,
84462306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_2ND_NODVS_BUCK_VOLT,
84562306a36Sopenharmony_ci			.vsel_mask = BD71847_BUCK4_MASK,
84662306a36Sopenharmony_ci			.vsel_range_reg = BD718XX_REG_2ND_NODVS_BUCK_VOLT,
84762306a36Sopenharmony_ci			.vsel_range_mask = BD71847_BUCK4_RANGE_MASK,
84862306a36Sopenharmony_ci			.linear_range_selectors_bitfield = bd71847_buck4_volt_range_sel,
84962306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
85062306a36Sopenharmony_ci			.enable_time = BD71847_BUCK4_STARTUP_TIME,
85162306a36Sopenharmony_ci			.owner = THIS_MODULE,
85262306a36Sopenharmony_ci		},
85362306a36Sopenharmony_ci		.init = {
85462306a36Sopenharmony_ci			.reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL,
85562306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
85662306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
85762306a36Sopenharmony_ci		},
85862306a36Sopenharmony_ci	},
85962306a36Sopenharmony_ci	{
86062306a36Sopenharmony_ci		.desc = {
86162306a36Sopenharmony_ci			.name = "buck5",
86262306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK5"),
86362306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
86462306a36Sopenharmony_ci			.id = BD718XX_BUCK5,
86562306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
86662306a36Sopenharmony_ci			.volt_table = &bd718xx_3rd_nodvs_buck_volts[0],
86762306a36Sopenharmony_ci			.n_voltages = ARRAY_SIZE(bd718xx_3rd_nodvs_buck_volts),
86862306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_3RD_NODVS_BUCK_VOLT,
86962306a36Sopenharmony_ci			.vsel_mask = BD718XX_3RD_NODVS_BUCK_MASK,
87062306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_3RD_NODVS_BUCK_CTRL,
87162306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
87262306a36Sopenharmony_ci			.enable_time = BD71847_BUCK5_STARTUP_TIME,
87362306a36Sopenharmony_ci			.owner = THIS_MODULE,
87462306a36Sopenharmony_ci		},
87562306a36Sopenharmony_ci		.init = {
87662306a36Sopenharmony_ci			.reg = BD718XX_REG_3RD_NODVS_BUCK_CTRL,
87762306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
87862306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
87962306a36Sopenharmony_ci		},
88062306a36Sopenharmony_ci	},
88162306a36Sopenharmony_ci	{
88262306a36Sopenharmony_ci		.desc = {
88362306a36Sopenharmony_ci			.name = "buck6",
88462306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK6"),
88562306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
88662306a36Sopenharmony_ci			.id = BD718XX_BUCK6,
88762306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
88862306a36Sopenharmony_ci			.n_voltages = BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM,
88962306a36Sopenharmony_ci			.linear_ranges = bd718xx_4th_nodvs_buck_volts,
89062306a36Sopenharmony_ci			.n_linear_ranges =
89162306a36Sopenharmony_ci				ARRAY_SIZE(bd718xx_4th_nodvs_buck_volts),
89262306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_4TH_NODVS_BUCK_VOLT,
89362306a36Sopenharmony_ci			.vsel_mask = BD718XX_4TH_NODVS_BUCK_MASK,
89462306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_4TH_NODVS_BUCK_CTRL,
89562306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
89662306a36Sopenharmony_ci			.enable_time = BD71847_BUCK6_STARTUP_TIME,
89762306a36Sopenharmony_ci			.owner = THIS_MODULE,
89862306a36Sopenharmony_ci		},
89962306a36Sopenharmony_ci		.init = {
90062306a36Sopenharmony_ci			.reg = BD718XX_REG_4TH_NODVS_BUCK_CTRL,
90162306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
90262306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
90362306a36Sopenharmony_ci		},
90462306a36Sopenharmony_ci	},
90562306a36Sopenharmony_ci	{
90662306a36Sopenharmony_ci		.desc = {
90762306a36Sopenharmony_ci			.name = "ldo1",
90862306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO1"),
90962306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
91062306a36Sopenharmony_ci			.id = BD718XX_LDO1,
91162306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
91262306a36Sopenharmony_ci			.n_voltages = BD718XX_LDO1_VOLTAGE_NUM,
91362306a36Sopenharmony_ci			.linear_ranges = bd718xx_ldo1_volts,
91462306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_ldo1_volts),
91562306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO1_VOLT,
91662306a36Sopenharmony_ci			.vsel_mask = BD718XX_LDO1_MASK,
91762306a36Sopenharmony_ci			.vsel_range_reg = BD718XX_REG_LDO1_VOLT,
91862306a36Sopenharmony_ci			.vsel_range_mask = BD718XX_LDO1_RANGE_MASK,
91962306a36Sopenharmony_ci			.linear_range_selectors_bitfield = bd718xx_ldo1_volt_range_sel,
92062306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO1_VOLT,
92162306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
92262306a36Sopenharmony_ci			.enable_time = BD71847_LDO1_STARTUP_TIME,
92362306a36Sopenharmony_ci			.owner = THIS_MODULE,
92462306a36Sopenharmony_ci		},
92562306a36Sopenharmony_ci		.init = {
92662306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO1_VOLT,
92762306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
92862306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
92962306a36Sopenharmony_ci		},
93062306a36Sopenharmony_ci	},
93162306a36Sopenharmony_ci	{
93262306a36Sopenharmony_ci		.desc = {
93362306a36Sopenharmony_ci			.name = "ldo2",
93462306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO2"),
93562306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
93662306a36Sopenharmony_ci			.id = BD718XX_LDO2,
93762306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
93862306a36Sopenharmony_ci			.volt_table = &ldo_2_volts[0],
93962306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO2_VOLT,
94062306a36Sopenharmony_ci			.vsel_mask = BD718XX_LDO2_MASK,
94162306a36Sopenharmony_ci			.n_voltages = ARRAY_SIZE(ldo_2_volts),
94262306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO2_VOLT,
94362306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
94462306a36Sopenharmony_ci			.enable_time = BD71847_LDO2_STARTUP_TIME,
94562306a36Sopenharmony_ci			.owner = THIS_MODULE,
94662306a36Sopenharmony_ci		},
94762306a36Sopenharmony_ci		.init = {
94862306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO2_VOLT,
94962306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
95062306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
95162306a36Sopenharmony_ci		},
95262306a36Sopenharmony_ci	},
95362306a36Sopenharmony_ci	{
95462306a36Sopenharmony_ci		.desc = {
95562306a36Sopenharmony_ci			.name = "ldo3",
95662306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO3"),
95762306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
95862306a36Sopenharmony_ci			.id = BD718XX_LDO3,
95962306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
96062306a36Sopenharmony_ci			.n_voltages = BD718XX_LDO3_VOLTAGE_NUM,
96162306a36Sopenharmony_ci			.linear_ranges = bd718xx_ldo3_volts,
96262306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_ldo3_volts),
96362306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO3_VOLT,
96462306a36Sopenharmony_ci			.vsel_mask = BD718XX_LDO3_MASK,
96562306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO3_VOLT,
96662306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
96762306a36Sopenharmony_ci			.enable_time = BD71847_LDO3_STARTUP_TIME,
96862306a36Sopenharmony_ci			.owner = THIS_MODULE,
96962306a36Sopenharmony_ci		},
97062306a36Sopenharmony_ci		.init = {
97162306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO3_VOLT,
97262306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
97362306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
97462306a36Sopenharmony_ci		},
97562306a36Sopenharmony_ci	},
97662306a36Sopenharmony_ci	{
97762306a36Sopenharmony_ci		.desc = {
97862306a36Sopenharmony_ci			.name = "ldo4",
97962306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO4"),
98062306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
98162306a36Sopenharmony_ci			.id = BD718XX_LDO4,
98262306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
98362306a36Sopenharmony_ci			.n_voltages = BD718XX_LDO4_VOLTAGE_NUM,
98462306a36Sopenharmony_ci			.linear_ranges = bd718xx_ldo4_volts,
98562306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_ldo4_volts),
98662306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO4_VOLT,
98762306a36Sopenharmony_ci			.vsel_mask = BD718XX_LDO4_MASK,
98862306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO4_VOLT,
98962306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
99062306a36Sopenharmony_ci			.enable_time = BD71847_LDO4_STARTUP_TIME,
99162306a36Sopenharmony_ci			.owner = THIS_MODULE,
99262306a36Sopenharmony_ci		},
99362306a36Sopenharmony_ci		.init = {
99462306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO4_VOLT,
99562306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
99662306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
99762306a36Sopenharmony_ci		},
99862306a36Sopenharmony_ci	},
99962306a36Sopenharmony_ci	{
100062306a36Sopenharmony_ci		.desc = {
100162306a36Sopenharmony_ci			.name = "ldo5",
100262306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO5"),
100362306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
100462306a36Sopenharmony_ci			.id = BD718XX_LDO5,
100562306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
100662306a36Sopenharmony_ci			.n_voltages = BD71847_LDO5_VOLTAGE_NUM,
100762306a36Sopenharmony_ci			.linear_ranges = bd71847_ldo5_volts,
100862306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd71847_ldo5_volts),
100962306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO5_VOLT,
101062306a36Sopenharmony_ci			.vsel_mask = BD71847_LDO5_MASK,
101162306a36Sopenharmony_ci			.vsel_range_reg = BD718XX_REG_LDO5_VOLT,
101262306a36Sopenharmony_ci			.vsel_range_mask = BD71847_LDO5_RANGE_MASK,
101362306a36Sopenharmony_ci			.linear_range_selectors_bitfield = bd71847_ldo5_volt_range_sel,
101462306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO5_VOLT,
101562306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
101662306a36Sopenharmony_ci			.enable_time = BD71847_LDO5_STARTUP_TIME,
101762306a36Sopenharmony_ci			.owner = THIS_MODULE,
101862306a36Sopenharmony_ci		},
101962306a36Sopenharmony_ci		.init = {
102062306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO5_VOLT,
102162306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
102262306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
102362306a36Sopenharmony_ci		},
102462306a36Sopenharmony_ci	},
102562306a36Sopenharmony_ci	{
102662306a36Sopenharmony_ci		.desc = {
102762306a36Sopenharmony_ci			.name = "ldo6",
102862306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO6"),
102962306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
103062306a36Sopenharmony_ci			.id = BD718XX_LDO6,
103162306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
103262306a36Sopenharmony_ci			.n_voltages = BD718XX_LDO6_VOLTAGE_NUM,
103362306a36Sopenharmony_ci			.linear_ranges = bd718xx_ldo6_volts,
103462306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_ldo6_volts),
103562306a36Sopenharmony_ci			/* LDO6 is supplied by buck5 */
103662306a36Sopenharmony_ci			.supply_name = "buck5",
103762306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO6_VOLT,
103862306a36Sopenharmony_ci			.vsel_mask = BD718XX_LDO6_MASK,
103962306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO6_VOLT,
104062306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
104162306a36Sopenharmony_ci			.enable_time = BD71847_LDO6_STARTUP_TIME,
104262306a36Sopenharmony_ci			.owner = THIS_MODULE,
104362306a36Sopenharmony_ci		},
104462306a36Sopenharmony_ci		.init = {
104562306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO6_VOLT,
104662306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
104762306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
104862306a36Sopenharmony_ci		},
104962306a36Sopenharmony_ci	},
105062306a36Sopenharmony_ci};
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_cistatic const struct regulator_ops *bd71837_swcontrol_ops[] = {
105362306a36Sopenharmony_ci	&bd718xx_dvs_buck_regulator_ops, &bd718xx_dvs_buck_regulator_ops,
105462306a36Sopenharmony_ci	&bd718xx_dvs_buck_regulator_ops, &bd718xx_dvs_buck_regulator_ops,
105562306a36Sopenharmony_ci	&bd71837_pickable_range_buck_ops, &bd71837_buck_regulator_ops,
105662306a36Sopenharmony_ci	&bd71837_buck_regulator_nolinear_ops, &bd71837_buck_regulator_ops,
105762306a36Sopenharmony_ci	&bd71837_pickable_range_ldo_ops, &bd71837_ldo_regulator_nolinear_ops,
105862306a36Sopenharmony_ci	&bd71837_ldo_regulator_ops, &bd71837_ldo_regulator_ops,
105962306a36Sopenharmony_ci	&bd71837_ldo_regulator_ops, &bd71837_ldo_regulator_ops,
106062306a36Sopenharmony_ci	&bd71837_ldo_regulator_ops,
106162306a36Sopenharmony_ci};
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_cistatic const struct regulator_ops *bd71837_hwcontrol_ops[] = {
106462306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops),
106562306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops),
106662306a36Sopenharmony_ci	&bd71837_buck34_ops_hwctrl, &bd71837_buck34_ops_hwctrl,
106762306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_pickable_range_buck_ops),
106862306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_buck_regulator_ops),
106962306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_buck_regulator_nolinear_ops),
107062306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_buck_regulator_ops),
107162306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_pickable_range_ldo_ops),
107262306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_ldo_regulator_nolinear_ops),
107362306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_ldo_regulator_ops),
107462306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_ldo_regulator_ops),
107562306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_ldo_regulator_ops),
107662306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_ldo_regulator_ops),
107762306a36Sopenharmony_ci	&BD718XX_HWOPNAME(bd71837_ldo_regulator_ops),
107862306a36Sopenharmony_ci};
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_cistatic struct bd718xx_regulator_data bd71837_regulators[] = {
108162306a36Sopenharmony_ci	{
108262306a36Sopenharmony_ci		.desc = {
108362306a36Sopenharmony_ci			.name = "buck1",
108462306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK1"),
108562306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
108662306a36Sopenharmony_ci			.id = BD718XX_BUCK1,
108762306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
108862306a36Sopenharmony_ci			.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
108962306a36Sopenharmony_ci			.linear_ranges = bd718xx_dvs_buck_volts,
109062306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_dvs_buck_volts),
109162306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_BUCK1_VOLT_RUN,
109262306a36Sopenharmony_ci			.vsel_mask = DVS_BUCK_RUN_MASK,
109362306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_BUCK1_CTRL,
109462306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
109562306a36Sopenharmony_ci			.enable_time = BD71837_BUCK1_STARTUP_TIME,
109662306a36Sopenharmony_ci			.ramp_delay_table = bd718xx_ramp_delay,
109762306a36Sopenharmony_ci			.n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
109862306a36Sopenharmony_ci			.ramp_reg = BD718XX_REG_BUCK1_CTRL,
109962306a36Sopenharmony_ci			.ramp_mask = BUCK_RAMPRATE_MASK,
110062306a36Sopenharmony_ci			.owner = THIS_MODULE,
110162306a36Sopenharmony_ci			.of_parse_cb = buck_set_hw_dvs_levels,
110262306a36Sopenharmony_ci		},
110362306a36Sopenharmony_ci		.dvs = {
110462306a36Sopenharmony_ci			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
110562306a36Sopenharmony_ci				     ROHM_DVS_LEVEL_SUSPEND,
110662306a36Sopenharmony_ci			.run_reg = BD718XX_REG_BUCK1_VOLT_RUN,
110762306a36Sopenharmony_ci			.run_mask = DVS_BUCK_RUN_MASK,
110862306a36Sopenharmony_ci			.idle_reg = BD718XX_REG_BUCK1_VOLT_IDLE,
110962306a36Sopenharmony_ci			.idle_mask = DVS_BUCK_RUN_MASK,
111062306a36Sopenharmony_ci			.suspend_reg = BD718XX_REG_BUCK1_VOLT_SUSP,
111162306a36Sopenharmony_ci			.suspend_mask = DVS_BUCK_RUN_MASK,
111262306a36Sopenharmony_ci		},
111362306a36Sopenharmony_ci		.init = {
111462306a36Sopenharmony_ci			.reg = BD718XX_REG_BUCK1_CTRL,
111562306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
111662306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
111762306a36Sopenharmony_ci		},
111862306a36Sopenharmony_ci	},
111962306a36Sopenharmony_ci	{
112062306a36Sopenharmony_ci		.desc = {
112162306a36Sopenharmony_ci			.name = "buck2",
112262306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK2"),
112362306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
112462306a36Sopenharmony_ci			.id = BD718XX_BUCK2,
112562306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
112662306a36Sopenharmony_ci			.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
112762306a36Sopenharmony_ci			.linear_ranges = bd718xx_dvs_buck_volts,
112862306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_dvs_buck_volts),
112962306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_BUCK2_VOLT_RUN,
113062306a36Sopenharmony_ci			.vsel_mask = DVS_BUCK_RUN_MASK,
113162306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_BUCK2_CTRL,
113262306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
113362306a36Sopenharmony_ci			.enable_time = BD71837_BUCK2_STARTUP_TIME,
113462306a36Sopenharmony_ci			.ramp_delay_table = bd718xx_ramp_delay,
113562306a36Sopenharmony_ci			.n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
113662306a36Sopenharmony_ci			.ramp_reg = BD718XX_REG_BUCK2_CTRL,
113762306a36Sopenharmony_ci			.ramp_mask = BUCK_RAMPRATE_MASK,
113862306a36Sopenharmony_ci			.owner = THIS_MODULE,
113962306a36Sopenharmony_ci			.of_parse_cb = buck_set_hw_dvs_levels,
114062306a36Sopenharmony_ci		},
114162306a36Sopenharmony_ci		.dvs = {
114262306a36Sopenharmony_ci			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE,
114362306a36Sopenharmony_ci			.run_reg = BD718XX_REG_BUCK2_VOLT_RUN,
114462306a36Sopenharmony_ci			.run_mask = DVS_BUCK_RUN_MASK,
114562306a36Sopenharmony_ci			.idle_reg = BD718XX_REG_BUCK2_VOLT_IDLE,
114662306a36Sopenharmony_ci			.idle_mask = DVS_BUCK_RUN_MASK,
114762306a36Sopenharmony_ci		},
114862306a36Sopenharmony_ci		.init = {
114962306a36Sopenharmony_ci			.reg = BD718XX_REG_BUCK2_CTRL,
115062306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
115162306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
115262306a36Sopenharmony_ci		},
115362306a36Sopenharmony_ci	},
115462306a36Sopenharmony_ci	{
115562306a36Sopenharmony_ci		.desc = {
115662306a36Sopenharmony_ci			.name = "buck3",
115762306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK3"),
115862306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
115962306a36Sopenharmony_ci			.id = BD718XX_BUCK3,
116062306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
116162306a36Sopenharmony_ci			.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
116262306a36Sopenharmony_ci			.linear_ranges = bd718xx_dvs_buck_volts,
116362306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_dvs_buck_volts),
116462306a36Sopenharmony_ci			.vsel_reg = BD71837_REG_BUCK3_VOLT_RUN,
116562306a36Sopenharmony_ci			.vsel_mask = DVS_BUCK_RUN_MASK,
116662306a36Sopenharmony_ci			.enable_reg = BD71837_REG_BUCK3_CTRL,
116762306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
116862306a36Sopenharmony_ci			.enable_time = BD71837_BUCK3_STARTUP_TIME,
116962306a36Sopenharmony_ci			.ramp_delay_table = bd718xx_ramp_delay,
117062306a36Sopenharmony_ci			.n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
117162306a36Sopenharmony_ci			.ramp_reg = BD71837_REG_BUCK3_CTRL,
117262306a36Sopenharmony_ci			.ramp_mask = BUCK_RAMPRATE_MASK,
117362306a36Sopenharmony_ci			.owner = THIS_MODULE,
117462306a36Sopenharmony_ci			.of_parse_cb = buck_set_hw_dvs_levels,
117562306a36Sopenharmony_ci		},
117662306a36Sopenharmony_ci		.dvs = {
117762306a36Sopenharmony_ci			.level_map = ROHM_DVS_LEVEL_RUN,
117862306a36Sopenharmony_ci			.run_reg = BD71837_REG_BUCK3_VOLT_RUN,
117962306a36Sopenharmony_ci			.run_mask = DVS_BUCK_RUN_MASK,
118062306a36Sopenharmony_ci		},
118162306a36Sopenharmony_ci		.init = {
118262306a36Sopenharmony_ci			.reg = BD71837_REG_BUCK3_CTRL,
118362306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
118462306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
118562306a36Sopenharmony_ci		},
118662306a36Sopenharmony_ci	},
118762306a36Sopenharmony_ci	{
118862306a36Sopenharmony_ci		.desc = {
118962306a36Sopenharmony_ci			.name = "buck4",
119062306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK4"),
119162306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
119262306a36Sopenharmony_ci			.id = BD718XX_BUCK4,
119362306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
119462306a36Sopenharmony_ci			.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
119562306a36Sopenharmony_ci			.linear_ranges = bd718xx_dvs_buck_volts,
119662306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_dvs_buck_volts),
119762306a36Sopenharmony_ci			.vsel_reg = BD71837_REG_BUCK4_VOLT_RUN,
119862306a36Sopenharmony_ci			.vsel_mask = DVS_BUCK_RUN_MASK,
119962306a36Sopenharmony_ci			.enable_reg = BD71837_REG_BUCK4_CTRL,
120062306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
120162306a36Sopenharmony_ci			.enable_time = BD71837_BUCK4_STARTUP_TIME,
120262306a36Sopenharmony_ci			.ramp_delay_table = bd718xx_ramp_delay,
120362306a36Sopenharmony_ci			.n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
120462306a36Sopenharmony_ci			.ramp_reg = BD71837_REG_BUCK4_CTRL,
120562306a36Sopenharmony_ci			.ramp_mask = BUCK_RAMPRATE_MASK,
120662306a36Sopenharmony_ci			.owner = THIS_MODULE,
120762306a36Sopenharmony_ci			.of_parse_cb = buck_set_hw_dvs_levels,
120862306a36Sopenharmony_ci		},
120962306a36Sopenharmony_ci		.dvs = {
121062306a36Sopenharmony_ci			.level_map = ROHM_DVS_LEVEL_RUN,
121162306a36Sopenharmony_ci			.run_reg = BD71837_REG_BUCK4_VOLT_RUN,
121262306a36Sopenharmony_ci			.run_mask = DVS_BUCK_RUN_MASK,
121362306a36Sopenharmony_ci		},
121462306a36Sopenharmony_ci		.init = {
121562306a36Sopenharmony_ci			.reg = BD71837_REG_BUCK4_CTRL,
121662306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
121762306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
121862306a36Sopenharmony_ci		},
121962306a36Sopenharmony_ci	},
122062306a36Sopenharmony_ci	{
122162306a36Sopenharmony_ci		.desc = {
122262306a36Sopenharmony_ci			.name = "buck5",
122362306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK5"),
122462306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
122562306a36Sopenharmony_ci			.id = BD718XX_BUCK5,
122662306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
122762306a36Sopenharmony_ci			.n_voltages = BD71837_BUCK5_VOLTAGE_NUM,
122862306a36Sopenharmony_ci			.linear_ranges = bd71837_buck5_volts,
122962306a36Sopenharmony_ci			.n_linear_ranges =
123062306a36Sopenharmony_ci				ARRAY_SIZE(bd71837_buck5_volts),
123162306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT,
123262306a36Sopenharmony_ci			.vsel_mask = BD71837_BUCK5_MASK,
123362306a36Sopenharmony_ci			.vsel_range_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT,
123462306a36Sopenharmony_ci			.vsel_range_mask = BD71837_BUCK5_RANGE_MASK,
123562306a36Sopenharmony_ci			.linear_range_selectors_bitfield = bd71837_buck5_volt_range_sel,
123662306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL,
123762306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
123862306a36Sopenharmony_ci			.enable_time = BD71837_BUCK5_STARTUP_TIME,
123962306a36Sopenharmony_ci			.owner = THIS_MODULE,
124062306a36Sopenharmony_ci		},
124162306a36Sopenharmony_ci		.init = {
124262306a36Sopenharmony_ci			.reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL,
124362306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
124462306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
124562306a36Sopenharmony_ci		},
124662306a36Sopenharmony_ci	},
124762306a36Sopenharmony_ci	{
124862306a36Sopenharmony_ci		.desc = {
124962306a36Sopenharmony_ci			.name = "buck6",
125062306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK6"),
125162306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
125262306a36Sopenharmony_ci			.id = BD718XX_BUCK6,
125362306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
125462306a36Sopenharmony_ci			.n_voltages = BD71837_BUCK6_VOLTAGE_NUM,
125562306a36Sopenharmony_ci			.linear_ranges = bd71837_buck6_volts,
125662306a36Sopenharmony_ci			.n_linear_ranges =
125762306a36Sopenharmony_ci				ARRAY_SIZE(bd71837_buck6_volts),
125862306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_2ND_NODVS_BUCK_VOLT,
125962306a36Sopenharmony_ci			.vsel_mask = BD71837_BUCK6_MASK,
126062306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL,
126162306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
126262306a36Sopenharmony_ci			.enable_time = BD71837_BUCK6_STARTUP_TIME,
126362306a36Sopenharmony_ci			.owner = THIS_MODULE,
126462306a36Sopenharmony_ci		},
126562306a36Sopenharmony_ci		.init = {
126662306a36Sopenharmony_ci			.reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL,
126762306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
126862306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
126962306a36Sopenharmony_ci		},
127062306a36Sopenharmony_ci	},
127162306a36Sopenharmony_ci	{
127262306a36Sopenharmony_ci		.desc = {
127362306a36Sopenharmony_ci			.name = "buck7",
127462306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK7"),
127562306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
127662306a36Sopenharmony_ci			.id = BD718XX_BUCK7,
127762306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
127862306a36Sopenharmony_ci			.volt_table = &bd718xx_3rd_nodvs_buck_volts[0],
127962306a36Sopenharmony_ci			.n_voltages = ARRAY_SIZE(bd718xx_3rd_nodvs_buck_volts),
128062306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_3RD_NODVS_BUCK_VOLT,
128162306a36Sopenharmony_ci			.vsel_mask = BD718XX_3RD_NODVS_BUCK_MASK,
128262306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_3RD_NODVS_BUCK_CTRL,
128362306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
128462306a36Sopenharmony_ci			.enable_time = BD71837_BUCK7_STARTUP_TIME,
128562306a36Sopenharmony_ci			.owner = THIS_MODULE,
128662306a36Sopenharmony_ci		},
128762306a36Sopenharmony_ci		.init = {
128862306a36Sopenharmony_ci			.reg = BD718XX_REG_3RD_NODVS_BUCK_CTRL,
128962306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
129062306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
129162306a36Sopenharmony_ci		},
129262306a36Sopenharmony_ci	},
129362306a36Sopenharmony_ci	{
129462306a36Sopenharmony_ci		.desc = {
129562306a36Sopenharmony_ci			.name = "buck8",
129662306a36Sopenharmony_ci			.of_match = of_match_ptr("BUCK8"),
129762306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
129862306a36Sopenharmony_ci			.id = BD718XX_BUCK8,
129962306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
130062306a36Sopenharmony_ci			.n_voltages = BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM,
130162306a36Sopenharmony_ci			.linear_ranges = bd718xx_4th_nodvs_buck_volts,
130262306a36Sopenharmony_ci			.n_linear_ranges =
130362306a36Sopenharmony_ci				ARRAY_SIZE(bd718xx_4th_nodvs_buck_volts),
130462306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_4TH_NODVS_BUCK_VOLT,
130562306a36Sopenharmony_ci			.vsel_mask = BD718XX_4TH_NODVS_BUCK_MASK,
130662306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_4TH_NODVS_BUCK_CTRL,
130762306a36Sopenharmony_ci			.enable_mask = BD718XX_BUCK_EN,
130862306a36Sopenharmony_ci			.enable_time = BD71837_BUCK8_STARTUP_TIME,
130962306a36Sopenharmony_ci			.owner = THIS_MODULE,
131062306a36Sopenharmony_ci		},
131162306a36Sopenharmony_ci		.init = {
131262306a36Sopenharmony_ci			.reg = BD718XX_REG_4TH_NODVS_BUCK_CTRL,
131362306a36Sopenharmony_ci			.mask = BD718XX_BUCK_SEL,
131462306a36Sopenharmony_ci			.val = BD718XX_BUCK_SEL,
131562306a36Sopenharmony_ci		},
131662306a36Sopenharmony_ci	},
131762306a36Sopenharmony_ci	{
131862306a36Sopenharmony_ci		.desc = {
131962306a36Sopenharmony_ci			.name = "ldo1",
132062306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO1"),
132162306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
132262306a36Sopenharmony_ci			.id = BD718XX_LDO1,
132362306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
132462306a36Sopenharmony_ci			.n_voltages = BD718XX_LDO1_VOLTAGE_NUM,
132562306a36Sopenharmony_ci			.linear_ranges = bd718xx_ldo1_volts,
132662306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_ldo1_volts),
132762306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO1_VOLT,
132862306a36Sopenharmony_ci			.vsel_mask = BD718XX_LDO1_MASK,
132962306a36Sopenharmony_ci			.vsel_range_reg = BD718XX_REG_LDO1_VOLT,
133062306a36Sopenharmony_ci			.vsel_range_mask = BD718XX_LDO1_RANGE_MASK,
133162306a36Sopenharmony_ci			.linear_range_selectors_bitfield = bd718xx_ldo1_volt_range_sel,
133262306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO1_VOLT,
133362306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
133462306a36Sopenharmony_ci			.enable_time = BD71837_LDO1_STARTUP_TIME,
133562306a36Sopenharmony_ci			.owner = THIS_MODULE,
133662306a36Sopenharmony_ci		},
133762306a36Sopenharmony_ci		.init = {
133862306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO1_VOLT,
133962306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
134062306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
134162306a36Sopenharmony_ci		},
134262306a36Sopenharmony_ci	},
134362306a36Sopenharmony_ci	{
134462306a36Sopenharmony_ci		.desc = {
134562306a36Sopenharmony_ci			.name = "ldo2",
134662306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO2"),
134762306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
134862306a36Sopenharmony_ci			.id = BD718XX_LDO2,
134962306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
135062306a36Sopenharmony_ci			.volt_table = &ldo_2_volts[0],
135162306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO2_VOLT,
135262306a36Sopenharmony_ci			.vsel_mask = BD718XX_LDO2_MASK,
135362306a36Sopenharmony_ci			.n_voltages = ARRAY_SIZE(ldo_2_volts),
135462306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO2_VOLT,
135562306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
135662306a36Sopenharmony_ci			.enable_time = BD71837_LDO2_STARTUP_TIME,
135762306a36Sopenharmony_ci			.owner = THIS_MODULE,
135862306a36Sopenharmony_ci		},
135962306a36Sopenharmony_ci		.init = {
136062306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO2_VOLT,
136162306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
136262306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
136362306a36Sopenharmony_ci		},
136462306a36Sopenharmony_ci	},
136562306a36Sopenharmony_ci	{
136662306a36Sopenharmony_ci		.desc = {
136762306a36Sopenharmony_ci			.name = "ldo3",
136862306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO3"),
136962306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
137062306a36Sopenharmony_ci			.id = BD718XX_LDO3,
137162306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
137262306a36Sopenharmony_ci			.n_voltages = BD718XX_LDO3_VOLTAGE_NUM,
137362306a36Sopenharmony_ci			.linear_ranges = bd718xx_ldo3_volts,
137462306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_ldo3_volts),
137562306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO3_VOLT,
137662306a36Sopenharmony_ci			.vsel_mask = BD718XX_LDO3_MASK,
137762306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO3_VOLT,
137862306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
137962306a36Sopenharmony_ci			.enable_time = BD71837_LDO3_STARTUP_TIME,
138062306a36Sopenharmony_ci			.owner = THIS_MODULE,
138162306a36Sopenharmony_ci		},
138262306a36Sopenharmony_ci		.init = {
138362306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO3_VOLT,
138462306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
138562306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
138662306a36Sopenharmony_ci		},
138762306a36Sopenharmony_ci	},
138862306a36Sopenharmony_ci	{
138962306a36Sopenharmony_ci		.desc = {
139062306a36Sopenharmony_ci			.name = "ldo4",
139162306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO4"),
139262306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
139362306a36Sopenharmony_ci			.id = BD718XX_LDO4,
139462306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
139562306a36Sopenharmony_ci			.n_voltages = BD718XX_LDO4_VOLTAGE_NUM,
139662306a36Sopenharmony_ci			.linear_ranges = bd718xx_ldo4_volts,
139762306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_ldo4_volts),
139862306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO4_VOLT,
139962306a36Sopenharmony_ci			.vsel_mask = BD718XX_LDO4_MASK,
140062306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO4_VOLT,
140162306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
140262306a36Sopenharmony_ci			.enable_time = BD71837_LDO4_STARTUP_TIME,
140362306a36Sopenharmony_ci			.owner = THIS_MODULE,
140462306a36Sopenharmony_ci		},
140562306a36Sopenharmony_ci		.init = {
140662306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO4_VOLT,
140762306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
140862306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
140962306a36Sopenharmony_ci		},
141062306a36Sopenharmony_ci	},
141162306a36Sopenharmony_ci	{
141262306a36Sopenharmony_ci		.desc = {
141362306a36Sopenharmony_ci			.name = "ldo5",
141462306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO5"),
141562306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
141662306a36Sopenharmony_ci			.id = BD718XX_LDO5,
141762306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
141862306a36Sopenharmony_ci			.n_voltages = BD71837_LDO5_VOLTAGE_NUM,
141962306a36Sopenharmony_ci			.linear_ranges = bd71837_ldo5_volts,
142062306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd71837_ldo5_volts),
142162306a36Sopenharmony_ci			/* LDO5 is supplied by buck6 */
142262306a36Sopenharmony_ci			.supply_name = "buck6",
142362306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO5_VOLT,
142462306a36Sopenharmony_ci			.vsel_mask = BD71837_LDO5_MASK,
142562306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO5_VOLT,
142662306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
142762306a36Sopenharmony_ci			.enable_time = BD71837_LDO5_STARTUP_TIME,
142862306a36Sopenharmony_ci			.owner = THIS_MODULE,
142962306a36Sopenharmony_ci		},
143062306a36Sopenharmony_ci		.init = {
143162306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO5_VOLT,
143262306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
143362306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
143462306a36Sopenharmony_ci		},
143562306a36Sopenharmony_ci		.additional_inits = bd71837_ldo5_inits,
143662306a36Sopenharmony_ci		.additional_init_amnt = ARRAY_SIZE(bd71837_ldo5_inits),
143762306a36Sopenharmony_ci	},
143862306a36Sopenharmony_ci	{
143962306a36Sopenharmony_ci		.desc = {
144062306a36Sopenharmony_ci			.name = "ldo6",
144162306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO6"),
144262306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
144362306a36Sopenharmony_ci			.id = BD718XX_LDO6,
144462306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
144562306a36Sopenharmony_ci			.n_voltages = BD718XX_LDO6_VOLTAGE_NUM,
144662306a36Sopenharmony_ci			.linear_ranges = bd718xx_ldo6_volts,
144762306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd718xx_ldo6_volts),
144862306a36Sopenharmony_ci			/* LDO6 is supplied by buck7 */
144962306a36Sopenharmony_ci			.supply_name = "buck7",
145062306a36Sopenharmony_ci			.vsel_reg = BD718XX_REG_LDO6_VOLT,
145162306a36Sopenharmony_ci			.vsel_mask = BD718XX_LDO6_MASK,
145262306a36Sopenharmony_ci			.enable_reg = BD718XX_REG_LDO6_VOLT,
145362306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
145462306a36Sopenharmony_ci			.enable_time = BD71837_LDO6_STARTUP_TIME,
145562306a36Sopenharmony_ci			.owner = THIS_MODULE,
145662306a36Sopenharmony_ci		},
145762306a36Sopenharmony_ci		.init = {
145862306a36Sopenharmony_ci			.reg = BD718XX_REG_LDO6_VOLT,
145962306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
146062306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
146162306a36Sopenharmony_ci		},
146262306a36Sopenharmony_ci		.additional_inits = bd71837_ldo6_inits,
146362306a36Sopenharmony_ci		.additional_init_amnt = ARRAY_SIZE(bd71837_ldo6_inits),
146462306a36Sopenharmony_ci	},
146562306a36Sopenharmony_ci	{
146662306a36Sopenharmony_ci		.desc = {
146762306a36Sopenharmony_ci			.name = "ldo7",
146862306a36Sopenharmony_ci			.of_match = of_match_ptr("LDO7"),
146962306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),
147062306a36Sopenharmony_ci			.id = BD718XX_LDO7,
147162306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,
147262306a36Sopenharmony_ci			.n_voltages = BD71837_LDO7_VOLTAGE_NUM,
147362306a36Sopenharmony_ci			.linear_ranges = bd71837_ldo7_volts,
147462306a36Sopenharmony_ci			.n_linear_ranges = ARRAY_SIZE(bd71837_ldo7_volts),
147562306a36Sopenharmony_ci			.vsel_reg = BD71837_REG_LDO7_VOLT,
147662306a36Sopenharmony_ci			.vsel_mask = BD71837_LDO7_MASK,
147762306a36Sopenharmony_ci			.enable_reg = BD71837_REG_LDO7_VOLT,
147862306a36Sopenharmony_ci			.enable_mask = BD718XX_LDO_EN,
147962306a36Sopenharmony_ci			.enable_time = BD71837_LDO7_STARTUP_TIME,
148062306a36Sopenharmony_ci			.owner = THIS_MODULE,
148162306a36Sopenharmony_ci		},
148262306a36Sopenharmony_ci		.init = {
148362306a36Sopenharmony_ci			.reg = BD71837_REG_LDO7_VOLT,
148462306a36Sopenharmony_ci			.mask = BD718XX_LDO_SEL,
148562306a36Sopenharmony_ci			.val = BD718XX_LDO_SEL,
148662306a36Sopenharmony_ci		},
148762306a36Sopenharmony_ci	},
148862306a36Sopenharmony_ci};
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_cistatic void mark_hw_controlled(struct device *dev, struct device_node *np,
149162306a36Sopenharmony_ci			       struct bd718xx_regulator_data *reg_data,
149262306a36Sopenharmony_ci			       unsigned int num_reg_data, int *info)
149362306a36Sopenharmony_ci{
149462306a36Sopenharmony_ci	int i;
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	for (i = 1; i <= num_reg_data; i++) {
149762306a36Sopenharmony_ci		if (!of_node_name_eq(np, reg_data[i-1].desc.of_match))
149862306a36Sopenharmony_ci			continue;
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci		*info |= 1 << (i - 1);
150162306a36Sopenharmony_ci		dev_dbg(dev, "regulator %d runlevel controlled\n", i);
150262306a36Sopenharmony_ci		return;
150362306a36Sopenharmony_ci	}
150462306a36Sopenharmony_ci	dev_warn(dev, "Bad regulator node\n");
150562306a36Sopenharmony_ci}
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci/*
150862306a36Sopenharmony_ci * Setups where regulator (especially the buck8) output voltage is scaled
150962306a36Sopenharmony_ci * by adding external connection where some other regulator output is connected
151062306a36Sopenharmony_ci * to feedback-pin (over suitable resistors) is getting popular amongst users
151162306a36Sopenharmony_ci * of BD71837. (This allows for example scaling down the buck8 voltages to suit
151262306a36Sopenharmony_ci * lover GPU voltages for projects where buck8 is (ab)used to supply power
151362306a36Sopenharmony_ci * for GPU. Additionally some setups do allow DVS for buck8 but as this do
151462306a36Sopenharmony_ci * produce voltage spikes the HW must be evaluated to be able to survive this
151562306a36Sopenharmony_ci * - hence I keep the DVS disabled for non DVS bucks by default. I don't want
151662306a36Sopenharmony_ci * to help you burn your proto board)
151762306a36Sopenharmony_ci *
151862306a36Sopenharmony_ci * So we allow describing this external connection from DT and scale the
151962306a36Sopenharmony_ci * voltages accordingly. This is what the connection should look like:
152062306a36Sopenharmony_ci *
152162306a36Sopenharmony_ci * |------------|
152262306a36Sopenharmony_ci * |	buck 8  |-------+----->Vout
152362306a36Sopenharmony_ci * |		|	|
152462306a36Sopenharmony_ci * |------------|	|
152562306a36Sopenharmony_ci *	| FB pin	|
152662306a36Sopenharmony_ci *	|		|
152762306a36Sopenharmony_ci *	+-------+--R2---+
152862306a36Sopenharmony_ci *		|
152962306a36Sopenharmony_ci *		R1
153062306a36Sopenharmony_ci *		|
153162306a36Sopenharmony_ci *	V FB-pull-up
153262306a36Sopenharmony_ci *
153362306a36Sopenharmony_ci *	Here the buck output is sifted according to formula:
153462306a36Sopenharmony_ci *
153562306a36Sopenharmony_ci * Vout_o = Vo - (Vpu - Vo)*R2/R1
153662306a36Sopenharmony_ci * Linear_step = step_orig*(R1+R2)/R1
153762306a36Sopenharmony_ci *
153862306a36Sopenharmony_ci * where:
153962306a36Sopenharmony_ci * Vout_o is adjusted voltage output at vsel reg value 0
154062306a36Sopenharmony_ci * Vo is original voltage output at vsel reg value 0
154162306a36Sopenharmony_ci * Vpu is the pull-up voltage V FB-pull-up in the picture
154262306a36Sopenharmony_ci * R1 and R2 are resistor values.
154362306a36Sopenharmony_ci *
154462306a36Sopenharmony_ci * As a real world example for buck8 and a specific GPU:
154562306a36Sopenharmony_ci * VLDO = 1.6V (used as FB-pull-up)
154662306a36Sopenharmony_ci * R1 = 1000ohms
154762306a36Sopenharmony_ci * R2 = 150ohms
154862306a36Sopenharmony_ci * VSEL 0x0 => 0.8V – (VLDO – 0.8) * R2 / R1 = 0.68V
154962306a36Sopenharmony_ci * Linear Step = 10mV * (R1 + R2) / R1 = 11.5mV
155062306a36Sopenharmony_ci */
155162306a36Sopenharmony_cistatic int setup_feedback_loop(struct device *dev, struct device_node *np,
155262306a36Sopenharmony_ci			       struct bd718xx_regulator_data *reg_data,
155362306a36Sopenharmony_ci			       unsigned int num_reg_data, int fb_uv)
155462306a36Sopenharmony_ci{
155562306a36Sopenharmony_ci	int i, r1, r2, ret;
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci	/*
155862306a36Sopenharmony_ci	 * We do adjust the values in the global desc based on DT settings.
155962306a36Sopenharmony_ci	 * This may not be best approach as it can cause problems if more than
156062306a36Sopenharmony_ci	 * one PMIC is controlled from same processor. I don't see such use-case
156162306a36Sopenharmony_ci	 * for BD718x7 now - so we spare some bits.
156262306a36Sopenharmony_ci	 *
156362306a36Sopenharmony_ci	 * If this will point out to be a problem - then we can allocate new
156462306a36Sopenharmony_ci	 * bd718xx_regulator_data array at probe and just use the global
156562306a36Sopenharmony_ci	 * array as a template where we copy initial values. Then we can
156662306a36Sopenharmony_ci	 * use allocated descs for regultor registration and do IC specific
156762306a36Sopenharmony_ci	 * modifications to this copy while leaving other PMICs untouched. But
156862306a36Sopenharmony_ci	 * that means allocating new array for each PMIC - and currently I see
156962306a36Sopenharmony_ci	 * no need for that.
157062306a36Sopenharmony_ci	 */
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci	for (i = 0; i < num_reg_data; i++) {
157362306a36Sopenharmony_ci		struct regulator_desc *desc = &reg_data[i].desc;
157462306a36Sopenharmony_ci		int j;
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci		if (!of_node_name_eq(np, desc->of_match))
157762306a36Sopenharmony_ci			continue;
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci		/* The feedback loop connection does not make sense for LDOs */
158062306a36Sopenharmony_ci		if (desc->id >= BD718XX_LDO1)
158162306a36Sopenharmony_ci			return -EINVAL;
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci		ret = of_property_read_u32(np, "rohm,feedback-pull-up-r1-ohms",
158462306a36Sopenharmony_ci					   &r1);
158562306a36Sopenharmony_ci		if (ret)
158662306a36Sopenharmony_ci			return ret;
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci		if (!r1)
158962306a36Sopenharmony_ci			return -EINVAL;
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci		ret = of_property_read_u32(np, "rohm,feedback-pull-up-r2-ohms",
159262306a36Sopenharmony_ci					   &r2);
159362306a36Sopenharmony_ci		if (ret)
159462306a36Sopenharmony_ci			return ret;
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci		if (desc->n_linear_ranges && desc->linear_ranges) {
159762306a36Sopenharmony_ci			struct linear_range *new;
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci			new = devm_kzalloc(dev, desc->n_linear_ranges *
160062306a36Sopenharmony_ci					   sizeof(struct linear_range),
160162306a36Sopenharmony_ci					   GFP_KERNEL);
160262306a36Sopenharmony_ci			if (!new)
160362306a36Sopenharmony_ci				return -ENOMEM;
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_ci			for (j = 0; j < desc->n_linear_ranges; j++) {
160662306a36Sopenharmony_ci				int min = desc->linear_ranges[j].min;
160762306a36Sopenharmony_ci				int step = desc->linear_ranges[j].step;
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci				min -= (fb_uv - min)*r2/r1;
161062306a36Sopenharmony_ci				step = step * (r1 + r2);
161162306a36Sopenharmony_ci				step /= r1;
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci				new[j].min = min;
161462306a36Sopenharmony_ci				new[j].step = step;
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_ci				dev_dbg(dev, "%s: old range min %d, step %d\n",
161762306a36Sopenharmony_ci					desc->name, desc->linear_ranges[j].min,
161862306a36Sopenharmony_ci					desc->linear_ranges[j].step);
161962306a36Sopenharmony_ci				dev_dbg(dev, "new range min %d, step %d\n", min,
162062306a36Sopenharmony_ci					step);
162162306a36Sopenharmony_ci			}
162262306a36Sopenharmony_ci			desc->linear_ranges = new;
162362306a36Sopenharmony_ci		}
162462306a36Sopenharmony_ci		dev_dbg(dev, "regulator '%s' has FB pull-up configured\n",
162562306a36Sopenharmony_ci			desc->name);
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci		return 0;
162862306a36Sopenharmony_ci	}
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_ci	return -ENODEV;
163162306a36Sopenharmony_ci}
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_cistatic int get_special_regulators(struct device *dev,
163462306a36Sopenharmony_ci				  struct bd718xx_regulator_data *reg_data,
163562306a36Sopenharmony_ci				  unsigned int num_reg_data, int *info)
163662306a36Sopenharmony_ci{
163762306a36Sopenharmony_ci	int ret;
163862306a36Sopenharmony_ci	struct device_node *np;
163962306a36Sopenharmony_ci	struct device_node *nproot = dev->of_node;
164062306a36Sopenharmony_ci	int uv;
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_ci	*info = 0;
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	nproot = of_get_child_by_name(nproot, "regulators");
164562306a36Sopenharmony_ci	if (!nproot) {
164662306a36Sopenharmony_ci		dev_err(dev, "failed to find regulators node\n");
164762306a36Sopenharmony_ci		return -ENODEV;
164862306a36Sopenharmony_ci	}
164962306a36Sopenharmony_ci	for_each_child_of_node(nproot, np) {
165062306a36Sopenharmony_ci		if (of_property_read_bool(np, "rohm,no-regulator-enable-control"))
165162306a36Sopenharmony_ci			mark_hw_controlled(dev, np, reg_data, num_reg_data,
165262306a36Sopenharmony_ci					   info);
165362306a36Sopenharmony_ci		ret = of_property_read_u32(np, "rohm,fb-pull-up-microvolt",
165462306a36Sopenharmony_ci					   &uv);
165562306a36Sopenharmony_ci		if (ret) {
165662306a36Sopenharmony_ci			if (ret == -EINVAL)
165762306a36Sopenharmony_ci				continue;
165862306a36Sopenharmony_ci			else
165962306a36Sopenharmony_ci				goto err_out;
166062306a36Sopenharmony_ci		}
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci		ret = setup_feedback_loop(dev, np, reg_data, num_reg_data, uv);
166362306a36Sopenharmony_ci		if (ret)
166462306a36Sopenharmony_ci			goto err_out;
166562306a36Sopenharmony_ci	}
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	of_node_put(nproot);
166862306a36Sopenharmony_ci	return 0;
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_cierr_out:
167162306a36Sopenharmony_ci	of_node_put(np);
167262306a36Sopenharmony_ci	of_node_put(nproot);
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_ci	return ret;
167562306a36Sopenharmony_ci}
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_cistatic int bd718xx_probe(struct platform_device *pdev)
167862306a36Sopenharmony_ci{
167962306a36Sopenharmony_ci	struct regmap *regmap;
168062306a36Sopenharmony_ci	struct regulator_config config = { 0 };
168162306a36Sopenharmony_ci	int i, j, err, omit_enable;
168262306a36Sopenharmony_ci	bool use_snvs;
168362306a36Sopenharmony_ci	struct bd718xx_regulator_data *reg_data;
168462306a36Sopenharmony_ci	unsigned int num_reg_data;
168562306a36Sopenharmony_ci	enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;
168662306a36Sopenharmony_ci	const struct regulator_ops **swops, **hwops;
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	regmap = dev_get_regmap(pdev->dev.parent, NULL);
168962306a36Sopenharmony_ci	if (!regmap) {
169062306a36Sopenharmony_ci		dev_err(&pdev->dev, "No MFD driver data\n");
169162306a36Sopenharmony_ci		return -EINVAL;
169262306a36Sopenharmony_ci	}
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci	switch (chip) {
169562306a36Sopenharmony_ci	case ROHM_CHIP_TYPE_BD71837:
169662306a36Sopenharmony_ci		reg_data = bd71837_regulators;
169762306a36Sopenharmony_ci		num_reg_data = ARRAY_SIZE(bd71837_regulators);
169862306a36Sopenharmony_ci		swops = &bd71837_swcontrol_ops[0];
169962306a36Sopenharmony_ci		hwops = &bd71837_hwcontrol_ops[0];
170062306a36Sopenharmony_ci		break;
170162306a36Sopenharmony_ci	case ROHM_CHIP_TYPE_BD71847:
170262306a36Sopenharmony_ci		reg_data = bd71847_regulators;
170362306a36Sopenharmony_ci		num_reg_data = ARRAY_SIZE(bd71847_regulators);
170462306a36Sopenharmony_ci		swops = &bd71847_swcontrol_ops[0];
170562306a36Sopenharmony_ci		hwops = &bd71847_hwcontrol_ops[0];
170662306a36Sopenharmony_ci		break;
170762306a36Sopenharmony_ci	default:
170862306a36Sopenharmony_ci		dev_err(&pdev->dev, "Unsupported chip type\n");
170962306a36Sopenharmony_ci		return -EINVAL;
171062306a36Sopenharmony_ci	}
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	/* Register LOCK release */
171362306a36Sopenharmony_ci	err = regmap_update_bits(regmap, BD718XX_REG_REGLOCK,
171462306a36Sopenharmony_ci				 (REGLOCK_PWRSEQ | REGLOCK_VREG), 0);
171562306a36Sopenharmony_ci	if (err)
171662306a36Sopenharmony_ci		return dev_err_probe(&pdev->dev, err, "Failed to unlock PMIC\n");
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci	dev_dbg(&pdev->dev, "Unlocked lock register 0x%x\n",
171962306a36Sopenharmony_ci		BD718XX_REG_REGLOCK);
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	use_snvs = of_property_read_bool(pdev->dev.parent->of_node,
172262306a36Sopenharmony_ci					 "rohm,reset-snvs-powered");
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	/*
172562306a36Sopenharmony_ci	 * Change the next stage from poweroff to be READY instead of SNVS
172662306a36Sopenharmony_ci	 * for all reset types because OTP loading at READY will clear SEL
172762306a36Sopenharmony_ci	 * bit allowing HW defaults for power rails to be used
172862306a36Sopenharmony_ci	 */
172962306a36Sopenharmony_ci	if (!use_snvs) {
173062306a36Sopenharmony_ci		err = regmap_update_bits(regmap, BD718XX_REG_TRANS_COND1,
173162306a36Sopenharmony_ci					 BD718XX_ON_REQ_POWEROFF_MASK |
173262306a36Sopenharmony_ci					 BD718XX_SWRESET_POWEROFF_MASK |
173362306a36Sopenharmony_ci					 BD718XX_WDOG_POWEROFF_MASK |
173462306a36Sopenharmony_ci					 BD718XX_KEY_L_POWEROFF_MASK,
173562306a36Sopenharmony_ci					 BD718XX_POWOFF_TO_RDY);
173662306a36Sopenharmony_ci		if (err)
173762306a36Sopenharmony_ci			return dev_err_probe(&pdev->dev, err,
173862306a36Sopenharmony_ci					     "Failed to change reset target\n");
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci		dev_dbg(&pdev->dev, "Changed all resets from SVNS to READY\n");
174162306a36Sopenharmony_ci	}
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci	config.dev = pdev->dev.parent;
174462306a36Sopenharmony_ci	config.regmap = regmap;
174562306a36Sopenharmony_ci	/*
174662306a36Sopenharmony_ci	 * There are cases when we want to leave the enable-control for
174762306a36Sopenharmony_ci	 * the HW state machine and use this driver only for voltage control.
174862306a36Sopenharmony_ci	 * One special case is when we use PMIC_STBY_REQ line from SoC to PMIC
174962306a36Sopenharmony_ci	 * in order to set the system to SUSPEND state.
175062306a36Sopenharmony_ci	 *
175162306a36Sopenharmony_ci	 * If regulator is taken under SW control the regulator state will not
175262306a36Sopenharmony_ci	 * be affected by PMIC state machine - Eg. regulator is likely to stay
175362306a36Sopenharmony_ci	 * on even in SUSPEND
175462306a36Sopenharmony_ci	 */
175562306a36Sopenharmony_ci	err = get_special_regulators(pdev->dev.parent, reg_data, num_reg_data,
175662306a36Sopenharmony_ci				     &omit_enable);
175762306a36Sopenharmony_ci	if (err)
175862306a36Sopenharmony_ci		return err;
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	for (i = 0; i < num_reg_data; i++) {
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_ci		struct regulator_desc *desc;
176362306a36Sopenharmony_ci		struct regulator_dev *rdev;
176462306a36Sopenharmony_ci		struct bd718xx_regulator_data *r;
176562306a36Sopenharmony_ci		int no_enable_control = omit_enable & (1 << i);
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci		r = &reg_data[i];
176862306a36Sopenharmony_ci		desc = &r->desc;
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci		if (no_enable_control)
177162306a36Sopenharmony_ci			desc->ops = hwops[i];
177262306a36Sopenharmony_ci		else
177362306a36Sopenharmony_ci			desc->ops = swops[i];
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci		rdev = devm_regulator_register(&pdev->dev, desc, &config);
177662306a36Sopenharmony_ci		if (IS_ERR(rdev))
177762306a36Sopenharmony_ci			return dev_err_probe(&pdev->dev, PTR_ERR(rdev),
177862306a36Sopenharmony_ci					     "failed to register %s regulator\n",
177962306a36Sopenharmony_ci					     desc->name);
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci		/*
178262306a36Sopenharmony_ci		 * Regulator register gets the regulator constraints and
178362306a36Sopenharmony_ci		 * applies them (set_machine_constraints). This should have
178462306a36Sopenharmony_ci		 * turned the control register(s) to correct values and we
178562306a36Sopenharmony_ci		 * can now switch the control from PMIC state machine to the
178662306a36Sopenharmony_ci		 * register interface
178762306a36Sopenharmony_ci		 *
178862306a36Sopenharmony_ci		 * At poweroff transition PMIC HW disables EN bit for
178962306a36Sopenharmony_ci		 * regulators but leaves SEL bit untouched. So if state
179062306a36Sopenharmony_ci		 * transition from POWEROFF is done to SNVS - then all power
179162306a36Sopenharmony_ci		 * rails controlled by SW (having SEL bit set) stay disabled
179262306a36Sopenharmony_ci		 * as EN is cleared. This will result boot failure if any
179362306a36Sopenharmony_ci		 * crucial systems are powered by these rails. We don't
179462306a36Sopenharmony_ci		 * enable SW control for crucial regulators if snvs state is
179562306a36Sopenharmony_ci		 * used
179662306a36Sopenharmony_ci		 */
179762306a36Sopenharmony_ci		if (!no_enable_control && (!use_snvs ||
179862306a36Sopenharmony_ci		    !rdev->constraints->always_on ||
179962306a36Sopenharmony_ci		    !rdev->constraints->boot_on)) {
180062306a36Sopenharmony_ci			err = regmap_update_bits(regmap, r->init.reg,
180162306a36Sopenharmony_ci						 r->init.mask, r->init.val);
180262306a36Sopenharmony_ci			if (err)
180362306a36Sopenharmony_ci				return dev_err_probe(&pdev->dev, err,
180462306a36Sopenharmony_ci					"Failed to take control for (%s)\n",
180562306a36Sopenharmony_ci					desc->name);
180662306a36Sopenharmony_ci		}
180762306a36Sopenharmony_ci		for (j = 0; j < r->additional_init_amnt; j++) {
180862306a36Sopenharmony_ci			err = regmap_update_bits(regmap,
180962306a36Sopenharmony_ci						 r->additional_inits[j].reg,
181062306a36Sopenharmony_ci						 r->additional_inits[j].mask,
181162306a36Sopenharmony_ci						 r->additional_inits[j].val);
181262306a36Sopenharmony_ci			if (err)
181362306a36Sopenharmony_ci				return dev_err_probe(&pdev->dev, err,
181462306a36Sopenharmony_ci					"Buck (%s) initialization failed\n",
181562306a36Sopenharmony_ci					desc->name);
181662306a36Sopenharmony_ci		}
181762306a36Sopenharmony_ci	}
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	return err;
182062306a36Sopenharmony_ci}
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_cistatic const struct platform_device_id bd718x7_pmic_id[] = {
182362306a36Sopenharmony_ci	{ "bd71837-pmic", ROHM_CHIP_TYPE_BD71837 },
182462306a36Sopenharmony_ci	{ "bd71847-pmic", ROHM_CHIP_TYPE_BD71847 },
182562306a36Sopenharmony_ci	{ },
182662306a36Sopenharmony_ci};
182762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(platform, bd718x7_pmic_id);
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_cistatic struct platform_driver bd718xx_regulator = {
183062306a36Sopenharmony_ci	.driver = {
183162306a36Sopenharmony_ci		.name = "bd718xx-pmic",
183262306a36Sopenharmony_ci		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
183362306a36Sopenharmony_ci	},
183462306a36Sopenharmony_ci	.probe = bd718xx_probe,
183562306a36Sopenharmony_ci	.id_table = bd718x7_pmic_id,
183662306a36Sopenharmony_ci};
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_cimodule_platform_driver(bd718xx_regulator);
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ciMODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
184162306a36Sopenharmony_ciMODULE_DESCRIPTION("BD71837/BD71847 voltage regulator driver");
184262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
184362306a36Sopenharmony_ciMODULE_ALIAS("platform:bd718xx-pmic");
1844