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