blob: 09c1b6bdc2e0bf3436b4a108fbd5987f6c5ef5f2 [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
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -070046/* Supported ENE ECs, ENE_LAST should always be LAST member */
47enum ene_chip_id {
48 ENE_KB932 = 0,
49 ENE_KB94X,
50 ENE_LAST
51};
52
53/* chip-specific parameters */
54typedef struct {
55 enum ene_chip_id chip_id;
56 uint8_t hwver;
57 uint8_t ediid;
58 uint32_t port_ec_command;
59 uint32_t port_ec_data;
60 uint8_t ec_reset_cmd;
61 uint8_t ec_reset_data;
62 uint8_t ec_restart_cmd;
63 uint8_t ec_restart_data;
64 uint16_t ec_status_buf;
65 uint8_t ec_is_stopping;
66 uint8_t ec_is_running;
67 uint32_t port_io_base;
68} ene_chip;
69
70/* table of supported chips + parameters */
71static ene_chip ene_chips[] = {
72 { ENE_KB932, /* chip_id */
73 0xa2, 0x02, /* hwver + ediid */
74 0x6c, 0x68, /* port_ec_{command,data} */
75 0x59, 0xf2, /* ec_reset_{cmd,data} */
76 0x59, 0xf9, /* ec_restart_{cmd,data} */
77 0xf554, /* ec_status_buf */
78 0xa5, 0x00, /* ec_is_{stopping,running} masks */
79 0xfd60 }, /* port_io_base */
80
81 { ENE_KB932, /* chip_id */
82 0xa3, 0x05, /* hwver + ediid */
83 0x66, 0x68, /* port_ec_{command,data} */
84 0x7d, 0x10, /* ec_reset_{cmd,data} */
85 0x7f, 0x10, /* ec_restart_{cmd,data} */
86 0xf710, /* ec_status_buf */
87 0x02, 0x00, /* ec_is_{stopping,running} masks */
88 0x0380 }, /* port_io_base */
89};
90
91/* pointer to table entry of identified chip */
92static ene_chip *found_chip;
93
Rong Changaaa1acf2012-06-21 19:21:18 +080094#define REG_EC_HWVER 0xff00
95#define REG_EC_FWVER 0xff01
96#define REG_EC_EDIID 0xff24
97#define REG_8051_CTRL 0xff14
98
Rong Changaaa1acf2012-06-21 19:21:18 +080099#define CPU_RESET 1
100
101/* Hwardware registers */
102#define REG_SPI_DATA 0xfeab
103#define REG_SPI_COMMAND 0xfeac
104#define REG_SPI_CONFIG 0xfead
105#define CFG_CSn_FORCE_LOW (1 << 4)
106#define CFG_COMMAND_WRITE_ENABLE (1 << 3)
107#define CFG_STATUS (1 << 1)
108#define CFG_ENABLE_BUSY_STATUS_CHECK (1 << 0)
109
110/* Timeout */
111#define EC_COMMAND_TIMEOUT 4
112#define EC_RESTART_TIMEOUT 10
113#define ENE_SPI_DELAY_CYCLE 4
114
Rong Changaaa1acf2012-06-21 19:21:18 +0800115static const uint8_t mask_input_buffer_full = 2;
116static const uint8_t mask_output_buffer_full = 1;
117
Rong Changaaa1acf2012-06-21 19:21:18 +0800118const int port_ene_bank = 1;
119const int port_ene_offset = 2;
120const int port_ene_data = 3;
121
122static void ec_command(uint8_t cmd, uint8_t data)
123{
124 struct timeval begin, now;
125
126 /* Spin wait for EC input buffer empty */
127 gettimeofday(&begin, NULL);
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700128 while (INB(found_chip->port_ec_command) & mask_input_buffer_full) {
Rong Changaaa1acf2012-06-21 19:21:18 +0800129 gettimeofday(&now, NULL);
130 if ((now.tv_sec - begin.tv_sec) >= EC_COMMAND_TIMEOUT) {
131 msg_pdbg("%s: buf not empty\n", __func__);
132 return;
133 }
134 }
135 /* Write command */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700136 OUTB(cmd, found_chip->port_ec_command);
Rong Changaaa1acf2012-06-21 19:21:18 +0800137
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700138 if (found_chip->chip_id == ENE_KB932) {
139 /* Spin wait for EC input buffer empty */
140 gettimeofday(&begin, NULL);
141 while (INB(found_chip->port_ec_command) &
142 mask_input_buffer_full) {
143 gettimeofday(&now, NULL);
144 if ((now.tv_sec - begin.tv_sec) >=
145 EC_COMMAND_TIMEOUT) {
146 msg_pdbg("%s: buf not empty\n", __func__);
147 return;
148 }
Rong Changaaa1acf2012-06-21 19:21:18 +0800149 }
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700150 /* Write data */
151 OUTB(data, found_chip->port_ec_data);
Rong Changaaa1acf2012-06-21 19:21:18 +0800152 }
Rong Changaaa1acf2012-06-21 19:21:18 +0800153}
154
155static uint8_t ene_read(uint16_t addr)
156{
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700157 uint8_t bank;
158 uint8_t offset;
159 uint8_t data;
160 uint32_t port_io_base;
Rong Changaaa1acf2012-06-21 19:21:18 +0800161
162 bank = addr >> 8;
163 offset = addr & 0xff;
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700164 port_io_base = found_chip->port_io_base;
Rong Changaaa1acf2012-06-21 19:21:18 +0800165
166 OUTB(bank, port_io_base + port_ene_bank);
167 OUTB(offset, port_io_base + port_ene_offset);
168 data = INB(port_io_base + port_ene_data);
169
170 return data;
171}
172
173static void ene_write(uint16_t addr, uint8_t data)
174{
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700175 uint8_t bank;
176 uint8_t offset;
177 uint32_t port_io_base;
Rong Changaaa1acf2012-06-21 19:21:18 +0800178
179 bank = addr >> 8;
180 offset = addr & 0xff;
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700181 port_io_base = found_chip->port_io_base;
Rong Changaaa1acf2012-06-21 19:21:18 +0800182
183 OUTB(bank, port_io_base + port_ene_bank);
184 OUTB(offset, port_io_base + port_ene_offset);
185
186 OUTB(data, port_io_base + port_ene_data);
187}
188
189/**
190 * wait_cycles, wait for n LPC bus clock cycles
191 *
192 * @param n: number of LPC cycles to wait
193 * @return void
194 */
195void wait_cycles(int n)
196{
197 while (n--)
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700198 INB(found_chip->port_io_base + port_ene_bank);
Rong Changaaa1acf2012-06-21 19:21:18 +0800199}
200
201static void ene_spi_start(void)
202{
203 int cfg;
204
205 cfg = ene_read(REG_SPI_CONFIG);
206 cfg |= CFG_CSn_FORCE_LOW;
207 cfg |= CFG_COMMAND_WRITE_ENABLE;
208 ene_write(REG_SPI_CONFIG, cfg);
209
210 wait_cycles(ENE_SPI_DELAY_CYCLE);
211}
212
213static void ene_spi_end(void)
214{
215 int cfg;
216
217 cfg = ene_read(REG_SPI_CONFIG);
218 cfg &= ~CFG_CSn_FORCE_LOW;
219 cfg |= CFG_COMMAND_WRITE_ENABLE;
220 ene_write(REG_SPI_CONFIG, cfg);
221
222 wait_cycles(ENE_SPI_DELAY_CYCLE);
223}
224
225static int ene_spi_wait(void)
226{
227 struct timeval begin, now;
228
229 gettimeofday(&begin, NULL);
230 while(ene_read(REG_SPI_CONFIG) & CFG_STATUS) {
231 gettimeofday(&now, NULL);
232 if ((now.tv_sec - begin.tv_sec) >= EC_COMMAND_TIMEOUT) {
233 msg_pdbg("%s: spi busy\n", __func__);
234 return 1;
235 }
236 }
237 return 0;
238}
239
240static int ene_spi_send_command(unsigned int writecnt,
241 unsigned int readcnt,
242 const unsigned char *writearr,
243 unsigned char *readarr)
244{
Rong Changaaa1acf2012-06-21 19:21:18 +0800245 int i;
246
247 ene_spi_start();
248
249 for (i = 0; i < writecnt; i++) {
250 ene_write(REG_SPI_COMMAND, writearr[i]);
251 if (ene_spi_wait()) {
252 msg_pdbg("%s: write count %d\n", __func__, i);
253 return 1;
254 }
255 }
256
257 for (i = 0; i < readcnt; i++) {
258 /* Push data by clock the serial bus */
259 ene_write(REG_SPI_COMMAND, 0);
260 if (ene_spi_wait()) {
261 msg_pdbg("%s: read count %d\n", __func__, i);
262 return 1;
263 }
264 readarr[i] = ene_read(REG_SPI_DATA);
265 if (ene_spi_wait()) {
266 msg_pdbg("%s: read count %d\n", __func__, i);
267 return 1;
268 }
269 }
270
271 ene_spi_end();
272 return 0;
273}
274
275static int ene_enter_flash_mode(void)
276{
Shawn Nematbakhshb903dfd2012-07-24 15:27:00 -0700277 uint8_t reg;
Rong Changaaa1acf2012-06-21 19:21:18 +0800278
279 struct timeval begin, now;
280 gettimeofday(&begin, NULL);
281
282 /* EC prepare reset */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700283 ec_command(found_chip->ec_reset_cmd, found_chip->ec_reset_data);
Rong Changaaa1acf2012-06-21 19:21:18 +0800284
285 /* Spin wait for EC ready */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700286 if (found_chip->chip_id == ENE_KB932) {
287 while (ene_read(found_chip->ec_status_buf) !=
288 found_chip->ec_is_running) {
289 gettimeofday(&now, NULL);
290 if ((now.tv_sec - begin.tv_sec) >=
291 EC_COMMAND_TIMEOUT) {
292 msg_pdbg("%s: ec reset busy\n", __func__);
293 return -1;
294 }
295 }
296 }
297 else {
298 while (ene_read(found_chip->ec_status_buf) !=
299 found_chip->ec_is_stopping) {
300 gettimeofday(&now, NULL);
301 if ((now.tv_sec - begin.tv_sec) >=
302 EC_COMMAND_TIMEOUT) {
303 msg_pdbg("%s: ec reset busy\n", __func__);
304 return -1;
305 }
Rong Changaaa1acf2012-06-21 19:21:18 +0800306 }
307 }
308
309 /* Wait 1 second */
310 sleep(1);
311
312 /* Reset 8051 */
313 reg = ene_read(REG_8051_CTRL);
314 reg |= CPU_RESET;
315 ene_write(REG_8051_CTRL, reg);
316
317 return 0;
318}
319
320static int ene_leave_flash_mode(void *data)
321{
Shawn Nematbakhshb903dfd2012-07-24 15:27:00 -0700322 uint8_t reg;
Rong Changaaa1acf2012-06-21 19:21:18 +0800323 struct timeval begin, now;
324
325 reg = ene_read(REG_8051_CTRL);
326 reg &= ~CPU_RESET;
327 ene_write(REG_8051_CTRL, reg);
328
329 gettimeofday(&begin, NULL);
330 /* EC restart */
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700331 while (ene_read(found_chip->ec_status_buf) !=
332 found_chip->ec_is_running) {
Rong Changaaa1acf2012-06-21 19:21:18 +0800333 gettimeofday(&now, NULL);
334 if ((now.tv_sec - begin.tv_sec) >= EC_RESTART_TIMEOUT) {
335 msg_pdbg("%s: ec restart busy\n", __func__);
336 return 1;
337 }
338 }
339
340 msg_pdbg("%s: send ec restart\n", __func__);
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700341 ec_command(found_chip->ec_restart_cmd, found_chip->ec_restart_data);
Rong Changea1ec812012-07-21 11:41:32 +0800342
Rong Changaaa1acf2012-06-21 19:21:18 +0800343 return 0;
344}
345
346static const struct spi_programmer spi_programmer_ene = {
347 .type = SPI_CONTROLLER_ENE,
348 .max_data_read = 256,
349 .max_data_write = 256,
350 .command = ene_spi_send_command,
351 .multicommand = default_spi_send_multicommand,
352 .read = default_spi_read,
353 .write_256 = default_spi_write_256,
354};
355
356int ene_probe_spi_flash(const char *name)
357{
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700358 uint8_t hwver, ediid, i;
Rong Changaaa1acf2012-06-21 19:21:18 +0800359
360 msg_pdbg("%s\n", __func__);
Rong Changaaa1acf2012-06-21 19:21:18 +0800361
Shawn Nematbakhsh36046f52012-07-26 09:42:36 -0700362 for (i = 0; i < ENE_LAST; ++i) {
363 found_chip = &ene_chips[i];
364
365 hwver = ene_read(REG_EC_HWVER);
366 ediid = ene_read(REG_EC_EDIID);
367
368 if(hwver == ene_chips[i].hwver &&
369 ediid == ene_chips[i].ediid) {
370 break;
371 }
372 }
373
374 if (i == ENE_LAST) {
375 msg_pdbg("ENE EC not found (probe failed)\n");
Rong Changaaa1acf2012-06-21 19:21:18 +0800376 return 0;
377 }
378
379 /* TODO: probe the EC stop protocol
380 *
381 * Compal - ec_command(0x41, 0xa1) returns 43 4f 4d 50 41 4c 9c
382 */
383
384
385 if (register_shutdown(ene_leave_flash_mode, NULL))
386 return 1;
387
388 ene_enter_flash_mode();
389
390 buses_supported |= BUS_LPC;
391 register_spi_programmer(&spi_programmer_ene);
392 msg_pdbg("%s: successfully initialized ene\n", __func__);
393 return 0;
394}
395
396#endif /* __i386__ || __x86_64__ */
397