xref: /linux/drivers/regulator/88pm8607.c (revision d2912cb15bdda8ba4a5dd73396ad62641af2f520)
1*d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2be0e2d3eSHaojian Zhuang /*
3be0e2d3eSHaojian Zhuang  * Regulators driver for Marvell 88PM8607
4be0e2d3eSHaojian Zhuang  *
5be0e2d3eSHaojian Zhuang  * Copyright (C) 2009 Marvell International Ltd.
6be0e2d3eSHaojian Zhuang  *	Haojian Zhuang <haojian.zhuang@marvell.com>
7be0e2d3eSHaojian Zhuang  */
8be0e2d3eSHaojian Zhuang #include <linux/kernel.h>
9be0e2d3eSHaojian Zhuang #include <linux/init.h>
10be0e2d3eSHaojian Zhuang #include <linux/err.h>
112e57d567SHaojian Zhuang #include <linux/of.h>
122e57d567SHaojian Zhuang #include <linux/regulator/of_regulator.h>
13be0e2d3eSHaojian Zhuang #include <linux/platform_device.h>
14be0e2d3eSHaojian Zhuang #include <linux/regulator/driver.h>
15be0e2d3eSHaojian Zhuang #include <linux/regulator/machine.h>
1653dbab7aSHaojian Zhuang #include <linux/mfd/88pm860x.h>
1765602c32SPaul Gortmaker #include <linux/module.h>
18be0e2d3eSHaojian Zhuang 
19be0e2d3eSHaojian Zhuang struct pm8607_regulator_info {
20be0e2d3eSHaojian Zhuang 	struct regulator_desc	desc;
21be0e2d3eSHaojian Zhuang 
229f79e9dbSHaojian Zhuang 	unsigned int	*vol_suspend;
239f79e9dbSHaojian Zhuang 
24be0e2d3eSHaojian Zhuang 	int	slope_double;
25be0e2d3eSHaojian Zhuang };
26be0e2d3eSHaojian Zhuang 
279f79e9dbSHaojian Zhuang static const unsigned int BUCK1_table[] = {
289f79e9dbSHaojian Zhuang 	 725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
299f79e9dbSHaojian Zhuang 	 925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
309f79e9dbSHaojian Zhuang 	1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
319f79e9dbSHaojian Zhuang 	1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
329f79e9dbSHaojian Zhuang 	      0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
339f79e9dbSHaojian Zhuang 	 200000,  225000,  250000,  275000,  300000,  325000,  350000,  375000,
349f79e9dbSHaojian Zhuang 	 400000,  425000,  450000,  475000,  500000,  525000,  550000,  575000,
359f79e9dbSHaojian Zhuang 	 600000,  625000,  650000,  675000,  700000,  725000,  750000,  775000,
369f79e9dbSHaojian Zhuang };
37be0e2d3eSHaojian Zhuang 
389f79e9dbSHaojian Zhuang static const unsigned int BUCK1_suspend_table[] = {
399f79e9dbSHaojian Zhuang 	      0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
409f79e9dbSHaojian Zhuang 	 200000,  225000,  250000,  275000,  300000,  325000,  350000,  375000,
419f79e9dbSHaojian Zhuang 	 400000,  425000,  450000,  475000,  500000,  525000,  550000,  575000,
429f79e9dbSHaojian Zhuang 	 600000,  625000,  650000,  675000,  700000,  725000,  750000,  775000,
439f79e9dbSHaojian Zhuang 	 800000,  825000,  850000,  875000,  900000,  925000,  950000,  975000,
449f79e9dbSHaojian Zhuang 	1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
459f79e9dbSHaojian Zhuang 	1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
469f79e9dbSHaojian Zhuang 	1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
479f79e9dbSHaojian Zhuang };
489f79e9dbSHaojian Zhuang 
499f79e9dbSHaojian Zhuang static const unsigned int BUCK2_table[] = {
509f79e9dbSHaojian Zhuang 	      0,   50000,  100000,  150000,  200000,  250000,  300000,  350000,
519f79e9dbSHaojian Zhuang 	 400000,  450000,  500000,  550000,  600000,  650000,  700000,  750000,
529f79e9dbSHaojian Zhuang 	 800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, 1150000,
539f79e9dbSHaojian Zhuang 	1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
549f79e9dbSHaojian Zhuang 	1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000,
559f79e9dbSHaojian Zhuang 	2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000,
569f79e9dbSHaojian Zhuang 	2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000,
579f79e9dbSHaojian Zhuang 	2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000,
589f79e9dbSHaojian Zhuang };
599f79e9dbSHaojian Zhuang 
609f79e9dbSHaojian Zhuang static const unsigned int BUCK2_suspend_table[] = {
619f79e9dbSHaojian Zhuang 	      0,   50000,  100000,  150000,  200000,  250000,  300000,  350000,
629f79e9dbSHaojian Zhuang 	 400000,  450000,  500000,  550000,  600000,  650000,  700000,  750000,
639f79e9dbSHaojian Zhuang 	 800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, 1150000,
649f79e9dbSHaojian Zhuang 	1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
659f79e9dbSHaojian Zhuang 	1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000,
669f79e9dbSHaojian Zhuang 	2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000,
679f79e9dbSHaojian Zhuang 	2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000,
689f79e9dbSHaojian Zhuang 	2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000,
699f79e9dbSHaojian Zhuang };
709f79e9dbSHaojian Zhuang 
719f79e9dbSHaojian Zhuang static const unsigned int BUCK3_table[] = {
729f79e9dbSHaojian Zhuang 	      0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
739f79e9dbSHaojian Zhuang 	 200000,  225000,  250000,  275000,  300000,  325000,  350000,  375000,
749f79e9dbSHaojian Zhuang 	 400000,  425000,  450000,  475000,  500000,  525000,  550000,  575000,
759f79e9dbSHaojian Zhuang 	 600000,  625000,  650000,  675000,  700000,  725000,  750000,  775000,
769f79e9dbSHaojian Zhuang 	 800000,  825000,  850000,  875000,  900000,  925000,  950000,  975000,
779f79e9dbSHaojian Zhuang 	1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
789f79e9dbSHaojian Zhuang 	1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
799f79e9dbSHaojian Zhuang 	1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
809f79e9dbSHaojian Zhuang };
819f79e9dbSHaojian Zhuang 
829f79e9dbSHaojian Zhuang static const unsigned int BUCK3_suspend_table[] = {
839f79e9dbSHaojian Zhuang 	      0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
849f79e9dbSHaojian Zhuang 	 200000,  225000,  250000,  275000,  300000,  325000,  350000,  375000,
859f79e9dbSHaojian Zhuang 	 400000,  425000,  450000,  475000,  500000,  525000,  550000,  575000,
869f79e9dbSHaojian Zhuang 	 600000,  625000,  650000,  675000,  700000,  725000,  750000,  775000,
879f79e9dbSHaojian Zhuang 	 800000,  825000,  850000,  875000,  900000,  925000,  950000,  975000,
889f79e9dbSHaojian Zhuang 	1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
899f79e9dbSHaojian Zhuang 	1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
909f79e9dbSHaojian Zhuang 	1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
919f79e9dbSHaojian Zhuang };
929f79e9dbSHaojian Zhuang 
939f79e9dbSHaojian Zhuang static const unsigned int LDO1_table[] = {
949f79e9dbSHaojian Zhuang 	1800000, 1200000, 2800000, 0,
959f79e9dbSHaojian Zhuang };
969f79e9dbSHaojian Zhuang 
979f79e9dbSHaojian Zhuang static const unsigned int LDO1_suspend_table[] = {
989f79e9dbSHaojian Zhuang 	1800000, 1200000, 0, 0,
999f79e9dbSHaojian Zhuang };
1009f79e9dbSHaojian Zhuang 
1019f79e9dbSHaojian Zhuang static const unsigned int LDO2_table[] = {
1029f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
1039f79e9dbSHaojian Zhuang };
1049f79e9dbSHaojian Zhuang 
1059f79e9dbSHaojian Zhuang static const unsigned int LDO2_suspend_table[] = {
1069f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
1079f79e9dbSHaojian Zhuang };
1089f79e9dbSHaojian Zhuang 
1099f79e9dbSHaojian Zhuang static const unsigned int LDO3_table[] = {
1109f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
1119f79e9dbSHaojian Zhuang };
1129f79e9dbSHaojian Zhuang 
1139f79e9dbSHaojian Zhuang static const unsigned int LDO3_suspend_table[] = {
1149f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
1159f79e9dbSHaojian Zhuang };
1169f79e9dbSHaojian Zhuang 
1179f79e9dbSHaojian Zhuang static const unsigned int LDO4_table[] = {
1189f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 3300000,
1199f79e9dbSHaojian Zhuang };
1209f79e9dbSHaojian Zhuang 
1219f79e9dbSHaojian Zhuang static const unsigned int LDO4_suspend_table[] = {
1229f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 2900000,
1239f79e9dbSHaojian Zhuang };
1249f79e9dbSHaojian Zhuang 
1259f79e9dbSHaojian Zhuang static const unsigned int LDO5_table[] = {
1269f79e9dbSHaojian Zhuang 	2900000, 3000000, 3100000, 3300000,
1279f79e9dbSHaojian Zhuang };
1289f79e9dbSHaojian Zhuang 
1299f79e9dbSHaojian Zhuang static const unsigned int LDO5_suspend_table[] = {
1309f79e9dbSHaojian Zhuang 	2900000, 0, 0, 0,
1319f79e9dbSHaojian Zhuang };
1329f79e9dbSHaojian Zhuang 
1339f79e9dbSHaojian Zhuang static const unsigned int LDO6_table[] = {
1349f79e9dbSHaojian Zhuang 	1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 3300000,
1359f79e9dbSHaojian Zhuang };
1369f79e9dbSHaojian Zhuang 
1379f79e9dbSHaojian Zhuang static const unsigned int LDO6_suspend_table[] = {
1389f79e9dbSHaojian Zhuang 	1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 2900000,
1399f79e9dbSHaojian Zhuang };
1409f79e9dbSHaojian Zhuang 
1419f79e9dbSHaojian Zhuang static const unsigned int LDO7_table[] = {
1429f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
1439f79e9dbSHaojian Zhuang };
1449f79e9dbSHaojian Zhuang 
1459f79e9dbSHaojian Zhuang static const unsigned int LDO7_suspend_table[] = {
1469f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
1479f79e9dbSHaojian Zhuang };
1489f79e9dbSHaojian Zhuang 
1499f79e9dbSHaojian Zhuang static const unsigned int LDO8_table[] = {
1509f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
1519f79e9dbSHaojian Zhuang };
1529f79e9dbSHaojian Zhuang 
1539f79e9dbSHaojian Zhuang static const unsigned int LDO8_suspend_table[] = {
1549f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
1559f79e9dbSHaojian Zhuang };
1569f79e9dbSHaojian Zhuang 
1579f79e9dbSHaojian Zhuang static const unsigned int LDO9_table[] = {
1589f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
1599f79e9dbSHaojian Zhuang };
1609f79e9dbSHaojian Zhuang 
1619f79e9dbSHaojian Zhuang static const unsigned int LDO9_suspend_table[] = {
1629f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
1639f79e9dbSHaojian Zhuang };
1649f79e9dbSHaojian Zhuang 
1659f79e9dbSHaojian Zhuang static const unsigned int LDO10_table[] = {
1669f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
1679f79e9dbSHaojian Zhuang 	1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
1689f79e9dbSHaojian Zhuang };
1699f79e9dbSHaojian Zhuang 
1709f79e9dbSHaojian Zhuang static const unsigned int LDO10_suspend_table[] = {
1719f79e9dbSHaojian Zhuang 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
1729f79e9dbSHaojian Zhuang 	1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
1739f79e9dbSHaojian Zhuang };
1749f79e9dbSHaojian Zhuang 
1759f79e9dbSHaojian Zhuang static const unsigned int LDO12_table[] = {
1769f79e9dbSHaojian Zhuang 	1800000, 1900000, 2700000, 2800000, 2900000, 3000000, 3100000, 3300000,
1779f79e9dbSHaojian Zhuang 	1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
1789f79e9dbSHaojian Zhuang };
1799f79e9dbSHaojian Zhuang 
1809f79e9dbSHaojian Zhuang static const unsigned int LDO12_suspend_table[] = {
1819f79e9dbSHaojian Zhuang 	1800000, 1900000, 2700000, 2800000, 2900000, 2900000, 2900000, 2900000,
1829f79e9dbSHaojian Zhuang 	1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
1839f79e9dbSHaojian Zhuang };
1849f79e9dbSHaojian Zhuang 
1859f79e9dbSHaojian Zhuang static const unsigned int LDO13_table[] = {
1863380643bSJett.Zhou 	1200000, 1300000, 1800000, 2000000, 2500000, 2800000, 3000000, 0,
1879f79e9dbSHaojian Zhuang };
1889f79e9dbSHaojian Zhuang 
1899f79e9dbSHaojian Zhuang static const unsigned int LDO13_suspend_table[] = {
1909f79e9dbSHaojian Zhuang 	0,
1919f79e9dbSHaojian Zhuang };
1929f79e9dbSHaojian Zhuang 
1939f79e9dbSHaojian Zhuang static const unsigned int LDO14_table[] = {
1949f79e9dbSHaojian Zhuang 	1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 3300000,
1959f79e9dbSHaojian Zhuang };
1969f79e9dbSHaojian Zhuang 
1979f79e9dbSHaojian Zhuang static const unsigned int LDO14_suspend_table[] = {
1989f79e9dbSHaojian Zhuang 	1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 2900000,
1999f79e9dbSHaojian Zhuang };
200be0e2d3eSHaojian Zhuang 
201be0e2d3eSHaojian Zhuang static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
202be0e2d3eSHaojian Zhuang {
203be0e2d3eSHaojian Zhuang 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
2042654d368SAxel Lin 	int ret;
205be0e2d3eSHaojian Zhuang 
2062654d368SAxel Lin 	ret = regulator_list_voltage_table(rdev, index);
2072654d368SAxel Lin 	if (ret < 0)
2082654d368SAxel Lin 		return ret;
2092654d368SAxel Lin 
210be0e2d3eSHaojian Zhuang 	if (info->slope_double)
211be0e2d3eSHaojian Zhuang 		ret <<= 1;
2122654d368SAxel Lin 
213be0e2d3eSHaojian Zhuang 	return ret;
214be0e2d3eSHaojian Zhuang }
215be0e2d3eSHaojian Zhuang 
21632cb5d30SBhumika Goyal static const struct regulator_ops pm8607_regulator_ops = {
217d3d7bcccSAxel Lin 	.list_voltage	= pm8607_list_voltage,
218c6f0a0efSAxel Lin 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
219c006b21fSAxel Lin 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
220ef26e0dbSAxel Lin 	.enable = regulator_enable_regmap,
221ef26e0dbSAxel Lin 	.disable = regulator_disable_regmap,
222ef26e0dbSAxel Lin 	.is_enabled = regulator_is_enabled_regmap,
223be0e2d3eSHaojian Zhuang };
224be0e2d3eSHaojian Zhuang 
22532cb5d30SBhumika Goyal static const struct regulator_ops pm8606_preg_ops = {
226318c658bSAxel Lin 	.enable		= regulator_enable_regmap,
227318c658bSAxel Lin 	.disable	= regulator_disable_regmap,
228318c658bSAxel Lin 	.is_enabled	= regulator_is_enabled_regmap,
229e7a7810aSJett.Zhou };
230e7a7810aSJett.Zhou 
231e7a7810aSJett.Zhou #define PM8606_PREG(ereg, ebit)						\
232e7a7810aSJett.Zhou {									\
233e7a7810aSJett.Zhou 	.desc	= {							\
234e7a7810aSJett.Zhou 		.name	= "PREG",					\
235e6626427SAxel Lin 		.of_match = of_match_ptr("PREG"),			\
236e6626427SAxel Lin 		.regulators_node = of_match_ptr("regulators"),		\
237e7a7810aSJett.Zhou 		.ops	= &pm8606_preg_ops,				\
238e7a7810aSJett.Zhou 		.type	= REGULATOR_CURRENT,				\
239e7a7810aSJett.Zhou 		.id	= PM8606_ID_PREG,				\
240e7a7810aSJett.Zhou 		.owner	= THIS_MODULE,					\
241e7a7810aSJett.Zhou 		.enable_reg = PM8606_##ereg,				\
242e7a7810aSJett.Zhou 		.enable_mask = (ebit),					\
243318c658bSAxel Lin 		.enable_is_inverted = true,				\
244e7a7810aSJett.Zhou 	},								\
245e7a7810aSJett.Zhou }
246e7a7810aSJett.Zhou 
24753b6949eSAxel Lin #define PM8607_DVC(vreg, ureg, ubit, ereg, ebit)			\
248be0e2d3eSHaojian Zhuang {									\
249be0e2d3eSHaojian Zhuang 	.desc	= {							\
2509f79e9dbSHaojian Zhuang 		.name	= #vreg,					\
251e6626427SAxel Lin 		.of_match = of_match_ptr(#vreg),			\
252e6626427SAxel Lin 		.regulators_node = of_match_ptr("regulators"),		\
253be0e2d3eSHaojian Zhuang 		.ops	= &pm8607_regulator_ops,			\
254be0e2d3eSHaojian Zhuang 		.type	= REGULATOR_VOLTAGE,				\
2559f79e9dbSHaojian Zhuang 		.id	= PM8607_ID_##vreg,				\
256be0e2d3eSHaojian Zhuang 		.owner	= THIS_MODULE,					\
2572654d368SAxel Lin 		.volt_table = vreg##_table,				\
25853b6949eSAxel Lin 		.n_voltages = ARRAY_SIZE(vreg##_table),			\
259c006b21fSAxel Lin 		.vsel_reg = PM8607_##vreg,				\
260c006b21fSAxel Lin 		.vsel_mask = ARRAY_SIZE(vreg##_table) - 1,		\
261c6f0a0efSAxel Lin 		.apply_reg = PM8607_##ureg,				\
262c6f0a0efSAxel Lin 		.apply_bit = (ubit),					\
263ef26e0dbSAxel Lin 		.enable_reg = PM8607_##ereg,				\
264ef26e0dbSAxel Lin 		.enable_mask = 1 << (ebit),				\
265be0e2d3eSHaojian Zhuang 	},								\
266be0e2d3eSHaojian Zhuang 	.slope_double	= (0),						\
2679f79e9dbSHaojian Zhuang 	.vol_suspend	= (unsigned int *)&vreg##_suspend_table,	\
268be0e2d3eSHaojian Zhuang }
269be0e2d3eSHaojian Zhuang 
27053b6949eSAxel Lin #define PM8607_LDO(_id, vreg, shift, ereg, ebit)			\
271be0e2d3eSHaojian Zhuang {									\
272be0e2d3eSHaojian Zhuang 	.desc	= {							\
273be0e2d3eSHaojian Zhuang 		.name	= "LDO" #_id,					\
274e6626427SAxel Lin 		.of_match = of_match_ptr("LDO" #_id),			\
275e6626427SAxel Lin 		.regulators_node = of_match_ptr("regulators"),		\
276be0e2d3eSHaojian Zhuang 		.ops	= &pm8607_regulator_ops,			\
277be0e2d3eSHaojian Zhuang 		.type	= REGULATOR_VOLTAGE,				\
278be0e2d3eSHaojian Zhuang 		.id	= PM8607_ID_LDO##_id,				\
279be0e2d3eSHaojian Zhuang 		.owner	= THIS_MODULE,					\
2802654d368SAxel Lin 		.volt_table = LDO##_id##_table,				\
28153b6949eSAxel Lin 		.n_voltages = ARRAY_SIZE(LDO##_id##_table),		\
282c006b21fSAxel Lin 		.vsel_reg = PM8607_##vreg,				\
283c006b21fSAxel Lin 		.vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \
284ef26e0dbSAxel Lin 		.enable_reg = PM8607_##ereg,				\
285ef26e0dbSAxel Lin 		.enable_mask = 1 << (ebit),				\
286be0e2d3eSHaojian Zhuang 	},								\
287be0e2d3eSHaojian Zhuang 	.slope_double	= (0),						\
2889f79e9dbSHaojian Zhuang 	.vol_suspend	= (unsigned int *)&LDO##_id##_suspend_table,	\
289be0e2d3eSHaojian Zhuang }
290be0e2d3eSHaojian Zhuang 
291be0e2d3eSHaojian Zhuang static struct pm8607_regulator_info pm8607_regulator_info[] = {
292c6f0a0efSAxel Lin 	PM8607_DVC(BUCK1, GO, BIT(0), SUPPLIES_EN11, 0),
293c6f0a0efSAxel Lin 	PM8607_DVC(BUCK2, GO, BIT(1), SUPPLIES_EN11, 1),
294c6f0a0efSAxel Lin 	PM8607_DVC(BUCK3, GO, BIT(2), SUPPLIES_EN11, 2),
295be0e2d3eSHaojian Zhuang 
29653b6949eSAxel Lin 	PM8607_LDO(1,         LDO1, 0, SUPPLIES_EN11, 3),
29753b6949eSAxel Lin 	PM8607_LDO(2,         LDO2, 0, SUPPLIES_EN11, 4),
29853b6949eSAxel Lin 	PM8607_LDO(3,         LDO3, 0, SUPPLIES_EN11, 5),
29953b6949eSAxel Lin 	PM8607_LDO(4,         LDO4, 0, SUPPLIES_EN11, 6),
30053b6949eSAxel Lin 	PM8607_LDO(5,         LDO5, 0, SUPPLIES_EN11, 7),
30153b6949eSAxel Lin 	PM8607_LDO(6,         LDO6, 0, SUPPLIES_EN12, 0),
30253b6949eSAxel Lin 	PM8607_LDO(7,         LDO7, 0, SUPPLIES_EN12, 1),
30353b6949eSAxel Lin 	PM8607_LDO(8,         LDO8, 0, SUPPLIES_EN12, 2),
30453b6949eSAxel Lin 	PM8607_LDO(9,         LDO9, 0, SUPPLIES_EN12, 3),
30553b6949eSAxel Lin 	PM8607_LDO(10,        LDO10, 0, SUPPLIES_EN12, 4),
30653b6949eSAxel Lin 	PM8607_LDO(12,        LDO12, 0, SUPPLIES_EN12, 5),
30753b6949eSAxel Lin 	PM8607_LDO(13, VIBRATOR_SET, 1, VIBRATOR_SET, 0),
30853b6949eSAxel Lin 	PM8607_LDO(14,        LDO14, 0, SUPPLIES_EN12, 6),
309ff13e9e2SHaojian Zhuang };
310e7a7810aSJett.Zhou 
311ff13e9e2SHaojian Zhuang static struct pm8607_regulator_info pm8606_regulator_info[] = {
312e7a7810aSJett.Zhou 	PM8606_PREG(PREREGULATORB, 5),
313be0e2d3eSHaojian Zhuang };
314be0e2d3eSHaojian Zhuang 
315a5023574SBill Pemberton static int pm8607_regulator_probe(struct platform_device *pdev)
316be0e2d3eSHaojian Zhuang {
31753dbab7aSHaojian Zhuang 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
318be0e2d3eSHaojian Zhuang 	struct pm8607_regulator_info *info = NULL;
319dff91d0bSJingoo Han 	struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev);
320c172708dSMark Brown 	struct regulator_config config = { };
3210e819b51SAxel Lin 	struct regulator_dev *rdev;
322586e1a17SHaojian Zhuang 	struct resource *res;
32322aad001SHaojian Zhuang 	int i;
324be0e2d3eSHaojian Zhuang 
32502367029SMark Brown 	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
326ff13e9e2SHaojian Zhuang 	if (res) {
327ff13e9e2SHaojian Zhuang 		/* There're resources in 88PM8607 regulator driver */
32822aad001SHaojian Zhuang 		for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
32922aad001SHaojian Zhuang 			info = &pm8607_regulator_info[i];
330a70abacbSHaojian Zhuang 			if (info->desc.vsel_reg == res->start)
33122aad001SHaojian Zhuang 				break;
33222aad001SHaojian Zhuang 		}
33399cd25ceSAxel Lin 		if (i == ARRAY_SIZE(pm8607_regulator_info)) {
33409969108SRandy Dunlap 			dev_err(&pdev->dev, "Failed to find regulator %llu\n",
33509969108SRandy Dunlap 				(unsigned long long)res->start);
336be0e2d3eSHaojian Zhuang 			return -EINVAL;
337be0e2d3eSHaojian Zhuang 		}
338ff13e9e2SHaojian Zhuang 	} else {
339ff13e9e2SHaojian Zhuang 		/* There's no resource in 88PM8606 PREG regulator driver */
340ff13e9e2SHaojian Zhuang 		info = &pm8606_regulator_info[0];
341ff13e9e2SHaojian Zhuang 		/* i is used to check regulator ID */
342ff13e9e2SHaojian Zhuang 		i = -1;
343ff13e9e2SHaojian Zhuang 	}
344be0e2d3eSHaojian Zhuang 
34522aad001SHaojian Zhuang 	/* check DVC ramp slope double */
3460e819b51SAxel Lin 	if ((i == PM8607_ID_BUCK3) && chip->buck3_double)
34722aad001SHaojian Zhuang 		info->slope_double = 1;
34822aad001SHaojian Zhuang 
349e6626427SAxel Lin 	config.dev = chip->dev;
350c172708dSMark Brown 	config.driver_data = info;
351c172708dSMark Brown 
3522e57d567SHaojian Zhuang 	if (pdata)
3532e57d567SHaojian Zhuang 		config.init_data = pdata;
3542e57d567SHaojian Zhuang 
355ef26e0dbSAxel Lin 	if (chip->id == CHIP_PM8607)
356ef26e0dbSAxel Lin 		config.regmap = chip->regmap;
357ef26e0dbSAxel Lin 	else
358ef26e0dbSAxel Lin 		config.regmap = chip->regmap_companion;
359ef26e0dbSAxel Lin 
3600e819b51SAxel Lin 	rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
3610e819b51SAxel Lin 	if (IS_ERR(rdev)) {
362be0e2d3eSHaojian Zhuang 		dev_err(&pdev->dev, "failed to register regulator %s\n",
363be0e2d3eSHaojian Zhuang 			info->desc.name);
3640e819b51SAxel Lin 		return PTR_ERR(rdev);
365be0e2d3eSHaojian Zhuang 	}
366be0e2d3eSHaojian Zhuang 
367be0e2d3eSHaojian Zhuang 	platform_set_drvdata(pdev, info);
368be0e2d3eSHaojian Zhuang 	return 0;
369be0e2d3eSHaojian Zhuang }
370be0e2d3eSHaojian Zhuang 
3710cfeddbdSKrzysztof Kozlowski static const struct platform_device_id pm8607_regulator_driver_ids[] = {
372e7a7810aSJett.Zhou 	{
373e7a7810aSJett.Zhou 		.name	= "88pm860x-regulator",
374e7a7810aSJett.Zhou 		.driver_data	= 0,
375e7a7810aSJett.Zhou 	}, {
376e7a7810aSJett.Zhou 		.name	= "88pm860x-preg",
377e7a7810aSJett.Zhou 		.driver_data	= 0,
378e7a7810aSJett.Zhou 	},
379e7a7810aSJett.Zhou 	{ },
380e7a7810aSJett.Zhou };
381e7a7810aSJett.Zhou MODULE_DEVICE_TABLE(platform, pm8607_regulator_driver_ids);
382e7a7810aSJett.Zhou 
383192bbb95SHaojian Zhuang static struct platform_driver pm8607_regulator_driver = {
384192bbb95SHaojian Zhuang 	.driver		= {
385192bbb95SHaojian Zhuang 		.name	= "88pm860x-regulator",
386192bbb95SHaojian Zhuang 	},
387192bbb95SHaojian Zhuang 	.probe		= pm8607_regulator_probe,
388e7a7810aSJett.Zhou 	.id_table	= pm8607_regulator_driver_ids,
389be0e2d3eSHaojian Zhuang };
390be0e2d3eSHaojian Zhuang 
391be0e2d3eSHaojian Zhuang static int __init pm8607_regulator_init(void)
392be0e2d3eSHaojian Zhuang {
393192bbb95SHaojian Zhuang 	return platform_driver_register(&pm8607_regulator_driver);
394be0e2d3eSHaojian Zhuang }
395be0e2d3eSHaojian Zhuang subsys_initcall(pm8607_regulator_init);
396be0e2d3eSHaojian Zhuang 
397be0e2d3eSHaojian Zhuang static void __exit pm8607_regulator_exit(void)
398be0e2d3eSHaojian Zhuang {
399192bbb95SHaojian Zhuang 	platform_driver_unregister(&pm8607_regulator_driver);
400be0e2d3eSHaojian Zhuang }
401be0e2d3eSHaojian Zhuang module_exit(pm8607_regulator_exit);
402be0e2d3eSHaojian Zhuang 
403be0e2d3eSHaojian Zhuang MODULE_LICENSE("GPL");
404be0e2d3eSHaojian Zhuang MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
405be0e2d3eSHaojian Zhuang MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM8607 PMIC");
406be0e2d3eSHaojian Zhuang MODULE_ALIAS("platform:88pm8607-regulator");
407