1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2018-2019 NXP
4 *
5 * Brief CAAM Job Rings Hardware Abstration Layer.
6 * Implementation of primitives to access HW
7 */
8 #include <caam_common.h>
9 #include <caam_hal_jr.h>
10 #include <caam_io.h>
11 #include <caam_pwr.h>
12 #include <caam_utils_delay.h>
13 #include <registers/ctrl_regs.h>
14 #include <registers/jr_regs.h>
15
16 #ifdef CFG_NXP_CAAM_RUNTIME_JR
17 /*
18 * List of common JR registers to save/restore
19 */
20 static const struct reglist jr_backup[] = {
21 BACKUP_REG(JRX_IRBAR, 2, 0, 0),
22 BACKUP_REG(JRX_IRSR, 1, 0, 0),
23 BACKUP_REG(JRX_ORBAR, 2, 0, 0),
24 BACKUP_REG(JRX_ORSR, 1, 0, 0),
25 BACKUP_REG(JRX_JRCFGR_LS, 1, 0, 0),
26 };
27 #endif /* CFG_NXP_CAAM_RUNTIME_JR */
28
caam_hal_jr_reset(vaddr_t baseaddr)29 enum caam_status caam_hal_jr_reset(vaddr_t baseaddr)
30 {
31 uint16_t timeout = 10000;
32 uint32_t reg_val = 0;
33
34 /*
35 * Reset is done in 2 steps:
36 * - Flush all pending jobs (Set RESET bit)
37 * - Reset the Job Ring (Set RESET bit second time)
38 */
39
40 /* Mask interrupts to poll for reset completion status */
41 io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK);
42
43 /* Initiate flush (required prior to reset) */
44 io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET);
45
46 do {
47 caam_udelay(100);
48 reg_val = io_caam_read32(baseaddr + JRX_JRINTR);
49 reg_val &= BM_JRX_JRINTR_HALT;
50 } while ((reg_val == JRINTR_HALT_ONGOING) && --timeout);
51
52 if (!timeout || reg_val != JRINTR_HALT_DONE) {
53 EMSG("Failed to flush job ring\n");
54 return CAAM_FAILURE;
55 }
56
57 /* Initiate reset */
58 timeout = 100;
59 io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET);
60 do {
61 caam_udelay(100);
62 reg_val = io_caam_read32(baseaddr + JRX_JRCR);
63 } while ((reg_val & JRX_JRCR_RESET) && --timeout);
64
65 if (!timeout) {
66 EMSG("Failed to reset job ring\n");
67 return CAAM_FAILURE;
68 }
69
70 return CAAM_NO_ERROR;
71 }
72
caam_hal_jr_config(vaddr_t baseaddr,uint8_t nbjobs,uint64_t inrings,uint64_t outrings)73 void caam_hal_jr_config(vaddr_t baseaddr, uint8_t nbjobs, uint64_t inrings,
74 uint64_t outrings)
75 {
76 uint32_t value = 0;
77
78 /* Setup the JR input queue */
79 #if defined(CFG_CAAM_64BIT) && defined(CFG_CAAM_LITTLE_ENDIAN)
80 io_caam_write32(baseaddr + JRX_IRBAR, inrings);
81 io_caam_write32(baseaddr + JRX_IRBAR + 4, inrings >> 32);
82 #else
83 io_caam_write32(baseaddr + JRX_IRBAR, inrings >> 32);
84 io_caam_write32(baseaddr + JRX_IRBAR + 4, inrings);
85 #endif
86 io_caam_write32(baseaddr + JRX_IRSR, nbjobs);
87
88 /* Setup the JR output queue */
89 #if defined(CFG_CAAM_64BIT) && defined(CFG_CAAM_LITTLE_ENDIAN)
90 io_caam_write32(baseaddr + JRX_ORBAR, outrings);
91 io_caam_write32(baseaddr + JRX_ORBAR + 4, outrings >> 32);
92 #else
93 io_caam_write32(baseaddr + JRX_ORBAR, outrings >> 32);
94 io_caam_write32(baseaddr + JRX_ORBAR + 4, outrings);
95 #endif
96 io_caam_write32(baseaddr + JRX_ORSR, nbjobs);
97
98 /* Disable the JR interrupt */
99 caam_hal_jr_disable_itr(baseaddr);
100
101 /*
102 * Configure interrupt and disable it:
103 * Optimization to generate an interrupt either when there are
104 * half of the job done
105 * or when there is a job done and 10 clock cycles elapsed without
106 * new job completion
107 */
108 value = JRX_JRCFGR_LS_ICTT(10);
109 value |= JRX_JRCFGR_LS_ICDCT(nbjobs / 2);
110 value |= JRX_JRCFGR_LS_ICEN;
111 value |= JRX_JRCFGR_LS_IMSK;
112 io_caam_write32(baseaddr + JRX_JRCFGR_LS, value);
113
114 #ifdef CFG_NXP_CAAM_RUNTIME_JR
115 caam_pwr_add_backup(baseaddr, jr_backup, ARRAY_SIZE(jr_backup));
116 #endif
117 }
118
caam_hal_jr_read_nbslot_available(vaddr_t baseaddr)119 uint32_t caam_hal_jr_read_nbslot_available(vaddr_t baseaddr)
120 {
121 return io_caam_read32(baseaddr + JRX_IRSAR);
122 }
123
caam_hal_jr_add_newjob(vaddr_t baseaddr)124 void caam_hal_jr_add_newjob(vaddr_t baseaddr)
125 {
126 io_caam_write32(baseaddr + JRX_IRJAR, 1);
127 }
128
caam_hal_jr_get_nbjob_done(vaddr_t baseaddr)129 uint32_t caam_hal_jr_get_nbjob_done(vaddr_t baseaddr)
130 {
131 return io_caam_read32(baseaddr + JRX_ORSFR);
132 }
133
caam_hal_jr_del_job(vaddr_t baseaddr)134 void caam_hal_jr_del_job(vaddr_t baseaddr)
135 {
136 io_caam_write32(baseaddr + JRX_ORJRR, 1);
137 }
138
139 #ifdef CFG_CAAM_ITR
caam_hal_jr_disable_itr(vaddr_t baseaddr)140 void caam_hal_jr_disable_itr(vaddr_t baseaddr)
141 {
142 io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK);
143 io_setbits32(baseaddr + JRX_JRINTR, JRX_JRINTR_JRI);
144 }
145
caam_hal_jr_enable_itr(vaddr_t baseaddr)146 void caam_hal_jr_enable_itr(vaddr_t baseaddr)
147 {
148 io_mask32(baseaddr + JRX_JRCFGR_LS, ~JRX_JRCFGR_LS_IMSK,
149 JRX_JRCFGR_LS_IMSK);
150 }
151 #else
caam_hal_jr_disable_itr(vaddr_t baseaddr __unused)152 void caam_hal_jr_disable_itr(vaddr_t baseaddr __unused) {}
caam_hal_jr_enable_itr(vaddr_t baseaddr __unused)153 void caam_hal_jr_enable_itr(vaddr_t baseaddr __unused) {}
154 #endif /* CFG_CAAM_ITR */
155
caam_hal_jr_check_ack_itr(vaddr_t baseaddr)156 bool caam_hal_jr_check_ack_itr(vaddr_t baseaddr)
157 {
158 uint32_t val = 0;
159
160 val = io_caam_read32(baseaddr + JRX_JRINTR);
161
162 if ((val & JRX_JRINTR_JRI) == JRX_JRINTR_JRI) {
163 /* Acknowledge interrupt */
164 io_setbits32(baseaddr + JRX_JRINTR, JRX_JRINTR_JRI);
165 return true;
166 }
167
168 return false;
169 }
170
caam_hal_jr_halt(vaddr_t baseaddr)171 enum caam_status caam_hal_jr_halt(vaddr_t baseaddr)
172 {
173 uint16_t timeout = 10000;
174 uint32_t val = 0;
175
176 /* Mask interrupts to poll for completion status */
177 io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK);
178
179 /* Request Job ring halt */
180 io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_PARK);
181
182 /* Check if there is a job running */
183 val = io_caam_read32(baseaddr + JRX_IRSR);
184 if ((caam_hal_jr_read_nbslot_available(baseaddr) == val) &&
185 (io_caam_read32(baseaddr + JRX_CSTA) != JRX_CSTA_BSY))
186 return CAAM_NO_ERROR;
187
188 /* Wait until all jobs complete */
189 do {
190 caam_udelay(10);
191 val = io_caam_read32(baseaddr + JRX_JRINTR);
192 val &= BM_JRX_JRINTR_HALT;
193 } while ((val != JRINTR_HALT_DONE) && --timeout);
194
195 if (!timeout)
196 return CAAM_BUSY;
197
198 return CAAM_NO_ERROR;
199 }
200
caam_hal_jr_flush(vaddr_t baseaddr)201 enum caam_status caam_hal_jr_flush(vaddr_t baseaddr)
202 {
203 uint16_t timeout = 10000;
204 uint32_t val = 0;
205
206 /* Mask interrupts to poll for completion status */
207 io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK);
208
209 /* Request Job ring to flush input queue */
210 io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET);
211
212 /* Check if there is a job running */
213 val = io_caam_read32(baseaddr + JRX_IRSR);
214 if ((caam_hal_jr_read_nbslot_available(baseaddr) == val) &&
215 (io_caam_read32(baseaddr + JRX_CSTA) != JRX_CSTA_BSY))
216 return CAAM_NO_ERROR;
217
218 /* Wait until all jobs complete */
219 do {
220 caam_udelay(10);
221 val = io_caam_read32(baseaddr + JRX_JRINTR);
222 val &= BM_JRX_JRINTR_HALT;
223 } while ((val == JRINTR_HALT_ONGOING) && --timeout);
224
225 if (!timeout)
226 return CAAM_BUSY;
227
228 return CAAM_NO_ERROR;
229 }
230
caam_hal_jr_resume(vaddr_t baseaddr)231 void caam_hal_jr_resume(vaddr_t baseaddr)
232 {
233 io_caam_write32(baseaddr + JRX_JRINTR, JRINTR_HALT_RESUME);
234
235 caam_hal_jr_enable_itr(baseaddr);
236 }
237
caam_hal_jr_input_index(vaddr_t baseaddr)238 uint8_t caam_hal_jr_input_index(vaddr_t baseaddr)
239 {
240 return io_caam_read32(baseaddr + JRX_IRRIR) >> 2;
241 }
242
caam_hal_jr_output_index(vaddr_t baseaddr)243 uint8_t caam_hal_jr_output_index(vaddr_t baseaddr)
244 {
245 return io_caam_read32(baseaddr + JRX_ORWIR) >> 3;
246 }
247