blob: 6ecacfeb93369092d8b076e2167472a6dab5201e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Stefan Roeseae6223d2015-01-19 11:33:40 +01002/*
3 * Copyright (C) Marvell International Ltd. and its affiliates
Stefan Roeseae6223d2015-01-19 11:33:40 +01004 */
5
Stefan Roeseae6223d2015-01-19 11:33:40 +01006#include <i2c.h>
Simon Glass0f2af882020-05-10 11:40:05 -06007#include <log.h>
Stefan Roeseae6223d2015-01-19 11:33:40 +01008#include <spl.h>
9#include <asm/io.h>
10#include <asm/arch/cpu.h>
11#include <asm/arch/soc.h>
12
13#include "xor.h"
14#include "xor_regs.h"
15
16static u32 xor_regs_ctrl_backup;
17static u32 xor_regs_base_backup[MAX_CS];
18static u32 xor_regs_mask_backup[MAX_CS];
19
Stefan Roeseae6223d2015-01-19 11:33:40 +010020static int mv_xor_cmd_set(u32 chan, int command);
21static int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl);
22
23void mv_sys_xor_init(MV_DRAM_INFO *dram_info)
24{
25 u32 reg, ui, base, cs_count;
26
27 xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0));
28 for (ui = 0; ui < MAX_CS; ui++)
29 xor_regs_base_backup[ui] = reg_read(XOR_BASE_ADDR_REG(0, ui));
30 for (ui = 0; ui < MAX_CS; ui++)
31 xor_regs_mask_backup[ui] = reg_read(XOR_SIZE_MASK_REG(0, ui));
32
33 reg = 0;
34 for (ui = 0; ui < (dram_info->num_cs + 1); ui++) {
35 /* Enable Window x for each CS */
36 reg |= (0x1 << (ui));
37 /* Enable Window x for each CS */
38 reg |= (0x3 << ((ui * 2) + 16));
39 }
40
41 reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg);
42
43 /* Last window - Base - 0x40000000, Attribute 0x1E - SRAM */
44 base = (SRAM_BASE & 0xFFFF0000) | 0x1E00;
45 reg_write(XOR_BASE_ADDR_REG(0, dram_info->num_cs), base);
46 /* Last window - Size - 64 MB */
47 reg_write(XOR_SIZE_MASK_REG(0, dram_info->num_cs), 0x03FF0000);
48
49 cs_count = 0;
50 for (ui = 0; ui < MAX_CS; ui++) {
51 if (dram_info->cs_ena & (1 << ui)) {
52 /*
53 * Window x - Base - 0x00000000, Attribute 0x0E - DRAM
54 */
55 base = 0;
56 switch (ui) {
57 case 0:
58 base |= 0xE00;
59 break;
60 case 1:
61 base |= 0xD00;
62 break;
63 case 2:
64 base |= 0xB00;
65 break;
66 case 3:
67 base |= 0x700;
68 break;
69 }
70
71 reg_write(XOR_BASE_ADDR_REG(0, cs_count), base);
72
73 /* Window x - Size - 256 MB */
74 reg_write(XOR_SIZE_MASK_REG(0, cs_count), 0x0FFF0000);
75 cs_count++;
76 }
77 }
78
79 mv_xor_hal_init(1);
80
81 return;
82}
83
84void mv_sys_xor_finish(void)
85{
86 u32 ui;
87
88 reg_write(XOR_WINDOW_CTRL_REG(0, 0), xor_regs_ctrl_backup);
89 for (ui = 0; ui < MAX_CS; ui++)
90 reg_write(XOR_BASE_ADDR_REG(0, ui), xor_regs_base_backup[ui]);
91 for (ui = 0; ui < MAX_CS; ui++)
92 reg_write(XOR_SIZE_MASK_REG(0, ui), xor_regs_mask_backup[ui]);
93
94 reg_write(XOR_ADDR_OVRD_REG(0, 0), 0);
95}
96
97/*
98 * mv_xor_hal_init - Initialize XOR engine
99 *
100 * DESCRIPTION:
101 * This function initialize XOR unit.
102 * INPUT:
103 * None.
104 *
105 * OUTPUT:
106 * None.
107 *
108 * RETURN:
109 * MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
110 */
Stefan Roesef3345e62015-08-06 14:43:13 +0200111void mv_xor_hal_init(u32 chan_num)
Stefan Roeseae6223d2015-01-19 11:33:40 +0100112{
113 u32 i;
114
115 /* Abort any XOR activity & set default configuration */
116 for (i = 0; i < chan_num; i++) {
117 mv_xor_cmd_set(i, MV_STOP);
118 mv_xor_ctrl_set(i, (1 << XEXCR_REG_ACC_PROTECT_OFFS) |
119 (4 << XEXCR_DST_BURST_LIMIT_OFFS) |
120 (4 << XEXCR_SRC_BURST_LIMIT_OFFS));
121 }
122}
123
124/*
125 * mv_xor_ctrl_set - Set XOR channel control registers
126 *
127 * DESCRIPTION:
128 *
129 * INPUT:
130 *
131 * OUTPUT:
132 * None.
133 *
134 * RETURN:
135 * MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
136 * NOTE:
137 * This function does not modify the OperationMode field of control register.
138 *
139 */
140static int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl)
141{
142 u32 val;
143
144 /* Update the XOR Engine [0..1] Configuration Registers (XExCR) */
145 val = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)))
146 & XEXCR_OPERATION_MODE_MASK;
147 xor_ctrl &= ~XEXCR_OPERATION_MODE_MASK;
148 xor_ctrl |= val;
149 reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), xor_ctrl);
150
151 return MV_OK;
152}
153
Marek BehĂșn8977d012021-03-04 11:23:14 +0100154int mv_xor_mem_init(u32 chan, u32 start_ptr, unsigned long long block_size,
155 u32 init_val_high, u32 init_val_low)
Stefan Roeseae6223d2015-01-19 11:33:40 +0100156{
157 u32 tmp;
158
159 /* Parameter checking */
160 if (chan >= MV_XOR_MAX_CHAN)
161 return MV_BAD_PARAM;
162
163 if (MV_ACTIVE == mv_xor_state_get(chan))
164 return MV_BUSY;
165
166 if ((block_size < XEXBSR_BLOCK_SIZE_MIN_VALUE) ||
167 (block_size > XEXBSR_BLOCK_SIZE_MAX_VALUE))
168 return MV_BAD_PARAM;
169
170 /* Set the operation mode to Memory Init */
171 tmp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
172 tmp &= ~XEXCR_OPERATION_MODE_MASK;
173 tmp |= XEXCR_OPERATION_MODE_MEM_INIT;
174 reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), tmp);
175
176 /*
177 * Update the start_ptr field in XOR Engine [0..1] Destination Pointer
178 * Register (XExDPR0)
179 */
180 reg_write(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), start_ptr);
181
182 /*
183 * Update the BlockSize field in the XOR Engine[0..1] Block Size
184 * Registers (XExBSR)
185 */
186 reg_write(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
187 block_size);
188
189 /*
190 * Update the field InitValL in the XOR Engine Initial Value Register
191 * Low (XEIVRL)
192 */
193 reg_write(XOR_INIT_VAL_LOW_REG(XOR_UNIT(chan)), init_val_low);
194
195 /*
196 * Update the field InitValH in the XOR Engine Initial Value Register
197 * High (XEIVRH)
198 */
199 reg_write(XOR_INIT_VAL_HIGH_REG(XOR_UNIT(chan)), init_val_high);
200
201 /* Start transfer */
202 reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
203 XEXACTR_XESTART_MASK);
204
205 return MV_OK;
206}
207
208/*
209 * mv_xor_transfer - Transfer data from source to destination on one of
210 * three modes (XOR,CRC32,DMA)
211 *
212 * DESCRIPTION:
213 * This function initiates XOR channel, according to function parameters,
214 * in order to perform XOR or CRC32 or DMA transaction.
215 * To gain maximum performance the user is asked to keep the following
216 * restrictions:
217 * 1) Selected engine is available (not busy).
218 * 1) This module does not take into consideration CPU MMU issues.
219 * In order for the XOR engine to access the appropreate source
220 * and destination, address parameters must be given in system
221 * physical mode.
222 * 2) This API does not take care of cache coherency issues. The source,
223 * destination and in case of chain the descriptor list are assumed
224 * to be cache coherent.
225 * 4) Parameters validity. For example, does size parameter exceeds
226 * maximum byte count of descriptor mode (16M or 64K).
227 *
228 * INPUT:
229 * chan - XOR channel number. See MV_XOR_CHANNEL enumerator.
230 * xor_type - One of three: XOR, CRC32 and DMA operations.
231 * xor_chain_ptr - address of chain pointer
232 *
233 * OUTPUT:
234 * None.
235 *
236 * RETURS:
237 * MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
238 *
239 */
240int mv_xor_transfer(u32 chan, int xor_type, u32 xor_chain_ptr)
241{
242 u32 tmp;
243
244 /* Parameter checking */
245 if (chan >= MV_XOR_MAX_CHAN) {
246 debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
247 return MV_BAD_PARAM;
248 }
249
250 if (MV_ACTIVE == mv_xor_state_get(chan)) {
251 debug("%s: ERR. Channel is already active\n", __func__);
252 return MV_BUSY;
253 }
254
255 if (0x0 == xor_chain_ptr) {
256 debug("%s: ERR. xor_chain_ptr is NULL pointer\n", __func__);
257 return MV_BAD_PARAM;
258 }
259
260 /* Read configuration register and mask the operation mode field */
261 tmp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
262 tmp &= ~XEXCR_OPERATION_MODE_MASK;
263
264 switch (xor_type) {
265 case MV_XOR:
266 if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_XOR_MASK)) {
267 debug("%s: ERR. Invalid chain pointer (bits [5:0] must be cleared)\n",
268 __func__);
269 return MV_BAD_PARAM;
270 }
271
272 /* Set the operation mode to XOR */
273 tmp |= XEXCR_OPERATION_MODE_XOR;
274 break;
275
276 case MV_DMA:
277 if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_DMA_MASK)) {
278 debug("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
279 __func__);
280 return MV_BAD_PARAM;
281 }
282
283 /* Set the operation mode to DMA */
284 tmp |= XEXCR_OPERATION_MODE_DMA;
285 break;
286
287 case MV_CRC32:
288 if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_CRC_MASK)) {
289 debug("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
290 __func__);
291 return MV_BAD_PARAM;
292 }
293
294 /* Set the operation mode to CRC32 */
295 tmp |= XEXCR_OPERATION_MODE_CRC;
296 break;
297
298 default:
299 return MV_BAD_PARAM;
300 }
301
302 /* Write the operation mode to the register */
303 reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), tmp);
304
305 /*
306 * Update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor
307 * Pointer Register (XExNDPR)
308 */
309 reg_write(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
310 xor_chain_ptr);
311
312 /* Start transfer */
313 reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
314 XEXACTR_XESTART_MASK);
315
316 return MV_OK;
317}
318
319/*
320 * mv_xor_state_get - Get XOR channel state.
321 *
322 * DESCRIPTION:
323 * XOR channel activity state can be active, idle, paused.
324 * This function retrunes the channel activity state.
325 *
326 * INPUT:
327 * chan - the channel number
328 *
329 * OUTPUT:
330 * None.
331 *
332 * RETURN:
333 * XOR_CHANNEL_IDLE - If the engine is idle.
334 * XOR_CHANNEL_ACTIVE - If the engine is busy.
335 * XOR_CHANNEL_PAUSED - If the engine is paused.
336 * MV_UNDEFINED_STATE - If the engine state is undefind or there is no
337 * such engine
338 *
339 */
340int mv_xor_state_get(u32 chan)
341{
342 u32 state;
343
344 /* Parameter checking */
345 if (chan >= MV_XOR_MAX_CHAN) {
346 debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
347 return MV_UNDEFINED_STATE;
348 }
349
350 /* Read the current state */
351 state = reg_read(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
352 state &= XEXACTR_XESTATUS_MASK;
353
354 /* Return the state */
355 switch (state) {
356 case XEXACTR_XESTATUS_IDLE:
357 return MV_IDLE;
358 case XEXACTR_XESTATUS_ACTIVE:
359 return MV_ACTIVE;
360 case XEXACTR_XESTATUS_PAUSED:
361 return MV_PAUSED;
362 }
363
364 return MV_UNDEFINED_STATE;
365}
366
367/*
368 * mv_xor_cmd_set - Set command of XOR channel
369 *
370 * DESCRIPTION:
371 * XOR channel can be started, idle, paused and restarted.
372 * Paused can be set only if channel is active.
373 * Start can be set only if channel is idle or paused.
374 * Restart can be set only if channel is paused.
375 * Stop can be set only if channel is active.
376 *
377 * INPUT:
378 * chan - The channel number
379 * command - The command type (start, stop, restart, pause)
380 *
381 * OUTPUT:
382 * None.
383 *
384 * RETURN:
385 * MV_OK on success , MV_BAD_PARAM on erroneous parameter, MV_ERROR on
386 * undefind XOR engine mode
387 *
388 */
389static int mv_xor_cmd_set(u32 chan, int command)
390{
391 int state;
392
393 /* Parameter checking */
394 if (chan >= MV_XOR_MAX_CHAN) {
395 debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
396 return MV_BAD_PARAM;
397 }
398
399 /* Get the current state */
400 state = mv_xor_state_get(chan);
401
402 /* Command is start and current state is idle */
403 if ((command == MV_START) && (state == MV_IDLE)) {
404 reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
405 XEXACTR_XESTART_MASK);
406 return MV_OK;
407 }
408 /* Command is stop and current state is active */
409 else if ((command == MV_STOP) && (state == MV_ACTIVE)) {
410 reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
411 XEXACTR_XESTOP_MASK);
412 return MV_OK;
413 }
414 /* Command is paused and current state is active */
415 else if ((command == MV_PAUSED) && (state == MV_ACTIVE)) {
416 reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
417 XEXACTR_XEPAUSE_MASK);
418 return MV_OK;
419 }
420 /* Command is restart and current state is paused */
421 else if ((command == MV_RESTART) && (state == MV_PAUSED)) {
422 reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
423 XEXACTR_XERESTART_MASK);
424 return MV_OK;
425 }
426 /* Command is stop and current state is active */
427 else if ((command == MV_STOP) && (state == MV_IDLE))
428 return MV_OK;
429
430 /* Illegal command */
431 debug("%s: ERR. Illegal command\n", __func__);
432
433 return MV_BAD_PARAM;
434}