blob: beadaa734f76f48f21a3604fb22a6d03e7b6e5fa [file] [log] [blame]
Rong Changaaa1acf2012-06-21 19:21:18 +08001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2012 Google Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * Neither the name of Google or the names of contributors or
18 * licensors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * This software is provided "AS IS," without a warranty of any kind.
22 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
23 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
24 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
25 * GOOGLE INC AND ITS LICENSORS SHALL NOT BE LIABLE
26 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
27 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
28 * GOOGLE OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
29 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
30 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
31 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
32 * EVEN IF GOOGLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33 */
34
35#if defined(__i386__) || defined(__x86_64__)
36#include <inttypes.h>
37#include <string.h>
38#include <unistd.h>
Shawn Nematbakhshb903dfd2012-07-24 15:27:00 -070039#include <sys/time.h>
Rong Changaaa1acf2012-06-21 19:21:18 +080040
41#include "chipdrivers.h"
42#include "flash.h"
43#include "programmer.h"
44#include "spi.h"
45
46#define REG_EC_HWVER 0xff00
47#define REG_EC_FWVER 0xff01
48#define REG_EC_EDIID 0xff24
49#define REG_8051_CTRL 0xff14
50
51#define HWVER 0xa2
52#define EDIID 0x02
53#define CPU_RESET 1
54
55/* Hwardware registers */
56#define REG_SPI_DATA 0xfeab
57#define REG_SPI_COMMAND 0xfeac
58#define REG_SPI_CONFIG 0xfead
59#define CFG_CSn_FORCE_LOW (1 << 4)
60#define CFG_COMMAND_WRITE_ENABLE (1 << 3)
61#define CFG_STATUS (1 << 1)
62#define CFG_ENABLE_BUSY_STATUS_CHECK (1 << 0)
63
64/* Timeout */
65#define EC_COMMAND_TIMEOUT 4
66#define EC_RESTART_TIMEOUT 10
67#define ENE_SPI_DELAY_CYCLE 4
68
69/* Configurable ec command/status */
70static unsigned int port_ec_command = 0x6c;
71static unsigned int port_ec_data = 0x68;
Rong Changea1ec812012-07-21 11:41:32 +080072static unsigned int port_ec_bios = 0x66;
Rong Changaaa1acf2012-06-21 19:21:18 +080073
74static uint8_t ec_reset_cmd = 0x59;
75static uint8_t ec_reset_data = 0xf2;
76
77static uint8_t ec_restart_cmd = 0x59;
78static uint8_t ec_restart_data = 0xf9;
79
Rong Changaaa1acf2012-06-21 19:21:18 +080080static const uint16_t ec_status_buf = 0xf554;
81static const uint8_t ec_is_stopping = 0xa5;
82static const uint8_t ec_is_running = 0;
83
84static const uint8_t mask_input_buffer_full = 2;
85static const uint8_t mask_output_buffer_full = 1;
86
87static unsigned int port_io_base = 0xfd60;
88const int port_ene_bank = 1;
89const int port_ene_offset = 2;
90const int port_ene_data = 3;
91
92static void ec_command(uint8_t cmd, uint8_t data)
93{
94 struct timeval begin, now;
95
96 /* Spin wait for EC input buffer empty */
97 gettimeofday(&begin, NULL);
98 while (INB(port_ec_command) & mask_input_buffer_full) {
99 gettimeofday(&now, NULL);
100 if ((now.tv_sec - begin.tv_sec) >= EC_COMMAND_TIMEOUT) {
101 msg_pdbg("%s: buf not empty\n", __func__);
102 return;
103 }
104 }
105 /* Write command */
106 OUTB(cmd, port_ec_command);
107
108 /* Spin wait for EC input buffer empty */
109 gettimeofday(&begin, NULL);
110 while (INB(port_ec_command) & mask_input_buffer_full) {
111 gettimeofday(&now, NULL);
112 if ((now.tv_sec - begin.tv_sec) >= EC_COMMAND_TIMEOUT) {
113 msg_pdbg("%s: buf not empty\n", __func__);
114 return;
115 }
116 }
117 /* Write data */
118 OUTB(data, port_ec_data);
119}
120
121static uint8_t ene_read(uint16_t addr)
122{
123 uint8_t bank;
124 uint8_t offset;
125 uint8_t data;
126
127 bank = addr >> 8;
128 offset = addr & 0xff;
129
130 OUTB(bank, port_io_base + port_ene_bank);
131 OUTB(offset, port_io_base + port_ene_offset);
132 data = INB(port_io_base + port_ene_data);
133
134 return data;
135}
136
137static void ene_write(uint16_t addr, uint8_t data)
138{
139 uint8_t bank;
140 uint8_t offset;
141
142 bank = addr >> 8;
143 offset = addr & 0xff;
144
145 OUTB(bank, port_io_base + port_ene_bank);
146 OUTB(offset, port_io_base + port_ene_offset);
147
148 OUTB(data, port_io_base + port_ene_data);
149}
150
151/**
152 * wait_cycles, wait for n LPC bus clock cycles
153 *
154 * @param n: number of LPC cycles to wait
155 * @return void
156 */
157void wait_cycles(int n)
158{
159 while (n--)
160 INB(port_io_base + port_ene_bank);
161}
162
163static void ene_spi_start(void)
164{
165 int cfg;
166
167 cfg = ene_read(REG_SPI_CONFIG);
168 cfg |= CFG_CSn_FORCE_LOW;
169 cfg |= CFG_COMMAND_WRITE_ENABLE;
170 ene_write(REG_SPI_CONFIG, cfg);
171
172 wait_cycles(ENE_SPI_DELAY_CYCLE);
173}
174
175static void ene_spi_end(void)
176{
177 int cfg;
178
179 cfg = ene_read(REG_SPI_CONFIG);
180 cfg &= ~CFG_CSn_FORCE_LOW;
181 cfg |= CFG_COMMAND_WRITE_ENABLE;
182 ene_write(REG_SPI_CONFIG, cfg);
183
184 wait_cycles(ENE_SPI_DELAY_CYCLE);
185}
186
187static int ene_spi_wait(void)
188{
189 struct timeval begin, now;
190
191 gettimeofday(&begin, NULL);
192 while(ene_read(REG_SPI_CONFIG) & CFG_STATUS) {
193 gettimeofday(&now, NULL);
194 if ((now.tv_sec - begin.tv_sec) >= EC_COMMAND_TIMEOUT) {
195 msg_pdbg("%s: spi busy\n", __func__);
196 return 1;
197 }
198 }
199 return 0;
200}
201
202static int ene_spi_send_command(unsigned int writecnt,
203 unsigned int readcnt,
204 const unsigned char *writearr,
205 unsigned char *readarr)
206{
Rong Changaaa1acf2012-06-21 19:21:18 +0800207 int i;
208
209 ene_spi_start();
210
211 for (i = 0; i < writecnt; i++) {
212 ene_write(REG_SPI_COMMAND, writearr[i]);
213 if (ene_spi_wait()) {
214 msg_pdbg("%s: write count %d\n", __func__, i);
215 return 1;
216 }
217 }
218
219 for (i = 0; i < readcnt; i++) {
220 /* Push data by clock the serial bus */
221 ene_write(REG_SPI_COMMAND, 0);
222 if (ene_spi_wait()) {
223 msg_pdbg("%s: read count %d\n", __func__, i);
224 return 1;
225 }
226 readarr[i] = ene_read(REG_SPI_DATA);
227 if (ene_spi_wait()) {
228 msg_pdbg("%s: read count %d\n", __func__, i);
229 return 1;
230 }
231 }
232
233 ene_spi_end();
234 return 0;
235}
236
237static int ene_enter_flash_mode(void)
238{
Shawn Nematbakhshb903dfd2012-07-24 15:27:00 -0700239 uint8_t reg;
Rong Changaaa1acf2012-06-21 19:21:18 +0800240
241 struct timeval begin, now;
242 gettimeofday(&begin, NULL);
243
244 /* EC prepare reset */
245 ec_command(ec_reset_cmd, ec_reset_data);
246
247 /* Spin wait for EC ready */
248 while (ene_read(ec_status_buf) != ec_is_running) {
249 gettimeofday(&now, NULL);
250 if ((now.tv_sec - begin.tv_sec) >= EC_COMMAND_TIMEOUT) {
251 msg_pdbg("%s: ec reset busy\n", __func__);
252 return -1;
253 }
254 }
255
256 /* Wait 1 second */
257 sleep(1);
258
259 /* Reset 8051 */
260 reg = ene_read(REG_8051_CTRL);
261 reg |= CPU_RESET;
262 ene_write(REG_8051_CTRL, reg);
263
264 return 0;
265}
266
267static int ene_leave_flash_mode(void *data)
268{
Shawn Nematbakhshb903dfd2012-07-24 15:27:00 -0700269 uint8_t reg;
Rong Changaaa1acf2012-06-21 19:21:18 +0800270 struct timeval begin, now;
271
272 reg = ene_read(REG_8051_CTRL);
273 reg &= ~CPU_RESET;
274 ene_write(REG_8051_CTRL, reg);
275
276 gettimeofday(&begin, NULL);
277 /* EC restart */
278 while (ene_read(ec_status_buf) != ec_is_running) {
279 gettimeofday(&now, NULL);
280 if ((now.tv_sec - begin.tv_sec) >= EC_RESTART_TIMEOUT) {
281 msg_pdbg("%s: ec restart busy\n", __func__);
282 return 1;
283 }
284 }
285
286 msg_pdbg("%s: send ec restart\n", __func__);
287 ec_command(ec_restart_cmd, ec_restart_data);
288
Rong Changea1ec812012-07-21 11:41:32 +0800289 /* Trigger ec to bios interrupt */
290 sleep(1);
291 OUTB(0x80, port_ec_bios);
292
Rong Changaaa1acf2012-06-21 19:21:18 +0800293 return 0;
294}
295
296static const struct spi_programmer spi_programmer_ene = {
297 .type = SPI_CONTROLLER_ENE,
298 .max_data_read = 256,
299 .max_data_write = 256,
300 .command = ene_spi_send_command,
301 .multicommand = default_spi_send_multicommand,
302 .read = default_spi_read,
303 .write_256 = default_spi_write_256,
304};
305
306int ene_probe_spi_flash(const char *name)
307{
308 uint8_t hwver, ediid;
309
310 msg_pdbg("%s\n", __func__);
311 hwver = ene_read(REG_EC_HWVER);
312 ediid = ene_read(REG_EC_EDIID);
313
314 if (hwver != HWVER || ediid != EDIID) {
315 msg_pdbg("ENE EC not found (probe failed) : hwver %02x ediid %02x\n",
316 hwver, ediid);
317 return 0;
318 }
319
320 /* TODO: probe the EC stop protocol
321 *
322 * Compal - ec_command(0x41, 0xa1) returns 43 4f 4d 50 41 4c 9c
323 */
324
325
326 if (register_shutdown(ene_leave_flash_mode, NULL))
327 return 1;
328
329 ene_enter_flash_mode();
330
331 buses_supported |= BUS_LPC;
332 register_spi_programmer(&spi_programmer_ene);
333 msg_pdbg("%s: successfully initialized ene\n", __func__);
334 return 0;
335}
336
337#endif /* __i386__ || __x86_64__ */
338