File Index
Files and directories
Sign in
FILE

ops_bcm4706.c

File preview with syntax highlighting.

linux-6.19.14/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * BCM47XX NAND flash driver
  4 *
  5 * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
  6 */
  7
  8#include "bcm47xxnflash.h"
  9
 10#include <linux/module.h>
 11#include <linux/kernel.h>
 12#include <linux/slab.h>
 13#include <linux/delay.h>
 14#include <linux/bcma/bcma.h>
 15
 16/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
 17 * shown ~1000 retries as maximum. */
 18#define NFLASH_READY_RETRIES		10000
 19
 20#define NFLASH_SECTOR_SIZE		512
 21
 22#define NCTL_CMD0			0x00010000
 23#define NCTL_COL			0x00020000	/* Update column with value from BCMA_CC_NFLASH_COL_ADDR */
 24#define NCTL_ROW			0x00040000	/* Update row (page) with value from BCMA_CC_NFLASH_ROW_ADDR */
 25#define NCTL_CMD1W			0x00080000
 26#define NCTL_READ			0x00100000
 27#define NCTL_WRITE			0x00200000
 28#define NCTL_SPECADDR			0x01000000
 29#define NCTL_READY			0x04000000
 30#define NCTL_ERR			0x08000000
 31#define NCTL_CSA			0x40000000
 32#define NCTL_START			0x80000000
 33
 34/**************************************************
 35 * Various helpers
 36 **************************************************/
 37
 38static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
 39{
 40	return ((ns * 1000 * clock) / 1000000) + 1;
 41}
 42
 43static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
 44{
 45	int i = 0;
 46
 47	bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, NCTL_START | code);
 48	for (i = 0; i < NFLASH_READY_RETRIES; i++) {
 49		if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_START)) {
 50			i = 0;
 51			break;
 52		}
 53	}
 54	if (i) {
 55		pr_err("NFLASH control command not ready!\n");
 56		return -EBUSY;
 57	}
 58	return 0;
 59}
 60
 61static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
 62{
 63	int i;
 64
 65	for (i = 0; i < NFLASH_READY_RETRIES; i++) {
 66		if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_READY) {
 67			if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) &
 68			    BCMA_CC_NFLASH_CTL_ERR) {
 69				pr_err("Error on polling\n");
 70				return -EBUSY;
 71			} else {
 72				return 0;
 73			}
 74		}
 75	}
 76
 77	pr_err("Polling timeout!\n");
 78	return -EBUSY;
 79}
 80
 81/**************************************************
 82 * R/W
 83 **************************************************/
 84
 85static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
 86					   int len)
 87{
 88	struct nand_chip *nand_chip = mtd_to_nand(mtd);
 89	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
 90
 91	u32 ctlcode;
 92	u32 *dest = (u32 *)buf;
 93	int i;
 94	int toread;
 95
 96	BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
 97	/* Don't validate column using nand_chip->page_shift, it may be bigger
 98	 * when accessing OOB */
 99
100	while (len) {
101		/* We can read maximum of 0x200 bytes at once */
102		toread = min(len, 0x200);
103
104		/* Set page and column */
105		bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR,
106				b47n->curr_column);
107		bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR,
108				b47n->curr_page_addr);
109
110		/* Prepare to read */
111		ctlcode = NCTL_CSA | NCTL_CMD1W | NCTL_ROW | NCTL_COL |
112			  NCTL_CMD0;
113		ctlcode |= NAND_CMD_READSTART << 8;
114		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode))
115			return;
116		if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc))
117			return;
118
119		/* Eventually read some data :) */
120		for (i = 0; i < toread; i += 4, dest++) {
121			ctlcode = NCTL_CSA | 0x30000000 | NCTL_READ;
122			if (i == toread - 4) /* Last read goes without that */
123				ctlcode &= ~NCTL_CSA;
124			if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
125							      ctlcode))
126				return;
127			*dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA);
128		}
129
130		b47n->curr_column += toread;
131		len -= toread;
132	}
133}
134
135static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
136					    const uint8_t *buf, int len)
137{
138	struct nand_chip *nand_chip = mtd_to_nand(mtd);
139	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
140	struct bcma_drv_cc *cc = b47n->cc;
141
142	u32 ctlcode;
143	const u32 *data = (u32 *)buf;
144	int i;
145
146	BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
147	/* Don't validate column using nand_chip->page_shift, it may be bigger
148	 * when accessing OOB */
149
150	for (i = 0; i < len; i += 4, data++) {
151		bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data);
152
153		ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE;
154		if (i == len - 4) /* Last read goes without that */
155			ctlcode &= ~NCTL_CSA;
156		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) {
157			pr_err("%s ctl_cmd didn't work!\n", __func__);
158			return;
159		}
160	}
161
162	b47n->curr_column += len;
163}
164
165/**************************************************
166 * NAND chip ops
167 **************************************************/
168
169static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct nand_chip *nand_chip,
170					       int cmd, unsigned int ctrl)
171{
172	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
173	u32 code = 0;
174	int rc;
175
176	if (cmd == NAND_CMD_NONE)
177		return;
178
179	if (cmd & NAND_CTRL_CLE)
180		code = cmd | NCTL_CMD0;
181
182	/* nCS is not needed for reset command */
183	if (cmd != NAND_CMD_RESET)
184		code |= NCTL_CSA;
185
186	rc = bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, code);
187	if (rc)
188		pr_err("ctl_cmd didn't work with error %d\n", rc);
189}
190
191/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
192static void bcm47xxnflash_ops_bcm4706_select_chip(struct nand_chip *chip,
193						  int cs)
194{
195	return;
196}
197
198static int bcm47xxnflash_ops_bcm4706_dev_ready(struct nand_chip *nand_chip)
199{
200	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
201
202	return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY);
203}
204
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 nand_chip *nand_chip,
213					      unsigned command, int column,
214					      int page_addr)
215{
216	struct mtd_info *mtd = nand_to_mtd(nand_chip);
217	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
218	struct bcma_drv_cc *cc = b47n->cc;
219	u32 ctlcode;
220	int i;
221
222	if (column != -1)
223		b47n->curr_column = column;
224	if (page_addr != -1)
225		b47n->curr_page_addr = page_addr;
226
227	switch (command) {
228	case NAND_CMD_RESET:
229		nand_chip->legacy.cmd_ctrl(nand_chip, command, NAND_CTRL_CLE);
230
231		ndelay(100);
232		nand_wait_ready(nand_chip);
233		break;
234	case NAND_CMD_READID:
235		ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0;
236		ctlcode |= NAND_CMD_READID;
237		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) {
238			pr_err("READID error\n");
239			break;
240		}
241
242		/*
243		 * Reading is specific, last one has to go without NCTL_CSA
244		 * bit. We don't know how many reads NAND subsystem is going
245		 * to perform, so cache everything.
246		 */
247		for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {
248			ctlcode = NCTL_CSA | NCTL_READ;
249			if (i == ARRAY_SIZE(b47n->id_data) - 1)
250				ctlcode &= ~NCTL_CSA;
251			if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
252							      ctlcode)) {
253				pr_err("READID error\n");
254				break;
255			}
256			b47n->id_data[i] =
257				bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA)
258				& 0xFF;
259		}
260
261		break;
262	case NAND_CMD_STATUS:
263		ctlcode = NCTL_CSA | NCTL_CMD0 | NAND_CMD_STATUS;
264		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
265			pr_err("STATUS command error\n");
266		break;
267	case NAND_CMD_READ0:
268		break;
269	case NAND_CMD_READOOB:
270		if (page_addr != -1)
271			b47n->curr_column += mtd->writesize;
272		break;
273	case NAND_CMD_ERASE1:
274		bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
275				b47n->curr_page_addr);
276		ctlcode = NCTL_ROW | NCTL_CMD1W | NCTL_CMD0 |
277			  NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8);
278		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
279			pr_err("ERASE1 failed\n");
280		break;
281	case NAND_CMD_ERASE2:
282		break;
283	case NAND_CMD_SEQIN:
284		/* Set page and column */
285		bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR,
286				b47n->curr_column);
287		bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
288				b47n->curr_page_addr);
289
290		/* Prepare to write */
291		ctlcode = 0x40000000 | NCTL_ROW | NCTL_COL | NCTL_CMD0;
292		ctlcode |= NAND_CMD_SEQIN;
293		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
294			pr_err("SEQIN failed\n");
295		break;
296	case NAND_CMD_PAGEPROG:
297		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_CMD0 |
298							  NAND_CMD_PAGEPROG))
299			pr_err("PAGEPROG failed\n");
300		if (bcm47xxnflash_ops_bcm4706_poll(cc))
301			pr_err("PAGEPROG not ready\n");
302		break;
303	default:
304		pr_err("Command 0x%X unsupported\n", command);
305		break;
306	}
307	b47n->curr_command = command;
308}
309
310static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct nand_chip *nand_chip)
311{
312	struct mtd_info *mtd = nand_to_mtd(nand_chip);
313	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
314	struct bcma_drv_cc *cc = b47n->cc;
315	u32 tmp = 0;
316
317	switch (b47n->curr_command) {
318	case NAND_CMD_READID:
319		if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) {
320			pr_err("Requested invalid id_data: %d\n",
321			       b47n->curr_column);
322			return 0;
323		}
324		return b47n->id_data[b47n->curr_column++];
325	case NAND_CMD_STATUS:
326		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_READ))
327			return 0;
328		return bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xff;
329	case NAND_CMD_READOOB:
330		bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4);
331		return tmp & 0xFF;
332	}
333
334	pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
335	return 0;
336}
337
338static void bcm47xxnflash_ops_bcm4706_read_buf(struct nand_chip *nand_chip,
339					       uint8_t *buf, int len)
340{
341	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
342
343	switch (b47n->curr_command) {
344	case NAND_CMD_READ0:
345	case NAND_CMD_READOOB:
346		bcm47xxnflash_ops_bcm4706_read(nand_to_mtd(nand_chip), buf,
347					       len);
348		return;
349	}
350
351	pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
352}
353
354static void bcm47xxnflash_ops_bcm4706_write_buf(struct nand_chip *nand_chip,
355						const uint8_t *buf, int len)
356{
357	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
358
359	switch (b47n->curr_command) {
360	case NAND_CMD_SEQIN:
361		bcm47xxnflash_ops_bcm4706_write(nand_to_mtd(nand_chip), buf,
362						len);
363		return;
364	}
365
366	pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command);
367}
368
369/**************************************************
370 * Init
371 **************************************************/
372
373int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
374{
375	struct nand_chip *nand_chip = (struct nand_chip *)&b47n->nand_chip;
376	int err;
377	u32 freq;
378	u16 clock;
379	u8 w0, w1, w2, w3, w4;
380
381	unsigned long chipsize; /* MiB */
382	u8 tbits, col_bits, col_size, row_bits, row_bsize;
383	u32 val;
384
385	nand_chip->legacy.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
386	nand_chip->legacy.cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl;
387	nand_chip->legacy.dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready;
388	b47n->nand_chip.legacy.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
389	b47n->nand_chip.legacy.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
390	b47n->nand_chip.legacy.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
391	b47n->nand_chip.legacy.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
392	b47n->nand_chip.legacy.set_features = nand_get_set_features_notsupp;
393	b47n->nand_chip.legacy.get_features = nand_get_set_features_notsupp;
394
395	nand_chip->legacy.chip_delay = 50;
396	b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
397	/* TODO: implement ECC */
398	b47n->nand_chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_NONE;
399
400	/* Enable NAND flash access */
401	bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
402		      BCMA_CC_4706_FLASHSCFG_NF1);
403
404	/* Configure wait counters */
405	if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
406		/* 400 MHz */
407		freq = 400000000 / 4;
408	} else {
409		freq = bcma_chipco_pll_read(b47n->cc, 4);
410		freq = (freq & 0xFFF) >> 3;
411		/* Fixed reference clock 25 MHz and m = 2 */
412		freq = (freq * 25000000 / 2) / 4;
413	}
414	clock = freq / 1000000;
415	w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
416	w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
417	w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
418	w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
419	w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
420	bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
421			(w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
422
423	/* Scan NAND */
424	err = nand_scan(&b47n->nand_chip, 1);
425	if (err) {
426		pr_err("Could not scan NAND flash: %d\n", err);
427		goto exit;
428	}
429
430	/* Configure FLASH */
431	chipsize = nanddev_target_size(&b47n->nand_chip.base) >> 20;
432	tbits = ffs(chipsize); /* find first bit set */
433	if (!tbits || tbits != fls(chipsize)) {
434		pr_err("Invalid flash size: 0x%lX\n", chipsize);
435		err = -ENOTSUPP;
436		goto exit;
437	}
438	tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
439
440	col_bits = b47n->nand_chip.page_shift + 1;
441	col_size = (col_bits + 7) / 8;
442
443	row_bits = tbits - col_bits + 1;
444	row_bsize = (row_bits + 7) / 8;
445
446	val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
447	bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
448
449exit:
450	if (err)
451		bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
452			       ~BCMA_CC_4706_FLASHSCFG_NF1);
453	return err;
454}
~/ Read-only file preview.