Blame view

drivers/regulator/tps65090-regulator.c 14.4 KB
9952f6918   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
452534e50   Venu Byravarasu   regulator: Add TP...
2
3
4
5
  /*
   * Regulator driver for tps65090 power management chip.
   *
   * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
452534e50   Venu Byravarasu   regulator: Add TP...
6
7
8
   */
  
  #include <linux/module.h>
ed11f1ead   Doug Anderson   regulator: tps650...
9
  #include <linux/delay.h>
452534e50   Venu Byravarasu   regulator: Add TP...
10
  #include <linux/init.h>
3012e8144   Linus Walleij   regulator: tps650...
11
12
  #include <linux/of.h>
  #include <linux/gpio/consumer.h>
452534e50   Venu Byravarasu   regulator: Add TP...
13
14
15
16
17
  #include <linux/slab.h>
  #include <linux/err.h>
  #include <linux/platform_device.h>
  #include <linux/regulator/driver.h>
  #include <linux/regulator/machine.h>
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
18
  #include <linux/regulator/of_regulator.h>
452534e50   Venu Byravarasu   regulator: Add TP...
19
  #include <linux/mfd/tps65090.h>
452534e50   Venu Byravarasu   regulator: Add TP...
20

ed11f1ead   Doug Anderson   regulator: tps650...
21
22
23
24
  #define MAX_CTRL_READ_TRIES	5
  #define MAX_FET_ENABLE_TRIES	1000
  
  #define CTRL_EN_BIT		0 /* Regulator enable bit, active high */
290414499   Doug Anderson   regulator: tps650...
25
  #define CTRL_WT_BIT		2 /* Regulator wait time 0 bit */
ed11f1ead   Doug Anderson   regulator: tps650...
26
27
  #define CTRL_PG_BIT		4 /* Regulator power good bit, 1=good */
  #define CTRL_TO_BIT		7 /* Regulator timeout bit, 1=wait */
290414499   Doug Anderson   regulator: tps650...
28
29
30
31
32
33
34
35
36
37
38
39
  
  #define MAX_OVERCURRENT_WAIT	3 /* Overcurrent wait must be <= this */
  
  /**
   * struct tps65090_regulator - Per-regulator data for a tps65090 regulator
   *
   * @dev: Pointer to our device.
   * @desc: The struct regulator_desc for the regulator.
   * @rdev: The struct regulator_dev for the regulator.
   * @overcurrent_wait_valid: True if overcurrent_wait is valid.
   * @overcurrent_wait: For FETs, the value to put in the WTFET bitfield.
   */
452534e50   Venu Byravarasu   regulator: Add TP...
40
  struct tps65090_regulator {
452534e50   Venu Byravarasu   regulator: Add TP...
41
  	struct device		*dev;
24282a1ca   Laxman Dewangan   regulator: tps650...
42
43
  	struct regulator_desc	*desc;
  	struct regulator_dev	*rdev;
290414499   Doug Anderson   regulator: tps650...
44
45
  	bool			overcurrent_wait_valid;
  	int			overcurrent_wait;
452534e50   Venu Byravarasu   regulator: Add TP...
46
  };
7d844ac3b   Rikard Falkeborn   regulator: tps650...
47
  static const struct regulator_ops tps65090_ext_control_ops = {
f329b1755   Laxman Dewangan   regulator: tps650...
48
  };
290414499   Doug Anderson   regulator: tps650...
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  /**
   * tps65090_reg_set_overcurrent_wait - Setup overcurrent wait
   *
   * This will set the overcurrent wait time based on what's in the regulator
   * info.
   *
   * @ri:		Overall regulator data
   * @rdev:	Regulator device
   *
   * Return: 0 if no error, non-zero if there was an error writing the register.
   */
  static int tps65090_reg_set_overcurrent_wait(struct tps65090_regulator *ri,
  					     struct regulator_dev *rdev)
  {
  	int ret;
  
  	ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
  				 MAX_OVERCURRENT_WAIT << CTRL_WT_BIT,
  				 ri->overcurrent_wait << CTRL_WT_BIT);
  	if (ret) {
  		dev_err(&rdev->dev, "Error updating overcurrent wait %#x
  ",
  			rdev->desc->enable_reg);
  	}
  
  	return ret;
  }
