nand_sam3.c
Go to the documentation of this file.
00001 00038 #include <drv/nand.h> 00039 #include <cfg/log.h> 00040 #include <io/sam3.h> 00041 #include <drv/timer.h> 00042 #include <cpu/power.h> // cpu_relax() 00043 00044 00045 /* 00046 * PIO definitions. 00047 */ 00048 #define NAND_PIN_CE BV(6) 00049 #define NAND_PIN_RB BV(2) 00050 #define NAND_PINS_PORTA (NAND_PIN_CE | NAND_PIN_RB) 00051 #define NAND_PERIPH_PORTA PIO_PERIPH_B 00052 00053 #define NAND_PIN_OE BV(19) 00054 #define NAND_PIN_WE BV(20) 00055 #define NAND_PIN_IO 0x0000FFFF 00056 #define NAND_PINS_PORTC (NAND_PIN_OE | NAND_PIN_WE | NAND_PIN_IO) 00057 #define NAND_PERIPH_PORTC PIO_PERIPH_A 00058 00059 #define NAND_PIN_CLE BV(9) 00060 #define NAND_PIN_ALE BV(8) 00061 #define NAND_PINS_PORTD (NAND_PIN_CLE | NAND_PIN_ALE) 00062 #define NAND_PERIPH_PORTD PIO_PERIPH_A 00063 00064 00065 /* 00066 * Wait for edge transition of READY/BUSY NAND 00067 * signal. 00068 * Return true for edge detection, false in case of timeout. 00069 */ 00070 bool nand_waitReadyBusy(UNUSED_ARG(Nand *, chip), time_t timeout) 00071 { 00072 time_t start = timer_clock(); 00073 00074 while (!(SMC_SR & SMC_SR_RB_EDGE0)) 00075 { 00076 cpu_relax(); 00077 if (timer_clock() - start > timeout) 00078 { 00079 LOG_INFO("nand: R/B timeout\n"); 00080 return false; 00081 } 00082 } 00083 00084 return true; 00085 } 00086 00087 00088 /* 00089 * Wait for transfer to complete until timeout. 00090 * If transfer completes return true, false in case of timeout. 00091 */ 00092 bool nand_waitTransferComplete(UNUSED_ARG(Nand *, chip), time_t timeout) 00093 { 00094 time_t start = timer_clock(); 00095 00096 while (!(SMC_SR & SMC_SR_XFRDONE)) 00097 { 00098 cpu_relax(); 00099 if (timer_clock() - start > timeout) 00100 { 00101 LOG_INFO("nand: xfer complete timeout\n"); 00102 return false; 00103 } 00104 } 00105 00106 return true; 00107 } 00108 00109 00110 /* 00111 * Send command to NAND and wait for completion. 00112 */ 00113 void nand_sendCommand(Nand *chip, 00114 uint32_t cmd1, uint32_t cmd2, 00115 int num_cycles, uint32_t cycle0, uint32_t cycle1234) 00116 { 00117 reg32_t *cmd_addr; 00118 uint32_t cmd_val; 00119 00120 while (HWREG(NFC_CMD_BASE_ADDR + NFC_CMD_NFCCMD) & 0x8000000); 00121 00122 if (num_cycles == 5) 00123 SMC_ADDR = cycle0; 00124 00125 cmd_val = NFC_CMD_NFCCMD 00126 | ((chip->chip_select << NFC_CMD_CSID_SHIFT) & NFC_CMD_CSID_MASK) 00127 | ((num_cycles << NFC_CMD_ACYCLE_SHIFT) & NFC_CMD_ACYCLE_MASK) 00128 | cmd1 << 2 00129 | cmd2 << 10; 00130 00131 // Check for commands transferring data 00132 if (cmd1 == NAND_CMD_WRITE_1 || cmd1 == NAND_CMD_READ_1 || cmd1 == NAND_CMD_READID) 00133 cmd_val |= NFC_CMD_NFCEN; 00134 00135 // Check for commands writing data 00136 if (cmd1 == NAND_CMD_WRITE_1) 00137 cmd_val |= NFC_CMD_NFCWR; 00138 00139 // Check for two command cycles 00140 if (cmd2) 00141 cmd_val |= NFC_CMD_VCMD2; 00142 00143 cmd_addr = (reg32_t *)(NFC_CMD_BASE_ADDR + cmd_val); 00144 *cmd_addr = cycle1234; 00145 00146 while (!(SMC_SR & SMC_SR_CMDDONE)); 00147 } 00148 00149 00150 /* 00151 * Get NAND chip status register. 00152 * 00153 * NOTE: this is global between different chip selects, so returns 00154 * the status register of the last used NAND chip. 00155 */ 00156 uint8_t nand_getChipStatus(UNUSED_ARG(Nand *, chip)) 00157 { 00158 return (uint8_t)HWREG(NFC_CMD_BASE_ADDR); 00159 } 00160 00161 00162 /* 00163 * Return pointer to buffer where data are read to or written from 00164 * by nand_sendCommand(). 00165 */ 00166 void *nand_dataBuffer(UNUSED_ARG(Nand *, chip)) 00167 { 00168 return (void *)NFC_SRAM_BASE_ADDR; 00169 } 00170 00171 00172 /* 00173 * Extract ECC data from ECC_PRx registers. 00174 */ 00175 bool nand_checkEcc(UNUSED_ARG(Nand *, chip)) 00176 { 00177 uint32_t sr1 = SMC_ECC_SR1; 00178 if (sr1) 00179 { 00180 LOG_INFO("ECC error, ECC_SR1=0x%lx\n", sr1); 00181 return false; 00182 } 00183 else 00184 return true; 00185 } 00186 00187 00188 /* 00189 * Compute ECC on data in a buffer. 00190 * 00191 * \param chip nand context 00192 * \param buf buffer containing data 00193 * \param size size of data buffer 00194 * \param ecc pointer to buffer where computed ECC is stored 00195 * \param ecc_size max size for ecc buffer 00196 */ 00197 void nand_computeEcc(UNUSED_ARG(Nand *, chip), 00198 UNUSED_ARG(const void *, buf), UNUSED_ARG(size_t, size), uint32_t *ecc, size_t ecc_size) 00199 { 00200 size_t i; 00201 for (i = 0; i < ecc_size; i++) 00202 ecc[i] = *((reg32_t *)(SMC_BASE + SMC_ECC_PR0_OFF) + i); 00203 } 00204 00205 00206 /* 00207 * Low-level hardware driver initialization. 00208 */ 00209 void nand_hwInit(UNUSED_ARG(Nand *, chip)) 00210 { 00211 // FIXME: Parameters specific for MT29F8G08AAD 00212 00213 // PIO init 00214 pmc_periphEnable(PIOA_ID); 00215 pmc_periphEnable(PIOC_ID); 00216 pmc_periphEnable(PIOD_ID); 00217 00218 PIO_PERIPH_SEL(PIOA_BASE, NAND_PINS_PORTA, NAND_PERIPH_PORTA); 00219 PIOA_PDR = NAND_PINS_PORTA; 00220 PIOA_PUER = NAND_PINS_PORTA; 00221 00222 PIO_PERIPH_SEL(PIOC_BASE, NAND_PINS_PORTC, NAND_PERIPH_PORTC); 00223 PIOC_PDR = NAND_PINS_PORTC; 00224 PIOC_PUER = NAND_PINS_PORTC; 00225 00226 PIO_PERIPH_SEL(PIOD_BASE, NAND_PINS_PORTD, NAND_PERIPH_PORTD); 00227 PIOD_PDR = NAND_PINS_PORTD; 00228 PIOD_PUER = NAND_PINS_PORTD; 00229 00230 pmc_periphEnable(SMC_SDRAMC_ID); 00231 00232 // SMC init 00233 SMC_SETUP0 = SMC_SETUP_NWE_SETUP(0) 00234 | SMC_SETUP_NCS_WR_SETUP(0) 00235 | SMC_SETUP_NRD_SETUP(0) 00236 | SMC_SETUP_NCS_RD_SETUP(0); 00237 00238 SMC_PULSE0 = SMC_PULSE_NWE_PULSE(2) 00239 | SMC_PULSE_NCS_WR_PULSE(3) 00240 | SMC_PULSE_NRD_PULSE(2) 00241 | SMC_PULSE_NCS_RD_PULSE(3); 00242 00243 SMC_CYCLE0 = SMC_CYCLE_NWE_CYCLE(3) 00244 | SMC_CYCLE_NRD_CYCLE(3); 00245 00246 SMC_TIMINGS0 = SMC_TIMINGS_TCLR(1) 00247 | SMC_TIMINGS_TADL(6) 00248 | SMC_TIMINGS_TAR(4) 00249 | SMC_TIMINGS_TRR(2) 00250 | SMC_TIMINGS_TWB(9) 00251 | SMC_TIMINGS_RBNSEL(7) 00252 | SMC_TIMINGS_NFSEL; 00253 00254 SMC_MODE0 = SMC_MODE_READ_MODE 00255 | SMC_MODE_WRITE_MODE; 00256 00257 SMC_CFG = SMC_CFG_PAGESIZE_PS2048_64 00258 | SMC_CFG_EDGECTRL 00259 | SMC_CFG_DTOMUL_X1048576 00260 | SMC_CFG_DTOCYC(0xF) 00261 | SMC_CFG_WSPARE 00262 | SMC_CFG_RSPARE; 00263 00264 // Disable SMC interrupts, reset and enable NFC controller 00265 SMC_IDR = ~0; 00266 SMC_CTRL = 0; 00267 SMC_CTRL = SMC_CTRL_NFCEN; 00268 00269 // Enable ECC, 1 ECC per 256 bytes 00270 SMC_ECC_CTRL = SMC_ECC_CTRL_SWRST; 00271 SMC_ECC_MD = SMC_ECC_MD_ECC_PAGESIZE_PS2048_64 | SMC_ECC_MD_TYPCORREC_C256B; 00272 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)