mtd: bcm47xxnflash: add cmd_ctrl handler
[deliverable/linux.git] / drivers / mtd / nand / bcm47xxnflash / ops_bcm4706.c
CommitLineData
19c0921c
RM
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
be0638d9
RM
12#include "bcm47xxnflash.h"
13
19c0921c
RM
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/slab.h>
17#include <linux/bcma/bcma.h>
18
0fbc5991 19/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
5a40b5fb
RM
20 * shown ~1000 retries as maxiumum. */
21#define NFLASH_READY_RETRIES 10000
0fbc5991 22
3c01d4cb
RM
23#define NFLASH_SECTOR_SIZE 512
24
e7e46168
RM
25#define NCTL_CMD0 0x00010000
26#define NCTL_CMD1W 0x00080000
27#define NCTL_READ 0x00100000
ecfe57b7 28#define NCTL_WRITE 0x00200000
e7e46168
RM
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
34
19c0921c
RM
35/**************************************************
36 * Various helpers
37 **************************************************/
38
39static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
40{
41 return ((ns * 1000 * clock) / 1000000) + 1;
42}
43
0fbc5991
RM
44static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
45{
46 int i = 0;
47
e7e46168 48 bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, NCTL_START | code);
0fbc5991 49 for (i = 0; i < NFLASH_READY_RETRIES; i++) {
e7e46168 50 if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_START)) {
0fbc5991
RM
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}
61
3c01d4cb
RM
62static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
63{
64 int i;
65
66 for (i = 0; i < NFLASH_READY_RETRIES; i++) {
e7e46168 67 if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_READY) {
3c01d4cb
RM
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 }
77
78 pr_err("Polling timeout!\n");
79 return -EBUSY;
80}
81
82/**************************************************
83 * R/W
84 **************************************************/
85
86static 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;
91
92 u32 ctlcode;
93 u32 *dest = (u32 *)buf;
94 int i;
95 int toread;
96
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 */
100
101 while (len) {
102 /* We can read maximum of 0x200 bytes at once */
103 toread = min(len, 0x200);
104
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);
110
111 /* Prepare to read */
e7e46168
RM
112 ctlcode = NCTL_CSA | NCTL_CMD1W | 0x00040000 | 0x00020000 |
113 NCTL_CMD0;
3c01d4cb
RM
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;
119
120 /* Eventually read some data :) */
121 for (i = 0; i < toread; i += 4, dest++) {
e7e46168 122 ctlcode = NCTL_CSA | 0x30000000 | NCTL_READ;
3c01d4cb 123 if (i == toread - 4) /* Last read goes without that */
e7e46168 124 ctlcode &= ~NCTL_CSA;
3c01d4cb
RM
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 }
130
131 b47n->curr_column += toread;
132 len -= toread;
133 }
134}
135
ecfe57b7
RM
136static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
137 const uint8_t *buf, int len)
138{
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;
142
143 u32 ctlcode;
144 const u32 *data = (u32 *)buf;
145 int i;
146
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 */
150
151 for (i = 0; i < len; i += 4, data++) {
152 bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data);
153
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 }
162
163 b47n->curr_column += len;
164}
165
19c0921c
RM
166/**************************************************
167 * NAND chip ops
168 **************************************************/
169
90de6332
RM
170static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd,
171 unsigned int ctrl)
172{
173 struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
174 struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
175 u32 code = 0;
176
177 if (cmd == NAND_CMD_NONE)
178 return;
179
180 if (cmd & NAND_CTRL_CLE)
181 code = cmd | NCTL_CMD0;
182
183 /* nCS is not needed for reset command */
184 if (cmd != NAND_CMD_RESET)
185 code |= NCTL_CSA;
186
187 bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, code);
188}
189
19c0921c
RM
190/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
191static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
192 int chip)
193{
194 return;
195}
196
5282a3ac
RM
197static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd)
198{
199 struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
200 struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
201
202 return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY);
203}
204
0fbc5991
RM
205/*
206 * Default nand_command and nand_command_lp don't match BCM4706 hardware layout.
207 * For example, reading chip id is performed in a non-standard way.
208 * Setting column and page is also handled differently, we use a special
209 * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
210 * standard commands would be much more complicated.
211 */
212static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
213 unsigned command, int column,
214 int page_addr)
215{
216 struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
217 struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
a6b3ed29 218 struct bcma_drv_cc *cc = b47n->cc;
0fbc5991
RM
219 u32 ctlcode;
220 int i;
221
222 if (column != -1)
223 b47n->curr_column = column;
3c01d4cb
RM
224 if (page_addr != -1)
225 b47n->curr_page_addr = page_addr;
0fbc5991
RM
226
227 switch (command) {
228 case NAND_CMD_RESET:
229 pr_warn("Chip reset not implemented yet\n");
230 break;
231 case NAND_CMD_READID:
e7e46168 232 ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0;
0fbc5991
RM
233 ctlcode |= NAND_CMD_READID;
234 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) {
235 pr_err("READID error\n");
236 break;
237 }
238
239 /*
e7e46168 240 * Reading is specific, last one has to go without NCTL_CSA
0fbc5991
RM
241 * bit. We don't know how many reads NAND subsystem is going
242 * to perform, so cache everything.
243 */
244 for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {
e7e46168 245 ctlcode = NCTL_CSA | NCTL_READ;
0fbc5991 246 if (i == ARRAY_SIZE(b47n->id_data) - 1)
e7e46168 247 ctlcode &= ~NCTL_CSA;
0fbc5991
RM
248 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
249 ctlcode)) {
250 pr_err("READID error\n");
251 break;
252 }
253 b47n->id_data[i] =
254 bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA)
255 & 0xFF;
256 }
257
258 break;
a6b3ed29
RM
259 case NAND_CMD_STATUS:
260 ctlcode = NCTL_CSA | NCTL_CMD0 | NAND_CMD_STATUS;
261 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
262 pr_err("STATUS command error\n");
263 break;
3c01d4cb
RM
264 case NAND_CMD_READ0:
265 break;
266 case NAND_CMD_READOOB:
267 if (page_addr != -1)
268 b47n->curr_column += mtd->writesize;
269 break;
ecfe57b7
RM
270 case NAND_CMD_ERASE1:
271 bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
272 b47n->curr_page_addr);
273 ctlcode = 0x00040000 | NCTL_CMD1W | NCTL_CMD0 |
274 NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8);
275 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
276 pr_err("ERASE1 failed\n");
277 break;
278 case NAND_CMD_ERASE2:
279 break;
280 case NAND_CMD_SEQIN:
281 /* Set page and column */
282 bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR,
283 b47n->curr_column);
284 bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
285 b47n->curr_page_addr);
286
287 /* Prepare to write */
288 ctlcode = 0x40000000 | 0x00040000 | 0x00020000 | 0x00010000;
289 ctlcode |= NAND_CMD_SEQIN;
290 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
291 pr_err("SEQIN failed\n");
292 break;
293 case NAND_CMD_PAGEPROG:
294 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, 0x00010000 |
295 NAND_CMD_PAGEPROG))
296 pr_err("PAGEPROG failed\n");
297 if (bcm47xxnflash_ops_bcm4706_poll(cc))
298 pr_err("PAGEPROG not ready\n");
299 break;
0fbc5991
RM
300 default:
301 pr_err("Command 0x%X unsupported\n", command);
302 break;
303 }
304 b47n->curr_command = command;
305}
306
307static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
308{
309 struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
310 struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
a6b3ed29 311 struct bcma_drv_cc *cc = b47n->cc;
3c01d4cb 312 u32 tmp = 0;
0fbc5991
RM
313
314 switch (b47n->curr_command) {
315 case NAND_CMD_READID:
316 if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) {
317 pr_err("Requested invalid id_data: %d\n",
318 b47n->curr_column);
319 return 0;
320 }
321 return b47n->id_data[b47n->curr_column++];
a6b3ed29
RM
322 case NAND_CMD_STATUS:
323 if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_READ))
324 return 0;
325 return bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xff;
3c01d4cb
RM
326 case NAND_CMD_READOOB:
327 bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4);
328 return tmp & 0xFF;
0fbc5991
RM
329 }
330
331 pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
332 return 0;
333}
334
3c01d4cb
RM
335static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
336 uint8_t *buf, int len)
337{
338 struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
339 struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
340
341 switch (b47n->curr_command) {
342 case NAND_CMD_READ0:
343 case NAND_CMD_READOOB:
344 bcm47xxnflash_ops_bcm4706_read(mtd, buf, len);
345 return;
346 }
347
348 pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
349}
350
ecfe57b7
RM
351static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd,
352 const uint8_t *buf, int len)
353{
354 struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
355 struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
356
357 switch (b47n->curr_command) {
358 case NAND_CMD_SEQIN:
359 bcm47xxnflash_ops_bcm4706_write(mtd, buf, len);
360 return;
361 }
362
363 pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command);
364}
365
19c0921c
RM
366/**************************************************
367 * Init
368 **************************************************/
369
370int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
371{
5282a3ac 372 struct nand_chip *nand_chip = (struct nand_chip *)&b47n->nand_chip;
19c0921c
RM
373 int err;
374 u32 freq;
375 u16 clock;
376 u8 w0, w1, w2, w3, w4;
377
378 unsigned long chipsize; /* MiB */
379 u8 tbits, col_bits, col_size, row_bits, row_bsize;
380 u32 val;
381
382 b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
90de6332 383 nand_chip->cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl;
5282a3ac 384 nand_chip->dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready;
0fbc5991
RM
385 b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
386 b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
3c01d4cb 387 b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
ecfe57b7 388 b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
5282a3ac
RM
389
390 nand_chip->chip_delay = 50;
3c01d4cb 391 b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
19c0921c
RM
392 b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
393
394 /* Enable NAND flash access */
395 bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
396 BCMA_CC_4706_FLASHSCFG_NF1);
397
398 /* Configure wait counters */
399 if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
785e5e11
RM
400 /* 400 MHz */
401 freq = 400000000 / 4;
19c0921c
RM
402 } else {
403 freq = bcma_chipco_pll_read(b47n->cc, 4);
785e5e11
RM
404 freq = (freq & 0xFFF) >> 3;
405 /* Fixed reference clock 25 MHz and m = 2 */
406 freq = (freq * 25000000 / 2) / 4;
19c0921c
RM
407 }
408 clock = freq / 1000000;
409 w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
410 w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
411 w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
412 w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
413 w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
414 bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
415 (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
416
417 /* Scan NAND */
418 err = nand_scan(&b47n->mtd, 1);
419 if (err) {
420 pr_err("Could not scan NAND flash: %d\n", err);
421 goto exit;
422 }
423
424 /* Configure FLASH */
425 chipsize = b47n->nand_chip.chipsize >> 20;
426 tbits = ffs(chipsize); /* find first bit set */
427 if (!tbits || tbits != fls(chipsize)) {
428 pr_err("Invalid flash size: 0x%lX\n", chipsize);
429 err = -ENOTSUPP;
430 goto exit;
431 }
432 tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
433
434 col_bits = b47n->nand_chip.page_shift + 1;
435 col_size = (col_bits + 7) / 8;
436
437 row_bits = tbits - col_bits + 1;
438 row_bsize = (row_bits + 7) / 8;
439
440 val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
441 bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
442
443exit:
444 if (err)
445 bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
446 ~BCMA_CC_4706_FLASHSCFG_NF1);
447 return err;
448}
This page took 0.131991 seconds and 5 git commands to generate.