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 Micron MT29F serial NAND driver for SAM3's static memory controller.
35 * \author Stefano Fedrigo <aleph@develer.com>
38 #include "mt29f_sam3.h"
39 #include "cfg/cfg_mt29f.h"
41 // Define log settings for cfg/log.h
42 #define LOG_LEVEL CONFIG_MT29F_LOG_LEVEL
43 #define LOG_FORMAT CONFIG_MT29F_LOG_FORMAT
46 #include <cfg/macros.h>
49 #include <io/kblock.h>
51 #include <drv/timer.h>
52 #include <drv/mt29f.h>
54 #include <cpu/power.h> /* cpu_relax() */
55 #include <cpu/types.h>
57 #include <string.h> /* memcpy() */
66 static size_t mt29f_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size)
71 static size_t mt29f_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size)
76 static int mt29f_error(struct KBlock *blk)
78 Mt29f *fls = FLASH_CAST(blk);
82 static void mt29f_clearerror(struct KBlock *blk)
84 Mt29f *fls = FLASH_CAST(blk);
88 static const KBlockVTable mt29f_buffered_vt =
90 .readDirect = mt29f_readDirect,
91 .writeDirect = mt29f_writeDirect,
93 .readBuf = kblock_swReadBuf,
94 .writeBuf = kblock_swWriteBuf,
95 .load = kblock_swLoad,
96 .store = kblock_swStore,
98 .close = kblock_swClose,
100 .error = mt29f_error,
101 .clearerr = mt29f_clearerror,
105 static const KBlockVTable mt29f_unbuffered_vt =
107 .readDirect = mt29f_readDirect,
108 .writeDirect = mt29f_writeDirect,
110 .close = kblock_swClose,
112 .error = mt29f_error,
113 .clearerr = mt29f_clearerror,
117 static struct Mt29fHardware mt29f_hw;
118 static uint8_t kblock_buf[MT29F_PAGE_SIZE];
121 static void common_init(Mt29f *fls)
123 memset(fls, 0, sizeof(*fls));
124 DB(fls->blk.priv.type = KBT_MT29F);
128 fls->blk.blk_size = MT29F_PAGE_SIZE;
129 fls->blk.blk_cnt = MT29F_SIZE / MT29F_PAGE_SIZE;
131 // TODO: put following stuff in hw_ file dependent (and configurable cs?)
132 pmc_periphEnable(PIOA_ID);
133 pmc_periphEnable(PIOC_ID);
134 pmc_periphEnable(PIOD_ID);
136 PIO_PERIPH_SEL(PIOA_BASE, MT29F_PINS_PORTA, MT29F_PERIPH_PORTA);
137 PIOA_PDR = MT29F_PINS_PORTA;
138 PIOA_PUER = MT29F_PINS_PORTA;
140 PIO_PERIPH_SEL(PIOC_BASE, MT29F_PINS_PORTC, MT29F_PERIPH_PORTC);
141 PIOC_PDR = MT29F_PINS_PORTC;
142 PIOC_PUER = MT29F_PINS_PORTC;
144 PIO_PERIPH_SEL(PIOD_BASE, MT29F_PINS_PORTD, MT29F_PERIPH_PORTD);
145 PIOD_PDR = MT29F_PINS_PORTD;
146 PIOD_PUER = MT29F_PINS_PORTD;
148 pmc_periphEnable(SMC_SDRAMC_ID);
150 SMC_SETUP0 = SMC_SETUP_NWE_SETUP(0)
151 | SMC_SETUP_NCS_WR_SETUP(0)
152 | SMC_SETUP_NRD_SETUP(0)
153 | SMC_SETUP_NCS_RD_SETUP(0);
155 SMC_PULSE0 = SMC_PULSE_NWE_PULSE(2)
156 | SMC_PULSE_NCS_WR_PULSE(3)
157 | SMC_PULSE_NRD_PULSE(2)
158 | SMC_PULSE_NCS_RD_PULSE(3);
160 SMC_CYCLE0 = SMC_CYCLE_NWE_CYCLE(3)
161 | SMC_CYCLE_NRD_CYCLE(3);
163 SMC_TIMINGS0 = SMC_TIMINGS_TCLR(1)
164 | SMC_TIMINGS_TADL(6)
168 | SMC_TIMINGS_RBNSEL(7)
171 SMC_MODE0 = SMC_MODE_READ_MODE
172 | SMC_MODE_WRITE_MODE;
178 void mt29f_hw_init(Mt29f *fls, int flags)
181 fls->blk.priv.vt = &mt29f_buffered_vt;
182 fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE;
183 fls->blk.priv.buf = kblock_buf;
185 // Load the first block in the cache
187 memcpy(fls->blk.priv.buf, start, fls->blk.blk_size);
191 void mt29f_hw_initUnbuffered(Mt29f *fls, int flags)
194 fls->blk.priv.vt = &mt29f_unbuffered_vt;