]>
Commit | Line | Data |
---|---|---|
dcbfd2e5 PP |
1 | /* Driver for ATMEL DataFlash support |
2 | * Author : Hamid Ikdoumi (Atmel) | |
3 | * | |
1a459660 | 4 | * SPDX-License-Identifier: GPL-2.0+ |
dcbfd2e5 PP |
5 | */ |
6 | ||
7 | #include <config.h> | |
8 | #include <common.h> | |
dcbfd2e5 PP |
9 | #include <dataflash.h> |
10 | ||
e54b9701 PP |
11 | /* |
12 | * spi.c API | |
13 | */ | |
6e4bf9b2 PP |
14 | extern unsigned int AT91F_SpiWrite(AT91PS_DataflashDesc pDesc); |
15 | extern void AT91F_SpiEnable(int cs); | |
dcbfd2e5 PP |
16 | |
17 | #define AT91C_TIMEOUT_WRDY 200000 | |
18 | ||
dcbfd2e5 PP |
19 | /*----------------------------------------------------------------------*/ |
20 | /* \fn AT91F_DataFlashSendCommand */ | |
21 | /* \brief Generic function to send a command to the dataflash */ | |
f01dbb54 | 22 | /*----------------------------------------------------------------------*/ |
6e4bf9b2 PP |
23 | AT91S_DataFlashStatus AT91F_DataFlashSendCommand(AT91PS_DataFlash pDataFlash, |
24 | unsigned char OpCode, | |
25 | unsigned int CmdSize, | |
26 | unsigned int DataflashAddress) | |
dcbfd2e5 PP |
27 | { |
28 | unsigned int adr; | |
29 | ||
6e4bf9b2 | 30 | if ((pDataFlash->pDataFlashDesc->state) != IDLE) |
dcbfd2e5 PP |
31 | return DATAFLASH_BUSY; |
32 | ||
33 | /* process the address to obtain page address and byte address */ | |
f01dbb54 | 34 | adr = ((DataflashAddress / (pDataFlash->pDevice->pages_size)) << |
de74b9ee | 35 | pDataFlash->pDevice->page_offset) + |
bd86220f | 36 | (DataflashAddress % (pDataFlash->pDevice->pages_size)); |
dcbfd2e5 | 37 | |
bd86220f | 38 | /* fill the command buffer */ |
dcbfd2e5 PP |
39 | pDataFlash->pDataFlashDesc->command[0] = OpCode; |
40 | if (pDataFlash->pDevice->pages_number >= 16384) { | |
f01dbb54 | 41 | pDataFlash->pDataFlashDesc->command[1] = |
bd86220f | 42 | (unsigned char)((adr & 0x0F000000) >> 24); |
f01dbb54 | 43 | pDataFlash->pDataFlashDesc->command[2] = |
bd86220f | 44 | (unsigned char)((adr & 0x00FF0000) >> 16); |
f01dbb54 | 45 | pDataFlash->pDataFlashDesc->command[3] = |
bd86220f | 46 | (unsigned char)((adr & 0x0000FF00) >> 8); |
f01dbb54 | 47 | pDataFlash->pDataFlashDesc->command[4] = |
bd86220f | 48 | (unsigned char)(adr & 0x000000FF); |
dcbfd2e5 | 49 | } else { |
f01dbb54 | 50 | pDataFlash->pDataFlashDesc->command[1] = |
bd86220f | 51 | (unsigned char)((adr & 0x00FF0000) >> 16); |
f01dbb54 | 52 | pDataFlash->pDataFlashDesc->command[2] = |
bd86220f | 53 | (unsigned char)((adr & 0x0000FF00) >> 8); |
f01dbb54 | 54 | pDataFlash->pDataFlashDesc->command[3] = |
bd86220f | 55 | (unsigned char)(adr & 0x000000FF); |
dcbfd2e5 PP |
56 | pDataFlash->pDataFlashDesc->command[4] = 0; |
57 | } | |
58 | pDataFlash->pDataFlashDesc->command[5] = 0; | |
59 | pDataFlash->pDataFlashDesc->command[6] = 0; | |
60 | pDataFlash->pDataFlashDesc->command[7] = 0; | |
61 | ||
62 | /* Initialize the SpiData structure for the spi write fuction */ | |
6e4bf9b2 | 63 | pDataFlash->pDataFlashDesc->tx_cmd_pt = |
bd86220f | 64 | pDataFlash->pDataFlashDesc->command; |
6e4bf9b2 PP |
65 | pDataFlash->pDataFlashDesc->tx_cmd_size = CmdSize; |
66 | pDataFlash->pDataFlashDesc->rx_cmd_pt = | |
bd86220f | 67 | pDataFlash->pDataFlashDesc->command; |
6e4bf9b2 | 68 | pDataFlash->pDataFlashDesc->rx_cmd_size = CmdSize; |
dcbfd2e5 PP |
69 | |
70 | /* send the command and read the data */ | |
6e4bf9b2 PP |
71 | return AT91F_SpiWrite(pDataFlash->pDataFlashDesc); |
72 | } | |
dcbfd2e5 PP |
73 | |
74 | /*----------------------------------------------------------------------*/ | |
75 | /* \fn AT91F_DataFlashGetStatus */ | |
76 | /* \brief Read the status register of the dataflash */ | |
f01dbb54 WD |
77 | /*----------------------------------------------------------------------*/ |
78 | AT91S_DataFlashStatus AT91F_DataFlashGetStatus(AT91PS_DataflashDesc pDesc) | |
dcbfd2e5 PP |
79 | { |
80 | AT91S_DataFlashStatus status; | |
81 | ||
82 | /* if a transfert is in progress ==> return 0 */ | |
6e4bf9b2 | 83 | if ((pDesc->state) != IDLE) |
dcbfd2e5 PP |
84 | return DATAFLASH_BUSY; |
85 | ||
86 | /* first send the read status command (D7H) */ | |
87 | pDesc->command[0] = DB_STATUS; | |
88 | pDesc->command[1] = 0; | |
89 | ||
6e4bf9b2 PP |
90 | pDesc->DataFlash_state = GET_STATUS; |
91 | pDesc->tx_data_size = 0; /* Transmit the command */ | |
92 | /* and receive response */ | |
93 | pDesc->tx_cmd_pt = pDesc->command; | |
94 | pDesc->rx_cmd_pt = pDesc->command; | |
95 | pDesc->rx_cmd_size = 2; | |
96 | pDesc->tx_cmd_size = 2; | |
97 | status = AT91F_SpiWrite(pDesc); | |
dcbfd2e5 | 98 | |
6e4bf9b2 | 99 | pDesc->DataFlash_state = *((unsigned char *)(pDesc->rx_cmd_pt) + 1); |
dcbfd2e5 PP |
100 | |
101 | return status; | |
102 | } | |
103 | ||
dcbfd2e5 PP |
104 | /*----------------------------------------------------------------------*/ |
105 | /* \fn AT91F_DataFlashWaitReady */ | |
106 | /* \brief wait for dataflash ready (bit7 of the status register == 1) */ | |
f01dbb54 WD |
107 | /*----------------------------------------------------------------------*/ |
108 | AT91S_DataFlashStatus AT91F_DataFlashWaitReady(AT91PS_DataflashDesc | |
bd86220f PP |
109 | pDataFlashDesc, |
110 | unsigned int timeout) | |
dcbfd2e5 PP |
111 | { |
112 | pDataFlashDesc->DataFlash_state = IDLE; | |
113 | ||
114 | do { | |
115 | AT91F_DataFlashGetStatus(pDataFlashDesc); | |
116 | timeout--; | |
6e4bf9b2 PP |
117 | } while (((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) && |
118 | (timeout > 0)); | |
dcbfd2e5 | 119 | |
6e4bf9b2 | 120 | if ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) |
dcbfd2e5 PP |
121 | return DATAFLASH_ERROR; |
122 | ||
123 | return DATAFLASH_OK; | |
124 | } | |
125 | ||
dcbfd2e5 | 126 | /*--------------------------------------------------------------------------*/ |
53677ef1 WD |
127 | /* Function Name : AT91F_DataFlashContinuousRead */ |
128 | /* Object : Continuous stream Read */ | |
dcbfd2e5 PP |
129 | /* Input Parameters : DataFlash Service */ |
130 | /* : <src> = dataflash address */ | |
131 | /* : <*dataBuffer> = data buffer pointer */ | |
132 | /* : <sizeToRead> = data buffer size */ | |
133 | /* Return value : State of the dataflash */ | |
f01dbb54 | 134 | /*--------------------------------------------------------------------------*/ |
bd86220f PP |
135 | AT91S_DataFlashStatus AT91F_DataFlashContinuousRead( |
136 | AT91PS_DataFlash pDataFlash, | |
137 | int src, | |
138 | unsigned char *dataBuffer, | |
139 | int sizeToRead) | |
dcbfd2e5 PP |
140 | { |
141 | AT91S_DataFlashStatus status; | |
142 | /* Test the size to read in the device */ | |
6e4bf9b2 | 143 | if ((src + sizeToRead) > |
bd86220f PP |
144 | (pDataFlash->pDevice->pages_size * |
145 | (pDataFlash->pDevice->pages_number))) | |
dcbfd2e5 PP |
146 | return DATAFLASH_MEMORY_OVERFLOW; |
147 | ||
148 | pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer; | |
149 | pDataFlash->pDataFlashDesc->rx_data_size = sizeToRead; | |
150 | pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer; | |
151 | pDataFlash->pDataFlashDesc->tx_data_size = sizeToRead; | |
152 | ||
bd86220f PP |
153 | status = AT91F_DataFlashSendCommand( |
154 | pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src); | |
dcbfd2e5 | 155 | /* Send the command to the dataflash */ |
6e4bf9b2 | 156 | return (status); |
dcbfd2e5 PP |
157 | } |
158 | ||
dcbfd2e5 PP |
159 | /*---------------------------------------------------------------------------*/ |
160 | /* Function Name : AT91F_DataFlashPagePgmBuf */ | |
161 | /* Object : Main memory page program thru buffer 1 or buffer 2 */ | |
162 | /* Input Parameters : DataFlash Service */ | |
163 | /* : <*src> = Source buffer */ | |
164 | /* : <dest> = dataflash destination address */ | |
165 | /* : <SizeToWrite> = data buffer size */ | |
166 | /* Return value : State of the dataflash */ | |
f01dbb54 | 167 | /*---------------------------------------------------------------------------*/ |
6e4bf9b2 PP |
168 | AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(AT91PS_DataFlash pDataFlash, |
169 | unsigned char *src, | |
170 | unsigned int dest, | |
171 | unsigned int SizeToWrite) | |
dcbfd2e5 PP |
172 | { |
173 | int cmdsize; | |
174 | pDataFlash->pDataFlashDesc->tx_data_pt = src; | |
175 | pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite; | |
176 | pDataFlash->pDataFlashDesc->rx_data_pt = src; | |
177 | pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite; | |
178 | ||
179 | cmdsize = 4; | |
180 | /* Send the command to the dataflash */ | |
181 | if (pDataFlash->pDevice->pages_number >= 16384) | |
182 | cmdsize = 5; | |
bd86220f PP |
183 | return (AT91F_DataFlashSendCommand( |
184 | pDataFlash, DB_PAGE_PGM_BUF1, cmdsize, dest)); | |
6e4bf9b2 | 185 | } |
dcbfd2e5 PP |
186 | |
187 | /*---------------------------------------------------------------------------*/ | |
188 | /* Function Name : AT91F_MainMemoryToBufferTransfert */ | |
189 | /* Object : Read a page in the SRAM Buffer 1 or 2 */ | |
190 | /* Input Parameters : DataFlash Service */ | |
191 | /* : Page concerned */ | |
53677ef1 | 192 | /* : */ |
dcbfd2e5 | 193 | /* Return value : State of the dataflash */ |
f01dbb54 | 194 | /*---------------------------------------------------------------------------*/ |
bd86220f PP |
195 | AT91S_DataFlashStatus AT91F_MainMemoryToBufferTransfert( |
196 | AT91PS_DataFlash | |
197 | pDataFlash, | |
198 | unsigned char | |
199 | BufferCommand, | |
200 | unsigned int page) | |
dcbfd2e5 PP |
201 | { |
202 | int cmdsize; | |
203 | /* Test if the buffer command is legal */ | |
de74b9ee WD |
204 | if ((BufferCommand != DB_PAGE_2_BUF1_TRF) && |
205 | (BufferCommand != DB_PAGE_2_BUF2_TRF)) { | |
dcbfd2e5 | 206 | return DATAFLASH_BAD_COMMAND; |
de74b9ee | 207 | } |
dcbfd2e5 PP |
208 | |
209 | /* no data to transmit or receive */ | |
210 | pDataFlash->pDataFlashDesc->tx_data_size = 0; | |
211 | cmdsize = 4; | |
212 | if (pDataFlash->pDevice->pages_number >= 16384) | |
213 | cmdsize = 5; | |
bd86220f PP |
214 | return (AT91F_DataFlashSendCommand( |
215 | pDataFlash, BufferCommand, cmdsize, | |
216 | page * pDataFlash->pDevice->pages_size)); | |
dcbfd2e5 PP |
217 | } |
218 | ||
dcbfd2e5 PP |
219 | /*-------------------------------------------------------------------------- */ |
220 | /* Function Name : AT91F_DataFlashWriteBuffer */ | |
221 | /* Object : Write data to the internal sram buffer 1 or 2 */ | |
222 | /* Input Parameters : DataFlash Service */ | |
223 | /* : <BufferCommand> = command to write buffer1 or 2 */ | |
224 | /* : <*dataBuffer> = data buffer to write */ | |
225 | /* : <bufferAddress> = address in the internal buffer */ | |
226 | /* : <SizeToWrite> = data buffer size */ | |
227 | /* Return value : State of the dataflash */ | |
228 | /*---------------------------------------------------------------------------*/ | |
bd86220f PP |
229 | AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer( |
230 | AT91PS_DataFlash pDataFlash, | |
231 | unsigned char BufferCommand, | |
232 | unsigned char *dataBuffer, | |
233 | unsigned int bufferAddress, | |
234 | int SizeToWrite) | |
dcbfd2e5 PP |
235 | { |
236 | int cmdsize; | |
237 | /* Test if the buffer command is legal */ | |
de74b9ee WD |
238 | if ((BufferCommand != DB_BUF1_WRITE) && |
239 | (BufferCommand != DB_BUF2_WRITE)) { | |
dcbfd2e5 | 240 | return DATAFLASH_BAD_COMMAND; |
de74b9ee | 241 | } |
dcbfd2e5 PP |
242 | |
243 | /* buffer address must be lower than page size */ | |
244 | if (bufferAddress > pDataFlash->pDevice->pages_size) | |
245 | return DATAFLASH_BAD_ADDRESS; | |
246 | ||
6e4bf9b2 | 247 | if ((pDataFlash->pDataFlashDesc->state) != IDLE) |
dcbfd2e5 PP |
248 | return DATAFLASH_BUSY; |
249 | ||
250 | /* Send first Write Command */ | |
251 | pDataFlash->pDataFlashDesc->command[0] = BufferCommand; | |
252 | pDataFlash->pDataFlashDesc->command[1] = 0; | |
253 | if (pDataFlash->pDevice->pages_number >= 16384) { | |
6e4bf9b2 PP |
254 | pDataFlash->pDataFlashDesc->command[2] = 0; |
255 | pDataFlash->pDataFlashDesc->command[3] = | |
bd86220f PP |
256 | (unsigned char)(((unsigned int)(bufferAddress & |
257 | pDataFlash->pDevice-> | |
258 | byte_mask)) >> 8); | |
6e4bf9b2 | 259 | pDataFlash->pDataFlashDesc->command[4] = |
bd86220f | 260 | (unsigned char)((unsigned int)bufferAddress & 0x00FF); |
dcbfd2e5 PP |
261 | cmdsize = 5; |
262 | } else { | |
6e4bf9b2 | 263 | pDataFlash->pDataFlashDesc->command[2] = |
bd86220f PP |
264 | (unsigned char)(((unsigned int)(bufferAddress & |
265 | pDataFlash->pDevice-> | |
266 | byte_mask)) >> 8); | |
6e4bf9b2 | 267 | pDataFlash->pDataFlashDesc->command[3] = |
bd86220f | 268 | (unsigned char)((unsigned int)bufferAddress & 0x00FF); |
6e4bf9b2 | 269 | pDataFlash->pDataFlashDesc->command[4] = 0; |
dcbfd2e5 PP |
270 | cmdsize = 4; |
271 | } | |
272 | ||
6e4bf9b2 | 273 | pDataFlash->pDataFlashDesc->tx_cmd_pt = |
bd86220f | 274 | pDataFlash->pDataFlashDesc->command; |
dcbfd2e5 | 275 | pDataFlash->pDataFlashDesc->tx_cmd_size = cmdsize; |
6e4bf9b2 | 276 | pDataFlash->pDataFlashDesc->rx_cmd_pt = |
bd86220f | 277 | pDataFlash->pDataFlashDesc->command; |
dcbfd2e5 PP |
278 | pDataFlash->pDataFlashDesc->rx_cmd_size = cmdsize; |
279 | ||
6e4bf9b2 PP |
280 | pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer; |
281 | pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer; | |
282 | pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite; | |
283 | pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite; | |
dcbfd2e5 PP |
284 | |
285 | return AT91F_SpiWrite(pDataFlash->pDataFlashDesc); | |
286 | } | |
287 | ||
288 | /*---------------------------------------------------------------------------*/ | |
289 | /* Function Name : AT91F_PageErase */ | |
53677ef1 | 290 | /* Object : Erase a page */ |
dcbfd2e5 PP |
291 | /* Input Parameters : DataFlash Service */ |
292 | /* : Page concerned */ | |
53677ef1 | 293 | /* : */ |
dcbfd2e5 PP |
294 | /* Return value : State of the dataflash */ |
295 | /*---------------------------------------------------------------------------*/ | |
bd86220f PP |
296 | AT91S_DataFlashStatus AT91F_PageErase( |
297 | AT91PS_DataFlash pDataFlash, | |
298 | unsigned int page) | |
dcbfd2e5 PP |
299 | { |
300 | int cmdsize; | |
301 | /* Test if the buffer command is legal */ | |
302 | /* no data to transmit or receive */ | |
6e4bf9b2 | 303 | pDataFlash->pDataFlashDesc->tx_data_size = 0; |
dcbfd2e5 PP |
304 | |
305 | cmdsize = 4; | |
306 | if (pDataFlash->pDevice->pages_number >= 16384) | |
307 | cmdsize = 5; | |
de74b9ee | 308 | return (AT91F_DataFlashSendCommand(pDataFlash, |
bd86220f PP |
309 | DB_PAGE_ERASE, cmdsize, |
310 | page * pDataFlash->pDevice->pages_size)); | |
dcbfd2e5 PP |
311 | } |
312 | ||
dcbfd2e5 PP |
313 | /*---------------------------------------------------------------------------*/ |
314 | /* Function Name : AT91F_BlockErase */ | |
53677ef1 | 315 | /* Object : Erase a Block */ |
dcbfd2e5 PP |
316 | /* Input Parameters : DataFlash Service */ |
317 | /* : Page concerned */ | |
53677ef1 | 318 | /* : */ |
dcbfd2e5 | 319 | /* Return value : State of the dataflash */ |
f01dbb54 | 320 | /*---------------------------------------------------------------------------*/ |
bd86220f PP |
321 | AT91S_DataFlashStatus AT91F_BlockErase( |
322 | AT91PS_DataFlash pDataFlash, | |
323 | unsigned int block) | |
dcbfd2e5 PP |
324 | { |
325 | int cmdsize; | |
326 | /* Test if the buffer command is legal */ | |
327 | /* no data to transmit or receive */ | |
6e4bf9b2 | 328 | pDataFlash->pDataFlashDesc->tx_data_size = 0; |
dcbfd2e5 PP |
329 | cmdsize = 4; |
330 | if (pDataFlash->pDevice->pages_number >= 16384) | |
331 | cmdsize = 5; | |
6e4bf9b2 | 332 | return (AT91F_DataFlashSendCommand(pDataFlash, DB_BLOCK_ERASE, cmdsize, |
bd86220f PP |
333 | block * 8 * |
334 | pDataFlash->pDevice->pages_size)); | |
dcbfd2e5 PP |
335 | } |
336 | ||
337 | /*---------------------------------------------------------------------------*/ | |
338 | /* Function Name : AT91F_WriteBufferToMain */ | |
339 | /* Object : Write buffer to the main memory */ | |
340 | /* Input Parameters : DataFlash Service */ | |
341 | /* : <BufferCommand> = command to send to buffer1 or buffer2 */ | |
342 | /* : <dest> = main memory address */ | |
343 | /* Return value : State of the dataflash */ | |
f01dbb54 | 344 | /*---------------------------------------------------------------------------*/ |
6e4bf9b2 | 345 | AT91S_DataFlashStatus AT91F_WriteBufferToMain(AT91PS_DataFlash pDataFlash, |
bd86220f PP |
346 | unsigned char BufferCommand, |
347 | unsigned int dest) | |
dcbfd2e5 PP |
348 | { |
349 | int cmdsize; | |
350 | /* Test if the buffer command is correct */ | |
351 | if ((BufferCommand != DB_BUF1_PAGE_PGM) && | |
bd86220f PP |
352 | (BufferCommand != DB_BUF1_PAGE_ERASE_PGM) && |
353 | (BufferCommand != DB_BUF2_PAGE_PGM) && | |
354 | (BufferCommand != DB_BUF2_PAGE_ERASE_PGM)) | |
dcbfd2e5 PP |
355 | return DATAFLASH_BAD_COMMAND; |
356 | ||
357 | /* no data to transmit or receive */ | |
358 | pDataFlash->pDataFlashDesc->tx_data_size = 0; | |
359 | ||
360 | cmdsize = 4; | |
361 | if (pDataFlash->pDevice->pages_number >= 16384) | |
362 | cmdsize = 5; | |
363 | /* Send the command to the dataflash */ | |
de74b9ee | 364 | return (AT91F_DataFlashSendCommand(pDataFlash, BufferCommand, |
bd86220f | 365 | cmdsize, dest)); |
6e4bf9b2 | 366 | } |
dcbfd2e5 PP |
367 | |
368 | /*---------------------------------------------------------------------------*/ | |
369 | /* Function Name : AT91F_PartialPageWrite */ | |
370 | /* Object : Erase partielly a page */ | |
371 | /* Input Parameters : <page> = page number */ | |
372 | /* : <AdrInpage> = adr to begin the fading */ | |
373 | /* : <length> = Number of bytes to erase */ | |
f01dbb54 | 374 | /*---------------------------------------------------------------------------*/ |
6e4bf9b2 | 375 | AT91S_DataFlashStatus AT91F_PartialPageWrite(AT91PS_DataFlash pDataFlash, |
bd86220f PP |
376 | unsigned char *src, |
377 | unsigned int dest, | |
378 | unsigned int size) | |
dcbfd2e5 PP |
379 | { |
380 | unsigned int page; | |
381 | unsigned int AdrInPage; | |
382 | ||
383 | page = dest / (pDataFlash->pDevice->pages_size); | |
384 | AdrInPage = dest % (pDataFlash->pDevice->pages_size); | |
385 | ||
386 | /* Read the contents of the page in the Sram Buffer */ | |
6e4bf9b2 | 387 | AT91F_MainMemoryToBufferTransfert(pDataFlash, DB_PAGE_2_BUF1_TRF, page); |
f01dbb54 | 388 | AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, |
6e4bf9b2 | 389 | AT91C_TIMEOUT_WRDY); |
dcbfd2e5 | 390 | /*Update the SRAM buffer */ |
f01dbb54 | 391 | AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src, |
bd86220f | 392 | AdrInPage, size); |
dcbfd2e5 | 393 | |
f01dbb54 | 394 | AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, |
bd86220f | 395 | AT91C_TIMEOUT_WRDY); |
dcbfd2e5 PP |
396 | |
397 | /* Erase page if a 128 Mbits device */ | |
398 | if (pDataFlash->pDevice->pages_number >= 16384) { | |
399 | AT91F_PageErase(pDataFlash, page); | |
400 | /* Rewrite the modified Sram Buffer in the main memory */ | |
f01dbb54 | 401 | AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, |
6e4bf9b2 | 402 | AT91C_TIMEOUT_WRDY); |
dcbfd2e5 PP |
403 | } |
404 | ||
405 | /* Rewrite the modified Sram Buffer in the main memory */ | |
6e4bf9b2 PP |
406 | return (AT91F_WriteBufferToMain(pDataFlash, DB_BUF1_PAGE_ERASE_PGM, |
407 | (page * | |
408 | pDataFlash->pDevice->pages_size))); | |
dcbfd2e5 PP |
409 | } |
410 | ||
411 | /*---------------------------------------------------------------------------*/ | |
412 | /* Function Name : AT91F_DataFlashWrite */ | |
413 | /* Object : */ | |
414 | /* Input Parameters : <*src> = Source buffer */ | |
415 | /* : <dest> = dataflash adress */ | |
416 | /* : <size> = data buffer size */ | |
f01dbb54 | 417 | /*---------------------------------------------------------------------------*/ |
6e4bf9b2 | 418 | AT91S_DataFlashStatus AT91F_DataFlashWrite(AT91PS_DataFlash pDataFlash, |
bd86220f PP |
419 | unsigned char *src, |
420 | int dest, int size) | |
dcbfd2e5 PP |
421 | { |
422 | unsigned int length; | |
423 | unsigned int page; | |
424 | unsigned int status; | |
425 | ||
426 | AT91F_SpiEnable(pDataFlash->pDevice->cs); | |
427 | ||
6e4bf9b2 | 428 | if ((dest + size) > (pDataFlash->pDevice->pages_size * |
bd86220f | 429 | (pDataFlash->pDevice->pages_number))) |
dcbfd2e5 PP |
430 | return DATAFLASH_MEMORY_OVERFLOW; |
431 | ||
432 | /* If destination does not fit a page start address */ | |
6e4bf9b2 | 433 | if ((dest % ((unsigned int)(pDataFlash->pDevice->pages_size))) != 0) { |
de74b9ee | 434 | length = |
bd86220f PP |
435 | pDataFlash->pDevice->pages_size - |
436 | (dest % ((unsigned int)(pDataFlash->pDevice->pages_size))); | |
dcbfd2e5 PP |
437 | |
438 | if (size < length) | |
439 | length = size; | |
440 | ||
6e4bf9b2 | 441 | if (!AT91F_PartialPageWrite(pDataFlash, src, dest, length)) |
dcbfd2e5 PP |
442 | return DATAFLASH_ERROR; |
443 | ||
f01dbb54 | 444 | AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, |
6e4bf9b2 | 445 | AT91C_TIMEOUT_WRDY); |
dcbfd2e5 PP |
446 | |
447 | /* Update size, source and destination pointers */ | |
448 | size -= length; | |
449 | dest += length; | |
450 | src += length; | |
451 | } | |
452 | ||
6e4bf9b2 | 453 | while ((size - pDataFlash->pDevice->pages_size) >= 0) { |
dcbfd2e5 PP |
454 | /* program dataflash page */ |
455 | page = (unsigned int)dest / (pDataFlash->pDevice->pages_size); | |
456 | ||
f01dbb54 | 457 | status = AT91F_DataFlashWriteBuffer(pDataFlash, |
bd86220f PP |
458 | DB_BUF1_WRITE, src, 0, |
459 | pDataFlash->pDevice-> | |
460 | pages_size); | |
f01dbb54 | 461 | AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, |
6e4bf9b2 | 462 | AT91C_TIMEOUT_WRDY); |
dcbfd2e5 PP |
463 | |
464 | status = AT91F_PageErase(pDataFlash, page); | |
f01dbb54 | 465 | AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, |
6e4bf9b2 | 466 | AT91C_TIMEOUT_WRDY); |
dcbfd2e5 PP |
467 | if (!status) |
468 | return DATAFLASH_ERROR; | |
469 | ||
6e4bf9b2 | 470 | status = AT91F_WriteBufferToMain(pDataFlash, |
bd86220f | 471 | DB_BUF1_PAGE_PGM, dest); |
6e4bf9b2 | 472 | if (!status) |
dcbfd2e5 PP |
473 | return DATAFLASH_ERROR; |
474 | ||
f01dbb54 | 475 | AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, |
6e4bf9b2 | 476 | AT91C_TIMEOUT_WRDY); |
dcbfd2e5 PP |
477 | |
478 | /* Update size, source and destination pointers */ | |
479 | size -= pDataFlash->pDevice->pages_size; | |
480 | dest += pDataFlash->pDevice->pages_size; | |
6e4bf9b2 | 481 | src += pDataFlash->pDevice->pages_size; |
dcbfd2e5 PP |
482 | } |
483 | ||
484 | /* If still some bytes to read */ | |
6e4bf9b2 | 485 | if (size > 0) { |
dcbfd2e5 | 486 | /* program dataflash page */ |
6e4bf9b2 | 487 | if (!AT91F_PartialPageWrite(pDataFlash, src, dest, size)) |
dcbfd2e5 PP |
488 | return DATAFLASH_ERROR; |
489 | ||
f01dbb54 | 490 | AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, |
6e4bf9b2 | 491 | AT91C_TIMEOUT_WRDY); |
dcbfd2e5 PP |
492 | } |
493 | return DATAFLASH_OK; | |
494 | } | |
495 | ||
dcbfd2e5 | 496 | /*---------------------------------------------------------------------------*/ |
53677ef1 | 497 | /* Function Name : AT91F_DataFlashRead */ |
dcbfd2e5 | 498 | /* Object : Read a block in dataflash */ |
53677ef1 WD |
499 | /* Input Parameters : */ |
500 | /* Return value : */ | |
dcbfd2e5 | 501 | /*---------------------------------------------------------------------------*/ |
6e4bf9b2 PP |
502 | int AT91F_DataFlashRead(AT91PS_DataFlash pDataFlash, |
503 | unsigned long addr, unsigned long size, char *buffer) | |
dcbfd2e5 PP |
504 | { |
505 | unsigned long SizeToRead; | |
506 | ||
507 | AT91F_SpiEnable(pDataFlash->pDevice->cs); | |
508 | ||
6e4bf9b2 | 509 | if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, |
bd86220f | 510 | AT91C_TIMEOUT_WRDY) != DATAFLASH_OK) |
dcbfd2e5 PP |
511 | return -1; |
512 | ||
513 | while (size) { | |
6e4bf9b2 | 514 | SizeToRead = (size < 0x8000) ? size : 0x8000; |
dcbfd2e5 | 515 | |
f01dbb54 | 516 | if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, |
bd86220f PP |
517 | AT91C_TIMEOUT_WRDY) != |
518 | DATAFLASH_OK) | |
dcbfd2e5 PP |
519 | return -1; |
520 | ||
6e4bf9b2 | 521 | if (AT91F_DataFlashContinuousRead(pDataFlash, addr, |
bd86220f PP |
522 | (uchar *) buffer, |
523 | SizeToRead) != DATAFLASH_OK) | |
dcbfd2e5 PP |
524 | return -1; |
525 | ||
526 | size -= SizeToRead; | |
527 | addr += SizeToRead; | |
528 | buffer += SizeToRead; | |
529 | } | |
530 | ||
531 | return DATAFLASH_OK; | |
532 | } | |
533 | ||
0c42f36f | 534 | /*---------------------------------------------------------------------------*/ |
53677ef1 WD |
535 | /* Function Name : AT91F_DataflashProbe */ |
536 | /* Object : */ | |
537 | /* Input Parameters : */ | |
0c42f36f | 538 | /* Return value : Dataflash status register */ |
f01dbb54 | 539 | /*---------------------------------------------------------------------------*/ |
6e4bf9b2 PP |
540 | int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc) |
541 | { | |
0c42f36f PP |
542 | AT91F_SpiEnable(cs); |
543 | AT91F_DataFlashGetStatus(pDesc); | |
6e4bf9b2 | 544 | return ((pDesc->command[1] == 0xFF) ? 0 : pDesc->command[1] & 0x3C); |
0c42f36f | 545 | } |