Blame view

drivers/mfd/rk808.c 17.6 KB
2025cf9e1   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
2
  /*
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
3
   * MFD core driver for Rockchip RK808/RK818
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
4
5
6
7
8
9
   *
   * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
   *
   * Author: Chris Zhong <zyw@rock-chips.com>
   * Author: Zhang Qing <zhangqing@rock-chips.com>
   *
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
10
11
12
   * Copyright (C) 2016 PHYTEC Messtechnik GmbH
   *
   * Author: Wadim Egorov <w.egorov@phytec.de>
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
13
14
15
16
17
18
19
   */
  
  #include <linux/i2c.h>
  #include <linux/interrupt.h>
  #include <linux/mfd/rk808.h>
  #include <linux/mfd/core.h>
  #include <linux/module.h>
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
20
  #include <linux/of_device.h>
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
21
22
23
24
25
26
27
  #include <linux/regmap.h>
  
  struct rk808_reg_data {
  	int addr;
  	int mask;
  	int value;
  };
2adb3b8e6   Doug Anderson   mfd: rk808: Add r...
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
  {
  	/*
  	 * Notes:
  	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
  	 *   we don't use that feature.  It's better to cache.
  	 * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
  	 *   bits are cleared in case when we shutoff anyway, but better safe.
  	 */
  
  	switch (reg) {
  	case RK808_SECONDS_REG ... RK808_WEEKS_REG:
  	case RK808_RTC_STATUS_REG:
  	case RK808_VB_MON_REG:
  	case RK808_THERMAL_REG:
  	case RK808_DCDC_UV_STS_REG:
  	case RK808_LDO_UV_STS_REG:
  	case RK808_DCDC_PG_REG:
  	case RK808_LDO_PG_REG:
  	case RK808_DEVCTRL_REG:
  	case RK808_INT_STS_REG1:
  	case RK808_INT_STS_REG2:
  		return true;
  	}
  
  	return false;
  }
586c1b412   Tony Xie   mfd: rk808: Add R...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
  {
  	/*
  	 * Notes:
  	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
  	 *   we don't use that feature.  It's better to cache.
  	 */
  
  	switch (reg) {
  	case RK817_SECONDS_REG ... RK817_WEEKS_REG:
  	case RK817_RTC_STATUS_REG:
  	case RK817_INT_STS_REG0:
  	case RK817_INT_STS_REG1:
  	case RK817_INT_STS_REG2:
  	case RK817_SYS_STS:
  		return true;
  	}
  
  	return true;
  }
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
75
76
77
78
79
80
81
  static const struct regmap_config rk818_regmap_config = {
  	.reg_bits = 8,
  	.val_bits = 8,
  	.max_register = RK818_USB_CTRL_REG,
  	.cache_type = REGCACHE_RBTREE,
  	.volatile_reg = rk808_is_volatile_reg,
  };
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
82
83
84
85
86
87
88
  static const struct regmap_config rk805_regmap_config = {
  	.reg_bits = 8,
  	.val_bits = 8,
  	.max_register = RK805_OFF_SOURCE_REG,
  	.cache_type = REGCACHE_RBTREE,
  	.volatile_reg = rk808_is_volatile_reg,
  };
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
89
90
91
92
  static const struct regmap_config rk808_regmap_config = {
  	.reg_bits = 8,
  	.val_bits = 8,
  	.max_register = RK808_IO_POL_REG,
2adb3b8e6   Doug Anderson   mfd: rk808: Add r...
93
94
  	.cache_type = REGCACHE_RBTREE,
  	.volatile_reg = rk808_is_volatile_reg,
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
95
  };
586c1b412   Tony Xie   mfd: rk808: Add R...
96
97
98
99
100
101
102
  static const struct regmap_config rk817_regmap_config = {
  	.reg_bits = 8,
  	.val_bits = 8,
  	.max_register = RK817_GPIO_INT_CFG,
  	.cache_type = REGCACHE_NONE,
  	.volatile_reg = rk817_is_volatile_reg,
  };
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
103
  static struct resource rtc_resources[] = {
eeb86ed3e   Heiko Stuebner   mfd: rk808: Use D...
104
  	DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM),
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
105
  };
586c1b412   Tony Xie   mfd: rk808: Add R...
106
107
108
  static struct resource rk817_rtc_resources[] = {
  	DEFINE_RES_IRQ(RK817_IRQ_RTC_ALARM),
  };
