Blame view

drivers/regulator/tps62360-regulator.c 14.3 KB
6219929f5   Laxman Dewangan   regulator: TPS623...
1
2
3
  /*
   * tps62360.c -- TI tps62360
   *
d1cf4f65e   Axel Lin   regulator: Add su...
4
   * Driver for processor core supply tps62360, tps62361B, tps62362 and tps62363.
6219929f5   Laxman Dewangan   regulator: TPS623...
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
   *
   * Copyright (c) 2012, NVIDIA Corporation.
   *
   * Author: Laxman Dewangan <ldewangan@nvidia.com>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation version 2.
   *
   * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
   * whether express or implied; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   * 02111-1307, USA
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/err.h>
684ae39b9   Laxman Dewangan   regulator: tps623...
29
30
31
32
  #include <linux/of.h>
  #include <linux/of_device.h>
  #include <linux/of_gpio.h>
  #include <linux/regulator/of_regulator.h>
6219929f5   Laxman Dewangan   regulator: TPS623...
33
34
35
36
37
38
  #include <linux/platform_device.h>
  #include <linux/regulator/driver.h>
  #include <linux/regulator/machine.h>
  #include <linux/regulator/tps62360.h>
  #include <linux/gpio.h>
  #include <linux/i2c.h>
6219929f5   Laxman Dewangan   regulator: TPS623...
39
40
41
42
43
44
45
46
47
48
49
50
  #include <linux/slab.h>
  #include <linux/regmap.h>
  
  /* Register definitions */
  #define REG_VSET0		0
  #define REG_VSET1		1
  #define REG_VSET2		2
  #define REG_VSET3		3
  #define REG_CONTROL		4
  #define REG_TEMP		5
  #define REG_RAMPCTRL		6
  #define REG_CHIPID		8
9a00630c3   Laxman Dewangan   regulator: tps623...
51
  #define FORCE_PWM_ENABLE	BIT(7)
d1cf4f65e   Axel Lin   regulator: Add su...
52
  enum chips {TPS62360, TPS62361, TPS62362, TPS62363};
6219929f5   Laxman Dewangan   regulator: TPS623...
53

2935fb18a   Laxman Dewangan   regulator: tps623...
54
  #define TPS62360_BASE_VOLTAGE	770000
6219929f5   Laxman Dewangan   regulator: TPS623...
55
  #define TPS62360_N_VOLTAGES	64
2935fb18a   Laxman Dewangan   regulator: tps623...
56
  #define TPS62361_BASE_VOLTAGE	500000
6219929f5   Laxman Dewangan   regulator: TPS623...
57
58
59
60
  #define TPS62361_N_VOLTAGES	128
  
  /* tps 62360 chip information */
  struct tps62360_chip {
6219929f5   Laxman Dewangan   regulator: TPS623...
61
62
  	struct device *dev;
  	struct regulator_desc desc;
6219929f5   Laxman Dewangan   regulator: TPS623...
63
64
  	struct regulator_dev *rdev;
  	struct regmap *regmap;
6219929f5   Laxman Dewangan   regulator: TPS623...
65
66
  	int vsel0_gpio;
  	int vsel1_gpio;
6219929f5   Laxman Dewangan   regulator: TPS623...
67
68
  	u8 voltage_reg_mask;
  	bool en_internal_pulldn;
6219929f5   Laxman Dewangan   regulator: TPS623...
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  	bool en_discharge;
  	bool valid_gpios;
  	int lru_index[4];
  	int curr_vset_vsel[4];
  	int curr_vset_id;
  };
  
  /*
   * find_voltage_set_register: Find new voltage configuration register
   * (VSET) id.
   * The finding of the new VSET register will be based on the LRU mechanism.
   * Each VSET register will have different voltage configured . This
   * Function will look if any of the VSET register have requested voltage set
   * or not.
   *     - If it is already there then it will make that register as most
   *       recently used and return as found so that caller need not to set
   *       the VSET register but need to set the proper gpios to select this
   *       VSET register.
   *     - If requested voltage is not found then it will use the least
   *       recently mechanism to get new VSET register for new configuration
   *       and will return not_found so that caller need to set new VSET
   *       register and then gpios (both).
   */
  static bool find_voltage_set_register(struct tps62360_chip *tps,
  		int req_vsel, int *vset_reg_id)
  {
  	int i;
  	bool found = false;
  	int new_vset_reg = tps->lru_index[3];
  	int found_index = 3;
2935fb18a   Laxman Dewangan   regulator: tps623...
99

6219929f5   Laxman Dewangan   regulator: TPS623...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  	for (i = 0; i < 4; ++i) {
  		if (tps->curr_vset_vsel[tps->lru_index[i]] == req_vsel) {
  			new_vset_reg = tps->lru_index[i];
  			found_index = i;
  			found = true;
  			goto update_lru_index;
  		}
  	}
  
  update_lru_index:
  	for (i = found_index; i > 0; i--)
  		tps->lru_index[i] = tps->lru_index[i - 1];
  
  	tps->lru_index[0] = new_vset_reg;
  	*vset_reg_id = new_vset_reg;
  	return found;
  }
