1cb3b2e62SSimon Glass /*
2cb3b2e62SSimon Glass * (C) Copyright 2014 Google, Inc
3cb3b2e62SSimon Glass *
4cb3b2e62SSimon Glass * SPDX-License-Identifier: GPL-2.0+
5cb3b2e62SSimon Glass */
6cb3b2e62SSimon Glass
7cb3b2e62SSimon Glass #include <common.h>
8cb3b2e62SSimon Glass #include <asm/msr.h>
9cb3b2e62SSimon Glass #include <asm/mtrr.h>
10cb3b2e62SSimon Glass
11cb3b2e62SSimon Glass static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
12cb3b2e62SSimon Glass "Uncacheable",
13cb3b2e62SSimon Glass "Combine",
14cb3b2e62SSimon Glass "2",
15cb3b2e62SSimon Glass "3",
16cb3b2e62SSimon Glass "Through",
17cb3b2e62SSimon Glass "Protect",
18cb3b2e62SSimon Glass "Back",
19cb3b2e62SSimon Glass };
20cb3b2e62SSimon Glass
do_mtrr_list(void)21cb3b2e62SSimon Glass static int do_mtrr_list(void)
22cb3b2e62SSimon Glass {
23cb3b2e62SSimon Glass int i;
24cb3b2e62SSimon Glass
25cb3b2e62SSimon Glass printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||",
26cb3b2e62SSimon Glass "Mask ||", "Size ||");
27cb3b2e62SSimon Glass for (i = 0; i < MTRR_COUNT; i++) {
28cb3b2e62SSimon Glass const char *type = "Invalid";
29cb3b2e62SSimon Glass uint64_t base, mask, size;
30cb3b2e62SSimon Glass bool valid;
31cb3b2e62SSimon Glass
32cb3b2e62SSimon Glass base = native_read_msr(MTRR_PHYS_BASE_MSR(i));
33cb3b2e62SSimon Glass mask = native_read_msr(MTRR_PHYS_MASK_MSR(i));
34cb3b2e62SSimon Glass size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1);
35cb3b2e62SSimon Glass size |= (1 << 12) - 1;
36cb3b2e62SSimon Glass size += 1;
37cb3b2e62SSimon Glass valid = mask & MTRR_PHYS_MASK_VALID;
38cb3b2e62SSimon Glass type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
39cb3b2e62SSimon Glass printf("%d %-5s %-12s %016llx %016llx %016llx\n", i,
40*df07d919SBin Meng valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK,
41*df07d919SBin Meng mask & ~MTRR_PHYS_MASK_VALID, size);
42cb3b2e62SSimon Glass }
43cb3b2e62SSimon Glass
44cb3b2e62SSimon Glass return 0;
45cb3b2e62SSimon Glass }
46cb3b2e62SSimon Glass
do_mtrr_set(uint reg,int argc,char * const argv[])47cb3b2e62SSimon Glass static int do_mtrr_set(uint reg, int argc, char * const argv[])
48cb3b2e62SSimon Glass {
49cb3b2e62SSimon Glass const char *typename = argv[0];
50cb3b2e62SSimon Glass struct mtrr_state state;
51cb3b2e62SSimon Glass uint32_t start, size;
52cb3b2e62SSimon Glass uint64_t base, mask;
53cb3b2e62SSimon Glass int i, type = -1;
54cb3b2e62SSimon Glass bool valid;
55cb3b2e62SSimon Glass
56cb3b2e62SSimon Glass if (argc < 3)
57cb3b2e62SSimon Glass return CMD_RET_USAGE;
58cb3b2e62SSimon Glass for (i = 0; i < MTRR_TYPE_COUNT; i++) {
59cb3b2e62SSimon Glass if (*typename == *mtrr_type_name[i])
60cb3b2e62SSimon Glass type = i;
61cb3b2e62SSimon Glass }
62cb3b2e62SSimon Glass if (type == -1) {
63cb3b2e62SSimon Glass printf("Invalid type name %s\n", typename);
64cb3b2e62SSimon Glass return CMD_RET_USAGE;
65cb3b2e62SSimon Glass }
66cb3b2e62SSimon Glass start = simple_strtoul(argv[1], NULL, 16);
67cb3b2e62SSimon Glass size = simple_strtoul(argv[2], NULL, 16);
68cb3b2e62SSimon Glass
69cb3b2e62SSimon Glass base = start | type;
70cb3b2e62SSimon Glass valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID;
71cb3b2e62SSimon Glass mask = ~((uint64_t)size - 1);
72cb3b2e62SSimon Glass mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
73cb3b2e62SSimon Glass if (valid)
74cb3b2e62SSimon Glass mask |= MTRR_PHYS_MASK_VALID;
75cb3b2e62SSimon Glass
76cb3b2e62SSimon Glass printf("base=%llx, mask=%llx\n", base, mask);
77cb3b2e62SSimon Glass mtrr_open(&state);
78cb3b2e62SSimon Glass wrmsrl(MTRR_PHYS_BASE_MSR(reg), base);
79cb3b2e62SSimon Glass wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
80cb3b2e62SSimon Glass mtrr_close(&state);
81cb3b2e62SSimon Glass
82cb3b2e62SSimon Glass return 0;
83cb3b2e62SSimon Glass }
84cb3b2e62SSimon Glass
mtrr_set_valid(int reg,bool valid)85cb3b2e62SSimon Glass static int mtrr_set_valid(int reg, bool valid)
86cb3b2e62SSimon Glass {
87cb3b2e62SSimon Glass struct mtrr_state state;
88cb3b2e62SSimon Glass uint64_t mask;
89cb3b2e62SSimon Glass
90cb3b2e62SSimon Glass mtrr_open(&state);
91cb3b2e62SSimon Glass mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg));
92cb3b2e62SSimon Glass if (valid)
93cb3b2e62SSimon Glass mask |= MTRR_PHYS_MASK_VALID;
94cb3b2e62SSimon Glass else
95cb3b2e62SSimon Glass mask &= ~MTRR_PHYS_MASK_VALID;
96cb3b2e62SSimon Glass wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
97cb3b2e62SSimon Glass mtrr_close(&state);
98cb3b2e62SSimon Glass
99cb3b2e62SSimon Glass return 0;
100cb3b2e62SSimon Glass }
101cb3b2e62SSimon Glass
do_mtrr(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])102cb3b2e62SSimon Glass static int do_mtrr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
103cb3b2e62SSimon Glass {
104cb3b2e62SSimon Glass const char *cmd;
105cb3b2e62SSimon Glass uint reg;
106cb3b2e62SSimon Glass
107cb3b2e62SSimon Glass cmd = argv[1];
108cb3b2e62SSimon Glass if (argc < 2 || *cmd == 'l')
109cb3b2e62SSimon Glass return do_mtrr_list();
110cb3b2e62SSimon Glass argc -= 2;
111cb3b2e62SSimon Glass argv += 2;
112cb3b2e62SSimon Glass if (argc <= 0)
113cb3b2e62SSimon Glass return CMD_RET_USAGE;
114cb3b2e62SSimon Glass reg = simple_strtoul(argv[0], NULL, 16);
115cb3b2e62SSimon Glass if (reg >= MTRR_COUNT) {
116cb3b2e62SSimon Glass printf("Invalid register number\n");
117cb3b2e62SSimon Glass return CMD_RET_USAGE;
118cb3b2e62SSimon Glass }
119cb3b2e62SSimon Glass if (*cmd == 'e')
120cb3b2e62SSimon Glass return mtrr_set_valid(reg, true);
121cb3b2e62SSimon Glass else if (*cmd == 'd')
122cb3b2e62SSimon Glass return mtrr_set_valid(reg, false);
123cb3b2e62SSimon Glass else if (*cmd == 's')
124cb3b2e62SSimon Glass return do_mtrr_set(reg, argc - 1, argv + 1);
125cb3b2e62SSimon Glass else
126cb3b2e62SSimon Glass return CMD_RET_USAGE;
127cb3b2e62SSimon Glass
128cb3b2e62SSimon Glass return 0;
129cb3b2e62SSimon Glass }
130cb3b2e62SSimon Glass
131cb3b2e62SSimon Glass U_BOOT_CMD(
132cb3b2e62SSimon Glass mtrr, 6, 1, do_mtrr,
133cb3b2e62SSimon Glass "Use x86 memory type range registers (32-bit only)",
134cb3b2e62SSimon Glass "[list] - list current registers\n"
135cb3b2e62SSimon Glass "set <reg> <type> <start> <size> - set a register\n"
136cb3b2e62SSimon Glass "\t<type> is Uncacheable, Combine, Through, Protect, Back\n"
137cb3b2e62SSimon Glass "disable <reg> - disable a register\n"
138cb3b2e62SSimon Glass "ensable <reg> - enable a register"
139cb3b2e62SSimon Glass );
140