Commit a4c66509f1b95884e5753d5a30cf2cf884adb821
Committed by
Andy Fleming
1 parent
fcea30688f
Exists in
master
and in
54 other branches
powerpc/mpc8xxx: Enable 3-way and 4-way DDR interleaving
Restructure DDR interleaving option to support 3 and 4 DDR controllers for 2-, 3- and 4-way interleaving. Signed-off-by: York Sun <yorksun@freescale.com> Signed-off-by: Andy Fleming <afleming@freescale.com>
Showing 10 changed files with 489 additions and 320 deletions Side-by-side Diff
- arch/powerpc/cpu/mpc85xx/cpu.c
- arch/powerpc/cpu/mpc85xx/ddr-gen3.c
- arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
- arch/powerpc/cpu/mpc8xxx/ddr/main.c
- arch/powerpc/cpu/mpc8xxx/ddr/options.c
- arch/powerpc/cpu/mpc8xxx/ddr/util.c
- arch/powerpc/include/asm/fsl_ddr_sdram.h
- arch/powerpc/include/asm/fsl_law.h
- arch/powerpc/include/asm/immap_85xx.h
- doc/README.fsl-ddr
arch/powerpc/cpu/mpc85xx/cpu.c
... | ... | @@ -430,9 +430,19 @@ |
430 | 430 | case 0: |
431 | 431 | ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR; |
432 | 432 | break; |
433 | -#ifdef CONFIG_SYS_MPC85xx_DDR2_ADDR | |
433 | +#if defined(CONFIG_SYS_MPC85xx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) | |
434 | 434 | case 1: |
435 | 435 | ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR; |
436 | + break; | |
437 | +#endif | |
438 | +#if defined(CONFIG_SYS_MPC85xx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) | |
439 | + case 2: | |
440 | + ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR; | |
441 | + break; | |
442 | +#endif | |
443 | +#if defined(CONFIG_SYS_MPC85xx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) | |
444 | + case 3: | |
445 | + ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR4_ADDR; | |
436 | 446 | break; |
437 | 447 | #endif |
438 | 448 | default: |
arch/powerpc/cpu/mpc85xx/ddr-gen3.c
... | ... | @@ -32,9 +32,21 @@ |
32 | 32 | case 0: |
33 | 33 | ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR; |
34 | 34 | break; |
35 | +#if defined(CONFIG_SYS_MPC85xx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) | |
35 | 36 | case 1: |
36 | 37 | ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR; |
37 | 38 | break; |
39 | +#endif | |
40 | +#if defined(CONFIG_SYS_MPC85xx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) | |
41 | + case 2: | |
42 | + ddr = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR; | |
43 | + break; | |
44 | +#endif | |
45 | +#if defined(CONFIG_SYS_MPC85xx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) | |
46 | + case 3: | |
47 | + ddr = (void *)CONFIG_SYS_MPC85xx_DDR4_ADDR; | |
48 | + break; | |
49 | +#endif | |
38 | 50 | default: |
39 | 51 | printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); |
40 | 52 | return; |
arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
... | ... | @@ -151,8 +151,19 @@ |
151 | 151 | if (dimm_params[dimm_number].n_ranks > 0) { |
152 | 152 | go_config = 1; |
153 | 153 | /* These fields only available in CS0_CONFIG */ |
154 | - intlv_en = popts->memctl_interleaving; | |
155 | - intlv_ctl = popts->memctl_interleaving_mode; | |
154 | + if (!popts->memctl_interleaving) | |
155 | + break; | |
156 | + switch (popts->memctl_interleaving_mode) { | |
157 | + case FSL_DDR_CACHE_LINE_INTERLEAVING: | |
158 | + case FSL_DDR_PAGE_INTERLEAVING: | |
159 | + case FSL_DDR_BANK_INTERLEAVING: | |
160 | + case FSL_DDR_SUPERBANK_INTERLEAVING: | |
161 | + intlv_en = popts->memctl_interleaving; | |
162 | + intlv_ctl = popts->memctl_interleaving_mode; | |
163 | + break; | |
164 | + default: | |
165 | + break; | |
166 | + } | |
156 | 167 | } |
157 | 168 | break; |
158 | 169 | case 1: |
159 | 170 | |
160 | 171 | |
161 | 172 | |
162 | 173 | |
163 | 174 | |
164 | 175 | |
165 | 176 | |
166 | 177 | |
... | ... | @@ -1413,73 +1424,37 @@ |
1413 | 1424 | |
1414 | 1425 | /* Chip Select Memory Bounds (CSn_BNDS) */ |
1415 | 1426 | for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { |
1416 | - unsigned long long ea = 0, sa = 0; | |
1427 | + unsigned long long ea, sa; | |
1417 | 1428 | unsigned int cs_per_dimm |
1418 | 1429 | = CONFIG_CHIP_SELECTS_PER_CTRL / CONFIG_DIMM_SLOTS_PER_CTLR; |
1419 | 1430 | unsigned int dimm_number |
1420 | 1431 | = i / cs_per_dimm; |
1421 | 1432 | unsigned long long rank_density |
1422 | - = dimm_params[dimm_number].rank_density; | |
1433 | + = dimm_params[dimm_number].rank_density >> dbw_cap_adj; | |
1423 | 1434 | |
1424 | - if (((i == 1) && (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1)) || | |
1425 | - ((i == 2) && (popts->ba_intlv_ctl & 0x04)) || | |
1426 | - ((i == 3) && (popts->ba_intlv_ctl & FSL_DDR_CS2_CS3))) { | |
1427 | - /* | |
1428 | - * Don't set up boundaries for unused CS | |
1429 | - * cs1 for cs0_cs1, cs0_cs1_and_cs2_cs3, cs0_cs1_cs2_cs3 | |
1430 | - * cs2 for cs0_cs1_cs2_cs3 | |
1431 | - * cs3 for cs2_cs3, cs0_cs1_and_cs2_cs3, cs0_cs1_cs2_cs3 | |
1432 | - * But we need to set the ODT_RD_CFG and | |
1433 | - * ODT_WR_CFG for CS1_CONFIG here. | |
1434 | - */ | |
1435 | - set_csn_config(dimm_number, i, ddr, popts, dimm_params); | |
1436 | - continue; | |
1437 | - } | |
1438 | 1435 | if (dimm_params[dimm_number].n_ranks == 0) { |
1439 | 1436 | debug("Skipping setup of CS%u " |
1440 | 1437 | "because n_ranks on DIMM %u is 0\n", i, dimm_number); |
1441 | 1438 | continue; |
1442 | 1439 | } |
1443 | - if (popts->memctl_interleaving && popts->ba_intlv_ctl) { | |
1444 | - /* | |
1445 | - * This works superbank 2CS | |
1446 | - * There are 2 or more memory controllers configured | |
1447 | - * identically, memory is interleaved between them, | |
1448 | - * and each controller uses rank interleaving within | |
1449 | - * itself. Therefore the starting and ending address | |
1450 | - * on each controller is twice the amount present on | |
1451 | - * each controller. If any CS is not included in the | |
1452 | - * interleaving, the memory on that CS is not accssible | |
1453 | - * and the total memory size is reduced. The CS is also | |
1454 | - * disabled. | |
1455 | - */ | |
1456 | - unsigned long long ctlr_density = 0; | |
1440 | + if (popts->memctl_interleaving) { | |
1457 | 1441 | switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { |
1442 | + case FSL_DDR_CS0_CS1_CS2_CS3: | |
1443 | + break; | |
1458 | 1444 | case FSL_DDR_CS0_CS1: |
1459 | 1445 | case FSL_DDR_CS0_CS1_AND_CS2_CS3: |
1460 | - ctlr_density = dimm_params[0].rank_density * 2; | |
1461 | 1446 | if (i > 1) |
1462 | 1447 | cs_en = 0; |
1463 | 1448 | break; |
1464 | 1449 | case FSL_DDR_CS2_CS3: |
1465 | - ctlr_density = dimm_params[0].rank_density; | |
1450 | + default: | |
1466 | 1451 | if (i > 0) |
1467 | 1452 | cs_en = 0; |
1468 | 1453 | break; |
1469 | - case FSL_DDR_CS0_CS1_CS2_CS3: | |
1470 | - /* | |
1471 | - * The four CS interleaving should have been verified by | |
1472 | - * populate_memctl_options() | |
1473 | - */ | |
1474 | - ctlr_density = dimm_params[0].rank_density * 4; | |
1475 | - break; | |
1476 | - default: | |
1477 | - break; | |
1478 | 1454 | } |
1479 | - ea = (CONFIG_NUM_DDR_CONTROLLERS * | |
1480 | - (ctlr_density >> dbw_cap_adj)) - 1; | |
1481 | - } | |
1482 | - else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) { | |
1455 | + sa = common_dimm->base_address; | |
1456 | + ea = common_dimm->total_mem - 1; | |
1457 | + } else if (!popts->memctl_interleaving) { | |
1483 | 1458 | /* |
1484 | 1459 | * If memory interleaving between controllers is NOT |
1485 | 1460 | * enabled, the starting address for each memory |
1486 | 1461 | |
1487 | 1462 | |
1488 | 1463 | |
1489 | 1464 | |
1490 | 1465 | |
1491 | 1466 | |
1492 | 1467 | |
1493 | 1468 | |
1494 | 1469 | |
... | ... | @@ -1491,49 +1466,40 @@ |
1491 | 1466 | */ |
1492 | 1467 | switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { |
1493 | 1468 | case FSL_DDR_CS0_CS1_CS2_CS3: |
1494 | - /* CS0+CS1+CS2+CS3 interleaving, only CS0_CNDS | |
1495 | - * needs to be set. | |
1496 | - */ | |
1497 | 1469 | sa = common_dimm->base_address; |
1498 | - ea = sa + (4 * (rank_density >> dbw_cap_adj))-1; | |
1470 | + ea = common_dimm->total_mem - 1; | |
1499 | 1471 | break; |
1500 | 1472 | case FSL_DDR_CS0_CS1_AND_CS2_CS3: |
1501 | - /* CS0+CS1 and CS2+CS3 interleaving, CS0_CNDS | |
1502 | - * and CS2_CNDS need to be set. | |
1503 | - */ | |
1504 | - if ((i == 2) && (dimm_number == 0)) { | |
1473 | + if ((i >= 2) && (dimm_number == 0)) { | |
1505 | 1474 | sa = dimm_params[dimm_number].base_address + |
1506 | - 2 * (rank_density >> dbw_cap_adj); | |
1507 | - ea = sa + 2 * (rank_density >> dbw_cap_adj) - 1; | |
1475 | + 2 * rank_density; | |
1476 | + ea = sa + 2 * rank_density - 1; | |
1508 | 1477 | } else { |
1509 | 1478 | sa = dimm_params[dimm_number].base_address; |
1510 | - ea = sa + (2 * (rank_density >> | |
1511 | - dbw_cap_adj)) - 1; | |
1479 | + ea = sa + 2 * rank_density - 1; | |
1512 | 1480 | } |
1513 | 1481 | break; |
1514 | 1482 | case FSL_DDR_CS0_CS1: |
1515 | - /* CS0+CS1 interleaving, CS0_CNDS needs | |
1516 | - * to be set | |
1517 | - */ | |
1518 | 1483 | if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { |
1519 | 1484 | sa = dimm_params[dimm_number].base_address; |
1520 | - ea = sa + (rank_density >> dbw_cap_adj) - 1; | |
1521 | - sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); | |
1522 | - ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); | |
1485 | + ea = sa + rank_density - 1; | |
1486 | + if (i != 1) | |
1487 | + sa += (i % cs_per_dimm) * rank_density; | |
1488 | + ea += (i % cs_per_dimm) * rank_density; | |
1523 | 1489 | } else { |
1524 | 1490 | sa = 0; |
1525 | 1491 | ea = 0; |
1526 | 1492 | } |
1527 | 1493 | if (i == 0) |
1528 | - ea += (rank_density >> dbw_cap_adj); | |
1494 | + ea += rank_density; | |
1529 | 1495 | break; |
1530 | 1496 | case FSL_DDR_CS2_CS3: |
1531 | - /* CS2+CS3 interleaving*/ | |
1532 | 1497 | if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { |
1533 | 1498 | sa = dimm_params[dimm_number].base_address; |
1534 | - ea = sa + (rank_density >> dbw_cap_adj) - 1; | |
1535 | - sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); | |
1536 | - ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); | |
1499 | + ea = sa + rank_density - 1; | |
1500 | + if (i != 3) | |
1501 | + sa += (i % cs_per_dimm) * rank_density; | |
1502 | + ea += (i % cs_per_dimm) * rank_density; | |
1537 | 1503 | } else { |
1538 | 1504 | sa = 0; |
1539 | 1505 | ea = 0; |
1540 | 1506 | |
... | ... | @@ -1542,36 +1508,16 @@ |
1542 | 1508 | ea += (rank_density >> dbw_cap_adj); |
1543 | 1509 | break; |
1544 | 1510 | default: /* No bank(chip-select) interleaving */ |
1511 | + sa = dimm_params[dimm_number].base_address; | |
1512 | + ea = sa + rank_density - 1; | |
1513 | + if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { | |
1514 | + sa += (i % cs_per_dimm) * rank_density; | |
1515 | + ea += (i % cs_per_dimm) * rank_density; | |
1516 | + } else { | |
1517 | + sa = 0; | |
1518 | + ea = 0; | |
1519 | + } | |
1545 | 1520 | break; |
1546 | - } | |
1547 | - } | |
1548 | - else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) { | |
1549 | - /* | |
1550 | - * Only the rank on CS0 of each memory controller may | |
1551 | - * be used if memory controller interleaving is used | |
1552 | - * without rank interleaving within each memory | |
1553 | - * controller. However, the ending address programmed | |
1554 | - * into each CS0 must be the sum of the amount of | |
1555 | - * memory in the two CS0 ranks. | |
1556 | - */ | |
1557 | - if (i == 0) { | |
1558 | - ea = (2 * (rank_density >> dbw_cap_adj)) - 1; | |
1559 | - } | |
1560 | - | |
1561 | - } | |
1562 | - else if (!popts->memctl_interleaving && !popts->ba_intlv_ctl) { | |
1563 | - /* | |
1564 | - * No rank interleaving and no memory controller | |
1565 | - * interleaving. | |
1566 | - */ | |
1567 | - sa = dimm_params[dimm_number].base_address; | |
1568 | - ea = sa + (rank_density >> dbw_cap_adj) - 1; | |
1569 | - if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { | |
1570 | - sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); | |
1571 | - ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); | |
1572 | - } else { | |
1573 | - sa = 0; | |
1574 | - ea = 0; | |
1575 | 1521 | } |
1576 | 1522 | } |
1577 | 1523 |
arch/powerpc/cpu/mpc8xxx/ddr/main.c
1 | 1 | /* |
2 | - * Copyright 2008-2011 Freescale Semiconductor, Inc. | |
2 | + * Copyright 2008-2012 Freescale Semiconductor, Inc. | |
3 | 3 | * |
4 | 4 | * This program is free software; you can redistribute it and/or |
5 | 5 | * modify it under the terms of the GNU General Public License |
6 | 6 | |
7 | 7 | |
... | ... | @@ -15,13 +15,15 @@ |
15 | 15 | #include <common.h> |
16 | 16 | #include <i2c.h> |
17 | 17 | #include <asm/fsl_ddr_sdram.h> |
18 | +#include <asm/fsl_law.h> | |
18 | 19 | |
19 | 20 | #include "ddr.h" |
20 | 21 | |
21 | -extern void fsl_ddr_set_lawbar( | |
22 | +void fsl_ddr_set_lawbar( | |
22 | 23 | const common_timing_params_t *memctl_common_params, |
23 | 24 | unsigned int memctl_interleaved, |
24 | 25 | unsigned int ctrl_num); |
26 | +void fsl_ddr_set_intl3r(const unsigned int granule_size); | |
25 | 27 | |
26 | 28 | /* processor specific function */ |
27 | 29 | extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, |
... | ... | @@ -51,6 +53,22 @@ |
51 | 53 | [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */ |
52 | 54 | [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */ |
53 | 55 | }; |
56 | +#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) | |
57 | +u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { | |
58 | + [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ | |
59 | + [1][0] = SPD_EEPROM_ADDRESS2, /* controller 2 */ | |
60 | + [2][0] = SPD_EEPROM_ADDRESS3, /* controller 3 */ | |
61 | +}; | |
62 | +#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) | |
63 | +u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { | |
64 | + [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ | |
65 | + [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ | |
66 | + [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */ | |
67 | + [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */ | |
68 | + [2][0] = SPD_EEPROM_ADDRESS5, /* controller 3 */ | |
69 | + [2][1] = SPD_EEPROM_ADDRESS6, /* controller 3 */ | |
70 | +}; | |
71 | + | |
54 | 72 | #endif |
55 | 73 | |
56 | 74 | static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address) |
57 | 75 | |
... | ... | @@ -156,12 +174,12 @@ |
156 | 174 | return step_string_tbl[s]; |
157 | 175 | } |
158 | 176 | |
159 | -int step_assign_addresses(fsl_ddr_info_t *pinfo, | |
160 | - unsigned int dbw_cap_adj[], | |
161 | - unsigned int *all_memctl_interleaving, | |
162 | - unsigned int *all_ctlr_rank_interleaving) | |
177 | +unsigned long long step_assign_addresses(fsl_ddr_info_t *pinfo, | |
178 | + unsigned int dbw_cap_adj[]) | |
163 | 179 | { |
164 | 180 | int i, j; |
181 | + unsigned long long total_mem, current_mem_base, total_ctlr_mem; | |
182 | + unsigned long long rank_density, ctlr_density = 0; | |
165 | 183 | |
166 | 184 | /* |
167 | 185 | * If a reduced data width is requested, but the SPD |
168 | 186 | |
169 | 187 | |
170 | 188 | |
171 | 189 | |
172 | 190 | |
173 | 191 | |
174 | 192 | |
175 | 193 | |
176 | 194 | |
177 | 195 | |
178 | 196 | |
179 | 197 | |
... | ... | @@ -220,86 +238,108 @@ |
220 | 238 | "specified controller %u\n", i); |
221 | 239 | return 1; |
222 | 240 | } |
241 | + debug("dbw_cap_adj[%d]=%d\n", i, dbw_cap_adj[i]); | |
223 | 242 | } |
224 | 243 | |
225 | - j = 0; | |
226 | - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) | |
227 | - if (pinfo->memctl_opts[i].memctl_interleaving) | |
228 | - j++; | |
229 | - /* | |
230 | - * Not support less than all memory controllers interleaving | |
231 | - * if more than two controllers | |
232 | - */ | |
233 | - if (j == CONFIG_NUM_DDR_CONTROLLERS) | |
234 | - *all_memctl_interleaving = 1; | |
235 | - | |
236 | - /* Check that all controllers are rank interleaving. */ | |
237 | - j = 0; | |
238 | - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) | |
239 | - if (pinfo->memctl_opts[i].ba_intlv_ctl) | |
240 | - j++; | |
241 | - /* | |
242 | - * All memory controllers must be populated to qualify for | |
243 | - * all controller rank interleaving | |
244 | - */ | |
245 | - if (j == CONFIG_NUM_DDR_CONTROLLERS) | |
246 | - *all_ctlr_rank_interleaving = 1; | |
247 | - | |
248 | - if (*all_memctl_interleaving) { | |
249 | - unsigned long long addr, total_mem_per_ctlr = 0; | |
250 | - /* | |
251 | - * If interleaving between memory controllers, | |
252 | - * make each controller start at a base address | |
253 | - * of 0. | |
254 | - * | |
255 | - * Also, if bank interleaving (chip select | |
256 | - * interleaving) is enabled on each memory | |
257 | - * controller, CS0 needs to be programmed to | |
258 | - * cover the entire memory range on that memory | |
259 | - * controller | |
260 | - * | |
261 | - * Bank interleaving also implies that each | |
262 | - * addressed chip select is identical in size. | |
263 | - */ | |
264 | - | |
244 | + current_mem_base = 0ull; | |
245 | + total_mem = 0; | |
246 | + if (pinfo->memctl_opts[0].memctl_interleaving) { | |
247 | + rank_density = pinfo->dimm_params[0][0].rank_density >> | |
248 | + dbw_cap_adj[0]; | |
249 | + switch (pinfo->memctl_opts[0].ba_intlv_ctl & | |
250 | + FSL_DDR_CS0_CS1_CS2_CS3) { | |
251 | + case FSL_DDR_CS0_CS1_CS2_CS3: | |
252 | + ctlr_density = 4 * rank_density; | |
253 | + break; | |
254 | + case FSL_DDR_CS0_CS1: | |
255 | + case FSL_DDR_CS0_CS1_AND_CS2_CS3: | |
256 | + ctlr_density = 2 * rank_density; | |
257 | + break; | |
258 | + case FSL_DDR_CS2_CS3: | |
259 | + default: | |
260 | + ctlr_density = rank_density; | |
261 | + break; | |
262 | + } | |
263 | + debug("rank density is 0x%llx, ctlr density is 0x%llx\n", | |
264 | + rank_density, ctlr_density); | |
265 | 265 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { |
266 | - addr = 0; | |
267 | - pinfo->common_timing_params[i].base_address = 0ull; | |
268 | - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { | |
269 | - unsigned long long cap | |
270 | - = pinfo->dimm_params[i][j].capacity; | |
271 | - | |
272 | - pinfo->dimm_params[i][j].base_address = addr; | |
273 | - addr += cap >> dbw_cap_adj[i]; | |
274 | - total_mem_per_ctlr += cap >> dbw_cap_adj[i]; | |
266 | + if (pinfo->memctl_opts[i].memctl_interleaving) { | |
267 | + switch (pinfo->memctl_opts[i].memctl_interleaving_mode) { | |
268 | + case FSL_DDR_CACHE_LINE_INTERLEAVING: | |
269 | + case FSL_DDR_PAGE_INTERLEAVING: | |
270 | + case FSL_DDR_BANK_INTERLEAVING: | |
271 | + case FSL_DDR_SUPERBANK_INTERLEAVING: | |
272 | + total_ctlr_mem = 2 * ctlr_density; | |
273 | + break; | |
274 | + case FSL_DDR_3WAY_1KB_INTERLEAVING: | |
275 | + case FSL_DDR_3WAY_4KB_INTERLEAVING: | |
276 | + case FSL_DDR_3WAY_8KB_INTERLEAVING: | |
277 | + total_ctlr_mem = 3 * ctlr_density; | |
278 | + break; | |
279 | + case FSL_DDR_4WAY_1KB_INTERLEAVING: | |
280 | + case FSL_DDR_4WAY_4KB_INTERLEAVING: | |
281 | + case FSL_DDR_4WAY_8KB_INTERLEAVING: | |
282 | + total_ctlr_mem = 4 * ctlr_density; | |
283 | + break; | |
284 | + default: | |
285 | + panic("Unknown interleaving mode"); | |
286 | + } | |
287 | + pinfo->common_timing_params[i].base_address = | |
288 | + current_mem_base; | |
289 | + pinfo->common_timing_params[i].total_mem = | |
290 | + total_ctlr_mem; | |
291 | + total_mem = current_mem_base + total_ctlr_mem; | |
292 | + debug("ctrl %d base 0x%llx\n", i, current_mem_base); | |
293 | + debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); | |
294 | + } else { | |
295 | + /* when 3rd controller not interleaved */ | |
296 | + current_mem_base = total_mem; | |
297 | + total_ctlr_mem = 0; | |
298 | + pinfo->common_timing_params[i].base_address = | |
299 | + current_mem_base; | |
300 | + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { | |
301 | + unsigned long long cap = | |
302 | + pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i]; | |
303 | + pinfo->dimm_params[i][j].base_address = | |
304 | + current_mem_base; | |
305 | + debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base); | |
306 | + current_mem_base += cap; | |
307 | + total_ctlr_mem += cap; | |
308 | + } | |
309 | + debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); | |
310 | + pinfo->common_timing_params[i].total_mem = | |
311 | + total_ctlr_mem; | |
312 | + total_mem += total_ctlr_mem; | |
275 | 313 | } |
276 | 314 | } |
277 | - pinfo->common_timing_params[0].total_mem = total_mem_per_ctlr; | |
278 | 315 | } else { |
279 | 316 | /* |
280 | 317 | * Simple linear assignment if memory |
281 | 318 | * controllers are not interleaved. |
282 | 319 | */ |
283 | - unsigned long long cur_memsize = 0; | |
284 | 320 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { |
285 | - u64 total_mem_per_ctlr = 0; | |
321 | + total_ctlr_mem = 0; | |
286 | 322 | pinfo->common_timing_params[i].base_address = |
287 | - cur_memsize; | |
323 | + current_mem_base; | |
288 | 324 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { |
289 | 325 | /* Compute DIMM base addresses. */ |
290 | 326 | unsigned long long cap = |
291 | - pinfo->dimm_params[i][j].capacity; | |
327 | + pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i]; | |
292 | 328 | pinfo->dimm_params[i][j].base_address = |
293 | - cur_memsize; | |
294 | - cur_memsize += cap >> dbw_cap_adj[i]; | |
295 | - total_mem_per_ctlr += cap >> dbw_cap_adj[i]; | |
329 | + current_mem_base; | |
330 | + debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base); | |
331 | + current_mem_base += cap; | |
332 | + total_ctlr_mem += cap; | |
296 | 333 | } |
334 | + debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); | |
297 | 335 | pinfo->common_timing_params[i].total_mem = |
298 | - total_mem_per_ctlr; | |
336 | + total_ctlr_mem; | |
337 | + total_mem += total_ctlr_mem; | |
299 | 338 | } |
300 | 339 | } |
340 | + debug("Total mem by %s is 0x%llx\n", __func__, total_mem); | |
301 | 341 | |
302 | - return 0; | |
342 | + return total_mem; | |
303 | 343 | } |
304 | 344 | |
305 | 345 | unsigned long long |
... | ... | @@ -307,8 +347,6 @@ |
307 | 347 | unsigned int size_only) |
308 | 348 | { |
309 | 349 | unsigned int i, j; |
310 | - unsigned int all_controllers_memctl_interleaving = 0; | |
311 | - unsigned int all_controllers_rank_interleaving = 0; | |
312 | 350 | unsigned long long total_mem = 0; |
313 | 351 | |
314 | 352 | fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg; |
... | ... | @@ -346,8 +384,9 @@ |
346 | 384 | retval = compute_dimm_parameters(spd, pdimm, i); |
347 | 385 | #ifdef CONFIG_SYS_DDR_RAW_TIMING |
348 | 386 | if (retval != 0) { |
349 | - printf("SPD error! Trying fallback to " | |
350 | - "raw timing calculation\n"); | |
387 | + printf("SPD error on controller %d! " | |
388 | + "Trying fallback to raw timing " | |
389 | + "calculation\n", i); | |
351 | 390 | fsl_ddr_get_dimm_params(pdimm, i, j); |
352 | 391 | } |
353 | 392 | #else |
354 | 393 | |
355 | 394 | |
... | ... | @@ -407,17 +446,14 @@ |
407 | 446 | &pinfo->memctl_opts[i], |
408 | 447 | pinfo->dimm_params[i], i); |
409 | 448 | } |
410 | - check_interleaving_options(pinfo); | |
411 | 449 | case STEP_ASSIGN_ADDRESSES: |
412 | 450 | /* STEP 5: Assign addresses to chip selects */ |
413 | - step_assign_addresses(pinfo, | |
414 | - dbw_capacity_adjust, | |
415 | - &all_controllers_memctl_interleaving, | |
416 | - &all_controllers_rank_interleaving); | |
451 | + check_interleaving_options(pinfo); | |
452 | + total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust); | |
417 | 453 | |
418 | 454 | case STEP_COMPUTE_REGS: |
419 | 455 | /* STEP 6: compute controller register values */ |
420 | - debug("FSL Memory ctrl cg register computation\n"); | |
456 | + debug("FSL Memory ctrl register computation\n"); | |
421 | 457 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { |
422 | 458 | if (timing_params[i].ndimms_present == 0) { |
423 | 459 | memset(&ddr_reg[i], 0, |
... | ... | @@ -437,21 +473,7 @@ |
437 | 473 | break; |
438 | 474 | } |
439 | 475 | |
440 | - /* Compute the total amount of memory. */ | |
441 | - | |
442 | - /* | |
443 | - * If bank interleaving but NOT memory controller interleaving | |
444 | - * CS_BNDS describe the quantity of memory on each memory | |
445 | - * controller, so the total is the sum across. | |
446 | - */ | |
447 | - if (!all_controllers_memctl_interleaving | |
448 | - && all_controllers_rank_interleaving) { | |
449 | - total_mem = 0; | |
450 | - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
451 | - total_mem += timing_params[i].total_mem; | |
452 | - } | |
453 | - | |
454 | - } else { | |
476 | + { | |
455 | 477 | /* |
456 | 478 | * Compute the amount of memory available just by |
457 | 479 | * looking for the highest valid CSn_BNDS value. |
... | ... | @@ -489,7 +511,7 @@ |
489 | 511 | phys_size_t fsl_ddr_sdram(void) |
490 | 512 | { |
491 | 513 | unsigned int i; |
492 | - unsigned int memctl_interleaved; | |
514 | + unsigned int law_memctl = LAW_TRGT_IF_DDR_1; | |
493 | 515 | unsigned long long total_memory; |
494 | 516 | fsl_ddr_info_t info; |
495 | 517 | |
... | ... | @@ -504,34 +526,6 @@ |
504 | 526 | #endif |
505 | 527 | total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0); |
506 | 528 | |
507 | - /* Check for memory controller interleaving. */ | |
508 | - memctl_interleaved = 0; | |
509 | - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
510 | - memctl_interleaved += | |
511 | - info.memctl_opts[i].memctl_interleaving; | |
512 | - } | |
513 | - | |
514 | - if (memctl_interleaved) { | |
515 | - if (memctl_interleaved == CONFIG_NUM_DDR_CONTROLLERS) { | |
516 | - debug("memctl interleaving\n"); | |
517 | - /* | |
518 | - * Change the meaning of memctl_interleaved | |
519 | - * to be "boolean". | |
520 | - */ | |
521 | - memctl_interleaved = 1; | |
522 | - } else { | |
523 | - printf("Warning: memctl interleaving not " | |
524 | - "properly configured on all controllers\n"); | |
525 | - memctl_interleaved = 0; | |
526 | - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) | |
527 | - info.memctl_opts[i].memctl_interleaving = 0; | |
528 | - debug("Recomputing with memctl_interleaving off.\n"); | |
529 | - total_memory = fsl_ddr_compute(&info, | |
530 | - STEP_ASSIGN_ADDRESSES, | |
531 | - 0); | |
532 | - } | |
533 | - } | |
534 | - | |
535 | 529 | /* Program configuration registers. */ |
536 | 530 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { |
537 | 531 | debug("Programming controller %u\n", i); |
538 | 532 | |
539 | 533 | |
... | ... | @@ -544,24 +538,69 @@ |
544 | 538 | fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i); |
545 | 539 | } |
546 | 540 | |
547 | - if (memctl_interleaved) { | |
548 | - const unsigned int ctrl_num = 0; | |
549 | - | |
550 | - /* Only set LAWBAR1 if memory controller interleaving is on. */ | |
551 | - fsl_ddr_set_lawbar(&info.common_timing_params[0], | |
552 | - memctl_interleaved, ctrl_num); | |
553 | - } else { | |
554 | - /* | |
555 | - * Memory controller interleaving is NOT on; | |
556 | - * set each lawbar individually. | |
557 | - */ | |
558 | - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
541 | + /* program LAWs */ | |
542 | + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
543 | + if (info.memctl_opts[i].memctl_interleaving) { | |
544 | + switch (info.memctl_opts[i].memctl_interleaving_mode) { | |
545 | + case FSL_DDR_CACHE_LINE_INTERLEAVING: | |
546 | + case FSL_DDR_PAGE_INTERLEAVING: | |
547 | + case FSL_DDR_BANK_INTERLEAVING: | |
548 | + case FSL_DDR_SUPERBANK_INTERLEAVING: | |
549 | + if (i == 0) { | |
550 | + law_memctl = LAW_TRGT_IF_DDR_INTRLV; | |
551 | + fsl_ddr_set_lawbar(&info.common_timing_params[i], | |
552 | + law_memctl, i); | |
553 | + } else if (i == 2) { | |
554 | + law_memctl = LAW_TRGT_IF_DDR_INTLV_34; | |
555 | + fsl_ddr_set_lawbar(&info.common_timing_params[i], | |
556 | + law_memctl, i); | |
557 | + } | |
558 | + break; | |
559 | + case FSL_DDR_3WAY_1KB_INTERLEAVING: | |
560 | + case FSL_DDR_3WAY_4KB_INTERLEAVING: | |
561 | + case FSL_DDR_3WAY_8KB_INTERLEAVING: | |
562 | + law_memctl = LAW_TRGT_IF_DDR_INTLV_123; | |
563 | + if (i == 0) { | |
564 | + fsl_ddr_set_intl3r(info.memctl_opts[i].memctl_interleaving_mode); | |
565 | + fsl_ddr_set_lawbar(&info.common_timing_params[i], | |
566 | + law_memctl, i); | |
567 | + } | |
568 | + break; | |
569 | + case FSL_DDR_4WAY_1KB_INTERLEAVING: | |
570 | + case FSL_DDR_4WAY_4KB_INTERLEAVING: | |
571 | + case FSL_DDR_4WAY_8KB_INTERLEAVING: | |
572 | + law_memctl = LAW_TRGT_IF_DDR_INTLV_1234; | |
573 | + if (i == 0) | |
574 | + fsl_ddr_set_lawbar(&info.common_timing_params[i], | |
575 | + law_memctl, i); | |
576 | + /* place holder for future 4-way interleaving */ | |
577 | + break; | |
578 | + default: | |
579 | + break; | |
580 | + } | |
581 | + } else { | |
582 | + switch (i) { | |
583 | + case 0: | |
584 | + law_memctl = LAW_TRGT_IF_DDR_1; | |
585 | + break; | |
586 | + case 1: | |
587 | + law_memctl = LAW_TRGT_IF_DDR_2; | |
588 | + break; | |
589 | + case 2: | |
590 | + law_memctl = LAW_TRGT_IF_DDR_3; | |
591 | + break; | |
592 | + case 3: | |
593 | + law_memctl = LAW_TRGT_IF_DDR_4; | |
594 | + break; | |
595 | + default: | |
596 | + break; | |
597 | + } | |
559 | 598 | fsl_ddr_set_lawbar(&info.common_timing_params[i], |
560 | - 0, i); | |
599 | + law_memctl, i); | |
561 | 600 | } |
562 | 601 | } |
563 | 602 | |
564 | - debug("total_memory = %llu\n", total_memory); | |
603 | + debug("total_memory by %s = %llu\n", __func__, total_memory); | |
565 | 604 | |
566 | 605 | #if !defined(CONFIG_PHYS_64BIT) |
567 | 606 | /* Check for 4G or more. Bad. */ |
arch/powerpc/cpu/mpc8xxx/ddr/options.c
1 | 1 | /* |
2 | - * Copyright 2008, 2010-2011 Freescale Semiconductor, Inc. | |
2 | + * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc. | |
3 | 3 | * |
4 | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | 5 | * under the terms of the GNU General Public License as published by the Free |
6 | 6 | |
7 | 7 | |
... | ... | @@ -790,47 +790,98 @@ |
790 | 790 | * should be a subset of the requested configuration. |
791 | 791 | */ |
792 | 792 | #if (CONFIG_NUM_DDR_CONTROLLERS > 1) |
793 | - if (hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf)) { | |
794 | - if (pdimm[0].n_ranks == 0) { | |
795 | - printf("There is no rank on CS0 for controller %d. Because only" | |
796 | - " rank on CS0 and ranks chip-select interleaved with CS0" | |
797 | - " are controller interleaved, force non memory " | |
798 | - "controller interleaving\n", ctrl_num); | |
799 | - popts->memctl_interleaving = 0; | |
800 | - } else { | |
801 | - popts->memctl_interleaving = 1; | |
802 | - /* | |
803 | - * test null first. if CONFIG_HWCONFIG is not defined | |
804 | - * hwconfig_arg_cmp returns non-zero | |
805 | - */ | |
806 | - if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", | |
807 | - "null", buf)) { | |
808 | - popts->memctl_interleaving = 0; | |
809 | - debug("memory controller interleaving disabled.\n"); | |
810 | - } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
811 | - "ctlr_intlv", | |
812 | - "cacheline", buf)) | |
813 | - popts->memctl_interleaving_mode = | |
814 | - FSL_DDR_CACHE_LINE_INTERLEAVING; | |
815 | - else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", | |
816 | - "page", buf)) | |
817 | - popts->memctl_interleaving_mode = | |
818 | - FSL_DDR_PAGE_INTERLEAVING; | |
819 | - else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", | |
820 | - "bank", buf)) | |
821 | - popts->memctl_interleaving_mode = | |
822 | - FSL_DDR_BANK_INTERLEAVING; | |
823 | - else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", | |
824 | - "superbank", buf)) | |
825 | - popts->memctl_interleaving_mode = | |
826 | - FSL_DDR_SUPERBANK_INTERLEAVING; | |
827 | - else { | |
828 | - popts->memctl_interleaving = 0; | |
829 | - printf("hwconfig has unrecognized parameter for ctlr_intlv.\n"); | |
830 | - } | |
831 | - } | |
793 | + if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf)) | |
794 | + goto done; | |
795 | + | |
796 | + if (pdimm[0].n_ranks == 0) { | |
797 | + printf("There is no rank on CS0 for controller %d.\n", ctrl_num); | |
798 | + popts->memctl_interleaving = 0; | |
799 | + goto done; | |
832 | 800 | } |
801 | + popts->memctl_interleaving = 1; | |
802 | + /* | |
803 | + * test null first. if CONFIG_HWCONFIG is not defined | |
804 | + * hwconfig_arg_cmp returns non-zero | |
805 | + */ | |
806 | + if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", | |
807 | + "null", buf)) { | |
808 | + popts->memctl_interleaving = 0; | |
809 | + debug("memory controller interleaving disabled.\n"); | |
810 | + } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
811 | + "ctlr_intlv", | |
812 | + "cacheline", buf)) { | |
813 | + popts->memctl_interleaving_mode = | |
814 | + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? | |
815 | + 0 : FSL_DDR_CACHE_LINE_INTERLEAVING; | |
816 | + popts->memctl_interleaving = | |
817 | + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? | |
818 | + 0 : 1; | |
819 | + } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
820 | + "ctlr_intlv", | |
821 | + "page", buf)) { | |
822 | + popts->memctl_interleaving_mode = | |
823 | + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? | |
824 | + 0 : FSL_DDR_PAGE_INTERLEAVING; | |
825 | + popts->memctl_interleaving = | |
826 | + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? | |
827 | + 0 : 1; | |
828 | + } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
829 | + "ctlr_intlv", | |
830 | + "bank", buf)) { | |
831 | + popts->memctl_interleaving_mode = | |
832 | + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? | |
833 | + 0 : FSL_DDR_BANK_INTERLEAVING; | |
834 | + popts->memctl_interleaving = | |
835 | + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? | |
836 | + 0 : 1; | |
837 | + } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
838 | + "ctlr_intlv", | |
839 | + "superbank", buf)) { | |
840 | + popts->memctl_interleaving_mode = | |
841 | + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? | |
842 | + 0 : FSL_DDR_SUPERBANK_INTERLEAVING; | |
843 | + popts->memctl_interleaving = | |
844 | + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? | |
845 | + 0 : 1; | |
846 | +#if (CONFIG_NUM_DDR_CONTROLLERS == 3) | |
847 | + } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
848 | + "ctlr_intlv", | |
849 | + "3way_1KB", buf)) { | |
850 | + popts->memctl_interleaving_mode = | |
851 | + FSL_DDR_3WAY_1KB_INTERLEAVING; | |
852 | + } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
853 | + "ctlr_intlv", | |
854 | + "3way_4KB", buf)) { | |
855 | + popts->memctl_interleaving_mode = | |
856 | + FSL_DDR_3WAY_4KB_INTERLEAVING; | |
857 | + } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
858 | + "ctlr_intlv", | |
859 | + "3way_8KB", buf)) { | |
860 | + popts->memctl_interleaving_mode = | |
861 | + FSL_DDR_3WAY_8KB_INTERLEAVING; | |
862 | +#elif (CONFIG_NUM_DDR_CONTROLLERS == 4) | |
863 | + } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
864 | + "ctlr_intlv", | |
865 | + "4way_1KB", buf)) { | |
866 | + popts->memctl_interleaving_mode = | |
867 | + FSL_DDR_4WAY_1KB_INTERLEAVING; | |
868 | + } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
869 | + "ctlr_intlv", | |
870 | + "4way_4KB", buf)) { | |
871 | + popts->memctl_interleaving_mode = | |
872 | + FSL_DDR_4WAY_4KB_INTERLEAVING; | |
873 | + } else if (hwconfig_subarg_cmp_f("fsl_ddr", | |
874 | + "ctlr_intlv", | |
875 | + "4way_8KB", buf)) { | |
876 | + popts->memctl_interleaving_mode = | |
877 | + FSL_DDR_4WAY_8KB_INTERLEAVING; | |
833 | 878 | #endif |
879 | + } else { | |
880 | + popts->memctl_interleaving = 0; | |
881 | + printf("hwconfig has unrecognized parameter for ctlr_intlv.\n"); | |
882 | + } | |
883 | +done: | |
884 | +#endif | |
834 | 885 | if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) && |
835 | 886 | (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) { |
836 | 887 | /* test null first. if CONFIG_HWCONFIG is not defined, |
837 | 888 | |
838 | 889 | |
... | ... | @@ -859,20 +910,20 @@ |
859 | 910 | popts->ba_intlv_ctl = 0; |
860 | 911 | printf("Not enough bank(chip-select) for " |
861 | 912 | "CS0+CS1+CS2+CS3 on controller %d, " |
862 | - "force non-interleaving!\n", ctrl_num); | |
913 | + "interleaving disabled!\n", ctrl_num); | |
863 | 914 | } |
864 | 915 | #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) |
865 | 916 | if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) { |
866 | 917 | popts->ba_intlv_ctl = 0; |
867 | 918 | printf("Not enough bank(chip-select) for " |
868 | 919 | "CS0+CS1+CS2+CS3 on controller %d, " |
869 | - "force non-interleaving!\n", ctrl_num); | |
920 | + "interleaving disabled!\n", ctrl_num); | |
870 | 921 | } |
871 | 922 | if (pdimm[0].capacity != pdimm[1].capacity) { |
872 | 923 | popts->ba_intlv_ctl = 0; |
873 | 924 | printf("Not identical DIMM size for " |
874 | 925 | "CS0+CS1+CS2+CS3 on controller %d, " |
875 | - "force non-interleaving!\n", ctrl_num); | |
926 | + "interleaving disabled!\n", ctrl_num); | |
876 | 927 | } |
877 | 928 | #endif |
878 | 929 | break; |
... | ... | @@ -881,7 +932,7 @@ |
881 | 932 | popts->ba_intlv_ctl = 0; |
882 | 933 | printf("Not enough bank(chip-select) for " |
883 | 934 | "CS0+CS1 on controller %d, " |
884 | - "force non-interleaving!\n", ctrl_num); | |
935 | + "interleaving disabled!\n", ctrl_num); | |
885 | 936 | } |
886 | 937 | break; |
887 | 938 | case FSL_DDR_CS2_CS3: |
888 | 939 | |
... | ... | @@ -889,13 +940,13 @@ |
889 | 940 | if (pdimm[0].n_ranks < 4) { |
890 | 941 | popts->ba_intlv_ctl = 0; |
891 | 942 | printf("Not enough bank(chip-select) for CS2+CS3 " |
892 | - "on controller %d, force non-interleaving!\n", ctrl_num); | |
943 | + "on controller %d, interleaving disabled!\n", ctrl_num); | |
893 | 944 | } |
894 | 945 | #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) |
895 | 946 | if (pdimm[1].n_ranks < 2) { |
896 | 947 | popts->ba_intlv_ctl = 0; |
897 | 948 | printf("Not enough bank(chip-select) for CS2+CS3 " |
898 | - "on controller %d, force non-interleaving!\n", ctrl_num); | |
949 | + "on controller %d, interleaving disabled!\n", ctrl_num); | |
899 | 950 | } |
900 | 951 | #endif |
901 | 952 | break; |
902 | 953 | |
... | ... | @@ -905,14 +956,14 @@ |
905 | 956 | popts->ba_intlv_ctl = 0; |
906 | 957 | printf("Not enough bank(CS) for CS0+CS1 and " |
907 | 958 | "CS2+CS3 on controller %d, " |
908 | - "force non-interleaving!\n", ctrl_num); | |
959 | + "interleaving disabled!\n", ctrl_num); | |
909 | 960 | } |
910 | 961 | #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) |
911 | 962 | if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) { |
912 | 963 | popts->ba_intlv_ctl = 0; |
913 | 964 | printf("Not enough bank(CS) for CS0+CS1 and " |
914 | 965 | "CS2+CS3 on controller %d, " |
915 | - "force non-interleaving!\n", ctrl_num); | |
966 | + "interleaving disabled!\n", ctrl_num); | |
916 | 967 | } |
917 | 968 | #endif |
918 | 969 | break; |
919 | 970 | |
920 | 971 | |
921 | 972 | |
922 | 973 | |
923 | 974 | |
924 | 975 | |
925 | 976 | |
926 | 977 | |
927 | 978 | |
... | ... | @@ -954,33 +1005,73 @@ |
954 | 1005 | |
955 | 1006 | void check_interleaving_options(fsl_ddr_info_t *pinfo) |
956 | 1007 | { |
957 | - int i, j, check_n_ranks, intlv_fixed = 0; | |
1008 | + int i, j, k, check_n_ranks, intlv_invalid = 0; | |
1009 | + unsigned int check_intlv, check_n_row_addr, check_n_col_addr; | |
958 | 1010 | unsigned long long check_rank_density; |
1011 | + struct dimm_params_s *dimm; | |
959 | 1012 | /* |
960 | 1013 | * Check if all controllers are configured for memory |
961 | 1014 | * controller interleaving. Identical dimms are recommended. At least |
962 | - * the size should be checked. | |
1015 | + * the size, row and col address should be checked. | |
963 | 1016 | */ |
964 | 1017 | j = 0; |
965 | 1018 | check_n_ranks = pinfo->dimm_params[0][0].n_ranks; |
966 | 1019 | check_rank_density = pinfo->dimm_params[0][0].rank_density; |
1020 | + check_n_row_addr = pinfo->dimm_params[0][0].n_row_addr; | |
1021 | + check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr; | |
1022 | + check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode; | |
967 | 1023 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { |
968 | - if ((pinfo->memctl_opts[i].memctl_interleaving) && \ | |
969 | - (check_rank_density == pinfo->dimm_params[i][0].rank_density) && \ | |
970 | - (check_n_ranks == pinfo->dimm_params[i][0].n_ranks)) { | |
1024 | + dimm = &pinfo->dimm_params[i][0]; | |
1025 | + if (!pinfo->memctl_opts[i].memctl_interleaving) { | |
1026 | + continue; | |
1027 | + } else if (((check_rank_density != dimm->rank_density) || | |
1028 | + (check_n_ranks != dimm->n_ranks) || | |
1029 | + (check_n_row_addr != dimm->n_row_addr) || | |
1030 | + (check_n_col_addr != dimm->n_col_addr) || | |
1031 | + (check_intlv != | |
1032 | + pinfo->memctl_opts[i].memctl_interleaving_mode))){ | |
1033 | + intlv_invalid = 1; | |
1034 | + break; | |
1035 | + } else { | |
971 | 1036 | j++; |
972 | 1037 | } |
1038 | + | |
973 | 1039 | } |
974 | - if (j != CONFIG_NUM_DDR_CONTROLLERS) { | |
1040 | + if (intlv_invalid) { | |
975 | 1041 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) |
976 | - if (pinfo->memctl_opts[i].memctl_interleaving) { | |
1042 | + pinfo->memctl_opts[i].memctl_interleaving = 0; | |
1043 | + printf("Not all DIMMs are identical. " | |
1044 | + "Memory controller interleaving disabled.\n"); | |
1045 | + } else { | |
1046 | + switch (check_intlv) { | |
1047 | + case FSL_DDR_CACHE_LINE_INTERLEAVING: | |
1048 | + case FSL_DDR_PAGE_INTERLEAVING: | |
1049 | + case FSL_DDR_BANK_INTERLEAVING: | |
1050 | + case FSL_DDR_SUPERBANK_INTERLEAVING: | |
1051 | + if (3 == CONFIG_NUM_DDR_CONTROLLERS) | |
1052 | + k = 2; | |
1053 | + else | |
1054 | + k = CONFIG_NUM_DDR_CONTROLLERS; | |
1055 | + break; | |
1056 | + case FSL_DDR_3WAY_1KB_INTERLEAVING: | |
1057 | + case FSL_DDR_3WAY_4KB_INTERLEAVING: | |
1058 | + case FSL_DDR_3WAY_8KB_INTERLEAVING: | |
1059 | + case FSL_DDR_4WAY_1KB_INTERLEAVING: | |
1060 | + case FSL_DDR_4WAY_4KB_INTERLEAVING: | |
1061 | + case FSL_DDR_4WAY_8KB_INTERLEAVING: | |
1062 | + default: | |
1063 | + k = CONFIG_NUM_DDR_CONTROLLERS; | |
1064 | + break; | |
1065 | + } | |
1066 | + debug("%d of %d controllers are interleaving.\n", j, k); | |
1067 | + if (j != k) { | |
1068 | + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) | |
977 | 1069 | pinfo->memctl_opts[i].memctl_interleaving = 0; |
978 | - intlv_fixed = 1; | |
979 | - } | |
980 | - if (intlv_fixed) | |
981 | - printf("Not all DIMMs are identical in size. " | |
982 | - "Memory controller interleaving disabled.\n"); | |
1070 | + printf("Not all controllers have compatible " | |
1071 | + "interleaving mode. All disabled.\n"); | |
1072 | + } | |
983 | 1073 | } |
1074 | + debug("Checking interleaving options completed\n"); | |
984 | 1075 | } |
985 | 1076 | |
986 | 1077 | int fsl_use_spd(void) |
arch/powerpc/cpu/mpc8xxx/ddr/util.c
1 | 1 | /* |
2 | - * Copyright 2008-2011 Freescale Semiconductor, Inc. | |
2 | + * Copyright 2008-2012 Freescale Semiconductor, Inc. | |
3 | 3 | * |
4 | 4 | * This program is free software; you can redistribute it and/or |
5 | 5 | * modify it under the terms of the GNU General Public License |
... | ... | @@ -79,7 +79,7 @@ |
79 | 79 | |
80 | 80 | void |
81 | 81 | __fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, |
82 | - unsigned int memctl_interleaved, | |
82 | + unsigned int law_memctl, | |
83 | 83 | unsigned int ctrl_num) |
84 | 84 | { |
85 | 85 | unsigned long long base = memctl_common_params->base_address; |
86 | 86 | |
... | ... | @@ -98,28 +98,13 @@ |
98 | 98 | if ((base + size) >= CONFIG_MAX_MEM_MAPPED) |
99 | 99 | size = CONFIG_MAX_MEM_MAPPED - base; |
100 | 100 | #endif |
101 | - | |
102 | - if (ctrl_num == 0) { | |
103 | - /* | |
104 | - * Set up LAW for DDR controller 1 space. | |
105 | - */ | |
106 | - unsigned int lawbar1_target_id = memctl_interleaved | |
107 | - ? LAW_TRGT_IF_DDR_INTRLV : LAW_TRGT_IF_DDR_1; | |
108 | - | |
109 | - if (set_ddr_laws(base, size, lawbar1_target_id) < 0) { | |
110 | - printf("%s: ERROR (ctrl #0, intrlv=%d)\n", __func__, | |
111 | - memctl_interleaved); | |
112 | - return ; | |
113 | - } | |
114 | - } else if (ctrl_num == 1) { | |
115 | - if (set_ddr_laws(base, size, LAW_TRGT_IF_DDR_2) < 0) { | |
116 | - printf("%s: ERROR (ctrl #1)\n", __func__); | |
117 | - return ; | |
118 | - } | |
119 | - } else { | |
120 | - printf("%s: unexpected DDR controller number (%u)\n", __func__, | |
121 | - ctrl_num); | |
101 | + if (set_ddr_laws(base, size, law_memctl) < 0) { | |
102 | + printf("%s: ERROR (ctrl #%d, TRGT ID=%x)\n", __func__, ctrl_num, | |
103 | + law_memctl); | |
104 | + return ; | |
122 | 105 | } |
106 | + debug("setup ddr law base = 0x%llx, size 0x%llx, TRGT_ID 0x%x\n", | |
107 | + base, size, law_memctl); | |
123 | 108 | } |
124 | 109 | |
125 | 110 | __attribute__((weak, alias("__fsl_ddr_set_lawbar"))) void |
... | ... | @@ -127,6 +112,15 @@ |
127 | 112 | unsigned int memctl_interleaved, |
128 | 113 | unsigned int ctrl_num); |
129 | 114 | |
115 | +void fsl_ddr_set_intl3r(const unsigned int granule_size) | |
116 | +{ | |
117 | +#ifdef CONFIG_E6500 | |
118 | + u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); | |
119 | + *mcintl3r = 0x80000000 | (granule_size & 0x1f); | |
120 | + debug("Enable MCINTL3R with granule size 0x%x\n", granule_size); | |
121 | +#endif | |
122 | +} | |
123 | + | |
130 | 124 | void board_add_ram_info(int use_default) |
131 | 125 | { |
132 | 126 | #if defined(CONFIG_MPC83xx) |
... | ... | @@ -137,6 +131,9 @@ |
137 | 131 | #elif defined(CONFIG_MPC86xx) |
138 | 132 | ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC86xx_DDR_ADDR); |
139 | 133 | #endif |
134 | +#if defined(CONFIG_E6500) && (CONFIG_NUM_DDR_CONTROLLERS == 3) | |
135 | + u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); | |
136 | +#endif | |
140 | 137 | #if (CONFIG_NUM_DDR_CONTROLLERS > 1) |
141 | 138 | uint32_t cs0_config = in_be32(&ddr->cs0_config); |
142 | 139 | #endif |
... | ... | @@ -180,7 +177,29 @@ |
180 | 177 | else |
181 | 178 | puts(", ECC off)"); |
182 | 179 | |
183 | -#if (CONFIG_NUM_DDR_CONTROLLERS > 1) | |
180 | +#if (CONFIG_NUM_DDR_CONTROLLERS == 3) | |
181 | +#ifdef CONFIG_E6500 | |
182 | + if (*mcintl3r & 0x80000000) { | |
183 | + puts("\n"); | |
184 | + puts(" DDR Controller Interleaving Mode: "); | |
185 | + switch (*mcintl3r & 0x1f) { | |
186 | + case FSL_DDR_3WAY_1KB_INTERLEAVING: | |
187 | + puts("3-way 1KB"); | |
188 | + break; | |
189 | + case FSL_DDR_3WAY_4KB_INTERLEAVING: | |
190 | + puts("3-way 4KB"); | |
191 | + break; | |
192 | + case FSL_DDR_3WAY_8KB_INTERLEAVING: | |
193 | + puts("3-way 8KB"); | |
194 | + break; | |
195 | + default: | |
196 | + puts("3-way UNKNOWN"); | |
197 | + break; | |
198 | + } | |
199 | + } | |
200 | +#endif | |
201 | +#endif | |
202 | +#if (CONFIG_NUM_DDR_CONTROLLERS >= 2) | |
184 | 203 | if (cs0_config & 0x20000000) { |
185 | 204 | puts("\n"); |
186 | 205 | puts(" DDR Controller Interleaving Mode: "); |
arch/powerpc/include/asm/fsl_ddr_sdram.h
... | ... | @@ -76,6 +76,13 @@ |
76 | 76 | #define FSL_DDR_PAGE_INTERLEAVING 0x1 |
77 | 77 | #define FSL_DDR_BANK_INTERLEAVING 0x2 |
78 | 78 | #define FSL_DDR_SUPERBANK_INTERLEAVING 0x3 |
79 | +#define FSL_DDR_3WAY_1KB_INTERLEAVING 0xA | |
80 | +#define FSL_DDR_3WAY_4KB_INTERLEAVING 0xC | |
81 | +#define FSL_DDR_3WAY_8KB_INTERLEAVING 0xD | |
82 | +/* placeholder for 4-way interleaving */ | |
83 | +#define FSL_DDR_4WAY_1KB_INTERLEAVING 0x1A | |
84 | +#define FSL_DDR_4WAY_4KB_INTERLEAVING 0x1C | |
85 | +#define FSL_DDR_4WAY_8KB_INTERLEAVING 0x1D | |
79 | 86 | |
80 | 87 | /* DDR_SDRAM_CFG - DDR SDRAM Control Configuration |
81 | 88 | */ |
arch/powerpc/include/asm/fsl_law.h
... | ... | @@ -60,8 +60,12 @@ |
60 | 60 | |
61 | 61 | LAW_TRGT_IF_DDR_1 = 0x10, |
62 | 62 | LAW_TRGT_IF_DDR_2 = 0x11, /* 2nd controller */ |
63 | + LAW_TRGT_IF_DDR_3 = 0x12, | |
64 | + LAW_TRGT_IF_DDR_4 = 0x13, | |
63 | 65 | LAW_TRGT_IF_DDR_INTRLV = 0x14, |
64 | - | |
66 | + LAW_TRGT_IF_DDR_INTLV_34 = 0x15, | |
67 | + LAW_TRGT_IF_DDR_INTLV_123 = 0x17, | |
68 | + LAW_TRGT_IF_DDR_INTLV_1234 = 0x16, | |
65 | 69 | LAW_TRGT_IF_BMAN = 0x18, |
66 | 70 | LAW_TRGT_IF_DCSR = 0x1d, |
67 | 71 | LAW_TRGT_IF_LBC = 0x1f, |
... | ... | @@ -87,6 +91,12 @@ |
87 | 91 | LAW_TRGT_IF_DPAA_SWP_SRAM = 0x0e, |
88 | 92 | LAW_TRGT_IF_DDR = 0x0f, |
89 | 93 | LAW_TRGT_IF_DDR_2 = 0x16, /* 2nd controller */ |
94 | + /* place holder for 3-way and 4-way interleaving */ | |
95 | + LAW_TRGT_IF_DDR_3, | |
96 | + LAW_TRGT_IF_DDR_4, | |
97 | + LAW_TRGT_IF_DDR_INTLV_34, | |
98 | + LAW_TRGT_IF_DDR_INTLV_123, | |
99 | + LAW_TRGT_IF_DDR_INTLV_1234, | |
90 | 100 | }; |
91 | 101 | #define LAW_TRGT_IF_DDR_1 LAW_TRGT_IF_DDR |
92 | 102 | #define LAW_TRGT_IF_PCI_1 LAW_TRGT_IF_PCI |
arch/powerpc/include/asm/immap_85xx.h
... | ... | @@ -2621,6 +2621,7 @@ |
2621 | 2621 | #define CONFIG_SYS_FSL_CORENET_CCM_OFFSET 0x0000 |
2622 | 2622 | #define CONFIG_SYS_MPC85xx_DDR_OFFSET 0x8000 |
2623 | 2623 | #define CONFIG_SYS_MPC85xx_DDR2_OFFSET 0x9000 |
2624 | +#define CONFIG_SYS_MPC85xx_DDR3_OFFSET 0xA000 | |
2624 | 2625 | #define CONFIG_SYS_FSL_CORENET_CLK_OFFSET 0xE1000 |
2625 | 2626 | #define CONFIG_SYS_FSL_CORENET_RCPM_OFFSET 0xE2000 |
2626 | 2627 | #define CONFIG_SYS_FSL_CORENET_SERDES_OFFSET 0xEA000 |
... | ... | @@ -2740,6 +2741,8 @@ |
2740 | 2741 | (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR_OFFSET) |
2741 | 2742 | #define CONFIG_SYS_MPC85xx_DDR2_ADDR \ |
2742 | 2743 | (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR2_OFFSET) |
2744 | +#define CONFIG_SYS_MPC85xx_DDR3_ADDR \ | |
2745 | + (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR3_OFFSET) | |
2743 | 2746 | #define CONFIG_SYS_LBC_ADDR \ |
2744 | 2747 | (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_LBC_OFFSET) |
2745 | 2748 | #define CONFIG_SYS_IFC_ADDR \ |
doc/README.fsl-ddr
1 | +Table of interleaving 2-4 controllers | |
2 | +===================================== | |
3 | + +--------------+-----------------------------------------------------------+ | |
4 | + |Configuration | Memory Controller | | |
5 | + | | 1 2 3 4 | | |
6 | + |--------------+--------------+--------------+-----------------------------+ | |
7 | + | Two memory | Not Intlv'ed | Not Intlv'ed | | | |
8 | + | complexes +--------------+--------------+ | | |
9 | + | | 2-way Intlv'ed | | | |
10 | + |--------------+--------------+--------------+--------------+ | | |
11 | + | | Not Intlv'ed | Not Intlv'ed | Not Intlv'ed | | | |
12 | + | Three memory +--------------+--------------+--------------+ | | |
13 | + | complexes | 2-way Intlv'ed | Not Intlv'ed | | | |
14 | + | +-----------------------------+--------------+ | | |
15 | + | | 3-way Intlv'ed | | | |
16 | + +--------------+--------------+--------------+--------------+--------------+ | |
17 | + | | Not Intlv'ed | Not Intlv'ed | Not Intlv'ed | Not Intlv'ed | | |
18 | + | Four memory +--------------+--------------+--------------+--------------+ | |
19 | + | complexes | 2-way Intlv'ed | 2-way Intlv'ed | | |
20 | + | +-----------------------------+-----------------------------+ | |
21 | + | | 4-way Intlv'ed | | |
22 | + +--------------+-----------------------------------------------------------+ | |
1 | 23 | |
2 | -Table of interleaving modes supported in cpu/8xxx/ddr/ | |
24 | + | |
25 | +Table of 2-way interleaving modes supported in cpu/8xxx/ddr/ | |
3 | 26 | ====================================================== |
4 | 27 | +-------------+---------------------------------------------------------+ |
5 | 28 | | | Rank Interleaving | |
... | ... | @@ -55,6 +78,15 @@ |
55 | 78 | |
56 | 79 | # superbank |
57 | 80 | setenv hwconfig "fsl_ddr:ctlr_intlv=superbank" |
81 | + | |
82 | + # 1KB 3-way interleaving | |
83 | + setenv hwconfig "fsl_ddr:ctlr_intlv=3way_1KB" | |
84 | + | |
85 | + # 4KB 3-way interleaving | |
86 | + setenv hwconfig "fsl_ddr:ctlr_intlv=3way_4KB" | |
87 | + | |
88 | + # 8KB 3-way interleaving | |
89 | + setenv hwconfig "fsl_ddr:ctlr_intlv=3way_8KB" | |
58 | 90 | |
59 | 91 | # disable bank (chip-select) interleaving |
60 | 92 | setenv hwconfig "fsl_ddr:bank_intlv=null" |