a60cfce05   Laxman Dewangan   regulator: tps623...
117
  static int tps62360_dcdc_get_voltage_sel(struct regulator_dev *dev)
6219929f5   Laxman Dewangan   regulator: TPS623...
118
119
120
121
122
123
124
125
  {
  	struct tps62360_chip *tps = rdev_get_drvdata(dev);
  	int vsel;
  	unsigned int data;
  	int ret;
  
  	ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data);
  	if (ret < 0) {
2935fb18a   Laxman Dewangan   regulator: tps623...
126
127
128
  		dev_err(tps->dev, "%s(): register %d read failed with err %d
  ",
  			__func__, REG_VSET0 + tps->curr_vset_id, ret);
6219929f5   Laxman Dewangan   regulator: TPS623...
129
130
131
  		return ret;
  	}
  	vsel = (int)data & tps->voltage_reg_mask;
a60cfce05   Laxman Dewangan   regulator: tps623...
132
  	return vsel;
6219929f5   Laxman Dewangan   regulator: TPS623...
133
  }
41097afd6   Axel Lin   regulator: tps623...
134
135
  static int tps62360_dcdc_set_voltage_sel(struct regulator_dev *dev,
  					 unsigned selector)
6219929f5   Laxman Dewangan   regulator: TPS623...
136
137
  {
  	struct tps62360_chip *tps = rdev_get_drvdata(dev);
6219929f5   Laxman Dewangan   regulator: TPS623...
138
139
140
  	int ret;
  	bool found = false;
  	int new_vset_id = tps->curr_vset_id;
6219929f5   Laxman Dewangan   regulator: TPS623...
141
142
143
144
145
  	/*
  	 * If gpios are available to select the VSET register then least
  	 * recently used register for new configuration.
  	 */
  	if (tps->valid_gpios)
41097afd6   Axel Lin   regulator: tps623...
146
  		found = find_voltage_set_register(tps, selector, &new_vset_id);
6219929f5   Laxman Dewangan   regulator: TPS623...
147
148
149
  
  	if (!found) {
  		ret = regmap_update_bits(tps->regmap, REG_VSET0 + new_vset_id,
41097afd6   Axel Lin   regulator: tps623...
150
  				tps->voltage_reg_mask, selector);
6219929f5   Laxman Dewangan   regulator: TPS623...
151
  		if (ret < 0) {
2935fb18a   Laxman Dewangan   regulator: tps623...
152
153
154
155
  			dev_err(tps->dev,
  				"%s(): register %d update failed with err %d
  ",
  				 __func__, REG_VSET0 + new_vset_id, ret);
6219929f5   Laxman Dewangan   regulator: TPS623...
156
157
158
  			return ret;
  		}
  		tps->curr_vset_id = new_vset_id;
41097afd6   Axel Lin   regulator: tps623...
159
  		tps->curr_vset_vsel[new_vset_id] = selector;
6219929f5   Laxman Dewangan   regulator: TPS623...
160
161
162
163
  	}
  
  	/* Select proper VSET register vio gpios */
  	if (tps->valid_gpios) {
2935fb18a   Laxman Dewangan   regulator: tps623...
164
  		gpio_set_value_cansleep(tps->vsel0_gpio, new_vset_id & 0x1);
6219929f5   Laxman Dewangan   regulator: TPS623...
165
166
167
168
169
  		gpio_set_value_cansleep(tps->vsel1_gpio,
  					(new_vset_id >> 1) & 0x1);
  	}
  	return 0;
  }
