Initial sketch of a driver for MT29F serial NAND.
[bertos.git] / bertos / cpu / cortex-m3 / drv / mt29f_sam3.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
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.
10  *
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.
15  *
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
19  *
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.
28  *
29  * Copyright 2011 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \brief Micron MT29F serial NAND driver for SAM3's static memory controller.
34  *
35  * \author Stefano Fedrigo <aleph@develer.com>
36  */
37
38 #include "mt29f_sam3.h"
39 #include "cfg/cfg_mt29f.h"
40
41 // Define log settings for cfg/log.h
42 #define LOG_LEVEL    CONFIG_MT29F_LOG_LEVEL
43 #define LOG_FORMAT   CONFIG_MT29F_LOG_FORMAT
44
45 #include <cfg/log.h>
46 #include <cfg/macros.h>
47
48 #include <io/sam3.h>
49 #include <io/kblock.h>
50
51 #include <drv/timer.h>
52 #include <drv/mt29f.h>
53
54 #include <cpu/power.h> /* cpu_relax() */
55 #include <cpu/types.h>
56
57 #include <string.h> /* memcpy() */
58
59
60 struct Mt29fHardware
61 {
62         int boh;
63 };
64
65
66 static size_t mt29f_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size)
67 {
68 }
69
70
71 static size_t mt29f_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size)
72 {
73 }
74
75
76 static int mt29f_error(struct KBlock *blk)
77 {
78         Mt29f *fls = FLASH_CAST(blk);
79 }
80
81
82 static void mt29f_clearerror(struct KBlock *blk)
83 {
84         Mt29f *fls = FLASH_CAST(blk);
85 }
86
87
88 static const KBlockVTable mt29f_buffered_vt =
89 {
90         .readDirect = mt29f_readDirect,
91         .writeDirect = mt29f_writeDirect,
92
93         .readBuf = kblock_swReadBuf,
94         .writeBuf = kblock_swWriteBuf,
95         .load = kblock_swLoad,
96         .store = kblock_swStore,
97
98         .close = kblock_swClose,
99
100         .error = mt29f_error,
101         .clearerr = mt29f_clearerror,
102 };
103
104
105 static const KBlockVTable mt29f_unbuffered_vt =
106 {
107         .readDirect = mt29f_readDirect,
108         .writeDirect = mt29f_writeDirect,
109
110         .close = kblock_swClose,
111
112         .error = mt29f_error,
113         .clearerr = mt29f_clearerror,
114 };
115
116
117 static struct Mt29fHardware mt29f_hw;
118 static uint8_t kblock_buf[MT29F_PAGE_SIZE];
119
120
121 static void common_init(Mt29f *fls)
122 {
123         memset(fls, 0, sizeof(*fls));
124         DB(fls->blk.priv.type = KBT_MT29F);
125
126         fls->hw = &mt29f_hw;
127
128         fls->blk.blk_size = MT29F_PAGE_SIZE;
129         fls->blk.blk_cnt =  MT29F_SIZE / MT29F_PAGE_SIZE;
130
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);
135
136         PIO_PERIPH_SEL(PIOA_BASE, MT29F_PINS_PORTA, MT29F_PERIPH_PORTA);
137         PIOA_PDR = MT29F_PINS_PORTA;
138         PIOA_PUER = MT29F_PINS_PORTA;
139
140         PIO_PERIPH_SEL(PIOC_BASE, MT29F_PINS_PORTC, MT29F_PERIPH_PORTC);
141         PIOC_PDR = MT29F_PINS_PORTC;
142         PIOC_PUER = MT29F_PINS_PORTC;
143
144         PIO_PERIPH_SEL(PIOD_BASE, MT29F_PINS_PORTD, MT29F_PERIPH_PORTD);
145         PIOD_PDR = MT29F_PINS_PORTD;
146         PIOD_PUER = MT29F_PINS_PORTD;
147
148     pmc_periphEnable(SMC_SDRAMC_ID);
149
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);
154
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);
159
160     SMC_CYCLE0 = SMC_CYCLE_NWE_CYCLE(3)
161                 | SMC_CYCLE_NRD_CYCLE(3);
162
163     SMC_TIMINGS0 = SMC_TIMINGS_TCLR(1)
164                 | SMC_TIMINGS_TADL(6)
165                 | SMC_TIMINGS_TAR(4)
166                 | SMC_TIMINGS_TRR(2)
167                 | SMC_TIMINGS_TWB(9)
168                 | SMC_TIMINGS_RBNSEL(7)
169                 | SMC_TIMINGS_NFSEL;
170
171     SMC_MODE0 = SMC_MODE_READ_MODE
172                 | SMC_MODE_WRITE_MODE;
173
174
175 }
176
177
178 void mt29f_hw_init(Mt29f *fls, int flags)
179 {
180         common_init(fls);
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;
184
185         // Load the first block in the cache
186         void *start = 0x0;
187         memcpy(fls->blk.priv.buf, start, fls->blk.blk_size);
188 }
189
190
191 void mt29f_hw_initUnbuffered(Mt29f *fls, int flags)
192 {
193         common_init(fls);
194         fls->blk.priv.vt = &mt29f_unbuffered_vt;
195 }
196