Blame view

drivers/regulator/fan53555.c 13.4 KB
6a1beee2f   Axel Lin   regulator: fan535...
1
2
3
4
5
6
7
8
9
  // SPDX-License-Identifier: GPL-2.0
  //
  // FAN53555 Fairchild Digitally Programmable TinyBuck Regulator Driver.
  //
  // Supported Part Numbers:
  // FAN53555UC00X/01X/03X/04X/05X
  //
  // Copyright (c) 2012 Marvell Technology Ltd.
  // Yunfan Zhang <yfzhang@marvell.com>
49d8c5992   Yunfan Zhang   regulator: Fairch...
10
11
12
13
14
15
  #include <linux/module.h>
  #include <linux/param.h>
  #include <linux/err.h>
  #include <linux/platform_device.h>
  #include <linux/regulator/driver.h>
  #include <linux/regulator/machine.h>
91f23d8fb   Heiko Stuebner   regulator: fan535...
16
17
  #include <linux/regulator/of_regulator.h>
  #include <linux/of_device.h>
49d8c5992   Yunfan Zhang   regulator: Fairch...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  #include <linux/i2c.h>
  #include <linux/slab.h>
  #include <linux/regmap.h>
  #include <linux/regulator/fan53555.h>
  
  /* Voltage setting */
  #define FAN53555_VSEL0		0x00
  #define FAN53555_VSEL1		0x01
  /* Control register */
  #define FAN53555_CONTROL	0x02
  /* IC Type */
  #define FAN53555_ID1		0x03
  /* IC mask version */
  #define FAN53555_ID2		0x04
  /* Monitor register */
  #define FAN53555_MONITOR	0x05
  
  /* VSEL bit definitions */
  #define VSEL_BUCK_EN	(1 << 7)
  #define VSEL_MODE		(1 << 6)
49d8c5992   Yunfan Zhang   regulator: Fairch...
38
39
40
41
42
43
44
45
  /* Chip ID and Verison */
  #define DIE_ID		0x0F	/* ID1 */
  #define DIE_REV		0x0F	/* ID2 */
  /* Control bit definitions */
  #define CTL_OUTPUT_DISCHG	(1 << 7)
  #define CTL_SLEW_MASK		(0x7 << 4)
  #define CTL_SLEW_SHIFT		4
  #define CTL_RESET			(1 << 2)
f2a9eb975   Bjorn Andersson   regulator: fan535...
46
47
  #define CTL_MODE_VSEL0_MODE	BIT(0)
  #define CTL_MODE_VSEL1_MODE	BIT(1)
49d8c5992   Yunfan Zhang   regulator: Fairch...
48
49
  
  #define FAN53555_NVOLTAGES	64	/* Numbers of voltages */
f2a9eb975   Bjorn Andersson   regulator: fan535...
50
  #define FAN53526_NVOLTAGES	128
49d8c5992   Yunfan Zhang   regulator: Fairch...
51

ee30928ab   Heiko Stuebner   regulator: fan535...
52
  enum fan53555_vendor {
f2a9eb975   Bjorn Andersson   regulator: fan535...
53
54
  	FAN53526_VENDOR_FAIRCHILD = 0,
  	FAN53555_VENDOR_FAIRCHILD,
ee30928ab   Heiko Stuebner   regulator: fan535...
55
56
  	FAN53555_VENDOR_SILERGY,
  };
f2a9eb975   Bjorn Andersson   regulator: fan535...
57
58
59
60
61
62
63
  enum {
  	FAN53526_CHIP_ID_01 = 1,
  };
  
  enum {
  	FAN53526_CHIP_REV_08 = 8,
  };
49d8c5992   Yunfan Zhang   regulator: Fairch...
64
65
66
67
68
69
70
71
  /* IC Type */
  enum {
  	FAN53555_CHIP_ID_00 = 0,
  	FAN53555_CHIP_ID_01,
  	FAN53555_CHIP_ID_02,
  	FAN53555_CHIP_ID_03,
  	FAN53555_CHIP_ID_04,
  	FAN53555_CHIP_ID_05,
5e39cf497   Wadim Egorov   regulator: fan535...
72
  	FAN53555_CHIP_ID_08 = 8,
49d8c5992   Yunfan Zhang   regulator: Fairch...
73
  };
