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