Commit 9ac4ffbde1a5015c9929ee8578d3811b716e2fd3
1 parent
9a17eb5b7e
Exists in
master
and in
50 other branches
Driver/DDR: Add Freescale DDR driver for ARM
Make PowerPC specific code conditional so ARM SoCs can reuse this driver. Add DDR3 driver for ARM. Signed-off-by: York Sun <yorksun@freescale.com>
Showing 5 changed files with 230 additions and 4 deletions Side-by-side Diff
README
... | ... | @@ -450,6 +450,9 @@ |
450 | 450 | CONFIG_SYS_FSL_DDRC_GEN3 |
451 | 451 | Freescale DDR3 controller. |
452 | 452 | |
453 | + CONFIG_SYS_FSL_DDRC_ARM_GEN3 | |
454 | + Freescale DDR3 controller for ARM-based SoCs. | |
455 | + | |
453 | 456 | CONFIG_SYS_FSL_DDR1 |
454 | 457 | Board config to use DDR1. It can be enabled for SoCs with |
455 | 458 | Freescale DDR1 or DDR2 controllers, depending on the board |
drivers/ddr/fsl/Makefile
... | ... | @@ -31,5 +31,5 @@ |
31 | 31 | obj-$(CONFIG_SYS_FSL_DDRC_GEN2) += mpc85xx_ddr_gen2.o |
32 | 32 | obj-$(CONFIG_SYS_FSL_DDRC_GEN3) += mpc85xx_ddr_gen3.o |
33 | 33 | obj-$(CONFIG_SYS_FSL_DDR_86XX) += mpc86xx_ddr.o |
34 | -obj-$(CONFIG_FSL_DDR_INTERACTIVE) += interactive.o | |
34 | +obj-$(CONFIG_SYS_FSL_DDRC_ARM_GEN3) += arm_ddr_gen3.o |
drivers/ddr/fsl/arm_ddr_gen3.c
1 | +/* | |
2 | + * Copyright 2013 Freescale Semiconductor, Inc. | |
3 | + * | |
4 | + * SPDX-License-Identifier: GPL-2.0+ | |
5 | + * | |
6 | + * Derived from mpc85xx_ddr_gen3.c, removed all workarounds | |
7 | + */ | |
8 | + | |
9 | +#include <common.h> | |
10 | +#include <asm/io.h> | |
11 | +#include <fsl_ddr_sdram.h> | |
12 | +#include <asm/processor.h> | |
13 | +#include <fsl_immap.h> | |
14 | + | |
15 | +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) | |
16 | +#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL | |
17 | +#endif | |
18 | + | |
19 | + | |
20 | +/* | |
21 | + * regs has the to-be-set values for DDR controller registers | |
22 | + * ctrl_num is the DDR controller number | |
23 | + * step: 0 goes through the initialization in one pass | |
24 | + * 1 sets registers and returns before enabling controller | |
25 | + * 2 resumes from step 1 and continues to initialize | |
26 | + * Dividing the initialization to two steps to deassert DDR reset signal | |
27 | + * to comply with JEDEC specs for RDIMMs. | |
28 | + */ | |
29 | +void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, | |
30 | + unsigned int ctrl_num, int step) | |
31 | +{ | |
32 | + unsigned int i, bus_width; | |
33 | + struct ccsr_ddr __iomem *ddr; | |
34 | + u32 temp_sdram_cfg; | |
35 | + u32 total_gb_size_per_controller; | |
36 | + int timeout; | |
37 | + | |
38 | + switch (ctrl_num) { | |
39 | + case 0: | |
40 | + ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; | |
41 | + break; | |
42 | +#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) | |
43 | + case 1: | |
44 | + ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR; | |
45 | + break; | |
46 | +#endif | |
47 | +#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) | |
48 | + case 2: | |
49 | + ddr = (void *)CONFIG_SYS_FSL_DDR3_ADDR; | |
50 | + break; | |
51 | +#endif | |
52 | +#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) | |
53 | + case 3: | |
54 | + ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR; | |
55 | + break; | |
56 | +#endif | |
57 | + default: | |
58 | + printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num); | |
59 | + return; | |
60 | + } | |
61 | + | |
62 | + if (step == 2) | |
63 | + goto step2; | |
64 | + | |
65 | + if (regs->ddr_eor) | |
66 | + out_be32(&ddr->eor, regs->ddr_eor); | |
67 | + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { | |
68 | + if (i == 0) { | |
69 | + out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); | |
70 | + out_be32(&ddr->cs0_config, regs->cs[i].config); | |
71 | + out_be32(&ddr->cs0_config_2, regs->cs[i].config_2); | |
72 | + | |
73 | + } else if (i == 1) { | |
74 | + out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); | |
75 | + out_be32(&ddr->cs1_config, regs->cs[i].config); | |
76 | + out_be32(&ddr->cs1_config_2, regs->cs[i].config_2); | |
77 | + | |
78 | + } else if (i == 2) { | |
79 | + out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); | |
80 | + out_be32(&ddr->cs2_config, regs->cs[i].config); | |
81 | + out_be32(&ddr->cs2_config_2, regs->cs[i].config_2); | |
82 | + | |
83 | + } else if (i == 3) { | |
84 | + out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); | |
85 | + out_be32(&ddr->cs3_config, regs->cs[i].config); | |
86 | + out_be32(&ddr->cs3_config_2, regs->cs[i].config_2); | |
87 | + } | |
88 | + } | |
89 | + | |
90 | + out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3); | |
91 | + out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0); | |
92 | + out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); | |
93 | + out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); | |
94 | + out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); | |
95 | + out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); | |
96 | + out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2); | |
97 | + out_be32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3); | |
98 | + out_be32(&ddr->sdram_mode_4, regs->ddr_sdram_mode_4); | |
99 | + out_be32(&ddr->sdram_mode_5, regs->ddr_sdram_mode_5); | |
100 | + out_be32(&ddr->sdram_mode_6, regs->ddr_sdram_mode_6); | |
101 | + out_be32(&ddr->sdram_mode_7, regs->ddr_sdram_mode_7); | |
102 | + out_be32(&ddr->sdram_mode_8, regs->ddr_sdram_mode_8); | |
103 | + out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl); | |
104 | + out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); | |
105 | + out_be32(&ddr->sdram_data_init, regs->ddr_data_init); | |
106 | + out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); | |
107 | + out_be32(&ddr->init_addr, regs->ddr_init_addr); | |
108 | + out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); | |
109 | + | |
110 | + out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4); | |
111 | + out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5); | |
112 | + out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl); | |
113 | + out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl); | |
114 | +#ifndef CONFIG_SYS_FSL_DDR_EMU | |
115 | + /* | |
116 | + * Skip these two registers if running on emulator | |
117 | + * because emulator doesn't have skew between bytes. | |
118 | + */ | |
119 | + | |
120 | + if (regs->ddr_wrlvl_cntl_2) | |
121 | + out_be32(&ddr->ddr_wrlvl_cntl_2, regs->ddr_wrlvl_cntl_2); | |
122 | + if (regs->ddr_wrlvl_cntl_3) | |
123 | + out_be32(&ddr->ddr_wrlvl_cntl_3, regs->ddr_wrlvl_cntl_3); | |
124 | +#endif | |
125 | + | |
126 | + out_be32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr); | |
127 | + out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1); | |
128 | + out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2); | |
129 | + out_be32(&ddr->ddr_cdr1, regs->ddr_cdr1); | |
130 | + out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2); | |
131 | + out_be32(&ddr->err_disable, regs->err_disable); | |
132 | + out_be32(&ddr->err_int_en, regs->err_int_en); | |
133 | + for (i = 0; i < 32; i++) { | |
134 | + if (regs->debug[i]) { | |
135 | + debug("Write to debug_%d as %08x\n", i + 1, | |
136 | + regs->debug[i]); | |
137 | + out_be32(&ddr->debug[i], regs->debug[i]); | |
138 | + } | |
139 | + } | |
140 | + | |
141 | + /* | |
142 | + * For RDIMMs, JEDEC spec requires clocks to be stable before reset is | |
143 | + * deasserted. Clocks start when any chip select is enabled and clock | |
144 | + * control register is set. Because all DDR components are connected to | |
145 | + * one reset signal, this needs to be done in two steps. Step 1 is to | |
146 | + * get the clocks started. Step 2 resumes after reset signal is | |
147 | + * deasserted. | |
148 | + */ | |
149 | + if (step == 1) { | |
150 | + udelay(200); | |
151 | + return; | |
152 | + } | |
153 | + | |
154 | +step2: | |
155 | + /* Set, but do not enable the memory */ | |
156 | + temp_sdram_cfg = regs->ddr_sdram_cfg; | |
157 | + temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN); | |
158 | + out_be32(&ddr->sdram_cfg, temp_sdram_cfg); | |
159 | + | |
160 | + /* | |
161 | + * 500 painful micro-seconds must elapse between | |
162 | + * the DDR clock setup and the DDR config enable. | |
163 | + * DDR2 need 200 us, and DDR3 need 500 us from spec, | |
164 | + * we choose the max, that is 500 us for all of case. | |
165 | + */ | |
166 | + udelay(500); | |
167 | + asm volatile("dsb sy;isb"); | |
168 | + | |
169 | + /* Let the controller go */ | |
170 | + temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI; | |
171 | + out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN); | |
172 | + asm volatile("dsb sy;isb"); | |
173 | + | |
174 | + total_gb_size_per_controller = 0; | |
175 | + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { | |
176 | + if (!(regs->cs[i].config & 0x80000000)) | |
177 | + continue; | |
178 | + total_gb_size_per_controller += 1 << ( | |
179 | + ((regs->cs[i].config >> 14) & 0x3) + 2 + | |
180 | + ((regs->cs[i].config >> 8) & 0x7) + 12 + | |
181 | + ((regs->cs[i].config >> 0) & 0x7) + 8 + | |
182 | + 3 - ((regs->ddr_sdram_cfg >> 19) & 0x3) - | |
183 | + 26); /* minus 26 (count of 64M) */ | |
184 | + } | |
185 | + if (regs->cs[0].config & 0x20000000) { | |
186 | + /* 2-way interleaving */ | |
187 | + total_gb_size_per_controller <<= 1; | |
188 | + } | |
189 | + /* | |
190 | + * total memory / bus width = transactions needed | |
191 | + * transactions needed / data rate = seconds | |
192 | + * to add plenty of buffer, double the time | |
193 | + * For example, 2GB on 666MT/s 64-bit bus takes about 402ms | |
194 | + * Let's wait for 800ms | |
195 | + */ | |
196 | + bus_width = 3 - ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK) | |
197 | + >> SDRAM_CFG_DBW_SHIFT); | |
198 | + timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 / | |
199 | + (get_ddr_freq(0) >> 20)) << 1; | |
200 | + total_gb_size_per_controller >>= 4; /* shift down to gb size */ | |
201 | + debug("total %d GB\n", total_gb_size_per_controller); | |
202 | + debug("Need to wait up to %d * 10ms\n", timeout); | |
203 | + | |
204 | + /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */ | |
205 | + while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) && | |
206 | + (timeout >= 0)) { | |
207 | + udelay(10000); /* throttle polling rate */ | |
208 | + timeout--; | |
209 | + } | |
210 | + | |
211 | + if (timeout <= 0) | |
212 | + printf("Waiting for D_INIT timeout. Memory may not work.\n"); | |
213 | +} |
drivers/ddr/fsl/main.c
... | ... | @@ -15,16 +15,18 @@ |
15 | 15 | #include <common.h> |
16 | 16 | #include <i2c.h> |
17 | 17 | #include <fsl_ddr_sdram.h> |
18 | -#include <asm/fsl_law.h> | |
19 | - | |
20 | 18 | #include <fsl_ddr.h> |
21 | 19 | |
20 | +#ifdef CONFIG_PPC | |
21 | +#include <asm/fsl_law.h> | |
22 | + | |
22 | 23 | void fsl_ddr_set_lawbar( |
23 | 24 | const common_timing_params_t *memctl_common_params, |
24 | 25 | unsigned int memctl_interleaved, |
25 | 26 | unsigned int ctrl_num); |
26 | -void fsl_ddr_set_intl3r(const unsigned int granule_size); | |
27 | +#endif | |
27 | 28 | |
29 | +void fsl_ddr_set_intl3r(const unsigned int granule_size); | |
28 | 30 | #if defined(SPD_EEPROM_ADDRESS) || \ |
29 | 31 | defined(SPD_EEPROM_ADDRESS1) || defined(SPD_EEPROM_ADDRESS2) || \ |
30 | 32 | defined(SPD_EEPROM_ADDRESS3) || defined(SPD_EEPROM_ADDRESS4) |
31 | 33 | |
... | ... | @@ -549,7 +551,9 @@ |
549 | 551 | phys_size_t fsl_ddr_sdram(void) |
550 | 552 | { |
551 | 553 | unsigned int i; |
554 | +#ifdef CONFIG_PPC | |
552 | 555 | unsigned int law_memctl = LAW_TRGT_IF_DDR_1; |
556 | +#endif | |
553 | 557 | unsigned long long total_memory; |
554 | 558 | fsl_ddr_info_t info; |
555 | 559 | int deassert_reset; |
... | ... | @@ -621,6 +625,7 @@ |
621 | 625 | } |
622 | 626 | } |
623 | 627 | |
628 | +#ifdef CONFIG_PPC | |
624 | 629 | /* program LAWs */ |
625 | 630 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { |
626 | 631 | if (info.memctl_opts[i].memctl_interleaving) { |
... | ... | @@ -681,6 +686,7 @@ |
681 | 686 | law_memctl, i); |
682 | 687 | } |
683 | 688 | } |
689 | +#endif | |
684 | 690 | |
685 | 691 | debug("total_memory by %s = %llu\n", __func__, total_memory); |
686 | 692 |
drivers/ddr/fsl/util.c
... | ... | @@ -7,7 +7,9 @@ |
7 | 7 | */ |
8 | 8 | |
9 | 9 | #include <common.h> |
10 | +#ifdef CONFIG_PPC | |
10 | 11 | #include <asm/fsl_law.h> |
12 | +#endif | |
11 | 13 | #include <div64.h> |
12 | 14 | |
13 | 15 | #include <fsl_ddr.h> |
... | ... | @@ -79,6 +81,7 @@ |
79 | 81 | return get_memory_clk_period_ps() * mclk; |
80 | 82 | } |
81 | 83 | |
84 | +#ifdef CONFIG_PPC | |
82 | 85 | void |
83 | 86 | __fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, |
84 | 87 | unsigned int law_memctl, |
... | ... | @@ -113,6 +116,7 @@ |
113 | 116 | fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, |
114 | 117 | unsigned int memctl_interleaved, |
115 | 118 | unsigned int ctrl_num); |
119 | +#endif | |
116 | 120 | |
117 | 121 | void fsl_ddr_set_intl3r(const unsigned int granule_size) |
118 | 122 | { |