lkml.org 
[lkml]   [2024]   [Feb]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 08/12] mtd: rawnand: brcmnand: Add BCMBCA read data bus interface
    Date
    The BCMBCA broadband SoC integrates the NAND controller differently than
    STB, iProc and other SoCs. It has different endianness for NAND cache
    data.

    Add a SoC read data bus shim for BCMBCA to meet the specific SoC need
    and performance improvement using the optimized memcpy function on NAND
    cache memory.

    Signed-off-by: William Zhang <william.zhang@broadcom.com>
    Reviewed-by: David Regan <dregan@broadcom.com>

    ---

    Changes in v5: None
    Changes in v4: None
    Changes in v3:
    - Updated bcmbca_read_data_bus comment

    Changes in v2:
    - Drop the is_param argument to the read data bus function now that we
    have the exec_op API to read the parameter page and ONFI data
    - Remove be32_to_cpu from brcmnand_read_data_bus

    drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c | 27 +++++++++++++++++++++
    drivers/mtd/nand/raw/brcmnand/brcmnand.c | 20 ++++++++++++---
    drivers/mtd/nand/raw/brcmnand/brcmnand.h | 2 ++
    3 files changed, 46 insertions(+), 3 deletions(-)

    diff --git a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c
    index 3e2f3b79788d..7ad3e7a98f97 100644
    --- a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c
    +++ b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c
    @@ -26,6 +26,18 @@ enum {
    BCMBCA_CTLRDY = BIT(4),
    };

    +#if defined(CONFIG_ARM64)
    +#define ALIGN_REQ 8
    +#else
    +#define ALIGN_REQ 4
    +#endif
    +
    +static inline bool bcmbca_nand_is_buf_aligned(void *flash_cache, void *buffer)
    +{
    + return IS_ALIGNED((uintptr_t)buffer, ALIGN_REQ) &&
    + IS_ALIGNED((uintptr_t)flash_cache, ALIGN_REQ);
    +}
    +
    static bool bcmbca_nand_intc_ack(struct brcmnand_soc *soc)
    {
    struct bcmbca_nand_soc *priv =
    @@ -56,6 +68,20 @@ static void bcmbca_nand_intc_set(struct brcmnand_soc *soc, bool en)
    brcmnand_writel(val, mmio);
    }

    +static void bcmbca_read_data_bus(struct brcmnand_soc *soc,
    + void __iomem *flash_cache, u32 *buffer, int fc_words)
    +{
    + /*
    + * memcpy can do unaligned aligned access depending on source
    + * and dest address, which is incompatible with nand cache. Fallback
    + * to the memcpy_fromio in such case
    + */
    + if (bcmbca_nand_is_buf_aligned((void *)flash_cache, buffer))
    + memcpy((void *)buffer, (void *)flash_cache, fc_words * 4);
    + else
    + memcpy_fromio((void *)buffer, flash_cache, fc_words * 4);
    +}
    +
    static int bcmbca_nand_probe(struct platform_device *pdev)
    {
    struct device *dev = &pdev->dev;
    @@ -73,6 +99,7 @@ static int bcmbca_nand_probe(struct platform_device *pdev)

    soc->ctlrdy_ack = bcmbca_nand_intc_ack;
    soc->ctlrdy_set_enabled = bcmbca_nand_intc_set;
    + soc->read_data_bus = bcmbca_read_data_bus;

    return brcmnand_probe(pdev, soc);
    }
    diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
    index 8faca43ae1ff..73fdf7ce21aa 100644
    --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
    +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
    @@ -851,6 +851,20 @@ static inline u32 edu_readl(struct brcmnand_controller *ctrl,
    return brcmnand_readl(ctrl->edu_base + offs);
    }

    +static inline void brcmnand_read_data_bus(struct brcmnand_controller *ctrl,
    + void __iomem *flash_cache, u32 *buffer, int fc_words)
    +{
    + struct brcmnand_soc *soc = ctrl->soc;
    + int i;
    +
    + if (soc->read_data_bus) {
    + soc->read_data_bus(soc, flash_cache, buffer, fc_words);
    + } else {
    + for (i = 0; i < fc_words; i++)
    + buffer[i] = brcmnand_read_fc(ctrl, i);
    + }
    +}
    +
    static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl)
    {

    @@ -1975,7 +1989,7 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
    {
    struct brcmnand_host *host = nand_get_controller_data(chip);
    struct brcmnand_controller *ctrl = host->ctrl;
    - int i, j, ret = 0;
    + int i, ret = 0;

    brcmnand_clear_ecc_addr(ctrl);

    @@ -1988,8 +2002,8 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
    if (likely(buf)) {
    brcmnand_soc_data_bus_prepare(ctrl->soc, false);

    - for (j = 0; j < FC_WORDS; j++, buf++)
    - *buf = brcmnand_read_fc(ctrl, j);
    + brcmnand_read_data_bus(ctrl, ctrl->nand_fc, buf, FC_WORDS);
    + buf += FC_WORDS;

    brcmnand_soc_data_bus_unprepare(ctrl->soc, false);
    }
    diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.h b/drivers/mtd/nand/raw/brcmnand/brcmnand.h
    index 928114c0be5e..7261a69989fe 100644
    --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.h
    +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.h
    @@ -24,6 +24,8 @@ struct brcmnand_soc {
    void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en);
    void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare,
    bool is_param);
    + void (*read_data_bus)(struct brcmnand_soc *soc, void __iomem *flash_cache,
    + u32 *buffer, int fc_words);
    const struct brcmnand_io_ops *ops;
    };

    --
    2.37.3

    \
     
     \ /
      Last update: 2024-05-27 14:53    [W:4.294 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site