]> git.sur5r.net Git - u-boot/blobdiff - drivers/ddr/marvell/a38x/xor.c
ARM: mvebu: a38x: sync ddr training code with upstream
[u-boot] / drivers / ddr / marvell / a38x / xor.c
index e53834f54a94b7bb65c694a006d7fec4545e2712..024cecd777c5a5d06cc2328d0b82b68fb5fc453b 100644 (file)
@@ -3,13 +3,6 @@
  * Copyright (C) Marvell International Ltd. and its affiliates
  */
 
-#include <common.h>
-#include <i2c.h>
-#include <spl.h>
-#include <asm/io.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/soc.h>
-
 #include "ddr3_init.h"
 #include "xor_regs.h"
 
 #endif
 
 static u32 ui_xor_regs_ctrl_backup;
-static u32 ui_xor_regs_base_backup[MAX_CS];
-static u32 ui_xor_regs_mask_backup[MAX_CS];
+static u32 ui_xor_regs_base_backup[MAX_CS_NUM + 1];
+static u32 ui_xor_regs_mask_backup[MAX_CS_NUM + 1];
 
-void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, u32 cs_size, u32 base_delta)
+void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, uint64_t cs_size, u32 base_delta)
 {
-       u32 reg, ui, base, cs_count;
+       u32 reg, ui, cs_count;
+       uint64_t base, size_mask;
 
        ui_xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0));
-       for (ui = 0; ui < MAX_CS; ui++)
+       for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
                ui_xor_regs_base_backup[ui] =
                        reg_read(XOR_BASE_ADDR_REG(0, ui));
-       for (ui = 0; ui < MAX_CS; ui++)
+       for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
                ui_xor_regs_mask_backup[ui] =
                        reg_read(XOR_SIZE_MASK_REG(0, ui));
 
        reg = 0;
-       for (ui = 0; ui < (num_of_cs); ui++) {
-               /* Enable Window x for each CS */
-               reg |= (0x1 << (ui));
-               /* Enable Window x for each CS */
-               reg |= (0x3 << ((ui * 2) + 16));
+       for (ui = 0, cs_count = 0;
+            (cs_count < num_of_cs) && (ui < 8);
+            ui++, cs_count++) {
+               if (cs_ena & (1 << ui)) {
+                       /* Enable Window x for each CS */
+                       reg |= (0x1 << (ui));
+                       /* Enable Window x for each CS */
+                       reg |= (0x3 << ((ui * 2) + 16));
+               }
        }
 
        reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg);
 
        cs_count = 0;
-       for (ui = 0; ui < num_of_cs; ui++) {
+       for (ui = 0, cs_count = 0;
+            (cs_count < num_of_cs) && (ui < 8);
+            ui++, cs_count++) {
                if (cs_ena & (1 << ui)) {
                        /*
                         * window x - Base - 0x00000000,
                         * Attribute 0x0e - DRAM
                         */
                        base = cs_size * ui + base_delta;
+                       /* fixed size 2GB for each CS */
+                       size_mask = 0x7FFF0000;
                        switch (ui) {
                        case 0:
                                base |= 0xe00;
@@ -67,13 +69,19 @@ void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, u32 cs_size, u32 base_delta)
                        case 3:
                                base |= 0x700;
                                break;
+                       case 4: /* SRAM */
+                               base = 0x40000000;
+                               /* configure as shared transaction */
+                               base |= 0x1F00;
+                               size_mask = 0xF0000;
+                               break;
                        }
 
-                       reg_write(XOR_BASE_ADDR_REG(0, cs_count), base);
-
+                       reg_write(XOR_BASE_ADDR_REG(0, ui), (u32)base);
+                       size_mask = (cs_size / _64K) - 1;
+                       size_mask = (size_mask << XESMRX_SIZE_MASK_OFFS) & XESMRX_SIZE_MASK_MASK;
                        /* window x - Size */
-                       reg_write(XOR_SIZE_MASK_REG(0, cs_count), 0x7fff0000);
-                       cs_count++;
+                       reg_write(XOR_SIZE_MASK_REG(0, ui), (u32)size_mask);
                }
        }
 
@@ -87,10 +95,10 @@ void mv_sys_xor_finish(void)
        u32 ui;
 
        reg_write(XOR_WINDOW_CTRL_REG(0, 0), ui_xor_regs_ctrl_backup);
-       for (ui = 0; ui < MAX_CS; ui++)
+       for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
                reg_write(XOR_BASE_ADDR_REG(0, ui),
                          ui_xor_regs_base_backup[ui]);
-       for (ui = 0; ui < MAX_CS; ui++)
+       for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
                reg_write(XOR_SIZE_MASK_REG(0, ui),
                          ui_xor_regs_mask_backup[ui]);
 
@@ -153,11 +161,14 @@ int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl)
        return MV_OK;
 }
 
