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