blob: b2afb598c73e6f970121ae332737a957057c9d82 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassfc0ba2d2015-01-01 16:18:15 -07002/*
3 * (C) Copyright 2014 Google, Inc
Simon Glassfc0ba2d2015-01-01 16:18:15 -07004 */
5
Simon Glassed38aef2020-05-10 11:40:03 -06006#include <command.h>
Simon Glass7403c262020-07-17 08:48:22 -06007#include <log.h>
Tom Rini5c1444f2024-04-27 08:10:59 -06008#include <vsprintf.h>
Simon Glassfc0ba2d2015-01-01 16:18:15 -07009#include <asm/msr.h>
Simon Glass7403c262020-07-17 08:48:22 -060010#include <asm/mp.h>
Simon Glassfc0ba2d2015-01-01 16:18:15 -070011#include <asm/mtrr.h>
12
Simon Glass29e1d772020-07-17 08:48:27 -060013static int do_mtrr_set(int cpu_select, uint reg, int argc, char *const argv[])
Simon Glassfc0ba2d2015-01-01 16:18:15 -070014{
15 const char *typename = argv[0];
Simon Glassfc0ba2d2015-01-01 16:18:15 -070016 uint32_t start, size;
17 uint64_t base, mask;
Simon Glassfb842432023-07-15 21:38:36 -060018 int type = -1;
Simon Glassfc0ba2d2015-01-01 16:18:15 -070019 bool valid;
Simon Glass29e1d772020-07-17 08:48:27 -060020 int ret;
Simon Glassfc0ba2d2015-01-01 16:18:15 -070021
22 if (argc < 3)
23 return CMD_RET_USAGE;
Simon Glassfb842432023-07-15 21:38:36 -060024 type = mtrr_get_type_by_name(typename);
25 if (type < 0) {
Simon Glassfc0ba2d2015-01-01 16:18:15 -070026 printf("Invalid type name %s\n", typename);
27 return CMD_RET_USAGE;
28 }
Simon Glass3ff49ec2021-07-24 09:03:29 -060029 start = hextoul(argv[1], NULL);
30 size = hextoul(argv[2], NULL);
Simon Glassfc0ba2d2015-01-01 16:18:15 -070031
32 base = start | type;
33 valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID;
34 mask = ~((uint64_t)size - 1);
35 mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
36 if (valid)
37 mask |= MTRR_PHYS_MASK_VALID;
38
Simon Glass29e1d772020-07-17 08:48:27 -060039 ret = mtrr_set(cpu_select, reg, base, mask);
40 if (ret)
41 return CMD_RET_FAILURE;
Simon Glassfc0ba2d2015-01-01 16:18:15 -070042
43 return 0;
44}
45
Simon Glassed38aef2020-05-10 11:40:03 -060046static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc,
47 char *const argv[])
Simon Glassfc0ba2d2015-01-01 16:18:15 -070048{
Simon Glassfbf120c2020-09-22 14:54:51 -060049 int reg_count = mtrr_get_var_count();
Simon Glass2c601b62020-07-17 08:48:28 -060050 int cmd;
Simon Glass7403c262020-07-17 08:48:22 -060051 int cpu_select;
Simon Glassfc0ba2d2015-01-01 16:18:15 -070052 uint reg;
Simon Glass2c601b62020-07-17 08:48:28 -060053 int ret;
Simon Glassfc0ba2d2015-01-01 16:18:15 -070054
Simon Glass7403c262020-07-17 08:48:22 -060055 cpu_select = MP_SELECT_BSP;
Simon Glasse643edd2020-07-17 08:48:29 -060056 if (argc >= 3 && !strcmp("-c", argv[1])) {
57 const char *cpustr;
58
59 cpustr = argv[2];
60 if (*cpustr == 'a')
61 cpu_select = MP_SELECT_ALL;
62 else
63 cpu_select = simple_strtol(cpustr, NULL, 16);
64 argc -= 2;
65 argv += 2;
66 }
Simon Glass2c601b62020-07-17 08:48:28 -060067 argc--;
68 argv++;
69 cmd = argv[0] ? *argv[0] : 0;
70 if (argc < 1 || !cmd) {
71 cmd = 'l';
72 reg = 0;
Wolfgang Wallner9abf45b2020-08-14 09:55:24 +020073 }
74 if (cmd != 'l') {
Simon Glass2c601b62020-07-17 08:48:28 -060075 if (argc < 2)
76 return CMD_RET_USAGE;
Simon Glass3ff49ec2021-07-24 09:03:29 -060077 reg = hextoul(argv[1], NULL);
Simon Glassfbf120c2020-09-22 14:54:51 -060078 if (reg >= reg_count) {
Simon Glass2c601b62020-07-17 08:48:28 -060079 printf("Invalid register number\n");
80 return CMD_RET_USAGE;
81 }
82 }
83 if (cmd == 'l') {
Simon Glass3ac9fdb2020-07-17 08:48:31 -060084 bool first;
85 int i;
86
87 i = mp_first_cpu(cpu_select);
88 if (i < 0) {
89 printf("Invalid CPU (err=%d)\n", i);
90 return CMD_RET_FAILURE;
91 }
92 first = true;
93 for (; i >= 0; i = mp_next_cpu(cpu_select, i)) {
94 if (!first)
95 printf("\n");
96 printf("CPU %d:\n", i);
Simon Glassfb842432023-07-15 21:38:36 -060097 ret = mtrr_list(reg_count, i);
Simon Glass3ac9fdb2020-07-17 08:48:31 -060098 if (ret) {
Simon Glasscb3a7ac2023-05-04 16:54:54 -060099 printf("Failed to read CPU %s (err=%d)\n",
100 i < MP_SELECT_ALL ? simple_itoa(i) : "",
Simon Glass3ac9fdb2020-07-17 08:48:31 -0600101 ret);
102 return CMD_RET_FAILURE;
103 }
104 first = false;
105 }
Simon Glass2c601b62020-07-17 08:48:28 -0600106 } else {
107 switch (cmd) {
108 case 'e':
109 ret = mtrr_set_valid(cpu_select, reg, true);
110 break;
111 case 'd':
112 ret = mtrr_set_valid(cpu_select, reg, false);
113 break;
114 case 's':
115 ret = do_mtrr_set(cpu_select, reg, argc - 2, argv + 2);
116 break;
117 default:
118 return CMD_RET_USAGE;
119 }
120 if (ret) {
121 printf("Operation failed (err=%d)\n", ret);
122 return CMD_RET_FAILURE;
123 }
Simon Glassfc0ba2d2015-01-01 16:18:15 -0700124 }
Simon Glassfc0ba2d2015-01-01 16:18:15 -0700125
126 return 0;
127}
128
129U_BOOT_CMD(
Simon Glasse643edd2020-07-17 08:48:29 -0600130 mtrr, 8, 1, do_mtrr,
Simon Glassfc0ba2d2015-01-01 16:18:15 -0700131 "Use x86 memory type range registers (32-bit only)",
132 "[list] - list current registers\n"
133 "set <reg> <type> <start> <size> - set a register\n"
134 "\t<type> is Uncacheable, Combine, Through, Protect, Back\n"
135 "disable <reg> - disable a register\n"
Simon Glasse643edd2020-07-17 08:48:29 -0600136 "enable <reg> - enable a register\n"
137 "\n"
138 "Precede command with '-c <n>|all' to access a particular hex CPU, e.g.\n"
139 " mtrr -c all list; mtrr -c 2e list"
Simon Glassfc0ba2d2015-01-01 16:18:15 -0700140);