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
mv_sys_xor_init(MV_DRAM_INFO * dram_info)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
mv_sys_xor_finish(void)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 */
mv_xor_hal_init(u32 chan_num)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 */
mv_xor_ctrl_set(u32 chan,u32 xor_ctrl)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
mv_xor_mem_init(u32 chan,u32 start_ptr,u32 block_size,u32 init_val_high,u32 init_val_low)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 */
mv_xor_transfer(u32 chan,int xor_type,u32 xor_chain_ptr)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 */
mv_xor_state_get(u32 chan)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 */
mv_xor_cmd_set(u32 chan,int command)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