Commit e4303b25 authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by David Woodhouse
Browse files

mtd: mxc_nand: move function pointers to a per-SOC struct



This prepares switching to platform ids and of-tree probing.

Signed-off-by: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 8556958a
Loading
Loading
Loading
Loading
+104 −66
Original line number Diff line number Diff line
@@ -140,6 +140,19 @@

#define NFC_V3_DELAY_LINE		(host->regs_ip + 0x34)

struct mxc_nand_host;

struct mxc_nand_devtype_data {
	void (*preset)(struct mtd_info *);
	void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
	void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
	void (*send_page)(struct mtd_info *, unsigned int);
	void (*send_read_id)(struct mxc_nand_host *);
	uint16_t (*get_dev_status)(struct mxc_nand_host *);
	int (*check_int)(struct mxc_nand_host *);
	void (*irq_control)(struct mxc_nand_host *, int);
};

struct mxc_nand_host {
	struct mtd_info		mtd;
	struct nand_chip	nand;
@@ -165,14 +178,7 @@ struct mxc_nand_host {
	unsigned int		buf_start;
	int			spare_len;

	void			(*preset)(struct mtd_info *);
	void			(*send_cmd)(struct mxc_nand_host *, uint16_t, int);
	void			(*send_addr)(struct mxc_nand_host *, uint16_t, int);
	void			(*send_page)(struct mtd_info *, unsigned int);
	void			(*send_read_id)(struct mxc_nand_host *);
	uint16_t		(*get_dev_status)(struct mxc_nand_host *);
	int			(*check_int)(struct mxc_nand_host *);
	void			(*irq_control)(struct mxc_nand_host *, int);
	const struct mxc_nand_devtype_data *devtype_data;

	/*
	 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
@@ -315,7 +321,7 @@ static void irq_control(struct mxc_nand_host *host, int activate)
		else
			disable_irq_nosync(host->irq);
	} else {
		host->irq_control(host, activate);
		host->devtype_data->irq_control(host, activate);
	}
}

@@ -323,7 +329,7 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
{
	struct mxc_nand_host *host = dev_id;

	if (!host->check_int(host))
	if (!host->devtype_data->check_int(host))
		return IRQ_NONE;

	irq_control(host, 0);
@@ -341,14 +347,14 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
	int max_retries = 8000;

	if (useirq) {
		if (!host->check_int(host)) {
		if (!host->devtype_data->check_int(host)) {
			INIT_COMPLETION(host->op_completion);
			irq_control(host, 1);
			wait_for_completion(&host->op_completion);
		}
	} else {
		while (max_retries-- > 0) {
			if (host->check_int(host))
			if (host->devtype_data->check_int(host))
				break;

			udelay(1);
@@ -621,7 +627,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)

	/* Check for status request */
	if (host->status_request)
		return host->get_dev_status(host) & 0xFF;
		return host->devtype_data->get_dev_status(host) & 0xFF;

	ret = *(uint8_t *)(host->data_buf + host->buf_start);
	host->buf_start++;
@@ -756,34 +762,44 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
		 * perform a read/write buf operation, the saved column
		  * address is used to index into the full page.
		 */
		host->send_addr(host, 0, page_addr == -1);
		host->devtype_data->send_addr(host, 0, page_addr == -1);
		if (mtd->writesize > 512)
			/* another col addr cycle for 2k page */
			host->send_addr(host, 0, false);
			host->devtype_data->send_addr(host, 0, false);
	}

