diff options
author | Arnd Bergmann <arnd@arndb.de> | 2014-02-25 11:42:59 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2014-02-25 11:43:20 -0500 |
commit | 8c4a57bcd80532c4fef5f87d0c53be25718294ed (patch) | |
tree | 56e21b6d7201bac111162d0888aa4334051255d8 | |
parent | b5feaefb45e878a6a4900925e5bdae9b73257616 (diff) | |
parent | 67f5185cad24b3c3d9ab07508dfcab55cdab02de (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.c | 107 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-da830-evm.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-da850-evm.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-dm644x-evm.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-dm646x-evm.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-mityomapl138.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/davinci_nand.c | 22 | ||||
-rw-r--r-- | include/linux/platform_data/mtd-davinci-aemif.h | 5 |
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 | ||
47 | static inline unsigned int davinci_aemif_readl(void __iomem *base, int offset) | ||
48 | { | ||
49 | return readl_relaxed(base + offset); | ||
50 | } | ||
51 | |||
52 | static 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 | */ |
89 | int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, | 102 | static 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 | } |
133 | EXPORT_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 | */ | ||
150 | int 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); | ||
213 | err: | ||
214 | clk_disable_unprepare(clk); | ||
215 | err_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 | ||
437 | static const short mityomap_mii_pins[] = { | 441 | static 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 | ||
34 | int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, | 36 | int davinci_aemif_setup(struct platform_device *pdev); |
35 | void __iomem *base, unsigned cs); | ||
36 | #endif | 37 | #endif |