diff options
Diffstat (limited to 'drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c')
-rw-r--r-- | drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c | 1134 |
1 files changed, 728 insertions, 406 deletions
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c index 89318a48d9..334c2906fd 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c @@ -3,12 +3,6 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include <common.h> -#include <spl.h> -#include <asm/io.h> -#include <asm/arch/cpu.h> -#include <asm/arch/soc.h> - #include "ddr3_init.h" #define PATTERN_1 0x55555555 @@ -21,6 +15,7 @@ u32 phy_reg_bk[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; u32 training_res[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS * HWS_SEARCH_DIR_LIMIT]; +u8 byte_status[MAX_INTERFACE_NUM][MAX_BUS_NUM]; /* holds the bit status in the byte in wrapper function*/ u16 mask_results_dq_reg_map[] = { RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG, @@ -43,14 +38,39 @@ u16 mask_results_dq_reg_map[] = { RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, +#if MAX_BUS_NUM == 9 + RESULT_CONTROL_PUP_5_BIT_0_REG, RESULT_CONTROL_PUP_5_BIT_1_REG, + RESULT_CONTROL_PUP_5_BIT_2_REG, RESULT_CONTROL_PUP_5_BIT_3_REG, + RESULT_CONTROL_PUP_5_BIT_4_REG, RESULT_CONTROL_PUP_5_BIT_5_REG, + RESULT_CONTROL_PUP_5_BIT_6_REG, RESULT_CONTROL_PUP_5_BIT_7_REG, + RESULT_CONTROL_PUP_6_BIT_0_REG, RESULT_CONTROL_PUP_6_BIT_1_REG, + RESULT_CONTROL_PUP_6_BIT_2_REG, RESULT_CONTROL_PUP_6_BIT_3_REG, + RESULT_CONTROL_PUP_6_BIT_4_REG, RESULT_CONTROL_PUP_6_BIT_5_REG, + RESULT_CONTROL_PUP_6_BIT_6_REG, RESULT_CONTROL_PUP_6_BIT_7_REG, + RESULT_CONTROL_PUP_7_BIT_0_REG, RESULT_CONTROL_PUP_7_BIT_1_REG, + RESULT_CONTROL_PUP_7_BIT_2_REG, RESULT_CONTROL_PUP_7_BIT_3_REG, + RESULT_CONTROL_PUP_7_BIT_4_REG, RESULT_CONTROL_PUP_7_BIT_5_REG, + RESULT_CONTROL_PUP_7_BIT_6_REG, RESULT_CONTROL_PUP_7_BIT_7_REG, + RESULT_CONTROL_PUP_8_BIT_0_REG, RESULT_CONTROL_PUP_8_BIT_1_REG, + RESULT_CONTROL_PUP_8_BIT_2_REG, RESULT_CONTROL_PUP_8_BIT_3_REG, + RESULT_CONTROL_PUP_8_BIT_4_REG, RESULT_CONTROL_PUP_8_BIT_5_REG, + RESULT_CONTROL_PUP_8_BIT_6_REG, RESULT_CONTROL_PUP_8_BIT_7_REG, +#endif + 0xffff }; u16 mask_results_pup_reg_map[] = { RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG, RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_3_REG, - RESULT_CONTROL_BYTE_PUP_4_REG + RESULT_CONTROL_BYTE_PUP_4_REG, +#if MAX_BUS_NUM == 9 + RESULT_CONTROL_BYTE_PUP_5_REG, RESULT_CONTROL_BYTE_PUP_6_REG, + RESULT_CONTROL_BYTE_PUP_7_REG, RESULT_CONTROL_BYTE_PUP_8_REG, +#endif + 0xffff }; +#if MAX_BUS_NUM == 5 u16 mask_results_dq_reg_map_pup3_ecc[] = { RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG, RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG, @@ -68,17 +88,120 @@ u16 mask_results_dq_reg_map_pup3_ecc[] = { RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, - RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG, - RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, - RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, - RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, + RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG, + RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG, + RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG, + RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG }; +#endif +#if MAX_BUS_NUM == 5 u16 mask_results_pup_reg_map_pup3_ecc[] = { RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG, RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_4_REG, RESULT_CONTROL_BYTE_PUP_4_REG }; +#endif + +struct pattern_info pattern_table_64[] = { + /* + * num_of_phases_tx, tx_burst_size; + * delay_between_bursts, num_of_phases_rx, + * start_addr, pattern_len + */ + {0x7, 0x7, 2, 0x7, 0x00000, 8}, /* PATTERN_PBS1 */ + {0x7, 0x7, 2, 0x7, 0x00080, 8}, /* PATTERN_PBS2 */ + {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_PBS3 */ + {0x7, 0x7, 2, 0x7, 0x00030, 8}, /* PATTERN_TEST */ + {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_RL */ + {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_RL2 */ + {0x1f, 0xf, 2, 0xf, 0x00680, 32}, /* PATTERN_STATIC_PBS */ + {0x1f, 0xf, 2, 0xf, 0x00a80, 32}, /* PATTERN_KILLER_DQ0 */ + {0x1f, 0xf, 2, 0xf, 0x01280, 32}, /* PATTERN_KILLER_DQ1 */ + {0x1f, 0xf, 2, 0xf, 0x01a80, 32}, /* PATTERN_KILLER_DQ2 */ + {0x1f, 0xf, 2, 0xf, 0x02280, 32}, /* PATTERN_KILLER_DQ3 */ + {0x1f, 0xf, 2, 0xf, 0x02a80, 32}, /* PATTERN_KILLER_DQ4 */ + {0x1f, 0xf, 2, 0xf, 0x03280, 32}, /* PATTERN_KILLER_DQ5 */ + {0x1f, 0xf, 2, 0xf, 0x03a80, 32}, /* PATTERN_KILLER_DQ6 */ + {0x1f, 0xf, 2, 0xf, 0x04280, 32}, /* PATTERN_KILLER_DQ7 */ + {0x1f, 0xf, 2, 0xf, 0x00e80, 32}, /* PATTERN_KILLER_DQ0_64 */ + {0x1f, 0xf, 2, 0xf, 0x01680, 32}, /* PATTERN_KILLER_DQ1_64 */ + {0x1f, 0xf, 2, 0xf, 0x01e80, 32}, /* PATTERN_KILLER_DQ2_64 */ + {0x1f, 0xf, 2, 0xf, 0x02680, 32}, /* PATTERN_KILLER_DQ3_64 */ + {0x1f, 0xf, 2, 0xf, 0x02e80, 32}, /* PATTERN_KILLER_DQ4_64 */ + {0x1f, 0xf, 2, 0xf, 0x03680, 32}, /* PATTERN_KILLER_DQ5_64 */ + {0x1f, 0xf, 2, 0xf, 0x03e80, 32}, /* PATTERN_KILLER_DQ6_64 */ + {0x1f, 0xf, 2, 0xf, 0x04680, 32}, /* PATTERN_KILLER_DQ7_64 */ + {0x1f, 0xf, 2, 0xf, 0x04a80, 32}, /* PATTERN_KILLER_DQ0_INV */ + {0x1f, 0xf, 2, 0xf, 0x05280, 32}, /* PATTERN_KILLER_DQ1_INV */ + {0x1f, 0xf, 2, 0xf, 0x05a80, 32}, /* PATTERN_KILLER_DQ2_INV */ + {0x1f, 0xf, 2, 0xf, 0x06280, 32}, /* PATTERN_KILLER_DQ3_INV */ + {0x1f, 0xf, 2, 0xf, 0x06a80, 32}, /* PATTERN_KILLER_DQ4_INV */ + {0x1f, 0xf, 2, 0xf, 0x07280, 32}, /* PATTERN_KILLER_DQ5_INV */ + {0x1f, 0xf, 2, 0xf, 0x07a80, 32}, /* PATTERN_KILLER_DQ6_INV */ + {0x1f, 0xf, 2, 0xf, 0x08280, 32}, /* PATTERN_KILLER_DQ7_INV */ + {0x1f, 0xf, 2, 0xf, 0x04e80, 32}, /* PATTERN_KILLER_DQ0_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x05680, 32}, /* PATTERN_KILLER_DQ1_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x05e80, 32}, /* PATTERN_KILLER_DQ2_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x06680, 32}, /* PATTERN_KILLER_DQ3_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x06e80, 32}, /* PATTERN_KILLER_DQ4_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x07680, 32}, /* PATTERN_KILLER_DQ5_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x07e80, 32}, /* PATTERN_KILLER_DQ6_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x08680, 32}, /* PATTERN_KILLER_DQ7_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x08a80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0 */ + {0x1f, 0xf, 2, 0xf, 0x09280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0x1f, 0xf, 2, 0xf, 0x09a80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ + {0x1f, 0xf, 2, 0xf, 0x0a280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ + {0x1f, 0xf, 2, 0xf, 0x0aa80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ + {0x1f, 0xf, 2, 0xf, 0x0b280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ + {0x1f, 0xf, 2, 0xf, 0x0ba80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ + {0x1f, 0xf, 2, 0xf, 0x0c280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ + {0x1f, 0xf, 2, 0xf, 0x08e80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0_64 */ + {0x1f, 0xf, 2, 0xf, 0x09680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1_64 */ + {0x1f, 0xf, 2, 0xf, 0x09e80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2_64 */ + {0x1f, 0xf, 2, 0xf, 0x0a680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3_64 */ + {0x1f, 0xf, 2, 0xf, 0x0ae80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4_64 */ + {0x1f, 0xf, 2, 0xf, 0x0b680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5_64 */ + {0x1f, 0xf, 2, 0xf, 0x0be80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6_64 */ + {0x1f, 0xf, 2, 0xf, 0x0c680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7_64 */ + {0x1f, 0xf, 2, 0xf, 0x0ca80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ + {0x1f, 0xf, 2, 0xf, 0x0d280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ + {0x1f, 0xf, 2, 0xf, 0x0da80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ + {0x1f, 0xf, 2, 0xf, 0x0e280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ + {0x1f, 0xf, 2, 0xf, 0x0ea80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ + {0x1f, 0xf, 2, 0xf, 0x0f280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ + {0x1f, 0xf, 2, 0xf, 0x0fa80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ + {0x1f, 0xf, 2, 0xf, 0x10280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ + {0x1f, 0xf, 2, 0xf, 0x0ce80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0_64 */ + {0x1f, 0xf, 2, 0xf, 0x0d680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1_64 */ + {0x1f, 0xf, 2, 0xf, 0x0de80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2_64 */ + {0x1f, 0xf, 2, 0xf, 0x0e680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3_64 */ + {0x1f, 0xf, 2, 0xf, 0x0ee80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4_64 */ + {0x1f, 0xf, 2, 0xf, 0x0f680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5_64 */ + {0x1f, 0xf, 2, 0xf, 0x0fe80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6_64 */ + {0x1f, 0xf, 2, 0xf, 0x10680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7_64 */ + {0x1f, 0xf, 2, 0xf, 0x10a80, 32}, /* PATTERN_ISI_XTALK_FREE */ + {0x1f, 0xf, 2, 0xf, 0x10e80, 32}, /* PATTERN_ISI_XTALK_FREE_64 */ + {0x1f, 0xf, 2, 0xf, 0x11280, 32}, /* PATTERN_VREF */ + {0x1f, 0xf, 2, 0xf, 0x11680, 32}, /* PATTERN_VREF_64 */ + {0x1f, 0xf, 2, 0xf, 0x11a80, 32}, /* PATTERN_VREF_INV */ + {0x1f, 0xf, 2, 0xf, 0x11e80, 32}, /* PATTERN_FULL_SSO_0T */ + {0x1f, 0xf, 2, 0xf, 0x12280, 32}, /* PATTERN_FULL_SSO_1T */ + {0x1f, 0xf, 2, 0xf, 0x12680, 32}, /* PATTERN_FULL_SSO_2T */ + {0x1f, 0xf, 2, 0xf, 0x12a80, 32}, /* PATTERN_FULL_SSO_3T */ + {0x1f, 0xf, 2, 0xf, 0x12e80, 32}, /* PATTERN_RESONANCE_1T */ + {0x1f, 0xf, 2, 0xf, 0x13280, 32}, /* PATTERN_RESONANCE_2T */ + {0x1f, 0xf, 2, 0xf, 0x13680, 32}, /* PATTERN_RESONANCE_3T */ + {0x1f, 0xf, 2, 0xf, 0x13a80, 32}, /* PATTERN_RESONANCE_4T */ + {0x1f, 0xf, 2, 0xf, 0x13e80, 32}, /* PATTERN_RESONANCE_5T */ + {0x1f, 0xf, 2, 0xf, 0x14280, 32}, /* PATTERN_RESONANCE_6T */ + {0x1f, 0xf, 2, 0xf, 0x14680, 32}, /* PATTERN_RESONANCE_7T */ + {0x1f, 0xf, 2, 0xf, 0x14a80, 32}, /* PATTERN_RESONANCE_8T */ + {0x1f, 0xf, 2, 0xf, 0x14e80, 32}, /* PATTERN_RESONANCE_9T */ + {0x1f, 0xf, 2, 0xf, 0x15280, 32}, /* PATTERN_ZERO */ + {0x1f, 0xf, 2, 0xf, 0x15680, 32} /* PATTERN_ONE */ + /* Note: actual start_address is "<< 3" of defined address */ +}; struct pattern_info pattern_table_16[] = { /* @@ -87,7 +210,10 @@ struct pattern_info pattern_table_16[] = { */ {1, 1, 2, 1, 0x0080, 2}, /* PATTERN_PBS1 */ {1, 1, 2, 1, 0x00c0, 2}, /* PATTERN_PBS2 */ + {1, 1, 2, 1, 0x0380, 2}, /* PATTERN_PBS3 */ + {1, 1, 2, 1, 0x0040, 2}, /* PATTERN_TEST */ {1, 1, 2, 1, 0x0100, 2}, /* PATTERN_RL */ + {1, 1, 2, 1, 0x0000, 2}, /* PATTERN_RL2 */ {0xf, 0x7, 2, 0x7, 0x0140, 16}, /* PATTERN_STATIC_PBS */ {0xf, 0x7, 2, 0x7, 0x0190, 16}, /* PATTERN_KILLER_DQ0 */ {0xf, 0x7, 2, 0x7, 0x01d0, 16}, /* PATTERN_KILLER_DQ1 */ @@ -97,15 +223,29 @@ struct pattern_info pattern_table_16[] = { {0xf, 0x7, 2, 0x7, 0x02d0, 16}, /* PATTERN_KILLER_DQ5 */ {0xf, 0x7, 2, 0x7, 0x0310, 16}, /* PATTERN_KILLER_DQ6 */ {0xf, 0x7, 2, 0x7, 0x0350, 16}, /* PATTERN_KILLER_DQ7 */ - {1, 1, 2, 1, 0x0380, 2}, /* PATTERN_PBS3 */ - {1, 1, 2, 1, 0x0000, 2}, /* PATTERN_RL2 */ - {1, 1, 2, 1, 0x0040, 2}, /* PATTERN_TEST */ + {0xf, 0x7, 2, 0x7, 0x04c0, 16}, /* PATTERN_VREF */ {0xf, 0x7, 2, 0x7, 0x03c0, 16}, /* PATTERN_FULL_SSO_1T */ {0xf, 0x7, 2, 0x7, 0x0400, 16}, /* PATTERN_FULL_SSO_2T */ {0xf, 0x7, 2, 0x7, 0x0440, 16}, /* PATTERN_FULL_SSO_3T */ {0xf, 0x7, 2, 0x7, 0x0480, 16}, /* PATTERN_FULL_SSO_4T */ - {0xf, 0x7, 2, 0x7, 0x04c0, 16} /* PATTERN_VREF */ - /*Note: actual start_address is <<3 of defined addess */ + {0xf, 7, 2, 7, 0x6280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0xf, 7, 2, 7, 0x6680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0xf, 7, 2, 7, 0x6A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ + {0xf, 7, 2, 7, 0x6E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ + {0xf, 7, 2, 7, 0x7280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ + {0xf, 7, 2, 7, 0x7680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ + {0xf, 7, 2, 7, 0x7A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ + {0xf, 7, 2, 7, 0x7E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ + {0xf, 7, 2, 7, 0x8280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ + {0xf, 7, 2, 7, 0x8680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ + {0xf, 7, 2, 7, 0x8A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ + {0xf, 7, 2, 7, 0x8E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ + {0xf, 7, 2, 7, 0x9280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ + {0xf, 7, 2, 7, 0x9680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ + {0xf, 7, 2, 7, 0x9A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ + {0xf, 7, 2, 7, 0x9E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ + {0xf, 7, 2, 7, 0xA280, 16} /* PATTERN_ISI_XTALK_FREE */ + /* Note: actual start_address is "<< 3" of defined address */ }; struct pattern_info pattern_table_32[] = { @@ -115,7 +255,10 @@ struct pattern_info pattern_table_32[] = { */ {3, 3, 2, 3, 0x0080, 4}, /* PATTERN_PBS1 */ {3, 3, 2, 3, 0x00c0, 4}, /* PATTERN_PBS2 */ + {3, 3, 2, 3, 0x0380, 4}, /* PATTERN_PBS3 */ + {3, 3, 2, 3, 0x0040, 4}, /* PATTERN_TEST */ {3, 3, 2, 3, 0x0100, 4}, /* PATTERN_RL */ + {3, 3, 2, 3, 0x0000, 4}, /* PATTERN_RL2 */ {0x1f, 0xf, 2, 0xf, 0x0140, 32}, /* PATTERN_STATIC_PBS */ {0x1f, 0xf, 2, 0xf, 0x0190, 32}, /* PATTERN_KILLER_DQ0 */ {0x1f, 0xf, 2, 0xf, 0x01d0, 32}, /* PATTERN_KILLER_DQ1 */ @@ -125,15 +268,29 @@ struct pattern_info pattern_table_32[] = { {0x1f, 0xf, 2, 0xf, 0x02d0, 32}, /* PATTERN_KILLER_DQ5 */ {0x1f, 0xf, 2, 0xf, 0x0310, 32}, /* PATTERN_KILLER_DQ6 */ {0x1f, 0xf, 2, 0xf, 0x0350, 32}, /* PATTERN_KILLER_DQ7 */ - {3, 3, 2, 3, 0x0380, 4}, /* PATTERN_PBS3 */ - {3, 3, 2, 3, 0x0000, 4}, /* PATTERN_RL2 */ - {3, 3, 2, 3, 0x0040, 4}, /* PATTERN_TEST */ + {0x1f, 0xf, 2, 0xf, 0x04c0, 32}, /* PATTERN_VREF */ {0x1f, 0xf, 2, 0xf, 0x03c0, 32}, /* PATTERN_FULL_SSO_1T */ {0x1f, 0xf, 2, 0xf, 0x0400, 32}, /* PATTERN_FULL_SSO_2T */ {0x1f, 0xf, 2, 0xf, 0x0440, 32}, /* PATTERN_FULL_SSO_3T */ {0x1f, 0xf, 2, 0xf, 0x0480, 32}, /* PATTERN_FULL_SSO_4T */ - {0x1f, 0xf, 2, 0xf, 0x04c0, 32} /* PATTERN_VREF */ - /*Note: actual start_address is <<3 of defined addess */ + {0x1f, 0xF, 2, 0xf, 0x6280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0 */ + {0x1f, 0xF, 2, 0xf, 0x6680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0x1f, 0xF, 2, 0xf, 0x6A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ + {0x1f, 0xF, 2, 0xf, 0x6E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ + {0x1f, 0xF, 2, 0xf, 0x7280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ + {0x1f, 0xF, 2, 0xf, 0x7680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ + {0x1f, 0xF, 2, 0xf, 0x7A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ + {0x1f, 0xF, 2, 0xf, 0x7E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ + {0x1f, 0xF, 2, 0xf, 0x8280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ + {0x1f, 0xF, 2, 0xf, 0x8680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ + {0x1f, 0xF, 2, 0xf, 0x8A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ + {0x1f, 0xF, 2, 0xf, 0x8E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ + {0x1f, 0xF, 2, 0xf, 0x9280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ + {0x1f, 0xF, 2, 0xf, 0x9680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ + {0x1f, 0xF, 2, 0xf, 0x9A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ + {0x1f, 0xF, 2, 0xf, 0x9E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ + {0x1f, 0xF, 2, 0xf, 0xA280, 32} /* PATTERN_ISI_XTALK_FREE */ + /* Note: actual start_address is "<< 3" of defined address */ }; u32 train_dev_num; @@ -165,6 +322,10 @@ u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search, return buf_ptr; } +enum { + PASS, + FAIL +}; /* * IP Training search * Note: for one edge search only from fail to pass, else jitter can @@ -182,18 +343,19 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, enum hws_ddr_cs cs_type, u32 cs_num, enum hws_training_ip_stat *train_status) { - u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt, poll_cnt, + u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt, reg_data, pup_id; u32 tx_burst_size; u32 delay_between_burst; u32 rd_mode; - u32 read_data[MAX_INTERFACE_NUM]; + u32 data; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - if (pup_num >= tm->num_of_bus_per_interface) { + if (pup_num >= octets_per_if_num) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, ("pup_num %d not valid\n", pup_num)); } @@ -213,20 +375,20 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, /* All CSs to CS0 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - CS_ENABLE_REG, 1 << 3, 1 << 3)); + DUAL_DUNIT_CFG_REG, 1 << 3, 1 << 3)); /* All CSs to CS0 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_DATA_CONTROL_REG, + ODPG_DATA_CTRL_REG, (0x3 | (effective_cs << 26)), 0xc000003)); } else { CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - CS_ENABLE_REG, 0, 1 << 3)); + DUAL_DUNIT_CFG_REG, 0, 1 << 3)); /* CS select */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_DATA_CONTROL_REG, 0x3 | cs_num << 26, + ODPG_DATA_CTRL_REG, 0x3 | cs_num << 26, 0x3 | 3 << 26)); } @@ -248,7 +410,7 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, reg_data |= (direction == OPER_READ) ? 0x60 : 0xfa; CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_WRITE_READ_MODE_ENABLE_REG, reg_data, + ODPG_WR_RD_MODE_ENA_REG, reg_data, MASK_ALL_BITS)); reg_data = (edge_comp == EDGE_PF || edge_comp == EDGE_FP) ? 0 : 1 << 6; reg_data |= (edge_comp == EDGE_PF || edge_comp == EDGE_PFP) ? @@ -271,13 +433,13 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_TRAINING_CONTROL_REG, + GENERAL_TRAINING_OPCODE_REG, reg_data | (0x7 << 8) | (0x7 << 11), (0x3 | (0x3 << 2) | (0x3 << 6) | (1 << 5) | (0x7 << 8) | (0x7 << 11) | (0xf << 14) | (0x3 << 18) | (3 << 20)))); reg_data = (search_dir == HWS_LOW2HIGH) ? 0 : (1 << 8); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, interface_num, ODPG_OBJ1_OPCODE_REG, + (dev_num, access_type, interface_num, OPCODE_REG0_REG(1), 1 | reg_data | init_value << 9 | (1 << 25) | (1 << 26), 0xff | (1 << 8) | (0xffff << 9) | (1 << 25) | (1 << 26))); @@ -286,7 +448,7 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, * Max number of iterations */ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num, - ODPG_OBJ1_ITER_CNT_REG, num_iter, + OPCODE_REG1_REG(1), num_iter, 0xffff)); if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW && direction == OPER_READ) { @@ -294,12 +456,10 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, * Write2_dunit(0x10c0, 0x5f , [7:0]) * MC PBS Reg Address at DDR PHY */ - reg_data = 0x5f + - effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET; + reg_data = PBS_RX_BCAST_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW && direction == OPER_WRITE) { - reg_data = 0x1f + - effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET; + reg_data = PBS_TX_BCAST_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_ADLL && direction == OPER_WRITE) { /* @@ -310,11 +470,11 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, * Write2_dunit(0x10c0, 0x1 , [7:0]) * ADLL WR Reg Address at DDR PHY */ - reg_data = 1 + effective_cs * CS_REGISTER_ADDR_OFFSET; + reg_data = CTX_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_ADLL && direction == OPER_READ) { /* ADLL RD Reg Address at DDR PHY */ - reg_data = 3 + effective_cs * CS_REGISTER_ADDR_OFFSET; + reg_data = CRX_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW && direction == OPER_WRITE) { /* TBD not defined in 0.5.0 requirement */ @@ -325,12 +485,12 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, reg_data |= (0x6 << 28); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, interface_num, CALIB_OBJ_PRFA_REG, + (dev_num, access_type, interface_num, CAL_PHY_REG(1), reg_data | (init_value << 8), 0xff | (0xffff << 8) | (0xf << 24) | (u32) (0xf << 28))); - mask_dq_num_of_regs = tm->num_of_bus_per_interface * BUS_WIDTH_IN_BITS; - mask_pup_num_of_regs = tm->num_of_bus_per_interface; + mask_dq_num_of_regs = octets_per_if_num * BUS_WIDTH_IN_BITS; + mask_pup_num_of_regs = octets_per_if_num; if (result_type == RESULT_PER_BIT) { for (index_cnt = 0; index_cnt < mask_dq_num_of_regs; @@ -342,15 +502,12 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, } /* Mask disabled buses */ - for (pup_id = 0; pup_id < tm->num_of_bus_per_interface; + for (pup_id = 0; pup_id < octets_per_if_num; pup_id++) { - if (IS_ACTIVE(tm->bus_act_mask, pup_id) == 1) + if (IS_BUS_ACTIVE(tm->bus_act_mask, pup_id) == 1) continue; - for (index_cnt = (mask_dq_num_of_regs - pup_id * 8); - index_cnt < - (mask_dq_num_of_regs - (pup_id + 1) * 8); - index_cnt++) { + for (index_cnt = (pup_id * 8); index_cnt < (pup_id + 1) * 8; index_cnt++) { CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, @@ -384,89 +541,24 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, } } - /* Start Training Trigger */ - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num, - ODPG_TRAINING_TRIGGER_REG, 1, 1)); - /* wait for all RFU tests to finish (or timeout) */ - /* WA for 16 bit mode, more investigation needed */ - mdelay(1); - - /* Training "Done ?" */ - for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) { - if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0) - continue; - - if (interface_mask & (1 << index_cnt)) { - /* need to check results for this Dunit */ - for (poll_cnt = 0; poll_cnt < max_polling_for_done; - poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - index_cnt, - ODPG_TRAINING_STATUS_REG, - ®_data, MASK_ALL_BITS)); - if ((reg_data & 0x2) != 0) { - /*done */ - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_SUCCESS; - break; - } - } - - if (poll_cnt == max_polling_for_done) { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_TIMEOUT; - } - } - /* Be sure that ODPG done */ - CHECK_STATUS(is_odpg_access_done(dev_num, index_cnt)); - } - - /* Write ODPG done in Dunit */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_STATUS_DONE_REG, 0, 0x1)); + /* trigger training */ + mv_ddr_training_enable(); - /* wait for all Dunit tests to finish (or timeout) */ - /* Training "Done ?" */ - /* Training "Pass ?" */ - for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) { - if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0) - continue; - - if (interface_mask & (1 << index_cnt)) { - /* need to check results for this Dunit */ - for (poll_cnt = 0; poll_cnt < max_polling_for_done; - poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - index_cnt, - ODPG_TRAINING_TRIGGER_REG, - read_data, MASK_ALL_BITS)); - reg_data = read_data[index_cnt]; - if ((reg_data & 0x2) != 0) { - /* done */ - if ((reg_data & 0x4) == 0) { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_SUCCESS; - } else { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_FAIL; - } - break; - } - } + /* wa for 16-bit mode: wait for all rfu tests to finish or timeout */ + mdelay(1); - if (poll_cnt == max_polling_for_done) { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_TIMEOUT; - } - } + /* check for training done */ + if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) { + train_status[0] = HWS_TRAINING_IP_STATUS_TIMEOUT; + } else { /* training done; check for pass */ + if (data == PASS) + train_status[0] = HWS_TRAINING_IP_STATUS_SUCCESS; + else + train_status[0] = HWS_TRAINING_IP_STATUS_FAIL; } - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS)); + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); return MV_OK; } @@ -480,32 +572,47 @@ int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type, { u32 pattern_length_cnt = 0; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (pattern_length_cnt = 0; pattern_length_cnt < pattern_table[pattern].pattern_len; - pattern_length_cnt++) { - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - ODPG_PATTERN_DATA_LOW_REG, - pattern_table_get_word(dev_num, pattern, - (u8) (pattern_length_cnt * - 2)), MASK_ALL_BITS)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - ODPG_PATTERN_DATA_HI_REG, - pattern_table_get_word(dev_num, pattern, - (u8) (pattern_length_cnt * - 2 + 1)), - MASK_ALL_BITS)); + pattern_length_cnt++) { /* FIXME: the ecc patch below is only for a7040 A0 */ + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)/* || tm->bus_act_mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK*/) { + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_LOW_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt)), + MASK_ALL_BITS)); + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_HIGH_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt)), + MASK_ALL_BITS)); + } else { + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_LOW_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt * 2)), + MASK_ALL_BITS)); + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_HIGH_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt * 2 + 1)), + MASK_ALL_BITS)); + } CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - ODPG_PATTERN_ADDR_REG, pattern_length_cnt, + ODPG_DATA_WR_ADDR_REG, pattern_length_cnt, MASK_ALL_BITS)); } CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - ODPG_PATTERN_ADDR_OFFSET_REG, load_addr, MASK_ALL_BITS)); + ODPG_DATA_BUFFER_OFFS_REG, load_addr, MASK_ALL_BITS)); return MV_OK; } @@ -527,7 +634,7 @@ int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type, (rx_phases << 21) | (rd_mode << 25) | (cs_num << 26) | (addr_stress_jump << 29)); ret = ddr3_tip_if_write(dev_num, access_type, if_id, - ODPG_DATA_CONTROL_REG, data_value, 0xaffffffc); + ODPG_DATA_CTRL_REG, data_value, 0xaffffffc); if (ret != MV_OK) return ret; @@ -597,7 +704,8 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, u32 read_data[MAX_INTERFACE_NUM]; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * Agreed assumption: all CS mask contain same number of bits, @@ -605,11 +713,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, * all pups */ CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, CS_ENABLE_REG, + (dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG, (cs_num_type == 0) ? 1 << 3 : 0, (1 << 3))); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_DATA_CONTROL_REG, (cs_num_type << 26), (3 << 26))); + ODPG_DATA_CTRL_REG, (cs_num_type << 26), (3 << 26))); DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE, ("Read_from_d_b %d cs_type %d oper %d result_type %d direction %d search %d pup_num %d if_id %d pup_access_type %d\n", is_read_from_db, cs_num_type, operation, @@ -621,7 +729,7 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, ("ddr3_tip_read_training_result load_res = NULL")); return MV_FAIL; } - if (pup_num >= tm->num_of_bus_per_interface) { + if (pup_num >= octets_per_if_num) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, ("pup_num %d not valid\n", pup_num)); } @@ -639,11 +747,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, } else { /*pup_access_type == ACCESS_TYPE_MULTICAST) */ start_pup = 0; - end_pup = tm->num_of_bus_per_interface - 1; + end_pup = octets_per_if_num - 1; } for (pup_cnt = start_pup; pup_cnt <= end_pup; pup_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_cnt); DEBUG_TRAINING_IP_ENGINE( DEBUG_LEVEL_TRACE, ("if_id %d start_pup %d end_pup %d pup_cnt %d\n", @@ -689,11 +797,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, MASK_ALL_BITS)); if (is_check_result_validity == 1) { if ((read_data[if_id] & - 0x02000000) == 0) { + TIP_ENG_LOCK) == 0) { interface_train_res [reg_offset] = - 0x02000000 + - 64 + cons_tap; + TIP_ENG_LOCK + + TIP_TX_DLL_RANGE_MAX; } else { interface_train_res [reg_offset] = @@ -737,68 +845,35 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, int ddr3_tip_load_all_pattern_to_mem(u32 dev_num) { u32 pattern = 0, if_id; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); training_result[training_stage][if_id] = TEST_SUCCESS; } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } - for (pattern = 0; pattern < PATTERN_LIMIT; pattern++) + for (pattern = 0; pattern < PATTERN_LAST; pattern++) ddr3_tip_load_pattern_to_mem(dev_num, pattern); return MV_OK; } /* - * Wait till ODPG access is ready - */ -int is_odpg_access_done(u32 dev_num, u32 if_id) -{ - u32 poll_cnt = 0, data_value; - u32 read_data[MAX_INTERFACE_NUM]; - - for (poll_cnt = 0; poll_cnt < MAX_POLLING_ITERATIONS; poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_DONE, read_data, MASK_ALL_BITS)); - data_value = read_data[if_id]; - if (((data_value >> ODPG_BIST_DONE_BIT_OFFS) & 0x1) == - ODPG_BIST_DONE_BIT_VALUE) { - data_value = data_value & 0xfffffffe; - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, ODPG_BIST_DONE, data_value, - MASK_ALL_BITS)); - break; - } - } - - if (poll_cnt >= MAX_POLLING_ITERATIONS) { - DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, - ("Bist Activate: poll failure 2\n")); - return MV_FAIL; - } - - return MV_OK; -} - -/* * Load specific pattern to memory using ODPG */ int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern) { u32 reg_data, if_id; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* load pattern to memory */ /* @@ -813,57 +888,59 @@ int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern) (effective_cs << 26); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, reg_data, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, reg_data, MASK_ALL_BITS)); /* ODPG Write enable from BIST */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, (0x1 | (effective_cs << 26)), + ODPG_DATA_CTRL_REG, (0x1 | (effective_cs << 26)), 0xc000003)); /* disable error injection */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_DATA_ERROR_REG, 0, 0x1)); + ODPG_DATA_WR_DATA_ERR_REG, 0, 0x1)); /* load pattern to ODPG */ ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, pattern, pattern_table[pattern].start_addr); - for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - if (IS_ACTIVE(tm->if_act_mask, if_id) == 0) - continue; + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + SDRAM_ODT_CTRL_HIGH_REG, + 0x3, 0xf)); + } + + mv_ddr_odpg_enable(); + } else { CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1498, - 0x3, 0xf)); + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ODPG_DATA_CTRL_REG, (u32)(0x1 << 31), + (u32)(0x1 << 31))); } - - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_ENABLE_REG, 0x1 << ODPG_ENABLE_OFFS, - (0x1 << ODPG_ENABLE_OFFS))); - mdelay(1); - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - CHECK_STATUS(is_odpg_access_done(dev_num, if_id)); - } + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) + return MV_FAIL; /* Disable ODPG and stop write to memory */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, (0x1 << 30), (u32) (0x3 << 30))); + ODPG_DATA_CTRL_REG, (0x1 << 30), (u32) (0x3 << 30))); /* return to default */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS)); - - /* Disable odt0 for CS0 training - need to adjust for multy CS */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x1498, - 0x0, 0xf)); + ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + /* Disable odt0 for CS0 training - need to adjust for multy CS */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + SDRAM_ODT_CTRL_HIGH_REG, 0x0, 0xf)); + } /* temporary added */ mdelay(1); @@ -871,16 +948,6 @@ int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern) } /* - * Load specific pattern to memory using CPU - */ -int ddr3_tip_load_pattern_to_mem_by_cpu(u32 dev_num, enum hws_pattern pattern, - u32 offset) -{ - /* eranba - TBD */ - return MV_OK; -} - -/* * Training search routine */ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, @@ -902,8 +969,9 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, u32 interface_num = 0, start_if, end_if, init_value_used; enum hws_search_dir search_dir_id, start_search, end_search; enum hws_edge_compare edge_comp_used; - u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u8 cons_tap = 0; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (train_status == NULL) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, @@ -913,12 +981,12 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, if ((train_cs_type > CS_NON_SINGLE) || (edge_comp >= EDGE_PFP) || - (pattern >= PATTERN_LIMIT) || + (pattern >= PATTERN_LAST) || (direction > OPER_WRITE_AND_READ) || (search_dir > HWS_HIGH2LOW) || (control_element > HWS_CONTROL_ELEMENT_DQS_SKEW) || (result_type > RESULT_PER_BYTE) || - (pup_num >= tm->num_of_bus_per_interface) || + (pup_num >= octets_per_if_num) || (pup_access_type > ACCESS_TYPE_MULTICAST) || (if_id > 11) || (access_type > ACCESS_TYPE_MULTICAST)) { DEBUG_TRAINING_IP_ENGINE( @@ -968,7 +1036,7 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, for (interface_num = start_if; interface_num <= end_if; interface_num++) { - VALIDATE_ACTIVE(tm->if_act_mask, interface_num); + VALIDATE_IF_ACTIVE(tm->if_act_mask, interface_num); cs_num = 0; CHECK_STATUS(ddr3_tip_read_training_result (dev_num, interface_num, pup_access_type, @@ -982,48 +1050,99 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, return MV_OK; } - /* * Training search & read result routine + * This function implements the search algorithm + * first it calls the function ddr3_tip_ip_training_wrapper_int which triggers the search from l2h and h2l + * this function handles rx and tx search cases + * in case of rx it only triggers the search (l2h and h2l) + * in case of tx there are 3 optional algorithm phases: + * phase 1: + * it first triggers the search and handles the results as following (phase 1): + * each bit, which defined by the search two edges (e1 or VW_L and e2 or VW_H), match on of cases: + * 1. BIT_LOW_UI 0 =< VW =< 31 in case of jitter use: VW_L <= 31, VW_H <= 31 + * 2. BIT_HIGH_UI 32 =< VW =< 63 in case of jitter use: VW_L >= 32, VW_H >= 32 + * 3. BIT_SPLIT_IN VW_L <= 31 & VW_H >= 32 + * 4. BIT_SPLIT_OUT* VW_H < 32 & VW_L > 32 + * note: the VW units is adll taps + * phase 2: + * only bit case BIT_SPLIT_OUT requires another search (phase 2) from the middle range in two directions h2l and l2h + * because only this case is not locked by the search engine in the first search trigger (phase 1). + * phase 3: + * each subphy is categorized according to its bits definition. + * the sub-phy cases are as follows: + * 1.BYTE_NOT_DEFINED the byte has not yet been categorized + * 2.BYTE_HOMOGENEOUS_LOW 0 =< VW =< 31 + * 3.BYTE_HOMOGENEOUS_HIGH 32 =< VW =< 63 + * 4.BYTE_HOMOGENEOUS_SPLIT_IN VW_L <= 31 & VW_H >= 32 + * or the center of all bits in the byte =< 31 + * 5.BYTE_HOMOGENEOUS_SPLIT_OUT VW_H < 32 & VW_L > 32 + * 6.BYTE_SPLIT_OUT_MIX at least one bits is in split out state and one bit is in other + * or the center of all bits in the byte => 32 + * after the two phases above a center valid window for each subphy is calculated accordingly: + * center valid window = maximum center of all bits in the subphy - minimum center of all bits in the subphy. + * now decisions are made in each subphy as following: + * all subphys which are homogeneous remains as is + * all subphys which are homogeneous low | homogeneous high and the subphy center valid window is less than 32 + * mark this subphy as homogeneous split in. + * now the bits in the bytes which are BYTE_SPLIT_OUT_MIX needed to be reorganized and handles as following + * all bits which are BIT_LOW_UI will be added with 64 adll, + * this will hopefully ensures that all the bits in the sub phy can be sampled by the dqs */ int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type, - u32 if_id, - enum hws_access_type pup_access_type, - u32 pup_num, - enum hws_training_result result_type, - enum hws_control_element control_element, - enum hws_search_dir search_dir, - enum hws_dir direction, u32 interface_mask, - u32 init_value_l2h, u32 init_value_h2l, - u32 num_iter, enum hws_pattern pattern, - enum hws_edge_compare edge_comp, - enum hws_ddr_cs train_cs_type, u32 cs_num, - enum hws_training_ip_stat *train_status) + u32 if_id, + enum hws_access_type pup_access_type, + u32 pup_num, + enum hws_training_result result_type, + enum hws_control_element control_element, + enum hws_search_dir search_dir, + enum hws_dir direction, u32 interface_mask, + u32 init_value_l2h, u32 init_value_h2l, + u32 num_iter, enum hws_pattern pattern, + enum hws_edge_compare edge_comp, + enum hws_ddr_cs train_cs_type, u32 cs_num, + enum hws_training_ip_stat *train_status) { u8 e1, e2; - u32 interface_cnt, bit_id, start_if, end_if, bit_end = 0; + u32 bit_id, start_if, end_if, bit_end = 0; u32 *result[HWS_SEARCH_DIR_LIMIT] = { 0 }; u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0); u8 bit_bit_mask[MAX_BUS_NUM] = { 0 }, bit_bit_mask_active = 0; - u8 pup_id; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (pup_num >= tm->num_of_bus_per_interface) { + u8 bit_state[MAX_BUS_NUM * BUS_WIDTH_IN_BITS] = {0}; + u8 h2l_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; + u8 l2h_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; + u8 center_subphy_adll_window[MAX_BUS_NUM]; + u8 min_center_subphy_adll[MAX_BUS_NUM]; + u8 max_center_subphy_adll[MAX_BUS_NUM]; + u32 *l2h_if_train_res = NULL; + u32 *h2l_if_train_res = NULL; + enum hws_search_dir search_dir_id; + int status; + u32 bit_lock_result; + + u8 sybphy_id; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + if (pup_num >= octets_per_if_num) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, - ("pup_num %d not valid\n", pup_num)); + ("pup_num %d not valid\n", pup_num)); } if (if_id >= MAX_INTERFACE_NUM) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, - ("if_id %d not valid\n", if_id)); + ("if_id %d not valid\n", if_id)); } - CHECK_STATUS(ddr3_tip_ip_training_wrapper_int - (dev_num, access_type, if_id, pup_access_type, pup_num, - ALL_BITS_PER_PUP, result_type, control_element, - search_dir, direction, interface_mask, init_value_l2h, - init_value_h2l, num_iter, pattern, edge_comp, - train_cs_type, cs_num, train_status)); + status = ddr3_tip_ip_training_wrapper_int + (dev_num, access_type, if_id, pup_access_type, pup_num, + ALL_BITS_PER_PUP, result_type, control_element, + search_dir, direction, interface_mask, init_value_l2h, + init_value_h2l, num_iter, pattern, edge_comp, + train_cs_type, cs_num, train_status); + + if (MV_OK != status) + return status; if (access_type == ACCESS_TYPE_MULTICAST) { start_if = 0; @@ -1033,181 +1152,337 @@ int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type, end_if = if_id; } - for (interface_cnt = start_if; interface_cnt <= end_if; - interface_cnt++) { - VALIDATE_ACTIVE(tm->if_act_mask, interface_cnt); - for (pup_id = 0; - pup_id <= (tm->num_of_bus_per_interface - 1); pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); + for (if_id = start_if; if_id <= end_if; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + /* zero the database */ + bit_bit_mask_active = 0; /* clean the flag for level2 search */ + memset(bit_state, 0, sizeof(bit_state)); + /* phase 1 */ + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); if (result_type == RESULT_PER_BIT) - bit_end = BUS_WIDTH_IN_BITS - 1; + bit_end = BUS_WIDTH_IN_BITS; else bit_end = 0; - bit_bit_mask[pup_id] = 0; - for (bit_id = 0; bit_id <= bit_end; bit_id++) { - enum hws_search_dir search_dir_id; - for (search_dir_id = HWS_LOW2HIGH; - search_dir_id <= HWS_HIGH2LOW; - search_dir_id++) { - CHECK_STATUS - (ddr3_tip_read_training_result - (dev_num, interface_cnt, - ACCESS_TYPE_UNICAST, pup_id, - bit_id, search_dir_id, - direction, result_type, - TRAINING_LOAD_OPERATION_UNLOAD, - CS_SINGLE, - &result[search_dir_id], - 1, 0, 0)); + /* zero the data base */ + bit_bit_mask[sybphy_id] = 0; + byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED; + for (bit_id = 0; bit_id < bit_end; bit_id++) { + h2l_adll_value[sybphy_id][bit_id] = 64; + l2h_adll_value[sybphy_id][bit_id] = 0; + for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW; + search_dir_id++) { + status = ddr3_tip_read_training_result + (dev_num, if_id, + ACCESS_TYPE_UNICAST, sybphy_id, bit_id, + search_dir_id, direction, result_type, + TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, + &result[search_dir_id], 1, 0, 0); + + if (MV_OK != status) + return status; } - e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0], - EDGE_1); - e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0], - EDGE_1); - DEBUG_TRAINING_IP_ENGINE( - DEBUG_LEVEL_INFO, - ("wrapper if_id %d pup_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n", - interface_cnt, pup_id, bit_id, - result[HWS_LOW2HIGH][0], e1, + + e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0], EDGE_1); + e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0], EDGE_1); + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_INFO, + ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n", + if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1, result[HWS_HIGH2LOW][0], e2)); - /* TBD validate is valid only for tx */ - if (VALIDATE_TRAINING_LIMIT(e1, e2) == 1 && - GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) && - GET_LOCK_RESULT(result[HWS_LOW2HIGH][0])) { - /* Mark problem bits */ - bit_bit_mask[pup_id] |= 1 << bit_id; - bit_bit_mask_active = 1; + bit_lock_result = + (GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) && + GET_LOCK_RESULT(result[HWS_HIGH2LOW][0])); + + if (bit_lock_result) { + /* in case of read operation set the byte status as homogeneous low */ + if (direction == OPER_READ) { + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW; + } else if ((e2 - e1) > 32) { /* oper_write */ + /* split out */ + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_SPLIT_OUT; + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_SPLIT_OUT; + /* mark problem bits */ + bit_bit_mask[sybphy_id] |= (1 << bit_id); + bit_bit_mask_active = 1; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_SPLIT_OUT\n", + if_id, sybphy_id, bit_id)); + } else { + /* low ui */ + if (e1 <= 31 && e2 <= 31) { + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_LOW_UI; + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW; + l2h_adll_value[sybphy_id][bit_id] = e1; + h2l_adll_value[sybphy_id][bit_id] = e2; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_LOW_UI\n", + if_id, sybphy_id, bit_id)); + } + /* high ui */ + if (e1 >= 32 && e2 >= 32) { + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_HIGH_UI; + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_HIGH; + l2h_adll_value[sybphy_id][bit_id] = e1; + h2l_adll_value[sybphy_id][bit_id] = e2; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_HIGH_UI\n", + if_id, sybphy_id, bit_id)); + } + /* split in */ + if (e1 <= 31 && e2 >= 32) { + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_SPLIT_IN; + byte_status[if_id][sybphy_id] |= + BYTE_HOMOGENEOUS_SPLIT_IN; + l2h_adll_value[sybphy_id][bit_id] = e1; + h2l_adll_value[sybphy_id][bit_id] = e2; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_SPLIT_IN\n", + if_id, sybphy_id, bit_id)); + } + } + } else { + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_INFO, + ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x)" + "h2l 0x%x (e2 0x%x): bit cannot be categorized\n", + if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1, + result[HWS_HIGH2LOW][0], e2)); + /* mark the byte as not defined */ + byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED; + break; /* continue to next pup - no reason to analyze this byte */ } - } /* For all bits */ - } /* For all PUPs */ + } /* for all bits */ + } /* for all PUPs */ - /* Fix problem bits */ + /* phase 2 will occur only in write operation */ if (bit_bit_mask_active != 0) { - u32 *l2h_if_train_res = NULL; - u32 *h2l_if_train_res = NULL; - l2h_if_train_res = - ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH, - result_type, - interface_cnt); - h2l_if_train_res = - ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW, - result_type, - interface_cnt); - - ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST, - interface_cnt, - ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, result_type, - control_element, HWS_LOW2HIGH, - direction, interface_mask, - num_iter / 2, num_iter / 2, - pattern, EDGE_FP, train_cs_type, - cs_num, train_status); - - for (pup_id = 0; - pup_id <= (tm->num_of_bus_per_interface - 1); - pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); - - if (bit_bit_mask[pup_id] == 0) - continue; - - for (bit_id = 0; bit_id <= bit_end; bit_id++) { - if ((bit_bit_mask[pup_id] & - (1 << bit_id)) == 0) + l2h_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH, result_type, if_id); + h2l_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW, result_type, if_id); + /* search from middle to end */ + ddr3_tip_ip_training + (dev_num, ACCESS_TYPE_UNICAST, + if_id, ACCESS_TYPE_MULTICAST, + PARAM_NOT_CARE, result_type, + control_element, HWS_LOW2HIGH, + direction, interface_mask, + num_iter / 2, num_iter / 2, + pattern, EDGE_FP, train_cs_type, + cs_num, train_status); + + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) { + if (bit_bit_mask[sybphy_id] == 0) + continue; /* this byte bits have no split out state */ + + for (bit_id = 0; bit_id < bit_end; bit_id++) { + if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0) + continue; /* this bit is non split goto next bit */ + + /* enter the result to the data base */ + status = ddr3_tip_read_training_result + (dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id, + bit_id, HWS_LOW2HIGH, direction, result_type, + TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, + &l2h_if_train_res, 0, 0, 1); + + if (MV_OK != status) + return status; + + l2h_adll_value[sybphy_id][bit_id] = + l2h_if_train_res[sybphy_id * + BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK; + } + } + } + /* Search from middle to start */ + ddr3_tip_ip_training + (dev_num, ACCESS_TYPE_UNICAST, + if_id, ACCESS_TYPE_MULTICAST, + PARAM_NOT_CARE, result_type, + control_element, HWS_HIGH2LOW, + direction, interface_mask, + num_iter / 2, num_iter / 2, + pattern, EDGE_FP, train_cs_type, + cs_num, train_status); + + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) { + if (bit_bit_mask[sybphy_id] == 0) continue; - CHECK_STATUS - (ddr3_tip_read_training_result - (dev_num, interface_cnt, - ACCESS_TYPE_UNICAST, pup_id, - bit_id, HWS_LOW2HIGH, - direction, - result_type, - TRAINING_LOAD_OPERATION_UNLOAD, - CS_SINGLE, &l2h_if_train_res, - 0, 0, 1)); + + for (bit_id = 0; bit_id < bit_end; bit_id++) { + if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0) + continue; + + status = ddr3_tip_read_training_result + (dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id, + bit_id, HWS_HIGH2LOW, direction, result_type, + TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, + &h2l_if_train_res, 0, cons_tap, 1); + + if (MV_OK != status) + return status; + + h2l_adll_value[sybphy_id][bit_id] = + h2l_if_train_res[sybphy_id * + BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK; + } } } + } /* end if bit_bit_mask_active */ + /* + * phase 3 will occur only in write operation + * find the maximum and the minimum center of each subphy + */ + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + + if ((byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) && (direction == OPER_WRITE)) { + /* clear the arrays and parameters */ + center_subphy_adll_window[sybphy_id] = 0; + max_center_subphy_adll[sybphy_id] = 0; + min_center_subphy_adll[sybphy_id] = 64; + /* find the max and min center adll value in the current subphy */ + for (bit_id = 0; bit_id < bit_end; bit_id++) { + /* debug print all the bit edges after alignment */ + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d l2h %d h2l %d\n", + if_id, sybphy_id, bit_id, l2h_adll_value[sybphy_id][bit_id], + h2l_adll_value[sybphy_id][bit_id])); + + if (((l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2) > + max_center_subphy_adll[sybphy_id]) + max_center_subphy_adll[sybphy_id] = + (l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2; + if (((l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2) < + min_center_subphy_adll[sybphy_id]) + min_center_subphy_adll[sybphy_id] = + (l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2; + } - ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST, - interface_cnt, - ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, result_type, - control_element, HWS_HIGH2LOW, - direction, interface_mask, - num_iter / 2, num_iter / 2, - pattern, EDGE_FP, train_cs_type, - cs_num, train_status); - - for (pup_id = 0; - pup_id <= (tm->num_of_bus_per_interface - 1); - pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); - - if (bit_bit_mask[pup_id] == 0) - continue; - - for (bit_id = 0; bit_id <= bit_end; bit_id++) { - if ((bit_bit_mask[pup_id] & - (1 << bit_id)) == 0) - continue; - CHECK_STATUS - (ddr3_tip_read_training_result - (dev_num, interface_cnt, - ACCESS_TYPE_UNICAST, pup_id, - bit_id, HWS_HIGH2LOW, direction, - result_type, - TRAINING_LOAD_OPERATION_UNLOAD, - CS_SINGLE, &h2l_if_train_res, - 0, cons_tap, 1)); + /* calculate the center of the current subphy */ + center_subphy_adll_window[sybphy_id] = + max_center_subphy_adll[sybphy_id] - + min_center_subphy_adll[sybphy_id]; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d min center %d max center %d center %d\n", + if_id, sybphy_id, min_center_subphy_adll[sybphy_id], + max_center_subphy_adll[sybphy_id], + center_subphy_adll_window[sybphy_id])); + } + } + /* + * check byte state and fix bits state if needed + * in case the level 1 and 2 above subphy results are + * homogeneous continue to the next subphy + */ + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + if ((byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_LOW) || + (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_HIGH) || + (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_IN) || + (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_OUT) || + (byte_status[if_id][sybphy_id] == BYTE_NOT_DEFINED)) + continue; + + /* + * in case all of the bits in the current subphy are + * less than 32 which will find alignment in the subphy bits + * mark this subphy as homogeneous split in + */ + if (center_subphy_adll_window[sybphy_id] <= 31) + byte_status[if_id][sybphy_id] = BYTE_HOMOGENEOUS_SPLIT_IN; + + /* + * in case the current byte is split_out and the center is bigger than 31 + * the byte can be aligned. in this case add 64 to the the low ui bits aligning it + * to the other ui bits + */ + if (center_subphy_adll_window[sybphy_id] >= 32) { + byte_status[if_id][sybphy_id] = BYTE_SPLIT_OUT_MIX; + + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d byte state 0x%x\n", + if_id, sybphy_id, byte_status[if_id][sybphy_id])); + for (bit_id = 0; bit_id < bit_end; bit_id++) { + if (bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] == BIT_LOW_UI) { + l2h_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64; + h2l_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64; + } + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit_id %d added 64 adlls\n", + if_id, sybphy_id, bit_id)); } } - } /* if bit_bit_mask_active */ - } /* For all Interfacess */ + } + } /* for all interfaces */ return MV_OK; } +u8 mv_ddr_tip_sub_phy_byte_status_get(u32 if_id, u32 subphy_id) +{ + return byte_status[if_id][subphy_id]; +} + +void mv_ddr_tip_sub_phy_byte_status_set(u32 if_id, u32 subphy_id, u8 byte_status_data) +{ + byte_status[if_id][subphy_id] = byte_status_data; +} + /* * Load phy values */ int ddr3_tip_load_phy_values(int b_load) { u32 bus_cnt = 0, if_id, dev_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); - bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); if (b_load == 1) { CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CTX_PHY_REG(effective_cs), &phy_reg_bk[if_id][bus_cnt] [0])); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - RL_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + RL_PHY_REG(effective_cs), &phy_reg_bk[if_id][bus_cnt] [1])); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CRX_PHY_REG(effective_cs), &phy_reg_bk[if_id][bus_cnt] [2])); } else { @@ -1215,27 +1490,21 @@ int ddr3_tip_load_phy_values(int b_load) (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CTX_PHY_REG(effective_cs), phy_reg_bk[if_id][bus_cnt] [0])); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - RL_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + RL_PHY_REG(effective_cs), phy_reg_bk[if_id][bus_cnt] [1])); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CRX_PHY_REG(effective_cs), phy_reg_bk[if_id][bus_cnt] [2])); } @@ -1257,7 +1526,8 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM]; u32 *res = NULL; u32 search_state = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); ddr3_tip_load_phy_values(1); @@ -1279,11 +1549,11 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup_id = 0; pup_id < - tm->num_of_bus_per_interface; + octets_per_if_num; pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_id); CHECK_STATUS (ddr3_tip_read_training_result @@ -1322,11 +1592,20 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, return MV_OK; } +int mv_ddr_pattern_start_addr_set(struct pattern_info *pattern_tbl, enum hws_pattern pattern, u32 addr) +{ + pattern_tbl[pattern].start_addr = addr; + + return 0; +} + struct pattern_info *ddr3_tip_get_pattern_table() { - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) + return pattern_table_64; + else if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) return pattern_table_32; else return pattern_table_16; @@ -1334,20 +1613,63 @@ struct pattern_info *ddr3_tip_get_pattern_table() u16 *ddr3_tip_get_mask_results_dq_reg() { - struct hws_topology_map *tm = ddr3_get_topology_map(); +#if MAX_BUS_NUM == 5 + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) return mask_results_dq_reg_map_pup3_ecc; else +#endif return mask_results_dq_reg_map; } u16 *ddr3_tip_get_mask_results_pup_reg_map() { - struct hws_topology_map *tm = ddr3_get_topology_map(); +#if MAX_BUS_NUM == 5 + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) return mask_results_pup_reg_map_pup3_ecc; else +#endif return mask_results_pup_reg_map; } + +/* load expected dm pattern to odpg */ +#define LOW_NIBBLE_BYTE_MASK 0xf +#define HIGH_NIBBLE_BYTE_MASK 0xf0 +int mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type, enum hws_pattern pattern, + enum dm_direction dm_dir) +{ + struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 pattern_len = 0; + u32 data_low, data_high; + u8 dm_data; + + for (pattern_len = 0; + pattern_len < pattern_table[pattern].pattern_len; + pattern_len++) { + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) { + data_low = pattern_table_get_word(0, pattern, (u8)pattern_len); + data_high = data_low; + } else { + data_low = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2)); + data_high = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2 + 1)); + } + + /* odpg mbus dm definition is opposite to ddr4 protocol */ + if (dm_dir == DM_DIR_INVERSE) + dm_data = ~((data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK)); + else + dm_data = (data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK); + + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_LOW_REG, data_low, MASK_ALL_BITS); + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_HIGH_REG, data_high, MASK_ALL_BITS); + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_ADDR_REG, + pattern_len | ((dm_data & ODPG_DATA_WR_DATA_MASK) << ODPG_DATA_WR_DATA_OFFS), + MASK_ALL_BITS); + } + + return MV_OK; +} |