brintos

brintos / linux-shallow public Read only

0
0
Text · 12.6 KiB · 6487dfc Raw
452 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * BCM47XX NAND flash driver4 *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 has17 * shown ~1000 retries as maximum. */18#define NFLASH_READY_RETRIES		1000019 20#define NFLASH_SECTOR_SIZE		51221 22#define NCTL_CMD0			0x0001000023#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			0x0008000026#define NCTL_READ			0x0010000027#define NCTL_WRITE			0x0020000028#define NCTL_SPECADDR			0x0100000029#define NCTL_READY			0x0400000030#define NCTL_ERR			0x0800000031#define NCTL_CSA			0x4000000032#define NCTL_START			0x8000000033 34/**************************************************35 * Various helpers36 **************************************************/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/W83 **************************************************/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 bigger98	 * 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 bigger148	 * 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 ops167 **************************************************/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 175	if (cmd == NAND_CMD_NONE)176		return;177 178	if (cmd & NAND_CTRL_CLE)179		code = cmd | NCTL_CMD0;180 181	/* nCS is not needed for reset command */182	if (cmd != NAND_CMD_RESET)183		code |= NCTL_CSA;184 185	bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, code);186}187 188/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */189static void bcm47xxnflash_ops_bcm4706_select_chip(struct nand_chip *chip,190						  int cs)191{192	return;193}194 195static int bcm47xxnflash_ops_bcm4706_dev_ready(struct nand_chip *nand_chip)196{197	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);198 199	return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY);200}201 202/*203 * Default nand_command and nand_command_lp don't match BCM4706 hardware layout.204 * For example, reading chip id is performed in a non-standard way.205 * Setting column and page is also handled differently, we use a special206 * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert207 * standard commands would be much more complicated.208 */209static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct nand_chip *nand_chip,210					      unsigned command, int column,211					      int page_addr)212{213	struct mtd_info *mtd = nand_to_mtd(nand_chip);214	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);215	struct bcma_drv_cc *cc = b47n->cc;216	u32 ctlcode;217	int i;218 219	if (column != -1)220		b47n->curr_column = column;221	if (page_addr != -1)222		b47n->curr_page_addr = page_addr;223 224	switch (command) {225	case NAND_CMD_RESET:226		nand_chip->legacy.cmd_ctrl(nand_chip, command, NAND_CTRL_CLE);227 228		ndelay(100);229		nand_wait_ready(nand_chip);230		break;231	case NAND_CMD_READID:232		ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0;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		/*240		 * Reading is specific, last one has to go without NCTL_CSA241		 * bit. We don't know how many reads NAND subsystem is going242		 * to perform, so cache everything.243		 */244		for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {245			ctlcode = NCTL_CSA | NCTL_READ;246			if (i == ARRAY_SIZE(b47n->id_data) - 1)247				ctlcode &= ~NCTL_CSA;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;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;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;270	case NAND_CMD_ERASE1:271		bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,272				b47n->curr_page_addr);273		ctlcode = NCTL_ROW | 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 | NCTL_ROW | NCTL_COL | NCTL_CMD0;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, NCTL_CMD0 |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;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 nand_chip *nand_chip)308{309	struct mtd_info *mtd = nand_to_mtd(nand_chip);310	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);311	struct bcma_drv_cc *cc = b47n->cc;312	u32 tmp = 0;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++];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;326	case NAND_CMD_READOOB:327		bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4);328		return tmp & 0xFF;329	}330 331	pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);332	return 0;333}334 335static void bcm47xxnflash_ops_bcm4706_read_buf(struct nand_chip *nand_chip,336					       uint8_t *buf, int len)337{338	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);339 340	switch (b47n->curr_command) {341	case NAND_CMD_READ0:342	case NAND_CMD_READOOB:343		bcm47xxnflash_ops_bcm4706_read(nand_to_mtd(nand_chip), buf,344					       len);345		return;346	}347 348	pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);349}350 351static void bcm47xxnflash_ops_bcm4706_write_buf(struct nand_chip *nand_chip,352						const uint8_t *buf, int len)353{354	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);355 356	switch (b47n->curr_command) {357	case NAND_CMD_SEQIN:358		bcm47xxnflash_ops_bcm4706_write(nand_to_mtd(nand_chip), buf,359						len);360		return;361	}362 363	pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command);364}365 366/**************************************************367 * Init368 **************************************************/369 370int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)371{372	struct nand_chip *nand_chip = (struct nand_chip *)&b47n->nand_chip;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	nand_chip->legacy.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;383	nand_chip->legacy.cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl;384	nand_chip->legacy.dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready;385	b47n->nand_chip.legacy.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;386	b47n->nand_chip.legacy.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;387	b47n->nand_chip.legacy.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;388	b47n->nand_chip.legacy.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;389	b47n->nand_chip.legacy.set_features = nand_get_set_features_notsupp;390	b47n->nand_chip.legacy.get_features = nand_get_set_features_notsupp;391 392	nand_chip->legacy.chip_delay = 50;393	b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;394	/* TODO: implement ECC */395	b47n->nand_chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_NONE;396 397	/* Enable NAND flash access */398	bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,399		      BCMA_CC_4706_FLASHSCFG_NF1);400 401	/* Configure wait counters */402	if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {403		/* 400 MHz */404		freq = 400000000 / 4;405	} else {406		freq = bcma_chipco_pll_read(b47n->cc, 4);407		freq = (freq & 0xFFF) >> 3;408		/* Fixed reference clock 25 MHz and m = 2 */409		freq = (freq * 25000000 / 2) / 4;410	}411	clock = freq / 1000000;412	w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);413	w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);414	w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);415	w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);416	w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);417	bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,418			(w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));419 420	/* Scan NAND */421	err = nand_scan(&b47n->nand_chip, 1);422	if (err) {423		pr_err("Could not scan NAND flash: %d\n", err);424		goto exit;425	}426 427	/* Configure FLASH */428	chipsize = nanddev_target_size(&b47n->nand_chip.base) >> 20;429	tbits = ffs(chipsize); /* find first bit set */430	if (!tbits || tbits != fls(chipsize)) {431		pr_err("Invalid flash size: 0x%lX\n", chipsize);432		err = -ENOTSUPP;433		goto exit;434	}435	tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */436 437	col_bits = b47n->nand_chip.page_shift + 1;438	col_size = (col_bits + 7) / 8;439 440	row_bits = tbits - col_bits + 1;441	row_bsize = (row_bits + 7) / 8;442 443	val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;444	bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);445 446exit:447	if (err)448		bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,449			       ~BCMA_CC_4706_FLASHSCFG_NF1);450	return err;451}452