e57cbb70b   Wadim Egorov   regulator: fan535...
74
75
76
77
78
  /* IC mask revision */
  enum {
  	FAN53555_CHIP_REV_00 = 0x3,
  	FAN53555_CHIP_REV_13 = 0xf,
  };
ee30928ab   Heiko Stuebner   regulator: fan535...
79
80
  enum {
  	SILERGY_SYR82X = 8,
5365e3df4   Vasily Khoruzhick   regulator: fan535...
81
  	SILERGY_SYR83X = 9,
ee30928ab   Heiko Stuebner   regulator: fan535...
82
  };
49d8c5992   Yunfan Zhang   regulator: Fairch...
83
  struct fan53555_device_info {
ee30928ab   Heiko Stuebner   regulator: fan535...
84
  	enum fan53555_vendor vendor;
49d8c5992   Yunfan Zhang   regulator: Fairch...
85
86
  	struct device *dev;
  	struct regulator_desc desc;
49d8c5992   Yunfan Zhang   regulator: Fairch...
87
88
89
90
91
92
93
94
95
  	struct regulator_init_data *regulator;
  	/* IC Type and Rev */
  	int chip_id;
  	int chip_rev;
  	/* Voltage setting register */
  	unsigned int vol_reg;
  	unsigned int sleep_reg;
  	/* Voltage range and step(linear) */
  	unsigned int vsel_min;
49d8c5992   Yunfan Zhang   regulator: Fairch...
96
  	unsigned int vsel_step;
f2a9eb975   Bjorn Andersson   regulator: fan535...
97
  	unsigned int vsel_count;
f2a9eb975   Bjorn Andersson   regulator: fan535...
98
99
100
  	/* Mode */
  	unsigned int mode_reg;
  	unsigned int mode_mask;
49d8c5992   Yunfan Zhang   regulator: Fairch...
101
102
103
104
105
106
107
108
109
110
111
112
113
  	/* Sleep voltage cache */
  	unsigned int sleep_vol_cache;
  };
  
  static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
  {
  	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
  	int ret;
  
  	if (di->sleep_vol_cache == uV)
  		return 0;
  	ret = regulator_map_voltage_linear(rdev, uV, uV);
  	if (ret < 0)
145fe1e1d   Sachin Kamat   regulator: fan535...
114
  		return ret;
a69929c7a   Axel Lin   regulator: fan535...
115
  	ret = regmap_update_bits(rdev->regmap, di->sleep_reg,
f2a9eb975   Bjorn Andersson   regulator: fan535...
116
  				 di->desc.vsel_mask, ret);
49d8c5992   Yunfan Zhang   regulator: Fairch...
117
  	if (ret < 0)
145fe1e1d   Sachin Kamat   regulator: fan535...
118
  		return ret;
49d8c5992   Yunfan Zhang   regulator: Fairch...
119
120
121
122
123
124
  	/* Cache the sleep voltage setting.
  	 * Might not be the real voltage which is rounded */
  	di->sleep_vol_cache = uV;
  
  	return 0;
  }
ab7cad331   zhangqing   regulator: fan535...
125
126
127
  static int fan53555_set_suspend_enable(struct regulator_dev *rdev)
  {
  	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
a69929c7a   Axel Lin   regulator: fan535...
128
  	return regmap_update_bits(rdev->regmap, di->sleep_reg,
ab7cad331   zhangqing   regulator: fan535...
129
130
131
132
133
134
  				  VSEL_BUCK_EN, VSEL_BUCK_EN);
  }
  
  static int fan53555_set_suspend_disable(struct regulator_dev *rdev)
  {
  	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
a69929c7a   Axel Lin   regulator: fan535...
135
  	return regmap_update_bits(rdev->regmap, di->sleep_reg,
ab7cad331   zhangqing   regulator: fan535...
136
137
  				  VSEL_BUCK_EN, 0);
  }
