Add support to extended EC series
[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 <stdlib.h>
22 #include <unistd.h>
23 #include <sys/io.h>
24 #include "ec.h"
25
26 extern int verbose;
27
28 #define debug(x...) if (verbose) printf(x)
29
30 int send_ec_command(uint8_t command)
31 {
32         int timeout;
33
34         timeout = 0x7ff;
35         while ((inb(EC_SC) & EC_IBF) && --timeout) {
36                 usleep(10);
37                 if ((timeout & 0xff) == 0)
38                         debug(".");
39         }
40         if (!timeout) {
41                 debug("Timeout while sending command 0x%02x to EC!\n",
42                        command);
43                 // return -1;
44         }
45
46         outb(command, EC_SC);
47         return 0;
48 }
49
50 int send_ec_data(uint8_t data)
51 {
52         int timeout;
53
54         timeout = 0x7ff;
55         while ((inb(EC_SC) & EC_IBF) && --timeout) {    // wait for IBF = 0
56                 usleep(10);
57                 if ((timeout & 0xff) == 0)
58                         debug(".");
59         }
60         if (timeout) {
61                 debug("Timeout while sending data 0x%02x to EC!\n", data);
62                 // return -1;
63         }
64
65         outb(data, EC_DATA);
66
67         return 0;
68 }
69
70 int send_ec_data_nowait(uint8_t data)
71 {
72         outb(data, EC_DATA);
73
74         return 0;
75 }
76
77 uint8_t recv_ec_data(void)
78 {
79         int timeout;
80         uint8_t data;
81
82         timeout = 0x7fff;
83         while (--timeout) {     // Wait for OBF = 1
84                 if (inb(EC_SC) & EC_OBF) {
85                         break;
86                 }
87                 usleep(10);
88                 if ((timeout & 0xff) == 0)
89                         debug(".");
90         }
91         if (!timeout) {
92                 debug("\nTimeout while receiving data from EC!\n");
93                 // return -1;
94         }
95
96         data = inb(EC_DATA);
97         debug("recv_ec_data: 0x%02x\n", data);
98
99         return data;
100 }
101
102 uint8_t ec_read(uint8_t addr)
103 {
104         send_ec_command(RD_EC);
105         send_ec_data(addr);
106
107         return recv_ec_data();
108 }
109
110 uint8_t ec_ext_read(uint16_t addr)
111 {
112         send_ec_command(WR_EC);
113         send_ec_data(0x02);
114         send_ec_data(addr & 0xff);
115         send_ec_command(RX_EC);
116         send_ec_data(addr >> 8);
117
118         return recv_ec_data();
119 }
120
121 int ec_ext_write(uint16_t addr, uint8_t data)
122 {
123         send_ec_command(WR_EC);
124         send_ec_data(0x02);
125         send_ec_data(addr & 0xff);
126         send_ec_command(WX_EC);
127         send_ec_data(addr >> 8);
128     
129         return send_ec_data(data);
130 }
131
132 int ec_write(uint8_t addr, uint8_t data)
133 {
134         send_ec_command(WR_EC);
135         send_ec_data(addr);
136
137         return send_ec_data(data);
138 }
139
140 uint8_t ec_idx_read(uint16_t addr)
141 {
142         uint16_t lpc_idx = 0x380;
143
144         outb(addr & 0xff, lpc_idx + 2);
145         outb(addr >> 8, lpc_idx + 1);
146
147         return inb(lpc_idx + 3);
148 }