Skip to content

Commit

Permalink
mtd: brcmnand: iProc big endian and ONFI support
Browse files Browse the repository at this point in the history
This patch adds big endian and ONFI support for various iProc based
SoCs that use the core brcmstb NAND controller

This patch was originally implemented by Prafulla Kota
<prafulla.kota@broadcom.com> and fully tested on iProc based NS2 SVK

Signed-off-by: Prafulla Kota <prafulla.kota@broadcom.com>
Signed-off-by: Ray Jui <ray.jui@broadcom.com>
Reviewed-by: Kamal Dasu <kdasu.kdev@gmail.com>
Acked-by: Kamal Dasu <kdasu.kdev@gmail.com>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
  • Loading branch information
Ray Jui authored and Boris Brezillon committed Sep 23, 2016
1 parent 10ffd57 commit eab7fdc
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 15 deletions.
12 changes: 6 additions & 6 deletions drivers/mtd/nand/brcmnand/brcmnand.c
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
u32 *flash_cache = (u32 *)ctrl->flash_cache;
int i;

brcmnand_soc_data_bus_prepare(ctrl->soc);
brcmnand_soc_data_bus_prepare(ctrl->soc, true);

/*
* Must cache the FLASH_CACHE now, since changes in
Expand All @@ -1349,7 +1349,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
*/
flash_cache[i] = be32_to_cpu(brcmnand_read_fc(ctrl, i));

brcmnand_soc_data_bus_unprepare(ctrl->soc);
brcmnand_soc_data_bus_unprepare(ctrl->soc, true);

/* Cleanup from HW quirk: restore SECTOR_SIZE_1K */
if (host->hwcfg.sector_size_1k)
Expand Down Expand Up @@ -1565,12 +1565,12 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
brcmnand_waitfunc(mtd, chip);

if (likely(buf)) {
brcmnand_soc_data_bus_prepare(ctrl->soc);
brcmnand_soc_data_bus_prepare(ctrl->soc, false);

for (j = 0; j < FC_WORDS; j++, buf++)
*buf = brcmnand_read_fc(ctrl, j);

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

if (oob)
Expand Down Expand Up @@ -1815,12 +1815,12 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip,
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);

if (buf) {
brcmnand_soc_data_bus_prepare(ctrl->soc);
brcmnand_soc_data_bus_prepare(ctrl->soc, false);

for (j = 0; j < FC_WORDS; j++, buf++)
brcmnand_write_fc(ctrl, j, *buf);

brcmnand_soc_data_bus_unprepare(ctrl->soc);
brcmnand_soc_data_bus_unprepare(ctrl->soc, false);
} else if (oob) {
for (j = 0; j < FC_WORDS; j++)
brcmnand_write_fc(ctrl, j, 0xffffffff);
Expand Down
13 changes: 8 additions & 5 deletions drivers/mtd/nand/brcmnand/brcmnand.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,22 @@ struct dev_pm_ops;
struct brcmnand_soc {
bool (*ctlrdy_ack)(struct brcmnand_soc *soc);
void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en);
void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare);
void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare,
bool is_param);
};

static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc)
static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc,
bool is_param)
{
if (soc && soc->prepare_data_bus)
soc->prepare_data_bus(soc, true);
soc->prepare_data_bus(soc, true, is_param);
}

static inline void brcmnand_soc_data_bus_unprepare(struct brcmnand_soc *soc)
static inline void brcmnand_soc_data_bus_unprepare(struct brcmnand_soc *soc,
bool is_param)
{
if (soc && soc->prepare_data_bus)
soc->prepare_data_bus(soc, false);
soc->prepare_data_bus(soc, false, is_param);
}

static inline u32 brcmnand_readl(void __iomem *addr)
Expand Down
18 changes: 14 additions & 4 deletions drivers/mtd/nand/brcmnand/iproc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en)
spin_unlock_irqrestore(&priv->idm_lock, flags);
}

static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare)
static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare,
bool is_param)
{
struct iproc_nand_soc *priv =
container_of(soc, struct iproc_nand_soc, soc);
Expand All @@ -86,10 +87,19 @@ static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare)

val = brcmnand_readl(mmio);

if (prepare)
val |= IPROC_NAND_APB_LE_MODE;
else
/*
* In the case of BE or when dealing with NAND data, alway configure
* the APB bus to LE mode before accessing the FIFO and back to BE mode
* after the access is done
*/
if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) || !is_param) {
if (prepare)
val |= IPROC_NAND_APB_LE_MODE;
else
val &= ~IPROC_NAND_APB_LE_MODE;
} else { /* when in LE accessing the parameter page, keep APB in BE */
val &= ~IPROC_NAND_APB_LE_MODE;
}

brcmnand_writel(val, mmio);

Expand Down

0 comments on commit eab7fdc

Please sign in to comment.