Skip to content

Commit 546e425

Browse files
William Zhangmiquelraynal
William Zhang
authored andcommitted
mtd: rawnand: brcmnand: Add BCMBCA read data bus interface
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 <[email protected]> Reviewed-by: David Regan <[email protected]> Signed-off-by: Miquel Raynal <[email protected]> Link: https://lore.kernel.org/linux-mtd/[email protected]
1 parent 198eef9 commit 546e425

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ enum {
2626
BCMBCA_CTLRDY = BIT(4),
2727
};
2828

29+
#if defined(CONFIG_ARM64)
30+
#define ALIGN_REQ 8
31+
#else
32+
#define ALIGN_REQ 4
33+
#endif
34+
35+
static inline bool bcmbca_nand_is_buf_aligned(void *flash_cache, void *buffer)
36+
{
37+
return IS_ALIGNED((uintptr_t)buffer, ALIGN_REQ) &&
38+
IS_ALIGNED((uintptr_t)flash_cache, ALIGN_REQ);
39+
}
40+
2941
static bool bcmbca_nand_intc_ack(struct brcmnand_soc *soc)
3042
{
3143
struct bcmbca_nand_soc *priv =
@@ -56,6 +68,20 @@ static void bcmbca_nand_intc_set(struct brcmnand_soc *soc, bool en)
5668
brcmnand_writel(val, mmio);
5769
}
5870

71+
static void bcmbca_read_data_bus(struct brcmnand_soc *soc,
72+
void __iomem *flash_cache, u32 *buffer, int fc_words)
73+
{
74+
/*
75+
* memcpy can do unaligned aligned access depending on source
76+
* and dest address, which is incompatible with nand cache. Fallback
77+
* to the memcpy_fromio in such case
78+
*/
79+
if (bcmbca_nand_is_buf_aligned((void *)flash_cache, buffer))
80+
memcpy((void *)buffer, (void *)flash_cache, fc_words * 4);
81+
else
82+
memcpy_fromio((void *)buffer, flash_cache, fc_words * 4);
83+
}
84+
5985
static int bcmbca_nand_probe(struct platform_device *pdev)
6086
{
6187
struct device *dev = &pdev->dev;
@@ -73,6 +99,7 @@ static int bcmbca_nand_probe(struct platform_device *pdev)
7399

74100
soc->ctlrdy_ack = bcmbca_nand_intc_ack;
75101
soc->ctlrdy_set_enabled = bcmbca_nand_intc_set;
102+
soc->read_data_bus = bcmbca_read_data_bus;
76103

77104
return brcmnand_probe(pdev, soc);
78105
}

drivers/mtd/nand/raw/brcmnand/brcmnand.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,20 @@ static inline u32 edu_readl(struct brcmnand_controller *ctrl,
851851
return brcmnand_readl(ctrl->edu_base + offs);
852852
}
853853

854+
static inline void brcmnand_read_data_bus(struct brcmnand_controller *ctrl,
855+
void __iomem *flash_cache, u32 *buffer, int fc_words)
856+
{
857+
struct brcmnand_soc *soc = ctrl->soc;
858+
int i;
859+
860+
if (soc->read_data_bus) {
861+
soc->read_data_bus(soc, flash_cache, buffer, fc_words);
862+
} else {
863+
for (i = 0; i < fc_words; i++)
864+
buffer[i] = brcmnand_read_fc(ctrl, i);
865+
}
866+
}
867+
854868
static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl)
855869
{
856870

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

19801994
brcmnand_clear_ecc_addr(ctrl);
19811995

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

1991-
for (j = 0; j < FC_WORDS; j++, buf++)
1992-
*buf = brcmnand_read_fc(ctrl, j);
2005+
brcmnand_read_data_bus(ctrl, ctrl->nand_fc, buf, FC_WORDS);
2006+
buf += FC_WORDS;
19932007

19942008
brcmnand_soc_data_bus_unprepare(ctrl->soc, false);
19952009
}

drivers/mtd/nand/raw/brcmnand/brcmnand.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ struct brcmnand_soc {
2424
void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en);
2525
void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare,
2626
bool is_param);
27+
void (*read_data_bus)(struct brcmnand_soc *soc, void __iomem *flash_cache,
28+
u32 *buffer, int fc_words);
2729
const struct brcmnand_io_ops *ops;
2830
};
2931

0 commit comments

Comments
 (0)