uboot/drivers/ddr/marvell/a38x/xor.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) Marvell International Ltd. and its affiliates
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0
   5 */
   6
   7#include <common.h>
   8#include <i2c.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 "ddr3_init.h"
  15#include "xor_regs.h"
  16
  17/* defines  */
  18#ifdef MV_DEBUG
  19#define DB(x)   x
  20#else
  21#define DB(x)
  22#endif
  23
  24static u32 ui_xor_regs_ctrl_backup;
  25static u32 ui_xor_regs_base_backup[MAX_CS];
  26static u32 ui_xor_regs_mask_backup[MAX_CS];
  27
  28void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, u32 cs_size, u32 base_delta)
  29{
  30        u32 reg, ui, base, cs_count;
  31
  32        ui_xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0));
  33        for (ui = 0; ui < MAX_CS; ui++)
  34                ui_xor_regs_base_backup[ui] =
  35                        reg_read(XOR_BASE_ADDR_REG(0, ui));
  36        for (ui = 0; ui < MAX_CS; ui++)
  37                ui_xor_regs_mask_backup[ui] =
  38                        reg_read(XOR_SIZE_MASK_REG(0, ui));
  39
  40        reg = 0;
  41        for (ui = 0; ui < (num_of_cs); ui++) {
  42                /* Enable Window x for each CS */
  43                reg |= (0x1 << (ui));
  44                /* Enable Window x for each CS */
  45                reg |= (0x3 << ((ui * 2) + 16));
  46        }
  47
  48        reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg);
  49
  50        cs_count = 0;
  51        for (ui = 0; ui < num_of_cs; ui++) {
  52                if (cs_ena & (1 << ui)) {
  53                        /*
  54                         * window x - Base - 0x00000000,
  55                         * Attribute 0x0e - DRAM
  56                         */
  57                        base = cs_size * ui + base_delta;
  58                        switch (ui) {
  59                        case 0:
  60                                base |= 0xe00;
  61                                break;
  62                        case 1:
  63                                base |= 0xd00;
  64                                break;
  65                        case 2:
  66                                base |= 0xb00;
  67                                break;
  68                        case 3:
  69                                base |= 0x700;
  70                                break;
  71                        }
  72
  73                        reg_write(XOR_BASE_ADDR_REG(0, cs_count), base);
  74
  75                        /* window x - Size */
  76                        reg_write(XOR_SIZE_MASK_REG(0, cs_count), 0x7fff0000);
  77                        cs_count++;
  78                }
  79        }
  80
  81        mv_xor_hal_init(1);
  82
  83        return;
  84}
  85
  86void mv_sys_xor_finish(void)
  87{
  88        u32 ui;
  89
  90        reg_write(XOR_WINDOW_CTRL_REG(0, 0), ui_xor_regs_ctrl_backup);
  91        for (ui = 0; ui < MAX_CS; ui++)
  92                reg_write(XOR_BASE_ADDR_REG(0, ui),
  93                          ui_xor_regs_base_backup[ui]);
  94        for (ui = 0; ui < MAX_CS; ui++)
  95                reg_write(XOR_SIZE_MASK_REG(0, ui),
  96                          ui_xor_regs_mask_backup[ui]);
  97
  98        reg_write(XOR_ADDR_OVRD_REG(0, 0), 0);
  99}
 100
 101/*
 102 * mv_xor_hal_init - Initialize XOR engine
 103 *
 104 * DESCRIPTION:
 105 *               This function initialize XOR unit.
 106 * INPUT:
 107 *       None.
 108 *
 109 * OUTPUT:
 110 *       None.
 111 *
 112 * RETURN:
 113 *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
 114 */
 115void mv_xor_hal_init(u32 xor_chan_num)
 116{
 117        u32 i;
 118
 119        /* Abort any XOR activity & set default configuration */
 120        for (i = 0; i < xor_chan_num; i++) {
 121                mv_xor_command_set(i, MV_STOP);
 122                mv_xor_ctrl_set(i, (1 << XEXCR_REG_ACC_PROTECT_OFFS) |
 123                                (4 << XEXCR_DST_BURST_LIMIT_OFFS) |
 124                                (4 << XEXCR_SRC_BURST_LIMIT_OFFS));
 125        }
 126}
 127
 128/*
 129 * mv_xor_ctrl_set - Set XOR channel control registers
 130 *
 131 * DESCRIPTION:
 132 *
 133 * INPUT:
 134 *
 135 * OUTPUT:
 136 *       None.
 137 *
 138 * RETURN:
 139 *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
 140 * NOTE:
 141 *  This function does not modify the Operation_mode field of control register.
 142 */
 143int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl)
 144{
 145        u32 old_value;
 146
 147        /* update the XOR Engine [0..1] Configuration Registers (XEx_c_r) */
 148        old_value = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan))) &
 149                XEXCR_OPERATION_MODE_MASK;
 150        xor_ctrl &= ~XEXCR_OPERATION_MODE_MASK;
 151        xor_ctrl |= old_value;
 152        reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), xor_ctrl);
 153
 154        return MV_OK;
 155}
 156
 157int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size,
 158                    u32 init_val_high, u32 init_val_low)
 159{
 160        u32 temp;
 161
 162        /* Parameter checking */
 163        if (chan >= MV_XOR_MAX_CHAN)
 164                return MV_BAD_PARAM;
 165
 166        if (MV_ACTIVE == mv_xor_state_get(chan))
 167                return MV_BUSY;
 168
 169        if ((block_size < XEXBSR_BLOCK_SIZE_MIN_VALUE) ||
 170            (block_size > XEXBSR_BLOCK_SIZE_MAX_VALUE))
 171                return MV_BAD_PARAM;
 172
 173        /* set the operation mode to Memory Init */
 174        temp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
 175        temp &= ~XEXCR_OPERATION_MODE_MASK;
 176        temp |= XEXCR_OPERATION_MODE_MEM_INIT;
 177        reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
 178
 179        /*
 180         * update the start_ptr field in XOR Engine [0..1] Destination Pointer
 181         * Register
 182         */
 183        reg_write(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), start_ptr);
 184
 185        /*
 186         * update the Block_size field in the XOR Engine[0..1] Block Size
 187         * Registers
 188         */
 189        reg_write(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
 190                  block_size);
 191
 192        /*
 193         * update the field Init_val_l in the XOR Engine Initial Value Register
 194         * Low (XEIVRL)
 195         */
 196        reg_write(XOR_INIT_VAL_LOW_REG(XOR_UNIT(chan)), init_val_low);
 197
 198        /*
 199         * update the field Init_val_h in the XOR Engine Initial Value Register
 200         * High (XEIVRH)
 201         */
 202        reg_write(XOR_INIT_VAL_HIGH_REG(XOR_UNIT(chan)), init_val_high);
 203
 204        /* start transfer */
 205        reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
 206                    XEXACTR_XESTART_MASK);
 207
 208        return MV_OK;
 209}
 210
 211/*
 212 * mv_xor_state_get - Get XOR channel state.
 213 *
 214 * DESCRIPTION:
 215 *       XOR channel activity state can be active, idle, paused.
 216 *       This function retrunes the channel activity state.
 217 *
 218 * INPUT:
 219 *       chan     - the channel number
 220 *
 221 * OUTPUT:
 222 *       None.
 223 *
 224 * RETURN:
 225 *       XOR_CHANNEL_IDLE    - If the engine is idle.
 226 *       XOR_CHANNEL_ACTIVE  - If the engine is busy.
 227 *       XOR_CHANNEL_PAUSED  - If the engine is paused.
 228 *       MV_UNDEFINED_STATE  - If the engine state is undefind or there is no
 229 *                             such engine
 230 */
 231enum mv_state mv_xor_state_get(u32 chan)
 232{
 233        u32 state;
 234
 235        /* Parameter checking   */
 236        if (chan >= MV_XOR_MAX_CHAN) {
 237                DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
 238                return MV_UNDEFINED_STATE;
 239        }
 240
 241        /* read the current state */
 242        state = reg_read(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
 243        state &= XEXACTR_XESTATUS_MASK;
 244
 245        /* return the state */
 246        switch (state) {
 247        case XEXACTR_XESTATUS_IDLE:
 248                return MV_IDLE;
 249        case XEXACTR_XESTATUS_ACTIVE:
 250                return MV_ACTIVE;
 251        case XEXACTR_XESTATUS_PAUSED:
 252                return MV_PAUSED;
 253        }
 254
 255        return MV_UNDEFINED_STATE;
 256}
 257
 258/*
 259 * mv_xor_command_set - Set command of XOR channel
 260 *
 261 * DESCRIPTION:
 262 *       XOR channel can be started, idle, paused and restarted.
 263 *       Paused can be set only if channel is active.
 264 *       Start can be set only if channel is idle or paused.
 265 *       Restart can be set only if channel is paused.
 266 *       Stop can be set only if channel is active.
 267 *
 268 * INPUT:
 269 *       chan     - The channel number
 270 *       command  - The command type (start, stop, restart, pause)
 271 *
 272 * OUTPUT:
 273 *       None.
 274 *
 275 * RETURN:
 276 *       MV_OK on success , MV_BAD_PARAM on erroneous parameter, MV_ERROR on
 277 *       undefind XOR engine mode
 278 */
 279int mv_xor_command_set(u32 chan, enum mv_command command)
 280{
 281        enum mv_state state;
 282
 283        /* Parameter checking */
 284        if (chan >= MV_XOR_MAX_CHAN) {
 285                DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
 286                return MV_BAD_PARAM;
 287        }
 288
 289        /* get the current state */
 290        state = mv_xor_state_get(chan);
 291
 292        if ((command == MV_START) && (state == MV_IDLE)) {
 293                /* command is start and current state is idle */
 294                reg_bit_set(XOR_ACTIVATION_REG
 295                            (XOR_UNIT(chan), XOR_CHAN(chan)),
 296                            XEXACTR_XESTART_MASK);
 297                return MV_OK;
 298        } else if ((command == MV_STOP) && (state == MV_ACTIVE)) {
 299                /* command is stop and current state is active */
 300                reg_bit_set(XOR_ACTIVATION_REG
 301                            (XOR_UNIT(chan), XOR_CHAN(chan)),
 302                            XEXACTR_XESTOP_MASK);
 303                return MV_OK;
 304        } else if (((enum mv_state)command == MV_PAUSED) &&
 305                   (state == MV_ACTIVE)) {
 306                /* command is paused and current state is active */
 307                reg_bit_set(XOR_ACTIVATION_REG
 308                            (XOR_UNIT(chan), XOR_CHAN(chan)),
 309                            XEXACTR_XEPAUSE_MASK);
 310                return MV_OK;
 311        } else if ((command == MV_RESTART) && (state == MV_PAUSED)) {
 312                /* command is restart and current state is paused */
 313                reg_bit_set(XOR_ACTIVATION_REG
 314                            (XOR_UNIT(chan), XOR_CHAN(chan)),
 315                            XEXACTR_XERESTART_MASK);
 316                return MV_OK;
 317        } else if ((command == MV_STOP) && (state == MV_IDLE)) {
 318                /* command is stop and current state is active */
 319                return MV_OK;
 320        }
 321
 322        /* illegal command */
 323        DB(printf("%s: ERR. Illegal command\n", __func__));
 324
 325        return MV_BAD_PARAM;
 326}
 327
 328void ddr3_new_tip_ecc_scrub(void)
 329{
 330        u32 cs_c, max_cs;
 331        u32 cs_ena = 0;
 332
 333        printf("DDR3 Training Sequence - Start scrubbing\n");
 334
 335        max_cs = hws_ddr3_tip_max_cs_get();
 336        for (cs_c = 0; cs_c < max_cs; cs_c++)
 337                cs_ena |= 1 << cs_c;
 338
 339        mv_sys_xor_init(max_cs, cs_ena, 0x80000000, 0);
 340
 341        mv_xor_mem_init(0, 0x00000000, 0x80000000, 0xdeadbeef, 0xdeadbeef);
 342        /* wait for previous transfer completion */
 343        while (mv_xor_state_get(0) != MV_IDLE)
 344                ;
 345
 346        mv_xor_mem_init(0, 0x80000000, 0x40000000, 0xdeadbeef, 0xdeadbeef);
 347
 348        /* wait for previous transfer completion */
 349        while (mv_xor_state_get(0) != MV_IDLE)
 350                ;
 351
 352        /* Return XOR State */
 353        mv_sys_xor_finish();
 354
 355        printf("DDR3 Training Sequence - End scrubbing\n");
 356}
 357