xref: /openbmc/u-boot/board/freescale/p1022ds/ddr.c (revision 6b7c0f5e)
1 /*
2  * Copyright 2010 Freescale Semiconductor, Inc.
3  * Authors: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
4  *          Timur Tabi <timur@freescale.com>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; either version 2 of the License, or (at your option)
9  * any later version.
10  */
11 
12 #include <common.h>
13 #include <i2c.h>
14 
15 #include <asm/fsl_ddr_sdram.h>
16 #include <asm/fsl_ddr_dimm_params.h>
17 
18 unsigned int fsl_ddr_get_mem_data_rate(void)
19 {
20 	return get_ddr_freq(0);
21 }
22 
23 void fsl_ddr_get_spd(ddr3_spd_eeprom_t *ctrl_dimms_spd, unsigned int ctrl_num)
24 {
25 	int ret;
26 
27 	/*
28 	 * The P1022 has only one DDR controller, and the board has only one
29 	 * DIMM slot.
30 	 */
31 	ret = i2c_read(SPD_EEPROM_ADDRESS1, 0, 1, (u8 *)ctrl_dimms_spd,
32 		       sizeof(ddr3_spd_eeprom_t));
33 	if (ret) {
34 		debug("DDR: failed to read SPD from address %u\n",
35 		      SPD_EEPROM_ADDRESS1);
36 		memset(ctrl_dimms_spd, 0, sizeof(ddr3_spd_eeprom_t));
37 	}
38 }
39 
40 typedef struct {
41 	u32 datarate_mhz_low;
42 	u32 datarate_mhz_high;
43 	u32 n_ranks;
44 	u32 clk_adjust;		/* Range: 0-8 */
45 	u32 cpo;		/* Range: 2-31 */
46 	u32 write_data_delay;	/* Range: 0-6 */
47 	u32 force_2T;
48 } board_specific_parameters_t;
49 
50 static const board_specific_parameters_t bsp[] = {
51 /*
52  *        lo|  hi|  num|  clk| cpo|wrdata|2T
53  *       mhz| mhz|ranks|adjst|    | delay|
54  */
55 	{  0, 333,    1,    5,  31,     3, 0},
56 	{334, 400,    1,    5,  31,     3, 0},
57 	{401, 549,    1,    5,  31,     3, 0},
58 	{550, 680,    1,    5,  31,     5, 0},
59 	{681, 850,    1,    5,  31,     5, 0},
60 	{  0, 333,    2,    5,  31,     3, 0},
61 	{334, 400,    2,    5,  31,     3, 0},
62 	{401, 549,    2,    5,  31,     3, 0},
63 	{550, 680,    2,    5,  31,     5, 0},
64 	{681, 850,    2,    5,  31,     5, 0},
65 };
66 
67 void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm,
68 			   unsigned int ctrl_num)
69 {
70 	unsigned long ddr_freq;
71 	unsigned int i;
72 
73 	/* set odt_rd_cfg and odt_wr_cfg. */
74 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
75 		popts->cs_local_opts[i].odt_rd_cfg = 0;
76 		popts->cs_local_opts[i].odt_wr_cfg = 1;
77 	}
78 
79 	/*
80 	 * Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr
81 	 * freqency and n_banks specified in board_specific_parameters table.
82 	 */
83 	ddr_freq = get_ddr_freq(0) / 1000000;
84 	for (i = 0; i < ARRAY_SIZE(bsp); i++) {
85 		if (ddr_freq >= bsp[i].datarate_mhz_low &&
86 		    ddr_freq <= bsp[i].datarate_mhz_high &&
87 		    pdimm->n_ranks == bsp[i].n_ranks) {
88 			popts->clk_adjust = bsp[i].clk_adjust;
89 			popts->cpo_override = bsp[i].cpo;
90 			popts->write_data_delay = bsp[i].write_data_delay;
91 			popts->twoT_en = bsp[i].force_2T;
92 			break;
93 		}
94 	}
95 
96 	popts->half_strength_driver_enable = 1;
97 
98 	/* Per AN4039, enable ZQ calibration. */
99 	popts->zq_en = 1;
100 
101 	/*
102 	 * For wake-up on ARP, we need auto self refresh enabled
103 	 */
104 	popts->auto_self_refresh_en = 1;
105 	popts->sr_it = 0xb;
106 }
107