]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/kernel-video.git/blob - drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
Merge branch 'drm-nouveau-fixes-3.8' of git://anongit.freedesktop.org/git/nouveau...
[android-sdk/kernel-video.git] / drivers / mtd / nand / bcm47xxnflash / ops_bcm4706.c
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  */
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/bcma/bcma.h>
17 #include "bcm47xxnflash.h"
19 /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
20  * shown ~1000 retries as maxiumum. */
21 #define NFLASH_READY_RETRIES            10000
23 #define NFLASH_SECTOR_SIZE              512
25 #define NCTL_CMD0                       0x00010000
26 #define NCTL_CMD1W                      0x00080000
27 #define NCTL_READ                       0x00100000
28 #define NCTL_WRITE                      0x00200000
29 #define NCTL_SPECADDR                   0x01000000
30 #define NCTL_READY                      0x04000000
31 #define NCTL_ERR                        0x08000000
32 #define NCTL_CSA                        0x40000000
33 #define NCTL_START                      0x80000000
35 /**************************************************
36  * Various helpers
37  **************************************************/
39 static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
40 {
41         return ((ns * 1000 * clock) / 1000000) + 1;
42 }
44 static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
45 {
46         int i = 0;
48         bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, NCTL_START | code);
49         for (i = 0; i < NFLASH_READY_RETRIES; i++) {
50                 if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_START)) {
51                         i = 0;
52                         break;
53                 }
54         }
55         if (i) {
56                 pr_err("NFLASH control command not ready!\n");
57                 return -EBUSY;
58         }
59         return 0;
60 }
62 static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
63 {
64         int i;
66         for (i = 0; i < NFLASH_READY_RETRIES; i++) {
67                 if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_READY) {
68                         if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) &
69                             BCMA_CC_NFLASH_CTL_ERR) {
70                                 pr_err("Error on polling\n");
71                                 return -EBUSY;
72                         } else {
73                                 return 0;
74                         }
75                 }
76         }
78         pr_err("Polling timeout!\n");
79         return -EBUSY;
80 }
82 /**************************************************
83  * R/W
84  **************************************************/
86 static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
87                                            int len)
88 {
89         struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
90         struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
92         u32 ctlcode;
93         u32 *dest = (u32 *)buf;
94         int i;
95         int toread;
97         BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
98         /* Don't validate column using nand_chip->page_shift, it may be bigger
99          * when accessing OOB */
101         while (len) {
102                 /* We can read maximum of 0x200 bytes at once */
103                 toread = min(len, 0x200);
105                 /* Set page and column */
106                 bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR,
107                                 b47n->curr_column);
108                 bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR,
109                                 b47n->curr_page_addr);
111                 /* Prepare to read */
112                 ctlcode = NCTL_CSA | NCTL_CMD1W | 0x00040000 | 0x00020000 |
113                           NCTL_CMD0;
114                 ctlcode |= NAND_CMD_READSTART << 8;
115                 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode))
116                         return;
117                 if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc))
118                         return;
120                 /* Eventually read some data :) */
121                 for (i = 0; i < toread; i += 4, dest++) {
122                         ctlcode = NCTL_CSA | 0x30000000 | NCTL_READ;
123                         if (i == toread - 4) /* Last read goes without that */
124                                 ctlcode &= ~NCTL_CSA;
125                         if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
126                                                               ctlcode))
127                                 return;
128                         *dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA);
129                 }
131                 b47n->curr_column += toread;
132                 len -= toread;
133         }
136 static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
137                                             const uint8_t *buf, int len)
139         struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
140         struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
141         struct bcma_drv_cc *cc = b47n->cc;
143         u32 ctlcode;
144         const u32 *data = (u32 *)buf;
145         int i;
147         BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
148         /* Don't validate column using nand_chip->page_shift, it may be bigger
149          * when accessing OOB */
151         for (i = 0; i < len; i += 4, data++) {
152                 bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data);
154                 ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE;
155                 if (i == len - 4) /* Last read goes without that */
156                         ctlcode &= ~NCTL_CSA;
157                 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) {
158                         pr_err("%s ctl_cmd didn't work!\n", __func__);
159                         return;
160                 }
161         }
163         b47n->curr_column += len;
166 /**************************************************
167  * NAND chip ops
168  **************************************************/
170 /* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
171 static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
172                                                   int chip)
174         return;
177 /*
178  * Default nand_command and nand_command_lp don't match BCM4706 hardware layout.
179  * For example, reading chip id is performed in a non-standard way.
180  * Setting column and page is also handled differently, we use a special
181  * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
182  * standard commands would be much more complicated.
183  */
184 static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
185                                               unsigned command, int column,
186                                               int page_addr)
188         struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
189         struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
190         struct bcma_drv_cc *cc = b47n->cc;
191         u32 ctlcode;
192         int i;
194         if (column != -1)
195                 b47n->curr_column = column;
196         if (page_addr != -1)
197                 b47n->curr_page_addr = page_addr;
199         switch (command) {
200         case NAND_CMD_RESET:
201                 pr_warn("Chip reset not implemented yet\n");
202                 break;
203         case NAND_CMD_READID:
204                 ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0;
205                 ctlcode |= NAND_CMD_READID;
206                 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) {
207                         pr_err("READID error\n");
208                         break;
209                 }
211                 /*
212                  * Reading is specific, last one has to go without NCTL_CSA
213                  * bit. We don't know how many reads NAND subsystem is going
214                  * to perform, so cache everything.
215                  */
216                 for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {
217                         ctlcode = NCTL_CSA | NCTL_READ;
218                         if (i == ARRAY_SIZE(b47n->id_data) - 1)
219                                 ctlcode &= ~NCTL_CSA;
220                         if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
221                                                               ctlcode)) {
222                                 pr_err("READID error\n");
223                                 break;
224                         }
225                         b47n->id_data[i] =
226                                 bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA)
227                                 & 0xFF;
228                 }
230                 break;
231         case NAND_CMD_STATUS:
232                 ctlcode = NCTL_CSA | NCTL_CMD0 | NAND_CMD_STATUS;
233                 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
234                         pr_err("STATUS command error\n");
235                 break;
236         case NAND_CMD_READ0:
237                 break;
238         case NAND_CMD_READOOB:
239                 if (page_addr != -1)
240                         b47n->curr_column += mtd->writesize;
241                 break;
242         case NAND_CMD_ERASE1:
243                 bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
244                                 b47n->curr_page_addr);
245                 ctlcode = 0x00040000 | NCTL_CMD1W | NCTL_CMD0 |
246                           NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8);
247                 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
248                         pr_err("ERASE1 failed\n");
249                 break;
250         case NAND_CMD_ERASE2:
251                 break;
252         case NAND_CMD_SEQIN:
253                 /* Set page and column */
254                 bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR,
255                                 b47n->curr_column);
256                 bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
257                                 b47n->curr_page_addr);
259                 /* Prepare to write */
260                 ctlcode = 0x40000000 | 0x00040000 | 0x00020000 | 0x00010000;
261                 ctlcode |= NAND_CMD_SEQIN;
262                 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
263                         pr_err("SEQIN failed\n");
264                 break;
265         case NAND_CMD_PAGEPROG:
266                 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, 0x00010000 |
267                                                           NAND_CMD_PAGEPROG))
268                         pr_err("PAGEPROG failed\n");
269                 if (bcm47xxnflash_ops_bcm4706_poll(cc))
270                         pr_err("PAGEPROG not ready\n");
271                 break;
272         default:
273                 pr_err("Command 0x%X unsupported\n", command);
274                 break;
275         }
276         b47n->curr_command = command;
279 static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
281         struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
282         struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
283         struct bcma_drv_cc *cc = b47n->cc;
284         u32 tmp = 0;
286         switch (b47n->curr_command) {
287         case NAND_CMD_READID:
288                 if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) {
289                         pr_err("Requested invalid id_data: %d\n",
290                                b47n->curr_column);
291                         return 0;
292                 }
293                 return b47n->id_data[b47n->curr_column++];
294         case NAND_CMD_STATUS:
295                 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_READ))
296                         return 0;
297                 return bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xff;
298         case NAND_CMD_READOOB:
299                 bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4);
300                 return tmp & 0xFF;
301         }
303         pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
304         return 0;
307 static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
308                                                uint8_t *buf, int len)
310         struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
311         struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
313         switch (b47n->curr_command) {
314         case NAND_CMD_READ0:
315         case NAND_CMD_READOOB:
316                 bcm47xxnflash_ops_bcm4706_read(mtd, buf, len);
317                 return;
318         }
320         pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
323 static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd,
324                                                 const uint8_t *buf, int len)
326         struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
327         struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
329         switch (b47n->curr_command) {
330         case NAND_CMD_SEQIN:
331                 bcm47xxnflash_ops_bcm4706_write(mtd, buf, len);
332                 return;
333         }
335         pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command);
338 /**************************************************
339  * Init
340  **************************************************/
342 int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
344         int err;
345         u32 freq;
346         u16 clock;
347         u8 w0, w1, w2, w3, w4;
349         unsigned long chipsize; /* MiB */
350         u8 tbits, col_bits, col_size, row_bits, row_bsize;
351         u32 val;
353         b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
354         b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
355         b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
356         b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
357         b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
358         b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
359         b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
361         /* Enable NAND flash access */
362         bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
363                       BCMA_CC_4706_FLASHSCFG_NF1);
365         /* Configure wait counters */
366         if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
367                 freq = 100000000;
368         } else {
369                 freq = bcma_chipco_pll_read(b47n->cc, 4);
370                 freq = (freq * 0xFFF) >> 3;
371                 freq = (freq * 25000000) >> 3;
372         }
373         clock = freq / 1000000;
374         w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
375         w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
376         w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
377         w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
378         w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
379         bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
380                         (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
382         /* Scan NAND */
383         err = nand_scan(&b47n->mtd, 1);
384         if (err) {
385                 pr_err("Could not scan NAND flash: %d\n", err);
386                 goto exit;
387         }
389         /* Configure FLASH */
390         chipsize = b47n->nand_chip.chipsize >> 20;
391         tbits = ffs(chipsize); /* find first bit set */
392         if (!tbits || tbits != fls(chipsize)) {
393                 pr_err("Invalid flash size: 0x%lX\n", chipsize);
394                 err = -ENOTSUPP;
395                 goto exit;
396         }
397         tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
399         col_bits = b47n->nand_chip.page_shift + 1;
400         col_size = (col_bits + 7) / 8;
402         row_bits = tbits - col_bits + 1;
403         row_bsize = (row_bits + 7) / 8;
405         val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
406         bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
408 exit:
409         if (err)
410                 bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
411                                ~BCMA_CC_4706_FLASHSCFG_NF1);
412         return err;