1.clong sunxi-tools
git clone https://github.com/Icenowy/sunxi-tools.git -b f1c100s-spiflash
2.install libusb
sudo apt install libz libusb-1.0-0-dev
2.1
sudo git branch -a
2.2
sudo git checkout //NAME
2.3
sudo make clean
3.make make install
4.check ver
sudo sunxi-fel ver
5.check soc
sudo sunxi-fel -l
6.check spiflash
sudo sunxi-fel spiflash-info
7.read
sudo sunxi-fel spiflash-read 地址 长度 存放数据的文件路径
8.write
sudo sunxi-fel spiflash-write 地址 长度 存放数据的文件路径
sudo sunxi-fel -p spiflash-write 0 u-boot-sunxi-with-spl.bin
9.分区
mtd0 1024kb spl+uboot 0x0000000-0x0100000 : “uboot”
mtd1 64kb dtb 0x0100000-0x0110000 : “dtb”
mtd2 4096kb linux 0x0110000-0x0510000 : “kernel”
mtd3 ----- rootfs 0x0510000-0x2000000 : “rootfs”
10.16M以上spi falsh
修改drivers/mtd/spi/spi_flash.c
static int write_bar(struct spi_flash *flash, u32 offset)
{
u8 cmd, bank_sel;
int ret;
bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift);
if (bank_sel == flash->bank_curr)
goto bar_end;
cmd = flash->bank_write_cmd;
ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
if (ret < 0) {
debug("SF: fail to write bank register\n");
return ret;
}
bar_end:
flash->bank_curr = bank_sel;
return flash->bank_curr;
}
10.1.新增fel-spiflash.c
#define CMD_WRITE_ENABLE 0x06
#define SPI_FLASH_16MB_BOUN 0x1000000
size_t bank_curr = 0;
void aw_fel_spiflash_write_helper(feldev_handle *dev,
uint32_t offset, void *buf, size_t len,
size_t erase_size, uint8_t erase_cmd,
size_t program_size, uint8_t program_cmd)
{
uint8_t *buf8 = (uint8_t *)buf;
size_t max_chunk_size = dev->soc_info->scratch_addr - dev->soc_info->spl_addr;
size_t cmd_idx, bank_sel;
if (max_chunk_size > 0x1000)
max_chunk_size = 0x1000;
uint8_t *cmdbuf = malloc(max_chunk_size);
cmd_idx = 0;
prepare_spi_batch_data_transfer(dev, dev->soc_info->spl_addr);
//add bank support
{
cmd_idx = 0;
bank_sel = offset /SPI_FLASH_16MB_BOUN;
if (bank_sel == bank_curr)
goto bar_end;
/* Emit write enable command */
cmdbuf[cmd_idx++] = 0;
cmdbuf[cmd_idx++] = 1;
cmdbuf[cmd_idx++] = CMD_WRITE_ENABLE;
/* Emit write bank */
cmdbuf[cmd_idx++] = 0;
cmdbuf[cmd_idx++] = 2;
cmdbuf[cmd_idx++] = CMD_EXTNADDR_WREAR;
cmdbuf[cmd_idx++] = offset >> 24;
/* Emit wait for completion */
cmdbuf[cmd_idx++] = 0xFF;
cmdbuf[cmd_idx++] = 0xFF;
/* Emit the end marker */
cmdbuf[cmd_idx++] = 0;
cmdbuf[cmd_idx++] = 0;
aw_fel_write(dev, cmdbuf, dev->soc_info->spl_addr, cmd_idx);
aw_fel_remotefunc_execute(dev, NULL);
bar_end:
bank_curr = bank_sel;
}
cmd_idx = 0;
11.flash驱动drivers/mtd/spi/spi_flash_ids.c
const struct spi_flash_info spi_flash_ids[] = {
{“w25p80”, INFO(0xef2014, 0x0, 64 * 1024, 16, 0) },
{“w25p16”, INFO(0xef2015, 0x0, 64 * 1024, 32, 0) },
{“w25p32”, INFO(0xef2016, 0x0, 64 * 1024, 64, 0) },
{“w25x40”, INFO(0xef3013, 0x0, 64 * 1024, 8, SECT_4K) },
{“w25x16”, INFO(0xef3015, 0x0, 64 * 1024, 32, SECT_4K) },
{“w25x32”, INFO(0xef3016, 0x0, 64 * 1024, 64, SECT_4K) },
{“w25x64”, INFO(0xef3017, 0x0, 64 * 1024, 128, SECT_4K) },
{“w25q80bl”, INFO(0xef4014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K) },
{“w25q16cl”, INFO(0xef4015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) },
{“w25q32bv”, INFO(0xef4016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) },
{“w25q64cv”, INFO(0xef4017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) },
{“w25q128bv”, INFO(0xef4018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) },
{“w25q256”, INFO(0xef4019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) },
{“w25q80bw”, INFO(0xef5014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K) },
{“w25q16dw”, INFO(0xef6015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) },
{“w25q32dw”, INFO(0xef6016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) },
{“w25q64dw”, INFO(0xef6017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) },
{“w25q128fw”, INFO(0xef6018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) },
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)
.id = {
((_jedec_id) >> 16) & 0xff,
((_jedec_id) >> 8) & 0xff,
(_jedec_id) & 0xff,
((_ext_id) >> 8) & 0xff,
(_ext_id) & 0xff,
},
.id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),
.sector_size = (_sector_size),
.n_sectors = (_n_sectors),
.page_size = 256,
.flags = (_flags),
struct spi_flash_info {
/* Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) */
const char *name;
/*
* This array stores the ID bytes.
* The first three bytes are the JEDIC ID.
* JEDEC ID zero means "no ID" (mostly older chips).
*/
u8 id[SPI_FLASH_MAX_ID_LEN];
u8 id_len;
/*
* The size listed here is what works with SPINOR_OP_SE, which isn't
* necessarily called a "sector" by the vendor.
*/
u32 sector_size;
u32 n_sectors;
u16 page_size;
u16 flags;
#define SECT_4K BIT(0) /* CMD_ERASE_4K works uniformly /
#define E_FSR BIT(1) / use flag status register for /
#define SST_WR BIT(2) / use SST byte/word programming /
#define WR_QPP BIT(3) / use Quad Page Program /
#define RD_QUAD BIT(4) / use Quad Read /
#define RD_DUAL BIT(5) / use Dual Read /
#define RD_QUADIO BIT(6) / use Quad IO Read /
#define RD_DUALIO BIT(7) / use Dual IO Read */
#define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO)
};