Hi,

Le jeudi 12 novembre 2015 à 19:05 +0100, Paul Kocialkowski a écrit :
> Le mercredi 11 novembre 2015 à 22:13 +0100, Nico Huber a écrit :
> > Dear flashrom maintainers, ;)
> > 
> > I have one last concern with this patch. It makes flashrom probe auto-
> > matically by emitting SPI 0x30 commands and I have no idea if that may
> > harm SPI chips that interpret it in any non-obvious way. Do we have a
> > policy for adding new probe commands?
> 
> I suppose the other way round might also be problematic: I haven't
> checked for sure that other chips don't send instructions for probe that
> would be seen as valid for the EDI protocol.
> 
> This seems like a real problem to me. Maybe we could indicate in the
> command line what type (protocol) of probing we want to do
> (JEDEC/EDI/etc). We could keep JEDEC as default so that the default
> behaviour remains the same.

Does this solution seem agreeable? Otherwise, suggestions are welcome!

In the meantime, could we get this patch merged and agree and fixing
this particular problem in a subsequent patch?

Thanks!

> > If you share my concerns, is there a way to disable the automatic probe?
> > If not, well, it's acked-by :)
> 
> I guess we should follow up this discussion and introduce a solution in
> a future patch. I could work on that if no one else is interested.
> 
> > On 11.11.2015 16:55, Paul Kocialkowski wrote:
> > > The ENE Embedded Debug Interface (EDI) is a SPI-based interface for 
> > > accessing
> > > the memory of ENE embedded controllers.
> > > 
> > > The ENE KB9012 EC is an embedded controller found on various laptops such 
> > > as
> > > the Lenovo G505s. It features a 8051 microcontroller and has 128 KiB of 
> > > internal
> > > storage for program data.
> > > 
> > > EDI can be accessed on the KB9012 through pins 59-62 (CS-CLK-MOSI-MISO) 
> > > when
> > > flash direct access is not in use. Some firmwares disable EDI at 
> > > run-time, so
> > > it might be necessary to ground pin 42 to reset the 8051 microcontroller 
> > > before
> > > accessing the KB9012 via EDI.
> > > 
> > > Signed-off-by: Paul Kocialkowski <[email protected]>
> > Acked-by: Nico Huber <[email protected]>
> > 
> > > ---
> > >  Makefile      |   2 +-
> > >  chipdrivers.h |   6 +
> > >  edi.c         | 497 
> > > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  edi.h         |  30 ++++
> > >  ene.h         |  51 ++++++
> > >  flashchips.c  |  23 +++
> > >  6 files changed, 608 insertions(+), 1 deletion(-)
> > >  create mode 100644 edi.c
> > >  create mode 100644 edi.h
> > >  create mode 100644 ene.h
> > > 
> > > diff --git a/Makefile b/Makefile
> > > index c439d8d..661c52a 100644
> > > --- a/Makefile
> > > +++ b/Makefile
> > > @@ -368,7 +368,7 @@ endif
> > >  
> > >  CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \
> > >   sst28sf040.o 82802ab.o \
> > > - sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o spi25_statusreg.o \
> > > + sst49lfxxxc.o sst_fwhub.o edi.o flashchips.o spi.o spi25.o 
> > > spi25_statusreg.o \
> > >   opaque.o sfdp.o en29lv640b.o at45db.o
> > >  
> > >  
> > > ###############################################################################
> > > diff --git a/chipdrivers.h b/chipdrivers.h
> > > index cac94f3..8015b52 100644
> > > --- a/chipdrivers.h
> > > +++ b/chipdrivers.h
> > > @@ -194,4 +194,10 @@ int erase_sector_stm50(struct flashctx *flash, 
> > > unsigned int block, unsigned int
> > >  int probe_en29lv640b(struct flashctx *flash);
> > >  int write_en29lv640b(struct flashctx *flash, const uint8_t *buf, 
> > > unsigned int start, unsigned int len);
> > >  
> > > +/* edi.c */
> > > +int edi_chip_block_erase(struct flashctx *flash, unsigned int page, 
> > > unsigned int size);
> > > +int edi_chip_write(struct flashctx *flash, const uint8_t *buf, unsigned 
> > > int start, unsigned int len);
> > > +int edi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int 
> > > start, unsigned int len);
> > > +int edi_probe_kb9012(struct flashctx *flash);
> > > +
> > >  #endif /* !__CHIPDRIVERS_H__ */
> > > diff --git a/edi.c b/edi.c
> > > new file mode 100644
> > > index 0000000..0ca1704
> > > --- /dev/null
> > > +++ b/edi.c
> > > @@ -0,0 +1,497 @@
> > > +/*
> > > + * This file is part of the flashrom project.
> > > + *
> > > + * Copyright (C) 2015 Paul Kocialkowski <[email protected]>
> > > + *
> > > + * This program is free software; you can redistribute it and/or modify
> > > + * it under the terms of the GNU General Public License as published by
> > > + * the Free Software Foundation; either version 2 of the License, or
> > > + * (at your option) any later version.
> > > + *
> > > + * This program is distributed in the hope that it will be useful,
> > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > > + * GNU General Public License for more details.
> > > + */
> > > +
> > > +#include <string.h>
> > > +#include "flash.h"
> > > +#include "ene.h"
> > > +#include "edi.h"
> > > +
> > > +static unsigned int edi_read_buffer_length = 
> > > EDI_READ_BUFFER_LENGTH_DEFAULT;
> > > +
> > > +static const struct ene_chip ene_kb9012 = {
> > > + .hwversion = ENE_KB9012_HWVERSION,
> > > + .ediid = ENE_KB9012_EDIID,
> > > +};
> > > +
> > > +static void edi_write_cmd(unsigned char *cmd, unsigned short address, 
> > > unsigned char data)
> > > +{
> > > + cmd[0] = EDI_WRITE; /* EDI write command. */
> > > + cmd[1] = 0x00; /* Address is only 2 bytes. */
> > > + cmd[2] = (address >> 8) & 0xff; /* Address higher byte. */
> > > + cmd[3] = (address >> 0) & 0xff; /* Address lower byte. */
> > > + cmd[4] = data; /* Write data. */
> > > +}
> > > +
> > > +static void edi_read_cmd(unsigned char *cmd, unsigned short address)
> > > +{
> > > + cmd[0] = EDI_READ; /* EDI read command. */
> > > + cmd[1] = 0x00; /* Address is only 2 bytes. */
> > > + cmd[2] = (address >> 8) & 0xff; /* Address higher byte. */
> > > + cmd[3] = (address >> 0) & 0xff; /* Address lower byte. */
> > > +}
> > > +
> > > +static int edi_write(struct flashctx *flash, unsigned short address, 
> > > unsigned char data)
> > > +{
> > > + unsigned char cmd[5];
> > > + int rc;
> > > +
> > > + edi_write_cmd(cmd, address, data);
> > > +
> > > + rc = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
> > > + if (rc)
> > > +         return -1;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int edi_read_byte(struct flashctx *flash, unsigned short address, 
> > > unsigned char *data)
> > > +{
> > > + unsigned char cmd[4];
> > > + unsigned char buffer[edi_read_buffer_length];
> > > + unsigned int index;
> > > + unsigned int i;
> > > + int rc;
> > > +
> > > + edi_read_cmd(cmd, address);
> > > +
> > > + rc = spi_send_command(flash, sizeof(cmd), sizeof(buffer), cmd, buffer);
> > > + if (rc)
> > > +         return -1;
> > > +
> > > + index = 0;
> > > +
> > > + for (i = 0; i < sizeof(buffer); i++) {
> > > +         index = i;
> > > +
> > > +         if (buffer[i] == EDI_NOT_READY)
> > > +                 continue;
> > > +
> > > +         if (buffer[i] == EDI_READY) {
> > > +                 if (i == (sizeof(buffer) - 1)) {
> > > +                         /*
> > > +                          * Buffer size was too small for receiving the 
> > > value.
> > > +                          * This is as good as getting only 
> > > EDI_NOT_READY.
> > > +                          */
> > > +
> > > +                         buffer[i] = EDI_NOT_READY;
> > > +                         break;
> > > +                 }
> > > +
> > > +                 *data = buffer[i + 1];
> > > +                 return 0;
> > > +         }
> > > + }
> > > +
> > > + if (buffer[index] == EDI_NOT_READY)
> > > +         return -EDI_NOT_READY;
> > > +
> > > + return -1;
> > > +}
> > > +
> > > +static int edi_read(struct flashctx *flash, unsigned short address, 
> > > unsigned char *data)
> > > +{
> > > + int rc;
> > > +
> > > + do {
> > > +         rc = edi_read_byte(flash, address, data);
> > > +         if (rc == -EDI_NOT_READY) {
> > > +                 /*
> > > +                  * Buffer size is increased, one step at a time,
> > > +                  * to hold more data if we only catch EDI_NOT_READY.
> > > +                  * Once CS is deasserted, no more data will be sent by 
> > > the EC,
> > > +                  * so we cannot keep reading afterwards and have to 
> > > start a new
> > > +                  * transaction with a longer buffer, to be safe.
> > > +                  */
> > > +
> > > +                 if (edi_read_buffer_length < 
> > > EDI_READ_BUFFER_LENGTH_MAX) {
> > > +                         msg_pwarn("%s: Retrying read with greater 
> > > buffer length!\n", __func__);
> > > +                         edi_read_buffer_length++;
> > > +                 } else {
> > > +                         msg_perr("%s: Maximum buffer length reached and 
> > > data still not ready!\n", __func__);
> > > +                         return -1;
> > > +                 }
> > > +         } else if (rc < 0) {
> > > +                 return -1;
> > > +         }
> > > + } while (rc == -EDI_NOT_READY);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int edi_disable(struct flashctx *flash)
> > > +{
> > > + unsigned char cmd = EDI_DISABLE;
> > > + int rc;
> > > +
> > > + rc = spi_send_command(flash, sizeof(cmd), 0, &cmd, NULL);
> > > + if (rc)
> > > +         return -1;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int edi_chip_probe(struct flashctx *flash, const struct ene_chip 
> > > *chip)
> > > +{
> > > + unsigned char hwversion;
> > > + unsigned char ediid;
> > > + int rc;
> > > +
> > > + rc = edi_read(flash, ENE_EC_HWVERSION, &hwversion);
> > > + if (rc < 0)
> > > +         return 0;
> > > +
> > > + rc = edi_read(flash, ENE_EC_EDIID, &ediid);
> > > + if (rc < 0)
> > > +         return 0;
> > > +
> > > + if (chip->hwversion == hwversion && chip->ediid == ediid)
> > > +         return 1;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int edi_spi_enable(struct flashctx *flash)
> > > +{
> > > + unsigned char buffer;
> > > + int rc;
> > > +
> > > + rc = edi_read(flash, ENE_XBI_EFCFG, &buffer);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + buffer |= ENE_XBI_EFCFG_CMD_WE;
> > > +
> > > + rc = edi_write(flash, ENE_XBI_EFCFG, buffer);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int edi_spi_disable(struct flashctx *flash)
> > > +{
> > > + unsigned char buffer;
> > > + int rc;
> > > +
> > > + rc = edi_read(flash, ENE_XBI_EFCFG, &buffer);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + buffer &= ~ENE_XBI_EFCFG_CMD_WE;
> > > +
> > > + rc = edi_write(flash, ENE_XBI_EFCFG, buffer);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int edi_spi_busy(struct flashctx *flash)
> > > +{
> > > + unsigned char buffer;
> > > + int rc;
> > > +
> > > + rc = edi_read(flash, ENE_XBI_EFCFG, &buffer);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + return !!(buffer & ENE_XBI_EFCFG_BUSY);
> > > +}
> > > +
> > > +static int edi_spi_address(struct flashctx *flash, unsigned int start, 
> > > unsigned int address)
> > > +{
> > > + int rc;
> > > +
> > > + if ((address == start) || (((address - 1) & 0xff) != (address & 0xff))) 
> > > {
> > > +         rc = edi_write(flash, ENE_XBI_EFA0, ((address & 0xff) >> 0));
> > > +         if (rc < 0)
> > > +                 return -1;
> > > + }
> > > +
> > > + if ((address == start) || (((address - 1) & 0xff00) != (address & 
> > > 0xff00))) {
> > > +         rc = edi_write(flash, ENE_XBI_EFA1, ((address & 0xff00) >> 8));
> > > +         if (rc < 0)
> > > +                 return -1;
> > > + }
> > > +
> > > + if ((address == start) || (((address - 1) & 0xff0000) != (address & 
> > > 0xff0000))) {
> > > +         rc = edi_write(flash, ENE_XBI_EFA2, ((address & 0xff0000) >> 
> > > 16));
> > > +         if (rc < 0)
> > > +                 return -1;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int edi_8051_reset(struct flashctx *flash)
> > > +{
> > > + unsigned char buffer;
> > > + int rc;
> > > +
> > > + rc = edi_read(flash, ENE_EC_PXCFG, &buffer);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + buffer |= ENE_EC_PXCFG_8051_RESET;
> > > +
> > > + rc = edi_write(flash, ENE_EC_PXCFG, buffer);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int edi_8051_execute(struct flashctx *flash)
> > > +{
> > > + unsigned char buffer;
> > > + int rc;
> > > +
> > > + rc = edi_read(flash, ENE_EC_PXCFG, &buffer);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + buffer &= ~ENE_EC_PXCFG_8051_RESET;
> > > +
> > > + rc = edi_write(flash, ENE_EC_PXCFG, buffer);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +int edi_chip_block_erase(struct flashctx *flash, unsigned int page, 
> > > unsigned int size)
> > > +{
> > > + unsigned int timeout = 64;
> > > + int rc;
> > > +
> > > + if (size != flash->chip->page_size) {
> > > +         msg_perr("%s: Block erase size is not page size!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + rc = edi_spi_enable(flash);
> > > + if (rc < 0) {
> > > +         msg_perr("%s: Unable to enable SPI!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + rc = edi_spi_address(flash, page, page);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + rc = edi_write(flash, ENE_XBI_EFCMD, ENE_XBI_EFCMD_ERASE);
> > > + if (rc < 0)
> > > +         return -1;
> > > +
> > > + while (edi_spi_busy(flash) == 1 && timeout) {
> > > +         programmer_delay(10);
> > > +         timeout--;
> > > + }
> > > +
> > > + if (!timeout) {
> > > +         msg_perr("%s: Timed out waiting for SPI not busy!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + rc = edi_spi_disable(flash);
> > > + if (rc < 0) {
> > > +         msg_perr("%s: Unable to disable SPI!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +int edi_chip_write(struct flashctx *flash, const uint8_t *buf, unsigned 
> > > int start, unsigned int len)
> > > +{
> > > + unsigned int address = start;
> > > + unsigned int pages;
> > > + unsigned int timeout;
> > > + unsigned int i, j;
> > > + int rc;
> > > +
> > > + if ((start % flash->chip->page_size) != 0) {
> > > +         msg_perr("%s: Start address is not page-aligned!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + if ((len % flash->chip->page_size) != 0) {
> > > +         msg_perr("%s: Length is not page-aligned!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + pages = len / flash->chip->page_size;
> > > +
> > > + rc = edi_spi_enable(flash);
> > > + if (rc < 0) {
> > > +         msg_perr("%s: Unable to enable SPI!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + for (i = 0; i < pages; i++) {
> > > +         timeout = 64;
> > > +
> > > +         /* Clear page buffer. */
> > > +         rc = edi_write(flash, ENE_XBI_EFCMD, ENE_XBI_EFCMD_HVPL_CLEAR);
> > > +         if (rc < 0)
> > > +                 return -1;
> > > +
> > > +         for (j = 0; j < flash->chip->page_size; j++) {
> > > +                 rc = edi_spi_address(flash, start, address);
> > > +                 if (rc < 0)
> > > +                         return -1;
> > > +
> > > +                 rc = edi_write(flash, ENE_XBI_EFDAT, *buf);
> > > +                 if (rc < 0)
> > > +                         return -1;
> > > +
> > > +                 rc = edi_write(flash, ENE_XBI_EFCMD, 
> > > ENE_XBI_EFCMD_HVPL_LATCH);
> > > +                 if (rc < 0)
> > > +                         return -1;
> > > +
> > > +                 buf++;
> > > +                 address++;
> > > +         }
> > > +
> > > +         /* Program page buffer to flash. */
> > > +         rc = edi_write(flash, ENE_XBI_EFCMD, ENE_XBI_EFCMD_PROGRAM);
> > > +         if (rc < 0)
> > > +                 return -1;
> > > +
> > > +         while (edi_spi_busy(flash) == 1 && timeout) {
> > > +                 programmer_delay(10);
> > > +                 timeout--;
> > > +         }
> > > +
> > > +         if (!timeout) {
> > > +                 msg_perr("%s: Timed out waiting for SPI not busy!\n", 
> > > __func__);
> > > +                 return -1;
> > > +         }
> > > + }
> > > +
> > > + rc = edi_spi_disable(flash);
> > > + if (rc < 0) {
> > > +         msg_perr("%s: Unable to disable SPI!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +int edi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int 
> > > start, unsigned int len)
> > > +{
> > > + unsigned int address = start;
> > > + unsigned int i;
> > > + unsigned int timeout;
> > > + int rc;
> > > +
> > > + rc = edi_spi_enable(flash);
> > > + if (rc < 0) {
> > > +         msg_perr("%s: Unable to enable SPI!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + /*
> > > +  * EDI brings such a drastic overhead that there is about no need to
> > > +  * have any delay in between calls. The EDI protocol will handle wait
> > > +  * I/O times on its own anyway.
> > > +  */
> > > +
> > > + for (i = 0; i < len; i++) {
> > > +         timeout = 64;
> > > +
> > > +         rc = edi_spi_address(flash, start, address);
> > > +         if (rc < 0)
> > > +                 return -1;
> > > +
> > > +         rc = edi_write(flash, ENE_XBI_EFCMD, ENE_XBI_EFCMD_READ);
> > > +         if (rc < 0)
> > > +                 return -1;
> > > +
> > > +         do {
> > > +                 rc = edi_read(flash, ENE_XBI_EFDAT, buf);
> > > +                 if (rc == 0)
> > > +                         break;
> > > +
> > > +                 /* Just in case. */
> > > +                 while (edi_spi_busy(flash) == 1 && timeout) {
> > > +                         programmer_delay(10);
> > > +                         timeout--;
> > > +                 }
> > > +
> > > +                 if (!timeout) {
> > > +                         msg_perr("%s: Timed out waiting for SPI not 
> > > busy!\n", __func__);
> > > +                         return -1;
> > > +                 }
> > > +         } while (1);
> > > +
> > > +         buf++;
> > > +         address++;
> > > + }
> > > +
> > > + rc = edi_spi_disable(flash);
> > > + if (rc < 0) {
> > > +         msg_perr("%s: Unable to disable SPI!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +int edi_shutdown(void *data)
> > > +{
> > > + struct flashctx *flash;
> > > + int rc;
> > > +
> > > + if (data == NULL)
> > > +         return -1;
> > > +
> > > + flash = (struct flashctx *)data;
> > > +
> > > + rc = edi_8051_execute(flash);
> > > + if (rc < 0) {
> > > +         msg_perr("%s: Unable to execute 8051!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + rc = edi_disable(flash);
> > > + if (rc < 0) {
> > > +         msg_perr("%s: Unable to disable EDI!\n", __func__);
> > > +         return -1;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +int edi_probe_kb9012(struct flashctx *flash)
> > > +{
> > > + int probe;
> > > + int rc;
> > > +
> > > + probe = edi_chip_probe(flash, &ene_kb9012);
> > > + if (!probe)
> > > +         return 0;
> > > +
> > > + rc = edi_8051_reset(flash);
> > > + if (rc < 0) {
> > > +         msg_perr("%s: Unable to reset 8051!\n", __func__);
> > > +         return 0;
> > > + }
> > > +
> > > + register_shutdown(edi_shutdown, (void *)flash);
> > > +
> > > + return 1;
> > > +}
> > > diff --git a/edi.h b/edi.h
> > > new file mode 100644
> > > index 0000000..542bf26
> > > --- /dev/null
> > > +++ b/edi.h
> > > @@ -0,0 +1,30 @@
> > > +/*
> > > + * This file is part of the flashrom project.
> > > + *
> > > + * Copyright (C) 2015 Paul Kocialkowski <[email protected]>
> > > + *
> > > + * This program is free software; you can redistribute it and/or modify
> > > + * it under the terms of the GNU General Public License as published by
> > > + * the Free Software Foundation; either version 2 of the License, or
> > > + * (at your option) any later version.
> > > + *
> > > + * This program is distributed in the hope that it will be useful,
> > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > > + * GNU General Public License for more details.
> > > + */
> > > +
> > > +#ifndef __EDI_H__
> > > +#define __EDI_H__ 1
> > > +
> > > +#define EDI_READ                 0x30
> > > +#define EDI_WRITE                        0x40
> > > +#define EDI_DISABLE                      0xf3
> > > +
> > > +#define EDI_NOT_READY                    0x5f
> > > +#define EDI_READY                        0x50
> > > +
> > > +#define EDI_READ_BUFFER_LENGTH_DEFAULT   3
> > > +#define EDI_READ_BUFFER_LENGTH_MAX       32
> > > +
> > > +#endif
> > > diff --git a/ene.h b/ene.h
> > > new file mode 100644
> > > index 0000000..e03e49b
> > > --- /dev/null
> > > +++ b/ene.h
> > > @@ -0,0 +1,51 @@
> > > +/*
> > > + * This file is part of the flashrom project.
> > > + *
> > > + * Copyright (C) 2015 Paul Kocialkowski <[email protected]>
> > > + *
> > > + * This program is free software; you can redistribute it and/or modify
> > > + * it under the terms of the GNU General Public License as published by
> > > + * the Free Software Foundation; either version 2 of the License, or
> > > + * (at your option) any later version.
> > > + *
> > > + * This program is distributed in the hope that it will be useful,
> > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > > + * GNU General Public License for more details.
> > > + */
> > > +
> > > +#ifndef __ENE_H__
> > > +#define __ENE_H__ 1
> > > +
> > > +#define ENE_XBI_EFA0                     0xfea8
> > > +#define ENE_XBI_EFA1                     0xfea9
> > > +#define ENE_XBI_EFA2                     0xfeaa
> > > +#define ENE_XBI_EFDAT                    0xfeab
> > > +#define ENE_XBI_EFCMD                    0xfeac
> > > +#define ENE_XBI_EFCFG                    0xfead
> > > +
> > > +#define ENE_XBI_EFCFG_CMD_WE             (1 << 3)
> > > +#define ENE_XBI_EFCFG_BUSY               (1 << 1)
> > > +
> > > +#define ENE_XBI_EFCMD_HVPL_LATCH 0x02
> > > +#define ENE_XBI_EFCMD_READ               0x03
> > > +#define ENE_XBI_EFCMD_ERASE              0x20
> > > +#define ENE_XBI_EFCMD_PROGRAM            0x70
> > > +#define ENE_XBI_EFCMD_HVPL_CLEAR 0x80
> > > +
> > > +#define ENE_EC_PXCFG                     0xff14
> > > +
> > > +#define ENE_EC_PXCFG_8051_RESET          0x01
> > > +
> > > +#define ENE_EC_HWVERSION         0xff00
> > > +#define ENE_EC_EDIID                     0xff24
> > > +
> > > +#define ENE_KB9012_HWVERSION             0xc3
> > > +#define ENE_KB9012_EDIID         0x04
> > > +
> > > +struct ene_chip {
> > > + unsigned char hwversion;
> > > + unsigned char ediid;
> > > +};
> > > +
> > > +#endif
> > > diff --git a/flashchips.c b/flashchips.c
> > > index 574ad74..13f0574 100644
> > > --- a/flashchips.c
> > > +++ b/flashchips.c
> > > @@ -3201,6 +3201,29 @@ const struct flashchip flashchips[] = {
> > >   },
> > >  
> > >   {
> > > +         .vendor         = "ENE",
> > > +         .name           = "KB9012 (EDI)",
> > > +         .bustype        = BUS_SPI,
> > > +         .total_size     = 128,
> > > +         .page_size      = 128,
> > > +         .feature_bits   = FEATURE_ERASED_ZERO,
> > > +         .tested         = TEST_OK_PREW,
> > > +         .probe          = edi_probe_kb9012,
> > > +         .probe_timing   = TIMING_ZERO,
> > > +         .block_erasers  =
> > > +         {
> > > +                 {
> > > +                         .eraseblocks = { {128, 1024} },
> > > +                         .block_erase = edi_chip_block_erase,
> > > +                 },
> > > +         },
> > > +         .gran           = write_gran_128bytes,
> > > +         .write          = edi_chip_write,
> > > +         .read           = edi_chip_read,
> > > +         .voltage        = {2700, 3600},
> > > + },
> > > +
> > > + {
> > >           .vendor         = "ESMT",
> > >           .name           = "F49B002UA",
> > >           .bustype        = BUS_PARALLEL,
> > > 
> > 
> 
> _______________________________________________
> flashrom mailing list
> [email protected]
> http://www.flashrom.org/mailman/listinfo/flashrom

Attachment: signature.asc
Description: This is a digitally signed message part

_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to