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