Patchwork [v3] ARM: davinci: aemif: get rid of davinci-nand driver dependency on aemif

login
register
mail settings
Submitter Ivan Khoronzhuk
Date Dec. 5, 2013, 6:11 p.m.
Message ID <1386267092-18615-1-git-send-email-ivan.khoronzhuk@ti.com>
Download mbox | patch
Permalink /patch/297343/
State Not Applicable
Headers show

Comments

Ivan Khoronzhuk - Dec. 5, 2013, 6:11 p.m.
The problem that the set timings code contains the call of Davinci
platform function davinci_aemif_setup_timing() which is not
accessible if kernel is built for another platform like Keystone.

The Keysone platform is going to use TI AEMIF driver.
If TI AEMIF is used we don't need to set timings and bus width.
It is done by AEMIF driver.

To get rid of davinci-nand driver dependency on aemif platform code
we moved aemif code to davinci platform.

The platform AEMIF code (aemif.c) has to be removed once Davinci
will be converted to DT and use ti-aemif.c driver.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
---
v3..v2:
- rebased on following patch series:
	[PATCH v3 0/9] Reuse davinci-nand driver for Keystone arch
	http://www.spinics.net/lists/arm-kernel/msg291723.html
- removed AEMIF setup from next boards:
	 arch/arm/mach-davinci/board-dm355-evm.c
	 arch/arm/mach-davinci/board-dm355-leopard.c
	 arch/arm/mach-davinci/board-dm365-evm.c
	 arch/arm/mach-davinci/board-neuros-osd2.c
	 arch/arm/mach-davinci/devices-tnetv107x.c
- removed repeated clk_get() from davinci_aemif_setup_timing()

v2..v1:
- enabled AEMIF clock
- removed EXPORT_SYMBOL(davinci_aemif_setup)
- renamed ugly name davinci_ntosd2_nandflash_device
CC:
Sekhar Nori <nsekhar@ti.com>

 arch/arm/mach-davinci/aemif.c                   |  106 ++++++++++++++++++++---
 arch/arm/mach-davinci/board-da830-evm.c         |    3 +
 arch/arm/mach-davinci/board-da850-evm.c         |    3 +
 arch/arm/mach-davinci/board-dm644x-evm.c        |    5 ++
 arch/arm/mach-davinci/board-dm646x-evm.c        |    3 +
 arch/arm/mach-davinci/board-mityomapl138.c      |    3 +
 drivers/mtd/nand/davinci_nand.c                 |   22 -----
 include/linux/platform_data/mtd-davinci-aemif.h |    5 +-
 8 files changed, 115 insertions(+), 35 deletions(-)
Sekhar Nori - Dec. 6, 2013, 9:04 p.m.
On 12/5/2013 11:41 PM, Ivan Khoronzhuk wrote:

> diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
> index 7aa105b..98a66ff 100644
> --- a/arch/arm/mach-davinci/board-mityomapl138.c
> +++ b/arch/arm/mach-davinci/board-mityomapl138.c
> @@ -432,6 +432,9 @@ static void __init mityomapl138_setup_nand(void)
>  {
>  	platform_add_devices(mityomapl138_devices,
>  				 ARRAY_SIZE(mityomapl138_devices));
> +
> +	if (davinci_aemif_setup(&mityomapl138_nandflash_device))
> +		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
>  }

I must be missing something, but exactly why is this required for
board-mityomapl138.c?

Thanks,
Sekhar
Ivan Khoronzhuk - Dec. 9, 2013, 8:58 a.m.
On 12/06/2013 11:04 PM, Sekhar Nori wrote:
> On 12/5/2013 11:41 PM, Ivan Khoronzhuk wrote:
> 
>> diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
>> index 7aa105b..98a66ff 100644
>> --- a/arch/arm/mach-davinci/board-mityomapl138.c
>> +++ b/arch/arm/mach-davinci/board-mityomapl138.c
>> @@ -432,6 +432,9 @@ static void __init mityomapl138_setup_nand(void)
>>   {
>>   	platform_add_devices(mityomapl138_devices,
>>   				 ARRAY_SIZE(mityomapl138_devices));
>> +
>> +	if (davinci_aemif_setup(&mityomapl138_nandflash_device))
>> +		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
>>   }
> 
> I must be missing something, but exactly why is this required for
> board-mityomapl138.c?
> 
> Thanks,
> Sekhar
> 

