4 * \brief Static Memory Controller (SMC) driver for SAM.
\r
6 * Copyright (c) 2011-2013 Atmel Corporation. All rights reserved.
\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
15 * 1. Redistributions of source code must retain the above copyright notice,
\r
16 * this list of conditions and the following disclaimer.
\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
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
25 * 4. This software may only be redistributed and used in connection with an
\r
26 * Atmel microcontroller product.
\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
56 * \defgroup sam_drivers_smc_group Static Memory Controller (SMC)
\r
58 * Driver for the Static Memory Controller. It provides functions for configuring
\r
59 * and using the on-chip SMC.
\r
64 #if ((SAM3S) || (SAM3U) || (SAM3XA) || (SAM4S) || (SAM4E))
\r
65 #define SMC_WPKEY_VALUE (0x534D43)
\r
67 * \brief Configure the SMC Setup timing for the specified Chip Select.
\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
73 void smc_set_setup_timing(Smc *p_smc, uint32_t ul_cs,
\r
74 uint32_t ul_setup_timing)
\r
76 p_smc->SMC_CS_NUMBER[ul_cs].SMC_SETUP = ul_setup_timing;
\r
80 * \brief Configure the SMC pulse timing for the specified Chip Select.
\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
86 void smc_set_pulse_timing(Smc *p_smc, uint32_t ul_cs,
\r
87 uint32_t ul_pulse_timing)
\r
89 p_smc->SMC_CS_NUMBER[ul_cs].SMC_PULSE = ul_pulse_timing;
\r
93 * \brief Configure the SMC cycle timing for the specified Chip Select.
\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
99 void smc_set_cycle_timing(Smc *p_smc, uint32_t ul_cs,
\r
100 uint32_t ul_cycle_timing)
\r
102 p_smc->SMC_CS_NUMBER[ul_cs].SMC_CYCLE = ul_cycle_timing;
\r
106 * \brief Configure the SMC mode for the specified Chip Select.
\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
112 void smc_set_mode(Smc *p_smc, uint32_t ul_cs, uint32_t ul_mode)
\r
114 p_smc->SMC_CS_NUMBER[ul_cs].SMC_MODE = ul_mode;
\r
118 * \brief Get the SMC mode of the specified Chip Select.
\r
120 * \param p_smc Pointer to an SMC instance.
\r
121 * \param ul_cs Chip select number to be set.
\r
123 * \return SMC mode.
\r
125 uint32_t smc_get_mode(Smc *p_smc, uint32_t ul_cs)
\r
127 return p_smc->SMC_CS_NUMBER[ul_cs].SMC_MODE;
\r
131 * \brief Set write protection of SMC registers.
\r
133 * \param p_smc Pointer to an SMC instance.
\r
134 * \param ul_enable 1 to enable, 0 to disable.
\r
136 void smc_enable_writeprotect(Smc *p_smc, uint32_t ul_enable)
\r
138 #if (SAM3S || SAM4S || SAM4E)
\r
141 SMC_WPMR_WPKEY(SMC_WPKEY_VALUE) | SMC_WPMR_WPEN;
\r
143 p_smc->SMC_WPMR = SMC_WPMR_WPKEY(SMC_WPKEY_VALUE);
\r
147 SMC_WPCR_WP_KEY(SMC_WPKEY_VALUE) |
\r
150 p_smc->SMC_WPCR = SMC_WPCR_WP_KEY(SMC_WPKEY_VALUE);
\r
155 * \brief Get the status of SMC write protection register.
\r
157 * \param p_smc Pointer to an SMC instance.
\r
159 * \return Write protect status.
\r
161 uint32_t smc_get_writeprotect_status(Smc *p_smc)
\r
163 return p_smc->SMC_WPSR;
\r
165 #endif /* ((SAM3S) || (SAM3U) || (SAM3XA)) */
\r
167 #if ((SAM3U) || (SAM3XA))
\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
174 void smc_set_nand_timing(Smc *p_smc, uint32_t ul_cs,
\r
175 uint32_t ul_nand_timing)
\r
177 p_smc->SMC_CS_NUMBER[ul_cs].SMC_TIMINGS= ul_nand_timing;
\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
185 void smc_nfc_init(Smc *p_smc, uint32_t ul_config)
\r
187 p_smc->SMC_CFG = ul_config;
\r
191 * \brief Set NFC page size.
\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
196 void smc_nfc_set_page_size(Smc *p_smc, uint32_t ul_page_size)
\r
198 p_smc->SMC_CFG &= (~SMC_CFG_PAGESIZE_Msk);
\r
199 p_smc->SMC_CFG |= ul_page_size;
\r
203 * \brief Enable NFC controller to read both main and spare area in read mode.
\r
205 * \param p_smc Pointer to an SMC instance.
\r
207 void smc_nfc_enable_spare_read(Smc *p_smc)
\r
209 p_smc->SMC_CFG |= SMC_CFG_RSPARE;
\r
213 * \brief Prevent NFC controller from reading the spare area in read mode.
\r
215 * \param p_smc Pointer to an SMC instance.
\r
217 void smc_nfc_disable_spare_read(Smc *p_smc)
\r
219 p_smc->SMC_CFG &= (~SMC_CFG_RSPARE);
\r
223 * \brief Enable NFC controller to write both main and spare area in write mode.
\r
225 * \param p_smc Pointer to an SMC instance.
\r
227 void smc_nfc_enable_spare_write(Smc *p_smc)
\r
229 p_smc->SMC_CFG |= SMC_CFG_WSPARE;
\r
233 * \brief Prevent NFC controller from writing the spare area in read mode.
\r
235 * \param p_smc Pointer to an SMC instance.
\r
237 void smc_nfc_disable_spare_write(Smc *p_smc)
\r
239 p_smc->SMC_CFG &= (~SMC_CFG_WSPARE);
\r
243 * \brief Enable NFC controller.
\r
245 * \param p_smc Pointer to an SMC instance.
\r
247 void smc_nfc_enable(Smc *p_smc)
\r
249 p_smc->SMC_CTRL = SMC_CTRL_NFCEN;
\r
253 * \brief Disable NFC controller.
\r
255 * \param p_smc Pointer to an SMC instance.
\r
257 void smc_nfc_disable(Smc *p_smc)
\r
259 p_smc->SMC_CTRL = SMC_CTRL_NFCDIS;
\r
263 * \brief Get the NFC Status.
\r
265 * \param p_smc Pointer to an SMC instance.
\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
271 uint32_t smc_nfc_get_status(Smc *p_smc)
\r
273 return p_smc->SMC_SR;
\r
277 * \brief Enable SMC interrupts.
\r
279 * \param p_smc Pointer to an SMC instance.
\r
280 * \param ul_sources Interrupt source bitmap.
\r
282 void smc_nfc_enable_interrupt(Smc *p_smc, uint32_t ul_sources)
\r
284 p_smc->SMC_IER = ul_sources;
\r
288 * \brief Disable SMC interrupts.
\r
290 * \param p_smc Pointer to an SMC instance.
\r
291 * \param ul_sources Interrupt source bitmap.
\r
293 void smc_nfc_disable_interrupt(Smc *p_smc, uint32_t ul_sources)
\r
295 p_smc->SMC_IDR = ul_sources;
\r
299 * \brief Get the interrupt mask.
\r
301 * \param p_smc Pointer to an SMC instance.
\r
303 * \return Interrupt mask bitmap.
\r
305 uint32_t smc_nfc_get_interrupt_mask(Smc *p_smc)
\r
307 return p_smc->SMC_IMR;
\r
311 * \brief Set flash cycle 0 address.
\r
313 * \param p_smc Pointer to an SMC instance.
\r
314 * \param uc_address0 Address cycle 0 in 5 address cycles.
\r
316 void smc_nfc_set_address0(Smc *p_smc, uint8_t uc_address0)
\r
318 p_smc->SMC_ADDR = uc_address0;
\r
322 * \brief Set NFC sram bank.
\r
324 * \param p_smc Pointer to an SMC instance.
\r
325 * \param ul_bank NFC sram bank.
\r
327 void smc_nfc_set_bank(Smc *p_smc, uint32_t ul_bank)
\r
329 p_smc->SMC_BANK = SMC_BANK_BANK(ul_bank);
\r
333 * \brief Use the HOST nandflash controller to send a command.
\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
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
343 volatile uint32_t *p_command_address;
\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
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
358 * \brief Initialize ECC mode.
\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
365 void smc_ecc_init(Smc *p_smc, uint32_t ul_type, uint32_t ul_pagesize)
\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
373 * \brief Get ECC status by giving ecc number.
\r
375 * \param p_smc Pointer to an SMC instance.
\r
376 * \param ul_parity_number ECC parity number from 0 to 15.
\r
378 * \return ECC status by giving ECC number.
\r
380 uint32_t smc_ecc_get_status(Smc *p_smc, uint32_t ul_parity_number)
\r
384 if (ul_parity_number < 8) {
\r
385 status = p_smc->SMC_ECC_SR1;
\r
387 status = p_smc->SMC_ECC_SR2;
\r
388 ul_parity_number -= 8;
\r
391 return ((status >> (ul_parity_number * 4)) & ECC_STATUS_MASK);
\r
395 * \brief Get all ECC parity registers value.
\r
397 * \param p_smc Pointer to an SMC instance.
\r
398 * \param p_ecc Pointer to a parity buffer.
\r
400 void smc_ecc_get_value(Smc *p_smc, uint32_t *p_ecc)
\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
419 #endif /* ((SAM3U) || (SAM3XA)) */
\r