Files
luban-lite-t3e-pro/bsp/peripheral/spinor_sfud/src/sfud_qe.c
刘可亮 7bbc029dae v1.0.0
2023-08-30 16:21:18 +08:00

196 lines
4.7 KiB
C

/*
* Copyright (c) 2022, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "../inc/sfud.h"
#include <string.h>
#include "sfud_flash_def.h"
#ifdef SFUD_USING_QSPI
/* Status Register 2 bits. */
#define SR2_QUAD_EN_BIT1 (1 << 1)
#define SR1_QUAD_EN_BIT6 (1 << 6)
#define SR2_QUAD_EN_BIT7 (1 << 7)
static const sfud_qspi_flash_qe_info qspi_flash_qe_info_table[] = SFUD_FLASH_QE_INFO_TABLE;
sfud_err sfud_read_cr(const sfud_flash *flash, uint8_t *status) {
uint8_t cmd = SFUD_CMD_READ_CONFIG_REGISTER;
SFUD_ASSERT(flash);
SFUD_ASSERT(status);
return flash->spi.wr(&flash->spi, &cmd, 1, status, 1);
}
static int spi_nor_write_16bit_cr_and_check(sfud_flash *flash, uint8_t cr)
{
int ret;
uint8_t sr_cr[2];
uint8_t sr_written;
/* Keep the current value of the Status Register 1. */
ret = sfud_read_status(flash, sr_cr);
if (ret)
return ret;
sr_cr[1] = cr;
ret = sfud_write_status2(flash, sr_cr);
if (ret)
return ret;
sr_written = sr_cr[0];
ret = sfud_read_status(flash, sr_cr);
if (ret)
return ret;
if (sr_written != sr_cr[0]) {
SFUD_INFO("SR: Read back test failed\n");
return -1;
}
if (flash->flags & SNOR_F_NO_READ_CR)
return 0;
ret = sfud_read_cr(flash, &sr_cr[1]);
if (ret)
return ret;
if (cr != sr_cr[1]) {
/* write again, some flash can not support write 16bit base register1 addr. */
sfud_write_reg(flash, SFUD_CMD_WRITE_STATUS2_REGISTER, &cr);
sfud_read_cr(flash, &sr_cr[1]);
if (cr != sr_cr[1]) {
SFUD_INFO("CR: read back test failed\n");
return -1;
}
}
return 0;
}
static int spi_nor_write_sr1_and_check(sfud_flash *flash, uint8_t sr1)
{
int ret;
uint8_t status;
ret = sfud_write_status(flash, false, sr1);
if (ret)
return ret;
ret = sfud_read_status(flash, &status);
if (ret)
return ret;
if (status!= sr1) {
SFUD_INFO("SR1: read back test failed\n");
return -1;
}
return 0;
}
/**
* spi_nor_sr1_bit6_quad_enable() - Set the Quad Enable BIT(6) in the Status
* Register 1.
*
* Bit 6 of the Status Register 1 is the QE bit for Macronix like QSPI memories.
*
* Return: 0 on success, -errno otherwise.
*/
int spi_nor_sr1_bit6_quad_enable(sfud_flash *flash)
{
int ret;
uint8_t sr;
ret = sfud_read_status(flash, &sr);
if (ret)
return ret;
if (sr & SR1_QUAD_EN_BIT6)
return 0;
sr |= SR1_QUAD_EN_BIT6;
return spi_nor_write_sr1_and_check(flash, sr);
}
/**
* spi_nor_sr2_bit1_quad_enable() - set the Quad Enable BIT(1) in the Status
* Register 2.
* @nor: pointer to a 'struct spi_nor'.
*
* Bit 1 of the Status Register 2 is the QE bit for Spansion like QSPI memories.
*
* Return: 0 on success, -errno otherwise.
*/
int spi_nor_sr2_bit1_quad_enable(sfud_flash *flash)
{
int ret;
uint8_t buf[2];
if (flash->flags & SNOR_F_NO_READ_CR)
return spi_nor_write_16bit_cr_and_check(flash, SR2_QUAD_EN_BIT1);
ret = sfud_read_cr(flash, buf);
if (ret)
return ret;
if (buf[0] & SR2_QUAD_EN_BIT1)
return 0;
buf[0] |= SR2_QUAD_EN_BIT1;
return spi_nor_write_16bit_cr_and_check(flash, buf[0]);
}
extern sfud_err set_write_enabled(const sfud_flash *flash, bool enabled);
#define QUAD_EN_BIT(offset) 1UL << offset
int spi_nor_quad_enable(sfud_flash *flash)
{
uint8_t buf_data = 0;
uint8_t wr_reg_status = 0;
uint8_t rd_reg_status = 0;
uint8_t qe_bit = 0;
/* get wr_reg_status, rd_reg_status and qe_bit, If don't found, the default is compatible sr2_bit1 or SFDP */
for (int i = 0;
i < sizeof(qspi_flash_qe_info_table) / sizeof(sfud_qspi_flash_qe_info);
i++) {
if ((qspi_flash_qe_info_table[i].mf_id == flash->chip.mf_id) &&
(qspi_flash_qe_info_table[i].type_id == flash->chip.type_id) &&
(qspi_flash_qe_info_table[i].capacity_id ==
flash->chip.capacity_id)) {
wr_reg_status = qspi_flash_qe_info_table[i].wr_reg_status;
rd_reg_status = qspi_flash_qe_info_table[i].rd_reg_status;
qe_bit = qspi_flash_qe_info_table[i].qe_bit;
goto qe_table;
}
}
goto sr2_bit1;
qe_table:
set_write_enabled(flash, true);
sfud_read_reg(flash, rd_reg_status, &buf_data);
buf_data |= QUAD_EN_BIT(qe_bit);
sfud_write_reg(flash, wr_reg_status, &buf_data);
sfud_read_reg(flash, rd_reg_status, &buf_data);
if (buf_data & QUAD_EN_BIT(qe_bit)) {
return 0;
}
return 1;
sr2_bit1:
spi_nor_sr2_bit1_quad_enable(flash);
return 0;
}
#endif