mtd: bcm47xxnflash: init NAND on BCM4706
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
This commit is contained in:
parent
a5401370c5
commit
19c0921c84
2 changed files with 110 additions and 0 deletions
|
@ -1,3 +1,4 @@
|
|||
bcm47xxnflash-y += main.o
|
||||
bcm47xxnflash- += ops_bcm4706.o
|
||||
|
||||
obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash.o
|
||||
|
|
109
drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
Normal file
109
drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* BCM47XX NAND flash driver
|
||||
*
|
||||
* Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include "bcm47xxnflash.h"
|
||||
|
||||
/**************************************************
|
||||
* Various helpers
|
||||
**************************************************/
|
||||
|
||||
static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
|
||||
{
|
||||
return ((ns * 1000 * clock) / 1000000) + 1;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* NAND chip ops
|
||||
**************************************************/
|
||||
|
||||
/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
|
||||
static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
|
||||
int chip)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Init
|
||||
**************************************************/
|
||||
|
||||
int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
|
||||
{
|
||||
int err;
|
||||
u32 freq;
|
||||
u16 clock;
|
||||
u8 w0, w1, w2, w3, w4;
|
||||
|
||||
unsigned long chipsize; /* MiB */
|
||||
u8 tbits, col_bits, col_size, row_bits, row_bsize;
|
||||
u32 val;
|
||||
|
||||
b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
|
||||
b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
|
||||
|
||||
/* Enable NAND flash access */
|
||||
bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
|
||||
BCMA_CC_4706_FLASHSCFG_NF1);
|
||||
|
||||
/* Configure wait counters */
|
||||
if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
|
||||
freq = 100000000;
|
||||
} else {
|
||||
freq = bcma_chipco_pll_read(b47n->cc, 4);
|
||||
freq = (freq * 0xFFF) >> 3;
|
||||
freq = (freq * 25000000) >> 3;
|
||||
}
|
||||
clock = freq / 1000000;
|
||||
w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
|
||||
w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
|
||||
w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
|
||||
w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
|
||||
w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
|
||||
bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
|
||||
(w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
|
||||
|
||||
/* Scan NAND */
|
||||
err = nand_scan(&b47n->mtd, 1);
|
||||
if (err) {
|
||||
pr_err("Could not scan NAND flash: %d\n", err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Configure FLASH */
|
||||
chipsize = b47n->nand_chip.chipsize >> 20;
|
||||
tbits = ffs(chipsize); /* find first bit set */
|
||||
if (!tbits || tbits != fls(chipsize)) {
|
||||
pr_err("Invalid flash size: 0x%lX\n", chipsize);
|
||||
err = -ENOTSUPP;
|
||||
goto exit;
|
||||
}
|
||||
tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
|
||||
|
||||
col_bits = b47n->nand_chip.page_shift + 1;
|
||||
col_size = (col_bits + 7) / 8;
|
||||
|
||||
row_bits = tbits - col_bits + 1;
|
||||
row_bsize = (row_bits + 7) / 8;
|
||||
|
||||
val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
|
||||
bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
|
||||
|
||||
exit:
|
||||
if (err)
|
||||
bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
|
||||
~BCMA_CC_4706_FLASHSCFG_NF1);
|
||||
return err;
|
||||
}
|
Loading…
Reference in a new issue