f7c22398f   Joseph Chen   mfd: rk808: Add R...
109
  static struct resource rk805_key_resources[] = {
bc85e4adb   Heiko Stuebner   mfd: rk808: Fix R...
110
111
  	DEFINE_RES_IRQ(RK805_IRQ_PWRON_RISE),
  	DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL),
f7c22398f   Joseph Chen   mfd: rk808: Add R...
112
  };
586c1b412   Tony Xie   mfd: rk808: Add R...
113
114
115
116
  static struct resource rk817_pwrkey_resources[] = {
  	DEFINE_RES_IRQ(RK817_IRQ_PWRON_RISE),
  	DEFINE_RES_IRQ(RK817_IRQ_PWRON_FALL),
  };
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
117
118
119
  static const struct mfd_cell rk805s[] = {
  	{ .name = "rk808-clkout", },
  	{ .name = "rk808-regulator", },
8d249b67c   Joseph Chen   mfd: rk808: Add R...
120
  	{ .name = "rk805-pinctrl", },
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
121
122
123
124
125
  	{
  		.name = "rk808-rtc",
  		.num_resources = ARRAY_SIZE(rtc_resources),
  		.resources = &rtc_resources[0],
  	},
f7c22398f   Joseph Chen   mfd: rk808: Add R...
126
127
128
129
  	{	.name = "rk805-pwrkey",
  		.num_resources = ARRAY_SIZE(rk805_key_resources),
  		.resources = &rk805_key_resources[0],
  	},
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
130
  };
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
131
132
133
134
135
136
  static const struct mfd_cell rk808s[] = {
  	{ .name = "rk808-clkout", },
  	{ .name = "rk808-regulator", },
  	{
  		.name = "rk808-rtc",
  		.num_resources = ARRAY_SIZE(rtc_resources),
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
137
  		.resources = rtc_resources,
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
138
139
  	},
  };
