mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-23 22:14:54 +00:00
mtd: spi-nor-core: Rework hwcaps selection
The spi-mem layer provides a spi_mem_supports_op() function to check whether a specific operation is supported by the controller or not. This is much more accurate than the hwcaps selection logic based on SPI_{RX,TX}_ flags. Rework the hwcaps selection logic to use spi_mem_supports_op(). To make sure the build doesn't break for boards not using CONFIG_DM_SPI, add a simple SPI_{RX,TX}_ based hwcaps selection logic in spi-mem-nodm similar to spi_mem_default_supports_op(). This change is only compile-tested. To avoid SPL size problems on the x530 board, the old hwcaps selection is still kept around. Leaving the code in-place was getting difficult to read and understand, so the code is restructured to have it all in one isolated function. As a result of this, the parameter hwcaps to spi_nor_setup() is no longer needed. Remove it. Based on the Linux commit c76f5089796a (mtd: spi-nor: Rework hwcaps selection for the spi-mem case, 2019-08-06) Signed-off-by: Pratyush Yadav <p.yadav@ti.com> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
This commit is contained in:
parent
8702188ce5
commit
71025f013c
4 changed files with 280 additions and 52 deletions
|
@ -88,6 +88,15 @@ config SPI_FLASH_SFDP_SUPPORT
|
||||||
SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP)
|
SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP)
|
||||||
tables as per JESD216 standard.
|
tables as per JESD216 standard.
|
||||||
|
|
||||||
|
config SPI_FLASH_SMART_HWCAPS
|
||||||
|
bool "Smart hardware capability detection based on SPI MEM supports_op() hook"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Enable support for smart hardware capability detection based on SPI
|
||||||
|
MEM supports_op() hook that lets controllers express whether they
|
||||||
|
can support a type of operation in a much more refined way compared
|
||||||
|
to using flags like SPI_RX_DUAL, SPI_TX_QUAD, etc.
|
||||||
|
|
||||||
config SPI_FLASH_BAR
|
config SPI_FLASH_BAR
|
||||||
bool "SPI flash Bank/Extended address register support"
|
bool "SPI flash Bank/Extended address register support"
|
||||||
help
|
help
|
||||||
|
|
|
@ -2299,6 +2299,194 @@ static int spi_nor_hwcaps_pp2cmd(u32 hwcaps)
|
||||||
ARRAY_SIZE(hwcaps_pp2cmd));
|
ARRAY_SIZE(hwcaps_pp2cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SPI_FLASH_SMART_HWCAPS
|
||||||
|
/**
|
||||||
|
* spi_nor_check_op - check if the operation is supported by controller
|
||||||
|
* @nor: pointer to a 'struct spi_nor'
|
||||||
|
* @op: pointer to op template to be checked
|
||||||
|
*
|
||||||
|
* Returns 0 if operation is supported, -ENOTSUPP otherwise.
|
||||||
|
*/
|
||||||
|
static int spi_nor_check_op(struct spi_nor *nor,
|
||||||
|
struct spi_mem_op *op)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* First test with 4 address bytes. The opcode itself might be a 3B
|
||||||
|
* addressing opcode but we don't care, because SPI controller
|
||||||
|
* implementation should not check the opcode, but just the sequence.
|
||||||
|
*/
|
||||||
|
op->addr.nbytes = 4;
|
||||||
|
if (!spi_mem_supports_op(nor->spi, op)) {
|
||||||
|
if (nor->mtd.size > SZ_16M)
|
||||||
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
/* If flash size <= 16MB, 3 address bytes are sufficient */
|
||||||
|
op->addr.nbytes = 3;
|
||||||
|
if (!spi_mem_supports_op(nor->spi, op))
|
||||||
|
return -ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spi_nor_check_readop - check if the read op is supported by controller
|
||||||
|
* @nor: pointer to a 'struct spi_nor'
|
||||||
|
* @read: pointer to op template to be checked
|
||||||
|
*
|
||||||
|
* Returns 0 if operation is supported, -ENOTSUPP otherwise.
|
||||||
|
*/
|
||||||
|
static int spi_nor_check_readop(struct spi_nor *nor,
|
||||||
|
const struct spi_nor_read_command *read)
|
||||||
|
{
|
||||||
|
struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(read->opcode, 1),
|
||||||
|
SPI_MEM_OP_ADDR(3, 0, 1),
|
||||||
|
SPI_MEM_OP_DUMMY(0, 1),
|
||||||
|
SPI_MEM_OP_DATA_IN(0, NULL, 1));
|
||||||
|
|
||||||
|
op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(read->proto);
|
||||||
|
op.addr.buswidth = spi_nor_get_protocol_addr_nbits(read->proto);
|
||||||
|
op.data.buswidth = spi_nor_get_protocol_data_nbits(read->proto);
|
||||||
|
op.dummy.buswidth = op.addr.buswidth;
|
||||||
|
op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) *
|
||||||
|
op.dummy.buswidth / 8;
|
||||||
|
|
||||||
|
return spi_nor_check_op(nor, &op);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spi_nor_check_pp - check if the page program op is supported by controller
|
||||||
|
* @nor: pointer to a 'struct spi_nor'
|
||||||
|
* @pp: pointer to op template to be checked
|
||||||
|
*
|
||||||
|
* Returns 0 if operation is supported, -ENOTSUPP otherwise.
|
||||||
|
*/
|
||||||
|
static int spi_nor_check_pp(struct spi_nor *nor,
|
||||||
|
const struct spi_nor_pp_command *pp)
|
||||||
|
{
|
||||||
|
struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(pp->opcode, 1),
|
||||||
|
SPI_MEM_OP_ADDR(3, 0, 1),
|
||||||
|
SPI_MEM_OP_NO_DUMMY,
|
||||||
|
SPI_MEM_OP_DATA_OUT(0, NULL, 1));
|
||||||
|
|
||||||
|
op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(pp->proto);
|
||||||
|
op.addr.buswidth = spi_nor_get_protocol_addr_nbits(pp->proto);
|
||||||
|
op.data.buswidth = spi_nor_get_protocol_data_nbits(pp->proto);
|
||||||
|
|
||||||
|
return spi_nor_check_op(nor, &op);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spi_nor_adjust_hwcaps - Find optimal Read/Write protocol based on SPI
|
||||||
|
* controller capabilities
|
||||||
|
* @nor: pointer to a 'struct spi_nor'
|
||||||
|
* @params: pointer to the 'struct spi_nor_flash_parameter'
|
||||||
|
* representing SPI NOR flash capabilities
|
||||||
|
* @hwcaps: pointer to resulting capabilities after adjusting
|
||||||
|
* according to controller and flash's capability
|
||||||
|
*
|
||||||
|
* Discard caps based on what the SPI controller actually supports (using
|
||||||
|
* spi_mem_supports_op()).
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
spi_nor_adjust_hwcaps(struct spi_nor *nor,
|
||||||
|
const struct spi_nor_flash_parameter *params,
|
||||||
|
u32 *hwcaps)
|
||||||
|
{
|
||||||
|
unsigned int cap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable all caps by default. We will mask them after checking what's
|
||||||
|
* really supported using spi_mem_supports_op().
|
||||||
|
*/
|
||||||
|
*hwcaps = SNOR_HWCAPS_ALL;
|
||||||
|
|
||||||
|
/* DTR modes are not supported yet, mask them all. */
|
||||||
|
*hwcaps &= ~SNOR_HWCAPS_DTR;
|
||||||
|
|
||||||
|
/* X-X-X modes are not supported yet, mask them all. */
|
||||||
|
*hwcaps &= ~SNOR_HWCAPS_X_X_X;
|
||||||
|
|
||||||
|
for (cap = 0; cap < sizeof(*hwcaps) * BITS_PER_BYTE; cap++) {
|
||||||
|
int rdidx, ppidx;
|
||||||
|
|
||||||
|
if (!(*hwcaps & BIT(cap)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rdidx = spi_nor_hwcaps_read2cmd(BIT(cap));
|
||||||
|
if (rdidx >= 0 &&
|
||||||
|
spi_nor_check_readop(nor, ¶ms->reads[rdidx]))
|
||||||
|
*hwcaps &= ~BIT(cap);
|
||||||
|
|
||||||
|
ppidx = spi_nor_hwcaps_pp2cmd(BIT(cap));
|
||||||
|
if (ppidx < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (spi_nor_check_pp(nor, ¶ms->page_programs[ppidx]))
|
||||||
|
*hwcaps &= ~BIT(cap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* spi_nor_adjust_hwcaps - Find optimal Read/Write protocol based on SPI
|
||||||
|
* controller capabilities
|
||||||
|
* @nor: pointer to a 'struct spi_nor'
|
||||||
|
* @params: pointer to the 'struct spi_nor_flash_parameter'
|
||||||
|
* representing SPI NOR flash capabilities
|
||||||
|
* @hwcaps: pointer to resulting capabilities after adjusting
|
||||||
|
* according to controller and flash's capability
|
||||||
|
*
|
||||||
|
* Select caps based on what the SPI controller and SPI flash both support.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
spi_nor_adjust_hwcaps(struct spi_nor *nor,
|
||||||
|
const struct spi_nor_flash_parameter *params,
|
||||||
|
u32 *hwcaps)
|
||||||
|
{
|
||||||
|
struct spi_slave *spi = nor->spi;
|
||||||
|
u32 ignored_mask = (SNOR_HWCAPS_READ_2_2_2 |
|
||||||
|
SNOR_HWCAPS_READ_4_4_4 |
|
||||||
|
SNOR_HWCAPS_READ_8_8_8 |
|
||||||
|
SNOR_HWCAPS_PP_4_4_4 |
|
||||||
|
SNOR_HWCAPS_PP_8_8_8);
|
||||||
|
u32 spi_hwcaps = (SNOR_HWCAPS_READ | SNOR_HWCAPS_READ_FAST |
|
||||||
|
SNOR_HWCAPS_PP);
|
||||||
|
|
||||||
|
/* Get the hardware capabilities the SPI controller supports. */
|
||||||
|
if (spi->mode & SPI_RX_OCTAL) {
|
||||||
|
spi_hwcaps |= SNOR_HWCAPS_READ_1_1_8;
|
||||||
|
|
||||||
|
if (spi->mode & SPI_TX_OCTAL)
|
||||||
|
spi_hwcaps |= (SNOR_HWCAPS_READ_1_8_8 |
|
||||||
|
SNOR_HWCAPS_PP_1_1_8 |
|
||||||
|
SNOR_HWCAPS_PP_1_8_8);
|
||||||
|
} else if (spi->mode & SPI_RX_QUAD) {
|
||||||
|
spi_hwcaps |= SNOR_HWCAPS_READ_1_1_4;
|
||||||
|
|
||||||
|
if (spi->mode & SPI_TX_QUAD)
|
||||||
|
spi_hwcaps |= (SNOR_HWCAPS_READ_1_4_4 |
|
||||||
|
SNOR_HWCAPS_PP_1_1_4 |
|
||||||
|
SNOR_HWCAPS_PP_1_4_4);
|
||||||
|
} else if (spi->mode & SPI_RX_DUAL) {
|
||||||
|
spi_hwcaps |= SNOR_HWCAPS_READ_1_1_2;
|
||||||
|
|
||||||
|
if (spi->mode & SPI_TX_DUAL)
|
||||||
|
spi_hwcaps |= SNOR_HWCAPS_READ_1_2_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keep only the hardware capabilities supported by both the SPI
|
||||||
|
* controller and the SPI flash memory.
|
||||||
|
*/
|
||||||
|
*hwcaps = spi_hwcaps & params->hwcaps.mask;
|
||||||
|
if (*hwcaps & ignored_mask) {
|
||||||
|
dev_dbg(nor->dev,
|
||||||
|
"SPI n-n-n protocols are not supported yet.\n");
|
||||||
|
*hwcaps &= ~ignored_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SPI_FLASH_SMART_HWCAPS */
|
||||||
|
|
||||||
static int spi_nor_select_read(struct spi_nor *nor,
|
static int spi_nor_select_read(struct spi_nor *nor,
|
||||||
const struct spi_nor_flash_parameter *params,
|
const struct spi_nor_flash_parameter *params,
|
||||||
u32 shared_hwcaps)
|
u32 shared_hwcaps)
|
||||||
|
@ -2379,30 +2567,13 @@ static int spi_nor_select_erase(struct spi_nor *nor,
|
||||||
|
|
||||||
static int spi_nor_default_setup(struct spi_nor *nor,
|
static int spi_nor_default_setup(struct spi_nor *nor,
|
||||||
const struct flash_info *info,
|
const struct flash_info *info,
|
||||||
const struct spi_nor_flash_parameter *params,
|
const struct spi_nor_flash_parameter *params)
|
||||||
const struct spi_nor_hwcaps *hwcaps)
|
|
||||||
{
|
{
|
||||||
u32 ignored_mask, shared_mask;
|
u32 shared_mask;
|
||||||
bool enable_quad_io;
|
bool enable_quad_io;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/*
|
spi_nor_adjust_hwcaps(nor, params, &shared_mask);
|
||||||
* Keep only the hardware capabilities supported by both the SPI
|
|
||||||
* controller and the SPI flash memory.
|
|
||||||
*/
|
|
||||||
shared_mask = hwcaps->mask & params->hwcaps.mask;
|
|
||||||
|
|
||||||
/* SPI n-n-n protocols are not supported yet. */
|
|
||||||
ignored_mask = (SNOR_HWCAPS_READ_2_2_2 |
|
|
||||||
SNOR_HWCAPS_READ_4_4_4 |
|
|
||||||
SNOR_HWCAPS_READ_8_8_8 |
|
|
||||||
SNOR_HWCAPS_PP_4_4_4 |
|
|
||||||
SNOR_HWCAPS_PP_8_8_8);
|
|
||||||
if (shared_mask & ignored_mask) {
|
|
||||||
dev_dbg(nor->dev,
|
|
||||||
"SPI n-n-n protocols are not supported yet.\n");
|
|
||||||
shared_mask &= ~ignored_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the (Fast) Read command. */
|
/* Select the (Fast) Read command. */
|
||||||
err = spi_nor_select_read(nor, params, shared_mask);
|
err = spi_nor_select_read(nor, params, shared_mask);
|
||||||
|
@ -2440,13 +2611,12 @@ static int spi_nor_default_setup(struct spi_nor *nor,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
|
static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
|
||||||
const struct spi_nor_flash_parameter *params,
|
const struct spi_nor_flash_parameter *params)
|
||||||
const struct spi_nor_hwcaps *hwcaps)
|
|
||||||
{
|
{
|
||||||
if (!nor->setup)
|
if (!nor->setup)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return nor->setup(nor, info, params, hwcaps);
|
return nor->setup(nor, info, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spi_nor_init(struct spi_nor *nor)
|
static int spi_nor_init(struct spi_nor *nor)
|
||||||
|
@ -2502,11 +2672,6 @@ int spi_nor_scan(struct spi_nor *nor)
|
||||||
struct spi_nor_flash_parameter params;
|
struct spi_nor_flash_parameter params;
|
||||||
const struct flash_info *info = NULL;
|
const struct flash_info *info = NULL;
|
||||||
struct mtd_info *mtd = &nor->mtd;
|
struct mtd_info *mtd = &nor->mtd;
|
||||||
struct spi_nor_hwcaps hwcaps = {
|
|
||||||
.mask = SNOR_HWCAPS_READ |
|
|
||||||
SNOR_HWCAPS_READ_FAST |
|
|
||||||
SNOR_HWCAPS_PP,
|
|
||||||
};
|
|
||||||
struct spi_slave *spi = nor->spi;
|
struct spi_slave *spi = nor->spi;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -2521,27 +2686,6 @@ int spi_nor_scan(struct spi_nor *nor)
|
||||||
|
|
||||||
nor->setup = spi_nor_default_setup;
|
nor->setup = spi_nor_default_setup;
|
||||||
|
|
||||||
if (spi->mode & SPI_RX_OCTAL) {
|
|
||||||
hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;
|
|
||||||
|
|
||||||
if (spi->mode & SPI_TX_OCTAL)
|
|
||||||
hwcaps.mask |= (SNOR_HWCAPS_READ_1_8_8 |
|
|
||||||
SNOR_HWCAPS_PP_1_1_8 |
|
|
||||||
SNOR_HWCAPS_PP_1_8_8);
|
|
||||||
} else if (spi->mode & SPI_RX_QUAD) {
|
|
||||||
hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;
|
|
||||||
|
|
||||||
if (spi->mode & SPI_TX_QUAD)
|
|
||||||
hwcaps.mask |= (SNOR_HWCAPS_READ_1_4_4 |
|
|
||||||
SNOR_HWCAPS_PP_1_1_4 |
|
|
||||||
SNOR_HWCAPS_PP_1_4_4);
|
|
||||||
} else if (spi->mode & SPI_RX_DUAL) {
|
|
||||||
hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;
|
|
||||||
|
|
||||||
if (spi->mode & SPI_TX_DUAL)
|
|
||||||
hwcaps.mask |= SNOR_HWCAPS_READ_1_2_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
info = spi_nor_read_id(nor);
|
info = spi_nor_read_id(nor);
|
||||||
if (IS_ERR_OR_NULL(info))
|
if (IS_ERR_OR_NULL(info))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
@ -2616,7 +2760,7 @@ int spi_nor_scan(struct spi_nor *nor)
|
||||||
* - set the SPI protocols for register and memory accesses.
|
* - set the SPI protocols for register and memory accesses.
|
||||||
* - set the Quad Enable bit if needed (required by SPI x-y-4 protos).
|
* - set the Quad Enable bit if needed (required by SPI x-y-4 protos).
|
||||||
*/
|
*/
|
||||||
ret = spi_nor_setup(nor, info, ¶ms, &hwcaps);
|
ret = spi_nor_setup(nor, info, ¶ms);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -105,3 +105,65 @@ int spi_mem_adjust_op_size(struct spi_slave *slave,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int spi_check_buswidth_req(struct spi_slave *slave, u8 buswidth, bool tx)
|
||||||
|
{
|
||||||
|
u32 mode = slave->mode;
|
||||||
|
|
||||||
|
switch (buswidth) {
|
||||||
|
case 1:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
if ((tx && (mode & (SPI_TX_DUAL | SPI_TX_QUAD))) ||
|
||||||
|
(!tx && (mode & (SPI_RX_DUAL | SPI_RX_QUAD))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if ((tx && (mode & SPI_TX_QUAD)) ||
|
||||||
|
(!tx && (mode & SPI_RX_QUAD)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
if ((tx && (mode & SPI_TX_OCTAL)) ||
|
||||||
|
(!tx && (mode & SPI_RX_OCTAL)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool spi_mem_supports_op(struct spi_slave *slave, const struct spi_mem_op *op)
|
||||||
|
{
|
||||||
|
if (spi_check_buswidth_req(slave, op->cmd.buswidth, true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (op->addr.nbytes &&
|
||||||
|
spi_check_buswidth_req(slave, op->addr.buswidth, true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (op->dummy.nbytes &&
|
||||||
|
spi_check_buswidth_req(slave, op->dummy.buswidth, true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (op->data.nbytes &&
|
||||||
|
spi_check_buswidth_req(slave, op->data.buswidth,
|
||||||
|
op->data.dir == SPI_MEM_DATA_OUT))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (op->cmd.nbytes != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -312,6 +312,20 @@ struct spi_nor_hwcaps {
|
||||||
#define SNOR_HWCAPS_PP_1_8_8 BIT(21)
|
#define SNOR_HWCAPS_PP_1_8_8 BIT(21)
|
||||||
#define SNOR_HWCAPS_PP_8_8_8 BIT(22)
|
#define SNOR_HWCAPS_PP_8_8_8 BIT(22)
|
||||||
|
|
||||||
|
#define SNOR_HWCAPS_X_X_X (SNOR_HWCAPS_READ_2_2_2 | \
|
||||||
|
SNOR_HWCAPS_READ_4_4_4 | \
|
||||||
|
SNOR_HWCAPS_READ_8_8_8 | \
|
||||||
|
SNOR_HWCAPS_PP_4_4_4 | \
|
||||||
|
SNOR_HWCAPS_PP_8_8_8)
|
||||||
|
|
||||||
|
#define SNOR_HWCAPS_DTR (SNOR_HWCAPS_READ_1_1_1_DTR | \
|
||||||
|
SNOR_HWCAPS_READ_1_2_2_DTR | \
|
||||||
|
SNOR_HWCAPS_READ_1_4_4_DTR | \
|
||||||
|
SNOR_HWCAPS_READ_1_8_8_DTR)
|
||||||
|
|
||||||
|
#define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \
|
||||||
|
SNOR_HWCAPS_PP_MASK)
|
||||||
|
|
||||||
struct spi_nor_read_command {
|
struct spi_nor_read_command {
|
||||||
u8 num_mode_clocks;
|
u8 num_mode_clocks;
|
||||||
u8 num_wait_states;
|
u8 num_wait_states;
|
||||||
|
@ -461,8 +475,7 @@ struct spi_nor {
|
||||||
struct spi_nor_fixups *fixups;
|
struct spi_nor_fixups *fixups;
|
||||||
|
|
||||||
int (*setup)(struct spi_nor *nor, const struct flash_info *info,
|
int (*setup)(struct spi_nor *nor, const struct flash_info *info,
|
||||||
const struct spi_nor_flash_parameter *params,
|
const struct spi_nor_flash_parameter *params);
|
||||||
const struct spi_nor_hwcaps *hwcaps);
|
|
||||||
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
|
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
|
||||||
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
|
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
|
||||||
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
|
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
|
||||||
|
|
Loading…
Add table
Reference in a new issue