drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c

Source file repositories/reference/linux-study-clean/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
Extension
.c
Size
12986 bytes
Lines
455
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_START)) {
			i = 0;
			break;
		}
	}
	if (i) {
		pr_err("NFLASH control command not ready!\n");
		return -EBUSY;
	}
	return 0;
}

static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
{
	int i;

	for (i = 0; i < NFLASH_READY_RETRIES; i++) {
		if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_READY) {
			if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) &
			    BCMA_CC_NFLASH_CTL_ERR) {
				pr_err("Error on polling\n");
				return -EBUSY;
			} else {
				return 0;
			}
		}
	}

	pr_err("Polling timeout!\n");
	return -EBUSY;
}

/**************************************************
 * R/W
 **************************************************/

static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
					   int len)
{
	struct nand_chip *nand_chip = mtd_to_nand(mtd);
	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);

	u32 ctlcode;
	u32 *dest = (u32 *)buf;
	int i;
	int toread;

	BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
	/* Don't validate column using nand_chip->page_shift, it may be bigger
	 * when accessing OOB */

	while (len) {
		/* We can read maximum of 0x200 bytes at once */
		toread = min(len, 0x200);

		/* Set page and column */
		bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR,
				b47n->curr_column);
		bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR,
				b47n->curr_page_addr);

		/* Prepare to read */
		ctlcode = NCTL_CSA | NCTL_CMD1W | NCTL_ROW | NCTL_COL |
			  NCTL_CMD0;
		ctlcode |= NAND_CMD_READSTART << 8;
		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode))
			return;
		if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc))
			return;

		/* Eventually read some data :) */
		for (i = 0; i < toread; i += 4, dest++) {
			ctlcode = NCTL_CSA | 0x30000000 | NCTL_READ;
			if (i == toread - 4) /* Last read goes without that */
				ctlcode &= ~NCTL_CSA;
			if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
							      ctlcode))
				return;
			*dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA);
		}

		b47n->curr_column += toread;
		len -= toread;
	}
}

static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
					    const uint8_t *buf, int len)
{
	struct nand_chip *nand_chip = mtd_to_nand(mtd);

Annotation

Implementation Notes