[dc0a7df] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
[c991eeec] | 4 | * @ingroup RTEMSBSPsPowerPCQorIQMMU |
---|
[dc0a7df] | 5 | * |
---|
| 6 | * @brief MMU implementation. |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | /* |
---|
[9ec5ff4e] | 10 | * Copyright (c) 2011, 2018 embedded brains GmbH. All rights reserved. |
---|
[dc0a7df] | 11 | * |
---|
| 12 | * embedded brains GmbH |
---|
[bd39add] | 13 | * Dornierstr. 4 |
---|
[dc0a7df] | 14 | * 82178 Puchheim |
---|
| 15 | * Germany |
---|
| 16 | * <rtems@embedded-brains.de> |
---|
| 17 | * |
---|
| 18 | * The license and distribution terms for this file may be |
---|
| 19 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 20 | * http://www.rtems.org/license/LICENSE. |
---|
[dc0a7df] | 21 | */ |
---|
| 22 | |
---|
[bd39add] | 23 | #include <bsp.h> |
---|
[d3f60af] | 24 | #include <bsp/bootcard.h> |
---|
| 25 | #include <bsp/fdt.h> |
---|
[dc0a7df] | 26 | #include <bsp/linker-symbols.h> |
---|
[d3f60af] | 27 | #include <bsp/mmu.h> |
---|
[dc0a7df] | 28 | #include <bsp/qoriq.h> |
---|
| 29 | |
---|
[d3f60af] | 30 | #include <sys/param.h> |
---|
| 31 | |
---|
| 32 | #include <libfdt.h> |
---|
| 33 | |
---|
| 34 | #include <rtems/config.h> |
---|
[eea21eac] | 35 | #include <rtems/sysinit.h> |
---|
[d3f60af] | 36 | |
---|
[dc0a7df] | 37 | #define TEXT __attribute__((section(".bsp_start_text"))) |
---|
| 38 | #define DATA __attribute__((section(".bsp_start_data"))) |
---|
| 39 | |
---|
| 40 | typedef struct { |
---|
[c8aeb76] | 41 | uintptr_t begin; |
---|
| 42 | uintptr_t size; |
---|
[dc0a7df] | 43 | uint32_t mas2; |
---|
| 44 | uint32_t mas3; |
---|
[0e05095a] | 45 | uint32_t mas7; |
---|
[dc0a7df] | 46 | } entry; |
---|
| 47 | |
---|
| 48 | #define ENTRY_X(b, s) { \ |
---|
[c8aeb76] | 49 | .begin = (uintptr_t) b, \ |
---|
| 50 | .size = (uintptr_t) s, \ |
---|
[dc0a7df] | 51 | .mas2 = 0, \ |
---|
[65ee42c] | 52 | .mas3 = FSL_EIS_MAS3_SX \ |
---|
[dc0a7df] | 53 | } |
---|
| 54 | |
---|
| 55 | #define ENTRY_R(b, s) { \ |
---|
[c8aeb76] | 56 | .begin = (uintptr_t) b, \ |
---|
| 57 | .size = (uintptr_t) s, \ |
---|
[dc0a7df] | 58 | .mas2 = 0, \ |
---|
| 59 | .mas3 = FSL_EIS_MAS3_SR \ |
---|
| 60 | } |
---|
| 61 | |
---|
[bd39add] | 62 | #ifdef RTEMS_SMP |
---|
| 63 | #define ENTRY_RW_MAS2 FSL_EIS_MAS2_M |
---|
| 64 | #else |
---|
| 65 | #define ENTRY_RW_MAS2 0 |
---|
| 66 | #endif |
---|
| 67 | |
---|
[dc0a7df] | 68 | #define ENTRY_RW(b, s) { \ |
---|
[c8aeb76] | 69 | .begin = (uintptr_t) b, \ |
---|
| 70 | .size = (uintptr_t) s, \ |
---|
[bd39add] | 71 | .mas2 = ENTRY_RW_MAS2, \ |
---|
[dc0a7df] | 72 | .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \ |
---|
| 73 | } |
---|
| 74 | |
---|
[cf8e033] | 75 | #define ENTRY_IO(b, s) { \ |
---|
[c8aeb76] | 76 | .begin = (uintptr_t) b, \ |
---|
| 77 | .size = (uintptr_t) s, \ |
---|
[cf8e033] | 78 | .mas2 = FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, \ |
---|
| 79 | .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \ |
---|
| 80 | } |
---|
| 81 | |
---|
[dc0a7df] | 82 | #define ENTRY_DEV(b, s) { \ |
---|
[c8aeb76] | 83 | .begin = (uintptr_t) b, \ |
---|
| 84 | .size = (uintptr_t) s, \ |
---|
[dc0a7df] | 85 | .mas2 = FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, \ |
---|
[0e05095a] | 86 | .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, \ |
---|
| 87 | .mas7 = QORIQ_MMU_DEVICE_MAS7 \ |
---|
[dc0a7df] | 88 | } |
---|
| 89 | |
---|
[c70f9d1] | 90 | /* |
---|
| 91 | * MMU entry for BMan and QMan software portals. |
---|
| 92 | * |
---|
| 93 | * The M bit must be set if stashing is used, see 3.3.8.6 DQRR Entry Stashing |
---|
| 94 | * and 3.3.8 Software Portals in T4240DPAARM. |
---|
| 95 | * |
---|
| 96 | * The G bit must be set, otherwise ECC errors in the QMan software portals |
---|
| 97 | * will occur. No documentation reference for this is available. |
---|
| 98 | */ |
---|
[707ecbe] | 99 | #define ENTRY_DEV_CACHED(b, s) { \ |
---|
[c8aeb76] | 100 | .begin = (uintptr_t) b, \ |
---|
| 101 | .size = (uintptr_t) s, \ |
---|
[c70f9d1] | 102 | .mas2 = FSL_EIS_MAS2_M | FSL_EIS_MAS2_G, \ |
---|
[707ecbe] | 103 | .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, \ |
---|
| 104 | .mas7 = QORIQ_MMU_DEVICE_MAS7 \ |
---|
| 105 | } |
---|
| 106 | |
---|
[d3f60af] | 107 | #define WORKSPACE_ENTRY_INDEX 0 |
---|
| 108 | |
---|
| 109 | static entry DATA config[] = { |
---|
| 110 | /* Must be first entry, see WORKSPACE_ENTRY_INDEX */ |
---|
| 111 | ENTRY_RW(bsp_section_work_begin, bsp_section_work_size), |
---|
| 112 | |
---|
[3abfe7ca] | 113 | #if defined(RTEMS_MULTIPROCESSING) && \ |
---|
| 114 | defined(QORIQ_INTERCOM_AREA_BEGIN) && \ |
---|
| 115 | defined(QORIQ_INTERCOM_AREA_SIZE) |
---|
[dc0a7df] | 116 | { |
---|
| 117 | .begin = QORIQ_INTERCOM_AREA_BEGIN, |
---|
| 118 | .size = QORIQ_INTERCOM_AREA_SIZE, |
---|
| 119 | .mas2 = FSL_EIS_MAS2_M, |
---|
| 120 | .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW |
---|
| 121 | }, |
---|
| 122 | #endif |
---|
| 123 | ENTRY_X(bsp_section_start_begin, bsp_section_start_size), |
---|
| 124 | ENTRY_R(bsp_section_fast_text_load_begin, bsp_section_fast_text_size), |
---|
| 125 | ENTRY_X(bsp_section_fast_text_begin, bsp_section_fast_text_size), |
---|
| 126 | ENTRY_X(bsp_section_text_begin, bsp_section_text_size), |
---|
| 127 | ENTRY_R(bsp_section_rodata_load_begin, bsp_section_rodata_size), |
---|
| 128 | ENTRY_R(bsp_section_rodata_begin, bsp_section_rodata_size), |
---|
| 129 | ENTRY_R(bsp_section_fast_data_load_begin, bsp_section_fast_data_size), |
---|
| 130 | ENTRY_RW(bsp_section_fast_data_begin, bsp_section_fast_data_size), |
---|
| 131 | ENTRY_R(bsp_section_data_load_begin, bsp_section_data_size), |
---|
| 132 | ENTRY_RW(bsp_section_data_begin, bsp_section_data_size), |
---|
| 133 | ENTRY_RW(bsp_section_sbss_begin, bsp_section_sbss_size), |
---|
| 134 | ENTRY_RW(bsp_section_bss_begin, bsp_section_bss_size), |
---|
[715d616] | 135 | ENTRY_RW(bsp_section_rtemsstack_begin, bsp_section_rtemsstack_size), |
---|
[dc0a7df] | 136 | ENTRY_RW(bsp_section_stack_begin, bsp_section_stack_size), |
---|
[cf8e033] | 137 | ENTRY_IO(bsp_section_nocache_begin, bsp_section_nocache_size), |
---|
[53c99b8] | 138 | ENTRY_IO(bsp_section_nocachenoload_begin, bsp_section_nocachenoload_size), |
---|
[31540bfb] | 139 | #ifndef QORIQ_IS_HYPERVISOR_GUEST |
---|
[707ecbe] | 140 | #if QORIQ_CHIP_IS_T_VARIANT(QORIQ_CHIP_VARIANT) |
---|
| 141 | /* BMan Portals */ |
---|
[dd863f8] | 142 | ENTRY_DEV_CACHED(&qoriq_bman_portal[0][0], sizeof(qoriq_bman_portal[0])), |
---|
| 143 | ENTRY_DEV(&qoriq_bman_portal[1][0], sizeof(qoriq_bman_portal[1])), |
---|
[707ecbe] | 144 | /* QMan Portals */ |
---|
[dd863f8] | 145 | ENTRY_DEV_CACHED(&qoriq_qman_portal[0][0], sizeof(qoriq_qman_portal[0])), |
---|
| 146 | ENTRY_DEV(&qoriq_qman_portal[1][0], sizeof(qoriq_qman_portal[1])), |
---|
[707ecbe] | 147 | #endif |
---|
[dc0a7df] | 148 | ENTRY_DEV(&qoriq, sizeof(qoriq)) |
---|
[31540bfb] | 149 | #endif |
---|
[dc0a7df] | 150 | }; |
---|
| 151 | |
---|
[d3f60af] | 152 | static DATA char memory_path[] = "/memory"; |
---|
| 153 | |
---|
[9ec5ff4e] | 154 | #ifdef QORIQ_IS_HYPERVISOR_GUEST |
---|
| 155 | static void TEXT add_dpaa_bqman_portals( |
---|
| 156 | qoriq_mmu_context *context, |
---|
| 157 | const void *fdt, |
---|
| 158 | const char *compatible |
---|
| 159 | ) |
---|
| 160 | { |
---|
| 161 | int node; |
---|
| 162 | |
---|
| 163 | node = -1; |
---|
| 164 | |
---|
| 165 | while (true) { |
---|
| 166 | const void *val; |
---|
| 167 | int len; |
---|
| 168 | uintptr_t paddr; |
---|
| 169 | uintptr_t size; |
---|
| 170 | |
---|
| 171 | node = fdt_node_offset_by_compatible(fdt, node, compatible); |
---|
| 172 | if (node < 0) { |
---|
| 173 | break; |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | val = fdt_getprop(fdt, node, "reg", &len); |
---|
| 177 | if (len != 32) { |
---|
| 178 | continue; |
---|
| 179 | } |
---|
| 180 | |
---|
| 181 | paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[0]); |
---|
| 182 | size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[1]); |
---|
| 183 | |
---|
| 184 | qoriq_mmu_add( |
---|
| 185 | context, |
---|
| 186 | paddr, |
---|
| 187 | paddr + size - 1, |
---|
| 188 | 0, |
---|
| 189 | FSL_EIS_MAS2_M | FSL_EIS_MAS2_G, |
---|
| 190 | FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, |
---|
| 191 | QORIQ_MMU_DEVICE_MAS7 |
---|
| 192 | ); |
---|
| 193 | |
---|
| 194 | paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[2]); |
---|
| 195 | size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[3]); |
---|
| 196 | |
---|
| 197 | qoriq_mmu_add( |
---|
| 198 | context, |
---|
| 199 | paddr, |
---|
| 200 | paddr + size - 1, |
---|
| 201 | 0, |
---|
| 202 | FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, |
---|
| 203 | FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, |
---|
| 204 | QORIQ_MMU_DEVICE_MAS7 |
---|
| 205 | ); |
---|
| 206 | } |
---|
| 207 | } |
---|
| 208 | |
---|
| 209 | static void TEXT add_dpaa_bpool(qoriq_mmu_context *context, const void *fdt) |
---|
| 210 | { |
---|
| 211 | int node; |
---|
| 212 | |
---|
| 213 | node = -1; |
---|
| 214 | |
---|
| 215 | while (true) { |
---|
| 216 | const void *val; |
---|
| 217 | int len; |
---|
| 218 | uintptr_t config_count; |
---|
| 219 | uintptr_t size; |
---|
| 220 | uintptr_t paddr; |
---|
| 221 | |
---|
| 222 | node = fdt_node_offset_by_compatible(fdt, node, "fsl,bpool"); |
---|
| 223 | if (node < 0) { |
---|
| 224 | break; |
---|
| 225 | } |
---|
| 226 | |
---|
| 227 | val = fdt_getprop(fdt, node, "fsl,bpool-ethernet-cfg", &len); |
---|
| 228 | if (len != 24) { |
---|
| 229 | continue; |
---|
| 230 | } |
---|
| 231 | |
---|
| 232 | config_count = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[0]); |
---|
| 233 | size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[1]); |
---|
| 234 | paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[2]); |
---|
| 235 | |
---|
| 236 | qoriq_mmu_add( |
---|
| 237 | context, |
---|
| 238 | paddr, |
---|
| 239 | paddr + config_count * size - 1, |
---|
| 240 | 0, |
---|
| 241 | FSL_EIS_MAS2_M, |
---|
| 242 | FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, |
---|
| 243 | 0 |
---|
| 244 | ); |
---|
| 245 | } |
---|
| 246 | } |
---|
| 247 | #endif |
---|
| 248 | |
---|
| 249 | static void TEXT config_fdt_adjust(const void *fdt) |
---|
[d3f60af] | 250 | { |
---|
| 251 | int node; |
---|
| 252 | |
---|
| 253 | node = fdt_path_offset_namelen( |
---|
| 254 | fdt, |
---|
| 255 | memory_path, |
---|
| 256 | (int) sizeof(memory_path) - 1 |
---|
| 257 | ); |
---|
| 258 | |
---|
| 259 | if (node >= 0) { |
---|
| 260 | int len; |
---|
| 261 | const void *val; |
---|
[5d44981c] | 262 | uint64_t mem_begin; |
---|
| 263 | uint64_t mem_size; |
---|
[d3f60af] | 264 | |
---|
| 265 | val = fdt_getprop(fdt, node, "reg", &len); |
---|
| 266 | if (len == 8) { |
---|
[5d44981c] | 267 | mem_begin = fdt32_to_cpu(((fdt32_t *) val)[0]); |
---|
| 268 | mem_size = fdt32_to_cpu(((fdt32_t *) val)[1]); |
---|
[d3f60af] | 269 | } else if (len == 16) { |
---|
[5d44981c] | 270 | mem_begin = fdt64_to_cpu(((fdt64_t *) val)[0]); |
---|
| 271 | mem_size = fdt64_to_cpu(((fdt64_t *) val)[1]); |
---|
[d3f60af] | 272 | } else { |
---|
[5d44981c] | 273 | mem_begin = 0; |
---|
| 274 | mem_size = 0; |
---|
[d3f60af] | 275 | } |
---|
| 276 | |
---|
[95a4b1f] | 277 | #ifndef __powerpc64__ |
---|
[5d44981c] | 278 | mem_size = MIN(mem_size, 0x80000000U); |
---|
[95a4b1f] | 279 | #endif |
---|
[d3f60af] | 280 | |
---|
[6584eb2] | 281 | if ( |
---|
[5d44981c] | 282 | mem_begin == 0 |
---|
| 283 | && mem_size > (uintptr_t) bsp_section_work_end |
---|
[6584eb2] | 284 | && (uintptr_t) bsp_section_nocache_end |
---|
| 285 | < (uintptr_t) bsp_section_work_end |
---|
| 286 | ) { |
---|
[5d44981c] | 287 | /* Assign new value to allow a bsp_restart() */ |
---|
| 288 | config[WORKSPACE_ENTRY_INDEX].size = (uintptr_t) mem_size |
---|
| 289 | - (uintptr_t) bsp_section_work_begin; |
---|
[d3f60af] | 290 | } |
---|
| 291 | } |
---|
| 292 | } |
---|
| 293 | |
---|
[f6e793a2] | 294 | void TEXT qoriq_mmu_config(bool boot_processor, int first_tlb, int scratch_tlb) |
---|
[dc0a7df] | 295 | { |
---|
| 296 | qoriq_mmu_context context; |
---|
[9ec5ff4e] | 297 | const void *fdt; |
---|
| 298 | int max_count; |
---|
| 299 | int i; |
---|
[dc0a7df] | 300 | |
---|
[f2e6c3e] | 301 | for (i = 0; i < QORIQ_TLB1_ENTRY_COUNT; ++i) { |
---|
[dc0a7df] | 302 | if (i != scratch_tlb) { |
---|
| 303 | qoriq_tlb1_invalidate(i); |
---|
| 304 | } |
---|
| 305 | } |
---|
| 306 | |
---|
[9ec5ff4e] | 307 | fdt = bsp_fdt_get(); |
---|
| 308 | qoriq_mmu_context_init(&context); |
---|
| 309 | |
---|
| 310 | #ifdef QORIQ_IS_HYPERVISOR_GUEST |
---|
| 311 | add_dpaa_bqman_portals(&context, fdt, "fsl,bman-portal"); |
---|
| 312 | add_dpaa_bqman_portals(&context, fdt, "fsl,qman-portal"); |
---|
| 313 | add_dpaa_bpool(&context, fdt); |
---|
| 314 | max_count = QORIQ_TLB1_ENTRY_COUNT - 1; |
---|
| 315 | #else |
---|
| 316 | max_count = (3 * QORIQ_TLB1_ENTRY_COUNT) / 4; |
---|
| 317 | #endif |
---|
| 318 | |
---|
| 319 | if (boot_processor) { |
---|
| 320 | config_fdt_adjust(fdt); |
---|
| 321 | } |
---|
| 322 | |
---|
[dc0a7df] | 323 | for (i = 0; i < (int) (sizeof(config) / sizeof(config [0])); ++i) { |
---|
| 324 | const entry *cur = &config [i]; |
---|
| 325 | if (cur->size > 0) { |
---|
| 326 | qoriq_mmu_add( |
---|
| 327 | &context, |
---|
| 328 | cur->begin, |
---|
| 329 | cur->begin + cur->size - 1, |
---|
| 330 | 0, |
---|
| 331 | cur->mas2, |
---|
[0e05095a] | 332 | cur->mas3, |
---|
| 333 | cur->mas7 |
---|
[dc0a7df] | 334 | ); |
---|
| 335 | } |
---|
| 336 | } |
---|
| 337 | |
---|
[9ec5ff4e] | 338 | qoriq_mmu_partition(&context, max_count); |
---|
[dc0a7df] | 339 | qoriq_mmu_write_to_tlb1(&context, first_tlb); |
---|
| 340 | } |
---|
[d3f60af] | 341 | |
---|
[eea21eac] | 342 | static Memory_Area _Memory_Areas[1]; |
---|
| 343 | |
---|
| 344 | static const Memory_Information _Memory_Information = |
---|
| 345 | MEMORY_INFORMATION_INITIALIZER(_Memory_Areas); |
---|
| 346 | |
---|
| 347 | static void bsp_memory_initialize(void) |
---|
[d3f60af] | 348 | { |
---|
| 349 | const entry *we = &config[WORKSPACE_ENTRY_INDEX]; |
---|
| 350 | |
---|
[eea21eac] | 351 | _Memory_Initialize_by_size( |
---|
| 352 | &_Memory_Areas[0], |
---|
| 353 | (void *) we->begin, |
---|
| 354 | we->size |
---|
| 355 | ); |
---|
| 356 | } |
---|
| 357 | |
---|
| 358 | RTEMS_SYSINIT_ITEM( |
---|
| 359 | bsp_memory_initialize, |
---|
| 360 | RTEMS_SYSINIT_MEMORY, |
---|
| 361 | RTEMS_SYSINIT_ORDER_MIDDLE |
---|
| 362 | ); |
---|
| 363 | |
---|
| 364 | const Memory_Information *_Memory_Get(void) |
---|
| 365 | { |
---|
| 366 | return &_Memory_Information; |
---|
[d3f60af] | 367 | } |
---|