1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3 * Cadence DDR Driver
4 *
5 * Copyright (C) 2012-2026 Cadence Design Systems, Inc.
6 * Copyright (C) 2018-2026 Texas Instruments Incorporated - https://www.ti.com/
7 */
8
9 #include <errno.h>
10
11 #include <lib/utils_def.h>
12
13 #include "cps_drv_lpddr4.h"
14 #include "lpddr4.h"
15 #include "lpddr4_ctl_regs.h"
16 #include "lpddr4_if.h"
17 #include "lpddr4_structs_if.h"
18
19 #define LPDDR4_INT_STATUS_MASTER_MASK GENMASK(31, 31)
20
21 struct ctlint_entry {
22 uint8_t grp_shift;
23 uint8_t int_shift;
24 };
25
26 static const struct ctlint_entry ctlintmap[] = {
27 [LPDDR4_INTR_TIMEOUT_ZQ_CAL_INIT] = { 0, 7 },
28 [LPDDR4_INTR_TIMEOUT_ZQ_CALLATCH] = { 0, 8 },
29 [LPDDR4_INTR_TIMEOUT_ZQ_CALSTART] = { 0, 9 },
30 [LPDDR4_INTR_TIMEOUT_MRR_TEMP] = { 0, 14 },
31 [LPDDR4_INTR_TIMEOUT_DQS_OSC_REQ] = { 0, 15 },
32 [LPDDR4_INTR_TIMEOUT_DFI_UPDATE] = { 0, 16 },
33 [LPDDR4_INTR_TIMEOUT_LP_WAKEUP] = { 0, 17 },
34 [LPDDR4_INTR_TIMEOUT_AUTO_REFRESH_MAX] = { 0, 19 },
35 [LPDDR4_INTR_ECC_ERROR] = { 1, 0 },
36 [LPDDR4_INTR_LP_DONE] = { 2, 0 },
37 [LPDDR4_INTR_LP_TIMEOUT] = { 2, 3 },
38 [LPDDR4_INTR_PORT_TIMEOUT] = { 3, 0 },
39 [LPDDR4_INTR_RFIFO_TIMEOUT] = { 4, 0 },
40 [LPDDR4_INTR_TRAINING_ZQ_STATUS] = { 5, 11 },
41 [LPDDR4_INTR_TRAINING_DQS_OSC_DONE] = { 5, 12 },
42 [LPDDR4_INTR_TRAINING_DQS_OSC_UPDATE_DONE] = { 5, 13 },
43 [LPDDR4_INTR_TRAINING_DQS_OSC_OVERFLOW] = { 5, 14 },
44 [LPDDR4_INTR_TRAINING_DQS_OSC_VAR_OUT] = { 5, 15 },
45 [LPDDR4_INTR_USERIF_OUTSIDE_MEM_ACCESS] = { 6, 0 },
46 [LPDDR4_INTR_USERIF_MULTI_OUTSIDE_MEM_ACCESS] = { 6, 1 },
47 [LPDDR4_INTR_USERIF_PORT_CMD_ERROR] = { 6, 2 },
48 [LPDDR4_INTR_USERIF_WRAP] = { 6, 6 },
49 [LPDDR4_INTR_USERIF_INVAL_SETTING] = { 6, 7 },
50 [LPDDR4_INTR_MISC_MRR_TRAFFIC] = { 7, 3 },
51 [LPDDR4_INTR_MISC_SW_REQ_MODE] = { 7, 4 },
52 [LPDDR4_INTR_MISC_CHANGE_TEMP_REFRESH] = { 7, 5 },
53 [LPDDR4_INTR_MISC_TEMP_ALERT] = { 7, 6 },
54 [LPDDR4_INTR_MISC_REFRESH_STATUS] = { 7, 7 },
55 [LPDDR4_INTR_BIST_DONE] = { 8, 0 },
56 [LPDDR4_INTR_CRC] = { 9, 0 },
57 [LPDDR4_INTR_DFI_UPDATE_ERROR] = { 10, 0 },
58 [LPDDR4_INTR_DFI_PHY_ERROR] = { 10, 1 },
59 [LPDDR4_INTR_DFI_BUS_ERROR] = { 10, 2 },
60 [LPDDR4_INTR_DFI_STATE_CHANGE] = { 10, 3 },
61 [LPDDR4_INTR_DFI_DLL_SYNC_DONE] = { 10, 4 },
62 [LPDDR4_INTR_DFI_TIMEOUT] = { 10, 5 },
63 [LPDDR4_INTR_DIMM] = { 11, 0 },
64 [LPDDR4_INTR_FREQ_DFS_REQ_HW_IGNORE] = { 12, 0 },
65 [LPDDR4_INTR_FREQ_DFS_HW_TERMINATE] = { 12, 1 },
66 [LPDDR4_INTR_FREQ_DFS_HW_DONE] = { 12, 2 },
67 [LPDDR4_INTR_FREQ_DFS_REQ_SW_IGNORE] = { 12, 3 },
68 [LPDDR4_INTR_FREQ_DFS_SW_TERMINATE] = { 12, 4 },
69 [LPDDR4_INTR_FREQ_DFS_SW_DONE] = { 12, 5 },
70 [LPDDR4_INTR_INIT_MEM_RESET_DONE] = { 13, 0 },
71 [LPDDR4_INTR_MC_INIT_DONE] = { 13, 1 },
72 [LPDDR4_INTR_INIT_POWER_ON_STATE] = { 13, 3 },
73 [LPDDR4_INTR_MRR_ERROR] = { 14, 0 },
74 [LPDDR4_INTR_MR_READ_DONE] = { 14, 2 },
75 [LPDDR4_INTR_MR_WRITE_DONE] = { 14, 3 },
76 [LPDDR4_INTR_PARITY_ERROR] = { 15, 2 },
77 [LPDDR4_INTR_LOR_BITS] = { 16, 0 },
78 };
79
ti_lpddr4_enable_pi_initiator(const ti_lpddr4_privatedata * pd)80 void ti_lpddr4_enable_pi_initiator(const ti_lpddr4_privatedata *pd)
81 {
82 uint32_t regval = 0U;
83
84 lpddr4_ctlregs *ctlregbase = pd->ctlbase;
85
86 regval = CPS_FLD_SET(TI_LPDDR4__PI_NORMAL_LVL_SEQ__FLD,
87 ctlregbase->TI_LPDDR4__PI_NORMAL_LVL_SEQ__REG);
88 ctlregbase->TI_LPDDR4__PI_NORMAL_LVL_SEQ__REG = regval;
89 regval = CPS_FLD_SET(TI_LPDDR4__PI_INIT_LVL_EN__FLD,
90 ctlregbase->TI_LPDDR4__PI_INIT_LVL_EN__REG);
91 ctlregbase->TI_LPDDR4__PI_INIT_LVL_EN__REG = regval;
92 }
93
ti_lpddr4_checkctlinterrupt(const ti_lpddr4_privatedata * pd,ti_lpddr4_intr_ctlinterrupt intr,bool * irqstatus)94 uint32_t ti_lpddr4_checkctlinterrupt(const ti_lpddr4_privatedata *pd,
95 ti_lpddr4_intr_ctlinterrupt intr,
96 bool *irqstatus)
97 {
98 uint32_t result;
99 uint32_t ctlmasterirqstatus = 0U;
100 uint32_t ctlgrpirqstatus = 0U;
101 uint32_t ctlmasterintflag = 0U;
102
103 result = ti_lpddr4_intr_ctlint_sf(pd, intr, irqstatus);
104 if (result != 0U) {
105 return result;
106 }
107
108 lpddr4_ctlregs *ctlregbase = pd->ctlbase;
109
110 ctlmasterirqstatus =
111 (ctlregbase->TI_LPDDR4__INT_STATUS_MASTER__REG &
112 (~LPDDR4_INT_STATUS_MASTER_MASK));
113
114 switch (intr) {
115 case LPDDR4_INTR_TIMEOUT_ZQ_CAL_INIT:
116 case LPDDR4_INTR_TIMEOUT_ZQ_CALLATCH:
117 case LPDDR4_INTR_TIMEOUT_ZQ_CALSTART:
118 case LPDDR4_INTR_TIMEOUT_MRR_TEMP:
119 case LPDDR4_INTR_TIMEOUT_DQS_OSC_REQ:
120 case LPDDR4_INTR_TIMEOUT_DFI_UPDATE:
121 case LPDDR4_INTR_TIMEOUT_LP_WAKEUP:
122 case LPDDR4_INTR_TIMEOUT_AUTO_REFRESH_MAX:
123 ctlgrpirqstatus = ctlregbase->TI_LPDDR4__INT_STATUS_TIMEOUT__REG;
124 break;
125 case LPDDR4_INTR_LP_DONE:
126 case LPDDR4_INTR_LP_TIMEOUT:
127 ctlgrpirqstatus = CPS_FLD_READ(TI_LPDDR4__INT_STATUS_LOWPOWER__FLD,
128 ctlregbase->TI_LPDDR4__INT_STATUS_LOWPOWER__REG);
129 break;
130 case LPDDR4_INTR_TRAINING_ZQ_STATUS:
131 case LPDDR4_INTR_TRAINING_DQS_OSC_DONE:
132 case LPDDR4_INTR_TRAINING_DQS_OSC_UPDATE_DONE:
133 case LPDDR4_INTR_TRAINING_DQS_OSC_OVERFLOW:
134 case LPDDR4_INTR_TRAINING_DQS_OSC_VAR_OUT:
135 ctlgrpirqstatus = ctlregbase->TI_LPDDR4__INT_STATUS_TRAINING__REG;
136 break;
137 case LPDDR4_INTR_USERIF_OUTSIDE_MEM_ACCESS:
138 case LPDDR4_INTR_USERIF_MULTI_OUTSIDE_MEM_ACCESS:
139 case LPDDR4_INTR_USERIF_PORT_CMD_ERROR:
140 case LPDDR4_INTR_USERIF_WRAP:
141 case LPDDR4_INTR_USERIF_INVAL_SETTING:
142 ctlgrpirqstatus = ctlregbase->TI_LPDDR4__INT_STATUS_USERIF__REG;
143 break;
144 case LPDDR4_INTR_MISC_MRR_TRAFFIC:
145 case LPDDR4_INTR_MISC_SW_REQ_MODE:
146 case LPDDR4_INTR_MISC_CHANGE_TEMP_REFRESH:
147 case LPDDR4_INTR_MISC_TEMP_ALERT:
148 case LPDDR4_INTR_MISC_REFRESH_STATUS:
149 ctlgrpirqstatus = CPS_FLD_READ(TI_LPDDR4__INT_STATUS_MISC__FLD,
150 ctlregbase->TI_LPDDR4__INT_STATUS_MISC__REG);
151 break;
152 case LPDDR4_INTR_BIST_DONE:
153 ctlgrpirqstatus = CPS_FLD_READ(TI_LPDDR4__INT_STATUS_BIST__FLD,
154 ctlregbase->TI_LPDDR4__INT_STATUS_BIST__REG);
155 break;
156 case LPDDR4_INTR_DFI_UPDATE_ERROR:
157 case LPDDR4_INTR_DFI_PHY_ERROR:
158 case LPDDR4_INTR_DFI_BUS_ERROR:
159 case LPDDR4_INTR_DFI_STATE_CHANGE:
160 case LPDDR4_INTR_DFI_DLL_SYNC_DONE:
161 case LPDDR4_INTR_DFI_TIMEOUT:
162 ctlgrpirqstatus = CPS_FLD_READ(TI_LPDDR4__INT_STATUS_DFI__FLD,
163 ctlregbase->TI_LPDDR4__INT_STATUS_DFI__REG);
164 break;
165 case LPDDR4_INTR_FREQ_DFS_REQ_HW_IGNORE:
166 case LPDDR4_INTR_FREQ_DFS_HW_TERMINATE:
167 case LPDDR4_INTR_FREQ_DFS_HW_DONE:
168 case LPDDR4_INTR_FREQ_DFS_REQ_SW_IGNORE:
169 case LPDDR4_INTR_FREQ_DFS_SW_TERMINATE:
170 case LPDDR4_INTR_FREQ_DFS_SW_DONE:
171 ctlgrpirqstatus = CPS_FLD_READ(TI_LPDDR4__INT_STATUS_FREQ__FLD,
172 ctlregbase->TI_LPDDR4__INT_STATUS_FREQ__REG);
173 break;
174 case LPDDR4_INTR_INIT_MEM_RESET_DONE:
175 case LPDDR4_INTR_MC_INIT_DONE:
176 case LPDDR4_INTR_INIT_POWER_ON_STATE:
177 ctlgrpirqstatus = CPS_FLD_READ(TI_LPDDR4__INT_STATUS_INIT__FLD,
178 ctlregbase->TI_LPDDR4__INT_STATUS_INIT__REG);
179 break;
180 case LPDDR4_INTR_MRR_ERROR:
181 case LPDDR4_INTR_MR_READ_DONE:
182 case LPDDR4_INTR_MR_WRITE_DONE:
183 ctlgrpirqstatus = ctlregbase->TI_LPDDR4__INT_STATUS_MODE__REG;
184 break;
185 case LPDDR4_INTR_PARITY_ERROR:
186 ctlgrpirqstatus = CPS_FLD_READ(TI_LPDDR4__INT_STATUS_PARITY__FLD,
187 ctlregbase->TI_LPDDR4__INT_STATUS_PARITY__REG);
188 break;
189 default:
190 ctlmasterintflag = 1U;
191 break;
192 }
193
194 if ((ctlintmap[intr].int_shift < TI_WORD_SHIFT) &&
195 (ctlintmap[intr].grp_shift < TI_WORD_SHIFT)) {
196 if ((((ctlmasterirqstatus >> ctlintmap[intr].grp_shift) &
197 TI_LPDDR4_BIT_MASK) > 0U) &&
198 (((ctlgrpirqstatus >> ctlintmap[intr].int_shift) &
199 TI_LPDDR4_BIT_MASK) > 0U) &&
200 (ctlmasterintflag == 0U))
201 *irqstatus = true;
202 else if ((((ctlmasterirqstatus >> ctlintmap[intr].grp_shift) &
203 TI_LPDDR4_BIT_MASK) > 0U) &&
204 (ctlmasterintflag == 1U))
205 *irqstatus = true;
206 else
207 *irqstatus = false;
208 }
209
210 return result;
211 }
212
ti_lpddr4_ackctlinterrupt(const ti_lpddr4_privatedata * pd,ti_lpddr4_intr_ctlinterrupt intr)213 uint32_t ti_lpddr4_ackctlinterrupt(const ti_lpddr4_privatedata *pd,
214 ti_lpddr4_intr_ctlinterrupt intr)
215 {
216 uint32_t result;
217 uint32_t regval = 0U;
218 lpddr4_ctlregs *ctlregbase;
219
220 result = ti_lpddr4_intr_ack_ctlint_sf(pd, intr);
221 if (result != 0U) {
222 return result;
223 }
224 if (ctlintmap[intr].int_shift >= TI_WORD_SHIFT) {
225 return result;
226 }
227
228 ctlregbase = pd->ctlbase;
229
230 switch (intr) {
231 case LPDDR4_INTR_TIMEOUT_ZQ_CAL_INIT:
232 case LPDDR4_INTR_TIMEOUT_ZQ_CALLATCH:
233 case LPDDR4_INTR_TIMEOUT_ZQ_CALSTART:
234 case LPDDR4_INTR_TIMEOUT_MRR_TEMP:
235 case LPDDR4_INTR_TIMEOUT_DQS_OSC_REQ:
236 case LPDDR4_INTR_TIMEOUT_DFI_UPDATE:
237 case LPDDR4_INTR_TIMEOUT_LP_WAKEUP:
238 case LPDDR4_INTR_TIMEOUT_AUTO_REFRESH_MAX:
239 ctlregbase->TI_LPDDR4__INT_ACK_TIMEOUT__REG =
240 TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift;
241 break;
242 case LPDDR4_INTR_LP_DONE:
243 case LPDDR4_INTR_LP_TIMEOUT:
244 regval = CPS_FLD_WRITE(TI_LPDDR4__INT_ACK_LOWPOWER__FLD,
245 ctlregbase->TI_LPDDR4__INT_ACK_LOWPOWER__REG,
246 (TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift));
247 ctlregbase->TI_LPDDR4__INT_ACK_LOWPOWER__REG = regval;
248 break;
249 case LPDDR4_INTR_TRAINING_ZQ_STATUS:
250 case LPDDR4_INTR_TRAINING_DQS_OSC_DONE:
251 case LPDDR4_INTR_TRAINING_DQS_OSC_UPDATE_DONE:
252 case LPDDR4_INTR_TRAINING_DQS_OSC_OVERFLOW:
253 case LPDDR4_INTR_TRAINING_DQS_OSC_VAR_OUT:
254 ctlregbase->TI_LPDDR4__INT_ACK_TRAINING__REG =
255 TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift;
256 break;
257 case LPDDR4_INTR_USERIF_OUTSIDE_MEM_ACCESS:
258 case LPDDR4_INTR_USERIF_MULTI_OUTSIDE_MEM_ACCESS:
259 case LPDDR4_INTR_USERIF_PORT_CMD_ERROR:
260 case LPDDR4_INTR_USERIF_WRAP:
261 case LPDDR4_INTR_USERIF_INVAL_SETTING:
262 ctlregbase->TI_LPDDR4__INT_ACK_USERIF__REG =
263 TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift;
264 break;
265 case LPDDR4_INTR_MISC_MRR_TRAFFIC:
266 case LPDDR4_INTR_MISC_SW_REQ_MODE:
267 case LPDDR4_INTR_MISC_CHANGE_TEMP_REFRESH:
268 case LPDDR4_INTR_MISC_TEMP_ALERT:
269 case LPDDR4_INTR_MISC_REFRESH_STATUS:
270 ctlregbase->TI_LPDDR4__INT_ACK_MISC__REG =
271 TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift;
272 break;
273 case LPDDR4_INTR_BIST_DONE:
274 regval = CPS_FLD_WRITE(TI_LPDDR4__INT_ACK_BIST__FLD,
275 ctlregbase->TI_LPDDR4__INT_ACK_BIST__REG,
276 TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift);
277 ctlregbase->TI_LPDDR4__INT_ACK_BIST__REG = regval;
278 break;
279 case LPDDR4_INTR_DFI_UPDATE_ERROR:
280 case LPDDR4_INTR_DFI_PHY_ERROR:
281 case LPDDR4_INTR_DFI_BUS_ERROR:
282 case LPDDR4_INTR_DFI_STATE_CHANGE:
283 case LPDDR4_INTR_DFI_DLL_SYNC_DONE:
284 case LPDDR4_INTR_DFI_TIMEOUT:
285 ctlregbase->TI_LPDDR4__INT_ACK_DFI__REG =
286 TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift;
287 break;
288 case LPDDR4_INTR_FREQ_DFS_REQ_HW_IGNORE:
289 case LPDDR4_INTR_FREQ_DFS_HW_TERMINATE:
290 case LPDDR4_INTR_FREQ_DFS_HW_DONE:
291 case LPDDR4_INTR_FREQ_DFS_REQ_SW_IGNORE:
292 case LPDDR4_INTR_FREQ_DFS_SW_TERMINATE:
293 case LPDDR4_INTR_FREQ_DFS_SW_DONE:
294 regval = CPS_FLD_WRITE(TI_LPDDR4__INT_ACK_FREQ__FLD,
295 ctlregbase->TI_LPDDR4__INT_ACK_FREQ__REG,
296 (TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift));
297 ctlregbase->TI_LPDDR4__INT_ACK_FREQ__REG = regval;
298 break;
299 case LPDDR4_INTR_INIT_MEM_RESET_DONE:
300 case LPDDR4_INTR_MC_INIT_DONE:
301 case LPDDR4_INTR_INIT_POWER_ON_STATE:
302 regval = CPS_FLD_WRITE(TI_LPDDR4__INT_ACK_INIT__FLD,
303 ctlregbase->TI_LPDDR4__INT_ACK_INIT__REG,
304 (TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift));
305 ctlregbase->TI_LPDDR4__INT_ACK_INIT__REG = regval;
306 break;
307 case LPDDR4_INTR_MRR_ERROR:
308 case LPDDR4_INTR_MR_READ_DONE:
309 case LPDDR4_INTR_MR_WRITE_DONE:
310 ctlregbase->TI_LPDDR4__INT_ACK_MODE__REG =
311 TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift;
312 break;
313 case LPDDR4_INTR_PARITY_ERROR:
314 regval = CPS_FLD_WRITE(TI_LPDDR4__INT_ACK_PARITY__FLD,
315 ctlregbase->TI_LPDDR4__INT_ACK_PARITY__REG,
316 TI_LPDDR4_BIT_MASK << ctlintmap[intr].int_shift);
317 ctlregbase->TI_LPDDR4__INT_ACK_PARITY__REG = regval;
318 break;
319 default:
320 break;
321 }
322
323 return result;
324 }
325