Blame view

drivers/mfd/tps65910.c 12.6 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
2
  /*
a8799defb   Paul Gortmaker   mfd: tps65910: Ma...
3
   * tps65910.c  --  TI TPS6591x chip family multi-function driver
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
4
5
6
7
8
   *
   * Copyright 2010 Texas Instruments Inc.
   *
   * Author: Graeme Gregory <gg@slimlogic.co.uk>
   * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
9
   */
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
10
  #include <linux/init.h>
dc9913a05   Laxman Dewangan   mfd: Use regmap f...
11
  #include <linux/err.h>
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
12
13
  #include <linux/slab.h>
  #include <linux/i2c.h>
4aab3fada   Laxman Dewangan   mfd: tps65910: Mo...
14
15
16
  #include <linux/interrupt.h>
  #include <linux/irq.h>
  #include <linux/irqdomain.h>
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
17
  #include <linux/mfd/core.h>
dc9913a05   Laxman Dewangan   mfd: Use regmap f...
18
  #include <linux/regmap.h>
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
19
  #include <linux/mfd/tps65910.h>
1fead3f39   Sachin Kamat   mfd: tps65910: In...
20
  #include <linux/of.h>
cd4209ced   Rhyland Klein   mfd: Add tps65910...
21
  #include <linux/of_device.h>
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
22

5863eabb2   Venu Byravarasu   mfd: tps65910: Ad...
23
24
25
26
27
28
29
  static struct resource rtc_resources[] = {
  	{
  		.start  = TPS65910_IRQ_RTC_ALARM,
  		.end    = TPS65910_IRQ_RTC_ALARM,
  		.flags  = IORESOURCE_IRQ,
  	}
  };
30fe2b5bd   Geert Uytterhoeven   mfd: ti: Constify...
30
  static const struct mfd_cell tps65910s[] = {
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
31
  	{
32df986e9   Laxman Dewangan   mfd: Register tps...
32
33
34
  		.name = "tps65910-gpio",
  	},
  	{
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
35
36
37
38
  		.name = "tps65910-pmic",
  	},
  	{
  		.name = "tps65910-rtc",
5863eabb2   Venu Byravarasu   mfd: tps65910: Ad...
39
40
  		.num_resources = ARRAY_SIZE(rtc_resources),
  		.resources = &rtc_resources[0],
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
41
42
43
44
45
  	},
  	{
  		.name = "tps65910-power",
  	},
  };
