Commit 4bc02243 authored by Boris Brezillon's avatar Boris Brezillon Committed by Miquel Raynal
Browse files

mtd: rawnand: atmel: Get rid of the legacy interface implementation

parent 03b3e0c2
Loading
Loading
Loading
Loading
+1 −197
Original line number Diff line number Diff line
@@ -417,133 +417,6 @@ err:
	return -EIO;
}

static u8 atmel_nand_read_byte(struct nand_chip *chip)
{
	struct atmel_nand *nand = to_atmel_nand(chip);

	return ioread8(nand->activecs->io.virt);
}

static void atmel_nand_write_byte(struct nand_chip *chip, u8 byte)
{
	struct atmel_nand *nand = to_atmel_nand(chip);

	if (chip->options & NAND_BUSWIDTH_16)
		iowrite16(byte | (byte << 8), nand->activecs->io.virt);
	else
		iowrite8(byte, nand->activecs->io.virt);
}

static void atmel_nand_read_buf(struct nand_chip *chip, u8 *buf, int len)
{
	struct atmel_nand *nand = to_atmel_nand(chip);
	struct atmel_nand_controller *nc;

	nc = to_nand_controller(chip->controller);

	/*
	 * If the controller supports DMA, the buffer address is DMA-able and
	 * len is long enough to make DMA transfers profitable, let's trigger
	 * a DMA transfer. If it fails, fallback to PIO mode.
	 */
	if (nc->dmac && virt_addr_valid(buf) &&
	    len >= MIN_DMA_LEN &&
	    !atmel_nand_dma_transfer(nc, buf, nand->activecs->io.dma, len,
				     DMA_FROM_DEVICE))
		return;

	if (chip->options & NAND_BUSWIDTH_16)
		ioread16_rep(nand->activecs->io.virt, buf, len / 2);
	else
		ioread8_rep(nand->activecs->io.virt, buf, len);
}

static void atmel_nand_write_buf(struct nand_chip *chip, const u8 *buf, int len)
{
	struct atmel_nand *nand = to_atmel_nand(chip);
	struct atmel_nand_controller *nc;

	nc = to_nand_controller(chip->controller);

	/*
	 * If the controller supports DMA, the buffer address is DMA-able and
	 * len is long enough to make DMA transfers profitable, let's trigger
	 * a DMA transfer. If it fails, fallback to PIO mode.
	 */
	if (nc->dmac && virt_addr_valid(buf) &&
	    len >= MIN_DMA_LEN &&
	    !atmel_nand_dma_transfer(nc, (void *)buf, nand->activecs->io.dma,
				     len, DMA_TO_DEVICE))
		return;

	if (chip->options & NAND_BUSWIDTH_16)
		iowrite16_rep(nand->activecs->io.virt, buf, len / 2);
	else
		iowrite8_rep(nand->activecs->io.virt, buf, len);
}

static int atmel_nand_dev_ready(struct nand_chip *chip)
{
	struct atmel_nand *nand = to_atmel_nand(chip);

	return gpiod_get_value(nand->activecs->rb.gpio);
}

static void atmel_nand_select_chip(struct nand_chip *chip, int cs)
{
	struct atmel_nand *nand = to_atmel_nand(chip);

	if (cs < 0 || cs >= nand->numcs) {
		nand->activecs = NULL;
		chip->legacy.dev_ready = NULL;
		return;
	}

	nand->activecs = &nand->cs[cs];

	if (nand->activecs->rb.type == ATMEL_NAND_GPIO_RB)
		chip->legacy.dev_ready = atmel_nand_dev_ready;
}

static int atmel_hsmc_nand_dev_ready(struct nand_chip *chip)
{
	struct atmel_nand *nand = to_atmel_nand(chip);
	struct atmel_hsmc_nand_controller *nc;
	u32 status;

	nc = to_hsmc_nand_controller(chip->controller);

	regmap_read(nc->base.smc, ATMEL_HSMC_NFC_SR, &status);

	return status & ATMEL_HSMC_NFC_SR_RBEDGE(nand->activecs->rb.id);
}

static void atmel_hsmc_nand_select_chip(struct nand_chip *chip, int cs)
{
	struct mtd_info *mtd = nand_to_mtd(chip);
	struct atmel_nand *nand = to_atmel_nand(chip);
	struct atmel_hsmc_nand_controller *nc;

	nc = to_hsmc_nand_controller(chip->controller);

	atmel_nand_select_chip(chip, cs);

	if (!nand->activecs)
		return;

	if (nand->activecs->rb.type == ATMEL_NAND_NATIVE_RB)
		chip->legacy.dev_ready = atmel_hsmc_nand_dev_ready;

	regmap_update_bits(nc->base.smc, ATMEL_HSMC_NFC_CFG,
			   ATMEL_HSMC_NFC_CFG_PAGESIZE_MASK |
			   ATMEL_HSMC_NFC_CFG_SPARESIZE_MASK |
			   ATMEL_HSMC_NFC_CFG_RSPARE |
			   ATMEL_HSMC_NFC_CFG_WSPARE,
			   ATMEL_HSMC_NFC_CFG_PAGESIZE(mtd->writesize) |
			   ATMEL_HSMC_NFC_CFG_SPARESIZE(mtd->oobsize) |
			   ATMEL_HSMC_NFC_CFG_RSPARE);
}

