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_NO_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_NO_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