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