	/* Write out page address, if necessary */
	if (page_addr != -1) {
		/* paddr_0 - p_addr_7 */
		host->send_addr(host, (page_addr & 0xff), false);
		host->devtype_data->send_addr(host, (page_addr & 0xff), false);

		if (mtd->writesize > 512) {
			if (mtd->size >= 0x10000000) {
				/* paddr_8 - paddr_15 */
				host->send_addr(host, (page_addr >> 8) & 0xff, false);
				host->send_addr(host, (page_addr >> 16) & 0xff, true);
				host->devtype_data->send_addr(host,
						(page_addr >> 8) & 0xff,
						false);
				host->devtype_data->send_addr(host,
						(page_addr >> 16) & 0xff,
						true);
			} else
				/* paddr_8 - paddr_15 */
				host->send_addr(host, (page_addr >> 8) & 0xff, true);
				host->devtype_data->send_addr(host,
						(page_addr >> 8) & 0xff, true);
		} else {
			/* One more address cycle for higher density devices */
			if (mtd->size >= 0x4000000) {
				/* paddr_8 - paddr_15 */
				host->send_addr(host, (page_addr >> 8) & 0xff, false);
				host->send_addr(host, (page_addr >> 16) & 0xff, true);
				host->devtype_data->send_addr(host,
						(page_addr >> 8) & 0xff,
						false);
				host->devtype_data->send_addr(host,
						(page_addr >> 16) & 0xff,
						true);
			} else
				/* paddr_8 - paddr_15 */
				host->send_addr(host, (page_addr >> 8) & 0xff, true);
				host->devtype_data->send_addr(host,
						(page_addr >> 8) & 0xff, true);
		}
	}
}
@@ -942,15 +958,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
	/* Command pre-processing step */
	switch (command) {
	case NAND_CMD_RESET:
		host->preset(mtd);
		host->send_cmd(host, command, false);
		host->devtype_data->preset(mtd);
		host->devtype_data->send_cmd(host, command, false);
		break;

	case NAND_CMD_STATUS:
		host->buf_start = 0;
		host->status_request = true;

		host->send_cmd(host, command, true);
		host->devtype_data->send_cmd(host, command, true);
		mxc_do_addr_cycle(mtd, column, page_addr);
		break;

@@ -963,13 +979,14 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,

		command = NAND_CMD_READ0; /* only READ0 is valid */

		host->send_cmd(host, command, false);
		host->devtype_data->send_cmd(host, command, false);
		mxc_do_addr_cycle(mtd, column, page_addr);

		if (mtd->writesize > 512)
			host->send_cmd(host, NAND_CMD_READSTART, true);
			host->devtype_data->send_cmd(host,
					NAND_CMD_READSTART, true);

		host->send_page(mtd, NFC_OUTPUT);
		host->devtype_data->send_page(mtd, NFC_OUTPUT);

		memcpy(host->data_buf, host->main_area0, mtd->writesize);
		copy_spare(mtd, true);
@@ -982,28 +999,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,

		host->buf_start = column;

		host->send_cmd(host, command, false);
		host->devtype_data->send_cmd(host, command, false);
		mxc_do_addr_cycle(mtd, column, page_addr);
		break;

	case NAND_CMD_PAGEPROG:
		memcpy(host->main_area0, host->data_buf, mtd->writesize);
		copy_spare(mtd, false);
		host->send_page(mtd, NFC_INPUT);
		host->send_cmd(host, command, true);
		host->devtype_data->send_page(mtd, NFC_INPUT);
		host->devtype_data->send_cmd(host, command, true);
		mxc_do_addr_cycle(mtd, column, page_addr);
		break;

	case NAND_CMD_READID:
		host->send_cmd(host, command, true);
		host->devtype_data->send_cmd(host, command, true);
		mxc_do_addr_cycle(mtd, column, page_addr);
		host->send_read_id(host);
		host->devtype_data->send_read_id(host);
		host->buf_start = column;
		break;

	case NAND_CMD_ERASE1:
	case NAND_CMD_ERASE2:
		host->send_cmd(host, command, false);
		host->devtype_data->send_cmd(host, command, false);
		mxc_do_addr_cycle(mtd, column, page_addr);

		break;
@@ -1037,6 +1054,42 @@ static struct nand_bbt_descr bbt_mirror_descr = {
	.pattern = mirror_pattern,
};

/* v1: i.MX21, i.MX27, i.MX31 */
static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
	.preset = preset_v1_v2,
	.send_cmd = send_cmd_v1_v2,
	.send_addr = send_addr_v1_v2,
	.send_page = send_page_v1_v2,
	.send_read_id = send_read_id_v1_v2,
	.get_dev_status = get_dev_status_v1_v2,
	.check_int = check_int_v1_v2,
	.irq_control = irq_control_v1_v2,
};

/* v21: i.MX25, i.MX35 */
static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
	.preset = preset_v1_v2,
	.send_cmd = send_cmd_v1_v2,
	.send_addr = send_addr_v1_v2,
	.send_page = send_page_v1_v2,
	.send_read_id = send_read_id_v1_v2,
	.get_dev_status = get_dev_status_v1_v2,
	.check_int = check_int_v1_v2,
	.irq_control = irq_control_v1_v2,
};

