Author: stefanct Date: Tue Aug 27 20:02:19 2013 New Revision: 1725 URL: http://flashrom.org/trac/flashrom/changeset/1725
Log: Add support for AT45CS1282.
This one is even more strange than the AT45DB chips. Like the AT45DB321C it does not support any power-of-2 page sizes. There is only one asymmetrical eraser and that uses two opcodes.
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at Acked-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at
Modified: trunk/at45db.c trunk/chipdrivers.h trunk/flashchips.c
Modified: trunk/at45db.c ============================================================================== --- trunk/at45db.c Tue Aug 27 20:02:12 2013 (r1724) +++ trunk/at45db.c Tue Aug 27 20:02:19 2013 (r1725) @@ -419,6 +419,47 @@ return at45db_erase(flash, AT45DB_CHIP_ERASE, AT45DB_CHIP_ERASE_ADDR, 500000, 200); }
+/* This one is really special and works only for AT45CS1282. It uses two different opcodes depending on the + * address and has an asymmetric layout. */ +int spi_erase_at45cs_sector(struct flashctx *flash, unsigned int addr, unsigned int blocklen) +{ + const unsigned int page_size = flash->chip->page_size; + const unsigned int total_size = flash->chip->total_size * 1024; + const struct block_eraser be = flash->chip->block_erasers[0]; + const unsigned int sec_0a_top = be.eraseblocks[0].size; + const unsigned int sec_0b_top = be.eraseblocks[0].size + be.eraseblocks[1].size; + + if ((addr + blocklen) > total_size) { + msg_cerr("%s: tried to erase a sector beyond flash boundary: addr=%u, blocklen=%u, size=%u\n", + __func__, addr, blocklen, total_size); + return 1; + } + + bool partial_range = false; + uint8_t opcode = 0x7C; /* Used for all but sector 0a. */ + if (addr < sec_0a_top) { + opcode = 0x50; + /* One single sector of 8 pages at address 0. */ + if (addr != 0 || blocklen != (8 * page_size)) + partial_range = true; + } else if (addr < sec_0b_top) { + /* One single sector of 248 pages adjacent to the first. */ + if (addr != sec_0a_top || blocklen != (248 * page_size)) + partial_range = true; + } else { + /* The rest is filled by 63 aligned sectors of 256 pages. */ + if ((addr % (256 * page_size)) != 0 || (blocklen % (256 * page_size)) != 0) + partial_range = true; + } + if (partial_range) { + msg_cerr("%s: cannot erase partial sectors: addr=%u, blocklen=%u\n", __func__, addr, blocklen); + return 1; + } + + /* Needs up to 4 s for completion, so let's wait 20 seconds in 200 ms steps. */ + return at45db_erase(flash, opcode, at45db_convert_addr(addr, page_size), 200000, 100); +} + static int at45db_fill_buffer1(struct flashctx *flash, uint8_t *bytes, unsigned int off, unsigned int len) { const unsigned int page_size = flash->chip->page_size;
Modified: trunk/chipdrivers.h ============================================================================== --- trunk/chipdrivers.h Tue Aug 27 20:02:12 2013 (r1724) +++ trunk/chipdrivers.h Tue Aug 27 20:02:19 2013 (r1725) @@ -121,6 +121,7 @@ int spi_erase_at45db_block(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_erase_at45db_sector(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_erase_at45db_chip(struct flashctx *flash, unsigned int addr, unsigned int blocklen); +int spi_erase_at45cs_sector(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
/* 82802ab.c */ uint8_t wait_82802ab(struct flashctx *flash);
Modified: trunk/flashchips.c ============================================================================== --- trunk/flashchips.c Tue Aug 27 20:02:12 2013 (r1724) +++ trunk/flashchips.c Tue Aug 27 20:02:19 2013 (r1725) @@ -2323,11 +2323,26 @@ .total_size = 16896 /* No power of two sizes */, .page_size = 1056 /* No power of two sizes */, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ - .tested = TEST_BAD_REW, + /* OTP: 128B total, 64B pre-programmed; read 0x77 (4 dummy bytes); write 0x9A (via buffer) */ + .feature_bits = FEATURE_OTP, + .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .write = NULL /* Incompatible Page write */, - .read = NULL /* Incompatible read */, + .block_erasers = + { + { + .eraseblocks = { + {8 * 1056, 1}, /* sector 0a: opcode 50h */ + {248 * 1056, 1}, /* sector 0b: opcode 7Ch */ + {256 * 1056, 63}, /* sectors 1 - 63: opcode 7Ch */ + }, + .block_erase = spi_erase_at45cs_sector, + } + }, + .printlock = spi_prettyprint_status_register_plain, + .gran = write_gran_1056bytes, + .write = spi_write_at45db, + .read = spi_read_at45db, .voltage = {2700, 3600}, },