xref: /rk3399_rockchip-uboot/board/varisys/cyrus/ddr.c (revision f1683aa73c31db0a025e0254e6ce1ee7e56aad3e)
187e29878SAndy Fleming /*
287e29878SAndy Fleming  * Based on corenet_ds ddr code
387e29878SAndy Fleming  *
487e29878SAndy Fleming  * SPDX-License-Identifier:    GPL-2.0+
587e29878SAndy Fleming  */
687e29878SAndy Fleming 
787e29878SAndy Fleming #include <common.h>
887e29878SAndy Fleming #include <i2c.h>
987e29878SAndy Fleming #include <hwconfig.h>
1087e29878SAndy Fleming #include <asm/mmu.h>
1187e29878SAndy Fleming #include <fsl_ddr_sdram.h>
1287e29878SAndy Fleming #include <fsl_ddr_dimm_params.h>
1387e29878SAndy Fleming #include <asm/fsl_law.h>
1487e29878SAndy Fleming 
1587e29878SAndy Fleming DECLARE_GLOBAL_DATA_PTR;
1687e29878SAndy Fleming 
1787e29878SAndy Fleming 
1887e29878SAndy Fleming struct board_specific_parameters {
1987e29878SAndy Fleming 	u32 n_ranks;
2087e29878SAndy Fleming 	u32 datarate_mhz_high;
2187e29878SAndy Fleming 	u32 clk_adjust;
2287e29878SAndy Fleming 	u32 wrlvl_start;
2387e29878SAndy Fleming 	u32 cpo;
2487e29878SAndy Fleming 	u32 write_data_delay;
2587e29878SAndy Fleming 	u32 force_2t;
2687e29878SAndy Fleming };
2787e29878SAndy Fleming 
2887e29878SAndy Fleming /*
2987e29878SAndy Fleming  * This table contains all valid speeds we want to override with board
3087e29878SAndy Fleming  * specific parameters. datarate_mhz_high values need to be in ascending order
3187e29878SAndy Fleming  * for each n_ranks group.
3287e29878SAndy Fleming  */
3387e29878SAndy Fleming static const struct board_specific_parameters udimm0[] = {
3487e29878SAndy Fleming 	/*
3587e29878SAndy Fleming 	 * memory controller 0
3687e29878SAndy Fleming 	 *   num|  hi|  clk| wrlvl | cpo  |wrdata|2T
3787e29878SAndy Fleming 	 * ranks| mhz|adjst| start |      |delay |
3887e29878SAndy Fleming 	 */
3987e29878SAndy Fleming 	{4,   850,    4,     6,   0xff,    2,  0},
4087e29878SAndy Fleming 	{4,   950,    5,     7,   0xff,    2,  0},
4187e29878SAndy Fleming 	{4,  1050,    5,     8,   0xff,    2,  0},
4287e29878SAndy Fleming 	{4,  1250,    5,    10,   0xff,    2,  0},
4387e29878SAndy Fleming 	{4,  1350,    5,    11,   0xff,    2,  0},
4487e29878SAndy Fleming 	{4,  1666,    5,    12,   0xff,    2,  0},
4587e29878SAndy Fleming 	{2,   850,    5,     6,   0xff,    2,  0},
4687e29878SAndy Fleming 	{2,  1050,    5,     7,   0xff,    2,  0},
4787e29878SAndy Fleming 	{2,  1250,    4,     6,   0xff,    2,  0},
4887e29878SAndy Fleming 	{2,  1350,    5,     7,   0xff,    2,  0},
4987e29878SAndy Fleming 	{2,  1666,    5,     8,   0xff,    2,  0},
5087e29878SAndy Fleming 	{1,  1250,    4,     6,   0xff,    2,  0},
5187e29878SAndy Fleming 	{1,  1335,    4,     7,   0xff,    2,  0},
5287e29878SAndy Fleming 	{1,  1666,    4,     8,   0xff,    2,  0},
5387e29878SAndy Fleming 	{}
5487e29878SAndy Fleming };
5587e29878SAndy Fleming 
5687e29878SAndy Fleming /*
5787e29878SAndy Fleming  * The two slots have slightly different timing. The center values are good
5887e29878SAndy Fleming  * for both slots. We use identical speed tables for them. In future use, if
5987e29878SAndy Fleming  * DIMMs have fewer center values that require two separated tables, copy the
6087e29878SAndy Fleming  * udimm0 table to udimm1 and make changes to clk_adjust and wrlvl_start.
6187e29878SAndy Fleming  */
6287e29878SAndy Fleming static const struct board_specific_parameters *udimms[] = {
6387e29878SAndy Fleming 	udimm0,
6487e29878SAndy Fleming 	udimm0,
6587e29878SAndy Fleming };
6687e29878SAndy Fleming 
6787e29878SAndy Fleming static const struct board_specific_parameters rdimm0[] = {
6887e29878SAndy Fleming 	/*
6987e29878SAndy Fleming 	 * memory controller 0
7087e29878SAndy Fleming 	 *   num|  hi|  clk| wrlvl | cpo  |wrdata|2T
7187e29878SAndy Fleming 	 * ranks| mhz|adjst| start |      |delay |
7287e29878SAndy Fleming 	 */
7387e29878SAndy Fleming 	{4,   850,    4,     6,   0xff,    2,  0},
7487e29878SAndy Fleming 	{4,   950,    5,     7,   0xff,    2,  0},
7587e29878SAndy Fleming 	{4,  1050,    5,     8,   0xff,    2,  0},
7687e29878SAndy Fleming 	{4,  1250,    5,    10,   0xff,    2,  0},
7787e29878SAndy Fleming 	{4,  1350,    5,    11,   0xff,    2,  0},
7887e29878SAndy Fleming 	{4,  1666,    5,    12,   0xff,    2,  0},
7987e29878SAndy Fleming 	{2,   850,    4,     6,   0xff,    2,  0},
8087e29878SAndy Fleming 	{2,  1050,    4,     7,   0xff,    2,  0},
8187e29878SAndy Fleming 	{2,  1666,    4,     8,   0xff,    2,  0},
8287e29878SAndy Fleming 	{1,   850,    4,     5,   0xff,    2,  0},
8387e29878SAndy Fleming 	{1,   950,    4,     7,   0xff,    2,  0},
8487e29878SAndy Fleming 	{1,  1666,    4,     8,   0xff,    2,  0},
8587e29878SAndy Fleming 	{}
8687e29878SAndy Fleming };
8787e29878SAndy Fleming 
8887e29878SAndy Fleming /*
8987e29878SAndy Fleming  * The two slots have slightly different timing. See comments above.
9087e29878SAndy Fleming  */
9187e29878SAndy Fleming static const struct board_specific_parameters *rdimms[] = {
9287e29878SAndy Fleming 	rdimm0,
9387e29878SAndy Fleming 	rdimm0,
9487e29878SAndy Fleming };
9587e29878SAndy Fleming 
fsl_ddr_board_options(memctl_options_t * popts,dimm_params_t * pdimm,unsigned int ctrl_num)9687e29878SAndy Fleming void fsl_ddr_board_options(memctl_options_t *popts,
9787e29878SAndy Fleming 				dimm_params_t *pdimm,
9887e29878SAndy Fleming 				unsigned int ctrl_num)
9987e29878SAndy Fleming {
10087e29878SAndy Fleming 	const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
10187e29878SAndy Fleming 	ulong ddr_freq;
10287e29878SAndy Fleming 
10387e29878SAndy Fleming 	if (ctrl_num > 1) {
10487e29878SAndy Fleming 		printf("Wrong parameter for controller number %d", ctrl_num);
10587e29878SAndy Fleming 		return;
10687e29878SAndy Fleming 	}
10787e29878SAndy Fleming 	if (!pdimm->n_ranks)
10887e29878SAndy Fleming 		return;
10987e29878SAndy Fleming 
11087e29878SAndy Fleming 	if (popts->registered_dimm_en)
11187e29878SAndy Fleming 		pbsp = rdimms[ctrl_num];
11287e29878SAndy Fleming 	else
11387e29878SAndy Fleming 		pbsp = udimms[ctrl_num];
11487e29878SAndy Fleming 
11587e29878SAndy Fleming 
11687e29878SAndy Fleming 	/* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr
11787e29878SAndy Fleming 	 * freqency and n_banks specified in board_specific_parameters table.
11887e29878SAndy Fleming 	 */
11987e29878SAndy Fleming 	ddr_freq = get_ddr_freq(0) / 1000000;
12087e29878SAndy Fleming 	while (pbsp->datarate_mhz_high) {
12187e29878SAndy Fleming 		if (pbsp->n_ranks == pdimm->n_ranks) {
12287e29878SAndy Fleming 			if (ddr_freq <= pbsp->datarate_mhz_high) {
12387e29878SAndy Fleming 				popts->cpo_override = pbsp->cpo;
12487e29878SAndy Fleming 				popts->write_data_delay =
12587e29878SAndy Fleming 					pbsp->write_data_delay;
12687e29878SAndy Fleming 				popts->clk_adjust = pbsp->clk_adjust;
12787e29878SAndy Fleming 				popts->wrlvl_start = pbsp->wrlvl_start;
12887e29878SAndy Fleming 				popts->twot_en = pbsp->force_2t;
12987e29878SAndy Fleming 				goto found;
13087e29878SAndy Fleming 			}
13187e29878SAndy Fleming 			pbsp_highest = pbsp;
13287e29878SAndy Fleming 		}
13387e29878SAndy Fleming 		pbsp++;
13487e29878SAndy Fleming 	}
13587e29878SAndy Fleming 
13687e29878SAndy Fleming 	if (pbsp_highest) {
13787e29878SAndy Fleming 		printf("Error: board specific timing not found for data rate %lu MT/s!\nTrying to use the highest speed (%u) parameters\n",
13887e29878SAndy Fleming 			ddr_freq, pbsp_highest->datarate_mhz_high);
13987e29878SAndy Fleming 		popts->cpo_override = pbsp_highest->cpo;
14087e29878SAndy Fleming 		popts->write_data_delay = pbsp_highest->write_data_delay;
14187e29878SAndy Fleming 		popts->clk_adjust = pbsp_highest->clk_adjust;
14287e29878SAndy Fleming 		popts->wrlvl_start = pbsp_highest->wrlvl_start;
14387e29878SAndy Fleming 		popts->twot_en = pbsp_highest->force_2t;
14487e29878SAndy Fleming 	} else {
14587e29878SAndy Fleming 		panic("DIMM is not supported by this board");
14687e29878SAndy Fleming 	}
14787e29878SAndy Fleming found:
14887e29878SAndy Fleming 	/*
14987e29878SAndy Fleming 	 * Factors to consider for half-strength driver enable:
15087e29878SAndy Fleming 	 *	- number of DIMMs installed
15187e29878SAndy Fleming 	 */
15287e29878SAndy Fleming 	popts->half_strength_driver_enable = 0;
15387e29878SAndy Fleming 	/*
15487e29878SAndy Fleming 	 * Write leveling override
15587e29878SAndy Fleming 	 */
15687e29878SAndy Fleming 	popts->wrlvl_override = 1;
15787e29878SAndy Fleming 	popts->wrlvl_sample = 0xf;
15887e29878SAndy Fleming 
15987e29878SAndy Fleming 	/*
16087e29878SAndy Fleming 	 * Rtt and Rtt_WR override
16187e29878SAndy Fleming 	 */
16287e29878SAndy Fleming 	popts->rtt_override = 0;
16387e29878SAndy Fleming 
16487e29878SAndy Fleming 	/* Enable ZQ calibration */
16587e29878SAndy Fleming 	popts->zq_en = 1;
16687e29878SAndy Fleming 
16787e29878SAndy Fleming 	/* DHC_EN =1, ODT = 60 Ohm */
16887e29878SAndy Fleming 	popts->ddr_cdr1 = DDR_CDR1_DHC_EN;
16987e29878SAndy Fleming }
17087e29878SAndy Fleming 
dram_init(void)171*f1683aa7SSimon Glass int dram_init(void)
17287e29878SAndy Fleming {
17387e29878SAndy Fleming 	phys_size_t dram_size;
17487e29878SAndy Fleming 
17587e29878SAndy Fleming 	puts("Initializing....");
17687e29878SAndy Fleming 
17787e29878SAndy Fleming 	if (!fsl_use_spd())
17887e29878SAndy Fleming 		panic("Cyrus only supports using SPD for DRAM\n");
17987e29878SAndy Fleming 
18087e29878SAndy Fleming 	puts("using SPD\n");
18187e29878SAndy Fleming 	dram_size = fsl_ddr_sdram();
18287e29878SAndy Fleming 
18387e29878SAndy Fleming 	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
18487e29878SAndy Fleming 	dram_size *= 0x100000;
18587e29878SAndy Fleming 
18687e29878SAndy Fleming 	debug("    DDR: ");
187088454cdSSimon Glass 	gd->ram_size = dram_size;
188088454cdSSimon Glass 
189088454cdSSimon Glass 	return 0;
19087e29878SAndy Fleming }
191