586c1b412   Tony Xie   mfd: rk808: Add R...
140
141
142
143
  static const struct mfd_cell rk817s[] = {
  	{ .name = "rk808-clkout",},
  	{ .name = "rk808-regulator",},
  	{
bc85e4adb   Heiko Stuebner   mfd: rk808: Fix R...
144
  		.name = "rk805-pwrkey",
586c1b412   Tony Xie   mfd: rk808: Add R...
145
146
147
148
149
150
151
152
153
  		.num_resources = ARRAY_SIZE(rk817_pwrkey_resources),
  		.resources = &rk817_pwrkey_resources[0],
  	},
  	{
  		.name = "rk808-rtc",
  		.num_resources = ARRAY_SIZE(rk817_rtc_resources),
  		.resources = &rk817_rtc_resources[0],
  	},
  };
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
154
155
156
157
158
159
160
161
162
  static const struct mfd_cell rk818s[] = {
  	{ .name = "rk808-clkout", },
  	{ .name = "rk808-regulator", },
  	{
  		.name = "rk808-rtc",
  		.num_resources = ARRAY_SIZE(rtc_resources),
  		.resources = rtc_resources,
  	},
  };
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
163
164
165
166
167
168
169
170
171
172
  static const struct rk808_reg_data rk805_pre_init_reg[] = {
  	{RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
  				 RK805_BUCK1_2_ILMAX_4000MA},
  	{RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
  				 RK805_BUCK1_2_ILMAX_4000MA},
  	{RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
  				 RK805_BUCK3_ILMAX_3000MA},
  	{RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
  				 RK805_BUCK4_ILMAX_3500MA},
  	{RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA},
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
173
174
  	{RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C},
  };
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
175
  static const struct rk808_reg_data rk808_pre_init_reg[] = {
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
176
177
178
179
180
  	{ RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK,  BUCK_ILMIN_150MA },
  	{ RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK,  BUCK_ILMIN_200MA },
  	{ RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
  	{ RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK,  BUCK_ILMIN_200MA },
  	{ RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK,  BUCK_ILMIN_200MA },
e19f74288   Chris Zhong   mfd: rk808: Disab...
181
  	{ RK808_DCDC_UV_ACT_REG,  BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE},
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
182
183
184
  	{ RK808_VB_MON_REG,       MASK_ALL,         VB_LO_ACT |
  						    VB_LO_SEL_3500MV },
  };
586c1b412   Tony Xie   mfd: rk808: Add R...
185
186
  static const struct rk808_reg_data rk817_pre_init_reg[] = {
  	{RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP},
dbd16ef53   Heiko Stuebner   mfd: rk808: Set R...
187
  	{RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L},
586c1b412   Tony Xie   mfd: rk808: Add R...
188
189
190
  	{RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK,
  					   RK817_HOTDIE_105 | RK817_TSD_140},
  };
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  static const struct rk808_reg_data rk818_pre_init_reg[] = {
  	/* improve efficiency */
  	{ RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK,  BUCK_ILMIN_250MA },
  	{ RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK,  BUCK_ILMIN_250MA },
  	{ RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
  	{ RK818_USB_CTRL_REG,	  RK818_USB_ILIM_SEL_MASK,
  						    RK818_USB_ILMIN_2000MA },
  	/* close charger when usb lower then 3.4V */
  	{ RK818_USB_CTRL_REG,	  RK818_USB_CHG_SD_VSEL_MASK,
  						    (0x7 << 4) },
  	/* no action when vref */
  	{ RK818_H5V_EN_REG,	  BIT(1),	    RK818_REF_RDY_CTRL },
  	/* enable HDMI 5V */
  	{ RK818_H5V_EN_REG,	  BIT(0),	    RK818_H5V_EN },
  	{ RK808_VB_MON_REG,	  MASK_ALL,	    VB_LO_ACT |
  						    VB_LO_SEL_3500MV },
  };
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
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
233
234
235
236
237
238
239
240
241
  static const struct regmap_irq rk805_irqs[] = {
  	[RK805_IRQ_PWRON_RISE] = {
  		.mask = RK805_IRQ_PWRON_RISE_MSK,
  		.reg_offset = 0,
  	},
  	[RK805_IRQ_VB_LOW] = {
  		.mask = RK805_IRQ_VB_LOW_MSK,
  		.reg_offset = 0,
  	},
  	[RK805_IRQ_PWRON] = {
  		.mask = RK805_IRQ_PWRON_MSK,
  		.reg_offset = 0,
  	},
  	[RK805_IRQ_PWRON_LP] = {
  		.mask = RK805_IRQ_PWRON_LP_MSK,
  		.reg_offset = 0,
  	},
  	[RK805_IRQ_HOTDIE] = {
  		.mask = RK805_IRQ_HOTDIE_MSK,
  		.reg_offset = 0,
  	},
  	[RK805_IRQ_RTC_ALARM] = {
  		.mask = RK805_IRQ_RTC_ALARM_MSK,
  		.reg_offset = 0,
  	},
  	[RK805_IRQ_RTC_PERIOD] = {
  		.mask = RK805_IRQ_RTC_PERIOD_MSK,
  		.reg_offset = 0,
  	},
  	[RK805_IRQ_PWRON_FALL] = {
  		.mask = RK805_IRQ_PWRON_FALL_MSK,
  		.reg_offset = 0,
  	},
  };
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
  static const struct regmap_irq rk808_irqs[] = {
  	/* INT_STS */
  	[RK808_IRQ_VOUT_LO] = {
  		.mask = RK808_IRQ_VOUT_LO_MSK,
  		.reg_offset = 0,
  	},
  	[RK808_IRQ_VB_LO] = {
  		.mask = RK808_IRQ_VB_LO_MSK,
  		.reg_offset = 0,
  	},
  	[RK808_IRQ_PWRON] = {
  		.mask = RK808_IRQ_PWRON_MSK,
  		.reg_offset = 0,
  	},
  	[RK808_IRQ_PWRON_LP] = {
  		.mask = RK808_IRQ_PWRON_LP_MSK,
  		.reg_offset = 0,
  	},
  	[RK808_IRQ_HOTDIE] = {
  		.mask = RK808_IRQ_HOTDIE_MSK,
  		.reg_offset = 0,
  	},
  	[RK808_IRQ_RTC_ALARM] = {
  		.mask = RK808_IRQ_RTC_ALARM_MSK,
  		.reg_offset = 0,
  	},
  	[RK808_IRQ_RTC_PERIOD] = {
  		.mask = RK808_IRQ_RTC_PERIOD_MSK,
  		.reg_offset = 0,
  	},
  
  	/* INT_STS2 */
  	[RK808_IRQ_PLUG_IN_INT] = {
  		.mask = RK808_IRQ_PLUG_IN_INT_MSK,
  		.reg_offset = 1,
  	},
  	[RK808_IRQ_PLUG_OUT_INT] = {
  		.mask = RK808_IRQ_PLUG_OUT_INT_MSK,
  		.reg_offset = 1,
  	},
  };
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
283
284
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
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
  static const struct regmap_irq rk818_irqs[] = {
  	/* INT_STS */
  	[RK818_IRQ_VOUT_LO] = {
  		.mask = RK818_IRQ_VOUT_LO_MSK,
  		.reg_offset = 0,
  	},
  	[RK818_IRQ_VB_LO] = {
  		.mask = RK818_IRQ_VB_LO_MSK,
  		.reg_offset = 0,
  	},
  	[RK818_IRQ_PWRON] = {
  		.mask = RK818_IRQ_PWRON_MSK,
  		.reg_offset = 0,
  	},
  	[RK818_IRQ_PWRON_LP] = {
  		.mask = RK818_IRQ_PWRON_LP_MSK,
  		.reg_offset = 0,
  	},
  	[RK818_IRQ_HOTDIE] = {
  		.mask = RK818_IRQ_HOTDIE_MSK,
  		.reg_offset = 0,
  	},
  	[RK818_IRQ_RTC_ALARM] = {
  		.mask = RK818_IRQ_RTC_ALARM_MSK,
  		.reg_offset = 0,
  	},
  	[RK818_IRQ_RTC_PERIOD] = {
  		.mask = RK818_IRQ_RTC_PERIOD_MSK,
  		.reg_offset = 0,
  	},
  	[RK818_IRQ_USB_OV] = {
  		.mask = RK818_IRQ_USB_OV_MSK,
  		.reg_offset = 0,
  	},
  
  	/* INT_STS2 */
  	[RK818_IRQ_PLUG_IN] = {
  		.mask = RK818_IRQ_PLUG_IN_MSK,
  		.reg_offset = 1,
  	},
  	[RK818_IRQ_PLUG_OUT] = {
  		.mask = RK818_IRQ_PLUG_OUT_MSK,
  		.reg_offset = 1,
  	},
  	[RK818_IRQ_CHG_OK] = {
  		.mask = RK818_IRQ_CHG_OK_MSK,
  		.reg_offset = 1,
  	},
  	[RK818_IRQ_CHG_TE] = {
  		.mask = RK818_IRQ_CHG_TE_MSK,
  		.reg_offset = 1,
  	},
  	[RK818_IRQ_CHG_TS1] = {
  		.mask = RK818_IRQ_CHG_TS1_MSK,
  		.reg_offset = 1,
  	},
  	[RK818_IRQ_TS2] = {
  		.mask = RK818_IRQ_TS2_MSK,
  		.reg_offset = 1,
  	},
  	[RK818_IRQ_CHG_CVTLIM] = {
  		.mask = RK818_IRQ_CHG_CVTLIM_MSK,
  		.reg_offset = 1,
  	},
  	[RK818_IRQ_DISCHG_ILIM] = {
  		.mask = RK818_IRQ_DISCHG_ILIM_MSK,
  		.reg_offset = 1,
  	},
  };
586c1b412   Tony Xie   mfd: rk808: Add R...
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  static const struct regmap_irq rk817_irqs[RK817_IRQ_END] = {
  	REGMAP_IRQ_REG_LINE(0, 8),
  	REGMAP_IRQ_REG_LINE(1, 8),
  	REGMAP_IRQ_REG_LINE(2, 8),
  	REGMAP_IRQ_REG_LINE(3, 8),
  	REGMAP_IRQ_REG_LINE(4, 8),
  	REGMAP_IRQ_REG_LINE(5, 8),
  	REGMAP_IRQ_REG_LINE(6, 8),
  	REGMAP_IRQ_REG_LINE(7, 8),
  	REGMAP_IRQ_REG_LINE(8, 8),
  	REGMAP_IRQ_REG_LINE(9, 8),
  	REGMAP_IRQ_REG_LINE(10, 8),
  	REGMAP_IRQ_REG_LINE(11, 8),
  	REGMAP_IRQ_REG_LINE(12, 8),
  	REGMAP_IRQ_REG_LINE(13, 8),
  	REGMAP_IRQ_REG_LINE(14, 8),
  	REGMAP_IRQ_REG_LINE(15, 8),
  	REGMAP_IRQ_REG_LINE(16, 8),
  	REGMAP_IRQ_REG_LINE(17, 8),
  	REGMAP_IRQ_REG_LINE(18, 8),
  	REGMAP_IRQ_REG_LINE(19, 8),
  	REGMAP_IRQ_REG_LINE(20, 8),
  	REGMAP_IRQ_REG_LINE(21, 8),
  	REGMAP_IRQ_REG_LINE(22, 8),
  	REGMAP_IRQ_REG_LINE(23, 8)
  };
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
378
379
380
381
382
383
384
385
386
387
  static struct regmap_irq_chip rk805_irq_chip = {
  	.name = "rk805",
  	.irqs = rk805_irqs,
  	.num_irqs = ARRAY_SIZE(rk805_irqs),
  	.num_regs = 1,
  	.status_base = RK805_INT_STS_REG,
  	.mask_base = RK805_INT_STS_MSK_REG,
  	.ack_base = RK805_INT_STS_REG,
  	.init_ack_masked = true,
  };
24e34b9d7   Bhumika Goyal   mfd: constify reg...
388
  static const struct regmap_irq_chip rk808_irq_chip = {
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
389
390
391
392
393
394
395
396
397
398
  	.name = "rk808",
  	.irqs = rk808_irqs,
  	.num_irqs = ARRAY_SIZE(rk808_irqs),
  	.num_regs = 2,
  	.irq_reg_stride = 2,
  	.status_base = RK808_INT_STS_REG1,
  	.mask_base = RK808_INT_STS_MSK_REG1,
  	.ack_base = RK808_INT_STS_REG1,
  	.init_ack_masked = true,
  };
586c1b412   Tony Xie   mfd: rk808: Add R...
399
400
401
402
403
404
405
406
407
408
409
  static struct regmap_irq_chip rk817_irq_chip = {
  	.name = "rk817",
  	.irqs = rk817_irqs,
  	.num_irqs = ARRAY_SIZE(rk817_irqs),
  	.num_regs = 3,
  	.irq_reg_stride = 2,
  	.status_base = RK817_INT_STS_REG0,
  	.mask_base = RK817_INT_STS_MSK_REG0,
  	.ack_base = RK817_INT_STS_REG0,
  	.init_ack_masked = true,
  };
24e34b9d7   Bhumika Goyal   mfd: constify reg...
410
  static const struct regmap_irq_chip rk818_irq_chip = {
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
411
412
413
414
415
416
417
418
419
420
  	.name = "rk818",
  	.irqs = rk818_irqs,
  	.num_irqs = ARRAY_SIZE(rk818_irqs),
  	.num_regs = 2,
  	.irq_reg_stride = 2,
  	.status_base = RK818_INT_STS_REG1,
  	.mask_base = RK818_INT_STS_MSK_REG1,
  	.ack_base = RK818_INT_STS_REG1,
  	.init_ack_masked = true,
  };
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
421
  static struct i2c_client *rk808_i2c_client;
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
422

7a52cbcce   Robin Murphy   mfd: rk808: Reduc...
423
  static void rk808_pm_power_off(void)
b2e2c8509   Jianhong Chen   mfd: rk808: RK818...
424
425
  {
  	int ret;
7a52cbcce   Robin Murphy   mfd: rk808: Reduc...
426
  	unsigned int reg, bit;
b2e2c8509   Jianhong Chen   mfd: rk808: RK818...
427
  	struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
7a52cbcce   Robin Murphy   mfd: rk808: Reduc...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  	switch (rk808->variant) {
  	case RK805_ID:
  		reg = RK805_DEV_CTRL_REG;
  		bit = DEV_OFF;
  		break;
  	case RK808_ID:
  		reg = RK808_DEVCTRL_REG,
  		bit = DEV_OFF_RST;
  		break;
  	case RK818_ID:
  		reg = RK818_DEVCTRL_REG;
  		bit = DEV_OFF;
  		break;
  	default:
b2e2c8509   Jianhong Chen   mfd: rk808: RK818...
442
  		return;
7a52cbcce   Robin Murphy   mfd: rk808: Reduc...
443
444
  	}
  	ret = regmap_update_bits(rk808->regmap, reg, bit, bit);
b2e2c8509   Jianhong Chen   mfd: rk808: RK818...
445
  	if (ret)
ac195d942   Stefan Mavrodiev   mfd: rk808: Prepa...
446
447
  		dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!
  ");
b2e2c8509   Jianhong Chen   mfd: rk808: RK818...
448
  }
90df3a823   Robin Murphy   mfd: rk808: Stop ...
449
  static void rk8xx_shutdown(struct i2c_client *client)
586c1b412   Tony Xie   mfd: rk808: Add R...
450
  {
90df3a823   Robin Murphy   mfd: rk808: Stop ...
451
  	struct rk808 *rk808 = i2c_get_clientdata(client);
586c1b412   Tony Xie   mfd: rk808: Add R...
452
  	int ret;
90df3a823   Robin Murphy   mfd: rk808: Stop ...
453
  	switch (rk808->variant) {
42679765f   Robin Murphy   mfd: rk808: Conve...
454
455
456
457
458
459
  	case RK805_ID:
  		ret = regmap_update_bits(rk808->regmap,
  					 RK805_GPIO_IO_POL_REG,
  					 SLP_SD_MSK,
  					 SHUTDOWN_FUN);
  		break;
90df3a823   Robin Murphy   mfd: rk808: Stop ...
460
461
  	case RK809_ID:
  	case RK817_ID:
586c1b412   Tony Xie   mfd: rk808: Add R...
462
463
464
465
  		ret = regmap_update_bits(rk808->regmap,
  					 RK817_SYS_CFG(3),
  					 RK817_SLPPIN_FUNC_MSK,
  					 SLPPIN_DN_FUN);
90df3a823   Robin Murphy   mfd: rk808: Stop ...
466
467
468
  		break;
  	default:
  		return;
586c1b412   Tony Xie   mfd: rk808: Add R...
469
  	}
90df3a823   Robin Murphy   mfd: rk808: Stop ...
470
471
472
473
  	if (ret)
  		dev_warn(&client->dev,
  			 "Cannot switch to power down function
  ");
b2e2c8509   Jianhong Chen   mfd: rk808: RK818...
474
  }
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
475
  static const struct of_device_id rk808_of_match[] = {
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
476
  	{ .compatible = "rockchip,rk805" },
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
477
  	{ .compatible = "rockchip,rk808" },
586c1b412   Tony Xie   mfd: rk808: Add R...
478
479
  	{ .compatible = "rockchip,rk809" },
  	{ .compatible = "rockchip,rk817" },
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
480
481
482
483
  	{ .compatible = "rockchip,rk818" },
  	{ },
  };
  MODULE_DEVICE_TABLE(of, rk808_of_match);
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
484
485
486
487
488
  static int rk808_probe(struct i2c_client *client,
  		       const struct i2c_device_id *id)
  {
  	struct device_node *np = client->dev.of_node;
  	struct rk808 *rk808;
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
489
490
491
492
  	const struct rk808_reg_data *pre_init_reg;
  	const struct mfd_cell *cells;
  	int nr_pre_init_regs;
  	int nr_cells;
d8f083a30   Soeren Moch   mfd: rk808: Alway...
493
  	int msb, lsb;
586c1b412   Tony Xie   mfd: rk808: Add R...
494
  	unsigned char pmic_id_msb, pmic_id_lsb;
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
495
496
  	int ret;
  	int i;
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
497
498
499
  	rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL);
  	if (!rk808)
  		return -ENOMEM;
586c1b412   Tony Xie   mfd: rk808: Add R...
500
501
502
503
504
505
506
507
  	if (of_device_is_compatible(np, "rockchip,rk817") ||
  	    of_device_is_compatible(np, "rockchip,rk809")) {
  		pmic_id_msb = RK817_ID_MSB;
  		pmic_id_lsb = RK817_ID_LSB;
  	} else {
  		pmic_id_msb = RK808_ID_MSB;
  		pmic_id_lsb = RK808_ID_LSB;
  	}
9d6105e19   Elaine Zhang   mfd: rk808: Fix u...
508
  	/* Read chip variant */
586c1b412   Tony Xie   mfd: rk808: Add R...
509
  	msb = i2c_smbus_read_byte_data(client, pmic_id_msb);
9d6105e19   Elaine Zhang   mfd: rk808: Fix u...
510
511
512
  	if (msb < 0) {
  		dev_err(&client->dev, "failed to read the chip id at 0x%x
  ",
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
513
  			RK808_ID_MSB);
9d6105e19   Elaine Zhang   mfd: rk808: Fix u...
514
  		return msb;
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
515
  	}
586c1b412   Tony Xie   mfd: rk808: Add R...
516
  	lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb);
9d6105e19   Elaine Zhang   mfd: rk808: Fix u...
517
518
519
520
521
522
523
524
525
526
  	if (lsb < 0) {
  		dev_err(&client->dev, "failed to read the chip id at 0x%x
  ",
  			RK808_ID_LSB);
  		return lsb;
  	}
  
  	rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
  	dev_info(&client->dev, "chip id: 0x%x
  ", (unsigned int)rk808->variant);
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
527
528
  
  	switch (rk808->variant) {
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
529
530
531
532
533
534
535
  	case RK805_ID:
  		rk808->regmap_cfg = &rk805_regmap_config;
  		rk808->regmap_irq_chip = &rk805_irq_chip;
  		pre_init_reg = rk805_pre_init_reg;
  		nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
  		cells = rk805s;
  		nr_cells = ARRAY_SIZE(rk805s);
990f05f6a   Elaine Zhang   mfd: rk808: Add R...
536
  		break;
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
  	case RK808_ID:
  		rk808->regmap_cfg = &rk808_regmap_config;
  		rk808->regmap_irq_chip = &rk808_irq_chip;
  		pre_init_reg = rk808_pre_init_reg;
  		nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
  		cells = rk808s;
  		nr_cells = ARRAY_SIZE(rk808s);
  		break;
  	case RK818_ID:
  		rk808->regmap_cfg = &rk818_regmap_config;
  		rk808->regmap_irq_chip = &rk818_irq_chip;
  		pre_init_reg = rk818_pre_init_reg;
  		nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
  		cells = rk818s;
  		nr_cells = ARRAY_SIZE(rk818s);
  		break;
586c1b412   Tony Xie   mfd: rk808: Add R...
553
554
555
556
557
558
559
560
  	case RK809_ID:
  	case RK817_ID:
  		rk808->regmap_cfg = &rk817_regmap_config;
  		rk808->regmap_irq_chip = &rk817_irq_chip;
  		pre_init_reg = rk817_pre_init_reg;
  		nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg);
  		cells = rk817s;
  		nr_cells = ARRAY_SIZE(rk817s);
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
561
562
563
564
565
566
567
568
569
570
571
572
  		break;
  	default:
  		dev_err(&client->dev, "Unsupported RK8XX ID %lu
  ",
  			rk808->variant);
  		return -EINVAL;
  	}
  
  	rk808->i2c = client;
  	i2c_set_clientdata(client, rk808);
  
  	rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg);
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
573
574
575
576
577
  	if (IS_ERR(rk808->regmap)) {
  		dev_err(&client->dev, "regmap initialization failed
  ");
  		return PTR_ERR(rk808->regmap);
  	}
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
578
579
580
581
  	if (!client->irq) {
  		dev_err(&client->dev, "No interrupt support, no core IRQ
  ");
  		return -EINVAL;
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
582
583
584
585
  	}
  
  	ret = regmap_add_irq_chip(rk808->regmap, client->irq,
  				  IRQF_ONESHOT, -1,
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
586
  				  rk808->regmap_irq_chip, &rk808->irq_data);
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
587
588
589
590
591
  	if (ret) {
  		dev_err(&client->dev, "Failed to add irq_chip %d
  ", ret);
  		return ret;
  	}
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
592
593
594
595
596
597
598
599
600
601
602
603
604
  	for (i = 0; i < nr_pre_init_regs; i++) {
  		ret = regmap_update_bits(rk808->regmap,
  					pre_init_reg[i].addr,
  					pre_init_reg[i].mask,
  					pre_init_reg[i].value);
  		if (ret) {
  			dev_err(&client->dev,
  				"0x%x write err
  ",
  				pre_init_reg[i].addr);
  			return ret;
  		}
  	}
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
605

2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
606
607
608
  	ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
  			      cells, nr_cells, NULL, 0,
  			      regmap_irq_get_domain(rk808->irq_data));
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
609
610
611
612
613
  	if (ret) {
  		dev_err(&client->dev, "failed to add MFD devices %d
  ", ret);
  		goto err_irq;
  	}
d8f083a30   Soeren Moch   mfd: rk808: Alway...
614
  	if (of_property_read_bool(np, "rockchip,system-power-controller")) {
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
615
  		rk808_i2c_client = client;
7a52cbcce   Robin Murphy   mfd: rk808: Reduc...
616
  		pm_power_off = rk808_pm_power_off;
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
617
618
619
620
621
622
623
624
625
626
627
628
629
630
  	}
  
  	return 0;
  
  err_irq:
  	regmap_del_irq_chip(client->irq, rk808->irq_data);
  	return ret;
  }
  
  static int rk808_remove(struct i2c_client *client)
  {
  	struct rk808 *rk808 = i2c_get_clientdata(client);
  
  	regmap_del_irq_chip(client->irq, rk808->irq_data);
763049946   Stefan Mavrodiev   mfd: rk808: Check...
631
632
633
634
635
  
  	/**
  	 * pm_power_off may points to a function from another module.
  	 * Check if the pointer is set by us and only then overwrite it.
  	 */
7a52cbcce   Robin Murphy   mfd: rk808: Reduc...
636
  	if (pm_power_off == rk808_pm_power_off)
763049946   Stefan Mavrodiev   mfd: rk808: Check...
637
  		pm_power_off = NULL;
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
638
639
640
  
  	return 0;
  }
5752bc437   Arnd Bergmann   mfd: rk808: Mark ...
641
  static int __maybe_unused rk8xx_suspend(struct device *dev)
586c1b412   Tony Xie   mfd: rk808: Add R...
642
  {
08e8c0d9e   Robin Murphy   mfd: rk808: Ensur...
643
  	struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev));
586c1b412   Tony Xie   mfd: rk808: Add R...
644
645
646
  	int ret = 0;
  
  	switch (rk808->variant) {
42679765f   Robin Murphy   mfd: rk808: Conve...
647
648
649
650
651
652
  	case RK805_ID:
  		ret = regmap_update_bits(rk808->regmap,
  					 RK805_GPIO_IO_POL_REG,
  					 SLP_SD_MSK,
  					 SLEEP_FUN);
  		break;
586c1b412   Tony Xie   mfd: rk808: Add R...
653
654
655
656
657
658
659
660
661
662
663
664
665
  	case RK809_ID:
  	case RK817_ID:
  		ret = regmap_update_bits(rk808->regmap,
  					 RK817_SYS_CFG(3),
  					 RK817_SLPPIN_FUNC_MSK,
  					 SLPPIN_SLP_FUN);
  		break;
  	default:
  		break;
  	}
  
  	return ret;
  }
5752bc437   Arnd Bergmann   mfd: rk808: Mark ...
666
  static int __maybe_unused rk8xx_resume(struct device *dev)
586c1b412   Tony Xie   mfd: rk808: Add R...
667
  {
08e8c0d9e   Robin Murphy   mfd: rk808: Ensur...
668
  	struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev));
