1 /* 2 * Copyright 2008-2011 Freescale Semiconductor, Inc. 3 * 4 * (C) Copyright 2000 5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 11 #include <linux/compiler.h> 12 #include <asm/fsl_law.h> 13 #include <asm/io.h> 14 #include <linux/log2.h> 15 16 DECLARE_GLOBAL_DATA_PTR; 17 18 #define FSL_HW_NUM_LAWS CONFIG_SYS_FSL_NUM_LAWS 19 20 #ifdef CONFIG_FSL_CORENET 21 #define LAW_BASE (CONFIG_SYS_FSL_CORENET_CCM_ADDR) 22 #define LAWAR_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawar) 23 #define LAWBARH_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarh) 24 #define LAWBARL_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarl) 25 #define LAWBAR_SHIFT 0 26 #else 27 #define LAW_BASE (CONFIG_SYS_IMMR + 0xc08) 28 #define LAWAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x + 2) 29 #define LAWBAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x) 30 #define LAWBAR_SHIFT 12 31 #endif 32 33 34 static inline phys_addr_t get_law_base_addr(int idx) 35 { 36 #ifdef CONFIG_FSL_CORENET 37 return (phys_addr_t) 38 ((u64)in_be32(LAWBARH_ADDR(idx)) << 32) | 39 in_be32(LAWBARL_ADDR(idx)); 40 #else 41 return (phys_addr_t)in_be32(LAWBAR_ADDR(idx)) << LAWBAR_SHIFT; 42 #endif 43 } 44 45 static inline void set_law_base_addr(int idx, phys_addr_t addr) 46 { 47 #ifdef CONFIG_FSL_CORENET 48 out_be32(LAWBARL_ADDR(idx), addr & 0xffffffff); 49 out_be32(LAWBARH_ADDR(idx), (u64)addr >> 32); 50 #else 51 out_be32(LAWBAR_ADDR(idx), addr >> LAWBAR_SHIFT); 52 #endif 53 } 54 55 void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id) 56 { 57 gd->arch.used_laws |= (1 << idx); 58 59 out_be32(LAWAR_ADDR(idx), 0); 60 set_law_base_addr(idx, addr); 61 out_be32(LAWAR_ADDR(idx), LAW_EN | ((u32)id << 20) | (u32)sz); 62 63 /* Read back so that we sync the writes */ 64 in_be32(LAWAR_ADDR(idx)); 65 } 66 67 void disable_law(u8 idx) 68 { 69 gd->arch.used_laws &= ~(1 << idx); 70 71 out_be32(LAWAR_ADDR(idx), 0); 72 set_law_base_addr(idx, 0); 73 74 /* Read back so that we sync the writes */ 75 in_be32(LAWAR_ADDR(idx)); 76 77 return; 78 } 79 80 #if !defined(CONFIG_NAND_SPL) && \ 81 (!defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SPL_INIT_MINIMAL)) 82 static int get_law_entry(u8 i, struct law_entry *e) 83 { 84 u32 lawar; 85 86 lawar = in_be32(LAWAR_ADDR(i)); 87 88 if (!(lawar & LAW_EN)) 89 return 0; 90 91 e->addr = get_law_base_addr(i); 92 e->size = lawar & 0x3f; 93 e->trgt_id = (lawar >> 20) & 0xff; 94 95 return 1; 96 } 97 #endif 98 99 int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) 100 { 101 u32 idx = ffz(gd->arch.used_laws); 102 103 if (idx >= FSL_HW_NUM_LAWS) 104 return -1; 105 106 set_law(idx, addr, sz, id); 107 108 return idx; 109 } 110 111 #if !defined(CONFIG_NAND_SPL) && \ 112 (!defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SPL_INIT_MINIMAL)) 113 int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) 114 { 115 u32 idx; 116 117 /* we have no LAWs free */ 118 if (gd->arch.used_laws == -1) 119 return -1; 120 121 /* grab the last free law */ 122 idx = __ilog2(~(gd->arch.used_laws)); 123 124 if (idx >= FSL_HW_NUM_LAWS) 125 return -1; 126 127 set_law(idx, addr, sz, id); 128 129 return idx; 130 } 131 132 struct law_entry find_law(phys_addr_t addr) 133 { 134 struct law_entry entry; 135 int i; 136 137 entry.index = -1; 138 entry.addr = 0; 139 entry.size = 0; 140 entry.trgt_id = 0; 141 142 for (i = 0; i < FSL_HW_NUM_LAWS; i++) { 143 u64 upper; 144 145 if (!get_law_entry(i, &entry)) 146 continue; 147 148 upper = entry.addr + (2ull << entry.size); 149 if ((addr >= entry.addr) && (addr < upper)) { 150 entry.index = i; 151 break; 152 } 153 } 154 155 return entry; 156 } 157 158 void print_laws(void) 159 { 160 int i; 161 u32 lawar; 162 163 printf("\nLocal Access Window Configuration\n"); 164 for (i = 0; i < FSL_HW_NUM_LAWS; i++) { 165 lawar = in_be32(LAWAR_ADDR(i)); 166 #ifdef CONFIG_FSL_CORENET 167 printf("LAWBARH%02d: 0x%08x LAWBARL%02d: 0x%08x", 168 i, in_be32(LAWBARH_ADDR(i)), 169 i, in_be32(LAWBARL_ADDR(i))); 170 #else 171 printf("LAWBAR%02d: 0x%08x", i, in_be32(LAWBAR_ADDR(i))); 172 #endif 173 printf(" LAWAR%02d: 0x%08x\n", i, lawar); 174 printf("\t(EN: %d TGT: 0x%02x SIZE: ", 175 (lawar & LAW_EN) ? 1 : 0, (lawar >> 20) & 0xff); 176 print_size(lawar_size(lawar), ")\n"); 177 } 178 179 return; 180 } 181 182 /* use up to 2 LAWs for DDR, used the last available LAWs */ 183 int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id) 184 { 185 u64 start_align, law_sz; 186 int law_sz_enc; 187 188 if (start == 0) 189 start_align = 1ull << (LAW_SIZE_32G + 1); 190 else 191 start_align = 1ull << (__ffs64(start)); 192 law_sz = min(start_align, sz); 193 law_sz_enc = __ilog2_u64(law_sz) - 1; 194 195 if (set_last_law(start, law_sz_enc, id) < 0) 196 return -1; 197 198 /* recalculate size based on what was actually covered by the law */ 199 law_sz = 1ull << __ilog2_u64(law_sz); 200 201 /* do we still have anything to map */ 202 sz = sz - law_sz; 203 if (sz) { 204 start += law_sz; 205 206 start_align = 1ull << (__ffs64(start)); 207 law_sz = min(start_align, sz); 208 law_sz_enc = __ilog2_u64(law_sz) - 1; 209 210 if (set_last_law(start, law_sz_enc, id) < 0) 211 return -1; 212 } else { 213 return 0; 214 } 215 216 /* do we still have anything to map */ 217 sz = sz - law_sz; 218 if (sz) 219 return 1; 220 221 return 0; 222 } 223 #endif /* not SPL */ 224 225 void disable_non_ddr_laws(void) 226 { 227 int i; 228 int id; 229 for (i = 0; i < FSL_HW_NUM_LAWS; i++) { 230 u32 lawar = in_be32(LAWAR_ADDR(i)); 231 232 if (lawar & LAW_EN) { 233 id = (lawar & ~LAW_EN) >> 20; 234 switch (id) { 235 case LAW_TRGT_IF_DDR_1: 236 case LAW_TRGT_IF_DDR_2: 237 case LAW_TRGT_IF_DDR_3: 238 case LAW_TRGT_IF_DDR_4: 239 case LAW_TRGT_IF_DDR_INTRLV: 240 case LAW_TRGT_IF_DDR_INTLV_34: 241 case LAW_TRGT_IF_DDR_INTLV_123: 242 case LAW_TRGT_IF_DDR_INTLV_1234: 243 continue; 244 default: 245 disable_law(i); 246 } 247 } 248 } 249 } 250 251 void init_laws(void) 252 { 253 int i; 254 255 #if FSL_HW_NUM_LAWS < 32 256 gd->arch.used_laws = ~((1 << FSL_HW_NUM_LAWS) - 1); 257 #elif FSL_HW_NUM_LAWS == 32 258 gd->arch.used_laws = 0; 259 #else 260 #error FSL_HW_NUM_LAWS can not be greater than 32 w/o code changes 261 #endif 262 263 #if defined(CONFIG_SECURE_BOOT) && defined(CONFIG_E500) && \ 264 !defined(CONFIG_E500MC) 265 /* ISBC (Boot ROM) creates a LAW 0 entry for non PBL platforms, 266 * which is not disabled before transferring the control to uboot. 267 * Disable the LAW 0 entry here. 268 */ 269 disable_law(0); 270 #endif 271 272 #if !defined(CONFIG_SECURE_BOOT) 273 /* 274 * if any non DDR LAWs has been created earlier, remove them before 275 * LAW table is parsed. 276 */ 277 disable_non_ddr_laws(); 278 #endif 279 280 /* 281 * Any LAWs that were set up before we booted assume they are meant to 282 * be around and mark them used. 283 */ 284 for (i = 0; i < FSL_HW_NUM_LAWS; i++) { 285 u32 lawar = in_be32(LAWAR_ADDR(i)); 286 287 if (lawar & LAW_EN) 288 gd->arch.used_laws |= (1 << i); 289 } 290 291 for (i = 0; i < num_law_entries; i++) { 292 if (law_table[i].index == -1) 293 set_next_law(law_table[i].addr, law_table[i].size, 294 law_table[i].trgt_id); 295 else 296 set_law(law_table[i].index, law_table[i].addr, 297 law_table[i].size, law_table[i].trgt_id); 298 } 299 300 #ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE 301 /* check RCW to get which port is used for boot */ 302 ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR; 303 u32 bootloc = in_be32(&gur->rcwsr[6]); 304 /* 305 * in SRIO or PCIE boot we need to set specail LAWs for 306 * SRIO or PCIE interfaces. 307 */ 308 switch ((bootloc & FSL_CORENET_RCWSR6_BOOT_LOC) >> 23) { 309 case 0x0: /* boot from PCIE1 */ 310 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS, 311 LAW_SIZE_1M, 312 LAW_TRGT_IF_PCIE_1); 313 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS, 314 LAW_SIZE_1M, 315 LAW_TRGT_IF_PCIE_1); 316 break; 317 case 0x1: /* boot from PCIE2 */ 318 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS, 319 LAW_SIZE_1M, 320 LAW_TRGT_IF_PCIE_2); 321 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS, 322 LAW_SIZE_1M, 323 LAW_TRGT_IF_PCIE_2); 324 break; 325 case 0x2: /* boot from PCIE3 */ 326 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS, 327 LAW_SIZE_1M, 328 LAW_TRGT_IF_PCIE_3); 329 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS, 330 LAW_SIZE_1M, 331 LAW_TRGT_IF_PCIE_3); 332 break; 333 case 0x8: /* boot from SRIO1 */ 334 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS, 335 LAW_SIZE_1M, 336 LAW_TRGT_IF_RIO_1); 337 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS, 338 LAW_SIZE_1M, 339 LAW_TRGT_IF_RIO_1); 340 break; 341 case 0x9: /* boot from SRIO2 */ 342 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS, 343 LAW_SIZE_1M, 344 LAW_TRGT_IF_RIO_2); 345 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS, 346 LAW_SIZE_1M, 347 LAW_TRGT_IF_RIO_2); 348 break; 349 default: 350 break; 351 } 352 #endif 353 354 return ; 355 } 356