49d8c5992   Yunfan Zhang   regulator: Fairch...
138
139
140
141
142
143
  static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
  {
  	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
  
  	switch (mode) {
  	case REGULATOR_MODE_FAST:
a69929c7a   Axel Lin   regulator: fan535...
144
  		regmap_update_bits(rdev->regmap, di->mode_reg,
f2a9eb975   Bjorn Andersson   regulator: fan535...
145
  				   di->mode_mask, di->mode_mask);
49d8c5992   Yunfan Zhang   regulator: Fairch...
146
147
  		break;
  	case REGULATOR_MODE_NORMAL:
a69929c7a   Axel Lin   regulator: fan535...
148
  		regmap_update_bits(rdev->regmap, di->vol_reg, di->mode_mask, 0);
49d8c5992   Yunfan Zhang   regulator: Fairch...
149
150
151
152
153
154
155
156
157
158
159
160
  		break;
  	default:
  		return -EINVAL;
  	}
  	return 0;
  }
  
  static unsigned int fan53555_get_mode(struct regulator_dev *rdev)
  {
  	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
  	unsigned int val;
  	int ret = 0;
a69929c7a   Axel Lin   regulator: fan535...
161
  	ret = regmap_read(rdev->regmap, di->mode_reg, &val);
49d8c5992   Yunfan Zhang   regulator: Fairch...
162
163
  	if (ret < 0)
  		return ret;
f2a9eb975   Bjorn Andersson   regulator: fan535...
164
  	if (val & di->mode_mask)
49d8c5992   Yunfan Zhang   regulator: Fairch...
165
166
167
168
  		return REGULATOR_MODE_FAST;
  	else
  		return REGULATOR_MODE_NORMAL;
  }
