]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M4F_ATSAM4E_Atmel_Studio/src/ASF/sam/drivers/ebi/smc/smc.c
Update copyright date ready for tagging V10.1.0.
[freertos] / FreeRTOS / Demo / CORTEX_M4F_ATSAM4E_Atmel_Studio / src / ASF / sam / drivers / ebi / smc / smc.c
1 /**\r
2  * \file\r
3  *\r
4  * \brief Static Memory Controller (SMC) driver for SAM.\r
5  *\r
6  * Copyright (c) 2011-2013 Atmel Corporation. All rights reserved.\r
7  *\r
8  * \asf_license_start\r
9  *\r
10  * \page License\r
11  *\r
12  * Redistribution and use in source and binary forms, with or without\r
13  * modification, are permitted provided that the following conditions are met:\r
14  *\r
15  * 1. Redistributions of source code must retain the above copyright notice,\r
16  *    this list of conditions and the following disclaimer.\r
17  *\r
18  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
19  *    this list of conditions and the following disclaimer in the documentation\r
20  *    and/or other materials provided with the distribution.\r
21  *\r
22  * 3. The name of Atmel may not be used to endorse or promote products derived\r
23  *    from this software without specific prior written permission.\r
24  *\r
25  * 4. This software may only be redistributed and used in connection with an\r
26  *    Atmel microcontroller product.\r
27  *\r
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
38  * POSSIBILITY OF SUCH DAMAGE.\r
39  *\r
40  * \asf_license_stop\r
41  *\r
42  */\r
43 \r
44 #include "smc.h"\r
45 #include "board.h"\r
46 \r
47 /// @cond 0\r
48 /**INDENT-OFF**/\r
49 #ifdef __cplusplus\r
50 extern "C" {\r
51 #endif\r
52 /**INDENT-ON**/\r
53 /// @endcond\r
54 \r
55 /**\r
56  * \defgroup sam_drivers_smc_group Static Memory Controller (SMC)\r
57  *\r
58  * Driver for the Static Memory Controller. It provides functions for configuring\r
59  * and using the on-chip SMC.\r
60  *\r
61  * @{\r
62  */\r
63 \r
64 #if ((SAM3S) || (SAM3U) || (SAM3XA) || (SAM4S) || (SAM4E))\r
65 #define SMC_WPKEY_VALUE (0x534D43)\r
66 /**\r
67  * \brief Configure the SMC Setup timing for the specified Chip Select.\r
68  *\r
69  * \param p_smc Pointer to an SMC instance.\r
70  * \param ul_cs Chip Select number to be set.\r
71  * \param ul_setup_timing Setup timing for NWE, NCS, NRD.\r
72  */\r
73 void smc_set_setup_timing(Smc *p_smc, uint32_t ul_cs,\r
74                 uint32_t ul_setup_timing)\r
75 {\r
76         p_smc->SMC_CS_NUMBER[ul_cs].SMC_SETUP = ul_setup_timing;\r
77 }\r
78 \r
79 /**\r
80  * \brief Configure the SMC pulse timing for the specified Chip Select.\r
81  *\r
82  * \param p_smc Pointer to an SMC instance.\r
83  * \param ul_cs Chip Select number to be set.\r
84  * \param ul_pulse_timing Pulse timing for NWE,NCS,NRD.\r
85  */\r
86 void smc_set_pulse_timing(Smc *p_smc, uint32_t ul_cs,\r
87                 uint32_t ul_pulse_timing)\r
88 {\r
89         p_smc->SMC_CS_NUMBER[ul_cs].SMC_PULSE = ul_pulse_timing;\r
90 }\r
91 \r
92 /**\r
93  * \brief Configure the SMC cycle timing for the specified Chip Select.\r
94  *\r
95  * \param p_smc Pointer to an SMC instance.\r
96  * \param ul_cs Chip Select number to be set.\r
97  * \param ul_cycle_timing Cycle timing for NWE and NRD.\r
98  */\r
99 void smc_set_cycle_timing(Smc *p_smc, uint32_t ul_cs,\r
100                 uint32_t ul_cycle_timing)\r
101 {\r
102         p_smc->SMC_CS_NUMBER[ul_cs].SMC_CYCLE = ul_cycle_timing;\r
103 }\r
104 \r
105 /**\r
106  * \brief Configure the SMC mode for the specified Chip Select.\r
107  *\r
108  * \param p_smc Pointer to an SMC instance.\r
109  * \param ul_cs Chip select number to be set.\r
110  * \param ul_mode SMC mode.\r
111  */\r
112 void smc_set_mode(Smc *p_smc, uint32_t ul_cs, uint32_t ul_mode)\r
113 {\r
114         p_smc->SMC_CS_NUMBER[ul_cs].SMC_MODE = ul_mode;\r
115 }\r
116 \r
117 /**\r
118  * \brief Get the SMC mode of the specified Chip Select.\r
119  *\r
120  * \param p_smc Pointer to an SMC instance.\r
121  * \param ul_cs Chip select number to be set.\r
122  *\r
123  * \return SMC mode.\r
124  */\r
125 uint32_t smc_get_mode(Smc *p_smc, uint32_t ul_cs)\r
126 {\r
127         return p_smc->SMC_CS_NUMBER[ul_cs].SMC_MODE;\r
128 }\r
129 \r
130 /**\r
131  * \brief Set write protection of SMC registers.\r
132  *\r
133  * \param p_smc Pointer to an SMC instance.\r
134  * \param ul_enable 1 to enable, 0 to disable.\r
135  */\r
136 void smc_enable_writeprotect(Smc *p_smc, uint32_t ul_enable)\r
137 {\r
138 #if (SAM3S || SAM4S || SAM4E)\r
139         if (ul_enable)\r
140                 p_smc->SMC_WPMR =\r
141                                 SMC_WPMR_WPKEY(SMC_WPKEY_VALUE) | SMC_WPMR_WPEN;\r
142         else\r
143                 p_smc->SMC_WPMR = SMC_WPMR_WPKEY(SMC_WPKEY_VALUE);\r
144 #else\r
145         if (ul_enable)\r
146                 p_smc->SMC_WPCR =\r
147                                 SMC_WPCR_WP_KEY(SMC_WPKEY_VALUE) |\r
148                                 SMC_WPCR_WP_EN;\r
149         else\r
150                 p_smc->SMC_WPCR = SMC_WPCR_WP_KEY(SMC_WPKEY_VALUE);\r
151 #endif\r
152 }\r
153 \r
154 /**\r
155  * \brief Get the status of SMC write protection register.\r
156  *\r
157  * \param p_smc Pointer to an SMC instance.\r
158  *\r
159  * \return Write protect status.\r
160  */\r
161 uint32_t smc_get_writeprotect_status(Smc *p_smc)\r
162 {\r
163         return p_smc->SMC_WPSR;\r
164 }\r
165 #endif /* ((SAM3S) || (SAM3U) || (SAM3XA)) */\r
166 \r
167 #if ((SAM3U) || (SAM3XA))\r
168 /**\r
169  * \brief Configure the SMC nand timing for the specified Chip Select.\r
170  * \param p_smc Pointer to an SMC instance.\r
171  * \param ul_cs Chip Select number to be set.\r
172  * \param ul_nand_timing nand timing for related signal.\r
173  */\r
174 void smc_set_nand_timing(Smc *p_smc, uint32_t ul_cs,\r
175                 uint32_t ul_nand_timing)\r
176 {\r
177         p_smc->SMC_CS_NUMBER[ul_cs].SMC_TIMINGS= ul_nand_timing;\r
178 }\r
179 \r
180 /**\r
181  * \brief Initialize NFC configuration.\r
182  * \param p_smc Pointer to an SMC instance.\r
183  * \param ul_config SMC NFC Configuration.\r
184  */\r
185 void smc_nfc_init(Smc *p_smc, uint32_t ul_config)\r
186 {\r
187         p_smc->SMC_CFG = ul_config;\r
188 }\r
189 \r
190 /**\r
191  * \brief Set NFC page size.\r
192  *\r
193  * \param p_smc Pointer to an SMC instance.\r
194  * \param ul_page_size Use pattern defined in the device header file.\r
195  */\r
196 void smc_nfc_set_page_size(Smc *p_smc, uint32_t ul_page_size)\r
197 {\r
198         p_smc->SMC_CFG &= (~SMC_CFG_PAGESIZE_Msk);\r
199         p_smc->SMC_CFG |= ul_page_size;\r
200 }\r
201 \r
202 /**\r
203  * \brief Enable NFC controller to read both main and spare area in read mode.\r
204  *\r
205  * \param p_smc Pointer to an SMC instance.\r
206  */\r
207 void smc_nfc_enable_spare_read(Smc *p_smc)\r
208 {\r
209         p_smc->SMC_CFG |= SMC_CFG_RSPARE;\r
210 }\r
211 \r
212 /**\r
213  * \brief Prevent NFC controller from reading the spare area in read mode.\r
214  *\r
215  * \param p_smc Pointer to an SMC instance.\r
216  */\r
217 void smc_nfc_disable_spare_read(Smc *p_smc)\r
218 {\r
219         p_smc->SMC_CFG &= (~SMC_CFG_RSPARE);\r
220 }\r
221 \r
222 /**\r
223  * \brief Enable NFC controller to write both main and spare area in write mode.\r
224  *\r
225  * \param p_smc Pointer to an SMC instance.\r
226  */\r
227 void smc_nfc_enable_spare_write(Smc *p_smc)\r
228 {\r
229         p_smc->SMC_CFG |= SMC_CFG_WSPARE;\r
230 }\r
231 \r
232 /**\r
233  * \brief Prevent NFC controller from writing the spare area in read mode.\r
234  *\r
235  * \param p_smc Pointer to an SMC instance.\r
236  */\r
237 void smc_nfc_disable_spare_write(Smc *p_smc)\r
238 {\r
239         p_smc->SMC_CFG &= (~SMC_CFG_WSPARE);\r
240 }\r
241 \r
242 /**\r
243  * \brief Enable NFC controller.\r
244  *\r
245  * \param p_smc Pointer to an SMC instance.\r
246  */\r
247 void smc_nfc_enable(Smc *p_smc)\r
248 {\r
249         p_smc->SMC_CTRL = SMC_CTRL_NFCEN;\r
250 }\r
251 \r
252 /**\r
253  * \brief Disable NFC controller.\r
254  *\r
255  * \param p_smc Pointer to an SMC instance.\r
256  */\r
257 void smc_nfc_disable(Smc *p_smc)\r
258 {\r
259         p_smc->SMC_CTRL = SMC_CTRL_NFCDIS;\r
260 }\r
261 \r
262 /**\r
263  * \brief Get the NFC Status.\r
264  *\r
265  * \param p_smc Pointer to an SMC instance.\r
266  *\r
267  * \return Returns the current status register of SMC NFC Status Register.\r
268  * This resets the internal value of the status register, so further\r
269  * read may yield different values.\r
270  */\r
271 uint32_t smc_nfc_get_status(Smc *p_smc)\r
272 {\r
273         return p_smc->SMC_SR;\r
274 }\r
275 \r
276 /**\r
277  * \brief Enable SMC interrupts.\r
278  *\r
279  * \param p_smc Pointer to an SMC instance.\r
280  * \param ul_sources Interrupt source bitmap.\r
281  */\r
282 void smc_nfc_enable_interrupt(Smc *p_smc, uint32_t ul_sources)\r
283 {\r
284         p_smc->SMC_IER = ul_sources;\r
285 }\r
286 \r
287 /**\r
288  * \brief Disable SMC interrupts.\r
289  *\r
290  * \param p_smc Pointer to an SMC instance.\r
291  * \param ul_sources Interrupt source bitmap.\r
292  */\r
293 void smc_nfc_disable_interrupt(Smc *p_smc, uint32_t ul_sources)\r
294 {\r
295         p_smc->SMC_IDR = ul_sources;\r
296 }\r
297 \r
298 /**\r
299  * \brief Get the interrupt mask.\r
300  *\r
301  * \param p_smc Pointer to an SMC instance.\r
302  *\r
303  * \return Interrupt mask bitmap.\r
304  */\r
305 uint32_t smc_nfc_get_interrupt_mask(Smc *p_smc)\r
306 {\r
307         return p_smc->SMC_IMR;\r
308 }\r
309 \r
310 /**\r
311  * \brief Set flash cycle 0 address.\r
312  *\r
313  * \param p_smc Pointer to an SMC instance.\r
314  * \param uc_address0 Address cycle 0 in 5 address cycles.\r
315  */\r
316 void smc_nfc_set_address0(Smc *p_smc, uint8_t uc_address0)\r
317 {\r
318         p_smc->SMC_ADDR = uc_address0;\r
319 }\r
320 \r
321 /**\r
322  * \brief Set NFC sram bank.\r
323  *\r
324  * \param p_smc Pointer to an SMC instance.\r
325  * \param ul_bank NFC sram bank.\r
326  */\r
327 void smc_nfc_set_bank(Smc *p_smc, uint32_t ul_bank)\r
328 {\r
329         p_smc->SMC_BANK = SMC_BANK_BANK(ul_bank);\r
330 }\r
331 \r
332 /**\r
333  * \brief Use the HOST nandflash controller to send a command.\r
334  *\r
335  * \param p_smc Pointer to an SMC instance.\r
336  * \param ul_cmd Command to send.\r
337  * \param ul_address_cycle Address cycle when command access is decoded.\r
338  * \param ul_cycle0 Address at first cycle.\r
339  */\r
340 void smc_nfc_send_command(Smc *p_smc, uint32_t ul_cmd,\r
341                 uint32_t ul_address_cycle, uint32_t ul_cycle0)\r
342 {\r
343         volatile uint32_t *p_command_address;\r
344 \r
345         /* Wait until host controller is not busy. */\r
346         while (((*((volatile uint32_t *)(BOARD_NF_DATA_ADDR + NFCADDR_CMD_NFCCMD)))\r
347                         & NFC_BUSY_FLAG) == NFC_BUSY_FLAG) {\r
348         }\r
349         /* Send the command plus the ADDR_CYCLE. */\r
350         p_command_address = (volatile uint32_t *)(ul_cmd + BOARD_NF_DATA_ADDR);\r
351         p_smc->SMC_ADDR = ul_cycle0;\r
352         *p_command_address = ul_address_cycle;\r
353         while (!((p_smc->SMC_SR & SMC_SR_CMDDONE) == SMC_SR_CMDDONE)) {\r
354         }\r
355 }\r
356 \r
357 /**\r
358  * \brief Initialize ECC mode.\r
359  *\r
360  * \param p_smc Pointer to an SMC instance.\r
361  * \param ul_type Type of correction, use pattern defined in the device header file.\r
362  * \param ul_pagesize Page size of NAND Flash device, use pattern defined in\r
363  * the device header file.\r
364  */\r
365 void smc_ecc_init(Smc *p_smc, uint32_t ul_type, uint32_t ul_pagesize)\r
366 {\r
367         /* Software Reset ECC. */\r
368         p_smc->SMC_ECC_CTRL = SMC_ECC_CTRL_SWRST;\r
369         p_smc->SMC_ECC_MD = ul_type | ul_pagesize;\r
370 }\r
371 \r
372 /**\r
373  * \brief Get ECC status by giving ecc number.\r
374  *\r
375  * \param p_smc Pointer to an SMC instance.\r
376  * \param ul_parity_number ECC parity number from 0 to 15.\r
377  *\r
378  * \return ECC status by giving ECC number.\r
379  */\r
380 uint32_t smc_ecc_get_status(Smc *p_smc, uint32_t ul_parity_number)\r
381 {\r
382         uint32_t status;\r
383 \r
384         if (ul_parity_number < 8) {\r
385                 status = p_smc->SMC_ECC_SR1;\r
386         } else {\r
387                 status = p_smc->SMC_ECC_SR2;\r
388                 ul_parity_number -= 8;\r
389         }\r
390 \r
391         return ((status >> (ul_parity_number * 4)) & ECC_STATUS_MASK);\r
392 }\r
393 \r
394 /**\r
395  * \brief Get all ECC parity registers value.\r
396  *\r
397  * \param p_smc Pointer to an SMC instance.\r
398  * \param p_ecc Pointer to a parity buffer.\r
399  */\r
400 void smc_ecc_get_value(Smc *p_smc, uint32_t *p_ecc)\r
401 {\r
402         p_ecc[0] = p_smc->SMC_ECC_PR0;\r
403         p_ecc[1] = p_smc->SMC_ECC_PR1;\r
404         p_ecc[2] = p_smc->SMC_ECC_PR2;\r
405         p_ecc[3] = p_smc->SMC_ECC_PR3;\r
406         p_ecc[4] = p_smc->SMC_ECC_PR4;\r
407         p_ecc[5] = p_smc->SMC_ECC_PR5;\r
408         p_ecc[6] = p_smc->SMC_ECC_PR6;\r
409         p_ecc[7] = p_smc->SMC_ECC_PR7;\r
410         p_ecc[8] = p_smc->SMC_ECC_PR8;\r
411         p_ecc[9] = p_smc->SMC_ECC_PR9;\r
412         p_ecc[10] = p_smc->SMC_ECC_PR10;\r
413         p_ecc[11] = p_smc->SMC_ECC_PR11;\r
414         p_ecc[12] = p_smc->SMC_ECC_PR12;\r
415         p_ecc[13] = p_smc->SMC_ECC_PR13;\r
416         p_ecc[14] = p_smc->SMC_ECC_PR14;\r
417         p_ecc[15] = p_smc->SMC_ECC_PR15;\r
418 }\r
419 #endif /* ((SAM3U) || (SAM3XA)) */\r
420 \r
421 //@}\r
422 \r
423 /// @cond 0\r
424 /**INDENT-OFF**/\r
425 #ifdef __cplusplus\r
426 }\r
427 #endif\r
428 /**INDENT-ON**/\r
429 /// @endcond\r