xref: /aosp_15_r20/external/coreboot/util/ectool/ec.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #if !(defined __NetBSD__ || defined __OpenBSD__)
9 #include <sys/io.h>
10 #endif
11 #include "ec.h"
12 
13 static int ec_data = 0x62;
14 static int ec_sc = 0x66;
15 
16 #if defined __NetBSD__ || defined __OpenBSD__
17 #include <machine/sysarch.h>
inb(unsigned port)18 static uint8_t inb(unsigned port)
19 {
20 	uint8_t data;
21 	__asm volatile("inb %w1,%0" : "=a" (data) : "d" (port));
22 	return data;
23 }
outb(uint8_t data,unsigned port)24 static __inline void outb(uint8_t data, unsigned port)
25 {
26 	__asm volatile("outb %0,%w1" : : "a" (data), "d" (port));
27 }
28 #endif
29 
30 extern int verbose;
31 
32 #define debug(x...) if (verbose) printf(x)
33 
send_ec_command(uint8_t command)34 int send_ec_command(uint8_t command)
35 {
36 	int timeout;
37 
38 	timeout = 0x7ff;
39 	while ((inb(ec_sc) & EC_IBF) && --timeout) {
40 		usleep(10);
41 		if ((timeout & 0xff) == 0)
42 			debug(".");
43 	}
44 	if (!timeout) {
45 		debug("Timeout while sending command 0x%02x to EC!\n",
46 		       command);
47 		// return -1;
48 	}
49 
50 	outb(command, ec_sc);
51 	return 0;
52 }
53 
send_ec_data(uint8_t data)54 int send_ec_data(uint8_t data)
55 {
56 	int timeout;
57 
58 	timeout = 0x7ff;
59 	while ((inb(ec_sc) & EC_IBF) && --timeout) {	// wait for IBF = 0
60 		usleep(10);
61 		if ((timeout & 0xff) == 0)
62 			debug(".");
63 	}
64 	if (!timeout) {
65 		debug("Timeout while sending data 0x%02x to EC!\n", data);
66 		// return -1;
67 	}
68 
69 	outb(data, ec_data);
70 
71 	return 0;
72 }
73 
send_ec_data_nowait(uint8_t data)74 int send_ec_data_nowait(uint8_t data)
75 {
76 	outb(data, ec_data);
77 
78 	return 0;
79 }
80 
recv_ec_data(void)81 uint8_t recv_ec_data(void)
82 {
83 	int timeout;
84 	uint8_t data;
85 
86 	timeout = 0x7fff;
87 	while (--timeout) {	// Wait for OBF = 1
88 		if (inb(ec_sc) & EC_OBF)
89 			break;
90 
91 		usleep(10);
92 		if ((timeout & 0xff) == 0)
93 			debug(".");
94 	}
95 	if (!timeout) {
96 		debug("\nTimeout while receiving data from EC!\n");
97 		// return -1;
98 	}
99 
100 	data = inb(ec_data);
101 	debug("recv_ec_data: 0x%02x\n", data);
102 
103 	return data;
104 }
105 
ec_read(uint8_t addr)106 uint8_t ec_read(uint8_t addr)
107 {
108 	send_ec_command(RD_EC);
109 	send_ec_data(addr);
110 
111 	return recv_ec_data();
112 }
113 
ec_ext_read(uint16_t addr)114 uint8_t ec_ext_read(uint16_t addr)
115 {
116 	send_ec_command(WR_EC);
117 	send_ec_data(0x02);
118 	send_ec_data(addr & 0xff);
119 	send_ec_command(RX_EC);
120 	send_ec_data(addr >> 8);
121 
122 	return recv_ec_data();
123 }
124 
ec_ext_write(uint16_t addr,uint8_t data)125 int ec_ext_write(uint16_t addr, uint8_t data)
126 {
127 	send_ec_command(WR_EC);
128 	send_ec_data(0x02);
129 	send_ec_data(addr & 0xff);
130 	send_ec_command(WX_EC);
131 	send_ec_data(addr >> 8);
132 
133 	return send_ec_data(data);
134 }
135 
ec_write(uint8_t addr,uint8_t data)136 int ec_write(uint8_t addr, uint8_t data)
137 {
138 	send_ec_command(WR_EC);
139 	send_ec_data(addr);
140 
141 	return send_ec_data(data);
142 }
143 
ec_idx_read(uint16_t addr)144 uint8_t ec_idx_read(uint16_t addr)
145 {
146 	uint16_t lpc_idx = 0x380;
147 
148 	outb(addr & 0xff, lpc_idx + 2);
149 	outb(addr >> 8, lpc_idx + 1);
150 
151 	return inb(lpc_idx + 3);
152 }
153 
ec_query(void)154 uint8_t ec_query(void)
155 {
156 	send_ec_command(QR_EC);
157 	return recv_ec_data();
158 }
159 
get_ec_ports(void)160 int get_ec_ports(void)
161 {
162 	FILE *fp = fopen("/proc/ioports", "r");
163 	int data = 0, cmd = 0;
164 	char line[100];
165 
166 	if (fp == NULL)
167 		return -1;
168 
169 	while (!feof(fp) && (data == 0 || cmd == 0)) {
170 		if (fgets(line, sizeof(line), fp) == NULL) {
171 			fprintf(stderr, "Can not read from /proc/ioports.\n");
172 			break;
173 		}
174 		if (strstr(line, "EC data") != NULL)
175 			data = strtol(line, NULL, 16);
176 
177 		if (strstr(line, "EC cmd") != NULL)
178 			cmd = strtol(line, NULL, 16);
179 	}
180 
181 	fclose(fp);
182 	if (data != 0 && cmd != 0) {
183 		debug("EC data = 0x%x, EC cmd = 0x%x\n", data, cmd);
184 		ec_data = data;
185 		ec_sc = cmd;
186 	} else {
187 		return -1;
188 	}
189 	return 0;
190 }
191