board-mityomapl138.c - only one board file with NAND_BUSWIDTH_16 option set in pdata.
By default bus width is treated as 8 bit, in another case we have to set it.
Currently bus width setup is done in davinci_aemif_setup(). So, to set bus width
correctly we have to call davinci_aemif_setup() for board in question.
Ivan Khoronzhuk - Dec. 18, 2013, 11:51 a.m.
On 12/05/2013 08:11 PM, Ivan Khoronzhuk wrote:
> The problem that the set timings code contains the call of Davinci
> platform function davinci_aemif_setup_timing() which is not
> accessible if kernel is built for another platform like Keystone.
> 
> The Keysone platform is going to use TI AEMIF driver.
> If TI AEMIF is used we don't need to set timings and bus width.
> It is done by AEMIF driver.
> 
> To get rid of davinci-nand driver dependency on aemif platform code
> we moved aemif code to davinci platform.
> 
> The platform AEMIF code (aemif.c) has to be removed once Davinci
> will be converted to DT and use ti-aemif.c driver.
> 
> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
> ---
> v3..v2:
> - rebased on following patch series:
> 	[PATCH v3 0/9] Reuse davinci-nand driver for Keystone arch
> 	http://www.spinics.net/lists/arm-kernel/msg291723.html
> - removed AEMIF setup from next boards:
> 	 arch/arm/mach-davinci/board-dm355-evm.c
> 	 arch/arm/mach-davinci/board-dm355-leopard.c
> 	 arch/arm/mach-davinci/board-dm365-evm.c
> 	 arch/arm/mach-davinci/board-neuros-osd2.c
> 	 arch/arm/mach-davinci/devices-tnetv107x.c
> - removed repeated clk_get() from davinci_aemif_setup_timing()
> 
> v2..v1:
> - enabled AEMIF clock
> - removed EXPORT_SYMBOL(davinci_aemif_setup)
> - renamed ugly name davinci_ntosd2_nandflash_device
> CC:
> Sekhar Nori <nsekhar@ti.com>
> 
>   arch/arm/mach-davinci/aemif.c                   |  106 ++++++++++++++++++++---
>   arch/arm/mach-davinci/board-da830-evm.c         |    3 +
>   arch/arm/mach-davinci/board-da850-evm.c         |    3 +
>   arch/arm/mach-davinci/board-dm644x-evm.c        |    5 ++
>   arch/arm/mach-davinci/board-dm646x-evm.c        |    3 +
>   arch/arm/mach-davinci/board-mityomapl138.c      |    3 +
>   drivers/mtd/nand/davinci_nand.c                 |   22 -----
>   include/linux/platform_data/mtd-davinci-aemif.h |    5 +-
>   8 files changed, 115 insertions(+), 35 deletions(-)
> 
> diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c
> index f091a90..7adfb7e 100644
> --- a/arch/arm/mach-davinci/aemif.c
> +++ b/arch/arm/mach-davinci/aemif.c
> @@ -16,6 +16,7 @@
>   #include <linux/time.h>
>   
>   #include <linux/platform_data/mtd-davinci-aemif.h>
> +#include <linux/platform_data/mtd-davinci.h>
>   
>   /* Timing value configuration */
>   
> @@ -43,6 +44,17 @@
>   				WSTROBE(WSTROBE_MAX) | \
>   				WSETUP(WSETUP_MAX))
>   
> +static inline unsigned int davinci_aemif_readl(void __iomem *base, int offset)
> +{
> +	return readl_relaxed(base + offset);
> +}
> +
> +static inline void davinci_aemif_writel(void __iomem *base,
> +					int offset, unsigned long value)
> +{
> +	writel_relaxed(value, base + offset);
> +}
> +
>   /*
>    * aemif_calc_rate - calculate timing data.
>    * @wanted: The cycle time needed in nanoseconds.
> @@ -76,6 +88,7 @@ static int aemif_calc_rate(int wanted, unsigned long clk, int max)
>    * @t: timing values to be progammed
>    * @base: The virtual base address of the AEMIF interface
>    * @cs: chip-select to program the timing values for
> + * @clkrate: the AEMIF clkrate
>    *
>    * This function programs the given timing values (in real clock) into the
>    * AEMIF registers taking the AEMIF clock into account.
> @@ -86,24 +99,17 @@ static int aemif_calc_rate(int wanted, unsigned long clk, int max)
>    *
>    * Returns 0 on success, else negative errno.
>    */
> -int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
> -					void __iomem *base, unsigned cs)
> +static int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
> +					void __iomem *base, unsigned cs,
> +					unsigned long clkrate)
>   {
>   	unsigned set, val;
>   	int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
>   	unsigned offset = A1CR_OFFSET + cs * 4;
> -	struct clk *aemif_clk;
> -	unsigned long clkrate;
>   
>   	if (!t)
>   		return 0;	/* Nothing to do */
>   
> -	aemif_clk = clk_get(NULL, "aemif");
> -	if (IS_ERR(aemif_clk))
> -		return PTR_ERR(aemif_clk);
> -
> -	clkrate = clk_get_rate(aemif_clk);
> -
>   	clkrate /= 1000;	/* turn clock into kHz for ease of use */
>   
>   	ta	= aemif_calc_rate(t->ta, clkrate, TA_MAX);
> @@ -130,4 +136,82 @@ int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
>   
>   	return 0;
>   }
> -EXPORT_SYMBOL(davinci_aemif_setup_timing);
> +
> +/**
> + * davinci_aemif_setup - setup AEMIF interface by davinci_nand_pdata
> + * @pdev - link to platform device to setup settings for
> + *
> + * This function does not use any locking while programming the AEMIF
> + * because it is expected that there is only one user of a given
> + * chip-select.
> + *
> + * Returns 0 on success, else negative errno.
> + */
> +int davinci_aemif_setup(struct platform_device *pdev)
> +{
> +	struct davinci_nand_pdata *pdata = dev_get_platdata(&pdev->dev);
> +	uint32_t val;
> +	unsigned long clkrate;
> +	struct resource	*res;
> +	void __iomem *base;
> +	struct clk* clk;
> +	int ret = 0;
> +
> +	clk = clk_get(&pdev->dev, "aemif");
> +	if (IS_ERR(clk)) {
> +		ret = PTR_ERR(clk);
> +		dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = clk_prepare_enable(clk);
> +	if (ret < 0) {
> +		dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if (!res) {
> +		dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	base = ioremap(res->start, resource_size(res));
> +	if (!base) {
> +		dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res);
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	/*
> +	 * Setup Async configuration register in case we did not boot
> +	 * from NAND and so bootloader did not bother to set it up.
> +	 */
> +	val = davinci_aemif_readl(base, A1CR_OFFSET + pdev->id * 4);
> +	/*
> +	 * Extended Wait is not valid and Select Strobe mode is not
> +	 * used
> +	 */
> +	val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
> +	if (pdata->options & NAND_BUSWIDTH_16)
> +		val |= 0x1;
> +
> +	davinci_aemif_writel(base, A1CR_OFFSET + pdev->id * 4, val);
> +
> +	clkrate = clk_get_rate(clk);
> +
> +	if (pdata->timing)
> +		ret = davinci_aemif_setup_timing(pdata->timing, base, pdev->id,
> +						 clkrate);
> +
> +	if (ret < 0)
> +		dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
> +
> +	iounmap(base);
> +err:
> +	clk_disable_unprepare(clk);
> +	clk_put(clk);
> +	return ret;
> +}
> diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
> index d1f45af..5623131 100644
> --- a/arch/arm/mach-davinci/board-da830-evm.c
> +++ b/arch/arm/mach-davinci/board-da830-evm.c
> @@ -419,6 +419,9 @@ static inline void da830_evm_init_nand(int mux_mode)
>   	if (ret)
>   		pr_warning("da830_evm_init: NAND device not registered.\n");
>   
> +	if (davinci_aemif_setup(&da830_evm_nand_device))
> +		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
> +
>   	gpio_direction_output(mux_mode, 1);
>   }
>   #else
> diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
> index e0af0ec..234c5bb 100644
> --- a/arch/arm/mach-davinci/board-da850-evm.c
> +++ b/arch/arm/mach-davinci/board-da850-evm.c
> @@ -358,6 +358,9 @@ static inline void da850_evm_setup_nor_nand(void)
>   
>   		platform_add_devices(da850_evm_devices,
>   					ARRAY_SIZE(da850_evm_devices));
> +
> +		if (davinci_aemif_setup(&da850_evm_nandflash_device))
> +			pr_warn("%s: Cannot configure AEMIF.\n", __func__);
>   	}
>   }
>   
> diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
> index 987605b7..5602957 100644
> --- a/arch/arm/mach-davinci/board-dm644x-evm.c
> +++ b/arch/arm/mach-davinci/board-dm644x-evm.c
> @@ -778,6 +778,11 @@ static __init void davinci_evm_init(void)
>   		/* only one device will be jumpered and detected */
>   		if (HAS_NAND) {
>   			platform_device_register(&davinci_evm_nandflash_device);
> +
> +			if (davinci_aemif_setup(&davinci_evm_nandflash_device))
> +				pr_warn("%s: Cannot configure AEMIF.\n",
> +					__func__);
> +
>   			evm_leds[7].default_trigger = "nand-disk";
>   			if (HAS_NOR)
>   				pr_warning("WARNING: both NAND and NOR flash "
> diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
> index 13d0801..ae129bc 100644
> --- a/arch/arm/mach-davinci/board-dm646x-evm.c
> +++ b/arch/arm/mach-davinci/board-dm646x-evm.c
> @@ -805,6 +805,9 @@ static __init void evm_init(void)
>   
>   	platform_device_register(&davinci_nand_device);
>   
> +	if (davinci_aemif_setup(&davinci_nand_device))
> +		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
> +
>   	dm646x_init_edma(dm646x_edma_rsv);
>   
>   	if (HAS_ATA)
> diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
> index 7aa105b..98a66ff 100644
> --- a/arch/arm/mach-davinci/board-mityomapl138.c
> +++ b/arch/arm/mach-davinci/board-mityomapl138.c
> @@ -432,6 +432,9 @@ static void __init mityomapl138_setup_nand(void)
>   {
>   	platform_add_devices(mityomapl138_devices,
>   				 ARRAY_SIZE(mityomapl138_devices));
> +
> +	if (davinci_aemif_setup(&mityomapl138_nandflash_device))
> +		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
>   }
>   
>   static const short mityomap_mii_pins[] = {
> diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
> index 0cd4dbc..4463b0e 100644
> --- a/drivers/mtd/nand/davinci_nand.c
> +++ b/drivers/mtd/nand/davinci_nand.c
> @@ -741,28 +741,6 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
>   		goto err_clk_enable;
>   	}
>   
> -	/*
> -	 * Setup Async configuration register in case we did not boot from
> -	 * NAND and so bootloader did not bother to set it up.
> -	 */
> -	val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
> -
> -	/* Extended Wait is not valid and Select Strobe mode is not used */
> -	val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
> -	if (info->chip.options & NAND_BUSWIDTH_16)
> -		val |= 0x1;
> -
> -	davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
> -
> -	ret = 0;
> -	if (info->timing)
> -		ret = davinci_aemif_setup_timing(info->timing, info->base,
> -							info->core_chipsel);
> -	if (ret < 0) {
> -		dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
> -		goto err;
> -	}
> -
>   	spin_lock_irq(&davinci_nand_lock);
>   
>   	/* put CSxNAND into NAND mode */
> diff --git a/include/linux/platform_data/mtd-davinci-aemif.h b/include/linux/platform_data/mtd-davinci-aemif.h
> index 05b2934..97948ac 100644
> --- a/include/linux/platform_data/mtd-davinci-aemif.h
> +++ b/include/linux/platform_data/mtd-davinci-aemif.h
> @@ -10,6 +10,8 @@
>   #ifndef _MACH_DAVINCI_AEMIF_H
>   #define _MACH_DAVINCI_AEMIF_H
>   
> +#include <linux/platform_device.h>
> +
>   #define NRCSR_OFFSET		0x00
>   #define AWCCR_OFFSET		0x04
>   #define A1CR_OFFSET		0x10
> @@ -31,6 +33,5 @@ struct davinci_aemif_timing {
>   	u8	ta;
>   };
>   
> -int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
> -					void __iomem *base, unsigned cs);
> +int davinci_aemif_setup(struct platform_device *pdev);
>   #endif
> 

Hi, Sekhar

This patch is based on "Reuse davinci-nand driver for Keystone arch" series.
The series has passed review at https://lkml.org/lkml/2013/12/17/241
and can be found at http://git.infradead.org/l2-mtd.git

This patch can be still applied on top of the series without conflicts. 

Can you please pick up the $subject patch if you are OK with it?
Sekhar Nori - Dec. 18, 2013, 12:13 p.m.
On Wednesday 18 December 2013 05:21 PM, ivan.khoronzhuk wrote:
> Hi, Sekhar
> 
> This patch is based on "Reuse davinci-nand driver for Keystone arch" series.
> The series has passed review at https://lkml.org/lkml/2013/12/17/241
> and can be found at http://git.infradead.org/l2-mtd.git
> 
> This patch can be still applied on top of the series without conflicts. 
> 
> Can you please pick up the $subject patch if you are OK with it?

I have no problems with the patch and can pick it too, but need ack from
MTD maintainer (David) as it touches drivers/mtd/ too.

David,

If you do not have the patch, we can resend it.

Thanks,
Sekhar
Ivan Khoronzhuk - Dec. 26, 2013, 12:06 p.m.
On 12/18/2013 02:13 PM, Sekhar Nori wrote:
> On Wednesday 18 December 2013 05:21 PM, ivan.khoronzhuk wrote:
>> Hi, Sekhar
>>
>> This patch is based on "Reuse davinci-nand driver for Keystone arch" series.
>> The series has passed review at https://lkml.org/lkml/2013/12/17/241
>> and can be found at http://git.infradead.org/l2-mtd.git
>>
>> This patch can be still applied on top of the series without conflicts.
>>
>> Can you please pick up the $subject patch if you are OK with it?
>
> I have no problems with the patch and can pick it too, but need ack from
> MTD maintainer (David) as it touches drivers/mtd/ too.
>
> David,
>
> If you do not have the patch, we can resend it.
>
> Thanks,
> Sekhar
>

Hi Brian,

Do you agree if this patch will go through Davinci tree?

This is the last one we need to reuse Davinci Nand driver for Keystone.
Sekhar Nori - Jan. 9, 2014, 10:39 a.m.
On Thursday 26 December 2013 05:36 PM, ivan.khoronzhuk wrote:
> On 12/18/2013 02:13 PM, Sekhar Nori wrote:
>> On Wednesday 18 December 2013 05:21 PM, ivan.khoronzhuk wrote:
>>> Hi, Sekhar
>>>
>>> This patch is based on "Reuse davinci-nand driver for Keystone arch"
>>> series.
>>> The series has passed review at https://lkml.org/lkml/2013/12/17/241
>>> and can be found at http://git.infradead.org/l2-mtd.git
>>>
>>> This patch can be still applied on top of the series without conflicts.
>>>
>>> Can you please pick up the $subject patch if you are OK with it?
>>
>> I have no problems with the patch and can pick it too, but need ack from
>> MTD maintainer (David) as it touches drivers/mtd/ too.
>>
>> David,
>>
>> If you do not have the patch, we can resend it.
>>
>> Thanks,
>> Sekhar
>>
> 
> Hi Brian,
> 
> Do you agree if this patch will go through Davinci tree?
> 
> This is the last one we need to reuse Davinci Nand driver for Keystone.

Since we never got an ack from MTD folks, I am going and go ahead and
try pushing this through ARM-SoC regardless. I will CC the MTD
maintainers on the pull request so any objections could even be posted
there.

Thanks,
Sekhar
Brian Norris - Jan. 9, 2014, 4:33 p.m.
On Thu, Jan 09, 2014 at 04:09:00PM +0530, Sekhar Nori wrote:
> On Thursday 26 December 2013 05:36 PM, ivan.khoronzhuk wrote:
> > On 12/18/2013 02:13 PM, Sekhar Nori wrote:
> >> On Wednesday 18 December 2013 05:21 PM, ivan.khoronzhuk wrote:
> >>> Hi, Sekhar
> >>>
> >>> This patch is based on "Reuse davinci-nand driver for Keystone arch"
> >>> series.
> >>> The series has passed review at https://lkml.org/lkml/2013/12/17/241
> >>> and can be found at http://git.infradead.org/l2-mtd.git
> >>>
> >>> This patch can be still applied on top of the series without conflicts.
> >>>
> >>> Can you please pick up the $subject patch if you are OK with it?
> >>
> >> I have no problems with the patch and can pick it too, but need ack from
> >> MTD maintainer (David) as it touches drivers/mtd/ too.
> >>
> >> David,
> >>
> >> If you do not have the patch, we can resend it.
> >>
> >> Thanks,
> >> Sekhar
> >>
> > 
> > Hi Brian,
> > 
> > Do you agree if this patch will go through Davinci tree?
> > 
> > This is the last one we need to reuse Davinci Nand driver for Keystone.
> 
> Since we never got an ack from MTD folks, I am going and go ahead and
> try pushing this through ARM-SoC regardless. I will CC the MTD
> maintainers on the pull request so any objections could even be posted
> there.

Sorry, I've been a little busy / out for vacation. The MTD parts look OK
to me. Feel free to take it in your tree.

Acked-by: Brian Norris <computersforpeace@gmail.com>

Brian
Sekhar Nori - Jan. 10, 2014, 4:19 a.m.
On Thursday 09 January 2014 10:03 PM, Brian Norris wrote:
> On Thu, Jan 09, 2014 at 04:09:00PM +0530, Sekhar Nori wrote:
>> On Thursday 26 December 2013 05:36 PM, ivan.khoronzhuk wrote:
>>> On 12/18/2013 02:13 PM, Sekhar Nori wrote:
>>>> On Wednesday 18 December 2013 05:21 PM, ivan.khoronzhuk wrote:
>>>>> Hi, Sekhar
>>>>>
>>>>> This patch is based on "Reuse davinci-nand driver for Keystone arch"
>>>>> series.
>>>>> The series has passed review at https://lkml.org/lkml/2013/12/17/241
>>>>> and can be found at http://git.infradead.org/l2-mtd.git
>>>>>
>>>>> This patch can be still applied on top of the series without conflicts.
>>>>>
>>>>> Can you please pick up the $subject patch if you are OK with it?
>>>>
>>>> I have no problems with the patch and can pick it too, but need ack from
>>>> MTD maintainer (David) as it touches drivers/mtd/ too.
>>>>
>>>> David,
>>>>
>>>> If you do not have the patch, we can resend it.
>>>>
>>>> Thanks,
>>>> Sekhar
>>>>
>>>
>>> Hi Brian,
>>>
>>> Do you agree if this patch will go through Davinci tree?
>>>
>>> This is the last one we need to reuse Davinci Nand driver for Keystone.
>>
>> Since we never got an ack from MTD folks, I am going and go ahead and
>> try pushing this through ARM-SoC regardless. I will CC the MTD
>> maintainers on the pull request so any objections could even be posted
>> there.
> 
> Sorry, I've been a little busy / out for vacation. The MTD parts look OK
> to me. Feel free to take it in your tree.
> 
> Acked-by: Brian Norris <computersforpeace@gmail.com>

Thanks Brian!

Regards,
Sekhar
Sekhar Nori - Jan. 10, 2014, 7:15 a.m.
On Thursday 09 January 2014 10:03 PM, Brian Norris wrote:
> On Thu, Jan 09, 2014 at 04:09:00PM +0530, Sekhar Nori wrote:
>> On Thursday 26 December 2013 05:36 PM, ivan.khoronzhuk wrote:
>>> On 12/18/2013 02:13 PM, Sekhar Nori wrote:
>>>> On Wednesday 18 December 2013 05:21 PM, ivan.khoronzhuk wrote:
>>>>> Hi, Sekhar
>>>>>
>>>>> This patch is based on "Reuse davinci-nand driver for Keystone arch"
>>>>> series.
>>>>> The series has passed review at https://lkml.org/lkml/2013/12/17/241
>>>>> and can be found at http://git.infradead.org/l2-mtd.git
>>>>>
>>>>> This patch can be still applied on top of the series without conflicts.
>>>>>
>>>>> Can you please pick up the $subject patch if you are OK with it?
>>>>
>>>> I have no problems with the patch and can pick it too, but need ack from
>>>> MTD maintainer (David) as it touches drivers/mtd/ too.
>>>>
>>>> David,
>>>>
>>>> If you do not have the patch, we can resend it.
>>>>
>>>> Thanks,
>>>> Sekhar
>>>>
>>>
>>> Hi Brian,
>>>
>>> Do you agree if this patch will go through Davinci tree?
>>>
>>> This is the last one we need to reuse Davinci Nand driver for Keystone.
>>
>> Since we never got an ack from MTD folks, I am going and go ahead and
>> try pushing this through ARM-SoC regardless. I will CC the MTD
>> maintainers on the pull request so any objections could even be posted
>> there.
> 
> Sorry, I've been a little busy / out for vacation. The MTD parts look OK
> to me. Feel free to take it in your tree.
> 
> Acked-by: Brian Norris <computersforpeace@gmail.com>

Actually the NAND portion conflicts with some of the changes from Ivan
you took recently. I think it will be better if you take this patch too
with my ack. For me to take it through ARM-SoC, I need an immutable
branch from you - with commits same as what you will eventually be
sending to Linus, based on which I can send a pull request.

In any case, there is a v4 needed to fix a build and checkpatch error I
just noticed. I will send it out soon.

Thanks,
Sekhar

Patch

diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c
index f091a90..7adfb7e 100644
--- a/arch/arm/mach-davinci/aemif.c
+++ b/arch/arm/mach-davinci/aemif.c
@@ -16,6 +16,7 @@ 
 #include <linux/time.h>
 
 #include <linux/platform_data/mtd-davinci-aemif.h>
+#include <linux/platform_data/mtd-davinci.h>
 
 /* Timing value configuration */
 
@@ -43,6 +44,17 @@ 
 				WSTROBE(WSTROBE_MAX) | \
 				WSETUP(WSETUP_MAX))
 
