2 * AEMIF support for DaVinci SoCs
4 * Copyright (C) 2010 Texas Instruments Incorporated. http://www.ti.com/
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/kernel.h>
13 #include <linux/err.h>
14 #include <linux/clk.h>
15 #include <linux/module.h>
16 #include <linux/time.h>
18 #include <linux/platform_data/mtd-davinci-aemif.h>
19 #include <linux/platform_data/mtd-davinci.h>
21 /* Timing value configuration */
23 #define TA(x) ((x) << 2)
24 #define RHOLD(x) ((x) << 4)
25 #define RSTROBE(x) ((x) << 7)
26 #define RSETUP(x) ((x) << 13)
27 #define WHOLD(x) ((x) << 17)
28 #define WSTROBE(x) ((x) << 20)
29 #define WSETUP(x) ((x) << 26)
33 #define RSTROBE_MAX 0x3f
34 #define RSETUP_MAX 0xf
36 #define WSTROBE_MAX 0x3f
37 #define WSETUP_MAX 0xf
39 #define TIMING_MASK (TA(TA_MAX) | \
41 RSTROBE(RSTROBE_MAX) | \
42 RSETUP(RSETUP_MAX) | \
44 WSTROBE(WSTROBE_MAX) | \
47 static inline unsigned int davinci_aemif_readl(void __iomem
*base
, int offset
)
49 return readl_relaxed(base
+ offset
);
52 static inline void davinci_aemif_writel(void __iomem
*base
,
53 int offset
, unsigned long value
)
55 writel_relaxed(value
, base
+ offset
);
59 * aemif_calc_rate - calculate timing data.
60 * @wanted: The cycle time needed in nanoseconds.
61 * @clk: The input clock rate in kHz.
62 * @max: The maximum divider value that can be programmed.
64 * On success, returns the calculated timing value minus 1 for easy
65 * programming into AEMIF timing registers, else negative errno.
67 static int aemif_calc_rate(int wanted
, unsigned long clk
, int max
)
71 result
= DIV_ROUND_UP((wanted
* clk
), NSEC_PER_MSEC
) - 1;
73 pr_debug("%s: result %d from %ld, %d\n", __func__
, result
, clk
, wanted
);
75 /* It is generally OK to have a more relaxed timing than requested... */
79 /* ... But configuring tighter timings is not an option. */
80 else if (result
> max
)
87 * davinci_aemif_setup_timing - setup timing values for a given AEMIF interface
88 * @t: timing values to be progammed
89 * @base: The virtual base address of the AEMIF interface
90 * @cs: chip-select to program the timing values for
91 * @clkrate: the AEMIF clkrate
93 * This function programs the given timing values (in real clock) into the
94 * AEMIF registers taking the AEMIF clock into account.
96 * This function does not use any locking while programming the AEMIF
97 * because it is expected that there is only one user of a given
100 * Returns 0 on success, else negative errno.
102 static int davinci_aemif_setup_timing(struct davinci_aemif_timing
*t
,
103 void __iomem
*base
, unsigned cs
,
104 unsigned long clkrate
)
107 int ta
, rhold
, rstrobe
, rsetup
, whold
, wstrobe
, wsetup
;
108 unsigned offset
= A1CR_OFFSET
+ cs
* 4;
111 return 0; /* Nothing to do */
113 clkrate
/= 1000; /* turn clock into kHz for ease of use */
115 ta
= aemif_calc_rate(t
->ta
, clkrate
, TA_MAX
);
116 rhold
= aemif_calc_rate(t
->rhold
, clkrate
, RHOLD_MAX
);
117 rstrobe
= aemif_calc_rate(t
->rstrobe
, clkrate
, RSTROBE_MAX
);
118 rsetup
= aemif_calc_rate(t
->rsetup
, clkrate
, RSETUP_MAX
);
119 whold
= aemif_calc_rate(t
->whold
, clkrate
, WHOLD_MAX
);
120 wstrobe
= aemif_calc_rate(t
->wstrobe
, clkrate
, WSTROBE_MAX
);
121 wsetup
= aemif_calc_rate(t
->wsetup
, clkrate
, WSETUP_MAX
);
123 if (ta
< 0 || rhold
< 0 || rstrobe
< 0 || rsetup
< 0 ||
124 whold
< 0 || wstrobe
< 0 || wsetup
< 0) {
125 pr_err("%s: cannot get suitable timings\n", __func__
);
129 set
= TA(ta
) | RHOLD(rhold
) | RSTROBE(rstrobe
) | RSETUP(rsetup
) |
130 WHOLD(whold
) | WSTROBE(wstrobe
) | WSETUP(wsetup
);
132 val
= __raw_readl(base
+ offset
);
135 __raw_writel(val
, base
+ offset
);
141 * davinci_aemif_setup - setup AEMIF interface by davinci_nand_pdata
142 * @pdev - link to platform device to setup settings for
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
148 * Returns 0 on success, else negative errno.
150 int davinci_aemif_setup(struct platform_device
*pdev
)
152 struct davinci_nand_pdata
*pdata
= dev_get_platdata(&pdev
->dev
);
154 unsigned long clkrate
;
155 struct resource
*res
;
160 clk
= clk_get(&pdev
->dev
, "aemif");
163 dev_dbg(&pdev
->dev
, "unable to get AEMIF clock, err %d\n", ret
);
167 ret
= clk_prepare_enable(clk
);
169 dev_dbg(&pdev
->dev
, "unable to enable AEMIF clock, err %d\n",
174 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 1);
176 dev_err(&pdev
->dev
, "cannot get IORESOURCE_MEM\n");
181 base
= ioremap(res
->start
, resource_size(res
));
183 dev_err(&pdev
->dev
, "ioremap failed for resource %pR\n", res
);
189 * Setup Async configuration register in case we did not boot
190 * from NAND and so bootloader did not bother to set it up.
192 val
= davinci_aemif_readl(base
, A1CR_OFFSET
+ pdev
->id
* 4);
194 * Extended Wait is not valid and Select Strobe mode is not
197 val
&= ~(ACR_ASIZE_MASK
| ACR_EW_MASK
| ACR_SS_MASK
);
198 if (pdata
->options
& NAND_BUSWIDTH_16
)
201 davinci_aemif_writel(base
, A1CR_OFFSET
+ pdev
->id
* 4, val
);
203 clkrate
= clk_get_rate(clk
);
206 ret
= davinci_aemif_setup_timing(pdata
->timing
, base
, pdev
->id
,
210 dev_dbg(&pdev
->dev
, "NAND timing values setup fail\n");
214 clk_disable_unprepare(clk
);