util/pmh7tool: Add tool to dump PMH7 registers
[coreboot.git] / util / pmh7tool / pmh7tool.c
blobd0c652eb2a0e91e9c949b9a98d406f8bd42838c6
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2018 Evgeny Zinoviev <me@ch1p.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <getopt.h>
19 #include <sys/io.h>
20 #include <errno.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <stdint.h>
24 #include "pmh7tool.h"
26 uint8_t pmh7_register_read(uint16_t reg)
28 outb(reg & 0xff, EC_LENOVO_PMH7_ADDR_L);
29 outb((reg & 0xff00) >> 8, EC_LENOVO_PMH7_ADDR_H);
30 return inb(EC_LENOVO_PMH7_DATA);
33 void pmh7_register_write(uint16_t reg, uint8_t val)
35 outb(reg & 0xff, EC_LENOVO_PMH7_ADDR_L);
36 outb((reg & 0xff00) >> 8, EC_LENOVO_PMH7_ADDR_H);
37 outb(val, EC_LENOVO_PMH7_DATA);
40 void pmh7_register_set_bit(uint16_t reg, uint8_t bit)
42 uint8_t val;
44 val = pmh7_register_read(reg);
45 pmh7_register_write(reg, val | (1 << bit));
48 void pmh7_register_clear_bit(uint16_t reg, uint8_t bit)
50 uint8_t val;
52 val = pmh7_register_read(reg);
53 pmh7_register_write(reg, val & ~(1 << bit));
56 void print_usage(const char *name)
58 printf("usage: %s\n", name);
59 printf("\n"
60 " -h, --help: print this help\n"
61 " -d, --dump: print registers\n"
62 " -w, --write <addr> <data>: write to register\n"
63 " -r, --read <addr>: read from register\n"
64 " -c, --clear-bit <addr> <bit>\n"
65 " -s, --set-bit <addr> <bit>\n"
66 "\n"
67 "Attention! Writing to PMH7 registers is very dangerous, as you\n"
68 " directly manipulate the power rails, enable lines,\n"
69 " interrupt lines or something else of the device.\n"
70 " Proceed with caution."
71 "\n");
74 enum action {HELP, DUMP, WRITE, READ, CLEAR, SET};
76 int main(int argc, char *argv[])
78 enum action act = HELP;
79 int opt, option_index = 0;
80 long input_addr = 0, input_data = 0;
82 static struct option long_options[] = {
83 {"help", 0, 0, 'h'},
84 {"dump", 0, 0, 'd'},
85 {"write", 1, 0, 'w'},
86 {"read", 1, 0, 'r'},
87 {"clear-bit", 1, 0, 'c'},
88 {"set-bit", 1, 0, 's'},
89 {0, 0, 0, 0}
92 if (argv[1] == NULL) {
93 print_usage(argv[0]);
94 exit(0);
97 while ((opt = getopt_long(argc, argv, "hdw:r:c:s:",
98 long_options, &option_index)) != EOF) {
99 switch (opt) {
100 case 'd':
101 act = DUMP;
102 break;
104 case 'r':
105 input_addr = strtoul(optarg, NULL, 16);
106 act = READ;
107 break;
109 case 'w':
110 case 'c':
111 case 's':
112 input_addr = strtoul(optarg, NULL, 16);
114 if (optind < argc && *argv[optind] != '-') {
115 input_data = strtoul(argv[optind], NULL, 16);
116 optind++;
117 } else {
118 fprintf(stderr,
119 "Error: -%c option requires two arguments\n",
120 opt);
121 exit(1);
124 switch (opt) {
125 case 'w':
126 act = WRITE;
127 break;
128 case 'c':
129 act = CLEAR;
130 break;
131 case 's':
132 act = SET;
133 break;
135 break;
139 if (optind < argc) {
140 fprintf(stderr, "Error: Extra parameter found.\n");
141 print_usage(argv[0]);
142 exit(1);
145 if (act == HELP) {
146 print_usage(argv[0]);
147 exit(0);
150 if (input_addr > 0x1ff) {
151 fprintf(stderr,
152 "Error: <addr> cannot be greater than 9 bits long.\n");
153 exit(1);
156 if (act == SET || act == CLEAR) {
157 if (input_data > 7) {
158 fprintf(stderr,
159 "Error: <bit> cannot be greater than 7.\n");
160 exit(1);
162 } else {
163 if (input_data > 0xff) {
164 fprintf(stderr,
165 "Error: <data> cannot be greater than 8 bits long.\n");
166 exit(1);
170 if (geteuid() != 0) {
171 fprintf(stderr, "You must be root.\n");
172 exit(1);
175 if (ioperm(EC_LENOVO_PMH7_BASE, 0x10, 1)) {
176 fprintf(stderr, "ioperm: %s\n", strerror(errno));
177 exit(1);
180 switch (act) {
181 case DUMP:
182 for (int i = 0; i < 0x200; i++) {
183 if ((i % 0x10) == 0) {
184 if (i != 0)
185 printf("\n");
186 printf("%04x: ", i);
188 printf("%02x ", pmh7_register_read(i));
190 printf("\n");
191 break;
193 case READ:
194 printf("%02x\n", pmh7_register_read(input_addr));
195 break;
197 case WRITE:
198 pmh7_register_write(input_addr, input_data);
199 break;
201 case CLEAR:
202 pmh7_register_clear_bit(input_addr, input_data);
203 break;
205 case SET:
206 pmh7_register_set_bit(input_addr, input_data);
207 break;
209 default:
210 break;
213 return 0;