blob: a189a094b53cdc7e3d1e1f22e8c0f2e35e4cb33a [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauerb5ab3232009-04-22 07:23:00 +00002
3#include <stdio.h>
Stefan Reinauer2dd1ded2010-09-27 18:48:15 +00004#include <stdint.h>
Stefan Reinauerb5ab3232009-04-22 07:23:00 +00005#include <stdlib.h>
Iru Cai2e8f4cc2018-01-25 21:44:09 +08006#include <string.h>
Stefan Reinauerb5ab3232009-04-22 07:23:00 +00007#include <unistd.h>
Steven Dee3236f7b2017-01-29 14:52:56 -05008#if !(defined __NetBSD__ || defined __OpenBSD__)
Stefan Reinauerb5ab3232009-04-22 07:23:00 +00009#include <sys/io.h>
Andrey Korolyov393d9322016-01-05 14:27:59 +030010#endif
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000011#include "ec.h"
12
Iru Cai2e8f4cc2018-01-25 21:44:09 +080013static int ec_data = 0x62;
14static int ec_sc = 0x66;
15
Steven Dee3236f7b2017-01-29 14:52:56 -050016#if defined __NetBSD__ || defined __OpenBSD__
Andrey Korolyov393d9322016-01-05 14:27:59 +030017#include <machine/sysarch.h>
18static uint8_t inb(unsigned port)
19{
20 uint8_t data;
21 __asm volatile("inb %w1,%0" : "=a" (data) : "d" (port));
22 return data;
23}
24static __inline void outb(uint8_t data, unsigned port)
25{
26 __asm volatile("outb %0,%w1" : : "a" (data), "d" (port));
27}
28#endif
29
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000030extern int verbose;
31
32#define debug(x...) if (verbose) printf(x)
33
34int send_ec_command(uint8_t command)
35{
36 int timeout;
37
38 timeout = 0x7ff;
Iru Cai2e8f4cc2018-01-25 21:44:09 +080039 while ((inb(ec_sc) & EC_IBF) && --timeout) {
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000040 usleep(10);
41 if ((timeout & 0xff) == 0)
42 debug(".");
43 }
44 if (!timeout) {
Anton Kochkov7e59f7692010-06-29 21:13:20 +000045 debug("Timeout while sending command 0x%02x to EC!\n",
Uwe Hermann257ae3f2009-04-22 12:28:14 +000046 command);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000047 // return -1;
48 }
49
Iru Cai2e8f4cc2018-01-25 21:44:09 +080050 outb(command, ec_sc);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000051 return 0;
52}
53
54int send_ec_data(uint8_t data)
55{
56 int timeout;
57
58 timeout = 0x7ff;
Iru Cai2e8f4cc2018-01-25 21:44:09 +080059 while ((inb(ec_sc) & EC_IBF) && --timeout) { // wait for IBF = 0
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000060 usleep(10);
61 if ((timeout & 0xff) == 0)
62 debug(".");
63 }
Arthur Heymans2873a4a2017-04-06 14:17:26 +020064 if (!timeout) {
Anton Kochkov7e59f7692010-06-29 21:13:20 +000065 debug("Timeout while sending data 0x%02x to EC!\n", data);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000066 // return -1;
67 }
68
Iru Cai2e8f4cc2018-01-25 21:44:09 +080069 outb(data, ec_data);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000070
71 return 0;
72}
73
74int send_ec_data_nowait(uint8_t data)
75{
Iru Cai2e8f4cc2018-01-25 21:44:09 +080076 outb(data, ec_data);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000077
78 return 0;
79}
80
81uint8_t recv_ec_data(void)
82{
83 int timeout;
84 uint8_t data;
85
86 timeout = 0x7fff;
Uwe Hermann257ae3f2009-04-22 12:28:14 +000087 while (--timeout) { // Wait for OBF = 1
Iru Cai2e8f4cc2018-01-25 21:44:09 +080088 if (inb(ec_sc) & EC_OBF)
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000089 break;
Iru Cai2e8f4cc2018-01-25 21:44:09 +080090
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000091 usleep(10);
92 if ((timeout & 0xff) == 0)
93 debug(".");
94 }
95 if (!timeout) {
Anton Kochkov7e59f7692010-06-29 21:13:20 +000096 debug("\nTimeout while receiving data from EC!\n");
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000097 // return -1;
98 }
99
Iru Cai2e8f4cc2018-01-25 21:44:09 +0800100 data = inb(ec_data);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000101 debug("recv_ec_data: 0x%02x\n", data);
102
103 return data;
104}
105
106uint8_t ec_read(uint8_t addr)
107{
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000108 send_ec_command(RD_EC);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000109 send_ec_data(addr);
110
111 return recv_ec_data();
112}
113
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000114uint8_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
125int 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);
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700132
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000133 return send_ec_data(data);
134}
135
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000136int ec_write(uint8_t addr, uint8_t data)
137{
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000138 send_ec_command(WR_EC);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000139 send_ec_data(addr);
Uwe Hermann257ae3f2009-04-22 12:28:14 +0000140
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000141 return send_ec_data(data);
142}
Stefan Reinauer984e0f32010-01-16 17:50:55 +0000143
144uint8_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);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000150
Stefan Reinauer984e0f32010-01-16 17:50:55 +0000151 return inb(lpc_idx + 3);
152}
Alexander Couzens0edf4192015-02-06 22:27:33 +0100153
154uint8_t ec_query(void)
155{
156 send_ec_command(QR_EC);
157 return recv_ec_data();
158}
Iru Cai2e8f4cc2018-01-25 21:44:09 +0800159
160int 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)) {
Stefan Reinauer3a782592020-10-22 22:16:20 +0000170 if (fgets(line, sizeof(line), fp) == NULL) {
171 fprintf(stderr, "Can not read from /proc/ioports.\n");
172 break;
173 }
Iru Cai2e8f4cc2018-01-25 21:44:09 +0800174 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}