Patchwork [1/2] mtd: gpmi: add device tree support to gpmi-nand

login
register
mail settings
Submitter Huang Shijie
Date May 4, 2012, 3:13 a.m.
Message ID <1336101182-5200-1-git-send-email-b32955@freescale.com>
Download mbox | patch
Permalink /patch/156797/
State New
Headers show

Comments

Huang Shijie - May 4, 2012, 3:13 a.m.
This patch just adds the DT support to gpmi-nand.

Signed-off-by: Huang Shijie <b32955@freescale.com>
---
Please select the CONFIG_USE_OF before you do the compiler-test.
thanks.

---
 .../devicetree/bindings/mtd/gpmi-nand.txt          |   33 +++++
 drivers/mtd/nand/gpmi-nand/gpmi-lib.c              |    7 +-
 drivers/mtd/nand/gpmi-nand/gpmi-nand.c             |  125 ++++++++++----------
 drivers/mtd/nand/gpmi-nand/gpmi-nand.h             |    4 +-
 include/linux/mtd/gpmi-nand.h                      |    8 +-
 5 files changed, 104 insertions(+), 73 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/gpmi-nand.txt
Subodh Nijsure - May 4, 2012, 3:36 a.m.
Hello Huang,

On 05/03/2012 08:13 PM, Huang Shijie wrote:
> This patch just adds the DT support to gpmi-nand.
>
> Signed-off-by: Huang Shijie<b32955@freescale.com>
> ---
> Please select the CONFIG_USE_OF before you do the compiler-test.
> thanks.
Any chance you can add some information on what kind of mtd tests were 
done with this code change and on what platform?

Also if one wanted to test this patch say on mx28 based hardware, one 
should apply this patch against arm-soc tree, top of the 3.5-next tree?

