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