aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/nand/bcm47xxnflash/Makefile1
-rw-r--r--drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c109
2 files changed, 110 insertions, 0 deletions
diff --git a/drivers/mtd/nand/bcm47xxnflash/Makefile b/drivers/mtd/nand/bcm47xxnflash/Makefile
index 1d0693af6e98..4f688f9655ad 100644
--- a/drivers/mtd/nand/bcm47xxnflash/Makefile
+++ b/drivers/mtd/nand/bcm47xxnflash/Makefile
@@ -1,3 +1,4 @@
1bcm47xxnflash-y += main.o 1bcm47xxnflash-y += main.o
2bcm47xxnflash- += ops_bcm4706.o
2 3
3obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash.o 4obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash.o
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
new file mode 100644
index 000000000000..ae8a79387c27
--- /dev/null
+++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
@@ -0,0 +1,109 @@
1/*
2 * BCM47XX NAND flash driver
3 *
4 * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/slab.h>
15#include <linux/bcma/bcma.h>
16
17#include "bcm47xxnflash.h"
18
19/**************************************************
20 * Various helpers
21 **************************************************/
22
23static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
24{
25 return ((ns * 1000 * clock) / 1000000) + 1;
26}
27
28/**************************************************
29 * NAND chip ops
30 **************************************************/
31
32/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
33static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
34 int chip)
35{
36 return;
37}
38
39/**************************************************
40 * Init
41 **************************************************/
42
43int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
44{
45 int err;
46 u32 freq;
47 u16 clock;
48 u8 w0, w1, w2, w3, w4;
49
50 unsigned long chipsize; /* MiB */
51 u8 tbits, col_bits, col_size, row_bits, row_bsize;
52 u32 val;
53
54 b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
55 b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
56
57 /* Enable NAND flash access */
58 bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
59 BCMA_CC_4706_FLASHSCFG_NF1);
60
61 /* Configure wait counters */
62 if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
63 freq = 100000000;
64 } else {
65 freq = bcma_chipco_pll_read(b47n->cc, 4);
66 freq = (freq * 0xFFF) >> 3;
67 freq = (freq * 25000000) >> 3;
68 }
69 clock = freq / 1000000;
70 w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
71 w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
72 w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
73 w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
74 w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
75 bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
76 (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
77
78 /* Scan NAND */
79 err = nand_scan(&b47n->mtd, 1);
80 if (err) {
81 pr_err("Could not scan NAND flash: %d\n", err);
82 goto exit;
83 }
84
85 /* Configure FLASH */
86 chipsize = b47n->nand_chip.chipsize >> 20;
87 tbits = ffs(chipsize); /* find first bit set */
88 if (!tbits || tbits != fls(chipsize)) {
89 pr_err("Invalid flash size: 0x%lX\n", chipsize);
90 err = -ENOTSUPP;
91 goto exit;
92 }
93 tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
94
95 col_bits = b47n->nand_chip.page_shift + 1;
96 col_size = (col_bits + 7) / 8;
97
98 row_bits = tbits - col_bits + 1;
99 row_bsize = (row_bits + 7) / 8;
100
101 val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
102 bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
103
104exit:
105 if (err)
106 bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
107 ~BCMA_CC_4706_FLASHSCFG_NF1);
108 return err;
109}