bool DevSPIMem_AT::erase_chip() { write_enable(); spi.send1b( Cmd::ER_C ); bool r = wait_ready(); return r; }
/* Enable/disable 4-byte addressing mode. */ static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, int enable) { int status; bool need_wren = false; u8 cmd; switch (JEDEC_MFR(info)) { case SNOR_MFR_MICRON: /* Some Micron need WREN command; all will accept it */ need_wren = true; case SNOR_MFR_MACRONIX: case SNOR_MFR_WINBOND: if (need_wren) write_enable(nor); cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; status = nor->write_reg(nor, cmd, NULL, 0); if (need_wren) write_disable(nor); return status; default: /* Spansion style */ nor->cmd_buf[0] = enable << 7; return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); } }
/*---------------------------------------------------------------------------*/ static const char * program_page(unsigned long offset, const unsigned char *p, int nbytes) { const unsigned char *end = p + nbytes; int s; wait_ready(); write_enable(); s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_PP); spi_tx(offset >> 16); /* MSB */ spi_tx(offset >> 8); spi_tx(offset >> 0); /* LSB */ for(; p < end; p++) { spi_tx(~*p); } SPI_FLASH_DISABLE(); splx(s); return p; }
/* Enable/disable 4-byte addressing mode. */ static inline int set_4byte(struct spi_nor *nor, u32 jedec_id, int enable) { int status; bool need_wren = false; u8 cmd; switch (JEDEC_MFR(jedec_id)) { case CFI_MFR_ST: /* Micron, actually */ /* Some Micron need WREN command; all will accept it */ need_wren = true; case CFI_MFR_MACRONIX: case 0xEF /* winbond */: if (need_wren) write_enable(nor); cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; status = nor->write_reg(nor, cmd, NULL, 0, 0); if (need_wren) write_disable(nor); return status; default: /* Spansion style */ nor->cmd_buf[0] = enable << 7; return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0); } }
void SST25VF016B::eraseSector(long sectorAddress, byte sectorSize) { byte address_b[4]; address_b[0] = sectorAddress; address_b[1] = sectorAddress >> 8; address_b[2] = sectorAddress >> 16; address_b[3] = sectorAddress >> 24; write_enable(); switch(sectorSize) { case SECTOR_4KB: SPI.transfer(CE, SECTOR_ERASE_4K, SPI_CONTINUE); // 4KB sector erase break; case SECTOR_32KB: SPI.transfer(CE, SECTOR_ERASE_32K, SPI_CONTINUE); // 32KB sector erase break; case SECTOR_64KB: SPI.transfer(CE, SECTOR_ERASE_64K, SPI_CONTINUE); // 64KB sector erase break; } SPI.transfer(CE, address_b[2], SPI_CONTINUE); // Address MSB [A23-A16] SPI.transfer(CE, address_b[1], SPI_CONTINUE); // Address MSB [A15-A8] SPI.transfer(CE, address_b[0], SPI_LAST); // Address MSB [A7-A0] }
/* * Enable/disable 4-byte addressing mode. */ static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) { int status; bool need_wren = false; switch (JEDEC_MFR(jedec_id)) { case CFI_MFR_ST: /* Micron, actually */ /* Some Micron need WREN command; all will accept it */ need_wren = true; case CFI_MFR_MACRONIX: case 0xEF /* winbond */: if (need_wren) write_enable(flash); flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; status = spi_write(flash->spi, flash->command, 1); if (need_wren) write_disable(flash); return status; default: /* Spansion style */ flash->command[0] = OPCODE_BRWR; flash->command[1] = enable << 7; return spi_write(flash->spi, flash->command, 2); } }
//Byte Page Program allows 1 to 256 bytes of data to be programmed into previously erased memory locations //Erased locations have a logical state fo 1 void flash_program(uint8_t address[3], uint8_t *data, int len) { int i; //First we need to enable write write_enable(); //Bring CSN low flash_csn_low(); //Write OPCODE flash_transfer_byte(BP_PROGRAM); //Write the three addresses flash_transfer_byte(address[2]); flash_transfer_byte(address[1]); flash_transfer_byte(address[0]); for(i=0;i<len;i++) { flash_transfer_byte(data[i]); } //Bring CSN high flash_csn_high(); //Loop until write actually has taken place. while(flash_busy() == 1); }
/* * Write an address range to the nor chip. Data must be written in * FLASH_PAGESIZE chunks. The address range may be any size provided * it is within the physical boundaries. */ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct spi_nor *nor = mtd_to_spi_nor(mtd); u32 page_offset, page_size, i; int ret; dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); if (ret) return ret; /* Wait until finished previous write command. */ ret = wait_till_ready(nor); if (ret) goto write_err; write_enable(nor); page_offset = to & (nor->page_size - 1); /* do all the bytes fit onto one page? */ if (page_offset + len <= nor->page_size) { nor->write(nor, to, len, retlen, buf); } else { /* the size of data remaining on the first page */ page_size = nor->page_size - page_offset; nor->write(nor, to, page_size, retlen, buf); /* write everything in nor->page_size chunks */ for (i = page_size; i < len; i += page_size) { page_size = len - i; if (page_size > nor->page_size) page_size = nor->page_size; wait_till_ready(nor); write_enable(nor); nor->write(nor, to + i, page_size, retlen, buf + i); } } write_err: spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); return 0; }
int DevSPIMem_AT::write( const uint8_t *buf, uint32_t addr, int n ) { write_enable(); uint8_t c[4]; c[0] = Cmd::PGM; c[3] = addr & 0xFF; addr <<= 8; c[2] = addr & 0xFF; addr <<= 8; c[1] = addr & 0xFF; int nt = spi.sendM_sendN_b( c, 4, buf, n ); bool r = wait_ready(); return r ? nt : 0; }
void update_code(void) { while(_Sys_SPI_Buzy) vTaskDelayUntil( &FLLastExecutionTime, ( portTickType ) 1 / portTICK_RATE_MS ); portDISABLE_INTERRUPTS(); _Sys_SPI_Buzy=1; portENABLE_INTERRUPTS(); write_enable();write_data(0x7F, 0xF5, 10, (unsigned char*)"Relkon 001"); portDISABLE_INTERRUPTS(); _Sys_SPI_Buzy=0; portENABLE_INTERRUPTS(); }
static void bulk_erase(void) { static struct spi_ctx be_ctx; static const enum EZPORT_CMD be_cmd = EZPORT_BE; write_enable(); spi_queue_xfer(&be_ctx, EZPORT_SPI_CS, &be_cmd, 1, NULL, 0, NULL, NULL); check_status(); }
bool DevSPIMem_AT::erase_sector( uint32_t addr ) { write_enable(); uint8_t c[4]; c[0] = Cmd::ER_S;c[3] = addr & 0xFF; addr <<= 8; c[2] = addr & 0xFF; addr <<= 8; c[1] = addr & 0xFF; addr <<= 8; spi.sendM_recvN_b( c, 4, nullptr, 0 ); bool r = wait_ready(); return r; }
void SST25VF016B::writeByte(byte b, long address) { byte address_b[4]; address_b[0] = address; address_b[1] = address >> 8; address_b[2] = address >> 16; address_b[3] = address >> 24; write_enable(); SPI.transfer(CE, BYTE_WRITE, SPI_CONTINUE); // Read command SPI.transfer(CE, address_b[2], SPI_CONTINUE); // Address MSB [A23-A16] SPI.transfer(CE, address_b[1], SPI_CONTINUE); // Address MSB [A15-A8] SPI.transfer(CE, address_b[0], SPI_CONTINUE); // Address MSB [A7-A0] SPI.transfer(CE, b, SPI_LAST); // Data byte }
/* * Erase the whole flash memory * * Returns 0 if successful, non-zero otherwise. */ static int erase_chip(struct spi_nor *nor) { int ret; dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10)); /* Wait until finished previous write command. */ ret = wait_till_ready(nor); if (ret) return ret; /* Send write enable, then erase commands. */ write_enable(nor); return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); }
static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { struct spi_nor *nor = mtd_to_spi_nor(mtd); uint32_t offset = ofs; uint8_t status_old, status_new; int ret = 0; ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); if (ret) return ret; /* Wait until finished previous command */ ret = wait_till_ready(nor); if (ret) goto err; status_old = read_sr(nor); if (offset+len > mtd->size - (mtd->size / 64)) status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0); else if (offset+len > mtd->size - (mtd->size / 32)) status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; else if (offset+len > mtd->size - (mtd->size / 16)) status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; else if (offset+len > mtd->size - (mtd->size / 8)) status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; else if (offset+len > mtd->size - (mtd->size / 4)) status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; else if (offset+len > mtd->size - (mtd->size / 2)) status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; else status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; /* Only modify protection if it will not lock other areas */ if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) < (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { write_enable(nor); ret = write_sr(nor, status_new); if (ret) goto err; } err: spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); return ret; }
void write_status_reg(uint8_t byte) { //First we need to enable write write_enable(); //Bring CSN low flash_csn_low(); //Write OPCODE flash_transfer_byte(WR_STATUS); //Write the three addresses flash_transfer_byte(byte); //Bring CSN high flash_csn_high(); }
/* * Erase 64k bytes of data. It takes about 1s before WIP goes low! */ static void erase_sector(unsigned long offset) { int s; wait_ready(); write_enable(); s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_SE); spi_tx(offset >> 16); /* MSB */ spi_tx(offset >> 8); spi_tx(offset >> 0); /* LSB */ SPI_FLASH_DISABLE(); splx(s); }
/* * Erase the whole flash memory * * Returns 0 if successful, non-zero otherwise. */ static int erase_chip(struct m25p *flash) { DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB\n", flash->spi->dev.bus_id, __func__, flash->mtd.size / 1024); /* Wait until finished previous write command. */ if (wait_till_ready(flash)) return 1; /* Send write enable, then erase commands. */ write_enable(flash); /* Set up command buffer. */ flash->command[0] = OPCODE_CHIP_ERASE; spi_write(flash->spi, flash->command, 1); return 0; }
/* * Erase 64k bytes of data. It takes about 1s before WIP goes low! */ static void erase_sector(unsigned long offset) { int s; wait_ready(); write_enable(); s = splhigh(); SPI_FLASH_ENABLE(); FASTSPI_TX(SPI_FLASH_INS_SE); FASTSPI_TX(offset >> 16); /* MSB */ FASTSPI_TX(offset >> 8); FASTSPI_TX(offset >> 0); /* LSB */ SPI_WAITFORTx_ENDED(); SPI_FLASH_DISABLE(); splx(s); }
static int macronix_quad_enable(struct spi_nor *nor) { int ret, val; val = read_sr(nor); write_enable(nor); nor->cmd_buf[0] = val | SR_QUAD_EN_MX; nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); if (wait_till_ready(nor)) return 1; ret = read_sr(nor); if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { dev_err(nor->dev, "Macronix Quad bit not set\n"); return -EINVAL; } return 0; }
void block_erase(uint8_t address[3], uint8_t byte) { //First we need to enable write write_enable(); //Bring CSN low flash_csn_low(); //Write OPCODE flash_transfer_byte(byte); //Write the three addresses flash_transfer_byte(address[2]); flash_transfer_byte(address[1]); flash_transfer_byte(address[0]); //Bring CSN high flash_csn_high(); //Loop until erase actually has taken place. while(flash_busy() == 1); }
/* * Erase one sector of flash memory at offset ``offset'' which is any * address within the sector which should be erased. * * Returns 0 if successful, non-zero otherwise. */ static int erase_sector(struct m25p *flash, u32 offset) { DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n", flash->spi->dev.bus_id, __FUNCTION__, flash->mtd.erasesize / 1024, offset); /* Wait until finished previous write command. */ if (wait_till_ready(flash)) return 1; /* Send write enable, then erase commands. */ write_enable(flash); /* Set up command buffer. */ flash->command[0] = flash->erase_opcode; flash->command[1] = offset >> 16; flash->command[2] = offset >> 8; flash->command[3] = offset; spi_write(flash->spi, flash->command, sizeof(flash->command)); return 0; }
static int spansion_quad_enable(struct spi_nor *nor) { int ret; int quad_en = CR_QUAD_EN_SPAN << 8; write_enable(nor); ret = write_sr_cr(nor, quad_en); if (ret < 0) { dev_err(nor->dev, "error while writing configuration register\n"); return -EINVAL; } /* read back and check it */ ret = read_cr(nor); if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { dev_err(nor->dev, "Spansion Quad bit not set\n"); return -EINVAL; } return 0; }
static size_t program_sector(size_t addr) { static struct spi_ctx_bare sp_ctx; static struct sg tx_sg[2]; static uint8_t header[4]; size_t len = FLASH_SECTOR_SIZE; write_enable(); header[0] = EZPORT_SP; header[1] = addr >> 16; header[2] = addr >> 8; header[3] = addr; sg_init(tx_sg, (void *)header, 4, _binary_payload_bin_start + addr, len); spi_queue_xfer_sg(&sp_ctx, EZPORT_SPI_CS, tx_sg, NULL, NULL, NULL); check_status(); return (addr + len); }
/* * Erase an address range on the flash chip. The address range may extend * one or more erase sectors. Return an error is there is a problem erasing. */ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) { struct m25p *flash = mtd_to_m25p(mtd); u32 addr,len; uint64_t tmpdiv; int rem, rem1; DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", flash->spi->dev.bus_id, __FUNCTION__, "at", (u32)instr->addr, instr->len); /* sanity checks */ if (instr->addr + instr->len > device_size(&(flash->mtd))) return -EINVAL; tmpdiv = (uint64_t) instr->addr; rem = do_div(tmpdiv, mtd->erasesize); tmpdiv = (uint64_t) instr->len; rem1 = do_div(tmpdiv, mtd->erasesize); if (rem != 0 || rem1 != 0) { return -EINVAL; } addr = instr->addr; len = instr->len; mutex_lock(&flash->lock); /* REVISIT in some cases we could speed up erasing large regions * by using OPCODE_SE instead of OPCODE_BE_4K */ /* now erase those sectors */ while (len) { #ifdef CONFIG_MIPS_BRCM97XXX /* BSPI remaps each 4MB segment */ if (erase_sector(flash, (addr + 0x400000) & 0xffffff)) { #else if (erase_sector(flash, addr)) { #endif instr->state = MTD_ERASE_FAILED; mutex_unlock(&flash->lock); return -EIO; } addr += mtd->erasesize; len -= mtd->erasesize; } mutex_unlock(&flash->lock); instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); return 0; } /* * Read an address range from the flash chip. The address range * may be any size provided it is within the physical boundaries. */ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct m25p *flash = mtd_to_m25p(mtd); struct spi_transfer t[2]; struct spi_message m; size_t total_len = len; DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", flash->spi->dev.bus_id, __FUNCTION__, "from", (u32)from, len); /* sanity checks */ if (!len) return 0; if (from + len > device_size(&(flash->mtd))) return -EINVAL; if (retlen) *retlen = 0; total_len = len; while(total_len) { len = total_len; #if 0 //defined(BRCM_SPI_SS_WAR) /* * For testing purposes only - read 12 bytes at a time: * * 3548a0 MSPI has a 12-byte limit (PR42350). * MSPI emulated via BSPI has no such limit. * In production BSPI is always used because it is much faster. */ if(len > 12) len = 12; #endif #ifdef CONFIG_MIPS_BRCM97XXX /* don't cross a 4MB boundary due to remapping */ len = min(len, (0x400000 - ((u32)from & 0x3fffff))); #endif spi_message_init(&m); memset(t, 0, (sizeof t)); t[0].tx_buf = flash->command; t[0].len = sizeof(flash->command); spi_message_add_tail(&t[0], &m); t[1].rx_buf = buf; t[1].len = len; spi_message_add_tail(&t[1], &m); /* Byte count starts at zero. */ mutex_lock(&flash->lock); /* Wait till previous write/erase is done. */ if (wait_till_ready(flash)) { /* REVISIT status return?? */ mutex_unlock(&flash->lock); return 1; } /* FIXME switch to OPCODE_FAST_READ. It's required for higher * clocks; and at this writing, every chip this driver handles * supports that opcode. */ /* Set up the write data buffer. */ flash->command[0] = OPCODE_READ; #ifdef CONFIG_MIPS_BRCM97XXX /* BSPI remaps each 4MB segment */ flash->command[1] = ((from >> 16) + 0x40) & 0xff; #else flash->command[1] = from >> 16; #endif flash->command[2] = from >> 8; flash->command[3] = from; spi_sync(flash->spi, &m); *retlen += m.actual_length - sizeof(flash->command); mutex_unlock(&flash->lock); from += len; buf += len; total_len -= len; } return 0; } /* * Write an address range to the flash chip. Data must be written in * FLASH_PAGESIZE chunks. The address range may be any size provided * it is within the physical boundaries. */ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct m25p *flash = mtd_to_m25p(mtd); u32 page_offset, page_size; struct spi_transfer t[2]; struct spi_message m; DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", flash->spi->dev.bus_id, __FUNCTION__, "to", (u32)to, len); if (retlen) *retlen = 0; /* sanity checks */ if (!len) return(0); if (to + len > device_size(&(flash->mtd))) return -EINVAL; #ifdef BRCM_SPI_SS_WAR if(len > 12) return -EIO; #endif spi_message_init(&m); memset(t, 0, (sizeof t)); t[0].tx_buf = flash->command; t[0].len = sizeof(flash->command); spi_message_add_tail(&t[0], &m); t[1].tx_buf = buf; spi_message_add_tail(&t[1], &m); mutex_lock(&flash->lock); /* Wait until finished previous write command. */ if (wait_till_ready(flash)) return 1; write_enable(flash); /* Set up the opcode in the write buffer. */ flash->command[0] = OPCODE_PP; #ifdef CONFIG_MIPS_BRCM97XXX /* BSPI remaps each 4MB segment */ flash->command[1] = ((to >> 16) + 0x40) & 0xff; #else flash->command[1] = to >> 16; #endif flash->command[2] = to >> 8; flash->command[3] = to; /* what page do we start with? */ page_offset = to % FLASH_PAGESIZE; /* do all the bytes fit onto one page? */ if (page_offset + len <= FLASH_PAGESIZE) { t[1].len = len; spi_sync(flash->spi, &m); *retlen = m.actual_length - sizeof(flash->command); } else { u32 i; /* the size of data remaining on the first page */ page_size = FLASH_PAGESIZE - page_offset; t[1].len = page_size; spi_sync(flash->spi, &m); *retlen = m.actual_length - sizeof(flash->command); /* write everything in PAGESIZE chunks */ for (i = page_size; i < len; i += page_size) { page_size = len - i; if (page_size > FLASH_PAGESIZE) page_size = FLASH_PAGESIZE; /* write the next page to flash */ #ifdef CONFIG_MIPS_BRCM97XXX /* BSPI remaps each 4MB segment */ flash->command[1] = (((to + i) >> 16) + 0x40) & 0xff; #else flash->command[1] = (to + i) >> 16; #endif flash->command[2] = (to + i) >> 8; flash->command[3] = (to + i); t[1].tx_buf = buf + i; t[1].len = page_size; wait_till_ready(flash); write_enable(flash); spi_sync(flash->spi, &m); if (retlen) *retlen += m.actual_length - sizeof(flash->command); } } mutex_unlock(&flash->lock); return 0; } /****************************************************************************/ /* * SPI device driver setup and teardown */ struct flash_info { char *name; /* JEDEC id zero means "no ID" (most older chips); otherwise it has * a high byte of zero plus three data bytes: the manufacturer id, * then a two byte device id. */ u32 jedec_id; /* The size listed here is what works with OPCODE_SE, which isn't * necessarily called a "sector" by the vendor. */ unsigned sector_size; u16 n_sectors; u16 flags; #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ }; /* NOTE: double check command sets and memory organization when you add * more flash chips. This current list focusses on newer chips, which * have been converging on command sets which including JEDEC ID. */ static struct flash_info __devinitdata m25p_data [] = { /* Atmel -- some are (confusingly) marketed as "DataFlash" */ { "at25fs010", 0x1f6601, 32 * 1024, 4, SECT_4K, }, { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, }, { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, }, { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, }, { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, }, { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, }, { "at26df321", 0x1f4701, 64 * 1024, 64, SECT_4K, }, /* Spansion -- single (large) sector size only, at least * for the chips listed here (without boot sectors). */ { "s25sl004a", 0x010212, 64 * 1024, 8, }, { "s25sl008a", 0x010213, 64 * 1024, 16, }, { "s25sl016a", 0x010214, 64 * 1024, 32, }, { "s25sl032a", 0x010215, 64 * 1024, 64, }, { "s25sl064a", 0x010216, 64 * 1024, 128, }, #ifdef CONFIG_MIPS_BRCM97XXX { "s25fl128p", 0x012018, 64 * 1024, 256, }, #endif /* SST -- large erase sizes are "overlays", "sectors" are 4K */ { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, }, { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, }, { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, }, { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, }, /* ST Microelectronics -- newer production may have feature updates */ { "m25p05", 0x202010, 32 * 1024, 2, }, { "m25p10", 0x202011, 32 * 1024, 4, }, { "m25p20", 0x202012, 64 * 1024, 4, }, { "m25p40", 0x202013, 64 * 1024, 8, }, #ifndef CONFIG_MIPS_BRCM97XXX /* ID 0 is detected when there's nothing on the bus */ { "m25p80", 0, 64 * 1024, 16, }, #endif { "m25p16", 0x202015, 64 * 1024, 32, }, { "m25p32", 0x202016, 64 * 1024, 64, }, { "m25p64", 0x202017, 64 * 1024, 128, }, { "m25p128", 0x202018, 256 * 1024, 64, }, { "m45pe80", 0x204014, 64 * 1024, 16, }, { "m45pe16", 0x204015, 64 * 1024, 32, }, { "m25pe80", 0x208014, 64 * 1024, 16, }, { "m25pe16", 0x208015, 64 * 1024, 32, SECT_4K, }, /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, }, { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, }, { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, }, { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, }, { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, }, { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, }, { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, }, }; static struct flash_info *__devinit jedec_probe(struct spi_device *spi) { int tmp; u8 code = OPCODE_RDID; u8 id[3]; u32 jedec; struct flash_info *info; /* JEDEC also defines an optional "extended device information" * string for after vendor-specific data, after the three bytes * we use here. Supporting some chips might require using it. */ tmp = spi_write_then_read(spi, &code, 1, id, 3); if (tmp < 0) { DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", spi->dev.bus_id, tmp); return NULL; } jedec = id[0]; jedec = jedec << 8; jedec |= id[1]; jedec = jedec << 8; jedec |= id[2]; for (tmp = 0, info = m25p_data; tmp < ARRAY_SIZE(m25p_data); tmp++, info++) { if (info->jedec_id == jedec) return info; } dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec); return NULL; }
int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, enum read_mode mode) { struct flash_info *info; struct flash_platform_data *data; struct device *dev = nor->dev; struct mtd_info *mtd = nor->mtd; struct device_node *np = dev->of_node; int ret; int i; ret = spi_nor_check(nor); if (ret) return ret; /* Platform data helps sort out which chip type we have, as * well as how this board partitions it. If we don't have * a chip ID, try the JEDEC id commands; they'll work for most * newer chips, even if we don't recognize the particular chip. */ data = dev_get_platdata(dev); if (data && data->type) { const struct spi_device_id *plat_id; for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) { plat_id = &spi_nor_ids[i]; if (strcmp(data->type, plat_id->name)) continue; break; } if (i < ARRAY_SIZE(spi_nor_ids) - 1) id = plat_id; else dev_warn(dev, "unrecognized id %s\n", data->type); } info = (void *)id->driver_data; if (info->jedec_id) { const struct spi_device_id *jid; jid = jedec_probe(nor); if (IS_ERR(jid)) { return PTR_ERR(jid); } else if (jid != id) { /* * JEDEC knows better, so overwrite platform ID. We * can't trust partitions any longer, but we'll let * mtd apply them anyway, since some partitions may be * marked read-only, and we don't want to lose that * information, even if it's not 100% accurate. */ dev_warn(dev, "found %s, expected %s\n", jid->name, id->name); id = jid; info = (void *)jid->driver_data; } } mutex_init(&nor->lock); /* * Atmel, SST and Intel/Numonyx serial nor tend to power * up with the software protection bits set */ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { write_enable(nor); write_sr(nor, 0); } if (data && data->name) mtd->name = data->name; else mtd->name = dev_name(dev); mtd->type = MTD_NORFLASH; mtd->writesize = 1; mtd->flags = MTD_CAP_NORFLASH; mtd->size = info->sector_size * info->n_sectors; mtd->_erase = spi_nor_erase; mtd->_read = spi_nor_read; /* nor protection support for STmicro chips */ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { mtd->_lock = spi_nor_lock; mtd->_unlock = spi_nor_unlock; } /* sst nor chips use AAI word program */ if (info->flags & SST_WRITE) mtd->_write = sst_write; else mtd->_write = spi_nor_write; /* prefer "small sector" erase if possible */ if (info->flags & SECT_4K) { nor->erase_opcode = SPINOR_OP_BE_4K; mtd->erasesize = 4096; } else if (info->flags & SECT_4K_PMC) { nor->erase_opcode = SPINOR_OP_BE_4K_PMC; mtd->erasesize = 4096; } else { nor->erase_opcode = SPINOR_OP_SE; mtd->erasesize = info->sector_size; } if (info->flags & SPI_NOR_NO_ERASE) mtd->flags |= MTD_NO_ERASE; mtd->dev.parent = dev; nor->page_size = info->page_size; mtd->writebufsize = nor->page_size; if (np) { /* If we were instantiated by DT, use it */ if (of_property_read_bool(np, "m25p,fast-read")) nor->flash_read = SPI_NOR_FAST; else nor->flash_read = SPI_NOR_NORMAL; } else { /* If we weren't instantiated by DT, default to fast-read */ nor->flash_read = SPI_NOR_FAST; } /* Some devices cannot do fast-read, no matter what DT tells us */ if (info->flags & SPI_NOR_NO_FR) nor->flash_read = SPI_NOR_NORMAL; /* Quad/Dual-read mode takes precedence over fast/normal */ if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { ret = set_quad_mode(nor, info->jedec_id); if (ret) { dev_err(dev, "quad mode not supported\n"); return ret; } nor->flash_read = SPI_NOR_QUAD; } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) { nor->flash_read = SPI_NOR_DUAL; } /* Default commands */ switch (nor->flash_read) { case SPI_NOR_QUAD: nor->read_opcode = SPINOR_OP_READ_1_1_4; break; case SPI_NOR_DUAL: nor->read_opcode = SPINOR_OP_READ_1_1_2; break; case SPI_NOR_FAST: nor->read_opcode = SPINOR_OP_READ_FAST; break; case SPI_NOR_NORMAL: nor->read_opcode = SPINOR_OP_READ; break; default: dev_err(dev, "No Read opcode defined\n"); return -EINVAL; } nor->program_opcode = SPINOR_OP_PP; if (info->addr_width) nor->addr_width = info->addr_width; else if (mtd->size > 0x1000000) { /* enable 4-byte addressing if the device exceeds 16MiB */ nor->addr_width = 4; if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { /* Dedicated 4-byte command set */ switch (nor->flash_read) { case SPI_NOR_QUAD: nor->read_opcode = SPINOR_OP_READ4_1_1_4; break; case SPI_NOR_DUAL: nor->read_opcode = SPINOR_OP_READ4_1_1_2; break; case SPI_NOR_FAST: nor->read_opcode = SPINOR_OP_READ4_FAST; break; case SPI_NOR_NORMAL: nor->read_opcode = SPINOR_OP_READ4; break; } nor->program_opcode = SPINOR_OP_PP_4B; /* No small sector erase for 4-byte command set */ nor->erase_opcode = SPINOR_OP_SE_4B; mtd->erasesize = info->sector_size; } else set_4byte(nor, info->jedec_id, 1); } else { nor->addr_width = 3; } nor->read_dummy = spi_nor_read_dummy_cycles(nor); dev_info(dev, "%s (%lld Kbytes)\n", id->name, (long long)mtd->size >> 10); dev_dbg(dev, "mtd .name = %s, .size = 0x%llx (%lldMiB), " ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20), mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions); if (mtd->numeraseregions) for (i = 0; i < mtd->numeraseregions; i++) dev_dbg(dev, "mtd.eraseregions[%d] = { .offset = 0x%llx, " ".erasesize = 0x%.8x (%uKiB), " ".numblocks = %d }\n", i, (long long)mtd->eraseregions[i].offset, mtd->eraseregions[i].erasesize, mtd->eraseregions[i].erasesize / 1024, mtd->eraseregions[i].numblocks); return 0; }
void SST25VF016B::eraseChip(void) { write_enable(); SPI.transfer(CE, CHIP_ERASE); // Chip-Erase }
static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct spi_nor *nor = mtd_to_spi_nor(mtd); size_t actual; int ret; dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); if (ret) return ret; /* Wait until finished previous write command. */ ret = wait_till_ready(nor); if (ret) goto time_out; write_enable(nor); nor->sst_write_second = false; actual = to % 2; /* Start write from odd address. */ if (actual) { nor->program_opcode = SPINOR_OP_BP; /* write one byte. */ nor->write(nor, to, 1, retlen, buf); ret = wait_till_ready(nor); if (ret) goto time_out; } to += actual; /* Write out most of the data here. */ for (; actual < len - 1; actual += 2) { nor->program_opcode = SPINOR_OP_AAI_WP; /* write two bytes. */ nor->write(nor, to, 2, retlen, buf + actual); ret = wait_till_ready(nor); if (ret) goto time_out; to += 2; nor->sst_write_second = true; } nor->sst_write_second = false; write_disable(nor); ret = wait_till_ready(nor); if (ret) goto time_out; /* Write out trailing byte if it exists. */ if (actual != len) { write_enable(nor); nor->program_opcode = SPINOR_OP_BP; nor->write(nor, to, 1, retlen, buf + actual); ret = wait_till_ready(nor); if (ret) goto time_out; write_disable(nor); } time_out: spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); return ret; }
/* * Write an address range to the flash chip. Data must be written in * FLASH_PAGESIZE chunks. The address range may be any size provided * it is within the physical boundaries. */ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct m25p *flash = mtd_to_m25p(mtd); u32 page_offset, page_size; struct spi_transfer t[2]; struct spi_message m; DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", flash->spi->dev.bus_id, __func__, "to", (u32)to, len); if (retlen) *retlen = 0; /* sanity checks */ if (!len) return(0); if (to + len > flash->mtd.size) return -EINVAL; spi_message_init(&m); memset(t, 0, (sizeof t)); t[0].tx_buf = flash->command; t[0].len = CMD_SIZE; spi_message_add_tail(&t[0], &m); t[1].tx_buf = buf; spi_message_add_tail(&t[1], &m); mutex_lock(&flash->lock); /* Wait until finished previous write command. */ if (wait_till_ready(flash)) { mutex_unlock(&flash->lock); return 1; } write_enable(flash); /* Set up the opcode in the write buffer. */ flash->command[0] = OPCODE_PP; flash->command[1] = to >> 16; flash->command[2] = to >> 8; flash->command[3] = to; /* what page do we start with? */ page_offset = to % FLASH_PAGESIZE; /* do all the bytes fit onto one page? */ if (page_offset + len <= FLASH_PAGESIZE) { t[1].len = len; spi_sync(flash->spi, &m); *retlen = m.actual_length - CMD_SIZE; } else { u32 i; /* the size of data remaining on the first page */ page_size = FLASH_PAGESIZE - page_offset; t[1].len = page_size; spi_sync(flash->spi, &m); *retlen = m.actual_length - CMD_SIZE; /* write everything in PAGESIZE chunks */ for (i = page_size; i < len; i += page_size) { page_size = len - i; if (page_size > FLASH_PAGESIZE) page_size = FLASH_PAGESIZE; /* write the next page to flash */ flash->command[1] = (to + i) >> 16; flash->command[2] = (to + i) >> 8; flash->command[3] = (to + i); t[1].tx_buf = buf + i; t[1].len = page_size; wait_till_ready(flash); write_enable(flash); spi_sync(flash->spi, &m); if (retlen) *retlen += m.actual_length - CMD_SIZE; } } mutex_unlock(&flash->lock); return 0; }
static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct m25p *flash = mtd_to_m25p(mtd); struct spi_transfer t[2]; struct spi_message m; size_t actual; int cmd_sz, ret; if (retlen) *retlen = 0; /* sanity checks */ if (!len) return 0; if (to + len > flash->mtd.size) return -EINVAL; spi_message_init(&m); memset(t, 0, (sizeof t)); t[0].tx_buf = flash->command; t[0].len = CMD_SIZE; spi_message_add_tail(&t[0], &m); t[1].tx_buf = buf; spi_message_add_tail(&t[1], &m); mutex_lock(&flash->lock); /* Wait until finished previous write command. */ ret = wait_till_ready(flash); if (ret) goto time_out; write_enable(flash); actual = to % 2; /* Start write from odd address. */ if (actual) { flash->command[0] = OPCODE_BP; flash->command[1] = to >> 16; flash->command[2] = to >> 8; flash->command[3] = to; /* write one byte. */ t[1].len = 1; spi_sync(flash->spi, &m); ret = wait_till_ready(flash); if (ret) goto time_out; *retlen += m.actual_length - CMD_SIZE; } to += actual; flash->command[0] = OPCODE_AAI_WP; flash->command[1] = to >> 16; flash->command[2] = to >> 8; flash->command[3] = to; cmd_sz = CMD_SIZE; for (; actual < len - 1; actual += 2) { t[0].len = cmd_sz; /* write two bytes. */ t[1].len = 2; t[1].tx_buf = buf + actual; spi_sync(flash->spi, &m); ret = wait_till_ready(flash); if (ret) goto time_out; *retlen += m.actual_length - cmd_sz; cmd_sz = 1; to += 2; } write_disable(flash); ret = wait_till_ready(flash); if (ret) goto time_out; if (actual != len) { write_enable(flash); flash->command[0] = OPCODE_BP; flash->command[1] = to >> 16; flash->command[2] = to >> 8; flash->command[3] = to; t[0].len = CMD_SIZE; t[1].len = 1; t[1].tx_buf = buf + actual; spi_sync(flash->spi, &m); ret = wait_till_ready(flash); if (ret) goto time_out; *retlen += m.actual_length - CMD_SIZE; write_disable(flash); }