diff options
Diffstat (limited to 'util/flashrom/ichspi.c')
-rw-r--r-- | util/flashrom/ichspi.c | 800 |
1 files changed, 0 insertions, 800 deletions
diff --git a/util/flashrom/ichspi.c b/util/flashrom/ichspi.c deleted file mode 100644 index 19f4b8066a..0000000000 --- a/util/flashrom/ichspi.c +++ /dev/null @@ -1,800 +0,0 @@ -/* - * This file is part of the flashrom project. - * - * Copyright (C) 2008 Stefan Wildemann <stefan.wildemann@kontron.com> - * Copyright (C) 2008 Claus Gindhart <claus.gindhart@kontron.com> - * Copyright (C) 2008 Dominik Geyer <dominik.geyer@kontron.com> - * Copyright (C) 2008 coresystems GmbH <info@coresystems.de> - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * This module is designed for supporting the devices - * ST M25P40 - * ST M25P80 - * ST M25P16 - * ST M25P32 already tested - * ST M25P64 - * AT 25DF321 already tested - * - */ - -#include <stdio.h> -#include <string.h> -#include <stdint.h> -#include <sys/mman.h> -#include <pci/pci.h> -#include "flash.h" -#include "spi.h" - -/* ICH9 controller register definition */ -#define ICH9_REG_FADDR 0x08 /* 32 Bits */ -#define ICH9_REG_FDATA0 0x10 /* 64 Bytes */ - -#define ICH9_REG_SSFS 0x90 /* 08 Bits */ -#define SSFS_SCIP 0x00000001 -#define SSFS_CDS 0x00000004 -#define SSFS_FCERR 0x00000008 -#define SSFS_AEL 0x00000010 - -#define ICH9_REG_SSFC 0x91 /* 24 Bits */ -#define SSFC_SCGO 0x00000200 -#define SSFC_ACS 0x00000400 -#define SSFC_SPOP 0x00000800 -#define SSFC_COP 0x00001000 -#define SSFC_DBC 0x00010000 -#define SSFC_DS 0x00400000 -#define SSFC_SME 0x00800000 -#define SSFC_SCF 0x01000000 -#define SSFC_SCF_20MHZ 0x00000000 -#define SSFC_SCF_33MHZ 0x01000000 - -#define ICH9_REG_PREOP 0x94 /* 16 Bits */ -#define ICH9_REG_OPTYPE 0x96 /* 16 Bits */ -#define ICH9_REG_OPMENU 0x98 /* 64 Bits */ - -// ICH9R SPI commands -#define SPI_OPCODE_TYPE_READ_NO_ADDRESS 0 -#define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS 1 -#define SPI_OPCODE_TYPE_READ_WITH_ADDRESS 2 -#define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS 3 - -// ICH7 registers -#define ICH7_REG_SPIS 0x00 /* 16 Bits */ -#define SPIS_SCIP 0x00000001 -#define SPIS_CDS 0x00000004 -#define SPIS_FCERR 0x00000008 - -/* VIA SPI is compatible with ICH7, but maxdata - to transfer is 16 bytes. - - DATA byte count on ICH7 is 8:13, on VIA 8:11 - - bit 12 is port select CS0 CS1 - bit 13 is FAST READ enable - bit 7 is used with fast read and one shot controls CS de-assert? -*/ - -#define ICH7_REG_SPIC 0x02 /* 16 Bits */ -#define SPIC_SCGO 0x0002 -#define SPIC_ACS 0x0004 -#define SPIC_SPOP 0x0008 -#define SPIC_DS 0x4000 - -#define ICH7_REG_SPIA 0x04 /* 32 Bits */ -#define ICH7_REG_SPID0 0x08 /* 64 Bytes */ -#define ICH7_REG_PREOP 0x54 /* 16 Bits */ -#define ICH7_REG_OPTYPE 0x56 /* 16 Bits */ -#define ICH7_REG_OPMENU 0x58 /* 64 Bits */ - -/* ICH SPI configuration lock-down. May be set during chipset enabling. */ -int ichspi_lock = 0; - -typedef struct _OPCODE { - uint8_t opcode; //This commands spi opcode - uint8_t spi_type; //This commands spi type - uint8_t atomic; //Use preop: (0: none, 1: preop0, 2: preop1 -} OPCODE; - -/* Opcode definition: - * Preop 1: Write Enable - * Preop 2: Write Status register enable - * - * OP 0: Write address - * OP 1: Read Address - * OP 2: ERASE block - * OP 3: Read Status register - * OP 4: Read ID - * OP 5: Write Status register - * OP 6: chip private (read JDEC id) - * OP 7: Chip erase - */ -typedef struct _OPCODES { - uint8_t preop[2]; - OPCODE opcode[8]; -} OPCODES; - -static OPCODES *curopcodes = NULL; - -/* HW access functions */ -static inline uint32_t REGREAD32(int X) -{ - volatile uint32_t regval; - regval = *(volatile uint32_t *)((uint8_t *) spibar + X); - return regval; -} - -static inline uint16_t REGREAD16(int X) -{ - volatile uint16_t regval; - regval = *(volatile uint16_t *)((uint8_t *) spibar + X); - return regval; -} - -#define REGWRITE32(X,Y) (*(uint32_t *)((uint8_t *)spibar+X)=Y) -#define REGWRITE16(X,Y) (*(uint16_t *)((uint8_t *)spibar+X)=Y) -#define REGWRITE8(X,Y) (*(uint8_t *)((uint8_t *)spibar+X)=Y) - -/* Common SPI functions */ -static inline int find_opcode(OPCODES *op, uint8_t opcode); -static inline int find_preop(OPCODES *op, uint8_t preop); -static int generate_opcodes(OPCODES * op); -static int program_opcodes(OPCODES * op); -static int run_opcode(OPCODE op, uint32_t offset, - uint8_t datalength, uint8_t * data); -static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, - int offset, int maxdata); -static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes, - int offset, int maxdata); - -/* for pairing opcodes with their required preop */ -struct preop_opcode_pair { - uint8_t preop; - uint8_t opcode; -}; - -struct preop_opcode_pair pops[] = { - {JEDEC_WREN, JEDEC_BYTE_PROGRAM}, - {JEDEC_WREN, JEDEC_SE}, /* sector erase */ - {JEDEC_WREN, JEDEC_BE_52}, /* block erase */ - {JEDEC_WREN, JEDEC_BE_D8}, /* block erase */ - {JEDEC_WREN, JEDEC_CE_60}, /* chip erase */ - {JEDEC_WREN, JEDEC_CE_C7}, /* chip erase */ - {JEDEC_EWSR, JEDEC_WRSR}, - {0,} -}; - -OPCODES O_ST_M25P = { - { - JEDEC_WREN, - 0}, - { - {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 1}, // Write Byte - {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data - {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 1}, // Erase Sector - {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read Device Status Reg - {JEDEC_RES, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Resume Deep Power-Down - {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 1}, // Write Status Register - {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read JDEC ID - {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 1}, // Bulk erase - } -}; - -OPCODES O_EXISTING = {}; - -static inline int find_opcode(OPCODES *op, uint8_t opcode) -{ - int a; - - for (a = 0; a < 8; a++) { - if (op->opcode[a].opcode == opcode) - return a; - } - - return -1; -} - -static inline int find_preop(OPCODES *op, uint8_t preop) -{ - int a; - - for (a = 0; a < 2; a++) { - if (op->preop[a] == preop) - return a; - } - - return -1; -} - -static int generate_opcodes(OPCODES * op) -{ - int a, b, i; - uint16_t preop, optype; - uint32_t opmenu[2]; - - if (op == NULL) { - printf_debug("\n%s: null OPCODES pointer!\n", __FUNCTION__); - return -1; - } - - switch (flashbus) { - case BUS_TYPE_ICH7_SPI: - case BUS_TYPE_VIA_SPI: - preop = REGREAD16(ICH7_REG_PREOP); - optype = REGREAD16(ICH7_REG_OPTYPE); - opmenu[0] = REGREAD32(ICH7_REG_OPMENU); - opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4); - break; - case BUS_TYPE_ICH9_SPI: - preop = REGREAD16(ICH9_REG_PREOP); - optype = REGREAD16(ICH9_REG_OPTYPE); - opmenu[0] = REGREAD32(ICH9_REG_OPMENU); - opmenu[1] = REGREAD32(ICH9_REG_OPMENU + 4); - break; - default: - printf_debug("%s: unsupported chipset\n", __FUNCTION__); - return -1; - } - - op->preop[0] = (uint8_t) preop; - op->preop[1] = (uint8_t) (preop >> 8); - - for (a = 0; a < 8; a++) { - op->opcode[a].spi_type = (uint8_t) (optype & 0x3); - optype >>= 2; - } - - for (a = 0; a < 4; a++) { - op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff); - opmenu[0] >>= 8; - } - - for (a = 4; a < 8; a++) { - op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff); - opmenu[1] >>= 8; - } - - /* atomic (link opcode with required pre-op) */ - for (a = 4; a < 8; a++) - op->opcode[a].atomic = 0; - - for (i = 0; pops[i].opcode; i++) { - a = find_opcode(op, pops[i].opcode); - b = find_preop(op, pops[i].preop); - if ((a != -1) && (b != -1)) - op->opcode[a].atomic = (uint8_t) ++b; - } - - return 0; -} - -int program_opcodes(OPCODES * op) -{ - uint8_t a; - uint16_t preop, optype; - uint32_t opmenu[2]; - - /* Program Prefix Opcodes */ - /* 0:7 Prefix Opcode 1 */ - preop = (op->preop[0]); - /* 8:16 Prefix Opcode 2 */ - preop |= ((uint16_t) op->preop[1]) << 8; - - /* Program Opcode Types 0 - 7 */ - optype = 0; - for (a = 0; a < 8; a++) { - optype |= ((uint16_t) op->opcode[a].spi_type) << (a * 2); - } - - /* Program Allowable Opcodes 0 - 3 */ - opmenu[0] = 0; - for (a = 0; a < 4; a++) { - opmenu[0] |= ((uint32_t) op->opcode[a].opcode) << (a * 8); - } - - /*Program Allowable Opcodes 4 - 7 */ - opmenu[1] = 0; - for (a = 4; a < 8; a++) { - opmenu[1] |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8); - } - - printf_debug("\n%s: preop=%04x optype=%04x opmenu=%08x%08x\n", __func__, preop, optype, opmenu[0], opmenu[1]); - switch (flashbus) { - case BUS_TYPE_ICH7_SPI: - case BUS_TYPE_VIA_SPI: - REGWRITE16(ICH7_REG_PREOP, preop); - REGWRITE16(ICH7_REG_OPTYPE, optype); - REGWRITE32(ICH7_REG_OPMENU, opmenu[0]); - REGWRITE32(ICH7_REG_OPMENU + 4, opmenu[1]); - break; - case BUS_TYPE_ICH9_SPI: - REGWRITE16(ICH9_REG_PREOP, preop); - REGWRITE16(ICH9_REG_OPTYPE, optype); - REGWRITE32(ICH9_REG_OPMENU, opmenu[0]); - REGWRITE32(ICH9_REG_OPMENU + 4, opmenu[1]); - break; - default: - printf_debug("%s: unsupported chipset\n", __FUNCTION__); - return -1; - } - - return 0; -} - -/* This function generates OPCODES from or programs OPCODES to ICH according to - * the chipset's SPI configuration lock. - * - * It should be called before ICH sends any spi command. - */ -int ich_init_opcodes(void) -{ - int rc = 0; - OPCODES *curopcodes_done; - - if (curopcodes) - return 0; - - if (ichspi_lock) { - printf_debug("Generating OPCODES... "); - curopcodes_done = &O_EXISTING; - rc = generate_opcodes(curopcodes_done); - } else { - printf_debug("Programming OPCODES... "); - curopcodes_done = &O_ST_M25P; - rc = program_opcodes(curopcodes_done); - } - - if (rc) { - curopcodes = NULL; - printf_debug("failed\n"); - return 1; - } else { - curopcodes = curopcodes_done; - printf_debug("done\n"); - return 0; - } -} - -static int ich7_run_opcode(OPCODE op, uint32_t offset, - uint8_t datalength, uint8_t * data, int maxdata) -{ - int write_cmd = 0; - int timeout; - uint32_t temp32 = 0; - uint16_t temp16; - uint32_t a; - uint64_t opmenu; - int opcode_index; - - /* Is it a write command? */ - if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) - || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) { - write_cmd = 1; - } - - /* Programm Offset in Flash into FADDR */ - REGWRITE32(ICH7_REG_SPIA, (offset & 0x00FFFFFF)); /* SPI addresses are 24 BIT only */ - - /* Program data into FDATA0 to N */ - if (write_cmd && (datalength != 0)) { - temp32 = 0; - for (a = 0; a < datalength; a++) { - if ((a % 4) == 0) { - temp32 = 0; - } - - temp32 |= ((uint32_t) data[a]) << ((a % 4) * 8); - - if ((a % 4) == 3) { - REGWRITE32(ICH7_REG_SPID0 + (a - (a % 4)), - temp32); - } - } - if (((a - 1) % 4) != 3) { - REGWRITE32(ICH7_REG_SPID0 + - ((a - 1) - ((a - 1) % 4)), temp32); - } - - } - - /* Assemble SPIS */ - temp16 = 0; - /* clear error status registers */ - temp16 |= (SPIS_CDS + SPIS_FCERR); - REGWRITE16(ICH7_REG_SPIS, temp16); - - /* Assemble SPIC */ - temp16 = 0; - - if (datalength != 0) { - temp16 |= SPIC_DS; - temp16 |= ((uint32_t) ((datalength - 1) & (maxdata - 1))) << 8; - } - - /* Select opcode */ - opmenu = REGREAD32(ICH7_REG_OPMENU); - opmenu |= ((uint64_t)REGREAD32(ICH7_REG_OPMENU + 4)) << 32; - - for (opcode_index = 0; opcode_index < 8; opcode_index++) { - if ((opmenu & 0xff) == op.opcode) { - break; - } - opmenu >>= 8; - } - if (opcode_index == 8) { - printf_debug("Opcode %x not found.\n", op.opcode); - return 1; - } - temp16 |= ((uint16_t) (opcode_index & 0x07)) << 4; - - /* Handle Atomic */ - if (op.atomic != 0) { - /* Select atomic command */ - temp16 |= SPIC_ACS; - /* Select prefix opcode */ - if ((op.atomic - 1) == 1) { - /*Select prefix opcode 2 */ - temp16 |= SPIC_SPOP; - } - } - - /* Start */ - temp16 |= SPIC_SCGO; - - /* write it */ - REGWRITE16(ICH7_REG_SPIC, temp16); - - /* wait for cycle complete */ - timeout = 1000 * 60; // 60s is a looong timeout. - while (((REGREAD16(ICH7_REG_SPIS) & SPIS_CDS) == 0) && --timeout) { - myusec_delay(1000); - } - if (!timeout) { - printf_debug("timeout\n"); - } - - if ((REGREAD16(ICH7_REG_SPIS) & SPIS_FCERR) != 0) { - printf_debug("Transaction error!\n"); - return 1; - } - - if ((!write_cmd) && (datalength != 0)) { - for (a = 0; a < datalength; a++) { - if ((a % 4) == 0) { - temp32 = REGREAD32(ICH7_REG_SPID0 + (a)); - } - - data[a] = - (temp32 & (((uint32_t) 0xff) << ((a % 4) * 8))) - >> ((a % 4) * 8); - } - } - - return 0; -} - -static int ich9_run_opcode(OPCODE op, uint32_t offset, - uint8_t datalength, uint8_t * data) -{ - int write_cmd = 0; - int timeout; - uint32_t temp32; - uint32_t a; - uint64_t opmenu; - int opcode_index; - - /* Is it a write command? */ - if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) - || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) { - write_cmd = 1; - } - - /* Programm Offset in Flash into FADDR */ - REGWRITE32(ICH9_REG_FADDR, (offset & 0x00FFFFFF)); /* SPI addresses are 24 BIT only */ - - /* Program data into FDATA0 to N */ - if (write_cmd && (datalength != 0)) { - temp32 = 0; - for (a = 0; a < datalength; a++) { - if ((a % 4) == 0) { - temp32 = 0; - } - - temp32 |= ((uint32_t) data[a]) << ((a % 4) * 8); - - if ((a % 4) == 3) { - REGWRITE32(ICH9_REG_FDATA0 + (a - (a % 4)), - temp32); - } - } - if (((a - 1) % 4) != 3) { - REGWRITE32(ICH9_REG_FDATA0 + - ((a - 1) - ((a - 1) % 4)), temp32); - } - } - - /* Assemble SSFS + SSFC */ - temp32 = 0; - - /* clear error status registers */ - temp32 |= (SSFS_CDS + SSFS_FCERR); - /* USE 20 MhZ */ - temp32 |= SSFC_SCF_20MHZ; - - if (datalength != 0) { - uint32_t datatemp; - temp32 |= SSFC_DS; - datatemp = ((uint32_t) ((datalength - 1) & 0x3f)) << (8 + 8); - temp32 |= datatemp; - } - - /* Select opcode */ - opmenu = REGREAD32(ICH9_REG_OPMENU); - opmenu |= ((uint64_t)REGREAD32(ICH9_REG_OPMENU + 4)) << 32; - - for (opcode_index = 0; opcode_index < 8; opcode_index++) { - if ((opmenu & 0xff) == op.opcode) { - break; - } - opmenu >>= 8; - } - if (opcode_index == 8) { - printf_debug("Opcode %x not found.\n", op.opcode); - return 1; - } - temp32 |= ((uint32_t) (opcode_index & 0x07)) << (8 + 4); - - /* Handle Atomic */ - if (op.atomic != 0) { - /* Select atomic command */ - temp32 |= SSFC_ACS; - /* Selct prefix opcode */ - if ((op.atomic - 1) == 1) { - /*Select prefix opcode 2 */ - temp32 |= SSFC_SPOP; - } - } - - /* Start */ - temp32 |= SSFC_SCGO; - - /* write it */ - REGWRITE32(ICH9_REG_SSFS, temp32); - - /*wait for cycle complete */ - timeout = 1000 * 60; // 60s is a looong timeout. - while (((REGREAD32(ICH9_REG_SSFS) & SSFS_CDS) == 0) && --timeout) { - myusec_delay(1000); - } - if (!timeout) { - printf_debug("timeout\n"); - } - - if ((REGREAD32(ICH9_REG_SSFS) & SSFS_FCERR) != 0) { - printf_debug("Transaction error!\n"); - return 1; - } - - if ((!write_cmd) && (datalength != 0)) { - for (a = 0; a < datalength; a++) { - if ((a % 4) == 0) { - temp32 = REGREAD32(ICH9_REG_FDATA0 + (a)); - } - - data[a] = - (temp32 & (((uint32_t) 0xff) << ((a % 4) * 8))) - >> ((a % 4) * 8); - } - } - - return 0; -} - -static int run_opcode(OPCODE op, uint32_t offset, - uint8_t datalength, uint8_t * data) -{ - switch (flashbus) { - case BUS_TYPE_VIA_SPI: - return ich7_run_opcode(op, offset, datalength, data, 16); - case BUS_TYPE_ICH7_SPI: - return ich7_run_opcode(op, offset, datalength, data, 64); - case BUS_TYPE_ICH9_SPI: - return ich9_run_opcode(op, offset, datalength, data); - default: - printf_debug("%s: unsupported chipset\n", __FUNCTION__); - } - - /* If we ever get here, something really weird happened */ - return -1; -} - -static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int offset, - int maxdata) -{ - int page_size = flash->page_size; - uint32_t remaining = flash->page_size; - int a; - - printf_debug("ich_spi_read_page: offset=%d, number=%d, buf=%p\n", - offset, page_size, buf); - - for (a = 0; a < page_size; a += maxdata) { - if (remaining < maxdata) { - - if (spi_nbyte_read(offset + (page_size - remaining), - &buf[page_size - remaining], remaining)) { - printf_debug("Error reading"); - return 1; - } - remaining = 0; - } else { - if (spi_nbyte_read(offset + (page_size - remaining), - &buf[page_size - remaining], maxdata)) { - printf_debug("Error reading"); - return 1; - } - remaining -= maxdata; - } - } - - return 0; -} - -static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes, - int offset, int maxdata) -{ - int page_size = flash->page_size; - uint32_t remaining = page_size; - int a; - - printf_debug("ich_spi_write_page: offset=%d, number=%d, buf=%p\n", - offset, page_size, bytes); - - for (a = 0; a < page_size; a += maxdata) { - if (remaining < maxdata) { - if (run_opcode - (curopcodes->opcode[0], - offset + (page_size - remaining), remaining, - &bytes[page_size - remaining]) != 0) { - printf_debug("Error writing"); - return 1; - } - remaining = 0; - } else { - if (run_opcode - (curopcodes->opcode[0], - offset + (page_size - remaining), maxdata, - &bytes[page_size - remaining]) != 0) { - printf_debug("Error writing"); - return 1; - } - remaining -= maxdata; - } - } - - return 0; -} - -int ich_spi_read(struct flashchip *flash, uint8_t * buf) -{ - int i, rc = 0; - int total_size = flash->total_size * 1024; - int page_size = flash->page_size; - int maxdata = 64; - - if (flashbus == BUS_TYPE_VIA_SPI) { - maxdata = 16; - } - - for (i = 0; (i < total_size / page_size) && (rc == 0); i++) { - rc = ich_spi_read_page(flash, (void *)(buf + i * page_size), - i * page_size, maxdata); - } - - return rc; -} - -int ich_spi_write(struct flashchip *flash, uint8_t * buf) -{ - int i, j, rc = 0; - int total_size = flash->total_size * 1024; - int page_size = flash->page_size; - int erase_size = 64 * 1024; - int maxdata = 64; - - spi_disable_blockprotect(); - - printf("Programming page: \n"); - - for (i = 0; i < total_size / erase_size; i++) { - /* FIMXE: call the chip-specific spi_block_erase_XX instead. - * For this, we need to add a block erase function to - * struct flashchip. - */ - rc = spi_block_erase_d8(flash, i * erase_size); - if (rc) { - printf("Error erasing block at 0x%x\n", i); - break; - } - - if (flashbus == BUS_TYPE_VIA_SPI) - maxdata = 16; - - for (j = 0; j < erase_size / page_size; j++) { - ich_spi_write_page(flash, - (void *)(buf + (i * erase_size) + (j * page_size)), - (i * erase_size) + (j * page_size), maxdata); - } - } - - printf("\n"); - - return rc; -} - -int ich_spi_command(unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, unsigned char *readarr) -{ - int a; - int opcode_index = -1; - const unsigned char cmd = *writearr; - OPCODE *opcode; - uint32_t addr = 0; - uint8_t *data; - int count; - - /* find cmd in opcodes-table */ - for (a = 0; a < 8; a++) { - if ((curopcodes->opcode[a]).opcode == cmd) { - opcode_index = a; - break; - } - } - - /* unknown / not programmed command */ - if (opcode_index == -1) { - printf_debug("Invalid OPCODE 0x%02x\n", cmd); - return 1; - } - - opcode = &(curopcodes->opcode[opcode_index]); - - /* if opcode-type requires an address */ - if (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS || - opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) { - addr = (writearr[1] << 16) | - (writearr[2] << 8) | (writearr[3] << 0); - } - - /* translate read/write array/count */ - if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) { - data = (uint8_t *) (writearr + 1); - count = writecnt - 1; - } else if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) { - data = (uint8_t *) (writearr + 4); - count = writecnt - 4; - } else { - data = (uint8_t *) readarr; - count = readcnt; - } - - if (run_opcode(*opcode, addr, count, data) != 0) { - printf_debug("run OPCODE 0x%02x failed\n", opcode->opcode); - return 1; - } - - return 0; -} |