blob: 8adba1640ff3affedc9863c99861ff24f38d218e [file] [log] [blame]
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +03001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2015 Paul Kocialkowski <contact@paulk.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <string.h>
18#include "flash.h"
Nico Hubera94ce1c2026-02-19 19:24:44 +010019#include "programmer.h"
Nico Huber6bd4f102026-02-22 23:28:13 +010020#include "chipdrivers/edi.h"
Nico Huberd5185632024-01-05 18:44:41 +010021#include "spi_command.h"
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +030022#include "ene.h"
23#include "edi.h"
24
25static unsigned int edi_read_buffer_length = EDI_READ_BUFFER_LENGTH_DEFAULT;
26
27static const struct ene_chip ene_kb9012 = {
28 .hwversion = ENE_KB9012_HWVERSION,
29 .ediid = ENE_KB9012_EDIID,
30};
31
32static void edi_write_cmd(unsigned char *cmd, unsigned short address, unsigned char data)
33{
34 cmd[0] = EDI_WRITE; /* EDI write command. */
35 cmd[1] = 0x00; /* Address is only 2 bytes. */
36 cmd[2] = (address >> 8) & 0xff; /* Address higher byte. */
37 cmd[3] = (address >> 0) & 0xff; /* Address lower byte. */
38 cmd[4] = data; /* Write data. */
39}
40
41static void edi_read_cmd(unsigned char *cmd, unsigned short address)
42{
43 cmd[0] = EDI_READ; /* EDI read command. */
44 cmd[1] = 0x00; /* Address is only 2 bytes. */
45 cmd[2] = (address >> 8) & 0xff; /* Address higher byte. */
46 cmd[3] = (address >> 0) & 0xff; /* Address lower byte. */
47}
48
Nico Hubera94ce1c2026-02-19 19:24:44 +010049static int edi_write(const struct spi_master *spi, unsigned short address, unsigned char data)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +030050{
51 unsigned char cmd[5];
52 int rc;
53
54 edi_write_cmd(cmd, address, data);
55
Nico Hubera94ce1c2026-02-19 19:24:44 +010056 rc = spi->command(spi, sizeof(cmd), 0, cmd, NULL);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +030057 if (rc)
58 return -1;
59
60 return 0;
61}
62
Nico Hubera94ce1c2026-02-19 19:24:44 +010063static int edi_read_byte(const struct spi_master *spi, unsigned short address, unsigned char *data)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +030064{
65 unsigned char cmd[4];
66 unsigned char buffer[edi_read_buffer_length];
67 unsigned int index;
68 unsigned int i;
69 int rc;
70
71 edi_read_cmd(cmd, address);
72
Nico Hubera94ce1c2026-02-19 19:24:44 +010073 rc = spi->command(spi, sizeof(cmd), sizeof(buffer), cmd, buffer);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +030074 if (rc)
75 return -1;
76
77 index = 0;
78
79 for (i = 0; i < sizeof(buffer); i++) {
80 index = i;
81
82 if (buffer[i] == EDI_NOT_READY)
83 continue;
84
85 if (buffer[i] == EDI_READY) {
86 if (i == (sizeof(buffer) - 1)) {
87 /*
88 * Buffer size was too small for receiving the value.
89 * This is as good as getting only EDI_NOT_READY.
90 */
91
92 buffer[i] = EDI_NOT_READY;
93 break;
94 }
95
96 *data = buffer[i + 1];
97 return 0;
98 }
99 }
100
101 if (buffer[index] == EDI_NOT_READY)
102 return -EDI_NOT_READY;
103
104 return -1;
105}
106
Nico Hubera94ce1c2026-02-19 19:24:44 +0100107static int edi_read(const struct spi_master *spi, unsigned short address, unsigned char *data)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300108{
109 int rc;
110
111 do {
Nico Hubera94ce1c2026-02-19 19:24:44 +0100112 rc = edi_read_byte(spi, address, data);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300113 if (rc == -EDI_NOT_READY) {
114 /*
115 * Buffer size is increased, one step at a time,
116 * to hold more data if we only catch EDI_NOT_READY.
117 * Once CS is deasserted, no more data will be sent by the EC,
118 * so we cannot keep reading afterwards and have to start a new
119 * transaction with a longer buffer, to be safe.
120 */
121
122 if (edi_read_buffer_length < EDI_READ_BUFFER_LENGTH_MAX) {
123 msg_pwarn("%s: Retrying read with greater buffer length!\n", __func__);
124 edi_read_buffer_length++;
125 } else {
126 msg_perr("%s: Maximum buffer length reached and data still not ready!\n", __func__);
127 return -1;
128 }
129 } else if (rc < 0) {
130 return -1;
131 }
132 } while (rc == -EDI_NOT_READY);
133
134 return 0;
135}
136
Nico Hubera94ce1c2026-02-19 19:24:44 +0100137static int edi_disable(const struct spi_master *spi)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300138{
139 unsigned char cmd = EDI_DISABLE;
140 int rc;
141
Nico Hubera94ce1c2026-02-19 19:24:44 +0100142 rc = spi->command(spi, sizeof(cmd), 0, &cmd, NULL);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300143 if (rc)
144 return -1;
145
146 return 0;
147}
148
Nico Hubera94ce1c2026-02-19 19:24:44 +0100149static int edi_chip_probe(const struct spi_master *spi, const struct ene_chip *chip)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300150{
151 unsigned char hwversion;
152 unsigned char ediid;
153 int rc;
154
Nico Hubera94ce1c2026-02-19 19:24:44 +0100155 rc = edi_read(spi, ENE_EC_HWVERSION, &hwversion);
Mike Banon3a826042018-01-15 01:09:16 +0300156 if (rc < 0) {
157 msg_cdbg("%s: reading hwversion failed\n", __func__);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300158 return 0;
Mike Banon3a826042018-01-15 01:09:16 +0300159 }
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300160
Nico Hubera94ce1c2026-02-19 19:24:44 +0100161 rc = edi_read(spi, ENE_EC_EDIID, &ediid);
Mike Banon3a826042018-01-15 01:09:16 +0300162 if (rc < 0) {
163 msg_cdbg("%s: reading ediid failed\n", __func__);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300164 return 0;
Mike Banon3a826042018-01-15 01:09:16 +0300165 }
166
167 msg_cdbg("%s: hwversion 0x%02x, ediid 0x%02x\n", __func__, hwversion, ediid);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300168
169 if (chip->hwversion == hwversion && chip->ediid == ediid)
170 return 1;
171
172 return 0;
173}
174
Nico Hubera94ce1c2026-02-19 19:24:44 +0100175static int edi_spi_enable(const struct spi_master *spi)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300176{
177 unsigned char buffer;
178 int rc;
179
Nico Hubera94ce1c2026-02-19 19:24:44 +0100180 rc = edi_read(spi, ENE_XBI_EFCFG, &buffer);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300181 if (rc < 0)
182 return -1;
183
184 buffer |= ENE_XBI_EFCFG_CMD_WE;
185
Nico Hubera94ce1c2026-02-19 19:24:44 +0100186 rc = edi_write(spi, ENE_XBI_EFCFG, buffer);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300187 if (rc < 0)
188 return -1;
189
190 return 0;
191}
192
Nico Hubera94ce1c2026-02-19 19:24:44 +0100193static int edi_spi_disable(const struct spi_master *spi)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300194{
195 unsigned char buffer;
196 int rc;
197
Nico Hubera94ce1c2026-02-19 19:24:44 +0100198 rc = edi_read(spi, ENE_XBI_EFCFG, &buffer);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300199 if (rc < 0)
200 return -1;
201
202 buffer &= ~ENE_XBI_EFCFG_CMD_WE;
203
Nico Hubera94ce1c2026-02-19 19:24:44 +0100204 rc = edi_write(spi, ENE_XBI_EFCFG, buffer);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300205 if (rc < 0)
206 return -1;
207
208 return 0;
209}
210
Nico Hubera94ce1c2026-02-19 19:24:44 +0100211static int edi_spi_busy(const struct spi_master *spi)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300212{
213 unsigned char buffer;
214 int rc;
215
Nico Hubera94ce1c2026-02-19 19:24:44 +0100216 rc = edi_read(spi, ENE_XBI_EFCFG, &buffer);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300217 if (rc < 0)
218 return -1;
219
220 return !!(buffer & ENE_XBI_EFCFG_BUSY);
221}
222
Nico Hubera94ce1c2026-02-19 19:24:44 +0100223static int edi_spi_address(const struct spi_master *spi, unsigned int start, unsigned int address)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300224{
225 int rc;
226
227 if ((address == start) || (((address - 1) & 0xff) != (address & 0xff))) {
Nico Hubera94ce1c2026-02-19 19:24:44 +0100228 rc = edi_write(spi, ENE_XBI_EFA0, ((address & 0xff) >> 0));
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300229 if (rc < 0)
230 return -1;
231 }
232
233 if ((address == start) || (((address - 1) & 0xff00) != (address & 0xff00))) {
Nico Hubera94ce1c2026-02-19 19:24:44 +0100234 rc = edi_write(spi, ENE_XBI_EFA1, ((address & 0xff00) >> 8));
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300235 if (rc < 0)
236 return -1;
237 }
238
239 if ((address == start) || (((address - 1) & 0xff0000) != (address & 0xff0000))) {
Nico Hubera94ce1c2026-02-19 19:24:44 +0100240 rc = edi_write(spi, ENE_XBI_EFA2, ((address & 0xff0000) >> 16));
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300241 if (rc < 0)
242 return -1;
243 }
244
245 return 0;
246}
247
Nico Hubera94ce1c2026-02-19 19:24:44 +0100248static int edi_8051_reset(const struct spi_master *spi)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300249{
250 unsigned char buffer;
251 int rc;
252
Nico Hubera94ce1c2026-02-19 19:24:44 +0100253 rc = edi_read(spi, ENE_EC_PXCFG, &buffer);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300254 if (rc < 0)
255 return -1;
256
257 buffer |= ENE_EC_PXCFG_8051_RESET;
258
Nico Hubera94ce1c2026-02-19 19:24:44 +0100259 rc = edi_write(spi, ENE_EC_PXCFG, buffer);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300260 if (rc < 0)
261 return -1;
262
263 return 0;
264}
265
Nico Hubera94ce1c2026-02-19 19:24:44 +0100266static int edi_8051_execute(const struct spi_master *spi)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300267{
268 unsigned char buffer;
269 int rc;
270
Nico Hubera94ce1c2026-02-19 19:24:44 +0100271 rc = edi_read(spi, ENE_EC_PXCFG, &buffer);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300272 if (rc < 0)
273 return -1;
274
275 buffer &= ~ENE_EC_PXCFG_8051_RESET;
276
Nico Hubera94ce1c2026-02-19 19:24:44 +0100277 rc = edi_write(spi, ENE_EC_PXCFG, buffer);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300278 if (rc < 0)
279 return -1;
280
281 return 0;
282}
283
284int edi_chip_block_erase(struct flashctx *flash, unsigned int page, unsigned int size)
285{
Nico Hubera94ce1c2026-02-19 19:24:44 +0100286 const struct spi_master *const spi = flash->mst.spi;
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300287 unsigned int timeout = 64;
288 int rc;
289
290 if (size != flash->chip->page_size) {
291 msg_perr("%s: Block erase size is not page size!\n", __func__);
292 return -1;
293 }
294
Nico Hubera94ce1c2026-02-19 19:24:44 +0100295 rc = edi_spi_enable(spi);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300296 if (rc < 0) {
297 msg_perr("%s: Unable to enable SPI!\n", __func__);
298 return -1;
299 }
300
Nico Hubera94ce1c2026-02-19 19:24:44 +0100301 rc = edi_spi_address(spi, page, page);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300302 if (rc < 0)
303 return -1;
304
Nico Hubera94ce1c2026-02-19 19:24:44 +0100305 rc = edi_write(spi, ENE_XBI_EFCMD, ENE_XBI_EFCMD_ERASE);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300306 if (rc < 0)
307 return -1;
308
Nico Hubera94ce1c2026-02-19 19:24:44 +0100309 while (edi_spi_busy(spi) == 1 && timeout) {
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300310 programmer_delay(10);
311 timeout--;
312 }
313
314 if (!timeout) {
315 msg_perr("%s: Timed out waiting for SPI not busy!\n", __func__);
316 return -1;
317 }
318
Nico Hubera94ce1c2026-02-19 19:24:44 +0100319 rc = edi_spi_disable(spi);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300320 if (rc < 0) {
321 msg_perr("%s: Unable to disable SPI!\n", __func__);
322 return -1;
323 }
324
325 return 0;
326}
327
328int edi_chip_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
329{
Nico Hubera94ce1c2026-02-19 19:24:44 +0100330 const struct spi_master *const spi = flash->mst.spi;
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300331 unsigned int address = start;
332 unsigned int pages;
333 unsigned int timeout;
334 unsigned int i, j;
335 int rc;
336
337 if ((start % flash->chip->page_size) != 0) {
338 msg_perr("%s: Start address is not page-aligned!\n", __func__);
339 return -1;
340 }
341
342 if ((len % flash->chip->page_size) != 0) {
343 msg_perr("%s: Length is not page-aligned!\n", __func__);
344 return -1;
345 }
346
347 pages = len / flash->chip->page_size;
348
Nico Hubera94ce1c2026-02-19 19:24:44 +0100349 rc = edi_spi_enable(spi);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300350 if (rc < 0) {
351 msg_perr("%s: Unable to enable SPI!\n", __func__);
352 return -1;
353 }
354
355 for (i = 0; i < pages; i++) {
356 timeout = 64;
357
358 /* Clear page buffer. */
Nico Hubera94ce1c2026-02-19 19:24:44 +0100359 rc = edi_write(spi, ENE_XBI_EFCMD, ENE_XBI_EFCMD_HVPL_CLEAR);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300360 if (rc < 0)
361 return -1;
362
363 for (j = 0; j < flash->chip->page_size; j++) {
Nico Hubera94ce1c2026-02-19 19:24:44 +0100364 rc = edi_spi_address(spi, start, address);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300365 if (rc < 0)
366 return -1;
367
Nico Hubera94ce1c2026-02-19 19:24:44 +0100368 rc = edi_write(spi, ENE_XBI_EFDAT, *buf);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300369 if (rc < 0)
370 return -1;
371
Nico Hubera94ce1c2026-02-19 19:24:44 +0100372 rc = edi_write(spi, ENE_XBI_EFCMD, ENE_XBI_EFCMD_HVPL_LATCH);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300373 if (rc < 0)
374 return -1;
375
376 buf++;
377 address++;
378 }
379
380 /* Program page buffer to flash. */
Nico Hubera94ce1c2026-02-19 19:24:44 +0100381 rc = edi_write(spi, ENE_XBI_EFCMD, ENE_XBI_EFCMD_PROGRAM);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300382 if (rc < 0)
383 return -1;
384
Nico Hubera94ce1c2026-02-19 19:24:44 +0100385 while (edi_spi_busy(spi) == 1 && timeout) {
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300386 programmer_delay(10);
387 timeout--;
388 }
389
390 if (!timeout) {
391 msg_perr("%s: Timed out waiting for SPI not busy!\n", __func__);
392 return -1;
393 }
Richard Hughes842d6782021-01-15 09:48:12 +0000394
395 flashprog_progress_add(flash, flash->chip->page_size);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300396 }
397
Nico Hubera94ce1c2026-02-19 19:24:44 +0100398 rc = edi_spi_disable(spi);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300399 if (rc < 0) {
400 msg_perr("%s: Unable to disable SPI!\n", __func__);
401 return -1;
402 }
403
404 return 0;
405}
406
407int edi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
408{
Nico Hubera94ce1c2026-02-19 19:24:44 +0100409 const struct spi_master *const spi = flash->mst.spi;
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300410 unsigned int address = start;
411 unsigned int i;
412 unsigned int timeout;
413 int rc;
414
Nico Hubera94ce1c2026-02-19 19:24:44 +0100415 rc = edi_spi_enable(spi);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300416 if (rc < 0) {
417 msg_perr("%s: Unable to enable SPI!\n", __func__);
418 return -1;
419 }
420
421 /*
422 * EDI brings such a drastic overhead that there is about no need to
423 * have any delay in between calls. The EDI protocol will handle wait
424 * I/O times on its own anyway.
425 */
426
427 for (i = 0; i < len; i++) {
428 timeout = 64;
429
Nico Hubera94ce1c2026-02-19 19:24:44 +0100430 rc = edi_spi_address(spi, start, address);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300431 if (rc < 0)
432 return -1;
433
Nico Hubera94ce1c2026-02-19 19:24:44 +0100434 rc = edi_write(spi, ENE_XBI_EFCMD, ENE_XBI_EFCMD_READ);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300435 if (rc < 0)
436 return -1;
437
438 do {
Nico Hubera94ce1c2026-02-19 19:24:44 +0100439 rc = edi_read(spi, ENE_XBI_EFDAT, buf);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300440 if (rc == 0)
441 break;
442
443 /* Just in case. */
Nico Hubera94ce1c2026-02-19 19:24:44 +0100444 while (edi_spi_busy(spi) == 1 && timeout) {
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300445 programmer_delay(10);
446 timeout--;
447 }
448
449 if (!timeout) {
450 msg_perr("%s: Timed out waiting for SPI not busy!\n", __func__);
451 return -1;
452 }
453 } while (1);
454
455 buf++;
456 address++;
Richard Hughes842d6782021-01-15 09:48:12 +0000457 flashprog_progress_add(flash, 1);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300458 }
459
Nico Hubera94ce1c2026-02-19 19:24:44 +0100460 rc = edi_spi_disable(spi);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300461 if (rc < 0) {
462 msg_perr("%s: Unable to disable SPI!\n", __func__);
463 return -1;
464 }
465
466 return 0;
467}
468
Nico Huber4af02fe2026-02-21 12:29:26 +0100469static void edi_finish(struct flashctx *flash)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300470{
Nico Huber4af02fe2026-02-21 12:29:26 +0100471 const struct spi_master *const spi = flash->mst.spi;
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300472
Nico Huber4af02fe2026-02-21 12:29:26 +0100473 if (edi_8051_execute(spi) < 0)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300474 msg_perr("%s: Unable to execute 8051!\n", __func__);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300475
Nico Huber4af02fe2026-02-21 12:29:26 +0100476 if (edi_disable(spi) < 0)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300477 msg_perr("%s: Unable to disable EDI!\n", __func__);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300478}
479
480int edi_probe_kb9012(struct flashctx *flash)
481{
Nico Hubera94ce1c2026-02-19 19:24:44 +0100482 const struct spi_master *const spi = flash->mst.spi;
Paul Kocialkowskia590f482018-01-15 01:08:39 +0300483 unsigned char hwversion;
484
485 /*
486 * ENE chips enable EDI by detecting a clock frequency between 1 MHz and
487 * 8 MHz. In many cases, the chip won't be able to both detect the clock
488 * signal and serve the associated request at the same time.
489 *
490 * Thus, a dummy read has to be added to ensure that EDI is enabled and
491 * operational starting from the next request. This dummy read below
492 * draws the chip's attention and as result the chip enables its EDI.
493 */
Nico Hubera94ce1c2026-02-19 19:24:44 +0100494 edi_read(spi, ENE_EC_HWVERSION, &hwversion);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300495
Nico Huber4af02fe2026-02-21 12:29:26 +0100496 return edi_chip_probe(spi, &ene_kb9012);
497}
498
499int edi_prepare(struct flashctx *flash, enum preparation_steps step)
500{
501 int rc;
502
503 if (step < PREPARE_FULL)
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300504 return 0;
505
Nico Huber4af02fe2026-02-21 12:29:26 +0100506 rc = edi_8051_reset(flash->mst.spi);
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300507 if (rc < 0) {
508 msg_perr("%s: Unable to reset 8051!\n", __func__);
Nico Huber4af02fe2026-02-21 12:29:26 +0100509 return rc;
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300510 }
511
Nico Huber4af02fe2026-02-21 12:29:26 +0100512 flash->chip->finish_access = edi_finish;
513 return 0;
Paul Kocialkowski80ae14e2018-01-15 01:07:46 +0300514}