xref: /openbmc/u-boot/drivers/ddr/marvell/axp/xor.c (revision 8a23fc9c)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) Marvell International Ltd. and its affiliates
4  */
5 
6 #include <common.h>
7 #include <i2c.h>
8 #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 
16 static u32 xor_regs_ctrl_backup;
17 static u32 xor_regs_base_backup[MAX_CS];
18 static u32 xor_regs_mask_backup[MAX_CS];
19 
20 static int mv_xor_cmd_set(u32 chan, int command);
21 static int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl);
22 
23 void 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 
84 void 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  */
111 void mv_xor_hal_init(u32 chan_num)
112 {
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  */
140 static 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 
154 int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size, u32 init_val_high,
155 		    u32 init_val_low)
156 {
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  */
240 int 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  */
340 int 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  */
389 static 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 }
435