+static inline unsigned int davinci_aemif_readl(void __iomem *base, int offset)
+{
+	return readl_relaxed(base + offset);
+}
+
+static inline void davinci_aemif_writel(void __iomem *base,
+					int offset, unsigned long value)
+{
+	writel_relaxed(value, base + offset);
+}
+
 /*
  * aemif_calc_rate - calculate timing data.
  * @wanted: The cycle time needed in nanoseconds.
@@ -76,6 +88,7 @@  static int aemif_calc_rate(int wanted, unsigned long clk, int max)
  * @t: timing values to be progammed
  * @base: The virtual base address of the AEMIF interface
  * @cs: chip-select to program the timing values for
+ * @clkrate: the AEMIF clkrate
  *
  * This function programs the given timing values (in real clock) into the
  * AEMIF registers taking the AEMIF clock into account.
@@ -86,24 +99,17 @@  static int aemif_calc_rate(int wanted, unsigned long clk, int max)
  *
  * Returns 0 on success, else negative errno.
  */
-int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
-					void __iomem *base, unsigned cs)
+static int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
+					void __iomem *base, unsigned cs,
+					unsigned long clkrate)
 {
 	unsigned set, val;
 	int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
 	unsigned offset = A1CR_OFFSET + cs * 4;
-	struct clk *aemif_clk;
-	unsigned long clkrate;
 
 	if (!t)
 		return 0;	/* Nothing to do */
 
-	aemif_clk = clk_get(NULL, "aemif");
-	if (IS_ERR(aemif_clk))
-		return PTR_ERR(aemif_clk);
-
-	clkrate = clk_get_rate(aemif_clk);
-
 	clkrate /= 1000;	/* turn clock into kHz for ease of use */
 
 	ta	= aemif_calc_rate(t->ta, clkrate, TA_MAX);
@@ -130,4 +136,82 @@  int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
 
 	return 0;
 }
