blob: d6c20001d88db50427a2f6754eef6e887eaa37d8 [file] [log] [blame]
Stefan Reinauerb5ab3232009-04-22 07:23:00 +00001/*
2 * This file is part of the ectool project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
Uwe Hermann257ae3f2009-04-22 12:28:14 +00008 * published by the Free Software Foundation; version 2 of the License.
Stefan Reinauerb5ab3232009-04-22 07:23:00 +00009 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000014 */
15
16#include <stdio.h>
Stefan Reinauer2dd1ded2010-09-27 18:48:15 +000017#include <stdint.h>
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000018#include <stdlib.h>
Iru Cai2e8f4cc2018-01-25 21:44:09 +080019#include <string.h>
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000020#include <unistd.h>
Steven Dee3236f7b2017-01-29 14:52:56 -050021#if !(defined __NetBSD__ || defined __OpenBSD__)
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000022#include <sys/io.h>
Andrey Korolyov393d9322016-01-05 14:27:59 +030023#endif
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000024#include "ec.h"
25
Iru Cai2e8f4cc2018-01-25 21:44:09 +080026static int ec_data = 0x62;
27static int ec_sc = 0x66;
28
Steven Dee3236f7b2017-01-29 14:52:56 -050029#if defined __NetBSD__ || defined __OpenBSD__
Andrey Korolyov393d9322016-01-05 14:27:59 +030030#include <machine/sysarch.h>
31static uint8_t inb(unsigned port)
32{
33 uint8_t data;
34 __asm volatile("inb %w1,%0" : "=a" (data) : "d" (port));
35 return data;
36}
37static __inline void outb(uint8_t data, unsigned port)
38{
39 __asm volatile("outb %0,%w1" : : "a" (data), "d" (port));
40}
41#endif
42
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000043extern int verbose;
44
45#define debug(x...) if (verbose) printf(x)
46
47int send_ec_command(uint8_t command)
48{
49 int timeout;
50
51 timeout = 0x7ff;
Iru Cai2e8f4cc2018-01-25 21:44:09 +080052 while ((inb(ec_sc) & EC_IBF) && --timeout) {
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000053 usleep(10);
54 if ((timeout & 0xff) == 0)
55 debug(".");
56 }
57 if (!timeout) {
Anton Kochkov7e59f7692010-06-29 21:13:20 +000058 debug("Timeout while sending command 0x%02x to EC!\n",
Uwe Hermann257ae3f2009-04-22 12:28:14 +000059 command);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000060 // return -1;
61 }
62
Iru Cai2e8f4cc2018-01-25 21:44:09 +080063 outb(command, ec_sc);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000064 return 0;
65}
66
67int send_ec_data(uint8_t data)
68{
69 int timeout;
70
71 timeout = 0x7ff;
Iru Cai2e8f4cc2018-01-25 21:44:09 +080072 while ((inb(ec_sc) & EC_IBF) && --timeout) { // wait for IBF = 0
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000073 usleep(10);
74 if ((timeout & 0xff) == 0)
75 debug(".");
76 }
Arthur Heymans2873a4a2017-04-06 14:17:26 +020077 if (!timeout) {
Anton Kochkov7e59f7692010-06-29 21:13:20 +000078 debug("Timeout while sending data 0x%02x to EC!\n", data);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000079 // return -1;
80 }
81
Iru Cai2e8f4cc2018-01-25 21:44:09 +080082 outb(data, ec_data);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000083
84 return 0;
85}
86
87int send_ec_data_nowait(uint8_t data)
88{
Iru Cai2e8f4cc2018-01-25 21:44:09 +080089 outb(data, ec_data);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000090
91 return 0;
92}
93
94uint8_t recv_ec_data(void)
95{
96 int timeout;
97 uint8_t data;
98
99 timeout = 0x7fff;
Uwe Hermann257ae3f2009-04-22 12:28:14 +0000100 while (--timeout) { // Wait for OBF = 1
Iru Cai2e8f4cc2018-01-25 21:44:09 +0800101 if (inb(ec_sc) & EC_OBF)
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000102 break;
Iru Cai2e8f4cc2018-01-25 21:44:09 +0800103
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000104 usleep(10);
105 if ((timeout & 0xff) == 0)
106 debug(".");
107 }
108 if (!timeout) {
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000109 debug("\nTimeout while receiving data from EC!\n");
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000110 // return -1;
111 }
112
Iru Cai2e8f4cc2018-01-25 21:44:09 +0800113 data = inb(ec_data);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000114 debug("recv_ec_data: 0x%02x\n", data);
115
116 return data;
117}
118
119uint8_t ec_read(uint8_t addr)
120{
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000121 send_ec_command(RD_EC);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000122 send_ec_data(addr);
123
124 return recv_ec_data();
125}
126
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000127uint8_t ec_ext_read(uint16_t addr)
128{
129 send_ec_command(WR_EC);
130 send_ec_data(0x02);
131 send_ec_data(addr & 0xff);
132 send_ec_command(RX_EC);
133 send_ec_data(addr >> 8);
134
135 return recv_ec_data();
136}
137
138int ec_ext_write(uint16_t addr, uint8_t data)
139{
140 send_ec_command(WR_EC);
141 send_ec_data(0x02);
142 send_ec_data(addr & 0xff);
143 send_ec_command(WX_EC);
144 send_ec_data(addr >> 8);
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700145
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000146 return send_ec_data(data);
147}
148
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000149int ec_write(uint8_t addr, uint8_t data)
150{
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000151 send_ec_command(WR_EC);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000152 send_ec_data(addr);
Uwe Hermann257ae3f2009-04-22 12:28:14 +0000153
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000154 return send_ec_data(data);
155}
Stefan Reinauer984e0f32010-01-16 17:50:55 +0000156
157uint8_t ec_idx_read(uint16_t addr)
158{
159 uint16_t lpc_idx = 0x380;
160
161 outb(addr & 0xff, lpc_idx + 2);
162 outb(addr >> 8, lpc_idx + 1);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000163
Stefan Reinauer984e0f32010-01-16 17:50:55 +0000164 return inb(lpc_idx + 3);
165}
Alexander Couzens0edf4192015-02-06 22:27:33 +0100166
167uint8_t ec_query(void)
168{
169 send_ec_command(QR_EC);
170 return recv_ec_data();
171}
Iru Cai2e8f4cc2018-01-25 21:44:09 +0800172
173int get_ec_ports(void)
174{
175 FILE *fp = fopen("/proc/ioports", "r");
176 int data = 0, cmd = 0;
177 char line[100];
178
179 if (fp == NULL)
180 return -1;
181
182 while (!feof(fp) && (data == 0 || cmd == 0)) {
183 fgets(line, sizeof(line), fp);
184 if (strstr(line, "EC data") != NULL)
185 data = strtol(line, NULL, 16);
186
187 if (strstr(line, "EC cmd") != NULL)
188 cmd = strtol(line, NULL, 16);
189 }
190
191 fclose(fp);
192 if (data != 0 && cmd != 0) {
193 debug("EC data = 0x%x, EC cmd = 0x%x\n", data, cmd);
194 ec_data = data;
195 ec_sc = cmd;
196 } else {
197 return -1;
198 }
199 return 0;
200}