All of lore.kernel.org
 help / color / mirror / Atom feed
From: Grygorii Strashko <grygorii.strashko@ti.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 11/15] drivers: nand: omap_gpmc: convert driver to adopt driver model
Date: Tue, 31 Jan 2017 15:37:13 -0600	[thread overview]
Message-ID: <20170131213717.30745-12-grygorii.strashko@ti.com> (raw)
In-Reply-To: <20170131213717.30745-1-grygorii.strashko@ti.com>

From: Mugunthan V N <mugunthanvnm@ti.com>

adopt omap_gpmc driver to driver model.

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 drivers/mtd/nand/omap_gpmc.c | 205 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 205 insertions(+)

diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index b540bc3..a2d1634 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -16,6 +16,10 @@
 #include <nand.h>
 #include <linux/mtd/omap_elm.h>
 
+#include <dm.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
 #define BADBLOCK_MARKER_LENGTH	2
 #define SECTOR_BYTES		512
 #define ECCCLEAR		(0x1 << 8)
@@ -46,11 +50,22 @@ struct omap_nand_info {
 	enum omap_ecc ecc_scheme;
 	uint8_t cs;
 	uint8_t ws;		/* wait status pin (0,1) */
+	uint8_t bus_width;	/* Bus width of NAND device */
 };
 
+#ifndef CONFIG_DM_NAND
 /* We are wasting a bit of memory but al least we are safe */
 static struct omap_nand_info omap_nand_info[GPMC_MAX_CS];
 
+#else
+
+struct omap_gpmc_platdata {
+	struct omap_nand_info *omap_nand_info;
+	struct gpmc *gpmc_cfg;
+	int max_cs;
+};
+#endif
+
 /*
  * omap_nand_hwcontrol - Set the address pointers corretly for the
  *			following address/data/command operation
@@ -945,6 +960,8 @@ int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 }
 #endif /* CONFIG_SPL_BUILD */
 
