]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/crypto/fsl/jr.c
a107e6afcbb8eec10ef4ae0f5ac74df1f2e30c11
[karo-tx-uboot.git] / drivers / crypto / fsl / jr.c
1 /*
2  * Copyright 2008-2014 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  *
6  * Based on CAAM driver in drivers/crypto/caam in Linux
7  */
8
9 #include <common.h>
10 #include <malloc.h>
11 #include "fsl_sec.h"
12 #include "jr.h"
13
14 #define CIRC_CNT(head, tail, size)      (((head) - (tail)) & (size - 1))
15 #define CIRC_SPACE(head, tail, size)    CIRC_CNT((tail), (head) + 1, (size))
16
17 struct jobring jr;
18
19 static inline void start_jr0(void)
20 {
21         ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
22         u32 ctpr_ms = sec_in32(&sec->ctpr_ms);
23         u32 scfgr = sec_in32(&sec->scfgr);
24
25         if (ctpr_ms & SEC_CTPR_MS_VIRT_EN_INCL) {
26                 /* VIRT_EN_INCL = 1 & VIRT_EN_POR = 1 or
27                  * VIRT_EN_INCL = 1 & VIRT_EN_POR = 0 & SEC_SCFGR_VIRT_EN = 1
28                  */
29                 if ((ctpr_ms & SEC_CTPR_MS_VIRT_EN_POR) ||
30                     (!(ctpr_ms & SEC_CTPR_MS_VIRT_EN_POR) &&
31                                         (scfgr & SEC_SCFGR_VIRT_EN)))
32                         sec_out32(&sec->jrstartr, CONFIG_JRSTARTR_JR0);
33         } else {
34                 /* VIRT_EN_INCL = 0 && VIRT_EN_POR_VALUE = 1 */
35                 if (ctpr_ms & SEC_CTPR_MS_VIRT_EN_POR)
36                         sec_out32(&sec->jrstartr, CONFIG_JRSTARTR_JR0);
37         }
38 }
39
40 static inline void jr_reset_liodn(void)
41 {
42         ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
43         sec_out32(&sec->jrliodnr[0].ls, 0);
44 }
45
46 static inline void jr_disable_irq(void)
47 {
48         struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
49         uint32_t jrcfg = sec_in32(&regs->jrcfg1);
50
51         jrcfg = jrcfg | JR_INTMASK;
52
53         sec_out32(&regs->jrcfg1, jrcfg);
54 }
55
56 static void jr_initregs(void)
57 {
58         struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
59         phys_addr_t ip_base = virt_to_phys((void *)jr.input_ring);
60         phys_addr_t op_base = virt_to_phys((void *)jr.output_ring);
61
62 #ifdef CONFIG_PHYS_64BIT
63         sec_out32(&regs->irba_h, ip_base >> 32);
64 #else
65         sec_out32(&regs->irba_h, 0x0);
66 #endif
67         sec_out32(&regs->irba_l, (uint32_t)ip_base);
68 #ifdef CONFIG_PHYS_64BIT
69         sec_out32(&regs->orba_h, op_base >> 32);
70 #else
71         sec_out32(&regs->orba_h, 0x0);
72 #endif
73         sec_out32(&regs->orba_l, (uint32_t)op_base);
74         sec_out32(&regs->ors, JR_SIZE);
75         sec_out32(&regs->irs, JR_SIZE);
76
77         if (!jr.irq)
78                 jr_disable_irq();
79 }
80
81 static int jr_init(void)
82 {
83         memset(&jr, 0, sizeof(struct jobring));
84
85         jr.jq_id = DEFAULT_JR_ID;
86         jr.irq = DEFAULT_IRQ;
87
88 #ifdef CONFIG_FSL_CORENET
89         jr.liodn = DEFAULT_JR_LIODN;
90 #endif
91         jr.size = JR_SIZE;
92         jr.input_ring = (dma_addr_t *)malloc(JR_SIZE * sizeof(dma_addr_t));
93         if (!jr.input_ring)
94                 return -1;
95         jr.output_ring =
96             (struct op_ring *)malloc(JR_SIZE * sizeof(struct op_ring));
97         if (!jr.output_ring)
98                 return -1;
99
100         memset(jr.input_ring, 0, JR_SIZE * sizeof(dma_addr_t));
101         memset(jr.output_ring, 0, JR_SIZE * sizeof(struct op_ring));
102
103         start_jr0();
104
105         jr_initregs();
106
107         return 0;
108 }
109
110 static int jr_sw_cleanup(void)
111 {
112         jr.head = 0;
113         jr.tail = 0;
114         jr.read_idx = 0;
115         jr.write_idx = 0;
116         memset(jr.info, 0, sizeof(jr.info));
117         memset(jr.input_ring, 0, jr.size * sizeof(dma_addr_t));
118         memset(jr.output_ring, 0, jr.size * sizeof(struct op_ring));
119
120         return 0;
121 }
122
123 static int jr_hw_reset(void)
124 {
125         struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
126         uint32_t timeout = 100000;
127         uint32_t jrint, jrcr;
128
129         sec_out32(&regs->jrcr, JRCR_RESET);
130         do {
131                 jrint = sec_in32(&regs->jrint);
132         } while (((jrint & JRINT_ERR_HALT_MASK) ==
133                   JRINT_ERR_HALT_INPROGRESS) && --timeout);
134
135         jrint = sec_in32(&regs->jrint);
136         if (((jrint & JRINT_ERR_HALT_MASK) !=
137              JRINT_ERR_HALT_INPROGRESS) && timeout == 0)
138                 return -1;
139
140         timeout = 100000;
141         sec_out32(&regs->jrcr, JRCR_RESET);
142         do {
143                 jrcr = sec_in32(&regs->jrcr);
144         } while ((jrcr & JRCR_RESET) && --timeout);
145
146         if (timeout == 0)
147                 return -1;
148
149         return 0;
150 }
151
152 /* -1 --- error, can't enqueue -- no space available */
153 static int jr_enqueue(uint32_t *desc_addr,
154                void (*callback)(uint32_t desc, uint32_t status, void *arg),
155                void *arg)
156 {
157         struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
158         int head = jr.head;
159         dma_addr_t desc_phys_addr = virt_to_phys(desc_addr);
160
161         if (sec_in32(&regs->irsa) == 0 ||
162             CIRC_SPACE(jr.head, jr.tail, jr.size) <= 0)
163                 return -1;
164
165         jr.input_ring[head] = desc_phys_addr;
166         jr.info[head].desc_phys_addr = desc_phys_addr;
167         jr.info[head].desc_addr = (uint32_t)desc_addr;
168         jr.info[head].callback = (void *)callback;
169         jr.info[head].arg = arg;
170         jr.info[head].op_done = 0;
171
172         jr.head = (head + 1) & (jr.size - 1);
173
174         sec_out32(&regs->irja, 1);
175
176         return 0;
177 }
178
179 static int jr_dequeue(void)
180 {
181         struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
182         int head = jr.head;
183         int tail = jr.tail;
184         int idx, i, found;
185         void (*callback)(uint32_t desc, uint32_t status, void *arg);
186         void *arg = NULL;
187
188         while (sec_in32(&regs->orsf) && CIRC_CNT(jr.head, jr.tail, jr.size)) {
189                 found = 0;
190
191                 dma_addr_t op_desc = jr.output_ring[jr.tail].desc;
192                 uint32_t status = jr.output_ring[jr.tail].status;
193                 uint32_t desc_virt;
194
195                 for (i = 0; CIRC_CNT(head, tail + i, jr.size) >= 1; i++) {
196                         idx = (tail + i) & (jr.size - 1);
197                         if (op_desc == jr.info[idx].desc_phys_addr) {
198                                 desc_virt = jr.info[idx].desc_addr;
199                                 found = 1;
200                                 break;
201                         }
202                 }
203
204                 /* Error condition if match not found */
205                 if (!found)
206                         return -1;
207
208                 jr.info[idx].op_done = 1;
209                 callback = (void *)jr.info[idx].callback;
210                 arg = jr.info[idx].arg;
211
212                 /* When the job on tail idx gets done, increment
213                  * tail till the point where job completed out of oredr has
214                  * been taken into account
215                  */
216                 if (idx == tail)
217                         do {
218                                 tail = (tail + 1) & (jr.size - 1);
219                         } while (jr.info[tail].op_done);
220
221                 jr.tail = tail;
222                 jr.read_idx = (jr.read_idx + 1) & (jr.size - 1);
223
224                 sec_out32(&regs->orjr, 1);
225                 jr.info[idx].op_done = 0;
226
227                 callback(desc_virt, status, arg);
228         }
229
230         return 0;
231 }
232
233 static void desc_done(uint32_t desc, uint32_t status, void *arg)
234 {
235         struct result *x = arg;
236         x->status = status;
237         caam_jr_strstatus(status);
238         x->done = 1;
239 }
240
241 int run_descriptor_jr(uint32_t *desc)
242 {
243         unsigned long long timeval = get_ticks();
244         unsigned long long timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
245         struct result op;
246         int ret = 0;
247
248         memset(&op, sizeof(op), 0);
249
250         ret = jr_enqueue(desc, desc_done, &op);
251         if (ret) {
252                 debug("Error in SEC enq\n");
253                 ret = JQ_ENQ_ERR;
254                 goto out;
255         }
256
257         timeval = get_ticks();
258         timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
259         while (op.done != 1) {
260                 ret = jr_dequeue();
261                 if (ret) {
262                         debug("Error in SEC deq\n");
263                         ret = JQ_DEQ_ERR;
264                         goto out;
265                 }
266
267                 if ((get_ticks() - timeval) > timeout) {
268                         debug("SEC Dequeue timed out\n");
269                         ret = JQ_DEQ_TO_ERR;
270                         goto out;
271                 }
272         }
273
274         if (!op.status) {
275                 debug("Error %x\n", op.status);
276                 ret = op.status;
277         }
278 out:
279         return ret;
280 }
281
282 int jr_reset(void)
283 {
284         if (jr_hw_reset() < 0)
285                 return -1;
286
287         /* Clean up the jobring structure maintained by software */
288         jr_sw_cleanup();
289
290         return 0;
291 }
292
293 int sec_reset(void)
294 {
295         ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
296         uint32_t mcfgr = sec_in32(&sec->mcfgr);
297         uint32_t timeout = 100000;
298
299         mcfgr |= MCFGR_SWRST;
300         sec_out32(&sec->mcfgr, mcfgr);
301
302         mcfgr |= MCFGR_DMA_RST;
303         sec_out32(&sec->mcfgr, mcfgr);
304         do {
305                 mcfgr = sec_in32(&sec->mcfgr);
306         } while ((mcfgr & MCFGR_DMA_RST) == MCFGR_DMA_RST && --timeout);
307
308         if (timeout == 0)
309                 return -1;
310
311         timeout = 100000;
312         do {
313                 mcfgr = sec_in32(&sec->mcfgr);
314         } while ((mcfgr & MCFGR_SWRST) == MCFGR_SWRST && --timeout);
315
316         if (timeout == 0)
317                 return -1;
318
319         return 0;
320 }
321
322 int sec_init(void)
323 {
324         int ret = 0;
325
326 #ifdef CONFIG_PHYS_64BIT
327         ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
328         uint32_t mcr = sec_in32(&sec->mcfgr);
329
330         sec_out32(&sec->mcfgr, mcr | 1 << MCFGR_PS_SHIFT);
331 #endif
332         ret = jr_init();
333         if (ret < 0)
334                 return -1;
335
336         return ret;
337 }