]>
Commit | Line | Data |
---|---|---|
1f022d84 FF |
1 | /* |
2 | * Copyright (c) 2014 MediaTek Inc. | |
3 | * Author: Flora Fu, MediaTek | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License version 2 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | */ | |
14 | #include <linux/clk.h> | |
15 | #include <linux/interrupt.h> | |
16 | #include <linux/io.h> | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/module.h> | |
19 | #include <linux/of_device.h> | |
20 | #include <linux/platform_device.h> | |
21 | #include <linux/regmap.h> | |
22 | #include <linux/reset.h> | |
23 | ||
24 | #define PWRAP_MT8135_BRIDGE_IORD_ARB_EN 0x4 | |
25 | #define PWRAP_MT8135_BRIDGE_WACS3_EN 0x10 | |
26 | #define PWRAP_MT8135_BRIDGE_INIT_DONE3 0x14 | |
27 | #define PWRAP_MT8135_BRIDGE_WACS4_EN 0x24 | |
28 | #define PWRAP_MT8135_BRIDGE_INIT_DONE4 0x28 | |
29 | #define PWRAP_MT8135_BRIDGE_INT_EN 0x38 | |
30 | #define PWRAP_MT8135_BRIDGE_TIMER_EN 0x48 | |
31 | #define PWRAP_MT8135_BRIDGE_WDT_UNIT 0x50 | |
32 | #define PWRAP_MT8135_BRIDGE_WDT_SRC_EN 0x54 | |
33 | ||
34 | /* macro for wrapper status */ | |
35 | #define PWRAP_GET_WACS_RDATA(x) (((x) >> 0) & 0x0000ffff) | |
36 | #define PWRAP_GET_WACS_FSM(x) (((x) >> 16) & 0x00000007) | |
37 | #define PWRAP_GET_WACS_REQ(x) (((x) >> 19) & 0x00000001) | |
38 | #define PWRAP_STATE_SYNC_IDLE0 (1 << 20) | |
39 | #define PWRAP_STATE_INIT_DONE0 (1 << 21) | |
40 | ||
41 | /* macro for WACS FSM */ | |
42 | #define PWRAP_WACS_FSM_IDLE 0x00 | |
43 | #define PWRAP_WACS_FSM_REQ 0x02 | |
44 | #define PWRAP_WACS_FSM_WFDLE 0x04 | |
45 | #define PWRAP_WACS_FSM_WFVLDCLR 0x06 | |
46 | #define PWRAP_WACS_INIT_DONE 0x01 | |
47 | #define PWRAP_WACS_WACS_SYNC_IDLE 0x01 | |
48 | #define PWRAP_WACS_SYNC_BUSY 0x00 | |
49 | ||
50 | /* macro for device wrapper default value */ | |
51 | #define PWRAP_DEW_READ_TEST_VAL 0x5aa5 | |
52 | #define PWRAP_DEW_WRITE_TEST_VAL 0xa55a | |
53 | ||
54 | /* macro for manual command */ | |
060a1d64 | 55 | #define PWRAP_MAN_CMD_SPI_WRITE_NEW (1 << 14) |
1f022d84 FF |
56 | #define PWRAP_MAN_CMD_SPI_WRITE (1 << 13) |
57 | #define PWRAP_MAN_CMD_OP_CSH (0x0 << 8) | |
58 | #define PWRAP_MAN_CMD_OP_CSL (0x1 << 8) | |
59 | #define PWRAP_MAN_CMD_OP_CK (0x2 << 8) | |
60 | #define PWRAP_MAN_CMD_OP_OUTS (0x8 << 8) | |
61 | #define PWRAP_MAN_CMD_OP_OUTD (0x9 << 8) | |
62 | #define PWRAP_MAN_CMD_OP_OUTQ (0xa << 8) | |
63 | ||
a3bbfbb0 HC |
64 | /* macro for Watch Dog Timer Source */ |
65 | #define PWRAP_WDT_SRC_EN_STAUPD_TRIG (1 << 25) | |
66 | #define PWRAP_WDT_SRC_EN_HARB_STAUPD_DLE (1 << 20) | |
67 | #define PWRAP_WDT_SRC_EN_HARB_STAUPD_ALE (1 << 6) | |
68 | #define PWRAP_WDT_SRC_MASK_ALL 0xffffffff | |
69 | #define PWRAP_WDT_SRC_MASK_NO_STAUPD ~(PWRAP_WDT_SRC_EN_STAUPD_TRIG | \ | |
70 | PWRAP_WDT_SRC_EN_HARB_STAUPD_DLE | \ | |
71 | PWRAP_WDT_SRC_EN_HARB_STAUPD_ALE) | |
72 | ||
d56b31e2 SW |
73 | /* Group of bits used for shown slave capability */ |
74 | #define PWRAP_SLV_CAP_SPI BIT(0) | |
75 | #define PWRAP_SLV_CAP_DUALIO BIT(1) | |
76 | #define PWRAP_SLV_CAP_SECURITY BIT(2) | |
77 | #define HAS_CAP(_c, _x) (((_c) & (_x)) == (_x)) | |
78 | ||
b28d78cd JC |
79 | /* defines for slave device wrapper registers */ |
80 | enum dew_regs { | |
81 | PWRAP_DEW_BASE, | |
82 | PWRAP_DEW_DIO_EN, | |
83 | PWRAP_DEW_READ_TEST, | |
84 | PWRAP_DEW_WRITE_TEST, | |
85 | PWRAP_DEW_CRC_EN, | |
86 | PWRAP_DEW_CRC_VAL, | |
87 | PWRAP_DEW_MON_GRP_SEL, | |
88 | PWRAP_DEW_CIPHER_KEY_SEL, | |
89 | PWRAP_DEW_CIPHER_IV_SEL, | |
90 | PWRAP_DEW_CIPHER_RDY, | |
91 | PWRAP_DEW_CIPHER_MODE, | |
92 | PWRAP_DEW_CIPHER_SWRST, | |
93 | ||
94 | /* MT6397 only regs */ | |
95 | PWRAP_DEW_EVENT_OUT_EN, | |
96 | PWRAP_DEW_EVENT_SRC_EN, | |
97 | PWRAP_DEW_EVENT_SRC, | |
98 | PWRAP_DEW_EVENT_FLAG, | |
99 | PWRAP_DEW_MON_FLAG_SEL, | |
100 | PWRAP_DEW_EVENT_TEST, | |
101 | PWRAP_DEW_CIPHER_LOAD, | |
102 | PWRAP_DEW_CIPHER_START, | |
5ae48040 JC |
103 | |
104 | /* MT6323 only regs */ | |
105 | PWRAP_DEW_CIPHER_EN, | |
106 | PWRAP_DEW_RDDMY_NO, | |
107 | }; | |
108 | ||
109 | static const u32 mt6323_regs[] = { | |
110 | [PWRAP_DEW_BASE] = 0x0000, | |
111 | [PWRAP_DEW_DIO_EN] = 0x018a, | |
112 | [PWRAP_DEW_READ_TEST] = 0x018c, | |
113 | [PWRAP_DEW_WRITE_TEST] = 0x018e, | |
114 | [PWRAP_DEW_CRC_EN] = 0x0192, | |
115 | [PWRAP_DEW_CRC_VAL] = 0x0194, | |
116 | [PWRAP_DEW_MON_GRP_SEL] = 0x0196, | |
117 | [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0198, | |
118 | [PWRAP_DEW_CIPHER_IV_SEL] = 0x019a, | |
119 | [PWRAP_DEW_CIPHER_EN] = 0x019c, | |
120 | [PWRAP_DEW_CIPHER_RDY] = 0x019e, | |
121 | [PWRAP_DEW_CIPHER_MODE] = 0x01a0, | |
122 | [PWRAP_DEW_CIPHER_SWRST] = 0x01a2, | |
123 | [PWRAP_DEW_RDDMY_NO] = 0x01a4, | |
b28d78cd JC |
124 | }; |
125 | ||
126 | static const u32 mt6397_regs[] = { | |
127 | [PWRAP_DEW_BASE] = 0xbc00, | |
128 | [PWRAP_DEW_EVENT_OUT_EN] = 0xbc00, | |
129 | [PWRAP_DEW_DIO_EN] = 0xbc02, | |
130 | [PWRAP_DEW_EVENT_SRC_EN] = 0xbc04, | |
131 | [PWRAP_DEW_EVENT_SRC] = 0xbc06, | |
132 | [PWRAP_DEW_EVENT_FLAG] = 0xbc08, | |
133 | [PWRAP_DEW_READ_TEST] = 0xbc0a, | |
134 | [PWRAP_DEW_WRITE_TEST] = 0xbc0c, | |
135 | [PWRAP_DEW_CRC_EN] = 0xbc0e, | |
136 | [PWRAP_DEW_CRC_VAL] = 0xbc10, | |
137 | [PWRAP_DEW_MON_GRP_SEL] = 0xbc12, | |
138 | [PWRAP_DEW_MON_FLAG_SEL] = 0xbc14, | |
139 | [PWRAP_DEW_EVENT_TEST] = 0xbc16, | |
140 | [PWRAP_DEW_CIPHER_KEY_SEL] = 0xbc18, | |
141 | [PWRAP_DEW_CIPHER_IV_SEL] = 0xbc1a, | |
142 | [PWRAP_DEW_CIPHER_LOAD] = 0xbc1c, | |
143 | [PWRAP_DEW_CIPHER_START] = 0xbc1e, | |
144 | [PWRAP_DEW_CIPHER_RDY] = 0xbc20, | |
145 | [PWRAP_DEW_CIPHER_MODE] = 0xbc22, | |
146 | [PWRAP_DEW_CIPHER_SWRST] = 0xbc24, | |
147 | }; | |
1f022d84 FF |
148 | |
149 | enum pwrap_regs { | |
150 | PWRAP_MUX_SEL, | |
151 | PWRAP_WRAP_EN, | |
152 | PWRAP_DIO_EN, | |
153 | PWRAP_SIDLY, | |
154 | PWRAP_CSHEXT_WRITE, | |
155 | PWRAP_CSHEXT_READ, | |
156 | PWRAP_CSLEXT_START, | |
157 | PWRAP_CSLEXT_END, | |
158 | PWRAP_STAUPD_PRD, | |
159 | PWRAP_STAUPD_GRPEN, | |
160 | PWRAP_STAUPD_MAN_TRIG, | |
161 | PWRAP_STAUPD_STA, | |
162 | PWRAP_WRAP_STA, | |
163 | PWRAP_HARB_INIT, | |
164 | PWRAP_HARB_HPRIO, | |
165 | PWRAP_HIPRIO_ARB_EN, | |
166 | PWRAP_HARB_STA0, | |
167 | PWRAP_HARB_STA1, | |
168 | PWRAP_MAN_EN, | |
169 | PWRAP_MAN_CMD, | |
170 | PWRAP_MAN_RDATA, | |
171 | PWRAP_MAN_VLDCLR, | |
172 | PWRAP_WACS0_EN, | |
173 | PWRAP_INIT_DONE0, | |
174 | PWRAP_WACS0_CMD, | |
175 | PWRAP_WACS0_RDATA, | |
176 | PWRAP_WACS0_VLDCLR, | |
177 | PWRAP_WACS1_EN, | |
178 | PWRAP_INIT_DONE1, | |
179 | PWRAP_WACS1_CMD, | |
180 | PWRAP_WACS1_RDATA, | |
181 | PWRAP_WACS1_VLDCLR, | |
182 | PWRAP_WACS2_EN, | |
183 | PWRAP_INIT_DONE2, | |
184 | PWRAP_WACS2_CMD, | |
185 | PWRAP_WACS2_RDATA, | |
186 | PWRAP_WACS2_VLDCLR, | |
187 | PWRAP_INT_EN, | |
188 | PWRAP_INT_FLG_RAW, | |
189 | PWRAP_INT_FLG, | |
190 | PWRAP_INT_CLR, | |
191 | PWRAP_SIG_ADR, | |
192 | PWRAP_SIG_MODE, | |
193 | PWRAP_SIG_VALUE, | |
194 | PWRAP_SIG_ERRVAL, | |
195 | PWRAP_CRC_EN, | |
196 | PWRAP_TIMER_EN, | |
197 | PWRAP_TIMER_STA, | |
198 | PWRAP_WDT_UNIT, | |
199 | PWRAP_WDT_SRC_EN, | |
200 | PWRAP_WDT_FLG, | |
201 | PWRAP_DEBUG_INT_SEL, | |
202 | PWRAP_CIPHER_KEY_SEL, | |
203 | PWRAP_CIPHER_IV_SEL, | |
204 | PWRAP_CIPHER_RDY, | |
205 | PWRAP_CIPHER_MODE, | |
206 | PWRAP_CIPHER_SWRST, | |
207 | PWRAP_DCM_EN, | |
208 | PWRAP_DCM_DBC_PRD, | |
209 | ||
060a1d64 JC |
210 | /* MT2701 only regs */ |
211 | PWRAP_ADC_CMD_ADDR, | |
212 | PWRAP_PWRAP_ADC_CMD, | |
213 | PWRAP_ADC_RDY_ADDR, | |
214 | PWRAP_ADC_RDATA_ADDR1, | |
215 | PWRAP_ADC_RDATA_ADDR2, | |
216 | ||
69d0c060 CX |
217 | /* MT7622 only regs */ |
218 | PWRAP_EINT_STA0_ADR, | |
219 | PWRAP_EINT_STA1_ADR, | |
220 | PWRAP_STA, | |
221 | PWRAP_CLR, | |
222 | PWRAP_DVFS_ADR8, | |
223 | PWRAP_DVFS_WDATA8, | |
224 | PWRAP_DVFS_ADR9, | |
225 | PWRAP_DVFS_WDATA9, | |
226 | PWRAP_DVFS_ADR10, | |
227 | PWRAP_DVFS_WDATA10, | |
228 | PWRAP_DVFS_ADR11, | |
229 | PWRAP_DVFS_WDATA11, | |
230 | PWRAP_DVFS_ADR12, | |
231 | PWRAP_DVFS_WDATA12, | |
232 | PWRAP_DVFS_ADR13, | |
233 | PWRAP_DVFS_WDATA13, | |
234 | PWRAP_DVFS_ADR14, | |
235 | PWRAP_DVFS_WDATA14, | |
236 | PWRAP_DVFS_ADR15, | |
237 | PWRAP_DVFS_WDATA15, | |
238 | PWRAP_EXT_CK, | |
239 | PWRAP_ADC_RDATA_ADDR, | |
240 | PWRAP_GPS_STA, | |
241 | PWRAP_SW_RST, | |
242 | PWRAP_DVFS_STEP_CTRL0, | |
243 | PWRAP_DVFS_STEP_CTRL1, | |
244 | PWRAP_DVFS_STEP_CTRL2, | |
245 | PWRAP_SPI2_CTRL, | |
246 | ||
1f022d84 FF |
247 | /* MT8135 only regs */ |
248 | PWRAP_CSHEXT, | |
249 | PWRAP_EVENT_IN_EN, | |
250 | PWRAP_EVENT_DST_EN, | |
251 | PWRAP_RRARB_INIT, | |
252 | PWRAP_RRARB_EN, | |
253 | PWRAP_RRARB_STA0, | |
254 | PWRAP_RRARB_STA1, | |
255 | PWRAP_EVENT_STA, | |
256 | PWRAP_EVENT_STACLR, | |
257 | PWRAP_CIPHER_LOAD, | |
258 | PWRAP_CIPHER_START, | |
259 | ||
260 | /* MT8173 only regs */ | |
261 | PWRAP_RDDMY, | |
262 | PWRAP_SI_CK_CON, | |
263 | PWRAP_DVFS_ADR0, | |
264 | PWRAP_DVFS_WDATA0, | |
265 | PWRAP_DVFS_ADR1, | |
266 | PWRAP_DVFS_WDATA1, | |
267 | PWRAP_DVFS_ADR2, | |
268 | PWRAP_DVFS_WDATA2, | |
269 | PWRAP_DVFS_ADR3, | |
270 | PWRAP_DVFS_WDATA3, | |
271 | PWRAP_DVFS_ADR4, | |
272 | PWRAP_DVFS_WDATA4, | |
273 | PWRAP_DVFS_ADR5, | |
274 | PWRAP_DVFS_WDATA5, | |
275 | PWRAP_DVFS_ADR6, | |
276 | PWRAP_DVFS_WDATA6, | |
277 | PWRAP_DVFS_ADR7, | |
278 | PWRAP_DVFS_WDATA7, | |
279 | PWRAP_SPMINF_STA, | |
280 | PWRAP_CIPHER_EN, | |
281 | }; | |
282 | ||
060a1d64 JC |
283 | static int mt2701_regs[] = { |
284 | [PWRAP_MUX_SEL] = 0x0, | |
285 | [PWRAP_WRAP_EN] = 0x4, | |
286 | [PWRAP_DIO_EN] = 0x8, | |
287 | [PWRAP_SIDLY] = 0xc, | |
288 | [PWRAP_RDDMY] = 0x18, | |
289 | [PWRAP_SI_CK_CON] = 0x1c, | |
290 | [PWRAP_CSHEXT_WRITE] = 0x20, | |
291 | [PWRAP_CSHEXT_READ] = 0x24, | |
292 | [PWRAP_CSLEXT_START] = 0x28, | |
293 | [PWRAP_CSLEXT_END] = 0x2c, | |
294 | [PWRAP_STAUPD_PRD] = 0x30, | |
295 | [PWRAP_STAUPD_GRPEN] = 0x34, | |
296 | [PWRAP_STAUPD_MAN_TRIG] = 0x38, | |
297 | [PWRAP_STAUPD_STA] = 0x3c, | |
298 | [PWRAP_WRAP_STA] = 0x44, | |
299 | [PWRAP_HARB_INIT] = 0x48, | |
300 | [PWRAP_HARB_HPRIO] = 0x4c, | |
301 | [PWRAP_HIPRIO_ARB_EN] = 0x50, | |
302 | [PWRAP_HARB_STA0] = 0x54, | |
303 | [PWRAP_HARB_STA1] = 0x58, | |
304 | [PWRAP_MAN_EN] = 0x5c, | |
305 | [PWRAP_MAN_CMD] = 0x60, | |
306 | [PWRAP_MAN_RDATA] = 0x64, | |
307 | [PWRAP_MAN_VLDCLR] = 0x68, | |
308 | [PWRAP_WACS0_EN] = 0x6c, | |
309 | [PWRAP_INIT_DONE0] = 0x70, | |
310 | [PWRAP_WACS0_CMD] = 0x74, | |
311 | [PWRAP_WACS0_RDATA] = 0x78, | |
312 | [PWRAP_WACS0_VLDCLR] = 0x7c, | |
313 | [PWRAP_WACS1_EN] = 0x80, | |
314 | [PWRAP_INIT_DONE1] = 0x84, | |
315 | [PWRAP_WACS1_CMD] = 0x88, | |
316 | [PWRAP_WACS1_RDATA] = 0x8c, | |
317 | [PWRAP_WACS1_VLDCLR] = 0x90, | |
318 | [PWRAP_WACS2_EN] = 0x94, | |
319 | [PWRAP_INIT_DONE2] = 0x98, | |
320 | [PWRAP_WACS2_CMD] = 0x9c, | |
321 | [PWRAP_WACS2_RDATA] = 0xa0, | |
322 | [PWRAP_WACS2_VLDCLR] = 0xa4, | |
323 | [PWRAP_INT_EN] = 0xa8, | |
324 | [PWRAP_INT_FLG_RAW] = 0xac, | |
325 | [PWRAP_INT_FLG] = 0xb0, | |
326 | [PWRAP_INT_CLR] = 0xb4, | |
327 | [PWRAP_SIG_ADR] = 0xb8, | |
328 | [PWRAP_SIG_MODE] = 0xbc, | |
329 | [PWRAP_SIG_VALUE] = 0xc0, | |
330 | [PWRAP_SIG_ERRVAL] = 0xc4, | |
331 | [PWRAP_CRC_EN] = 0xc8, | |
332 | [PWRAP_TIMER_EN] = 0xcc, | |
333 | [PWRAP_TIMER_STA] = 0xd0, | |
334 | [PWRAP_WDT_UNIT] = 0xd4, | |
335 | [PWRAP_WDT_SRC_EN] = 0xd8, | |
336 | [PWRAP_WDT_FLG] = 0xdc, | |
337 | [PWRAP_DEBUG_INT_SEL] = 0xe0, | |
338 | [PWRAP_DVFS_ADR0] = 0xe4, | |
339 | [PWRAP_DVFS_WDATA0] = 0xe8, | |
340 | [PWRAP_DVFS_ADR1] = 0xec, | |
341 | [PWRAP_DVFS_WDATA1] = 0xf0, | |
342 | [PWRAP_DVFS_ADR2] = 0xf4, | |
343 | [PWRAP_DVFS_WDATA2] = 0xf8, | |
344 | [PWRAP_DVFS_ADR3] = 0xfc, | |
345 | [PWRAP_DVFS_WDATA3] = 0x100, | |
346 | [PWRAP_DVFS_ADR4] = 0x104, | |
347 | [PWRAP_DVFS_WDATA4] = 0x108, | |
348 | [PWRAP_DVFS_ADR5] = 0x10c, | |
349 | [PWRAP_DVFS_WDATA5] = 0x110, | |
350 | [PWRAP_DVFS_ADR6] = 0x114, | |
351 | [PWRAP_DVFS_WDATA6] = 0x118, | |
352 | [PWRAP_DVFS_ADR7] = 0x11c, | |
353 | [PWRAP_DVFS_WDATA7] = 0x120, | |
354 | [PWRAP_CIPHER_KEY_SEL] = 0x124, | |
355 | [PWRAP_CIPHER_IV_SEL] = 0x128, | |
356 | [PWRAP_CIPHER_EN] = 0x12c, | |
357 | [PWRAP_CIPHER_RDY] = 0x130, | |
358 | [PWRAP_CIPHER_MODE] = 0x134, | |
359 | [PWRAP_CIPHER_SWRST] = 0x138, | |
360 | [PWRAP_DCM_EN] = 0x13c, | |
361 | [PWRAP_DCM_DBC_PRD] = 0x140, | |
362 | [PWRAP_ADC_CMD_ADDR] = 0x144, | |
363 | [PWRAP_PWRAP_ADC_CMD] = 0x148, | |
364 | [PWRAP_ADC_RDY_ADDR] = 0x14c, | |
365 | [PWRAP_ADC_RDATA_ADDR1] = 0x150, | |
366 | [PWRAP_ADC_RDATA_ADDR2] = 0x154, | |
367 | }; | |
368 | ||
69d0c060 CX |
369 | static int mt7622_regs[] = { |
370 | [PWRAP_MUX_SEL] = 0x0, | |
371 | [PWRAP_WRAP_EN] = 0x4, | |
372 | [PWRAP_DIO_EN] = 0x8, | |
373 | [PWRAP_SIDLY] = 0xC, | |
374 | [PWRAP_RDDMY] = 0x10, | |
375 | [PWRAP_SI_CK_CON] = 0x14, | |
376 | [PWRAP_CSHEXT_WRITE] = 0x18, | |
377 | [PWRAP_CSHEXT_READ] = 0x1C, | |
378 | [PWRAP_CSLEXT_START] = 0x20, | |
379 | [PWRAP_CSLEXT_END] = 0x24, | |
380 | [PWRAP_STAUPD_PRD] = 0x28, | |
381 | [PWRAP_STAUPD_GRPEN] = 0x2C, | |
382 | [PWRAP_EINT_STA0_ADR] = 0x30, | |
383 | [PWRAP_EINT_STA1_ADR] = 0x34, | |
384 | [PWRAP_STA] = 0x38, | |
385 | [PWRAP_CLR] = 0x3C, | |
386 | [PWRAP_STAUPD_MAN_TRIG] = 0x40, | |
387 | [PWRAP_STAUPD_STA] = 0x44, | |
388 | [PWRAP_WRAP_STA] = 0x48, | |
389 | [PWRAP_HARB_INIT] = 0x4C, | |
390 | [PWRAP_HARB_HPRIO] = 0x50, | |
391 | [PWRAP_HIPRIO_ARB_EN] = 0x54, | |
392 | [PWRAP_HARB_STA0] = 0x58, | |
393 | [PWRAP_HARB_STA1] = 0x5C, | |
394 | [PWRAP_MAN_EN] = 0x60, | |
395 | [PWRAP_MAN_CMD] = 0x64, | |
396 | [PWRAP_MAN_RDATA] = 0x68, | |
397 | [PWRAP_MAN_VLDCLR] = 0x6C, | |
398 | [PWRAP_WACS0_EN] = 0x70, | |
399 | [PWRAP_INIT_DONE0] = 0x74, | |
400 | [PWRAP_WACS0_CMD] = 0x78, | |
401 | [PWRAP_WACS0_RDATA] = 0x7C, | |
402 | [PWRAP_WACS0_VLDCLR] = 0x80, | |
403 | [PWRAP_WACS1_EN] = 0x84, | |
404 | [PWRAP_INIT_DONE1] = 0x88, | |
405 | [PWRAP_WACS1_CMD] = 0x8C, | |
406 | [PWRAP_WACS1_RDATA] = 0x90, | |
407 | [PWRAP_WACS1_VLDCLR] = 0x94, | |
408 | [PWRAP_WACS2_EN] = 0x98, | |
409 | [PWRAP_INIT_DONE2] = 0x9C, | |
410 | [PWRAP_WACS2_CMD] = 0xA0, | |
411 | [PWRAP_WACS2_RDATA] = 0xA4, | |
412 | [PWRAP_WACS2_VLDCLR] = 0xA8, | |
413 | [PWRAP_INT_EN] = 0xAC, | |
414 | [PWRAP_INT_FLG_RAW] = 0xB0, | |
415 | [PWRAP_INT_FLG] = 0xB4, | |
416 | [PWRAP_INT_CLR] = 0xB8, | |
417 | [PWRAP_SIG_ADR] = 0xBC, | |
418 | [PWRAP_SIG_MODE] = 0xC0, | |
419 | [PWRAP_SIG_VALUE] = 0xC4, | |
420 | [PWRAP_SIG_ERRVAL] = 0xC8, | |
421 | [PWRAP_CRC_EN] = 0xCC, | |
422 | [PWRAP_TIMER_EN] = 0xD0, | |
423 | [PWRAP_TIMER_STA] = 0xD4, | |
424 | [PWRAP_WDT_UNIT] = 0xD8, | |
425 | [PWRAP_WDT_SRC_EN] = 0xDC, | |
426 | [PWRAP_WDT_FLG] = 0xE0, | |
427 | [PWRAP_DEBUG_INT_SEL] = 0xE4, | |
428 | [PWRAP_DVFS_ADR0] = 0xE8, | |
429 | [PWRAP_DVFS_WDATA0] = 0xEC, | |
430 | [PWRAP_DVFS_ADR1] = 0xF0, | |
431 | [PWRAP_DVFS_WDATA1] = 0xF4, | |
432 | [PWRAP_DVFS_ADR2] = 0xF8, | |
433 | [PWRAP_DVFS_WDATA2] = 0xFC, | |
434 | [PWRAP_DVFS_ADR3] = 0x100, | |
435 | [PWRAP_DVFS_WDATA3] = 0x104, | |
436 | [PWRAP_DVFS_ADR4] = 0x108, | |
437 | [PWRAP_DVFS_WDATA4] = 0x10C, | |
438 | [PWRAP_DVFS_ADR5] = 0x110, | |
439 | [PWRAP_DVFS_WDATA5] = 0x114, | |
440 | [PWRAP_DVFS_ADR6] = 0x118, | |
441 | [PWRAP_DVFS_WDATA6] = 0x11C, | |
442 | [PWRAP_DVFS_ADR7] = 0x120, | |
443 | [PWRAP_DVFS_WDATA7] = 0x124, | |
444 | [PWRAP_DVFS_ADR8] = 0x128, | |
445 | [PWRAP_DVFS_WDATA8] = 0x12C, | |
446 | [PWRAP_DVFS_ADR9] = 0x130, | |
447 | [PWRAP_DVFS_WDATA9] = 0x134, | |
448 | [PWRAP_DVFS_ADR10] = 0x138, | |
449 | [PWRAP_DVFS_WDATA10] = 0x13C, | |
450 | [PWRAP_DVFS_ADR11] = 0x140, | |
451 | [PWRAP_DVFS_WDATA11] = 0x144, | |
452 | [PWRAP_DVFS_ADR12] = 0x148, | |
453 | [PWRAP_DVFS_WDATA12] = 0x14C, | |
454 | [PWRAP_DVFS_ADR13] = 0x150, | |
455 | [PWRAP_DVFS_WDATA13] = 0x154, | |
456 | [PWRAP_DVFS_ADR14] = 0x158, | |
457 | [PWRAP_DVFS_WDATA14] = 0x15C, | |
458 | [PWRAP_DVFS_ADR15] = 0x160, | |
459 | [PWRAP_DVFS_WDATA15] = 0x164, | |
460 | [PWRAP_SPMINF_STA] = 0x168, | |
461 | [PWRAP_CIPHER_KEY_SEL] = 0x16C, | |
462 | [PWRAP_CIPHER_IV_SEL] = 0x170, | |
463 | [PWRAP_CIPHER_EN] = 0x174, | |
464 | [PWRAP_CIPHER_RDY] = 0x178, | |
465 | [PWRAP_CIPHER_MODE] = 0x17C, | |
466 | [PWRAP_CIPHER_SWRST] = 0x180, | |
467 | [PWRAP_DCM_EN] = 0x184, | |
468 | [PWRAP_DCM_DBC_PRD] = 0x188, | |
469 | [PWRAP_EXT_CK] = 0x18C, | |
470 | [PWRAP_ADC_CMD_ADDR] = 0x190, | |
471 | [PWRAP_PWRAP_ADC_CMD] = 0x194, | |
472 | [PWRAP_ADC_RDATA_ADDR] = 0x198, | |
473 | [PWRAP_GPS_STA] = 0x19C, | |
474 | [PWRAP_SW_RST] = 0x1A0, | |
475 | [PWRAP_DVFS_STEP_CTRL0] = 0x238, | |
476 | [PWRAP_DVFS_STEP_CTRL1] = 0x23C, | |
477 | [PWRAP_DVFS_STEP_CTRL2] = 0x240, | |
478 | [PWRAP_SPI2_CTRL] = 0x244, | |
479 | }; | |
480 | ||
1f022d84 FF |
481 | static int mt8173_regs[] = { |
482 | [PWRAP_MUX_SEL] = 0x0, | |
483 | [PWRAP_WRAP_EN] = 0x4, | |
484 | [PWRAP_DIO_EN] = 0x8, | |
485 | [PWRAP_SIDLY] = 0xc, | |
486 | [PWRAP_RDDMY] = 0x10, | |
487 | [PWRAP_SI_CK_CON] = 0x14, | |
488 | [PWRAP_CSHEXT_WRITE] = 0x18, | |
489 | [PWRAP_CSHEXT_READ] = 0x1c, | |
490 | [PWRAP_CSLEXT_START] = 0x20, | |
491 | [PWRAP_CSLEXT_END] = 0x24, | |
492 | [PWRAP_STAUPD_PRD] = 0x28, | |
493 | [PWRAP_STAUPD_GRPEN] = 0x2c, | |
494 | [PWRAP_STAUPD_MAN_TRIG] = 0x40, | |
495 | [PWRAP_STAUPD_STA] = 0x44, | |
496 | [PWRAP_WRAP_STA] = 0x48, | |
497 | [PWRAP_HARB_INIT] = 0x4c, | |
498 | [PWRAP_HARB_HPRIO] = 0x50, | |
499 | [PWRAP_HIPRIO_ARB_EN] = 0x54, | |
500 | [PWRAP_HARB_STA0] = 0x58, | |
501 | [PWRAP_HARB_STA1] = 0x5c, | |
502 | [PWRAP_MAN_EN] = 0x60, | |
503 | [PWRAP_MAN_CMD] = 0x64, | |
504 | [PWRAP_MAN_RDATA] = 0x68, | |
505 | [PWRAP_MAN_VLDCLR] = 0x6c, | |
506 | [PWRAP_WACS0_EN] = 0x70, | |
507 | [PWRAP_INIT_DONE0] = 0x74, | |
508 | [PWRAP_WACS0_CMD] = 0x78, | |
509 | [PWRAP_WACS0_RDATA] = 0x7c, | |
510 | [PWRAP_WACS0_VLDCLR] = 0x80, | |
511 | [PWRAP_WACS1_EN] = 0x84, | |
512 | [PWRAP_INIT_DONE1] = 0x88, | |
513 | [PWRAP_WACS1_CMD] = 0x8c, | |
514 | [PWRAP_WACS1_RDATA] = 0x90, | |
515 | [PWRAP_WACS1_VLDCLR] = 0x94, | |
516 | [PWRAP_WACS2_EN] = 0x98, | |
517 | [PWRAP_INIT_DONE2] = 0x9c, | |
518 | [PWRAP_WACS2_CMD] = 0xa0, | |
519 | [PWRAP_WACS2_RDATA] = 0xa4, | |
520 | [PWRAP_WACS2_VLDCLR] = 0xa8, | |
521 | [PWRAP_INT_EN] = 0xac, | |
522 | [PWRAP_INT_FLG_RAW] = 0xb0, | |
523 | [PWRAP_INT_FLG] = 0xb4, | |
524 | [PWRAP_INT_CLR] = 0xb8, | |
525 | [PWRAP_SIG_ADR] = 0xbc, | |
526 | [PWRAP_SIG_MODE] = 0xc0, | |
527 | [PWRAP_SIG_VALUE] = 0xc4, | |
528 | [PWRAP_SIG_ERRVAL] = 0xc8, | |
529 | [PWRAP_CRC_EN] = 0xcc, | |
530 | [PWRAP_TIMER_EN] = 0xd0, | |
531 | [PWRAP_TIMER_STA] = 0xd4, | |
532 | [PWRAP_WDT_UNIT] = 0xd8, | |
533 | [PWRAP_WDT_SRC_EN] = 0xdc, | |
534 | [PWRAP_WDT_FLG] = 0xe0, | |
535 | [PWRAP_DEBUG_INT_SEL] = 0xe4, | |
536 | [PWRAP_DVFS_ADR0] = 0xe8, | |
537 | [PWRAP_DVFS_WDATA0] = 0xec, | |
538 | [PWRAP_DVFS_ADR1] = 0xf0, | |
539 | [PWRAP_DVFS_WDATA1] = 0xf4, | |
540 | [PWRAP_DVFS_ADR2] = 0xf8, | |
541 | [PWRAP_DVFS_WDATA2] = 0xfc, | |
542 | [PWRAP_DVFS_ADR3] = 0x100, | |
543 | [PWRAP_DVFS_WDATA3] = 0x104, | |
544 | [PWRAP_DVFS_ADR4] = 0x108, | |
545 | [PWRAP_DVFS_WDATA4] = 0x10c, | |
546 | [PWRAP_DVFS_ADR5] = 0x110, | |
547 | [PWRAP_DVFS_WDATA5] = 0x114, | |
548 | [PWRAP_DVFS_ADR6] = 0x118, | |
549 | [PWRAP_DVFS_WDATA6] = 0x11c, | |
550 | [PWRAP_DVFS_ADR7] = 0x120, | |
551 | [PWRAP_DVFS_WDATA7] = 0x124, | |
552 | [PWRAP_SPMINF_STA] = 0x128, | |
553 | [PWRAP_CIPHER_KEY_SEL] = 0x12c, | |
554 | [PWRAP_CIPHER_IV_SEL] = 0x130, | |
555 | [PWRAP_CIPHER_EN] = 0x134, | |
556 | [PWRAP_CIPHER_RDY] = 0x138, | |
557 | [PWRAP_CIPHER_MODE] = 0x13c, | |
558 | [PWRAP_CIPHER_SWRST] = 0x140, | |
559 | [PWRAP_DCM_EN] = 0x144, | |
560 | [PWRAP_DCM_DBC_PRD] = 0x148, | |
561 | }; | |
562 | ||
563 | static int mt8135_regs[] = { | |
564 | [PWRAP_MUX_SEL] = 0x0, | |
565 | [PWRAP_WRAP_EN] = 0x4, | |
566 | [PWRAP_DIO_EN] = 0x8, | |
567 | [PWRAP_SIDLY] = 0xc, | |
568 | [PWRAP_CSHEXT] = 0x10, | |
569 | [PWRAP_CSHEXT_WRITE] = 0x14, | |
570 | [PWRAP_CSHEXT_READ] = 0x18, | |
571 | [PWRAP_CSLEXT_START] = 0x1c, | |
572 | [PWRAP_CSLEXT_END] = 0x20, | |
573 | [PWRAP_STAUPD_PRD] = 0x24, | |
574 | [PWRAP_STAUPD_GRPEN] = 0x28, | |
575 | [PWRAP_STAUPD_MAN_TRIG] = 0x2c, | |
576 | [PWRAP_STAUPD_STA] = 0x30, | |
577 | [PWRAP_EVENT_IN_EN] = 0x34, | |
578 | [PWRAP_EVENT_DST_EN] = 0x38, | |
579 | [PWRAP_WRAP_STA] = 0x3c, | |
580 | [PWRAP_RRARB_INIT] = 0x40, | |
581 | [PWRAP_RRARB_EN] = 0x44, | |
582 | [PWRAP_RRARB_STA0] = 0x48, | |
583 | [PWRAP_RRARB_STA1] = 0x4c, | |
584 | [PWRAP_HARB_INIT] = 0x50, | |
585 | [PWRAP_HARB_HPRIO] = 0x54, | |
586 | [PWRAP_HIPRIO_ARB_EN] = 0x58, | |
587 | [PWRAP_HARB_STA0] = 0x5c, | |
588 | [PWRAP_HARB_STA1] = 0x60, | |
589 | [PWRAP_MAN_EN] = 0x64, | |
590 | [PWRAP_MAN_CMD] = 0x68, | |
591 | [PWRAP_MAN_RDATA] = 0x6c, | |
592 | [PWRAP_MAN_VLDCLR] = 0x70, | |
593 | [PWRAP_WACS0_EN] = 0x74, | |
594 | [PWRAP_INIT_DONE0] = 0x78, | |
595 | [PWRAP_WACS0_CMD] = 0x7c, | |
596 | [PWRAP_WACS0_RDATA] = 0x80, | |
597 | [PWRAP_WACS0_VLDCLR] = 0x84, | |
598 | [PWRAP_WACS1_EN] = 0x88, | |
599 | [PWRAP_INIT_DONE1] = 0x8c, | |
600 | [PWRAP_WACS1_CMD] = 0x90, | |
601 | [PWRAP_WACS1_RDATA] = 0x94, | |
602 | [PWRAP_WACS1_VLDCLR] = 0x98, | |
603 | [PWRAP_WACS2_EN] = 0x9c, | |
604 | [PWRAP_INIT_DONE2] = 0xa0, | |
605 | [PWRAP_WACS2_CMD] = 0xa4, | |
606 | [PWRAP_WACS2_RDATA] = 0xa8, | |
607 | [PWRAP_WACS2_VLDCLR] = 0xac, | |
608 | [PWRAP_INT_EN] = 0xb0, | |
609 | [PWRAP_INT_FLG_RAW] = 0xb4, | |
610 | [PWRAP_INT_FLG] = 0xb8, | |
611 | [PWRAP_INT_CLR] = 0xbc, | |
612 | [PWRAP_SIG_ADR] = 0xc0, | |
613 | [PWRAP_SIG_MODE] = 0xc4, | |
614 | [PWRAP_SIG_VALUE] = 0xc8, | |
615 | [PWRAP_SIG_ERRVAL] = 0xcc, | |
616 | [PWRAP_CRC_EN] = 0xd0, | |
617 | [PWRAP_EVENT_STA] = 0xd4, | |
618 | [PWRAP_EVENT_STACLR] = 0xd8, | |
619 | [PWRAP_TIMER_EN] = 0xdc, | |
620 | [PWRAP_TIMER_STA] = 0xe0, | |
621 | [PWRAP_WDT_UNIT] = 0xe4, | |
622 | [PWRAP_WDT_SRC_EN] = 0xe8, | |
623 | [PWRAP_WDT_FLG] = 0xec, | |
624 | [PWRAP_DEBUG_INT_SEL] = 0xf0, | |
625 | [PWRAP_CIPHER_KEY_SEL] = 0x134, | |
626 | [PWRAP_CIPHER_IV_SEL] = 0x138, | |
627 | [PWRAP_CIPHER_LOAD] = 0x13c, | |
628 | [PWRAP_CIPHER_START] = 0x140, | |
629 | [PWRAP_CIPHER_RDY] = 0x144, | |
630 | [PWRAP_CIPHER_MODE] = 0x148, | |
631 | [PWRAP_CIPHER_SWRST] = 0x14c, | |
632 | [PWRAP_DCM_EN] = 0x15c, | |
633 | [PWRAP_DCM_DBC_PRD] = 0x160, | |
634 | }; | |
635 | ||
b28d78cd | 636 | enum pmic_type { |
5ae48040 | 637 | PMIC_MT6323, |
ec833686 | 638 | PMIC_MT6380, |
b28d78cd JC |
639 | PMIC_MT6397, |
640 | }; | |
641 | ||
1f022d84 | 642 | enum pwrap_type { |
060a1d64 | 643 | PWRAP_MT2701, |
69d0c060 | 644 | PWRAP_MT7622, |
1f022d84 FF |
645 | PWRAP_MT8135, |
646 | PWRAP_MT8173, | |
647 | }; | |
648 | ||
ec833686 | 649 | struct pmic_wrapper; |
b28d78cd JC |
650 | struct pwrap_slv_type { |
651 | const u32 *dew_regs; | |
652 | enum pmic_type type; | |
7f80f100 | 653 | const struct regmap_config *regmap; |
d56b31e2 SW |
654 | /* Flags indicating the capability for the target slave */ |
655 | u32 caps; | |
ec833686 SW |
656 | /* |
657 | * pwrap operations are highly associated with the PMIC types, | |
658 | * so the pointers added increases flexibility allowing determination | |
659 | * which type is used by the detection through device tree. | |
660 | */ | |
661 | int (*pwrap_read)(struct pmic_wrapper *wrp, u32 adr, u32 *rdata); | |
a10616f0 | 662 | int (*pwrap_write)(struct pmic_wrapper *wrp, u32 adr, u32 wdata); |
b28d78cd JC |
663 | }; |
664 | ||
1f022d84 FF |
665 | struct pmic_wrapper { |
666 | struct device *dev; | |
667 | void __iomem *base; | |
668 | struct regmap *regmap; | |
9bebedb0 | 669 | const struct pmic_wrapper_type *master; |
b28d78cd | 670 | const struct pwrap_slv_type *slave; |
1f022d84 FF |
671 | struct clk *clk_spi; |
672 | struct clk *clk_wrap; | |
673 | struct reset_control *rstc; | |
674 | ||
675 | struct reset_control *rstc_bridge; | |
676 | void __iomem *bridge_base; | |
677 | }; | |
678 | ||
a3978453 JC |
679 | struct pmic_wrapper_type { |
680 | int *regs; | |
681 | enum pwrap_type type; | |
682 | u32 arb_en_all; | |
e5eef49b | 683 | u32 int_en_all; |
174f7b4c | 684 | u32 spi_w; |
95b25c58 | 685 | u32 wdt_src; |
fb2c1934 | 686 | unsigned int has_bridge:1; |
a3978453 | 687 | int (*init_reg_clock)(struct pmic_wrapper *wrp); |
41c11f32 | 688 | int (*init_soc_specific)(struct pmic_wrapper *wrp); |
a3978453 JC |
689 | }; |
690 | ||
1f022d84 FF |
691 | static u32 pwrap_readl(struct pmic_wrapper *wrp, enum pwrap_regs reg) |
692 | { | |
9bebedb0 | 693 | return readl(wrp->base + wrp->master->regs[reg]); |
1f022d84 FF |
694 | } |
695 | ||
696 | static void pwrap_writel(struct pmic_wrapper *wrp, u32 val, enum pwrap_regs reg) | |
697 | { | |
9bebedb0 | 698 | writel(val, wrp->base + wrp->master->regs[reg]); |
1f022d84 FF |
699 | } |
700 | ||
701 | static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp) | |
702 | { | |
703 | u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | |
704 | ||
705 | return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE; | |
706 | } | |
707 | ||
708 | static bool pwrap_is_fsm_vldclr(struct pmic_wrapper *wrp) | |
709 | { | |
710 | u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | |
711 | ||
712 | return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR; | |
713 | } | |
714 | ||
73efe579 HC |
715 | /* |
716 | * Timeout issue sometimes caused by the last read command | |
717 | * failed because pmic wrap could not got the FSM_VLDCLR | |
718 | * in time after finishing WACS2_CMD. It made state machine | |
719 | * still on FSM_VLDCLR and timeout next time. | |
720 | * Check the status of FSM and clear the vldclr to recovery the | |
721 | * error. | |
722 | */ | |
723 | static inline void pwrap_leave_fsm_vldclr(struct pmic_wrapper *wrp) | |
724 | { | |
725 | if (pwrap_is_fsm_vldclr(wrp)) | |
726 | pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR); | |
727 | } | |
728 | ||
1f022d84 FF |
729 | static bool pwrap_is_sync_idle(struct pmic_wrapper *wrp) |
730 | { | |
731 | return pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_SYNC_IDLE0; | |
732 | } | |
733 | ||
734 | static bool pwrap_is_fsm_idle_and_sync_idle(struct pmic_wrapper *wrp) | |
735 | { | |
736 | u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | |
737 | ||
738 | return (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE) && | |
739 | (val & PWRAP_STATE_SYNC_IDLE0); | |
740 | } | |
741 | ||
742 | static int pwrap_wait_for_state(struct pmic_wrapper *wrp, | |
743 | bool (*fp)(struct pmic_wrapper *)) | |
744 | { | |
745 | unsigned long timeout; | |
746 | ||
e180f887 | 747 | timeout = jiffies + usecs_to_jiffies(10000); |
1f022d84 FF |
748 | |
749 | do { | |
750 | if (time_after(jiffies, timeout)) | |
751 | return fp(wrp) ? 0 : -ETIMEDOUT; | |
752 | if (fp(wrp)) | |
753 | return 0; | |
754 | } while (1); | |
755 | } | |
756 | ||
ec833686 | 757 | static int pwrap_read16(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) |
1f022d84 FF |
758 | { |
759 | int ret; | |
1f022d84 FF |
760 | |
761 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); | |
73efe579 HC |
762 | if (ret) { |
763 | pwrap_leave_fsm_vldclr(wrp); | |
1f022d84 | 764 | return ret; |
73efe579 | 765 | } |
1f022d84 FF |
766 | |
767 | pwrap_writel(wrp, (adr >> 1) << 16, PWRAP_WACS2_CMD); | |
768 | ||
769 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr); | |
770 | if (ret) | |
771 | return ret; | |
772 | ||
773 | *rdata = PWRAP_GET_WACS_RDATA(pwrap_readl(wrp, PWRAP_WACS2_RDATA)); | |
774 | ||
d956b80a SH |
775 | pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR); |
776 | ||
1f022d84 FF |
777 | return 0; |
778 | } | |
779 | ||
ec833686 SW |
780 | static int pwrap_read32(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) |
781 | { | |
782 | int ret, msb; | |
783 | ||
784 | *rdata = 0; | |
785 | for (msb = 0; msb < 2; msb++) { | |
786 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); | |
787 | if (ret) { | |
788 | pwrap_leave_fsm_vldclr(wrp); | |
789 | return ret; | |
790 | } | |
791 | ||
792 | pwrap_writel(wrp, ((msb << 30) | (adr << 16)), | |
793 | PWRAP_WACS2_CMD); | |
794 | ||
795 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr); | |
796 | if (ret) | |
797 | return ret; | |
798 | ||
799 | *rdata += (PWRAP_GET_WACS_RDATA(pwrap_readl(wrp, | |
800 | PWRAP_WACS2_RDATA)) << (16 * msb)); | |
801 | ||
802 | pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR); | |
803 | } | |
804 | ||
805 | return 0; | |
806 | } | |
807 | ||
808 | static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) | |
809 | { | |
810 | return wrp->slave->pwrap_read(wrp, adr, rdata); | |
811 | } | |
812 | ||
a10616f0 SW |
813 | static int pwrap_write16(struct pmic_wrapper *wrp, u32 adr, u32 wdata) |
814 | { | |
815 | int ret; | |
816 | ||
817 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); | |
818 | if (ret) { | |
819 | pwrap_leave_fsm_vldclr(wrp); | |
820 | return ret; | |
821 | } | |
822 | ||
823 | pwrap_writel(wrp, (1 << 31) | ((adr >> 1) << 16) | wdata, | |
824 | PWRAP_WACS2_CMD); | |
825 | ||
826 | return 0; | |
827 | } | |
828 | ||
829 | static int pwrap_write32(struct pmic_wrapper *wrp, u32 adr, u32 wdata) | |
830 | { | |
831 | int ret, msb, rdata; | |
832 | ||
833 | for (msb = 0; msb < 2; msb++) { | |
834 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); | |
835 | if (ret) { | |
836 | pwrap_leave_fsm_vldclr(wrp); | |
837 | return ret; | |
838 | } | |
839 | ||
840 | pwrap_writel(wrp, (1 << 31) | (msb << 30) | (adr << 16) | | |
841 | ((wdata >> (msb * 16)) & 0xffff), | |
842 | PWRAP_WACS2_CMD); | |
843 | ||
844 | /* | |
845 | * The pwrap_read operation is the requirement of hardware used | |
846 | * for the synchronization between two successive 16-bit | |
847 | * pwrap_writel operations composing one 32-bit bus writing. | |
848 | * Otherwise, we'll find the result fails on the lower 16-bit | |
849 | * pwrap writing. | |
850 | */ | |
851 | if (!msb) | |
852 | pwrap_read(wrp, adr, &rdata); | |
853 | } | |
854 | ||
855 | return 0; | |
856 | } | |
857 | ||
858 | static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata) | |
859 | { | |
860 | return wrp->slave->pwrap_write(wrp, adr, wdata); | |
861 | } | |
862 | ||
1f022d84 FF |
863 | static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata) |
864 | { | |
865 | return pwrap_read(context, adr, rdata); | |
866 | } | |
867 | ||
868 | static int pwrap_regmap_write(void *context, u32 adr, u32 wdata) | |
869 | { | |
870 | return pwrap_write(context, adr, wdata); | |
871 | } | |
872 | ||
873 | static int pwrap_reset_spislave(struct pmic_wrapper *wrp) | |
874 | { | |
875 | int ret, i; | |
876 | ||
877 | pwrap_writel(wrp, 0, PWRAP_HIPRIO_ARB_EN); | |
878 | pwrap_writel(wrp, 0, PWRAP_WRAP_EN); | |
879 | pwrap_writel(wrp, 1, PWRAP_MUX_SEL); | |
880 | pwrap_writel(wrp, 1, PWRAP_MAN_EN); | |
881 | pwrap_writel(wrp, 0, PWRAP_DIO_EN); | |
882 | ||
174f7b4c | 883 | pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_CSL, |
1f022d84 | 884 | PWRAP_MAN_CMD); |
174f7b4c | 885 | pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS, |
1f022d84 | 886 | PWRAP_MAN_CMD); |
174f7b4c | 887 | pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_CSH, |
1f022d84 FF |
888 | PWRAP_MAN_CMD); |
889 | ||
890 | for (i = 0; i < 4; i++) | |
174f7b4c | 891 | pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS, |
1f022d84 FF |
892 | PWRAP_MAN_CMD); |
893 | ||
894 | ret = pwrap_wait_for_state(wrp, pwrap_is_sync_idle); | |
895 | if (ret) { | |
896 | dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret); | |
897 | return ret; | |
898 | } | |
899 | ||
900 | pwrap_writel(wrp, 0, PWRAP_MAN_EN); | |
901 | pwrap_writel(wrp, 0, PWRAP_MUX_SEL); | |
902 | ||
903 | return 0; | |
904 | } | |
905 | ||
906 | /* | |
907 | * pwrap_init_sidly - configure serial input delay | |
908 | * | |
909 | * This configures the serial input delay. We can configure 0, 2, 4 or 6ns | |
910 | * delay. Do a read test with all possible values and chose the best delay. | |
911 | */ | |
912 | static int pwrap_init_sidly(struct pmic_wrapper *wrp) | |
913 | { | |
914 | u32 rdata; | |
915 | u32 i; | |
916 | u32 pass = 0; | |
917 | signed char dly[16] = { | |
918 | -1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1 | |
919 | }; | |
920 | ||
921 | for (i = 0; i < 4; i++) { | |
922 | pwrap_writel(wrp, i, PWRAP_SIDLY); | |
b28d78cd JC |
923 | pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], |
924 | &rdata); | |
1f022d84 FF |
925 | if (rdata == PWRAP_DEW_READ_TEST_VAL) { |
926 | dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i); | |
927 | pass |= 1 << i; | |
928 | } | |
929 | } | |
930 | ||
931 | if (dly[pass] < 0) { | |
932 | dev_err(wrp->dev, "sidly pass range 0x%x not continuous\n", | |
933 | pass); | |
934 | return -EIO; | |
935 | } | |
936 | ||
937 | pwrap_writel(wrp, dly[pass], PWRAP_SIDLY); | |
938 | ||
939 | return 0; | |
940 | } | |
941 | ||
d56b31e2 SW |
942 | static int pwrap_init_dual_io(struct pmic_wrapper *wrp) |
943 | { | |
944 | int ret; | |
945 | u32 rdata; | |
946 | ||
947 | /* Enable dual IO mode */ | |
948 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1); | |
949 | ||
950 | /* Check IDLE & INIT_DONE in advance */ | |
951 | ret = pwrap_wait_for_state(wrp, | |
952 | pwrap_is_fsm_idle_and_sync_idle); | |
953 | if (ret) { | |
954 | dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret); | |
955 | return ret; | |
956 | } | |
957 | ||
958 | pwrap_writel(wrp, 1, PWRAP_DIO_EN); | |
959 | ||
960 | /* Read Test */ | |
961 | pwrap_read(wrp, | |
962 | wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata); | |
963 | if (rdata != PWRAP_DEW_READ_TEST_VAL) { | |
964 | dev_err(wrp->dev, | |
965 | "Read failed on DIO mode: 0x%04x!=0x%04x\n", | |
966 | PWRAP_DEW_READ_TEST_VAL, rdata); | |
967 | return -EFAULT; | |
968 | } | |
969 | ||
970 | return 0; | |
971 | } | |
972 | ||
68189ed5 SW |
973 | /* |
974 | * pwrap_init_chip_select_ext is used to configure CS extension time for each | |
975 | * phase during data transactions on the pwrap bus. | |
976 | */ | |
977 | static void pwrap_init_chip_select_ext(struct pmic_wrapper *wrp, u8 hext_write, | |
978 | u8 hext_read, u8 lext_start, | |
979 | u8 lext_end) | |
1f022d84 | 980 | { |
68189ed5 SW |
981 | /* |
982 | * After finishing a write and read transaction, extends CS high time | |
983 | * to be at least xT of BUS CLK as hext_write and hext_read specifies | |
984 | * respectively. | |
985 | */ | |
986 | pwrap_writel(wrp, hext_write, PWRAP_CSHEXT_WRITE); | |
987 | pwrap_writel(wrp, hext_read, PWRAP_CSHEXT_READ); | |
a3978453 | 988 | |
68189ed5 SW |
989 | /* |
990 | * Extends CS low time after CSL and before CSH command to be at | |
991 | * least xT of BUS CLK as lext_start and lext_end specifies | |
992 | * respectively. | |
993 | */ | |
994 | pwrap_writel(wrp, lext_start, PWRAP_CSLEXT_START); | |
995 | pwrap_writel(wrp, lext_end, PWRAP_CSLEXT_END); | |
a3978453 JC |
996 | } |
997 | ||
68189ed5 | 998 | static int pwrap_common_init_reg_clock(struct pmic_wrapper *wrp) |
a3978453 | 999 | { |
68189ed5 SW |
1000 | switch (wrp->master->type) { |
1001 | case PWRAP_MT8173: | |
1002 | pwrap_init_chip_select_ext(wrp, 0, 4, 2, 2); | |
1003 | break; | |
1004 | case PWRAP_MT8135: | |
1005 | pwrap_writel(wrp, 0x4, PWRAP_CSHEXT); | |
1006 | pwrap_init_chip_select_ext(wrp, 0, 4, 0, 0); | |
1007 | break; | |
1008 | default: | |
1009 | break; | |
1010 | } | |
1f022d84 FF |
1011 | |
1012 | return 0; | |
1013 | } | |
1014 | ||
060a1d64 JC |
1015 | static int pwrap_mt2701_init_reg_clock(struct pmic_wrapper *wrp) |
1016 | { | |
1017 | switch (wrp->slave->type) { | |
1018 | case PMIC_MT6397: | |
1019 | pwrap_writel(wrp, 0xc, PWRAP_RDDMY); | |
68189ed5 | 1020 | pwrap_init_chip_select_ext(wrp, 4, 0, 2, 2); |
060a1d64 JC |
1021 | break; |
1022 | ||
1023 | case PMIC_MT6323: | |
1024 | pwrap_writel(wrp, 0x8, PWRAP_RDDMY); | |
1025 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_RDDMY_NO], | |
1026 | 0x8); | |
68189ed5 | 1027 | pwrap_init_chip_select_ext(wrp, 5, 0, 2, 2); |
060a1d64 | 1028 | break; |
ec833686 SW |
1029 | default: |
1030 | break; | |
060a1d64 JC |
1031 | } |
1032 | ||
1033 | return 0; | |
1034 | } | |
1035 | ||
1f022d84 FF |
1036 | static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp) |
1037 | { | |
1038 | return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1; | |
1039 | } | |
1040 | ||
1041 | static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp) | |
1042 | { | |
1043 | u32 rdata; | |
1044 | int ret; | |
1045 | ||
b28d78cd JC |
1046 | ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY], |
1047 | &rdata); | |
1f022d84 FF |
1048 | if (ret) |
1049 | return 0; | |
1050 | ||
1051 | return rdata == 1; | |
1052 | } | |
1053 | ||
1054 | static int pwrap_init_cipher(struct pmic_wrapper *wrp) | |
1055 | { | |
1056 | int ret; | |
15e56099 | 1057 | u32 rdata = 0; |
1f022d84 FF |
1058 | |
1059 | pwrap_writel(wrp, 0x1, PWRAP_CIPHER_SWRST); | |
1060 | pwrap_writel(wrp, 0x0, PWRAP_CIPHER_SWRST); | |
1061 | pwrap_writel(wrp, 0x1, PWRAP_CIPHER_KEY_SEL); | |
1062 | pwrap_writel(wrp, 0x2, PWRAP_CIPHER_IV_SEL); | |
1063 | ||
25269cef JC |
1064 | switch (wrp->master->type) { |
1065 | case PWRAP_MT8135: | |
1f022d84 FF |
1066 | pwrap_writel(wrp, 1, PWRAP_CIPHER_LOAD); |
1067 | pwrap_writel(wrp, 1, PWRAP_CIPHER_START); | |
25269cef | 1068 | break; |
060a1d64 | 1069 | case PWRAP_MT2701: |
25269cef | 1070 | case PWRAP_MT8173: |
1f022d84 | 1071 | pwrap_writel(wrp, 1, PWRAP_CIPHER_EN); |
25269cef | 1072 | break; |
69d0c060 CX |
1073 | case PWRAP_MT7622: |
1074 | pwrap_writel(wrp, 0, PWRAP_CIPHER_EN); | |
1075 | break; | |
1f022d84 FF |
1076 | } |
1077 | ||
1078 | /* Config cipher mode @PMIC */ | |
b28d78cd JC |
1079 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1); |
1080 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0); | |
1081 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1); | |
1082 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2); | |
1083 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], 0x1); | |
1084 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], 0x1); | |
1f022d84 | 1085 | |
5ae48040 JC |
1086 | switch (wrp->slave->type) { |
1087 | case PMIC_MT6397: | |
1088 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], | |
1089 | 0x1); | |
1090 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], | |
1091 | 0x1); | |
1092 | break; | |
1093 | case PMIC_MT6323: | |
1094 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN], | |
1095 | 0x1); | |
1096 | break; | |
ec833686 SW |
1097 | default: |
1098 | break; | |
5ae48040 JC |
1099 | } |
1100 | ||
1f022d84 FF |
1101 | /* wait for cipher data ready@AP */ |
1102 | ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready); | |
1103 | if (ret) { | |
1104 | dev_err(wrp->dev, "cipher data ready@AP fail, ret=%d\n", ret); | |
1105 | return ret; | |
1106 | } | |
1107 | ||
1108 | /* wait for cipher data ready@PMIC */ | |
1109 | ret = pwrap_wait_for_state(wrp, pwrap_is_pmic_cipher_ready); | |
1110 | if (ret) { | |
cbd71f0a SW |
1111 | dev_err(wrp->dev, |
1112 | "timeout waiting for cipher data ready@PMIC\n"); | |
1f022d84 FF |
1113 | return ret; |
1114 | } | |
1115 | ||
1116 | /* wait for cipher mode idle */ | |
b28d78cd | 1117 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_MODE], 0x1); |
1f022d84 FF |
1118 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle); |
1119 | if (ret) { | |
1120 | dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret); | |
1121 | return ret; | |
1122 | } | |
1123 | ||
1124 | pwrap_writel(wrp, 1, PWRAP_CIPHER_MODE); | |
1125 | ||
1126 | /* Write Test */ | |
b28d78cd JC |
1127 | if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_WRITE_TEST], |
1128 | PWRAP_DEW_WRITE_TEST_VAL) || | |
1129 | pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_WRITE_TEST], | |
1130 | &rdata) || | |
1131 | (rdata != PWRAP_DEW_WRITE_TEST_VAL)) { | |
1f022d84 FF |
1132 | dev_err(wrp->dev, "rdata=0x%04X\n", rdata); |
1133 | return -EFAULT; | |
1134 | } | |
1135 | ||
1136 | return 0; | |
1137 | } | |
1138 | ||
d56b31e2 SW |
1139 | static int pwrap_init_security(struct pmic_wrapper *wrp) |
1140 | { | |
1141 | int ret; | |
1142 | ||
1143 | /* Enable encryption */ | |
1144 | ret = pwrap_init_cipher(wrp); | |
1145 | if (ret) | |
1146 | return ret; | |
1147 | ||
1148 | /* Signature checking - using CRC */ | |
1149 | if (pwrap_write(wrp, | |
1150 | wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1)) | |
1151 | return -EFAULT; | |
1152 | ||
1153 | pwrap_writel(wrp, 0x1, PWRAP_CRC_EN); | |
1154 | pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE); | |
1155 | pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL], | |
1156 | PWRAP_SIG_ADR); | |
1157 | pwrap_writel(wrp, | |
1158 | wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); | |
1159 | ||
1160 | return 0; | |
1161 | } | |
1162 | ||
41c11f32 JC |
1163 | static int pwrap_mt8135_init_soc_specific(struct pmic_wrapper *wrp) |
1164 | { | |
1165 | /* enable pwrap events and pwrap bridge in AP side */ | |
1166 | pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN); | |
1167 | pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN); | |
1168 | writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN); | |
1169 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN); | |
1170 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN); | |
1171 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT); | |
1172 | writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN); | |
1173 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN); | |
1174 | writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN); | |
1175 | ||
1176 | /* enable PMIC event out and sources */ | |
b28d78cd JC |
1177 | if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_OUT_EN], |
1178 | 0x1) || | |
1179 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_SRC_EN], | |
1180 | 0xffff)) { | |
41c11f32 JC |
1181 | dev_err(wrp->dev, "enable dewrap fail\n"); |
1182 | return -EFAULT; | |
1183 | } | |
1184 | ||
1185 | return 0; | |
1186 | } | |
1187 | ||
1188 | static int pwrap_mt8173_init_soc_specific(struct pmic_wrapper *wrp) | |
1189 | { | |
1190 | /* PMIC_DEWRAP enables */ | |
b28d78cd JC |
1191 | if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_OUT_EN], |
1192 | 0x1) || | |
1193 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_SRC_EN], | |
1194 | 0xffff)) { | |
41c11f32 JC |
1195 | dev_err(wrp->dev, "enable dewrap fail\n"); |
1196 | return -EFAULT; | |
1197 | } | |
1198 | ||
1199 | return 0; | |
1200 | } | |
1201 | ||
060a1d64 JC |
1202 | static int pwrap_mt2701_init_soc_specific(struct pmic_wrapper *wrp) |
1203 | { | |
1204 | /* GPS_INTF initialization */ | |
1205 | switch (wrp->slave->type) { | |
1206 | case PMIC_MT6323: | |
1207 | pwrap_writel(wrp, 0x076c, PWRAP_ADC_CMD_ADDR); | |
1208 | pwrap_writel(wrp, 0x8000, PWRAP_PWRAP_ADC_CMD); | |
1209 | pwrap_writel(wrp, 0x072c, PWRAP_ADC_RDY_ADDR); | |
1210 | pwrap_writel(wrp, 0x072e, PWRAP_ADC_RDATA_ADDR1); | |
1211 | pwrap_writel(wrp, 0x0730, PWRAP_ADC_RDATA_ADDR2); | |
1212 | break; | |
1213 | default: | |
1214 | break; | |
1215 | } | |
1216 | ||
1217 | return 0; | |
1218 | } | |
1219 | ||
69d0c060 CX |
1220 | static int pwrap_mt7622_init_soc_specific(struct pmic_wrapper *wrp) |
1221 | { | |
1222 | pwrap_writel(wrp, 0, PWRAP_STAUPD_PRD); | |
1223 | /* enable 2wire SPI master */ | |
1224 | pwrap_writel(wrp, 0x8000000, PWRAP_SPI2_CTRL); | |
1225 | ||
1226 | return 0; | |
1227 | } | |
1228 | ||
1f022d84 FF |
1229 | static int pwrap_init(struct pmic_wrapper *wrp) |
1230 | { | |
1231 | int ret; | |
1f022d84 FF |
1232 | |
1233 | reset_control_reset(wrp->rstc); | |
1234 | if (wrp->rstc_bridge) | |
1235 | reset_control_reset(wrp->rstc_bridge); | |
1236 | ||
25269cef | 1237 | if (wrp->master->type == PWRAP_MT8173) { |
1f022d84 FF |
1238 | /* Enable DCM */ |
1239 | pwrap_writel(wrp, 3, PWRAP_DCM_EN); | |
1240 | pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); | |
1241 | } | |
1242 | ||
d56b31e2 SW |
1243 | if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SPI)) { |
1244 | /* Reset SPI slave */ | |
1245 | ret = pwrap_reset_spislave(wrp); | |
1246 | if (ret) | |
1247 | return ret; | |
1248 | } | |
1f022d84 FF |
1249 | |
1250 | pwrap_writel(wrp, 1, PWRAP_WRAP_EN); | |
1251 | ||
9bebedb0 | 1252 | pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); |
1f022d84 FF |
1253 | |
1254 | pwrap_writel(wrp, 1, PWRAP_WACS2_EN); | |
1255 | ||
a3978453 | 1256 | ret = wrp->master->init_reg_clock(wrp); |
1f022d84 FF |
1257 | if (ret) |
1258 | return ret; | |
1259 | ||
d56b31e2 SW |
1260 | if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SPI)) { |
1261 | /* Setup serial input delay */ | |
1262 | ret = pwrap_init_sidly(wrp); | |
1263 | if (ret) | |
1264 | return ret; | |
1f022d84 FF |
1265 | } |
1266 | ||
d56b31e2 SW |
1267 | if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_DUALIO)) { |
1268 | /* Enable dual I/O mode */ | |
1269 | ret = pwrap_init_dual_io(wrp); | |
1270 | if (ret) | |
1271 | return ret; | |
1f022d84 FF |
1272 | } |
1273 | ||
d56b31e2 SW |
1274 | if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SECURITY)) { |
1275 | /* Enable security on bus */ | |
1276 | ret = pwrap_init_security(wrp); | |
1277 | if (ret) | |
1278 | return ret; | |
1279 | } | |
1f022d84 | 1280 | |
25269cef | 1281 | if (wrp->master->type == PWRAP_MT8135) |
1f022d84 FF |
1282 | pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN); |
1283 | ||
1284 | pwrap_writel(wrp, 0x1, PWRAP_WACS0_EN); | |
1285 | pwrap_writel(wrp, 0x1, PWRAP_WACS1_EN); | |
1286 | pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN); | |
1287 | pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD); | |
1288 | pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN); | |
1f022d84 | 1289 | |
41c11f32 JC |
1290 | if (wrp->master->init_soc_specific) { |
1291 | ret = wrp->master->init_soc_specific(wrp); | |
1292 | if (ret) | |
1293 | return ret; | |
1f022d84 FF |
1294 | } |
1295 | ||
1296 | /* Setup the init done registers */ | |
1297 | pwrap_writel(wrp, 1, PWRAP_INIT_DONE2); | |
1298 | pwrap_writel(wrp, 1, PWRAP_INIT_DONE0); | |
1299 | pwrap_writel(wrp, 1, PWRAP_INIT_DONE1); | |
1300 | ||
25269cef | 1301 | if (wrp->master->has_bridge) { |
1f022d84 FF |
1302 | writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3); |
1303 | writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4); | |
1304 | } | |
1305 | ||
1306 | return 0; | |
1307 | } | |
1308 | ||
1309 | static irqreturn_t pwrap_interrupt(int irqno, void *dev_id) | |
1310 | { | |
1311 | u32 rdata; | |
1312 | struct pmic_wrapper *wrp = dev_id; | |
1313 | ||
1314 | rdata = pwrap_readl(wrp, PWRAP_INT_FLG); | |
1315 | ||
1316 | dev_err(wrp->dev, "unexpected interrupt int=0x%x\n", rdata); | |
1317 | ||
1318 | pwrap_writel(wrp, 0xffffffff, PWRAP_INT_CLR); | |
1319 | ||
1320 | return IRQ_HANDLED; | |
1321 | } | |
1322 | ||
7f80f100 | 1323 | static const struct regmap_config pwrap_regmap_config16 = { |
1f022d84 FF |
1324 | .reg_bits = 16, |
1325 | .val_bits = 16, | |
1326 | .reg_stride = 2, | |
1327 | .reg_read = pwrap_regmap_read, | |
1328 | .reg_write = pwrap_regmap_write, | |
1329 | .max_register = 0xffff, | |
1330 | }; | |
1331 | ||
7f80f100 SW |
1332 | static const struct regmap_config pwrap_regmap_config32 = { |
1333 | .reg_bits = 32, | |
1334 | .val_bits = 32, | |
1335 | .reg_stride = 4, | |
1336 | .reg_read = pwrap_regmap_read, | |
1337 | .reg_write = pwrap_regmap_write, | |
1338 | .max_register = 0xffff, | |
1339 | }; | |
1340 | ||
5ae48040 JC |
1341 | static const struct pwrap_slv_type pmic_mt6323 = { |
1342 | .dew_regs = mt6323_regs, | |
1343 | .type = PMIC_MT6323, | |
7f80f100 | 1344 | .regmap = &pwrap_regmap_config16, |
d56b31e2 SW |
1345 | .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO | |
1346 | PWRAP_SLV_CAP_SECURITY, | |
ec833686 | 1347 | .pwrap_read = pwrap_read16, |
a10616f0 | 1348 | .pwrap_write = pwrap_write16, |
ec833686 SW |
1349 | }; |
1350 | ||
1351 | static const struct pwrap_slv_type pmic_mt6380 = { | |
1352 | .dew_regs = NULL, | |
1353 | .type = PMIC_MT6380, | |
7f80f100 | 1354 | .regmap = &pwrap_regmap_config32, |
d56b31e2 | 1355 | .caps = 0, |
ec833686 | 1356 | .pwrap_read = pwrap_read32, |
a10616f0 | 1357 | .pwrap_write = pwrap_write32, |
5ae48040 JC |
1358 | }; |
1359 | ||
b28d78cd JC |
1360 | static const struct pwrap_slv_type pmic_mt6397 = { |
1361 | .dew_regs = mt6397_regs, | |
1362 | .type = PMIC_MT6397, | |
7f80f100 | 1363 | .regmap = &pwrap_regmap_config16, |
d56b31e2 SW |
1364 | .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO | |
1365 | PWRAP_SLV_CAP_SECURITY, | |
ec833686 | 1366 | .pwrap_read = pwrap_read16, |
a10616f0 | 1367 | .pwrap_write = pwrap_write16, |
b28d78cd JC |
1368 | }; |
1369 | ||
1370 | static const struct of_device_id of_slave_match_tbl[] = { | |
1371 | { | |
5ae48040 JC |
1372 | .compatible = "mediatek,mt6323", |
1373 | .data = &pmic_mt6323, | |
7f80f100 SW |
1374 | }, { |
1375 | /* The MT6380 PMIC only implements a regulator, so we bind it | |
1376 | * directly instead of using a MFD. | |
1377 | */ | |
1378 | .compatible = "mediatek,mt6380-regulator", | |
1379 | .data = &pmic_mt6380, | |
5ae48040 | 1380 | }, { |
b28d78cd JC |
1381 | .compatible = "mediatek,mt6397", |
1382 | .data = &pmic_mt6397, | |
f32fbbad | 1383 | }, { |
b28d78cd JC |
1384 | /* sentinel */ |
1385 | } | |
1386 | }; | |
1387 | MODULE_DEVICE_TABLE(of, of_slave_match_tbl); | |
1388 | ||
060a1d64 JC |
1389 | static const struct pmic_wrapper_type pwrap_mt2701 = { |
1390 | .regs = mt2701_regs, | |
1391 | .type = PWRAP_MT2701, | |
1392 | .arb_en_all = 0x3f, | |
7f058c0a | 1393 | .int_en_all = ~(u32)(BIT(31) | BIT(2)), |
060a1d64 JC |
1394 | .spi_w = PWRAP_MAN_CMD_SPI_WRITE_NEW, |
1395 | .wdt_src = PWRAP_WDT_SRC_MASK_ALL, | |
1396 | .has_bridge = 0, | |
1397 | .init_reg_clock = pwrap_mt2701_init_reg_clock, | |
1398 | .init_soc_specific = pwrap_mt2701_init_soc_specific, | |
1399 | }; | |
1400 | ||
69d0c060 CX |
1401 | static const struct pmic_wrapper_type pwrap_mt7622 = { |
1402 | .regs = mt7622_regs, | |
1403 | .type = PWRAP_MT7622, | |
1404 | .arb_en_all = 0xff, | |
1405 | .int_en_all = ~(u32)BIT(31), | |
1406 | .spi_w = PWRAP_MAN_CMD_SPI_WRITE, | |
1407 | .wdt_src = PWRAP_WDT_SRC_MASK_ALL, | |
1408 | .has_bridge = 0, | |
1409 | .init_reg_clock = pwrap_common_init_reg_clock, | |
1410 | .init_soc_specific = pwrap_mt7622_init_soc_specific, | |
1411 | }; | |
1412 | ||
2ae24fb1 | 1413 | static const struct pmic_wrapper_type pwrap_mt8135 = { |
a3978453 JC |
1414 | .regs = mt8135_regs, |
1415 | .type = PWRAP_MT8135, | |
1416 | .arb_en_all = 0x1ff, | |
7f058c0a | 1417 | .int_en_all = ~(u32)(BIT(31) | BIT(1)), |
174f7b4c | 1418 | .spi_w = PWRAP_MAN_CMD_SPI_WRITE, |
95b25c58 | 1419 | .wdt_src = PWRAP_WDT_SRC_MASK_ALL, |
25269cef | 1420 | .has_bridge = 1, |
68189ed5 | 1421 | .init_reg_clock = pwrap_common_init_reg_clock, |
41c11f32 | 1422 | .init_soc_specific = pwrap_mt8135_init_soc_specific, |
a3978453 JC |
1423 | }; |
1424 | ||
2ae24fb1 | 1425 | static const struct pmic_wrapper_type pwrap_mt8173 = { |
a3978453 JC |
1426 | .regs = mt8173_regs, |
1427 | .type = PWRAP_MT8173, | |
1428 | .arb_en_all = 0x3f, | |
7f058c0a | 1429 | .int_en_all = ~(u32)(BIT(31) | BIT(1)), |
174f7b4c | 1430 | .spi_w = PWRAP_MAN_CMD_SPI_WRITE, |
95b25c58 | 1431 | .wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD, |
25269cef | 1432 | .has_bridge = 0, |
68189ed5 | 1433 | .init_reg_clock = pwrap_common_init_reg_clock, |
41c11f32 | 1434 | .init_soc_specific = pwrap_mt8173_init_soc_specific, |
a3978453 JC |
1435 | }; |
1436 | ||
2ae24fb1 | 1437 | static const struct of_device_id of_pwrap_match_tbl[] = { |
1f022d84 | 1438 | { |
060a1d64 JC |
1439 | .compatible = "mediatek,mt2701-pwrap", |
1440 | .data = &pwrap_mt2701, | |
69d0c060 CX |
1441 | }, { |
1442 | .compatible = "mediatek,mt7622-pwrap", | |
1443 | .data = &pwrap_mt7622, | |
060a1d64 | 1444 | }, { |
1f022d84 FF |
1445 | .compatible = "mediatek,mt8135-pwrap", |
1446 | .data = &pwrap_mt8135, | |
1447 | }, { | |
1448 | .compatible = "mediatek,mt8173-pwrap", | |
1449 | .data = &pwrap_mt8173, | |
1450 | }, { | |
1451 | /* sentinel */ | |
1452 | } | |
1453 | }; | |
1454 | MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl); | |
1455 | ||
1456 | static int pwrap_probe(struct platform_device *pdev) | |
1457 | { | |
95b25c58 | 1458 | int ret, irq; |
1f022d84 FF |
1459 | struct pmic_wrapper *wrp; |
1460 | struct device_node *np = pdev->dev.of_node; | |
1461 | const struct of_device_id *of_id = | |
1462 | of_match_device(of_pwrap_match_tbl, &pdev->dev); | |
b28d78cd | 1463 | const struct of_device_id *of_slave_id = NULL; |
1f022d84 FF |
1464 | struct resource *res; |
1465 | ||
58a823dd | 1466 | if (!of_id) { |
1467 | dev_err(&pdev->dev, "Error: No device match found\n"); | |
1468 | return -ENODEV; | |
1469 | } | |
1470 | ||
b28d78cd JC |
1471 | if (pdev->dev.of_node->child) |
1472 | of_slave_id = of_match_node(of_slave_match_tbl, | |
1473 | pdev->dev.of_node->child); | |
1474 | if (!of_slave_id) { | |
1475 | dev_dbg(&pdev->dev, "slave pmic should be defined in dts\n"); | |
1476 | return -EINVAL; | |
1477 | } | |
1478 | ||
1f022d84 FF |
1479 | wrp = devm_kzalloc(&pdev->dev, sizeof(*wrp), GFP_KERNEL); |
1480 | if (!wrp) | |
1481 | return -ENOMEM; | |
1482 | ||
1483 | platform_set_drvdata(pdev, wrp); | |
1484 | ||
9bebedb0 | 1485 | wrp->master = of_id->data; |
b28d78cd | 1486 | wrp->slave = of_slave_id->data; |
1f022d84 FF |
1487 | wrp->dev = &pdev->dev; |
1488 | ||
1489 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap"); | |
1490 | wrp->base = devm_ioremap_resource(wrp->dev, res); | |
1491 | if (IS_ERR(wrp->base)) | |
1492 | return PTR_ERR(wrp->base); | |
1493 | ||
1494 | wrp->rstc = devm_reset_control_get(wrp->dev, "pwrap"); | |
1495 | if (IS_ERR(wrp->rstc)) { | |
1496 | ret = PTR_ERR(wrp->rstc); | |
1497 | dev_dbg(wrp->dev, "cannot get pwrap reset: %d\n", ret); | |
1498 | return ret; | |
1499 | } | |
1500 | ||
25269cef | 1501 | if (wrp->master->has_bridge) { |
1f022d84 FF |
1502 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
1503 | "pwrap-bridge"); | |
1504 | wrp->bridge_base = devm_ioremap_resource(wrp->dev, res); | |
1505 | if (IS_ERR(wrp->bridge_base)) | |
1506 | return PTR_ERR(wrp->bridge_base); | |
1507 | ||
cbd71f0a SW |
1508 | wrp->rstc_bridge = devm_reset_control_get(wrp->dev, |
1509 | "pwrap-bridge"); | |
1f022d84 FF |
1510 | if (IS_ERR(wrp->rstc_bridge)) { |
1511 | ret = PTR_ERR(wrp->rstc_bridge); | |
cbd71f0a SW |
1512 | dev_dbg(wrp->dev, |
1513 | "cannot get pwrap-bridge reset: %d\n", ret); | |
1f022d84 FF |
1514 | return ret; |
1515 | } | |
1516 | } | |
1517 | ||
1518 | wrp->clk_spi = devm_clk_get(wrp->dev, "spi"); | |
1519 | if (IS_ERR(wrp->clk_spi)) { | |
cbd71f0a SW |
1520 | dev_dbg(wrp->dev, "failed to get clock: %ld\n", |
1521 | PTR_ERR(wrp->clk_spi)); | |
1f022d84 FF |
1522 | return PTR_ERR(wrp->clk_spi); |
1523 | } | |
1524 | ||
1525 | wrp->clk_wrap = devm_clk_get(wrp->dev, "wrap"); | |
1526 | if (IS_ERR(wrp->clk_wrap)) { | |
cbd71f0a SW |
1527 | dev_dbg(wrp->dev, "failed to get clock: %ld\n", |
1528 | PTR_ERR(wrp->clk_wrap)); | |
1f022d84 FF |
1529 | return PTR_ERR(wrp->clk_wrap); |
1530 | } | |
1531 | ||
1532 | ret = clk_prepare_enable(wrp->clk_spi); | |
1533 | if (ret) | |
1534 | return ret; | |
1535 | ||
1536 | ret = clk_prepare_enable(wrp->clk_wrap); | |
1537 | if (ret) | |
1538 | goto err_out1; | |
1539 | ||
1540 | /* Enable internal dynamic clock */ | |
1541 | pwrap_writel(wrp, 1, PWRAP_DCM_EN); | |
1542 | pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); | |
1543 | ||
1544 | /* | |
1545 | * The PMIC could already be initialized by the bootloader. | |
1546 | * Skip initialization here in this case. | |
1547 | */ | |
1548 | if (!pwrap_readl(wrp, PWRAP_INIT_DONE2)) { | |
1549 | ret = pwrap_init(wrp); | |
1550 | if (ret) { | |
1551 | dev_dbg(wrp->dev, "init failed with %d\n", ret); | |
1552 | goto err_out2; | |
1553 | } | |
1554 | } | |
1555 | ||
1556 | if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_INIT_DONE0)) { | |
1557 | dev_dbg(wrp->dev, "initialization isn't finished\n"); | |
f282693f CJ |
1558 | ret = -ENODEV; |
1559 | goto err_out2; | |
1f022d84 FF |
1560 | } |
1561 | ||
bbe379fc HC |
1562 | /* Initialize watchdog, may not be done by the bootloader */ |
1563 | pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT); | |
a3bbfbb0 HC |
1564 | /* |
1565 | * Since STAUPD was not used on mt8173 platform, | |
1566 | * so STAUPD of WDT_SRC which should be turned off | |
1567 | */ | |
95b25c58 | 1568 | pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN); |
bbe379fc | 1569 | pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); |
e5eef49b | 1570 | pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN); |
bbe379fc | 1571 | |
1f022d84 | 1572 | irq = platform_get_irq(pdev, 0); |
cbd71f0a SW |
1573 | ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, |
1574 | IRQF_TRIGGER_HIGH, | |
1575 | "mt-pmic-pwrap", wrp); | |
1f022d84 FF |
1576 | if (ret) |
1577 | goto err_out2; | |
1578 | ||
7f80f100 | 1579 | wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, wrp->slave->regmap); |
f282693f CJ |
1580 | if (IS_ERR(wrp->regmap)) { |
1581 | ret = PTR_ERR(wrp->regmap); | |
1582 | goto err_out2; | |
1583 | } | |
1f022d84 FF |
1584 | |
1585 | ret = of_platform_populate(np, NULL, NULL, wrp->dev); | |
1586 | if (ret) { | |
37c342cb RH |
1587 | dev_dbg(wrp->dev, "failed to create child devices at %pOF\n", |
1588 | np); | |
1f022d84 FF |
1589 | goto err_out2; |
1590 | } | |
1591 | ||
1592 | return 0; | |
1593 | ||
1594 | err_out2: | |
1595 | clk_disable_unprepare(wrp->clk_wrap); | |
1596 | err_out1: | |
1597 | clk_disable_unprepare(wrp->clk_spi); | |
1598 | ||
1599 | return ret; | |
1600 | } | |
1601 | ||
1602 | static struct platform_driver pwrap_drv = { | |
1603 | .driver = { | |
1604 | .name = "mt-pmic-pwrap", | |
1f022d84 FF |
1605 | .of_match_table = of_match_ptr(of_pwrap_match_tbl), |
1606 | }, | |
1607 | .probe = pwrap_probe, | |
1608 | }; | |
1609 | ||
1610 | module_platform_driver(pwrap_drv); | |
1611 | ||
1612 | MODULE_AUTHOR("Flora Fu, MediaTek"); | |
1613 | MODULE_DESCRIPTION("MediaTek MT8135 PMIC Wrapper Driver"); | |
1614 | MODULE_LICENSE("GPL v2"); |