lkml.org 
[lkml]   [2022]   [Jun]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH 2/2] mtd: spi-nor: Add support for stacked/parallel memories
    Date
    While initializing the flash parameter structure, size of each flash is
    updated with the values coming from "stacked-memories" and
    "parallel-memories" DT properties.

    Two new nor->flags (SNOR_F_HAS_STACKED and SNOR_F_HAS_PARALLEL) are added
    to distinguish between the stacked and parallel configuration.

    In parallel configuration all the operations need to be performed on both
    the flashes simultaneously, So during each operation SPI-NOR needs to set
    0th bit(CS0) & 1st bit(CS1) in nor->spimem->spi->cs_index_mask. The GQSPI
    driver will then assert CS0 & CS1.

    In stacked configuration the SPI-NOR, with individual flash size information,
    will determining the flash on which the operation need to be performed and
    it will set the appropriate CS bit in nor->spimem->spi->cs_index_mask.

    Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
    ---
    drivers/mtd/spi-nor/core.c | 104 +++++++++++++++++++++++++++++++-----
    drivers/mtd/spi-nor/core.h | 5 ++
    include/linux/mtd/spi-nor.h | 8 ++-
    3 files changed, 104 insertions(+), 13 deletions(-)

    diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
    index 502967c76c5f..5d9bbb28659a 100644
    --- a/drivers/mtd/spi-nor/core.c
    +++ b/drivers/mtd/spi-nor/core.c
    @@ -2463,6 +2463,9 @@ static void spi_nor_init_fixup_flags(struct spi_nor *nor)
    */
    static void spi_nor_late_init_params(struct spi_nor *nor)
    {
    + struct device_node *np = spi_nor_get_flash_node(nor);
    + u64 flash_size[SNOR_FLASH_CNT_MAX];
    +
    if (nor->manufacturer && nor->manufacturer->fixups &&
    nor->manufacturer->fixups->late_init)
    nor->manufacturer->fixups->late_init(nor);
    @@ -2479,6 +2482,27 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
    */
    if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
    spi_nor_init_default_locking_ops(nor);
    +
    + /*
    + * The flashes that are connected in stacked mode should be of same make.
    + * Except the flash size all other properties are identical for all the
    + * flashes connected in stacked mode.
    + * The flashes that are connected in parallel mode should be identical.
    + */
    + if (!of_property_read_u64_array(np, "stacked-memories", &flash_size[0], SNOR_FLASH_CNT_MAX)) {
    + nor->flags |= SNOR_F_HAS_STACKED;
    + } else if (!of_property_read_u64_array(np, "parallel-memories", &flash_size[0], SNOR_FLASH_CNT_MAX)){
    + nor->flags |= SNOR_F_HAS_PARALLEL;
    + }
    +
    + if (nor->flags & (SNOR_F_HAS_STACKED | SNOR_F_HAS_PARALLEL)) {
    + nor->params[1] = devm_kzalloc(nor->dev, sizeof(*nor->params[0]), GFP_KERNEL);
    + if (!nor->params[1])
    + return -ENOMEM;
    + memcpy(nor->params[1], nor->params[0], sizeof(*nor->params[0]));
    + nor->params[1]->size = flash_size[1];
    + }
    + return 0;
    }

    /**
    @@ -2614,8 +2638,8 @@ static int spi_nor_init_params(struct spi_nor *nor)
    {
    int ret;

    - nor->params = devm_kzalloc(nor->dev, sizeof(*nor->params), GFP_KERNEL);
    - if (!nor->params)
    + nor->params[0] = devm_kzalloc(nor->dev, sizeof(*nor->params[0]), GFP_KERNEL);
    + if (!nor->params[0])
    return -ENOMEM;

    spi_nor_init_default_params(nor);
    @@ -2677,19 +2701,51 @@ static int spi_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
    */
    static int spi_nor_quad_enable(struct spi_nor *nor)
    {
    - if (!nor->params->quad_enable)
    - return 0;
    + u8 idx;
    + int err;

    - if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
    - spi_nor_get_protocol_width(nor->write_proto) == 4))
    - return 0;
    + if (nor->flags & SNOR_F_HAS_PARALLEL) {
    + if (!nor->params[0]->quad_enable)
    + return 0;

    - return nor->params->quad_enable(nor);
    + if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
    + spi_nor_get_protocol_width(nor->write_proto) == 4))
    + return 0;
    + /*
    + * In parallel mode both chip selects i.e., CS0 &
    + * CS1 need to be asserted simulatneously.
    + */
    + nor->spimem->spi->cs_index_mask = SPI_NOR_ENABLE_BOTH_CS;
    + err = nor->params[0]->quad_enable(nor);
    + } else {
    + for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++) {
    + if (nor->params[idx] != NULL) {
    +
    + if (!nor->params[idx]->quad_enable)
    + return 0;
    +
    + if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
    + spi_nor_get_protocol_width(nor->write_proto) == 4))
    + return 0;
    +
    + /*
    + * Set the appropriate CS index before
    + * issuing the command.
    + */
    + nor->spimem->spi->cs_index_mask = 0x01 << idx;
    + err = nor->params[idx]->quad_enable(nor);
    + if (err)
    + return err;
    + }
    + }
    + }
    + return err;
    }

    static int spi_nor_init(struct spi_nor *nor)
    {
    int err;
    + int idx;

    err = spi_nor_octal_dtr_enable(nor, true);
    if (err) {
    @@ -2730,7 +2786,25 @@ static int spi_nor_init(struct spi_nor *nor)
    */
    WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
    "enabling reset hack; may not recover from unexpected reboots\n");
    - nor->params->set_4byte_addr_mode(nor, true);
    + if (nor->flags & SNOR_F_HAS_PARALLEL) {
    + /*
    + * In parallel mode both chip selects i.e., CS0 &
    + * CS1 need to be asserted simulatneously.
    + */
    + nor->spimem->spi->cs_index_mask = SPI_NOR_ENABLE_BOTH_CS;
    + nor->params[0]->set_4byte_addr_mode(nor, true);
    + } else {
    + for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++) {
    + if (nor->params[idx] != NULL) {
    + /*
    + * Select the appropriate CS index before
    + * issuing the command.
    + */
    + nor->spimem->spi->cs_index_mask = 0x01 << idx;
    + nor->params[idx]->set_4byte_addr_mode(nor, true);
    + }
    + }
    + }
    }

    return 0;
    @@ -2913,6 +2987,8 @@ static void spi_nor_set_mtd_info(struct spi_nor *nor)
    {
    struct mtd_info *mtd = &nor->mtd;
    struct device *dev = nor->dev;
    + u64 total_sz =0;
    + int idx;

    spi_nor_set_mtd_locking_ops(nor);
    spi_nor_set_mtd_otp_ops(nor);
    @@ -2926,9 +3002,13 @@ static void spi_nor_set_mtd_info(struct spi_nor *nor)
    mtd->flags |= MTD_NO_ERASE;
    else
    mtd->_erase = spi_nor_erase;
    - mtd->writesize = nor->params->writesize;
    - mtd->writebufsize = nor->params->page_size;
    - mtd->size = nor->params->size;
    + mtd->writesize = nor->params[0]->writesize;
    + mtd->writebufsize = nor->params[0]->page_size;
    + for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++) {
    + if (nor->params[idx] != NULL)
    + total_sz += nor->params[idx]->size;
    + }
    + mtd->size = total_sz;
    mtd->_read = spi_nor_read;
    /* Might be already set by some SST flashes. */
    if (!mtd->_write)
    diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
    index 3f841ec36e56..4e8bf3cbe331 100644
    --- a/drivers/mtd/spi-nor/core.h
    +++ b/drivers/mtd/spi-nor/core.h
    @@ -11,6 +11,9 @@

    #define SPI_NOR_MAX_ID_LEN 6

    +/* In parallel configuration enable both CS */
    +#define SPI_NOR_ENABLE_BOTH_CS (BIT(0) | BIT(1))
    +
    /* Standard SPI NOR flash operations. */
    #define SPI_NOR_READID_OP(naddr, ndummy, buf, len) \
    SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 0), \
    @@ -130,6 +133,8 @@ enum spi_nor_option_flags {
    SNOR_F_IO_MODE_EN_VOLATILE = BIT(11),
    SNOR_F_SOFT_RESET = BIT(12),
    SNOR_F_SWP_IS_VOLATILE = BIT(13),
    + SNOR_F_HAS_STACKED = BIT(14),
    + SNOR_F_HAS_PARALLEL = BIT(15),
    };

    struct spi_nor_read_command {
    diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
    index 1ede4c89805a..40800e7235ee 100644
    --- a/include/linux/mtd/spi-nor.h
    +++ b/include/linux/mtd/spi-nor.h
    @@ -128,6 +128,12 @@
    #define SR2_LB3 BIT(5) /* Security Register Lock Bit 3 */
    #define SR2_QUAD_EN_BIT7 BIT(7)

    +/*
    + * Maximum number of flashes that can be connected
    + * in stacked/parallel configuration
    + */
    +#define SNOR_FLASH_CNT_MAX 2
    +
    /* Supported SPI protocols */
    #define SNOR_PROTO_INST_MASK GENMASK(23, 16)
    #define SNOR_PROTO_INST_SHIFT 16
    @@ -397,7 +403,7 @@ struct spi_nor {

    const struct spi_nor_controller_ops *controller_ops;

    - struct spi_nor_flash_parameter *params;
    + struct spi_nor_flash_parameter *params[SNOR_FLASH_CNT_MAX];

    struct {
    struct spi_mem_dirmap_desc *rdesc;
    --
    2.17.1
    \
     
     \ /
      Last update: 2022-06-06 13:28    [W:2.570 / U:0.996 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site