586c1b412   Tony Xie   mfd: rk808: Add R...
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
  	int ret = 0;
  
  	switch (rk808->variant) {
  	case RK809_ID:
  	case RK817_ID:
  		ret = regmap_update_bits(rk808->regmap,
  					 RK817_SYS_CFG(3),
  					 RK817_SLPPIN_FUNC_MSK,
  					 SLPPIN_NULL_FUN);
  		break;
  	default:
  		break;
  	}
  
  	return ret;
  }
4d82fa67d   Lee Jones   mfd: rk808: Make ...
685
  static SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume);
586c1b412   Tony Xie   mfd: rk808: Add R...
686

f69a7cf74   Chris Zhong   mfd: RK808: Add n...
687
688
689
690
  static struct i2c_driver rk808_i2c_driver = {
  	.driver = {
  		.name = "rk808",
  		.of_match_table = rk808_of_match,
586c1b412   Tony Xie   mfd: rk808: Add R...
691
  		.pm = &rk8xx_pm_ops,
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
692
693
694
  	},
  	.probe    = rk808_probe,
  	.remove   = rk808_remove,
90df3a823   Robin Murphy   mfd: rk808: Stop ...
695
  	.shutdown = rk8xx_shutdown,
f69a7cf74   Chris Zhong   mfd: RK808: Add n...
696
697
698
699
700
701
702
  };
  
  module_i2c_driver(rk808_i2c_driver);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
  MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
2eedcbfc0   Wadim Egorov   mfd: rk808: Add R...
703
704
  MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
  MODULE_DESCRIPTION("RK808/RK818 PMIC driver");