blob: 1b585aac954fc840727f56033386debfca9a04b8 [file] [log] [blame]
Aubrey.Li3f0606a2007-03-09 13:38:44 +08001/****************************************************************************
2 * SPI flash driver for M25P64
3 ****************************************************************************/
4#include <common.h>
5#include <linux/ctype.h>
6
7#if defined(CONFIG_SPI)
8
9 /*Application definitions */
10
11#define NUM_SECTORS 128 /* number of sectors */
12#define SECTOR_SIZE 0x10000
13#define NOP_NUM 1000
14
15#define COMMON_SPI_SETTINGS (SPE|MSTR|CPHA|CPOL) /*Settings to the SPI_CTL */
16#define TIMOD01 (0x01) /*stes the SPI to work with core instructions */
17
18 /*Flash commands */
19#define SPI_WREN (0x06) /*Set Write Enable Latch */
20#define SPI_WRDI (0x04) /*Reset Write Enable Latch */
21#define SPI_RDSR (0x05) /*Read Status Register */
22#define SPI_WRSR (0x01) /*Write Status Register */
23#define SPI_READ (0x03) /*Read data from memory */
24#define SPI_PP (0x02) /*Program Data into memory */
25#define SPI_SE (0xD8) /*Erase one sector in memory */
26#define SPI_BE (0xC7) /*Erase all memory */
27#define WIP (0x1) /*Check the write in progress bit of the SPI status register */
28#define WEL (0x2) /*Check the write enable bit of the SPI status register */
29
30#define TIMEOUT 350000000
31
32typedef enum {
33 NO_ERR,
34 POLL_TIMEOUT,
35 INVALID_SECTOR,
36 INVALID_BLOCK,
37} ERROR_CODE;
38
39void spi_init_f(void);
40void spi_init_r(void);
41ssize_t spi_read(uchar *, int, uchar *, int);
42ssize_t spi_write(uchar *, int, uchar *, int);
43
44char ReadStatusRegister(void);
45void Wait_For_SPIF(void);
46void SetupSPI(const int spi_setting);
47void SPI_OFF(void);
48void SendSingleCommand(const int iCommand);
49
50ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector);
51ERROR_CODE EraseBlock(int nBlock);
52ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData);
53ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData);
54ERROR_CODE Wait_For_Status(char Statusbit);
55ERROR_CODE Wait_For_WEL(void);
56
57/* -------------------
58 * Variables
59 * ------------------- */
60
61/* **************************************************************************
62 *
63 * Function: spi_init_f
64 *
65 * Description: Init SPI-Controller (ROM part)
66 *
67 * return: ---
68 *
69 * *********************************************************************** */
70void spi_init_f(void)
71{
72}
73
74/* **************************************************************************
75 *
76 * Function: spi_init_r
77 *
78 * Description: Init SPI-Controller (RAM part) -
79 * The malloc engine is ready and we can move our buffers to
80 * normal RAM
81 *
82 * return: ---
83 *
84 * *********************************************************************** */
85void spi_init_r(void)
86{
87 return;
88}
89
90/****************************************************************************
91 * Function: spi_write
92 **************************************************************************** */
93ssize_t spi_write(uchar * addr, int alen, uchar * buffer, int len)
94{
95 unsigned long offset;
96 int start_block, end_block;
97 int start_byte, end_byte;
98 ERROR_CODE result = NO_ERR;
99 uchar temp[SECTOR_SIZE];
100 int i, num;
101
102 offset = addr[0] << 16 | addr[1] << 8 | addr[2];
103 /* Get the start block number */
104 result = GetSectorNumber(offset, &start_block);
105 if (result == INVALID_SECTOR) {
106 printf("Invalid sector! ");
107 return 0;
108 }
109 /* Get the end block number */
110 result = GetSectorNumber(offset + len - 1, &end_block);
111 if (result == INVALID_SECTOR) {
112 printf("Invalid sector! ");
113 return 0;
114 }
115
116 for (num = start_block; num <= end_block; num++) {
117 ReadData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp);
118 start_byte = num * SECTOR_SIZE;
119 end_byte = (num + 1) * SECTOR_SIZE - 1;
120 if (start_byte < offset)
121 start_byte = offset;
122 if (end_byte > (offset + len))
123 end_byte = (offset + len - 1);
124 for (i = start_byte; i <= end_byte; i++)
125 temp[i - num * SECTOR_SIZE] = buffer[i - offset];
126 EraseBlock(num);
127 result = WriteData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp);
128 if (result != NO_ERR)
129 return 0;
130 printf(".");
131 }
132 return len;
133}
134
135/****************************************************************************
136 * Function: spi_read
137 **************************************************************************** */
138ssize_t spi_read(uchar * addr, int alen, uchar * buffer, int len)
139{
140 unsigned long offset;
141 offset = addr[0] << 16 | addr[1] << 8 | addr[2];
142 ReadData(offset, len, (int *)buffer);
143 return len;
144}
145
146void SendSingleCommand(const int iCommand)
147{
148 unsigned short dummy;
149
150 /*turns on the SPI in single write mode */
151 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
152
153 /*sends the actual command to the SPI TX register */
154 *pSPI_TDBR = iCommand;
155 __builtin_bfin_ssync();
156
157 /*The SPI status register will be polled to check the SPIF bit */
158 Wait_For_SPIF();
159
160 dummy = *pSPI_RDBR;
161
162 /*The SPI will be turned off */
163 SPI_OFF();
164
165}
166
167void SetupSPI(const int spi_setting)
168{
169
170 if (icache_status() || dcache_status())
171 udelay(CONFIG_CCLK_HZ / 50000000);
172 /*sets up the PF2 to be the slave select of the SPI */
173 *pSPI_FLG = 0xFB04;
174 *pSPI_BAUD = CONFIG_SPI_BAUD;
175 *pSPI_CTL = spi_setting;
176 __builtin_bfin_ssync();
177}
178
179void SPI_OFF(void)
180{
181
182 *pSPI_CTL = 0x0400; /* disable SPI */
183 *pSPI_FLG = 0;
184 *pSPI_BAUD = 0;
185 __builtin_bfin_ssync();
186 udelay(CONFIG_CCLK_HZ / 50000000);
187
188}
189
190void Wait_For_SPIF(void)
191{
192 unsigned short dummyread;
193 while ((*pSPI_STAT & TXS)) ;
194 while (!(*pSPI_STAT & SPIF)) ;
195 while (!(*pSPI_STAT & RXS)) ;
196 dummyread = *pSPI_RDBR; /* Read dummy to empty the receive register */
197
198}
199
200ERROR_CODE Wait_For_WEL(void)
201{
202 int i;
203 char status_register = 0;
204 ERROR_CODE ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */
205
206 for (i = 0; i < TIMEOUT; i++) {
207 status_register = ReadStatusRegister();
208 if ((status_register & WEL)) {
209 ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */
210 break;
211 }
212 ErrorCode = POLL_TIMEOUT; /* Time out error */
213 };
214
215 return ErrorCode;
216}
217
218ERROR_CODE Wait_For_Status(char Statusbit)
219{
220 int i;
221 char status_register = 0xFF;
222 ERROR_CODE ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */
223
224 for (i = 0; i < TIMEOUT; i++) {
225 status_register = ReadStatusRegister();
226 if (!(status_register & Statusbit)) {
227 ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */
228 break;
229 }
230 ErrorCode = POLL_TIMEOUT; /* Time out error */
231 };
232
233 return ErrorCode;
234}
235
236char ReadStatusRegister(void)
237{
238 char status_register = 0;
239
240 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); /* Turn on the SPI */
241
242 *pSPI_TDBR = SPI_RDSR; /* send instruction to read status register */
243 __builtin_bfin_ssync();
244 Wait_For_SPIF(); /*wait until the instruction has been sent */
245 *pSPI_TDBR = 0; /*send dummy to receive the status register */
246 __builtin_bfin_ssync();
247 Wait_For_SPIF(); /*wait until the data has been sent */
248 status_register = *pSPI_RDBR; /*read the status register */
249
250 SPI_OFF(); /* Turn off the SPI */
251
252 return status_register;
253}
254
255ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector)
256{
257 int nSector = 0;
258 ERROR_CODE ErrorCode = NO_ERR;
259
260 if (ulOffset > (NUM_SECTORS * 0x10000 - 1)) {
261 ErrorCode = INVALID_SECTOR;
262 return ErrorCode;
263 }
264
265 nSector = (int)ulOffset / 0x10000;
266 *pnSector = nSector;
267
268 /* ok */
269 return ErrorCode;
270}
271
272ERROR_CODE EraseBlock(int nBlock)
273{
274 unsigned long ulSectorOff = 0x0, ShiftValue;
275 ERROR_CODE ErrorCode = NO_ERR;
276
277 /* if the block is invalid just return */
278 if ((nBlock < 0) || (nBlock > NUM_SECTORS)) {
279 ErrorCode = INVALID_BLOCK; /* tells us if there was an error erasing flash */
280 return ErrorCode;
281 }
282 /* figure out the offset of the block in flash */
283 if ((nBlock >= 0) && (nBlock < NUM_SECTORS)) {
284 ulSectorOff = (nBlock * SECTOR_SIZE);
285
286 } else {
287 ErrorCode = INVALID_BLOCK; /* tells us if there was an error erasing flash */
288 return ErrorCode;
289 }
290
291 /* A write enable instruction must previously have been executed */
292 SendSingleCommand(SPI_WREN);
293
294 /*The status register will be polled to check the write enable latch "WREN" */
295 ErrorCode = Wait_For_WEL();
296
297 if (POLL_TIMEOUT == ErrorCode) {
298 printf("SPI Erase block error\n");
299 return ErrorCode;
300 } else
301 /*Turn on the SPI to send single commands */
302 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
303
304 /* Send the erase block command to the flash followed by the 24 address */
305 /* to point to the start of a sector. */
306 *pSPI_TDBR = SPI_SE;
307 __builtin_bfin_ssync();
308 Wait_For_SPIF();
309 ShiftValue = (ulSectorOff >> 16); /* Send the highest byte of the 24 bit address at first */
310 *pSPI_TDBR = ShiftValue;
311 __builtin_bfin_ssync();
312 Wait_For_SPIF(); /* Wait until the instruction has been sent */
313 ShiftValue = (ulSectorOff >> 8); /* Send the middle byte of the 24 bit address at second */
314 *pSPI_TDBR = ShiftValue;
315 __builtin_bfin_ssync();
316 Wait_For_SPIF(); /* Wait until the instruction has been sent */
317 *pSPI_TDBR = ulSectorOff; /* Send the lowest byte of the 24 bit address finally */
318 __builtin_bfin_ssync();
319 Wait_For_SPIF(); /* Wait until the instruction has been sent */
320
321 /*Turns off the SPI */
322 SPI_OFF();
323
324 /* Poll the status register to check the Write in Progress bit */
325 /* Sector erase takes time */
326 ErrorCode = Wait_For_Status(WIP);
327
328 /* block erase should be complete */
329 return ErrorCode;
330}
331
332/*****************************************************************************
333* ERROR_CODE ReadData()
334*
335* Read a value from flash for verify purpose
336*
337* Inputs: unsigned long ulStart - holds the SPI start address
338* int pnData - pointer to store value read from flash
339* long lCount - number of elements to read
340***************************************************************************** */
341ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData)
342{
343 unsigned long ShiftValue;
344 char *cnData;
345 int i;
346
347 cnData = (char *)pnData; /* Pointer cast to be able to increment byte wise */
348
349 /* Start SPI interface */
350 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
351
352 *pSPI_TDBR = SPI_READ; /* Send the read command to SPI device */
353 __builtin_bfin_ssync();
354 Wait_For_SPIF(); /* Wait until the instruction has been sent */
355 ShiftValue = (ulStart >> 16); /* Send the highest byte of the 24 bit address at first */
356 *pSPI_TDBR = ShiftValue; /* Send the byte to the SPI device */
357 __builtin_bfin_ssync();
358 Wait_For_SPIF(); /* Wait until the instruction has been sent */
359 ShiftValue = (ulStart >> 8); /* Send the middle byte of the 24 bit address at second */
360 *pSPI_TDBR = ShiftValue; /* Send the byte to the SPI device */
361 __builtin_bfin_ssync();
362 Wait_For_SPIF(); /* Wait until the instruction has been sent */
363 *pSPI_TDBR = ulStart; /* Send the lowest byte of the 24 bit address finally */
364 __builtin_bfin_ssync();
365 Wait_For_SPIF(); /* Wait until the instruction has been sent */
366
367 /* After the SPI device address has been placed on the MOSI pin the data can be */
368 /* received on the MISO pin. */
369 for (i = 0; i < lCount; i++) {
370 *pSPI_TDBR = 0; /*send dummy */
371 __builtin_bfin_ssync();
372 while (!(*pSPI_STAT & RXS)) ;
373 *cnData++ = *pSPI_RDBR; /*read */
374
375 if ((i >= SECTOR_SIZE) && (i % SECTOR_SIZE == 0))
376 printf(".");
377 }
378
379 SPI_OFF(); /* Turn off the SPI */
380
381 return NO_ERR;
382}
383
384ERROR_CODE WriteFlash(unsigned long ulStartAddr, long lTransferCount,
385 int *iDataSource, long *lWriteCount)
386{
387
388 unsigned long ulWAddr;
389 long lWTransferCount = 0;
390 int i;
391 char iData;
392 char *temp = (char *)iDataSource;
393 ERROR_CODE ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */
394
395 /* First, a Write Enable Command must be sent to the SPI. */
396 SendSingleCommand(SPI_WREN);
397
398 /* Second, the SPI Status Register will be tested whether the */
399 /* Write Enable Bit has been set. */
400 ErrorCode = Wait_For_WEL();
401 if (POLL_TIMEOUT == ErrorCode) {
402 printf("SPI Write Time Out\n");
403 return ErrorCode;
404 } else
405 /* Third, the 24 bit address will be shifted out the SPI MOSI bytewise. */
406 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); /* Turns the SPI on */
407 *pSPI_TDBR = SPI_PP;
408 __builtin_bfin_ssync();
409 Wait_For_SPIF(); /*wait until the instruction has been sent */
410 ulWAddr = (ulStartAddr >> 16);
411 *pSPI_TDBR = ulWAddr;
412 __builtin_bfin_ssync();
413 Wait_For_SPIF(); /*wait until the instruction has been sent */
414 ulWAddr = (ulStartAddr >> 8);
415 *pSPI_TDBR = ulWAddr;
416 __builtin_bfin_ssync();
417 Wait_For_SPIF(); /*wait until the instruction has been sent */
418 ulWAddr = ulStartAddr;
419 *pSPI_TDBR = ulWAddr;
420 __builtin_bfin_ssync();
421 Wait_For_SPIF(); /*wait until the instruction has been sent */
422 /* Fourth, maximum number of 256 bytes will be taken from the Buffer */
423 /* and sent to the SPI device. */
424 for (i = 0; (i < lTransferCount) && (i < 256); i++, lWTransferCount++) {
425 iData = *temp;
426 *pSPI_TDBR = iData;
427 __builtin_bfin_ssync();
428 Wait_For_SPIF(); /*wait until the instruction has been sent */
429 temp++;
430 }
431
432 SPI_OFF(); /* Turns the SPI off */
433
434 /* Sixth, the SPI Write in Progress Bit must be toggled to ensure the */
435 /* programming is done before start of next transfer. */
436 ErrorCode = Wait_For_Status(WIP);
437
438 if (POLL_TIMEOUT == ErrorCode) {
439 printf("SPI Program Time out!\n");
440 return ErrorCode;
441 } else
442
443 *lWriteCount = lWTransferCount;
444
445 return ErrorCode;
446}
447
448ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData)
449{
450
451 unsigned long ulWStart = ulStart;
452 long lWCount = lCount, lWriteCount;
453 long *pnWriteCount = &lWriteCount;
454
455 ERROR_CODE ErrorCode = NO_ERR;
456
457 while (lWCount != 0) {
458 ErrorCode = WriteFlash(ulWStart, lWCount, pnData, pnWriteCount);
459
460 /* After each function call of WriteFlash the counter must be adjusted */
461 lWCount -= *pnWriteCount;
462
463 /* Also, both address pointers must be recalculated. */
464 ulWStart += *pnWriteCount;
465 pnData += *pnWriteCount / 4;
466 }
467
468 /* return the appropriate error code */
469 return ErrorCode;
470}
471
472#endif /* CONFIG_SPI */