ed11f1ead   Doug Anderson   regulator: tps650...
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
  /**
   * tps65090_try_enable_fet - Try to enable a FET
   *
   * @rdev:	Regulator device
   *
   * Return: 0 if ok, -ENOTRECOVERABLE if the FET power good bit did not get
   * set, or some other -ve value if another error occurred (e.g. i2c error)
   */
  static int tps65090_try_enable_fet(struct regulator_dev *rdev)
  {
  	unsigned int control;
  	int ret, i;
  
  	ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
  				 rdev->desc->enable_mask,
  				 rdev->desc->enable_mask);
  	if (ret < 0) {
  		dev_err(&rdev->dev, "Error in updating reg %#x
  ",
  			rdev->desc->enable_reg);
  		return ret;
  	}
  
  	for (i = 0; i < MAX_CTRL_READ_TRIES; i++) {
  		ret = regmap_read(rdev->regmap, rdev->desc->enable_reg,
  				  &control);
  		if (ret < 0)
  			return ret;
  
  		if (!(control & BIT(CTRL_TO_BIT)))
  			break;
  
  		usleep_range(1000, 1500);
  	}
  	if (!(control & BIT(CTRL_PG_BIT)))
  		return -ENOTRECOVERABLE;
  
  	return 0;
  }
  
  /**
   * tps65090_fet_enable - Enable a FET, trying a few times if it fails
   *
   * Some versions of the tps65090 have issues when turning on the FETs.
   * This function goes through several steps to ensure the best chance of the
   * FET going on.  Specifically:
   * - We'll make sure that we bump the "overcurrent wait" to the maximum, which
   *   increases the chances that we'll turn on properly.
   * - We'll retry turning the FET on multiple times (turning off in between).
   *
   * @rdev:	Regulator device
   *
   * Return: 0 if ok, non-zero if it fails.
   */
  static int tps65090_fet_enable(struct regulator_dev *rdev)
  {
  	int ret, tries;
  
  	/*
  	 * Try enabling multiple times until we succeed since sometimes the
  	 * first try times out.
  	 */
  	tries = 0;
  	while (true) {
  		ret = tps65090_try_enable_fet(rdev);
  		if (!ret)
  			break;
  		if (ret != -ENOTRECOVERABLE || tries == MAX_FET_ENABLE_TRIES)
  			goto err;
  
  		/* Try turning the FET off (and then on again) */
  		ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
  					 rdev->desc->enable_mask, 0);
  		if (ret)
  			goto err;
  
  		tries++;
  	}
  
  	if (tries)
  		dev_warn(&rdev->dev, "reg %#x enable ok after %d tries
  ",
  			 rdev->desc->enable_reg, tries);
  
  	return 0;
  err:
  	dev_warn(&rdev->dev, "reg %#x enable failed
  ", rdev->desc->enable_reg);
  	WARN_ON(1);
  
  	return ret;
  }
7d844ac3b   Rikard Falkeborn   regulator: tps650...
168
  static const struct regulator_ops tps65090_reg_control_ops = {
f329b1755   Laxman Dewangan   regulator: tps650...
169
170
171
  	.enable		= regulator_enable_regmap,
  	.disable	= regulator_disable_regmap,
  	.is_enabled	= regulator_is_enabled_regmap,
452534e50   Venu Byravarasu   regulator: Add TP...
172
  };
7d844ac3b   Rikard Falkeborn   regulator: tps650...
173
  static const struct regulator_ops tps65090_fet_control_ops = {
ed11f1ead   Doug Anderson   regulator: tps650...
174
175
176
177
  	.enable		= tps65090_fet_enable,
  	.disable	= regulator_disable_regmap,
  	.is_enabled	= regulator_is_enabled_regmap,
  };
7d844ac3b   Rikard Falkeborn   regulator: tps650...
178
  static const struct regulator_ops tps65090_ldo_ops = {
3a81ef8c2   Laxman Dewangan   regulator: tps650...
179
  };
4f2352cf5   Javier Martinez Canillas   regulator: tps650...
180
  #define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _nvolt, _volt, _ops) \
