blob: e1004a5068a62f2ccb3da2602376715e045005b6 [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>
David Hendricks2b56e472016-10-21 19:05:21 -070037#include <stdlib.h>
Rong Changaaa1acf2012-06-21 19:21:18 +080038#include <string.h>
39#include <unistd.h>
Shawn Nematbakhshb903dfd2012-07-24 15:27:00 -070040#include <sys/time.h>
Rong Changaaa1acf2012-06-21 19:21:18 +080041
42#include "chipdrivers.h"
43#include "flash.h"
44#include "programmer.h"
45#include "spi.h"
46
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -070047/* Supported ENE ECs, ENE_LAST should always be LAST member */
48enum ene_chip_id {
49 ENE_KB932 = 0,
50 ENE_KB94X,
51 ENE_LAST
52};
53
Rong Changd8889e52012-07-27 21:42:25 +080054/* EC state */
55enum ene_ec_state {
56 EC_STATE_NORMAL,
57 EC_STATE_IDLE,
58 EC_STATE_RESET,
59 EC_STATE_UNKNOWN
60};
61
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -070062/* chip-specific parameters */
63typedef struct {
64 enum ene_chip_id chip_id;
65 uint8_t hwver;
66 uint8_t ediid;
Rong Changd8889e52012-07-27 21:42:25 +080067 uint32_t port_bios;
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -070068 uint32_t port_ec_command;
69 uint32_t port_ec_data;
70 uint8_t ec_reset_cmd;
71 uint8_t ec_reset_data;
72 uint8_t ec_restart_cmd;
73 uint8_t ec_restart_data;
Rong Changd8889e52012-07-27 21:42:25 +080074 uint8_t ec_pause_cmd;
75 uint8_t ec_pause_data;
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -070076 uint16_t ec_status_buf;
77 uint8_t ec_is_stopping;
78 uint8_t ec_is_running;
Rong Changd8889e52012-07-27 21:42:25 +080079 uint8_t ec_is_pausing;
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -070080 uint32_t port_io_base;
81} ene_chip;
82
83/* table of supported chips + parameters */
84static ene_chip ene_chips[] = {
85 { ENE_KB932, /* chip_id */
86 0xa2, 0x02, /* hwver + ediid */
Rong Changd8889e52012-07-27 21:42:25 +080087 0x66, /* port_bios */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -070088 0x6c, 0x68, /* port_ec_{command,data} */
89 0x59, 0xf2, /* ec_reset_{cmd,data} */
90 0x59, 0xf9, /* ec_restart_{cmd,data} */
Rong Changd8889e52012-07-27 21:42:25 +080091 0x59, 0xf1, /* ec_pause_{cmd,data} */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -070092 0xf554, /* ec_status_buf */
93 0xa5, 0x00, /* ec_is_{stopping,running} masks */
Rong Changd8889e52012-07-27 21:42:25 +080094 0x33, /* ec_is_pausing mask */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -070095 0xfd60 }, /* port_io_base */
96
Rong Changd8889e52012-07-27 21:42:25 +080097 { ENE_KB94X, /* chip_id */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -070098 0xa3, 0x05, /* hwver + ediid */
Rong Changd8889e52012-07-27 21:42:25 +080099 0x66, /* port_bios */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700100 0x66, 0x68, /* port_ec_{command,data} */
101 0x7d, 0x10, /* ec_reset_{cmd,data} */
102 0x7f, 0x10, /* ec_restart_{cmd,data} */
agnescheng433ff582012-09-26 12:33:35 +0800103 0x7e, 0x10, /* ec_pause_{cmd,data} */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700104 0xf710, /* ec_status_buf */
105 0x02, 0x00, /* ec_is_{stopping,running} masks */
agnescheng433ff582012-09-26 12:33:35 +0800106 0x01, /* ec_is_pausing mask */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700107 0x0380 }, /* port_io_base */
108};
109
110/* pointer to table entry of identified chip */
111static ene_chip *found_chip;
Rong Changd8889e52012-07-27 21:42:25 +0800112/* current ec state */
113static enum ene_ec_state ec_state = EC_STATE_NORMAL;
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700114
Rong Changaaa1acf2012-06-21 19:21:18 +0800115#define REG_EC_HWVER 0xff00
116#define REG_EC_FWVER 0xff01
117#define REG_EC_EDIID 0xff24
118#define REG_8051_CTRL 0xff14
Rong Changd8889e52012-07-27 21:42:25 +0800119#define REG_EC_EXTCMD 0xff10
Rong Changaaa1acf2012-06-21 19:21:18 +0800120
Rong Changaaa1acf2012-06-21 19:21:18 +0800121#define CPU_RESET 1
122
123/* Hwardware registers */
124#define REG_SPI_DATA 0xfeab
125#define REG_SPI_COMMAND 0xfeac
126#define REG_SPI_CONFIG 0xfead
127#define CFG_CSn_FORCE_LOW (1 << 4)
128#define CFG_COMMAND_WRITE_ENABLE (1 << 3)
129#define CFG_STATUS (1 << 1)
130#define CFG_ENABLE_BUSY_STATUS_CHECK (1 << 0)
131
132/* Timeout */
133#define EC_COMMAND_TIMEOUT 4
134#define EC_RESTART_TIMEOUT 10
135#define ENE_SPI_DELAY_CYCLE 4
agnescheng433ff582012-09-26 12:33:35 +0800136#define EC_PAUSE_TIMEOUT 12
Shawn Nematbakhsh9c0cd8d2013-05-15 17:07:13 -0700137#define EC_RESET_TRIES 3
agnescheng433ff582012-09-26 12:33:35 +0800138
139#define ENE_KB94X_PAUSE_WAKEUP_PORT 0x64
Rong Changaaa1acf2012-06-21 19:21:18 +0800140
David Hendricks835b3102015-11-05 20:33:00 -0800141#define MASK_INPUT_BUFFER_FULL 2
142#define MASK_OUTPUT_BUFFER_FULL 1
Rong Changaaa1acf2012-06-21 19:21:18 +0800143
Rong Changaaa1acf2012-06-21 19:21:18 +0800144const int port_ene_bank = 1;
145const int port_ene_offset = 2;
146const int port_ene_data = 3;
147
agnescheng433ff582012-09-26 12:33:35 +0800148static struct timeval pause_begin, pause_now;
149
Rong Changaaa1acf2012-06-21 19:21:18 +0800150static void ec_command(uint8_t cmd, uint8_t data)
151{
152 struct timeval begin, now;
153
154 /* Spin wait for EC input buffer empty */
155 gettimeofday(&begin, NULL);
David Hendricks835b3102015-11-05 20:33:00 -0800156 while (INB(found_chip->port_ec_command) & MASK_INPUT_BUFFER_FULL) {
Rong Changaaa1acf2012-06-21 19:21:18 +0800157 gettimeofday(&now, NULL);
158 if ((now.tv_sec - begin.tv_sec) >= EC_COMMAND_TIMEOUT) {
159 msg_pdbg("%s: buf not empty\n", __func__);
160 return;
161 }
162 }
agnescheng433ff582012-09-26 12:33:35 +0800163
Rong Changaaa1acf2012-06-21 19:21:18 +0800164 /* Write command */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700165 OUTB(cmd, found_chip->port_ec_command);
Rong Changaaa1acf2012-06-21 19:21:18 +0800166
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700167 if (found_chip->chip_id == ENE_KB932) {
168 /* Spin wait for EC input buffer empty */
169 gettimeofday(&begin, NULL);
170 while (INB(found_chip->port_ec_command) &
David Hendricks835b3102015-11-05 20:33:00 -0800171 MASK_INPUT_BUFFER_FULL) {
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700172 gettimeofday(&now, NULL);
173 if ((now.tv_sec - begin.tv_sec) >=
174 EC_COMMAND_TIMEOUT) {
175 msg_pdbg("%s: buf not empty\n", __func__);
176 return;
177 }
Rong Changaaa1acf2012-06-21 19:21:18 +0800178 }
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700179 /* Write data */
180 OUTB(data, found_chip->port_ec_data);
Rong Changaaa1acf2012-06-21 19:21:18 +0800181 }
Rong Changaaa1acf2012-06-21 19:21:18 +0800182}
183
184static uint8_t ene_read(uint16_t addr)
185{
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700186 uint8_t bank;
187 uint8_t offset;
188 uint8_t data;
189 uint32_t port_io_base;
Rong Changaaa1acf2012-06-21 19:21:18 +0800190
191 bank = addr >> 8;
192 offset = addr & 0xff;
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700193 port_io_base = found_chip->port_io_base;
Rong Changaaa1acf2012-06-21 19:21:18 +0800194
195 OUTB(bank, port_io_base + port_ene_bank);
196 OUTB(offset, port_io_base + port_ene_offset);
197 data = INB(port_io_base + port_ene_data);
198
199 return data;
200}
201
202static void ene_write(uint16_t addr, uint8_t data)
203{
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700204 uint8_t bank;
205 uint8_t offset;
206 uint32_t port_io_base;
Rong Changaaa1acf2012-06-21 19:21:18 +0800207
208 bank = addr >> 8;
209 offset = addr & 0xff;
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700210 port_io_base = found_chip->port_io_base;
Rong Changaaa1acf2012-06-21 19:21:18 +0800211
212 OUTB(bank, port_io_base + port_ene_bank);
213 OUTB(offset, port_io_base + port_ene_offset);
214
215 OUTB(data, port_io_base + port_ene_data);
216}
217
218/**
219 * wait_cycles, wait for n LPC bus clock cycles
220 *
221 * @param n: number of LPC cycles to wait
222 * @return void
223 */
224void wait_cycles(int n)
225{
226 while (n--)
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700227 INB(found_chip->port_io_base + port_ene_bank);
Rong Changaaa1acf2012-06-21 19:21:18 +0800228}
229
Rong Changd8889e52012-07-27 21:42:25 +0800230static int is_spicmd_write(uint8_t cmd)
231{
232 switch (cmd) {
Rong Chang7797e4c2012-08-19 00:40:49 +0800233 case JEDEC_WREN:
234 /* Chip Write Enable */
235 case JEDEC_EWSR:
236 /* Write Status Enable */
Rong Changd8889e52012-07-27 21:42:25 +0800237 case JEDEC_CE_60:
238 /* Chip Erase 0x60 */
239 case JEDEC_CE_C7:
240 /* Chip Erase 0xc7 */
241 case JEDEC_BE_52:
242 /* Block Erase 0x52 */
243 case JEDEC_BE_D8:
244 /* Block Erase 0xd8 */
245 case JEDEC_BE_D7:
246 /* Block Erase 0xd7 */
247 case JEDEC_SE:
248 /* Sector Erase */
249 case JEDEC_BYTE_PROGRAM:
250 /* Write memory byte */
251 case JEDEC_AAI_WORD_PROGRAM:
252 /* Write AAI word */
253 return 1;
254 }
255 return 0;
256}
257
Rong Changaaa1acf2012-06-21 19:21:18 +0800258static void ene_spi_start(void)
259{
260 int cfg;
261
262 cfg = ene_read(REG_SPI_CONFIG);
263 cfg |= CFG_CSn_FORCE_LOW;
264 cfg |= CFG_COMMAND_WRITE_ENABLE;
265 ene_write(REG_SPI_CONFIG, cfg);
266
267 wait_cycles(ENE_SPI_DELAY_CYCLE);
268}
269
270static void ene_spi_end(void)
271{
272 int cfg;
273
274 cfg = ene_read(REG_SPI_CONFIG);
275 cfg &= ~CFG_CSn_FORCE_LOW;
276 cfg |= CFG_COMMAND_WRITE_ENABLE;
277 ene_write(REG_SPI_CONFIG, cfg);
278
279 wait_cycles(ENE_SPI_DELAY_CYCLE);
280}
281
282static int ene_spi_wait(void)
283{
284 struct timeval begin, now;
285
286 gettimeofday(&begin, NULL);
287 while(ene_read(REG_SPI_CONFIG) & CFG_STATUS) {
288 gettimeofday(&now, NULL);
289 if ((now.tv_sec - begin.tv_sec) >= EC_COMMAND_TIMEOUT) {
290 msg_pdbg("%s: spi busy\n", __func__);
291 return 1;
292 }
293 }
294 return 0;
295}
296
Rong Changd8889e52012-07-27 21:42:25 +0800297static int ene_pause_ec(void)
298{
299 struct timeval begin, now;
300
301 if (!found_chip->ec_pause_cmd)
302 return -1;
303
304 /* EC prepare pause */
305 ec_command(found_chip->ec_pause_cmd, found_chip->ec_pause_data);
306
307 gettimeofday(&begin, NULL);
308 /* Spin wait for EC ready */
309 while (ene_read(found_chip->ec_status_buf) !=
310 found_chip->ec_is_pausing) {
311 gettimeofday(&now, NULL);
312 if ((now.tv_sec - begin.tv_sec) >=
313 EC_COMMAND_TIMEOUT) {
314 msg_pdbg("%s: unable to pause ec\n", __func__);
315 return -1;
316 }
317 }
318
agnescheng433ff582012-09-26 12:33:35 +0800319
320 gettimeofday(&pause_begin, NULL);
Rong Changd8889e52012-07-27 21:42:25 +0800321 ec_state = EC_STATE_IDLE;
322 return 0;
323}
324
325static int ene_resume_ec(void)
326{
327 struct timeval begin, now;
328
agnescheng433ff582012-09-26 12:33:35 +0800329
330 if (found_chip->chip_id == ENE_KB94X)
331 OUTB(0xff, ENE_KB94X_PAUSE_WAKEUP_PORT);
332 else
333 /* Trigger 8051 interrupt to resume */
334 ene_write(REG_EC_EXTCMD, 0xff);
Rong Changd8889e52012-07-27 21:42:25 +0800335
336 gettimeofday(&begin, NULL);
337 while (ene_read(found_chip->ec_status_buf) !=
338 found_chip->ec_is_running) {
339 gettimeofday(&now, NULL);
340 if ((now.tv_sec - begin.tv_sec) >=
341 EC_COMMAND_TIMEOUT) {
342 msg_pdbg("%s: unable to resume ec\n", __func__);
343 return -1;
344 }
345 }
346
347 ec_state = EC_STATE_NORMAL;
348 return 0;
349}
350
agnescheng433ff582012-09-26 12:33:35 +0800351static int ene_pause_timeout_check(void)
352{
353 gettimeofday(&pause_now, NULL);
354 if ((pause_now.tv_sec - pause_begin.tv_sec) >=
355 EC_PAUSE_TIMEOUT) {
356 if(ene_resume_ec() == 0)
357 ene_pause_ec();
358
359 }
360 return 0;
361}
362
Rong Changd8889e52012-07-27 21:42:25 +0800363static int ene_reset_ec(void)
364{
365 uint8_t reg;
366
367 struct timeval begin, now;
368 gettimeofday(&begin, NULL);
369
370 /* EC prepare reset */
371 ec_command(found_chip->ec_reset_cmd, found_chip->ec_reset_data);
372
373 /* Spin wait for EC ready */
374 while (ene_read(found_chip->ec_status_buf) !=
375 found_chip->ec_is_stopping) {
376 gettimeofday(&now, NULL);
377 if ((now.tv_sec - begin.tv_sec) >=
378 EC_COMMAND_TIMEOUT) {
379 msg_pdbg("%s: unable to reset ec\n", __func__);
380 return -1;
381 }
382 }
383
384 /* Wait 1 second */
385 sleep(1);
386
387 /* Reset 8051 */
388 reg = ene_read(REG_8051_CTRL);
389 reg |= CPU_RESET;
390 ene_write(REG_8051_CTRL, reg);
391
392 ec_state = EC_STATE_RESET;
393 return 0;
394}
395
agnescheng433ff582012-09-26 12:33:35 +0800396static int ene_enter_flash_mode(void)
397{
398 if (ene_pause_ec())
399 return ene_reset_ec();
400 return 0;
401}
402
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700403static int ene_spi_send_command(const struct flashctx *flash,
404 unsigned int writecnt,
Rong Changaaa1acf2012-06-21 19:21:18 +0800405 unsigned int readcnt,
406 const unsigned char *writearr,
407 unsigned char *readarr)
408{
Rong Changaaa1acf2012-06-21 19:21:18 +0800409 int i;
Shawn Nematbakhsh9c0cd8d2013-05-15 17:07:13 -0700410 int tries = EC_RESET_TRIES;
Rong Changaaa1acf2012-06-21 19:21:18 +0800411
Rong Changd8889e52012-07-27 21:42:25 +0800412 if (ec_state == EC_STATE_IDLE && is_spicmd_write(writearr[0])) {
Shawn Nematbakhsh9c0cd8d2013-05-15 17:07:13 -0700413 do {
414 /* Enter reset mode if we need to write/erase */
415 if (ene_resume_ec())
416 continue;
417
418 if (!ene_reset_ec())
419 break;
420 } while (--tries > 0);
421
422 if (!tries) {
423 msg_perr("%s: EC failed reset, skipping write\n",
424 __func__);
425 ec_state = EC_STATE_IDLE;
426 return 1;
427 }
Rong Changd8889e52012-07-27 21:42:25 +0800428 }
agnescheng433ff582012-09-26 12:33:35 +0800429 else if(found_chip->chip_id == ENE_KB94X && ec_state == EC_STATE_IDLE)
430 ene_pause_timeout_check();
Rong Changd8889e52012-07-27 21:42:25 +0800431
Rong Changaaa1acf2012-06-21 19:21:18 +0800432 ene_spi_start();
433
434 for (i = 0; i < writecnt; i++) {
435 ene_write(REG_SPI_COMMAND, writearr[i]);
436 if (ene_spi_wait()) {
437 msg_pdbg("%s: write count %d\n", __func__, i);
438 return 1;
439 }
440 }
441
442 for (i = 0; i < readcnt; i++) {
443 /* Push data by clock the serial bus */
444 ene_write(REG_SPI_COMMAND, 0);
445 if (ene_spi_wait()) {
446 msg_pdbg("%s: read count %d\n", __func__, i);
447 return 1;
448 }
449 readarr[i] = ene_read(REG_SPI_DATA);
450 if (ene_spi_wait()) {
451 msg_pdbg("%s: read count %d\n", __func__, i);
452 return 1;
453 }
454 }
455
456 ene_spi_end();
457 return 0;
458}
459
David Hendricks93784b42016-08-09 17:00:38 -0700460static int ene_leave_flash_mode(void *data)
Rong Changaaa1acf2012-06-21 19:21:18 +0800461{
Rong Changd8889e52012-07-27 21:42:25 +0800462 int rv = 0;
Shawn Nematbakhshb903dfd2012-07-24 15:27:00 -0700463 uint8_t reg;
Rong Changaaa1acf2012-06-21 19:21:18 +0800464 struct timeval begin, now;
465
Rong Changd8889e52012-07-27 21:42:25 +0800466 if (ec_state == EC_STATE_RESET) {
467 reg = ene_read(REG_8051_CTRL);
468 reg &= ~CPU_RESET;
469 ene_write(REG_8051_CTRL, reg);
Rong Changaaa1acf2012-06-21 19:21:18 +0800470
Rong Changd8889e52012-07-27 21:42:25 +0800471 gettimeofday(&begin, NULL);
472 /* EC restart */
473 while (ene_read(found_chip->ec_status_buf) !=
474 found_chip->ec_is_running) {
475 gettimeofday(&now, NULL);
476 if ((now.tv_sec - begin.tv_sec) >=
477 EC_RESTART_TIMEOUT) {
478 msg_pdbg("%s: ec restart busy\n", __func__);
479 rv = 1;
480 goto exit;
481 }
Rong Changaaa1acf2012-06-21 19:21:18 +0800482 }
Rong Changd8889e52012-07-27 21:42:25 +0800483 msg_pdbg("%s: send ec restart\n", __func__);
484 ec_command(found_chip->ec_restart_cmd,
485 found_chip->ec_restart_data);
486
487 ec_state = EC_STATE_NORMAL;
488 rv = 0;
489 goto exit;
Rong Changaaa1acf2012-06-21 19:21:18 +0800490 }
491
Rong Changd8889e52012-07-27 21:42:25 +0800492 rv = ene_resume_ec();
Rong Changea1ec812012-07-21 11:41:32 +0800493
Rong Changd8889e52012-07-27 21:42:25 +0800494exit:
495 /*
496 * Trigger ec interrupt after pause/reset by sending 0x80
497 * to bios command port.
498 */
499 OUTB(0x80, found_chip->port_bios);
500 return rv;
Rong Changaaa1acf2012-06-21 19:21:18 +0800501}
502
503static const struct spi_programmer spi_programmer_ene = {
504 .type = SPI_CONTROLLER_ENE,
505 .max_data_read = 256,
506 .max_data_write = 256,
507 .command = ene_spi_send_command,
508 .multicommand = default_spi_send_multicommand,
509 .read = default_spi_read,
510 .write_256 = default_spi_write_256,
511};
512
David Hendricksac1d25c2016-08-09 17:00:58 -0700513int ene_probe_spi_flash(const char *name)
Rong Changaaa1acf2012-06-21 19:21:18 +0800514{
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700515 uint8_t hwver, ediid, i;
David Hendricks2b56e472016-10-21 19:05:21 -0700516 int ret = 0;
517 char *p = NULL;
Rong Changaaa1acf2012-06-21 19:21:18 +0800518
David Hendricksba0827a2013-05-03 20:25:40 -0700519 if (alias && alias->type != ALIAS_EC)
520 return 1;
521
Rong Changaaa1acf2012-06-21 19:21:18 +0800522 msg_pdbg("%s\n", __func__);
Rong Changaaa1acf2012-06-21 19:21:18 +0800523
David Hendricks2b56e472016-10-21 19:05:21 -0700524 p = extract_programmer_param("type");
525 if (p && strcmp(p, "ec")) {
526 msg_pdbg("ene_lpc only supports \"ec\" type devices\n");
527 ret = 1;
528 goto ene_probe_spi_flash_exit;
529 }
530
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700531 for (i = 0; i < ENE_LAST; ++i) {
532 found_chip = &ene_chips[i];
533
534 hwver = ene_read(REG_EC_HWVER);
535 ediid = ene_read(REG_EC_EDIID);
536
537 if(hwver == ene_chips[i].hwver &&
538 ediid == ene_chips[i].ediid) {
539 break;
540 }
541 }
542
543 if (i == ENE_LAST) {
544 msg_pdbg("ENE EC not found (probe failed)\n");
David Hendricks2b56e472016-10-21 19:05:21 -0700545 ret = 1;
546 goto ene_probe_spi_flash_exit;
Rong Changaaa1acf2012-06-21 19:21:18 +0800547 }
548
549 /* TODO: probe the EC stop protocol
550 *
551 * Compal - ec_command(0x41, 0xa1) returns 43 4f 4d 50 41 4c 9c
552 */
553
554
David Hendricks2b56e472016-10-21 19:05:21 -0700555 if (register_shutdown(ene_leave_flash_mode, NULL)) {
556 ret = 1;
557 goto ene_probe_spi_flash_exit;
558 }
Rong Changaaa1acf2012-06-21 19:21:18 +0800559
560 ene_enter_flash_mode();
561
David Hendricksac1d25c2016-08-09 17:00:58 -0700562 buses_supported |= BUS_LPC;
Rong Changaaa1acf2012-06-21 19:21:18 +0800563 register_spi_programmer(&spi_programmer_ene);
564 msg_pdbg("%s: successfully initialized ene\n", __func__);
David Hendricks2b56e472016-10-21 19:05:21 -0700565ene_probe_spi_flash_exit:
566 free(p);
567 return ret;
Rong Changaaa1acf2012-06-21 19:21:18 +0800568}
569
570#endif /* __i386__ || __x86_64__ */
571