1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2014 Google, Inc 4 * 5 * Memory Type Range Regsters - these are used to tell the CPU whether 6 * memory is cacheable and if so the cache write mode to use. 7 * 8 * These can speed up booting. See the mtrr command. 9 * 10 * Reference: Intel Architecture Software Developer's Manual, Volume 3: 11 * System Programming 12 */ 13 14 #include <common.h> 15 #include <asm/io.h> 16 #include <asm/msr.h> 17 #include <asm/mtrr.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 /* Prepare to adjust MTRRs */ 22 void mtrr_open(struct mtrr_state *state) 23 { 24 if (!gd->arch.has_mtrr) 25 return; 26 27 state->enable_cache = dcache_status(); 28 29 if (state->enable_cache) 30 disable_caches(); 31 state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR); 32 wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN); 33 } 34 35 /* Clean up after adjusting MTRRs, and enable them */ 36 void mtrr_close(struct mtrr_state *state) 37 { 38 if (!gd->arch.has_mtrr) 39 return; 40 41 wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN); 42 if (state->enable_cache) 43 enable_caches(); 44 } 45 46 int mtrr_commit(bool do_caches) 47 { 48 struct mtrr_request *req = gd->arch.mtrr_req; 49 struct mtrr_state state; 50 uint64_t mask; 51 int i; 52 53 if (!gd->arch.has_mtrr) 54 return -ENOSYS; 55 56 mtrr_open(&state); 57 for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) { 58 mask = ~(req->size - 1); 59 mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; 60 wrmsrl(MTRR_PHYS_BASE_MSR(i), req->start | req->type); 61 wrmsrl(MTRR_PHYS_MASK_MSR(i), mask | MTRR_PHYS_MASK_VALID); 62 } 63 64 /* Clear the ones that are unused */ 65 for (; i < MTRR_COUNT; i++) 66 wrmsrl(MTRR_PHYS_MASK_MSR(i), 0); 67 mtrr_close(&state); 68 69 return 0; 70 } 71 72 int mtrr_add_request(int type, uint64_t start, uint64_t size) 73 { 74 struct mtrr_request *req; 75 uint64_t mask; 76 77 if (!gd->arch.has_mtrr) 78 return -ENOSYS; 79 80 if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS) 81 return -ENOSPC; 82 req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++]; 83 req->type = type; 84 req->start = start; 85 req->size = size; 86 debug("%d: type=%d, %08llx %08llx\n", gd->arch.mtrr_req_count - 1, 87 req->type, req->start, req->size); 88 mask = ~(req->size - 1); 89 mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; 90 mask |= MTRR_PHYS_MASK_VALID; 91 debug(" %016llx %016llx\n", req->start | req->type, mask); 92 93 return 0; 94 } 95