-EXPORT_SYMBOL(davinci_aemif_setup_timing);
+
+/**
+ * davinci_aemif_setup - setup AEMIF interface by davinci_nand_pdata
+ * @pdev - link to platform device to setup settings for
+ *
+ * This function does not use any locking while programming the AEMIF
+ * because it is expected that there is only one user of a given
+ * chip-select.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int davinci_aemif_setup(struct platform_device *pdev)
+{
+	struct davinci_nand_pdata *pdata = dev_get_platdata(&pdev->dev);
+	uint32_t val;
+	unsigned long clkrate;
+	struct resource	*res;
+	void __iomem *base;
+	struct clk* clk;
+	int ret = 0;
+
+	clk = clk_get(&pdev->dev, "aemif");
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret < 0) {
+		dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n",
+			ret);
+		return ret;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	base = ioremap(res->start, resource_size(res));
+	if (!base) {
+		dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/*
+	 * Setup Async configuration register in case we did not boot
+	 * from NAND and so bootloader did not bother to set it up.
+	 */
+	val = davinci_aemif_readl(base, A1CR_OFFSET + pdev->id * 4);
+	/*
+	 * Extended Wait is not valid and Select Strobe mode is not
+	 * used
+	 */
+	val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
+	if (pdata->options & NAND_BUSWIDTH_16)
+		val |= 0x1;
+
+	davinci_aemif_writel(base, A1CR_OFFSET + pdev->id * 4, val);
+
+	clkrate = clk_get_rate(clk);
+
+	if (pdata->timing)
+		ret = davinci_aemif_setup_timing(pdata->timing, base, pdev->id,
+						 clkrate);
+
+	if (ret < 0)
+		dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
+
+	iounmap(base);
+err:
+	clk_disable_unprepare(clk);
+	clk_put(clk);
+	return ret;
+}
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index d1f45af..5623131 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -419,6 +419,9 @@  static inline void da830_evm_init_nand(int mux_mode)
 	if (ret)
 		pr_warning("da830_evm_init: NAND device not registered.\n");
 
