xref: /openbmc/linux/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
293db446aSBoris Brezillon /*
393db446aSBoris Brezillon  * BCM47XX NAND flash driver
493db446aSBoris Brezillon  *
593db446aSBoris Brezillon  * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
693db446aSBoris Brezillon  */
793db446aSBoris Brezillon 
893db446aSBoris Brezillon #include "bcm47xxnflash.h"
993db446aSBoris Brezillon 
1093db446aSBoris Brezillon #include <linux/module.h>
1193db446aSBoris Brezillon #include <linux/kernel.h>
1293db446aSBoris Brezillon #include <linux/slab.h>
1393db446aSBoris Brezillon #include <linux/delay.h>
1493db446aSBoris Brezillon #include <linux/bcma/bcma.h>
1593db446aSBoris Brezillon 
1693db446aSBoris Brezillon /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
17*36ac78ceSJiangshan Yi  * shown ~1000 retries as maximum. */
1893db446aSBoris Brezillon #define NFLASH_READY_RETRIES		10000
1993db446aSBoris Brezillon 
2093db446aSBoris Brezillon #define NFLASH_SECTOR_SIZE		512
2193db446aSBoris Brezillon 
2293db446aSBoris Brezillon #define NCTL_CMD0			0x00010000
2393db446aSBoris Brezillon #define NCTL_COL			0x00020000	/* Update column with value from BCMA_CC_NFLASH_COL_ADDR */
2493db446aSBoris Brezillon #define NCTL_ROW			0x00040000	/* Update row (page) with value from BCMA_CC_NFLASH_ROW_ADDR */
2593db446aSBoris Brezillon #define NCTL_CMD1W			0x00080000
2693db446aSBoris Brezillon #define NCTL_READ			0x00100000
2793db446aSBoris Brezillon #define NCTL_WRITE			0x00200000
2893db446aSBoris Brezillon #define NCTL_SPECADDR			0x01000000
2993db446aSBoris Brezillon #define NCTL_READY			0x04000000
3093db446aSBoris Brezillon #define NCTL_ERR			0x08000000
3193db446aSBoris Brezillon #define NCTL_CSA			0x40000000
3293db446aSBoris Brezillon #define NCTL_START			0x80000000
3393db446aSBoris Brezillon 
3493db446aSBoris Brezillon /**************************************************
3593db446aSBoris Brezillon  * Various helpers
3693db446aSBoris Brezillon  **************************************************/
3793db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns,u16 clock)3893db446aSBoris Brezillon static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
3993db446aSBoris Brezillon {
4093db446aSBoris Brezillon 	return ((ns * 1000 * clock) / 1000000) + 1;
4193db446aSBoris Brezillon }
4293db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc * cc,u32 code)4393db446aSBoris Brezillon static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
4493db446aSBoris Brezillon {
4593db446aSBoris Brezillon 	int i = 0;
4693db446aSBoris Brezillon 
4793db446aSBoris Brezillon 	bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, NCTL_START | code);
4893db446aSBoris Brezillon 	for (i = 0; i < NFLASH_READY_RETRIES; i++) {
4993db446aSBoris Brezillon 		if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_START)) {
5093db446aSBoris Brezillon 			i = 0;
5193db446aSBoris Brezillon 			break;
5293db446aSBoris Brezillon 		}
5393db446aSBoris Brezillon 	}
5493db446aSBoris Brezillon 	if (i) {
5593db446aSBoris Brezillon 		pr_err("NFLASH control command not ready!\n");
5693db446aSBoris Brezillon 		return -EBUSY;
5793db446aSBoris Brezillon 	}
5893db446aSBoris Brezillon 	return 0;
5993db446aSBoris Brezillon }
6093db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc * cc)6193db446aSBoris Brezillon static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
6293db446aSBoris Brezillon {
6393db446aSBoris Brezillon 	int i;
6493db446aSBoris Brezillon 
6593db446aSBoris Brezillon 	for (i = 0; i < NFLASH_READY_RETRIES; i++) {
6693db446aSBoris Brezillon 		if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_READY) {
6793db446aSBoris Brezillon 			if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) &
6893db446aSBoris Brezillon 			    BCMA_CC_NFLASH_CTL_ERR) {
6993db446aSBoris Brezillon 				pr_err("Error on polling\n");
7093db446aSBoris Brezillon 				return -EBUSY;
7193db446aSBoris Brezillon 			} else {
7293db446aSBoris Brezillon 				return 0;
7393db446aSBoris Brezillon 			}
7493db446aSBoris Brezillon 		}
7593db446aSBoris Brezillon 	}
7693db446aSBoris Brezillon 
7793db446aSBoris Brezillon 	pr_err("Polling timeout!\n");
7893db446aSBoris Brezillon 	return -EBUSY;
7993db446aSBoris Brezillon }
8093db446aSBoris Brezillon 
8193db446aSBoris Brezillon /**************************************************
8293db446aSBoris Brezillon  * R/W
8393db446aSBoris Brezillon  **************************************************/
8493db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_read(struct mtd_info * mtd,uint8_t * buf,int len)8593db446aSBoris Brezillon static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
8693db446aSBoris Brezillon 					   int len)
8793db446aSBoris Brezillon {
8893db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
8993db446aSBoris Brezillon 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
9093db446aSBoris Brezillon 
9193db446aSBoris Brezillon 	u32 ctlcode;
9293db446aSBoris Brezillon 	u32 *dest = (u32 *)buf;
9393db446aSBoris Brezillon 	int i;
9493db446aSBoris Brezillon 	int toread;
9593db446aSBoris Brezillon 
9693db446aSBoris Brezillon 	BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
9793db446aSBoris Brezillon 	/* Don't validate column using nand_chip->page_shift, it may be bigger
9893db446aSBoris Brezillon 	 * when accessing OOB */
9993db446aSBoris Brezillon 
10093db446aSBoris Brezillon 	while (len) {
10193db446aSBoris Brezillon 		/* We can read maximum of 0x200 bytes at once */
10293db446aSBoris Brezillon 		toread = min(len, 0x200);
10393db446aSBoris Brezillon 
10493db446aSBoris Brezillon 		/* Set page and column */
10593db446aSBoris Brezillon 		bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR,
10693db446aSBoris Brezillon 				b47n->curr_column);
10793db446aSBoris Brezillon 		bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR,
10893db446aSBoris Brezillon 				b47n->curr_page_addr);
10993db446aSBoris Brezillon 
11093db446aSBoris Brezillon 		/* Prepare to read */
11193db446aSBoris Brezillon 		ctlcode = NCTL_CSA | NCTL_CMD1W | NCTL_ROW | NCTL_COL |
11293db446aSBoris Brezillon 			  NCTL_CMD0;
11393db446aSBoris Brezillon 		ctlcode |= NAND_CMD_READSTART << 8;
11493db446aSBoris Brezillon 		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode))
11593db446aSBoris Brezillon 			return;
11693db446aSBoris Brezillon 		if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc))
11793db446aSBoris Brezillon 			return;
11893db446aSBoris Brezillon 
11993db446aSBoris Brezillon 		/* Eventually read some data :) */
12093db446aSBoris Brezillon 		for (i = 0; i < toread; i += 4, dest++) {
12193db446aSBoris Brezillon 			ctlcode = NCTL_CSA | 0x30000000 | NCTL_READ;
12293db446aSBoris Brezillon 			if (i == toread - 4) /* Last read goes without that */
12393db446aSBoris Brezillon 				ctlcode &= ~NCTL_CSA;
12493db446aSBoris Brezillon 			if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
12593db446aSBoris Brezillon 							      ctlcode))
12693db446aSBoris Brezillon 				return;
12793db446aSBoris Brezillon 			*dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA);
12893db446aSBoris Brezillon 		}
12993db446aSBoris Brezillon 
13093db446aSBoris Brezillon 		b47n->curr_column += toread;
13193db446aSBoris Brezillon 		len -= toread;
13293db446aSBoris Brezillon 	}
13393db446aSBoris Brezillon }
13493db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_write(struct mtd_info * mtd,const uint8_t * buf,int len)13593db446aSBoris Brezillon static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
13693db446aSBoris Brezillon 					    const uint8_t *buf, int len)
13793db446aSBoris Brezillon {
13893db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
13993db446aSBoris Brezillon 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
14093db446aSBoris Brezillon 	struct bcma_drv_cc *cc = b47n->cc;
14193db446aSBoris Brezillon 
14293db446aSBoris Brezillon 	u32 ctlcode;
14393db446aSBoris Brezillon 	const u32 *data = (u32 *)buf;
14493db446aSBoris Brezillon 	int i;
14593db446aSBoris Brezillon 
14693db446aSBoris Brezillon 	BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
14793db446aSBoris Brezillon 	/* Don't validate column using nand_chip->page_shift, it may be bigger
14893db446aSBoris Brezillon 	 * when accessing OOB */
14993db446aSBoris Brezillon 
15093db446aSBoris Brezillon 	for (i = 0; i < len; i += 4, data++) {
15193db446aSBoris Brezillon 		bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data);
15293db446aSBoris Brezillon 
15393db446aSBoris Brezillon 		ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE;
15493db446aSBoris Brezillon 		if (i == len - 4) /* Last read goes without that */
15593db446aSBoris Brezillon 			ctlcode &= ~NCTL_CSA;
15693db446aSBoris Brezillon 		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) {
15793db446aSBoris Brezillon 			pr_err("%s ctl_cmd didn't work!\n", __func__);
15893db446aSBoris Brezillon 			return;
15993db446aSBoris Brezillon 		}
16093db446aSBoris Brezillon 	}
16193db446aSBoris Brezillon 
16293db446aSBoris Brezillon 	b47n->curr_column += len;
16393db446aSBoris Brezillon }
16493db446aSBoris Brezillon 
16593db446aSBoris Brezillon /**************************************************
16693db446aSBoris Brezillon  * NAND chip ops
16793db446aSBoris Brezillon  **************************************************/
16893db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct nand_chip * nand_chip,int cmd,unsigned int ctrl)1690f808c16SBoris Brezillon static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct nand_chip *nand_chip,
1700f808c16SBoris Brezillon 					       int cmd, unsigned int ctrl)
17193db446aSBoris Brezillon {
17293db446aSBoris Brezillon 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
17393db446aSBoris Brezillon 	u32 code = 0;
17493db446aSBoris Brezillon 
17593db446aSBoris Brezillon 	if (cmd == NAND_CMD_NONE)
17693db446aSBoris Brezillon 		return;
17793db446aSBoris Brezillon 
17893db446aSBoris Brezillon 	if (cmd & NAND_CTRL_CLE)
17993db446aSBoris Brezillon 		code = cmd | NCTL_CMD0;
18093db446aSBoris Brezillon 
18193db446aSBoris Brezillon 	/* nCS is not needed for reset command */
18293db446aSBoris Brezillon 	if (cmd != NAND_CMD_RESET)
18393db446aSBoris Brezillon 		code |= NCTL_CSA;
18493db446aSBoris Brezillon 
18593db446aSBoris Brezillon 	bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, code);
18693db446aSBoris Brezillon }
18793db446aSBoris Brezillon 
18893db446aSBoris Brezillon /* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
bcm47xxnflash_ops_bcm4706_select_chip(struct nand_chip * chip,int cs)189758b56f5SBoris Brezillon static void bcm47xxnflash_ops_bcm4706_select_chip(struct nand_chip *chip,
190758b56f5SBoris Brezillon 						  int cs)
19193db446aSBoris Brezillon {
19293db446aSBoris Brezillon 	return;
19393db446aSBoris Brezillon }
19493db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_dev_ready(struct nand_chip * nand_chip)19550a487e7SBoris Brezillon static int bcm47xxnflash_ops_bcm4706_dev_ready(struct nand_chip *nand_chip)
19693db446aSBoris Brezillon {
19793db446aSBoris Brezillon 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
19893db446aSBoris Brezillon 
19993db446aSBoris Brezillon 	return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY);
20093db446aSBoris Brezillon }
20193db446aSBoris Brezillon 
20293db446aSBoris Brezillon /*
20393db446aSBoris Brezillon  * Default nand_command and nand_command_lp don't match BCM4706 hardware layout.
20493db446aSBoris Brezillon  * For example, reading chip id is performed in a non-standard way.
20593db446aSBoris Brezillon  * Setting column and page is also handled differently, we use a special
20693db446aSBoris Brezillon  * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
20793db446aSBoris Brezillon  * standard commands would be much more complicated.
20893db446aSBoris Brezillon  */
bcm47xxnflash_ops_bcm4706_cmdfunc(struct nand_chip * nand_chip,unsigned command,int column,int page_addr)2095295cf2eSBoris Brezillon static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct nand_chip *nand_chip,
21093db446aSBoris Brezillon 					      unsigned command, int column,
21193db446aSBoris Brezillon 					      int page_addr)
21293db446aSBoris Brezillon {
2135295cf2eSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(nand_chip);
21493db446aSBoris Brezillon 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
21593db446aSBoris Brezillon 	struct bcma_drv_cc *cc = b47n->cc;
21693db446aSBoris Brezillon 	u32 ctlcode;
21793db446aSBoris Brezillon 	int i;
21893db446aSBoris Brezillon 
21993db446aSBoris Brezillon 	if (column != -1)
22093db446aSBoris Brezillon 		b47n->curr_column = column;
22193db446aSBoris Brezillon 	if (page_addr != -1)
22293db446aSBoris Brezillon 		b47n->curr_page_addr = page_addr;
22393db446aSBoris Brezillon 
22493db446aSBoris Brezillon 	switch (command) {
22593db446aSBoris Brezillon 	case NAND_CMD_RESET:
226bf6065c6SBoris Brezillon 		nand_chip->legacy.cmd_ctrl(nand_chip, command, NAND_CTRL_CLE);
22793db446aSBoris Brezillon 
22893db446aSBoris Brezillon 		ndelay(100);
2292b356ab4SBoris Brezillon 		nand_wait_ready(nand_chip);
23093db446aSBoris Brezillon 		break;
23193db446aSBoris Brezillon 	case NAND_CMD_READID:
23293db446aSBoris Brezillon 		ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0;
23393db446aSBoris Brezillon 		ctlcode |= NAND_CMD_READID;
23493db446aSBoris Brezillon 		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) {
23593db446aSBoris Brezillon 			pr_err("READID error\n");
23693db446aSBoris Brezillon 			break;
23793db446aSBoris Brezillon 		}
23893db446aSBoris Brezillon 
23993db446aSBoris Brezillon 		/*
24093db446aSBoris Brezillon 		 * Reading is specific, last one has to go without NCTL_CSA
24193db446aSBoris Brezillon 		 * bit. We don't know how many reads NAND subsystem is going
24293db446aSBoris Brezillon 		 * to perform, so cache everything.
24393db446aSBoris Brezillon 		 */
24493db446aSBoris Brezillon 		for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {
24593db446aSBoris Brezillon 			ctlcode = NCTL_CSA | NCTL_READ;
24693db446aSBoris Brezillon 			if (i == ARRAY_SIZE(b47n->id_data) - 1)
24793db446aSBoris Brezillon 				ctlcode &= ~NCTL_CSA;
24893db446aSBoris Brezillon 			if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
24993db446aSBoris Brezillon 							      ctlcode)) {
25093db446aSBoris Brezillon 				pr_err("READID error\n");
25193db446aSBoris Brezillon 				break;
25293db446aSBoris Brezillon 			}
25393db446aSBoris Brezillon 			b47n->id_data[i] =
25493db446aSBoris Brezillon 				bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA)
25593db446aSBoris Brezillon 				& 0xFF;
25693db446aSBoris Brezillon 		}
25793db446aSBoris Brezillon 
25893db446aSBoris Brezillon 		break;
25993db446aSBoris Brezillon 	case NAND_CMD_STATUS:
26093db446aSBoris Brezillon 		ctlcode = NCTL_CSA | NCTL_CMD0 | NAND_CMD_STATUS;
26193db446aSBoris Brezillon 		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
26293db446aSBoris Brezillon 			pr_err("STATUS command error\n");
26393db446aSBoris Brezillon 		break;
26493db446aSBoris Brezillon 	case NAND_CMD_READ0:
26593db446aSBoris Brezillon 		break;
26693db446aSBoris Brezillon 	case NAND_CMD_READOOB:
26793db446aSBoris Brezillon 		if (page_addr != -1)
26893db446aSBoris Brezillon 			b47n->curr_column += mtd->writesize;
26993db446aSBoris Brezillon 		break;
27093db446aSBoris Brezillon 	case NAND_CMD_ERASE1:
27193db446aSBoris Brezillon 		bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
27293db446aSBoris Brezillon 				b47n->curr_page_addr);
27393db446aSBoris Brezillon 		ctlcode = NCTL_ROW | NCTL_CMD1W | NCTL_CMD0 |
27493db446aSBoris Brezillon 			  NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8);
27593db446aSBoris Brezillon 		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
27693db446aSBoris Brezillon 			pr_err("ERASE1 failed\n");
27793db446aSBoris Brezillon 		break;
27893db446aSBoris Brezillon 	case NAND_CMD_ERASE2:
27993db446aSBoris Brezillon 		break;
28093db446aSBoris Brezillon 	case NAND_CMD_SEQIN:
28193db446aSBoris Brezillon 		/* Set page and column */
28293db446aSBoris Brezillon 		bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR,
28393db446aSBoris Brezillon 				b47n->curr_column);
28493db446aSBoris Brezillon 		bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
28593db446aSBoris Brezillon 				b47n->curr_page_addr);
28693db446aSBoris Brezillon 
28793db446aSBoris Brezillon 		/* Prepare to write */
28893db446aSBoris Brezillon 		ctlcode = 0x40000000 | NCTL_ROW | NCTL_COL | NCTL_CMD0;
28993db446aSBoris Brezillon 		ctlcode |= NAND_CMD_SEQIN;
29093db446aSBoris Brezillon 		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
29193db446aSBoris Brezillon 			pr_err("SEQIN failed\n");
29293db446aSBoris Brezillon 		break;
29393db446aSBoris Brezillon 	case NAND_CMD_PAGEPROG:
29493db446aSBoris Brezillon 		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_CMD0 |
29593db446aSBoris Brezillon 							  NAND_CMD_PAGEPROG))
29693db446aSBoris Brezillon 			pr_err("PAGEPROG failed\n");
29793db446aSBoris Brezillon 		if (bcm47xxnflash_ops_bcm4706_poll(cc))
29893db446aSBoris Brezillon 			pr_err("PAGEPROG not ready\n");
29993db446aSBoris Brezillon 		break;
30093db446aSBoris Brezillon 	default:
30193db446aSBoris Brezillon 		pr_err("Command 0x%X unsupported\n", command);
30293db446aSBoris Brezillon 		break;
30393db446aSBoris Brezillon 	}
30493db446aSBoris Brezillon 	b47n->curr_command = command;
30593db446aSBoris Brezillon }
30693db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_read_byte(struct nand_chip * nand_chip)3077e534323SBoris Brezillon static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct nand_chip *nand_chip)
30893db446aSBoris Brezillon {
3097e534323SBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(nand_chip);
31093db446aSBoris Brezillon 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
31193db446aSBoris Brezillon 	struct bcma_drv_cc *cc = b47n->cc;
31293db446aSBoris Brezillon 	u32 tmp = 0;
31393db446aSBoris Brezillon 
31493db446aSBoris Brezillon 	switch (b47n->curr_command) {
31593db446aSBoris Brezillon 	case NAND_CMD_READID:
31693db446aSBoris Brezillon 		if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) {
31793db446aSBoris Brezillon 			pr_err("Requested invalid id_data: %d\n",
31893db446aSBoris Brezillon 			       b47n->curr_column);
31993db446aSBoris Brezillon 			return 0;
32093db446aSBoris Brezillon 		}
32193db446aSBoris Brezillon 		return b47n->id_data[b47n->curr_column++];
32293db446aSBoris Brezillon 	case NAND_CMD_STATUS:
32393db446aSBoris Brezillon 		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_READ))
32493db446aSBoris Brezillon 			return 0;
32593db446aSBoris Brezillon 		return bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xff;
32693db446aSBoris Brezillon 	case NAND_CMD_READOOB:
32793db446aSBoris Brezillon 		bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4);
32893db446aSBoris Brezillon 		return tmp & 0xFF;
32993db446aSBoris Brezillon 	}
33093db446aSBoris Brezillon 
33193db446aSBoris Brezillon 	pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
33293db446aSBoris Brezillon 	return 0;
33393db446aSBoris Brezillon }
33493db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_read_buf(struct nand_chip * nand_chip,uint8_t * buf,int len)3357e534323SBoris Brezillon static void bcm47xxnflash_ops_bcm4706_read_buf(struct nand_chip *nand_chip,
33693db446aSBoris Brezillon 					       uint8_t *buf, int len)
33793db446aSBoris Brezillon {
33893db446aSBoris Brezillon 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
33993db446aSBoris Brezillon 
34093db446aSBoris Brezillon 	switch (b47n->curr_command) {
34193db446aSBoris Brezillon 	case NAND_CMD_READ0:
34293db446aSBoris Brezillon 	case NAND_CMD_READOOB:
3437e534323SBoris Brezillon 		bcm47xxnflash_ops_bcm4706_read(nand_to_mtd(nand_chip), buf,
3447e534323SBoris Brezillon 					       len);
34593db446aSBoris Brezillon 		return;
34693db446aSBoris Brezillon 	}
34793db446aSBoris Brezillon 
34893db446aSBoris Brezillon 	pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
34993db446aSBoris Brezillon }
35093db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_write_buf(struct nand_chip * nand_chip,const uint8_t * buf,int len)351c0739d85SBoris Brezillon static void bcm47xxnflash_ops_bcm4706_write_buf(struct nand_chip *nand_chip,
35293db446aSBoris Brezillon 						const uint8_t *buf, int len)
35393db446aSBoris Brezillon {
35493db446aSBoris Brezillon 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
35593db446aSBoris Brezillon 
35693db446aSBoris Brezillon 	switch (b47n->curr_command) {
35793db446aSBoris Brezillon 	case NAND_CMD_SEQIN:
358c0739d85SBoris Brezillon 		bcm47xxnflash_ops_bcm4706_write(nand_to_mtd(nand_chip), buf,
359c0739d85SBoris Brezillon 						len);
36093db446aSBoris Brezillon 		return;
36193db446aSBoris Brezillon 	}
36293db446aSBoris Brezillon 
36393db446aSBoris Brezillon 	pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command);
36493db446aSBoris Brezillon }
36593db446aSBoris Brezillon 
36693db446aSBoris Brezillon /**************************************************
36793db446aSBoris Brezillon  * Init
36893db446aSBoris Brezillon  **************************************************/
36993db446aSBoris Brezillon 
bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash * b47n)37093db446aSBoris Brezillon int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
37193db446aSBoris Brezillon {
37293db446aSBoris Brezillon 	struct nand_chip *nand_chip = (struct nand_chip *)&b47n->nand_chip;
37393db446aSBoris Brezillon 	int err;
37493db446aSBoris Brezillon 	u32 freq;
37593db446aSBoris Brezillon 	u16 clock;
37693db446aSBoris Brezillon 	u8 w0, w1, w2, w3, w4;
37793db446aSBoris Brezillon 
37893db446aSBoris Brezillon 	unsigned long chipsize; /* MiB */
37993db446aSBoris Brezillon 	u8 tbits, col_bits, col_size, row_bits, row_bsize;
38093db446aSBoris Brezillon 	u32 val;
38193db446aSBoris Brezillon 
3827d6c37e9SBoris Brezillon 	nand_chip->legacy.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
383bf6065c6SBoris Brezillon 	nand_chip->legacy.cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl;
3848395b753SBoris Brezillon 	nand_chip->legacy.dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready;
385bf6065c6SBoris Brezillon 	b47n->nand_chip.legacy.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
386716bbbabSBoris Brezillon 	b47n->nand_chip.legacy.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
387716bbbabSBoris Brezillon 	b47n->nand_chip.legacy.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
388716bbbabSBoris Brezillon 	b47n->nand_chip.legacy.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
38945240367SBoris Brezillon 	b47n->nand_chip.legacy.set_features = nand_get_set_features_notsupp;
39045240367SBoris Brezillon 	b47n->nand_chip.legacy.get_features = nand_get_set_features_notsupp;
39193db446aSBoris Brezillon 
3923cece3abSBoris Brezillon 	nand_chip->legacy.chip_delay = 50;
39393db446aSBoris Brezillon 	b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
394bace41f8SMiquel Raynal 	/* TODO: implement ECC */
395bace41f8SMiquel Raynal 	b47n->nand_chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_NONE;
39693db446aSBoris Brezillon 
39793db446aSBoris Brezillon 	/* Enable NAND flash access */
39893db446aSBoris Brezillon 	bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
39993db446aSBoris Brezillon 		      BCMA_CC_4706_FLASHSCFG_NF1);
40093db446aSBoris Brezillon 
40193db446aSBoris Brezillon 	/* Configure wait counters */
40293db446aSBoris Brezillon 	if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
40393db446aSBoris Brezillon 		/* 400 MHz */
40493db446aSBoris Brezillon 		freq = 400000000 / 4;
40593db446aSBoris Brezillon 	} else {
40693db446aSBoris Brezillon 		freq = bcma_chipco_pll_read(b47n->cc, 4);
40793db446aSBoris Brezillon 		freq = (freq & 0xFFF) >> 3;
40893db446aSBoris Brezillon 		/* Fixed reference clock 25 MHz and m = 2 */
40993db446aSBoris Brezillon 		freq = (freq * 25000000 / 2) / 4;
41093db446aSBoris Brezillon 	}
41193db446aSBoris Brezillon 	clock = freq / 1000000;
41293db446aSBoris Brezillon 	w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
41393db446aSBoris Brezillon 	w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
41493db446aSBoris Brezillon 	w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
41593db446aSBoris Brezillon 	w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
41693db446aSBoris Brezillon 	w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
41793db446aSBoris Brezillon 	bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
41893db446aSBoris Brezillon 			(w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
41993db446aSBoris Brezillon 
42093db446aSBoris Brezillon 	/* Scan NAND */
42100ad378fSBoris Brezillon 	err = nand_scan(&b47n->nand_chip, 1);
42293db446aSBoris Brezillon 	if (err) {
42393db446aSBoris Brezillon 		pr_err("Could not scan NAND flash: %d\n", err);
42493db446aSBoris Brezillon 		goto exit;
42593db446aSBoris Brezillon 	}
42693db446aSBoris Brezillon 
42793db446aSBoris Brezillon 	/* Configure FLASH */
4286c836d51SBoris Brezillon 	chipsize = nanddev_target_size(&b47n->nand_chip.base) >> 20;
42993db446aSBoris Brezillon 	tbits = ffs(chipsize); /* find first bit set */
43093db446aSBoris Brezillon 	if (!tbits || tbits != fls(chipsize)) {
43193db446aSBoris Brezillon 		pr_err("Invalid flash size: 0x%lX\n", chipsize);
43293db446aSBoris Brezillon 		err = -ENOTSUPP;
43393db446aSBoris Brezillon 		goto exit;
43493db446aSBoris Brezillon 	}
43593db446aSBoris Brezillon 	tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
43693db446aSBoris Brezillon 
43793db446aSBoris Brezillon 	col_bits = b47n->nand_chip.page_shift + 1;
43893db446aSBoris Brezillon 	col_size = (col_bits + 7) / 8;
43993db446aSBoris Brezillon 
44093db446aSBoris Brezillon 	row_bits = tbits - col_bits + 1;
44193db446aSBoris Brezillon 	row_bsize = (row_bits + 7) / 8;
44293db446aSBoris Brezillon 
44393db446aSBoris Brezillon 	val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
44493db446aSBoris Brezillon 	bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
44593db446aSBoris Brezillon 
44693db446aSBoris Brezillon exit:
44793db446aSBoris Brezillon 	if (err)
44893db446aSBoris Brezillon 		bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
44993db446aSBoris Brezillon 			       ~BCMA_CC_4706_FLASHSCFG_NF1);
45093db446aSBoris Brezillon 	return err;
45193db446aSBoris Brezillon }
452