blob: 62cb72dc94fdf0774ed3bb080c6cdb8c26ffdb2d [file] [log] [blame]
James Lo1e0765d2021-10-05 18:14:12 +08001/* SPDX-License-Identifier: GPL-2.0-only */
2
3/*
4 * This file is created based on MT8186 Functional Specification
5 * Chapter number: 3.7
6 */
7
8#include <device/mmio.h>
9#include <soc/infracfg.h>
10#include <soc/pll.h>
11#include <soc/pmic_wrap.h>
12#include <timer.h>
13
14#define PRIORITY_FIELD(x) ((x % 4) * 8)
15#define PRIORITY_IN(id, priority) (id << PRIORITY_FIELD(priority))
16#define PRIORITY_OUT(id, priority) (priority << PRIORITY_FIELD(id))
17
18enum {
19 MD_ADCINF0 = 8,
20 MD_ADCINF1 = 9,
21 STAUPD = 10,
22 GPSINF0 = 11,
23
24 PRIORITY_IN_SEL_2 = PRIORITY_IN(MD_ADCINF0, 9) |
25 PRIORITY_IN(MD_ADCINF1, 10) |
26 PRIORITY_IN(STAUPD, 8) |
27 PRIORITY_IN(GPSINF0, 11),
28
29 PRIORITY_OUT_SEL_2 = PRIORITY_OUT(MD_ADCINF0, 9) |
30 PRIORITY_OUT(MD_ADCINF1, 10) |
31 PRIORITY_OUT(STAUPD, 8) |
32 PRIORITY_OUT(GPSINF0, 11),
33};
34
35#define PENDING_US(x) x
36enum {
37 STARVE_ENABLE = 0x1 << 10,
38 COUNTER0_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x2),
39 COUNTER1_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x3),
40 COUNTER2_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x3),
41 COUNTER3_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x3),
42 COUNTER4_PENDING_THRES = STARVE_ENABLE | PENDING_US(0xf),
43 COUNTER5_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x20),
44 COUNTER6_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x28),
45 COUNTER7_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x28),
46 COUNTER8_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x13),
47 COUNTER9_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x17),
48 COUNTER10_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x17),
49 COUNTER11_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x7c),
50 COUNTER12_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x7c),
51 COUNTER13_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x340),
52 COUNTER16_PENDING_THRES = STARVE_ENABLE | PENDING_US(0x340),
53};
54
55static void pwrap_soft_reset(void)
56{
57 write32(&mt8186_infracfg_ao->infra_globalcon_rst2_set, 0x1);
58 write32(&mt8186_infracfg_ao->infra_globalcon_rst2_clr, 0x1);
59}
60
61static void pwrap_spi_clk_set(void)
62{
63 write32(&mt8186_infracfg_ao->module_sw_cg_0_set, 0x0000000f);
64 write32(&mt8186_infracfg_ao->module_sw_cg_2_set, 0x00000100);
65
66 write32(&mtk_topckgen->clk_cfg_8_clr, 0x00970000);
67 write32(&mtk_topckgen->clk_cfg_8_set, 0x00040000);
68 write32(&mtk_topckgen->clk_cfg_update1, (0x1 << 3));
69
70 write32(&mt8186_infracfg_ao->pmicw_clock_ctrl,
71 read32(&mt8186_infracfg_ao->pmicw_clock_ctrl) & ~(0x1 << 2));
72
73 pwrap_soft_reset();
74
75 write32(&mt8186_infracfg_ao->module_sw_cg_0_clr, 0x0000000f);
76 write32(&mt8186_infracfg_ao->module_sw_cg_2_clr, 0x00000100);
77}
78
79static s32 pwrap_init_dio(u16 dio_en)
80{
81 pwrap_write_nochk(PMIC_DEW_DIO_EN, dio_en);
82
83 if (!wait_us(100,
84 !wait_for_idle_and_sync(read32(&mtk_pwrap->wacs2_rdata))))
85 return -1;
86
87 write32(&mtk_pwrap->dio_en, dio_en);
88 return 0;
89}
90
91static void pwrap_lock_spislvreg(void)
92{
93 pwrap_write_nochk(PMIC_SPISLV_KEY, 0x0);
94}
95
96static void pwrap_initstaupd(void)
97{
98 write32(&mtk_pwrap->staupd_grpen,
99 SIG_PMIC_0 | INT_STA_PMIC_0 | MD_ADC_DATA0 |
100 MD_ADC_DATA1 | GPS_ADC_DATA0 | GPS_ADC_DATA1);
101
102 /* CRC */
103 pwrap_write_nochk(PMIC_DEW_CRC_EN, 0x1);
104 write32(&mtk_pwrap->crc_en, 0x1);
105 write32(&mtk_pwrap->sig_adr, PMIC_DEW_CRC_VAL);
106
107 write32(&mtk_pwrap->eint_sta0_adr, PMIC_CPU_INT_STA);
108
109 /* MD ADC Interface */
110 write32(&mtk_pwrap->md_auxadc_rdata_latest_addr,
111 (PMIC_AUXADC_ADC35 << 16) + PMIC_AUXADC_ADC31);
112 write32(&mtk_pwrap->md_auxadc_rdata_wp_addr,
113 (PMIC_AUXADC_ADC35 << 16) + PMIC_AUXADC_ADC31);
114 for (size_t i = 0; i < 32; i++)
115 write32(&mtk_pwrap->md_auxadc_rdata[i],
116 (PMIC_AUXADC_ADC35 << 16) + PMIC_AUXADC_ADC31);
117
118 write32(&mtk_pwrap->int_gps_auxadc_cmd_addr,
119 (PMIC_AUXADC_RQST1 << 16) + PMIC_AUXADC_RQST0);
120 write32(&mtk_pwrap->int_gps_auxadc_cmd, (GPS_MAIN << 16) + GPS_SUBSYS);
121 write32(&mtk_pwrap->int_gps_auxadc_rdata_addr,
122 (PMIC_AUXADC_ADC32 << 16) + PMIC_AUXADC_ADC17);
123
124 write32(&mtk_pwrap->ext_gps_auxadc_rdata_addr, PMIC_AUXADC_ADC31);
125}
126
127static void pwrap_starve_set(void)
128{
129 write32(&mtk_pwrap->harb_hprio, ARB_PRIORITY);
130 write32(&mtk_pwrap->starv_counter_0, COUNTER0_PENDING_THRES);
131 write32(&mtk_pwrap->starv_counter_1, COUNTER1_PENDING_THRES);
132 write32(&mtk_pwrap->starv_counter_2, COUNTER2_PENDING_THRES);
133 write32(&mtk_pwrap->starv_counter_3, COUNTER3_PENDING_THRES);
134 write32(&mtk_pwrap->starv_counter_4, COUNTER4_PENDING_THRES);
135 write32(&mtk_pwrap->starv_counter_5, COUNTER5_PENDING_THRES);
136 write32(&mtk_pwrap->starv_counter_6, COUNTER6_PENDING_THRES);
137 write32(&mtk_pwrap->starv_counter_7, COUNTER7_PENDING_THRES);
138 write32(&mtk_pwrap->starv_counter_8, COUNTER8_PENDING_THRES);
139 write32(&mtk_pwrap->starv_counter_9, COUNTER9_PENDING_THRES);
140 write32(&mtk_pwrap->starv_counter_10, COUNTER10_PENDING_THRES);
141 write32(&mtk_pwrap->starv_counter_11, COUNTER11_PENDING_THRES);
142 write32(&mtk_pwrap->starv_counter_12, COUNTER12_PENDING_THRES);
143 write32(&mtk_pwrap->starv_counter_13, COUNTER13_PENDING_THRES);
144 write32(&mtk_pwrap->starv_counter_16, COUNTER16_PENDING_THRES);
145}
146
147static void pwrap_enable(void)
148{
149 write32(&mtk_pwrap->hiprio_arb_en, ARB_USER_EN);
150 write32(&mtk_pwrap->wacs0_en, 0x1);
151 write32(&mtk_pwrap->wacs2_en, 0x1);
152 write32(&mtk_pwrap->wacs_p2p_en, 0x1);
153 write32(&mtk_pwrap->wacs_md32_en, 0x1);
154 write32(&mtk_pwrap->staupd_ctrl, STA_PD_98_5_US);
155 write32(&mtk_pwrap->wdt_ctrl, WATCHDOG_TIMER_7_5_MS);
156 write32(&mtk_pwrap->wdt_src_en_0, WDT_MONITOR_ALL);
157 write32(&mtk_pwrap->wdt_src_en_1, WDT_MONITOR_ALL);
158 write32(&mtk_pwrap->timer_ctrl, 0x1);
159 write32(&mtk_pwrap->int0_en, INT0_MONITOR);
160 write32(&mtk_pwrap->int1_en, INT1_MONITOR);
161}
162
163static s32 pwrap_init_sistrobe(void)
164{
165 u16 rdata;
166 int si_sample_ctrl;
167 int test_data[30] = {
168 0x6996, 0x9669, 0x6996, 0x9669, 0x6996, 0x9669, 0x6996,
169 0x9669, 0x6996, 0x9669, 0x5AA5, 0xA55A, 0x5AA5, 0xA55A,
170 0x5AA5, 0xA55A, 0x5AA5, 0xA55A, 0x5AA5, 0xA55A, 0x1B27,
171 0x1B27, 0x1B27, 0x1B27, 0x1B27, 0x1B27, 0x1B27, 0x1B27,
172 0x1B27, 0x1B27};
173
174 for (si_sample_ctrl = 0; si_sample_ctrl < 16; si_sample_ctrl++) {
175 write32(&mtk_pwrap->si_sample_ctrl, si_sample_ctrl << 5);
176
177 pwrap_read_nochk(PMIC_DEW_READ_TEST, &rdata);
178 if (rdata == DEFAULT_VALUE_READ_TEST)
179 break;
180 }
181
182 if (si_sample_ctrl == 16)
183 return E_CLK_EDGE;
184
185 if (si_sample_ctrl == 15)
186 return E_CLK_LAST_SETTING;
187
188 /*
189 * Add the delay time of SPI data from PMIC to align the start boundary
190 * to current sampling clock edge.
191 */
192 for (int si_dly = 0; si_dly < 10; si_dly++) {
193 pwrap_write_nochk(PMIC_RG_SPI_CON2, si_dly);
194
195 int start_boundary_found = 0;
196 for (size_t i = 0; i < 30; i++) {
197 pwrap_write_nochk(PMIC_DEW_WRITE_TEST, test_data[i]);
198 pwrap_read_nochk(PMIC_DEW_WRITE_TEST, &rdata);
199 if ((rdata & 0x7fff) != (test_data[i] & 0x7fff)) {
200 start_boundary_found = 1;
201 break;
202 }
203 }
204 if (start_boundary_found == 1)
205 break;
206 }
207
208 /*
209 * Change the sampling clock edge to the next one which is the middle
210 * of SPI data window.
211 */
212 write32(&mtk_pwrap->si_sample_ctrl, ++si_sample_ctrl << 5);
213
214 /* Read Test */
215 pwrap_read_nochk(PMIC_DEW_READ_TEST, &rdata);
216 if (rdata != DEFAULT_VALUE_READ_TEST) {
217 pwrap_err("rdata = %#x, exp = %#x\n", rdata,
218 DEFAULT_VALUE_READ_TEST);
219 return E_PWR_READ_TEST_FAIL;
220 }
221
222 return 0;
223}
224
225static void pwrap_init_spislv(void)
226{
227 /* Turn on IO filter function */
228 pwrap_write_nochk(PMIC_FILTER_CON0, SPI_FILTER);
229 /* Turn on IO SMT function to improve noise immunity */
230 pwrap_write_nochk(PMIC_SMT_CON1, SPI_SMT);
231 /* Turn off IO pull function for power saving */
232 pwrap_write_nochk(PMIC_GPIO_PULLEN0_CLR, SPI_PULL_DISABLE);
233 /* Enable SPI R/W in suspend mode */
234 pwrap_write_nochk(PMIC_RG_SPI_CON0, 0x1);
235 /* Set PMIC GPIO driving current to 4mA */
236 pwrap_write_nochk(PMIC_DRV_CON1, SPI_DRIVING);
237}
238
239static void pwrap_init_reg_clock(void)
240{
241 write32(&mtk_pwrap->ext_ck_write, 0x1);
242
243 pwrap_write_nochk(PMIC_DEW_RDDMY_NO, DUMMY_READ_CYCLES);
244 write32(&mtk_pwrap->rddmy, DUMMY_READ_CYCLES);
245
246 write32(&mtk_pwrap->cshext_write, 0);
247 write32(&mtk_pwrap->cshext_read, 0);
248 write32(&mtk_pwrap->cslext_write, 0);
249 write32(&mtk_pwrap->cslext_read, 0);
250}
251
252s32 pwrap_init(void)
253{
254 s32 sub_return = 0, sub_return1 = 0;
255 u16 rdata;
256
257 pwrap_spi_clk_set();
258
259 /* Reset spislv */
260 sub_return = pwrap_reset_spislv();
261 if (sub_return != 0) {
262 pwrap_err("reset_spislv fail, ret=%d\n", sub_return);
263 return E_PWR_INIT_RESET_SPI;
264 }
265
266 /* Enable WRAP */
267 write32(&mtk_pwrap->wrap_en, 0x1);
268
269 /* Enable WACS2 */
270 write32(&mtk_pwrap->wacs2_en, 0x1);
271 write32(&mtk_pwrap->hiprio_arb_en, WACS2); /* ONLY WACS2 */
272
273 /* SPI Waveform Configuration */
274 pwrap_init_reg_clock();
275
276 /* SPI Slave Configuration */
277 pwrap_init_spislv();
278
279 /* Enable DIO mode */
280 sub_return = pwrap_init_dio(1);
281 if (sub_return != 0) {
282 pwrap_err("dio test error, ret=%d\n", sub_return);
283 return E_PWR_INIT_DIO;
284 }
285
286 /* Input data calibration flow; */
287 sub_return = pwrap_init_sistrobe();
288 if (sub_return != 0) {
289 pwrap_err("InitSiStrobe fail,ret=%d\n", sub_return);
290 return E_PWR_INIT_SIDLY;
291 }
292
293 /*
294 * Write test using WACS2,
295 * make sure the read/write function ready.
296 */
297 sub_return = pwrap_write_nochk(PMIC_DEW_WRITE_TEST, WRITE_TEST_VALUE);
298 sub_return1 = pwrap_read_nochk(PMIC_DEW_WRITE_TEST, &rdata);
299 if (rdata != WRITE_TEST_VALUE || sub_return || sub_return1) {
300 pwrap_err("write error, rdata=%#x, return=%d, return1=%d\n",
301 rdata, sub_return, sub_return1);
302 return E_PWR_INIT_WRITE_TEST;
303 }
304
305 /*
306 * Status update function initialization
307 * 1. Signature Checking using CRC (CRC 0 only)
308 * 2. EINT update
309 * 3. Read back Auxadc thermal data for GPS
310 */
311 pwrap_initstaupd();
312
313 write32(&mtk_pwrap->priority_user_sel_2, PRIORITY_IN_SEL_2);
314 write32(&mtk_pwrap->arbiter_out_sel_2, PRIORITY_OUT_SEL_2);
315
316 pwrap_starve_set();
317
318 pwrap_enable();
319
320 /* Initialization Done */
321 write32(&mtk_pwrap->init_done0, 0x1);
322 write32(&mtk_pwrap->init_done2, 0x1);
323 write32(&mtk_pwrap->init_done_p2p, 0x1);
324 write32(&mtk_pwrap->init_done_md32, 0x1);
325
326 /* Lock SPISLV Registers */
327 pwrap_lock_spislvreg();
328
329 return 0;
330}