9a00630c3   Laxman Dewangan   regulator: tps623...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  static int tps62360_set_mode(struct regulator_dev *rdev, unsigned int mode)
  {
  	struct tps62360_chip *tps = rdev_get_drvdata(rdev);
  	int i;
  	int val;
  	int ret;
  
  	/* Enable force PWM mode in FAST mode only. */
  	switch (mode) {
  	case REGULATOR_MODE_FAST:
  		val = FORCE_PWM_ENABLE;
  		break;
  
  	case REGULATOR_MODE_NORMAL:
  		val = 0;
  		break;
  
  	default:
  		return -EINVAL;
  	}
  
  	if (!tps->valid_gpios) {
  		ret = regmap_update_bits(tps->regmap,
  			REG_VSET0 + tps->curr_vset_id, FORCE_PWM_ENABLE, val);
  		if (ret < 0)
  			dev_err(tps->dev,
  				"%s(): register %d update failed with err %d
  ",
  				__func__, REG_VSET0 + tps->curr_vset_id, ret);
  		return ret;
  	}
  
  	/* If gpios are valid then all register set need to be control */
  	for (i = 0; i < 4; ++i) {
  		ret = regmap_update_bits(tps->regmap,
  					REG_VSET0 + i, FORCE_PWM_ENABLE, val);
  		if (ret < 0) {
  			dev_err(tps->dev,
  				"%s(): register %d update failed with err %d
  ",
  				__func__, REG_VSET0 + i, ret);
  			return ret;
  		}
  	}
  	return ret;
  }
  
  static unsigned int tps62360_get_mode(struct regulator_dev *rdev)
  {
  	struct tps62360_chip *tps = rdev_get_drvdata(rdev);
  	unsigned int data;
  	int ret;
  
  	ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data);
  	if (ret < 0) {
  		dev_err(tps->dev, "%s(): register %d read failed with err %d
  ",
  			__func__, REG_VSET0 + tps->curr_vset_id, ret);
  		return ret;
  	}
  	return (data & FORCE_PWM_ENABLE) ?
  				REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
  }
6219929f5   Laxman Dewangan   regulator: TPS623...
233
  static struct regulator_ops tps62360_dcdc_ops = {
a60cfce05   Laxman Dewangan   regulator: tps623...
234
  	.get_voltage_sel	= tps62360_dcdc_get_voltage_sel,
41097afd6   Axel Lin   regulator: tps623...
235
  	.set_voltage_sel	= tps62360_dcdc_set_voltage_sel,
7f225ba58   Axel Lin   regulator: tps623...
236
  	.list_voltage		= regulator_list_voltage_linear,
41097afd6   Axel Lin   regulator: tps623...
237
  	.map_voltage		= regulator_map_voltage_linear,
0072f0a82   Axel Lin   regulator: tps623...
238
  	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
9a00630c3   Laxman Dewangan   regulator: tps623...
239
240
  	.set_mode		= tps62360_set_mode,
  	.get_mode		= tps62360_get_mode,
6219929f5   Laxman Dewangan   regulator: TPS623...
241
  };
a5023574d   Bill Pemberton   regulator: remove...
242
  static int tps62360_init_dcdc(struct tps62360_chip *tps,
6219929f5   Laxman Dewangan   regulator: TPS623...
243
244
245
  		struct tps62360_regulator_platform_data *pdata)
  {
  	int ret;
a60cfce05   Laxman Dewangan   regulator: tps623...
246
  	unsigned int ramp_ctrl;
6219929f5   Laxman Dewangan   regulator: TPS623...
247

2935fb18a   Laxman Dewangan   regulator: tps623...
248
  	/* Initialize internal pull up/down control */
6219929f5   Laxman Dewangan   regulator: TPS623...
249
250
251
252
253
  	if (tps->en_internal_pulldn)
  		ret = regmap_write(tps->regmap, REG_CONTROL, 0xE0);
  	else
  		ret = regmap_write(tps->regmap, REG_CONTROL, 0x0);
  	if (ret < 0) {
2935fb18a   Laxman Dewangan   regulator: tps623...
254
255
256
257
  		dev_err(tps->dev,
  			"%s(): register %d write failed with err %d
  ",
  			__func__, REG_CONTROL, ret);
6219929f5   Laxman Dewangan   regulator: TPS623...
258
259
  		return ret;
  	}
6219929f5   Laxman Dewangan   regulator: TPS623...
260
261
  	/* Reset output discharge path to reduce power consumption */
  	ret = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), 0);
