mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-15 19:08:54 +00:00
196 lines
4.7 KiB
C
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
|