4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2011 Develer S.r.l. (http://www.develer.com/)
33 * \brief NAND driver hardware implementation for SAM3's static memory controller.
35 * \author Stefano Fedrigo <aleph@develer.com>
41 #include <drv/timer.h>
42 #include <cpu/power.h> // cpu_relax()
48 #define NAND_PIN_CE BV(6)
49 #define NAND_PIN_RB BV(2)
50 #define NAND_PINS_PORTA (NAND_PIN_CE | NAND_PIN_RB)
51 #define NAND_PERIPH_PORTA PIO_PERIPH_B
53 #define NAND_PIN_OE BV(19)
54 #define NAND_PIN_WE BV(20)
55 #define NAND_PIN_IO 0x0000FFFF
56 #define NAND_PINS_PORTC (NAND_PIN_OE | NAND_PIN_WE | NAND_PIN_IO)
57 #define NAND_PERIPH_PORTC PIO_PERIPH_A
59 #define NAND_PIN_CLE BV(9)
60 #define NAND_PIN_ALE BV(8)
61 #define NAND_PINS_PORTD (NAND_PIN_CLE | NAND_PIN_ALE)
62 #define NAND_PERIPH_PORTD PIO_PERIPH_A
66 * Wait for edge transition of READY/BUSY NAND
68 * Return true for edge detection, false in case of timeout.
70 bool nand_waitReadyBusy(UNUSED_ARG(Nand *, chip), time_t timeout)
72 time_t start = timer_clock();
74 while (!(SMC_SR & SMC_SR_RB_EDGE0))
77 if (timer_clock() - start > timeout)
79 LOG_INFO("nand: R/B timeout\n");
89 * Wait for transfer to complete until timeout.
90 * If transfer completes return true, false in case of timeout.
92 bool nand_waitTransferComplete(UNUSED_ARG(Nand *, chip), time_t timeout)
94 time_t start = timer_clock();
96 while (!(SMC_SR & SMC_SR_XFRDONE))
99 if (timer_clock() - start > timeout)
101 LOG_INFO("nand: xfer complete timeout\n");
111 * Send command to NAND and wait for completion.
113 void nand_sendCommand(Nand *chip,
114 uint32_t cmd1, uint32_t cmd2,
115 int num_cycles, uint32_t cycle0, uint32_t cycle1234)
120 while (HWREG(NFC_CMD_BASE_ADDR + NFC_CMD_NFCCMD) & 0x8000000);
125 cmd_val = NFC_CMD_NFCCMD
126 | ((chip->chip_select << NFC_CMD_CSID_SHIFT) & NFC_CMD_CSID_MASK)
127 | ((num_cycles << NFC_CMD_ACYCLE_SHIFT) & NFC_CMD_ACYCLE_MASK)
131 // Check for commands transferring data
132 if (cmd1 == NAND_CMD_WRITE_1 || cmd1 == NAND_CMD_READ_1 || cmd1 == NAND_CMD_READID)
133 cmd_val |= NFC_CMD_NFCEN;
135 // Check for commands writing data
136 if (cmd1 == NAND_CMD_WRITE_1)
137 cmd_val |= NFC_CMD_NFCWR;
139 // Check for two command cycles
141 cmd_val |= NFC_CMD_VCMD2;
143 cmd_addr = (reg32_t *)(NFC_CMD_BASE_ADDR + cmd_val);
144 *cmd_addr = cycle1234;
146 while (!(SMC_SR & SMC_SR_CMDDONE));
151 * Get NAND chip status register.
153 * NOTE: this is global between different chip selects, so returns
154 * the status register of the last used NAND chip.
156 uint8_t nand_getChipStatus(UNUSED_ARG(Nand *, chip))
158 return (uint8_t)HWREG(NFC_CMD_BASE_ADDR);
163 * Return pointer to buffer where data are read to or written from
164 * by nand_sendCommand().
166 void *nand_dataBuffer(UNUSED_ARG(Nand *, chip))
168 return (void *)NFC_SRAM_BASE_ADDR;
173 * Extract ECC data from ECC_PRx registers.
175 bool nand_checkEcc(UNUSED_ARG(Nand *, chip))
177 uint32_t sr1 = SMC_ECC_SR1;
180 LOG_INFO("ECC error, ECC_SR1=0x%lx\n", sr1);
189 * Compute ECC on data in a buffer.
191 * \param chip nand context
192 * \param buf buffer containing data
193 * \param size size of data buffer
194 * \param ecc pointer to buffer where computed ECC is stored
195 * \param ecc_size max size for ecc buffer
197 void nand_computeEcc(UNUSED_ARG(Nand *, chip),
198 UNUSED_ARG(const void *, buf), UNUSED_ARG(size_t, size), uint32_t *ecc, size_t ecc_size)
201 for (i = 0; i < ecc_size; i++)
202 ecc[i] = *((reg32_t *)(SMC_BASE + SMC_ECC_PR0_OFF) + i);
207 * Low-level hardware driver initialization.
209 void nand_hwInit(UNUSED_ARG(Nand *, chip))
211 // FIXME: Parameters specific for MT29F8G08AAD
214 pmc_periphEnable(PIOA_ID);
215 pmc_periphEnable(PIOC_ID);
216 pmc_periphEnable(PIOD_ID);
218 PIO_PERIPH_SEL(PIOA_BASE, NAND_PINS_PORTA, NAND_PERIPH_PORTA);
219 PIOA_PDR = NAND_PINS_PORTA;
220 PIOA_PUER = NAND_PINS_PORTA;
222 PIO_PERIPH_SEL(PIOC_BASE, NAND_PINS_PORTC, NAND_PERIPH_PORTC);
223 PIOC_PDR = NAND_PINS_PORTC;
224 PIOC_PUER = NAND_PINS_PORTC;
226 PIO_PERIPH_SEL(PIOD_BASE, NAND_PINS_PORTD, NAND_PERIPH_PORTD);
227 PIOD_PDR = NAND_PINS_PORTD;
228 PIOD_PUER = NAND_PINS_PORTD;
230 pmc_periphEnable(SMC_SDRAMC_ID);
233 SMC_SETUP0 = SMC_SETUP_NWE_SETUP(0)
234 | SMC_SETUP_NCS_WR_SETUP(0)
235 | SMC_SETUP_NRD_SETUP(0)
236 | SMC_SETUP_NCS_RD_SETUP(0);
238 SMC_PULSE0 = SMC_PULSE_NWE_PULSE(2)
239 | SMC_PULSE_NCS_WR_PULSE(3)
240 | SMC_PULSE_NRD_PULSE(2)
241 | SMC_PULSE_NCS_RD_PULSE(3);
243 SMC_CYCLE0 = SMC_CYCLE_NWE_CYCLE(3)
244 | SMC_CYCLE_NRD_CYCLE(3);
246 SMC_TIMINGS0 = SMC_TIMINGS_TCLR(1)
247 | SMC_TIMINGS_TADL(6)
251 | SMC_TIMINGS_RBNSEL(7)
254 SMC_MODE0 = SMC_MODE_READ_MODE
255 | SMC_MODE_WRITE_MODE;
257 SMC_CFG = SMC_CFG_PAGESIZE_PS2048_64
259 | SMC_CFG_DTOMUL_X1048576
260 | SMC_CFG_DTOCYC(0xF)
264 // Disable SMC interrupts, reset and enable NFC controller
267 SMC_CTRL = SMC_CTRL_NFCEN;
269 // Enable ECC, 1 ECC per 256 bytes
270 SMC_ECC_CTRL = SMC_ECC_CTRL_SWRST;
271 SMC_ECC_MD = SMC_ECC_MD_ECC_PAGESIZE_PS2048_64 | SMC_ECC_MD_TYPCORREC_C256B;