xref: /rk3399_rockchip-uboot/arch/x86/lib/cmd_mtrr.c (revision f448c5d3200372fa73f340144d013fdecf4e2f1f)
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