1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2016 Freescale Semiconductor, Inc.
4 */
5
6#include <common.h>
7#include <fsl_ddr_sdram.h>
8#include <fsl_ddr_dimm_params.h>
9#ifdef CONFIG_FSL_DEEP_SLEEP
10#include <fsl_sleep.h>
11#endif
12#include <log.h>
13#include <asm/arch/clock.h>
14#include <asm/global_data.h>
15#include "ddr.h"
16
17DECLARE_GLOBAL_DATA_PTR;
18
19void fsl_ddr_board_options(memctl_options_t *popts,
20			   dimm_params_t *pdimm,
21			   unsigned int ctrl_num)
22{
23	const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
24	ulong ddr_freq;
25
26	if (ctrl_num > 3) {
27		printf("Not supported controller number %d\n", ctrl_num);
28		return;
29	}
30	if (!pdimm->n_ranks)
31		return;
32
33	pbsp = udimms[0];
34
35	/* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr
36	 * freqency and n_banks specified in board_specific_parameters table.
37	 */
38	ddr_freq = get_ddr_freq(0) / 1000000;
39	while (pbsp->datarate_mhz_high) {
40		if (pbsp->n_ranks == pdimm->n_ranks) {
41			if (ddr_freq <= pbsp->datarate_mhz_high) {
42				popts->clk_adjust = pbsp->clk_adjust;
43				popts->wrlvl_start = pbsp->wrlvl_start;
44				popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
45				popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
46				goto found;
47			}
48			pbsp_highest = pbsp;
49		}
50		pbsp++;
51	}
52
53	if (pbsp_highest) {
54		printf("Error: board specific timing not found for %lu MT/s\n",
55		       ddr_freq);
56		printf("Trying to use the highest speed (%u) parameters\n",
57		       pbsp_highest->datarate_mhz_high);
58		popts->clk_adjust = pbsp_highest->clk_adjust;
59		popts->wrlvl_start = pbsp_highest->wrlvl_start;
60		popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
61		popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
62	} else {
63		panic("DIMM is not supported by this board");
64	}
65found:
66	debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n",
67	      pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb);
68
69	popts->data_bus_width = 0;      /* 64b data bus */
70	popts->otf_burst_chop_en = 0;
71	popts->burst_length = DDR_BL8;
72	popts->bstopre = 0;		/* enable auto precharge */
73
74	popts->half_strength_driver_enable = 0;
75	/*
76	 * Write leveling override
77	 */
78	popts->wrlvl_override = 1;
79	popts->wrlvl_sample = 0xf;
80
81	/*
82	 * Rtt and Rtt_WR override
83	 */
84	popts->rtt_override = 0;
85
86	/* Enable ZQ calibration */
87	popts->zq_en = 1;
88
89	popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
90	popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
91			  DDR_CDR2_VREF_TRAIN_EN | DDR_CDR2_VREF_RANGE_2;
92
93	/* optimize cpo for erratum A-009942 */
94	popts->cpo_sample = 0x70;
95}
96
97#ifdef CONFIG_TFABOOT
98int fsl_initdram(void)
99{
100	gd->ram_size = tfa_get_dram_size();
101	if (!gd->ram_size)
102		gd->ram_size = fsl_ddr_sdram_size();
103
104	return 0;
105}
106#else
107int fsl_initdram(void)
108{
109	phys_size_t dram_size;
110
111#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
112	gd->ram_size = fsl_ddr_sdram_size();
113
114	return 0;
115#else
116	puts("Initializing DDR....using SPD\n");
117
118	dram_size = fsl_ddr_sdram();
119#endif
120
121#ifdef CONFIG_FSL_DEEP_SLEEP
122	fsl_dp_ddr_restore();
123#endif
124
125	erratum_a008850_post();
126
127	gd->ram_size = dram_size;
128
129	return 0;
130}
131#endif
132