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