121b567d8   Krzysztof Kozlowski   regulator: fan535...
169
  static const int slew_rates[] = {
dd7e71fbe   Heiko Stuebner   regulator: fan535...
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
  	64000,
  	32000,
  	16000,
  	 8000,
  	 4000,
  	 2000,
  	 1000,
  	  500,
  };
  
  static int fan53555_set_ramp(struct regulator_dev *rdev, int ramp)
  {
  	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
  	int regval = -1, i;
  
  	for (i = 0; i < ARRAY_SIZE(slew_rates); i++) {
  		if (ramp <= slew_rates[i])
  			regval = i;
  		else
  			break;
  	}
  
  	if (regval < 0) {
  		dev_err(di->dev, "unsupported ramp value %d
  ", ramp);
  		return -EINVAL;
  	}
a69929c7a   Axel Lin   regulator: fan535...
197
  	return regmap_update_bits(rdev->regmap, FAN53555_CONTROL,
dd7e71fbe   Heiko Stuebner   regulator: fan535...
198
199
  				  CTL_SLEW_MASK, regval << CTL_SLEW_SHIFT);
  }
71880ab24   Bhumika Goyal   regulator: fan535...
200
  static const struct regulator_ops fan53555_regulator_ops = {
49d8c5992   Yunfan Zhang   regulator: Fairch...
201
202
  	.set_voltage_sel = regulator_set_voltage_sel_regmap,
  	.get_voltage_sel = regulator_get_voltage_sel_regmap,
fda87a428   Heiko Stuebner   regulator: fan535...
203
  	.set_voltage_time_sel = regulator_set_voltage_time_sel,
49d8c5992   Yunfan Zhang   regulator: Fairch...
204
205
206
207
208
209
210
211
  	.map_voltage = regulator_map_voltage_linear,
  	.list_voltage = regulator_list_voltage_linear,
  	.set_suspend_voltage = fan53555_set_suspend_voltage,
  	.enable = regulator_enable_regmap,
  	.disable = regulator_disable_regmap,
  	.is_enabled = regulator_is_enabled_regmap,
  	.set_mode = fan53555_set_mode,
  	.get_mode = fan53555_get_mode,
dd7e71fbe   Heiko Stuebner   regulator: fan535...
212
  	.set_ramp_delay = fan53555_set_ramp,
ab7cad331   zhangqing   regulator: fan535...
213
214
  	.set_suspend_enable = fan53555_set_suspend_enable,
  	.set_suspend_disable = fan53555_set_suspend_disable,
49d8c5992   Yunfan Zhang   regulator: Fairch...
215
  };
f2a9eb975   Bjorn Andersson   regulator: fan535...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  static int fan53526_voltages_setup_fairchild(struct fan53555_device_info *di)
  {
  	/* Init voltage range and step */
  	switch (di->chip_id) {
  	case FAN53526_CHIP_ID_01:
  		switch (di->chip_rev) {
  		case FAN53526_CHIP_REV_08:
  			di->vsel_min = 600000;
  			di->vsel_step = 6250;
  			break;
  		default:
  			dev_err(di->dev,
  				"Chip ID %d with rev %d not supported!
  ",
  				di->chip_id, di->chip_rev);
  			return -EINVAL;
  		}
  		break;
  	default:
  		dev_err(di->dev,
  			"Chip ID %d not supported!
  ", di->chip_id);
  		return -EINVAL;
  	}
  
  	di->vsel_count = FAN53526_NVOLTAGES;
  
  	return 0;
  }
ee30928ab   Heiko Stuebner   regulator: fan535...
245
246
247
248
249
  static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di)
  {
  	/* Init voltage range and step */
  	switch (di->chip_id) {
  	case FAN53555_CHIP_ID_00:
e57cbb70b   Wadim Egorov   regulator: fan535...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  		switch (di->chip_rev) {
  		case FAN53555_CHIP_REV_00:
  			di->vsel_min = 600000;
  			di->vsel_step = 10000;
  			break;
  		case FAN53555_CHIP_REV_13:
  			di->vsel_min = 800000;
  			di->vsel_step = 10000;
  			break;
  		default:
  			dev_err(di->dev,
  				"Chip ID %d with rev %d not supported!
  ",
  				di->chip_id, di->chip_rev);
  			return -EINVAL;
  		}
  		break;
ee30928ab   Heiko Stuebner   regulator: fan535...
267
268
269
  	case FAN53555_CHIP_ID_01:
  	case FAN53555_CHIP_ID_03:
  	case FAN53555_CHIP_ID_05:
5e39cf497   Wadim Egorov   regulator: fan535...
270
  	case FAN53555_CHIP_ID_08:
ee30928ab   Heiko Stuebner   regulator: fan535...
271
272
273
274
275
276
277
278
279
280
281
282
283
  		di->vsel_min = 600000;
  		di->vsel_step = 10000;
  		break;
  	case FAN53555_CHIP_ID_04:
  		di->vsel_min = 603000;
  		di->vsel_step = 12826;
  		break;
  	default:
  		dev_err(di->dev,
  			"Chip ID %d not supported!
  ", di->chip_id);
  		return -EINVAL;
  	}
f2a9eb975   Bjorn Andersson   regulator: fan535...
284
  	di->vsel_count = FAN53555_NVOLTAGES;
ee30928ab   Heiko Stuebner   regulator: fan535...
285
286
287
288
289
290
291
292
  	return 0;
  }
  
  static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di)
  {
  	/* Init voltage range and step */
  	switch (di->chip_id) {
  	case SILERGY_SYR82X:
5365e3df4   Vasily Khoruzhick   regulator: fan535...
293
  	case SILERGY_SYR83X:
ee30928ab   Heiko Stuebner   regulator: fan535...
294
295
296
297
298
299
300
301
302
  		di->vsel_min = 712500;
  		di->vsel_step = 12500;
  		break;
  	default:
  		dev_err(di->dev,
  			"Chip ID %d not supported!
  ", di->chip_id);
  		return -EINVAL;
  	}
f2a9eb975   Bjorn Andersson   regulator: fan535...
303
  	di->vsel_count = FAN53555_NVOLTAGES;
ee30928ab   Heiko Stuebner   regulator: fan535...
304
305
  	return 0;
  }
49d8c5992   Yunfan Zhang   regulator: Fairch...
306
307
308
309
310
311
312
313
  /* For 00,01,03,05 options:
   * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V.
   * For 04 option:
   * VOUT = 0.603V + NSELx * 12.826mV, from 0.603 to 1.411V.
   * */
  static int fan53555_device_setup(struct fan53555_device_info *di,
  				struct fan53555_platform_data *pdata)
  {
ee30928ab   Heiko Stuebner   regulator: fan535...
314
  	int ret = 0;
49d8c5992   Yunfan Zhang   regulator: Fairch...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  	/* Setup voltage control register */
  	switch (pdata->sleep_vsel_id) {
  	case FAN53555_VSEL_ID_0:
  		di->sleep_reg = FAN53555_VSEL0;
  		di->vol_reg = FAN53555_VSEL1;
  		break;
  	case FAN53555_VSEL_ID_1:
  		di->sleep_reg = FAN53555_VSEL1;
  		di->vol_reg = FAN53555_VSEL0;
  		break;
  	default:
  		dev_err(di->dev, "Invalid VSEL ID!
  ");
  		return -EINVAL;
  	}
ee30928ab   Heiko Stuebner   regulator: fan535...
330

f2a9eb975   Bjorn Andersson   regulator: fan535...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  	/* Setup mode control register */
  	switch (di->vendor) {
  	case FAN53526_VENDOR_FAIRCHILD:
  		di->mode_reg = FAN53555_CONTROL;
  
  		switch (pdata->sleep_vsel_id) {
  		case FAN53555_VSEL_ID_0:
  			di->mode_mask = CTL_MODE_VSEL1_MODE;
  			break;
  		case FAN53555_VSEL_ID_1:
  			di->mode_mask = CTL_MODE_VSEL0_MODE;
  			break;
  		}
  		break;
  	case FAN53555_VENDOR_FAIRCHILD:
  	case FAN53555_VENDOR_SILERGY:
  		di->mode_reg = di->vol_reg;
  		di->mode_mask = VSEL_MODE;
  		break;
  	default:
  		dev_err(di->dev, "vendor %d not supported!
  ", di->vendor);
  		return -EINVAL;
  	}
  
  	/* Setup voltage range */
ee30928ab   Heiko Stuebner   regulator: fan535...
357
  	switch (di->vendor) {
f2a9eb975   Bjorn Andersson   regulator: fan535...
358
359
360
  	case FAN53526_VENDOR_FAIRCHILD:
  		ret = fan53526_voltages_setup_fairchild(di);
  		break;
ee30928ab   Heiko Stuebner   regulator: fan535...
361
362
  	case FAN53555_VENDOR_FAIRCHILD:
  		ret = fan53555_voltages_setup_fairchild(di);
49d8c5992   Yunfan Zhang   regulator: Fairch...
363
  		break;
ee30928ab   Heiko Stuebner   regulator: fan535...
364
365
  	case FAN53555_VENDOR_SILERGY:
  		ret = fan53555_voltages_setup_silergy(di);
49d8c5992   Yunfan Zhang   regulator: Fairch...
366
367
  		break;
  	default:
fe230531b   Axel Lin   regulator: fan535...
368
369
  		dev_err(di->dev, "vendor %d not supported!
  ", di->vendor);
49d8c5992   Yunfan Zhang   regulator: Fairch...
370
371
  		return -EINVAL;
  	}
dd7e71fbe   Heiko Stuebner   regulator: fan535...
372

ee30928ab   Heiko Stuebner   regulator: fan535...
373
  	return ret;
49d8c5992   Yunfan Zhang   regulator: Fairch...
374
375
376
377
378
379
  }
  
  static int fan53555_regulator_register(struct fan53555_device_info *di,
  			struct regulator_config *config)
  {
  	struct regulator_desc *rdesc = &di->desc;
a69929c7a   Axel Lin   regulator: fan535...
380
  	struct regulator_dev *rdev;
49d8c5992   Yunfan Zhang   regulator: Fairch...
381
382
  
  	rdesc->name = "fan53555-reg";
3415d6011   Heiko Stuebner   regulator: fan535...
383
  	rdesc->supply_name = "vin";
49d8c5992   Yunfan Zhang   regulator: Fairch...
384
385
  	rdesc->ops = &fan53555_regulator_ops;
  	rdesc->type = REGULATOR_VOLTAGE;
f2a9eb975   Bjorn Andersson   regulator: fan535...
386
  	rdesc->n_voltages = di->vsel_count;
49d8c5992   Yunfan Zhang   regulator: Fairch...
387
388
389
390
391
  	rdesc->enable_reg = di->vol_reg;
  	rdesc->enable_mask = VSEL_BUCK_EN;
  	rdesc->min_uV = di->vsel_min;
  	rdesc->uV_step = di->vsel_step;
  	rdesc->vsel_reg = di->vol_reg;
f2a9eb975   Bjorn Andersson   regulator: fan535...
392
  	rdesc->vsel_mask = di->vsel_count - 1;
49d8c5992   Yunfan Zhang   regulator: Fairch...
393
  	rdesc->owner = THIS_MODULE;
a69929c7a   Axel Lin   regulator: fan535...
394
395
  	rdev = devm_regulator_register(di->dev, &di->desc, config);
  	return PTR_ERR_OR_ZERO(rdev);
49d8c5992   Yunfan Zhang   regulator: Fairch...
396
  }
121b567d8   Krzysztof Kozlowski   regulator: fan535...
397
  static const struct regmap_config fan53555_regmap_config = {
49d8c5992   Yunfan Zhang   regulator: Fairch...
398
399
400
  	.reg_bits = 8,
  	.val_bits = 8,
  };
91f23d8fb   Heiko Stuebner   regulator: fan535...
401
  static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
072e78b12   Javier Martinez Canillas   regulator: of: Ad...
402
403
  					      struct device_node *np,
  					      const struct regulator_desc *desc)
91f23d8fb   Heiko Stuebner   regulator: fan535...
404
405
406
407
408
409
410
411
  {
  	struct fan53555_platform_data *pdata;
  	int ret;
  	u32 tmp;
  
  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
  	if (!pdata)
  		return NULL;
072e78b12   Javier Martinez Canillas   regulator: of: Ad...
412
  	pdata->regulator = of_get_regulator_init_data(dev, np, desc);
91f23d8fb   Heiko Stuebner   regulator: fan535...
413
414
415
416
417
418
419
420
  
  	ret = of_property_read_u32(np, "fcs,suspend-voltage-selector",
  				   &tmp);
  	if (!ret)
  		pdata->sleep_vsel_id = tmp;
  
  	return pdata;
  }
5e97d7e80   Jisheng Zhang   regulator: fan535...
421
  static const struct of_device_id __maybe_unused fan53555_dt_ids[] = {
91f23d8fb   Heiko Stuebner   regulator: fan535...
422
  	{
f2a9eb975   Bjorn Andersson   regulator: fan535...
423
424
425
  		.compatible = "fcs,fan53526",
  		.data = (void *)FAN53526_VENDOR_FAIRCHILD,
  	}, {
91f23d8fb   Heiko Stuebner   regulator: fan535...
426
  		.compatible = "fcs,fan53555",
ee30928ab   Heiko Stuebner   regulator: fan535...
427
428
429
430
431
432
433
  		.data = (void *)FAN53555_VENDOR_FAIRCHILD
  	}, {
  		.compatible = "silergy,syr827",
  		.data = (void *)FAN53555_VENDOR_SILERGY,
  	}, {
  		.compatible = "silergy,syr828",
  		.data = (void *)FAN53555_VENDOR_SILERGY,
91f23d8fb   Heiko Stuebner   regulator: fan535...
434
435
436
437
  	},
  	{ }
  };
  MODULE_DEVICE_TABLE(of, fan53555_dt_ids);
a5023574d   Bill Pemberton   regulator: remove...
438
  static int fan53555_regulator_probe(struct i2c_client *client,
49d8c5992   Yunfan Zhang   regulator: Fairch...
439
440
  				const struct i2c_device_id *id)
  {
91f23d8fb   Heiko Stuebner   regulator: fan535...
441
  	struct device_node *np = client->dev.of_node;
49d8c5992   Yunfan Zhang   regulator: Fairch...
442
443
444
  	struct fan53555_device_info *di;
  	struct fan53555_platform_data *pdata;
  	struct regulator_config config = { };
a69929c7a   Axel Lin   regulator: fan535...
445
  	struct regmap *regmap;
49d8c5992   Yunfan Zhang   regulator: Fairch...
446
447
  	unsigned int val;
  	int ret;
072e78b12   Javier Martinez Canillas   regulator: of: Ad...
448
449
450
451
  	di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
  					GFP_KERNEL);
  	if (!di)
  		return -ENOMEM;
dff91d0b7   Jingoo Han   regulator: use de...
452
  	pdata = dev_get_platdata(&client->dev);
91f23d8fb   Heiko Stuebner   regulator: fan535...
453
  	if (!pdata)
072e78b12   Javier Martinez Canillas   regulator: of: Ad...
454
  		pdata = fan53555_parse_dt(&client->dev, np, &di->desc);
91f23d8fb   Heiko Stuebner   regulator: fan535...
455

49d8c5992   Yunfan Zhang   regulator: Fairch...
456
457
458
459
460
  	if (!pdata || !pdata->regulator) {
  		dev_err(&client->dev, "Platform data not found!
  ");
  		return -ENODEV;
  	}
e13426bf2   Axel Lin   regulator: fan535...
461
  	di->regulator = pdata->regulator;
ee30928ab   Heiko Stuebner   regulator: fan535...
462
  	if (client->dev.of_node) {
d110e3e92   Jisheng Zhang   regulator: fan535...
463
464
  		di->vendor =
  			(unsigned long)of_device_get_match_data(&client->dev);
ee30928ab   Heiko Stuebner   regulator: fan535...
465
  	} else {
91f23d8fb   Heiko Stuebner   regulator: fan535...
466
467
  		/* if no ramp constraint set, get the pdata ramp_delay */
  		if (!di->regulator->constraints.ramp_delay) {
87919e0cf   Axel Lin   regulator: fan535...
468
469
470
471
472
  			if (pdata->slew_rate >= ARRAY_SIZE(slew_rates)) {
  				dev_err(&client->dev, "Invalid slew_rate
  ");
  				return -EINVAL;
  			}
dd7e71fbe   Heiko Stuebner   regulator: fan535...
473

91f23d8fb   Heiko Stuebner   regulator: fan535...
474
  			di->regulator->constraints.ramp_delay
87919e0cf   Axel Lin   regulator: fan535...
475
  					= slew_rates[pdata->slew_rate];
91f23d8fb   Heiko Stuebner   regulator: fan535...
476
  		}
ee30928ab   Heiko Stuebner   regulator: fan535...
477
478
  
  		di->vendor = id->driver_data;
dd7e71fbe   Heiko Stuebner   regulator: fan535...
479
  	}
a69929c7a   Axel Lin   regulator: fan535...
480
481
  	regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config);
  	if (IS_ERR(regmap)) {
49d8c5992   Yunfan Zhang   regulator: Fairch...
482
483
  		dev_err(&client->dev, "Failed to allocate regmap!
  ");
a69929c7a   Axel Lin   regulator: fan535...
484
  		return PTR_ERR(regmap);
49d8c5992   Yunfan Zhang   regulator: Fairch...
485
486
  	}
  	di->dev = &client->dev;
49d8c5992   Yunfan Zhang   regulator: Fairch...
487
488
  	i2c_set_clientdata(client, di);
  	/* Get chip ID */
a69929c7a   Axel Lin   regulator: fan535...
489
  	ret = regmap_read(regmap, FAN53555_ID1, &val);
49d8c5992   Yunfan Zhang   regulator: Fairch...
490
491
492
  	if (ret < 0) {
  		dev_err(&client->dev, "Failed to get chip ID!
  ");
145fe1e1d   Sachin Kamat   regulator: fan535...
493
  		return ret;
49d8c5992   Yunfan Zhang   regulator: Fairch...
494
495
496
  	}
  	di->chip_id = val & DIE_ID;
  	/* Get chip revision */
a69929c7a   Axel Lin   regulator: fan535...
497
  	ret = regmap_read(regmap, FAN53555_ID2, &val);
49d8c5992   Yunfan Zhang   regulator: Fairch...
498
499
500
  	if (ret < 0) {
  		dev_err(&client->dev, "Failed to get chip Rev!
  ");
145fe1e1d   Sachin Kamat   regulator: fan535...
501
  		return ret;
49d8c5992   Yunfan Zhang   regulator: Fairch...
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
  	}
  	di->chip_rev = val & DIE_REV;
  	dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!
  ",
  				di->chip_id, di->chip_rev);
  	/* Device init */
  	ret = fan53555_device_setup(di, pdata);
  	if (ret < 0) {
  		dev_err(&client->dev, "Failed to setup device!
  ");
  		return ret;
  	}
  	/* Register regulator */
  	config.dev = di->dev;
  	config.init_data = di->regulator;
a69929c7a   Axel Lin   regulator: fan535...
517
  	config.regmap = regmap;
49d8c5992   Yunfan Zhang   regulator: Fairch...
518
  	config.driver_data = di;
91f23d8fb   Heiko Stuebner   regulator: fan535...
519
  	config.of_node = np;
49d8c5992   Yunfan Zhang   regulator: Fairch...
520
521
522
523
524
525
526
  	ret = fan53555_regulator_register(di, &config);
  	if (ret < 0)
  		dev_err(&client->dev, "Failed to register regulator!
  ");
  	return ret;
  
  }
49d8c5992   Yunfan Zhang   regulator: Fairch...
527
  static const struct i2c_device_id fan53555_id[] = {
ee30928ab   Heiko Stuebner   regulator: fan535...
528
  	{
f2a9eb975   Bjorn Andersson   regulator: fan535...
529
530
531
  		.name = "fan53526",
  		.driver_data = FAN53526_VENDOR_FAIRCHILD
  	}, {
ee30928ab   Heiko Stuebner   regulator: fan535...
532
533
534
  		.name = "fan53555",
  		.driver_data = FAN53555_VENDOR_FAIRCHILD
  	}, {
fc1111b88   Guillaume Tucker   regulator: fan535...
535
536
537
538
  		.name = "syr827",
  		.driver_data = FAN53555_VENDOR_SILERGY
  	}, {
  		.name = "syr828",
ee30928ab   Heiko Stuebner   regulator: fan535...
539
540
  		.driver_data = FAN53555_VENDOR_SILERGY
  	},
49d8c5992   Yunfan Zhang   regulator: Fairch...
541
542
  	{ },
  };
e80c47bd7   Javier Martinez Canillas   regulator: fan535...
543
  MODULE_DEVICE_TABLE(i2c, fan53555_id);
49d8c5992   Yunfan Zhang   regulator: Fairch...
544
545
546
547
  
  static struct i2c_driver fan53555_regulator_driver = {
  	.driver = {
  		.name = "fan53555-regulator",
91f23d8fb   Heiko Stuebner   regulator: fan535...
548
  		.of_match_table = of_match_ptr(fan53555_dt_ids),
49d8c5992   Yunfan Zhang   regulator: Fairch...
549
550
  	},
  	.probe = fan53555_regulator_probe,
49d8c5992   Yunfan Zhang   regulator: Fairch...
551
552
553
554
555
556
557
558
  	.id_table = fan53555_id,
  };
  
  module_i2c_driver(fan53555_regulator_driver);
  
  MODULE_AUTHOR("Yunfan Zhang <yfzhang@marvell.com>");
  MODULE_DESCRIPTION("FAN53555 regulator driver");
  MODULE_LICENSE("GPL v2");