+#ifndef CONFIG_DM_NAND
+
 /*
  * Board-specific NAND initialization. The following members of the
  * argument are board-specific:
@@ -1036,3 +1053,191 @@ int board_nand_init(struct nand_chip *nand)
 
 	return 0;
 }
+
+#else /* CONFIG_DM_NAND */
+
+static int omap_gpmc_probe(struct udevice *dev)
+{
+	struct nand_chip *nand = dev_get_priv(dev);
+	struct omap_gpmc_platdata *pdata = dev_get_platdata(dev);
+	struct gpmc *gpmc_cfg = pdata->gpmc_cfg;
+	int32_t gpmc_config = 0;
+	int ecc_opt;
+	int cs = cs_next++;
+	int err = 0;
+
+	while (cs < pdata->max_cs) {
+		/* Check if NAND type is set */
+		if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
+			/* Found it!! */
+			break;
+		}
+		cs++;
+	}
+
+	if (cs >= pdata->max_cs) {
+		printf("nand: error: Unable to find NAND settings in GPMC Configuration - quitting\n");
+		return -ENODEV;
+	}
+
+	gpmc_config = readl(&gpmc_cfg->config);
+	/* Disable Write protect */
+	gpmc_config |= 0x10;
+	writel(gpmc_config, &gpmc_cfg->config);
+
+	nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
+	nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
+	nand->priv	= &pdata->omap_nand_info[cs];
+	nand->cmd_ctrl	= omap_nand_hwcontrol;
+	nand->options	|= NAND_NO_PADDING | NAND_CACHEPRG;
+	nand->chip_delay = 100;
+	nand->ecc.layout = &omap_ecclayout;
+
+	/* configure driver and controller based on NAND device bus-width */
+	gpmc_config = readl(&gpmc_cfg->cs[cs].config1);
+	if (pdata->omap_nand_info[cs].bus_width == 16) {
+		nand->options |= NAND_BUSWIDTH_16;
+		writel(gpmc_config | (0x1 << 12), &gpmc_cfg->cs[cs].config1);
+	} else {
+		nand->options &= ~NAND_BUSWIDTH_16;
+		writel(gpmc_config & ~(0x1 << 12), &gpmc_cfg->cs[cs].config1);
+	}
+
+	ecc_opt = pdata->omap_nand_info[cs].ecc_scheme;
+	/* select ECC scheme */
+	if (ecc_opt != OMAP_ECC_HAM1_CODE_SW) {
+		err = omap_select_ecc_scheme(nand, ecc_opt,
+					     CONFIG_SYS_NAND_PAGE_SIZE,
+					     CONFIG_SYS_NAND_OOBSIZE);
+	} else {
+		/*
+		 * pagesize and oobsize are not required to
+		 * configure sw ecc-scheme
+		 */
+		err = omap_select_ecc_scheme(nand, ecc_opt, 0, 0);
+	}
+	if (err)
+		return err;
+
+#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
+	nand->read_buf = omap_nand_read_prefetch;
+#else
+	if (nand->options & NAND_BUSWIDTH_16)
+		nand->read_buf = nand_read_buf16;
+	else
+		nand->read_buf = nand_read_buf;
+#endif
+
+	nand->dev_ready = omap_dev_ready;
+
+	return 0;
+}
+
+static int omap_gpmc_get_ecc_opt(int node, int elm_node)
+{
+	const void *fdt = gd->fdt_blob;
+	const char *ecc_str;
+	int ecc_opt = -ENOENT;
+
+	ecc_str = fdt_getprop(fdt, node, "ti,nand-ecc-opt", NULL);
+	if (!ecc_str) {
+		error("DT entry for ti,nand-ecc-opt not found\n");
+		return -ENOENT;
+	}
+
+	if (!strcmp(ecc_str, "sw")) {
+		ecc_opt = OMAP_ECC_HAM1_CODE_SW;
+	} else if (!strcmp(ecc_str, "ham1") ||
+		   !strcmp(ecc_str, "hw") ||
+		   !strcmp(ecc_str, "hw-romcode")) {
+		ecc_opt = OMAP_ECC_HAM1_CODE_HW;
+	} else if (!strcmp(ecc_str, "bch4")) {
+		if (elm_node > 0)
+			ecc_opt = OMAP_ECC_BCH4_CODE_HW;
+		else
+			ecc_opt = OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
+	} else if (!strcmp(ecc_str, "bch8")) {
+		if (elm_node > 0)
+			ecc_opt = OMAP_ECC_BCH8_CODE_HW;
+		else
+			ecc_opt = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
+	} else if (!strcmp(ecc_str, "bch16")) {
+		if (elm_node > 0)
+			ecc_opt = OMAP_ECC_BCH16_CODE_HW;
+		else
+			error("BCH16 requires ELM support\n");
+	} else {
+		error("ti,nand-ecc-opt invalid value\n");
+		return -EINVAL;
+	}
+
+	return ecc_opt;
+}
+
+static int omap_gpmc_ofdata_to_platdata(struct udevice *dev)
+{
+	struct omap_gpmc_platdata *pdata = dev_get_platdata(dev);
+	const void *fdt = gd->fdt_blob;
+	int node = dev->of_offset;
+	int subnode;
+
+	pdata->gpmc_cfg = (struct gpmc *)dev_get_addr(dev);
+	pdata->max_cs = fdtdec_get_int(fdt, node, "gpmc,num-cs", -1);
+	if (pdata->max_cs < 0) {
+		error("max chip select not found in DT\n");
+		return -ENOENT;
+	}
+
+	pdata->omap_nand_info = calloc(pdata->max_cs,
+				       sizeof(struct omap_nand_info));
+	if (!pdata->omap_nand_info)
+		return -ENOMEM;
+
+	fdt_for_each_subnode(subnode, fdt, node) {
+		int cs;
+		int len;
+		int elm_node;
+		const char *name;
+		struct omap_nand_info *nand_info;
+
+		name = fdt_get_name(fdt, subnode, &len);
+		if (strncmp(name, "nand", 4))
+			continue;
+
+		cs = fdtdec_get_int(fdt, subnode, "reg", -1);
+		if (cs < 0 || cs >= pdata->max_cs) {
+			error("Invalid cs for nand device\n");
+			return -EINVAL;
+		}
+		nand_info = &pdata->omap_nand_info[cs];
+
+		/* get bus width 8 or 16, if not present 8 */
+		nand_info->bus_width = fdtdec_get_int(fdt, subnode,
+						      "nand-bus-width", 8);
+
+		elm_node = fdtdec_lookup_phandle(fdt, subnode, "ti,elm-id");
+
+		nand_info->ecc_scheme = omap_gpmc_get_ecc_opt(subnode,
+							      elm_node);
+		if (nand_info->ecc_scheme < 0)
+			return nand_info->ecc_scheme;
+	}
+	return 0;
+}
+
+static const struct udevice_id omap_gpmc_ids[] = {
+	{ .compatible = "ti,am3352-gpmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(omap_gpmc) = {
+	.name	= "omap_gpmc",
+	.id	= UCLASS_NAND,
+	.of_match = omap_gpmc_ids,
+	.ofdata_to_platdata = omap_gpmc_ofdata_to_platdata,
+	.probe	= omap_gpmc_probe,
+	.priv_auto_alloc_size = sizeof(struct nand_chip),
+	.platdata_auto_alloc_size = sizeof(struct omap_gpmc_platdata),
+	.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif /* CONFIG_DM_NAND */
-- 
2.10.1.dirty

  parent reply	other threads:[~2017-01-31 21:37 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-31 21:37 [U-Boot] [PATCH v2 00/15] nand: device model bringup on am335x evm and am437x gpevm Grygorii Strashko
2017-01-31 21:37 ` [U-Boot] [PATCH v2 01/15] cmd: bootm: fix build when CONFIG_CMD_IMLS_NAND Grygorii Strashko
2017-02-06  1:56   ` Tom Rini
2017-02-06 15:33     ` Simon Glass
2017-02-09  3:03   ` [U-Boot] [U-Boot, v2, " Tom Rini
2017-01-31 21:37 ` [U-Boot] [PATCH v2 02/15] cmd: nand: abstract global variable usage for dm conversion Grygorii Strashko
2017-02-06  1:57   ` Tom Rini
2017-02-09 17:51     ` Grygorii Strashko
2017-02-09 18:12       ` Tom Rini
2017-02-06 15:33   ` Simon Glass
2017-02-08 21:23   ` [U-Boot] [U-Boot, v2, " Tom Rini
2017-01-31 21:37 ` [U-Boot] [PATCH v2 03/15] common: env_nand: use get_nand_dev_by_index() Grygorii Strashko
2017-02-06  1:57   ` Tom Rini
2017-02-06 15:33     ` Simon Glass
2017-01-31 21:37 ` [U-Boot] [PATCH v2 04/15] dfu: dfu_nand: " Grygorii Strashko
2017-02-06  1:57   ` Tom Rini
2017-02-06 15:34     ` Simon Glass
2017-01-31 21:37 ` [U-Boot] [PATCH v2 05/15] cmd: bootm: " Grygorii Strashko
2017-02-06  1:57   ` Tom Rini
2017-02-06 15:34     ` Simon Glass
2017-01-31 21:37 ` [U-Boot] [PATCH v2 06/15] cmd: jffs2: " Grygorii Strashko
2017-02-06  1:57   ` Tom Rini
2017-02-06 15:34     ` Simon Glass
2017-01-31 21:37 ` [U-Boot] [PATCH v2 07/15] common: " Grygorii Strashko
2017-02-06  1:57   ` Tom Rini
2017-02-06 15:33     ` Simon Glass
2017-01-31 21:37 ` [U-Boot] [PATCH v2 08/15] fs: " Grygorii Strashko
2017-02-06  1:57   ` Tom Rini
2017-02-06 15:34     ` Simon Glass
2017-01-31 21:37 ` [U-Boot] [PATCH v2 09/15] cmd: nand: remove direct access to struct mtd_info->priv Grygorii Strashko
2017-02-06  1:57   ` Tom Rini
2017-02-06 15:34   ` Simon Glass
2017-01-31 21:37 ` [U-Boot] [PATCH v2 10/15] drivers: nand: implement a NAND uclass Grygorii Strashko
2017-02-06 15:34   ` Simon Glass
2017-02-06 18:39     ` Grygorii Strashko
2017-02-10 16:22       ` Simon Glass
2017-02-10 18:23         ` Grygorii Strashko
2017-01-31 21:37 ` Grygorii Strashko [this message]
2017-02-06  1:57   ` [U-Boot] [PATCH v2 11/15] drivers: nand: omap_gpmc: convert driver to adopt driver model Tom Rini
2017-02-06 18:40     ` Grygorii Strashko
2017-02-10 16:22   ` Simon Glass
2017-01-31 21:37 ` [U-Boot] [PATCH v2 12/15] am43xx_evm: nand: do not define DM_NAND for spl Grygorii Strashko
2017-01-31 21:37 ` [U-Boot] [PATCH v2 13/15] defconfig: am43xx_evm: enable NAND driver model Grygorii Strashko
2017-01-31 21:37 ` [U-Boot] [PATCH v2 14/15] am335x_evm: nand: do not define DM_NAND for spl Grygorii Strashko
2017-01-31 21:37 ` [U-Boot] [PATCH v2 15/15] defconfig: am335x_evm: enable NAND driver model Grygorii Strashko
2017-02-06  1:56 ` [U-Boot] [PATCH v2 00/15] nand: device model bringup on am335x evm and am437x gpevm Tom Rini
2017-02-06 18:50   ` Grygorii Strashko
2017-02-07 17:19     ` Tom Rini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170131213717.30745-12-grygorii.strashko@ti.com \
    --to=grygorii.strashko@ti.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.