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