blob: 098e8126d916c8dc25f114c49cfbd3b0943c576c [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>
19#include <unistd.h>
Andrey Korolyov393d9322016-01-05 14:27:59 +030020#ifndef __NetBSD__
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000021#include <sys/io.h>
Andrey Korolyov393d9322016-01-05 14:27:59 +030022#endif
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000023#include "ec.h"
24
Andrey Korolyov393d9322016-01-05 14:27:59 +030025#ifdef __NetBSD__
26#include <machine/sysarch.h>
27static uint8_t inb(unsigned port)
28{
29 uint8_t data;
30 __asm volatile("inb %w1,%0" : "=a" (data) : "d" (port));
31 return data;
32}
33static __inline void outb(uint8_t data, unsigned port)
34{
35 __asm volatile("outb %0,%w1" : : "a" (data), "d" (port));
36}
37#endif
38
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000039extern int verbose;
40
41#define debug(x...) if (verbose) printf(x)
42
43int send_ec_command(uint8_t command)
44{
45 int timeout;
46
47 timeout = 0x7ff;
48 while ((inb(EC_SC) & EC_IBF) && --timeout) {
49 usleep(10);
50 if ((timeout & 0xff) == 0)
51 debug(".");
52 }
53 if (!timeout) {
Anton Kochkov7e59f7692010-06-29 21:13:20 +000054 debug("Timeout while sending command 0x%02x to EC!\n",
Uwe Hermann257ae3f2009-04-22 12:28:14 +000055 command);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000056 // return -1;
57 }
58
59 outb(command, EC_SC);
60 return 0;
61}
62
63int send_ec_data(uint8_t data)
64{
65 int timeout;
66
67 timeout = 0x7ff;
Uwe Hermann257ae3f2009-04-22 12:28:14 +000068 while ((inb(EC_SC) & EC_IBF) && --timeout) { // wait for IBF = 0
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000069 usleep(10);
70 if ((timeout & 0xff) == 0)
71 debug(".");
72 }
Anton Kochkov7e59f7692010-06-29 21:13:20 +000073 if (timeout) {
74 debug("Timeout while sending data 0x%02x to EC!\n", data);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000075 // return -1;
76 }
77
78 outb(data, EC_DATA);
79
80 return 0;
81}
82
83int send_ec_data_nowait(uint8_t data)
84{
85 outb(data, EC_DATA);
86
87 return 0;
88}
89
90uint8_t recv_ec_data(void)
91{
92 int timeout;
93 uint8_t data;
94
95 timeout = 0x7fff;
Uwe Hermann257ae3f2009-04-22 12:28:14 +000096 while (--timeout) { // Wait for OBF = 1
Stefan Reinauerb5ab3232009-04-22 07:23:00 +000097 if (inb(EC_SC) & EC_OBF) {
98 break;
99 }
100 usleep(10);
101 if ((timeout & 0xff) == 0)
102 debug(".");
103 }
104 if (!timeout) {
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000105 debug("\nTimeout while receiving data from EC!\n");
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000106 // return -1;
107 }
108
109 data = inb(EC_DATA);
110 debug("recv_ec_data: 0x%02x\n", data);
111
112 return data;
113}
114
115uint8_t ec_read(uint8_t addr)
116{
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000117 send_ec_command(RD_EC);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000118 send_ec_data(addr);
119
120 return recv_ec_data();
121}
122
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000123uint8_t ec_ext_read(uint16_t addr)
124{
125 send_ec_command(WR_EC);
126 send_ec_data(0x02);
127 send_ec_data(addr & 0xff);
128 send_ec_command(RX_EC);
129 send_ec_data(addr >> 8);
130
131 return recv_ec_data();
132}
133
134int ec_ext_write(uint16_t addr, uint8_t data)
135{
136 send_ec_command(WR_EC);
137 send_ec_data(0x02);
138 send_ec_data(addr & 0xff);
139 send_ec_command(WX_EC);
140 send_ec_data(addr >> 8);
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700141
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000142 return send_ec_data(data);
143}
144
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000145int ec_write(uint8_t addr, uint8_t data)
146{
Anton Kochkov7e59f7692010-06-29 21:13:20 +0000147 send_ec_command(WR_EC);
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000148 send_ec_data(addr);
Uwe Hermann257ae3f2009-04-22 12:28:14 +0000149
Stefan Reinauerb5ab3232009-04-22 07:23:00 +0000150 return send_ec_data(data);
151}
Stefan Reinauer984e0f32010-01-16 17:50:55 +0000152
153uint8_t ec_idx_read(uint16_t addr)
154{
155 uint16_t lpc_idx = 0x380;
156
157 outb(addr & 0xff, lpc_idx + 2);
158 outb(addr >> 8, lpc_idx + 1);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000159
Stefan Reinauer984e0f32010-01-16 17:50:55 +0000160 return inb(lpc_idx + 3);
161}
Alexander Couzens0edf4192015-02-06 22:27:33 +0100162
163uint8_t ec_query(void)
164{
165 send_ec_command(QR_EC);
166 return recv_ec_data();
167}