static int atmel_nfc_exec_op(struct atmel_hsmc_nand_controller *nc, bool poll)
{
	u8 *addrs = nc->op.addrs;
@@ -594,53 +467,6 @@ static int atmel_nfc_exec_op(struct atmel_hsmc_nand_controller *nc, bool poll)
	return ret;
}

static void atmel_hsmc_nand_cmd_ctrl(struct nand_chip *chip, int dat,
				     unsigned int ctrl)
{
	struct atmel_nand *nand = to_atmel_nand(chip);
	struct atmel_hsmc_nand_controller *nc;

	nc = to_hsmc_nand_controller(chip->controller);

	if (ctrl & NAND_ALE) {
		if (nc->op.naddrs == ATMEL_NFC_MAX_ADDR_CYCLES)
			return;

		nc->op.addrs[nc->op.naddrs++] = dat;
	} else if (ctrl & NAND_CLE) {
		if (nc->op.ncmds > 1)
			return;

		nc->op.cmds[nc->op.ncmds++] = dat;
	}

	if (dat == NAND_CMD_NONE) {
		nc->op.cs = nand->activecs->id;
		atmel_nfc_exec_op(nc, true);
	}
}

static void atmel_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
				unsigned int ctrl)
{
	struct atmel_nand *nand = to_atmel_nand(chip);
	struct atmel_nand_controller *nc;

	nc = to_nand_controller(chip->controller);

	if ((ctrl & NAND_CTRL_CHANGE) && nand->activecs->csgpio) {
		if (ctrl & NAND_NCE)
			gpiod_set_value(nand->activecs->csgpio, 0);
		else
			gpiod_set_value(nand->activecs->csgpio, 1);
	}

	if (ctrl & NAND_ALE)
		writeb(cmd, nand->activecs->io.virt + nc->caps->ale_offs);
	else if (ctrl & NAND_CLE)
		writeb(cmd, nand->activecs->io.virt + nc->caps->cle_offs);
}

static void atmel_nand_data_in(struct atmel_nand *nand, void *buf,
			       unsigned int len, bool force_8bit)
{
@@ -1722,19 +1548,9 @@ static void atmel_nand_init(struct atmel_nand_controller *nc,
	mtd->dev.parent = nc->dev;
	nand->base.controller = &nc->base;

	chip->legacy.cmd_ctrl = atmel_nand_cmd_ctrl;
	chip->legacy.read_byte = atmel_nand_read_byte;
	chip->legacy.write_byte = atmel_nand_write_byte;
	chip->legacy.read_buf = atmel_nand_read_buf;
	chip->legacy.write_buf = atmel_nand_write_buf;
	chip->legacy.select_chip = atmel_nand_select_chip;

	if (!nc->mck || !nc->caps->ops->setup_interface)
		chip->options |= NAND_KEEP_TIMINGS;

	/* Some NANDs require a longer delay than the default one (20us). */
	chip->legacy.chip_delay = 40;

	/*
	 * Use a bounce buffer when the buffer passed by the MTD user is not
	 * suitable for DMA.
@@ -1773,18 +1589,6 @@ static void atmel_smc_nand_init(struct atmel_nand_controller *nc,
				   smc_nc->ebi_csa->nfd0_on_d16);
}

static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc,
				 struct atmel_nand *nand)
{
	struct nand_chip *chip = &nand->base;

	atmel_nand_init(nc, nand);

	/* Overload some methods for the HSMC controller. */
	chip->legacy.cmd_ctrl = atmel_hsmc_nand_cmd_ctrl;
	chip->legacy.select_chip = atmel_hsmc_nand_select_chip;
}

static int atmel_nand_controller_remove_nand(struct atmel_nand *nand)
{
	struct nand_chip *chip = &nand->base;
@@ -2569,7 +2373,7 @@ static const struct atmel_nand_controller_ops atmel_hsmc_nc_ops = {
	.probe = atmel_hsmc_nand_controller_probe,
	.remove = atmel_hsmc_nand_controller_remove,
	.ecc_init = atmel_hsmc_nand_ecc_init,
	.nand_init = atmel_hsmc_nand_init,
	.nand_init = atmel_nand_init,
	.setup_interface = atmel_hsmc_nand_setup_interface,
	.exec_op = atmel_hsmc_nand_exec_op,
};