cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ops_bcm4706.c (12911B)


      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 maxiumum. */
     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
    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 special
    206 * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
    207 * 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_CSA
    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++) {
    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 * Init
    368 **************************************************/
    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}