4aab3fada   Laxman Dewangan   mfd: tps65910: Mo...
46
47
48
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
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
168
169
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
  static const struct regmap_irq tps65911_irqs[] = {
  	/* INT_STS */
  	[TPS65911_IRQ_PWRHOLD_F] = {
  		.mask = INT_MSK_PWRHOLD_F_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65911_IRQ_VBAT_VMHI] = {
  		.mask = INT_MSK_VMBHI_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65911_IRQ_PWRON] = {
  		.mask = INT_MSK_PWRON_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65911_IRQ_PWRON_LP] = {
  		.mask = INT_MSK_PWRON_LP_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65911_IRQ_PWRHOLD_R] = {
  		.mask = INT_MSK_PWRHOLD_R_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65911_IRQ_HOTDIE] = {
  		.mask = INT_MSK_HOTDIE_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65911_IRQ_RTC_ALARM] = {
  		.mask = INT_MSK_RTC_ALARM_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65911_IRQ_RTC_PERIOD] = {
  		.mask = INT_MSK_RTC_PERIOD_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  
  	/* INT_STS2 */
  	[TPS65911_IRQ_GPIO0_R] = {
  		.mask = INT_MSK2_GPIO0_R_IT_MSK_MASK,
  		.reg_offset = 1,
  	},
  	[TPS65911_IRQ_GPIO0_F] = {
  		.mask = INT_MSK2_GPIO0_F_IT_MSK_MASK,
  		.reg_offset = 1,
  	},
  	[TPS65911_IRQ_GPIO1_R] = {
  		.mask = INT_MSK2_GPIO1_R_IT_MSK_MASK,
  		.reg_offset = 1,
  	},
  	[TPS65911_IRQ_GPIO1_F] = {
  		.mask = INT_MSK2_GPIO1_F_IT_MSK_MASK,
  		.reg_offset = 1,
  	},
  	[TPS65911_IRQ_GPIO2_R] = {
  		.mask = INT_MSK2_GPIO2_R_IT_MSK_MASK,
  		.reg_offset = 1,
  	},
  	[TPS65911_IRQ_GPIO2_F] = {
  		.mask = INT_MSK2_GPIO2_F_IT_MSK_MASK,
  		.reg_offset = 1,
  	},
  	[TPS65911_IRQ_GPIO3_R] = {
  		.mask = INT_MSK2_GPIO3_R_IT_MSK_MASK,
  		.reg_offset = 1,
  	},
  	[TPS65911_IRQ_GPIO3_F] = {
  		.mask = INT_MSK2_GPIO3_F_IT_MSK_MASK,
  		.reg_offset = 1,
  	},
  
  	/* INT_STS2 */
  	[TPS65911_IRQ_GPIO4_R] = {
  		.mask = INT_MSK3_GPIO4_R_IT_MSK_MASK,
  		.reg_offset = 2,
  	},
  	[TPS65911_IRQ_GPIO4_F] = {
  		.mask = INT_MSK3_GPIO4_F_IT_MSK_MASK,
  		.reg_offset = 2,
  	},
  	[TPS65911_IRQ_GPIO5_R] = {
  		.mask = INT_MSK3_GPIO5_R_IT_MSK_MASK,
  		.reg_offset = 2,
  	},
  	[TPS65911_IRQ_GPIO5_F] = {
  		.mask = INT_MSK3_GPIO5_F_IT_MSK_MASK,
  		.reg_offset = 2,
  	},
  	[TPS65911_IRQ_WTCHDG] = {
  		.mask = INT_MSK3_WTCHDG_IT_MSK_MASK,
  		.reg_offset = 2,
  	},
  	[TPS65911_IRQ_VMBCH2_H] = {
  		.mask = INT_MSK3_VMBCH2_H_IT_MSK_MASK,
  		.reg_offset = 2,
  	},
  	[TPS65911_IRQ_VMBCH2_L] = {
  		.mask = INT_MSK3_VMBCH2_L_IT_MSK_MASK,
  		.reg_offset = 2,
  	},
  	[TPS65911_IRQ_PWRDN] = {
  		.mask = INT_MSK3_PWRDN_IT_MSK_MASK,
  		.reg_offset = 2,
  	},
  };
  
  static const struct regmap_irq tps65910_irqs[] = {
  	/* INT_STS */
  	[TPS65910_IRQ_VBAT_VMBDCH] = {
  		.mask = TPS65910_INT_MSK_VMBDCH_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65910_IRQ_VBAT_VMHI] = {
  		.mask = TPS65910_INT_MSK_VMBHI_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65910_IRQ_PWRON] = {
  		.mask = TPS65910_INT_MSK_PWRON_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65910_IRQ_PWRON_LP] = {
  		.mask = TPS65910_INT_MSK_PWRON_LP_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65910_IRQ_PWRHOLD] = {
  		.mask = TPS65910_INT_MSK_PWRHOLD_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65910_IRQ_HOTDIE] = {
  		.mask = TPS65910_INT_MSK_HOTDIE_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65910_IRQ_RTC_ALARM] = {
  		.mask = TPS65910_INT_MSK_RTC_ALARM_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  	[TPS65910_IRQ_RTC_PERIOD] = {
  		.mask = TPS65910_INT_MSK_RTC_PERIOD_IT_MSK_MASK,
  		.reg_offset = 0,
  	},
  
  	/* INT_STS2 */
  	[TPS65910_IRQ_GPIO_R] = {
  		.mask = TPS65910_INT_MSK2_GPIO0_F_IT_MSK_MASK,
  		.reg_offset = 1,
  	},
  	[TPS65910_IRQ_GPIO_F] = {
  		.mask = TPS65910_INT_MSK2_GPIO0_R_IT_MSK_MASK,
  		.reg_offset = 1,
  	},
  };
  
  static struct regmap_irq_chip tps65911_irq_chip = {
  	.name = "tps65910",
  	.irqs = tps65911_irqs,
  	.num_irqs = ARRAY_SIZE(tps65911_irqs),
  	.num_regs = 3,
  	.irq_reg_stride = 2,
  	.status_base = TPS65910_INT_STS,
  	.mask_base = TPS65910_INT_MSK,
0582c0faf   Kim, Milo   mfd: tps65910: Fi...
204
  	.ack_base = TPS65910_INT_STS,
4aab3fada   Laxman Dewangan   mfd: tps65910: Mo...
205
206
207
208
209
210
211
212
213
214
  };
  
  static struct regmap_irq_chip tps65910_irq_chip = {
  	.name = "tps65910",
  	.irqs = tps65910_irqs,
  	.num_irqs = ARRAY_SIZE(tps65910_irqs),
  	.num_regs = 2,
  	.irq_reg_stride = 2,
  	.status_base = TPS65910_INT_STS,
  	.mask_base = TPS65910_INT_MSK,
0582c0faf   Kim, Milo   mfd: tps65910: Fi...
215
  	.ack_base = TPS65910_INT_STS,
4aab3fada   Laxman Dewangan   mfd: tps65910: Mo...
216
217
218
219
220
  };
  
  static int tps65910_irq_init(struct tps65910 *tps65910, int irq,
  		    struct tps65910_platform_data *pdata)
  {
dae3be365   Markus Elfring   mfd: tps65910: De...
221
  	int ret;
4aab3fada   Laxman Dewangan   mfd: tps65910: Mo...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  	static struct regmap_irq_chip *tps6591x_irqs_chip;
  
  	if (!irq) {
  		dev_warn(tps65910->dev, "No interrupt support, no core IRQ
  ");
  		return -EINVAL;
  	}
  
  	if (!pdata) {
  		dev_warn(tps65910->dev, "No interrupt support, no pdata
  ");
  		return -EINVAL;
  	}
  
  	switch (tps65910_chip_id(tps65910)) {
  	case TPS65910:
  		tps6591x_irqs_chip = &tps65910_irq_chip;
  		break;
  	case TPS65911:
  		tps6591x_irqs_chip = &tps65911_irq_chip;
  		break;
  	}
  
  	tps65910->chip_irq = irq;
6167c5bce   Laxman Dewangan   mfd: tps65910: Us...
246
247
248
249
  	ret = devm_regmap_add_irq_chip(tps65910->dev, tps65910->regmap,
  				       tps65910->chip_irq,
  				       IRQF_ONESHOT, pdata->irq_base,
  				       tps6591x_irqs_chip, &tps65910->irq_data);
483e2dfdb   Krzysztof Kozlowski   mfd: tps65910: Fi...
250
  	if (ret < 0) {
4aab3fada   Laxman Dewangan   mfd: tps65910: Mo...
251
252
  		dev_warn(tps65910->dev, "Failed to add irq_chip %d
  ", ret);
483e2dfdb   Krzysztof Kozlowski   mfd: tps65910: Fi...
253
254
  		tps65910->chip_irq = 0;
  	}
4aab3fada   Laxman Dewangan   mfd: tps65910: Mo...
255
256
  	return ret;
  }
dc9913a05   Laxman Dewangan   mfd: Use regmap f...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  static bool is_volatile_reg(struct device *dev, unsigned int reg)
  {
  	struct tps65910 *tps65910 = dev_get_drvdata(dev);
  
  	/*
  	 * Caching all regulator registers.
  	 * All regualator register address range is same for
  	 * TPS65910 and TPS65911
  	 */
  	if ((reg >= TPS65910_VIO) && (reg <= TPS65910_VDAC)) {
  		/* Check for non-existing register */
  		if (tps65910_chip_id(tps65910) == TPS65910)
  			if ((reg == TPS65911_VDDCTRL_OP) ||
  				(reg == TPS65911_VDDCTRL_SR))
  				return true;
  		return false;
  	}
  	return true;
  }
39ecb0376   Laxman Dewangan   mfd: Use correct ...
276
  static const struct regmap_config tps65910_regmap_config = {
dc9913a05   Laxman Dewangan   mfd: Use regmap f...
277
278
279
  	.reg_bits = 8,
  	.val_bits = 8,
  	.volatile_reg = is_volatile_reg,
3bf6bf9be   Laxman Dewangan   mfd: Cache tps659...
280
  	.max_register = TPS65910_MAX_REGISTER - 1,
dc9913a05   Laxman Dewangan   mfd: Use regmap f...
281
282
  	.cache_type = REGCACHE_RBTREE,
  };
f791be492   Bill Pemberton   mfd: remove use o...
283
  static int tps65910_ck32k_init(struct tps65910 *tps65910,
712db99df   Johan Hovold   mfd: Add support ...
284
285
  					struct tps65910_board *pmic_pdata)
  {
712db99df   Johan Hovold   mfd: Add support ...
286
  	int ret;
d02e83cbc   Johan Hovold   mfd: Add tps65910...
287
288
289
290
  	if (!pmic_pdata->en_ck32k_xtal)
  		return 0;
  
  	ret = tps65910_reg_clear_bits(tps65910, TPS65910_DEVCTRL,
712db99df   Johan Hovold   mfd: Add support ...
291
  						DEVCTRL_CK32K_CTRL_MASK);
d02e83cbc   Johan Hovold   mfd: Add tps65910...
292
293
294
295
  	if (ret < 0) {
  		dev_err(tps65910->dev, "clear ck32k_ctrl failed: %d
  ", ret);
  		return ret;
712db99df   Johan Hovold   mfd: Add support ...
296
297
298
299
  	}
  
  	return 0;
  }
f791be492   Bill Pemberton   mfd: remove use o...
300
  static int tps65910_sleepinit(struct tps65910 *tps65910,
201cf0528   Laxman Dewangan   mfd: Add support ...
301
302
  		struct tps65910_board *pmic_pdata)
  {
da257efa8   Markus Elfring   mfd: tps65910: De...
303
  	struct device *dev;
dae3be365   Markus Elfring   mfd: tps65910: De...
304
  	int ret;
201cf0528   Laxman Dewangan   mfd: Add support ...
305

201cf0528   Laxman Dewangan   mfd: Add support ...
306
307
  	if (!pmic_pdata->en_dev_slp)
  		return 0;
71bc4f1de   Markus Elfring   mfd: tps65910: Mo...
308
  	dev = tps65910->dev;
201cf0528   Laxman Dewangan   mfd: Add support ...
309
  	/* enabling SLEEP device state */
3f7e82759   Rhyland Klein   mfd: Commonize tp...
310
  	ret = tps65910_reg_set_bits(tps65910, TPS65910_DEVCTRL,
201cf0528   Laxman Dewangan   mfd: Add support ...
311
312
313
314
315
316
  				DEVCTRL_DEV_SLP_MASK);
  	if (ret < 0) {
  		dev_err(dev, "set dev_slp failed: %d
  ", ret);
  		goto err_sleep_init;
  	}
a9bc67de0   Michał Mirosław   regulator: tps659...
317
  	if (pmic_pdata->slp_keepon.therm_keepon) {
3f7e82759   Rhyland Klein   mfd: Commonize tp...
318
319
  		ret = tps65910_reg_set_bits(tps65910,
  				TPS65910_SLEEP_KEEP_RES_ON,
201cf0528   Laxman Dewangan   mfd: Add support ...
320
321
322
323
324
325
326
  				SLEEP_KEEP_RES_ON_THERM_KEEPON_MASK);
  		if (ret < 0) {
  			dev_err(dev, "set therm_keepon failed: %d
  ", ret);
  			goto disable_dev_slp;
  		}
  	}
a9bc67de0   Michał Mirosław   regulator: tps659...
327
  	if (pmic_pdata->slp_keepon.clkout32k_keepon) {
3f7e82759   Rhyland Klein   mfd: Commonize tp...
328
329
  		ret = tps65910_reg_set_bits(tps65910,
  				TPS65910_SLEEP_KEEP_RES_ON,
201cf0528   Laxman Dewangan   mfd: Add support ...
330
331
332
333
334
335
336
  				SLEEP_KEEP_RES_ON_CLKOUT32K_KEEPON_MASK);
  		if (ret < 0) {
  			dev_err(dev, "set clkout32k_keepon failed: %d
  ", ret);
  			goto disable_dev_slp;
  		}
  	}
a9bc67de0   Michał Mirosław   regulator: tps659...
337
  	if (pmic_pdata->slp_keepon.i2chs_keepon) {
3f7e82759   Rhyland Klein   mfd: Commonize tp...
338
339
  		ret = tps65910_reg_set_bits(tps65910,
  				TPS65910_SLEEP_KEEP_RES_ON,
201cf0528   Laxman Dewangan   mfd: Add support ...
340
341
342
343
344
345
346
347
348
349
350
  				SLEEP_KEEP_RES_ON_I2CHS_KEEPON_MASK);
  		if (ret < 0) {
  			dev_err(dev, "set i2chs_keepon failed: %d
  ", ret);
  			goto disable_dev_slp;
  		}
  	}
  
  	return 0;
  
  disable_dev_slp:
3f7e82759   Rhyland Klein   mfd: Commonize tp...
351
352
  	tps65910_reg_clear_bits(tps65910, TPS65910_DEVCTRL,
  				DEVCTRL_DEV_SLP_MASK);
201cf0528   Laxman Dewangan   mfd: Add support ...
353
354
355
356
  
  err_sleep_init:
  	return ret;
  }
cd4209ced   Rhyland Klein   mfd: Add tps65910...
357
  #ifdef CONFIG_OF
c0dfbfe2a   Jingoo Han   mfd: tps65910: Ma...
358
  static const struct of_device_id tps65910_of_match[] = {
cd4209ced   Rhyland Klein   mfd: Add tps65910...
359
360
361
362
  	{ .compatible = "ti,tps65910", .data = (void *)TPS65910},
  	{ .compatible = "ti,tps65911", .data = (void *)TPS65911},
  	{ },
  };
cd4209ced   Rhyland Klein   mfd: Add tps65910...
363
364
  
  static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
01a0f4aaa   Lee Jones   mfd: tps65910: Ri...
365
  						unsigned long *chip_id)
cd4209ced   Rhyland Klein   mfd: Add tps65910...
366
367
368
369
370
  {
  	struct device_node *np = client->dev.of_node;
  	struct tps65910_board *board_info;
  	unsigned int prop;
  	const struct of_device_id *match;
dae3be365   Markus Elfring   mfd: tps65910: De...
371
  	int ret;
cd4209ced   Rhyland Klein   mfd: Add tps65910...
372
373
374
375
376
377
378
  
  	match = of_match_device(tps65910_of_match, &client->dev);
  	if (!match) {
  		dev_err(&client->dev, "Failed to find matching dt id
  ");
  		return NULL;
  	}
01a0f4aaa   Lee Jones   mfd: tps65910: Ri...
379
  	*chip_id  = (unsigned long)match->data;
cd4209ced   Rhyland Klein   mfd: Add tps65910...
380
381
382
  
  	board_info = devm_kzalloc(&client->dev, sizeof(*board_info),
  			GFP_KERNEL);
93e879ef0   Markus Elfring   mfd: tps65910: De...
383
  	if (!board_info)
cd4209ced   Rhyland Klein   mfd: Add tps65910...
384
  		return NULL;
cd4209ced   Rhyland Klein   mfd: Add tps65910...
385
386
387
388
  
  	ret = of_property_read_u32(np, "ti,vmbch-threshold", &prop);
  	if (!ret)
  		board_info->vmbch_threshold = prop;
cd4209ced   Rhyland Klein   mfd: Add tps65910...
389
390
391
392
  
  	ret = of_property_read_u32(np, "ti,vmbch2-threshold", &prop);
  	if (!ret)
  		board_info->vmbch2_threshold = prop;
cd4209ced   Rhyland Klein   mfd: Add tps65910...
393

bcc1dd4cd   Johan Hovold   mfd: Add device-t...
394
395
  	prop = of_property_read_bool(np, "ti,en-ck32k-xtal");
  	board_info->en_ck32k_xtal = prop;
a9bc67de0   Michał Mirosław   regulator: tps659...
396
397
398
399
400
401
402
403
404
405
406
  	prop = of_property_read_bool(np, "ti,sleep-enable");
  	board_info->en_dev_slp = prop;
  
  	prop = of_property_read_bool(np, "ti,sleep-keep-therm");
  	board_info->slp_keepon.therm_keepon = prop;
  
  	prop = of_property_read_bool(np, "ti,sleep-keep-ck32k");
  	board_info->slp_keepon.clkout32k_keepon = prop;
  
  	prop = of_property_read_bool(np, "ti,sleep-keep-hsclk");
  	board_info->slp_keepon.i2chs_keepon = prop;
cd4209ced   Rhyland Klein   mfd: Add tps65910...
407
408
  	board_info->irq = client->irq;
  	board_info->irq_base = -1;
b079fa720   Bill Huang   mfd: dt: tps65910...
409
410
  	board_info->pm_off = of_property_read_bool(np,
  			"ti,system-power-controller");
cd4209ced   Rhyland Klein   mfd: Add tps65910...
411
412
413
414
  
  	return board_info;
  }
  #else
7f65f74cc   Samuel Ortiz   mfd: Fix tps65910...
415
416
  static inline
  struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
01a0f4aaa   Lee Jones   mfd: tps65910: Ri...
417
  					 unsigned long *chip_id)
cd4209ced   Rhyland Klein   mfd: Add tps65910...
418
419
420
421
  {
  	return NULL;
  }
  #endif
201cf0528   Laxman Dewangan   mfd: Add support ...
422

b079fa720   Bill Huang   mfd: dt: tps65910...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
  static struct i2c_client *tps65910_i2c_client;
  static void tps65910_power_off(void)
  {
  	struct tps65910 *tps65910;
  
  	tps65910 = dev_get_drvdata(&tps65910_i2c_client->dev);
  
  	if (tps65910_reg_set_bits(tps65910, TPS65910_DEVCTRL,
  			DEVCTRL_PWR_OFF_MASK) < 0)
  		return;
  
  	tps65910_reg_clear_bits(tps65910, TPS65910_DEVCTRL,
  			DEVCTRL_DEV_ON_MASK);
  }
f791be492   Bill Pemberton   mfd: remove use o...
437
  static int tps65910_i2c_probe(struct i2c_client *i2c,
01a0f4aaa   Lee Jones   mfd: tps65910: Ri...
438
  			      const struct i2c_device_id *id)
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
439
440
  {
  	struct tps65910 *tps65910;
2537df722   Graeme Gregory   TPS65910: GPIO: A...
441
  	struct tps65910_board *pmic_plat_data;
cb8d86545   Laxman Dewangan   mfd: Save device ...
442
  	struct tps65910_board *of_pmic_plat_data = NULL;
e3471bdc2   Graeme Gregory   TPS65910: IRQ: Ad...
443
  	struct tps65910_platform_data *init_data;
01a0f4aaa   Lee Jones   mfd: tps65910: Ri...
444
  	unsigned long chip_id = id->driver_data;
dae3be365   Markus Elfring   mfd: tps65910: De...
445
  	int ret;
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
446

2537df722   Graeme Gregory   TPS65910: GPIO: A...
447
  	pmic_plat_data = dev_get_platdata(&i2c->dev);
cd4209ced   Rhyland Klein   mfd: Add tps65910...
448

cb8d86545   Laxman Dewangan   mfd: Save device ...
449
  	if (!pmic_plat_data && i2c->dev.of_node) {
cd4209ced   Rhyland Klein   mfd: Add tps65910...
450
  		pmic_plat_data = tps65910_parse_dt(i2c, &chip_id);
cb8d86545   Laxman Dewangan   mfd: Save device ...
451
452
  		of_pmic_plat_data = pmic_plat_data;
  	}
cd4209ced   Rhyland Klein   mfd: Add tps65910...
453

2537df722   Graeme Gregory   TPS65910: GPIO: A...
454
455
  	if (!pmic_plat_data)
  		return -EINVAL;
63fe7dee9   Laxman Dewangan   mfd: Convert all ...
456
  	init_data = devm_kzalloc(&i2c->dev, sizeof(*init_data), GFP_KERNEL);
e3471bdc2   Graeme Gregory   TPS65910: IRQ: Ad...
457
458
  	if (init_data == NULL)
  		return -ENOMEM;
63fe7dee9   Laxman Dewangan   mfd: Convert all ...
459
460
  	tps65910 = devm_kzalloc(&i2c->dev, sizeof(*tps65910), GFP_KERNEL);
  	if (tps65910 == NULL)
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
461
  		return -ENOMEM;
cb8d86545   Laxman Dewangan   mfd: Save device ...
462
  	tps65910->of_plat_data = of_pmic_plat_data;
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
463
464
465
  	i2c_set_clientdata(i2c, tps65910);
  	tps65910->dev = &i2c->dev;
  	tps65910->i2c_client = i2c;
cd4209ced   Rhyland Klein   mfd: Add tps65910...
466
  	tps65910->id = chip_id;
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
467

be1c77002   Arnout Vandecappelle (Essensium/Mind)   mfd: tps65910: Wo...
468
469
470
471
472
  	/* Work around silicon erratum SWCZ010: the tps65910 may miss the
  	 * first I2C transfer. So issue a dummy transfer before the first
  	 * real transfer.
  	 */
  	i2c_master_send(i2c, "", 1);
63fe7dee9   Laxman Dewangan   mfd: Convert all ...
473
  	tps65910->regmap = devm_regmap_init_i2c(i2c, &tps65910_regmap_config);
dc9913a05   Laxman Dewangan   mfd: Use regmap f...
474
475
476
477
  	if (IS_ERR(tps65910->regmap)) {
  		ret = PTR_ERR(tps65910->regmap);
  		dev_err(&i2c->dev, "regmap initialization failed: %d
  ", ret);
63fe7dee9   Laxman Dewangan   mfd: Convert all ...
478
  		return ret;
dc9913a05   Laxman Dewangan   mfd: Use regmap f...
479
  	}
b1224cd11   Jesper Juhl   mfd: Avoid two as...
480
  	init_data->irq = pmic_plat_data->irq;
1773140fe   Laxman Dewangan   mfd: Initialize t...
481
  	init_data->irq_base = pmic_plat_data->irq_base;
b1224cd11   Jesper Juhl   mfd: Avoid two as...
482

1e351a95b   Afzal Mohammed   mfd: Make TPS6591...
483
  	tps65910_irq_init(tps65910, init_data->irq, init_data);
d02e83cbc   Johan Hovold   mfd: Add tps65910...
484
  	tps65910_ck32k_init(tps65910, pmic_plat_data);
201cf0528   Laxman Dewangan   mfd: Add support ...
485
  	tps65910_sleepinit(tps65910, pmic_plat_data);
b079fa720   Bill Huang   mfd: dt: tps65910...
486
487
488
489
  	if (pmic_plat_data->pm_off && !pm_power_off) {
  		tps65910_i2c_client = i2c;
  		pm_power_off = tps65910_power_off;
  	}
f3466e776   Laxman Dewangan   mfd: tps65910: Us...
490
491
492
493
  	ret = devm_mfd_add_devices(tps65910->dev, -1,
  				   tps65910s, ARRAY_SIZE(tps65910s),
  				   NULL, 0,
  				   regmap_irq_get_domain(tps65910->irq_data));
10ecb80e8   Laxman Dewangan   mfd: tps65910: In...
494
495
496
497
498
  	if (ret < 0) {
  		dev_err(&i2c->dev, "mfd_add_devices failed: %d
  ", ret);
  		return ret;
  	}
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
499
500
  	return ret;
  }
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
501
  static const struct i2c_device_id tps65910_i2c_id[] = {
795570561   Jorge Eduardo Candelaria   MFD: TPS65910: Ad...
502
503
         { "tps65910", TPS65910 },
         { "tps65911", TPS65911 },
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
504
505
         { }
  };
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
506
507
508
509
  
  static struct i2c_driver tps65910_i2c_driver = {
  	.driver = {
  		   .name = "tps65910",
cd4209ced   Rhyland Klein   mfd: Add tps65910...
510
  		   .of_match_table = of_match_ptr(tps65910_of_match),
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
511
512
  	},
  	.probe = tps65910_i2c_probe,
27c6750ec   Graeme Gregory   MFD: TPS65910: Ad...
513
514
515
516
517
518
519
520
521
  	.id_table = tps65910_i2c_id,
  };
  
  static int __init tps65910_i2c_init(void)
  {
  	return i2c_add_driver(&tps65910_i2c_driver);
  }
  /* init early so consumer devices can complete system boot */
  subsys_initcall(tps65910_i2c_init);