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 /* Prepare to adjust MTRRs */ 21 void mtrr_open(struct mtrr_state *state) 22 { 23 state->enable_cache = dcache_status(); 24 25 if (state->enable_cache) 26 disable_caches(); 27 state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR); 28 wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN); 29 } 30 31 /* Clean up after adjusting MTRRs, and enable them */ 32 void mtrr_close(struct mtrr_state *state) 33 { 34 wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN); 35 if (state->enable_cache) 36 enable_caches(); 37 } 38 39 int mtrr_commit(bool do_caches) 40 { 41 struct mtrr_request *req = gd->arch.mtrr_req; 42 struct mtrr_state state; 43 uint64_t mask; 44 int i; 45 46 mtrr_open(&state); 47 for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) { 48 mask = ~(req->size - 1); 49 mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; 50 wrmsrl(MTRR_PHYS_BASE_MSR(i), req->start | req->type); 51 wrmsrl(MTRR_PHYS_MASK_MSR(i), mask | MTRR_PHYS_MASK_VALID); 52 } 53 54 /* Clear the ones that are unused */ 55 for (; i < MTRR_COUNT; i++) 56 wrmsrl(MTRR_PHYS_MASK_MSR(i), 0); 57 mtrr_close(&state); 58 59 return 0; 60 } 61 62 int mtrr_add_request(int type, uint64_t start, uint64_t size) 63 { 64 struct mtrr_request *req; 65 uint64_t mask; 66 67 if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS) 68 return -ENOSPC; 69 req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++]; 70 req->type = type; 71 req->start = start; 72 req->size = size; 73 debug("%d: type=%d, %08llx %08llx\n", gd->arch.mtrr_req_count - 1, 74 req->type, req->start, req->size); 75 mask = ~(req->size - 1); 76 mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; 77 mask |= MTRR_PHYS_MASK_VALID; 78 debug(" %016llx %016llx\n", req->start | req->type, mask); 79 80 return 0; 81 } 82