1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * MFD core driver for Rockchip RK806
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Xu Shengfei <xsf@rock-chips.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/mfd/core.h>
12*4882a593Smuzhiyun #include <linux/mfd/rk806.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/of_device.h>
15*4882a593Smuzhiyun #include <linux/of_gpio.h>
16*4882a593Smuzhiyun #include <linux/spi/spi.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #define TSD_TEMP_140 0x00
19*4882a593Smuzhiyun #define TSD_TEMP_160 0x01
20*4882a593Smuzhiyun #define VB_LO_ACT_SD 0x00
21*4882a593Smuzhiyun #define VB_LO_ACT_INT 0x01
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun static const struct reg_field rk806_reg_fields[] = {
24*4882a593Smuzhiyun [POWER_EN0] = REG_FIELD(0x00, 0, 7),
25*4882a593Smuzhiyun [POWER_EN1] = REG_FIELD(0x01, 0, 7),
26*4882a593Smuzhiyun [POWER_EN2] = REG_FIELD(0x02, 0, 7),
27*4882a593Smuzhiyun [POWER_EN3] = REG_FIELD(0x03, 0, 7),
28*4882a593Smuzhiyun [POWER_EN4] = REG_FIELD(0x04, 0, 7),
29*4882a593Smuzhiyun [POWER_EN5] = REG_FIELD(0x05, 0, 7),
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun [BUCK4_EN_MASK] = REG_FIELD(0x00, 7, 7),
32*4882a593Smuzhiyun [BUCK3_EN_MASK] = REG_FIELD(0x00, 6, 6),
33*4882a593Smuzhiyun [BUCK2_EN_MASK] = REG_FIELD(0x00, 5, 5),
34*4882a593Smuzhiyun [BUCK1_EN_MASK] = REG_FIELD(0x00, 4, 4),
35*4882a593Smuzhiyun [BUCK4_EN] = REG_FIELD(0X00, 3, 3),
36*4882a593Smuzhiyun [BUCK3_EN] = REG_FIELD(0X00, 2, 2),
37*4882a593Smuzhiyun [BUCK2_EN] = REG_FIELD(0X00, 1, 1),
38*4882a593Smuzhiyun [BUCK1_EN] = REG_FIELD(0X00, 0, 0),
39*4882a593Smuzhiyun [BUCK8_EN_MASK] = REG_FIELD(0x01, 7, 7),
40*4882a593Smuzhiyun [BUCK7_EN_MASK] = REG_FIELD(0x01, 6, 6),
41*4882a593Smuzhiyun [BUCK6_EN_MASK] = REG_FIELD(0x01, 5, 5),
42*4882a593Smuzhiyun [BUCK5_EN_MASK] = REG_FIELD(0x01, 4, 4),
43*4882a593Smuzhiyun [BUCK8_EN] = REG_FIELD(0x01, 3, 3),
44*4882a593Smuzhiyun [BUCK7_EN] = REG_FIELD(0x01, 2, 2),
45*4882a593Smuzhiyun [BUCK6_EN] = REG_FIELD(0x01, 1, 1),
46*4882a593Smuzhiyun [BUCK5_EN] = REG_FIELD(0x01, 0, 0),
47*4882a593Smuzhiyun [BUCK10_EN_MASK] = REG_FIELD(0x02, 5, 5),
48*4882a593Smuzhiyun [BUCK9_EN_MASK] = REG_FIELD(0x02, 4, 4),
49*4882a593Smuzhiyun [BUCK10_EN] = REG_FIELD(0x02, 1, 1),
50*4882a593Smuzhiyun [BUCK9_EN] = REG_FIELD(0x02, 0, 0),
51*4882a593Smuzhiyun [NLDO4_EN_MASK] = REG_FIELD(0x03, 7, 7),
52*4882a593Smuzhiyun [NLDO3_EN_MASK] = REG_FIELD(0x03, 6, 6),
53*4882a593Smuzhiyun [NLDO2_EN_MASK] = REG_FIELD(0x03, 5, 5),
54*4882a593Smuzhiyun [NLDO1_EN_MASK] = REG_FIELD(0x03, 4, 4),
55*4882a593Smuzhiyun [NLDO4_EN] = REG_FIELD(0x03, 3, 3),
56*4882a593Smuzhiyun [NLDO3_EN] = REG_FIELD(0x03, 2, 2),
57*4882a593Smuzhiyun [NLDO2_EN] = REG_FIELD(0x03, 1, 1),
58*4882a593Smuzhiyun [NLDO1_EN] = REG_FIELD(0x03, 0, 0),
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun [PLDO3_EN_MASK] = REG_FIELD(0x04, 7, 7),
61*4882a593Smuzhiyun [PLDO2_EN_MASK] = REG_FIELD(0x04, 6, 6),
62*4882a593Smuzhiyun [PLDO1_EN_MASK] = REG_FIELD(0x04, 5, 5),
63*4882a593Smuzhiyun [PLDO6_EN_MASK] = REG_FIELD(0x04, 4, 4),
64*4882a593Smuzhiyun [PLDO3_EN] = REG_FIELD(0x04, 3, 3),
65*4882a593Smuzhiyun [PLDO2_EN] = REG_FIELD(0x04, 2, 2),
66*4882a593Smuzhiyun [PLDO1_EN] = REG_FIELD(0x04, 1, 1),
67*4882a593Smuzhiyun [PLDO6_EN] = REG_FIELD(0x04, 0, 0),
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun [NLDO5_EN_MASK] = REG_FIELD(0x05, 6, 6),
70*4882a593Smuzhiyun [PLDO5_EN_MASK] = REG_FIELD(0x05, 5, 5),
71*4882a593Smuzhiyun [PLDO4_EN_MASK] = REG_FIELD(0x05, 4, 4),
72*4882a593Smuzhiyun [NLDO5_EN] = REG_FIELD(0x05, 2, 2),
73*4882a593Smuzhiyun [PLDO5_EN] = REG_FIELD(0x05, 1, 1),
74*4882a593Smuzhiyun [PLDO4_EN] = REG_FIELD(0x05, 0, 0),
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun [BUCK8_SLP_EN] = REG_FIELD(0x06, 7, 7),
77*4882a593Smuzhiyun [BUCK7_SLP_EN] = REG_FIELD(0x06, 6, 6),
78*4882a593Smuzhiyun [BUCK6_SLP_EN] = REG_FIELD(0x06, 5, 5),
79*4882a593Smuzhiyun [BUCK5_SLP_EN] = REG_FIELD(0x06, 4, 4),
80*4882a593Smuzhiyun [BUCK4_SLP_EN] = REG_FIELD(0x06, 3, 3),
81*4882a593Smuzhiyun [BUCK3_SLP_EN] = REG_FIELD(0x06, 2, 2),
82*4882a593Smuzhiyun [BUCK2_SLP_EN] = REG_FIELD(0x06, 1, 1),
83*4882a593Smuzhiyun [BUCK1_SLP_EN] = REG_FIELD(0x06, 0, 0),
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun [BUCK10_SLP_EN] = REG_FIELD(0x07, 7, 7),
86*4882a593Smuzhiyun [BUCK9_SLP_EN] = REG_FIELD(0x07, 6, 6),
87*4882a593Smuzhiyun [NLDO5_SLP_EN] = REG_FIELD(0x07, 4, 4),
88*4882a593Smuzhiyun [NLDO4_SLP_EN] = REG_FIELD(0x07, 3, 3),
89*4882a593Smuzhiyun [NLDO3_SLP_EN] = REG_FIELD(0x07, 2, 2),
90*4882a593Smuzhiyun [NLDO2_SLP_EN] = REG_FIELD(0x07, 1, 1),
91*4882a593Smuzhiyun [NLDO1_SLP_EN] = REG_FIELD(0x07, 0, 0),
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun [PLDO5_SLP_EN] = REG_FIELD(0x08, 5, 5),
94*4882a593Smuzhiyun [PLDO4_SLP_EN] = REG_FIELD(0x08, 4, 4),
95*4882a593Smuzhiyun [PLDO3_SLP_EN] = REG_FIELD(0x08, 3, 3),
96*4882a593Smuzhiyun [PLDO2_SLP_EN] = REG_FIELD(0x08, 2, 2),
97*4882a593Smuzhiyun [PLDO1_SLP_EN] = REG_FIELD(0x08, 1, 1),
98*4882a593Smuzhiyun [PLDO6_SLP_EN] = REG_FIELD(0x08, 0, 0),
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun [BUCK1_RATE] = REG_FIELD(0x10, 6, 7),
101*4882a593Smuzhiyun [BUCK2_RATE] = REG_FIELD(0x11, 6, 7),
102*4882a593Smuzhiyun [BUCK3_RATE] = REG_FIELD(0x12, 6, 7),
103*4882a593Smuzhiyun [BUCK4_RATE] = REG_FIELD(0x13, 6, 7),
104*4882a593Smuzhiyun [BUCK5_RATE] = REG_FIELD(0x14, 6, 7),
105*4882a593Smuzhiyun [BUCK6_RATE] = REG_FIELD(0x15, 6, 7),
106*4882a593Smuzhiyun [BUCK7_RATE] = REG_FIELD(0x16, 6, 7),
107*4882a593Smuzhiyun [BUCK8_RATE] = REG_FIELD(0x17, 6, 7),
108*4882a593Smuzhiyun [BUCK9_RATE] = REG_FIELD(0x18, 6, 7),
109*4882a593Smuzhiyun [BUCK10_RATE] = REG_FIELD(0x19, 6, 7),
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun [BUCK1_ON_VSEL] = REG_FIELD(0x1A, 0, 7),
112*4882a593Smuzhiyun [BUCK2_ON_VSEL] = REG_FIELD(0x1B, 0, 7),
113*4882a593Smuzhiyun [BUCK3_ON_VSEL] = REG_FIELD(0x1C, 0, 7),
114*4882a593Smuzhiyun [BUCK4_ON_VSEL] = REG_FIELD(0x1D, 0, 7),
115*4882a593Smuzhiyun [BUCK5_ON_VSEL] = REG_FIELD(0x1E, 0, 7),
116*4882a593Smuzhiyun [BUCK6_ON_VSEL] = REG_FIELD(0x1F, 0, 7),
117*4882a593Smuzhiyun [BUCK7_ON_VSEL] = REG_FIELD(0x20, 0, 7),
118*4882a593Smuzhiyun [BUCK8_ON_VSEL] = REG_FIELD(0x21, 0, 7),
119*4882a593Smuzhiyun [BUCK9_ON_VSEL] = REG_FIELD(0x22, 0, 7),
120*4882a593Smuzhiyun [BUCK10_ON_VSEL] = REG_FIELD(0x23, 0, 7),
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun [BUCK1_SLP_VSEL] = REG_FIELD(0x24, 0, 7),
123*4882a593Smuzhiyun [BUCK2_SLP_VSEL] = REG_FIELD(0x25, 0, 7),
124*4882a593Smuzhiyun [BUCK3_SLP_VSEL] = REG_FIELD(0x26, 0, 7),
125*4882a593Smuzhiyun [BUCK4_SLP_VSEL] = REG_FIELD(0x27, 0, 7),
126*4882a593Smuzhiyun [BUCK5_SLP_VSEL] = REG_FIELD(0x28, 0, 7),
127*4882a593Smuzhiyun [BUCK6_SLP_VSEL] = REG_FIELD(0x29, 0, 7),
128*4882a593Smuzhiyun [BUCK7_SLP_VSEL] = REG_FIELD(0x2A, 0, 7),
129*4882a593Smuzhiyun [BUCK8_SLP_VSEL] = REG_FIELD(0x2B, 0, 7),
130*4882a593Smuzhiyun [BUCK9_SLP_VSEL] = REG_FIELD(0x2C, 0, 7),
131*4882a593Smuzhiyun [BUCK10_SLP_VSEL] = REG_FIELD(0x2D, 0, 7),
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun [NLDO1_ON_VSEL] = REG_FIELD(0x43, 0, 7),
134*4882a593Smuzhiyun [NLDO2_ON_VSEL] = REG_FIELD(0x44, 0, 7),
135*4882a593Smuzhiyun [NLDO3_ON_VSEL] = REG_FIELD(0x45, 0, 7),
136*4882a593Smuzhiyun [NLDO4_ON_VSEL] = REG_FIELD(0x46, 0, 7),
137*4882a593Smuzhiyun [NLDO5_ON_VSEL] = REG_FIELD(0x47, 0, 7),
138*4882a593Smuzhiyun [NLDO1_SLP_VSEL] = REG_FIELD(0x48, 0, 7),
139*4882a593Smuzhiyun [NLDO2_SLP_VSEL] = REG_FIELD(0x49, 0, 7),
140*4882a593Smuzhiyun [NLDO3_SLP_VSEL] = REG_FIELD(0x4A, 0, 7),
141*4882a593Smuzhiyun [NLDO4_SLP_VSEL] = REG_FIELD(0x4B, 0, 7),
142*4882a593Smuzhiyun [NLDO5_SLP_VSEL] = REG_FIELD(0x4C, 0, 7),
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun [PLDO1_ON_VSEL] = REG_FIELD(0x4E, 0, 7),
145*4882a593Smuzhiyun [PLDO2_ON_VSEL] = REG_FIELD(0x4F, 0, 7),
146*4882a593Smuzhiyun [PLDO3_ON_VSEL] = REG_FIELD(0x50, 0, 7),
147*4882a593Smuzhiyun [PLDO4_ON_VSEL] = REG_FIELD(0x51, 0, 7),
148*4882a593Smuzhiyun [PLDO5_ON_VSEL] = REG_FIELD(0x52, 0, 7),
149*4882a593Smuzhiyun [PLDO6_ON_VSEL] = REG_FIELD(0x53, 0, 7),
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun [PLDO1_SLP_VSEL] = REG_FIELD(0x54, 0, 7),
152*4882a593Smuzhiyun [PLDO2_SLP_VSEL] = REG_FIELD(0x55, 0, 7),
153*4882a593Smuzhiyun [PLDO3_SLP_VSEL] = REG_FIELD(0x56, 0, 7),
154*4882a593Smuzhiyun [PLDO4_SLP_VSEL] = REG_FIELD(0x57, 0, 7),
155*4882a593Smuzhiyun [PLDO5_SLP_VSEL] = REG_FIELD(0x58, 0, 7),
156*4882a593Smuzhiyun [PLDO6_SLP_VSEL] = REG_FIELD(0x59, 0, 7),
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun [CHIP_NAME_H] = REG_FIELD(0x5A, 0, 7),
159*4882a593Smuzhiyun [CHIP_NAME_L] = REG_FIELD(0x5B, 4, 7),
160*4882a593Smuzhiyun [CHIP_VER] = REG_FIELD(0x5B, 0, 3),
161*4882a593Smuzhiyun [OTP_VER] = REG_FIELD(0x5C, 0, 3),
162*4882a593Smuzhiyun /* SYS_STS */
163*4882a593Smuzhiyun [PWRON_STS] = REG_FIELD(0x5D, 7, 7),
164*4882a593Smuzhiyun [VDC_STS] = REG_FIELD(0x5D, 6, 6),
165*4882a593Smuzhiyun [VB_UV_STSS] = REG_FIELD(0x5D, 5, 5),
166*4882a593Smuzhiyun [VB_LO_STS] = REG_FIELD(0x5D, 4, 4),
167*4882a593Smuzhiyun [HOTDIE_STS] = REG_FIELD(0x5D, 3, 3),
168*4882a593Smuzhiyun [TSD_STS] = REG_FIELD(0x5D, 2, 2),
169*4882a593Smuzhiyun [VB_OV_STS] = REG_FIELD(0x5D, 0, 0),
170*4882a593Smuzhiyun /* SYS_CFG0 */
171*4882a593Smuzhiyun [VB_UV_DLY] = REG_FIELD(0x5E, 7, 7),
172*4882a593Smuzhiyun [VB_UV_SEL] = REG_FIELD(0x5E, 4, 6),
173*4882a593Smuzhiyun [VB_LO_ACT] = REG_FIELD(0x5E, 3, 3),
174*4882a593Smuzhiyun [VB_LO_SEL] = REG_FIELD(0x5E, 0, 2),
175*4882a593Smuzhiyun /* SYS_CFG1 */
176*4882a593Smuzhiyun [ABNORDET_EN] = REG_FIELD(0x5F, 7, 7),
177*4882a593Smuzhiyun [TSD_TEMP] = REG_FIELD(0x5F, 6, 6),
178*4882a593Smuzhiyun [HOTDIE_TMP] = REG_FIELD(0x5F, 4, 5),
179*4882a593Smuzhiyun [SYS_OV_SD_EN] = REG_FIELD(0x5F, 3, 3),
180*4882a593Smuzhiyun [SYS_OV_SD_DLY_SEL] = REG_FIELD(0x5F, 2, 2),
181*4882a593Smuzhiyun [DLY_ABN_SHORT] = REG_FIELD(0x5F, 0, 1),
182*4882a593Smuzhiyun /* SYS_OPTION */
183*4882a593Smuzhiyun [VCCXDET_DIS] = REG_FIELD(0x61, 4, 5),
184*4882a593Smuzhiyun [OSC_TC] = REG_FIELD(0x61, 2, 3),
185*4882a593Smuzhiyun [ENB2_2M] = REG_FIELD(0x61, 1, 1),
186*4882a593Smuzhiyun [ENB_32K] = REG_FIELD(0x61, 0, 0),
187*4882a593Smuzhiyun /* SLEEP_CONFIG0 */
188*4882a593Smuzhiyun [PWRCTRL2_POL] = REG_FIELD(0x62, 7, 7),
189*4882a593Smuzhiyun [PWRCTRL2_FUN] = REG_FIELD(0x62, 4, 6),
190*4882a593Smuzhiyun [PWRCTRL1_POL] = REG_FIELD(0x62, 3, 3),
191*4882a593Smuzhiyun [PWRCTRL1_FUN] = REG_FIELD(0x62, 0, 2),
192*4882a593Smuzhiyun /* SLEEP_CONFIG1 */
193*4882a593Smuzhiyun [PWRCTRL3_POL] = REG_FIELD(0x63, 3, 3),
194*4882a593Smuzhiyun [PWRCTRL3_FUN] = REG_FIELD(0x63, 0, 2),
195*4882a593Smuzhiyun /* SLEEP_VSEL_CTR_SEL0 */
196*4882a593Smuzhiyun [BUCK4_VSEL_CTR_SEL] = REG_FIELD(0x65, 4, 5),
197*4882a593Smuzhiyun [BUCK3_VSEL_CTR_SEL] = REG_FIELD(0x65, 0, 1),
198*4882a593Smuzhiyun [BUCK2_VSEL_CTR_SEL] = REG_FIELD(0x64, 4, 5),
199*4882a593Smuzhiyun [BUCK1_VSEL_CTR_SEL] = REG_FIELD(0x64, 0, 1),
200*4882a593Smuzhiyun /* SLEEP_VSEL_CTR_SEL1 */
201*4882a593Smuzhiyun [BUCK8_VSEL_CTR_SEL] = REG_FIELD(0x67, 4, 5),
202*4882a593Smuzhiyun [BUCK7_VSEL_CTR_SEL] = REG_FIELD(0x67, 0, 1),
203*4882a593Smuzhiyun [BUCK6_VSEL_CTR_SEL] = REG_FIELD(0x66, 4, 5),
204*4882a593Smuzhiyun [BUCK5_VSEL_CTR_SEL] = REG_FIELD(0x66, 0, 1),
205*4882a593Smuzhiyun /* SLEEP_VSEL_CTR_SEL2 */
206*4882a593Smuzhiyun [NLDO2_VSEL_CTR_SEL] = REG_FIELD(0x69, 4, 5),
207*4882a593Smuzhiyun [NLDO1_VSEL_CTR_SEL] = REG_FIELD(0x69, 0, 1),
208*4882a593Smuzhiyun [BUCK10_VSEL_CTR_SEL] = REG_FIELD(0x68, 4, 5),
209*4882a593Smuzhiyun [BUCK9_VSEL_CTR_SEL] = REG_FIELD(0x68, 0, 1),
210*4882a593Smuzhiyun /* SLEEP_VSEL_CTR_SEL3 */
211*4882a593Smuzhiyun [NLDO5_VSEL_CTR_SEL] = REG_FIELD(0x6b, 0, 1),
212*4882a593Smuzhiyun [NLDO4_VSEL_CTR_SEL] = REG_FIELD(0x6a, 4, 5),
213*4882a593Smuzhiyun [NLDO3_VSEL_CTR_SEL] = REG_FIELD(0x6a, 0, 1),
214*4882a593Smuzhiyun /* SLEEP_VSEL_CTR_SEL4 */
215*4882a593Smuzhiyun [PLDO4_VSEL_CTR_SEL] = REG_FIELD(0x6d, 4, 5),
216*4882a593Smuzhiyun [PLDO3_VSEL_CTR_SEL] = REG_FIELD(0x6d, 0, 0),
217*4882a593Smuzhiyun [PLDO2_VSEL_CTR_SEL] = REG_FIELD(0x6c, 4, 5),
218*4882a593Smuzhiyun [PLDO1_VSEL_CTR_SEL] = REG_FIELD(0x6c, 0, 1),
219*4882a593Smuzhiyun /* SLEEP_VSEL_CTR_SEL5 */
220*4882a593Smuzhiyun [PLDO6_VSEL_CTR_SEL] = REG_FIELD(0x6e, 4, 5),
221*4882a593Smuzhiyun [PLDO5_VSEL_CTR_SEL] = REG_FIELD(0x6e, 0, 1),
222*4882a593Smuzhiyun /* DVS_CTRL_SEL0 */
223*4882a593Smuzhiyun [BUCK4_DVS_CTR_SEL] = REG_FIELD(0x65, 6, 7),
224*4882a593Smuzhiyun [BUCK3_DVS_CTR_SEL] = REG_FIELD(0x65, 2, 3),
225*4882a593Smuzhiyun [BUCK2_DVS_CTR_SEL] = REG_FIELD(0x64, 6, 7),
226*4882a593Smuzhiyun [BUCK1_DVS_CTR_SEL] = REG_FIELD(0x64, 2, 3),
227*4882a593Smuzhiyun /* DVS_CTRL_SEL1*/
228*4882a593Smuzhiyun [BUCK8_DVS_CTR_SEL] = REG_FIELD(0x67, 6, 7),
229*4882a593Smuzhiyun [BUCK7_DVS_CTR_SEL] = REG_FIELD(0x67, 2, 3),
230*4882a593Smuzhiyun [BUCK6_DVS_CTR_SEL] = REG_FIELD(0x66, 6, 7),
231*4882a593Smuzhiyun [BUCK5_DVS_CTR_SEL] = REG_FIELD(0x66, 2, 3),
232*4882a593Smuzhiyun /* DVS_CTRL_SEL2 */
233*4882a593Smuzhiyun [NLDO2_DVS_CTR_SEL] = REG_FIELD(0x69, 6, 7),
234*4882a593Smuzhiyun [NLDO1_DVS_CTR_SEL] = REG_FIELD(0x69, 2, 3),
235*4882a593Smuzhiyun [BUCK10_DVS_CTR_SEL] = REG_FIELD(0x68, 6, 7),
236*4882a593Smuzhiyun [BUCK9_DVS_CTR_SEL] = REG_FIELD(0x68, 2, 3),
237*4882a593Smuzhiyun /* DVS_CTRL_SEL3 */
238*4882a593Smuzhiyun [NLDO5_DVS_CTR_SEL] = REG_FIELD(0x6b, 2, 3),
239*4882a593Smuzhiyun [NLDO4_DVS_CTR_SEL] = REG_FIELD(0x6a, 6, 7),
240*4882a593Smuzhiyun [NLDO3_DVS_CTR_SEL] = REG_FIELD(0x6a, 2, 3),
241*4882a593Smuzhiyun /* DVS_CTRL_SEL4 */
242*4882a593Smuzhiyun [PLDO4_DVS_CTR_SEL] = REG_FIELD(0x6d, 6, 7),
243*4882a593Smuzhiyun [PLDO3_DVS_CTR_SEL] = REG_FIELD(0x6d, 2, 3),
244*4882a593Smuzhiyun [PLDO2_DVS_CTR_SEL] = REG_FIELD(0x6c, 6, 7),
245*4882a593Smuzhiyun [PLDO1_DVS_CTR_SEL] = REG_FIELD(0x6c, 2, 3),
246*4882a593Smuzhiyun /* DVS_CTRL_SEL5 */
247*4882a593Smuzhiyun [PLDO6_DVS_CTR_SEL] = REG_FIELD(0x6e, 6, 7),
248*4882a593Smuzhiyun [PLDO5_DVS_CTR_SEL] = REG_FIELD(0x6e, 2, 3),
249*4882a593Smuzhiyun /* DVS_START_CTRL */
250*4882a593Smuzhiyun [DVS_START3] = REG_FIELD(0x70, 2, 2),
251*4882a593Smuzhiyun [DVS_START2] = REG_FIELD(0x70, 1, 1),
252*4882a593Smuzhiyun [DVS_START1] = REG_FIELD(0x70, 0, 0),
253*4882a593Smuzhiyun /* SLEEP_GPIO */
254*4882a593Smuzhiyun [SLP3_DATA] = REG_FIELD(0x71, 6, 6),
255*4882a593Smuzhiyun [SLP2_DATA] = REG_FIELD(0x71, 5, 5),
256*4882a593Smuzhiyun [SLP1_DATA] = REG_FIELD(0x71, 4, 4),
257*4882a593Smuzhiyun [SLP3_DR] = REG_FIELD(0x71, 2, 2),
258*4882a593Smuzhiyun [SLP2_DR] = REG_FIELD(0x71, 1, 1),
259*4882a593Smuzhiyun [SLP1_DR] = REG_FIELD(0x71, 0, 0),
260*4882a593Smuzhiyun /* SYS_CFG3 */
261*4882a593Smuzhiyun [RST_FUN] = REG_FIELD(0x72, 6, 7),
262*4882a593Smuzhiyun [DEV_RST] = REG_FIELD(0x72, 5, 5),
263*4882a593Smuzhiyun [DEV_SLP] = REG_FIELD(0x72, 4, 4),
264*4882a593Smuzhiyun [SLAVE_RESTART_FUN] = REG_FIELD(0x72, 1, 1),
265*4882a593Smuzhiyun [DEV_OFF] = REG_FIELD(0x72, 0, 0),
266*4882a593Smuzhiyun [WDT_CLR] = REG_FIELD(0x73, 4, 4),
267*4882a593Smuzhiyun [WDT_EN] = REG_FIELD(0x73, 3, 3),
268*4882a593Smuzhiyun [WDT_SET] = REG_FIELD(0x73, 0, 3),
269*4882a593Smuzhiyun [ON_SOURCE] = REG_FIELD(0x74, 0, 7),
270*4882a593Smuzhiyun [OFF_SOURCE] = REG_FIELD(0x75, 0, 7),
271*4882a593Smuzhiyun /* PWRON_KEY */
272*4882a593Smuzhiyun [PWRON_ON_TIME] = REG_FIELD(0x76, 7, 7),
273*4882a593Smuzhiyun [PWRON_LP_ACT] = REG_FIELD(0x76, 6, 6),
274*4882a593Smuzhiyun [PWRON_LP_OFF_TIME] = REG_FIELD(0x76, 4, 5),
275*4882a593Smuzhiyun [PWRON_LP_TM_SEL] = REG_FIELD(0x76, 2, 3),
276*4882a593Smuzhiyun [PWRON_DB_SEL] = REG_FIELD(0x76, 0, 1),
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun /* GPIO_INT_CONFIG */
279*4882a593Smuzhiyun [INT_FUNCTION] = REG_FIELD(0x7b, 2, 2),
280*4882a593Smuzhiyun [INT_POL] = REG_FIELD(0x7b, 1, 1),
281*4882a593Smuzhiyun [INT_FC_EN] = REG_FIELD(0x7b, 0, 0),
282*4882a593Smuzhiyun [BUCK9_RATE2] = REG_FIELD(0xEA, 0, 0),
283*4882a593Smuzhiyun [BUCK10_RATE2] = REG_FIELD(0xEA, 1, 1),
284*4882a593Smuzhiyun [LDO_RATE] = REG_FIELD(0xEA, 3, 5),
285*4882a593Smuzhiyun [BUCK1_RATE2] = REG_FIELD(0xEB, 0, 0),
286*4882a593Smuzhiyun [BUCK2_RATE2] = REG_FIELD(0xEB, 1, 1),
287*4882a593Smuzhiyun [BUCK3_RATE2] = REG_FIELD(0xEB, 2, 2),
288*4882a593Smuzhiyun [BUCK4_RATE2] = REG_FIELD(0xEB, 3, 3),
289*4882a593Smuzhiyun [BUCK5_RATE2] = REG_FIELD(0xEB, 4, 4),
290*4882a593Smuzhiyun [BUCK6_RATE2] = REG_FIELD(0xEB, 5, 5),
291*4882a593Smuzhiyun [BUCK7_RATE2] = REG_FIELD(0xEB, 6, 6),
292*4882a593Smuzhiyun [BUCK8_RATE2] = REG_FIELD(0xEB, 7, 7),
293*4882a593Smuzhiyun };
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun static struct resource rk806_pwrkey_resources[] = {
296*4882a593Smuzhiyun DEFINE_RES_IRQ(RK806_IRQ_PWRON_FALL),
297*4882a593Smuzhiyun DEFINE_RES_IRQ(RK806_IRQ_PWRON_RISE),
298*4882a593Smuzhiyun };
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun static const struct mfd_cell rk806_cells[] = {
301*4882a593Smuzhiyun { .name = "rk806-pinctrl", },
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun .name = "rk805-pwrkey",
304*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(rk806_pwrkey_resources),
305*4882a593Smuzhiyun .resources = &rk806_pwrkey_resources[0],
306*4882a593Smuzhiyun },
307*4882a593Smuzhiyun { .name = "rk806-regulator", },
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun };
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun static const struct regmap_irq rk806_irqs[] = {
312*4882a593Smuzhiyun /* INT_STS0 IRQs */
313*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_PWRON_FALL, 0, RK806_INT_STS_PWRON_FALL),
314*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_PWRON_RISE, 0, RK806_INT_STS_PWRON_RISE),
315*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_PWRON, 0, RK806_INT_STS_PWRON),
316*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_PWRON_LP, 0, RK806_INT_STS_PWRON_LP),
317*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_HOTDIE, 0, RK806_INT_STS_HOTDIE),
318*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_VDC_RISE, 0, RK806_INT_STS_VDC_RISE),
319*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_VDC_FALL, 0, RK806_INT_STS_VDC_FALL),
320*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_VB_LO, 0, RK806_INT_STS_VB_LO),
321*4882a593Smuzhiyun /* INT_STS1 IRQs */
322*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_REV0, 1, RK806_INT_STS_REV0),
323*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_REV1, 1, RK806_INT_STS_REV1),
324*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_REV2, 1, RK806_INT_STS_REV2),
325*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_CRC_ERROR, 1, RK806_INT_STS_CRC_ERROR),
326*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_SLP3_GPIO, 1, RK806_INT_STS_SLP3_GPIO),
327*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_SLP2_GPIO, 1, RK806_INT_STS_SLP2_GPIO),
328*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_SLP1_GPIO, 1, RK806_INT_STS_SLP1_GPIO),
329*4882a593Smuzhiyun REGMAP_IRQ_REG(RK806_IRQ_WDT, 1, RK806_INT_STS_WDT),
330*4882a593Smuzhiyun };
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun static struct regmap_irq_chip rk806_irq_chip = {
333*4882a593Smuzhiyun .name = "rk806",
334*4882a593Smuzhiyun .irqs = rk806_irqs,
335*4882a593Smuzhiyun .num_irqs = ARRAY_SIZE(rk806_irqs),
336*4882a593Smuzhiyun .num_regs = 2,
337*4882a593Smuzhiyun .irq_reg_stride = 2,
338*4882a593Smuzhiyun .mask_base = RK806_INT_MSK0,
339*4882a593Smuzhiyun .status_base = RK806_INT_STS0,
340*4882a593Smuzhiyun .ack_base = RK806_INT_STS0,
341*4882a593Smuzhiyun .init_ack_masked = true,
342*4882a593Smuzhiyun };
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun static const struct regmap_range rk806_yes_ranges[] = {
345*4882a593Smuzhiyun /* regmap_reg_range(RK806_INT_STS0, RK806_GPIO_INT_CONFIG), */
346*4882a593Smuzhiyun regmap_reg_range(RK806_POWER_EN0, RK806_POWER_EN5),
347*4882a593Smuzhiyun regmap_reg_range(0x70, 0x7a),
348*4882a593Smuzhiyun };
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun static const struct regmap_access_table rk806_volatile_table = {
351*4882a593Smuzhiyun .yes_ranges = rk806_yes_ranges,
352*4882a593Smuzhiyun .n_yes_ranges = ARRAY_SIZE(rk806_yes_ranges),
353*4882a593Smuzhiyun };
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun const struct regmap_config rk806_regmap_config_spi = {
356*4882a593Smuzhiyun .reg_bits = 8,
357*4882a593Smuzhiyun .val_bits = 8,
358*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
359*4882a593Smuzhiyun .volatile_table = &rk806_volatile_table,
360*4882a593Smuzhiyun };
361*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rk806_regmap_config_spi);
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun static struct kobject *rk806_kobj[2];
364*4882a593Smuzhiyun static struct rk806 *rk806_master;
365*4882a593Smuzhiyun static struct rk806 *rk806_slaver;
366*4882a593Smuzhiyun
rk806_master_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)367*4882a593Smuzhiyun static ssize_t rk806_master_store(struct device *dev,
368*4882a593Smuzhiyun struct device_attribute *attr,
369*4882a593Smuzhiyun const char *buf,
370*4882a593Smuzhiyun size_t count)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun u32 input[2], addr, data;
373*4882a593Smuzhiyun struct rk806 *rk806;
374*4882a593Smuzhiyun char cmd;
375*4882a593Smuzhiyun int ret;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun ret = sscanf(buf, "%c ", &cmd);
378*4882a593Smuzhiyun if (ret != 1) {
379*4882a593Smuzhiyun pr_err("Unknown command\n");
380*4882a593Smuzhiyun goto out;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun rk806 = rk806_master;
384*4882a593Smuzhiyun if (!rk806) {
385*4882a593Smuzhiyun pr_err("error! rk806 master is NULL\n");
386*4882a593Smuzhiyun return 0;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun switch (cmd) {
390*4882a593Smuzhiyun case 'w':
391*4882a593Smuzhiyun ret = sscanf(buf, "%c %x %x", &cmd, &input[0], &input[1]);
392*4882a593Smuzhiyun if (ret != 3) {
393*4882a593Smuzhiyun pr_err("error! cmd format: echo w [addr] [value]\n");
394*4882a593Smuzhiyun goto out;
395*4882a593Smuzhiyun };
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun addr = input[0] & 0xff;
398*4882a593Smuzhiyun data = input[1] & 0xff;
399*4882a593Smuzhiyun pr_info("cmd : %c %x %x\n\n", cmd, input[0], input[1]);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun regmap_write(rk806->regmap, addr, data);
402*4882a593Smuzhiyun regmap_read(rk806->regmap, addr, &data);
403*4882a593Smuzhiyun pr_info("new: %x %x\n", addr, data);
404*4882a593Smuzhiyun break;
405*4882a593Smuzhiyun case 'r':
406*4882a593Smuzhiyun ret = sscanf(buf, "%c %x ", &cmd, &input[0]);
407*4882a593Smuzhiyun if (ret != 2) {
408*4882a593Smuzhiyun pr_err("error! cmd format: echo r [addr]\n");
409*4882a593Smuzhiyun goto out;
410*4882a593Smuzhiyun };
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun pr_info("cmd : %c %x\n\n", cmd, input[0]);
413*4882a593Smuzhiyun addr = input[0] & 0xff;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun regmap_read(rk806->regmap, addr, &data);
416*4882a593Smuzhiyun pr_info("%x %x\n", input[0], data);
417*4882a593Smuzhiyun break;
418*4882a593Smuzhiyun default:
419*4882a593Smuzhiyun pr_err("Unknown command\n");
420*4882a593Smuzhiyun break;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun out:
424*4882a593Smuzhiyun return count;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
rk806_slaver_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)427*4882a593Smuzhiyun static ssize_t rk806_slaver_store(struct device *dev,
428*4882a593Smuzhiyun struct device_attribute *attr,
429*4882a593Smuzhiyun const char *buf,
430*4882a593Smuzhiyun size_t count)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun u32 input[2], addr, data;
433*4882a593Smuzhiyun struct rk806 *rk806;
434*4882a593Smuzhiyun char cmd;
435*4882a593Smuzhiyun int ret;
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun ret = sscanf(buf, "%c ", &cmd);
438*4882a593Smuzhiyun if (ret != 1) {
439*4882a593Smuzhiyun pr_err("Unknown command\n");
440*4882a593Smuzhiyun goto out;
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun rk806 = rk806_slaver;
444*4882a593Smuzhiyun if (!rk806) {
445*4882a593Smuzhiyun pr_err("error! rk806 slaver is NULL\n");
446*4882a593Smuzhiyun return 0;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun switch (cmd) {
450*4882a593Smuzhiyun case 'w':
451*4882a593Smuzhiyun ret = sscanf(buf, "%c %x %x", &cmd, &input[0], &input[1]);
452*4882a593Smuzhiyun if (ret != 3) {
453*4882a593Smuzhiyun pr_err("error! cmd format: echo w [addr] [value]\n");
454*4882a593Smuzhiyun goto out;
455*4882a593Smuzhiyun };
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun addr = input[0] & 0xff;
458*4882a593Smuzhiyun data = input[1] & 0xff;
459*4882a593Smuzhiyun pr_info("cmd : %c %x %x\n\n", cmd, input[0], input[1]);
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun regmap_write(rk806->regmap, addr, data);
462*4882a593Smuzhiyun regmap_read(rk806->regmap, addr, &data);
463*4882a593Smuzhiyun pr_info("new: %x %x\n", addr, data);
464*4882a593Smuzhiyun break;
465*4882a593Smuzhiyun case 'r':
466*4882a593Smuzhiyun ret = sscanf(buf, "%c %x ", &cmd, &input[0]);
467*4882a593Smuzhiyun if (ret != 2) {
468*4882a593Smuzhiyun pr_err("error! cmd format: echo r [addr]\n");
469*4882a593Smuzhiyun goto out;
470*4882a593Smuzhiyun };
471*4882a593Smuzhiyun pr_info("cmd : %c %x\n\n", cmd, input[0]);
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun addr = input[0] & 0xff;
474*4882a593Smuzhiyun regmap_read(rk806->regmap, addr, &data);
475*4882a593Smuzhiyun pr_info("%x %x\n", input[0], data);
476*4882a593Smuzhiyun break;
477*4882a593Smuzhiyun default:
478*4882a593Smuzhiyun pr_err("Unknown command\n");
479*4882a593Smuzhiyun break;
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun out:
483*4882a593Smuzhiyun return count;
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun static struct device_attribute rk806_master_attrs =
487*4882a593Smuzhiyun __ATTR(debug, 0200, NULL, rk806_master_store);
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun static struct device_attribute rk806_slaver_attrs =
490*4882a593Smuzhiyun __ATTR(debug, 0200, NULL, rk806_slaver_store);
491*4882a593Smuzhiyun
rk806_field_read(struct rk806 * rk806,enum rk806_fields field_id)492*4882a593Smuzhiyun int rk806_field_read(struct rk806 *rk806,
493*4882a593Smuzhiyun enum rk806_fields field_id)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun int ret;
496*4882a593Smuzhiyun int val;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun ret = regmap_field_read(rk806->rmap_fields[field_id], &val);
499*4882a593Smuzhiyun if (ret < 0)
500*4882a593Smuzhiyun return ret;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun return val;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rk806_field_read);
505*4882a593Smuzhiyun
rk806_field_write(struct rk806 * rk806,enum rk806_fields field_id,unsigned int val)506*4882a593Smuzhiyun int rk806_field_write(struct rk806 *rk806,
507*4882a593Smuzhiyun enum rk806_fields field_id,
508*4882a593Smuzhiyun unsigned int val)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun return regmap_field_write(rk806->rmap_fields[field_id], val);
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rk806_field_write);
513*4882a593Smuzhiyun
rk806_irq_init(struct rk806 * rk806)514*4882a593Smuzhiyun static void rk806_irq_init(struct rk806 *rk806)
515*4882a593Smuzhiyun {
516*4882a593Smuzhiyun /* INT pin polarity active low */
517*4882a593Smuzhiyun rk806_field_write(rk806, INT_POL, RK806_INT_POL_LOW);
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun
rk806_pinctrl_init(struct rk806 * rk806)520*4882a593Smuzhiyun static int rk806_pinctrl_init(struct rk806 *rk806)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun struct device *dev = rk806->dev;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun rk806->pins = devm_kzalloc(dev,
525*4882a593Smuzhiyun sizeof(struct rk806_pin_info),
526*4882a593Smuzhiyun GFP_KERNEL);
527*4882a593Smuzhiyun if (!rk806->pins)
528*4882a593Smuzhiyun return -ENOMEM;
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun rk806->pins->p = devm_pinctrl_get(dev);
531*4882a593Smuzhiyun if (IS_ERR(rk806->pins->p)) {
532*4882a593Smuzhiyun rk806->pins->p = NULL;
533*4882a593Smuzhiyun dev_err(dev, "no pinctrl handle\n");
534*4882a593Smuzhiyun return 0;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun rk806->pins->default_st = pinctrl_lookup_state(rk806->pins->p,
538*4882a593Smuzhiyun PINCTRL_STATE_DEFAULT);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun if (IS_ERR(rk806->pins->default_st))
541*4882a593Smuzhiyun dev_err(dev, "no default pinctrl state\n");
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun rk806->pins->power_off = pinctrl_lookup_state(rk806->pins->p,
544*4882a593Smuzhiyun "pmic-power-off");
545*4882a593Smuzhiyun if (IS_ERR(rk806->pins->power_off)) {
546*4882a593Smuzhiyun rk806->pins->power_off = NULL;
547*4882a593Smuzhiyun dev_err(dev, "no power-off pinctrl state\n");
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun rk806->pins->sleep = pinctrl_lookup_state(rk806->pins->p,
551*4882a593Smuzhiyun "pmic-sleep");
552*4882a593Smuzhiyun if (IS_ERR(rk806->pins->sleep)) {
553*4882a593Smuzhiyun rk806->pins->sleep = NULL;
554*4882a593Smuzhiyun dev_err(dev, "no sleep-setting state\n");
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun rk806->pins->reset = pinctrl_lookup_state(rk806->pins->p,
558*4882a593Smuzhiyun "pmic-reset");
559*4882a593Smuzhiyun if (IS_ERR(rk806->pins->reset)) {
560*4882a593Smuzhiyun rk806->pins->reset = NULL;
561*4882a593Smuzhiyun dev_err(dev, "no reset-setting pinctrl state\n");
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun rk806->pins->dvs = pinctrl_lookup_state(rk806->pins->p,
565*4882a593Smuzhiyun "pmic-dvs");
566*4882a593Smuzhiyun if (IS_ERR(rk806->pins->dvs)) {
567*4882a593Smuzhiyun rk806->pins->dvs = NULL;
568*4882a593Smuzhiyun dev_err(dev, "no dvs-setting pinctrl state\n");
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun return 0;
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun
rk806_vb_low_irq(int irq,void * rk806)574*4882a593Smuzhiyun static irqreturn_t rk806_vb_low_irq(int irq, void *rk806)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun return IRQ_HANDLED;
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun
rk806_low_power_irqs(struct rk806 * rk806)579*4882a593Smuzhiyun static int rk806_low_power_irqs(struct rk806 *rk806)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun struct rk806_platform_data *pdata;
582*4882a593Smuzhiyun int ret, vb_lo_irq;
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun pdata = rk806->pdata;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun if (!pdata->low_voltage_threshold)
587*4882a593Smuzhiyun return 0;
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun rk806_field_write(rk806, VB_LO_ACT, VB_LO_ACT_INT);
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun rk806_field_write(rk806, VB_LO_SEL,
592*4882a593Smuzhiyun (pdata->low_voltage_threshold - 2800) / 100);
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun vb_lo_irq = regmap_irq_get_virq(rk806->irq_data, RK806_IRQ_VB_LO);
595*4882a593Smuzhiyun if (vb_lo_irq < 0) {
596*4882a593Smuzhiyun dev_err(rk806->dev, "vb_lo_irq request failed!\n");
597*4882a593Smuzhiyun return vb_lo_irq;
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun ret = devm_request_threaded_irq(rk806->dev, vb_lo_irq,
601*4882a593Smuzhiyun NULL,
602*4882a593Smuzhiyun rk806_vb_low_irq,
603*4882a593Smuzhiyun IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
604*4882a593Smuzhiyun "rk806_vb_low", rk806);
605*4882a593Smuzhiyun if (ret) {
606*4882a593Smuzhiyun dev_err(rk806->dev, "vb_lo_irq request failed!\n");
607*4882a593Smuzhiyun return ret;
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun rk806->vb_lo_irq = vb_lo_irq;
611*4882a593Smuzhiyun disable_irq(rk806->vb_lo_irq);
612*4882a593Smuzhiyun enable_irq_wake(vb_lo_irq);
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun return 0;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun
rk806_parse_dt(struct rk806 * rk806)617*4882a593Smuzhiyun static int rk806_parse_dt(struct rk806 *rk806)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun struct rk806_platform_data *pdata;
620*4882a593Smuzhiyun struct device *dev = rk806->dev;
621*4882a593Smuzhiyun int rst_fun;
622*4882a593Smuzhiyun int ret;
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun pdata = rk806->pdata;
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun pdata->shutdown_voltage_threshold = 2700;
627*4882a593Smuzhiyun pdata->shutdown_temperture_threshold = 160;
628*4882a593Smuzhiyun pdata->hotdie_temperture_threshold = 115;
629*4882a593Smuzhiyun pdata->force_shutdown_enable = 1;
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun ret = device_property_read_u32(dev,
632*4882a593Smuzhiyun "low_voltage_threshold",
633*4882a593Smuzhiyun &pdata->low_voltage_threshold);
634*4882a593Smuzhiyun if (ret < 0) {
635*4882a593Smuzhiyun pdata->low_voltage_threshold = 0;
636*4882a593Smuzhiyun dev_info(dev, "low_voltage_threshold missing!\n");
637*4882a593Smuzhiyun } else {
638*4882a593Smuzhiyun if ((pdata->low_voltage_threshold > 3500) ||
639*4882a593Smuzhiyun (pdata->low_voltage_threshold < 2800)) {
640*4882a593Smuzhiyun dev_err(dev, "low_voltage_threshold out [2800 3500]!\n");
641*4882a593Smuzhiyun pdata->low_voltage_threshold = 2800;
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun ret = device_property_read_u32(dev,
645*4882a593Smuzhiyun "shutdown_voltage_threshold",
646*4882a593Smuzhiyun &pdata->shutdown_voltage_threshold);
647*4882a593Smuzhiyun if (ret < 0) {
648*4882a593Smuzhiyun pdata->force_shutdown_enable = 0;
649*4882a593Smuzhiyun dev_info(dev, "shutdown_voltage_threshold missing!\n");
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun if ((pdata->shutdown_voltage_threshold > 3400) ||
653*4882a593Smuzhiyun (pdata->shutdown_voltage_threshold < 2700)) {
654*4882a593Smuzhiyun dev_err(dev, "shutdown_voltage_threshold out [2700 3400]!\n");
655*4882a593Smuzhiyun pdata->shutdown_voltage_threshold = 2700;
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun ret = device_property_read_u32(dev,
659*4882a593Smuzhiyun "shutdown_temperture_threshold",
660*4882a593Smuzhiyun &pdata->shutdown_temperture_threshold);
661*4882a593Smuzhiyun if (ret < 0)
662*4882a593Smuzhiyun dev_info(dev, "shutdown_temperture_threshold missing!\n");
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun ret = device_property_read_u32(dev,
665*4882a593Smuzhiyun "hotdie_temperture_threshold",
666*4882a593Smuzhiyun &pdata->hotdie_temperture_threshold);
667*4882a593Smuzhiyun if (ret < 0)
668*4882a593Smuzhiyun dev_info(dev, "hotdie_temperture_threshold missing!\n");
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun ret = device_property_read_u32(dev, "pmic-reset-func", &rst_fun);
671*4882a593Smuzhiyun if (ret < 0) {
672*4882a593Smuzhiyun dev_info(dev, "pmic-reset-func missing!\n");
673*4882a593Smuzhiyun rk806_field_write(rk806, RST_FUN, 0x00);
674*4882a593Smuzhiyun } else
675*4882a593Smuzhiyun rk806_field_write(rk806, RST_FUN, rst_fun);
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun /* PWRON_ON_TIME: 0:500mS; 1:20mS */
678*4882a593Smuzhiyun if (device_property_read_bool(dev, "pwron-on-time-500ms"))
679*4882a593Smuzhiyun rk806_field_write(rk806, PWRON_ON_TIME, 0x00);
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun return 0;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun
rk806_init(struct rk806 * rk806)684*4882a593Smuzhiyun static int rk806_init(struct rk806 *rk806)
685*4882a593Smuzhiyun {
686*4882a593Smuzhiyun struct rk806_platform_data *pdata;
687*4882a593Smuzhiyun int vb_uv_sel;
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun pdata = rk806->pdata;
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun if (pdata->force_shutdown_enable) {
692*4882a593Smuzhiyun if (pdata->shutdown_voltage_threshold <= 2700)
693*4882a593Smuzhiyun vb_uv_sel = VB_UV_SEL_2700;
694*4882a593Smuzhiyun else
695*4882a593Smuzhiyun vb_uv_sel = (pdata->shutdown_voltage_threshold - 2700) / 100;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun rk806_field_write(rk806, VB_UV_SEL, vb_uv_sel);
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun if (pdata->hotdie_temperture_threshold >= 160)
701*4882a593Smuzhiyun rk806_field_write(rk806, TSD_TEMP, TSD_TEMP_160);
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun /* When the slave chip goes through a shutdown process, it will automatically trigger a restart */
704*4882a593Smuzhiyun rk806_field_write(rk806, SLAVE_RESTART_FUN, 0x01);
705*4882a593Smuzhiyun /* Digital output 2MHz clock force enable */
706*4882a593Smuzhiyun rk806_field_write(rk806, ENB2_2M, 0x01);
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun rk806_low_power_irqs(rk806);
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun return 0;
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun
rk806_device_init(struct rk806 * rk806)713*4882a593Smuzhiyun int rk806_device_init(struct rk806 *rk806)
714*4882a593Smuzhiyun {
715*4882a593Smuzhiyun struct device_node *np = rk806->dev->of_node;
716*4882a593Smuzhiyun struct rk806_platform_data *pdata;
717*4882a593Smuzhiyun int name_h, name_l, chip_ver, otp_ver;
718*4882a593Smuzhiyun int on_source, off_source;
719*4882a593Smuzhiyun int ret;
720*4882a593Smuzhiyun int i;
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun pdata = devm_kzalloc(rk806->dev, sizeof(*pdata), GFP_KERNEL);
723*4882a593Smuzhiyun if (!pdata)
724*4882a593Smuzhiyun return -ENOMEM;
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun rk806->pdata = pdata;
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(rk806_reg_fields); i++) {
729*4882a593Smuzhiyun const struct reg_field *reg_fields = rk806_reg_fields;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun rk806->rmap_fields[i] =
732*4882a593Smuzhiyun devm_regmap_field_alloc(rk806->dev,
733*4882a593Smuzhiyun rk806->regmap,
734*4882a593Smuzhiyun reg_fields[i]);
735*4882a593Smuzhiyun if (IS_ERR(rk806->rmap_fields[i])) {
736*4882a593Smuzhiyun dev_err(rk806->dev, "cannot allocate regmap field\n");
737*4882a593Smuzhiyun return PTR_ERR(rk806->rmap_fields[i]);
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun name_h = rk806_field_read(rk806, CHIP_NAME_H);
742*4882a593Smuzhiyun name_l = rk806_field_read(rk806, CHIP_NAME_L);
743*4882a593Smuzhiyun chip_ver = rk806_field_read(rk806, CHIP_VER);
744*4882a593Smuzhiyun otp_ver = rk806_field_read(rk806, OTP_VER);
745*4882a593Smuzhiyun dev_info(rk806->dev, "chip id: RK%x%x,ver:0x%x, 0x%x\n",
746*4882a593Smuzhiyun name_h, name_l, chip_ver, otp_ver);
747*4882a593Smuzhiyun if (chip_ver == VERSION_AB)
748*4882a593Smuzhiyun rk806_field_write(rk806, ABNORDET_EN, 0x01);
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun on_source = rk806_field_read(rk806, ON_SOURCE);
751*4882a593Smuzhiyun off_source = rk806_field_read(rk806, OFF_SOURCE);
752*4882a593Smuzhiyun dev_info(rk806->dev, "ON: 0x%x OFF:0x%x\n", on_source, off_source);
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun rk806_parse_dt(rk806);
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun rk806_irq_init(rk806);
757*4882a593Smuzhiyun ret = devm_regmap_add_irq_chip(rk806->dev,
758*4882a593Smuzhiyun rk806->regmap,
759*4882a593Smuzhiyun rk806->irq,
760*4882a593Smuzhiyun IRQF_ONESHOT | IRQF_SHARED,
761*4882a593Smuzhiyun 0,
762*4882a593Smuzhiyun &rk806_irq_chip,
763*4882a593Smuzhiyun &rk806->irq_data);
764*4882a593Smuzhiyun if (ret) {
765*4882a593Smuzhiyun dev_err(rk806->dev, "Failed to add IRQ chip: err = %d\n", ret);
766*4882a593Smuzhiyun return ret;
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun ret = devm_mfd_add_devices(rk806->dev,
770*4882a593Smuzhiyun PLATFORM_DEVID_AUTO,
771*4882a593Smuzhiyun rk806_cells,
772*4882a593Smuzhiyun ARRAY_SIZE(rk806_cells),
773*4882a593Smuzhiyun NULL,
774*4882a593Smuzhiyun 0,
775*4882a593Smuzhiyun regmap_irq_get_domain(rk806->irq_data));
776*4882a593Smuzhiyun if (ret < 0) {
777*4882a593Smuzhiyun dev_err(rk806->dev, "mfd_add_devices failed: %d\n", ret);
778*4882a593Smuzhiyun return ret;
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun rk806_pinctrl_init(rk806);
782*4882a593Smuzhiyun rk806_init(rk806);
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun if (strcmp(np->name, "rk806slave")) {
785*4882a593Smuzhiyun rk806_kobj[0] = kobject_create_and_add(np->name, NULL);
786*4882a593Smuzhiyun if (rk806_kobj[0]) {
787*4882a593Smuzhiyun ret = sysfs_create_file(rk806_kobj[0], &rk806_master_attrs.attr);
788*4882a593Smuzhiyun if (ret)
789*4882a593Smuzhiyun dev_err(rk806->dev, "create %s sysfs error\n", np->name);
790*4882a593Smuzhiyun else
791*4882a593Smuzhiyun rk806_master = rk806;
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun } else {
794*4882a593Smuzhiyun rk806_kobj[1] = kobject_create_and_add(np->name, NULL);
795*4882a593Smuzhiyun if (rk806_kobj[1]) {
796*4882a593Smuzhiyun ret = sysfs_create_file(rk806_kobj[1], &rk806_slaver_attrs.attr);
797*4882a593Smuzhiyun if (ret)
798*4882a593Smuzhiyun dev_err(rk806->dev, "create %s sysfs error\n", np->name);
799*4882a593Smuzhiyun else
800*4882a593Smuzhiyun rk806_slaver = rk806;
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun }
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun return 0;
805*4882a593Smuzhiyun }
806*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rk806_device_init);
807*4882a593Smuzhiyun
rk806_device_exit(struct rk806 * rk806)808*4882a593Smuzhiyun int rk806_device_exit(struct rk806 *rk806)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun struct device_node *np = rk806->dev->of_node;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun if (strcmp(np->name, "rk806slave")) {
813*4882a593Smuzhiyun if (rk806_kobj[0]) {
814*4882a593Smuzhiyun sysfs_remove_file(rk806_kobj[0], &rk806_master_attrs.attr);
815*4882a593Smuzhiyun kobject_put(rk806_kobj[0]);
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun } else {
818*4882a593Smuzhiyun if (rk806_kobj[1]) {
819*4882a593Smuzhiyun sysfs_remove_file(rk806_kobj[1], &rk806_slaver_attrs.attr);
820*4882a593Smuzhiyun kobject_put(rk806_kobj[1]);
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun return 0;
825*4882a593Smuzhiyun }
826*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rk806_device_exit);
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
829*4882a593Smuzhiyun MODULE_DESCRIPTION("rk806 MFD Driver");
830*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
831