/* v3: i.MX51, i.MX53 */
static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
	.preset = preset_v3,
	.send_cmd = send_cmd_v3,
	.send_addr = send_addr_v3,
	.send_page = send_page_v3,
	.send_read_id = send_read_id_v3,
	.get_dev_status = get_dev_status_v3,
	.check_int = check_int_v3,
	.irq_control = irq_control_v3,
};

static int __init mxcnd_probe(struct platform_device *pdev)
{
	struct nand_chip *this;
@@ -1100,27 +1153,10 @@ static int __init mxcnd_probe(struct platform_device *pdev)

	host->main_area0 = host->base;

	if (nfc_is_v1() || nfc_is_v21()) {
		host->preset = preset_v1_v2;
		host->send_cmd = send_cmd_v1_v2;
		host->send_addr = send_addr_v1_v2;
		host->send_page = send_page_v1_v2;
		host->send_read_id = send_read_id_v1_v2;
		host->get_dev_status = get_dev_status_v1_v2;
		host->check_int = check_int_v1_v2;
		host->irq_control = irq_control_v1_v2;
	if (nfc_is_v1()) {
		host->devtype_data = &imx21_nand_devtype_data;
		if (cpu_is_mx21())
			host->irqpending_quirk = 1;
	}

	if (nfc_is_v21()) {
		host->regs = host->base + 0x1e00;
		host->spare0 = host->base + 0x1000;
		host->spare_len = 64;
		oob_smallpage = &nandv2_hw_eccoob_smallpage;
		oob_largepage = &nandv2_hw_eccoob_largepage;
		this->ecc.bytes = 9;
	} else if (nfc_is_v1()) {
		host->regs = host->base + 0xe00;
		host->spare0 = host->base + 0x800;
		host->spare_len = 16;
@@ -1128,7 +1164,16 @@ static int __init mxcnd_probe(struct platform_device *pdev)
		oob_largepage = &nandv1_hw_eccoob_largepage;
		this->ecc.bytes = 3;
		host->eccsize = 1;
	} else if (nfc_is_v21()) {
		host->devtype_data = &imx25_nand_devtype_data;
		host->regs = host->base + 0x1e00;
		host->spare0 = host->base + 0x1000;
		host->spare_len = 64;
		oob_smallpage = &nandv2_hw_eccoob_smallpage;
		oob_largepage = &nandv2_hw_eccoob_largepage;
		this->ecc.bytes = 9;
	} else if (nfc_is_v3_2()) {
		host->devtype_data = &imx51_nand_devtype_data;
		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
		if (!res) {
			err = -ENODEV;
@@ -1142,14 +1187,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
		host->regs_axi = host->base + 0x1e00;
		host->spare0 = host->base + 0x1000;
		host->spare_len = 64;
		host->preset = preset_v3;
		host->send_cmd = send_cmd_v3;
		host->send_addr = send_addr_v3;
		host->send_page = send_page_v3;
		host->send_read_id = send_read_id_v3;
		host->check_int = check_int_v3;
		host->get_dev_status = get_dev_status_v3;
		host->irq_control = irq_control_v3;
		oob_smallpage = &nandv2_hw_eccoob_smallpage;
		oob_largepage = &nandv2_hw_eccoob_largepage;
	} else
@@ -1186,10 +1223,11 @@ static int __init mxcnd_probe(struct platform_device *pdev)
	host->irq = platform_get_irq(pdev, 0);

	/*
	 * Use host->irq_control here instead of irq_control because we must not
	 * disable_irq_nosync without having requested the irq
	 * Use host->devtype_data->irq_control() here instead of irq_control()
	 * because we must not disable_irq_nosync without having requested the
	 * irq.
	 */
	host->irq_control(host, 0);
	host->devtype_data->irq_control(host, 0);

	err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
	if (err)
@@ -1202,7 +1240,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
	 */
	if (host->irqpending_quirk) {
		disable_irq_nosync(host->irq);
		host->irq_control(host, 1);
		host->devtype_data->irq_control(host, 1);
	}

	/* first scan to find the device and get the page size */
@@ -1212,7 +1250,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
	}

	/* Call preset again, with correct writesize this time */
	host->preset(mtd);
	host->devtype_data->preset(mtd);

	if (mtd->writesize == 2048)
		this->ecc.layout = oob_largepage;