diff options
Diffstat (limited to 'drivers/ddr/mvebu/ddr3_sdram.c')
-rw-r--r-- | drivers/ddr/mvebu/ddr3_sdram.c | 669 |
1 files changed, 0 insertions, 669 deletions
diff --git a/drivers/ddr/mvebu/ddr3_sdram.c b/drivers/ddr/mvebu/ddr3_sdram.c deleted file mode 100644 index 50c1bf8361..0000000000 --- a/drivers/ddr/mvebu/ddr3_sdram.c +++ /dev/null @@ -1,669 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#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_hw_training.h" -#include "xor.h" -#include "xor_regs.h" - -static void ddr3_flush_l1_line(u32 line); - -extern u32 pbs_pattern[2][LEN_16BIT_PBS_PATTERN]; -extern u32 pbs_pattern_32b[2][LEN_PBS_PATTERN]; -#if defined(MV88F78X60) -extern u32 pbs_pattern_64b[2][LEN_PBS_PATTERN]; -#endif -extern u32 pbs_dq_mapping[PUP_NUM_64BIT][DQ_NUM]; - -#if defined(MV88F78X60) || defined(MV88F672X) -/* PBS locked dq (per pup) */ -u32 pbs_locked_dq[MAX_PUP_NUM][DQ_NUM] = { { 0 } }; -u32 pbs_locked_dm[MAX_PUP_NUM] = { 0 }; -u32 pbs_locked_value[MAX_PUP_NUM][DQ_NUM] = { { 0 } }; - -int per_bit_data[MAX_PUP_NUM][DQ_NUM]; -#endif - -static u32 sdram_data[LEN_KILLER_PATTERN] __aligned(32) = { 0 }; - -static struct crc_dma_desc dma_desc __aligned(32) = { 0 }; - -#define XOR_TIMEOUT 0x8000000 - -struct xor_channel_t { - struct crc_dma_desc *desc; - unsigned long desc_phys_addr; -}; - -#define XOR_CAUSE_DONE_MASK(chan) ((0x1 | 0x2) << (chan * 16)) - -void xor_waiton_eng(int chan) -{ - int timeout; - - timeout = 0; - while (!(reg_read(XOR_CAUSE_REG(XOR_UNIT(chan))) & - XOR_CAUSE_DONE_MASK(XOR_CHAN(chan)))) { - if (timeout > XOR_TIMEOUT) - goto timeout; - - timeout++; - } - - timeout = 0; - while (mv_xor_state_get(chan) != MV_IDLE) { - if (timeout > XOR_TIMEOUT) - goto timeout; - - timeout++; - } - - /* Clear int */ - reg_write(XOR_CAUSE_REG(XOR_UNIT(chan)), - ~(XOR_CAUSE_DONE_MASK(XOR_CHAN(chan)))); - -timeout: - return; -} - -static int special_compare_pattern(u32 uj) -{ - if ((uj == 30) || (uj == 31) || (uj == 61) || (uj == 62) || - (uj == 93) || (uj == 94) || (uj == 126) || (uj == 127)) - return 1; - - return 0; -} - -/* - * Compare code extracted as its used by multiple functions. This - * reduces code-size and makes it easier to maintain it. Additionally - * the code is not indented that much and therefore easier to read. - */ -static void compare_pattern_v1(u32 uj, u32 *pup, u32 *pattern, - u32 pup_groups, int debug_dqs) -{ - u32 val; - u32 uk; - u32 var1; - u32 var2; - __maybe_unused u32 dq; - - if (((sdram_data[uj]) != (pattern[uj])) && (*pup != 0xFF)) { - for (uk = 0; uk < PUP_NUM_32BIT; uk++) { - val = CMP_BYTE_SHIFT * uk; - var1 = ((sdram_data[uj] >> val) & CMP_BYTE_MASK); - var2 = ((pattern[uj] >> val) & CMP_BYTE_MASK); - - if (var1 != var2) { - *pup |= (1 << (uk + (PUP_NUM_32BIT * - (uj % pup_groups)))); - -#ifdef MV_DEBUG_DQS - if (!debug_dqs) - continue; - - for (dq = 0; dq < DQ_NUM; dq++) { - val = uk + (PUP_NUM_32BIT * - (uj % pup_groups)); - if (((var1 >> dq) & 0x1) != - ((var2 >> dq) & 0x1)) - per_bit_data[val][dq] = 1; - else - per_bit_data[val][dq] = 0; - } -#endif - } - } - } -} - -static void compare_pattern_v2(u32 uj, u32 *pup, u32 *pattern) -{ - u32 val; - u32 uk; - u32 var1; - u32 var2; - - if (((sdram_data[uj]) != (pattern[uj])) && (*pup != 0x3)) { - /* Found error */ - for (uk = 0; uk < PUP_NUM_32BIT; uk++) { - val = CMP_BYTE_SHIFT * uk; - var1 = (sdram_data[uj] >> val) & CMP_BYTE_MASK; - var2 = (pattern[uj] >> val) & CMP_BYTE_MASK; - if (var1 != var2) - *pup |= (1 << (uk % PUP_NUM_16BIT)); - } - } -} - -/* - * Name: ddr3_sdram_compare - * Desc: Execute compare per PUP - * Args: unlock_pup Bit array of the unlock pups - * new_locked_pup Output bit array of the pups with failed compare - * pattern Pattern to compare - * pattern_len Length of pattern (in bytes) - * sdram_offset offset address to the SDRAM - * write write to the SDRAM before read - * mask compare pattern with mask; - * mask_pattern Mask to compare pattern - * - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_sdram_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup, - u32 *new_locked_pup, u32 *pattern, - u32 pattern_len, u32 sdram_offset, int write, - int mask, u32 *mask_pattern, - int special_compare) -{ - u32 uj; - __maybe_unused u32 pup_groups; - __maybe_unused u32 dq; - -#if !defined(MV88F67XX) - if (dram_info->num_of_std_pups == PUP_NUM_64BIT) - pup_groups = 2; - else - pup_groups = 1; -#endif - - ddr3_reset_phy_read_fifo(); - - /* Check if need to write to sdram before read */ - if (write == 1) - ddr3_dram_sram_burst((u32)pattern, sdram_offset, pattern_len); - - ddr3_dram_sram_burst(sdram_offset, (u32)sdram_data, pattern_len); - - /* Compare read result to write */ - for (uj = 0; uj < pattern_len; uj++) { - if (special_compare && special_compare_pattern(uj)) - continue; - -#if defined(MV88F78X60) || defined(MV88F672X) - compare_pattern_v1(uj, new_locked_pup, pattern, pup_groups, 1); -#elif defined(MV88F67XX) - compare_pattern_v2(uj, new_locked_pup, pattern); -#endif - } - - return MV_OK; -} - -#if defined(MV88F78X60) || defined(MV88F672X) -/* - * Name: ddr3_sdram_dm_compare - * Desc: Execute compare per PUP - * Args: unlock_pup Bit array of the unlock pups - * new_locked_pup Output bit array of the pups with failed compare - * pattern Pattern to compare - * pattern_len Length of pattern (in bytes) - * sdram_offset offset address to the SDRAM - * write write to the SDRAM before read - * mask compare pattern with mask; - * mask_pattern Mask to compare pattern - * - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_sdram_dm_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup, - u32 *new_locked_pup, u32 *pattern, - u32 sdram_offset) -{ - u32 uj, uk, var1, var2, pup_groups; - u32 val; - u32 pup = 0; - - if (dram_info->num_of_std_pups == PUP_NUM_64BIT) - pup_groups = 2; - else - pup_groups = 1; - - ddr3_dram_sram_burst((u32)pattern, SDRAM_PBS_TX_OFFS, - LEN_PBS_PATTERN); - ddr3_dram_sram_burst(SDRAM_PBS_TX_OFFS, (u32)sdram_data, - LEN_PBS_PATTERN); - - /* Validate the correctness of the results */ - for (uj = 0; uj < LEN_PBS_PATTERN; uj++) - compare_pattern_v1(uj, &pup, pattern, pup_groups, 0); - - /* Test the DM Signals */ - *(u32 *)(SDRAM_PBS_TX_OFFS + 0x10) = 0x12345678; - *(u32 *)(SDRAM_PBS_TX_OFFS + 0x14) = 0x12345678; - - sdram_data[0] = *(u32 *)(SDRAM_PBS_TX_OFFS + 0x10); - sdram_data[1] = *(u32 *)(SDRAM_PBS_TX_OFFS + 0x14); - - for (uj = 0; uj < 2; uj++) { - if (((sdram_data[uj]) != (pattern[uj])) && - (*new_locked_pup != 0xFF)) { - for (uk = 0; uk < PUP_NUM_32BIT; uk++) { - val = CMP_BYTE_SHIFT * uk; - var1 = ((sdram_data[uj] >> val) & CMP_BYTE_MASK); - var2 = ((pattern[uj] >> val) & CMP_BYTE_MASK); - if (var1 != var2) { - *new_locked_pup |= (1 << (uk + - (PUP_NUM_32BIT * (uj % pup_groups)))); - *new_locked_pup |= pup; - } - } - } - } - - return MV_OK; -} - -/* - * Name: ddr3_sdram_pbs_compare - * Desc: Execute SRAM compare per PUP and DQ. - * Args: pup_locked bit array of locked pups - * is_tx Indicate whether Rx or Tx - * pbs_pattern_idx Index of PBS pattern - * pbs_curr_val The PBS value - * pbs_lock_val The value to set to locked PBS - * skew_array Global array to update with the compare results - * ai_unlock_pup_dq_array bit array of the locked / unlocked pups per dq. - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_sdram_pbs_compare(MV_DRAM_INFO *dram_info, u32 pup_locked, - int is_tx, u32 pbs_pattern_idx, - u32 pbs_curr_val, u32 pbs_lock_val, - u32 *skew_array, u8 *unlock_pup_dq_array, - u32 ecc) -{ - /* bit array failed dq per pup for current compare */ - u32 pbs_write_pup[DQ_NUM] = { 0 }; - u32 update_pup; /* pup as HW convention */ - u32 max_pup; /* maximal pup index */ - u32 pup_addr; - u32 ui, dq, pup; - int var1, var2; - u32 sdram_offset, pup_groups, tmp_pup; - u32 *pattern_ptr; - u32 val; - - /* Choose pattern */ - switch (dram_info->ddr_width) { -#if defined(MV88F672X) - case 16: - pattern_ptr = (u32 *)&pbs_pattern[pbs_pattern_idx]; - break; -#endif - case 32: - pattern_ptr = (u32 *)&pbs_pattern_32b[pbs_pattern_idx]; - break; -#if defined(MV88F78X60) - case 64: - pattern_ptr = (u32 *)&pbs_pattern_64b[pbs_pattern_idx]; - break; -#endif - default: - return MV_FAIL; - } - - max_pup = dram_info->num_of_std_pups; - - sdram_offset = SDRAM_PBS_I_OFFS + pbs_pattern_idx * SDRAM_PBS_NEXT_OFFS; - - if (dram_info->num_of_std_pups == PUP_NUM_64BIT) - pup_groups = 2; - else - pup_groups = 1; - - ddr3_reset_phy_read_fifo(); - - /* Check if need to write to sdram before read */ - if (is_tx == 1) { - ddr3_dram_sram_burst((u32)pattern_ptr, sdram_offset, - LEN_PBS_PATTERN); - } - - ddr3_dram_sram_read(sdram_offset, (u32)sdram_data, LEN_PBS_PATTERN); - - /* Compare read result to write */ - for (ui = 0; ui < LEN_PBS_PATTERN; ui++) { - if ((sdram_data[ui]) != (pattern_ptr[ui])) { - /* found error */ - /* error in low pup group */ - for (pup = 0; pup < PUP_NUM_32BIT; pup++) { - val = CMP_BYTE_SHIFT * pup; - var1 = ((sdram_data[ui] >> val) & - CMP_BYTE_MASK); - var2 = ((pattern_ptr[ui] >> val) & - CMP_BYTE_MASK); - - if (var1 != var2) { - if (dram_info->ddr_width > 16) { - tmp_pup = (pup + PUP_NUM_32BIT * - (ui % pup_groups)); - } else { - tmp_pup = (pup % PUP_NUM_16BIT); - } - - update_pup = (1 << tmp_pup); - if (ecc && (update_pup != 0x1)) - continue; - - /* - * Pup is failed - Go over all DQs and - * look for failures - */ - for (dq = 0; dq < DQ_NUM; dq++) { - val = tmp_pup * (1 - ecc) + - ecc * ECC_PUP; - if (((var1 >> dq) & 0x1) != - ((var2 >> dq) & 0x1)) { - if (pbs_locked_dq[val][dq] == 1 && - pbs_locked_value[val][dq] != pbs_curr_val) - continue; - - /* - * Activate write to - * update PBS to - * pbs_lock_val - */ - pbs_write_pup[dq] |= - update_pup; - - /* - * Update the - * unlock_pup_dq_array - */ - unlock_pup_dq_array[dq] &= - ~update_pup; - - /* - * Lock PBS value for - * failed bits in - * compare operation - */ - skew_array[tmp_pup * DQ_NUM + dq] = - pbs_curr_val; - } - } - } - } - } - } - - pup_addr = (is_tx == 1) ? PUP_PBS_TX : PUP_PBS_RX; - - /* Set last failed bits PBS to min / max pbs value */ - for (dq = 0; dq < DQ_NUM; dq++) { - for (pup = 0; pup < max_pup; pup++) { - if (pbs_write_pup[dq] & (1 << pup)) { - val = pup * (1 - ecc) + ecc * ECC_PUP; - if (pbs_locked_dq[val][dq] == 1 && - pbs_locked_value[val][dq] != pbs_curr_val) - continue; - - /* Mark the dq as locked */ - pbs_locked_dq[val][dq] = 1; - pbs_locked_value[val][dq] = pbs_curr_val; - ddr3_write_pup_reg(pup_addr + - pbs_dq_mapping[val][dq], - CS0, val, 0, pbs_lock_val); - } - } - } - - return MV_OK; -} -#endif - -/* - * Name: ddr3_sdram_direct_compare - * Desc: Execute compare per PUP without DMA (no burst mode) - * Args: unlock_pup Bit array of the unlock pups - * new_locked_pup Output bit array of the pups with failed compare - * pattern Pattern to compare - * pattern_len Length of pattern (in bytes) - * sdram_offset offset address to the SDRAM - * write write to the SDRAM before read - * mask compare pattern with mask; - * auiMaskPatter Mask to compare pattern - * - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_sdram_direct_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup, - u32 *new_locked_pup, u32 *pattern, - u32 pattern_len, u32 sdram_offset, - int write, int mask, u32 *mask_pattern) -{ - u32 uj, uk, pup_groups; - u32 *sdram_addr; /* used to read from SDRAM */ - - sdram_addr = (u32 *)sdram_offset; - - if (dram_info->num_of_std_pups == PUP_NUM_64BIT) - pup_groups = 2; - else - pup_groups = 1; - - /* Check if need to write before read */ - if (write == 1) { - for (uk = 0; uk < pattern_len; uk++) { - *sdram_addr = pattern[uk]; - sdram_addr++; - } - } - - sdram_addr = (u32 *)sdram_offset; - - for (uk = 0; uk < pattern_len; uk++) { - sdram_data[uk] = *sdram_addr; - sdram_addr++; - } - - /* Compare read result to write */ - for (uj = 0; uj < pattern_len; uj++) { - if (dram_info->ddr_width > 16) { - compare_pattern_v1(uj, new_locked_pup, pattern, - pup_groups, 0); - } else { - compare_pattern_v2(uj, new_locked_pup, pattern); - } - } - - return MV_OK; -} - -/* - * Name: ddr3_dram_sram_burst - * Desc: Read from the SDRAM in burst of 64 bytes - * Args: src - * dst - * Notes: Using the XOR mechanism - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_dram_sram_burst(u32 src, u32 dst, u32 len) -{ - u32 chan, byte_count, cs_num, byte; - struct xor_channel_t channel; - - chan = 0; - byte_count = len * 4; - - /* Wait for previous transfer completion */ - while (mv_xor_state_get(chan) != MV_IDLE) - ; - - /* Build the channel descriptor */ - channel.desc = &dma_desc; - - /* Enable Address Override and set correct src and dst */ - if (src < SRAM_BASE) { - /* src is DRAM CS, dst is SRAM */ - cs_num = (src / (1 + SDRAM_CS_SIZE)); - reg_write(XOR_ADDR_OVRD_REG(0, 0), - ((cs_num << 1) | (1 << 0))); - channel.desc->src_addr0 = (src % (1 + SDRAM_CS_SIZE)); - channel.desc->dst_addr = dst; - } else { - /* src is SRAM, dst is DRAM CS */ - cs_num = (dst / (1 + SDRAM_CS_SIZE)); - reg_write(XOR_ADDR_OVRD_REG(0, 0), - ((cs_num << 25) | (1 << 24))); - channel.desc->src_addr0 = (src); - channel.desc->dst_addr = (dst % (1 + SDRAM_CS_SIZE)); - channel.desc->src_addr0 = src; - channel.desc->dst_addr = (dst % (1 + SDRAM_CS_SIZE)); - } - - channel.desc->src_addr1 = 0; - channel.desc->byte_cnt = byte_count; - channel.desc->next_desc_ptr = 0; - channel.desc->status = 1 << 31; - channel.desc->desc_cmd = 0x0; - channel.desc_phys_addr = (unsigned long)&dma_desc; - - ddr3_flush_l1_line((u32)&dma_desc); - - /* Issue the transfer */ - if (mv_xor_transfer(chan, MV_DMA, channel.desc_phys_addr) != MV_OK) - return MV_FAIL; - - /* Wait for completion */ - xor_waiton_eng(chan); - - if (dst > SRAM_BASE) { - for (byte = 0; byte < byte_count; byte += 0x20) - cache_inv(dst + byte); - } - - return MV_OK; -} - -/* - * Name: ddr3_flush_l1_line - * Desc: - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -static void ddr3_flush_l1_line(u32 line) -{ - u32 reg; - -#if defined(MV88F672X) - reg = 1; -#else - reg = reg_read(REG_SAMPLE_RESET_LOW_ADDR) & - (1 << REG_SAMPLE_RESET_CPU_ARCH_OFFS); -#ifdef MV88F67XX - reg = ~reg & (1 << REG_SAMPLE_RESET_CPU_ARCH_OFFS); -#endif -#endif - - if (reg) { - /* V7 Arch mode */ - flush_l1_v7(line); - flush_l1_v7(line + CACHE_LINE_SIZE); - } else { - /* V6 Arch mode */ - flush_l1_v6(line); - flush_l1_v6(line + CACHE_LINE_SIZE); - } -} - -int ddr3_dram_sram_read(u32 src, u32 dst, u32 len) -{ - u32 ui; - u32 *dst_ptr, *src_ptr; - - dst_ptr = (u32 *)dst; - src_ptr = (u32 *)src; - - for (ui = 0; ui < len; ui++) { - *dst_ptr = *src_ptr; - dst_ptr++; - src_ptr++; - } - - return MV_OK; -} - -int ddr3_sdram_dqs_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup, - u32 *new_locked_pup, u32 *pattern, - u32 pattern_len, u32 sdram_offset, int write, - int mask, u32 *mask_pattern, - int special_compare) -{ - u32 uj, pup_groups; - - if (dram_info->num_of_std_pups == PUP_NUM_64BIT) - pup_groups = 2; - else - pup_groups = 1; - - ddr3_reset_phy_read_fifo(); - - /* Check if need to write to sdram before read */ - if (write == 1) - ddr3_dram_sram_burst((u32)pattern, sdram_offset, pattern_len); - - ddr3_dram_sram_burst(sdram_offset, (u32)sdram_data, pattern_len); - - /* Compare read result to write */ - for (uj = 0; uj < pattern_len; uj++) { - if (special_compare && special_compare_pattern(uj)) - continue; - - if (dram_info->ddr_width > 16) { - compare_pattern_v1(uj, new_locked_pup, pattern, - pup_groups, 1); - } else { - compare_pattern_v2(uj, new_locked_pup, pattern); - } - } - - return MV_OK; -} - -void ddr3_reset_phy_read_fifo(void) -{ - u32 reg; - - /* reset read FIFO */ - reg = reg_read(REG_DRAM_TRAINING_ADDR); - /* Start Auto Read Leveling procedure */ - reg |= (1 << REG_DRAM_TRAINING_RL_OFFS); - - /* 0x15B0 - Training Register */ - reg_write(REG_DRAM_TRAINING_ADDR, reg); - - reg = reg_read(REG_DRAM_TRAINING_2_ADDR); - reg |= ((1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS) + - (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS)); - - /* [0] = 1 - Enable SW override, [4] = 1 - FIFO reset */ - /* 0x15B8 - Training SW 2 Register */ - reg_write(REG_DRAM_TRAINING_2_ADDR, reg); - - do { - reg = reg_read(REG_DRAM_TRAINING_2_ADDR) & - (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS); - } while (reg); /* Wait for '0' */ - - reg = reg_read(REG_DRAM_TRAINING_ADDR); - - /* Clear Auto Read Leveling procedure */ - reg &= ~(1 << REG_DRAM_TRAINING_RL_OFFS); - - /* 0x15B0 - Training Register */ - reg_write(REG_DRAM_TRAINING_ADDR, reg); -} |