- Add s28hl512t, s28hl01gt (Takahiro)
- Rework s25hx_t_post_bfpt_fixup() (Takahiro)
This commit is contained in:
Tom Rini 2022-10-25 09:54:59 -04:00
commit f9d16f2c0d
7 changed files with 83 additions and 51 deletions

View File

@ -179,16 +179,18 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
size_t len, const char *buf, char *cmp_buf, size_t *skipped)
{
char *ptr = (char *)buf;
u32 start_offset = offset % flash->sector_size;
u32 read_offset = offset - start_offset;
debug("offset=%#x, sector_size=%#x, len=%#zx\n",
offset, flash->sector_size, len);
debug("offset=%#x+%#x, sector_size=%#x, len=%#zx\n",
read_offset, start_offset, flash->sector_size, len);
/* Read the entire sector so to allow for rewriting */
if (spi_flash_read(flash, offset, flash->sector_size, cmp_buf))
if (spi_flash_read(flash, read_offset, flash->sector_size, cmp_buf))
return "read";
/* Compare only what is meaningful (len) */
if (memcmp(cmp_buf, buf, len) == 0) {
debug("Skip region %x size %zx: no change\n",
offset, len);
if (memcmp(cmp_buf + start_offset, buf, len) == 0) {
debug("Skip region %x+%x size %zx: no change\n",
start_offset, read_offset, len);
*skipped += len;
return NULL;
}
@ -197,7 +199,7 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
return "erase";
/* If it's a partial sector, copy the data into the temp-buffer */
if (len != flash->sector_size) {
memcpy(cmp_buf, buf, len);
memcpy(cmp_buf + start_offset, buf, len);
ptr = cmp_buf;
}
/* Write one complete sector */
@ -238,6 +240,8 @@ static int spi_flash_update(struct spi_flash *flash, u32 offset,
for (; buf < end && !err_oper; buf += todo, offset += todo) {
todo = min_t(size_t, end - buf, flash->sector_size);
todo = min_t(size_t, end - buf,
flash->sector_size - (offset % flash->sector_size));
if (get_timer(last_update) > 100) {
printf(" \rUpdating, %zu%% %lu B/s",
100 - (end - buf) / scale,

View File

@ -149,7 +149,7 @@ CONFIG_SPI_FLASH_SFDP_SUPPORT=y
CONFIG_SPI_FLASH_SOFT_RESET=y
CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_S28HS512T=y
CONFIG_SPI_FLASH_S28HX_T=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SPI_FLASH_MT35XU=y
# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set

View File

@ -128,7 +128,7 @@ CONFIG_SPI_FLASH_SFDP_SUPPORT=y
CONFIG_SPI_FLASH_SOFT_RESET=y
CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_S28HS512T=y
CONFIG_SPI_FLASH_S28HX_T=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SPI_FLASH_MT35XU=y
CONFIG_PINCTRL=y

View File

@ -166,13 +166,13 @@ config SPI_FLASH_SPANSION
help
Add support for various Spansion SPI flash chips (S25FLxxx)
config SPI_FLASH_S28HS512T
bool "Cypress S28HS512T chip support"
config SPI_FLASH_S28HX_T
bool "Cypress SEMPER Octal (S28) chip support"
depends on SPI_FLASH_SPANSION
help
Add support for the Cypress S28HS512T chip. This is a separate config
because the fixup hooks for this flash add extra size overhead. Boards
that don't use the flash can disable this to save space.
Add support for the Cypress S28HL-T and S28HS-T chip. This is a separate
config because the fixup hooks for this flash add extra size overhead.
Boards that don't use the flash can disable this to save space.
config SPI_FLASH_STMICRO
bool "STMicro SPI flash support"

View File

@ -161,6 +161,7 @@ struct sfdp_header {
#define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */
#define BFPT_DWORD16_SOFT_RST BIT(12)
#define BFPT_DWORD16_EX4B_PWRCYC BIT(21)
#define BFPT_DWORD18_CMD_EXT_MASK GENMASK(30, 29)
#define BFPT_DWORD18_CMD_EXT_REP (0x0UL << 29) /* Repeat */
@ -329,10 +330,10 @@ static int spansion_read_any_reg(struct spi_nor *nor, u32 addr, u8 dummy,
u8 *val)
{
struct spi_mem_op op =
SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDAR, 1),
SPI_MEM_OP_ADDR(nor->addr_width, addr, 1),
SPI_MEM_OP_DUMMY(dummy / 8, 1),
SPI_MEM_OP_DATA_IN(1, NULL, 1));
SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDAR, 1),
SPI_MEM_OP_ADDR(nor->addr_mode_nbytes, addr, 1),
SPI_MEM_OP_DUMMY(dummy / 8, 1),
SPI_MEM_OP_DATA_IN(1, NULL, 1));
return spi_nor_read_write_reg(nor, &op, val);
}
@ -340,10 +341,10 @@ static int spansion_read_any_reg(struct spi_nor *nor, u32 addr, u8 dummy,
static int spansion_write_any_reg(struct spi_nor *nor, u32 addr, u8 val)
{
struct spi_mem_op op =
SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRAR, 1),
SPI_MEM_OP_ADDR(nor->addr_width, addr, 1),
SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_DATA_OUT(1, NULL, 1));
SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRAR, 1),
SPI_MEM_OP_ADDR(nor->addr_mode_nbytes, addr, 1),
SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_DATA_OUT(1, NULL, 1));
return spi_nor_read_write_reg(nor, &op, &val);
}
@ -2236,11 +2237,14 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
/* Number of address bytes. */
switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) {
case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY:
case BFPT_DWORD1_ADDRESS_BYTES_3_OR_4:
nor->addr_width = 3;
nor->addr_mode_nbytes = 3;
break;
case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY:
nor->addr_width = 4;
nor->addr_mode_nbytes = 4;
break;
default:
@ -2516,7 +2520,7 @@ static int spi_nor_parse_sccr(struct spi_nor *nor,
for (i = 0; i < sccr_header->length; i++)
table[i] = le32_to_cpu(table[i]);
if (FIELD_GET(SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE, table[22]))
if (FIELD_GET(SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE, table[21]))
nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
out:
@ -3273,10 +3277,24 @@ static int s25hx_t_post_bfpt_fixup(struct spi_nor *nor,
nor->erase_opcode = SPINOR_OP_SE_4B;
nor->mtd.erasesize = nor->info->sector_size;
ret = set_4byte(nor, nor->info, 1);
if (ret)
return ret;
nor->addr_width = 4;
/*
* The default address mode in multi-die package parts (>1Gb) may be
* 3- or 4-byte, depending on model number. BootROM code in some SoCs
* use 3-byte mode for backward compatibility and should switch to
* 4-byte mode after BootROM phase. Since registers in the 2nd die are
* mapped within 32-bit address space, we need to make sure the flash is
* in 4-byte address mode. The default address mode can be distinguished
* by BFPT 16th DWORD. Power cycle exits 4-byte address mode if default
* is 3-byte address mode.
*/
if (params->size > SZ_128M) {
if (bfpt->dwords[BFPT_DWORD(16)] & BFPT_DWORD16_EX4B_PWRCYC) {
ret = set_4byte(nor, nor->info, 1);
if (ret)
return ret;
}
nor->addr_mode_nbytes = 4;
}
/*
* The page_size is set to 512B from BFPT, but it actually depends on
@ -3333,7 +3351,7 @@ static struct spi_nor_fixups s25fl256l_fixups = {
};
#endif
#ifdef CONFIG_SPI_FLASH_S28HS512T
#ifdef CONFIG_SPI_FLASH_S28HX_T
/**
* spi_nor_cypress_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
* @nor: pointer to a 'struct spi_nor'
@ -3392,15 +3410,15 @@ static int spi_nor_cypress_octal_dtr_enable(struct spi_nor *nor)
return 0;
}
static int s28hs512t_erase_non_uniform(struct spi_nor *nor, loff_t addr)
static int s28hx_t_erase_non_uniform(struct spi_nor *nor, loff_t addr)
{
/* Factory default configuration: 32 x 4 KiB sectors at bottom. */
return spansion_erase_non_uniform(nor, addr, SPINOR_OP_S28_SE_4K,
0, SZ_128K);
}
static int s28hs512t_setup(struct spi_nor *nor, const struct flash_info *info,
const struct spi_nor_flash_parameter *params)
static int s28hx_t_setup(struct spi_nor *nor, const struct flash_info *info,
const struct spi_nor_flash_parameter *params)
{
struct spi_mem_op op;
u8 buf;
@ -3427,19 +3445,19 @@ static int s28hs512t_setup(struct spi_nor *nor, const struct flash_info *info,
return ret;
if (!(buf & SPINOR_REG_CYPRESS_CFR3V_UNISECT))
nor->erase = s28hs512t_erase_non_uniform;
nor->erase = s28hx_t_erase_non_uniform;
return spi_nor_default_setup(nor, info, params);
}
static void s28hs512t_default_init(struct spi_nor *nor)
static void s28hx_t_default_init(struct spi_nor *nor)
{
nor->octal_dtr_enable = spi_nor_cypress_octal_dtr_enable;
nor->setup = s28hs512t_setup;
nor->setup = s28hx_t_setup;
}
static void s28hs512t_post_sfdp_fixup(struct spi_nor *nor,
struct spi_nor_flash_parameter *params)
static void s28hx_t_post_sfdp_fixup(struct spi_nor *nor,
struct spi_nor_flash_parameter *params)
{
/*
* On older versions of the flash the xSPI Profile 1.0 table has the
@ -3469,10 +3487,10 @@ static void s28hs512t_post_sfdp_fixup(struct spi_nor *nor,
params->rdsr_addr_nbytes = 4;
}
static int s28hs512t_post_bfpt_fixup(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params)
static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params)
{
struct spi_mem_op op;
u8 buf;
@ -3509,12 +3527,12 @@ static int s28hs512t_post_bfpt_fixup(struct spi_nor *nor,
return 0;
}
static struct spi_nor_fixups s28hs512t_fixups = {
.default_init = s28hs512t_default_init,
.post_sfdp = s28hs512t_post_sfdp_fixup,
.post_bfpt = s28hs512t_post_bfpt_fixup,
static struct spi_nor_fixups s28hx_t_fixups = {
.default_init = s28hx_t_default_init,
.post_sfdp = s28hx_t_post_sfdp_fixup,
.post_bfpt = s28hx_t_post_bfpt_fixup,
};
#endif /* CONFIG_SPI_FLASH_S28HS512T */
#endif /* CONFIG_SPI_FLASH_S28HX_T */
#ifdef CONFIG_SPI_FLASH_MT35XU
static int spi_nor_micron_octal_dtr_enable(struct spi_nor *nor)
@ -3835,6 +3853,13 @@ void spi_nor_set_fixups(struct spi_nor *nor)
nor->fixups = &s25hx_t_fixups;
break;
#ifdef CONFIG_SPI_FLASH_S28HX_T
case 0x5a: /* S28HL (Octal, 3.3V) */
case 0x5b: /* S28HS (Octal, 1.8V) */
nor->fixups = &s28hx_t_fixups;
break;
#endif
default:
break;
}
@ -3845,11 +3870,6 @@ void spi_nor_set_fixups(struct spi_nor *nor)
nor->fixups = &s25fl256l_fixups;
#endif
#ifdef CONFIG_SPI_FLASH_S28HS512T
if (!strcmp(nor->info->name, "s28hs512t"))
nor->fixups = &s28hs512t_fixups;
#endif
#ifdef CONFIG_SPI_FLASH_MT35XU
if (!strcmp(nor->info->name, "mt35xu512aba"))
nor->fixups = &mt35xu512aba_fixups;

View File

@ -294,8 +294,11 @@ const struct flash_info spi_nor_ids[] = {
USE_CLSR) },
{ INFO6("s25hs02gt", 0x342b1c, 0x0f0090, 256 * 1024, 1024,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
#ifdef CONFIG_SPI_FLASH_S28HS512T
#ifdef CONFIG_SPI_FLASH_S28HX_T
{ INFO("s28hl512t", 0x345a1a, 0, 256 * 1024, 256, SPI_NOR_OCTAL_DTR_READ) },
{ INFO("s28hl01gt", 0x345a1b, 0, 256 * 1024, 512, SPI_NOR_OCTAL_DTR_READ) },
{ INFO("s28hs512t", 0x345b1a, 0, 256 * 1024, 256, SPI_NOR_OCTAL_DTR_READ) },
{ INFO("s28hs01gt", 0x345b1b, 0, 256 * 1024, 512, SPI_NOR_OCTAL_DTR_READ) },
#endif
#endif
#ifdef CONFIG_SPI_FLASH_SST /* SST */

View File

@ -494,6 +494,10 @@ struct spi_flash {
* @rdsr_dummy dummy cycles needed for Read Status Register command.
* @rdsr_addr_nbytes: dummy address bytes needed for Read Status Register
* command.
* @addr_mode_nbytes: number of address bytes of current address mode. Useful
* when the flash operates with 4B opcodes but needs the
* internal address mode for opcodes that don't have a 4B
* opcode correspondent.
* @bank_read_cmd: Bank read cmd
* @bank_write_cmd: Bank write cmd
* @bank_curr: Current flash bank
@ -540,6 +544,7 @@ struct spi_nor {
u8 program_opcode;
u8 rdsr_dummy;
u8 rdsr_addr_nbytes;
u8 addr_mode_nbytes;
#ifdef CONFIG_SPI_FLASH_BAR
u8 bank_read_cmd;
u8 bank_write_cmd;