a60cfce05   Laxman Dewangan   regulator: tps623...
262
  	if (ret < 0) {
2935fb18a   Laxman Dewangan   regulator: tps623...
263
264
265
266
  		dev_err(tps->dev,
  			"%s(): register %d update failed with err %d
  ",
  			__func__, REG_RAMPCTRL, ret);
a60cfce05   Laxman Dewangan   regulator: tps623...
267
268
269
270
271
272
  		return ret;
  	}
  
  	/* Get ramp value from ramp control register */
  	ret = regmap_read(tps->regmap, REG_RAMPCTRL, &ramp_ctrl);
  	if (ret < 0) {
2935fb18a   Laxman Dewangan   regulator: tps623...
273
274
275
276
  		dev_err(tps->dev,
  			"%s(): register %d read failed with err %d
  ",
  			__func__, REG_RAMPCTRL, ret);
a60cfce05   Laxman Dewangan   regulator: tps623...
277
278
  		return ret;
  	}
1864b6709   Axel Lin   regulator: tps623...
279
  	ramp_ctrl = (ramp_ctrl >> 5) & 0x7;
a60cfce05   Laxman Dewangan   regulator: tps623...
280
281
  
  	/* ramp mV/us = 32/(2^ramp_ctrl) */
0072f0a82   Axel Lin   regulator: tps623...
282
  	tps->desc.ramp_delay = DIV_ROUND_UP(32000, BIT(ramp_ctrl));
6219929f5   Laxman Dewangan   regulator: TPS623...
283
284
285
286
  	return ret;
  }
  
  static const struct regmap_config tps62360_regmap_config = {
16ea003bd   Laxman Dewangan   regulator: tps623...
287
288
289
290
  	.reg_bits		= 8,
  	.val_bits		= 8,
  	.max_register		= REG_CHIPID,
  	.cache_type		= REGCACHE_RBTREE,
6219929f5   Laxman Dewangan   regulator: TPS623...
291
  };
684ae39b9   Laxman Dewangan   regulator: tps623...
292
  static struct tps62360_regulator_platform_data *
072e78b12   Javier Martinez Canillas   regulator: of: Ad...
293
294
  	of_get_tps62360_platform_data(struct device *dev,
  				      const struct regulator_desc *desc)
684ae39b9   Laxman Dewangan   regulator: tps623...
295
296
297
298
299
  {
  	struct tps62360_regulator_platform_data *pdata;
  	struct device_node *np = dev->of_node;
  
  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
33e63ba6c   Sachin Kamat   regulator: tps623...
300
  	if (!pdata)
684ae39b9   Laxman Dewangan   regulator: tps623...
301
  		return NULL;
684ae39b9   Laxman Dewangan   regulator: tps623...
302

072e78b12   Javier Martinez Canillas   regulator: of: Ad...
303
304
  	pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node,
  							  desc);
684ae39b9   Laxman Dewangan   regulator: tps623...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  	if (!pdata->reg_init_data) {
  		dev_err(dev, "Not able to get OF regulator init data
  ");
  		return NULL;
  	}
  
  	pdata->vsel0_gpio = of_get_named_gpio(np, "vsel0-gpio", 0);
  	pdata->vsel1_gpio = of_get_named_gpio(np, "vsel1-gpio", 0);
  
  	if (of_find_property(np, "ti,vsel0-state-high", NULL))
  		pdata->vsel0_def_state = 1;
  
  	if (of_find_property(np, "ti,vsel1-state-high", NULL))
  		pdata->vsel1_def_state = 1;
  
  	if (of_find_property(np, "ti,enable-pull-down", NULL))
  		pdata->en_internal_pulldn = true;
684ae39b9   Laxman Dewangan   regulator: tps623...
322
323
324
325
326
327
328
329
330
331
332
333
334
  	if (of_find_property(np, "ti,enable-vout-discharge", NULL))
  		pdata->en_discharge = true;
  
  	return pdata;
  }
  
  #if defined(CONFIG_OF)
  static const struct of_device_id tps62360_of_match[] = {
  	 { .compatible = "ti,tps62360", .data = (void *)TPS62360},
  	 { .compatible = "ti,tps62361", .data = (void *)TPS62361},
  	 { .compatible = "ti,tps62362", .data = (void *)TPS62362},
  	 { .compatible = "ti,tps62363", .data = (void *)TPS62363},
  	{},
be15411d9   Axel Lin   regulator: tps623...
335
  };