452534e50   Venu Byravarasu   regulator: Add TP...
181
  {							\
24282a1ca   Laxman Dewangan   regulator: tps650...
182
183
  	.name = "TPS65090_RAILS"#_id,			\
  	.supply_name = _sname,				\
8620ca9f7   Laxman Dewangan   regulator: tps650...
184
  	.id = TPS65090_REGULATOR_##_id,			\
4f2352cf5   Javier Martinez Canillas   regulator: tps650...
185
  	.n_voltages = _nvolt,				\
24282a1ca   Laxman Dewangan   regulator: tps650...
186
  	.ops = &_ops,					\
4f2352cf5   Javier Martinez Canillas   regulator: tps650...
187
  	.fixed_uV = _volt,				\
24282a1ca   Laxman Dewangan   regulator: tps650...
188
  	.enable_reg = _en_reg,				\
ed11f1ead   Doug Anderson   regulator: tps650...
189
190
  	.enable_val = _en_bits,				\
  	.enable_mask = _en_bits,			\
24282a1ca   Laxman Dewangan   regulator: tps650...
191
192
  	.type = REGULATOR_VOLTAGE,			\
  	.owner = THIS_MODULE,				\
452534e50   Venu Byravarasu   regulator: Add TP...
193
  }
4f2352cf5   Javier Martinez Canillas   regulator: tps650...
194
195
196
197
198
  #define tps65090_REG_FIXEDV(_id, _sname, en_reg, _en_bits, _volt, _ops) \
  	tps65090_REG_DESC(_id, _sname, en_reg, _en_bits, 1, _volt, _ops)
  
  #define tps65090_REG_SWITCH(_id, _sname, en_reg, _en_bits, _ops) \
  	tps65090_REG_DESC(_id, _sname, en_reg, _en_bits, 0, 0, _ops)
24282a1ca   Laxman Dewangan   regulator: tps650...
199
  static struct regulator_desc tps65090_regulator_desc[] = {
4f2352cf5   Javier Martinez Canillas   regulator: tps650...
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
  	tps65090_REG_FIXEDV(DCDC1, "vsys1",   0x0C, BIT(CTRL_EN_BIT), 5000000,
  			    tps65090_reg_control_ops),
  	tps65090_REG_FIXEDV(DCDC2, "vsys2",   0x0D, BIT(CTRL_EN_BIT), 3300000,
  			    tps65090_reg_control_ops),
  	tps65090_REG_SWITCH(DCDC3, "vsys3",   0x0E, BIT(CTRL_EN_BIT),
  			    tps65090_reg_control_ops),
  
  	tps65090_REG_SWITCH(FET1,  "infet1",  0x0F,
  			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
  			    tps65090_fet_control_ops),
  	tps65090_REG_SWITCH(FET2,  "infet2",  0x10,
  			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
  			    tps65090_fet_control_ops),
  	tps65090_REG_SWITCH(FET3,  "infet3",  0x11,
  			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
  			    tps65090_fet_control_ops),
  	tps65090_REG_SWITCH(FET4,  "infet4",  0x12,
  			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
  			    tps65090_fet_control_ops),
  	tps65090_REG_SWITCH(FET5,  "infet5",  0x13,
  			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
  			    tps65090_fet_control_ops),
  	tps65090_REG_SWITCH(FET6,  "infet6",  0x14,
  			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
  			    tps65090_fet_control_ops),
  	tps65090_REG_SWITCH(FET7,  "infet7",  0x15,
  			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
  			    tps65090_fet_control_ops),
  
  	tps65090_REG_FIXEDV(LDO1,  "vsys-l1", 0, 0, 5000000,
  			    tps65090_ldo_ops),
  	tps65090_REG_FIXEDV(LDO2,  "vsys-l2", 0, 0, 3300000,
  			    tps65090_ldo_ops),
452534e50   Venu Byravarasu   regulator: Add TP...
233
  };
24282a1ca   Laxman Dewangan   regulator: tps650...
234
  static inline bool is_dcdc(int id)
452534e50   Venu Byravarasu   regulator: Add TP...
235
  {
24282a1ca   Laxman Dewangan   regulator: tps650...
236
  	switch (id) {
8620ca9f7   Laxman Dewangan   regulator: tps650...
237
238
239
  	case TPS65090_REGULATOR_DCDC1:
  	case TPS65090_REGULATOR_DCDC2:
  	case TPS65090_REGULATOR_DCDC3:
24282a1ca   Laxman Dewangan   regulator: tps650...
240
241
242
243
244
  		return true;
  	default:
  		return false;
  	}
  }
