xref: /openbmc/linux/drivers/regulator/fan53555.c (revision 3b26e483)
1 /*
2  * FAN53555 Fairchild Digitally Programmable TinyBuck Regulator Driver.
3  *
4  * Supported Part Numbers:
5  * FAN53555UC00X/01X/03X/04X/05X
6  *
7  * Copyright (c) 2012 Marvell Technology Ltd.
8  * Yunfan Zhang <yfzhang@marvell.com>
9  *
10  * This package is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  */
15 #include <linux/module.h>
16 #include <linux/param.h>
17 #include <linux/err.h>
18 #include <linux/platform_device.h>
19 #include <linux/regulator/driver.h>
20 #include <linux/regulator/machine.h>
21 #include <linux/i2c.h>
22 #include <linux/slab.h>
23 #include <linux/regmap.h>
24 #include <linux/regulator/fan53555.h>
25 
26 /* Voltage setting */
27 #define FAN53555_VSEL0		0x00
28 #define FAN53555_VSEL1		0x01
29 /* Control register */
30 #define FAN53555_CONTROL	0x02
31 /* IC Type */
32 #define FAN53555_ID1		0x03
33 /* IC mask version */
34 #define FAN53555_ID2		0x04
35 /* Monitor register */
36 #define FAN53555_MONITOR	0x05
37 
38 /* VSEL bit definitions */
39 #define VSEL_BUCK_EN	(1 << 7)
40 #define VSEL_MODE		(1 << 6)
41 #define VSEL_NSEL_MASK	0x3F
42 /* Chip ID and Verison */
43 #define DIE_ID		0x0F	/* ID1 */
44 #define DIE_REV		0x0F	/* ID2 */
45 /* Control bit definitions */
46 #define CTL_OUTPUT_DISCHG	(1 << 7)
47 #define CTL_SLEW_MASK		(0x7 << 4)
48 #define CTL_SLEW_SHIFT		4
49 #define CTL_RESET			(1 << 2)
50 
51 #define FAN53555_NVOLTAGES	64	/* Numbers of voltages */
52 
53 /* IC Type */
54 enum {
55 	FAN53555_CHIP_ID_00 = 0,
56 	FAN53555_CHIP_ID_01,
57 	FAN53555_CHIP_ID_02,
58 	FAN53555_CHIP_ID_03,
59 	FAN53555_CHIP_ID_04,
60 	FAN53555_CHIP_ID_05,
61 };
62 
63 struct fan53555_device_info {
64 	struct regmap *regmap;
65 	struct device *dev;
66 	struct regulator_desc desc;
67 	struct regulator_dev *rdev;
68 	struct regulator_init_data *regulator;
69 	/* IC Type and Rev */
70 	int chip_id;
71 	int chip_rev;
72 	/* Voltage setting register */
73 	unsigned int vol_reg;
74 	unsigned int sleep_reg;
75 	/* Voltage range and step(linear) */
76 	unsigned int vsel_min;
77 	unsigned int vsel_step;
78 	/* Voltage slew rate limiting */
79 	unsigned int slew_rate;
80 	/* Sleep voltage cache */
81 	unsigned int sleep_vol_cache;
82 };
83 
84 static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
85 {
86 	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
87 	int ret;
88 
89 	if (di->sleep_vol_cache == uV)
90 		return 0;
91 	ret = regulator_map_voltage_linear(rdev, uV, uV);
92 	if (ret < 0)
93 		return -EINVAL;
94 	ret = regmap_update_bits(di->regmap, di->sleep_reg,
95 					VSEL_NSEL_MASK, ret);
96 	if (ret < 0)
97 		return -EINVAL;
98 	/* Cache the sleep voltage setting.
99 	 * Might not be the real voltage which is rounded */
100 	di->sleep_vol_cache = uV;
101 
102 	return 0;
103 }
104 
105 static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
106 {
107 	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
108 
109 	switch (mode) {
110 	case REGULATOR_MODE_FAST:
111 		regmap_update_bits(di->regmap, di->vol_reg,
112 				VSEL_MODE, VSEL_MODE);
113 		break;
114 	case REGULATOR_MODE_NORMAL:
115 		regmap_update_bits(di->regmap, di->vol_reg, VSEL_MODE, 0);
116 		break;
117 	default:
118 		return -EINVAL;
119 	}
120 	return 0;
121 }
122 
123 static unsigned int fan53555_get_mode(struct regulator_dev *rdev)
124 {
125 	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
126 	unsigned int val;
127 	int ret = 0;
128 
129 	ret = regmap_read(di->regmap, di->vol_reg, &val);
130 	if (ret < 0)
131 		return ret;
132 	if (val & VSEL_MODE)
133 		return REGULATOR_MODE_FAST;
134 	else
135 		return REGULATOR_MODE_NORMAL;
136 }
137 
138 static struct regulator_ops fan53555_regulator_ops = {
139 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
140 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
141 	.map_voltage = regulator_map_voltage_linear,
142 	.list_voltage = regulator_list_voltage_linear,
143 	.set_suspend_voltage = fan53555_set_suspend_voltage,
144 	.enable = regulator_enable_regmap,
145 	.disable = regulator_disable_regmap,
146 	.is_enabled = regulator_is_enabled_regmap,
147 	.set_mode = fan53555_set_mode,
148 	.get_mode = fan53555_get_mode,
149 };
150 
151 /* For 00,01,03,05 options:
152  * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V.
153  * For 04 option:
154  * VOUT = 0.603V + NSELx * 12.826mV, from 0.603 to 1.411V.
155  * */
156 static int fan53555_device_setup(struct fan53555_device_info *di,
157 				struct fan53555_platform_data *pdata)
158 {
159 	unsigned int reg, data, mask;
160 
161 	/* Setup voltage control register */
162 	switch (pdata->sleep_vsel_id) {
163 	case FAN53555_VSEL_ID_0:
164 		di->sleep_reg = FAN53555_VSEL0;
165 		di->vol_reg = FAN53555_VSEL1;
166 		break;
167 	case FAN53555_VSEL_ID_1:
168 		di->sleep_reg = FAN53555_VSEL1;
169 		di->vol_reg = FAN53555_VSEL0;
170 		break;
171 	default:
172 		dev_err(di->dev, "Invalid VSEL ID!\n");
173 		return -EINVAL;
174 	}
175 	/* Init voltage range and step */
176 	switch (di->chip_id) {
177 	case FAN53555_CHIP_ID_00:
178 	case FAN53555_CHIP_ID_01:
179 	case FAN53555_CHIP_ID_03:
180 	case FAN53555_CHIP_ID_05:
181 		di->vsel_min = 600000;
182 		di->vsel_step = 10000;
183 		break;
184 	case FAN53555_CHIP_ID_04:
185 		di->vsel_min = 603000;
186 		di->vsel_step = 12826;
187 		break;
188 	default:
189 		dev_err(di->dev,
190 			"Chip ID[%d]\n not supported!\n", di->chip_id);
191 		return -EINVAL;
192 	}
193 	/* Init slew rate */
194 	if (pdata->slew_rate & 0x7)
195 		di->slew_rate = pdata->slew_rate;
196 	else
197 		di->slew_rate = FAN53555_SLEW_RATE_64MV;
198 	reg = FAN53555_CONTROL;
199 	data = di->slew_rate << CTL_SLEW_SHIFT;
200 	mask = CTL_SLEW_MASK;
201 	return regmap_update_bits(di->regmap, reg, mask, data);
202 }
203 
204 static int fan53555_regulator_register(struct fan53555_device_info *di,
205 			struct regulator_config *config)
206 {
207 	struct regulator_desc *rdesc = &di->desc;
208 
209 	rdesc->name = "fan53555-reg";
210 	rdesc->ops = &fan53555_regulator_ops;
211 	rdesc->type = REGULATOR_VOLTAGE;
212 	rdesc->n_voltages = FAN53555_NVOLTAGES;
213 	rdesc->enable_reg = di->vol_reg;
214 	rdesc->enable_mask = VSEL_BUCK_EN;
215 	rdesc->min_uV = di->vsel_min;
216 	rdesc->uV_step = di->vsel_step;
217 	rdesc->vsel_reg = di->vol_reg;
218 	rdesc->vsel_mask = VSEL_NSEL_MASK;
219 	rdesc->owner = THIS_MODULE;
220 
221 	di->rdev = regulator_register(&di->desc, config);
222 	if (IS_ERR(di->rdev))
223 		return PTR_ERR(di->rdev);
224 	return 0;
225 
226 }
227 
228 static struct regmap_config fan53555_regmap_config = {
229 	.reg_bits = 8,
230 	.val_bits = 8,
231 };
232 
233 static int __devinit fan53555_regulator_probe(struct i2c_client *client,
234 				const struct i2c_device_id *id)
235 {
236 	struct fan53555_device_info *di;
237 	struct fan53555_platform_data *pdata;
238 	struct regulator_config config = { };
239 	unsigned int val;
240 	int ret;
241 
242 	pdata = client->dev.platform_data;
243 	if (!pdata || !pdata->regulator) {
244 		dev_err(&client->dev, "Platform data not found!\n");
245 		return -ENODEV;
246 	}
247 
248 	di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
249 					GFP_KERNEL);
250 	if (!di) {
251 		dev_err(&client->dev, "Failed to allocate device info data!\n");
252 		return -ENOMEM;
253 	}
254 	di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config);
255 	if (IS_ERR(di->regmap)) {
256 		dev_err(&client->dev, "Failed to allocate regmap!\n");
257 		return PTR_ERR(di->regmap);
258 	}
259 	di->dev = &client->dev;
260 	di->regulator = pdata->regulator;
261 	i2c_set_clientdata(client, di);
262 	/* Get chip ID */
263 	ret = regmap_read(di->regmap, FAN53555_ID1, &val);
264 	if (ret < 0) {
265 		dev_err(&client->dev, "Failed to get chip ID!\n");
266 		return -ENODEV;
267 	}
268 	di->chip_id = val & DIE_ID;
269 	/* Get chip revision */
270 	ret = regmap_read(di->regmap, FAN53555_ID2, &val);
271 	if (ret < 0) {
272 		dev_err(&client->dev, "Failed to get chip Rev!\n");
273 		return -ENODEV;
274 	}
275 	di->chip_rev = val & DIE_REV;
276 	dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n",
277 				di->chip_id, di->chip_rev);
278 	/* Device init */
279 	ret = fan53555_device_setup(di, pdata);
280 	if (ret < 0) {
281 		dev_err(&client->dev, "Failed to setup device!\n");
282 		return ret;
283 	}
284 	/* Register regulator */
285 	config.dev = di->dev;
286 	config.init_data = di->regulator;
287 	config.regmap = di->regmap;
288 	config.driver_data = di;
289 	ret = fan53555_regulator_register(di, &config);
290 	if (ret < 0)
291 		dev_err(&client->dev, "Failed to register regulator!\n");
292 	return ret;
293 
294 }
295 
296 static int __devexit fan53555_regulator_remove(struct i2c_client *client)
297 {
298 	struct fan53555_device_info *di = i2c_get_clientdata(client);
299 
300 	regulator_unregister(di->rdev);
301 	return 0;
302 }
303 
304 static const struct i2c_device_id fan53555_id[] = {
305 	{"fan53555", -1},
306 	{ },
307 };
308 
309 static struct i2c_driver fan53555_regulator_driver = {
310 	.driver = {
311 		.name = "fan53555-regulator",
312 	},
313 	.probe = fan53555_regulator_probe,
314 	.remove = __devexit_p(fan53555_regulator_remove),
315 	.id_table = fan53555_id,
316 };
317 
318 module_i2c_driver(fan53555_regulator_driver);
319 
320 MODULE_AUTHOR("Yunfan Zhang <yfzhang@marvell.com>");
321 MODULE_DESCRIPTION("FAN53555 regulator driver");
322 MODULE_LICENSE("GPL v2");
323