684ae39b9   Laxman Dewangan   regulator: tps623...
336
337
  MODULE_DEVICE_TABLE(of, tps62360_of_match);
  #endif
a5023574d   Bill Pemberton   regulator: remove...
338
  static int tps62360_probe(struct i2c_client *client,
6219929f5   Laxman Dewangan   regulator: TPS623...
339
340
  				     const struct i2c_device_id *id)
  {
c172708d3   Mark Brown   regulator: core: ...
341
  	struct regulator_config config = { };
6219929f5   Laxman Dewangan   regulator: TPS623...
342
343
344
345
346
  	struct tps62360_regulator_platform_data *pdata;
  	struct regulator_dev *rdev;
  	struct tps62360_chip *tps;
  	int ret;
  	int i;
684ae39b9   Laxman Dewangan   regulator: tps623...
347
  	int chip_id;
6219929f5   Laxman Dewangan   regulator: TPS623...
348

dff91d0b7   Jingoo Han   regulator: use de...
349
  	pdata = dev_get_platdata(&client->dev);
684ae39b9   Laxman Dewangan   regulator: tps623...
350

072e78b12   Javier Martinez Canillas   regulator: of: Ad...
351
352
353
354
355
356
357
358
359
360
  	tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
  	if (!tps)
  		return -ENOMEM;
  
  	tps->desc.name = client->name;
  	tps->desc.id = 0;
  	tps->desc.ops = &tps62360_dcdc_ops;
  	tps->desc.type = REGULATOR_VOLTAGE;
  	tps->desc.owner = THIS_MODULE;
  	tps->desc.uV_step = 10000;
684ae39b9   Laxman Dewangan   regulator: tps623...
361
362
363
364
365
366
367
368
369
  	if (client->dev.of_node) {
  		const struct of_device_id *match;
  		match = of_match_device(of_match_ptr(tps62360_of_match),
  				&client->dev);
  		if (!match) {
  			dev_err(&client->dev, "Error: No device match found
  ");
  			return -ENODEV;
  		}
541f597f1   David Howells   regulator: tps623...
370
  		chip_id = (int)(long)match->data;
684ae39b9   Laxman Dewangan   regulator: tps623...
371
  		if (!pdata)
072e78b12   Javier Martinez Canillas   regulator: of: Ad...
372
373
  			pdata = of_get_tps62360_platform_data(&client->dev,
  							      &tps->desc);
0a62d03b4   Tuomas Tynkkynen   regulator: tps623...
374
375
376
377
378
379
  	} else if (id) {
  		chip_id = id->driver_data;
  	} else {
  		dev_err(&client->dev, "No device tree match or id table match found
  ");
  		return -ENODEV;
684ae39b9   Laxman Dewangan   regulator: tps623...
380
  	}
6219929f5   Laxman Dewangan   regulator: TPS623...
381
  	if (!pdata) {
2935fb18a   Laxman Dewangan   regulator: tps623...
382
383
  		dev_err(&client->dev, "%s(): Platform data not found
  ",
6219929f5   Laxman Dewangan   regulator: TPS623...
384
385
386
  						__func__);
  		return -EIO;
  	}
6219929f5   Laxman Dewangan   regulator: TPS623...
387
388
389
390
  	tps->en_discharge = pdata->en_discharge;
  	tps->en_internal_pulldn = pdata->en_internal_pulldn;
  	tps->vsel0_gpio = pdata->vsel0_gpio;
  	tps->vsel1_gpio = pdata->vsel1_gpio;
6219929f5   Laxman Dewangan   regulator: TPS623...
391
  	tps->dev = &client->dev;
d1cf4f65e   Axel Lin   regulator: Add su...
392

684ae39b9   Laxman Dewangan   regulator: tps623...
393
  	switch (chip_id) {
d1cf4f65e   Axel Lin   regulator: Add su...
394
395
  	case TPS62360:
  	case TPS62362:
b51524152   Axel Lin   regulator: tps623...
396
  		tps->desc.min_uV = TPS62360_BASE_VOLTAGE;
d1cf4f65e   Axel Lin   regulator: Add su...
397
398
399
400
401
  		tps->voltage_reg_mask = 0x3F;
  		tps->desc.n_voltages = TPS62360_N_VOLTAGES;
  		break;
  	case TPS62361:
  	case TPS62363:
b51524152   Axel Lin   regulator: tps623...
402
  		tps->desc.min_uV = TPS62361_BASE_VOLTAGE;
d1cf4f65e   Axel Lin   regulator: Add su...
403
404
405
406
407
408
  		tps->voltage_reg_mask = 0x7F;
  		tps->desc.n_voltages = TPS62361_N_VOLTAGES;
  		break;
  	default:
  		return -ENODEV;
  	}
6219929f5   Laxman Dewangan   regulator: TPS623...
409

9a4bdd87a   Axel Lin   regulator: tps623...
410
  	tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config);
6219929f5   Laxman Dewangan   regulator: TPS623...
411
412
  	if (IS_ERR(tps->regmap)) {
  		ret = PTR_ERR(tps->regmap);
2935fb18a   Laxman Dewangan   regulator: tps623...
413
414
415
416
  		dev_err(&client->dev,
  			"%s(): regmap allocation failed with err %d
  ",
  			__func__, ret);
6219929f5   Laxman Dewangan   regulator: TPS623...
417
418
419
420
421
422
423
424
425
426
  		return ret;
  	}
  	i2c_set_clientdata(client, tps);
  
  	tps->curr_vset_id = (pdata->vsel1_def_state & 1) * 2 +
  				(pdata->vsel0_def_state & 1);
  	tps->lru_index[0] = tps->curr_vset_id;
  	tps->valid_gpios = false;
  
  	if (gpio_is_valid(tps->vsel0_gpio) && gpio_is_valid(tps->vsel1_gpio)) {
2935fb18a   Laxman Dewangan   regulator: tps623...
427
428
429
  		int gpio_flags;
  		gpio_flags = (pdata->vsel0_def_state) ?
  				GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
8a8e3d591   Laxman Dewangan   regulator: tps623...
430
  		ret = devm_gpio_request_one(&client->dev, tps->vsel0_gpio,
2935fb18a   Laxman Dewangan   regulator: tps623...
431
  				gpio_flags, "tps62360-vsel0");
6219929f5   Laxman Dewangan   regulator: TPS623...
432
433
  		if (ret) {
  			dev_err(&client->dev,
2935fb18a   Laxman Dewangan   regulator: tps623...
434
435
436
  				"%s(): Could not obtain vsel0 GPIO %d: %d
  ",
  				__func__, tps->vsel0_gpio, ret);
8a8e3d591   Laxman Dewangan   regulator: tps623...
437
  			return ret;
6219929f5   Laxman Dewangan   regulator: TPS623...
438
  		}
2935fb18a   Laxman Dewangan   regulator: tps623...
439
440
  		gpio_flags = (pdata->vsel1_def_state) ?
  				GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
8a8e3d591   Laxman Dewangan   regulator: tps623...
441
  		ret = devm_gpio_request_one(&client->dev, tps->vsel1_gpio,
2935fb18a   Laxman Dewangan   regulator: tps623...
442
  				gpio_flags, "tps62360-vsel1");
6219929f5   Laxman Dewangan   regulator: TPS623...
443
444
  		if (ret) {
  			dev_err(&client->dev,
2935fb18a   Laxman Dewangan   regulator: tps623...
445
446
447
  				"%s(): Could not obtain vsel1 GPIO %d: %d
  ",
  				__func__, tps->vsel1_gpio, ret);
8a8e3d591   Laxman Dewangan   regulator: tps623...
448
  			return ret;
6219929f5   Laxman Dewangan   regulator: TPS623...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
  		}
  		tps->valid_gpios = true;
  
  		/*
  		 * Initialize the lru index with vset_reg id
  		 * The index 0 will be most recently used and
  		 * set with the tps->curr_vset_id */
  		for (i = 0; i < 4; ++i)
  			tps->lru_index[i] = i;
  		tps->lru_index[0] = tps->curr_vset_id;
  		tps->lru_index[tps->curr_vset_id] = 0;
  	}
  
  	ret = tps62360_init_dcdc(tps, pdata);
  	if (ret < 0) {
2935fb18a   Laxman Dewangan   regulator: tps623...
464
465
  		dev_err(tps->dev, "%s(): Init failed with err = %d
  ",
6219929f5   Laxman Dewangan   regulator: TPS623...
466
  				__func__, ret);
8a8e3d591   Laxman Dewangan   regulator: tps623...
467
  		return ret;
6219929f5   Laxman Dewangan   regulator: TPS623...
468
  	}
c172708d3   Mark Brown   regulator: core: ...
469
  	config.dev = &client->dev;
8bdca009e   Laxman Dewangan   regulator: tps623...
470
  	config.init_data = pdata->reg_init_data;
c172708d3   Mark Brown   regulator: core: ...
471
  	config.driver_data = tps;
9fc3815e2   Laxman Dewangan   regulator: tps623...
472
  	config.of_node = client->dev.of_node;
c172708d3   Mark Brown   regulator: core: ...
473

6219929f5   Laxman Dewangan   regulator: TPS623...
474
  	/* Register the regulators */
58c6e938c   Sachin Kamat   regulator: tps623...
475
  	rdev = devm_regulator_register(&client->dev, &tps->desc, &config);
6219929f5   Laxman Dewangan   regulator: TPS623...
476
  	if (IS_ERR(rdev)) {
2935fb18a   Laxman Dewangan   regulator: tps623...
477
478
479
480
  		dev_err(tps->dev,
  			"%s(): regulator register failed with err %s
  ",
  			__func__, id->name);
8a8e3d591   Laxman Dewangan   regulator: tps623...
481
  		return PTR_ERR(rdev);
6219929f5   Laxman Dewangan   regulator: TPS623...
482
483
484
485
  	}
  
  	tps->rdev = rdev;
  	return 0;
6219929f5   Laxman Dewangan   regulator: TPS623...
486
  }
6219929f5   Laxman Dewangan   regulator: TPS623...
487
488
489
490
491
492
493
494
495
496
497
  static void tps62360_shutdown(struct i2c_client *client)
  {
  	struct tps62360_chip *tps = i2c_get_clientdata(client);
  	int st;
  
  	if (!tps->en_discharge)
  		return;
  
  	/* Configure the output discharge path */
  	st = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), BIT(2));
  	if (st < 0)
