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