1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * MFD core driver for Rockchip RK8XX |
4 | * |
5 | * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd |
6 | * Copyright (C) 2016 PHYTEC Messtechnik GmbH |
7 | * |
8 | * Author: Chris Zhong <zyw@rock-chips.com> |
9 | * Author: Zhang Qing <zhangqing@rock-chips.com> |
10 | * Author: Wadim Egorov <w.egorov@phytec.de> |
11 | */ |
12 | |
13 | #include <linux/interrupt.h> |
14 | #include <linux/mfd/rk808.h> |
15 | #include <linux/mfd/core.h> |
16 | #include <linux/module.h> |
17 | #include <linux/property.h> |
18 | #include <linux/regmap.h> |
19 | #include <linux/reboot.h> |
20 | |
21 | struct rk808_reg_data { |
22 | int addr; |
23 | int mask; |
24 | int value; |
25 | }; |
26 | |
27 | static const struct resource rtc_resources[] = { |
28 | DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM), |
29 | }; |
30 | |
31 | static const struct resource rk817_rtc_resources[] = { |
32 | DEFINE_RES_IRQ(RK817_IRQ_RTC_ALARM), |
33 | }; |
34 | |
35 | static const struct resource rk805_key_resources[] = { |
36 | DEFINE_RES_IRQ(RK805_IRQ_PWRON_RISE), |
37 | DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL), |
38 | }; |
39 | |
40 | static struct resource rk806_pwrkey_resources[] = { |
41 | DEFINE_RES_IRQ(RK806_IRQ_PWRON_FALL), |
42 | DEFINE_RES_IRQ(RK806_IRQ_PWRON_RISE), |
43 | }; |
44 | |
45 | static const struct resource rk817_pwrkey_resources[] = { |
46 | DEFINE_RES_IRQ(RK817_IRQ_PWRON_FALL), |
47 | DEFINE_RES_IRQ(RK817_IRQ_PWRON_RISE), |
48 | }; |
49 | |
50 | static const struct resource rk817_charger_resources[] = { |
51 | DEFINE_RES_IRQ(RK817_IRQ_PLUG_IN), |
52 | DEFINE_RES_IRQ(RK817_IRQ_PLUG_OUT), |
53 | }; |
54 | |
55 | static const struct mfd_cell rk805s[] = { |
56 | { .name = "rk808-clkout" , }, |
57 | { .name = "rk808-regulator" , }, |
58 | { .name = "rk805-pinctrl" , }, |
59 | { |
60 | .name = "rk808-rtc" , |
61 | .num_resources = ARRAY_SIZE(rtc_resources), |
62 | .resources = &rtc_resources[0], |
63 | }, |
64 | { .name = "rk805-pwrkey" , |
65 | .num_resources = ARRAY_SIZE(rk805_key_resources), |
66 | .resources = &rk805_key_resources[0], |
67 | }, |
68 | }; |
69 | |
70 | static const struct mfd_cell rk806s[] = { |
71 | { .name = "rk805-pinctrl" , }, |
72 | { .name = "rk808-regulator" , }, |
73 | { |
74 | .name = "rk805-pwrkey" , |
75 | .resources = rk806_pwrkey_resources, |
76 | .num_resources = ARRAY_SIZE(rk806_pwrkey_resources), |
77 | }, |
78 | }; |
79 | |
80 | static const struct mfd_cell rk808s[] = { |
81 | { .name = "rk808-clkout" , }, |
82 | { .name = "rk808-regulator" , }, |
83 | { |
84 | .name = "rk808-rtc" , |
85 | .num_resources = ARRAY_SIZE(rtc_resources), |
86 | .resources = rtc_resources, |
87 | }, |
88 | }; |
89 | |
90 | static const struct mfd_cell rk817s[] = { |
91 | { .name = "rk808-clkout" , }, |
92 | { .name = "rk808-regulator" , }, |
93 | { |
94 | .name = "rk805-pwrkey" , |
95 | .num_resources = ARRAY_SIZE(rk817_pwrkey_resources), |
96 | .resources = &rk817_pwrkey_resources[0], |
97 | }, |
98 | { |
99 | .name = "rk808-rtc" , |
100 | .num_resources = ARRAY_SIZE(rk817_rtc_resources), |
101 | .resources = &rk817_rtc_resources[0], |
102 | }, |
103 | { .name = "rk817-codec" , }, |
104 | { |
105 | .name = "rk817-charger" , |
106 | .num_resources = ARRAY_SIZE(rk817_charger_resources), |
107 | .resources = &rk817_charger_resources[0], |
108 | }, |
109 | }; |
110 | |
111 | static const struct mfd_cell rk818s[] = { |
112 | { .name = "rk808-clkout" , }, |
113 | { .name = "rk808-regulator" , }, |
114 | { |
115 | .name = "rk808-rtc" , |
116 | .num_resources = ARRAY_SIZE(rtc_resources), |
117 | .resources = rtc_resources, |
118 | }, |
119 | }; |
120 | |
121 | static const struct rk808_reg_data rk805_pre_init_reg[] = { |
122 | {RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK, |
123 | RK805_BUCK1_2_ILMAX_4000MA}, |
124 | {RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK, |
125 | RK805_BUCK1_2_ILMAX_4000MA}, |
126 | {RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK, |
127 | RK805_BUCK3_ILMAX_3000MA}, |
128 | {RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK, |
129 | RK805_BUCK4_ILMAX_3500MA}, |
130 | {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA}, |
131 | {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C}, |
132 | }; |
133 | |
134 | static const struct rk808_reg_data rk806_pre_init_reg[] = { |
135 | { RK806_GPIO_INT_CONFIG, RK806_INT_POL_MSK, RK806_INT_POL_L }, |
136 | { RK806_SYS_CFG3, RK806_SLAVE_RESTART_FUN_MSK, RK806_SLAVE_RESTART_FUN_EN }, |
137 | { RK806_SYS_OPTION, RK806_SYS_ENB2_2M_MSK, RK806_SYS_ENB2_2M_EN }, |
138 | }; |
139 | |
140 | static const struct rk808_reg_data rk808_pre_init_reg[] = { |
141 | { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, |
142 | { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, |
143 | { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA }, |
144 | { RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA }, |
145 | { RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA }, |
146 | { RK808_DCDC_UV_ACT_REG, BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE}, |
147 | { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | |
148 | VB_LO_SEL_3500MV }, |
149 | }; |
150 | |
151 | static const struct rk808_reg_data rk817_pre_init_reg[] = { |
152 | {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, |
153 | /* Codec specific registers */ |
154 | { RK817_CODEC_DTOP_VUCTL, MASK_ALL, 0x03 }, |
155 | { RK817_CODEC_DTOP_VUCTIME, MASK_ALL, 0x00 }, |
156 | { RK817_CODEC_DTOP_LPT_SRST, MASK_ALL, 0x00 }, |
157 | { RK817_CODEC_DTOP_DIGEN_CLKE, MASK_ALL, 0x00 }, |
158 | /* from vendor driver, CODEC_AREF_RTCFG0 not defined in data sheet */ |
159 | { RK817_CODEC_AREF_RTCFG0, MASK_ALL, 0x00 }, |
160 | { RK817_CODEC_AREF_RTCFG1, MASK_ALL, 0x06 }, |
161 | { RK817_CODEC_AADC_CFG0, MASK_ALL, 0xc8 }, |
162 | /* from vendor driver, CODEC_AADC_CFG1 not defined in data sheet */ |
163 | { RK817_CODEC_AADC_CFG1, MASK_ALL, 0x00 }, |
164 | { RK817_CODEC_DADC_VOLL, MASK_ALL, 0x00 }, |
165 | { RK817_CODEC_DADC_VOLR, MASK_ALL, 0x00 }, |
166 | { RK817_CODEC_DADC_SR_ACL0, MASK_ALL, 0x00 }, |
167 | { RK817_CODEC_DADC_ALC1, MASK_ALL, 0x00 }, |
168 | { RK817_CODEC_DADC_ALC2, MASK_ALL, 0x00 }, |
169 | { RK817_CODEC_DADC_NG, MASK_ALL, 0x00 }, |
170 | { RK817_CODEC_DADC_HPF, MASK_ALL, 0x00 }, |
171 | { RK817_CODEC_DADC_RVOLL, MASK_ALL, 0xff }, |
172 | { RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff }, |
173 | { RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 }, |
174 | { RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 }, |
175 | { RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 }, |
176 | { RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 }, |
177 | { RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 }, |
178 | { RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 }, |
179 | { RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 }, |
180 | /* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */ |
181 | { RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 }, |
182 | { RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 }, |
183 | { RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 }, |
184 | { RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 }, |
185 | { RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 }, |
186 | { RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 }, |
187 | { RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 }, |
188 | { RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 }, |
189 | { RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 }, |
190 | { RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff }, |
191 | { RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff }, |
192 | { RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 }, |
193 | { RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 }, |
194 | { RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 }, |
195 | { RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 }, |
196 | { RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 }, |
197 | { RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 }, |
198 | { RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 }, |
199 | /* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */ |
200 | { RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 }, |
201 | { RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 }, |
202 | { RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 }, |
203 | { RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 }, |
204 | { RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 }, |
205 | { RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 }, |
206 | { RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 }, |
207 | { RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 }, |
208 | { RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 }, |
209 | { RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff }, |
210 | { RK817_CODEC_DDAC_RVOLR, MASK_ALL, 0xff }, |
211 | { RK817_CODEC_AHP_ANTI0, MASK_ALL, 0x00 }, |
212 | { RK817_CODEC_AHP_ANTI1, MASK_ALL, 0x00 }, |
213 | { RK817_CODEC_AHP_CFG0, MASK_ALL, 0xe0 }, |
214 | { RK817_CODEC_AHP_CFG1, MASK_ALL, 0x1f }, |
215 | { RK817_CODEC_AHP_CP, MASK_ALL, 0x09 }, |
216 | { RK817_CODEC_ACLASSD_CFG1, MASK_ALL, 0x69 }, |
217 | { RK817_CODEC_ACLASSD_CFG2, MASK_ALL, 0x44 }, |
218 | { RK817_CODEC_APLL_CFG0, MASK_ALL, 0x04 }, |
219 | { RK817_CODEC_APLL_CFG1, MASK_ALL, 0x00 }, |
220 | { RK817_CODEC_APLL_CFG2, MASK_ALL, 0x30 }, |
221 | { RK817_CODEC_APLL_CFG3, MASK_ALL, 0x19 }, |
222 | { RK817_CODEC_APLL_CFG4, MASK_ALL, 0x65 }, |
223 | { RK817_CODEC_APLL_CFG5, MASK_ALL, 0x01 }, |
224 | { RK817_CODEC_DI2S_CKM, MASK_ALL, 0x01 }, |
225 | { RK817_CODEC_DI2S_RSD, MASK_ALL, 0x00 }, |
226 | { RK817_CODEC_DI2S_RXCR1, MASK_ALL, 0x00 }, |
227 | { RK817_CODEC_DI2S_RXCR2, MASK_ALL, 0x17 }, |
228 | { RK817_CODEC_DI2S_RXCMD_TSD, MASK_ALL, 0x00 }, |
229 | { RK817_CODEC_DI2S_TXCR1, MASK_ALL, 0x00 }, |
230 | { RK817_CODEC_DI2S_TXCR2, MASK_ALL, 0x17 }, |
231 | { RK817_CODEC_DI2S_TXCR3_TXCMD, MASK_ALL, 0x00 }, |
232 | {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L}, |
233 | {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK, |
234 | RK817_HOTDIE_105 | RK817_TSD_140}, |
235 | }; |
236 | |
237 | static const struct rk808_reg_data rk818_pre_init_reg[] = { |
238 | /* improve efficiency */ |
239 | { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA }, |
240 | { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA }, |
241 | { RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA }, |
242 | { RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK, |
243 | RK818_USB_ILMIN_2000MA }, |
244 | /* close charger when usb lower then 3.4V */ |
245 | { RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK, |
246 | (0x7 << 4) }, |
247 | /* no action when vref */ |
248 | { RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL }, |
249 | /* enable HDMI 5V */ |
250 | { RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN }, |
251 | { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | |
252 | VB_LO_SEL_3500MV }, |
253 | }; |
254 | |
255 | static const struct regmap_irq rk805_irqs[] = { |
256 | [RK805_IRQ_PWRON_RISE] = { |
257 | .mask = RK805_IRQ_PWRON_RISE_MSK, |
258 | .reg_offset = 0, |
259 | }, |
260 | [RK805_IRQ_VB_LOW] = { |
261 | .mask = RK805_IRQ_VB_LOW_MSK, |
262 | .reg_offset = 0, |
263 | }, |
264 | [RK805_IRQ_PWRON] = { |
265 | .mask = RK805_IRQ_PWRON_MSK, |
266 | .reg_offset = 0, |
267 | }, |
268 | [RK805_IRQ_PWRON_LP] = { |
269 | .mask = RK805_IRQ_PWRON_LP_MSK, |
270 | .reg_offset = 0, |
271 | }, |
272 | [RK805_IRQ_HOTDIE] = { |
273 | .mask = RK805_IRQ_HOTDIE_MSK, |
274 | .reg_offset = 0, |
275 | }, |
276 | [RK805_IRQ_RTC_ALARM] = { |
277 | .mask = RK805_IRQ_RTC_ALARM_MSK, |
278 | .reg_offset = 0, |
279 | }, |
280 | [RK805_IRQ_RTC_PERIOD] = { |
281 | .mask = RK805_IRQ_RTC_PERIOD_MSK, |
282 | .reg_offset = 0, |
283 | }, |
284 | [RK805_IRQ_PWRON_FALL] = { |
285 | .mask = RK805_IRQ_PWRON_FALL_MSK, |
286 | .reg_offset = 0, |
287 | }, |
288 | }; |
289 | |
290 | static const struct regmap_irq rk806_irqs[] = { |
291 | /* INT_STS0 IRQs */ |
292 | REGMAP_IRQ_REG(RK806_IRQ_PWRON_FALL, 0, RK806_INT_STS_PWRON_FALL), |
293 | REGMAP_IRQ_REG(RK806_IRQ_PWRON_RISE, 0, RK806_INT_STS_PWRON_RISE), |
294 | REGMAP_IRQ_REG(RK806_IRQ_PWRON, 0, RK806_INT_STS_PWRON), |
295 | REGMAP_IRQ_REG(RK806_IRQ_PWRON_LP, 0, RK806_INT_STS_PWRON_LP), |
296 | REGMAP_IRQ_REG(RK806_IRQ_HOTDIE, 0, RK806_INT_STS_HOTDIE), |
297 | REGMAP_IRQ_REG(RK806_IRQ_VDC_RISE, 0, RK806_INT_STS_VDC_RISE), |
298 | REGMAP_IRQ_REG(RK806_IRQ_VDC_FALL, 0, RK806_INT_STS_VDC_FALL), |
299 | REGMAP_IRQ_REG(RK806_IRQ_VB_LO, 0, RK806_INT_STS_VB_LO), |
300 | /* INT_STS1 IRQs */ |
301 | REGMAP_IRQ_REG(RK806_IRQ_REV0, 1, RK806_INT_STS_REV0), |
302 | REGMAP_IRQ_REG(RK806_IRQ_REV1, 1, RK806_INT_STS_REV1), |
303 | REGMAP_IRQ_REG(RK806_IRQ_REV2, 1, RK806_INT_STS_REV2), |
304 | REGMAP_IRQ_REG(RK806_IRQ_CRC_ERROR, 1, RK806_INT_STS_CRC_ERROR), |
305 | REGMAP_IRQ_REG(RK806_IRQ_SLP3_GPIO, 1, RK806_INT_STS_SLP3_GPIO), |
306 | REGMAP_IRQ_REG(RK806_IRQ_SLP2_GPIO, 1, RK806_INT_STS_SLP2_GPIO), |
307 | REGMAP_IRQ_REG(RK806_IRQ_SLP1_GPIO, 1, RK806_INT_STS_SLP1_GPIO), |
308 | REGMAP_IRQ_REG(RK806_IRQ_WDT, 1, RK806_INT_STS_WDT), |
309 | }; |
310 | |
311 | static const struct regmap_irq rk808_irqs[] = { |
312 | /* INT_STS */ |
313 | [RK808_IRQ_VOUT_LO] = { |
314 | .mask = RK808_IRQ_VOUT_LO_MSK, |
315 | .reg_offset = 0, |
316 | }, |
317 | [RK808_IRQ_VB_LO] = { |
318 | .mask = RK808_IRQ_VB_LO_MSK, |
319 | .reg_offset = 0, |
320 | }, |
321 | [RK808_IRQ_PWRON] = { |
322 | .mask = RK808_IRQ_PWRON_MSK, |
323 | .reg_offset = 0, |
324 | }, |
325 | [RK808_IRQ_PWRON_LP] = { |
326 | .mask = RK808_IRQ_PWRON_LP_MSK, |
327 | .reg_offset = 0, |
328 | }, |
329 | [RK808_IRQ_HOTDIE] = { |
330 | .mask = RK808_IRQ_HOTDIE_MSK, |
331 | .reg_offset = 0, |
332 | }, |
333 | [RK808_IRQ_RTC_ALARM] = { |
334 | .mask = RK808_IRQ_RTC_ALARM_MSK, |
335 | .reg_offset = 0, |
336 | }, |
337 | [RK808_IRQ_RTC_PERIOD] = { |
338 | .mask = RK808_IRQ_RTC_PERIOD_MSK, |
339 | .reg_offset = 0, |
340 | }, |
341 | |
342 | /* INT_STS2 */ |
343 | [RK808_IRQ_PLUG_IN_INT] = { |
344 | .mask = RK808_IRQ_PLUG_IN_INT_MSK, |
345 | .reg_offset = 1, |
346 | }, |
347 | [RK808_IRQ_PLUG_OUT_INT] = { |
348 | .mask = RK808_IRQ_PLUG_OUT_INT_MSK, |
349 | .reg_offset = 1, |
350 | }, |
351 | }; |
352 | |
353 | static const struct regmap_irq rk818_irqs[] = { |
354 | /* INT_STS */ |
355 | [RK818_IRQ_VOUT_LO] = { |
356 | .mask = RK818_IRQ_VOUT_LO_MSK, |
357 | .reg_offset = 0, |
358 | }, |
359 | [RK818_IRQ_VB_LO] = { |
360 | .mask = RK818_IRQ_VB_LO_MSK, |
361 | .reg_offset = 0, |
362 | }, |
363 | [RK818_IRQ_PWRON] = { |
364 | .mask = RK818_IRQ_PWRON_MSK, |
365 | .reg_offset = 0, |
366 | }, |
367 | [RK818_IRQ_PWRON_LP] = { |
368 | .mask = RK818_IRQ_PWRON_LP_MSK, |
369 | .reg_offset = 0, |
370 | }, |
371 | [RK818_IRQ_HOTDIE] = { |
372 | .mask = RK818_IRQ_HOTDIE_MSK, |
373 | .reg_offset = 0, |
374 | }, |
375 | [RK818_IRQ_RTC_ALARM] = { |
376 | .mask = RK818_IRQ_RTC_ALARM_MSK, |
377 | .reg_offset = 0, |
378 | }, |
379 | [RK818_IRQ_RTC_PERIOD] = { |
380 | .mask = RK818_IRQ_RTC_PERIOD_MSK, |
381 | .reg_offset = 0, |
382 | }, |
383 | [RK818_IRQ_USB_OV] = { |
384 | .mask = RK818_IRQ_USB_OV_MSK, |
385 | .reg_offset = 0, |
386 | }, |
387 | |
388 | /* INT_STS2 */ |
389 | [RK818_IRQ_PLUG_IN] = { |
390 | .mask = RK818_IRQ_PLUG_IN_MSK, |
391 | .reg_offset = 1, |
392 | }, |
393 | [RK818_IRQ_PLUG_OUT] = { |
394 | .mask = RK818_IRQ_PLUG_OUT_MSK, |
395 | .reg_offset = 1, |
396 | }, |
397 | [RK818_IRQ_CHG_OK] = { |
398 | .mask = RK818_IRQ_CHG_OK_MSK, |
399 | .reg_offset = 1, |
400 | }, |
401 | [RK818_IRQ_CHG_TE] = { |
402 | .mask = RK818_IRQ_CHG_TE_MSK, |
403 | .reg_offset = 1, |
404 | }, |
405 | [RK818_IRQ_CHG_TS1] = { |
406 | .mask = RK818_IRQ_CHG_TS1_MSK, |
407 | .reg_offset = 1, |
408 | }, |
409 | [RK818_IRQ_TS2] = { |
410 | .mask = RK818_IRQ_TS2_MSK, |
411 | .reg_offset = 1, |
412 | }, |
413 | [RK818_IRQ_CHG_CVTLIM] = { |
414 | .mask = RK818_IRQ_CHG_CVTLIM_MSK, |
415 | .reg_offset = 1, |
416 | }, |
417 | [RK818_IRQ_DISCHG_ILIM] = { |
418 | .mask = RK818_IRQ_DISCHG_ILIM_MSK, |
419 | .reg_offset = 1, |
420 | }, |
421 | }; |
422 | |
423 | static const struct regmap_irq rk817_irqs[RK817_IRQ_END] = { |
424 | REGMAP_IRQ_REG_LINE(0, 8), |
425 | REGMAP_IRQ_REG_LINE(1, 8), |
426 | REGMAP_IRQ_REG_LINE(2, 8), |
427 | REGMAP_IRQ_REG_LINE(3, 8), |
428 | REGMAP_IRQ_REG_LINE(4, 8), |
429 | REGMAP_IRQ_REG_LINE(5, 8), |
430 | REGMAP_IRQ_REG_LINE(6, 8), |
431 | REGMAP_IRQ_REG_LINE(7, 8), |
432 | REGMAP_IRQ_REG_LINE(8, 8), |
433 | REGMAP_IRQ_REG_LINE(9, 8), |
434 | REGMAP_IRQ_REG_LINE(10, 8), |
435 | REGMAP_IRQ_REG_LINE(11, 8), |
436 | REGMAP_IRQ_REG_LINE(12, 8), |
437 | REGMAP_IRQ_REG_LINE(13, 8), |
438 | REGMAP_IRQ_REG_LINE(14, 8), |
439 | REGMAP_IRQ_REG_LINE(15, 8), |
440 | REGMAP_IRQ_REG_LINE(16, 8), |
441 | REGMAP_IRQ_REG_LINE(17, 8), |
442 | REGMAP_IRQ_REG_LINE(18, 8), |
443 | REGMAP_IRQ_REG_LINE(19, 8), |
444 | REGMAP_IRQ_REG_LINE(20, 8), |
445 | REGMAP_IRQ_REG_LINE(21, 8), |
446 | REGMAP_IRQ_REG_LINE(22, 8), |
447 | REGMAP_IRQ_REG_LINE(23, 8) |
448 | }; |
449 | |
450 | static struct regmap_irq_chip rk805_irq_chip = { |
451 | .name = "rk805" , |
452 | .irqs = rk805_irqs, |
453 | .num_irqs = ARRAY_SIZE(rk805_irqs), |
454 | .num_regs = 1, |
455 | .status_base = RK805_INT_STS_REG, |
456 | .mask_base = RK805_INT_STS_MSK_REG, |
457 | .ack_base = RK805_INT_STS_REG, |
458 | .init_ack_masked = true, |
459 | }; |
460 | |
461 | static struct regmap_irq_chip rk806_irq_chip = { |
462 | .name = "rk806" , |
463 | .irqs = rk806_irqs, |
464 | .num_irqs = ARRAY_SIZE(rk806_irqs), |
465 | .num_regs = 2, |
466 | .irq_reg_stride = 2, |
467 | .mask_base = RK806_INT_MSK0, |
468 | .status_base = RK806_INT_STS0, |
469 | .ack_base = RK806_INT_STS0, |
470 | .init_ack_masked = true, |
471 | }; |
472 | |
473 | static const struct regmap_irq_chip rk808_irq_chip = { |
474 | .name = "rk808" , |
475 | .irqs = rk808_irqs, |
476 | .num_irqs = ARRAY_SIZE(rk808_irqs), |
477 | .num_regs = 2, |
478 | .irq_reg_stride = 2, |
479 | .status_base = RK808_INT_STS_REG1, |
480 | .mask_base = RK808_INT_STS_MSK_REG1, |
481 | .ack_base = RK808_INT_STS_REG1, |
482 | .init_ack_masked = true, |
483 | }; |
484 | |
485 | static struct regmap_irq_chip rk817_irq_chip = { |
486 | .name = "rk817" , |
487 | .irqs = rk817_irqs, |
488 | .num_irqs = ARRAY_SIZE(rk817_irqs), |
489 | .num_regs = 3, |
490 | .irq_reg_stride = 2, |
491 | .status_base = RK817_INT_STS_REG0, |
492 | .mask_base = RK817_INT_STS_MSK_REG0, |
493 | .ack_base = RK817_INT_STS_REG0, |
494 | .init_ack_masked = true, |
495 | }; |
496 | |
497 | static const struct regmap_irq_chip rk818_irq_chip = { |
498 | .name = "rk818" , |
499 | .irqs = rk818_irqs, |
500 | .num_irqs = ARRAY_SIZE(rk818_irqs), |
501 | .num_regs = 2, |
502 | .irq_reg_stride = 2, |
503 | .status_base = RK818_INT_STS_REG1, |
504 | .mask_base = RK818_INT_STS_MSK_REG1, |
505 | .ack_base = RK818_INT_STS_REG1, |
506 | .init_ack_masked = true, |
507 | }; |
508 | |
509 | static int rk808_power_off(struct sys_off_data *data) |
510 | { |
511 | struct rk808 *rk808 = data->cb_data; |
512 | int ret; |
513 | unsigned int reg, bit; |
514 | |
515 | switch (rk808->variant) { |
516 | case RK805_ID: |
517 | reg = RK805_DEV_CTRL_REG; |
518 | bit = DEV_OFF; |
519 | break; |
520 | case RK806_ID: |
521 | reg = RK806_SYS_CFG3; |
522 | bit = DEV_OFF; |
523 | break; |
524 | case RK808_ID: |
525 | reg = RK808_DEVCTRL_REG, |
526 | bit = DEV_OFF_RST; |
527 | break; |
528 | case RK809_ID: |
529 | case RK817_ID: |
530 | reg = RK817_SYS_CFG(3); |
531 | bit = DEV_OFF; |
532 | break; |
533 | case RK818_ID: |
534 | reg = RK818_DEVCTRL_REG; |
535 | bit = DEV_OFF; |
536 | break; |
537 | default: |
538 | return NOTIFY_DONE; |
539 | } |
540 | ret = regmap_update_bits(map: rk808->regmap, reg, mask: bit, val: bit); |
541 | if (ret) |
542 | dev_err(rk808->dev, "Failed to shutdown device!\n" ); |
543 | |
544 | return NOTIFY_DONE; |
545 | } |
546 | |
547 | static int rk808_restart(struct sys_off_data *data) |
548 | { |
549 | struct rk808 *rk808 = data->cb_data; |
550 | unsigned int reg, bit; |
551 | int ret; |
552 | |
553 | switch (rk808->variant) { |
554 | case RK809_ID: |
555 | case RK817_ID: |
556 | reg = RK817_SYS_CFG(3); |
557 | bit = DEV_RST; |
558 | break; |
559 | |
560 | default: |
561 | return NOTIFY_DONE; |
562 | } |
563 | ret = regmap_update_bits(map: rk808->regmap, reg, mask: bit, val: bit); |
564 | if (ret) |
565 | dev_err(rk808->dev, "Failed to restart device!\n" ); |
566 | |
567 | return NOTIFY_DONE; |
568 | } |
569 | |
570 | void rk8xx_shutdown(struct device *dev) |
571 | { |
572 | struct rk808 *rk808 = dev_get_drvdata(dev); |
573 | int ret; |
574 | |
575 | switch (rk808->variant) { |
576 | case RK805_ID: |
577 | ret = regmap_update_bits(map: rk808->regmap, |
578 | RK805_GPIO_IO_POL_REG, |
579 | SLP_SD_MSK, |
580 | SHUTDOWN_FUN); |
581 | break; |
582 | case RK809_ID: |
583 | case RK817_ID: |
584 | ret = regmap_update_bits(map: rk808->regmap, |
585 | RK817_SYS_CFG(3), |
586 | RK817_SLPPIN_FUNC_MSK, |
587 | SLPPIN_DN_FUN); |
588 | break; |
589 | default: |
590 | return; |
591 | } |
592 | if (ret) |
593 | dev_warn(dev, |
594 | "Cannot switch to power down function\n" ); |
595 | } |
596 | EXPORT_SYMBOL_GPL(rk8xx_shutdown); |
597 | |
598 | int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap *regmap) |
599 | { |
600 | struct rk808 *rk808; |
601 | const struct rk808_reg_data *pre_init_reg; |
602 | const struct mfd_cell *cells; |
603 | int dual_support = 0; |
604 | int nr_pre_init_regs; |
605 | int nr_cells; |
606 | int ret; |
607 | int i; |
608 | |
609 | rk808 = devm_kzalloc(dev, size: sizeof(*rk808), GFP_KERNEL); |
610 | if (!rk808) |
611 | return -ENOMEM; |
612 | rk808->dev = dev; |
613 | rk808->variant = variant; |
614 | rk808->regmap = regmap; |
615 | dev_set_drvdata(dev, data: rk808); |
616 | |
617 | switch (rk808->variant) { |
618 | case RK805_ID: |
619 | rk808->regmap_irq_chip = &rk805_irq_chip; |
620 | pre_init_reg = rk805_pre_init_reg; |
621 | nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg); |
622 | cells = rk805s; |
623 | nr_cells = ARRAY_SIZE(rk805s); |
624 | break; |
625 | case RK806_ID: |
626 | rk808->regmap_irq_chip = &rk806_irq_chip; |
627 | pre_init_reg = rk806_pre_init_reg; |
628 | nr_pre_init_regs = ARRAY_SIZE(rk806_pre_init_reg); |
629 | cells = rk806s; |
630 | nr_cells = ARRAY_SIZE(rk806s); |
631 | dual_support = IRQF_SHARED; |
632 | break; |
633 | case RK808_ID: |
634 | rk808->regmap_irq_chip = &rk808_irq_chip; |
635 | pre_init_reg = rk808_pre_init_reg; |
636 | nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg); |
637 | cells = rk808s; |
638 | nr_cells = ARRAY_SIZE(rk808s); |
639 | break; |
640 | case RK818_ID: |
641 | rk808->regmap_irq_chip = &rk818_irq_chip; |
642 | pre_init_reg = rk818_pre_init_reg; |
643 | nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg); |
644 | cells = rk818s; |
645 | nr_cells = ARRAY_SIZE(rk818s); |
646 | break; |
647 | case RK809_ID: |
648 | case RK817_ID: |
649 | rk808->regmap_irq_chip = &rk817_irq_chip; |
650 | pre_init_reg = rk817_pre_init_reg; |
651 | nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg); |
652 | cells = rk817s; |
653 | nr_cells = ARRAY_SIZE(rk817s); |
654 | break; |
655 | default: |
656 | dev_err(dev, "Unsupported RK8XX ID %lu\n" , rk808->variant); |
657 | return -EINVAL; |
658 | } |
659 | |
660 | if (!irq) |
661 | return dev_err_probe(dev, err: -EINVAL, fmt: "No interrupt support, no core IRQ\n" ); |
662 | |
663 | ret = devm_regmap_add_irq_chip(dev, map: rk808->regmap, irq, |
664 | IRQF_ONESHOT | dual_support, irq_base: -1, |
665 | chip: rk808->regmap_irq_chip, data: &rk808->irq_data); |
666 | if (ret) |
667 | return dev_err_probe(dev, err: ret, fmt: "Failed to add irq_chip\n" ); |
668 | |
669 | for (i = 0; i < nr_pre_init_regs; i++) { |
670 | ret = regmap_update_bits(map: rk808->regmap, |
671 | reg: pre_init_reg[i].addr, |
672 | mask: pre_init_reg[i].mask, |
673 | val: pre_init_reg[i].value); |
674 | if (ret) |
675 | return dev_err_probe(dev, err: ret, fmt: "0x%x write err\n" , |
676 | pre_init_reg[i].addr); |
677 | } |
678 | |
679 | ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, n_devs: nr_cells, NULL, irq_base: 0, |
680 | irq_domain: regmap_irq_get_domain(data: rk808->irq_data)); |
681 | if (ret) |
682 | return dev_err_probe(dev, err: ret, fmt: "failed to add MFD devices\n" ); |
683 | |
684 | if (device_property_read_bool(dev, propname: "rockchip,system-power-controller" ) || |
685 | device_property_read_bool(dev, propname: "system-power-controller" )) { |
686 | ret = devm_register_sys_off_handler(dev, |
687 | mode: SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH, |
688 | callback: &rk808_power_off, cb_data: rk808); |
689 | if (ret) |
690 | return dev_err_probe(dev, err: ret, |
691 | fmt: "failed to register poweroff handler\n" ); |
692 | |
693 | switch (rk808->variant) { |
694 | case RK809_ID: |
695 | case RK817_ID: |
696 | ret = devm_register_sys_off_handler(dev, |
697 | mode: SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH, |
698 | callback: &rk808_restart, cb_data: rk808); |
699 | if (ret) |
700 | dev_warn(dev, "failed to register rst handler, %d\n" , ret); |
701 | break; |
702 | default: |
703 | dev_dbg(dev, "pmic controlled board reset not supported\n" ); |
704 | break; |
705 | } |
706 | } |
707 | |
708 | return 0; |
709 | } |
710 | EXPORT_SYMBOL_GPL(rk8xx_probe); |
711 | |
712 | int rk8xx_suspend(struct device *dev) |
713 | { |
714 | struct rk808 *rk808 = dev_get_drvdata(dev); |
715 | int ret = 0; |
716 | |
717 | switch (rk808->variant) { |
718 | case RK805_ID: |
719 | ret = regmap_update_bits(map: rk808->regmap, |
720 | RK805_GPIO_IO_POL_REG, |
721 | SLP_SD_MSK, |
722 | SLEEP_FUN); |
723 | break; |
724 | case RK809_ID: |
725 | case RK817_ID: |
726 | ret = regmap_update_bits(map: rk808->regmap, |
727 | RK817_SYS_CFG(3), |
728 | RK817_SLPPIN_FUNC_MSK, |
729 | SLPPIN_SLP_FUN); |
730 | break; |
731 | default: |
732 | break; |
733 | } |
734 | |
735 | return ret; |
736 | } |
737 | EXPORT_SYMBOL_GPL(rk8xx_suspend); |
738 | |
739 | int rk8xx_resume(struct device *dev) |
740 | { |
741 | struct rk808 *rk808 = dev_get_drvdata(dev); |
742 | int ret = 0; |
743 | |
744 | switch (rk808->variant) { |
745 | case RK809_ID: |
746 | case RK817_ID: |
747 | ret = regmap_update_bits(map: rk808->regmap, |
748 | RK817_SYS_CFG(3), |
749 | RK817_SLPPIN_FUNC_MSK, |
750 | SLPPIN_NULL_FUN); |
751 | break; |
752 | default: |
753 | break; |
754 | } |
755 | |
756 | return ret; |
757 | } |
758 | EXPORT_SYMBOL_GPL(rk8xx_resume); |
759 | |
760 | MODULE_LICENSE("GPL" ); |
761 | MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>" ); |
762 | MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>" ); |
763 | MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>" ); |
764 | MODULE_DESCRIPTION("RK8xx PMIC core" ); |
765 | |