mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-14 15:23:07 +00:00
08dcbc9823
Based on the JEDEC standard JESD79-3F. The tRAS timings should include the highest speed bins at a given frequency. This is similar to commit 683c67b ("mv_ddr: ddr3: fix tfaw timimg parameter") where the wrong comparison was used in the initial implementation. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> [https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell/pull/15] Signed-off-by: Chris Packham <judge.packham@gmail.com> Signed-off-by: Stefan Roese <sr@denx.de>
871 lines
20 KiB
C
871 lines
20 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) Marvell International Ltd. and its affiliates
|
|
*/
|
|
|
|
#include "ddr_ml_wrapper.h"
|
|
|
|
#include "ddr3_training_ip_flow.h"
|
|
#include "mv_ddr_topology.h"
|
|
#include "mv_ddr_training_db.h"
|
|
#include "ddr3_training_ip_db.h"
|
|
|
|
/* Device attributes structures */
|
|
enum mv_ddr_dev_attribute ddr_dev_attributes[MV_ATTR_LAST];
|
|
int ddr_dev_attr_init_done = 0;
|
|
|
|
static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index);
|
|
static inline u32 pattern_table_get_sso_word(u8 sso, u8 index);
|
|
static inline u32 pattern_table_get_vref_word(u8 index);
|
|
static inline u32 pattern_table_get_vref_word16(u8 index);
|
|
static inline u32 pattern_table_get_sso_full_xtalk_word(u8 bit, u8 index);
|
|
static inline u32 pattern_table_get_sso_full_xtalk_word16(u8 bit, u8 index);
|
|
static inline u32 pattern_table_get_sso_xtalk_free_word(u8 bit, u8 index);
|
|
static inline u32 pattern_table_get_sso_xtalk_free_word16(u8 bit, u8 index);
|
|
static inline u32 pattern_table_get_isi_word(u8 index);
|
|
static inline u32 pattern_table_get_isi_word16(u8 index);
|
|
|
|
/* List of allowed frequency listed in order of enum mv_ddr_freq */
|
|
static unsigned int freq_val[MV_DDR_FREQ_LAST] = {
|
|
0, /*MV_DDR_FREQ_LOW_FREQ */
|
|
400, /*MV_DDR_FREQ_400, */
|
|
533, /*MV_DDR_FREQ_533, */
|
|
666, /*MV_DDR_FREQ_667, */
|
|
800, /*MV_DDR_FREQ_800, */
|
|
933, /*MV_DDR_FREQ_933, */
|
|
1066, /*MV_DDR_FREQ_1066, */
|
|
311, /*MV_DDR_FREQ_311, */
|
|
333, /*MV_DDR_FREQ_333, */
|
|
467, /*MV_DDR_FREQ_467, */
|
|
850, /*MV_DDR_FREQ_850, */
|
|
600, /*MV_DDR_FREQ_600 */
|
|
300, /*MV_DDR_FREQ_300 */
|
|
900, /*MV_DDR_FREQ_900 */
|
|
360, /*MV_DDR_FREQ_360 */
|
|
1000 /*MV_DDR_FREQ_1000 */
|
|
};
|
|
|
|
unsigned int *mv_ddr_freq_tbl_get(void)
|
|
{
|
|
return &freq_val[0];
|
|
}
|
|
|
|
u32 mv_ddr_freq_get(enum mv_ddr_freq freq)
|
|
{
|
|
return freq_val[freq];
|
|
}
|
|
|
|
/* cas latency values per frequency for each speed bin index */
|
|
static struct mv_ddr_cl_val_per_freq cl_table[] = {
|
|
/*
|
|
* 400M 667M 933M 311M 467M 600M 360
|
|
* 100M 533M 800M 1066M 333M 850M 900
|
|
* 1000 (the order is 100, 400, 533 etc.)
|
|
*/
|
|
/* DDR3-800D */
|
|
{ {6, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
|
|
/* DDR3-800E */
|
|
{ {6, 6, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 6, 0, 6, 0} },
|
|
/* DDR3-1066E */
|
|
{ {6, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 0, 5, 0, 5, 0} },
|
|
/* DDR3-1066F */
|
|
{ {6, 6, 7, 0, 0, 0, 0, 6, 6, 7, 0, 0, 6, 0, 6, 0} },
|
|
/* DDR3-1066G */
|
|
{ {6, 6, 8, 0, 0, 0, 0, 6, 6, 8, 0, 0, 6, 0, 6, 0} },
|
|
/* DDR3-1333F* */
|
|
{ {6, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1333G */
|
|
{ {6, 5, 7, 8, 0, 0, 0, 5, 5, 7, 0, 8, 5, 0, 5, 0} },
|
|
/* DDR3-1333H */
|
|
{ {6, 6, 8, 9, 0, 0, 0, 6, 6, 8, 0, 9, 6, 0, 6, 0} },
|
|
/* DDR3-1333J* */
|
|
{ {6, 6, 8, 10, 0, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0}
|
|
/* DDR3-1600G* */},
|
|
{ {6, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1600H */
|
|
{ {6, 5, 6, 8, 9, 0, 0, 5, 5, 6, 0, 8, 5, 0, 5, 0} },
|
|
/* DDR3-1600J */
|
|
{ {6, 5, 7, 9, 10, 0, 0, 5, 5, 7, 0, 9, 5, 0, 5, 0} },
|
|
/* DDR3-1600K */
|
|
{ {6, 6, 8, 10, 11, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0 } },
|
|
/* DDR3-1866J* */
|
|
{ {6, 5, 6, 8, 9, 11, 0, 5, 5, 6, 11, 8, 5, 0, 5, 0} },
|
|
/* DDR3-1866K */
|
|
{ {6, 5, 7, 8, 10, 11, 0, 5, 5, 7, 11, 8, 5, 11, 5, 11} },
|
|
/* DDR3-1866L */
|
|
{ {6, 6, 7, 9, 11, 12, 0, 6, 6, 7, 12, 9, 6, 12, 6, 12} },
|
|
/* DDR3-1866M* */
|
|
{ {6, 6, 8, 10, 11, 13, 0, 6, 6, 8, 13, 10, 6, 13, 6, 13} },
|
|
/* DDR3-2133K* */
|
|
{ {6, 5, 6, 7, 9, 10, 11, 5, 5, 6, 10, 7, 5, 11, 5, 11} },
|
|
/* DDR3-2133L */
|
|
{ {6, 5, 6, 8, 9, 11, 12, 5, 5, 6, 11, 8, 5, 12, 5, 12} },
|
|
/* DDR3-2133M */
|
|
{ {6, 5, 7, 9, 10, 12, 13, 5, 5, 7, 12, 9, 5, 13, 5, 13} },
|
|
/* DDR3-2133N* */
|
|
{ {6, 6, 7, 9, 11, 13, 14, 6, 6, 7, 13, 9, 6, 14, 6, 14} },
|
|
/* DDR3-1333H-ext */
|
|
{ {6, 6, 7, 9, 0, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
|
|
/* DDR3-1600K-ext */
|
|
{ {6, 6, 7, 9, 11, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
|
|
/* DDR3-1866M-ext */
|
|
{ {6, 6, 7, 9, 11, 13, 0, 6, 6, 7, 13, 9, 6, 13, 6, 13} },
|
|
};
|
|
|
|
u32 mv_ddr_cl_val_get(u32 index, u32 freq)
|
|
{
|
|
return cl_table[index].cl_val[freq];
|
|
}
|
|
|
|
/* cas write latency values per frequency for each speed bin index */
|
|
static struct mv_ddr_cl_val_per_freq cwl_table[] = {
|
|
/*
|
|
* 400M 667M 933M 311M 467M 600M 360
|
|
* 100M 533M 800M 1066M 333M 850M 900
|
|
* (the order is 100, 400, 533 etc.)
|
|
*/
|
|
/* DDR3-800D */
|
|
{ {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
|
|
/* DDR3-800E */
|
|
{ {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
|
|
/* DDR3-1066E */
|
|
{ {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1066F */
|
|
{ {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1066G */
|
|
{ {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1333F* */
|
|
{ {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1333G */
|
|
{ {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1333H */
|
|
{ {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1333J* */
|
|
{ {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1600G* */
|
|
{ {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1600H */
|
|
{ {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1600J */
|
|
{ {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1600K */
|
|
{ {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1866J* */
|
|
{ {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1866K */
|
|
{ {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1866L */
|
|
{ {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
|
|
/* DDR3-1866M* */
|
|
{ {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
|
|
/* DDR3-2133K* */
|
|
{ {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
|
|
/* DDR3-2133L */
|
|
{ {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
|
|
/* DDR3-2133M */
|
|
{ {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
|
|
/* DDR3-2133N* */
|
|
{ {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
|
|
/* DDR3-1333H-ext */
|
|
{ {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1600K-ext */
|
|
{ {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
|
|
/* DDR3-1866M-ext */
|
|
{ {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
|
|
};
|
|
|
|
u32 mv_ddr_cwl_val_get(u32 index, u32 freq)
|
|
{
|
|
return cwl_table[index].cl_val[freq];
|
|
}
|
|
|
|
u8 twr_mask_table[] = {
|
|
10,
|
|
10,
|
|
10,
|
|
10,
|
|
10,
|
|
1, /* 5 */
|
|
2, /* 6 */
|
|
3, /* 7 */
|
|
4, /* 8 */
|
|
10,
|
|
5, /* 10 */
|
|
10,
|
|
6, /* 12 */
|
|
10,
|
|
7, /* 14 */
|
|
10,
|
|
0 /* 16 */
|
|
};
|
|
|
|
u8 cl_mask_table[] = {
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0x2,
|
|
0x4,
|
|
0x6,
|
|
0x8,
|
|
0xa,
|
|
0xc,
|
|
0xe,
|
|
0x1,
|
|
0x3,
|
|
0x5,
|
|
0x5
|
|
};
|
|
|
|
u8 cwl_mask_table[] = {
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0x1,
|
|
0x2,
|
|
0x3,
|
|
0x4,
|
|
0x5,
|
|
0x6,
|
|
0x7,
|
|
0x8,
|
|
0x9,
|
|
0x9
|
|
};
|
|
|
|
/* RFC values (in ns) */
|
|
static unsigned int rfc_table[] = {
|
|
90, /* 512M */
|
|
110, /* 1G */
|
|
160, /* 2G */
|
|
260, /* 4G */
|
|
350, /* 8G */
|
|
0, /* TODO: placeholder for 16-Mbit dev width */
|
|
0, /* TODO: placeholder for 32-Mbit dev width */
|
|
0, /* TODO: placeholder for 12-Mbit dev width */
|
|
0 /* TODO: placeholder for 24-Mbit dev width */
|
|
};
|
|
|
|
u32 mv_ddr_rfc_get(u32 mem)
|
|
{
|
|
return rfc_table[mem];
|
|
}
|
|
|
|
u32 speed_bin_table_t_rc[] = {
|
|
50000,
|
|
52500,
|
|
48750,
|
|
50625,
|
|
52500,
|
|
46500,
|
|
48000,
|
|
49500,
|
|
51000,
|
|
45000,
|
|
46250,
|
|
47500,
|
|
48750,
|
|
44700,
|
|
45770,
|
|
46840,
|
|
47910,
|
|
43285,
|
|
44220,
|
|
45155,
|
|
46090
|
|
};
|
|
|
|
u32 speed_bin_table_t_rcd_t_rp[] = {
|
|
12500,
|
|
15000,
|
|
11250,
|
|
13125,
|
|
15000,
|
|
10500,
|
|
12000,
|
|
13500,
|
|
15000,
|
|
10000,
|
|
11250,
|
|
12500,
|
|
13750,
|
|
10700,
|
|
11770,
|
|
12840,
|
|
13910,
|
|
10285,
|
|
11220,
|
|
12155,
|
|
13090,
|
|
};
|
|
|
|
enum {
|
|
PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR = 0,
|
|
PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM
|
|
};
|
|
|
|
static u8 pattern_killer_pattern_table_map[KILLER_PATTERN_LENGTH * 2][2] = {
|
|
/*Aggressor / Victim */
|
|
{1, 0},
|
|
{0, 0},
|
|
{1, 0},
|
|
{1, 1},
|
|
{0, 1},
|
|
{0, 1},
|
|
{1, 0},
|
|
{0, 1},
|
|
{1, 0},
|
|
{0, 1},
|
|
{1, 0},
|
|
{1, 0},
|
|
{0, 1},
|
|
{1, 0},
|
|
{0, 1},
|
|
{0, 0},
|
|
{1, 1},
|
|
{0, 0},
|
|
{1, 1},
|
|
{0, 0},
|
|
{1, 1},
|
|
{0, 0},
|
|
{1, 1},
|
|
{1, 0},
|
|
{0, 0},
|
|
{1, 1},
|
|
{0, 0},
|
|
{1, 1},
|
|
{0, 0},
|
|
{0, 0},
|
|
{0, 0},
|
|
{0, 1},
|
|
{0, 1},
|
|
{1, 1},
|
|
{0, 0},
|
|
{0, 0},
|
|
{1, 1},
|
|
{1, 1},
|
|
{0, 0},
|
|
{1, 1},
|
|
{0, 0},
|
|
{1, 1},
|
|
{1, 1},
|
|
{0, 0},
|
|
{0, 0},
|
|
{1, 1},
|
|
{0, 0},
|
|
{1, 1},
|
|
{0, 1},
|
|
{0, 0},
|
|
{0, 1},
|
|
{0, 1},
|
|
{0, 0},
|
|
{1, 1},
|
|
{1, 1},
|
|
{1, 0},
|
|
{1, 0},
|
|
{1, 1},
|
|
{1, 1},
|
|
{1, 1},
|
|
{1, 1},
|
|
{1, 1},
|
|
{1, 1},
|
|
{1, 1}
|
|
};
|
|
|
|
static u8 pattern_vref_pattern_table_map[] = {
|
|
/* 1 means 0xffffffff, 0 is 0x0 */
|
|
0xb8,
|
|
0x52,
|
|
0x55,
|
|
0x8a,
|
|
0x33,
|
|
0xa6,
|
|
0x6d,
|
|
0xfe
|
|
};
|
|
|
|
static struct mv_ddr_page_element page_tbl[] = {
|
|
/* 8-bit, 16-bit page size */
|
|
{MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 512M */
|
|
{MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 1G */
|
|
{MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 2G */
|
|
{MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 4G */
|
|
{MV_DDR_PAGE_SIZE_2K, MV_DDR_PAGE_SIZE_2K}, /* 8G */
|
|
{0, 0}, /* TODO: placeholder for 16-Mbit die capacity */
|
|
{0, 0}, /* TODO: placeholder for 32-Mbit die capacity */
|
|
{0, 0}, /* TODO: placeholder for 12-Mbit die capacity */
|
|
{0, 0} /* TODO: placeholder for 24-Mbit die capacity */
|
|
};
|
|
|
|
u32 mv_ddr_page_size_get(enum mv_ddr_dev_width bus_width, enum mv_ddr_die_capacity mem_size)
|
|
{
|
|
if (bus_width == MV_DDR_DEV_WIDTH_8BIT)
|
|
return page_tbl[mem_size].page_size_8bit;
|
|
else
|
|
return page_tbl[mem_size].page_size_16bit;
|
|
}
|
|
|
|
/* Return speed Bin value for selected index and t* element */
|
|
unsigned int mv_ddr_speed_bin_timing_get(enum mv_ddr_speed_bin index, enum mv_ddr_speed_bin_timing element)
|
|
{
|
|
u32 result = 0;
|
|
|
|
switch (element) {
|
|
case SPEED_BIN_TRCD:
|
|
case SPEED_BIN_TRP:
|
|
result = speed_bin_table_t_rcd_t_rp[index];
|
|
break;
|
|
case SPEED_BIN_TRAS:
|
|
if (index <= SPEED_BIN_DDR_1066G)
|
|
result = 37500;
|
|
else if (index <= SPEED_BIN_DDR_1333J)
|
|
result = 36000;
|
|
else if (index <= SPEED_BIN_DDR_1600K)
|
|
result = 35000;
|
|
else if (index <= SPEED_BIN_DDR_1866M)
|
|
result = 34000;
|
|
else
|
|
result = 33000;
|
|
break;
|
|
case SPEED_BIN_TRC:
|
|
result = speed_bin_table_t_rc[index];
|
|
break;
|
|
case SPEED_BIN_TRRD1K:
|
|
if (index <= SPEED_BIN_DDR_800E)
|
|
result = 10000;
|
|
else if (index <= SPEED_BIN_DDR_1066G)
|
|
result = 7500;
|
|
else if (index <= SPEED_BIN_DDR_1600K)
|
|
result = 6000;
|
|
else
|
|
result = 5000;
|
|
break;
|
|
case SPEED_BIN_TRRD2K:
|
|
if (index <= SPEED_BIN_DDR_1066G)
|
|
result = 10000;
|
|
else if (index <= SPEED_BIN_DDR_1600K)
|
|
result = 7500;
|
|
else
|
|
result = 6000;
|
|
break;
|
|
case SPEED_BIN_TPD:
|
|
if (index < SPEED_BIN_DDR_800E)
|
|
result = 7500;
|
|
else if (index < SPEED_BIN_DDR_1333J)
|
|
result = 5625;
|
|
else
|
|
result = 5000;
|
|
break;
|
|
case SPEED_BIN_TFAW1K:
|
|
if (index <= SPEED_BIN_DDR_800E)
|
|
result = 40000;
|
|
else if (index <= SPEED_BIN_DDR_1066G)
|
|
result = 37500;
|
|
else if (index <= SPEED_BIN_DDR_1600K)
|
|
result = 30000;
|
|
else if (index <= SPEED_BIN_DDR_1866M)
|
|
result = 27000;
|
|
else
|
|
result = 25000;
|
|
break;
|
|
case SPEED_BIN_TFAW2K:
|
|
if (index <= SPEED_BIN_DDR_1066G)
|
|
result = 50000;
|
|
else if (index <= SPEED_BIN_DDR_1333J)
|
|
result = 45000;
|
|
else if (index <= SPEED_BIN_DDR_1600K)
|
|
result = 40000;
|
|
else
|
|
result = 35000;
|
|
break;
|
|
case SPEED_BIN_TWTR:
|
|
result = 7500;
|
|
break;
|
|
case SPEED_BIN_TRTP:
|
|
result = 7500;
|
|
break;
|
|
case SPEED_BIN_TWR:
|
|
result = 15000;
|
|
break;
|
|
case SPEED_BIN_TMOD:
|
|
result = 15000;
|
|
break;
|
|
case SPEED_BIN_TXPDLL:
|
|
result = 24000;
|
|
break;
|
|
case SPEED_BIN_TXSDLL:
|
|
result = 512;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static inline u32 pattern_table_get_killer_word(u8 dqs, u8 index)
|
|
{
|
|
u8 i, byte = 0;
|
|
u8 role;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
role = (i == dqs) ?
|
|
(PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
|
|
(PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
|
|
byte |= pattern_killer_pattern_table_map[index][role] << i;
|
|
}
|
|
|
|
return byte | (byte << 8) | (byte << 16) | (byte << 24);
|
|
}
|
|
|
|
static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index)
|
|
{
|
|
u8 i, byte0 = 0, byte1 = 0;
|
|
u8 role;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
role = (i == dqs) ?
|
|
(PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
|
|
(PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
|
|
byte0 |= pattern_killer_pattern_table_map[index * 2][role] << i;
|
|
byte1 |= pattern_killer_pattern_table_map[index * 2 + 1][role] << i;
|
|
}
|
|
|
|
return byte0 | (byte0 << 8) | (byte1 << 16) | (byte1 << 24);
|
|
}
|
|
|
|
static inline u32 pattern_table_get_sso_word(u8 sso, u8 index)
|
|
{
|
|
u8 step = sso + 1;
|
|
|
|
if (0 == ((index / step) & 1))
|
|
return 0x0;
|
|
else
|
|
return 0xffffffff;
|
|
}
|
|
|
|
static inline u32 pattern_table_get_sso_full_xtalk_word(u8 bit, u8 index)
|
|
{
|
|
u8 byte = (1 << bit);
|
|
|
|
if ((index & 1) == 1)
|
|
byte = ~byte;
|
|
|
|
return byte | (byte << 8) | (byte << 16) | (byte << 24);
|
|
|
|
}
|
|
|
|
static inline u32 pattern_table_get_sso_xtalk_free_word(u8 bit, u8 index)
|
|
{
|
|
u8 byte = (1 << bit);
|
|
|
|
if ((index & 1) == 1)
|
|
byte = 0;
|
|
|
|
return byte | (byte << 8) | (byte << 16) | (byte << 24);
|
|
}
|
|
|
|
static inline u32 pattern_table_get_isi_word(u8 index)
|
|
{
|
|
u8 i0 = index % 32;
|
|
u8 i1 = index % 8;
|
|
u32 word;
|
|
|
|
if (i0 > 15)
|
|
word = ((i1 == 5) | (i1 == 7)) ? 0xffffffff : 0x0;
|
|
else
|
|
word = (i1 == 6) ? 0xffffffff : 0x0;
|
|
|
|
word = ((i0 % 16) > 7) ? ~word : word;
|
|
|
|
return word;
|
|
}
|
|
|
|
static inline u32 pattern_table_get_sso_full_xtalk_word16(u8 bit, u8 index)
|
|
{
|
|
u8 byte = (1 << bit);
|
|
|
|
if ((index & 1) == 1)
|
|
byte = ~byte;
|
|
|
|
return byte | (byte << 8) | ((~byte) << 16) | ((~byte) << 24);
|
|
}
|
|
|
|
static inline u32 pattern_table_get_sso_xtalk_free_word16(u8 bit, u8 index)
|
|
{
|
|
u8 byte = (1 << bit);
|
|
|
|
if ((index & 1) == 0)
|
|
return (byte << 16) | (byte << 24);
|
|
else
|
|
return byte | (byte << 8);
|
|
}
|
|
|
|
static inline u32 pattern_table_get_isi_word16(u8 index)
|
|
{
|
|
u8 i0 = index % 16;
|
|
u8 i1 = index % 4;
|
|
u32 word;
|
|
|
|
if (i0 > 7)
|
|
word = (i1 > 1) ? 0x0000ffff : 0x0;
|
|
else
|
|
word = (i1 == 3) ? 0xffff0000 : 0x0;
|
|
|
|
word = ((i0 % 8) > 3) ? ~word : word;
|
|
|
|
return word;
|
|
}
|
|
|
|
static inline u32 pattern_table_get_vref_word(u8 index)
|
|
{
|
|
if (0 == ((pattern_vref_pattern_table_map[index / 8] >>
|
|
(index % 8)) & 1))
|
|
return 0x0;
|
|
else
|
|
return 0xffffffff;
|
|
}
|
|
|
|
static inline u32 pattern_table_get_vref_word16(u8 index)
|
|
{
|
|
if (0 == pattern_killer_pattern_table_map
|
|
[PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
|
|
0 == pattern_killer_pattern_table_map
|
|
[PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
|
|
return 0x00000000;
|
|
else if (1 == pattern_killer_pattern_table_map
|
|
[PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
|
|
0 == pattern_killer_pattern_table_map
|
|
[PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
|
|
return 0xffff0000;
|
|
else if (0 == pattern_killer_pattern_table_map
|
|
[PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
|
|
1 == pattern_killer_pattern_table_map
|
|
[PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
|
|
return 0x0000ffff;
|
|
else
|
|
return 0xffffffff;
|
|
}
|
|
|
|
static inline u32 pattern_table_get_static_pbs_word(u8 index)
|
|
{
|
|
u16 temp;
|
|
|
|
temp = ((0x00ff << (index / 3)) & 0xff00) >> 8;
|
|
|
|
return temp | (temp << 8) | (temp << 16) | (temp << 24);
|
|
}
|
|
|
|
u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index)
|
|
{
|
|
u32 pattern = 0;
|
|
struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
|
|
|
|
if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) {
|
|
/* 32/64-bit patterns */
|
|
switch (type) {
|
|
case PATTERN_PBS1:
|
|
case PATTERN_PBS2:
|
|
if (index == 0 || index == 2 || index == 5 ||
|
|
index == 7)
|
|
pattern = PATTERN_55;
|
|
else
|
|
pattern = PATTERN_AA;
|
|
break;
|
|
case PATTERN_PBS3:
|
|
if (0 == (index & 1))
|
|
pattern = PATTERN_55;
|
|
else
|
|
pattern = PATTERN_AA;
|
|
break;
|
|
case PATTERN_RL:
|
|
if (index < 6)
|
|
pattern = PATTERN_00;
|
|
else
|
|
pattern = PATTERN_80;
|
|
break;
|
|
case PATTERN_STATIC_PBS:
|
|
pattern = pattern_table_get_static_pbs_word(index);
|
|
break;
|
|
case PATTERN_KILLER_DQ0:
|
|
case PATTERN_KILLER_DQ1:
|
|
case PATTERN_KILLER_DQ2:
|
|
case PATTERN_KILLER_DQ3:
|
|
case PATTERN_KILLER_DQ4:
|
|
case PATTERN_KILLER_DQ5:
|
|
case PATTERN_KILLER_DQ6:
|
|
case PATTERN_KILLER_DQ7:
|
|
pattern = pattern_table_get_killer_word(
|
|
(u8)(type - PATTERN_KILLER_DQ0), index);
|
|
break;
|
|
case PATTERN_RL2:
|
|
if (index < 6)
|
|
pattern = PATTERN_00;
|
|
else
|
|
pattern = PATTERN_01;
|
|
break;
|
|
case PATTERN_TEST:
|
|
if (index > 1 && index < 6)
|
|
pattern = PATTERN_00;
|
|
else
|
|
pattern = PATTERN_FF;
|
|
break;
|
|
case PATTERN_FULL_SSO0:
|
|
case PATTERN_FULL_SSO1:
|
|
case PATTERN_FULL_SSO2:
|
|
case PATTERN_FULL_SSO3:
|
|
pattern = pattern_table_get_sso_word(
|
|
(u8)(type - PATTERN_FULL_SSO0), index);
|
|
break;
|
|
case PATTERN_VREF:
|
|
pattern = pattern_table_get_vref_word(index);
|
|
break;
|
|
case PATTERN_SSO_FULL_XTALK_DQ0:
|
|
case PATTERN_SSO_FULL_XTALK_DQ1:
|
|
case PATTERN_SSO_FULL_XTALK_DQ2:
|
|
case PATTERN_SSO_FULL_XTALK_DQ3:
|
|
case PATTERN_SSO_FULL_XTALK_DQ4:
|
|
case PATTERN_SSO_FULL_XTALK_DQ5:
|
|
case PATTERN_SSO_FULL_XTALK_DQ6:
|
|
case PATTERN_SSO_FULL_XTALK_DQ7:
|
|
pattern = pattern_table_get_sso_full_xtalk_word(
|
|
(u8)(type - PATTERN_SSO_FULL_XTALK_DQ0), index);
|
|
break;
|
|
case PATTERN_SSO_XTALK_FREE_DQ0:
|
|
case PATTERN_SSO_XTALK_FREE_DQ1:
|
|
case PATTERN_SSO_XTALK_FREE_DQ2:
|
|
case PATTERN_SSO_XTALK_FREE_DQ3:
|
|
case PATTERN_SSO_XTALK_FREE_DQ4:
|
|
case PATTERN_SSO_XTALK_FREE_DQ5:
|
|
case PATTERN_SSO_XTALK_FREE_DQ6:
|
|
case PATTERN_SSO_XTALK_FREE_DQ7:
|
|
pattern = pattern_table_get_sso_xtalk_free_word(
|
|
(u8)(type - PATTERN_SSO_XTALK_FREE_DQ0), index);
|
|
break;
|
|
case PATTERN_ISI_XTALK_FREE:
|
|
pattern = pattern_table_get_isi_word(index);
|
|
break;
|
|
default:
|
|
printf("error: %s: unsupported pattern type [%d] found\n",
|
|
__func__, (int)type);
|
|
pattern = 0;
|
|
break;
|
|
}
|
|
} else {
|
|
/* 16bit patterns */
|
|
switch (type) {
|
|
case PATTERN_PBS1:
|
|
case PATTERN_PBS2:
|
|
case PATTERN_PBS3:
|
|
pattern = PATTERN_55AA;
|
|
break;
|
|
case PATTERN_RL:
|
|
if (index < 3)
|
|
pattern = PATTERN_00;
|
|
else
|
|
pattern = PATTERN_80;
|
|
break;
|
|
case PATTERN_STATIC_PBS:
|
|
pattern = PATTERN_00FF;
|
|
break;
|
|
case PATTERN_KILLER_DQ0:
|
|
case PATTERN_KILLER_DQ1:
|
|
case PATTERN_KILLER_DQ2:
|
|
case PATTERN_KILLER_DQ3:
|
|
case PATTERN_KILLER_DQ4:
|
|
case PATTERN_KILLER_DQ5:
|
|
case PATTERN_KILLER_DQ6:
|
|
case PATTERN_KILLER_DQ7:
|
|
pattern = pattern_table_get_killer_word16(
|
|
(u8)(type - PATTERN_KILLER_DQ0), index);
|
|
break;
|
|
case PATTERN_RL2:
|
|
if (index < 3)
|
|
pattern = PATTERN_00;
|
|
else
|
|
pattern = PATTERN_01;
|
|
break;
|
|
case PATTERN_TEST:
|
|
if ((index == 0) || (index == 3))
|
|
pattern = 0x00000000;
|
|
else
|
|
pattern = 0xFFFFFFFF;
|
|
break;
|
|
case PATTERN_FULL_SSO0:
|
|
pattern = 0x0000ffff;
|
|
break;
|
|
case PATTERN_FULL_SSO1:
|
|
case PATTERN_FULL_SSO2:
|
|
case PATTERN_FULL_SSO3:
|
|
pattern = pattern_table_get_sso_word(
|
|
(u8)(type - PATTERN_FULL_SSO1), index);
|
|
break;
|
|
case PATTERN_VREF:
|
|
pattern = pattern_table_get_vref_word16(index);
|
|
break;
|
|
case PATTERN_SSO_FULL_XTALK_DQ0:
|
|
case PATTERN_SSO_FULL_XTALK_DQ1:
|
|
case PATTERN_SSO_FULL_XTALK_DQ2:
|
|
case PATTERN_SSO_FULL_XTALK_DQ3:
|
|
case PATTERN_SSO_FULL_XTALK_DQ4:
|
|
case PATTERN_SSO_FULL_XTALK_DQ5:
|
|
case PATTERN_SSO_FULL_XTALK_DQ6:
|
|
case PATTERN_SSO_FULL_XTALK_DQ7:
|
|
pattern = pattern_table_get_sso_full_xtalk_word16(
|
|
(u8)(type - PATTERN_SSO_FULL_XTALK_DQ0), index);
|
|
break;
|
|
case PATTERN_SSO_XTALK_FREE_DQ0:
|
|
case PATTERN_SSO_XTALK_FREE_DQ1:
|
|
case PATTERN_SSO_XTALK_FREE_DQ2:
|
|
case PATTERN_SSO_XTALK_FREE_DQ3:
|
|
case PATTERN_SSO_XTALK_FREE_DQ4:
|
|
case PATTERN_SSO_XTALK_FREE_DQ5:
|
|
case PATTERN_SSO_XTALK_FREE_DQ6:
|
|
case PATTERN_SSO_XTALK_FREE_DQ7:
|
|
pattern = pattern_table_get_sso_xtalk_free_word16(
|
|
(u8)(type - PATTERN_SSO_XTALK_FREE_DQ0), index);
|
|
break;
|
|
case PATTERN_ISI_XTALK_FREE:
|
|
pattern = pattern_table_get_isi_word16(index);
|
|
break;
|
|
default:
|
|
printf("error: %s: unsupported pattern type [%d] found\n",
|
|
__func__, (int)type);
|
|
pattern = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return pattern;
|
|
}
|
|
|
|
/* Device attribute functions */
|
|
void ddr3_tip_dev_attr_init(u32 dev_num)
|
|
{
|
|
u32 attr_id;
|
|
|
|
for (attr_id = 0; attr_id < MV_ATTR_LAST; attr_id++)
|
|
ddr_dev_attributes[attr_id] = 0xFF;
|
|
|
|
ddr_dev_attr_init_done = 1;
|
|
}
|
|
|
|
u32 ddr3_tip_dev_attr_get(u32 dev_num, enum mv_ddr_dev_attribute attr_id)
|
|
{
|
|
if (ddr_dev_attr_init_done == 0)
|
|
ddr3_tip_dev_attr_init(dev_num);
|
|
|
|
return ddr_dev_attributes[attr_id];
|
|
}
|
|
|
|
void ddr3_tip_dev_attr_set(u32 dev_num, enum mv_ddr_dev_attribute attr_id, u32 value)
|
|
{
|
|
if (ddr_dev_attr_init_done == 0)
|
|
ddr3_tip_dev_attr_init(dev_num);
|
|
|
|
ddr_dev_attributes[attr_id] = value;
|
|
}
|