-int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size,
+int mv_xor_mem_init(u32 chan, u32 start_ptr, unsigned long long block_size,
                    u32 init_val_high, u32 init_val_low)
 {
        u32 temp;
 
+       if (block_size == _4G)
+               block_size -= 1;
+
        /* Parameter checking */
        if (chan >= MV_XOR_MAX_CHAN)
                return MV_BAD_PARAM;
@@ -328,28 +339,123 @@ void ddr3_new_tip_ecc_scrub(void)
 {
        u32 cs_c, max_cs;
        u32 cs_ena = 0;
+       u32 dev_num = 0;
+       uint64_t total_mem_size, cs_mem_size = 0;
 
-       printf("DDR3 Training Sequence - Start scrubbing\n");
-
-       max_cs = hws_ddr3_tip_max_cs_get();
+       printf("DDR Training Sequence - Start scrubbing\n");
+       max_cs = ddr3_tip_max_cs_get(dev_num);
        for (cs_c = 0; cs_c < max_cs; cs_c++)
                cs_ena |= 1 << cs_c;
 
-       mv_sys_xor_init(max_cs, cs_ena, 0x80000000, 0);
-
-       mv_xor_mem_init(0, 0x00000000, 0x80000000, 0xdeadbeef, 0xdeadbeef);
-       /* wait for previous transfer completion */
-       while (mv_xor_state_get(0) != MV_IDLE)
-               ;
-
-       mv_xor_mem_init(0, 0x80000000, 0x40000000, 0xdeadbeef, 0xdeadbeef);
-
+       mv_sys_xor_init(max_cs, cs_ena, cs_mem_size, 0);
+       total_mem_size = max_cs * cs_mem_size;
+       mv_xor_mem_init(0, 0, total_mem_size, 0xdeadbeef, 0xdeadbeef);
        /* wait for previous transfer completion */
        while (mv_xor_state_get(0) != MV_IDLE)
                ;
-
        /* Return XOR State */
        mv_sys_xor_finish();
 
        printf("DDR3 Training Sequence - End scrubbing\n");
 }
+
+/*
+* mv_xor_transfer - Transfer data from source to destination in one of
+*                  three modes: XOR, CRC32 or DMA
+*
+* DESCRIPTION:
+*      This function initiates XOR channel, according to function parameters,
+*      in order to perform XOR, CRC32 or DMA transaction.
+*      To gain maximum performance the user is asked to keep the following
+*      restrictions:
+*      1) Selected engine is available (not busy).
+*      2) This module does not take into consideration CPU MMU issues.
+*         In order for the XOR engine to access the appropriate source
+*         and destination, address parameters must be given in system
+*         physical mode.
+*      3) This API does not take care of cache coherency issues. The source,
+*         destination and, in case of chain, the descriptor list are assumed
+*         to be cache coherent.
+*      4) Parameters validity.
+*
+* INPUT:
+*      chan            - XOR channel number.
+*      type    - One of three: XOR, CRC32 and DMA operations.
+*      xor_chain_ptr   - address of chain pointer
+*
+* OUTPUT:
+*      None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+int mv_xor_transfer(u32 chan, enum xor_type type, u32 xor_chain_ptr)
+{
+       u32 temp;
+
+       /* Parameter checking */
+       if (chan >= MV_XOR_MAX_CHAN) {
+               DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
+               return MV_BAD_PARAM;
+       }
+       if (mv_xor_state_get(chan) == MV_ACTIVE) {
+               DB(printf("%s: ERR. Channel is already active\n", __func__));
+               return MV_BUSY;
+       }
+       if (xor_chain_ptr == 0x0) {
+               DB(printf("%s: ERR. xor_chain_ptr is NULL pointer\n", __func__));
+               return MV_BAD_PARAM;
+       }
+
+       /* read configuration register and mask the operation mode field */
+       temp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+       temp &= ~XEXCR_OPERATION_MODE_MASK;
+
+       switch (type) {
+       case MV_XOR:
+               if ((xor_chain_ptr & XEXDPR_DST_PTR_XOR_MASK) != 0) {
+                       DB(printf("%s: ERR. Invalid chain pointer (bits [5:0] must be cleared)\n",
+                                 __func__));
+                       return MV_BAD_PARAM;
+               }
+               /* set the operation mode to XOR */
+               temp |= XEXCR_OPERATION_MODE_XOR;
+               break;
+       case MV_DMA:
+               if ((xor_chain_ptr & XEXDPR_DST_PTR_DMA_MASK) != 0) {
+                       DB(printf("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
+                                 __func__));
+                       return MV_BAD_PARAM;
+               }
+               /* set the operation mode to DMA */
+               temp |= XEXCR_OPERATION_MODE_DMA;
+               break;
+       case MV_CRC32:
+               if ((xor_chain_ptr & XEXDPR_DST_PTR_CRC_MASK) != 0) {
+                       DB(printf("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
+                                 __func__));
+                       return MV_BAD_PARAM;
+               }
+               /* set the operation mode to CRC32 */
+               temp |= XEXCR_OPERATION_MODE_CRC;
+               break;
+       default:
+               return MV_BAD_PARAM;
+       }
+
+       /* write the operation mode to the register */
+       reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
+       /*
+        * update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor
+        * Pointer Register (XExNDPR)
+        */
+       reg_write(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+                 xor_chain_ptr);
+
+       /* start transfer */
+       reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+                   XEXACTR_XESTART_MASK);
+
+       return MV_OK;
+}