+	if (davinci_aemif_setup(&da830_evm_nand_device))
+		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
+
 	gpio_direction_output(mux_mode, 1);
 }
 #else
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index e0af0ec..234c5bb 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -358,6 +358,9 @@  static inline void da850_evm_setup_nor_nand(void)
 
 		platform_add_devices(da850_evm_devices,
 					ARRAY_SIZE(da850_evm_devices));
+
+		if (davinci_aemif_setup(&da850_evm_nandflash_device))
+			pr_warn("%s: Cannot configure AEMIF.\n", __func__);
 	}
 }
 
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 987605b7..5602957 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -778,6 +778,11 @@  static __init void davinci_evm_init(void)
 		/* only one device will be jumpered and detected */
 		if (HAS_NAND) {
 			platform_device_register(&davinci_evm_nandflash_device);
+
+			if (davinci_aemif_setup(&davinci_evm_nandflash_device))
+				pr_warn("%s: Cannot configure AEMIF.\n",
+					__func__);
+
 			evm_leds[7].default_trigger = "nand-disk";
 			if (HAS_NOR)
 				pr_warning("WARNING: both NAND and NOR flash "
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 13d0801..ae129bc 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -805,6 +805,9 @@  static __init void evm_init(void)
 
 	platform_device_register(&davinci_nand_device);
 
+	if (davinci_aemif_setup(&davinci_nand_device))
+		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
+
 	dm646x_init_edma(dm646x_edma_rsv);
 
 	if (HAS_ATA)
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index 7aa105b..98a66ff 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -432,6 +432,9 @@  static void __init mityomapl138_setup_nand(void)
 {
 	platform_add_devices(mityomapl138_devices,
 				 ARRAY_SIZE(mityomapl138_devices));
+
+	if (davinci_aemif_setup(&mityomapl138_nandflash_device))
+		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
 }
 
 static const short mityomap_mii_pins[] = {
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 0cd4dbc..4463b0e 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -741,28 +741,6 @@  static int __init nand_davinci_probe(struct platform_device *pdev)
 		goto err_clk_enable;
 	}
 
-	/*
-	 * Setup Async configuration register in case we did not boot from
-	 * NAND and so bootloader did not bother to set it up.
-	 */
-	val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
-
-	/* Extended Wait is not valid and Select Strobe mode is not used */
-	val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
-	if (info->chip.options & NAND_BUSWIDTH_16)
-		val |= 0x1;
-
-	davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
-
-	ret = 0;
-	if (info->timing)
-		ret = davinci_aemif_setup_timing(info->timing, info->base,
-							info->core_chipsel);
-	if (ret < 0) {
-		dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
-		goto err;
-	}
-
 	spin_lock_irq(&davinci_nand_lock);
 
 	/* put CSxNAND into NAND mode */
diff --git a/include/linux/platform_data/mtd-davinci-aemif.h b/include/linux/platform_data/mtd-davinci-aemif.h
index 05b2934..97948ac 100644
--- a/include/linux/platform_data/mtd-davinci-aemif.h
+++ b/include/linux/platform_data/mtd-davinci-aemif.h
@@ -10,6 +10,8 @@ 
 #ifndef _MACH_DAVINCI_AEMIF_H
 #define _MACH_DAVINCI_AEMIF_H
 
+#include <linux/platform_device.h>
+
 #define NRCSR_OFFSET		0x00
 #define AWCCR_OFFSET		0x04
 #define A1CR_OFFSET		0x10
@@ -31,6 +33,5 @@  struct davinci_aemif_timing {
 	u8	ta;
 };
 
-int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
-					void __iomem *base, unsigned cs);
+int davinci_aemif_setup(struct platform_device *pdev);
 #endif