1 /****************************************************************************
2 * SPI flash driver for M25P64
3 ****************************************************************************/
5 #include <linux/ctype.h>
8 #if defined(CONFIG_SPI)
10 /*Application definitions */
12 #define NUM_SECTORS 128 /* number of sectors */
13 #define SECTOR_SIZE 0x10000
16 #define COMMON_SPI_SETTINGS (SPE|MSTR|CPHA|CPOL) /*Settings to the SPI_CTL */
17 #define TIMOD01 (0x01) /*stes the SPI to work with core instructions */
20 #define SPI_WREN (0x06) /*Set Write Enable Latch */
21 #define SPI_WRDI (0x04) /*Reset Write Enable Latch */
22 #define SPI_RDSR (0x05) /*Read Status Register */
23 #define SPI_WRSR (0x01) /*Write Status Register */
24 #define SPI_READ (0x03) /*Read data from memory */
25 #define SPI_PP (0x02) /*Program Data into memory */
26 #define SPI_SE (0xD8) /*Erase one sector in memory */
27 #define SPI_BE (0xC7) /*Erase all memory */
28 #define WIP (0x1) /*Check the write in progress bit of the SPI status register */
29 #define WEL (0x2) /*Check the write enable bit of the SPI status register */
31 #define TIMEOUT 350000000
40 void spi_init_f(void);
41 void spi_init_r(void);
42 ssize_t spi_read(uchar *, int, uchar *, int);
43 ssize_t spi_write(uchar *, int, uchar *, int);
45 char ReadStatusRegister(void);
46 void Wait_For_SPIF(void);
47 void SetupSPI(const int spi_setting);
49 void SendSingleCommand(const int iCommand);
51 ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector);
52 ERROR_CODE EraseBlock(int nBlock);
53 ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData);
54 ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData);
55 ERROR_CODE Wait_For_Status(char Statusbit);
56 ERROR_CODE Wait_For_WEL(void);
58 /* -------------------
60 * ------------------- */
62 /* **************************************************************************
64 * Function: spi_init_f
66 * Description: Init SPI-Controller (ROM part)
70 * *********************************************************************** */
75 /* **************************************************************************
77 * Function: spi_init_r
79 * Description: Init SPI-Controller (RAM part) -
80 * The malloc engine is ready and we can move our buffers to
85 * *********************************************************************** */
91 /****************************************************************************
93 **************************************************************************** */
94 ssize_t spi_write(uchar * addr, int alen, uchar * buffer, int len)
97 int start_block, end_block;
98 int start_byte, end_byte;
99 ERROR_CODE result = NO_ERR;
100 uchar temp[SECTOR_SIZE];
103 offset = addr[0] << 16 | addr[1] << 8 | addr[2];
104 /* Get the start block number */
105 result = GetSectorNumber(offset, &start_block);
106 if (result == INVALID_SECTOR) {
107 printf("Invalid sector! ");
110 /* Get the end block number */
111 result = GetSectorNumber(offset + len - 1, &end_block);
112 if (result == INVALID_SECTOR) {
113 printf("Invalid sector! ");
117 for (num = start_block; num <= end_block; num++) {
118 ReadData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp);
119 start_byte = num * SECTOR_SIZE;
120 end_byte = (num + 1) * SECTOR_SIZE - 1;
121 if (start_byte < offset)
123 if (end_byte > (offset + len))
124 end_byte = (offset + len - 1);
125 for (i = start_byte; i <= end_byte; i++)
126 temp[i - num * SECTOR_SIZE] = buffer[i - offset];
128 result = WriteData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp);
129 if (result != NO_ERR)
136 /****************************************************************************
138 **************************************************************************** */
139 ssize_t spi_read(uchar * addr, int alen, uchar * buffer, int len)
141 unsigned long offset;
142 offset = addr[0] << 16 | addr[1] << 8 | addr[2];
143 ReadData(offset, len, (int *)buffer);
147 void SendSingleCommand(const int iCommand)
149 unsigned short dummy;
151 /*turns on the SPI in single write mode */
152 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
154 /*sends the actual command to the SPI TX register */
155 *pSPI_TDBR = iCommand;
158 /*The SPI status register will be polled to check the SPIF bit */
163 /*The SPI will be turned off */
168 void SetupSPI(const int spi_setting)
171 if (icache_status() || dcache_status())
172 udelay(CONFIG_CCLK_HZ / 50000000);
173 /*sets up the PF2 to be the slave select of the SPI */
175 *pSPI_BAUD = CONFIG_SPI_BAUD;
176 *pSPI_CTL = spi_setting;
183 *pSPI_CTL = 0x0400; /* disable SPI */
187 udelay(CONFIG_CCLK_HZ / 50000000);
191 void Wait_For_SPIF(void)
193 unsigned short dummyread;
194 while ((*pSPI_STAT & TXS)) ;
195 while (!(*pSPI_STAT & SPIF)) ;
196 while (!(*pSPI_STAT & RXS)) ;
197 dummyread = *pSPI_RDBR; /* Read dummy to empty the receive register */
201 ERROR_CODE Wait_For_WEL(void)
204 char status_register = 0;
205 ERROR_CODE ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */
207 for (i = 0; i < TIMEOUT; i++) {
208 status_register = ReadStatusRegister();
209 if ((status_register & WEL)) {
210 ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */
213 ErrorCode = POLL_TIMEOUT; /* Time out error */
219 ERROR_CODE Wait_For_Status(char Statusbit)
222 char status_register = 0xFF;
223 ERROR_CODE ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */
225 for (i = 0; i < TIMEOUT; i++) {
226 status_register = ReadStatusRegister();
227 if (!(status_register & Statusbit)) {
228 ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */
231 ErrorCode = POLL_TIMEOUT; /* Time out error */
237 char ReadStatusRegister(void)
239 char status_register = 0;
241 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); /* Turn on the SPI */
243 *pSPI_TDBR = SPI_RDSR; /* send instruction to read status register */
245 Wait_For_SPIF(); /*wait until the instruction has been sent */
246 *pSPI_TDBR = 0; /*send dummy to receive the status register */
248 Wait_For_SPIF(); /*wait until the data has been sent */
249 status_register = *pSPI_RDBR; /*read the status register */
251 SPI_OFF(); /* Turn off the SPI */
253 return status_register;
256 ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector)
259 ERROR_CODE ErrorCode = NO_ERR;
261 if (ulOffset > (NUM_SECTORS * 0x10000 - 1)) {
262 ErrorCode = INVALID_SECTOR;
266 nSector = (int)ulOffset / 0x10000;
273 ERROR_CODE EraseBlock(int nBlock)
275 unsigned long ulSectorOff = 0x0, ShiftValue;
276 ERROR_CODE ErrorCode = NO_ERR;
278 /* if the block is invalid just return */
279 if ((nBlock < 0) || (nBlock > NUM_SECTORS)) {
280 ErrorCode = INVALID_BLOCK; /* tells us if there was an error erasing flash */
283 /* figure out the offset of the block in flash */
284 if ((nBlock >= 0) && (nBlock < NUM_SECTORS)) {
285 ulSectorOff = (nBlock * SECTOR_SIZE);
288 ErrorCode = INVALID_BLOCK; /* tells us if there was an error erasing flash */
292 /* A write enable instruction must previously have been executed */
293 SendSingleCommand(SPI_WREN);
295 /*The status register will be polled to check the write enable latch "WREN" */
296 ErrorCode = Wait_For_WEL();
298 if (POLL_TIMEOUT == ErrorCode) {
299 printf("SPI Erase block error\n");
302 /*Turn on the SPI to send single commands */
303 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
305 /* Send the erase block command to the flash followed by the 24 address */
306 /* to point to the start of a sector. */
310 ShiftValue = (ulSectorOff >> 16); /* Send the highest byte of the 24 bit address at first */
311 *pSPI_TDBR = ShiftValue;
313 Wait_For_SPIF(); /* Wait until the instruction has been sent */
314 ShiftValue = (ulSectorOff >> 8); /* Send the middle byte of the 24 bit address at second */
315 *pSPI_TDBR = ShiftValue;
317 Wait_For_SPIF(); /* Wait until the instruction has been sent */
318 *pSPI_TDBR = ulSectorOff; /* Send the lowest byte of the 24 bit address finally */
320 Wait_For_SPIF(); /* Wait until the instruction has been sent */
322 /*Turns off the SPI */
325 /* Poll the status register to check the Write in Progress bit */
326 /* Sector erase takes time */
327 ErrorCode = Wait_For_Status(WIP);
329 /* block erase should be complete */
333 /*****************************************************************************
334 * ERROR_CODE ReadData()
336 * Read a value from flash for verify purpose
338 * Inputs: unsigned long ulStart - holds the SPI start address
339 * int pnData - pointer to store value read from flash
340 * long lCount - number of elements to read
341 ***************************************************************************** */
342 ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData)
344 unsigned long ShiftValue;
348 cnData = (char *)pnData; /* Pointer cast to be able to increment byte wise */
350 /* Start SPI interface */
351 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
353 *pSPI_TDBR = SPI_READ; /* Send the read command to SPI device */
355 Wait_For_SPIF(); /* Wait until the instruction has been sent */
356 ShiftValue = (ulStart >> 16); /* Send the highest byte of the 24 bit address at first */
357 *pSPI_TDBR = ShiftValue; /* Send the byte to the SPI device */
359 Wait_For_SPIF(); /* Wait until the instruction has been sent */
360 ShiftValue = (ulStart >> 8); /* Send the middle byte of the 24 bit address at second */
361 *pSPI_TDBR = ShiftValue; /* Send the byte to the SPI device */
363 Wait_For_SPIF(); /* Wait until the instruction has been sent */
364 *pSPI_TDBR = ulStart; /* Send the lowest byte of the 24 bit address finally */
366 Wait_For_SPIF(); /* Wait until the instruction has been sent */
368 /* After the SPI device address has been placed on the MOSI pin the data can be */
369 /* received on the MISO pin. */
370 for (i = 0; i < lCount; i++) {
371 *pSPI_TDBR = 0; /*send dummy */
373 while (!(*pSPI_STAT & RXS)) ;
374 *cnData++ = *pSPI_RDBR; /*read */
376 if ((i >= SECTOR_SIZE) && (i % SECTOR_SIZE == 0))
380 SPI_OFF(); /* Turn off the SPI */
385 ERROR_CODE WriteFlash(unsigned long ulStartAddr, long lTransferCount,
386 int *iDataSource, long *lWriteCount)
389 unsigned long ulWAddr;
390 long lWTransferCount = 0;
393 char *temp = (char *)iDataSource;
394 ERROR_CODE ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */
396 /* First, a Write Enable Command must be sent to the SPI. */
397 SendSingleCommand(SPI_WREN);
399 /* Second, the SPI Status Register will be tested whether the */
400 /* Write Enable Bit has been set. */
401 ErrorCode = Wait_For_WEL();
402 if (POLL_TIMEOUT == ErrorCode) {
403 printf("SPI Write Time Out\n");
406 /* Third, the 24 bit address will be shifted out the SPI MOSI bytewise. */
407 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); /* Turns the SPI on */
410 Wait_For_SPIF(); /*wait until the instruction has been sent */
411 ulWAddr = (ulStartAddr >> 16);
412 *pSPI_TDBR = ulWAddr;
414 Wait_For_SPIF(); /*wait until the instruction has been sent */
415 ulWAddr = (ulStartAddr >> 8);
416 *pSPI_TDBR = ulWAddr;
418 Wait_For_SPIF(); /*wait until the instruction has been sent */
419 ulWAddr = ulStartAddr;
420 *pSPI_TDBR = ulWAddr;
422 Wait_For_SPIF(); /*wait until the instruction has been sent */
423 /* Fourth, maximum number of 256 bytes will be taken from the Buffer */
424 /* and sent to the SPI device. */
425 for (i = 0; (i < lTransferCount) && (i < 256); i++, lWTransferCount++) {
429 Wait_For_SPIF(); /*wait until the instruction has been sent */
433 SPI_OFF(); /* Turns the SPI off */
435 /* Sixth, the SPI Write in Progress Bit must be toggled to ensure the */
436 /* programming is done before start of next transfer. */
437 ErrorCode = Wait_For_Status(WIP);
439 if (POLL_TIMEOUT == ErrorCode) {
440 printf("SPI Program Time out!\n");
444 *lWriteCount = lWTransferCount;
449 ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData)
452 unsigned long ulWStart = ulStart;
453 long lWCount = lCount, lWriteCount;
454 long *pnWriteCount = &lWriteCount;
456 ERROR_CODE ErrorCode = NO_ERR;
458 while (lWCount != 0) {
459 ErrorCode = WriteFlash(ulWStart, lWCount, pnData, pnWriteCount);
461 /* After each function call of WriteFlash the counter must be adjusted */
462 lWCount -= *pnWriteCount;
464 /* Also, both address pointers must be recalculated. */
465 ulWStart += *pnWriteCount;
466 pnData += *pnWriteCount / 4;
469 /* return the appropriate error code */
473 #endif /* CONFIG_SPI */