blob: 289865515ef5265903f34c1bcfb86ff51e84b379 [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 Rinidec7ea02024-05-20 13:35:03 -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 Glass3f691692025-03-15 14:25:43 +000016 u64 start, size;
Simon Glass3742cfa2025-03-15 14:25:42 +000017 u64 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 Glass3f691692025-03-15 14:25:43 +000029 start = hextoull(argv[1], NULL);
30 size = hextoull(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;
Simon Glass3742cfa2025-03-15 14:25:42 +000034 mask = mtrr_to_mask(size);
Simon Glassfc0ba2d2015-01-01 16:18:15 -070035 if (valid)
36 mask |= MTRR_PHYS_MASK_VALID;
37
Simon Glass29e1d772020-07-17 08:48:27 -060038 ret = mtrr_set(cpu_select, reg, base, mask);
39 if (ret)
40 return CMD_RET_FAILURE;
Simon Glassfc0ba2d2015-01-01 16:18:15 -070041
42 return 0;
43}
44
Simon Glassed38aef2020-05-10 11:40:03 -060045static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc,
46 char *const argv[])
Simon Glassfc0ba2d2015-01-01 16:18:15 -070047{
Simon Glassfbf120c2020-09-22 14:54:51 -060048 int reg_count = mtrr_get_var_count();
Simon Glass2c601b62020-07-17 08:48:28 -060049 int cmd;
Simon Glass7403c262020-07-17 08:48:22 -060050 int cpu_select;
Simon Glassfc0ba2d2015-01-01 16:18:15 -070051 uint reg;
Simon Glass2c601b62020-07-17 08:48:28 -060052 int ret;
Simon Glassfc0ba2d2015-01-01 16:18:15 -070053
Simon Glass7403c262020-07-17 08:48:22 -060054 cpu_select = MP_SELECT_BSP;
Simon Glasse643edd2020-07-17 08:48:29 -060055 if (argc >= 3 && !strcmp("-c", argv[1])) {
56 const char *cpustr;
57
58 cpustr = argv[2];
59 if (*cpustr == 'a')
60 cpu_select = MP_SELECT_ALL;
61 else
62 cpu_select = simple_strtol(cpustr, NULL, 16);
63 argc -= 2;
64 argv += 2;
65 }
Simon Glass2c601b62020-07-17 08:48:28 -060066 argc--;
67 argv++;
68 cmd = argv[0] ? *argv[0] : 0;
69 if (argc < 1 || !cmd) {
70 cmd = 'l';
71 reg = 0;
Wolfgang Wallner9abf45b2020-08-14 09:55:24 +020072 }
73 if (cmd != 'l') {
Simon Glass2c601b62020-07-17 08:48:28 -060074 if (argc < 2)
75 return CMD_RET_USAGE;
Simon Glass3ff49ec2021-07-24 09:03:29 -060076 reg = hextoul(argv[1], NULL);
Simon Glassfbf120c2020-09-22 14:54:51 -060077 if (reg >= reg_count) {
Simon Glass2c601b62020-07-17 08:48:28 -060078 printf("Invalid register number\n");
79 return CMD_RET_USAGE;
80 }
81 }
82 if (cmd == 'l') {
Simon Glass3ac9fdb2020-07-17 08:48:31 -060083 bool first;
84 int i;
85
86 i = mp_first_cpu(cpu_select);
87 if (i < 0) {
88 printf("Invalid CPU (err=%d)\n", i);
89 return CMD_RET_FAILURE;
90 }
91 first = true;
92 for (; i >= 0; i = mp_next_cpu(cpu_select, i)) {
93 if (!first)
94 printf("\n");
95 printf("CPU %d:\n", i);
Simon Glassfb842432023-07-15 21:38:36 -060096 ret = mtrr_list(reg_count, i);
Simon Glass3ac9fdb2020-07-17 08:48:31 -060097 if (ret) {
Simon Glasscb3a7ac2023-05-04 16:54:54 -060098 printf("Failed to read CPU %s (err=%d)\n",
99 i < MP_SELECT_ALL ? simple_itoa(i) : "",
Simon Glass3ac9fdb2020-07-17 08:48:31 -0600100 ret);
101 return CMD_RET_FAILURE;
102 }
103 first = false;
104 }
Simon Glass2c601b62020-07-17 08:48:28 -0600105 } else {
106 switch (cmd) {
107 case 'e':
108 ret = mtrr_set_valid(cpu_select, reg, true);
109 break;
110 case 'd':
111 ret = mtrr_set_valid(cpu_select, reg, false);
112 break;
113 case 's':
114 ret = do_mtrr_set(cpu_select, reg, argc - 2, argv + 2);
115 break;
116 default:
117 return CMD_RET_USAGE;
118 }
119 if (ret) {
120 printf("Operation failed (err=%d)\n", ret);
121 return CMD_RET_FAILURE;
122 }
Simon Glassfc0ba2d2015-01-01 16:18:15 -0700123 }
Simon Glassfc0ba2d2015-01-01 16:18:15 -0700124
125 return 0;
126}
127
128U_BOOT_CMD(
Simon Glasse643edd2020-07-17 08:48:29 -0600129 mtrr, 8, 1, do_mtrr,
Simon Glassfc0ba2d2015-01-01 16:18:15 -0700130 "Use x86 memory type range registers (32-bit only)",
131 "[list] - list current registers\n"
132 "set <reg> <type> <start> <size> - set a register\n"
133 "\t<type> is Uncacheable, Combine, Through, Protect, Back\n"
134 "disable <reg> - disable a register\n"
Simon Glasse643edd2020-07-17 08:48:29 -0600135 "enable <reg> - enable a register\n"
136 "\n"
137 "Precede command with '-c <n>|all' to access a particular hex CPU, e.g.\n"
138 " mtrr -c all list; mtrr -c 2e list"
Simon Glassfc0ba2d2015-01-01 16:18:15 -0700139);