-Subodh Nijsure
> ---
>   .../devicetree/bindings/mtd/gpmi-nand.txt          |   33 +++++
>   drivers/mtd/nand/gpmi-nand/gpmi-lib.c              |    7 +-
>   drivers/mtd/nand/gpmi-nand/gpmi-nand.c             |  125 ++++++++++----------
>   drivers/mtd/nand/gpmi-nand/gpmi-nand.h             |    4 +-
>   include/linux/mtd/gpmi-nand.h                      |    8 +-
>   5 files changed, 104 insertions(+), 73 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/mtd/gpmi-nand.txt
>
> diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
> new file mode 100644
> index 0000000..1a5bbd3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
> @@ -0,0 +1,33 @@
> +* Freescale General-Purpose Media Interface (GPMI)
> +
> +The GPMI nand controller provides an interface to control the
> +NAND flash chips. We support only one NAND chip now.
> +
> +Required properties:
> +  - compatible : should be "fsl,<chip>-gpmi-nand"
> +  - reg : should contain registers location and length for gpmi and bch.
> +  - reg-names: Should contain the reg names "gpmi-nand" and "bch"
> +  - interrupts : The first is the DMA interrupt number for GPMI.
> +                 The second is the BCH interrupt number.
> +  - interrupt-names : The interrupt names "gpmi-dma", "bch";
> +  - fsl,gpmi-dma-channel : Should contain the dma channel it uses.
> +
> +The device tree may optionally contain sub-nodes describing partitions of the
> +address space. See partition.txt for more detail.
> +
> +Examples:
> +
> +gpmi-nand@8000c000 {
> +	compatible = "fsl,imx28-gpmi-nand";
> +	#address-cells =<1>;
> +	#size-cells =<1>;
> +	reg =<0x8000c000 2000>,<0x8000a000 2000>;
> +	reg-names = "gpmi-nand", "bch";
> +	interrupts =<88>,<41>;
> +	interrupt-names = "gpmi-dma", "bch";
> +	fsl,gpmi-dma-channel =<4>;
> +
> +	partition@0 {
> +	...
> +	};
> +};
> diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
> index fa5200b..5c55c71 100644
> --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
> +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
> @@ -256,11 +256,12 @@ static unsigned int ns_to_cycles(unsigned int time,
>   	return max(k, min);
>   }
>
> +#define DEF_MIN_PROP_DELAY	5
> +#define DEF_MAX_PROP_DELAY	9
>   /* Apply timing to current hardware conditions. */
>   static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
>   					struct gpmi_nfc_hardware_timing *hw)
>   {
> -	struct gpmi_nand_platform_data *pdata = this->pdata;
>   	struct timing_threshod *nfc =&timing_default_threshold;
>   	struct nand_chip *nand =&this->nand;
>   	struct nand_timing target = this->timing;
> @@ -277,8 +278,8 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
>   	int ideal_sample_delay_in_ns;
>   	unsigned int sample_delay_factor;
>   	int tEYE;
> -	unsigned int min_prop_delay_in_ns = pdata->min_prop_delay_in_ns;
> -	unsigned int max_prop_delay_in_ns = pdata->max_prop_delay_in_ns;
> +	unsigned int min_prop_delay_in_ns = DEF_MIN_PROP_DELAY;
> +	unsigned int max_prop_delay_in_ns = DEF_MAX_PROP_DELAY;
>
>   	/*
>   	 * If there are multiple chips, we need to relax the timings to allow
> diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
> index 75b1dde..c351137 100644
> --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
> +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
> @@ -24,6 +24,7 @@
>   #include<linux/module.h>
>   #include<linux/mtd/gpmi-nand.h>
>   #include<linux/mtd/partitions.h>
> +#include<linux/of_device.h>
>   #include "gpmi-nand.h"
>
>   /* add our owner bbt descriptor */
> @@ -385,7 +386,7 @@ static void release_bch_irq(struct gpmi_nand_data *this)
>   static bool gpmi_dma_filter(struct dma_chan *chan, void *param)
>   {
>   	struct gpmi_nand_data *this = param;
> -	struct resource *r = this->private;
> +	int dma_channel = (int)this->private;
>
>   	if (!mxs_dma_is_apbh(chan))
>   		return false;
> @@ -397,7 +398,7 @@ static bool gpmi_dma_filter(struct dma_chan *chan, void *param)
>   	 *	for mx28 :	MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7
>   	 *		(These eight channels share the same IRQ!)
>   	 */
> -	if (r->start<= chan->chan_id&&  chan->chan_id<= r->end) {
> +	if (dma_channel == chan->chan_id) {
>   		chan->private =&this->dma_data;
>   		return true;
>   	}
> @@ -417,57 +418,45 @@ static void release_dma_channels(struct gpmi_nand_data *this)
>   static int __devinit acquire_dma_channels(struct gpmi_nand_data *this)
>   {
>   	struct platform_device *pdev = this->pdev;
> -	struct gpmi_nand_platform_data *pdata = this->pdata;
> -	struct resources *res =&this->resources;
> -	struct resource *r, *r_dma;
> -	unsigned int i;
> +	struct resource *r_dma;
> +	struct device_node *dn;
> +	int dma_channel;
> +	unsigned int ret;
> +	struct dma_chan *dma_chan;
> +	dma_cap_mask_t mask;
> +
> +	/* dma channel, we only use the first one. */
> +	dn = pdev->dev.of_node;
> +	ret = of_property_read_u32(dn, "fsl,gpmi-dma-channel",&dma_channel);
> +	if (ret) {
> +		pr_err("unable to get DMA channel from dt.\n");
> +		goto acquire_err;
> +	}
> +	this->private = (void *)dma_channel;
>
> -	r = platform_get_resource_byname(pdev, IORESOURCE_DMA,
> -					GPMI_NAND_DMA_CHANNELS_RES_NAME);
> +	/* gpmi dma interrupt */
>   	r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
>   					GPMI_NAND_DMA_INTERRUPT_RES_NAME);
> -	if (!r || !r_dma) {
> +	if (!r_dma) {
>   		pr_err("Can't get resource for DMA\n");
> -		return -ENXIO;
> +		goto acquire_err;
>   	}
> +	this->dma_data.chan_irq = r_dma->start;
>
> -	/* used in gpmi_dma_filter() */
> -	this->private = r;
> -
> -	for (i = r->start; i<= r->end; i++) {
> -		struct dma_chan *dma_chan;
> -		dma_cap_mask_t mask;
> +	/* request dma channel */
> +	dma_cap_zero(mask);
> +	dma_cap_set(DMA_SLAVE, mask);
>
> -		if (i - r->start>= pdata->max_chip_count)
> -			break;
> -
> -		dma_cap_zero(mask);
> -		dma_cap_set(DMA_SLAVE, mask);
> -
> -		/* get the DMA interrupt */
> -		if (r_dma->start == r_dma->end) {
> -			/* only register the first. */
> -			if (i == r->start)
> -				this->dma_data.chan_irq = r_dma->start;
> -			else
> -				this->dma_data.chan_irq = NO_IRQ;
> -		} else
> -			this->dma_data.chan_irq = r_dma->start + (i - r->start);
> -
> -		dma_chan = dma_request_channel(mask, gpmi_dma_filter, this);
> -		if (!dma_chan)
> -			goto acquire_err;
> -
> -		/* fill the first empty item */
> -		this->dma_chans[i - r->start] = dma_chan;
> +	dma_chan = dma_request_channel(mask, gpmi_dma_filter, this);
> +	if (!dma_chan) {
> +		pr_err("dma_request_channel failed.\n");
> +		goto acquire_err;
>   	}
>
> -	res->dma_low_channel = r->start;
> -	res->dma_high_channel = i;
> +	this->dma_chans[0] = dma_chan;
>   	return 0;
>
>   acquire_err:
> -	pr_err("Can't acquire DMA channel %u\n", i);
>   	release_dma_channels(this);
>   	return -EINVAL;
>   }
> @@ -1461,9 +1450,9 @@ void gpmi_nfc_exit(struct gpmi_nand_data *this)
>
>   static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this)
>   {
> -	struct gpmi_nand_platform_data *pdata = this->pdata;
>   	struct mtd_info  *mtd =&this->mtd;
>   	struct nand_chip *chip =&this->nand;
> +	struct mtd_part_parser_data ppdata = {};
>   	int ret;
>
>   	/* init current chip */
> @@ -1501,14 +1490,14 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this)
>   	if (ret)
>   		goto err_out;
>
> -	ret = nand_scan(mtd, pdata->max_chip_count);
> +	ret = nand_scan(mtd, 1);
>   	if (ret) {
>   		pr_err("Chip scan failed\n");
>   		goto err_out;
>   	}
>
> -	ret = mtd_device_parse_register(mtd, NULL, NULL,
> -			pdata->partitions, pdata->partition_count);
> +	ppdata.of_node = this->pdev->dev.of_node;
> +	ret = mtd_device_parse_register(mtd, NULL,&ppdata, NULL, 0);
>   	if (ret)
>   		goto err_out;
>   	return 0;
> @@ -1518,12 +1507,37 @@ err_out:
>   	return ret;
>   }
>
> +static const struct platform_device_id gpmi_ids[] = {
> +	{ .name = "imx23-gpmi-nand", .driver_data = IS_MX23, },
> +	{ .name = "imx28-gpmi-nand", .driver_data = IS_MX28, },
> +	{},
> +};
> +
> +static const struct of_device_id gpmi_nand_id_table[] = {
> +	{
> +		.compatible = "fsl,imx23-gpmi-nand",
> +		.data = (void *)&gpmi_ids[IS_MX23]
> +	}, {
> +		.compatible = "fsl,imx28-gpmi-nand",
> +		.data = (void *)&gpmi_ids[IS_MX28]
> +	}, {}
> +};
> +MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
> +
>   static int __devinit gpmi_nand_probe(struct platform_device *pdev)
>   {
> -	struct gpmi_nand_platform_data *pdata = pdev->dev.platform_data;
>   	struct gpmi_nand_data *this;
> +	const struct of_device_id *of_id;
>   	int ret;
>
> +	of_id = of_match_device(gpmi_nand_id_table,&pdev->dev);
> +	if (of_id) {
> +		pdev->id_entry = of_id->data;
> +	} else {
> +		pr_err("Failed to find the right device id.\n");
> +		return -ENOMEM;
> +	}
> +
>   	this = kzalloc(sizeof(*this), GFP_KERNEL);
>   	if (!this) {
>   		pr_err("Failed to allocate per-device memory\n");
> @@ -1533,13 +1547,6 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev)
>   	platform_set_drvdata(pdev, this);
>   	this->pdev  = pdev;
>   	this->dev   =&pdev->dev;
> -	this->pdata = pdata;
> -
> -	if (pdata->platform_init) {
> -		ret = pdata->platform_init();
> -		if (ret)
> -			goto platform_init_error;
> -	}
>
>   	ret = acquire_resources(this);
>   	if (ret)
> @@ -1557,7 +1564,6 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev)
>
>   exit_nfc_init:
>   	release_resources(this);
> -platform_init_error:
>   exit_acquire_resources:
>   	platform_set_drvdata(pdev, NULL);
>   	kfree(this);
> @@ -1575,19 +1581,10 @@ static int __exit gpmi_nand_remove(struct platform_device *pdev)
>   	return 0;
>   }
>
> -static const struct platform_device_id gpmi_ids[] = {
> -	{
> -		.name = "imx23-gpmi-nand",
> -		.driver_data = IS_MX23,
> -	}, {
> -		.name = "imx28-gpmi-nand",
> -		.driver_data = IS_MX28,
> -	}, {},
> -};
> -
>   static struct platform_driver gpmi_nand_driver = {
>   	.driver = {
>   		.name = "gpmi-nand",
> +		.of_match_table = gpmi_nand_id_table,
>   	},
>   	.probe   = gpmi_nand_probe,
>   	.remove  = __exit_p(gpmi_nand_remove),
> diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
> index ec6180d..12fdd77 100644
> --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
> +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
> @@ -266,8 +266,8 @@ extern int gpmi_read_page(struct gpmi_nand_data *,
>   #define STATUS_UNCORRECTABLE	0xfe
>
>   /* Use the platform_id to distinguish different Archs. */
> -#define IS_MX23			0x1
> -#define IS_MX28			0x2
> +#define IS_MX23			0x0
> +#define IS_MX28			0x1
>   #define GPMI_IS_MX23(x)		((x)->pdev->id_entry->driver_data == IS_MX23)
>   #define GPMI_IS_MX28(x)		((x)->pdev->id_entry->driver_data == IS_MX28)
>   #endif
> diff --git a/include/linux/mtd/gpmi-nand.h b/include/linux/mtd/gpmi-nand.h
> index 69b6dbf..ed3c4e0 100644
> --- a/include/linux/mtd/gpmi-nand.h
> +++ b/include/linux/mtd/gpmi-nand.h
> @@ -23,12 +23,12 @@
>   #define GPMI_NAND_RES_SIZE	6
>
>   /* Resource names for the GPMI NAND driver. */
> -#define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME  "GPMI NAND GPMI Registers"
> +#define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME  "gpmi-nand"
>   #define GPMI_NAND_GPMI_INTERRUPT_RES_NAME  "GPMI NAND GPMI Interrupt"
> -#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME   "GPMI NAND BCH Registers"
> -#define GPMI_NAND_BCH_INTERRUPT_RES_NAME   "GPMI NAND BCH Interrupt"
> +#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME   "bch"
> +#define GPMI_NAND_BCH_INTERRUPT_RES_NAME   "bch"
>   #define GPMI_NAND_DMA_CHANNELS_RES_NAME    "GPMI NAND DMA Channels"
> -#define GPMI_NAND_DMA_INTERRUPT_RES_NAME   "GPMI NAND DMA Interrupt"
> +#define GPMI_NAND_DMA_INTERRUPT_RES_NAME   "gpmi-dma"
>
>   /**
>    * struct gpmi_nand_platform_data - GPMI NAND driver platform data.
Huang Shijie - May 4, 2012, 4:30 a.m.
Hi,
> Any chance you can add some information on what kind of mtd tests were 
> done with this code change and on what platform?
I did bonnie++ test, and mtd_speed test on mx28evk board.
>
> Also if one wanted to test this patch say on mx28 based hardware, one 
> should apply this patch against arm-soc tree, top of the 3.5-next tree?
If you only want to test this on mx28 based hardware, you can just apply 
this patch against the arm-soc tree, top of the 3.5-next tree.
But you still need some extra mxs-dma patches (and maybe do some 
hardcode for pinctl) to make the gpmi-nand driver work.

Best Regards
Huang Shijie
Artem Bityutskiy - May 4, 2012, 9:41 a.m.
On Fri, 2012-05-04 at 11:13 +0800, Huang Shijie wrote:
> This patch just adds the DT support to gpmi-nand.
> 
> Signed-off-by: Huang Shijie <b32955@freescale.com>
> ---
> Please select the CONFIG_USE_OF before you do the compiler-test.
> thanks.

It should compile without CONFIG_USE_OF also just fine. Currently it
does not.
Huang Shijie - May 4, 2012, 10:26 a.m.
于 2012年05月04日 17:41, Artem Bityutskiy 写道:
> On Fri, 2012-05-04 at 11:13 +0800, Huang Shijie wrote:
>> This patch just adds the DT support to gpmi-nand.
>>
>> Signed-off-by: Huang Shijie<b32955@freescale.com>
>> ---
>> Please select the CONFIG_USE_OF before you do the compiler-test.
>> thanks.
> It should compile without CONFIG_USE_OF also just fine. Currently it
> does not.
>
why not select CONFIG_USE_OF as the gpmi-nand is converted to a DT driver.

If you insist that it should compile without CONFIG_USE_OF, i have to 
add back the header file ,
such as of_irq.h.

BR
Huang Shijie
Artem Bityutskiy - May 4, 2012, 10:37 a.m.
On Fri, 2012-05-04 at 18:26 +0800, Huang Shijie wrote:
> 于 2012年05月04日 17:41, Artem Bityutskiy 写道:
> > On Fri, 2012-05-04 at 11:13 +0800, Huang Shijie wrote:
> >> This patch just adds the DT support to gpmi-nand.
> >>
> >> Signed-off-by: Huang Shijie<b32955@freescale.com>
> >> ---
> >> Please select the CONFIG_USE_OF before you do the compiler-test.
> >> thanks.
> > It should compile without CONFIG_USE_OF also just fine. Currently it
> > does not.
> >
> why not select CONFIG_USE_OF as the gpmi-nand is converted to a DT driver.

Yes, it can be done as well. My point is that you should not break
compilation. These 2 patches do not compile with for me - aiaiai
reports:

--------------------------------------------------------------------------------
Failed to build the following commit for configuration "l2_mxs_defconfig" (architecture arm)":

d791f1c mtd: gpmi: add gpmi support for mx6q

drivers/mtd/nand/gpmi-nand/gpmi-lib.c:437:36: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
drivers/mtd/nand/gpmi-nand/gpmi-lib.c:579:35: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
In file included from include/linux/kernel.h:19:0,
                 from include/linux/clk.h:15,
                 from drivers/mtd/nand/gpmi-nand/gpmi-nand.c:21:
include/linux/bitops.h: In function 'hweight_long':
include/linux/bitops.h:66:26: warning: signed and unsigned type in conditional expression [-Wsign-compare]
In file included from include/linux/dma-mapping.h:73:0,
                 from drivers/mtd/nand/gpmi-nand/gpmi-nand.h:22,
                 from drivers/mtd/nand/gpmi-nand/gpmi-nand.c:28:
arch/arm/include/asm/dma-mapping.h: In function 'dma_mapping_error':
arch/arm/include/asm/dma-mapping.h:126:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
drivers/mtd/nand/gpmi-nand/gpmi-nand.c: In function 'release_bch_irq':
drivers/mtd/nand/gpmi-nand/gpmi-nand.c:382:11: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
drivers/mtd/nand/gpmi-nand/gpmi-nand.c: In function 'acquire_dma_channels':
drivers/mtd/nand/gpmi-nand/gpmi-nand.c:430:2: error: implicit declaration of function 'of_property_read_u32' [-Werror=implicit-function-declaration]
drivers/mtd/nand/gpmi-nand/gpmi-nand.c: In function 'mx23_check_transcription_stamp':
drivers/mtd/nand/gpmi-nand/gpmi-nand.c:1186:9: warning: variable 'byte' set but not used [-Wunused-but-set-variable]
drivers/mtd/nand/gpmi-nand/gpmi-nand.c: In function 'mx23_write_transcription_stamp':
drivers/mtd/nand/gpmi-nand/gpmi-nand.c:1247:15: warning: variable 'byte' set but not used [-Wunused-but-set-variable]
drivers/mtd/nand/gpmi-nand/gpmi-nand.c: At top level:
drivers/mtd/nand/gpmi-nand/gpmi-nand.c:1448:6: warning: no previous prototype for 'gpmi_nfc_exit' [-Wmissing-prototypes]
cc1: some warnings being treated as errors
make[5]: *** [drivers/mtd/nand/gpmi-nand/gpmi-nand.o] Error 1

--------------------------------------------------------------------------------

Patch

diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
new file mode 100644
index 0000000..1a5bbd3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
@@ -0,0 +1,33 @@ 
+* Freescale General-Purpose Media Interface (GPMI)
+
+The GPMI nand controller provides an interface to control the
+NAND flash chips. We support only one NAND chip now.
+
+Required properties:
+  - compatible : should be "fsl,<chip>-gpmi-nand"
+  - reg : should contain registers location and length for gpmi and bch.
+  - reg-names: Should contain the reg names "gpmi-nand" and "bch"
+  - interrupts : The first is the DMA interrupt number for GPMI.
+                 The second is the BCH interrupt number.
+  - interrupt-names : The interrupt names "gpmi-dma", "bch";
+  - fsl,gpmi-dma-channel : Should contain the dma channel it uses.
+
+The device tree may optionally contain sub-nodes describing partitions of the
+address space. See partition.txt for more detail.
+
+Examples:
+
+gpmi-nand@8000c000 {
+	compatible = "fsl,imx28-gpmi-nand";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	reg = <0x8000c000 2000>, <0x8000a000 2000>;
+	reg-names = "gpmi-nand", "bch";
+	interrupts = <88>, <41>;
+	interrupt-names = "gpmi-dma", "bch";
+	fsl,gpmi-dma-channel = <4>;
+
+	partition@0 {
+	...
+	};
+};
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index fa5200b..5c55c71 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -256,11 +256,12 @@  static unsigned int ns_to_cycles(unsigned int time,
 	return max(k, min);
 }
 
+#define DEF_MIN_PROP_DELAY	5
+#define DEF_MAX_PROP_DELAY	9
 /* Apply timing to current hardware conditions. */
 static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
 					struct gpmi_nfc_hardware_timing *hw)
 {
-	struct gpmi_nand_platform_data *pdata = this->pdata;
 	struct timing_threshod *nfc = &timing_default_threshold;
 	struct nand_chip *nand = &this->nand;
 	struct nand_timing target = this->timing;
@@ -277,8 +278,8 @@  static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
 	int ideal_sample_delay_in_ns;
 	unsigned int sample_delay_factor;
 	int tEYE;
-	unsigned int min_prop_delay_in_ns = pdata->min_prop_delay_in_ns;
-	unsigned int max_prop_delay_in_ns = pdata->max_prop_delay_in_ns;
+	unsigned int min_prop_delay_in_ns = DEF_MIN_PROP_DELAY;
+	unsigned int max_prop_delay_in_ns = DEF_MAX_PROP_DELAY;
 
 	/*
 	 * If there are multiple chips, we need to relax the timings to allow
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 75b1dde..c351137 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -24,6 +24,7 @@ 
 #include <linux/module.h>
 #include <linux/mtd/gpmi-nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/of_device.h>
 #include "gpmi-nand.h"
 
 /* add our owner bbt descriptor */
@@ -385,7 +386,7 @@  static void release_bch_irq(struct gpmi_nand_data *this)
 static bool gpmi_dma_filter(struct dma_chan *chan, void *param)
 {
 	struct gpmi_nand_data *this = param;
-	struct resource *r = this->private;
+	int dma_channel = (int)this->private;
 
 	if (!mxs_dma_is_apbh(chan))
 		return false;
@@ -397,7 +398,7 @@  static bool gpmi_dma_filter(struct dma_chan *chan, void *param)
 	 *	for mx28 :	MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7
 	 *		(These eight channels share the same IRQ!)
 	 */
-	if (r->start <= chan->chan_id && chan->chan_id <= r->end) {
+	if (dma_channel == chan->chan_id) {
 		chan->private = &this->dma_data;
 		return true;
 	}
@@ -417,57 +418,45 @@  static void release_dma_channels(struct gpmi_nand_data *this)
 static int __devinit acquire_dma_channels(struct gpmi_nand_data *this)
 {
 	struct platform_device *pdev = this->pdev;
-	struct gpmi_nand_platform_data *pdata = this->pdata;
-	struct resources *res = &this->resources;
-	struct resource *r, *r_dma;
-	unsigned int i;
+	struct resource *r_dma;
+	struct device_node *dn;
+	int dma_channel;
+	unsigned int ret;
+	struct dma_chan *dma_chan;
+	dma_cap_mask_t mask;
+
+	/* dma channel, we only use the first one. */
+	dn = pdev->dev.of_node;
+	ret = of_property_read_u32(dn, "fsl,gpmi-dma-channel", &dma_channel);
+	if (ret) {
+		pr_err("unable to get DMA channel from dt.\n");
+		goto acquire_err;
+	}
+	this->private = (void *)dma_channel;
 
-	r = platform_get_resource_byname(pdev, IORESOURCE_DMA,
-					GPMI_NAND_DMA_CHANNELS_RES_NAME);
+	/* gpmi dma interrupt */
 	r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
 					GPMI_NAND_DMA_INTERRUPT_RES_NAME);
-	if (!r || !r_dma) {
+	if (!r_dma) {
 		pr_err("Can't get resource for DMA\n");
-		return -ENXIO;
+		goto acquire_err;
 	}
+	this->dma_data.chan_irq = r_dma->start;
 
-	/* used in gpmi_dma_filter() */
-	this->private = r;
-
-	for (i = r->start; i <= r->end; i++) {
-		struct dma_chan *dma_chan;
-		dma_cap_mask_t mask;
+	/* request dma channel */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
 
-		if (i - r->start >= pdata->max_chip_count)
-			break;
-
-		dma_cap_zero(mask);
-		dma_cap_set(DMA_SLAVE, mask);
-
-		/* get the DMA interrupt */
-		if (r_dma->start == r_dma->end) {
-			/* only register the first. */
-			if (i == r->start)
-				this->dma_data.chan_irq = r_dma->start;
-			else
-				this->dma_data.chan_irq = NO_IRQ;
-		} else
-			this->dma_data.chan_irq = r_dma->start + (i - r->start);
-
-		dma_chan = dma_request_channel(mask, gpmi_dma_filter, this);
-		if (!dma_chan)
-			goto acquire_err;
-
-		/* fill the first empty item */
-		this->dma_chans[i - r->start] = dma_chan;
+	dma_chan = dma_request_channel(mask, gpmi_dma_filter, this);
+	if (!dma_chan) {
+		pr_err("dma_request_channel failed.\n");
+		goto acquire_err;
 	}
 
-	res->dma_low_channel = r->start;
-	res->dma_high_channel = i;
+	this->dma_chans[0] = dma_chan;
 	return 0;
 
 acquire_err:
-	pr_err("Can't acquire DMA channel %u\n", i);
 	release_dma_channels(this);
 	return -EINVAL;
 }
@@ -1461,9 +1450,9 @@  void gpmi_nfc_exit(struct gpmi_nand_data *this)
 
 static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this)
 {
-	struct gpmi_nand_platform_data *pdata = this->pdata;
 	struct mtd_info  *mtd = &this->mtd;
 	struct nand_chip *chip = &this->nand;
+	struct mtd_part_parser_data ppdata = {};
 	int ret;
 
 	/* init current chip */
@@ -1501,14 +1490,14 @@  static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this)
 	if (ret)
 		goto err_out;
 
-	ret = nand_scan(mtd, pdata->max_chip_count);
+	ret = nand_scan(mtd, 1);
 	if (ret) {
 		pr_err("Chip scan failed\n");
 		goto err_out;
 	}
 
-	ret = mtd_device_parse_register(mtd, NULL, NULL,
-			pdata->partitions, pdata->partition_count);
+	ppdata.of_node = this->pdev->dev.of_node;
+	ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
 	if (ret)
 		goto err_out;
 	return 0;
@@ -1518,12 +1507,37 @@  err_out:
 	return ret;
 }
 
+static const struct platform_device_id gpmi_ids[] = {
+	{ .name = "imx23-gpmi-nand", .driver_data = IS_MX23, },
+	{ .name = "imx28-gpmi-nand", .driver_data = IS_MX28, },
+	{},
+};
+
+static const struct of_device_id gpmi_nand_id_table[] = {
+	{
+		.compatible = "fsl,imx23-gpmi-nand",
+		.data = (void *)&gpmi_ids[IS_MX23]
+	}, {
+		.compatible = "fsl,imx28-gpmi-nand",
+		.data = (void *)&gpmi_ids[IS_MX28]
+	}, {}
+};
+MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
+
 static int __devinit gpmi_nand_probe(struct platform_device *pdev)
 {
-	struct gpmi_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct gpmi_nand_data *this;
+	const struct of_device_id *of_id;
 	int ret;
 
+	of_id = of_match_device(gpmi_nand_id_table, &pdev->dev);
+	if (of_id) {
+		pdev->id_entry = of_id->data;
+	} else {
+		pr_err("Failed to find the right device id.\n");
+		return -ENOMEM;
+	}
+
 	this = kzalloc(sizeof(*this), GFP_KERNEL);
 	if (!this) {
 		pr_err("Failed to allocate per-device memory\n");
@@ -1533,13 +1547,6 @@  static int __devinit gpmi_nand_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, this);
 	this->pdev  = pdev;
 	this->dev   = &pdev->dev;
-	this->pdata = pdata;
-
-	if (pdata->platform_init) {
-		ret = pdata->platform_init();
-		if (ret)
-			goto platform_init_error;
-	}
 
 	ret = acquire_resources(this);
 	if (ret)
@@ -1557,7 +1564,6 @@  static int __devinit gpmi_nand_probe(struct platform_device *pdev)
 
 exit_nfc_init:
 	release_resources(this);
-platform_init_error:
 exit_acquire_resources:
 	platform_set_drvdata(pdev, NULL);
 	kfree(this);
@@ -1575,19 +1581,10 @@  static int __exit gpmi_nand_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct platform_device_id gpmi_ids[] = {
-	{
-		.name = "imx23-gpmi-nand",
-		.driver_data = IS_MX23,
-	}, {
-		.name = "imx28-gpmi-nand",
-		.driver_data = IS_MX28,
-	}, {},
-};
-
 static struct platform_driver gpmi_nand_driver = {
 	.driver = {
 		.name = "gpmi-nand",
+		.of_match_table = gpmi_nand_id_table,
 	},
 	.probe   = gpmi_nand_probe,
 	.remove  = __exit_p(gpmi_nand_remove),
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
index ec6180d..12fdd77 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
@@ -266,8 +266,8 @@  extern int gpmi_read_page(struct gpmi_nand_data *,
 #define STATUS_UNCORRECTABLE	0xfe
 
 /* Use the platform_id to distinguish different Archs. */
-#define IS_MX23			0x1
-#define IS_MX28			0x2
+#define IS_MX23			0x0
+#define IS_MX28			0x1
 #define GPMI_IS_MX23(x)		((x)->pdev->id_entry->driver_data == IS_MX23)
 #define GPMI_IS_MX28(x)		((x)->pdev->id_entry->driver_data == IS_MX28)
 #endif
diff --git a/include/linux/mtd/gpmi-nand.h b/include/linux/mtd/gpmi-nand.h
index 69b6dbf..ed3c4e0 100644
--- a/include/linux/mtd/gpmi-nand.h
+++ b/include/linux/mtd/gpmi-nand.h
@@ -23,12 +23,12 @@ 
 #define GPMI_NAND_RES_SIZE	6
 
 /* Resource names for the GPMI NAND driver. */
-#define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME  "GPMI NAND GPMI Registers"
+#define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME  "gpmi-nand"
 #define GPMI_NAND_GPMI_INTERRUPT_RES_NAME  "GPMI NAND GPMI Interrupt"
-#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME   "GPMI NAND BCH Registers"
-#define GPMI_NAND_BCH_INTERRUPT_RES_NAME   "GPMI NAND BCH Interrupt"
+#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME   "bch"
+#define GPMI_NAND_BCH_INTERRUPT_RES_NAME   "bch"
 #define GPMI_NAND_DMA_CHANNELS_RES_NAME    "GPMI NAND DMA Channels"
-#define GPMI_NAND_DMA_INTERRUPT_RES_NAME   "GPMI NAND DMA Interrupt"
+#define GPMI_NAND_DMA_INTERRUPT_RES_NAME   "gpmi-dma"
 
 /**
  * struct gpmi_nand_platform_data - GPMI NAND driver platform data.