sunxi-fel增加对16M以上Flash的支持

由于SPI flash 的地址是24bit,也就是最大16M 地址空间,所以对于32M
flash,需要增加bank切换支持。

uboot中有 CONFIG_SPI_FLASH_BAR 选项可以使能bank切换。

但是sunxi-fel中尚未支持,所以下载的时候超出16M会循环覆盖掉。

这里介绍对sunxi-fel增加16M以上flash支持的方法。

u-boot的支持

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;
}

sunxi-fel的支持

#define CMD_WRITE_ENABLE 0x06
#define SPI_FLASH_16MB_BOUN  0x1000000
# define CMD_BANKADDR_BRWR              0x17    //only SPANSION flash use it
# define CMD_BANKADDR_BRRD              0x16
# define CMD_EXTNADDR_WREAR             0xC5
# define CMD_EXTNADDR_RDEAR             0xC8
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;

重新编译sunxi-fel后就可以烧录32M flash了~