1313#include <linux/err.h>
1414#include <linux/io.h>
1515#include <linux/kernel.h>
16+ #include <linux/memory/ti-aemif.h>
1617#include <linux/module.h>
18+ #include <linux/mutex.h>
1719#include <linux/of.h>
1820#include <linux/of_platform.h>
1921#include <linux/platform_device.h>
6971#define ACR_SSTROBE_MASK BIT(31)
7072#define ASIZE_16BIT 1
7173
72- #define CONFIG_MASK (TA(TA_MAX) | \
73- RHOLD(RHOLD_MAX) | \
74- RSTROBE(RSTROBE_MAX) | \
75- RSETUP(RSETUP_MAX) | \
76- WHOLD(WHOLD_MAX) | \
77- WSTROBE(WSTROBE_MAX) | \
78- WSETUP(WSETUP_MAX) | \
79- EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | \
80- ASIZE_MAX)
74+ #define TIMINGS_MASK (TA(TA_MAX) | \
75+ RHOLD(RHOLD_MAX) | \
76+ RSTROBE(RSTROBE_MAX) | \
77+ RSETUP(RSETUP_MAX) | \
78+ WHOLD(WHOLD_MAX) | \
79+ WSTROBE(WSTROBE_MAX) | \
80+ WSETUP(WSETUP_MAX))
81+
82+ #define CONFIG_MASK (EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | ASIZE_MAX)
8183
8284/**
83- * struct aemif_cs_data: structure to hold cs parameters
85+ * struct aemif_cs_data: structure to hold CS parameters
86+ * @timings: timings configuration
8487 * @cs: chip-select number
85- * @wstrobe: write strobe width, ns
86- * @rstrobe: read strobe width, ns
87- * @wsetup: write setup width, ns
88- * @whold: write hold width, ns
89- * @rsetup: read setup width, ns
90- * @rhold: read hold width, ns
91- * @ta: minimum turn around time, ns
9288 * @enable_ss: enable/disable select strobe mode
9389 * @enable_ew: enable/disable extended wait mode
9490 * @asize: width of the asynchronous device's data bus
9591 */
9692struct aemif_cs_data {
93+ struct aemif_cs_timings timings ;
9794 u8 cs ;
98- u16 wstrobe ;
99- u16 rstrobe ;
100- u8 wsetup ;
101- u8 whold ;
102- u8 rsetup ;
103- u8 rhold ;
104- u8 ta ;
10595 u8 enable_ss ;
10696 u8 enable_ew ;
10797 u8 asize ;
@@ -115,6 +105,7 @@ struct aemif_cs_data {
115105 * @num_cs: number of assigned chip-selects
116106 * @cs_offset: start number of cs nodes
117107 * @cs_data: array of chip-select settings
108+ * @config_cs_lock: lock used to access CS configuration
118109 */
119110struct aemif_device {
120111 void __iomem * base ;
@@ -123,20 +114,94 @@ struct aemif_device {
123114 u8 num_cs ;
124115 int cs_offset ;
125116 struct aemif_cs_data cs_data [NUM_CS ];
117+ struct mutex config_cs_lock ;
126118};
127119
120+ /**
121+ * aemif_check_cs_timings() - Check the validity of a CS timing configuration.
122+ * @timings: timings configuration
123+ *
124+ * @return: 0 if the timing configuration is valid, negative error number otherwise.
125+ */
126+ int aemif_check_cs_timings (struct aemif_cs_timings * timings )
127+ {
128+ if (timings -> ta > TA_MAX )
129+ return - EINVAL ;
130+
131+ if (timings -> rhold > RHOLD_MAX )
132+ return - EINVAL ;
133+
134+ if (timings -> rstrobe > RSTROBE_MAX )
135+ return - EINVAL ;
136+
137+ if (timings -> rsetup > RSETUP_MAX )
138+ return - EINVAL ;
139+
140+ if (timings -> whold > WHOLD_MAX )
141+ return - EINVAL ;
142+
143+ if (timings -> wstrobe > WSTROBE_MAX )
144+ return - EINVAL ;
145+
146+ if (timings -> wsetup > WSETUP_MAX )
147+ return - EINVAL ;
148+
149+ return 0 ;
150+ }
151+ EXPORT_SYMBOL_GPL (aemif_check_cs_timings );
152+
153+ /**
154+ * aemif_set_cs_timings() - Set the timing configuration of a given chip select.
155+ * @aemif: aemif device to configure
156+ * @cs: index of the chip select to configure
157+ * @timings: timings configuration to set
158+ *
159+ * @return: 0 on success, else negative errno.
160+ */
161+ int aemif_set_cs_timings (struct aemif_device * aemif , u8 cs ,
162+ struct aemif_cs_timings * timings )
163+ {
164+ unsigned int offset ;
165+ u32 val , set ;
166+ int ret ;
167+
168+ if (!timings || !aemif )
169+ return - EINVAL ;
170+
171+ if (cs > aemif -> num_cs )
172+ return - EINVAL ;
173+
174+ ret = aemif_check_cs_timings (timings );
175+ if (ret )
176+ return ret ;
177+
178+ set = TA (timings -> ta ) | RHOLD (timings -> rhold ) | RSTROBE (timings -> rstrobe ) |
179+ RSETUP (timings -> rsetup ) | WHOLD (timings -> whold ) |
180+ WSTROBE (timings -> wstrobe ) | WSETUP (timings -> wsetup );
181+
182+ offset = A1CR_OFFSET + cs * 4 ;
183+
184+ mutex_lock (& aemif -> config_cs_lock );
185+ val = readl (aemif -> base + offset );
186+ val &= ~TIMINGS_MASK ;
187+ val |= set ;
188+ writel (val , aemif -> base + offset );
189+ mutex_unlock (& aemif -> config_cs_lock );
190+
191+ return 0 ;
192+ }
193+ EXPORT_SYMBOL_GPL (aemif_set_cs_timings );
194+
128195/**
129196 * aemif_calc_rate - calculate timing data.
130197 * @pdev: platform device to calculate for
131198 * @wanted: The cycle time needed in nanoseconds.
132199 * @clk: The input clock rate in kHz.
133- * @max: The maximum divider value that can be programmed.
134200 *
135- * On success, returns the calculated timing value minus 1 for easy
136- * programming into AEMIF timing registers, else negative errno .
201+ * @return: the calculated timing value minus 1 for easy
202+ * programming into AEMIF timing registers.
137203 */
138- static int aemif_calc_rate (struct platform_device * pdev , int wanted ,
139- unsigned long clk , int max )
204+ static u32 aemif_calc_rate (struct platform_device * pdev , int wanted , unsigned long clk )
140205{
141206 int result ;
142207
@@ -149,10 +214,6 @@ static int aemif_calc_rate(struct platform_device *pdev, int wanted,
149214 if (result < 0 )
150215 result = 0 ;
151216
152- /* ... But configuring tighter timings is not an option. */
153- else if (result > max )
154- result = - EINVAL ;
155-
156217 return result ;
157218}
158219
@@ -174,48 +235,25 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum)
174235{
175236 struct aemif_device * aemif = platform_get_drvdata (pdev );
176237 struct aemif_cs_data * data = & aemif -> cs_data [csnum ];
177- int ta , rhold , rstrobe , rsetup , whold , wstrobe , wsetup ;
178- unsigned long clk_rate = aemif -> clk_rate ;
179238 unsigned offset ;
180239 u32 set , val ;
181240
182241 offset = A1CR_OFFSET + (data -> cs - aemif -> cs_offset ) * 4 ;
183242
184- ta = aemif_calc_rate (pdev , data -> ta , clk_rate , TA_MAX );
185- rhold = aemif_calc_rate (pdev , data -> rhold , clk_rate , RHOLD_MAX );
186- rstrobe = aemif_calc_rate (pdev , data -> rstrobe , clk_rate , RSTROBE_MAX );
187- rsetup = aemif_calc_rate (pdev , data -> rsetup , clk_rate , RSETUP_MAX );
188- whold = aemif_calc_rate (pdev , data -> whold , clk_rate , WHOLD_MAX );
189- wstrobe = aemif_calc_rate (pdev , data -> wstrobe , clk_rate , WSTROBE_MAX );
190- wsetup = aemif_calc_rate (pdev , data -> wsetup , clk_rate , WSETUP_MAX );
191-
192- if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 ||
193- whold < 0 || wstrobe < 0 || wsetup < 0 ) {
194- dev_err (& pdev -> dev , "%s: cannot get suitable timings\n" ,
195- __func__ );
196- return - EINVAL ;
197- }
198-
199- set = TA (ta ) | RHOLD (rhold ) | RSTROBE (rstrobe ) | RSETUP (rsetup ) |
200- WHOLD (whold ) | WSTROBE (wstrobe ) | WSETUP (wsetup );
201-
202- set |= (data -> asize & ACR_ASIZE_MASK );
243+ set = (data -> asize & ACR_ASIZE_MASK );
203244 if (data -> enable_ew )
204245 set |= ACR_EW_MASK ;
205246 if (data -> enable_ss )
206247 set |= ACR_SSTROBE_MASK ;
207248
249+ mutex_lock (& aemif -> config_cs_lock );
208250 val = readl (aemif -> base + offset );
209251 val &= ~CONFIG_MASK ;
210252 val |= set ;
211253 writel (val , aemif -> base + offset );
254+ mutex_unlock (& aemif -> config_cs_lock );
212255
213- return 0 ;
214- }
215-
216- static inline int aemif_cycles_to_nsec (int val , unsigned long clk_rate )
217- {
218- return ((val + 1 ) * NSEC_PER_MSEC ) / clk_rate ;
256+ return aemif_set_cs_timings (aemif , data -> cs - aemif -> cs_offset , & data -> timings );
219257}
220258
221259/**
@@ -231,19 +269,18 @@ static void aemif_get_hw_params(struct platform_device *pdev, int csnum)
231269{
232270 struct aemif_device * aemif = platform_get_drvdata (pdev );
233271 struct aemif_cs_data * data = & aemif -> cs_data [csnum ];
234- unsigned long clk_rate = aemif -> clk_rate ;
235272 u32 val , offset ;
236273
237274 offset = A1CR_OFFSET + (data -> cs - aemif -> cs_offset ) * 4 ;
238275 val = readl (aemif -> base + offset );
239276
240- data -> ta = aemif_cycles_to_nsec ( TA_VAL (val ), clk_rate );
241- data -> rhold = aemif_cycles_to_nsec ( RHOLD_VAL (val ), clk_rate );
242- data -> rstrobe = aemif_cycles_to_nsec ( RSTROBE_VAL (val ), clk_rate );
243- data -> rsetup = aemif_cycles_to_nsec ( RSETUP_VAL (val ), clk_rate );
244- data -> whold = aemif_cycles_to_nsec ( WHOLD_VAL (val ), clk_rate );
245- data -> wstrobe = aemif_cycles_to_nsec ( WSTROBE_VAL (val ), clk_rate );
246- data -> wsetup = aemif_cycles_to_nsec ( WSETUP_VAL (val ), clk_rate );
277+ data -> timings . ta = TA_VAL (val );
278+ data -> timings . rhold = RHOLD_VAL (val );
279+ data -> timings . rstrobe = RSTROBE_VAL (val );
280+ data -> timings . rsetup = RSETUP_VAL (val );
281+ data -> timings . whold = WHOLD_VAL (val );
282+ data -> timings . wstrobe = WSTROBE_VAL (val );
283+ data -> timings . wsetup = WSETUP_VAL (val );
247284 data -> enable_ew = EW_VAL (val );
248285 data -> enable_ss = SSTROBE_VAL (val );
249286 data -> asize = val & ASIZE_MAX ;
@@ -261,6 +298,7 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev,
261298 struct device_node * np )
262299{
263300 struct aemif_device * aemif = platform_get_drvdata (pdev );
301+ unsigned long clk_rate = aemif -> clk_rate ;
264302 struct aemif_cs_data * data ;
265303 u32 cs ;
266304 u32 val ;
@@ -288,32 +326,33 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev,
288326
289327 /* override the values from device node */
290328 if (!of_property_read_u32 (np , "ti,cs-min-turnaround-ns" , & val ))
291- data -> ta = val ;
329+ data -> timings . ta = aemif_calc_rate ( pdev , val , clk_rate ) ;
292330
293331 if (!of_property_read_u32 (np , "ti,cs-read-hold-ns" , & val ))
294- data -> rhold = val ;
332+ data -> timings . rhold = aemif_calc_rate ( pdev , val , clk_rate ) ;
295333
296334 if (!of_property_read_u32 (np , "ti,cs-read-strobe-ns" , & val ))
297- data -> rstrobe = val ;
335+ data -> timings . rstrobe = aemif_calc_rate ( pdev , val , clk_rate ) ;
298336
299337 if (!of_property_read_u32 (np , "ti,cs-read-setup-ns" , & val ))
300- data -> rsetup = val ;
338+ data -> timings . rsetup = aemif_calc_rate ( pdev , val , clk_rate ) ;
301339
302340 if (!of_property_read_u32 (np , "ti,cs-write-hold-ns" , & val ))
303- data -> whold = val ;
341+ data -> timings . whold = aemif_calc_rate ( pdev , val , clk_rate ) ;
304342
305343 if (!of_property_read_u32 (np , "ti,cs-write-strobe-ns" , & val ))
306- data -> wstrobe = val ;
344+ data -> timings . wstrobe = aemif_calc_rate ( pdev , val , clk_rate ) ;
307345
308346 if (!of_property_read_u32 (np , "ti,cs-write-setup-ns" , & val ))
309- data -> wsetup = val ;
347+ data -> timings . wsetup = aemif_calc_rate ( pdev , val , clk_rate ) ;
310348
311349 if (!of_property_read_u32 (np , "ti,cs-bus-width" , & val ))
312350 if (val == 16 )
313351 data -> asize = 1 ;
314352 data -> enable_ew = of_property_read_bool (np , "ti,cs-extended-wait-mode" );
315353 data -> enable_ss = of_property_read_bool (np , "ti,cs-select-strobe-mode" );
316- return 0 ;
354+
355+ return aemif_check_cs_timings (& data -> timings );
317356}
318357
319358static const struct of_device_id aemif_of_match [] = {
@@ -351,6 +390,7 @@ static int aemif_probe(struct platform_device *pdev)
351390 if (IS_ERR (aemif -> base ))
352391 return PTR_ERR (aemif -> base );
353392
393+ mutex_init (& aemif -> config_cs_lock );
354394 if (np ) {
355395 /*
356396 * For every controller device node, there is a cs device node
0 commit comments