2935fb18a   Laxman Dewangan   regulator: tps623...
498
499
500
501
  		dev_err(tps->dev,
  			"%s(): register %d update failed with err %d
  ",
  			__func__, REG_RAMPCTRL, st);
6219929f5   Laxman Dewangan   regulator: TPS623...
502
503
504
505
506
  }
  
  static const struct i2c_device_id tps62360_id[] = {
  	{.name = "tps62360", .driver_data = TPS62360},
  	{.name = "tps62361", .driver_data = TPS62361},
d1cf4f65e   Axel Lin   regulator: Add su...
507
508
  	{.name = "tps62362", .driver_data = TPS62362},
  	{.name = "tps62363", .driver_data = TPS62363},
6219929f5   Laxman Dewangan   regulator: TPS623...
509
510
511
512
513
514
515
516
  	{},
  };
  
  MODULE_DEVICE_TABLE(i2c, tps62360_id);
  
  static struct i2c_driver tps62360_i2c_driver = {
  	.driver = {
  		.name = "tps62360",
684ae39b9   Laxman Dewangan   regulator: tps623...
517
  		.of_match_table = of_match_ptr(tps62360_of_match),
6219929f5   Laxman Dewangan   regulator: TPS623...
518
519
  	},
  	.probe = tps62360_probe,
6219929f5   Laxman Dewangan   regulator: TPS623...
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
  	.shutdown = tps62360_shutdown,
  	.id_table = tps62360_id,
  };
  
  static int __init tps62360_init(void)
  {
  	return i2c_add_driver(&tps62360_i2c_driver);
  }
  subsys_initcall(tps62360_init);
  
  static void __exit tps62360_cleanup(void)
  {
  	i2c_del_driver(&tps62360_i2c_driver);
  }
  module_exit(tps62360_cleanup);
  
  MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
d1cf4f65e   Axel Lin   regulator: Add su...
537
  MODULE_DESCRIPTION("TPS6236x voltage regulator driver");
6219929f5   Laxman Dewangan   regulator: TPS623...
538
  MODULE_LICENSE("GPL v2");