static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *chip = mtd_to_nand(mtd); struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip); struct platform_device *dev = txx9_priv->dev; struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); if (ctrl & NAND_CTRL_CHANGE) { u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); mcr &= ~(TXX9_NDFMCR_CLE | TXX9_NDFMCR_ALE | TXX9_NDFMCR_CE); mcr |= ctrl & NAND_CLE ? TXX9_NDFMCR_CLE : 0; mcr |= ctrl & NAND_ALE ? TXX9_NDFMCR_ALE : 0; /* TXX9_NDFMCR_CE bit is 0:high 1:low */ mcr |= ctrl & NAND_NCE ? TXX9_NDFMCR_CE : 0; if (txx9_priv->cs >= 0 && (ctrl & NAND_NCE)) { mcr &= ~TXX9_NDFMCR_CS_MASK; mcr |= TXX9_NDFMCR_CS(txx9_priv->cs); } txx9ndfmc_write(dev, mcr, TXX9_NDFMCR); } if (cmd != NAND_CMD_NONE) txx9ndfmc_write(dev, cmd & 0xff, TXX9_NDFDTR); if (plat->flags & NDFMC_PLAT_FLAG_DUMMYWRITE) { /* dummy write to update external latch */ if ((ctrl & NAND_CTRL_CHANGE) && cmd == NAND_CMD_NONE) txx9ndfmc_write(dev, 0, TXX9_NDFDTR); } mmiowb(); }
static void meson_nfc_select_chip(struct nand_chip *nand, int chip) { struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); struct meson_nfc *nfc = nand_get_controller_data(nand); int ret, value; if (chip < 0 || WARN_ON_ONCE(chip >= meson_chip->nsels)) return; nfc->param.chip_select = meson_chip->sels[chip] ? NAND_CE1 : NAND_CE0; nfc->param.rb_select = nfc->param.chip_select; nfc->timing.twb = meson_chip->twb; nfc->timing.tadl = meson_chip->tadl; nfc->timing.tbers_max = meson_chip->tbers_max; if (nfc->clk_rate != meson_chip->clk_rate) { ret = clk_set_rate(nfc->device_clk, meson_chip->clk_rate); if (ret) { dev_err(nfc->dev, "failed to set clock rate\n"); return; } nfc->clk_rate = meson_chip->clk_rate; } if (nfc->bus_timing != meson_chip->bus_timing) { value = (NFC_CLK_CYCLE - 1) | (meson_chip->bus_timing << 5); writel(value, nfc->reg_base + NFC_REG_CFG); writel((1 << 31), nfc->reg_base + NFC_REG_CMD); nfc->bus_timing = meson_chip->bus_timing; } }
/* * Write OOB data to NAND. */ static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand, int page) { struct mxs_nand_info *nand_info = nand_get_controller_data(nand); uint8_t block_mark = 0; /* * There are fundamental incompatibilities between the i.MX GPMI NFC and * the NAND Flash MTD model that make it essentially impossible to write * the out-of-band bytes. * * We permit *ONE* exception. If the *intent* of writing the OOB is to * mark a block bad, we can do that. */ if (!nand_info->marking_block_bad) { printf("NXS NAND: Writing OOB isn't supported\n"); return -EIO; } /* Write the block mark. */ nand->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); nand->write_buf(mtd, &block_mark, 1); nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); /* Check if it worked. */ if (nand->waitfunc(mtd, nand) & NAND_STATUS_FAIL) return -EIO; return 0; }
static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir, int scrambler) { struct mtd_info *mtd = nand_to_mtd(nand); struct meson_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); u32 bch = meson_chip->bch_mode, cmd; int len = mtd->writesize, pagesize, pages; pagesize = nand->ecc.size; if (raw) { len = mtd->writesize + mtd->oobsize; cmd = (len & GENMASK(5, 0)) | scrambler | DMA_DIR(dir); writel(cmd, nfc->reg_base + NFC_REG_CMD); return; } pages = len / nand->ecc.size; cmd = CMDRWGEN(DMA_DIR(dir), scrambler, bch, NFC_CMD_SHORTMODE_DISABLE, pagesize, pages); writel(cmd, nfc->reg_base + NFC_REG_CMD); }
static int spinand_wait(struct mtd_info *mtd, struct nand_chip *chip) { struct spinand_info *info = nand_get_controller_data(chip); unsigned long timeo = jiffies; int retval, state = chip->state; u8 status; if (state == FL_ERASING) timeo += (HZ * 400) / 1000; else timeo += (HZ * 20) / 1000; while (time_before(jiffies, timeo)) { retval = spinand_read_status(info->spi, &status); if (retval < 0) { dev_err(&mtd->dev, "error %d reading status register\n", retval); return retval; } if ((status & STATUS_OIP_MASK) == STATUS_READY) return 0; cond_resched(); } return 0; }
/* * Select the NAND chip. */ static void mxs_nand_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *nand = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = nand_get_controller_data(nand); nand_info->cur_chip = chip; }
static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct nand_chip *nand_chip) { struct mtd_info *mtd = nand_to_mtd(nand_chip); struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); struct bcma_drv_cc *cc = b47n->cc; u32 tmp = 0; switch (b47n->curr_command) { case NAND_CMD_READID: if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) { pr_err("Requested invalid id_data: %d\n", b47n->curr_column); return 0; } return b47n->id_data[b47n->curr_column++]; case NAND_CMD_STATUS: if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_READ)) return 0; return bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xff; case NAND_CMD_READOOB: bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4); return tmp & 0xFF; } pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command); return 0; }
static int nand_dev_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_upm_nand *fun = nand_get_controller_data(chip); return fun->dev_ready(fun->chip_nr); }
static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY); }
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); struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); struct bcma_drv_cc *cc = b47n->cc; u32 ctlcode; const u32 *data = (u32 *)buf; int i; 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 */ for (i = 0; i < len; i += 4, data++) { bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data); ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE; if (i == len - 4) /* Last read goes without that */ ctlcode &= ~NCTL_CSA; if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) { pr_err("%s ctl_cmd didn't work!\n", __func__); return; } } b47n->curr_column += len; }
static u8 xway_readb(struct mtd_info *mtd, int op) { struct nand_chip *chip = mtd_to_nand(mtd); struct xway_nand_data *data = nand_get_controller_data(chip); return readb(data->nandaddr + op); }
static void xway_writeb(struct mtd_info *mtd, int op, u8 value) { struct nand_chip *chip = mtd_to_nand(mtd); struct xway_nand_data *data = nand_get_controller_data(chip); writeb(value, data->nandaddr + op); }
static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); return readb(oxnas->io_base); }
static int ndfc_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(chip); return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; }
static void oxnas_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); iowrite8_rep(oxnas->io_base, buf, len); }
/* * There are several places in this driver where we have to handle the OOB and * block marks. This is the function where things are the most complicated, so * this is where we try to explain it all. All the other places refer back to * here. * * These are the rules, in order of decreasing importance: * * 1) Nothing the caller does can be allowed to imperil the block mark, so all * write operations take measures to protect it. * * 2) In read operations, the first byte of the OOB we return must reflect the * true state of the block mark, no matter where that block mark appears in * the physical page. * * 3) ECC-based read operations return an OOB full of set bits (since we never * allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads * return). * * 4) "Raw" read operations return a direct view of the physical bytes in the * page, using the conventional definition of which bytes are data and which * are OOB. This gives the caller a way to see the actual, physical bytes * in the page, without the distortions applied by our ECC engine. * * What we do for this specific read operation depends on whether we're doing * "raw" read, or an ECC-based read. * * It turns out that knowing whether we want an "ECC-based" or "raw" read is not * easy. When reading a page, for example, the NAND Flash MTD code calls our * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an * ECC-based or raw view of the page is implicit in which function it calls * (there is a similar pair of ECC-based/raw functions for writing). * * Since MTD assumes the OOB is not covered by ECC, there is no pair of * ECC-based/raw functions for reading or or writing the OOB. The fact that the * caller wants an ECC-based or raw view of the page is not propagated down to * this driver. * * Since our OOB *is* covered by ECC, we need this information. So, we hook the * ecc.read_oob and ecc.write_oob function pointers in the owning * struct mtd_info with our own functions. These hook functions set the * raw_oob_mode field so that, when control finally arrives here, we'll know * what to do. */ static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand, int page) { struct mxs_nand_info *nand_info = nand_get_controller_data(nand); /* * First, fill in the OOB buffer. If we're doing a raw read, we need to * get the bytes from the physical page. If we're not doing a raw read, * we need to fill the buffer with set bits. */ if (nand_info->raw_oob_mode) { /* * If control arrives here, we're doing a "raw" read. Send the * command to read the conventional OOB and read it. */ nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); nand->read_buf(mtd, nand->oob_poi, mtd->oobsize); } else { /* * If control arrives here, we're not doing a "raw" read. Fill * the OOB buffer with set bits and correct the block mark. */ memset(nand->oob_poi, 0xff, mtd->oobsize); nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); mxs_nand_read_buf(mtd, nand->oob_poi, 1); } return 0; }
/* * Write a page to NAND. */ static int mxs_nand_ecc_write_page(struct mtd_info *mtd, struct nand_chip *nand, const uint8_t *buf, int oob_required, int page) { struct mxs_nand_info *nand_info = nand_get_controller_data(nand); struct mxs_dma_desc *d; uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; int ret; memcpy(nand_info->data_buf, buf, mtd->writesize); memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize); /* Handle block mark swapping. */ mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf); /* Compile the DMA descriptor - write data. */ d = mxs_nand_get_dma_desc(nand_info); d->cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END | (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET); d->cmd.address = 0; d->cmd.pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE | GPMI_CTRL0_WORD_LENGTH | (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | GPMI_CTRL0_ADDRESS_NAND_DATA; d->cmd.pio_words[1] = 0; d->cmd.pio_words[2] = GPMI_ECCCTRL_ENABLE_ECC | GPMI_ECCCTRL_ECC_CMD_ENCODE | GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE; d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize); d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf; d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf; mxs_dma_desc_append(channel, d); /* Flush caches */ mxs_nand_flush_data_buf(nand_info); /* Execute the DMA chain. */ ret = mxs_dma_go(channel); if (ret) { printf("MXS NAND: DMA write error\n"); goto rtn; } ret = mxs_nand_wait_for_bch_complete(); if (ret) { printf("MXS NAND: BCH write timeout\n"); goto rtn; } rtn: mxs_nand_return_dma_descs(nand_info); return 0; }
static inline struct spinand_state *mtd_to_state(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); struct spinand_info *info = nand_get_controller_data(chip); struct spinand_state *state = (struct spinand_state *)info->priv; return state; }
static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(chip); uint32_t *p = (uint32_t *) buf; for(;len > 0; len -= 4) out_be32(ndfc->ndfcbase + NDFC_DATA, *p++); }
/* Single CS command control */ static void oxnas_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *chip = mtd_to_nand(mtd); struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); if (ctrl & NAND_CLE) writeb(cmd, oxnas->io_base + OXNAS_NAND_CMD_CLE); else if (ctrl & NAND_ALE) writeb(cmd, oxnas->io_base + OXNAS_NAND_CMD_ALE); }
static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) { uint32_t ccr; struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(chip); ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); ccr |= NDFC_CCR_RESET_ECC; out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); wmb(); }
static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) { struct nand_chip *this = mtd_to_nand(mtd); void __iomem *io_base = (void __iomem *)nand_get_controller_data(this); writew(0, io_base + OMAP_MPUIO_IO_CNTL); writew(byte, this->IO_ADDR_W); gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0); ndelay(40); gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1); }
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(chip); if (cmd == NAND_CMD_NONE) return; if (ctrl & NAND_CLE) writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_CMD); else writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE); }
static void fun_select_chip(struct mtd_info *mtd, int chip_nr) { struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_upm_nand *fun = nand_get_controller_data(chip); if (chip_nr >= 0) { fun->chip_nr = chip_nr; chip->IO_ADDR_R = chip->IO_ADDR_W = fun->upm.io_addr + fun->chip_offset * chip_nr; } else if (chip_nr == -1) { chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); } }
/* * Test if the NAND flash is ready. */ static int mxs_nand_device_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = nand_get_controller_data(chip); struct mxs_gpmi_regs *gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE; uint32_t tmp; tmp = readl(&gpmi_regs->hw_gpmi_stat); tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip); return tmp & 1; }
/* * Write data to NAND. */ static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int length) { struct nand_chip *nand = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = nand_get_controller_data(nand); struct mxs_dma_desc *d; uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; int ret; if (length > NAND_MAX_PAGESIZE) { printf("MXS NAND: DMA buffer too big\n"); return; } if (!buf) { printf("MXS NAND: DMA buffer is NULL\n"); return; } memcpy(nand_info->data_buf, buf, length); /* Compile the DMA descriptor - a descriptor that writes data. */ d = mxs_nand_get_dma_desc(nand_info); d->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END | (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) | (length << MXS_DMA_DESC_BYTES_OFFSET); d->cmd.address = (dma_addr_t)nand_info->data_buf; d->cmd.pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE | GPMI_CTRL0_WORD_LENGTH | (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | GPMI_CTRL0_ADDRESS_NAND_DATA | length; mxs_dma_desc_append(channel, d); /* Flush caches */ mxs_nand_flush_data_buf(nand_info); /* Execute the DMA chain. */ ret = mxs_dma_go(channel); if (ret) printf("MXS NAND: DMA write error\n"); mxs_nand_return_dma_descs(nand_info); }
static u_char ams_delta_read_byte(struct mtd_info *mtd) { u_char res; struct nand_chip *this = mtd_to_nand(mtd); void __iomem *io_base = (void __iomem *)nand_get_controller_data(this); gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0); ndelay(40); writew(~0, io_base + OMAP_MPUIO_IO_CNTL); res = readw(this->IO_ADDR_R); gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1); return res; }
static void bcm47xxnflash_ops_bcm4706_write_buf(struct nand_chip *nand_chip, const uint8_t *buf, int len) { struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); switch (b47n->curr_command) { case NAND_CMD_SEQIN: bcm47xxnflash_ops_bcm4706_write(nand_to_mtd(nand_chip), buf, len); return; } pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command); }
static void ndfc_select_chip(struct mtd_info *mtd, int chip) { uint32_t ccr; struct nand_chip *nchip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(nchip); ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); if (chip >= 0) { ccr &= ~NDFC_CCR_BS_MASK; ccr |= NDFC_CCR_BS(chip + ndfc->chip_select); } else ccr |= NDFC_CCR_RESET_CE; out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); }
/* * Mark a block bad in NAND. * * This function is a veneer that replaces the function originally installed by * the NAND Flash MTD code. */ static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs) { struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = nand_get_controller_data(chip); int ret; nand_info->marking_block_bad = 1; ret = nand_info->hooked_block_markbad(mtd, ofs); nand_info->marking_block_bad = 0; return ret; }