aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2012-11-12 07:03:23 -0500
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>2012-11-22 02:32:41 -0500
commit0fbc5991551fa2024de7db79421e9a16ca9fe542 (patch)
tree4e6bdf839d2e0db3e5d9577041805b2f5fdd33cb
parent19c0921c842e0aa9ce8c540c9134fd358acc9b28 (diff)
mtd: bcm47xxnflash: support for NAND_CMD_READID command
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
-rw-r--r--drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h5
-rw-r--r--drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c101
2 files changed, 106 insertions, 0 deletions
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
index 2e8864a891e2..cc71400de116 100644
--- a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
+++ b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
@@ -9,6 +9,11 @@ struct bcm47xxnflash {
9 9
10 struct nand_chip nand_chip; 10 struct nand_chip nand_chip;
11 struct mtd_info mtd; 11 struct mtd_info mtd;
12
13 unsigned curr_command;
14 int curr_column;
15
16 u8 id_data[8];
12}; 17};
13 18
14#endif /* BCM47XXNFLASH */ 19#endif /* BCM47XXNFLASH */
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
index ae8a79387c27..7de190e9a788 100644
--- a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
+++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
@@ -16,6 +16,10 @@
16 16
17#include "bcm47xxnflash.h" 17#include "bcm47xxnflash.h"
18 18
19/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
20 * shown 164 retries as maxiumum. */
21#define NFLASH_READY_RETRIES 1000
22
19/************************************************** 23/**************************************************
20 * Various helpers 24 * Various helpers
21 **************************************************/ 25 **************************************************/
@@ -25,6 +29,24 @@ static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
25 return ((ns * 1000 * clock) / 1000000) + 1; 29 return ((ns * 1000 * clock) / 1000000) + 1;
26} 30}
27 31
32static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
33{
34 int i = 0;
35
36 bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, 0x80000000 | code);
37 for (i = 0; i < NFLASH_READY_RETRIES; i++) {
38 if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & 0x80000000)) {
39 i = 0;
40 break;
41 }
42 }
43 if (i) {
44 pr_err("NFLASH control command not ready!\n");
45 return -EBUSY;
46 }
47 return 0;
48}
49
28/************************************************** 50/**************************************************
29 * NAND chip ops 51 * NAND chip ops
30 **************************************************/ 52 **************************************************/
@@ -36,6 +58,83 @@ static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
36 return; 58 return;
37} 59}
38 60
61/*
62 * Default nand_command and nand_command_lp don't match BCM4706 hardware layout.
63 * For example, reading chip id is performed in a non-standard way.
64 * Setting column and page is also handled differently, we use a special
65 * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
66 * standard commands would be much more complicated.
67 */
68static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
69 unsigned command, int column,
70 int page_addr)
71{
72 struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
73 struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
74 u32 ctlcode;
75 int i;
76
77 if (column != -1)
78 b47n->curr_column = column;
79
80 switch (command) {
81 case NAND_CMD_RESET:
82 pr_warn("Chip reset not implemented yet\n");
83 break;
84 case NAND_CMD_READID:
85 ctlcode = 0x40000000 | 0x01000000 | 0x00080000 | 0x00010000;
86 ctlcode |= NAND_CMD_READID;
87 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) {
88 pr_err("READID error\n");
89 break;
90 }
91
92 /*
93 * Reading is specific, last one has to go without 0x40000000
94 * bit. We don't know how many reads NAND subsystem is going
95 * to perform, so cache everything.
96 */
97 for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {
98 ctlcode = 0x40000000 | 0x00100000;
99 if (i == ARRAY_SIZE(b47n->id_data) - 1)
100 ctlcode &= ~0x40000000;
101 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
102 ctlcode)) {
103 pr_err("READID error\n");
104 break;
105 }
106 b47n->id_data[i] =
107 bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA)
108 & 0xFF;
109 }
110
111 break;
112 default:
113 pr_err("Command 0x%X unsupported\n", command);
114 break;
115 }
116 b47n->curr_command = command;
117}
118
119static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
120{
121 struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
122 struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
123
124 switch (b47n->curr_command) {
125 case NAND_CMD_READID:
126 if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) {
127 pr_err("Requested invalid id_data: %d\n",
128 b47n->curr_column);
129 return 0;
130 }
131 return b47n->id_data[b47n->curr_column++];
132 }
133
134 pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
135 return 0;
136}
137
39/************************************************** 138/**************************************************
40 * Init 139 * Init
41 **************************************************/ 140 **************************************************/
@@ -52,6 +151,8 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
52 u32 val; 151 u32 val;
53 152
54 b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip; 153 b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
154 b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
155 b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
55 b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */ 156 b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
56 157
57 /* Enable NAND flash access */ 158 /* Enable NAND flash access */