treewide: replace GPLv2 long form headers with SPDX header
[coreboot.git] / util / ectool / ec.c
blobe008ac44d0716e37b8418b17c59df3a2ec1be43b
1 /* This file is part of the ectool project. */
2 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <stdio.h>
5 #include <stdint.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #if !(defined __NetBSD__ || defined __OpenBSD__)
10 #include <sys/io.h>
11 #endif
12 #include "ec.h"
14 static int ec_data = 0x62;
15 static int ec_sc = 0x66;
17 #if defined __NetBSD__ || defined __OpenBSD__
18 #include <machine/sysarch.h>
19 static uint8_t inb(unsigned port)
21 uint8_t data;
22 __asm volatile("inb %w1,%0" : "=a" (data) : "d" (port));
23 return data;
25 static __inline void outb(uint8_t data, unsigned port)
27 __asm volatile("outb %0,%w1" : : "a" (data), "d" (port));
29 #endif
31 extern int verbose;
33 #define debug(x...) if (verbose) printf(x)
35 int send_ec_command(uint8_t command)
37 int timeout;
39 timeout = 0x7ff;
40 while ((inb(ec_sc) & EC_IBF) && --timeout) {
41 usleep(10);
42 if ((timeout & 0xff) == 0)
43 debug(".");
45 if (!timeout) {
46 debug("Timeout while sending command 0x%02x to EC!\n",
47 command);
48 // return -1;
51 outb(command, ec_sc);
52 return 0;
55 int send_ec_data(uint8_t data)
57 int timeout;
59 timeout = 0x7ff;
60 while ((inb(ec_sc) & EC_IBF) && --timeout) { // wait for IBF = 0
61 usleep(10);
62 if ((timeout & 0xff) == 0)
63 debug(".");
65 if (!timeout) {
66 debug("Timeout while sending data 0x%02x to EC!\n", data);
67 // return -1;
70 outb(data, ec_data);
72 return 0;
75 int send_ec_data_nowait(uint8_t data)
77 outb(data, ec_data);
79 return 0;
82 uint8_t recv_ec_data(void)
84 int timeout;
85 uint8_t data;
87 timeout = 0x7fff;
88 while (--timeout) { // Wait for OBF = 1
89 if (inb(ec_sc) & EC_OBF)
90 break;
92 usleep(10);
93 if ((timeout & 0xff) == 0)
94 debug(".");
96 if (!timeout) {
97 debug("\nTimeout while receiving data from EC!\n");
98 // return -1;
101 data = inb(ec_data);
102 debug("recv_ec_data: 0x%02x\n", data);
104 return data;
107 uint8_t ec_read(uint8_t addr)
109 send_ec_command(RD_EC);
110 send_ec_data(addr);
112 return recv_ec_data();
115 uint8_t ec_ext_read(uint16_t addr)
117 send_ec_command(WR_EC);
118 send_ec_data(0x02);
119 send_ec_data(addr & 0xff);
120 send_ec_command(RX_EC);
121 send_ec_data(addr >> 8);
123 return recv_ec_data();
126 int ec_ext_write(uint16_t addr, uint8_t data)
128 send_ec_command(WR_EC);
129 send_ec_data(0x02);
130 send_ec_data(addr & 0xff);
131 send_ec_command(WX_EC);
132 send_ec_data(addr >> 8);
134 return send_ec_data(data);
137 int ec_write(uint8_t addr, uint8_t data)
139 send_ec_command(WR_EC);
140 send_ec_data(addr);
142 return send_ec_data(data);
145 uint8_t ec_idx_read(uint16_t addr)
147 uint16_t lpc_idx = 0x380;
149 outb(addr & 0xff, lpc_idx + 2);
150 outb(addr >> 8, lpc_idx + 1);
152 return inb(lpc_idx + 3);
155 uint8_t ec_query(void)
157 send_ec_command(QR_EC);
158 return recv_ec_data();
161 int get_ec_ports(void)
163 FILE *fp = fopen("/proc/ioports", "r");
164 int data = 0, cmd = 0;
165 char line[100];
167 if (fp == NULL)
168 return -1;
170 while (!feof(fp) && (data == 0 || cmd == 0)) {
171 fgets(line, sizeof(line), fp);
172 if (strstr(line, "EC data") != NULL)
173 data = strtol(line, NULL, 16);
175 if (strstr(line, "EC cmd") != NULL)
176 cmd = strtol(line, NULL, 16);
179 fclose(fp);
180 if (data != 0 && cmd != 0) {
181 debug("EC data = 0x%x, EC cmd = 0x%x\n", data, cmd);
182 ec_data = data;
183 ec_sc = cmd;
184 } else {
185 return -1;
187 return 0;