aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2014-02-25 11:42:59 -0500
committerArnd Bergmann <arnd@arndb.de>2014-02-25 11:43:20 -0500
commit8c4a57bcd80532c4fef5f87d0c53be25718294ed (patch)
tree56e21b6d7201bac111162d0888aa4334051255d8
parentb5feaefb45e878a6a4900925e5bdae9b73257616 (diff)
parent67f5185cad24b3c3d9ab07508dfcab55cdab02de (diff)
Merge tag 'davinci-for-v3.15/nand' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into next/drivers
A patch to break dependency of DaVinci NAND driver with mach-davinci. Required for reuse of driver on other platforms (keystone). * tag 'davinci-for-v3.15/nand' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci: ARM: davinci: aemif: get rid of davinci-nand driver dependency on aemif Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--arch/arm/mach-davinci/aemif.c107
-rw-r--r--arch/arm/mach-davinci/board-da830-evm.c3
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c3
-rw-r--r--arch/arm/mach-davinci/board-dm644x-evm.c5
-rw-r--r--arch/arm/mach-davinci/board-dm646x-evm.c3
-rw-r--r--arch/arm/mach-davinci/board-mityomapl138.c4
-rw-r--r--drivers/mtd/nand/davinci_nand.c22
-rw-r--r--include/linux/platform_data/mtd-davinci-aemif.h5
8 files changed, 117 insertions, 35 deletions
diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c
index f091a9010c2f..ff8b7e76b6e9 100644
--- a/arch/arm/mach-davinci/aemif.c
+++ b/arch/arm/mach-davinci/aemif.c
@@ -16,6 +16,7 @@
16#include <linux/time.h> 16#include <linux/time.h>
17 17
18#include <linux/platform_data/mtd-davinci-aemif.h> 18#include <linux/platform_data/mtd-davinci-aemif.h>
19#include <linux/platform_data/mtd-davinci.h>
19 20
20/* Timing value configuration */ 21/* Timing value configuration */
21 22
@@ -43,6 +44,17 @@
43 WSTROBE(WSTROBE_MAX) | \ 44 WSTROBE(WSTROBE_MAX) | \
44 WSETUP(WSETUP_MAX)) 45 WSETUP(WSETUP_MAX))
45 46
47static inline unsigned int davinci_aemif_readl(void __iomem *base, int offset)
48{
49 return readl_relaxed(base + offset);
50}
51
52static inline void davinci_aemif_writel(void __iomem *base,
53 int offset, unsigned long value)
54{
55 writel_relaxed(value, base + offset);
56}
57
46/* 58/*
47 * aemif_calc_rate - calculate timing data. 59 * aemif_calc_rate - calculate timing data.
48 * @wanted: The cycle time needed in nanoseconds. 60 * @wanted: The cycle time needed in nanoseconds.
@@ -76,6 +88,7 @@ static int aemif_calc_rate(int wanted, unsigned long clk, int max)
76 * @t: timing values to be progammed 88 * @t: timing values to be progammed
77 * @base: The virtual base address of the AEMIF interface 89 * @base: The virtual base address of the AEMIF interface
78 * @cs: chip-select to program the timing values for 90 * @cs: chip-select to program the timing values for
91 * @clkrate: the AEMIF clkrate
79 * 92 *
80 * This function programs the given timing values (in real clock) into the 93 * This function programs the given timing values (in real clock) into the
81 * AEMIF registers taking the AEMIF clock into account. 94 * AEMIF registers taking the AEMIF clock into account.
@@ -86,24 +99,17 @@ static int aemif_calc_rate(int wanted, unsigned long clk, int max)
86 * 99 *
87 * Returns 0 on success, else negative errno. 100 * Returns 0 on success, else negative errno.
88 */ 101 */
89int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, 102static int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
90 void __iomem *base, unsigned cs) 103 void __iomem *base, unsigned cs,
104 unsigned long clkrate)
91{ 105{
92 unsigned set, val; 106 unsigned set, val;
93 int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup; 107 int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
94 unsigned offset = A1CR_OFFSET + cs * 4; 108 unsigned offset = A1CR_OFFSET + cs * 4;
95 struct clk *aemif_clk;
96 unsigned long clkrate;
97 109
98 if (!t) 110 if (!t)
99 return 0; /* Nothing to do */ 111 return 0; /* Nothing to do */
100 112
101 aemif_clk = clk_get(NULL, "aemif");
102 if (IS_ERR(aemif_clk))
103 return PTR_ERR(aemif_clk);
104
105 clkrate = clk_get_rate(aemif_clk);
106
107 clkrate /= 1000; /* turn clock into kHz for ease of use */ 113 clkrate /= 1000; /* turn clock into kHz for ease of use */
108 114
109 ta = aemif_calc_rate(t->ta, clkrate, TA_MAX); 115 ta = aemif_calc_rate(t->ta, clkrate, TA_MAX);
@@ -130,4 +136,83 @@ int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
130 136
131 return 0; 137 return 0;
132} 138}
133EXPORT_SYMBOL(davinci_aemif_setup_timing); 139
140/**
141 * davinci_aemif_setup - setup AEMIF interface by davinci_nand_pdata
142 * @pdev - link to platform device to setup settings for
143 *
144 * This function does not use any locking while programming the AEMIF
145 * because it is expected that there is only one user of a given
146 * chip-select.
147 *
148 * Returns 0 on success, else negative errno.
149 */
150int davinci_aemif_setup(struct platform_device *pdev)
151{
152 struct davinci_nand_pdata *pdata = dev_get_platdata(&pdev->dev);
153 uint32_t val;
154 unsigned long clkrate;
155 struct resource *res;
156 void __iomem *base;
157 struct clk *clk;
158 int ret = 0;
159
160 clk = clk_get(&pdev->dev, "aemif");
161 if (IS_ERR(clk)) {
162 ret = PTR_ERR(clk);
163 dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
164 return ret;
165 }
166
167 ret = clk_prepare_enable(clk);
168 if (ret < 0) {
169 dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n",
170 ret);
171 goto err_put;
172 }
173
174 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
175 if (!res) {
176 dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
177 ret = -ENOMEM;
178 goto err;
179 }
180
181 base = ioremap(res->start, resource_size(res));
182 if (!base) {
183 dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res);
184 ret = -ENOMEM;
185 goto err;
186 }
187
188 /*
189 * Setup Async configuration register in case we did not boot
190 * from NAND and so bootloader did not bother to set it up.
191 */
192 val = davinci_aemif_readl(base, A1CR_OFFSET + pdev->id * 4);
193 /*
194 * Extended Wait is not valid and Select Strobe mode is not
195 * used
196 */
197 val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
198 if (pdata->options & NAND_BUSWIDTH_16)
199 val |= 0x1;
200
201 davinci_aemif_writel(base, A1CR_OFFSET + pdev->id * 4, val);
202
203 clkrate = clk_get_rate(clk);
204
205 if (pdata->timing)
206 ret = davinci_aemif_setup_timing(pdata->timing, base, pdev->id,
207 clkrate);
208
209 if (ret < 0)
210 dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
211
212 iounmap(base);
213err:
214 clk_disable_unprepare(clk);
215err_put:
216 clk_put(clk);
217 return ret;
218}
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index d1f45af7a530..5623131c4f0b 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)
419 if (ret) 419 if (ret)
420 pr_warning("da830_evm_init: NAND device not registered.\n"); 420 pr_warning("da830_evm_init: NAND device not registered.\n");
421 421
422 if (davinci_aemif_setup(&da830_evm_nand_device))
423 pr_warn("%s: Cannot configure AEMIF.\n", __func__);
424
422 gpio_direction_output(mux_mode, 1); 425 gpio_direction_output(mux_mode, 1);
423} 426}
424#else 427#else
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index e0af0eccde8f..234c5bb091f5 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)
358 358
359 platform_add_devices(da850_evm_devices, 359 platform_add_devices(da850_evm_devices,
360 ARRAY_SIZE(da850_evm_devices)); 360 ARRAY_SIZE(da850_evm_devices));
361
362 if (davinci_aemif_setup(&da850_evm_nandflash_device))
363 pr_warn("%s: Cannot configure AEMIF.\n", __func__);
361 } 364 }
362} 365}
363 366
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 987605b78556..5602957b67d7 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)
778 /* only one device will be jumpered and detected */ 778 /* only one device will be jumpered and detected */
779 if (HAS_NAND) { 779 if (HAS_NAND) {
780 platform_device_register(&davinci_evm_nandflash_device); 780 platform_device_register(&davinci_evm_nandflash_device);
781
782 if (davinci_aemif_setup(&davinci_evm_nandflash_device))
783 pr_warn("%s: Cannot configure AEMIF.\n",
784 __func__);
785
781 evm_leds[7].default_trigger = "nand-disk"; 786 evm_leds[7].default_trigger = "nand-disk";
782 if (HAS_NOR) 787 if (HAS_NOR)
783 pr_warning("WARNING: both NAND and NOR flash " 788 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 13d0801fd6b1..ae129bc49273 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)
805 805
806 platform_device_register(&davinci_nand_device); 806 platform_device_register(&davinci_nand_device);
807 807
808 if (davinci_aemif_setup(&davinci_nand_device))
809 pr_warn("%s: Cannot configure AEMIF.\n", __func__);
810
808 dm646x_init_edma(dm646x_edma_rsv); 811 dm646x_init_edma(dm646x_edma_rsv);
809 812
810 if (HAS_ATA) 813 if (HAS_ATA)
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index 7aa105b1fd0f..96fc00a167f5 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -27,6 +27,7 @@
27#include <mach/cp_intc.h> 27#include <mach/cp_intc.h>
28#include <mach/da8xx.h> 28#include <mach/da8xx.h>
29#include <linux/platform_data/mtd-davinci.h> 29#include <linux/platform_data/mtd-davinci.h>
30#include <linux/platform_data/mtd-davinci-aemif.h>
30#include <mach/mux.h> 31#include <mach/mux.h>
31#include <linux/platform_data/spi-davinci.h> 32#include <linux/platform_data/spi-davinci.h>
32 33
@@ -432,6 +433,9 @@ static void __init mityomapl138_setup_nand(void)
432{ 433{
433 platform_add_devices(mityomapl138_devices, 434 platform_add_devices(mityomapl138_devices,
434 ARRAY_SIZE(mityomapl138_devices)); 435 ARRAY_SIZE(mityomapl138_devices));
436
437 if (davinci_aemif_setup(&mityomapl138_nandflash_device))
438 pr_warn("%s: Cannot configure AEMIF.\n", __func__);
435} 439}
436 440
437static const short mityomap_mii_pins[] = { 441static const short mityomap_mii_pins[] = {
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index a4989ec6292e..8eb6a36f125a 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -746,28 +746,6 @@ static int nand_davinci_probe(struct platform_device *pdev)
746 goto err_clk_enable; 746 goto err_clk_enable;
747 } 747 }
748 748
749 /*
750 * Setup Async configuration register in case we did not boot from
751 * NAND and so bootloader did not bother to set it up.
752 */
753 val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
754
755 /* Extended Wait is not valid and Select Strobe mode is not used */
756 val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
757 if (info->chip.options & NAND_BUSWIDTH_16)
758 val |= 0x1;
759
760 davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
761
762 ret = 0;
763 if (info->timing)
764 ret = davinci_aemif_setup_timing(info->timing, info->base,
765 info->core_chipsel);
766 if (ret < 0) {
767 dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
768 goto err;
769 }
770
771 spin_lock_irq(&davinci_nand_lock); 749 spin_lock_irq(&davinci_nand_lock);
772 750
773 /* put CSxNAND into NAND mode */ 751 /* 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 05b293443097..97948ac2bb9b 100644
--- a/include/linux/platform_data/mtd-davinci-aemif.h
+++ b/include/linux/platform_data/mtd-davinci-aemif.h
@@ -10,6 +10,8 @@
10#ifndef _MACH_DAVINCI_AEMIF_H 10#ifndef _MACH_DAVINCI_AEMIF_H
11#define _MACH_DAVINCI_AEMIF_H 11#define _MACH_DAVINCI_AEMIF_H
12 12
13#include <linux/platform_device.h>
14
13#define NRCSR_OFFSET 0x00 15#define NRCSR_OFFSET 0x00
14#define AWCCR_OFFSET 0x04 16#define AWCCR_OFFSET 0x04
15#define A1CR_OFFSET 0x10 17#define A1CR_OFFSET 0x10
@@ -31,6 +33,5 @@ struct davinci_aemif_timing {
31 u8 ta; 33 u8 ta;
32}; 34};
33 35
34int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, 36int davinci_aemif_setup(struct platform_device *pdev);
35 void __iomem *base, unsigned cs);
36#endif 37#endif