blob: 46f1783299e0392fdf06e0e6ed0be4b5a972f3a4 [file] [log] [blame]
Victor Ding436b4152020-08-19 22:48:19 +10001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2012-2020, Google Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following disclaimer
15 * in the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Google Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Alternatively, this software may be distributed under the terms of the
34 * GNU General Public License ("GPL") version 2 as published by the Free
35 * Software Foundation.
36 */
37
38#if defined(__i386__) || defined(__x86_64__)
39#include <inttypes.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43#include <sys/time.h>
44
45#include "chipdrivers.h"
46#include "flash.h"
47#include "programmer.h"
48#include "hwaccess.h"
49#include "spi.h"
50
51/* MCU registers */
52#define REG_EC_HWVER 0xff00
53#define REG_EC_FWVER 0xff01
54#define REG_EC_EDIID 0xff24
55#define REG_8051_CTRL 0xff14
56#define REG_EC_EXTCMD 0xff10
57
58#define CPU_RESET 1
59
60/* MCU SPI peripheral registers */
61#define REG_SPI_DATA 0xfeab
62#define REG_SPI_COMMAND 0xfeac
63#define REG_SPI_CONFIG 0xfead
64
65#define CFG_CSn_FORCE_LOW (1 << 4)
66#define CFG_COMMAND_WRITE_ENABLE (1 << 3)
67#define CFG_STATUS (1 << 1)
68#define CFG_ENABLE_BUSY_STATUS_CHECK (1 << 0)
69
70/* Timeout */
71#define EC_COMMAND_TIMEOUT 4
72#define EC_RESTART_TIMEOUT 10
73#define ENE_SPI_DELAY_CYCLE 4
74#define EC_PAUSE_TIMEOUT 12
75#define EC_RESET_TRIES 3
76
77#define ENE_KB94X_PAUSE_WAKEUP_PORT 0x64
78
79#define MASK_INPUT_BUFFER_FULL 2
80#define MASK_OUTPUT_BUFFER_FULL 1
81
82const int port_ene_bank = 1;
83const int port_ene_offset = 2;
84const int port_ene_data = 3;
85
86/* Supported ENE ECs, ENE_LAST should always be LAST member */
87enum ene_chip_id {
88 ENE_KB932 = 0,
89 ENE_KB94X,
90 ENE_LAST
91};
92
93/* EC state */
94enum ene_ec_state {
95 EC_STATE_NORMAL,
96 EC_STATE_IDLE,
97 EC_STATE_RESET,
98 EC_STATE_UNKNOWN
99};
100
101/* chip-specific parameters */
102typedef struct {
103 enum ene_chip_id chip_id;
104 uint8_t hwver;
105 uint8_t ediid;
106 uint32_t port_bios;
107 uint32_t port_ec_command;
108 uint32_t port_ec_data;
109 uint8_t ec_reset_cmd;
110 uint8_t ec_reset_data;
111 uint8_t ec_restart_cmd;
112 uint8_t ec_restart_data;
113 uint8_t ec_pause_cmd;
114 uint8_t ec_pause_data;
115 uint16_t ec_status_buf;
116 uint8_t ec_is_stopping;
117 uint8_t ec_is_running;
118 uint8_t ec_is_pausing;
119 uint32_t port_io_base;
120} ene_chip_t;
121
122typedef struct
123{
124 /* pointer to table entry of identified chip */
125 ene_chip_t *chip;
126 /* current ec state */
127 enum ene_ec_state ec_state;
128 struct timeval pause_begin;
129} ene_lpc_data_t;
130
131/* table of supported chips + parameters */
132static ene_chip_t ene_chips[] = {
133 {
134 ENE_KB932, /* chip_id */
135 0xa2, 0x02, /* hwver + ediid */
136 0x66, /* port_bios */
137 0x6c, 0x68, /* port_ec_{command,data} */
138 0x59, 0xf2, /* ec_reset_{cmd,data} */
139 0x59, 0xf9, /* ec_restart_{cmd,data} */
140 0x59, 0xf1, /* ec_pause_{cmd,data} */
141 0xf554, /* ec_status_buf */
142 0xa5, 0x00, /* ec_is_{stopping,running} masks */
143 0x33, /* ec_is_pausing mask */
144 0xfd60 /* port_io_base */
145 },
146 {
147 ENE_KB94X, /* chip_id */
148 0xa3, 0x05, /* hwver + ediid */
149 0x66, /* port_bios */
150 0x66, 0x68, /* port_ec_{command,data} */
151 0x7d, 0x10, /* ec_reset_{cmd,data} */
152 0x7f, 0x10, /* ec_restart_{cmd,data} */
153 0x7e, 0x10, /* ec_pause_{cmd,data} */
154 0xf710, /* ec_status_buf */
155 0x02, 0x00, /* ec_is_{stopping,running} masks */
156 0x01, /* ec_is_pausing mask */
157 0x0380 /* port_io_base */
158 }
159};
160
161static void ec_command(const ene_chip_t *chip, uint8_t cmd, uint8_t data)
162{
163 struct timeval begin, now;
164
165 /* Spin wait for EC input buffer empty */
166 gettimeofday(&begin, NULL);
167 while (INB(chip->port_ec_command) & MASK_INPUT_BUFFER_FULL) {
168 gettimeofday(&now, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200169 if (now.tv_sec - begin.tv_sec >= EC_COMMAND_TIMEOUT) {
Victor Ding436b4152020-08-19 22:48:19 +1000170 msg_pdbg("%s: buf not empty\n", __func__);
171 return;
172 }
173 }
174
175 /* Write command */
176 OUTB(cmd, chip->port_ec_command);
177
178 if (chip->chip_id == ENE_KB932) {
179 /* Spin wait for EC input buffer empty */
180 gettimeofday(&begin, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200181 while (INB(chip->port_ec_command) & MASK_INPUT_BUFFER_FULL) {
Victor Ding436b4152020-08-19 22:48:19 +1000182 gettimeofday(&now, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200183 if (now.tv_sec - begin.tv_sec >= EC_COMMAND_TIMEOUT) {
Victor Ding436b4152020-08-19 22:48:19 +1000184 msg_pdbg("%s: buf not empty\n", __func__);
185 return;
186 }
187 }
188 /* Write data */
189 OUTB(data, chip->port_ec_data);
190 }
191}
192
193static uint8_t ene_read(const ene_chip_t *chip, uint16_t addr)
194{
195 uint8_t bank;
196 uint8_t offset;
197 uint8_t data;
198 uint32_t port_io_base;
199
200 bank = addr >> 8;
201 offset = addr & 0xff;
202 port_io_base = chip->port_io_base;
203
204 OUTB(bank, port_io_base + port_ene_bank);
205 OUTB(offset, port_io_base + port_ene_offset);
206 data = INB(port_io_base + port_ene_data);
207
208 return data;
209}
210
211static void ene_write(const ene_chip_t *chip, uint16_t addr, uint8_t data)
212{
213 uint8_t bank;
214 uint8_t offset;
215 uint32_t port_io_base;
216
217 bank = addr >> 8;
218 offset = addr & 0xff;
219 port_io_base = chip->port_io_base;
220
221 OUTB(bank, port_io_base + port_ene_bank);
222 OUTB(offset, port_io_base + port_ene_offset);
223
224 OUTB(data, port_io_base + port_ene_data);
225}
226
227/**
228 * wait_cycles, wait for n LPC bus clock cycles
229 *
230 * @param n: number of LPC cycles to wait
231 * @return void
232 */
233static void wait_cycles(const ene_chip_t *chip,int n)
234{
235 while (n--)
236 INB(chip->port_io_base + port_ene_bank);
237}
238
239static int is_spicmd_write(uint8_t cmd)
240{
241 switch (cmd) {
242 case JEDEC_WREN:
243 /* Chip Write Enable */
244 case JEDEC_EWSR:
245 /* Write Status Enable */
246 case JEDEC_CE_60:
247 /* Chip Erase 0x60 */
248 case JEDEC_CE_C7:
249 /* Chip Erase 0xc7 */
250 case JEDEC_BE_52:
251 /* Block Erase 0x52 */
252 case JEDEC_BE_D8:
253 /* Block Erase 0xd8 */
254 case JEDEC_BE_D7:
255 /* Block Erase 0xd7 */
256 case JEDEC_SE:
257 /* Sector Erase */
258 case JEDEC_BYTE_PROGRAM:
259 /* Write memory byte */
260 case JEDEC_AAI_WORD_PROGRAM:
261 /* Write AAI word */
262 return 1;
263 }
264 return 0;
265}
266
267static void ene_spi_start(const ene_chip_t *chip)
268{
269 int cfg;
270
271 cfg = ene_read(chip, REG_SPI_CONFIG);
272 cfg |= CFG_CSn_FORCE_LOW;
273 cfg |= CFG_COMMAND_WRITE_ENABLE;
274 ene_write(chip, REG_SPI_CONFIG, cfg);
275
276 wait_cycles(chip, ENE_SPI_DELAY_CYCLE);
277}
278
279static void ene_spi_end(const ene_chip_t *chip)
280{
281 int cfg;
282
283 cfg = ene_read(chip, REG_SPI_CONFIG);
284 cfg &= ~CFG_CSn_FORCE_LOW;
285 cfg |= CFG_COMMAND_WRITE_ENABLE;
286 ene_write(chip, REG_SPI_CONFIG, cfg);
287
288 wait_cycles(chip, ENE_SPI_DELAY_CYCLE);
289}
290
291static int ene_spi_wait(const ene_chip_t *chip)
292{
293 struct timeval begin, now;
294
295 gettimeofday(&begin, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200296 while (ene_read(chip, REG_SPI_CONFIG) & CFG_STATUS) {
Victor Ding436b4152020-08-19 22:48:19 +1000297 gettimeofday(&now, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200298 if (now.tv_sec - begin.tv_sec >= EC_COMMAND_TIMEOUT) {
Victor Ding436b4152020-08-19 22:48:19 +1000299 msg_pdbg("%s: spi busy\n", __func__);
300 return 1;
301 }
302 }
303 return 0;
304}
305
306static int ene_pause_ec(ene_lpc_data_t *ctx_data)
307{
308 struct timeval begin, now;
309 const ene_chip_t *chip = ctx_data->chip;
310
311 if (!chip->ec_pause_cmd)
312 return -1;
313
314 /* EC prepare pause */
315 ec_command(chip, chip->ec_pause_cmd, chip->ec_pause_data);
316
317 gettimeofday(&begin, NULL);
318 /* Spin wait for EC ready */
Angel Ponsb4a63e92021-04-16 11:16:52 +0200319 while (ene_read(chip, chip->ec_status_buf) != chip->ec_is_pausing) {
Victor Ding436b4152020-08-19 22:48:19 +1000320 gettimeofday(&now, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200321 if (now.tv_sec - begin.tv_sec >= EC_COMMAND_TIMEOUT) {
Victor Ding436b4152020-08-19 22:48:19 +1000322 msg_pdbg("%s: unable to pause ec\n", __func__);
323 return -1;
324 }
325 }
326
Victor Ding436b4152020-08-19 22:48:19 +1000327 gettimeofday(&ctx_data->pause_begin, NULL);
328 ctx_data->ec_state = EC_STATE_IDLE;
329 return 0;
330}
331
332static int ene_resume_ec(ene_lpc_data_t *ctx_data)
333{
334 struct timeval begin, now;
335 const ene_chip_t *chip = ctx_data->chip;
336
337 if (chip->chip_id == ENE_KB94X)
338 OUTB(0xff, ENE_KB94X_PAUSE_WAKEUP_PORT);
339 else
340 /* Trigger 8051 interrupt to resume */
341 ene_write(chip, REG_EC_EXTCMD, 0xff);
342
343 gettimeofday(&begin, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200344 while (ene_read(chip, chip->ec_status_buf) != chip->ec_is_running) {
Victor Ding436b4152020-08-19 22:48:19 +1000345 gettimeofday(&now, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200346 if (now.tv_sec - begin.tv_sec >= EC_COMMAND_TIMEOUT) {
Victor Ding436b4152020-08-19 22:48:19 +1000347 msg_pdbg("%s: unable to resume ec\n", __func__);
348 return -1;
349 }
350 }
351
352 ctx_data->ec_state = EC_STATE_NORMAL;
353 return 0;
354}
355
356static int ene_pause_timeout_check(ene_lpc_data_t *ctx_data)
357{
358 struct timeval pause_now;
359 gettimeofday(&pause_now, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200360 if (pause_now.tv_sec - ctx_data->pause_begin.tv_sec >= EC_PAUSE_TIMEOUT) {
361 if (ene_resume_ec(ctx_data) == 0)
Victor Ding436b4152020-08-19 22:48:19 +1000362 ene_pause_ec(ctx_data);
Victor Ding436b4152020-08-19 22:48:19 +1000363 }
364 return 0;
365}
366
367static int ene_reset_ec(ene_lpc_data_t *ctx_data)
368{
369 uint8_t reg;
370 struct timeval begin, now;
371 const ene_chip_t *chip = ctx_data->chip;
372
373 gettimeofday(&begin, NULL);
374
375 /* EC prepare reset */
376 ec_command(chip, chip->ec_reset_cmd, chip->ec_reset_data);
377
378 /* Spin wait for EC ready */
Angel Ponsb4a63e92021-04-16 11:16:52 +0200379 while (ene_read(chip, chip->ec_status_buf) != chip->ec_is_stopping) {
Victor Ding436b4152020-08-19 22:48:19 +1000380 gettimeofday(&now, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200381 if (now.tv_sec - begin.tv_sec >= EC_COMMAND_TIMEOUT) {
Victor Ding436b4152020-08-19 22:48:19 +1000382 msg_pdbg("%s: unable to reset ec\n", __func__);
383 return -1;
384 }
385 }
386
387 /* Wait 1 second */
388 sleep(1);
389
390 /* Reset 8051 */
391 reg = ene_read(chip, REG_8051_CTRL);
392 reg |= CPU_RESET;
393 ene_write(chip, REG_8051_CTRL, reg);
394
395 ctx_data->ec_state = EC_STATE_RESET;
396 return 0;
397}
398
399static int ene_enter_flash_mode(ene_lpc_data_t *ctx_data)
400{
401 if (ene_pause_ec(ctx_data))
402 return ene_reset_ec(ctx_data);
403 return 0;
404}
405
406static int ene_spi_send_command(const struct flashctx *flash,
407 unsigned int writecnt,
408 unsigned int readcnt,
409 const unsigned char *writearr,
410 unsigned char *readarr)
411{
412 unsigned int i;
413 int tries = EC_RESET_TRIES;
414 ene_lpc_data_t *ctx_data = (ene_lpc_data_t *)flash->mst->spi.data;
415 const ene_chip_t *chip = ctx_data->chip;
416
417 if (ctx_data->ec_state == EC_STATE_IDLE && is_spicmd_write(writearr[0])) {
418 do {
419 /* Enter reset mode if we need to write/erase */
420 if (ene_resume_ec(ctx_data))
421 continue;
422
423 if (!ene_reset_ec(ctx_data))
424 break;
425 } while (--tries > 0);
426
427 if (!tries) {
428 msg_perr("%s: EC failed reset, skipping write\n", __func__);
429 ctx_data->ec_state = EC_STATE_IDLE;
430 return 1;
431 }
Angel Ponsb4a63e92021-04-16 11:16:52 +0200432 } else if (chip->chip_id == ENE_KB94X && ctx_data->ec_state == EC_STATE_IDLE) {
Victor Ding436b4152020-08-19 22:48:19 +1000433 ene_pause_timeout_check(ctx_data);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200434 }
Victor Ding436b4152020-08-19 22:48:19 +1000435
436 ene_spi_start(chip);
437
438 for (i = 0; i < writecnt; i++) {
439 ene_write(chip, REG_SPI_COMMAND, writearr[i]);
440 if (ene_spi_wait(chip)) {
441 msg_pdbg("%s: write count %d\n", __func__, i);
442 return 1;
443 }
444 }
445
446 for (i = 0; i < readcnt; i++) {
447 /* Push data by clock the serial bus */
448 ene_write(chip, REG_SPI_COMMAND, 0);
449 if (ene_spi_wait(chip)) {
450 msg_pdbg("%s: read count %d\n", __func__, i);
451 return 1;
452 }
453 readarr[i] = ene_read(chip, REG_SPI_DATA);
454 if (ene_spi_wait(chip)) {
455 msg_pdbg("%s: read count %d\n", __func__, i);
456 return 1;
457 }
458 }
459
460 ene_spi_end(chip);
461 return 0;
462}
463
464static int ene_leave_flash_mode(void *data)
465{
466 ene_lpc_data_t *ctx_data = (ene_lpc_data_t *)data;
467 const ene_chip_t *chip = ctx_data->chip;
468 int rv = 0;
469 uint8_t reg;
470 struct timeval begin, now;
471
472 if (ctx_data->ec_state == EC_STATE_RESET) {
473 reg = ene_read(chip, REG_8051_CTRL);
474 reg &= ~CPU_RESET;
475 ene_write(chip, REG_8051_CTRL, reg);
476
477 gettimeofday(&begin, NULL);
478 /* EC restart */
Angel Ponsb4a63e92021-04-16 11:16:52 +0200479 while (ene_read(chip, chip->ec_status_buf) != chip->ec_is_running) {
Victor Ding436b4152020-08-19 22:48:19 +1000480 gettimeofday(&now, NULL);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200481 if (now.tv_sec - begin.tv_sec >= EC_RESTART_TIMEOUT) {
Victor Ding436b4152020-08-19 22:48:19 +1000482 msg_pdbg("%s: ec restart busy\n", __func__);
483 rv = 1;
484 goto exit;
485 }
486 }
487 msg_pdbg("%s: send ec restart\n", __func__);
Angel Ponsb4a63e92021-04-16 11:16:52 +0200488 ec_command(chip, chip->ec_restart_cmd, chip->ec_restart_data);
Victor Ding436b4152020-08-19 22:48:19 +1000489
490 ctx_data->ec_state = EC_STATE_NORMAL;
491 rv = 0;
492 goto exit;
493 }
494
495 rv = ene_resume_ec(ctx_data);
496
497exit:
498 /*
499 * Trigger ec interrupt after pause/reset by sending 0x80
500 * to bios command port.
501 */
502 OUTB(0x80, chip->port_bios);
503 free(data);
504 return rv;
505}
506
507static struct spi_master spi_master_ene = {
508 .max_data_read = 256,
509 .max_data_write = 256,
510 .command = ene_spi_send_command,
511 .multicommand = default_spi_send_multicommand,
512 .read = default_spi_read,
513 .write_256 = default_spi_write_256,
514};
515
Anastasia Klimchuk04fff282021-04-28 10:08:15 +1000516static int check_params(void)
517{
518 int ret = 0;
519 char *const p = extract_programmer_param("type");
520 if (p && strcmp(p, "ec")) {
521 msg_pdbg("ene_lpc only supports \"ec\" type devices\n");
522 ret = 1;
523 }
524
525 free(p);
526 return ret;
527}
528
Victor Ding436b4152020-08-19 22:48:19 +1000529int ene_lpc_init()
530{
531 uint8_t hwver, ediid, i;
Victor Ding436b4152020-08-19 22:48:19 +1000532 ene_lpc_data_t *ctx_data = NULL;
533
534 msg_pdbg("%s\n", __func__);
535
536 ctx_data = calloc(1, sizeof(ene_lpc_data_t));
537 if (!ctx_data) {
538 msg_perr("Unable to allocate space for extra context data.\n");
539 return 1;
540 }
541 ctx_data->ec_state = EC_STATE_NORMAL;
542
Anastasia Klimchuk4cc73632021-04-27 11:36:10 +1000543 if (check_params())
544 goto init_err_exit;
Victor Ding436b4152020-08-19 22:48:19 +1000545
546 for (i = 0; i < ENE_LAST; ++i) {
547 ctx_data->chip = &ene_chips[i];
548
549 hwver = ene_read(ctx_data->chip, REG_EC_HWVER);
550 ediid = ene_read(ctx_data->chip, REG_EC_EDIID);
551
552 if(hwver == ene_chips[i].hwver &&
553 ediid == ene_chips[i].ediid) {
554 break;
555 }
556 }
557
558 if (i == ENE_LAST) {
559 msg_pdbg("ENE EC not found (probe failed)\n");
Anastasia Klimchuk4cc73632021-04-27 11:36:10 +1000560 goto init_err_exit;
Victor Ding436b4152020-08-19 22:48:19 +1000561 }
562
563 /* TODO: probe the EC stop protocol
564 *
565 * Compal - ec_command(0x41, 0xa1) returns 43 4f 4d 50 41 4c 9c
566 */
567
Anastasia Klimchukfbf34792021-04-16 14:54:41 +1000568 ene_enter_flash_mode(ctx_data);
569
570 internal_buses_supported |= BUS_LPC;
571 spi_master_ene.data = ctx_data;
Victor Ding436b4152020-08-19 22:48:19 +1000572
Anastasia Klimchuk4cc73632021-04-27 11:36:10 +1000573 if (register_shutdown(ene_leave_flash_mode, ctx_data))
574 goto init_err_cleanup_exit;
Nico Huber7e496852021-05-11 17:38:14 +0200575 register_spi_master(&spi_master_ene, NULL);
Victor Ding436b4152020-08-19 22:48:19 +1000576 msg_pdbg("%s: successfully initialized ene\n", __func__);
577
Anastasia Klimchuk4cc73632021-04-27 11:36:10 +1000578 return 0;
579
580init_err_cleanup_exit:
581 ene_leave_flash_mode(ctx_data);
582 return 1;
583
584init_err_exit:
585 free(ctx_data);
586 return 1;
Victor Ding436b4152020-08-19 22:48:19 +1000587}
588
589#endif /* __i386__ || __x86_64__ */