xref: /linux/drivers/regulator/hi6421v530-regulator.c (revision 307797159ac25fe5a2048bf5c6a5718298edca57)
1 /*
2  * Device driver for regulators in Hi6421V530 IC
3  *
4  * Copyright (c) <2017> HiSilicon Technologies Co., Ltd.
5  *              http://www.hisilicon.com
6  * Copyright (c) <2017> Linaro Ltd.
7  *              http://www.linaro.org
8  *
9  * Author: Wang Xiaoyin <hw.wangxiaoyin@hisilicon.com>
10  *         Guodong Xu <guodong.xu@linaro.org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  */
16 
17 #include <linux/mfd/hi6421-pmic.h>
18 #include <linux/module.h>
19 #include <linux/of.h>
20 #include <linux/platform_device.h>
21 #include <linux/regmap.h>
22 #include <linux/regulator/driver.h>
23 
24 /*
25  * struct hi6421v530_regulator_info - hi6421v530 regulator information
26  * @desc: regulator description
27  * @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep
28  * @eco_microamp: eco mode load upper limit (in uA), valid for LDOs only
29  */
30 struct hi6421v530_regulator_info {
31 	struct regulator_desc rdesc;
32 	u8 mode_mask;
33 	u32 eco_microamp;
34 };
35 
36 /* HI6421v530 regulators */
37 enum hi6421v530_regulator_id {
38 	HI6421V530_LDO3,
39 	HI6421V530_LDO9,
40 	HI6421V530_LDO11,
41 	HI6421V530_LDO15,
42 	HI6421V530_LDO16,
43 };
44 
45 static const unsigned int ldo_3_voltages[] = {
46 	1800000, 1825000, 1850000, 1875000,
47 	1900000, 1925000, 1950000, 1975000,
48 	2000000, 2025000, 2050000, 2075000,
49 	2100000, 2125000, 2150000, 2200000,
50 };
51 
52 static const unsigned int ldo_9_11_voltages[] = {
53 	1750000, 1800000, 1825000, 2800000,
54 	2850000, 2950000, 3000000, 3300000,
55 };
56 
57 static const unsigned int ldo_15_16_voltages[] = {
58 	1750000, 1800000, 2400000, 2600000,
59 	2700000, 2850000, 2950000, 3000000,
60 };
61 
62 static const struct regulator_ops hi6421v530_ldo_ops;
63 
64 #define HI6421V530_LDO_ENABLE_TIME (350)
65 
66 /*
67  * _id - LDO id name string
68  * v_table - voltage table
69  * vreg - voltage select register
70  * vmask - voltage select mask
71  * ereg - enable register
72  * emask - enable mask
73  * odelay - off/on delay time in uS
74  * ecomask - eco mode mask
75  * ecoamp - eco mode load uppler limit in uA
76  */
77 #define HI6421V530_LDO(_ID, v_table, vreg, vmask, ereg, emask,		\
78 		   odelay, ecomask, ecoamp) {				\
79 	.rdesc = {							\
80 		.name		 = #_ID,				\
81 		.of_match        = of_match_ptr(#_ID),			\
82 		.regulators_node = of_match_ptr("regulators"),		\
83 		.ops		 = &hi6421v530_ldo_ops,			\
84 		.type		 = REGULATOR_VOLTAGE,			\
85 		.id		 = HI6421V530_##_ID,			\
86 		.owner		 = THIS_MODULE,				\
87 		.n_voltages	 = ARRAY_SIZE(v_table),			\
88 		.volt_table	 = v_table,				\
89 		.vsel_reg	 = HI6421_REG_TO_BUS_ADDR(vreg),	\
90 		.vsel_mask	 = vmask,				\
91 		.enable_reg	 = HI6421_REG_TO_BUS_ADDR(ereg),	\
92 		.enable_mask	 = emask,				\
93 		.enable_time	 = HI6421V530_LDO_ENABLE_TIME,		\
94 		.off_on_delay	 = odelay,				\
95 	},								\
96 	.mode_mask	= ecomask,					\
97 	.eco_microamp	= ecoamp,					\
98 }
99 
100 /* HI6421V530 regulator information */
101 
102 static struct hi6421v530_regulator_info hi6421v530_regulator_info[] = {
103 	HI6421V530_LDO(LDO3, ldo_3_voltages, 0x061, 0xf, 0x060, 0x2,
104 		   20000, 0x6, 8000),
105 	HI6421V530_LDO(LDO9, ldo_9_11_voltages, 0x06b, 0x7, 0x06a, 0x2,
106 		   40000, 0x6, 8000),
107 	HI6421V530_LDO(LDO11, ldo_9_11_voltages, 0x06f, 0x7, 0x06e, 0x2,
108 		   40000, 0x6, 8000),
109 	HI6421V530_LDO(LDO15, ldo_15_16_voltages, 0x077, 0x7, 0x076, 0x2,
110 		   40000, 0x6, 8000),
111 	HI6421V530_LDO(LDO16, ldo_15_16_voltages, 0x079, 0x7, 0x078, 0x2,
112 		   40000, 0x6, 8000),
113 };
114 
115 static unsigned int hi6421v530_regulator_ldo_get_mode(
116 					struct regulator_dev *rdev)
117 {
118 	struct hi6421v530_regulator_info *info;
119 	unsigned int reg_val;
120 
121 	info = rdev_get_drvdata(rdev);
122 	regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
123 
124 	if (reg_val & (info->mode_mask))
125 		return REGULATOR_MODE_IDLE;
126 
127 	return REGULATOR_MODE_NORMAL;
128 }
129 
130 static int hi6421v530_regulator_ldo_set_mode(struct regulator_dev *rdev,
131 						unsigned int mode)
132 {
133 	struct hi6421v530_regulator_info *info;
134 	unsigned int new_mode;
135 
136 	info = rdev_get_drvdata(rdev);
137 	switch (mode) {
138 	case REGULATOR_MODE_NORMAL:
139 		new_mode = 0;
140 		break;
141 	case REGULATOR_MODE_IDLE:
142 		new_mode = info->mode_mask;
143 		break;
144 	default:
145 		return -EINVAL;
146 	}
147 
148 	regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
149 			   info->mode_mask, new_mode);
150 
151 	return 0;
152 }
153 
154 
155 static const struct regulator_ops hi6421v530_ldo_ops = {
156 	.is_enabled = regulator_is_enabled_regmap,
157 	.enable = regulator_enable_regmap,
158 	.disable = regulator_disable_regmap,
159 	.list_voltage = regulator_list_voltage_table,
160 	.map_voltage = regulator_map_voltage_ascend,
161 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
162 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
163 	.get_mode = hi6421v530_regulator_ldo_get_mode,
164 	.set_mode = hi6421v530_regulator_ldo_set_mode,
165 };
166 
167 static int hi6421v530_regulator_probe(struct platform_device *pdev)
168 {
169 	struct hi6421_pmic *pmic;
170 	struct regulator_dev *rdev;
171 	struct regulator_config config = { };
172 	unsigned int i;
173 
174 	pmic = dev_get_drvdata(pdev->dev.parent);
175 	if (!pmic) {
176 		dev_err(&pdev->dev, "no pmic in the regulator parent node\n");
177 		return -ENODEV;
178 	}
179 
180 	for (i = 0; i < ARRAY_SIZE(hi6421v530_regulator_info); i++) {
181 		config.dev = pdev->dev.parent;
182 		config.regmap = pmic->regmap;
183 		config.driver_data = &hi6421v530_regulator_info[i];
184 
185 		rdev = devm_regulator_register(&pdev->dev,
186 				&hi6421v530_regulator_info[i].rdesc,
187 				&config);
188 		if (IS_ERR(rdev)) {
189 			dev_err(&pdev->dev, "failed to register regulator %s\n",
190 				hi6421v530_regulator_info[i].rdesc.name);
191 			return PTR_ERR(rdev);
192 		}
193 	}
194 	return 0;
195 }
196 
197 static const struct platform_device_id hi6421v530_regulator_table[] = {
198 	{ .name = "hi6421v530-regulator" },
199 	{},
200 };
201 MODULE_DEVICE_TABLE(platform, hi6421v530_regulator_table);
202 
203 static struct platform_driver hi6421v530_regulator_driver = {
204 	.id_table = hi6421v530_regulator_table,
205 	.driver = {
206 		.name	= "hi6421v530-regulator",
207 	},
208 	.probe	= hi6421v530_regulator_probe,
209 };
210 module_platform_driver(hi6421v530_regulator_driver);
211 
212 MODULE_AUTHOR("Wang Xiaoyin <hw.wangxiaoyin@hisilicon.com>");
213 MODULE_DESCRIPTION("Hi6421v530 regulator driver");
214 MODULE_LICENSE("GPL v2");
215