3rdparty/blobs: Update submodule to upstream main
[coreboot.git] / util / ectool / ec.c
bloba189a094b53cdc7e3d1e1f22e8c0f2e35e4cb33a
1 /* SPDX-License-Identifier: GPL-2.0-only */
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"
13 static int ec_data = 0x62;
14 static int ec_sc = 0x66;
16 #if defined __NetBSD__ || defined __OpenBSD__
17 #include <machine/sysarch.h>
18 static uint8_t inb(unsigned port)
20 uint8_t data;
21 __asm volatile("inb %w1,%0" : "=a" (data) : "d" (port));
22 return data;
24 static __inline void outb(uint8_t data, unsigned port)
26 __asm volatile("outb %0,%w1" : : "a" (data), "d" (port));
28 #endif
30 extern int verbose;
32 #define debug(x...) if (verbose) printf(x)
34 int send_ec_command(uint8_t command)
36 int timeout;
38 timeout = 0x7ff;
39 while ((inb(ec_sc) & EC_IBF) && --timeout) {
40 usleep(10);
41 if ((timeout & 0xff) == 0)
42 debug(".");
44 if (!timeout) {
45 debug("Timeout while sending command 0x%02x to EC!\n",
46 command);
47 // return -1;
50 outb(command, ec_sc);
51 return 0;
54 int send_ec_data(uint8_t data)
56 int timeout;
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(".");
64 if (!timeout) {
65 debug("Timeout while sending data 0x%02x to EC!\n", data);
66 // return -1;
69 outb(data, ec_data);
71 return 0;
74 int send_ec_data_nowait(uint8_t data)
76 outb(data, ec_data);
78 return 0;
81 uint8_t recv_ec_data(void)
83 int timeout;
84 uint8_t data;
86 timeout = 0x7fff;
87 while (--timeout) { // Wait for OBF = 1
88 if (inb(ec_sc) & EC_OBF)
89 break;
91 usleep(10);
92 if ((timeout & 0xff) == 0)
93 debug(".");
95 if (!timeout) {
96 debug("\nTimeout while receiving data from EC!\n");
97 // return -1;
100 data = inb(ec_data);
101 debug("recv_ec_data: 0x%02x\n", data);
103 return data;
106 uint8_t ec_read(uint8_t addr)
108 send_ec_command(RD_EC);
109 send_ec_data(addr);
111 return recv_ec_data();
114 uint8_t ec_ext_read(uint16_t addr)
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);
122 return recv_ec_data();
125 int ec_ext_write(uint16_t addr, uint8_t data)
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);
133 return send_ec_data(data);
136 int ec_write(uint8_t addr, uint8_t data)
138 send_ec_command(WR_EC);
139 send_ec_data(addr);
141 return send_ec_data(data);
144 uint8_t ec_idx_read(uint16_t addr)
146 uint16_t lpc_idx = 0x380;
148 outb(addr & 0xff, lpc_idx + 2);
149 outb(addr >> 8, lpc_idx + 1);
151 return inb(lpc_idx + 3);
154 uint8_t ec_query(void)
156 send_ec_command(QR_EC);
157 return recv_ec_data();
160 int get_ec_ports(void)
162 FILE *fp = fopen("/proc/ioports", "r");
163 int data = 0, cmd = 0;
164 char line[100];
166 if (fp == NULL)
167 return -1;
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;
174 if (strstr(line, "EC data") != NULL)
175 data = strtol(line, NULL, 16);
177 if (strstr(line, "EC cmd") != NULL)
178 cmd = strtol(line, NULL, 16);
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;
189 return 0;