- 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
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) size_t len, const char *buf, char *cmp_buf, size_t *skipped)
{ {
char *ptr = (char *)buf; 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", debug("offset=%#x+%#x, sector_size=%#x, len=%#zx\n",
offset, flash->sector_size, len); read_offset, start_offset, flash->sector_size, len);
/* Read the entire sector so to allow for rewriting */ /* 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"; return "read";
/* Compare only what is meaningful (len) */ /* Compare only what is meaningful (len) */
if (memcmp(cmp_buf, buf, len) == 0) { if (memcmp(cmp_buf + start_offset, buf, len) == 0) {
debug("Skip region %x size %zx: no change\n", debug("Skip region %x+%x size %zx: no change\n",
offset, len); start_offset, read_offset, len);
*skipped += len; *skipped += len;
return NULL; return NULL;
} }
@@ -197,7 +199,7 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
return "erase"; return "erase";
/* If it's a partial sector, copy the data into the temp-buffer */ /* If it's a partial sector, copy the data into the temp-buffer */
if (len != flash->sector_size) { if (len != flash->sector_size) {
memcpy(cmp_buf, buf, len); memcpy(cmp_buf + start_offset, buf, len);
ptr = cmp_buf; ptr = cmp_buf;
} }
/* Write one complete sector */ /* 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) { 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);
todo = min_t(size_t, end - buf,
flash->sector_size - (offset % flash->sector_size));
if (get_timer(last_update) > 100) { if (get_timer(last_update) > 100) {
printf(" \rUpdating, %zu%% %lu B/s", printf(" \rUpdating, %zu%% %lu B/s",
100 - (end - buf) / scale, 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=y
CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y
CONFIG_SPI_FLASH_SPANSION=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_STMICRO=y
CONFIG_SPI_FLASH_MT35XU=y CONFIG_SPI_FLASH_MT35XU=y
# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set # 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=y
CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y
CONFIG_SPI_FLASH_SPANSION=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_STMICRO=y
CONFIG_SPI_FLASH_MT35XU=y CONFIG_SPI_FLASH_MT35XU=y
CONFIG_PINCTRL=y CONFIG_PINCTRL=y

View File

@@ -166,13 +166,13 @@ config SPI_FLASH_SPANSION
help help
Add support for various Spansion SPI flash chips (S25FLxxx) Add support for various Spansion SPI flash chips (S25FLxxx)
config SPI_FLASH_S28HS512T config SPI_FLASH_S28HX_T
bool "Cypress S28HS512T chip support" bool "Cypress SEMPER Octal (S28) chip support"
depends on SPI_FLASH_SPANSION depends on SPI_FLASH_SPANSION
help help
Add support for the Cypress S28HS512T chip. This is a separate config Add support for the Cypress S28HL-T and S28HS-T chip. This is a separate
because the fixup hooks for this flash add extra size overhead. Boards config because the fixup hooks for this flash add extra size overhead.
that don't use the flash can disable this to save space. Boards that don't use the flash can disable this to save space.
config SPI_FLASH_STMICRO config SPI_FLASH_STMICRO
bool "STMicro SPI flash support" 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_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */
#define BFPT_DWORD16_SOFT_RST BIT(12) #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_MASK GENMASK(30, 29)
#define BFPT_DWORD18_CMD_EXT_REP (0x0UL << 29) /* Repeat */ #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) u8 *val)
{ {
struct spi_mem_op op = struct spi_mem_op op =
SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDAR, 1), SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDAR, 1),
SPI_MEM_OP_ADDR(nor->addr_width, addr, 1), SPI_MEM_OP_ADDR(nor->addr_mode_nbytes, addr, 1),
SPI_MEM_OP_DUMMY(dummy / 8, 1), SPI_MEM_OP_DUMMY(dummy / 8, 1),
SPI_MEM_OP_DATA_IN(1, NULL, 1)); SPI_MEM_OP_DATA_IN(1, NULL, 1));
return spi_nor_read_write_reg(nor, &op, val); 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) static int spansion_write_any_reg(struct spi_nor *nor, u32 addr, u8 val)
{ {
struct spi_mem_op op = struct spi_mem_op op =
SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRAR, 1), SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRAR, 1),
SPI_MEM_OP_ADDR(nor->addr_width, addr, 1), SPI_MEM_OP_ADDR(nor->addr_mode_nbytes, addr, 1),
SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_DATA_OUT(1, NULL, 1)); SPI_MEM_OP_DATA_OUT(1, NULL, 1));
return spi_nor_read_write_reg(nor, &op, &val); 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. */ /* Number of address bytes. */
switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) { switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) {
case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY: case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY:
case BFPT_DWORD1_ADDRESS_BYTES_3_OR_4:
nor->addr_width = 3; nor->addr_width = 3;
nor->addr_mode_nbytes = 3;
break; break;
case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY: case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY:
nor->addr_width = 4; nor->addr_width = 4;
nor->addr_mode_nbytes = 4;
break; break;
default: default:
@@ -2516,7 +2520,7 @@ static int spi_nor_parse_sccr(struct spi_nor *nor,
for (i = 0; i < sccr_header->length; i++) for (i = 0; i < sccr_header->length; i++)
table[i] = le32_to_cpu(table[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; nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
out: out:
@@ -3273,10 +3277,24 @@ static int s25hx_t_post_bfpt_fixup(struct spi_nor *nor,
nor->erase_opcode = SPINOR_OP_SE_4B; nor->erase_opcode = SPINOR_OP_SE_4B;
nor->mtd.erasesize = nor->info->sector_size; nor->mtd.erasesize = nor->info->sector_size;
ret = set_4byte(nor, nor->info, 1); /*
if (ret) * The default address mode in multi-die package parts (>1Gb) may be
return ret; * 3- or 4-byte, depending on model number. BootROM code in some SoCs
nor->addr_width = 4; * 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 * 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 #endif
#ifdef CONFIG_SPI_FLASH_S28HS512T #ifdef CONFIG_SPI_FLASH_S28HX_T
/** /**
* spi_nor_cypress_octal_dtr_enable() - Enable octal DTR on Cypress flashes. * spi_nor_cypress_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
* @nor: pointer to a 'struct spi_nor' * @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; 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. */ /* Factory default configuration: 32 x 4 KiB sectors at bottom. */
return spansion_erase_non_uniform(nor, addr, SPINOR_OP_S28_SE_4K, return spansion_erase_non_uniform(nor, addr, SPINOR_OP_S28_SE_4K,
0, SZ_128K); 0, SZ_128K);
} }
static int s28hs512t_setup(struct spi_nor *nor, const struct flash_info *info, static int s28hx_t_setup(struct spi_nor *nor, const struct flash_info *info,
const struct spi_nor_flash_parameter *params) const struct spi_nor_flash_parameter *params)
{ {
struct spi_mem_op op; struct spi_mem_op op;
u8 buf; u8 buf;
@@ -3427,19 +3445,19 @@ static int s28hs512t_setup(struct spi_nor *nor, const struct flash_info *info,
return ret; return ret;
if (!(buf & SPINOR_REG_CYPRESS_CFR3V_UNISECT)) 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); 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->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, static void s28hx_t_post_sfdp_fixup(struct spi_nor *nor,
struct spi_nor_flash_parameter *params) struct spi_nor_flash_parameter *params)
{ {
/* /*
* On older versions of the flash the xSPI Profile 1.0 table has the * 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; params->rdsr_addr_nbytes = 4;
} }
static int s28hs512t_post_bfpt_fixup(struct spi_nor *nor, static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header, const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt, const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params) struct spi_nor_flash_parameter *params)
{ {
struct spi_mem_op op; struct spi_mem_op op;
u8 buf; u8 buf;
@@ -3509,12 +3527,12 @@ static int s28hs512t_post_bfpt_fixup(struct spi_nor *nor,
return 0; return 0;
} }
static struct spi_nor_fixups s28hs512t_fixups = { static struct spi_nor_fixups s28hx_t_fixups = {
.default_init = s28hs512t_default_init, .default_init = s28hx_t_default_init,
.post_sfdp = s28hs512t_post_sfdp_fixup, .post_sfdp = s28hx_t_post_sfdp_fixup,
.post_bfpt = s28hs512t_post_bfpt_fixup, .post_bfpt = s28hx_t_post_bfpt_fixup,
}; };
#endif /* CONFIG_SPI_FLASH_S28HS512T */ #endif /* CONFIG_SPI_FLASH_S28HX_T */
#ifdef CONFIG_SPI_FLASH_MT35XU #ifdef CONFIG_SPI_FLASH_MT35XU
static int spi_nor_micron_octal_dtr_enable(struct spi_nor *nor) 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; nor->fixups = &s25hx_t_fixups;
break; 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: default:
break; break;
} }
@@ -3845,11 +3870,6 @@ void spi_nor_set_fixups(struct spi_nor *nor)
nor->fixups = &s25fl256l_fixups; nor->fixups = &s25fl256l_fixups;
#endif #endif
#ifdef CONFIG_SPI_FLASH_S28HS512T
if (!strcmp(nor->info->name, "s28hs512t"))
nor->fixups = &s28hs512t_fixups;
#endif
#ifdef CONFIG_SPI_FLASH_MT35XU #ifdef CONFIG_SPI_FLASH_MT35XU
if (!strcmp(nor->info->name, "mt35xu512aba")) if (!strcmp(nor->info->name, "mt35xu512aba"))
nor->fixups = &mt35xu512aba_fixups; nor->fixups = &mt35xu512aba_fixups;

View File

@@ -294,8 +294,11 @@ const struct flash_info spi_nor_ids[] = {
USE_CLSR) }, USE_CLSR) },
{ INFO6("s25hs02gt", 0x342b1c, 0x0f0090, 256 * 1024, 1024, { INFO6("s25hs02gt", 0x342b1c, 0x0f0090, 256 * 1024, 1024,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, 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("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
#endif #endif
#ifdef CONFIG_SPI_FLASH_SST /* SST */ #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_dummy dummy cycles needed for Read Status Register command.
* @rdsr_addr_nbytes: dummy address bytes needed for Read Status Register * @rdsr_addr_nbytes: dummy address bytes needed for Read Status Register
* command. * 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_read_cmd: Bank read cmd
* @bank_write_cmd: Bank write cmd * @bank_write_cmd: Bank write cmd
* @bank_curr: Current flash bank * @bank_curr: Current flash bank
@@ -540,6 +544,7 @@ struct spi_nor {
u8 program_opcode; u8 program_opcode;
u8 rdsr_dummy; u8 rdsr_dummy;
u8 rdsr_addr_nbytes; u8 rdsr_addr_nbytes;
u8 addr_mode_nbytes;
#ifdef CONFIG_SPI_FLASH_BAR #ifdef CONFIG_SPI_FLASH_BAR
u8 bank_read_cmd; u8 bank_read_cmd;
u8 bank_write_cmd; u8 bank_write_cmd;