162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// Copyright 2014 Embest Technology Co. Ltd. Inc.
462306a36Sopenharmony_ci// bd71815-regulator.c ROHM BD71815 regulator driver
562306a36Sopenharmony_ci//
662306a36Sopenharmony_ci// Author: Tony Luo <luofc@embedinfo.com>
762306a36Sopenharmony_ci//
862306a36Sopenharmony_ci// Partially rewritten at 2021 by
962306a36Sopenharmony_ci// Matti Vaittinen <matti.vaitinen@fi.rohmeurope.com>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/err.h>
1562306a36Sopenharmony_ci#include <linux/platform_device.h>
1662306a36Sopenharmony_ci#include <linux/of.h>
1762306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1862306a36Sopenharmony_ci#include <linux/regulator/driver.h>
1962306a36Sopenharmony_ci#include <linux/delay.h>
2062306a36Sopenharmony_ci#include <linux/slab.h>
2162306a36Sopenharmony_ci#include <linux/mfd/rohm-generic.h>
2262306a36Sopenharmony_ci#include <linux/mfd/rohm-bd71815.h>
2362306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistruct bd71815_regulator {
2662306a36Sopenharmony_ci	struct regulator_desc desc;
2762306a36Sopenharmony_ci	const struct rohm_dvs_config *dvs;
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic const int bd7181x_wled_currents[] = {
3162306a36Sopenharmony_ci	10, 20, 30, 50, 70, 100, 200, 300, 500, 700, 1000, 2000, 3000, 4000,
3262306a36Sopenharmony_ci	5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000, 15000,
3362306a36Sopenharmony_ci	16000, 17000, 18000, 19000, 20000, 21000, 22000, 23000, 24000, 25000,
3462306a36Sopenharmony_ci};
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic const struct rohm_dvs_config buck1_dvs = {
3762306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
3862306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
3962306a36Sopenharmony_ci	.run_reg		= BD71815_REG_BUCK1_VOLT_H,
4062306a36Sopenharmony_ci	.run_mask		= BD71815_VOLT_MASK,
4162306a36Sopenharmony_ci	.run_on_mask		= BD71815_BUCK_RUN_ON,
4262306a36Sopenharmony_ci	.snvs_on_mask		= BD71815_BUCK_SNVS_ON,
4362306a36Sopenharmony_ci	.suspend_reg		= BD71815_REG_BUCK1_VOLT_L,
4462306a36Sopenharmony_ci	.suspend_mask		= BD71815_VOLT_MASK,
4562306a36Sopenharmony_ci	.suspend_on_mask	= BD71815_BUCK_SUSP_ON,
4662306a36Sopenharmony_ci	.lpsr_reg		= BD71815_REG_BUCK1_VOLT_L,
4762306a36Sopenharmony_ci	.lpsr_mask		= BD71815_VOLT_MASK,
4862306a36Sopenharmony_ci	.lpsr_on_mask		= BD71815_BUCK_LPSR_ON,
4962306a36Sopenharmony_ci};
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic const struct rohm_dvs_config buck2_dvs = {
5262306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
5362306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
5462306a36Sopenharmony_ci	.run_reg		= BD71815_REG_BUCK2_VOLT_H,
5562306a36Sopenharmony_ci	.run_mask		= BD71815_VOLT_MASK,
5662306a36Sopenharmony_ci	.run_on_mask		= BD71815_BUCK_RUN_ON,
5762306a36Sopenharmony_ci	.snvs_on_mask		= BD71815_BUCK_SNVS_ON,
5862306a36Sopenharmony_ci	.suspend_reg		= BD71815_REG_BUCK2_VOLT_L,
5962306a36Sopenharmony_ci	.suspend_mask		= BD71815_VOLT_MASK,
6062306a36Sopenharmony_ci	.suspend_on_mask	= BD71815_BUCK_SUSP_ON,
6162306a36Sopenharmony_ci	.lpsr_reg		= BD71815_REG_BUCK2_VOLT_L,
6262306a36Sopenharmony_ci	.lpsr_mask		= BD71815_VOLT_MASK,
6362306a36Sopenharmony_ci	.lpsr_on_mask		= BD71815_BUCK_LPSR_ON,
6462306a36Sopenharmony_ci};
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic const struct rohm_dvs_config buck3_dvs = {
6762306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
6862306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
6962306a36Sopenharmony_ci	.run_reg		= BD71815_REG_BUCK3_VOLT,
7062306a36Sopenharmony_ci	.run_mask		= BD71815_VOLT_MASK,
7162306a36Sopenharmony_ci	.run_on_mask		= BD71815_BUCK_RUN_ON,
7262306a36Sopenharmony_ci	.snvs_on_mask		= BD71815_BUCK_SNVS_ON,
7362306a36Sopenharmony_ci	.suspend_on_mask	= BD71815_BUCK_SUSP_ON,
7462306a36Sopenharmony_ci	.lpsr_on_mask		= BD71815_BUCK_LPSR_ON,
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic const struct rohm_dvs_config buck4_dvs = {
7862306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
7962306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
8062306a36Sopenharmony_ci	.run_reg		= BD71815_REG_BUCK4_VOLT,
8162306a36Sopenharmony_ci	.run_mask		= BD71815_VOLT_MASK,
8262306a36Sopenharmony_ci	.run_on_mask		= BD71815_BUCK_RUN_ON,
8362306a36Sopenharmony_ci	.snvs_on_mask		= BD71815_BUCK_SNVS_ON,
8462306a36Sopenharmony_ci	.suspend_on_mask	= BD71815_BUCK_SUSP_ON,
8562306a36Sopenharmony_ci	.lpsr_on_mask		= BD71815_BUCK_LPSR_ON,
8662306a36Sopenharmony_ci};
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic const struct rohm_dvs_config ldo1_dvs = {
8962306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
9062306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
9162306a36Sopenharmony_ci	.run_reg		= BD71815_REG_LDO_MODE1,
9262306a36Sopenharmony_ci	.run_mask		= BD71815_VOLT_MASK,
9362306a36Sopenharmony_ci	.run_on_mask		= LDO1_RUN_ON,
9462306a36Sopenharmony_ci	.snvs_on_mask		= LDO1_SNVS_ON,
9562306a36Sopenharmony_ci	.suspend_on_mask	= LDO1_SUSP_ON,
9662306a36Sopenharmony_ci	.lpsr_on_mask		= LDO1_LPSR_ON,
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic const struct rohm_dvs_config ldo2_dvs = {
10062306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
10162306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
10262306a36Sopenharmony_ci	.run_reg		= BD71815_REG_LDO_MODE2,
10362306a36Sopenharmony_ci	.run_mask		= BD71815_VOLT_MASK,
10462306a36Sopenharmony_ci	.run_on_mask		= LDO2_RUN_ON,
10562306a36Sopenharmony_ci	.snvs_on_mask		= LDO2_SNVS_ON,
10662306a36Sopenharmony_ci	.suspend_on_mask	= LDO2_SUSP_ON,
10762306a36Sopenharmony_ci	.lpsr_on_mask		= LDO2_LPSR_ON,
10862306a36Sopenharmony_ci};
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistatic const struct rohm_dvs_config ldo3_dvs = {
11162306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
11262306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
11362306a36Sopenharmony_ci	.run_reg		= BD71815_REG_LDO_MODE2,
11462306a36Sopenharmony_ci	.run_mask		= BD71815_VOLT_MASK,
11562306a36Sopenharmony_ci	.run_on_mask		= LDO3_RUN_ON,
11662306a36Sopenharmony_ci	.snvs_on_mask		= LDO3_SNVS_ON,
11762306a36Sopenharmony_ci	.suspend_on_mask	= LDO3_SUSP_ON,
11862306a36Sopenharmony_ci	.lpsr_on_mask		= LDO3_LPSR_ON,
11962306a36Sopenharmony_ci};
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic const struct rohm_dvs_config ldo4_dvs = {
12262306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
12362306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
12462306a36Sopenharmony_ci	.run_reg		= BD71815_REG_LDO_MODE3,
12562306a36Sopenharmony_ci	.run_mask		= BD71815_VOLT_MASK,
12662306a36Sopenharmony_ci	.run_on_mask		= LDO4_RUN_ON,
12762306a36Sopenharmony_ci	.snvs_on_mask		= LDO4_SNVS_ON,
12862306a36Sopenharmony_ci	.suspend_on_mask	= LDO4_SUSP_ON,
12962306a36Sopenharmony_ci	.lpsr_on_mask		= LDO4_LPSR_ON,
13062306a36Sopenharmony_ci};
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic const struct rohm_dvs_config ldo5_dvs = {
13362306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
13462306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
13562306a36Sopenharmony_ci	.run_reg		= BD71815_REG_LDO_MODE3,
13662306a36Sopenharmony_ci	.run_mask		= BD71815_VOLT_MASK,
13762306a36Sopenharmony_ci	.run_on_mask		= LDO5_RUN_ON,
13862306a36Sopenharmony_ci	.snvs_on_mask		= LDO5_SNVS_ON,
13962306a36Sopenharmony_ci	.suspend_on_mask	= LDO5_SUSP_ON,
14062306a36Sopenharmony_ci	.lpsr_on_mask		= LDO5_LPSR_ON,
14162306a36Sopenharmony_ci};
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic const struct rohm_dvs_config dvref_dvs = {
14462306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
14562306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
14662306a36Sopenharmony_ci	.run_on_mask		= DVREF_RUN_ON,
14762306a36Sopenharmony_ci	.snvs_on_mask		= DVREF_SNVS_ON,
14862306a36Sopenharmony_ci	.suspend_on_mask	= DVREF_SUSP_ON,
14962306a36Sopenharmony_ci	.lpsr_on_mask		= DVREF_LPSR_ON,
15062306a36Sopenharmony_ci};
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistatic const struct rohm_dvs_config ldolpsr_dvs = {
15362306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
15462306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
15562306a36Sopenharmony_ci	.run_on_mask		= DVREF_RUN_ON,
15662306a36Sopenharmony_ci	.snvs_on_mask		= DVREF_SNVS_ON,
15762306a36Sopenharmony_ci	.suspend_on_mask	= DVREF_SUSP_ON,
15862306a36Sopenharmony_ci	.lpsr_on_mask		= DVREF_LPSR_ON,
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic const struct rohm_dvs_config buck5_dvs = {
16262306a36Sopenharmony_ci	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
16362306a36Sopenharmony_ci				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
16462306a36Sopenharmony_ci	.run_reg		= BD71815_REG_BUCK5_VOLT,
16562306a36Sopenharmony_ci	.run_mask		= BD71815_VOLT_MASK,
16662306a36Sopenharmony_ci	.run_on_mask		= BD71815_BUCK_RUN_ON,
16762306a36Sopenharmony_ci	.snvs_on_mask		= BD71815_BUCK_SNVS_ON,
16862306a36Sopenharmony_ci	.suspend_on_mask	= BD71815_BUCK_SUSP_ON,
16962306a36Sopenharmony_ci	.lpsr_on_mask		= BD71815_BUCK_LPSR_ON,
17062306a36Sopenharmony_ci};
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic int set_hw_dvs_levels(struct device_node *np,
17362306a36Sopenharmony_ci			     const struct regulator_desc *desc,
17462306a36Sopenharmony_ci			     struct regulator_config *cfg)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	struct bd71815_regulator *data;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	data = container_of(desc, struct bd71815_regulator, desc);
17962306a36Sopenharmony_ci	return rohm_regulator_set_dvs_levels(data->dvs, np, desc, cfg->regmap);
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci/*
18362306a36Sopenharmony_ci * Bucks 1 and 2 have two voltage selection registers where selected
18462306a36Sopenharmony_ci * voltage can be set. Which of the registers is used can be either controlled
18562306a36Sopenharmony_ci * by a control bit in register - or by HW state. If HW state specific voltages
18662306a36Sopenharmony_ci * are given - then we assume HW state based control should be used.
18762306a36Sopenharmony_ci *
18862306a36Sopenharmony_ci * If volatge value is updated to currently selected register - then output
18962306a36Sopenharmony_ci * voltage is immediately changed no matter what is set as ramp rate. Thus we
19062306a36Sopenharmony_ci * default changing voltage by writing new value to inactive register and
19162306a36Sopenharmony_ci * then updating the 'register selection' bit. This naturally only works when
19262306a36Sopenharmony_ci * HW state machine is not used to select the voltage.
19362306a36Sopenharmony_ci */
19462306a36Sopenharmony_cistatic int buck12_set_hw_dvs_levels(struct device_node *np,
19562306a36Sopenharmony_ci				    const struct regulator_desc *desc,
19662306a36Sopenharmony_ci				    struct regulator_config *cfg)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	struct bd71815_regulator *data;
19962306a36Sopenharmony_ci	int ret = 0, val;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	data = container_of(desc, struct bd71815_regulator, desc);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	if (of_property_present(np, "rohm,dvs-run-voltage") ||
20462306a36Sopenharmony_ci	    of_property_present(np, "rohm,dvs-suspend-voltage") ||
20562306a36Sopenharmony_ci	    of_property_present(np, "rohm,dvs-lpsr-voltage") ||
20662306a36Sopenharmony_ci	    of_property_present(np, "rohm,dvs-snvs-voltage")) {
20762306a36Sopenharmony_ci		ret = regmap_read(cfg->regmap, desc->vsel_reg, &val);
20862306a36Sopenharmony_ci		if (ret)
20962306a36Sopenharmony_ci			return ret;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci		if (!(BD71815_BUCK_STBY_DVS & val) &&
21262306a36Sopenharmony_ci		    !(BD71815_BUCK_DVSSEL & val)) {
21362306a36Sopenharmony_ci			int val2;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci			/*
21662306a36Sopenharmony_ci			 * We are currently using voltage from _L.
21762306a36Sopenharmony_ci			 * We'd better copy it to _H and switch to it to
21862306a36Sopenharmony_ci			 * avoid shutting us down if LPSR or SUSPEND is set to
21962306a36Sopenharmony_ci			 * disabled. _L value is at reg _H + 1
22062306a36Sopenharmony_ci			 */
22162306a36Sopenharmony_ci			ret = regmap_read(cfg->regmap, desc->vsel_reg + 1,
22262306a36Sopenharmony_ci					  &val2);
22362306a36Sopenharmony_ci			if (ret)
22462306a36Sopenharmony_ci				return ret;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci			ret = regmap_update_bits(cfg->regmap, desc->vsel_reg,
22762306a36Sopenharmony_ci						 BD71815_VOLT_MASK |
22862306a36Sopenharmony_ci						 BD71815_BUCK_DVSSEL,
22962306a36Sopenharmony_ci						 val2 | BD71815_BUCK_DVSSEL);
23062306a36Sopenharmony_ci			if (ret)
23162306a36Sopenharmony_ci				return ret;
23262306a36Sopenharmony_ci		}
23362306a36Sopenharmony_ci		ret = rohm_regulator_set_dvs_levels(data->dvs, np, desc,
23462306a36Sopenharmony_ci						    cfg->regmap);
23562306a36Sopenharmony_ci		if (ret)
23662306a36Sopenharmony_ci			return ret;
23762306a36Sopenharmony_ci		/*
23862306a36Sopenharmony_ci		 * DVS levels were given => use HW-state machine for voltage
23962306a36Sopenharmony_ci		 * controls. NOTE: AFAIK, This means that if voltage is changed
24062306a36Sopenharmony_ci		 * by SW the ramp-rate is not respected. Should we disable
24162306a36Sopenharmony_ci		 * SW voltage control when the HW state machine is used?
24262306a36Sopenharmony_ci		 */
24362306a36Sopenharmony_ci		ret = regmap_update_bits(cfg->regmap, desc->vsel_reg,
24462306a36Sopenharmony_ci					 BD71815_BUCK_STBY_DVS,
24562306a36Sopenharmony_ci					 BD71815_BUCK_STBY_DVS);
24662306a36Sopenharmony_ci	}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	return ret;
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci/*
25262306a36Sopenharmony_ci * BUCK1/2
25362306a36Sopenharmony_ci * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting
25462306a36Sopenharmony_ci * 00: 10.00mV/usec	10mV 1uS
25562306a36Sopenharmony_ci * 01: 5.00mV/usec	10mV 2uS
25662306a36Sopenharmony_ci * 10: 2.50mV/usec	10mV 4uS
25762306a36Sopenharmony_ci * 11: 1.25mV/usec	10mV 8uS
25862306a36Sopenharmony_ci */
25962306a36Sopenharmony_cistatic const unsigned int bd7181x_ramp_table[] = { 1250, 2500, 5000, 10000 };
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistatic int bd7181x_led_set_current_limit(struct regulator_dev *rdev,
26262306a36Sopenharmony_ci					int min_uA, int max_uA)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	int ret;
26562306a36Sopenharmony_ci	int onstatus;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	onstatus = regulator_is_enabled_regmap(rdev);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	ret = regulator_set_current_limit_regmap(rdev, min_uA, max_uA);
27062306a36Sopenharmony_ci	if (!ret) {
27162306a36Sopenharmony_ci		int newstatus;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci		newstatus = regulator_is_enabled_regmap(rdev);
27462306a36Sopenharmony_ci		if (onstatus != newstatus) {
27562306a36Sopenharmony_ci			/*
27662306a36Sopenharmony_ci			 * HW FIX: spurious led status change detected. Toggle
27762306a36Sopenharmony_ci			 * state as a workaround
27862306a36Sopenharmony_ci			 */
27962306a36Sopenharmony_ci			if (onstatus)
28062306a36Sopenharmony_ci				ret = regulator_enable_regmap(rdev);
28162306a36Sopenharmony_ci			else
28262306a36Sopenharmony_ci				ret = regulator_disable_regmap(rdev);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci			if (ret)
28562306a36Sopenharmony_ci				dev_err(rdev_get_dev(rdev),
28662306a36Sopenharmony_ci					"failed to revert the LED state (%d)\n",
28762306a36Sopenharmony_ci					ret);
28862306a36Sopenharmony_ci		}
28962306a36Sopenharmony_ci	}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	return ret;
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_cistatic int bd7181x_buck12_get_voltage_sel(struct regulator_dev *rdev)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	int rid = rdev_get_id(rdev);
29762306a36Sopenharmony_ci	int ret, regh, regl, val;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	regh = BD71815_REG_BUCK1_VOLT_H + rid * 0x2;
30062306a36Sopenharmony_ci	regl = BD71815_REG_BUCK1_VOLT_L + rid * 0x2;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	ret = regmap_read(rdev->regmap, regh, &val);
30362306a36Sopenharmony_ci	if (ret)
30462306a36Sopenharmony_ci		return ret;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	/*
30762306a36Sopenharmony_ci	 * If we use HW state machine based voltage reg selection - then we
30862306a36Sopenharmony_ci	 * return BD71815_REG_BUCK1_VOLT_H which is used at RUN.
30962306a36Sopenharmony_ci	 * Else we do return the BD71815_REG_BUCK1_VOLT_H or
31062306a36Sopenharmony_ci	 * BD71815_REG_BUCK1_VOLT_L depending on which is selected to be used
31162306a36Sopenharmony_ci	 * by BD71815_BUCK_DVSSEL bit
31262306a36Sopenharmony_ci	 */
31362306a36Sopenharmony_ci	if ((!(val & BD71815_BUCK_STBY_DVS)) && (!(val & BD71815_BUCK_DVSSEL)))
31462306a36Sopenharmony_ci		ret = regmap_read(rdev->regmap, regl, &val);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	if (ret)
31762306a36Sopenharmony_ci		return ret;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	return val & BD71815_VOLT_MASK;
32062306a36Sopenharmony_ci}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci/*
32362306a36Sopenharmony_ci * For Buck 1/2.
32462306a36Sopenharmony_ci */
32562306a36Sopenharmony_cistatic int bd7181x_buck12_set_voltage_sel(struct regulator_dev *rdev,
32662306a36Sopenharmony_ci					  unsigned int sel)
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	int rid = rdev_get_id(rdev);
32962306a36Sopenharmony_ci	int ret, val, reg, regh, regl;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	regh = BD71815_REG_BUCK1_VOLT_H + rid*0x2;
33262306a36Sopenharmony_ci	regl = BD71815_REG_BUCK1_VOLT_L + rid*0x2;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	ret = regmap_read(rdev->regmap, regh, &val);
33562306a36Sopenharmony_ci	if (ret)
33662306a36Sopenharmony_ci		return ret;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	/*
33962306a36Sopenharmony_ci	 * If bucks 1 & 2 are controlled by state machine - then the RUN state
34062306a36Sopenharmony_ci	 * voltage is set to BD71815_REG_BUCK1_VOLT_H. Changing SUSPEND/LPSR
34162306a36Sopenharmony_ci	 * voltages at runtime is not supported by this driver.
34262306a36Sopenharmony_ci	 */
34362306a36Sopenharmony_ci	if (((val & BD71815_BUCK_STBY_DVS))) {
34462306a36Sopenharmony_ci		return regmap_update_bits(rdev->regmap, regh, BD71815_VOLT_MASK,
34562306a36Sopenharmony_ci					  sel);
34662306a36Sopenharmony_ci	}
34762306a36Sopenharmony_ci	/* Update new voltage to the register which is not selected now */
34862306a36Sopenharmony_ci	if (val & BD71815_BUCK_DVSSEL)
34962306a36Sopenharmony_ci		reg = regl;
35062306a36Sopenharmony_ci	else
35162306a36Sopenharmony_ci		reg = regh;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	ret = regmap_update_bits(rdev->regmap, reg, BD71815_VOLT_MASK, sel);
35462306a36Sopenharmony_ci	if (ret)
35562306a36Sopenharmony_ci		return ret;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	/* Select the other DVS register to be used */
35862306a36Sopenharmony_ci	return regmap_update_bits(rdev->regmap, regh, BD71815_BUCK_DVSSEL,
35962306a36Sopenharmony_ci				  ~val);
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic const struct regulator_ops bd7181x_ldo_regulator_ops = {
36362306a36Sopenharmony_ci	.enable = regulator_enable_regmap,
36462306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
36562306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
36662306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
36762306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_regmap,
36862306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_regmap,
36962306a36Sopenharmony_ci};
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_cistatic const struct regulator_ops bd7181x_fixed_regulator_ops = {
37262306a36Sopenharmony_ci	.enable = regulator_enable_regmap,
37362306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
37462306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
37562306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
37662306a36Sopenharmony_ci};
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_cistatic const struct regulator_ops bd7181x_buck_regulator_ops = {
37962306a36Sopenharmony_ci	.enable = regulator_enable_regmap,
38062306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
38162306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
38262306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
38362306a36Sopenharmony_ci	.set_voltage_sel = regulator_set_voltage_sel_regmap,
38462306a36Sopenharmony_ci	.get_voltage_sel = regulator_get_voltage_sel_regmap,
38562306a36Sopenharmony_ci	.set_voltage_time_sel = regulator_set_voltage_time_sel,
38662306a36Sopenharmony_ci};
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_cistatic const struct regulator_ops bd7181x_buck12_regulator_ops = {
38962306a36Sopenharmony_ci	.enable = regulator_enable_regmap,
39062306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
39162306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
39262306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
39362306a36Sopenharmony_ci	.set_voltage_sel = bd7181x_buck12_set_voltage_sel,
39462306a36Sopenharmony_ci	.get_voltage_sel = bd7181x_buck12_get_voltage_sel,
39562306a36Sopenharmony_ci	.set_voltage_time_sel = regulator_set_voltage_time_sel,
39662306a36Sopenharmony_ci	.set_ramp_delay = regulator_set_ramp_delay_regmap,
39762306a36Sopenharmony_ci};
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_cistatic const struct regulator_ops bd7181x_led_regulator_ops = {
40062306a36Sopenharmony_ci	.enable = regulator_enable_regmap,
40162306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
40262306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
40362306a36Sopenharmony_ci	.set_current_limit = bd7181x_led_set_current_limit,
40462306a36Sopenharmony_ci	.get_current_limit = regulator_get_current_limit_regmap,
40562306a36Sopenharmony_ci};
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci#define BD71815_FIXED_REG(_name, _id, ereg, emsk, voltage, _dvs)	\
40862306a36Sopenharmony_ci	[(_id)] = {							\
40962306a36Sopenharmony_ci		.desc = {						\
41062306a36Sopenharmony_ci			.name = #_name,					\
41162306a36Sopenharmony_ci			.of_match = of_match_ptr(#_name),		\
41262306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),	\
41362306a36Sopenharmony_ci			.n_voltages = 1,				\
41462306a36Sopenharmony_ci			.ops = &bd7181x_fixed_regulator_ops,		\
41562306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,			\
41662306a36Sopenharmony_ci			.id = (_id),					\
41762306a36Sopenharmony_ci			.owner = THIS_MODULE,				\
41862306a36Sopenharmony_ci			.min_uV = (voltage),				\
41962306a36Sopenharmony_ci			.enable_reg = (ereg),				\
42062306a36Sopenharmony_ci			.enable_mask = (emsk),				\
42162306a36Sopenharmony_ci			.of_parse_cb = set_hw_dvs_levels,		\
42262306a36Sopenharmony_ci		},							\
42362306a36Sopenharmony_ci		.dvs = (_dvs),						\
42462306a36Sopenharmony_ci	}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci#define BD71815_BUCK_REG(_name, _id, vsel, ereg, min, max, step, _dvs)	\
42762306a36Sopenharmony_ci	[(_id)] = {							\
42862306a36Sopenharmony_ci		.desc = {						\
42962306a36Sopenharmony_ci			.name = #_name,					\
43062306a36Sopenharmony_ci			.of_match = of_match_ptr(#_name),		\
43162306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),	\
43262306a36Sopenharmony_ci			.n_voltages = ((max) - (min)) / (step) + 1,	\
43362306a36Sopenharmony_ci			.ops = &bd7181x_buck_regulator_ops,		\
43462306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,			\
43562306a36Sopenharmony_ci			.id = (_id),					\
43662306a36Sopenharmony_ci			.owner = THIS_MODULE,				\
43762306a36Sopenharmony_ci			.min_uV = (min),				\
43862306a36Sopenharmony_ci			.uV_step = (step),				\
43962306a36Sopenharmony_ci			.vsel_reg = (vsel),				\
44062306a36Sopenharmony_ci			.vsel_mask = BD71815_VOLT_MASK,			\
44162306a36Sopenharmony_ci			.enable_reg = (ereg),				\
44262306a36Sopenharmony_ci			.enable_mask = BD71815_BUCK_RUN_ON,		\
44362306a36Sopenharmony_ci			.of_parse_cb = set_hw_dvs_levels,		\
44462306a36Sopenharmony_ci		},							\
44562306a36Sopenharmony_ci		.dvs = (_dvs),						\
44662306a36Sopenharmony_ci	}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci#define BD71815_BUCK12_REG(_name, _id, vsel, ereg, min, max, step,	\
44962306a36Sopenharmony_ci			   _dvs)					\
45062306a36Sopenharmony_ci	[(_id)] = {							\
45162306a36Sopenharmony_ci		.desc = {						\
45262306a36Sopenharmony_ci			.name = #_name,					\
45362306a36Sopenharmony_ci			.of_match = of_match_ptr(#_name),		\
45462306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),	\
45562306a36Sopenharmony_ci			.n_voltages = ((max) - (min)) / (step) + 1,	\
45662306a36Sopenharmony_ci			.ops = &bd7181x_buck12_regulator_ops,		\
45762306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,			\
45862306a36Sopenharmony_ci			.id = (_id),					\
45962306a36Sopenharmony_ci			.owner = THIS_MODULE,				\
46062306a36Sopenharmony_ci			.min_uV = (min),				\
46162306a36Sopenharmony_ci			.uV_step = (step),				\
46262306a36Sopenharmony_ci			.vsel_reg = (vsel),				\
46362306a36Sopenharmony_ci			.vsel_mask = BD71815_VOLT_MASK,			\
46462306a36Sopenharmony_ci			.enable_reg = (ereg),				\
46562306a36Sopenharmony_ci			.enable_mask = BD71815_BUCK_RUN_ON,		\
46662306a36Sopenharmony_ci			.ramp_reg = (ereg),				\
46762306a36Sopenharmony_ci			.ramp_mask = BD71815_BUCK_RAMPRATE_MASK,	\
46862306a36Sopenharmony_ci			.ramp_delay_table = bd7181x_ramp_table,		\
46962306a36Sopenharmony_ci			.n_ramp_values = ARRAY_SIZE(bd7181x_ramp_table),\
47062306a36Sopenharmony_ci			.of_parse_cb = buck12_set_hw_dvs_levels,	\
47162306a36Sopenharmony_ci		},							\
47262306a36Sopenharmony_ci		.dvs = (_dvs),						\
47362306a36Sopenharmony_ci	}
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci#define BD71815_LED_REG(_name, _id, csel, mask, ereg, emsk, currents)	\
47662306a36Sopenharmony_ci	[(_id)] = {							\
47762306a36Sopenharmony_ci		.desc = {						\
47862306a36Sopenharmony_ci			.name = #_name,					\
47962306a36Sopenharmony_ci			.of_match = of_match_ptr(#_name),		\
48062306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),	\
48162306a36Sopenharmony_ci			.n_current_limits = ARRAY_SIZE(currents),	\
48262306a36Sopenharmony_ci			.ops = &bd7181x_led_regulator_ops,		\
48362306a36Sopenharmony_ci			.type = REGULATOR_CURRENT,			\
48462306a36Sopenharmony_ci			.id = (_id),					\
48562306a36Sopenharmony_ci			.owner = THIS_MODULE,				\
48662306a36Sopenharmony_ci			.curr_table = currents,				\
48762306a36Sopenharmony_ci			.csel_reg = (csel),				\
48862306a36Sopenharmony_ci			.csel_mask = (mask),				\
48962306a36Sopenharmony_ci			.enable_reg = (ereg),				\
49062306a36Sopenharmony_ci			.enable_mask = (emsk),				\
49162306a36Sopenharmony_ci		},							\
49262306a36Sopenharmony_ci	}
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci#define BD71815_LDO_REG(_name, _id, vsel, ereg, emsk, min, max, step,	\
49562306a36Sopenharmony_ci			_dvs)						\
49662306a36Sopenharmony_ci	[(_id)] = {							\
49762306a36Sopenharmony_ci		.desc = {						\
49862306a36Sopenharmony_ci			.name = #_name,					\
49962306a36Sopenharmony_ci			.of_match = of_match_ptr(#_name),		\
50062306a36Sopenharmony_ci			.regulators_node = of_match_ptr("regulators"),	\
50162306a36Sopenharmony_ci			.n_voltages = ((max) - (min)) / (step) + 1,	\
50262306a36Sopenharmony_ci			.ops = &bd7181x_ldo_regulator_ops,		\
50362306a36Sopenharmony_ci			.type = REGULATOR_VOLTAGE,			\
50462306a36Sopenharmony_ci			.id = (_id),					\
50562306a36Sopenharmony_ci			.owner = THIS_MODULE,				\
50662306a36Sopenharmony_ci			.min_uV = (min),				\
50762306a36Sopenharmony_ci			.uV_step = (step),				\
50862306a36Sopenharmony_ci			.vsel_reg = (vsel),				\
50962306a36Sopenharmony_ci			.vsel_mask = BD71815_VOLT_MASK,			\
51062306a36Sopenharmony_ci			.enable_reg = (ereg),				\
51162306a36Sopenharmony_ci			.enable_mask = (emsk),				\
51262306a36Sopenharmony_ci			.of_parse_cb = set_hw_dvs_levels,		\
51362306a36Sopenharmony_ci		},							\
51462306a36Sopenharmony_ci		.dvs = (_dvs),						\
51562306a36Sopenharmony_ci	}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_cistatic const struct bd71815_regulator bd71815_regulators[] = {
51862306a36Sopenharmony_ci	BD71815_BUCK12_REG(buck1, BD71815_BUCK1, BD71815_REG_BUCK1_VOLT_H,
51962306a36Sopenharmony_ci			   BD71815_REG_BUCK1_MODE, 800000, 2000000, 25000,
52062306a36Sopenharmony_ci			   &buck1_dvs),
52162306a36Sopenharmony_ci	BD71815_BUCK12_REG(buck2, BD71815_BUCK2, BD71815_REG_BUCK2_VOLT_H,
52262306a36Sopenharmony_ci			   BD71815_REG_BUCK2_MODE, 800000, 2000000, 25000,
52362306a36Sopenharmony_ci			   &buck2_dvs),
52462306a36Sopenharmony_ci	BD71815_BUCK_REG(buck3, BD71815_BUCK3, BD71815_REG_BUCK3_VOLT,
52562306a36Sopenharmony_ci			 BD71815_REG_BUCK3_MODE,  1200000, 2700000, 50000,
52662306a36Sopenharmony_ci			 &buck3_dvs),
52762306a36Sopenharmony_ci	BD71815_BUCK_REG(buck4, BD71815_BUCK4, BD71815_REG_BUCK4_VOLT,
52862306a36Sopenharmony_ci			 BD71815_REG_BUCK4_MODE,  1100000, 1850000, 25000,
52962306a36Sopenharmony_ci			 &buck4_dvs),
53062306a36Sopenharmony_ci	BD71815_BUCK_REG(buck5, BD71815_BUCK5, BD71815_REG_BUCK5_VOLT,
53162306a36Sopenharmony_ci			 BD71815_REG_BUCK5_MODE,  1800000, 3300000, 50000,
53262306a36Sopenharmony_ci			 &buck5_dvs),
53362306a36Sopenharmony_ci	BD71815_LDO_REG(ldo1, BD71815_LDO1, BD71815_REG_LDO1_VOLT,
53462306a36Sopenharmony_ci			BD71815_REG_LDO_MODE1, LDO1_RUN_ON, 800000, 3300000,
53562306a36Sopenharmony_ci			50000, &ldo1_dvs),
53662306a36Sopenharmony_ci	BD71815_LDO_REG(ldo2, BD71815_LDO2, BD71815_REG_LDO2_VOLT,
53762306a36Sopenharmony_ci			BD71815_REG_LDO_MODE2, LDO2_RUN_ON, 800000, 3300000,
53862306a36Sopenharmony_ci			50000, &ldo2_dvs),
53962306a36Sopenharmony_ci	/*
54062306a36Sopenharmony_ci	 * Let's default LDO3 to be enabled by SW. We can override ops if DT
54162306a36Sopenharmony_ci	 * says LDO3 should be enabled by HW when DCIN is connected.
54262306a36Sopenharmony_ci	 */
54362306a36Sopenharmony_ci	BD71815_LDO_REG(ldo3, BD71815_LDO3, BD71815_REG_LDO3_VOLT,
54462306a36Sopenharmony_ci			BD71815_REG_LDO_MODE2, LDO3_RUN_ON, 800000, 3300000,
54562306a36Sopenharmony_ci			50000, &ldo3_dvs),
54662306a36Sopenharmony_ci	BD71815_LDO_REG(ldo4, BD71815_LDO4, BD71815_REG_LDO4_VOLT,
54762306a36Sopenharmony_ci			BD71815_REG_LDO_MODE3, LDO4_RUN_ON, 800000, 3300000,
54862306a36Sopenharmony_ci			50000, &ldo4_dvs),
54962306a36Sopenharmony_ci	BD71815_LDO_REG(ldo5, BD71815_LDO5, BD71815_REG_LDO5_VOLT_H,
55062306a36Sopenharmony_ci			BD71815_REG_LDO_MODE3, LDO5_RUN_ON, 800000, 3300000,
55162306a36Sopenharmony_ci			50000, &ldo5_dvs),
55262306a36Sopenharmony_ci	BD71815_FIXED_REG(ldodvref, BD71815_LDODVREF, BD71815_REG_LDO_MODE4,
55362306a36Sopenharmony_ci			  DVREF_RUN_ON, 3000000, &dvref_dvs),
55462306a36Sopenharmony_ci	BD71815_FIXED_REG(ldolpsr, BD71815_LDOLPSR, BD71815_REG_LDO_MODE4,
55562306a36Sopenharmony_ci			  LDO_LPSR_RUN_ON, 1800000, &ldolpsr_dvs),
55662306a36Sopenharmony_ci	BD71815_LED_REG(wled, BD71815_WLED, BD71815_REG_LED_DIMM, LED_DIMM_MASK,
55762306a36Sopenharmony_ci			BD71815_REG_LED_CTRL, LED_RUN_ON,
55862306a36Sopenharmony_ci			bd7181x_wled_currents),
55962306a36Sopenharmony_ci};
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_cistatic int bd7181x_probe(struct platform_device *pdev)
56262306a36Sopenharmony_ci{
56362306a36Sopenharmony_ci	struct regulator_config config = {};
56462306a36Sopenharmony_ci	int i, ret;
56562306a36Sopenharmony_ci	struct gpio_desc *ldo4_en;
56662306a36Sopenharmony_ci	struct regmap *regmap;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	regmap = dev_get_regmap(pdev->dev.parent, NULL);
56962306a36Sopenharmony_ci	if (!regmap) {
57062306a36Sopenharmony_ci		dev_err(&pdev->dev, "No parent regmap\n");
57162306a36Sopenharmony_ci		return -ENODEV;
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	ldo4_en = devm_fwnode_gpiod_get(&pdev->dev,
57562306a36Sopenharmony_ci					dev_fwnode(pdev->dev.parent),
57662306a36Sopenharmony_ci					"rohm,vsel", GPIOD_ASIS, "ldo4-en");
57762306a36Sopenharmony_ci	if (IS_ERR(ldo4_en)) {
57862306a36Sopenharmony_ci		ret = PTR_ERR(ldo4_en);
57962306a36Sopenharmony_ci		if (ret != -ENOENT)
58062306a36Sopenharmony_ci			return ret;
58162306a36Sopenharmony_ci		ldo4_en = NULL;
58262306a36Sopenharmony_ci	}
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	/* Disable to go to ship-mode */
58562306a36Sopenharmony_ci	ret = regmap_update_bits(regmap, BD71815_REG_PWRCTRL, RESTARTEN, 0);
58662306a36Sopenharmony_ci	if (ret)
58762306a36Sopenharmony_ci		return ret;
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	config.dev = pdev->dev.parent;
59062306a36Sopenharmony_ci	config.regmap = regmap;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	for (i = 0; i < BD71815_REGULATOR_CNT; i++) {
59362306a36Sopenharmony_ci		const struct regulator_desc *desc;
59462306a36Sopenharmony_ci		struct regulator_dev *rdev;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci		desc = &bd71815_regulators[i].desc;
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci		if (i == BD71815_LDO4)
59962306a36Sopenharmony_ci			config.ena_gpiod = ldo4_en;
60062306a36Sopenharmony_ci		else
60162306a36Sopenharmony_ci			config.ena_gpiod = NULL;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci		rdev = devm_regulator_register(&pdev->dev, desc, &config);
60462306a36Sopenharmony_ci		if (IS_ERR(rdev))
60562306a36Sopenharmony_ci			return dev_err_probe(&pdev->dev, PTR_ERR(rdev),
60662306a36Sopenharmony_ci					     "failed to register %s regulator\n",
60762306a36Sopenharmony_ci					     desc->name);
60862306a36Sopenharmony_ci	}
60962306a36Sopenharmony_ci	return 0;
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_cistatic const struct platform_device_id bd7181x_pmic_id[] = {
61362306a36Sopenharmony_ci	{ "bd71815-pmic", ROHM_CHIP_TYPE_BD71815 },
61462306a36Sopenharmony_ci	{ },
61562306a36Sopenharmony_ci};
61662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(platform, bd7181x_pmic_id);
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_cistatic struct platform_driver bd7181x_regulator = {
61962306a36Sopenharmony_ci	.driver = {
62062306a36Sopenharmony_ci		.name = "bd7181x-pmic",
62162306a36Sopenharmony_ci		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
62262306a36Sopenharmony_ci	},
62362306a36Sopenharmony_ci	.probe = bd7181x_probe,
62462306a36Sopenharmony_ci	.id_table = bd7181x_pmic_id,
62562306a36Sopenharmony_ci};
62662306a36Sopenharmony_cimodule_platform_driver(bd7181x_regulator);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ciMODULE_AUTHOR("Tony Luo <luofc@embedinfo.com>");
62962306a36Sopenharmony_ciMODULE_DESCRIPTION("BD71815 voltage regulator driver");
63062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
63162306a36Sopenharmony_ciMODULE_ALIAS("platform:bd7181x-pmic");
632