Stefan Roese | b47a63d | 2015-10-02 08:20:35 +0200 | [diff] [blame] | 1 | /* |
| 2 | * (C) Copyright 2006 |
| 3 | * Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com |
| 4 | * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com |
| 5 | * Thierry Roman, AMCC/IBM, thierry_roman@fr.ibm.com |
| 6 | * Alain Saurel, AMCC/IBM, alain.saurel@fr.ibm.com |
| 7 | * Robert Snyder, AMCC/IBM, rob.snyder@fr.ibm.com |
| 8 | * |
| 9 | * (C) Copyright 2007-2013 |
| 10 | * Stefan Roese, DENX Software Engineering, sr@denx.de. |
| 11 | * |
| 12 | * SPDX-License-Identifier: GPL-2.0+ |
| 13 | */ |
| 14 | |
| 15 | /* define DEBUG for debugging output (obviously ;-)) */ |
| 16 | #if 0 |
| 17 | #define DEBUG |
| 18 | #endif |
| 19 | |
| 20 | #include <common.h> |
| 21 | #include <asm/processor.h> |
| 22 | #include <asm/mmu.h> |
| 23 | #include <asm/io.h> |
| 24 | #include <asm/cache.h> |
| 25 | #include <asm/ppc440.h> |
| 26 | #include <watchdog.h> |
| 27 | |
Simon Glass | 39f90ba | 2017-03-31 08:40:25 -0600 | [diff] [blame] | 28 | DECLARE_GLOBAL_DATA_PTR; |
| 29 | |
Stefan Roese | b47a63d | 2015-10-02 08:20:35 +0200 | [diff] [blame] | 30 | /* |
| 31 | * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory |
| 32 | * region. Right now the cache should still be disabled in U-Boot because of the |
| 33 | * EMAC driver, that need it's buffer descriptor to be located in non cached |
| 34 | * memory. |
| 35 | * |
| 36 | * If at some time this restriction doesn't apply anymore, just define |
| 37 | * CONFIG_4xx_DCACHE in the board config file and this code should setup |
| 38 | * everything correctly. |
| 39 | */ |
| 40 | #ifdef CONFIG_4xx_DCACHE |
| 41 | #define MY_TLB_WORD2_I_ENABLE 0 /* enable caching on SDRAM */ |
| 42 | #else |
| 43 | #define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */ |
| 44 | #endif |
| 45 | |
| 46 | /*-----------------------------------------------------------------------------+ |
| 47 | * Prototypes |
| 48 | *-----------------------------------------------------------------------------*/ |
| 49 | extern int denali_wait_for_dlllock(void); |
| 50 | extern void denali_core_search_data_eye(void); |
| 51 | extern void dcbz_area(u32 start_address, u32 num_bytes); |
| 52 | |
| 53 | static u32 is_ecc_enabled(void) |
| 54 | { |
| 55 | u32 val; |
| 56 | |
| 57 | mfsdram(DDR0_22, val); |
| 58 | val &= DDR0_22_CTRL_RAW_MASK; |
| 59 | if (val) |
| 60 | return 1; |
| 61 | else |
| 62 | return 0; |
| 63 | } |
| 64 | |
| 65 | void board_add_ram_info(int use_default) |
| 66 | { |
| 67 | PPC4xx_SYS_INFO board_cfg; |
| 68 | u32 val; |
| 69 | |
| 70 | if (is_ecc_enabled()) |
| 71 | puts(" (ECC"); |
| 72 | else |
| 73 | puts(" (ECC not"); |
| 74 | |
| 75 | get_sys_info(&board_cfg); |
| 76 | printf(" enabled, %ld MHz", (board_cfg.freqPLB * 2) / 1000000); |
| 77 | |
| 78 | mfsdram(DDR0_03, val); |
| 79 | val = DDR0_03_CASLAT_DECODE(val); |
| 80 | printf(", CL%d)", val); |
| 81 | } |
| 82 | |
| 83 | #ifdef CONFIG_DDR_ECC |
| 84 | static void wait_ddr_idle(void) |
| 85 | { |
| 86 | /* |
| 87 | * Controller idle status cannot be determined for Denali |
| 88 | * DDR2 code. Just return here. |
| 89 | */ |
| 90 | } |
| 91 | |
| 92 | static void program_ecc(u32 start_address, |
| 93 | u32 num_bytes, |
| 94 | u32 tlb_word2_i_value) |
| 95 | { |
| 96 | u32 val; |
| 97 | u32 current_addr = start_address; |
| 98 | u32 size; |
| 99 | int bytes_remaining; |
| 100 | |
| 101 | sync(); |
| 102 | wait_ddr_idle(); |
| 103 | |
| 104 | /* |
| 105 | * Because of 440EPx errata CHIP 11, we don't touch the last 256 |
| 106 | * bytes of SDRAM. |
| 107 | */ |
| 108 | bytes_remaining = num_bytes - CONFIG_SYS_MEM_TOP_HIDE; |
| 109 | |
| 110 | /* |
| 111 | * We have to write the ECC bytes by zeroing and flushing in smaller |
| 112 | * steps, since the whole 256MByte takes too long for the external |
| 113 | * watchdog. |
| 114 | */ |
| 115 | while (bytes_remaining > 0) { |
| 116 | size = min((64 << 20), bytes_remaining); |
| 117 | |
| 118 | /* Write zero's to SDRAM */ |
| 119 | dcbz_area(current_addr, size); |
| 120 | |
| 121 | /* Write modified dcache lines back to memory */ |
| 122 | clean_dcache_range(current_addr, current_addr + size); |
| 123 | |
| 124 | current_addr += 64 << 20; |
| 125 | bytes_remaining -= 64 << 20; |
| 126 | WATCHDOG_RESET(); |
| 127 | } |
| 128 | |
| 129 | sync(); |
| 130 | wait_ddr_idle(); |
| 131 | |
| 132 | /* Clear error status */ |
| 133 | mfsdram(DDR0_00, val); |
| 134 | mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL); |
| 135 | |
| 136 | /* Set 'int_mask' parameter to functionnal value */ |
| 137 | mfsdram(DDR0_01, val); |
| 138 | mtsdram(DDR0_01, ((val &~ DDR0_01_INT_MASK_MASK) | DDR0_01_INT_MASK_ALL_OFF)); |
| 139 | |
| 140 | sync(); |
| 141 | wait_ddr_idle(); |
| 142 | } |
| 143 | #endif |
| 144 | |
| 145 | /************************************************************************* |
| 146 | * |
Simon Glass | d35f338 | 2017-04-06 12:47:05 -0600 | [diff] [blame^] | 147 | * dram_init -- 440EPx's DDR controller is a DENALI Core |
Stefan Roese | b47a63d | 2015-10-02 08:20:35 +0200 | [diff] [blame] | 148 | * |
| 149 | ************************************************************************/ |
Simon Glass | d35f338 | 2017-04-06 12:47:05 -0600 | [diff] [blame^] | 150 | int dram_init(void) |
Stefan Roese | b47a63d | 2015-10-02 08:20:35 +0200 | [diff] [blame] | 151 | { |
Stefan Roese | b47a63d | 2015-10-02 08:20:35 +0200 | [diff] [blame] | 152 | /* CL=4 */ |
| 153 | mtsdram(DDR0_02, 0x00000000); |
| 154 | |
| 155 | mtsdram(DDR0_00, 0x0000190A); |
| 156 | mtsdram(DDR0_01, 0x01000000); |
| 157 | mtsdram(DDR0_03, 0x02040803); /* A suitable burst length was taken. CAS is right for our board */ |
| 158 | |
| 159 | mtsdram(DDR0_04, 0x0B030300); |
| 160 | mtsdram(DDR0_05, 0x02020308); |
| 161 | mtsdram(DDR0_06, 0x0003C812); |
| 162 | mtsdram(DDR0_07, 0x00090100); |
| 163 | mtsdram(DDR0_08, 0x03c80001); |
| 164 | mtsdram(DDR0_09, 0x00011D5F); |
| 165 | mtsdram(DDR0_10, 0x00000100); |
| 166 | mtsdram(DDR0_11, 0x000CC800); |
| 167 | mtsdram(DDR0_12, 0x00000003); |
| 168 | mtsdram(DDR0_14, 0x00000000); |
| 169 | mtsdram(DDR0_17, 0x1e000000); |
| 170 | mtsdram(DDR0_18, 0x1e1e1e1e); |
| 171 | mtsdram(DDR0_19, 0x1e1e1e1e); |
| 172 | mtsdram(DDR0_20, 0x0B0B0B0B); |
| 173 | mtsdram(DDR0_21, 0x0B0B0B0B); |
| 174 | #ifdef CONFIG_DDR_ECC |
| 175 | mtsdram(DDR0_22, 0x00267F0B | DDR0_22_CTRL_RAW_ECC_ENABLE); /* enable ECC */ |
| 176 | #else |
| 177 | mtsdram(DDR0_22, 0x00267F0B); |
| 178 | #endif |
| 179 | |
| 180 | mtsdram(DDR0_23, 0x01000000); |
| 181 | mtsdram(DDR0_24, 0x01010001); |
| 182 | |
| 183 | mtsdram(DDR0_26, 0x2D93028A); |
| 184 | mtsdram(DDR0_27, 0x0784682B); |
| 185 | |
| 186 | mtsdram(DDR0_28, 0x00000080); |
| 187 | mtsdram(DDR0_31, 0x00000000); |
| 188 | mtsdram(DDR0_42, 0x01000008); |
| 189 | |
| 190 | mtsdram(DDR0_43, 0x050A0200); |
| 191 | mtsdram(DDR0_44, 0x00000005); |
| 192 | mtsdram(DDR0_02, 0x00000001); /* Activate the denali core */ |
| 193 | |
| 194 | denali_wait_for_dlllock(); |
| 195 | |
| 196 | #if defined(CONFIG_DDR_DATA_EYE) |
| 197 | /* -----------------------------------------------------------+ |
| 198 | * Perform data eye search if requested. |
| 199 | * ----------------------------------------------------------*/ |
| 200 | program_tlb(0, CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MBYTES_SDRAM << 20, |
| 201 | TLB_WORD2_I_ENABLE); |
| 202 | denali_core_search_data_eye(); |
| 203 | remove_tlb(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MBYTES_SDRAM << 20); |
| 204 | #endif |
| 205 | |
| 206 | /* |
| 207 | * Program tlb entries for this size (dynamic) |
| 208 | */ |
| 209 | program_tlb(0, CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MBYTES_SDRAM << 20, |
| 210 | MY_TLB_WORD2_I_ENABLE); |
| 211 | |
| 212 | #if defined(CONFIG_DDR_ECC) |
| 213 | #if defined(CONFIG_4xx_DCACHE) |
| 214 | /* |
| 215 | * If ECC is enabled, initialize the parity bits. |
| 216 | */ |
| 217 | program_ecc(0, CONFIG_SYS_MBYTES_SDRAM << 20, 0); |
| 218 | #else /* CONFIG_4xx_DCACHE */ |
| 219 | /* |
| 220 | * Setup 2nd TLB with same physical address but different virtual address |
| 221 | * with cache enabled. This is done for fast ECC generation. |
| 222 | */ |
| 223 | program_tlb(0, CONFIG_SYS_DDR_CACHED_ADDR, CONFIG_SYS_MBYTES_SDRAM << 20, 0); |
| 224 | |
| 225 | /* |
| 226 | * If ECC is enabled, initialize the parity bits. |
| 227 | */ |
| 228 | program_ecc(CONFIG_SYS_DDR_CACHED_ADDR, CONFIG_SYS_MBYTES_SDRAM << 20, 0); |
| 229 | |
| 230 | /* |
| 231 | * Now after initialization (auto-calibration and ECC generation) |
| 232 | * remove the TLB entries with caches enabled and program again with |
| 233 | * desired cache functionality |
| 234 | */ |
| 235 | remove_tlb(CONFIG_SYS_DDR_CACHED_ADDR, CONFIG_SYS_MBYTES_SDRAM << 20); |
| 236 | #endif /* CONFIG_4xx_DCACHE */ |
| 237 | #endif /* CONFIG_DDR_ECC */ |
| 238 | |
| 239 | /* |
| 240 | * Clear possible errors resulting from data-eye-search. |
| 241 | * If not done, then we could get an interrupt later on when |
| 242 | * exceptions are enabled. |
| 243 | */ |
| 244 | set_mcsr(get_mcsr()); |
Stefan Roese | b47a63d | 2015-10-02 08:20:35 +0200 | [diff] [blame] | 245 | |
Simon Glass | 39f90ba | 2017-03-31 08:40:25 -0600 | [diff] [blame] | 246 | gd->ram_size = CONFIG_SYS_MBYTES_SDRAM << 20; |
| 247 | |
| 248 | return 0; |
Stefan Roese | b47a63d | 2015-10-02 08:20:35 +0200 | [diff] [blame] | 249 | } |