Newer
Older
* Copyright 2010-2014 Freescale Semiconductor, Inc.
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
* Based on code from spd_sdram.c
* Author: James Yang [at freescale.com]
* York Sun [at freescale.com]
*/
#include <common.h>
#include <linux/ctype.h>
#include <asm/types.h>
#include <asm/io.h>
#include <fsl_ddr_sdram.h>
#include <fsl_ddr.h>
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* Option parameter Structures */
struct options_string {
const char *option_name;
size_t offset;
unsigned int size;
const char printhex;
};
static unsigned int picos_to_mhz(unsigned int picos)
{
return 1000000 / picos;
}
static void print_option_table(const struct options_string *table,
int table_size,
const void *base)
{
unsigned int i;
unsigned int *ptr;
unsigned long long *ptr_l;
for (i = 0; i < table_size; i++) {
switch (table[i].size) {
case 4:
ptr = (unsigned int *) (base + table[i].offset);
if (table[i].printhex) {
printf("%s = 0x%08X\n",
table[i].option_name, *ptr);
} else {
printf("%s = %u\n",
table[i].option_name, *ptr);
}
break;
case 8:
ptr_l = (unsigned long long *) (base + table[i].offset);
printf("%s = %llu\n",
table[i].option_name, *ptr_l);
break;
default:
printf("Unrecognized size!\n");
break;
}
}
}
static int handle_option_table(const struct options_string *table,
int table_size,
void *base,
const char *opt,
const char *val)
{
unsigned int i;
unsigned int value, *ptr;
unsigned long long value_l, *ptr_l;
for (i = 0; i < table_size; i++) {
if (strcmp(table[i].option_name, opt) != 0)
continue;
switch (table[i].size) {
case 4:
value = simple_strtoul(val, NULL, 0);
ptr = base + table[i].offset;
*ptr = value;
break;
case 8:
value_l = simple_strtoull(val, NULL, 0);
ptr_l = base + table[i].offset;
*ptr_l = value_l;
break;
default:
printf("Unrecognized size!\n");
break;
}
return 1;
}
return 0;
}
static void fsl_ddr_generic_edit(void *pdata,
void *pend,
unsigned int element_size,
unsigned int element_num,
unsigned int value)
{
char *pcdata = (char *)pdata; /* BIG ENDIAN ONLY */
pcdata += element_num * element_size;
if ((pcdata + element_size) > (char *) pend) {
printf("trying to write past end of data\n");
return;
}
switch (element_size) {
case 1:
__raw_writeb(value, pcdata);
break;
case 2:
__raw_writew(value, pcdata);
break;
case 4:
__raw_writel(value, pcdata);
break;
default:
printf("unexpected element size %u\n", element_size);
break;
}
}
static void fsl_ddr_spd_edit(fsl_ddr_info_t *pinfo,
unsigned int ctrl_num,
unsigned int dimm_num,
unsigned int element_num,
unsigned int value)
{
generic_spd_eeprom_t *pspd;
pspd = &(pinfo->spd_installed_dimms[ctrl_num][dimm_num]);
fsl_ddr_generic_edit(pspd, pspd + 1, 1, element_num, value);
}
#define COMMON_TIMING(x) {#x, offsetof(common_timing_params_t, x), \
sizeof((common_timing_params_t *)0)->x, 0}
static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
unsigned int ctrl_num,
const char *optname_str,
const char *value_str)
{
common_timing_params_t *p = &pinfo->common_timing_params[ctrl_num];
static const struct options_string options[] = {
COMMON_TIMING(tckmin_x_ps),
COMMON_TIMING(tckmax_ps),
#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
COMMON_TIMING(taamin_ps),
COMMON_TIMING(trcd_ps),
COMMON_TIMING(trp_ps),
COMMON_TIMING(tras_ps),
#ifdef CONFIG_SYS_FSL_DDR4
COMMON_TIMING(trfc1_ps),
COMMON_TIMING(trfc2_ps),
COMMON_TIMING(trfc4_ps),
COMMON_TIMING(trrds_ps),
COMMON_TIMING(trrdl_ps),
COMMON_TIMING(tccdl_ps),
#else
COMMON_TIMING(twtr_ps),
COMMON_TIMING(trfc_ps),
COMMON_TIMING(trrd_ps),
COMMON_TIMING(trtp_ps),
#endif
COMMON_TIMING(twr_ps),
COMMON_TIMING(trc_ps),
COMMON_TIMING(refresh_rate_ps),
COMMON_TIMING(extended_op_srt),
#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
COMMON_TIMING(tis_ps),
COMMON_TIMING(tih_ps),
COMMON_TIMING(tds_ps),
COMMON_TIMING(tdh_ps),
COMMON_TIMING(tdqsq_max_ps),
COMMON_TIMING(tqhs_ps),
COMMON_TIMING(ndimms_present),
COMMON_TIMING(lowest_common_spd_caslat),
COMMON_TIMING(highest_common_derated_caslat),
COMMON_TIMING(additive_latency),
COMMON_TIMING(all_dimms_burst_lengths_bitmask),
COMMON_TIMING(all_dimms_registered),
COMMON_TIMING(all_dimms_unbuffered),
COMMON_TIMING(all_dimms_ecc_capable),
Loading
Loading full blame...