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