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