5bff0c2655aa4340c298eae8b4ccad925b832913
[coreboot.git] / util / ectool / ec.c
1 /*
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
8  * published by the Free Software Foundation; version 2 of the License.
9  *
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.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19
20 #include <stdio.h>
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/io.h>
25 #include "ec.h"
26
27 extern int verbose;
28
29 #define debug(x...) if (verbose) printf(x)
30
31 int send_ec_command(uint8_t command)
32 {
33         int timeout;
34
35         timeout = 0x7ff;
36         while ((inb(EC_SC) & EC_IBF) && --timeout) {
37                 usleep(10);
38                 if ((timeout & 0xff) == 0)
39                         debug(".");
40         }
41         if (!timeout) {
42                 debug("Timeout while sending command 0x%02x to EC!\n",
43                        command);
44                 // return -1;
45         }
46
47         outb(command, EC_SC);
48         return 0;
49 }
50
51 int send_ec_data(uint8_t data)
52 {
53         int timeout;
54
55         timeout = 0x7ff;
56         while ((inb(EC_SC) & EC_IBF) && --timeout) {    // wait for IBF = 0
57                 usleep(10);
58                 if ((timeout & 0xff) == 0)
59                         debug(".");
60         }
61         if (timeout) {
62                 debug("Timeout while sending data 0x%02x to EC!\n", data);
63                 // return -1;
64         }
65
66         outb(data, EC_DATA);
67
68         return 0;
69 }
70
71 int send_ec_data_nowait(uint8_t data)
72 {
73         outb(data, EC_DATA);
74
75         return 0;
76 }
77
78 uint8_t recv_ec_data(void)
79 {
80         int timeout;
81         uint8_t data;
82
83         timeout = 0x7fff;
84         while (--timeout) {     // Wait for OBF = 1
85                 if (inb(EC_SC) & EC_OBF) {
86                         break;
87                 }
88                 usleep(10);
89                 if ((timeout & 0xff) == 0)
90                         debug(".");
91         }
92         if (!timeout) {
93                 debug("\nTimeout while receiving data from EC!\n");
94                 // return -1;
95         }
96
97         data = inb(EC_DATA);
98         debug("recv_ec_data: 0x%02x\n", data);
99
100         return data;
101 }
102
103 uint8_t ec_read(uint8_t addr)
104 {
105         send_ec_command(RD_EC);
106         send_ec_data(addr);
107
108         return recv_ec_data();
109 }
110
111 uint8_t ec_ext_read(uint16_t addr)
112 {
113         send_ec_command(WR_EC);
114         send_ec_data(0x02);
115         send_ec_data(addr & 0xff);
116         send_ec_command(RX_EC);
117         send_ec_data(addr >> 8);
118
119         return recv_ec_data();
120 }
121
122 int ec_ext_write(uint16_t addr, uint8_t data)
123 {
124         send_ec_command(WR_EC);
125         send_ec_data(0x02);
126         send_ec_data(addr & 0xff);
127         send_ec_command(WX_EC);
128         send_ec_data(addr >> 8);
129     
130         return send_ec_data(data);
131 }
132
133 int ec_write(uint8_t addr, uint8_t data)
134 {
135         send_ec_command(WR_EC);
136         send_ec_data(addr);
137
138         return send_ec_data(data);
139 }
140
141 uint8_t ec_idx_read(uint16_t addr)
142 {
143         uint16_t lpc_idx = 0x380;
144
145         outb(addr & 0xff, lpc_idx + 2);
146         outb(addr >> 8, lpc_idx + 1);
147
148         return inb(lpc_idx + 3);
149 }