11aad3900SMatti Vaittinen // SPDX-License-Identifier: GPL-2.0-only
21aad3900SMatti Vaittinen //
31aad3900SMatti Vaittinen // Copyright 2014 Embest Technology Co. Ltd. Inc.
41aad3900SMatti Vaittinen // bd71815-regulator.c ROHM BD71815 regulator driver
51aad3900SMatti Vaittinen //
61aad3900SMatti Vaittinen // Author: Tony Luo <luofc@embedinfo.com>
71aad3900SMatti Vaittinen //
81aad3900SMatti Vaittinen // Partially rewritten at 2021 by
91aad3900SMatti Vaittinen // Matti Vaittinen <matti.vaitinen@fi.rohmeurope.com>
101aad3900SMatti Vaittinen 
111aad3900SMatti Vaittinen #include <linux/kernel.h>
121aad3900SMatti Vaittinen #include <linux/module.h>
131aad3900SMatti Vaittinen #include <linux/init.h>
141aad3900SMatti Vaittinen #include <linux/err.h>
151aad3900SMatti Vaittinen #include <linux/platform_device.h>
163799fa23SAxel Lin #include <linux/of.h>
173799fa23SAxel Lin #include <linux/gpio/consumer.h>
181aad3900SMatti Vaittinen #include <linux/regulator/driver.h>
191aad3900SMatti Vaittinen #include <linux/delay.h>
201aad3900SMatti Vaittinen #include <linux/slab.h>
211aad3900SMatti Vaittinen #include <linux/mfd/rohm-generic.h>
221aad3900SMatti Vaittinen #include <linux/mfd/rohm-bd71815.h>
231aad3900SMatti Vaittinen #include <linux/regulator/of_regulator.h>
241aad3900SMatti Vaittinen 
251aad3900SMatti Vaittinen struct bd71815_regulator {
261aad3900SMatti Vaittinen 	struct regulator_desc desc;
271aad3900SMatti Vaittinen 	const struct rohm_dvs_config *dvs;
281aad3900SMatti Vaittinen };
291aad3900SMatti Vaittinen 
301aad3900SMatti Vaittinen static const int bd7181x_wled_currents[] = {
311aad3900SMatti Vaittinen 	10, 20, 30, 50, 70, 100, 200, 300, 500, 700, 1000, 2000, 3000, 4000,
321aad3900SMatti Vaittinen 	5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000, 15000,
331aad3900SMatti Vaittinen 	16000, 17000, 18000, 19000, 20000, 21000, 22000, 23000, 24000, 25000,
341aad3900SMatti Vaittinen };
351aad3900SMatti Vaittinen 
361aad3900SMatti Vaittinen static const struct rohm_dvs_config buck1_dvs = {
371aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
381aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
391aad3900SMatti Vaittinen 	.run_reg		= BD71815_REG_BUCK1_VOLT_H,
401aad3900SMatti Vaittinen 	.run_mask		= BD71815_VOLT_MASK,
411aad3900SMatti Vaittinen 	.run_on_mask		= BD71815_BUCK_RUN_ON,
421aad3900SMatti Vaittinen 	.snvs_on_mask		= BD71815_BUCK_SNVS_ON,
431aad3900SMatti Vaittinen 	.suspend_reg		= BD71815_REG_BUCK1_VOLT_L,
441aad3900SMatti Vaittinen 	.suspend_mask		= BD71815_VOLT_MASK,
451aad3900SMatti Vaittinen 	.suspend_on_mask	= BD71815_BUCK_SUSP_ON,
461aad3900SMatti Vaittinen 	.lpsr_reg		= BD71815_REG_BUCK1_VOLT_L,
471aad3900SMatti Vaittinen 	.lpsr_mask		= BD71815_VOLT_MASK,
481aad3900SMatti Vaittinen 	.lpsr_on_mask		= BD71815_BUCK_LPSR_ON,
491aad3900SMatti Vaittinen };
501aad3900SMatti Vaittinen 
511aad3900SMatti Vaittinen static const struct rohm_dvs_config buck2_dvs = {
521aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
531aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
541aad3900SMatti Vaittinen 	.run_reg		= BD71815_REG_BUCK2_VOLT_H,
551aad3900SMatti Vaittinen 	.run_mask		= BD71815_VOLT_MASK,
561aad3900SMatti Vaittinen 	.run_on_mask		= BD71815_BUCK_RUN_ON,
571aad3900SMatti Vaittinen 	.snvs_on_mask		= BD71815_BUCK_SNVS_ON,
581aad3900SMatti Vaittinen 	.suspend_reg		= BD71815_REG_BUCK2_VOLT_L,
591aad3900SMatti Vaittinen 	.suspend_mask		= BD71815_VOLT_MASK,
601aad3900SMatti Vaittinen 	.suspend_on_mask	= BD71815_BUCK_SUSP_ON,
611aad3900SMatti Vaittinen 	.lpsr_reg		= BD71815_REG_BUCK2_VOLT_L,
621aad3900SMatti Vaittinen 	.lpsr_mask		= BD71815_VOLT_MASK,
631aad3900SMatti Vaittinen 	.lpsr_on_mask		= BD71815_BUCK_LPSR_ON,
641aad3900SMatti Vaittinen };
651aad3900SMatti Vaittinen 
661aad3900SMatti Vaittinen static const struct rohm_dvs_config buck3_dvs = {
671aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
681aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
691aad3900SMatti Vaittinen 	.run_reg		= BD71815_REG_BUCK3_VOLT,
701aad3900SMatti Vaittinen 	.run_mask		= BD71815_VOLT_MASK,
711aad3900SMatti Vaittinen 	.run_on_mask		= BD71815_BUCK_RUN_ON,
721aad3900SMatti Vaittinen 	.snvs_on_mask		= BD71815_BUCK_SNVS_ON,
731aad3900SMatti Vaittinen 	.suspend_on_mask	= BD71815_BUCK_SUSP_ON,
741aad3900SMatti Vaittinen 	.lpsr_on_mask		= BD71815_BUCK_LPSR_ON,
751aad3900SMatti Vaittinen };
761aad3900SMatti Vaittinen 
771aad3900SMatti Vaittinen static const struct rohm_dvs_config buck4_dvs = {
781aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
791aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
801aad3900SMatti Vaittinen 	.run_reg		= BD71815_REG_BUCK4_VOLT,
811aad3900SMatti Vaittinen 	.run_mask		= BD71815_VOLT_MASK,
821aad3900SMatti Vaittinen 	.run_on_mask		= BD71815_BUCK_RUN_ON,
831aad3900SMatti Vaittinen 	.snvs_on_mask		= BD71815_BUCK_SNVS_ON,
841aad3900SMatti Vaittinen 	.suspend_on_mask	= BD71815_BUCK_SUSP_ON,
851aad3900SMatti Vaittinen 	.lpsr_on_mask		= BD71815_BUCK_LPSR_ON,
861aad3900SMatti Vaittinen };
871aad3900SMatti Vaittinen 
881aad3900SMatti Vaittinen static const struct rohm_dvs_config ldo1_dvs = {
891aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
901aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
911aad3900SMatti Vaittinen 	.run_reg		= BD71815_REG_LDO_MODE1,
921aad3900SMatti Vaittinen 	.run_mask		= BD71815_VOLT_MASK,
931aad3900SMatti Vaittinen 	.run_on_mask		= LDO1_RUN_ON,
941aad3900SMatti Vaittinen 	.snvs_on_mask		= LDO1_SNVS_ON,
951aad3900SMatti Vaittinen 	.suspend_on_mask	= LDO1_SUSP_ON,
961aad3900SMatti Vaittinen 	.lpsr_on_mask		= LDO1_LPSR_ON,
971aad3900SMatti Vaittinen };
981aad3900SMatti Vaittinen 
991aad3900SMatti Vaittinen static const struct rohm_dvs_config ldo2_dvs = {
1001aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
1011aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
1021aad3900SMatti Vaittinen 	.run_reg		= BD71815_REG_LDO_MODE2,
1031aad3900SMatti Vaittinen 	.run_mask		= BD71815_VOLT_MASK,
1041aad3900SMatti Vaittinen 	.run_on_mask		= LDO2_RUN_ON,
1051aad3900SMatti Vaittinen 	.snvs_on_mask		= LDO2_SNVS_ON,
1061aad3900SMatti Vaittinen 	.suspend_on_mask	= LDO2_SUSP_ON,
1071aad3900SMatti Vaittinen 	.lpsr_on_mask		= LDO2_LPSR_ON,
1081aad3900SMatti Vaittinen };
1091aad3900SMatti Vaittinen 
1101aad3900SMatti Vaittinen static const struct rohm_dvs_config ldo3_dvs = {
1111aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
1121aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
1131aad3900SMatti Vaittinen 	.run_reg		= BD71815_REG_LDO_MODE2,
1141aad3900SMatti Vaittinen 	.run_mask		= BD71815_VOLT_MASK,
1151aad3900SMatti Vaittinen 	.run_on_mask		= LDO3_RUN_ON,
1161aad3900SMatti Vaittinen 	.snvs_on_mask		= LDO3_SNVS_ON,
1171aad3900SMatti Vaittinen 	.suspend_on_mask	= LDO3_SUSP_ON,
1181aad3900SMatti Vaittinen 	.lpsr_on_mask		= LDO3_LPSR_ON,
1191aad3900SMatti Vaittinen };
1201aad3900SMatti Vaittinen 
1211aad3900SMatti Vaittinen static const struct rohm_dvs_config ldo4_dvs = {
1221aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
1231aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
1241aad3900SMatti Vaittinen 	.run_reg		= BD71815_REG_LDO_MODE3,
1251aad3900SMatti Vaittinen 	.run_mask		= BD71815_VOLT_MASK,
1261aad3900SMatti Vaittinen 	.run_on_mask		= LDO4_RUN_ON,
1271aad3900SMatti Vaittinen 	.snvs_on_mask		= LDO4_SNVS_ON,
1281aad3900SMatti Vaittinen 	.suspend_on_mask	= LDO4_SUSP_ON,
1291aad3900SMatti Vaittinen 	.lpsr_on_mask		= LDO4_LPSR_ON,
1301aad3900SMatti Vaittinen };
1311aad3900SMatti Vaittinen 
1321aad3900SMatti Vaittinen static const struct rohm_dvs_config ldo5_dvs = {
1331aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
1341aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
1351aad3900SMatti Vaittinen 	.run_reg		= BD71815_REG_LDO_MODE3,
1361aad3900SMatti Vaittinen 	.run_mask		= BD71815_VOLT_MASK,
1371aad3900SMatti Vaittinen 	.run_on_mask		= LDO5_RUN_ON,
1381aad3900SMatti Vaittinen 	.snvs_on_mask		= LDO5_SNVS_ON,
1391aad3900SMatti Vaittinen 	.suspend_on_mask	= LDO5_SUSP_ON,
1401aad3900SMatti Vaittinen 	.lpsr_on_mask		= LDO5_LPSR_ON,
1411aad3900SMatti Vaittinen };
1421aad3900SMatti Vaittinen 
1431aad3900SMatti Vaittinen static const struct rohm_dvs_config dvref_dvs = {
1441aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
1451aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
1461aad3900SMatti Vaittinen 	.run_on_mask		= DVREF_RUN_ON,
1471aad3900SMatti Vaittinen 	.snvs_on_mask		= DVREF_SNVS_ON,
1481aad3900SMatti Vaittinen 	.suspend_on_mask	= DVREF_SUSP_ON,
1491aad3900SMatti Vaittinen 	.lpsr_on_mask		= DVREF_LPSR_ON,
1501aad3900SMatti Vaittinen };
1511aad3900SMatti Vaittinen 
1521aad3900SMatti Vaittinen static const struct rohm_dvs_config ldolpsr_dvs = {
1531aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
1541aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
1551aad3900SMatti Vaittinen 	.run_on_mask		= DVREF_RUN_ON,
1561aad3900SMatti Vaittinen 	.snvs_on_mask		= DVREF_SNVS_ON,
1571aad3900SMatti Vaittinen 	.suspend_on_mask	= DVREF_SUSP_ON,
1581aad3900SMatti Vaittinen 	.lpsr_on_mask		= DVREF_LPSR_ON,
1591aad3900SMatti Vaittinen };
1601aad3900SMatti Vaittinen 
1611aad3900SMatti Vaittinen static const struct rohm_dvs_config buck5_dvs = {
1621aad3900SMatti Vaittinen 	.level_map		= ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
1631aad3900SMatti Vaittinen 				  ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
1641aad3900SMatti Vaittinen 	.run_reg		= BD71815_REG_BUCK5_VOLT,
1651aad3900SMatti Vaittinen 	.run_mask		= BD71815_VOLT_MASK,
1661aad3900SMatti Vaittinen 	.run_on_mask		= BD71815_BUCK_RUN_ON,
1671aad3900SMatti Vaittinen 	.snvs_on_mask		= BD71815_BUCK_SNVS_ON,
1681aad3900SMatti Vaittinen 	.suspend_on_mask	= BD71815_BUCK_SUSP_ON,
1691aad3900SMatti Vaittinen 	.lpsr_on_mask		= BD71815_BUCK_LPSR_ON,
1701aad3900SMatti Vaittinen };
1711aad3900SMatti Vaittinen 
set_hw_dvs_levels(struct device_node * np,const struct regulator_desc * desc,struct regulator_config * cfg)1721aad3900SMatti Vaittinen static int set_hw_dvs_levels(struct device_node *np,
1731aad3900SMatti Vaittinen 			     const struct regulator_desc *desc,
1741aad3900SMatti Vaittinen 			     struct regulator_config *cfg)
1751aad3900SMatti Vaittinen {
1761aad3900SMatti Vaittinen 	struct bd71815_regulator *data;
1771aad3900SMatti Vaittinen 
1781aad3900SMatti Vaittinen 	data = container_of(desc, struct bd71815_regulator, desc);
1791aad3900SMatti Vaittinen 	return rohm_regulator_set_dvs_levels(data->dvs, np, desc, cfg->regmap);
1801aad3900SMatti Vaittinen }
1811aad3900SMatti Vaittinen 
1821aad3900SMatti Vaittinen /*
1831aad3900SMatti Vaittinen  * Bucks 1 and 2 have two voltage selection registers where selected
1841aad3900SMatti Vaittinen  * voltage can be set. Which of the registers is used can be either controlled
1851aad3900SMatti Vaittinen  * by a control bit in register - or by HW state. If HW state specific voltages
1861aad3900SMatti Vaittinen  * are given - then we assume HW state based control should be used.
1871aad3900SMatti Vaittinen  *
1881aad3900SMatti Vaittinen  * If volatge value is updated to currently selected register - then output
1891aad3900SMatti Vaittinen  * voltage is immediately changed no matter what is set as ramp rate. Thus we
1901aad3900SMatti Vaittinen  * default changing voltage by writing new value to inactive register and
1911aad3900SMatti Vaittinen  * then updating the 'register selection' bit. This naturally only works when
1921aad3900SMatti Vaittinen  * HW state machine is not used to select the voltage.
1931aad3900SMatti Vaittinen  */
buck12_set_hw_dvs_levels(struct device_node * np,const struct regulator_desc * desc,struct regulator_config * cfg)1941aad3900SMatti Vaittinen static int buck12_set_hw_dvs_levels(struct device_node *np,
1951aad3900SMatti Vaittinen 				    const struct regulator_desc *desc,
1961aad3900SMatti Vaittinen 				    struct regulator_config *cfg)
1971aad3900SMatti Vaittinen {
1981aad3900SMatti Vaittinen 	struct bd71815_regulator *data;
1991aad3900SMatti Vaittinen 	int ret = 0, val;
2001aad3900SMatti Vaittinen 
2011aad3900SMatti Vaittinen 	data = container_of(desc, struct bd71815_regulator, desc);
2021aad3900SMatti Vaittinen 
2037dda20c9SRob Herring 	if (of_property_present(np, "rohm,dvs-run-voltage") ||
2047dda20c9SRob Herring 	    of_property_present(np, "rohm,dvs-suspend-voltage") ||
2057dda20c9SRob Herring 	    of_property_present(np, "rohm,dvs-lpsr-voltage") ||
2067dda20c9SRob Herring 	    of_property_present(np, "rohm,dvs-snvs-voltage")) {
2071aad3900SMatti Vaittinen 		ret = regmap_read(cfg->regmap, desc->vsel_reg, &val);
2081aad3900SMatti Vaittinen 		if (ret)
2091aad3900SMatti Vaittinen 			return ret;
2101aad3900SMatti Vaittinen 
2111aad3900SMatti Vaittinen 		if (!(BD71815_BUCK_STBY_DVS & val) &&
2121aad3900SMatti Vaittinen 		    !(BD71815_BUCK_DVSSEL & val)) {
2131aad3900SMatti Vaittinen 			int val2;
2141aad3900SMatti Vaittinen 
2151aad3900SMatti Vaittinen 			/*
2161aad3900SMatti Vaittinen 			 * We are currently using voltage from _L.
2171aad3900SMatti Vaittinen 			 * We'd better copy it to _H and switch to it to
2181aad3900SMatti Vaittinen 			 * avoid shutting us down if LPSR or SUSPEND is set to
2191aad3900SMatti Vaittinen 			 * disabled. _L value is at reg _H + 1
2201aad3900SMatti Vaittinen 			 */
2211aad3900SMatti Vaittinen 			ret = regmap_read(cfg->regmap, desc->vsel_reg + 1,
2221aad3900SMatti Vaittinen 					  &val2);
2231aad3900SMatti Vaittinen 			if (ret)
2241aad3900SMatti Vaittinen 				return ret;
2251aad3900SMatti Vaittinen 
2261aad3900SMatti Vaittinen 			ret = regmap_update_bits(cfg->regmap, desc->vsel_reg,
2271aad3900SMatti Vaittinen 						 BD71815_VOLT_MASK |
2281aad3900SMatti Vaittinen 						 BD71815_BUCK_DVSSEL,
2291aad3900SMatti Vaittinen 						 val2 | BD71815_BUCK_DVSSEL);
2301aad3900SMatti Vaittinen 			if (ret)
2311aad3900SMatti Vaittinen 				return ret;
2321aad3900SMatti Vaittinen 		}
2331aad3900SMatti Vaittinen 		ret = rohm_regulator_set_dvs_levels(data->dvs, np, desc,
2341aad3900SMatti Vaittinen 						    cfg->regmap);
2351aad3900SMatti Vaittinen 		if (ret)
2361aad3900SMatti Vaittinen 			return ret;
2371aad3900SMatti Vaittinen 		/*
2381aad3900SMatti Vaittinen 		 * DVS levels were given => use HW-state machine for voltage
2391aad3900SMatti Vaittinen 		 * controls. NOTE: AFAIK, This means that if voltage is changed
2401aad3900SMatti Vaittinen 		 * by SW the ramp-rate is not respected. Should we disable
2411aad3900SMatti Vaittinen 		 * SW voltage control when the HW state machine is used?
2421aad3900SMatti Vaittinen 		 */
2431aad3900SMatti Vaittinen 		ret = regmap_update_bits(cfg->regmap, desc->vsel_reg,
2441aad3900SMatti Vaittinen 					 BD71815_BUCK_STBY_DVS,
2451aad3900SMatti Vaittinen 					 BD71815_BUCK_STBY_DVS);
2461aad3900SMatti Vaittinen 	}
2471aad3900SMatti Vaittinen 
2481aad3900SMatti Vaittinen 	return ret;
2491aad3900SMatti Vaittinen }
2501aad3900SMatti Vaittinen 
2511aad3900SMatti Vaittinen /*
2521aad3900SMatti Vaittinen  * BUCK1/2
2531aad3900SMatti Vaittinen  * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting
2541aad3900SMatti Vaittinen  * 00: 10.00mV/usec	10mV 1uS
2551aad3900SMatti Vaittinen  * 01: 5.00mV/usec	10mV 2uS
2561aad3900SMatti Vaittinen  * 10: 2.50mV/usec	10mV 4uS
2571aad3900SMatti Vaittinen  * 11: 1.25mV/usec	10mV 8uS
2581aad3900SMatti Vaittinen  */
259*47a0fe77SKalle Niemi static const unsigned int bd7181x_ramp_table[] = { 10000, 5000, 2500, 1250 };
2601aad3900SMatti Vaittinen 
bd7181x_led_set_current_limit(struct regulator_dev * rdev,int min_uA,int max_uA)2611aad3900SMatti Vaittinen static int bd7181x_led_set_current_limit(struct regulator_dev *rdev,
2621aad3900SMatti Vaittinen 					int min_uA, int max_uA)
2631aad3900SMatti Vaittinen {
2641aad3900SMatti Vaittinen 	int ret;
2651aad3900SMatti Vaittinen 	int onstatus;
2661aad3900SMatti Vaittinen 
2671aad3900SMatti Vaittinen 	onstatus = regulator_is_enabled_regmap(rdev);
2681aad3900SMatti Vaittinen 
2691aad3900SMatti Vaittinen 	ret = regulator_set_current_limit_regmap(rdev, min_uA, max_uA);
2701aad3900SMatti Vaittinen 	if (!ret) {
2711aad3900SMatti Vaittinen 		int newstatus;
2721aad3900SMatti Vaittinen 
2731aad3900SMatti Vaittinen 		newstatus = regulator_is_enabled_regmap(rdev);
2741aad3900SMatti Vaittinen 		if (onstatus != newstatus) {
2751aad3900SMatti Vaittinen 			/*
2761aad3900SMatti Vaittinen 			 * HW FIX: spurious led status change detected. Toggle
2771aad3900SMatti Vaittinen 			 * state as a workaround
2781aad3900SMatti Vaittinen 			 */
2791aad3900SMatti Vaittinen 			if (onstatus)
2801aad3900SMatti Vaittinen 				ret = regulator_enable_regmap(rdev);
2811aad3900SMatti Vaittinen 			else
2821aad3900SMatti Vaittinen 				ret = regulator_disable_regmap(rdev);
2831aad3900SMatti Vaittinen 
2841aad3900SMatti Vaittinen 			if (ret)
2851aad3900SMatti Vaittinen 				dev_err(rdev_get_dev(rdev),
2861aad3900SMatti Vaittinen 					"failed to revert the LED state (%d)\n",
2871aad3900SMatti Vaittinen 					ret);
2881aad3900SMatti Vaittinen 		}
2891aad3900SMatti Vaittinen 	}
2901aad3900SMatti Vaittinen 
2911aad3900SMatti Vaittinen 	return ret;
2921aad3900SMatti Vaittinen }
2931aad3900SMatti Vaittinen 
bd7181x_buck12_get_voltage_sel(struct regulator_dev * rdev)2941aad3900SMatti Vaittinen static int bd7181x_buck12_get_voltage_sel(struct regulator_dev *rdev)
2951aad3900SMatti Vaittinen {
2961aad3900SMatti Vaittinen 	int rid = rdev_get_id(rdev);
2971aad3900SMatti Vaittinen 	int ret, regh, regl, val;
2981aad3900SMatti Vaittinen 
2991aad3900SMatti Vaittinen 	regh = BD71815_REG_BUCK1_VOLT_H + rid * 0x2;
3001aad3900SMatti Vaittinen 	regl = BD71815_REG_BUCK1_VOLT_L + rid * 0x2;
3011aad3900SMatti Vaittinen 
3020ea461b4SAxel Lin 	ret = regmap_read(rdev->regmap, regh, &val);
3031aad3900SMatti Vaittinen 	if (ret)
3041aad3900SMatti Vaittinen 		return ret;
3051aad3900SMatti Vaittinen 
3061aad3900SMatti Vaittinen 	/*
3071aad3900SMatti Vaittinen 	 * If we use HW state machine based voltage reg selection - then we
3081aad3900SMatti Vaittinen 	 * return BD71815_REG_BUCK1_VOLT_H which is used at RUN.
3091aad3900SMatti Vaittinen 	 * Else we do return the BD71815_REG_BUCK1_VOLT_H or
3101aad3900SMatti Vaittinen 	 * BD71815_REG_BUCK1_VOLT_L depending on which is selected to be used
3111aad3900SMatti Vaittinen 	 * by BD71815_BUCK_DVSSEL bit
3121aad3900SMatti Vaittinen 	 */
3131aad3900SMatti Vaittinen 	if ((!(val & BD71815_BUCK_STBY_DVS)) && (!(val & BD71815_BUCK_DVSSEL)))
3140ea461b4SAxel Lin 		ret = regmap_read(rdev->regmap, regl, &val);
3151aad3900SMatti Vaittinen 
3161aad3900SMatti Vaittinen 	if (ret)
3171aad3900SMatti Vaittinen 		return ret;
3181aad3900SMatti Vaittinen 
3191aad3900SMatti Vaittinen 	return val & BD71815_VOLT_MASK;
3201aad3900SMatti Vaittinen }
3211aad3900SMatti Vaittinen 
3221aad3900SMatti Vaittinen /*
3231aad3900SMatti Vaittinen  * For Buck 1/2.
3241aad3900SMatti Vaittinen  */
bd7181x_buck12_set_voltage_sel(struct regulator_dev * rdev,unsigned int sel)3251aad3900SMatti Vaittinen static int bd7181x_buck12_set_voltage_sel(struct regulator_dev *rdev,
3261aad3900SMatti Vaittinen 					  unsigned int sel)
3271aad3900SMatti Vaittinen {
3281aad3900SMatti Vaittinen 	int rid = rdev_get_id(rdev);
3291aad3900SMatti Vaittinen 	int ret, val, reg, regh, regl;
3301aad3900SMatti Vaittinen 
3311aad3900SMatti Vaittinen 	regh = BD71815_REG_BUCK1_VOLT_H + rid*0x2;
3321aad3900SMatti Vaittinen 	regl = BD71815_REG_BUCK1_VOLT_L + rid*0x2;
3331aad3900SMatti Vaittinen 
3340ea461b4SAxel Lin 	ret = regmap_read(rdev->regmap, regh, &val);
3351aad3900SMatti Vaittinen 	if (ret)
3361aad3900SMatti Vaittinen 		return ret;
3371aad3900SMatti Vaittinen 
3381aad3900SMatti Vaittinen 	/*
3391aad3900SMatti Vaittinen 	 * If bucks 1 & 2 are controlled by state machine - then the RUN state
3401aad3900SMatti Vaittinen 	 * voltage is set to BD71815_REG_BUCK1_VOLT_H. Changing SUSPEND/LPSR
3411aad3900SMatti Vaittinen 	 * voltages at runtime is not supported by this driver.
3421aad3900SMatti Vaittinen 	 */
3431aad3900SMatti Vaittinen 	if (((val & BD71815_BUCK_STBY_DVS))) {
3440ea461b4SAxel Lin 		return regmap_update_bits(rdev->regmap, regh, BD71815_VOLT_MASK,
3451aad3900SMatti Vaittinen 					  sel);
3461aad3900SMatti Vaittinen 	}
3471aad3900SMatti Vaittinen 	/* Update new voltage to the register which is not selected now */
3481aad3900SMatti Vaittinen 	if (val & BD71815_BUCK_DVSSEL)
3491aad3900SMatti Vaittinen 		reg = regl;
3501aad3900SMatti Vaittinen 	else
3511aad3900SMatti Vaittinen 		reg = regh;
3521aad3900SMatti Vaittinen 
3530ea461b4SAxel Lin 	ret = regmap_update_bits(rdev->regmap, reg, BD71815_VOLT_MASK, sel);
3541aad3900SMatti Vaittinen 	if (ret)
3551aad3900SMatti Vaittinen 		return ret;
3561aad3900SMatti Vaittinen 
3571aad3900SMatti Vaittinen 	/* Select the other DVS register to be used */
3580ea461b4SAxel Lin 	return regmap_update_bits(rdev->regmap, regh, BD71815_BUCK_DVSSEL,
3590ea461b4SAxel Lin 				  ~val);
3601aad3900SMatti Vaittinen }
3611aad3900SMatti Vaittinen 
3621aad3900SMatti Vaittinen static const struct regulator_ops bd7181x_ldo_regulator_ops = {
3631aad3900SMatti Vaittinen 	.enable = regulator_enable_regmap,
3641aad3900SMatti Vaittinen 	.disable = regulator_disable_regmap,
3651aad3900SMatti Vaittinen 	.is_enabled = regulator_is_enabled_regmap,
3661aad3900SMatti Vaittinen 	.list_voltage = regulator_list_voltage_linear,
3671aad3900SMatti Vaittinen 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
3681aad3900SMatti Vaittinen 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
3691aad3900SMatti Vaittinen };
3701aad3900SMatti Vaittinen 
3711aad3900SMatti Vaittinen static const struct regulator_ops bd7181x_fixed_regulator_ops = {
3721aad3900SMatti Vaittinen 	.enable = regulator_enable_regmap,
3731aad3900SMatti Vaittinen 	.disable = regulator_disable_regmap,
3741aad3900SMatti Vaittinen 	.is_enabled = regulator_is_enabled_regmap,
3751aad3900SMatti Vaittinen 	.list_voltage = regulator_list_voltage_linear,
3761aad3900SMatti Vaittinen };
3771aad3900SMatti Vaittinen 
3781aad3900SMatti Vaittinen static const struct regulator_ops bd7181x_buck_regulator_ops = {
3791aad3900SMatti Vaittinen 	.enable = regulator_enable_regmap,
3801aad3900SMatti Vaittinen 	.disable = regulator_disable_regmap,
3811aad3900SMatti Vaittinen 	.is_enabled = regulator_is_enabled_regmap,
3821aad3900SMatti Vaittinen 	.list_voltage = regulator_list_voltage_linear,
3831aad3900SMatti Vaittinen 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
3841aad3900SMatti Vaittinen 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
3851aad3900SMatti Vaittinen 	.set_voltage_time_sel = regulator_set_voltage_time_sel,
3861aad3900SMatti Vaittinen };
3871aad3900SMatti Vaittinen 
3881aad3900SMatti Vaittinen static const struct regulator_ops bd7181x_buck12_regulator_ops = {
3891aad3900SMatti Vaittinen 	.enable = regulator_enable_regmap,
3901aad3900SMatti Vaittinen 	.disable = regulator_disable_regmap,
3911aad3900SMatti Vaittinen 	.is_enabled = regulator_is_enabled_regmap,
3921aad3900SMatti Vaittinen 	.list_voltage = regulator_list_voltage_linear,
3931aad3900SMatti Vaittinen 	.set_voltage_sel = bd7181x_buck12_set_voltage_sel,
3941aad3900SMatti Vaittinen 	.get_voltage_sel = bd7181x_buck12_get_voltage_sel,
3951aad3900SMatti Vaittinen 	.set_voltage_time_sel = regulator_set_voltage_time_sel,
3961aad3900SMatti Vaittinen 	.set_ramp_delay = regulator_set_ramp_delay_regmap,
3971aad3900SMatti Vaittinen };
3981aad3900SMatti Vaittinen 
3991aad3900SMatti Vaittinen static const struct regulator_ops bd7181x_led_regulator_ops = {
4001aad3900SMatti Vaittinen 	.enable = regulator_enable_regmap,
4011aad3900SMatti Vaittinen 	.disable = regulator_disable_regmap,
4021aad3900SMatti Vaittinen 	.is_enabled = regulator_is_enabled_regmap,
4031aad3900SMatti Vaittinen 	.set_current_limit = bd7181x_led_set_current_limit,
4041aad3900SMatti Vaittinen 	.get_current_limit = regulator_get_current_limit_regmap,
4051aad3900SMatti Vaittinen };
4061aad3900SMatti Vaittinen 
4071aad3900SMatti Vaittinen #define BD71815_FIXED_REG(_name, _id, ereg, emsk, voltage, _dvs)	\
4081aad3900SMatti Vaittinen 	[(_id)] = {							\
4091aad3900SMatti Vaittinen 		.desc = {						\
4101aad3900SMatti Vaittinen 			.name = #_name,					\
4111aad3900SMatti Vaittinen 			.of_match = of_match_ptr(#_name),		\
4121aad3900SMatti Vaittinen 			.regulators_node = of_match_ptr("regulators"),	\
4131aad3900SMatti Vaittinen 			.n_voltages = 1,				\
4141aad3900SMatti Vaittinen 			.ops = &bd7181x_fixed_regulator_ops,		\
4151aad3900SMatti Vaittinen 			.type = REGULATOR_VOLTAGE,			\
4161aad3900SMatti Vaittinen 			.id = (_id),					\
4171aad3900SMatti Vaittinen 			.owner = THIS_MODULE,				\
4181aad3900SMatti Vaittinen 			.min_uV = (voltage),				\
4191aad3900SMatti Vaittinen 			.enable_reg = (ereg),				\
4201aad3900SMatti Vaittinen 			.enable_mask = (emsk),				\
4211aad3900SMatti Vaittinen 			.of_parse_cb = set_hw_dvs_levels,		\
4221aad3900SMatti Vaittinen 		},							\
4231aad3900SMatti Vaittinen 		.dvs = (_dvs),						\
4241aad3900SMatti Vaittinen 	}
4251aad3900SMatti Vaittinen 
4261aad3900SMatti Vaittinen #define BD71815_BUCK_REG(_name, _id, vsel, ereg, min, max, step, _dvs)	\
4271aad3900SMatti Vaittinen 	[(_id)] = {							\
4281aad3900SMatti Vaittinen 		.desc = {						\
4291aad3900SMatti Vaittinen 			.name = #_name,					\
4301aad3900SMatti Vaittinen 			.of_match = of_match_ptr(#_name),		\
4311aad3900SMatti Vaittinen 			.regulators_node = of_match_ptr("regulators"),	\
4321aad3900SMatti Vaittinen 			.n_voltages = ((max) - (min)) / (step) + 1,	\
4331aad3900SMatti Vaittinen 			.ops = &bd7181x_buck_regulator_ops,		\
4341aad3900SMatti Vaittinen 			.type = REGULATOR_VOLTAGE,			\
4351aad3900SMatti Vaittinen 			.id = (_id),					\
4361aad3900SMatti Vaittinen 			.owner = THIS_MODULE,				\
4371aad3900SMatti Vaittinen 			.min_uV = (min),				\
4381aad3900SMatti Vaittinen 			.uV_step = (step),				\
4391aad3900SMatti Vaittinen 			.vsel_reg = (vsel),				\
4401aad3900SMatti Vaittinen 			.vsel_mask = BD71815_VOLT_MASK,			\
4411aad3900SMatti Vaittinen 			.enable_reg = (ereg),				\
4421aad3900SMatti Vaittinen 			.enable_mask = BD71815_BUCK_RUN_ON,		\
4431aad3900SMatti Vaittinen 			.of_parse_cb = set_hw_dvs_levels,		\
4441aad3900SMatti Vaittinen 		},							\
4451aad3900SMatti Vaittinen 		.dvs = (_dvs),						\
4461aad3900SMatti Vaittinen 	}
4471aad3900SMatti Vaittinen 
4481aad3900SMatti Vaittinen #define BD71815_BUCK12_REG(_name, _id, vsel, ereg, min, max, step,	\
4491aad3900SMatti Vaittinen 			   _dvs)					\
4501aad3900SMatti Vaittinen 	[(_id)] = {							\
4511aad3900SMatti Vaittinen 		.desc = {						\
4521aad3900SMatti Vaittinen 			.name = #_name,					\
4531aad3900SMatti Vaittinen 			.of_match = of_match_ptr(#_name),		\
4541aad3900SMatti Vaittinen 			.regulators_node = of_match_ptr("regulators"),	\
4551aad3900SMatti Vaittinen 			.n_voltages = ((max) - (min)) / (step) + 1,	\
4561aad3900SMatti Vaittinen 			.ops = &bd7181x_buck12_regulator_ops,		\
4571aad3900SMatti Vaittinen 			.type = REGULATOR_VOLTAGE,			\
4581aad3900SMatti Vaittinen 			.id = (_id),					\
4591aad3900SMatti Vaittinen 			.owner = THIS_MODULE,				\
4601aad3900SMatti Vaittinen 			.min_uV = (min),				\
4611aad3900SMatti Vaittinen 			.uV_step = (step),				\
4621aad3900SMatti Vaittinen 			.vsel_reg = (vsel),				\
463555767fdSMatti Vaittinen 			.vsel_mask = BD71815_VOLT_MASK,			\
4641aad3900SMatti Vaittinen 			.enable_reg = (ereg),				\
465555767fdSMatti Vaittinen 			.enable_mask = BD71815_BUCK_RUN_ON,		\
4661aad3900SMatti Vaittinen 			.ramp_reg = (ereg),				\
4671aad3900SMatti Vaittinen 			.ramp_mask = BD71815_BUCK_RAMPRATE_MASK,	\
4681aad3900SMatti Vaittinen 			.ramp_delay_table = bd7181x_ramp_table,		\
4691aad3900SMatti Vaittinen 			.n_ramp_values = ARRAY_SIZE(bd7181x_ramp_table),\
4701aad3900SMatti Vaittinen 			.of_parse_cb = buck12_set_hw_dvs_levels,	\
4711aad3900SMatti Vaittinen 		},							\
4721aad3900SMatti Vaittinen 		.dvs = (_dvs),						\
4731aad3900SMatti Vaittinen 	}
4741aad3900SMatti Vaittinen 
4751aad3900SMatti Vaittinen #define BD71815_LED_REG(_name, _id, csel, mask, ereg, emsk, currents)	\
4761aad3900SMatti Vaittinen 	[(_id)] = {							\
4771aad3900SMatti Vaittinen 		.desc = {						\
4781aad3900SMatti Vaittinen 			.name = #_name,					\
4791aad3900SMatti Vaittinen 			.of_match = of_match_ptr(#_name),		\
4801aad3900SMatti Vaittinen 			.regulators_node = of_match_ptr("regulators"),	\
4811aad3900SMatti Vaittinen 			.n_current_limits = ARRAY_SIZE(currents),	\
4821aad3900SMatti Vaittinen 			.ops = &bd7181x_led_regulator_ops,		\
4831aad3900SMatti Vaittinen 			.type = REGULATOR_CURRENT,			\
4841aad3900SMatti Vaittinen 			.id = (_id),					\
4851aad3900SMatti Vaittinen 			.owner = THIS_MODULE,				\
4861aad3900SMatti Vaittinen 			.curr_table = currents,				\
4871aad3900SMatti Vaittinen 			.csel_reg = (csel),				\
4881aad3900SMatti Vaittinen 			.csel_mask = (mask),				\
4891aad3900SMatti Vaittinen 			.enable_reg = (ereg),				\
4901aad3900SMatti Vaittinen 			.enable_mask = (emsk),				\
4911aad3900SMatti Vaittinen 		},							\
4921aad3900SMatti Vaittinen 	}
4931aad3900SMatti Vaittinen 
4941aad3900SMatti Vaittinen #define BD71815_LDO_REG(_name, _id, vsel, ereg, emsk, min, max, step,	\
4951aad3900SMatti Vaittinen 			_dvs)						\
4961aad3900SMatti Vaittinen 	[(_id)] = {							\
4971aad3900SMatti Vaittinen 		.desc = {						\
4981aad3900SMatti Vaittinen 			.name = #_name,					\
4991aad3900SMatti Vaittinen 			.of_match = of_match_ptr(#_name),		\
5001aad3900SMatti Vaittinen 			.regulators_node = of_match_ptr("regulators"),	\
5011aad3900SMatti Vaittinen 			.n_voltages = ((max) - (min)) / (step) + 1,	\
5021aad3900SMatti Vaittinen 			.ops = &bd7181x_ldo_regulator_ops,		\
5031aad3900SMatti Vaittinen 			.type = REGULATOR_VOLTAGE,			\
5041aad3900SMatti Vaittinen 			.id = (_id),					\
5051aad3900SMatti Vaittinen 			.owner = THIS_MODULE,				\
5061aad3900SMatti Vaittinen 			.min_uV = (min),				\
5071aad3900SMatti Vaittinen 			.uV_step = (step),				\
5081aad3900SMatti Vaittinen 			.vsel_reg = (vsel),				\
5091aad3900SMatti Vaittinen 			.vsel_mask = BD71815_VOLT_MASK,			\
5101aad3900SMatti Vaittinen 			.enable_reg = (ereg),				\
5111aad3900SMatti Vaittinen 			.enable_mask = (emsk),				\
5121aad3900SMatti Vaittinen 			.of_parse_cb = set_hw_dvs_levels,		\
5131aad3900SMatti Vaittinen 		},							\
5141aad3900SMatti Vaittinen 		.dvs = (_dvs),						\
5151aad3900SMatti Vaittinen 	}
5161aad3900SMatti Vaittinen 
5170ea461b4SAxel Lin static const struct bd71815_regulator bd71815_regulators[] = {
5181aad3900SMatti Vaittinen 	BD71815_BUCK12_REG(buck1, BD71815_BUCK1, BD71815_REG_BUCK1_VOLT_H,
5191aad3900SMatti Vaittinen 			   BD71815_REG_BUCK1_MODE, 800000, 2000000, 25000,
5201aad3900SMatti Vaittinen 			   &buck1_dvs),
5211aad3900SMatti Vaittinen 	BD71815_BUCK12_REG(buck2, BD71815_BUCK2, BD71815_REG_BUCK2_VOLT_H,
5221aad3900SMatti Vaittinen 			   BD71815_REG_BUCK2_MODE, 800000, 2000000, 25000,
5231aad3900SMatti Vaittinen 			   &buck2_dvs),
5241aad3900SMatti Vaittinen 	BD71815_BUCK_REG(buck3, BD71815_BUCK3, BD71815_REG_BUCK3_VOLT,
5251aad3900SMatti Vaittinen 			 BD71815_REG_BUCK3_MODE,  1200000, 2700000, 50000,
5261aad3900SMatti Vaittinen 			 &buck3_dvs),
5271aad3900SMatti Vaittinen 	BD71815_BUCK_REG(buck4, BD71815_BUCK4, BD71815_REG_BUCK4_VOLT,
5281aad3900SMatti Vaittinen 			 BD71815_REG_BUCK4_MODE,  1100000, 1850000, 25000,
5291aad3900SMatti Vaittinen 			 &buck4_dvs),
5301aad3900SMatti Vaittinen 	BD71815_BUCK_REG(buck5, BD71815_BUCK5, BD71815_REG_BUCK5_VOLT,
5311aad3900SMatti Vaittinen 			 BD71815_REG_BUCK5_MODE,  1800000, 3300000, 50000,
5321aad3900SMatti Vaittinen 			 &buck5_dvs),
5331aad3900SMatti Vaittinen 	BD71815_LDO_REG(ldo1, BD71815_LDO1, BD71815_REG_LDO1_VOLT,
5341aad3900SMatti Vaittinen 			BD71815_REG_LDO_MODE1, LDO1_RUN_ON, 800000, 3300000,
5351aad3900SMatti Vaittinen 			50000, &ldo1_dvs),
5361aad3900SMatti Vaittinen 	BD71815_LDO_REG(ldo2, BD71815_LDO2, BD71815_REG_LDO2_VOLT,
5371aad3900SMatti Vaittinen 			BD71815_REG_LDO_MODE2, LDO2_RUN_ON, 800000, 3300000,
5381aad3900SMatti Vaittinen 			50000, &ldo2_dvs),
5391aad3900SMatti Vaittinen 	/*
5401aad3900SMatti Vaittinen 	 * Let's default LDO3 to be enabled by SW. We can override ops if DT
5411aad3900SMatti Vaittinen 	 * says LDO3 should be enabled by HW when DCIN is connected.
5421aad3900SMatti Vaittinen 	 */
5431aad3900SMatti Vaittinen 	BD71815_LDO_REG(ldo3, BD71815_LDO3, BD71815_REG_LDO3_VOLT,
5441aad3900SMatti Vaittinen 			BD71815_REG_LDO_MODE2, LDO3_RUN_ON, 800000, 3300000,
5451aad3900SMatti Vaittinen 			50000, &ldo3_dvs),
5461aad3900SMatti Vaittinen 	BD71815_LDO_REG(ldo4, BD71815_LDO4, BD71815_REG_LDO4_VOLT,
5471aad3900SMatti Vaittinen 			BD71815_REG_LDO_MODE3, LDO4_RUN_ON, 800000, 3300000,
5481aad3900SMatti Vaittinen 			50000, &ldo4_dvs),
5491aad3900SMatti Vaittinen 	BD71815_LDO_REG(ldo5, BD71815_LDO5, BD71815_REG_LDO5_VOLT_H,
5501aad3900SMatti Vaittinen 			BD71815_REG_LDO_MODE3, LDO5_RUN_ON, 800000, 3300000,
5511aad3900SMatti Vaittinen 			50000, &ldo5_dvs),
5521aad3900SMatti Vaittinen 	BD71815_FIXED_REG(ldodvref, BD71815_LDODVREF, BD71815_REG_LDO_MODE4,
5531aad3900SMatti Vaittinen 			  DVREF_RUN_ON, 3000000, &dvref_dvs),
5541aad3900SMatti Vaittinen 	BD71815_FIXED_REG(ldolpsr, BD71815_LDOLPSR, BD71815_REG_LDO_MODE4,
5551aad3900SMatti Vaittinen 			  LDO_LPSR_RUN_ON, 1800000, &ldolpsr_dvs),
5561aad3900SMatti Vaittinen 	BD71815_LED_REG(wled, BD71815_WLED, BD71815_REG_LED_DIMM, LED_DIMM_MASK,
5571aad3900SMatti Vaittinen 			BD71815_REG_LED_CTRL, LED_RUN_ON,
5581aad3900SMatti Vaittinen 			bd7181x_wled_currents),
5591aad3900SMatti Vaittinen };
5601aad3900SMatti Vaittinen 
bd7181x_probe(struct platform_device * pdev)5611aad3900SMatti Vaittinen static int bd7181x_probe(struct platform_device *pdev)
5621aad3900SMatti Vaittinen {
5631aad3900SMatti Vaittinen 	struct regulator_config config = {};
5641aad3900SMatti Vaittinen 	int i, ret;
5651aad3900SMatti Vaittinen 	struct gpio_desc *ldo4_en;
5660ea461b4SAxel Lin 	struct regmap *regmap;
5671aad3900SMatti Vaittinen 
5680ea461b4SAxel Lin 	regmap = dev_get_regmap(pdev->dev.parent, NULL);
5690ea461b4SAxel Lin 	if (!regmap) {
5700ea461b4SAxel Lin 		dev_err(&pdev->dev, "No parent regmap\n");
5711aad3900SMatti Vaittinen 		return -ENODEV;
5721aad3900SMatti Vaittinen 	}
5731aad3900SMatti Vaittinen 
57497c9278eSDmitry Torokhov 	ldo4_en = devm_fwnode_gpiod_get(&pdev->dev,
57597c9278eSDmitry Torokhov 					dev_fwnode(pdev->dev.parent),
57697c9278eSDmitry Torokhov 					"rohm,vsel", GPIOD_ASIS, "ldo4-en");
5771aad3900SMatti Vaittinen 	if (IS_ERR(ldo4_en)) {
5781aad3900SMatti Vaittinen 		ret = PTR_ERR(ldo4_en);
5791aad3900SMatti Vaittinen 		if (ret != -ENOENT)
5801aad3900SMatti Vaittinen 			return ret;
5811aad3900SMatti Vaittinen 		ldo4_en = NULL;
5821aad3900SMatti Vaittinen 	}
5831aad3900SMatti Vaittinen 
5841aad3900SMatti Vaittinen 	/* Disable to go to ship-mode */
5850ea461b4SAxel Lin 	ret = regmap_update_bits(regmap, BD71815_REG_PWRCTRL, RESTARTEN, 0);
5861aad3900SMatti Vaittinen 	if (ret)
5871aad3900SMatti Vaittinen 		return ret;
5881aad3900SMatti Vaittinen 
5891aad3900SMatti Vaittinen 	config.dev = pdev->dev.parent;
5900ea461b4SAxel Lin 	config.regmap = regmap;
5911aad3900SMatti Vaittinen 
5921aad3900SMatti Vaittinen 	for (i = 0; i < BD71815_REGULATOR_CNT; i++) {
5930ea461b4SAxel Lin 		const struct regulator_desc *desc;
5941aad3900SMatti Vaittinen 		struct regulator_dev *rdev;
5951aad3900SMatti Vaittinen 
5960ea461b4SAxel Lin 		desc = &bd71815_regulators[i].desc;
5970ea461b4SAxel Lin 
5981aad3900SMatti Vaittinen 		if (i == BD71815_LDO4)
5991aad3900SMatti Vaittinen 			config.ena_gpiod = ldo4_en;
6000ea461b4SAxel Lin 		else
6010ea461b4SAxel Lin 			config.ena_gpiod = NULL;
6021aad3900SMatti Vaittinen 
6031aad3900SMatti Vaittinen 		rdev = devm_regulator_register(&pdev->dev, desc, &config);
604d4e93e8dSMatti Vaittinen 		if (IS_ERR(rdev))
605d4e93e8dSMatti Vaittinen 			return dev_err_probe(&pdev->dev, PTR_ERR(rdev),
6061aad3900SMatti Vaittinen 					     "failed to register %s regulator\n",
6071aad3900SMatti Vaittinen 					     desc->name);
6081aad3900SMatti Vaittinen 	}
6091aad3900SMatti Vaittinen 	return 0;
6101aad3900SMatti Vaittinen }
6111aad3900SMatti Vaittinen 
6121aad3900SMatti Vaittinen static const struct platform_device_id bd7181x_pmic_id[] = {
6131aad3900SMatti Vaittinen 	{ "bd71815-pmic", ROHM_CHIP_TYPE_BD71815 },
6141aad3900SMatti Vaittinen 	{ },
6151aad3900SMatti Vaittinen };
6161aad3900SMatti Vaittinen MODULE_DEVICE_TABLE(platform, bd7181x_pmic_id);
6171aad3900SMatti Vaittinen 
6181aad3900SMatti Vaittinen static struct platform_driver bd7181x_regulator = {
6191aad3900SMatti Vaittinen 	.driver = {
6201aad3900SMatti Vaittinen 		.name = "bd7181x-pmic",
62146600ab1SDouglas Anderson 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
6221aad3900SMatti Vaittinen 	},
6231aad3900SMatti Vaittinen 	.probe = bd7181x_probe,
6241aad3900SMatti Vaittinen 	.id_table = bd7181x_pmic_id,
6251aad3900SMatti Vaittinen };
6261aad3900SMatti Vaittinen module_platform_driver(bd7181x_regulator);
6271aad3900SMatti Vaittinen 
6281aad3900SMatti Vaittinen MODULE_AUTHOR("Tony Luo <luofc@embedinfo.com>");
6291aad3900SMatti Vaittinen MODULE_DESCRIPTION("BD71815 voltage regulator driver");
6301aad3900SMatti Vaittinen MODULE_LICENSE("GPL v2");
6311aad3900SMatti Vaittinen MODULE_ALIAS("platform:bd7181x-pmic");
632