uboot/arch/arm/mach-zynqmp/ecc_spl_init.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 *  Copyright(c) 2015 - 2020 Xilinx, Inc.
   4 *
   5 *  Jorge Ramirez-Ortiz <jorge@foundries.io>
   6 */
   7
   8#include <common.h>
   9#include <cpu_func.h>
  10#include <asm/arch/hardware.h>
  11#include <asm/arch/ecc_spl_init.h>
  12#include <asm/io.h>
  13#include <linux/delay.h>
  14
  15#define ZDMA_TRANSFER_MAX_LEN           (0x3FFFFFFFU - 7U)
  16#define ZDMA_CH_STATUS                  ((ADMA_CH0_BASEADDR) + 0x0000011CU)
  17#define ZDMA_CH_STATUS_STATE_MASK       0x00000003U
  18#define ZDMA_CH_STATUS_STATE_DONE       0x00000000U
  19#define ZDMA_CH_STATUS_STATE_ERR        0x00000003U
  20#define ZDMA_CH_CTRL0                   ((ADMA_CH0_BASEADDR) + 0x00000110U)
  21#define ZDMA_CH_CTRL0_POINT_TYPE_MASK   (u32)0x00000040U
  22#define ZDMA_CH_CTRL0_POINT_TYPE_NORMAL (u32)0x00000000U
  23#define ZDMA_CH_CTRL0_MODE_MASK         (u32)0x00000030U
  24#define ZDMA_CH_CTRL0_MODE_WR_ONLY      (u32)0x00000010U
  25#define ZDMA_CH_CTRL0_TOTAL_BYTE_COUNT  ((ADMA_CH0_BASEADDR) + 0x00000188U)
  26#define ZDMA_CH_WR_ONLY_WORD0           ((ADMA_CH0_BASEADDR) + 0x00000148U)
  27#define ZDMA_CH_WR_ONLY_WORD1           ((ADMA_CH0_BASEADDR) + 0x0000014CU)
  28#define ZDMA_CH_WR_ONLY_WORD2           ((ADMA_CH0_BASEADDR) + 0x00000150U)
  29#define ZDMA_CH_WR_ONLY_WORD3           ((ADMA_CH0_BASEADDR) + 0x00000154U)
  30#define ZDMA_CH_DST_DSCR_WORD0          ((ADMA_CH0_BASEADDR) + 0x00000138U)
  31#define ZDMA_CH_DST_DSCR_WORD0_LSB_MASK 0xFFFFFFFFU
  32#define ZDMA_CH_DST_DSCR_WORD1          ((ADMA_CH0_BASEADDR) + 0x0000013CU)
  33#define ZDMA_CH_DST_DSCR_WORD1_MSB_MASK 0x0001FFFFU
  34#define ZDMA_CH_SRC_DSCR_WORD2          ((ADMA_CH0_BASEADDR) + 0x00000130U)
  35#define ZDMA_CH_DST_DSCR_WORD2          ((ADMA_CH0_BASEADDR) + 0x00000140U)
  36#define ZDMA_CH_CTRL2                   ((ADMA_CH0_BASEADDR) + 0x00000200U)
  37#define ZDMA_CH_CTRL2_EN_MASK           0x00000001U
  38#define ZDMA_CH_ISR                     ((ADMA_CH0_BASEADDR) + 0x00000100U)
  39#define ZDMA_CH_ISR_DMA_DONE_MASK       0x00000400U
  40#define ECC_INIT_VAL_WORD               0xDEADBEEFU
  41
  42#define ZDMA_IDLE_TIMEOUT_USEC          1000000
  43#define ZDMA_DONE_TIMEOUT_USEC          5000000
  44
  45static void ecc_zdma_restore(void)
  46{
  47        /* Restore reset values for the DMA registers used */
  48        writel(ZDMA_CH_CTRL0, 0x00000080U);
  49        writel(ZDMA_CH_WR_ONLY_WORD0, 0x00000000U);
  50        writel(ZDMA_CH_WR_ONLY_WORD1, 0x00000000U);
  51        writel(ZDMA_CH_WR_ONLY_WORD2, 0x00000000U);
  52        writel(ZDMA_CH_WR_ONLY_WORD3, 0x00000000U);
  53        writel(ZDMA_CH_DST_DSCR_WORD0, 0x00000000U);
  54        writel(ZDMA_CH_DST_DSCR_WORD1, 0x00000000U);
  55        writel(ZDMA_CH_SRC_DSCR_WORD2, 0x00000000U);
  56        writel(ZDMA_CH_DST_DSCR_WORD2, 0x00000000U);
  57        writel(ZDMA_CH_CTRL0_TOTAL_BYTE_COUNT, 0x00000000U);
  58}
  59
  60static void ecc_dram_bank_init(u64 addr, u64 len)
  61{
  62        bool retry = true;
  63        u32 timeout;
  64        u64 bytes;
  65        u32 size;
  66        u64 src;
  67        u32 reg;
  68
  69        if (!len)
  70                return;
  71retry:
  72        bytes = len;
  73        src = addr;
  74        ecc_zdma_restore();
  75        while (bytes > 0) {
  76                size = bytes > ZDMA_TRANSFER_MAX_LEN ?
  77                        ZDMA_TRANSFER_MAX_LEN : (u32)bytes;
  78
  79                /* Wait until the DMA is in idle state */
  80                timeout = ZDMA_IDLE_TIMEOUT_USEC;
  81                do {
  82                        udelay(1);
  83                        reg = readl(ZDMA_CH_STATUS);
  84                        reg &= ZDMA_CH_STATUS_STATE_MASK;
  85                        if (!timeout--) {
  86                                puts("error, ECC DMA failed to idle\n");
  87                                goto done;
  88                        }
  89
  90                } while ((reg != ZDMA_CH_STATUS_STATE_DONE) &&
  91                        (reg != ZDMA_CH_STATUS_STATE_ERR));
  92
  93                /* Enable Simple (Write Only) Mode */
  94                reg = readl(ZDMA_CH_CTRL0);
  95                reg &= (ZDMA_CH_CTRL0_POINT_TYPE_MASK |
  96                        ZDMA_CH_CTRL0_MODE_MASK);
  97                reg |= (ZDMA_CH_CTRL0_POINT_TYPE_NORMAL |
  98                        ZDMA_CH_CTRL0_MODE_WR_ONLY);
  99                writel(reg, ZDMA_CH_CTRL0);
 100
 101                /* Fill in the data to be written */
 102                writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD0);
 103                writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD1);
 104                writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD2);
 105                writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD3);
 106
 107                /* Write Destination Address */
 108                writel((u32)(src & ZDMA_CH_DST_DSCR_WORD0_LSB_MASK),
 109                       ZDMA_CH_DST_DSCR_WORD0);
 110                writel((u32)((src >> 32) & ZDMA_CH_DST_DSCR_WORD1_MSB_MASK),
 111                       ZDMA_CH_DST_DSCR_WORD1);
 112
 113                /* Size to be Transferred. Recommended to set both src and dest sizes */
 114                writel(size, ZDMA_CH_SRC_DSCR_WORD2);
 115                writel(size, ZDMA_CH_DST_DSCR_WORD2);
 116
 117                /* DMA Enable */
 118                reg = readl(ZDMA_CH_CTRL2);
 119                reg |= ZDMA_CH_CTRL2_EN_MASK;
 120                writel(reg, ZDMA_CH_CTRL2);
 121
 122                /* Check the status of the transfer by polling on DMA Done */
 123                timeout = ZDMA_DONE_TIMEOUT_USEC;
 124                do {
 125                        udelay(1);
 126                        reg = readl(ZDMA_CH_ISR);
 127                        reg &= ZDMA_CH_ISR_DMA_DONE_MASK;
 128                        if (!timeout--) {
 129                                puts("error, ECC DMA timeout\n");
 130                                goto done;
 131                        }
 132                } while (reg != ZDMA_CH_ISR_DMA_DONE_MASK);
 133
 134                /* Clear DMA status */
 135                reg = readl(ZDMA_CH_ISR);
 136                reg |= ZDMA_CH_ISR_DMA_DONE_MASK;
 137                writel(ZDMA_CH_ISR_DMA_DONE_MASK, ZDMA_CH_ISR);
 138
 139                /* Read the channel status for errors */
 140                reg = readl(ZDMA_CH_STATUS);
 141                if (reg == ZDMA_CH_STATUS_STATE_ERR) {
 142                        if (retry) {
 143                                retry = false;
 144                                goto retry;
 145                        }
 146                        puts("error, ECC DMA error\n");
 147                        break;
 148                }
 149
 150                bytes -= size;
 151                src += size;
 152        }
 153done:
 154        ecc_zdma_restore();
 155}
 156
 157void zynqmp_ecc_init(void)
 158{
 159        ecc_dram_bank_init(CONFIG_SPL_ZYNQMP_DRAM_BANK1_BASE,
 160                           CONFIG_SPL_ZYNQMP_DRAM_BANK1_LEN);
 161        ecc_dram_bank_init(CONFIG_SPL_ZYNQMP_DRAM_BANK2_BASE,
 162                           CONFIG_SPL_ZYNQMP_DRAM_BANK2_LEN);
 163}
 164