452534e50   Venu Byravarasu   regulator: Add TP...
245

a5023574d   Bill Pemberton   regulator: remove...
246
  static int tps65090_config_ext_control(
24282a1ca   Laxman Dewangan   regulator: tps650...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  	struct tps65090_regulator *ri, bool enable)
  {
  	int ret;
  	struct device *parent = ri->dev->parent;
  	unsigned int reg_en_reg = ri->desc->enable_reg;
  
  	if (enable)
  		ret = tps65090_set_bits(parent, reg_en_reg, 1);
  	else
  		ret =  tps65090_clr_bits(parent, reg_en_reg, 1);
  	if (ret < 0)
  		dev_err(ri->dev, "Error in updating reg 0x%x
  ", reg_en_reg);
  	return ret;
  }
a5023574d   Bill Pemberton   regulator: remove...
262
  static int tps65090_regulator_disable_ext_control(
24282a1ca   Laxman Dewangan   regulator: tps650...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  		struct tps65090_regulator *ri,
  		struct tps65090_regulator_plat_data *tps_pdata)
  {
  	int ret = 0;
  	struct device *parent = ri->dev->parent;
  	unsigned int reg_en_reg = ri->desc->enable_reg;
  
  	/*
  	 * First enable output for internal control if require.
  	 * And then disable external control.
  	 */
  	if (tps_pdata->reg_init_data->constraints.always_on ||
  			tps_pdata->reg_init_data->constraints.boot_on) {
  		ret =  tps65090_set_bits(parent, reg_en_reg, 0);
  		if (ret < 0) {
  			dev_err(ri->dev, "Error in set reg 0x%x
  ", reg_en_reg);
  			return ret;
  		}
452534e50   Venu Byravarasu   regulator: Add TP...
282
  	}
24282a1ca   Laxman Dewangan   regulator: tps650...
283
  	return tps65090_config_ext_control(ri, false);
452534e50   Venu Byravarasu   regulator: Add TP...
284
  }
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
  #ifdef CONFIG_OF
  static struct of_regulator_match tps65090_matches[] = {
  	{ .name = "dcdc1", },
  	{ .name = "dcdc2", },
  	{ .name = "dcdc3", },
  	{ .name = "fet1",  },
  	{ .name = "fet2",  },
  	{ .name = "fet3",  },
  	{ .name = "fet4",  },
  	{ .name = "fet5",  },
  	{ .name = "fet6",  },
  	{ .name = "fet7",  },
  	{ .name = "ldo1",  },
  	{ .name = "ldo2",  },
  };
  
  static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
  		struct platform_device *pdev,
  		struct of_regulator_match **tps65090_reg_matches)
  {
  	struct tps65090_platform_data *tps65090_pdata;
  	struct device_node *np = pdev->dev.parent->of_node;
  	struct device_node *regulators;
  	int idx = 0, ret;
  	struct tps65090_regulator_plat_data *reg_pdata;
  
  	tps65090_pdata = devm_kzalloc(&pdev->dev, sizeof(*tps65090_pdata),
  				GFP_KERNEL);
0ad91c69a   Sachin Kamat   regulator: tps650...
313
  	if (!tps65090_pdata)
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
314
  		return ERR_PTR(-ENOMEM);
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
315

a86854d0c   Kees Cook   treewide: devm_kz...
316
317
318
  	reg_pdata = devm_kcalloc(&pdev->dev,
  				 TPS65090_REGULATOR_MAX, sizeof(*reg_pdata),
  				 GFP_KERNEL);
0ad91c69a   Sachin Kamat   regulator: tps650...
319
  	if (!reg_pdata)
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
320
  		return ERR_PTR(-ENOMEM);
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
321

4c850ead9   Laxman Dewangan   regulator: tps650...
322
  	regulators = of_get_child_by_name(np, "regulators");
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
323
324
325
326
327
  	if (!regulators) {
  		dev_err(&pdev->dev, "regulator node not found
  ");
  		return ERR_PTR(-ENODEV);
  	}
09a228e70   Axel Lin   regulator: tps650...
328
  	ret = of_regulator_match(&pdev->dev, regulators, tps65090_matches,
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
329
  			ARRAY_SIZE(tps65090_matches));
026cdfe6f   Sachin Kamat   regulator: tps650...
330
  	of_node_put(regulators);
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
331
332
333
334
335
336
337
338
339
340
341
  	if (ret < 0) {
  		dev_err(&pdev->dev,
  			"Error parsing regulator init data: %d
  ", ret);
  		return ERR_PTR(ret);
  	}
  
  	*tps65090_reg_matches = tps65090_matches;
  	for (idx = 0; idx < ARRAY_SIZE(tps65090_matches); idx++) {
  		struct regulator_init_data *ri_data;
  		struct tps65090_regulator_plat_data *rpdata;
51d98ff86   Dmitry Torokhov   regulator: tps650...
342
  		struct device_node *np;
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
343
344
345
  
  		rpdata = &reg_pdata[idx];
  		ri_data = tps65090_matches[idx].init_data;
51d98ff86   Dmitry Torokhov   regulator: tps650...
346
347
348
349
350
  		if (!ri_data)
  			continue;
  
  		np = tps65090_matches[idx].of_node;
  		if (!np)
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
351
352
353
  			continue;
  
  		rpdata->reg_init_data = ri_data;
51d98ff86   Dmitry Torokhov   regulator: tps650...
354
355
  		rpdata->enable_ext_control = of_property_read_bool(np,
  						"ti,enable-ext-control");
3012e8144   Linus Walleij   regulator: tps650...
356
357
358
359
360
361
362
363
  		if (rpdata->enable_ext_control) {
  			enum gpiod_flags gflags;
  
  			if (ri_data->constraints.always_on ||
  			    ri_data->constraints.boot_on)
  				gflags = GPIOD_OUT_HIGH;
  			else
  				gflags = GPIOD_OUT_LOW;
63239e4bf   Linus Walleij   regulator: Fetch ...
364
  			gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
3012e8144   Linus Walleij   regulator: tps650...
365

51d98ff86   Dmitry Torokhov   regulator: tps650...
366
367
368
369
370
371
  			rpdata->gpiod = devm_fwnode_gpiod_get(
  							&pdev->dev,
  							of_fwnode_handle(np),
  							"dcdc-ext-control",
  							gflags,
  							"tps65090");
025bf3772   Waibel Georg   gpio: Fix return ...
372
  			if (PTR_ERR(rpdata->gpiod) == -ENOENT) {
3012e8144   Linus Walleij   regulator: tps650...
373
374
375
  				dev_err(&pdev->dev,
  					"could not find DCDC external control GPIO
  ");
025bf3772   Waibel Georg   gpio: Fix return ...
376
377
378
  				rpdata->gpiod = NULL;
  			} else if (IS_ERR(rpdata->gpiod))
  				return ERR_CAST(rpdata->gpiod);
3012e8144   Linus Walleij   regulator: tps650...
379
  		}
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
380

51d98ff86   Dmitry Torokhov   regulator: tps650...
381
  		if (of_property_read_u32(np, "ti,overcurrent-wait",
290414499   Doug Anderson   regulator: tps650...
382
383
  					 &rpdata->overcurrent_wait) == 0)
  			rpdata->overcurrent_wait_valid = true;
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
384
385
386
387
388
389
390
391
392
393
394
395
396
  		tps65090_pdata->reg_pdata[idx] = rpdata;
  	}
  	return tps65090_pdata;
  }
  #else
  static inline struct tps65090_platform_data *tps65090_parse_dt_reg_data(
  			struct platform_device *pdev,
  			struct of_regulator_match **tps65090_reg_matches)
  {
  	*tps65090_reg_matches = NULL;
  	return NULL;
  }
  #endif
a5023574d   Bill Pemberton   regulator: remove...
397
  static int tps65090_regulator_probe(struct platform_device *pdev)
452534e50   Venu Byravarasu   regulator: Add TP...
398
  {
06c4998be   Axel Lin   regulator: tps650...
399
  	struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
452534e50   Venu Byravarasu   regulator: Add TP...
400
  	struct tps65090_regulator *ri = NULL;
c172708d3   Mark Brown   regulator: core: ...
401
  	struct regulator_config config = { };
452534e50   Venu Byravarasu   regulator: Add TP...
402
  	struct regulator_dev *rdev;
24282a1ca   Laxman Dewangan   regulator: tps650...
403
404
405
  	struct tps65090_regulator_plat_data *tps_pdata;
  	struct tps65090_regulator *pmic;
  	struct tps65090_platform_data *tps65090_pdata;
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
406
  	struct of_regulator_match *tps65090_reg_matches = NULL;
24282a1ca   Laxman Dewangan   regulator: tps650...
407
408
  	int num;
  	int ret;
452534e50   Venu Byravarasu   regulator: Add TP...
409

24282a1ca   Laxman Dewangan   regulator: tps650...
410
411
  	dev_dbg(&pdev->dev, "Probing regulator
  ");
452534e50   Venu Byravarasu   regulator: Add TP...
412

24282a1ca   Laxman Dewangan   regulator: tps650...
413
  	tps65090_pdata = dev_get_platdata(pdev->dev.parent);
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
414
415
416
417
  	if (!tps65090_pdata && tps65090_mfd->dev->of_node)
  		tps65090_pdata = tps65090_parse_dt_reg_data(pdev,
  					&tps65090_reg_matches);
  	if (IS_ERR_OR_NULL(tps65090_pdata)) {
24282a1ca   Laxman Dewangan   regulator: tps650...
418
419
  		dev_err(&pdev->dev, "Platform data missing
  ");
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
420
  		return tps65090_pdata ? PTR_ERR(tps65090_pdata) : -EINVAL;
452534e50   Venu Byravarasu   regulator: Add TP...
421
  	}
24282a1ca   Laxman Dewangan   regulator: tps650...
422

a86854d0c   Kees Cook   treewide: devm_kz...
423
424
425
  	pmic = devm_kcalloc(&pdev->dev,
  			    TPS65090_REGULATOR_MAX, sizeof(*pmic),
  			    GFP_KERNEL);
0ad91c69a   Sachin Kamat   regulator: tps650...
426
  	if (!pmic)
24282a1ca   Laxman Dewangan   regulator: tps650...
427
  		return -ENOMEM;
24282a1ca   Laxman Dewangan   regulator: tps650...
428

8620ca9f7   Laxman Dewangan   regulator: tps650...
429
  	for (num = 0; num < TPS65090_REGULATOR_MAX; num++) {
24282a1ca   Laxman Dewangan   regulator: tps650...
430
431
432
433
434
  		tps_pdata = tps65090_pdata->reg_pdata[num];
  
  		ri = &pmic[num];
  		ri->dev = &pdev->dev;
  		ri->desc = &tps65090_regulator_desc[num];
c122c5b68   Doug Anderson   regulator: tps650...
435
436
437
438
439
  		if (tps_pdata) {
  			ri->overcurrent_wait_valid =
  				tps_pdata->overcurrent_wait_valid;
  			ri->overcurrent_wait = tps_pdata->overcurrent_wait;
  		}
24282a1ca   Laxman Dewangan   regulator: tps650...
440
441
442
  
  		/*
  		 * TPS5090 DCDC support the control from external digital input.
f329b1755   Laxman Dewangan   regulator: tps650...
443
  		 * Configure it as per platform data.
24282a1ca   Laxman Dewangan   regulator: tps650...
444
445
  		 */
  		if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
f329b1755   Laxman Dewangan   regulator: tps650...
446
  			if (tps_pdata->enable_ext_control) {
3012e8144   Linus Walleij   regulator: tps650...
447
  				config.ena_gpiod = tps_pdata->gpiod;
f329b1755   Laxman Dewangan   regulator: tps650...
448
449
450
  				ri->desc->ops = &tps65090_ext_control_ops;
  			} else {
  				ret = tps65090_regulator_disable_ext_control(
24282a1ca   Laxman Dewangan   regulator: tps650...
451
  						ri, tps_pdata);
f329b1755   Laxman Dewangan   regulator: tps650...
452
453
  				if (ret < 0) {
  					dev_err(&pdev->dev,
24282a1ca   Laxman Dewangan   regulator: tps650...
454
455
  						"failed disable ext control
  ");
9738efae6   Sachin Kamat   regulator: tps650...
456
  					return ret;
f329b1755   Laxman Dewangan   regulator: tps650...
457
  				}
24282a1ca   Laxman Dewangan   regulator: tps650...
458
459
  			}
  		}
f329b1755   Laxman Dewangan   regulator: tps650...
460

6c7a7a0e3   Laxman Dewangan   regulator: tps650...
461
  		config.dev = pdev->dev.parent;
24282a1ca   Laxman Dewangan   regulator: tps650...
462
463
464
465
466
467
  		config.driver_data = ri;
  		config.regmap = tps65090_mfd->rmap;
  		if (tps_pdata)
  			config.init_data = tps_pdata->reg_init_data;
  		else
  			config.init_data = NULL;
6c7a7a0e3   Laxman Dewangan   regulator: tps650...
468
469
470
471
  		if (tps65090_reg_matches)
  			config.of_node = tps65090_reg_matches[num].of_node;
  		else
  			config.of_node = NULL;
24282a1ca   Laxman Dewangan   regulator: tps650...
472

870311e52   Linus Walleij   regulator: tps650...
473
474
475
476
477
478
  		/*
  		 * Hand the GPIO descriptor management over to the regulator
  		 * core, remove it from devres management.
  		 */
  		if (config.ena_gpiod)
  			devm_gpiod_unhinge(&pdev->dev, config.ena_gpiod);
9738efae6   Sachin Kamat   regulator: tps650...
479
  		rdev = devm_regulator_register(&pdev->dev, ri->desc, &config);
24282a1ca   Laxman Dewangan   regulator: tps650...
480
481
482
483
  		if (IS_ERR(rdev)) {
  			dev_err(&pdev->dev, "failed to register regulator %s
  ",
  				ri->desc->name);
9738efae6   Sachin Kamat   regulator: tps650...
484
  			return PTR_ERR(rdev);
24282a1ca   Laxman Dewangan   regulator: tps650...
485
486
  		}
  		ri->rdev = rdev;
f329b1755   Laxman Dewangan   regulator: tps650...
487

290414499   Doug Anderson   regulator: tps650...
488
489
490
491
492
  		if (ri->overcurrent_wait_valid) {
  			ret = tps65090_reg_set_overcurrent_wait(ri, rdev);
  			if (ret < 0)
  				return ret;
  		}
f329b1755   Laxman Dewangan   regulator: tps650...
493
494
495
496
  		/* Enable external control if it is require */
  		if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
  				tps_pdata->enable_ext_control) {
  			ret = tps65090_config_ext_control(ri, true);
9738efae6   Sachin Kamat   regulator: tps650...
497
498
  			if (ret < 0)
  				return ret;
f329b1755   Laxman Dewangan   regulator: tps650...
499
  		}
452534e50   Venu Byravarasu   regulator: Add TP...
500
  	}
24282a1ca   Laxman Dewangan   regulator: tps650...
501
  	platform_set_drvdata(pdev, pmic);
452534e50   Venu Byravarasu   regulator: Add TP...
502
  	return 0;
452534e50   Venu Byravarasu   regulator: Add TP...
503
504
505
506
  }
  
  static struct platform_driver tps65090_regulator_driver = {
  	.driver	= {
8620ca9f7   Laxman Dewangan   regulator: tps650...
507
  		.name	= "tps65090-pmic",
452534e50   Venu Byravarasu   regulator: Add TP...
508
509
  	},
  	.probe		= tps65090_regulator_probe,
452534e50   Venu Byravarasu   regulator: Add TP...
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
  };
  
  static int __init tps65090_regulator_init(void)
  {
  	return platform_driver_register(&tps65090_regulator_driver);
  }
  subsys_initcall(tps65090_regulator_init);
  
  static void __exit tps65090_regulator_exit(void)
  {
  	platform_driver_unregister(&tps65090_regulator_driver);
  }
  module_exit(tps65090_regulator_exit);
  
  MODULE_DESCRIPTION("tps65090 regulator driver");
  MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
  MODULE_LICENSE("GPL v2");
d95420b86   Axel Lin   regulator: tps650...
527
  MODULE_ALIAS("platform:tps65090-pmic");