1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Device access for Dialog DA9052 PMICs.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright(c) 2011 Dialog Semiconductor Ltd.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: David Dajun Chen <dchen@diasemi.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/delay.h>
12*4882a593Smuzhiyun #include <linux/input.h>
13*4882a593Smuzhiyun #include <linux/interrupt.h>
14*4882a593Smuzhiyun #include <linux/mfd/core.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <linux/module.h>
17*4882a593Smuzhiyun #include <linux/property.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include <linux/mfd/da9052/da9052.h>
20*4882a593Smuzhiyun #include <linux/mfd/da9052/pdata.h>
21*4882a593Smuzhiyun #include <linux/mfd/da9052/reg.h>
22*4882a593Smuzhiyun
da9052_reg_readable(struct device * dev,unsigned int reg)23*4882a593Smuzhiyun static bool da9052_reg_readable(struct device *dev, unsigned int reg)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun switch (reg) {
26*4882a593Smuzhiyun case DA9052_PAGE0_CON_REG:
27*4882a593Smuzhiyun case DA9052_STATUS_A_REG:
28*4882a593Smuzhiyun case DA9052_STATUS_B_REG:
29*4882a593Smuzhiyun case DA9052_STATUS_C_REG:
30*4882a593Smuzhiyun case DA9052_STATUS_D_REG:
31*4882a593Smuzhiyun case DA9052_EVENT_A_REG:
32*4882a593Smuzhiyun case DA9052_EVENT_B_REG:
33*4882a593Smuzhiyun case DA9052_EVENT_C_REG:
34*4882a593Smuzhiyun case DA9052_EVENT_D_REG:
35*4882a593Smuzhiyun case DA9052_FAULTLOG_REG:
36*4882a593Smuzhiyun case DA9052_IRQ_MASK_A_REG:
37*4882a593Smuzhiyun case DA9052_IRQ_MASK_B_REG:
38*4882a593Smuzhiyun case DA9052_IRQ_MASK_C_REG:
39*4882a593Smuzhiyun case DA9052_IRQ_MASK_D_REG:
40*4882a593Smuzhiyun case DA9052_CONTROL_A_REG:
41*4882a593Smuzhiyun case DA9052_CONTROL_B_REG:
42*4882a593Smuzhiyun case DA9052_CONTROL_C_REG:
43*4882a593Smuzhiyun case DA9052_CONTROL_D_REG:
44*4882a593Smuzhiyun case DA9052_PDDIS_REG:
45*4882a593Smuzhiyun case DA9052_INTERFACE_REG:
46*4882a593Smuzhiyun case DA9052_RESET_REG:
47*4882a593Smuzhiyun case DA9052_GPIO_0_1_REG:
48*4882a593Smuzhiyun case DA9052_GPIO_2_3_REG:
49*4882a593Smuzhiyun case DA9052_GPIO_4_5_REG:
50*4882a593Smuzhiyun case DA9052_GPIO_6_7_REG:
51*4882a593Smuzhiyun case DA9052_GPIO_8_9_REG:
52*4882a593Smuzhiyun case DA9052_GPIO_10_11_REG:
53*4882a593Smuzhiyun case DA9052_GPIO_12_13_REG:
54*4882a593Smuzhiyun case DA9052_GPIO_14_15_REG:
55*4882a593Smuzhiyun case DA9052_ID_0_1_REG:
56*4882a593Smuzhiyun case DA9052_ID_2_3_REG:
57*4882a593Smuzhiyun case DA9052_ID_4_5_REG:
58*4882a593Smuzhiyun case DA9052_ID_6_7_REG:
59*4882a593Smuzhiyun case DA9052_ID_8_9_REG:
60*4882a593Smuzhiyun case DA9052_ID_10_11_REG:
61*4882a593Smuzhiyun case DA9052_ID_12_13_REG:
62*4882a593Smuzhiyun case DA9052_ID_14_15_REG:
63*4882a593Smuzhiyun case DA9052_ID_16_17_REG:
64*4882a593Smuzhiyun case DA9052_ID_18_19_REG:
65*4882a593Smuzhiyun case DA9052_ID_20_21_REG:
66*4882a593Smuzhiyun case DA9052_SEQ_STATUS_REG:
67*4882a593Smuzhiyun case DA9052_SEQ_A_REG:
68*4882a593Smuzhiyun case DA9052_SEQ_B_REG:
69*4882a593Smuzhiyun case DA9052_SEQ_TIMER_REG:
70*4882a593Smuzhiyun case DA9052_BUCKA_REG:
71*4882a593Smuzhiyun case DA9052_BUCKB_REG:
72*4882a593Smuzhiyun case DA9052_BUCKCORE_REG:
73*4882a593Smuzhiyun case DA9052_BUCKPRO_REG:
74*4882a593Smuzhiyun case DA9052_BUCKMEM_REG:
75*4882a593Smuzhiyun case DA9052_BUCKPERI_REG:
76*4882a593Smuzhiyun case DA9052_LDO1_REG:
77*4882a593Smuzhiyun case DA9052_LDO2_REG:
78*4882a593Smuzhiyun case DA9052_LDO3_REG:
79*4882a593Smuzhiyun case DA9052_LDO4_REG:
80*4882a593Smuzhiyun case DA9052_LDO5_REG:
81*4882a593Smuzhiyun case DA9052_LDO6_REG:
82*4882a593Smuzhiyun case DA9052_LDO7_REG:
83*4882a593Smuzhiyun case DA9052_LDO8_REG:
84*4882a593Smuzhiyun case DA9052_LDO9_REG:
85*4882a593Smuzhiyun case DA9052_LDO10_REG:
86*4882a593Smuzhiyun case DA9052_SUPPLY_REG:
87*4882a593Smuzhiyun case DA9052_PULLDOWN_REG:
88*4882a593Smuzhiyun case DA9052_CHGBUCK_REG:
89*4882a593Smuzhiyun case DA9052_WAITCONT_REG:
90*4882a593Smuzhiyun case DA9052_ISET_REG:
91*4882a593Smuzhiyun case DA9052_BATCHG_REG:
92*4882a593Smuzhiyun case DA9052_CHG_CONT_REG:
93*4882a593Smuzhiyun case DA9052_INPUT_CONT_REG:
94*4882a593Smuzhiyun case DA9052_CHG_TIME_REG:
95*4882a593Smuzhiyun case DA9052_BBAT_CONT_REG:
96*4882a593Smuzhiyun case DA9052_BOOST_REG:
97*4882a593Smuzhiyun case DA9052_LED_CONT_REG:
98*4882a593Smuzhiyun case DA9052_LEDMIN123_REG:
99*4882a593Smuzhiyun case DA9052_LED1_CONF_REG:
100*4882a593Smuzhiyun case DA9052_LED2_CONF_REG:
101*4882a593Smuzhiyun case DA9052_LED3_CONF_REG:
102*4882a593Smuzhiyun case DA9052_LED1CONT_REG:
103*4882a593Smuzhiyun case DA9052_LED2CONT_REG:
104*4882a593Smuzhiyun case DA9052_LED3CONT_REG:
105*4882a593Smuzhiyun case DA9052_LED_CONT_4_REG:
106*4882a593Smuzhiyun case DA9052_LED_CONT_5_REG:
107*4882a593Smuzhiyun case DA9052_ADC_MAN_REG:
108*4882a593Smuzhiyun case DA9052_ADC_CONT_REG:
109*4882a593Smuzhiyun case DA9052_ADC_RES_L_REG:
110*4882a593Smuzhiyun case DA9052_ADC_RES_H_REG:
111*4882a593Smuzhiyun case DA9052_VDD_RES_REG:
112*4882a593Smuzhiyun case DA9052_VDD_MON_REG:
113*4882a593Smuzhiyun case DA9052_ICHG_AV_REG:
114*4882a593Smuzhiyun case DA9052_ICHG_THD_REG:
115*4882a593Smuzhiyun case DA9052_ICHG_END_REG:
116*4882a593Smuzhiyun case DA9052_TBAT_RES_REG:
117*4882a593Smuzhiyun case DA9052_TBAT_HIGHP_REG:
118*4882a593Smuzhiyun case DA9052_TBAT_HIGHN_REG:
119*4882a593Smuzhiyun case DA9052_TBAT_LOW_REG:
120*4882a593Smuzhiyun case DA9052_T_OFFSET_REG:
121*4882a593Smuzhiyun case DA9052_ADCIN4_RES_REG:
122*4882a593Smuzhiyun case DA9052_AUTO4_HIGH_REG:
123*4882a593Smuzhiyun case DA9052_AUTO4_LOW_REG:
124*4882a593Smuzhiyun case DA9052_ADCIN5_RES_REG:
125*4882a593Smuzhiyun case DA9052_AUTO5_HIGH_REG:
126*4882a593Smuzhiyun case DA9052_AUTO5_LOW_REG:
127*4882a593Smuzhiyun case DA9052_ADCIN6_RES_REG:
128*4882a593Smuzhiyun case DA9052_AUTO6_HIGH_REG:
129*4882a593Smuzhiyun case DA9052_AUTO6_LOW_REG:
130*4882a593Smuzhiyun case DA9052_TJUNC_RES_REG:
131*4882a593Smuzhiyun case DA9052_TSI_CONT_A_REG:
132*4882a593Smuzhiyun case DA9052_TSI_CONT_B_REG:
133*4882a593Smuzhiyun case DA9052_TSI_X_MSB_REG:
134*4882a593Smuzhiyun case DA9052_TSI_Y_MSB_REG:
135*4882a593Smuzhiyun case DA9052_TSI_LSB_REG:
136*4882a593Smuzhiyun case DA9052_TSI_Z_MSB_REG:
137*4882a593Smuzhiyun case DA9052_COUNT_S_REG:
138*4882a593Smuzhiyun case DA9052_COUNT_MI_REG:
139*4882a593Smuzhiyun case DA9052_COUNT_H_REG:
140*4882a593Smuzhiyun case DA9052_COUNT_D_REG:
141*4882a593Smuzhiyun case DA9052_COUNT_MO_REG:
142*4882a593Smuzhiyun case DA9052_COUNT_Y_REG:
143*4882a593Smuzhiyun case DA9052_ALARM_MI_REG:
144*4882a593Smuzhiyun case DA9052_ALARM_H_REG:
145*4882a593Smuzhiyun case DA9052_ALARM_D_REG:
146*4882a593Smuzhiyun case DA9052_ALARM_MO_REG:
147*4882a593Smuzhiyun case DA9052_ALARM_Y_REG:
148*4882a593Smuzhiyun case DA9052_SECOND_A_REG:
149*4882a593Smuzhiyun case DA9052_SECOND_B_REG:
150*4882a593Smuzhiyun case DA9052_SECOND_C_REG:
151*4882a593Smuzhiyun case DA9052_SECOND_D_REG:
152*4882a593Smuzhiyun case DA9052_PAGE1_CON_REG:
153*4882a593Smuzhiyun return true;
154*4882a593Smuzhiyun default:
155*4882a593Smuzhiyun return false;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
da9052_reg_writeable(struct device * dev,unsigned int reg)159*4882a593Smuzhiyun static bool da9052_reg_writeable(struct device *dev, unsigned int reg)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun switch (reg) {
162*4882a593Smuzhiyun case DA9052_PAGE0_CON_REG:
163*4882a593Smuzhiyun case DA9052_EVENT_A_REG:
164*4882a593Smuzhiyun case DA9052_EVENT_B_REG:
165*4882a593Smuzhiyun case DA9052_EVENT_C_REG:
166*4882a593Smuzhiyun case DA9052_EVENT_D_REG:
167*4882a593Smuzhiyun case DA9052_FAULTLOG_REG:
168*4882a593Smuzhiyun case DA9052_IRQ_MASK_A_REG:
169*4882a593Smuzhiyun case DA9052_IRQ_MASK_B_REG:
170*4882a593Smuzhiyun case DA9052_IRQ_MASK_C_REG:
171*4882a593Smuzhiyun case DA9052_IRQ_MASK_D_REG:
172*4882a593Smuzhiyun case DA9052_CONTROL_A_REG:
173*4882a593Smuzhiyun case DA9052_CONTROL_B_REG:
174*4882a593Smuzhiyun case DA9052_CONTROL_C_REG:
175*4882a593Smuzhiyun case DA9052_CONTROL_D_REG:
176*4882a593Smuzhiyun case DA9052_PDDIS_REG:
177*4882a593Smuzhiyun case DA9052_RESET_REG:
178*4882a593Smuzhiyun case DA9052_GPIO_0_1_REG:
179*4882a593Smuzhiyun case DA9052_GPIO_2_3_REG:
180*4882a593Smuzhiyun case DA9052_GPIO_4_5_REG:
181*4882a593Smuzhiyun case DA9052_GPIO_6_7_REG:
182*4882a593Smuzhiyun case DA9052_GPIO_8_9_REG:
183*4882a593Smuzhiyun case DA9052_GPIO_10_11_REG:
184*4882a593Smuzhiyun case DA9052_GPIO_12_13_REG:
185*4882a593Smuzhiyun case DA9052_GPIO_14_15_REG:
186*4882a593Smuzhiyun case DA9052_ID_0_1_REG:
187*4882a593Smuzhiyun case DA9052_ID_2_3_REG:
188*4882a593Smuzhiyun case DA9052_ID_4_5_REG:
189*4882a593Smuzhiyun case DA9052_ID_6_7_REG:
190*4882a593Smuzhiyun case DA9052_ID_8_9_REG:
191*4882a593Smuzhiyun case DA9052_ID_10_11_REG:
192*4882a593Smuzhiyun case DA9052_ID_12_13_REG:
193*4882a593Smuzhiyun case DA9052_ID_14_15_REG:
194*4882a593Smuzhiyun case DA9052_ID_16_17_REG:
195*4882a593Smuzhiyun case DA9052_ID_18_19_REG:
196*4882a593Smuzhiyun case DA9052_ID_20_21_REG:
197*4882a593Smuzhiyun case DA9052_SEQ_STATUS_REG:
198*4882a593Smuzhiyun case DA9052_SEQ_A_REG:
199*4882a593Smuzhiyun case DA9052_SEQ_B_REG:
200*4882a593Smuzhiyun case DA9052_SEQ_TIMER_REG:
201*4882a593Smuzhiyun case DA9052_BUCKA_REG:
202*4882a593Smuzhiyun case DA9052_BUCKB_REG:
203*4882a593Smuzhiyun case DA9052_BUCKCORE_REG:
204*4882a593Smuzhiyun case DA9052_BUCKPRO_REG:
205*4882a593Smuzhiyun case DA9052_BUCKMEM_REG:
206*4882a593Smuzhiyun case DA9052_BUCKPERI_REG:
207*4882a593Smuzhiyun case DA9052_LDO1_REG:
208*4882a593Smuzhiyun case DA9052_LDO2_REG:
209*4882a593Smuzhiyun case DA9052_LDO3_REG:
210*4882a593Smuzhiyun case DA9052_LDO4_REG:
211*4882a593Smuzhiyun case DA9052_LDO5_REG:
212*4882a593Smuzhiyun case DA9052_LDO6_REG:
213*4882a593Smuzhiyun case DA9052_LDO7_REG:
214*4882a593Smuzhiyun case DA9052_LDO8_REG:
215*4882a593Smuzhiyun case DA9052_LDO9_REG:
216*4882a593Smuzhiyun case DA9052_LDO10_REG:
217*4882a593Smuzhiyun case DA9052_SUPPLY_REG:
218*4882a593Smuzhiyun case DA9052_PULLDOWN_REG:
219*4882a593Smuzhiyun case DA9052_CHGBUCK_REG:
220*4882a593Smuzhiyun case DA9052_WAITCONT_REG:
221*4882a593Smuzhiyun case DA9052_ISET_REG:
222*4882a593Smuzhiyun case DA9052_BATCHG_REG:
223*4882a593Smuzhiyun case DA9052_CHG_CONT_REG:
224*4882a593Smuzhiyun case DA9052_INPUT_CONT_REG:
225*4882a593Smuzhiyun case DA9052_BBAT_CONT_REG:
226*4882a593Smuzhiyun case DA9052_BOOST_REG:
227*4882a593Smuzhiyun case DA9052_LED_CONT_REG:
228*4882a593Smuzhiyun case DA9052_LEDMIN123_REG:
229*4882a593Smuzhiyun case DA9052_LED1_CONF_REG:
230*4882a593Smuzhiyun case DA9052_LED2_CONF_REG:
231*4882a593Smuzhiyun case DA9052_LED3_CONF_REG:
232*4882a593Smuzhiyun case DA9052_LED1CONT_REG:
233*4882a593Smuzhiyun case DA9052_LED2CONT_REG:
234*4882a593Smuzhiyun case DA9052_LED3CONT_REG:
235*4882a593Smuzhiyun case DA9052_LED_CONT_4_REG:
236*4882a593Smuzhiyun case DA9052_LED_CONT_5_REG:
237*4882a593Smuzhiyun case DA9052_ADC_MAN_REG:
238*4882a593Smuzhiyun case DA9052_ADC_CONT_REG:
239*4882a593Smuzhiyun case DA9052_ADC_RES_L_REG:
240*4882a593Smuzhiyun case DA9052_ADC_RES_H_REG:
241*4882a593Smuzhiyun case DA9052_VDD_RES_REG:
242*4882a593Smuzhiyun case DA9052_VDD_MON_REG:
243*4882a593Smuzhiyun case DA9052_ICHG_THD_REG:
244*4882a593Smuzhiyun case DA9052_ICHG_END_REG:
245*4882a593Smuzhiyun case DA9052_TBAT_HIGHP_REG:
246*4882a593Smuzhiyun case DA9052_TBAT_HIGHN_REG:
247*4882a593Smuzhiyun case DA9052_TBAT_LOW_REG:
248*4882a593Smuzhiyun case DA9052_T_OFFSET_REG:
249*4882a593Smuzhiyun case DA9052_AUTO4_HIGH_REG:
250*4882a593Smuzhiyun case DA9052_AUTO4_LOW_REG:
251*4882a593Smuzhiyun case DA9052_AUTO5_HIGH_REG:
252*4882a593Smuzhiyun case DA9052_AUTO5_LOW_REG:
253*4882a593Smuzhiyun case DA9052_AUTO6_HIGH_REG:
254*4882a593Smuzhiyun case DA9052_AUTO6_LOW_REG:
255*4882a593Smuzhiyun case DA9052_TSI_CONT_A_REG:
256*4882a593Smuzhiyun case DA9052_TSI_CONT_B_REG:
257*4882a593Smuzhiyun case DA9052_COUNT_S_REG:
258*4882a593Smuzhiyun case DA9052_COUNT_MI_REG:
259*4882a593Smuzhiyun case DA9052_COUNT_H_REG:
260*4882a593Smuzhiyun case DA9052_COUNT_D_REG:
261*4882a593Smuzhiyun case DA9052_COUNT_MO_REG:
262*4882a593Smuzhiyun case DA9052_COUNT_Y_REG:
263*4882a593Smuzhiyun case DA9052_ALARM_MI_REG:
264*4882a593Smuzhiyun case DA9052_ALARM_H_REG:
265*4882a593Smuzhiyun case DA9052_ALARM_D_REG:
266*4882a593Smuzhiyun case DA9052_ALARM_MO_REG:
267*4882a593Smuzhiyun case DA9052_ALARM_Y_REG:
268*4882a593Smuzhiyun case DA9052_PAGE1_CON_REG:
269*4882a593Smuzhiyun return true;
270*4882a593Smuzhiyun default:
271*4882a593Smuzhiyun return false;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
da9052_reg_volatile(struct device * dev,unsigned int reg)275*4882a593Smuzhiyun static bool da9052_reg_volatile(struct device *dev, unsigned int reg)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun switch (reg) {
278*4882a593Smuzhiyun case DA9052_STATUS_A_REG:
279*4882a593Smuzhiyun case DA9052_STATUS_B_REG:
280*4882a593Smuzhiyun case DA9052_STATUS_C_REG:
281*4882a593Smuzhiyun case DA9052_STATUS_D_REG:
282*4882a593Smuzhiyun case DA9052_EVENT_A_REG:
283*4882a593Smuzhiyun case DA9052_EVENT_B_REG:
284*4882a593Smuzhiyun case DA9052_EVENT_C_REG:
285*4882a593Smuzhiyun case DA9052_EVENT_D_REG:
286*4882a593Smuzhiyun case DA9052_CONTROL_B_REG:
287*4882a593Smuzhiyun case DA9052_CONTROL_D_REG:
288*4882a593Smuzhiyun case DA9052_SUPPLY_REG:
289*4882a593Smuzhiyun case DA9052_FAULTLOG_REG:
290*4882a593Smuzhiyun case DA9052_CHG_TIME_REG:
291*4882a593Smuzhiyun case DA9052_ADC_RES_L_REG:
292*4882a593Smuzhiyun case DA9052_ADC_RES_H_REG:
293*4882a593Smuzhiyun case DA9052_VDD_RES_REG:
294*4882a593Smuzhiyun case DA9052_ICHG_AV_REG:
295*4882a593Smuzhiyun case DA9052_TBAT_RES_REG:
296*4882a593Smuzhiyun case DA9052_ADCIN4_RES_REG:
297*4882a593Smuzhiyun case DA9052_ADCIN5_RES_REG:
298*4882a593Smuzhiyun case DA9052_ADCIN6_RES_REG:
299*4882a593Smuzhiyun case DA9052_TJUNC_RES_REG:
300*4882a593Smuzhiyun case DA9052_TSI_X_MSB_REG:
301*4882a593Smuzhiyun case DA9052_TSI_Y_MSB_REG:
302*4882a593Smuzhiyun case DA9052_TSI_LSB_REG:
303*4882a593Smuzhiyun case DA9052_TSI_Z_MSB_REG:
304*4882a593Smuzhiyun case DA9052_COUNT_S_REG:
305*4882a593Smuzhiyun case DA9052_COUNT_MI_REG:
306*4882a593Smuzhiyun case DA9052_COUNT_H_REG:
307*4882a593Smuzhiyun case DA9052_COUNT_D_REG:
308*4882a593Smuzhiyun case DA9052_COUNT_MO_REG:
309*4882a593Smuzhiyun case DA9052_COUNT_Y_REG:
310*4882a593Smuzhiyun case DA9052_ALARM_MI_REG:
311*4882a593Smuzhiyun return true;
312*4882a593Smuzhiyun default:
313*4882a593Smuzhiyun return false;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun /*
318*4882a593Smuzhiyun * TBAT look-up table is computed from the R90 reg (8 bit register)
319*4882a593Smuzhiyun * reading as below. The battery temperature is in milliCentigrade
320*4882a593Smuzhiyun * TBAT = (1/(t1+1/298) - 273) * 1000 mC
321*4882a593Smuzhiyun * where t1 = (1/B)* ln(( ADCval * 2.5)/(R25*ITBAT*255))
322*4882a593Smuzhiyun * Default values are R25 = 10e3, B = 3380, ITBAT = 50e-6
323*4882a593Smuzhiyun * Example:
324*4882a593Smuzhiyun * R25=10E3, B=3380, ITBAT=50e-6, ADCVAL=62d calculates
325*4882a593Smuzhiyun * TBAT = 20015 mili degrees Centrigrade
326*4882a593Smuzhiyun *
327*4882a593Smuzhiyun */
328*4882a593Smuzhiyun static const int32_t tbat_lookup[255] = {
329*4882a593Smuzhiyun 183258, 144221, 124334, 111336, 101826, 94397, 88343, 83257,
330*4882a593Smuzhiyun 78889, 75071, 71688, 68656, 65914, 63414, 61120, 59001,
331*4882a593Smuzhiyun 570366, 55204, 53490, 51881, 50364, 48931, 47574, 46285,
332*4882a593Smuzhiyun 45059, 43889, 42772, 41703, 40678, 39694, 38748, 37838,
333*4882a593Smuzhiyun 36961, 36115, 35297, 34507, 33743, 33002, 32284, 31588,
334*4882a593Smuzhiyun 30911, 30254, 29615, 28994, 28389, 27799, 27225, 26664,
335*4882a593Smuzhiyun 26117, 25584, 25062, 24553, 24054, 23567, 23091, 22624,
336*4882a593Smuzhiyun 22167, 21719, 21281, 20851, 20429, 20015, 19610, 19211,
337*4882a593Smuzhiyun 18820, 18436, 18058, 17688, 17323, 16965, 16612, 16266,
338*4882a593Smuzhiyun 15925, 15589, 15259, 14933, 14613, 14298, 13987, 13681,
339*4882a593Smuzhiyun 13379, 13082, 12788, 12499, 12214, 11933, 11655, 11382,
340*4882a593Smuzhiyun 11112, 10845, 10582, 10322, 10066, 9812, 9562, 9315,
341*4882a593Smuzhiyun 9071, 8830, 8591, 8356, 8123, 7893, 7665, 7440,
342*4882a593Smuzhiyun 7218, 6998, 6780, 6565, 6352, 6141, 5933, 5726,
343*4882a593Smuzhiyun 5522, 5320, 5120, 4922, 4726, 4532, 4340, 4149,
344*4882a593Smuzhiyun 3961, 3774, 3589, 3406, 3225, 3045, 2867, 2690,
345*4882a593Smuzhiyun 2516, 2342, 2170, 2000, 1831, 1664, 1498, 1334,
346*4882a593Smuzhiyun 1171, 1009, 849, 690, 532, 376, 221, 67,
347*4882a593Smuzhiyun -84, -236, -386, -535, -683, -830, -975, -1119,
348*4882a593Smuzhiyun -1263, -1405, -1546, -1686, -1825, -1964, -2101, -2237,
349*4882a593Smuzhiyun -2372, -2506, -2639, -2771, -2902, -3033, -3162, -3291,
350*4882a593Smuzhiyun -3418, -3545, -3671, -3796, -3920, -4044, -4166, -4288,
351*4882a593Smuzhiyun -4409, -4529, -4649, -4767, -4885, -5002, -5119, -5235,
352*4882a593Smuzhiyun -5349, -5464, -5577, -5690, -5802, -5913, -6024, -6134,
353*4882a593Smuzhiyun -6244, -6352, -6461, -6568, -6675, -6781, -6887, -6992,
354*4882a593Smuzhiyun -7096, -7200, -7303, -7406, -7508, -7609, -7710, -7810,
355*4882a593Smuzhiyun -7910, -8009, -8108, -8206, -8304, -8401, -8497, -8593,
356*4882a593Smuzhiyun -8689, -8784, -8878, -8972, -9066, -9159, -9251, -9343,
357*4882a593Smuzhiyun -9435, -9526, -9617, -9707, -9796, -9886, -9975, -10063,
358*4882a593Smuzhiyun -10151, -10238, -10325, -10412, -10839, -10923, -11007, -11090,
359*4882a593Smuzhiyun -11173, -11256, -11338, -11420, -11501, -11583, -11663, -11744,
360*4882a593Smuzhiyun -11823, -11903, -11982
361*4882a593Smuzhiyun };
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun static const u8 chan_mux[DA9052_ADC_VBBAT + 1] = {
364*4882a593Smuzhiyun [DA9052_ADC_VDDOUT] = DA9052_ADC_MAN_MUXSEL_VDDOUT,
365*4882a593Smuzhiyun [DA9052_ADC_ICH] = DA9052_ADC_MAN_MUXSEL_ICH,
366*4882a593Smuzhiyun [DA9052_ADC_TBAT] = DA9052_ADC_MAN_MUXSEL_TBAT,
367*4882a593Smuzhiyun [DA9052_ADC_VBAT] = DA9052_ADC_MAN_MUXSEL_VBAT,
368*4882a593Smuzhiyun [DA9052_ADC_IN4] = DA9052_ADC_MAN_MUXSEL_AD4,
369*4882a593Smuzhiyun [DA9052_ADC_IN5] = DA9052_ADC_MAN_MUXSEL_AD5,
370*4882a593Smuzhiyun [DA9052_ADC_IN6] = DA9052_ADC_MAN_MUXSEL_AD6,
371*4882a593Smuzhiyun [DA9052_ADC_VBBAT] = DA9052_ADC_MAN_MUXSEL_VBBAT
372*4882a593Smuzhiyun };
373*4882a593Smuzhiyun
da9052_adc_manual_read(struct da9052 * da9052,unsigned char channel)374*4882a593Smuzhiyun int da9052_adc_manual_read(struct da9052 *da9052, unsigned char channel)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun int ret;
377*4882a593Smuzhiyun unsigned short calc_data;
378*4882a593Smuzhiyun unsigned short data;
379*4882a593Smuzhiyun unsigned char mux_sel;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun if (channel > DA9052_ADC_VBBAT)
382*4882a593Smuzhiyun return -EINVAL;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun mutex_lock(&da9052->auxadc_lock);
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun reinit_completion(&da9052->done);
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun /* Channel gets activated on enabling the Conversion bit */
389*4882a593Smuzhiyun mux_sel = chan_mux[channel] | DA9052_ADC_MAN_MAN_CONV;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun ret = da9052_reg_write(da9052, DA9052_ADC_MAN_REG, mux_sel);
392*4882a593Smuzhiyun if (ret < 0)
393*4882a593Smuzhiyun goto err;
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun /* Wait for an interrupt */
396*4882a593Smuzhiyun if (!wait_for_completion_timeout(&da9052->done,
397*4882a593Smuzhiyun msecs_to_jiffies(500))) {
398*4882a593Smuzhiyun dev_err(da9052->dev,
399*4882a593Smuzhiyun "timeout waiting for ADC conversion interrupt\n");
400*4882a593Smuzhiyun ret = -ETIMEDOUT;
401*4882a593Smuzhiyun goto err;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun ret = da9052_reg_read(da9052, DA9052_ADC_RES_H_REG);
405*4882a593Smuzhiyun if (ret < 0)
406*4882a593Smuzhiyun goto err;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun calc_data = (unsigned short)ret;
409*4882a593Smuzhiyun data = calc_data << 2;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun ret = da9052_reg_read(da9052, DA9052_ADC_RES_L_REG);
412*4882a593Smuzhiyun if (ret < 0)
413*4882a593Smuzhiyun goto err;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun calc_data = (unsigned short)(ret & DA9052_ADC_RES_LSB);
416*4882a593Smuzhiyun data |= calc_data;
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun ret = data;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun err:
421*4882a593Smuzhiyun mutex_unlock(&da9052->auxadc_lock);
422*4882a593Smuzhiyun return ret;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(da9052_adc_manual_read);
425*4882a593Smuzhiyun
da9052_adc_read_temp(struct da9052 * da9052)426*4882a593Smuzhiyun int da9052_adc_read_temp(struct da9052 *da9052)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun int tbat;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun tbat = da9052_reg_read(da9052, DA9052_TBAT_RES_REG);
431*4882a593Smuzhiyun if (tbat <= 0)
432*4882a593Smuzhiyun return tbat;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun /* ARRAY_SIZE check is not needed since TBAT is a 8-bit register */
435*4882a593Smuzhiyun return tbat_lookup[tbat - 1];
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(da9052_adc_read_temp);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun static const struct mfd_cell da9052_subdev_info[] = {
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun .name = "da9052-regulator",
442*4882a593Smuzhiyun .id = 0,
443*4882a593Smuzhiyun },
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun .name = "da9052-regulator",
446*4882a593Smuzhiyun .id = 1,
447*4882a593Smuzhiyun },
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun .name = "da9052-regulator",
450*4882a593Smuzhiyun .id = 2,
451*4882a593Smuzhiyun },
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun .name = "da9052-regulator",
454*4882a593Smuzhiyun .id = 3,
455*4882a593Smuzhiyun },
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun .name = "da9052-regulator",
458*4882a593Smuzhiyun .id = 4,
459*4882a593Smuzhiyun },
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun .name = "da9052-regulator",
462*4882a593Smuzhiyun .id = 5,
463*4882a593Smuzhiyun },
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun .name = "da9052-regulator",
466*4882a593Smuzhiyun .id = 6,
467*4882a593Smuzhiyun },
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun .name = "da9052-regulator",
470*4882a593Smuzhiyun .id = 7,
471*4882a593Smuzhiyun },
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun .name = "da9052-regulator",
474*4882a593Smuzhiyun .id = 8,
475*4882a593Smuzhiyun },
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun .name = "da9052-regulator",
478*4882a593Smuzhiyun .id = 9,
479*4882a593Smuzhiyun },
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun .name = "da9052-regulator",
482*4882a593Smuzhiyun .id = 10,
483*4882a593Smuzhiyun },
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun .name = "da9052-regulator",
486*4882a593Smuzhiyun .id = 11,
487*4882a593Smuzhiyun },
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun .name = "da9052-regulator",
490*4882a593Smuzhiyun .id = 12,
491*4882a593Smuzhiyun },
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun .name = "da9052-regulator",
494*4882a593Smuzhiyun .id = 13,
495*4882a593Smuzhiyun },
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun .name = "da9052-onkey",
498*4882a593Smuzhiyun },
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun .name = "da9052-rtc",
501*4882a593Smuzhiyun },
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun .name = "da9052-gpio",
504*4882a593Smuzhiyun },
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun .name = "da9052-hwmon",
507*4882a593Smuzhiyun },
508*4882a593Smuzhiyun {
509*4882a593Smuzhiyun .name = "da9052-leds",
510*4882a593Smuzhiyun },
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun .name = "da9052-wled1",
513*4882a593Smuzhiyun },
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun .name = "da9052-wled2",
516*4882a593Smuzhiyun },
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun .name = "da9052-wled3",
519*4882a593Smuzhiyun },
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun .name = "da9052-bat",
522*4882a593Smuzhiyun },
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun .name = "da9052-watchdog",
525*4882a593Smuzhiyun },
526*4882a593Smuzhiyun };
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun static const struct mfd_cell da9052_tsi_subdev_info[] = {
529*4882a593Smuzhiyun { .name = "da9052-tsi" },
530*4882a593Smuzhiyun };
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun const struct regmap_config da9052_regmap_config = {
533*4882a593Smuzhiyun .reg_bits = 8,
534*4882a593Smuzhiyun .val_bits = 8,
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun .max_register = DA9052_PAGE1_CON_REG,
539*4882a593Smuzhiyun .readable_reg = da9052_reg_readable,
540*4882a593Smuzhiyun .writeable_reg = da9052_reg_writeable,
541*4882a593Smuzhiyun .volatile_reg = da9052_reg_volatile,
542*4882a593Smuzhiyun };
543*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(da9052_regmap_config);
544*4882a593Smuzhiyun
da9052_clear_fault_log(struct da9052 * da9052)545*4882a593Smuzhiyun static int da9052_clear_fault_log(struct da9052 *da9052)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun int ret = 0;
548*4882a593Smuzhiyun int fault_log = 0;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun fault_log = da9052_reg_read(da9052, DA9052_FAULTLOG_REG);
551*4882a593Smuzhiyun if (fault_log < 0) {
552*4882a593Smuzhiyun dev_err(da9052->dev,
553*4882a593Smuzhiyun "Cannot read FAULT_LOG %d\n", fault_log);
554*4882a593Smuzhiyun return fault_log;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun if (fault_log) {
558*4882a593Smuzhiyun if (fault_log & DA9052_FAULTLOG_TWDERROR)
559*4882a593Smuzhiyun dev_dbg(da9052->dev,
560*4882a593Smuzhiyun "Fault log entry detected: TWD_ERROR\n");
561*4882a593Smuzhiyun if (fault_log & DA9052_FAULTLOG_VDDFAULT)
562*4882a593Smuzhiyun dev_dbg(da9052->dev,
563*4882a593Smuzhiyun "Fault log entry detected: VDD_FAULT\n");
564*4882a593Smuzhiyun if (fault_log & DA9052_FAULTLOG_VDDSTART)
565*4882a593Smuzhiyun dev_dbg(da9052->dev,
566*4882a593Smuzhiyun "Fault log entry detected: VDD_START\n");
567*4882a593Smuzhiyun if (fault_log & DA9052_FAULTLOG_TEMPOVER)
568*4882a593Smuzhiyun dev_dbg(da9052->dev,
569*4882a593Smuzhiyun "Fault log entry detected: TEMP_OVER\n");
570*4882a593Smuzhiyun if (fault_log & DA9052_FAULTLOG_KEYSHUT)
571*4882a593Smuzhiyun dev_dbg(da9052->dev,
572*4882a593Smuzhiyun "Fault log entry detected: KEY_SHUT\n");
573*4882a593Smuzhiyun if (fault_log & DA9052_FAULTLOG_NSDSET)
574*4882a593Smuzhiyun dev_dbg(da9052->dev,
575*4882a593Smuzhiyun "Fault log entry detected: nSD_SHUT\n");
576*4882a593Smuzhiyun if (fault_log & DA9052_FAULTLOG_WAITSET)
577*4882a593Smuzhiyun dev_dbg(da9052->dev,
578*4882a593Smuzhiyun "Fault log entry detected: WAIT_SHUT\n");
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun ret = da9052_reg_write(da9052,
581*4882a593Smuzhiyun DA9052_FAULTLOG_REG,
582*4882a593Smuzhiyun 0xFF);
583*4882a593Smuzhiyun if (ret < 0)
584*4882a593Smuzhiyun dev_err(da9052->dev,
585*4882a593Smuzhiyun "Cannot reset FAULT_LOG values %d\n", ret);
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun return ret;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
da9052_device_init(struct da9052 * da9052,u8 chip_id)591*4882a593Smuzhiyun int da9052_device_init(struct da9052 *da9052, u8 chip_id)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun struct da9052_pdata *pdata = dev_get_platdata(da9052->dev);
594*4882a593Smuzhiyun int ret;
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun mutex_init(&da9052->auxadc_lock);
597*4882a593Smuzhiyun init_completion(&da9052->done);
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun ret = da9052_clear_fault_log(da9052);
600*4882a593Smuzhiyun if (ret < 0)
601*4882a593Smuzhiyun dev_warn(da9052->dev, "Cannot clear FAULT_LOG\n");
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun if (pdata && pdata->init != NULL)
604*4882a593Smuzhiyun pdata->init(da9052);
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun da9052->chip_id = chip_id;
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun ret = da9052_irq_init(da9052);
609*4882a593Smuzhiyun if (ret != 0) {
610*4882a593Smuzhiyun dev_err(da9052->dev, "da9052_irq_init failed: %d\n", ret);
611*4882a593Smuzhiyun return ret;
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun ret = mfd_add_devices(da9052->dev, PLATFORM_DEVID_AUTO,
615*4882a593Smuzhiyun da9052_subdev_info,
616*4882a593Smuzhiyun ARRAY_SIZE(da9052_subdev_info), NULL, 0, NULL);
617*4882a593Smuzhiyun if (ret) {
618*4882a593Smuzhiyun dev_err(da9052->dev, "mfd_add_devices failed: %d\n", ret);
619*4882a593Smuzhiyun goto err;
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun /*
623*4882a593Smuzhiyun * Check if touchscreen pins are used are analogue input instead
624*4882a593Smuzhiyun * of having a touchscreen connected to them. The analogue input
625*4882a593Smuzhiyun * functionality will be provided by hwmon driver (if enabled).
626*4882a593Smuzhiyun */
627*4882a593Smuzhiyun if (!device_property_read_bool(da9052->dev, "dlg,tsi-as-adc")) {
628*4882a593Smuzhiyun ret = mfd_add_devices(da9052->dev, PLATFORM_DEVID_AUTO,
629*4882a593Smuzhiyun da9052_tsi_subdev_info,
630*4882a593Smuzhiyun ARRAY_SIZE(da9052_tsi_subdev_info),
631*4882a593Smuzhiyun NULL, 0, NULL);
632*4882a593Smuzhiyun if (ret) {
633*4882a593Smuzhiyun dev_err(da9052->dev, "failed to add TSI subdev: %d\n",
634*4882a593Smuzhiyun ret);
635*4882a593Smuzhiyun goto err;
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun return 0;
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun err:
642*4882a593Smuzhiyun mfd_remove_devices(da9052->dev);
643*4882a593Smuzhiyun da9052_irq_exit(da9052);
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun return ret;
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun
da9052_device_exit(struct da9052 * da9052)648*4882a593Smuzhiyun void da9052_device_exit(struct da9052 *da9052)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun mfd_remove_devices(da9052->dev);
651*4882a593Smuzhiyun da9052_irq_exit(da9052);
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
655*4882a593Smuzhiyun MODULE_DESCRIPTION("DA9052 MFD Core");
656*4882a593Smuzhiyun MODULE_LICENSE("GPL");
657