]>
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 | ||
b28d78cd JC |
73 | /* defines for slave device wrapper registers */ |
74 | enum dew_regs { | |
75 | PWRAP_DEW_BASE, | |
76 | PWRAP_DEW_DIO_EN, | |
77 | PWRAP_DEW_READ_TEST, | |
78 | PWRAP_DEW_WRITE_TEST, | |
79 | PWRAP_DEW_CRC_EN, | |
80 | PWRAP_DEW_CRC_VAL, | |
81 | PWRAP_DEW_MON_GRP_SEL, | |
82 | PWRAP_DEW_CIPHER_KEY_SEL, | |
83 | PWRAP_DEW_CIPHER_IV_SEL, | |
84 | PWRAP_DEW_CIPHER_RDY, | |
85 | PWRAP_DEW_CIPHER_MODE, | |
86 | PWRAP_DEW_CIPHER_SWRST, | |
87 | ||
88 | /* MT6397 only regs */ | |
89 | PWRAP_DEW_EVENT_OUT_EN, | |
90 | PWRAP_DEW_EVENT_SRC_EN, | |
91 | PWRAP_DEW_EVENT_SRC, | |
92 | PWRAP_DEW_EVENT_FLAG, | |
93 | PWRAP_DEW_MON_FLAG_SEL, | |
94 | PWRAP_DEW_EVENT_TEST, | |
95 | PWRAP_DEW_CIPHER_LOAD, | |
96 | PWRAP_DEW_CIPHER_START, | |
5ae48040 JC |
97 | |
98 | /* MT6323 only regs */ | |
99 | PWRAP_DEW_CIPHER_EN, | |
100 | PWRAP_DEW_RDDMY_NO, | |
101 | }; | |
102 | ||
103 | static const u32 mt6323_regs[] = { | |
104 | [PWRAP_DEW_BASE] = 0x0000, | |
105 | [PWRAP_DEW_DIO_EN] = 0x018a, | |
106 | [PWRAP_DEW_READ_TEST] = 0x018c, | |
107 | [PWRAP_DEW_WRITE_TEST] = 0x018e, | |
108 | [PWRAP_DEW_CRC_EN] = 0x0192, | |
109 | [PWRAP_DEW_CRC_VAL] = 0x0194, | |
110 | [PWRAP_DEW_MON_GRP_SEL] = 0x0196, | |
111 | [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0198, | |
112 | [PWRAP_DEW_CIPHER_IV_SEL] = 0x019a, | |
113 | [PWRAP_DEW_CIPHER_EN] = 0x019c, | |
114 | [PWRAP_DEW_CIPHER_RDY] = 0x019e, | |
115 | [PWRAP_DEW_CIPHER_MODE] = 0x01a0, | |
116 | [PWRAP_DEW_CIPHER_SWRST] = 0x01a2, | |
117 | [PWRAP_DEW_RDDMY_NO] = 0x01a4, | |
b28d78cd JC |
118 | }; |
119 | ||
120 | static const u32 mt6397_regs[] = { | |
121 | [PWRAP_DEW_BASE] = 0xbc00, | |
122 | [PWRAP_DEW_EVENT_OUT_EN] = 0xbc00, | |
123 | [PWRAP_DEW_DIO_EN] = 0xbc02, | |
124 | [PWRAP_DEW_EVENT_SRC_EN] = 0xbc04, | |
125 | [PWRAP_DEW_EVENT_SRC] = 0xbc06, | |
126 | [PWRAP_DEW_EVENT_FLAG] = 0xbc08, | |
127 | [PWRAP_DEW_READ_TEST] = 0xbc0a, | |
128 | [PWRAP_DEW_WRITE_TEST] = 0xbc0c, | |
129 | [PWRAP_DEW_CRC_EN] = 0xbc0e, | |
130 | [PWRAP_DEW_CRC_VAL] = 0xbc10, | |
131 | [PWRAP_DEW_MON_GRP_SEL] = 0xbc12, | |
132 | [PWRAP_DEW_MON_FLAG_SEL] = 0xbc14, | |
133 | [PWRAP_DEW_EVENT_TEST] = 0xbc16, | |
134 | [PWRAP_DEW_CIPHER_KEY_SEL] = 0xbc18, | |
135 | [PWRAP_DEW_CIPHER_IV_SEL] = 0xbc1a, | |
136 | [PWRAP_DEW_CIPHER_LOAD] = 0xbc1c, | |
137 | [PWRAP_DEW_CIPHER_START] = 0xbc1e, | |
138 | [PWRAP_DEW_CIPHER_RDY] = 0xbc20, | |
139 | [PWRAP_DEW_CIPHER_MODE] = 0xbc22, | |
140 | [PWRAP_DEW_CIPHER_SWRST] = 0xbc24, | |
141 | }; | |
1f022d84 FF |
142 | |
143 | enum pwrap_regs { | |
144 | PWRAP_MUX_SEL, | |
145 | PWRAP_WRAP_EN, | |
146 | PWRAP_DIO_EN, | |
147 | PWRAP_SIDLY, | |
148 | PWRAP_CSHEXT_WRITE, | |
149 | PWRAP_CSHEXT_READ, | |
150 | PWRAP_CSLEXT_START, | |
151 | PWRAP_CSLEXT_END, | |
152 | PWRAP_STAUPD_PRD, | |
153 | PWRAP_STAUPD_GRPEN, | |
154 | PWRAP_STAUPD_MAN_TRIG, | |
155 | PWRAP_STAUPD_STA, | |
156 | PWRAP_WRAP_STA, | |
157 | PWRAP_HARB_INIT, | |
158 | PWRAP_HARB_HPRIO, | |
159 | PWRAP_HIPRIO_ARB_EN, | |
160 | PWRAP_HARB_STA0, | |
161 | PWRAP_HARB_STA1, | |
162 | PWRAP_MAN_EN, | |
163 | PWRAP_MAN_CMD, | |
164 | PWRAP_MAN_RDATA, | |
165 | PWRAP_MAN_VLDCLR, | |
166 | PWRAP_WACS0_EN, | |
167 | PWRAP_INIT_DONE0, | |
168 | PWRAP_WACS0_CMD, | |
169 | PWRAP_WACS0_RDATA, | |
170 | PWRAP_WACS0_VLDCLR, | |
171 | PWRAP_WACS1_EN, | |
172 | PWRAP_INIT_DONE1, | |
173 | PWRAP_WACS1_CMD, | |
174 | PWRAP_WACS1_RDATA, | |
175 | PWRAP_WACS1_VLDCLR, | |
176 | PWRAP_WACS2_EN, | |
177 | PWRAP_INIT_DONE2, | |
178 | PWRAP_WACS2_CMD, | |
179 | PWRAP_WACS2_RDATA, | |
180 | PWRAP_WACS2_VLDCLR, | |
181 | PWRAP_INT_EN, | |
182 | PWRAP_INT_FLG_RAW, | |
183 | PWRAP_INT_FLG, | |
184 | PWRAP_INT_CLR, | |
185 | PWRAP_SIG_ADR, | |
186 | PWRAP_SIG_MODE, | |
187 | PWRAP_SIG_VALUE, | |
188 | PWRAP_SIG_ERRVAL, | |
189 | PWRAP_CRC_EN, | |
190 | PWRAP_TIMER_EN, | |
191 | PWRAP_TIMER_STA, | |
192 | PWRAP_WDT_UNIT, | |
193 | PWRAP_WDT_SRC_EN, | |
194 | PWRAP_WDT_FLG, | |
195 | PWRAP_DEBUG_INT_SEL, | |
196 | PWRAP_CIPHER_KEY_SEL, | |
197 | PWRAP_CIPHER_IV_SEL, | |
198 | PWRAP_CIPHER_RDY, | |
199 | PWRAP_CIPHER_MODE, | |
200 | PWRAP_CIPHER_SWRST, | |
201 | PWRAP_DCM_EN, | |
202 | PWRAP_DCM_DBC_PRD, | |
203 | ||
060a1d64 JC |
204 | /* MT2701 only regs */ |
205 | PWRAP_ADC_CMD_ADDR, | |
206 | PWRAP_PWRAP_ADC_CMD, | |
207 | PWRAP_ADC_RDY_ADDR, | |
208 | PWRAP_ADC_RDATA_ADDR1, | |
209 | PWRAP_ADC_RDATA_ADDR2, | |
210 | ||
1f022d84 FF |
211 | /* MT8135 only regs */ |
212 | PWRAP_CSHEXT, | |
213 | PWRAP_EVENT_IN_EN, | |
214 | PWRAP_EVENT_DST_EN, | |
215 | PWRAP_RRARB_INIT, | |
216 | PWRAP_RRARB_EN, | |
217 | PWRAP_RRARB_STA0, | |
218 | PWRAP_RRARB_STA1, | |
219 | PWRAP_EVENT_STA, | |
220 | PWRAP_EVENT_STACLR, | |
221 | PWRAP_CIPHER_LOAD, | |
222 | PWRAP_CIPHER_START, | |
223 | ||
224 | /* MT8173 only regs */ | |
225 | PWRAP_RDDMY, | |
226 | PWRAP_SI_CK_CON, | |
227 | PWRAP_DVFS_ADR0, | |
228 | PWRAP_DVFS_WDATA0, | |
229 | PWRAP_DVFS_ADR1, | |
230 | PWRAP_DVFS_WDATA1, | |
231 | PWRAP_DVFS_ADR2, | |
232 | PWRAP_DVFS_WDATA2, | |
233 | PWRAP_DVFS_ADR3, | |
234 | PWRAP_DVFS_WDATA3, | |
235 | PWRAP_DVFS_ADR4, | |
236 | PWRAP_DVFS_WDATA4, | |
237 | PWRAP_DVFS_ADR5, | |
238 | PWRAP_DVFS_WDATA5, | |
239 | PWRAP_DVFS_ADR6, | |
240 | PWRAP_DVFS_WDATA6, | |
241 | PWRAP_DVFS_ADR7, | |
242 | PWRAP_DVFS_WDATA7, | |
243 | PWRAP_SPMINF_STA, | |
244 | PWRAP_CIPHER_EN, | |
245 | }; | |
246 | ||
060a1d64 JC |
247 | static int mt2701_regs[] = { |
248 | [PWRAP_MUX_SEL] = 0x0, | |
249 | [PWRAP_WRAP_EN] = 0x4, | |
250 | [PWRAP_DIO_EN] = 0x8, | |
251 | [PWRAP_SIDLY] = 0xc, | |
252 | [PWRAP_RDDMY] = 0x18, | |
253 | [PWRAP_SI_CK_CON] = 0x1c, | |
254 | [PWRAP_CSHEXT_WRITE] = 0x20, | |
255 | [PWRAP_CSHEXT_READ] = 0x24, | |
256 | [PWRAP_CSLEXT_START] = 0x28, | |
257 | [PWRAP_CSLEXT_END] = 0x2c, | |
258 | [PWRAP_STAUPD_PRD] = 0x30, | |
259 | [PWRAP_STAUPD_GRPEN] = 0x34, | |
260 | [PWRAP_STAUPD_MAN_TRIG] = 0x38, | |
261 | [PWRAP_STAUPD_STA] = 0x3c, | |
262 | [PWRAP_WRAP_STA] = 0x44, | |
263 | [PWRAP_HARB_INIT] = 0x48, | |
264 | [PWRAP_HARB_HPRIO] = 0x4c, | |
265 | [PWRAP_HIPRIO_ARB_EN] = 0x50, | |
266 | [PWRAP_HARB_STA0] = 0x54, | |
267 | [PWRAP_HARB_STA1] = 0x58, | |
268 | [PWRAP_MAN_EN] = 0x5c, | |
269 | [PWRAP_MAN_CMD] = 0x60, | |
270 | [PWRAP_MAN_RDATA] = 0x64, | |
271 | [PWRAP_MAN_VLDCLR] = 0x68, | |
272 | [PWRAP_WACS0_EN] = 0x6c, | |
273 | [PWRAP_INIT_DONE0] = 0x70, | |
274 | [PWRAP_WACS0_CMD] = 0x74, | |
275 | [PWRAP_WACS0_RDATA] = 0x78, | |
276 | [PWRAP_WACS0_VLDCLR] = 0x7c, | |
277 | [PWRAP_WACS1_EN] = 0x80, | |
278 | [PWRAP_INIT_DONE1] = 0x84, | |
279 | [PWRAP_WACS1_CMD] = 0x88, | |
280 | [PWRAP_WACS1_RDATA] = 0x8c, | |
281 | [PWRAP_WACS1_VLDCLR] = 0x90, | |
282 | [PWRAP_WACS2_EN] = 0x94, | |
283 | [PWRAP_INIT_DONE2] = 0x98, | |
284 | [PWRAP_WACS2_CMD] = 0x9c, | |
285 | [PWRAP_WACS2_RDATA] = 0xa0, | |
286 | [PWRAP_WACS2_VLDCLR] = 0xa4, | |
287 | [PWRAP_INT_EN] = 0xa8, | |
288 | [PWRAP_INT_FLG_RAW] = 0xac, | |
289 | [PWRAP_INT_FLG] = 0xb0, | |
290 | [PWRAP_INT_CLR] = 0xb4, | |
291 | [PWRAP_SIG_ADR] = 0xb8, | |
292 | [PWRAP_SIG_MODE] = 0xbc, | |
293 | [PWRAP_SIG_VALUE] = 0xc0, | |
294 | [PWRAP_SIG_ERRVAL] = 0xc4, | |
295 | [PWRAP_CRC_EN] = 0xc8, | |
296 | [PWRAP_TIMER_EN] = 0xcc, | |
297 | [PWRAP_TIMER_STA] = 0xd0, | |
298 | [PWRAP_WDT_UNIT] = 0xd4, | |
299 | [PWRAP_WDT_SRC_EN] = 0xd8, | |
300 | [PWRAP_WDT_FLG] = 0xdc, | |
301 | [PWRAP_DEBUG_INT_SEL] = 0xe0, | |
302 | [PWRAP_DVFS_ADR0] = 0xe4, | |
303 | [PWRAP_DVFS_WDATA0] = 0xe8, | |
304 | [PWRAP_DVFS_ADR1] = 0xec, | |
305 | [PWRAP_DVFS_WDATA1] = 0xf0, | |
306 | [PWRAP_DVFS_ADR2] = 0xf4, | |
307 | [PWRAP_DVFS_WDATA2] = 0xf8, | |
308 | [PWRAP_DVFS_ADR3] = 0xfc, | |
309 | [PWRAP_DVFS_WDATA3] = 0x100, | |
310 | [PWRAP_DVFS_ADR4] = 0x104, | |
311 | [PWRAP_DVFS_WDATA4] = 0x108, | |
312 | [PWRAP_DVFS_ADR5] = 0x10c, | |
313 | [PWRAP_DVFS_WDATA5] = 0x110, | |
314 | [PWRAP_DVFS_ADR6] = 0x114, | |
315 | [PWRAP_DVFS_WDATA6] = 0x118, | |
316 | [PWRAP_DVFS_ADR7] = 0x11c, | |
317 | [PWRAP_DVFS_WDATA7] = 0x120, | |
318 | [PWRAP_CIPHER_KEY_SEL] = 0x124, | |
319 | [PWRAP_CIPHER_IV_SEL] = 0x128, | |
320 | [PWRAP_CIPHER_EN] = 0x12c, | |
321 | [PWRAP_CIPHER_RDY] = 0x130, | |
322 | [PWRAP_CIPHER_MODE] = 0x134, | |
323 | [PWRAP_CIPHER_SWRST] = 0x138, | |
324 | [PWRAP_DCM_EN] = 0x13c, | |
325 | [PWRAP_DCM_DBC_PRD] = 0x140, | |
326 | [PWRAP_ADC_CMD_ADDR] = 0x144, | |
327 | [PWRAP_PWRAP_ADC_CMD] = 0x148, | |
328 | [PWRAP_ADC_RDY_ADDR] = 0x14c, | |
329 | [PWRAP_ADC_RDATA_ADDR1] = 0x150, | |
330 | [PWRAP_ADC_RDATA_ADDR2] = 0x154, | |
331 | }; | |
332 | ||
1f022d84 FF |
333 | static int mt8173_regs[] = { |
334 | [PWRAP_MUX_SEL] = 0x0, | |
335 | [PWRAP_WRAP_EN] = 0x4, | |
336 | [PWRAP_DIO_EN] = 0x8, | |
337 | [PWRAP_SIDLY] = 0xc, | |
338 | [PWRAP_RDDMY] = 0x10, | |
339 | [PWRAP_SI_CK_CON] = 0x14, | |
340 | [PWRAP_CSHEXT_WRITE] = 0x18, | |
341 | [PWRAP_CSHEXT_READ] = 0x1c, | |
342 | [PWRAP_CSLEXT_START] = 0x20, | |
343 | [PWRAP_CSLEXT_END] = 0x24, | |
344 | [PWRAP_STAUPD_PRD] = 0x28, | |
345 | [PWRAP_STAUPD_GRPEN] = 0x2c, | |
346 | [PWRAP_STAUPD_MAN_TRIG] = 0x40, | |
347 | [PWRAP_STAUPD_STA] = 0x44, | |
348 | [PWRAP_WRAP_STA] = 0x48, | |
349 | [PWRAP_HARB_INIT] = 0x4c, | |
350 | [PWRAP_HARB_HPRIO] = 0x50, | |
351 | [PWRAP_HIPRIO_ARB_EN] = 0x54, | |
352 | [PWRAP_HARB_STA0] = 0x58, | |
353 | [PWRAP_HARB_STA1] = 0x5c, | |
354 | [PWRAP_MAN_EN] = 0x60, | |
355 | [PWRAP_MAN_CMD] = 0x64, | |
356 | [PWRAP_MAN_RDATA] = 0x68, | |
357 | [PWRAP_MAN_VLDCLR] = 0x6c, | |
358 | [PWRAP_WACS0_EN] = 0x70, | |
359 | [PWRAP_INIT_DONE0] = 0x74, | |
360 | [PWRAP_WACS0_CMD] = 0x78, | |
361 | [PWRAP_WACS0_RDATA] = 0x7c, | |
362 | [PWRAP_WACS0_VLDCLR] = 0x80, | |
363 | [PWRAP_WACS1_EN] = 0x84, | |
364 | [PWRAP_INIT_DONE1] = 0x88, | |
365 | [PWRAP_WACS1_CMD] = 0x8c, | |
366 | [PWRAP_WACS1_RDATA] = 0x90, | |
367 | [PWRAP_WACS1_VLDCLR] = 0x94, | |
368 | [PWRAP_WACS2_EN] = 0x98, | |
369 | [PWRAP_INIT_DONE2] = 0x9c, | |
370 | [PWRAP_WACS2_CMD] = 0xa0, | |
371 | [PWRAP_WACS2_RDATA] = 0xa4, | |
372 | [PWRAP_WACS2_VLDCLR] = 0xa8, | |
373 | [PWRAP_INT_EN] = 0xac, | |
374 | [PWRAP_INT_FLG_RAW] = 0xb0, | |
375 | [PWRAP_INT_FLG] = 0xb4, | |
376 | [PWRAP_INT_CLR] = 0xb8, | |
377 | [PWRAP_SIG_ADR] = 0xbc, | |
378 | [PWRAP_SIG_MODE] = 0xc0, | |
379 | [PWRAP_SIG_VALUE] = 0xc4, | |
380 | [PWRAP_SIG_ERRVAL] = 0xc8, | |
381 | [PWRAP_CRC_EN] = 0xcc, | |
382 | [PWRAP_TIMER_EN] = 0xd0, | |
383 | [PWRAP_TIMER_STA] = 0xd4, | |
384 | [PWRAP_WDT_UNIT] = 0xd8, | |
385 | [PWRAP_WDT_SRC_EN] = 0xdc, | |
386 | [PWRAP_WDT_FLG] = 0xe0, | |
387 | [PWRAP_DEBUG_INT_SEL] = 0xe4, | |
388 | [PWRAP_DVFS_ADR0] = 0xe8, | |
389 | [PWRAP_DVFS_WDATA0] = 0xec, | |
390 | [PWRAP_DVFS_ADR1] = 0xf0, | |
391 | [PWRAP_DVFS_WDATA1] = 0xf4, | |
392 | [PWRAP_DVFS_ADR2] = 0xf8, | |
393 | [PWRAP_DVFS_WDATA2] = 0xfc, | |
394 | [PWRAP_DVFS_ADR3] = 0x100, | |
395 | [PWRAP_DVFS_WDATA3] = 0x104, | |
396 | [PWRAP_DVFS_ADR4] = 0x108, | |
397 | [PWRAP_DVFS_WDATA4] = 0x10c, | |
398 | [PWRAP_DVFS_ADR5] = 0x110, | |
399 | [PWRAP_DVFS_WDATA5] = 0x114, | |
400 | [PWRAP_DVFS_ADR6] = 0x118, | |
401 | [PWRAP_DVFS_WDATA6] = 0x11c, | |
402 | [PWRAP_DVFS_ADR7] = 0x120, | |
403 | [PWRAP_DVFS_WDATA7] = 0x124, | |
404 | [PWRAP_SPMINF_STA] = 0x128, | |
405 | [PWRAP_CIPHER_KEY_SEL] = 0x12c, | |
406 | [PWRAP_CIPHER_IV_SEL] = 0x130, | |
407 | [PWRAP_CIPHER_EN] = 0x134, | |
408 | [PWRAP_CIPHER_RDY] = 0x138, | |
409 | [PWRAP_CIPHER_MODE] = 0x13c, | |
410 | [PWRAP_CIPHER_SWRST] = 0x140, | |
411 | [PWRAP_DCM_EN] = 0x144, | |
412 | [PWRAP_DCM_DBC_PRD] = 0x148, | |
413 | }; | |
414 | ||
415 | static int mt8135_regs[] = { | |
416 | [PWRAP_MUX_SEL] = 0x0, | |
417 | [PWRAP_WRAP_EN] = 0x4, | |
418 | [PWRAP_DIO_EN] = 0x8, | |
419 | [PWRAP_SIDLY] = 0xc, | |
420 | [PWRAP_CSHEXT] = 0x10, | |
421 | [PWRAP_CSHEXT_WRITE] = 0x14, | |
422 | [PWRAP_CSHEXT_READ] = 0x18, | |
423 | [PWRAP_CSLEXT_START] = 0x1c, | |
424 | [PWRAP_CSLEXT_END] = 0x20, | |
425 | [PWRAP_STAUPD_PRD] = 0x24, | |
426 | [PWRAP_STAUPD_GRPEN] = 0x28, | |
427 | [PWRAP_STAUPD_MAN_TRIG] = 0x2c, | |
428 | [PWRAP_STAUPD_STA] = 0x30, | |
429 | [PWRAP_EVENT_IN_EN] = 0x34, | |
430 | [PWRAP_EVENT_DST_EN] = 0x38, | |
431 | [PWRAP_WRAP_STA] = 0x3c, | |
432 | [PWRAP_RRARB_INIT] = 0x40, | |
433 | [PWRAP_RRARB_EN] = 0x44, | |
434 | [PWRAP_RRARB_STA0] = 0x48, | |
435 | [PWRAP_RRARB_STA1] = 0x4c, | |
436 | [PWRAP_HARB_INIT] = 0x50, | |
437 | [PWRAP_HARB_HPRIO] = 0x54, | |
438 | [PWRAP_HIPRIO_ARB_EN] = 0x58, | |
439 | [PWRAP_HARB_STA0] = 0x5c, | |
440 | [PWRAP_HARB_STA1] = 0x60, | |
441 | [PWRAP_MAN_EN] = 0x64, | |
442 | [PWRAP_MAN_CMD] = 0x68, | |
443 | [PWRAP_MAN_RDATA] = 0x6c, | |
444 | [PWRAP_MAN_VLDCLR] = 0x70, | |
445 | [PWRAP_WACS0_EN] = 0x74, | |
446 | [PWRAP_INIT_DONE0] = 0x78, | |
447 | [PWRAP_WACS0_CMD] = 0x7c, | |
448 | [PWRAP_WACS0_RDATA] = 0x80, | |
449 | [PWRAP_WACS0_VLDCLR] = 0x84, | |
450 | [PWRAP_WACS1_EN] = 0x88, | |
451 | [PWRAP_INIT_DONE1] = 0x8c, | |
452 | [PWRAP_WACS1_CMD] = 0x90, | |
453 | [PWRAP_WACS1_RDATA] = 0x94, | |
454 | [PWRAP_WACS1_VLDCLR] = 0x98, | |
455 | [PWRAP_WACS2_EN] = 0x9c, | |
456 | [PWRAP_INIT_DONE2] = 0xa0, | |
457 | [PWRAP_WACS2_CMD] = 0xa4, | |
458 | [PWRAP_WACS2_RDATA] = 0xa8, | |
459 | [PWRAP_WACS2_VLDCLR] = 0xac, | |
460 | [PWRAP_INT_EN] = 0xb0, | |
461 | [PWRAP_INT_FLG_RAW] = 0xb4, | |
462 | [PWRAP_INT_FLG] = 0xb8, | |
463 | [PWRAP_INT_CLR] = 0xbc, | |
464 | [PWRAP_SIG_ADR] = 0xc0, | |
465 | [PWRAP_SIG_MODE] = 0xc4, | |
466 | [PWRAP_SIG_VALUE] = 0xc8, | |
467 | [PWRAP_SIG_ERRVAL] = 0xcc, | |
468 | [PWRAP_CRC_EN] = 0xd0, | |
469 | [PWRAP_EVENT_STA] = 0xd4, | |
470 | [PWRAP_EVENT_STACLR] = 0xd8, | |
471 | [PWRAP_TIMER_EN] = 0xdc, | |
472 | [PWRAP_TIMER_STA] = 0xe0, | |
473 | [PWRAP_WDT_UNIT] = 0xe4, | |
474 | [PWRAP_WDT_SRC_EN] = 0xe8, | |
475 | [PWRAP_WDT_FLG] = 0xec, | |
476 | [PWRAP_DEBUG_INT_SEL] = 0xf0, | |
477 | [PWRAP_CIPHER_KEY_SEL] = 0x134, | |
478 | [PWRAP_CIPHER_IV_SEL] = 0x138, | |
479 | [PWRAP_CIPHER_LOAD] = 0x13c, | |
480 | [PWRAP_CIPHER_START] = 0x140, | |
481 | [PWRAP_CIPHER_RDY] = 0x144, | |
482 | [PWRAP_CIPHER_MODE] = 0x148, | |
483 | [PWRAP_CIPHER_SWRST] = 0x14c, | |
484 | [PWRAP_DCM_EN] = 0x15c, | |
485 | [PWRAP_DCM_DBC_PRD] = 0x160, | |
486 | }; | |
487 | ||
b28d78cd | 488 | enum pmic_type { |
5ae48040 | 489 | PMIC_MT6323, |
b28d78cd JC |
490 | PMIC_MT6397, |
491 | }; | |
492 | ||
1f022d84 | 493 | enum pwrap_type { |
060a1d64 | 494 | PWRAP_MT2701, |
1f022d84 FF |
495 | PWRAP_MT8135, |
496 | PWRAP_MT8173, | |
497 | }; | |
498 | ||
b28d78cd JC |
499 | struct pwrap_slv_type { |
500 | const u32 *dew_regs; | |
501 | enum pmic_type type; | |
502 | }; | |
503 | ||
1f022d84 FF |
504 | struct pmic_wrapper { |
505 | struct device *dev; | |
506 | void __iomem *base; | |
507 | struct regmap *regmap; | |
9bebedb0 | 508 | const struct pmic_wrapper_type *master; |
b28d78cd | 509 | const struct pwrap_slv_type *slave; |
1f022d84 FF |
510 | struct clk *clk_spi; |
511 | struct clk *clk_wrap; | |
512 | struct reset_control *rstc; | |
513 | ||
514 | struct reset_control *rstc_bridge; | |
515 | void __iomem *bridge_base; | |
516 | }; | |
517 | ||
a3978453 JC |
518 | struct pmic_wrapper_type { |
519 | int *regs; | |
520 | enum pwrap_type type; | |
521 | u32 arb_en_all; | |
e5eef49b | 522 | u32 int_en_all; |
174f7b4c | 523 | u32 spi_w; |
95b25c58 | 524 | u32 wdt_src; |
25269cef | 525 | int has_bridge:1; |
a3978453 | 526 | int (*init_reg_clock)(struct pmic_wrapper *wrp); |
41c11f32 | 527 | int (*init_soc_specific)(struct pmic_wrapper *wrp); |
a3978453 JC |
528 | }; |
529 | ||
1f022d84 FF |
530 | static u32 pwrap_readl(struct pmic_wrapper *wrp, enum pwrap_regs reg) |
531 | { | |
9bebedb0 | 532 | return readl(wrp->base + wrp->master->regs[reg]); |
1f022d84 FF |
533 | } |
534 | ||
535 | static void pwrap_writel(struct pmic_wrapper *wrp, u32 val, enum pwrap_regs reg) | |
536 | { | |
9bebedb0 | 537 | writel(val, wrp->base + wrp->master->regs[reg]); |
1f022d84 FF |
538 | } |
539 | ||
540 | static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp) | |
541 | { | |
542 | u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | |
543 | ||
544 | return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE; | |
545 | } | |
546 | ||
547 | static bool pwrap_is_fsm_vldclr(struct pmic_wrapper *wrp) | |
548 | { | |
549 | u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | |
550 | ||
551 | return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR; | |
552 | } | |
553 | ||
73efe579 HC |
554 | /* |
555 | * Timeout issue sometimes caused by the last read command | |
556 | * failed because pmic wrap could not got the FSM_VLDCLR | |
557 | * in time after finishing WACS2_CMD. It made state machine | |
558 | * still on FSM_VLDCLR and timeout next time. | |
559 | * Check the status of FSM and clear the vldclr to recovery the | |
560 | * error. | |
561 | */ | |
562 | static inline void pwrap_leave_fsm_vldclr(struct pmic_wrapper *wrp) | |
563 | { | |
564 | if (pwrap_is_fsm_vldclr(wrp)) | |
565 | pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR); | |
566 | } | |
567 | ||
1f022d84 FF |
568 | static bool pwrap_is_sync_idle(struct pmic_wrapper *wrp) |
569 | { | |
570 | return pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_SYNC_IDLE0; | |
571 | } | |
572 | ||
573 | static bool pwrap_is_fsm_idle_and_sync_idle(struct pmic_wrapper *wrp) | |
574 | { | |
575 | u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | |
576 | ||
577 | return (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE) && | |
578 | (val & PWRAP_STATE_SYNC_IDLE0); | |
579 | } | |
580 | ||
581 | static int pwrap_wait_for_state(struct pmic_wrapper *wrp, | |
582 | bool (*fp)(struct pmic_wrapper *)) | |
583 | { | |
584 | unsigned long timeout; | |
585 | ||
e180f887 | 586 | timeout = jiffies + usecs_to_jiffies(10000); |
1f022d84 FF |
587 | |
588 | do { | |
589 | if (time_after(jiffies, timeout)) | |
590 | return fp(wrp) ? 0 : -ETIMEDOUT; | |
591 | if (fp(wrp)) | |
592 | return 0; | |
593 | } while (1); | |
594 | } | |
595 | ||
596 | static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata) | |
597 | { | |
598 | int ret; | |
1f022d84 FF |
599 | |
600 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); | |
73efe579 HC |
601 | if (ret) { |
602 | pwrap_leave_fsm_vldclr(wrp); | |
1f022d84 | 603 | return ret; |
73efe579 | 604 | } |
1f022d84 FF |
605 | |
606 | pwrap_writel(wrp, (1 << 31) | ((adr >> 1) << 16) | wdata, | |
607 | PWRAP_WACS2_CMD); | |
608 | ||
609 | return 0; | |
610 | } | |
611 | ||
612 | static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) | |
613 | { | |
614 | int ret; | |
1f022d84 FF |
615 | |
616 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); | |
73efe579 HC |
617 | if (ret) { |
618 | pwrap_leave_fsm_vldclr(wrp); | |
1f022d84 | 619 | return ret; |
73efe579 | 620 | } |
1f022d84 FF |
621 | |
622 | pwrap_writel(wrp, (adr >> 1) << 16, PWRAP_WACS2_CMD); | |
623 | ||
624 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr); | |
625 | if (ret) | |
626 | return ret; | |
627 | ||
628 | *rdata = PWRAP_GET_WACS_RDATA(pwrap_readl(wrp, PWRAP_WACS2_RDATA)); | |
629 | ||
d956b80a SH |
630 | pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR); |
631 | ||
1f022d84 FF |
632 | return 0; |
633 | } | |
634 | ||
635 | static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata) | |
636 | { | |
637 | return pwrap_read(context, adr, rdata); | |
638 | } | |
639 | ||
640 | static int pwrap_regmap_write(void *context, u32 adr, u32 wdata) | |
641 | { | |
642 | return pwrap_write(context, adr, wdata); | |
643 | } | |
644 | ||
645 | static int pwrap_reset_spislave(struct pmic_wrapper *wrp) | |
646 | { | |
647 | int ret, i; | |
648 | ||
649 | pwrap_writel(wrp, 0, PWRAP_HIPRIO_ARB_EN); | |
650 | pwrap_writel(wrp, 0, PWRAP_WRAP_EN); | |
651 | pwrap_writel(wrp, 1, PWRAP_MUX_SEL); | |
652 | pwrap_writel(wrp, 1, PWRAP_MAN_EN); | |
653 | pwrap_writel(wrp, 0, PWRAP_DIO_EN); | |
654 | ||
174f7b4c | 655 | pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_CSL, |
1f022d84 | 656 | PWRAP_MAN_CMD); |
174f7b4c | 657 | pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS, |
1f022d84 | 658 | PWRAP_MAN_CMD); |
174f7b4c | 659 | pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_CSH, |
1f022d84 FF |
660 | PWRAP_MAN_CMD); |
661 | ||
662 | for (i = 0; i < 4; i++) | |
174f7b4c | 663 | pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS, |
1f022d84 FF |
664 | PWRAP_MAN_CMD); |
665 | ||
666 | ret = pwrap_wait_for_state(wrp, pwrap_is_sync_idle); | |
667 | if (ret) { | |
668 | dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret); | |
669 | return ret; | |
670 | } | |
671 | ||
672 | pwrap_writel(wrp, 0, PWRAP_MAN_EN); | |
673 | pwrap_writel(wrp, 0, PWRAP_MUX_SEL); | |
674 | ||
675 | return 0; | |
676 | } | |
677 | ||
678 | /* | |
679 | * pwrap_init_sidly - configure serial input delay | |
680 | * | |
681 | * This configures the serial input delay. We can configure 0, 2, 4 or 6ns | |
682 | * delay. Do a read test with all possible values and chose the best delay. | |
683 | */ | |
684 | static int pwrap_init_sidly(struct pmic_wrapper *wrp) | |
685 | { | |
686 | u32 rdata; | |
687 | u32 i; | |
688 | u32 pass = 0; | |
689 | signed char dly[16] = { | |
690 | -1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1 | |
691 | }; | |
692 | ||
693 | for (i = 0; i < 4; i++) { | |
694 | pwrap_writel(wrp, i, PWRAP_SIDLY); | |
b28d78cd JC |
695 | pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], |
696 | &rdata); | |
1f022d84 FF |
697 | if (rdata == PWRAP_DEW_READ_TEST_VAL) { |
698 | dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i); | |
699 | pass |= 1 << i; | |
700 | } | |
701 | } | |
702 | ||
703 | if (dly[pass] < 0) { | |
704 | dev_err(wrp->dev, "sidly pass range 0x%x not continuous\n", | |
705 | pass); | |
706 | return -EIO; | |
707 | } | |
708 | ||
709 | pwrap_writel(wrp, dly[pass], PWRAP_SIDLY); | |
710 | ||
711 | return 0; | |
712 | } | |
713 | ||
a3978453 | 714 | static int pwrap_mt8135_init_reg_clock(struct pmic_wrapper *wrp) |
1f022d84 | 715 | { |
a3978453 JC |
716 | pwrap_writel(wrp, 0x4, PWRAP_CSHEXT); |
717 | pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE); | |
718 | pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ); | |
719 | pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START); | |
720 | pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END); | |
721 | ||
722 | return 0; | |
723 | } | |
724 | ||
725 | static int pwrap_mt8173_init_reg_clock(struct pmic_wrapper *wrp) | |
726 | { | |
727 | pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE); | |
728 | pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ); | |
729 | pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); | |
730 | pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); | |
1f022d84 FF |
731 | |
732 | return 0; | |
733 | } | |
734 | ||
060a1d64 JC |
735 | static int pwrap_mt2701_init_reg_clock(struct pmic_wrapper *wrp) |
736 | { | |
737 | switch (wrp->slave->type) { | |
738 | case PMIC_MT6397: | |
739 | pwrap_writel(wrp, 0xc, PWRAP_RDDMY); | |
740 | pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_WRITE); | |
741 | pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_READ); | |
742 | pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); | |
743 | pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); | |
744 | break; | |
745 | ||
746 | case PMIC_MT6323: | |
747 | pwrap_writel(wrp, 0x8, PWRAP_RDDMY); | |
748 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_RDDMY_NO], | |
749 | 0x8); | |
750 | pwrap_writel(wrp, 0x5, PWRAP_CSHEXT_WRITE); | |
751 | pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_READ); | |
752 | pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); | |
753 | pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); | |
754 | break; | |
755 | } | |
756 | ||
757 | return 0; | |
758 | } | |
759 | ||
1f022d84 FF |
760 | static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp) |
761 | { | |
762 | return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1; | |
763 | } | |
764 | ||
765 | static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp) | |
766 | { | |
767 | u32 rdata; | |
768 | int ret; | |
769 | ||
b28d78cd JC |
770 | ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY], |
771 | &rdata); | |
1f022d84 FF |
772 | if (ret) |
773 | return 0; | |
774 | ||
775 | return rdata == 1; | |
776 | } | |
777 | ||
778 | static int pwrap_init_cipher(struct pmic_wrapper *wrp) | |
779 | { | |
780 | int ret; | |
781 | u32 rdata; | |
782 | ||
783 | pwrap_writel(wrp, 0x1, PWRAP_CIPHER_SWRST); | |
784 | pwrap_writel(wrp, 0x0, PWRAP_CIPHER_SWRST); | |
785 | pwrap_writel(wrp, 0x1, PWRAP_CIPHER_KEY_SEL); | |
786 | pwrap_writel(wrp, 0x2, PWRAP_CIPHER_IV_SEL); | |
787 | ||
25269cef JC |
788 | switch (wrp->master->type) { |
789 | case PWRAP_MT8135: | |
1f022d84 FF |
790 | pwrap_writel(wrp, 1, PWRAP_CIPHER_LOAD); |
791 | pwrap_writel(wrp, 1, PWRAP_CIPHER_START); | |
25269cef | 792 | break; |
060a1d64 | 793 | case PWRAP_MT2701: |
25269cef | 794 | case PWRAP_MT8173: |
1f022d84 | 795 | pwrap_writel(wrp, 1, PWRAP_CIPHER_EN); |
25269cef | 796 | break; |
1f022d84 FF |
797 | } |
798 | ||
799 | /* Config cipher mode @PMIC */ | |
b28d78cd JC |
800 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1); |
801 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0); | |
802 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1); | |
803 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2); | |
804 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], 0x1); | |
805 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], 0x1); | |
1f022d84 | 806 | |
5ae48040 JC |
807 | switch (wrp->slave->type) { |
808 | case PMIC_MT6397: | |
809 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], | |
810 | 0x1); | |
811 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], | |
812 | 0x1); | |
813 | break; | |
814 | case PMIC_MT6323: | |
815 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN], | |
816 | 0x1); | |
817 | break; | |
818 | } | |
819 | ||
1f022d84 FF |
820 | /* wait for cipher data ready@AP */ |
821 | ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready); | |
822 | if (ret) { | |
823 | dev_err(wrp->dev, "cipher data ready@AP fail, ret=%d\n", ret); | |
824 | return ret; | |
825 | } | |
826 | ||
827 | /* wait for cipher data ready@PMIC */ | |
828 | ret = pwrap_wait_for_state(wrp, pwrap_is_pmic_cipher_ready); | |
829 | if (ret) { | |
830 | dev_err(wrp->dev, "timeout waiting for cipher data ready@PMIC\n"); | |
831 | return ret; | |
832 | } | |
833 | ||
834 | /* wait for cipher mode idle */ | |
b28d78cd | 835 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_MODE], 0x1); |
1f022d84 FF |
836 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle); |
837 | if (ret) { | |
838 | dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret); | |
839 | return ret; | |
840 | } | |
841 | ||
842 | pwrap_writel(wrp, 1, PWRAP_CIPHER_MODE); | |
843 | ||
844 | /* Write Test */ | |
b28d78cd JC |
845 | if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_WRITE_TEST], |
846 | PWRAP_DEW_WRITE_TEST_VAL) || | |
847 | pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_WRITE_TEST], | |
848 | &rdata) || | |
849 | (rdata != PWRAP_DEW_WRITE_TEST_VAL)) { | |
1f022d84 FF |
850 | dev_err(wrp->dev, "rdata=0x%04X\n", rdata); |
851 | return -EFAULT; | |
852 | } | |
853 | ||
854 | return 0; | |
855 | } | |
856 | ||
41c11f32 JC |
857 | static int pwrap_mt8135_init_soc_specific(struct pmic_wrapper *wrp) |
858 | { | |
859 | /* enable pwrap events and pwrap bridge in AP side */ | |
860 | pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN); | |
861 | pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN); | |
862 | writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN); | |
863 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN); | |
864 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN); | |
865 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT); | |
866 | writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN); | |
867 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN); | |
868 | writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN); | |
869 | ||
870 | /* enable PMIC event out and sources */ | |
b28d78cd JC |
871 | if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_OUT_EN], |
872 | 0x1) || | |
873 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_SRC_EN], | |
874 | 0xffff)) { | |
41c11f32 JC |
875 | dev_err(wrp->dev, "enable dewrap fail\n"); |
876 | return -EFAULT; | |
877 | } | |
878 | ||
879 | return 0; | |
880 | } | |
881 | ||
882 | static int pwrap_mt8173_init_soc_specific(struct pmic_wrapper *wrp) | |
883 | { | |
884 | /* PMIC_DEWRAP enables */ | |
b28d78cd JC |
885 | if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_OUT_EN], |
886 | 0x1) || | |
887 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_SRC_EN], | |
888 | 0xffff)) { | |
41c11f32 JC |
889 | dev_err(wrp->dev, "enable dewrap fail\n"); |
890 | return -EFAULT; | |
891 | } | |
892 | ||
893 | return 0; | |
894 | } | |
895 | ||
060a1d64 JC |
896 | static int pwrap_mt2701_init_soc_specific(struct pmic_wrapper *wrp) |
897 | { | |
898 | /* GPS_INTF initialization */ | |
899 | switch (wrp->slave->type) { | |
900 | case PMIC_MT6323: | |
901 | pwrap_writel(wrp, 0x076c, PWRAP_ADC_CMD_ADDR); | |
902 | pwrap_writel(wrp, 0x8000, PWRAP_PWRAP_ADC_CMD); | |
903 | pwrap_writel(wrp, 0x072c, PWRAP_ADC_RDY_ADDR); | |
904 | pwrap_writel(wrp, 0x072e, PWRAP_ADC_RDATA_ADDR1); | |
905 | pwrap_writel(wrp, 0x0730, PWRAP_ADC_RDATA_ADDR2); | |
906 | break; | |
907 | default: | |
908 | break; | |
909 | } | |
910 | ||
911 | return 0; | |
912 | } | |
913 | ||
1f022d84 FF |
914 | static int pwrap_init(struct pmic_wrapper *wrp) |
915 | { | |
916 | int ret; | |
917 | u32 rdata; | |
918 | ||
919 | reset_control_reset(wrp->rstc); | |
920 | if (wrp->rstc_bridge) | |
921 | reset_control_reset(wrp->rstc_bridge); | |
922 | ||
25269cef | 923 | if (wrp->master->type == PWRAP_MT8173) { |
1f022d84 FF |
924 | /* Enable DCM */ |
925 | pwrap_writel(wrp, 3, PWRAP_DCM_EN); | |
926 | pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); | |
927 | } | |
928 | ||
929 | /* Reset SPI slave */ | |
930 | ret = pwrap_reset_spislave(wrp); | |
931 | if (ret) | |
932 | return ret; | |
933 | ||
934 | pwrap_writel(wrp, 1, PWRAP_WRAP_EN); | |
935 | ||
9bebedb0 | 936 | pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); |
1f022d84 FF |
937 | |
938 | pwrap_writel(wrp, 1, PWRAP_WACS2_EN); | |
939 | ||
a3978453 | 940 | ret = wrp->master->init_reg_clock(wrp); |
1f022d84 FF |
941 | if (ret) |
942 | return ret; | |
943 | ||
944 | /* Setup serial input delay */ | |
945 | ret = pwrap_init_sidly(wrp); | |
946 | if (ret) | |
947 | return ret; | |
948 | ||
949 | /* Enable dual IO mode */ | |
b28d78cd | 950 | pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1); |
1f022d84 FF |
951 | |
952 | /* Check IDLE & INIT_DONE in advance */ | |
953 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle); | |
954 | if (ret) { | |
955 | dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret); | |
956 | return ret; | |
957 | } | |
958 | ||
959 | pwrap_writel(wrp, 1, PWRAP_DIO_EN); | |
960 | ||
961 | /* Read Test */ | |
b28d78cd | 962 | pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata); |
1f022d84 FF |
963 | if (rdata != PWRAP_DEW_READ_TEST_VAL) { |
964 | dev_err(wrp->dev, "Read test failed after switch to DIO mode: 0x%04x != 0x%04x\n", | |
965 | PWRAP_DEW_READ_TEST_VAL, rdata); | |
966 | return -EFAULT; | |
967 | } | |
968 | ||
969 | /* Enable encryption */ | |
970 | ret = pwrap_init_cipher(wrp); | |
971 | if (ret) | |
972 | return ret; | |
973 | ||
974 | /* Signature checking - using CRC */ | |
b28d78cd | 975 | if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1)) |
1f022d84 FF |
976 | return -EFAULT; |
977 | ||
978 | pwrap_writel(wrp, 0x1, PWRAP_CRC_EN); | |
979 | pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE); | |
b28d78cd JC |
980 | pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL], |
981 | PWRAP_SIG_ADR); | |
9bebedb0 | 982 | pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); |
1f022d84 | 983 | |
25269cef | 984 | if (wrp->master->type == PWRAP_MT8135) |
1f022d84 FF |
985 | pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN); |
986 | ||
987 | pwrap_writel(wrp, 0x1, PWRAP_WACS0_EN); | |
988 | pwrap_writel(wrp, 0x1, PWRAP_WACS1_EN); | |
989 | pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN); | |
990 | pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD); | |
991 | pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN); | |
1f022d84 | 992 | |
41c11f32 JC |
993 | if (wrp->master->init_soc_specific) { |
994 | ret = wrp->master->init_soc_specific(wrp); | |
995 | if (ret) | |
996 | return ret; | |
1f022d84 FF |
997 | } |
998 | ||
999 | /* Setup the init done registers */ | |
1000 | pwrap_writel(wrp, 1, PWRAP_INIT_DONE2); | |
1001 | pwrap_writel(wrp, 1, PWRAP_INIT_DONE0); | |
1002 | pwrap_writel(wrp, 1, PWRAP_INIT_DONE1); | |
1003 | ||
25269cef | 1004 | if (wrp->master->has_bridge) { |
1f022d84 FF |
1005 | writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3); |
1006 | writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4); | |
1007 | } | |
1008 | ||
1009 | return 0; | |
1010 | } | |
1011 | ||
1012 | static irqreturn_t pwrap_interrupt(int irqno, void *dev_id) | |
1013 | { | |
1014 | u32 rdata; | |
1015 | struct pmic_wrapper *wrp = dev_id; | |
1016 | ||
1017 | rdata = pwrap_readl(wrp, PWRAP_INT_FLG); | |
1018 | ||
1019 | dev_err(wrp->dev, "unexpected interrupt int=0x%x\n", rdata); | |
1020 | ||
1021 | pwrap_writel(wrp, 0xffffffff, PWRAP_INT_CLR); | |
1022 | ||
1023 | return IRQ_HANDLED; | |
1024 | } | |
1025 | ||
1026 | static const struct regmap_config pwrap_regmap_config = { | |
1027 | .reg_bits = 16, | |
1028 | .val_bits = 16, | |
1029 | .reg_stride = 2, | |
1030 | .reg_read = pwrap_regmap_read, | |
1031 | .reg_write = pwrap_regmap_write, | |
1032 | .max_register = 0xffff, | |
1033 | }; | |
1034 | ||
5ae48040 JC |
1035 | static const struct pwrap_slv_type pmic_mt6323 = { |
1036 | .dew_regs = mt6323_regs, | |
1037 | .type = PMIC_MT6323, | |
1038 | }; | |
1039 | ||
b28d78cd JC |
1040 | static const struct pwrap_slv_type pmic_mt6397 = { |
1041 | .dew_regs = mt6397_regs, | |
1042 | .type = PMIC_MT6397, | |
1043 | }; | |
1044 | ||
1045 | static const struct of_device_id of_slave_match_tbl[] = { | |
1046 | { | |
5ae48040 JC |
1047 | .compatible = "mediatek,mt6323", |
1048 | .data = &pmic_mt6323, | |
1049 | }, { | |
b28d78cd JC |
1050 | .compatible = "mediatek,mt6397", |
1051 | .data = &pmic_mt6397, | |
1052 | }, { | |
1053 | /* sentinel */ | |
1054 | } | |
1055 | }; | |
1056 | MODULE_DEVICE_TABLE(of, of_slave_match_tbl); | |
1057 | ||
060a1d64 JC |
1058 | static const struct pmic_wrapper_type pwrap_mt2701 = { |
1059 | .regs = mt2701_regs, | |
1060 | .type = PWRAP_MT2701, | |
1061 | .arb_en_all = 0x3f, | |
7f058c0a | 1062 | .int_en_all = ~(u32)(BIT(31) | BIT(2)), |
060a1d64 JC |
1063 | .spi_w = PWRAP_MAN_CMD_SPI_WRITE_NEW, |
1064 | .wdt_src = PWRAP_WDT_SRC_MASK_ALL, | |
1065 | .has_bridge = 0, | |
1066 | .init_reg_clock = pwrap_mt2701_init_reg_clock, | |
1067 | .init_soc_specific = pwrap_mt2701_init_soc_specific, | |
1068 | }; | |
1069 | ||
a3978453 JC |
1070 | static struct pmic_wrapper_type pwrap_mt8135 = { |
1071 | .regs = mt8135_regs, | |
1072 | .type = PWRAP_MT8135, | |
1073 | .arb_en_all = 0x1ff, | |
7f058c0a | 1074 | .int_en_all = ~(u32)(BIT(31) | BIT(1)), |
174f7b4c | 1075 | .spi_w = PWRAP_MAN_CMD_SPI_WRITE, |
95b25c58 | 1076 | .wdt_src = PWRAP_WDT_SRC_MASK_ALL, |
25269cef | 1077 | .has_bridge = 1, |
a3978453 | 1078 | .init_reg_clock = pwrap_mt8135_init_reg_clock, |
41c11f32 | 1079 | .init_soc_specific = pwrap_mt8135_init_soc_specific, |
a3978453 JC |
1080 | }; |
1081 | ||
1082 | static struct pmic_wrapper_type pwrap_mt8173 = { | |
1083 | .regs = mt8173_regs, | |
1084 | .type = PWRAP_MT8173, | |
1085 | .arb_en_all = 0x3f, | |
7f058c0a | 1086 | .int_en_all = ~(u32)(BIT(31) | BIT(1)), |
174f7b4c | 1087 | .spi_w = PWRAP_MAN_CMD_SPI_WRITE, |
95b25c58 | 1088 | .wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD, |
25269cef | 1089 | .has_bridge = 0, |
a3978453 | 1090 | .init_reg_clock = pwrap_mt8173_init_reg_clock, |
41c11f32 | 1091 | .init_soc_specific = pwrap_mt8173_init_soc_specific, |
a3978453 JC |
1092 | }; |
1093 | ||
1f022d84 FF |
1094 | static struct of_device_id of_pwrap_match_tbl[] = { |
1095 | { | |
060a1d64 JC |
1096 | .compatible = "mediatek,mt2701-pwrap", |
1097 | .data = &pwrap_mt2701, | |
1098 | }, { | |
1f022d84 FF |
1099 | .compatible = "mediatek,mt8135-pwrap", |
1100 | .data = &pwrap_mt8135, | |
1101 | }, { | |
1102 | .compatible = "mediatek,mt8173-pwrap", | |
1103 | .data = &pwrap_mt8173, | |
1104 | }, { | |
1105 | /* sentinel */ | |
1106 | } | |
1107 | }; | |
1108 | MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl); | |
1109 | ||
1110 | static int pwrap_probe(struct platform_device *pdev) | |
1111 | { | |
95b25c58 | 1112 | int ret, irq; |
1f022d84 FF |
1113 | struct pmic_wrapper *wrp; |
1114 | struct device_node *np = pdev->dev.of_node; | |
1115 | const struct of_device_id *of_id = | |
1116 | of_match_device(of_pwrap_match_tbl, &pdev->dev); | |
b28d78cd | 1117 | const struct of_device_id *of_slave_id = NULL; |
1f022d84 FF |
1118 | struct resource *res; |
1119 | ||
58a823dd | 1120 | if (!of_id) { |
1121 | dev_err(&pdev->dev, "Error: No device match found\n"); | |
1122 | return -ENODEV; | |
1123 | } | |
1124 | ||
b28d78cd JC |
1125 | if (pdev->dev.of_node->child) |
1126 | of_slave_id = of_match_node(of_slave_match_tbl, | |
1127 | pdev->dev.of_node->child); | |
1128 | if (!of_slave_id) { | |
1129 | dev_dbg(&pdev->dev, "slave pmic should be defined in dts\n"); | |
1130 | return -EINVAL; | |
1131 | } | |
1132 | ||
1f022d84 FF |
1133 | wrp = devm_kzalloc(&pdev->dev, sizeof(*wrp), GFP_KERNEL); |
1134 | if (!wrp) | |
1135 | return -ENOMEM; | |
1136 | ||
1137 | platform_set_drvdata(pdev, wrp); | |
1138 | ||
9bebedb0 | 1139 | wrp->master = of_id->data; |
b28d78cd | 1140 | wrp->slave = of_slave_id->data; |
1f022d84 FF |
1141 | wrp->dev = &pdev->dev; |
1142 | ||
1143 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap"); | |
1144 | wrp->base = devm_ioremap_resource(wrp->dev, res); | |
1145 | if (IS_ERR(wrp->base)) | |
1146 | return PTR_ERR(wrp->base); | |
1147 | ||
1148 | wrp->rstc = devm_reset_control_get(wrp->dev, "pwrap"); | |
1149 | if (IS_ERR(wrp->rstc)) { | |
1150 | ret = PTR_ERR(wrp->rstc); | |
1151 | dev_dbg(wrp->dev, "cannot get pwrap reset: %d\n", ret); | |
1152 | return ret; | |
1153 | } | |
1154 | ||
25269cef | 1155 | if (wrp->master->has_bridge) { |
1f022d84 FF |
1156 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
1157 | "pwrap-bridge"); | |
1158 | wrp->bridge_base = devm_ioremap_resource(wrp->dev, res); | |
1159 | if (IS_ERR(wrp->bridge_base)) | |
1160 | return PTR_ERR(wrp->bridge_base); | |
1161 | ||
1162 | wrp->rstc_bridge = devm_reset_control_get(wrp->dev, "pwrap-bridge"); | |
1163 | if (IS_ERR(wrp->rstc_bridge)) { | |
1164 | ret = PTR_ERR(wrp->rstc_bridge); | |
1165 | dev_dbg(wrp->dev, "cannot get pwrap-bridge reset: %d\n", ret); | |
1166 | return ret; | |
1167 | } | |
1168 | } | |
1169 | ||
1170 | wrp->clk_spi = devm_clk_get(wrp->dev, "spi"); | |
1171 | if (IS_ERR(wrp->clk_spi)) { | |
1172 | dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_spi)); | |
1173 | return PTR_ERR(wrp->clk_spi); | |
1174 | } | |
1175 | ||
1176 | wrp->clk_wrap = devm_clk_get(wrp->dev, "wrap"); | |
1177 | if (IS_ERR(wrp->clk_wrap)) { | |
1178 | dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_wrap)); | |
1179 | return PTR_ERR(wrp->clk_wrap); | |
1180 | } | |
1181 | ||
1182 | ret = clk_prepare_enable(wrp->clk_spi); | |
1183 | if (ret) | |
1184 | return ret; | |
1185 | ||
1186 | ret = clk_prepare_enable(wrp->clk_wrap); | |
1187 | if (ret) | |
1188 | goto err_out1; | |
1189 | ||
1190 | /* Enable internal dynamic clock */ | |
1191 | pwrap_writel(wrp, 1, PWRAP_DCM_EN); | |
1192 | pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); | |
1193 | ||
1194 | /* | |
1195 | * The PMIC could already be initialized by the bootloader. | |
1196 | * Skip initialization here in this case. | |
1197 | */ | |
1198 | if (!pwrap_readl(wrp, PWRAP_INIT_DONE2)) { | |
1199 | ret = pwrap_init(wrp); | |
1200 | if (ret) { | |
1201 | dev_dbg(wrp->dev, "init failed with %d\n", ret); | |
1202 | goto err_out2; | |
1203 | } | |
1204 | } | |
1205 | ||
1206 | if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_INIT_DONE0)) { | |
1207 | dev_dbg(wrp->dev, "initialization isn't finished\n"); | |
f282693f CJ |
1208 | ret = -ENODEV; |
1209 | goto err_out2; | |
1f022d84 FF |
1210 | } |
1211 | ||
bbe379fc HC |
1212 | /* Initialize watchdog, may not be done by the bootloader */ |
1213 | pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT); | |
a3bbfbb0 HC |
1214 | /* |
1215 | * Since STAUPD was not used on mt8173 platform, | |
1216 | * so STAUPD of WDT_SRC which should be turned off | |
1217 | */ | |
95b25c58 | 1218 | pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN); |
bbe379fc | 1219 | pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); |
e5eef49b | 1220 | pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN); |
bbe379fc | 1221 | |
1f022d84 FF |
1222 | irq = platform_get_irq(pdev, 0); |
1223 | ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH, | |
1224 | "mt-pmic-pwrap", wrp); | |
1225 | if (ret) | |
1226 | goto err_out2; | |
1227 | ||
1228 | wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, &pwrap_regmap_config); | |
f282693f CJ |
1229 | if (IS_ERR(wrp->regmap)) { |
1230 | ret = PTR_ERR(wrp->regmap); | |
1231 | goto err_out2; | |
1232 | } | |
1f022d84 FF |
1233 | |
1234 | ret = of_platform_populate(np, NULL, NULL, wrp->dev); | |
1235 | if (ret) { | |
1236 | dev_dbg(wrp->dev, "failed to create child devices at %s\n", | |
1237 | np->full_name); | |
1238 | goto err_out2; | |
1239 | } | |
1240 | ||
1241 | return 0; | |
1242 | ||
1243 | err_out2: | |
1244 | clk_disable_unprepare(wrp->clk_wrap); | |
1245 | err_out1: | |
1246 | clk_disable_unprepare(wrp->clk_spi); | |
1247 | ||
1248 | return ret; | |
1249 | } | |
1250 | ||
1251 | static struct platform_driver pwrap_drv = { | |
1252 | .driver = { | |
1253 | .name = "mt-pmic-pwrap", | |
1f022d84 FF |
1254 | .of_match_table = of_match_ptr(of_pwrap_match_tbl), |
1255 | }, | |
1256 | .probe = pwrap_probe, | |
1257 | }; | |
1258 | ||
1259 | module_platform_driver(pwrap_drv); | |
1260 | ||
1261 | MODULE_AUTHOR("Flora Fu, MediaTek"); | |
1262 | MODULE_DESCRIPTION("MediaTek MT8135 PMIC Wrapper Driver"); | |
1263 | MODULE_LICENSE("GPL v2"); |