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.
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
)
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
)
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
);
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"
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."
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
[] = {
87 {"clear-bit", 1, 0, 'c'},
88 {"set-bit", 1, 0, 's'},
92 if (argv
[1] == NULL
) {
97 while ((opt
= getopt_long(argc
, argv
, "hdw:r:c:s:",
98 long_options
, &option_index
)) != EOF
) {
105 input_addr
= strtoul(optarg
, NULL
, 16);
112 input_addr
= strtoul(optarg
, NULL
, 16);
114 if (optind
< argc
&& *argv
[optind
] != '-') {
115 input_data
= strtoul(argv
[optind
], NULL
, 16);
119 "Error: -%c option requires two arguments\n",
140 fprintf(stderr
, "Error: Extra parameter found.\n");
141 print_usage(argv
[0]);
146 print_usage(argv
[0]);
150 if (input_addr
> 0x1ff) {
152 "Error: <addr> cannot be greater than 9 bits long.\n");
156 if (act
== SET
|| act
== CLEAR
) {
157 if (input_data
> 7) {
159 "Error: <bit> cannot be greater than 7.\n");
163 if (input_data
> 0xff) {
165 "Error: <data> cannot be greater than 8 bits long.\n");
170 if (geteuid() != 0) {
171 fprintf(stderr
, "You must be root.\n");
175 if (ioperm(EC_LENOVO_PMH7_BASE
, 0x10, 1)) {
176 fprintf(stderr
, "ioperm: %s\n", strerror(errno
));
182 for (int i
= 0; i
< 0x200; i
++) {
183 if ((i
% 0x10) == 0) {
188 printf("%02x ", pmh7_register_read(i
));
194 printf("%02x\n", pmh7_register_read(input_addr
));
198 pmh7_register_write(input_addr
, input_data
);
202 pmh7_register_clear_bit(input_addr
, input_data
);
206 pmh7_register_set_bit(input_addr
, input_data
);