Merge with git://www.denx.de/git/u-boot.git
[oweals/u-boot.git] / board / bf533-stamp / spi.c
1 /****************************************************************************
2  *  SPI flash driver for M25P64
3  ****************************************************************************/
4 #include <common.h>
5 #include <linux/ctype.h>
6 #include <asm/io.h>
7
8 #if defined(CONFIG_SPI)
9
10  /*Application definitions */
11
12 #define NUM_SECTORS     128     /* number of sectors */
13 #define SECTOR_SIZE             0x10000
14 #define NOP_NUM         1000
15
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 */
18
19  /*Flash commands */
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 */
30
31 #define TIMEOUT 350000000
32
33 typedef enum {
34         NO_ERR,
35         POLL_TIMEOUT,
36         INVALID_SECTOR,
37         INVALID_BLOCK,
38 } ERROR_CODE;
39
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);
44
45 char ReadStatusRegister(void);
46 void Wait_For_SPIF(void);
47 void SetupSPI(const int spi_setting);
48 void SPI_OFF(void);
49 void SendSingleCommand(const int iCommand);
50
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);
57
58 /* -------------------
59  * Variables
60  * ------------------- */
61
62 /* **************************************************************************
63  *
64  *  Function:    spi_init_f
65  *
66  *  Description: Init SPI-Controller (ROM part)
67  *
68  *  return:      ---
69  *
70  * *********************************************************************** */
71 void spi_init_f(void)
72 {
73 }
74
75 /* **************************************************************************
76  *
77  *  Function:    spi_init_r
78  *
79  *  Description: Init SPI-Controller (RAM part) -
80  *               The malloc engine is ready and we can move our buffers to
81  *               normal RAM
82  *
83  *  return:      ---
84  *
85  * *********************************************************************** */
86 void spi_init_r(void)
87 {
88         return;
89 }
90
91 /****************************************************************************
92  *  Function:    spi_write
93  **************************************************************************** */
94 ssize_t spi_write(uchar * addr, int alen, uchar * buffer, int len)
95 {
96         unsigned long offset;
97         int start_block, end_block;
98         int start_byte, end_byte;
99         ERROR_CODE result = NO_ERR;
100         uchar temp[SECTOR_SIZE];
101         int i, num;
102
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! ");
108                 return 0;
109         }
110         /* Get the end block number */
111         result = GetSectorNumber(offset + len - 1, &end_block);
112         if (result == INVALID_SECTOR) {
113                 printf("Invalid sector! ");
114                 return 0;
115         }
116
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)
122                         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];
127                 EraseBlock(num);
128                 result = WriteData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp);
129                 if (result != NO_ERR)
130                         return 0;
131                 printf(".");
132         }
133         return len;
134 }
135
136 /****************************************************************************
137  *  Function:    spi_read
138  **************************************************************************** */
139 ssize_t spi_read(uchar * addr, int alen, uchar * buffer, int len)
140 {
141         unsigned long offset;
142         offset = addr[0] << 16 | addr[1] << 8 | addr[2];
143         ReadData(offset, len, (int *)buffer);
144         return len;
145 }
146
147 void SendSingleCommand(const int iCommand)
148 {
149         unsigned short dummy;
150
151         /*turns on the SPI in single write mode */
152         SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
153
154         /*sends the actual command to the SPI TX register */
155         *pSPI_TDBR = iCommand;
156         sync();
157
158         /*The SPI status register will be polled to check the SPIF bit */
159         Wait_For_SPIF();
160
161         dummy = *pSPI_RDBR;
162
163         /*The SPI will be turned off */
164         SPI_OFF();
165
166 }
167
168 void SetupSPI(const int spi_setting)
169 {
170
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 */
174         *pSPI_FLG = 0xFB04;
175         *pSPI_BAUD = CONFIG_SPI_BAUD;
176         *pSPI_CTL = spi_setting;
177         sync();
178 }
179
180 void SPI_OFF(void)
181 {
182
183         *pSPI_CTL = 0x0400;     /* disable SPI */
184         *pSPI_FLG = 0;
185         *pSPI_BAUD = 0;
186         sync();
187         udelay(CONFIG_CCLK_HZ / 50000000);
188
189 }
190
191 void Wait_For_SPIF(void)
192 {
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      */
198
199 }
200
201 ERROR_CODE Wait_For_WEL(void)
202 {
203         int i;
204         char status_register = 0;
205         ERROR_CODE ErrorCode = NO_ERR;  /* tells us if there was an error erasing flash */
206
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 */
211                         break;
212                 }
213                 ErrorCode = POLL_TIMEOUT;       /* Time out error */
214         };
215
216         return ErrorCode;
217 }
218
219 ERROR_CODE Wait_For_Status(char Statusbit)
220 {
221         int i;
222         char status_register = 0xFF;
223         ERROR_CODE ErrorCode = NO_ERR;  /* tells us if there was an error erasing flash */
224
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 */
229                         break;
230                 }
231                 ErrorCode = POLL_TIMEOUT;       /* Time out error */
232         };
233
234         return ErrorCode;
235 }
236
237 char ReadStatusRegister(void)
238 {
239         char status_register = 0;
240
241         SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));      /* Turn on the SPI */
242
243         *pSPI_TDBR = SPI_RDSR;  /* send instruction to read status register */
244         sync();
245         Wait_For_SPIF();        /*wait until the instruction has been sent */
246         *pSPI_TDBR = 0;         /*send dummy to receive the status register */
247         sync();
248         Wait_For_SPIF();        /*wait until the data has been sent */
249         status_register = *pSPI_RDBR;   /*read the status register */
250
251         SPI_OFF();              /* Turn off the SPI */
252
253         return status_register;
254 }
255
256 ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector)
257 {
258         int nSector = 0;
259         ERROR_CODE ErrorCode = NO_ERR;
260
261         if (ulOffset > (NUM_SECTORS * 0x10000 - 1)) {
262                 ErrorCode = INVALID_SECTOR;
263                 return ErrorCode;
264         }
265
266         nSector = (int)ulOffset / 0x10000;
267         *pnSector = nSector;
268
269         /* ok */
270         return ErrorCode;
271 }
272
273 ERROR_CODE EraseBlock(int nBlock)
274 {
275         unsigned long ulSectorOff = 0x0, ShiftValue;
276         ERROR_CODE ErrorCode = NO_ERR;
277
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 */
281                 return ErrorCode;
282         }
283         /* figure out the offset of the block in flash */
284         if ((nBlock >= 0) && (nBlock < NUM_SECTORS)) {
285                 ulSectorOff = (nBlock * SECTOR_SIZE);
286
287         } else {
288                 ErrorCode = INVALID_BLOCK;      /* tells us if there was an error erasing flash */
289                 return ErrorCode;
290         }
291
292         /* A write enable instruction must previously have been executed */
293         SendSingleCommand(SPI_WREN);
294
295         /*The status register will be polled to check the write enable latch "WREN" */
296         ErrorCode = Wait_For_WEL();
297
298         if (POLL_TIMEOUT == ErrorCode) {
299                 printf("SPI Erase block error\n");
300                 return ErrorCode;
301         } else
302                 /*Turn on the SPI to send single commands */
303                 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
304
305         /* Send the erase block command to the flash followed by the 24 address  */
306         /* to point to the start of a sector. */
307         *pSPI_TDBR = SPI_SE;
308         sync();
309         Wait_For_SPIF();
310         ShiftValue = (ulSectorOff >> 16);       /* Send the highest byte of the 24 bit address at first */
311         *pSPI_TDBR = ShiftValue;
312         sync();
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;
316         sync();
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 */
319         sync();
320         Wait_For_SPIF();        /* Wait until the instruction has been sent */
321
322         /*Turns off the SPI */
323         SPI_OFF();
324
325         /* Poll the status register to check the Write in Progress bit */
326         /* Sector erase takes time */
327         ErrorCode = Wait_For_Status(WIP);
328
329         /* block erase should be complete */
330         return ErrorCode;
331 }
332
333 /*****************************************************************************
334 * ERROR_CODE ReadData()
335 *
336 * Read a value from flash for verify purpose
337 *
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)
343 {
344         unsigned long ShiftValue;
345         char *cnData;
346         int i;
347
348         cnData = (char *)pnData;        /* Pointer cast to be able to increment byte wise */
349
350         /* Start SPI interface   */
351         SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
352
353         *pSPI_TDBR = SPI_READ;  /* Send the read command to SPI device */
354         sync();
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 */
358         sync();
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 */
362         sync();
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 */
365         sync();
366         Wait_For_SPIF();        /* Wait until the instruction has been sent */
367
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 */
372                 sync();
373                 while (!(*pSPI_STAT & RXS)) ;
374                 *cnData++ = *pSPI_RDBR; /*read  */
375
376                 if ((i >= SECTOR_SIZE) && (i % SECTOR_SIZE == 0))
377                         printf(".");
378         }
379
380         SPI_OFF();              /* Turn off the SPI */
381
382         return NO_ERR;
383 }
384
385 ERROR_CODE WriteFlash(unsigned long ulStartAddr, long lTransferCount,
386                       int *iDataSource, long *lWriteCount)
387 {
388
389         unsigned long ulWAddr;
390         long lWTransferCount = 0;
391         int i;
392         char iData;
393         char *temp = (char *)iDataSource;
394         ERROR_CODE ErrorCode = NO_ERR;  /* tells us if there was an error erasing flash */
395
396         /* First, a Write Enable Command must be sent to the SPI. */
397         SendSingleCommand(SPI_WREN);
398
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");
404                 return ErrorCode;
405         } else
406                 /* Third, the 24 bit address will be shifted out the SPI MOSI bytewise. */
407                 SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));      /* Turns the SPI on */
408         *pSPI_TDBR = SPI_PP;
409         sync();
410         Wait_For_SPIF();        /*wait until the instruction has been sent */
411         ulWAddr = (ulStartAddr >> 16);
412         *pSPI_TDBR = ulWAddr;
413         sync();
414         Wait_For_SPIF();        /*wait until the instruction has been sent */
415         ulWAddr = (ulStartAddr >> 8);
416         *pSPI_TDBR = ulWAddr;
417         sync();
418         Wait_For_SPIF();        /*wait until the instruction has been sent */
419         ulWAddr = ulStartAddr;
420         *pSPI_TDBR = ulWAddr;
421         sync();
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++) {
426                 iData = *temp;
427                 *pSPI_TDBR = iData;
428                 sync();
429                 Wait_For_SPIF();        /*wait until the instruction has been sent */
430                 temp++;
431         }
432
433         SPI_OFF();              /* Turns the SPI off */
434
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);
438
439         if (POLL_TIMEOUT == ErrorCode) {
440                 printf("SPI Program Time out!\n");
441                 return ErrorCode;
442         } else
443
444                 *lWriteCount = lWTransferCount;
445
446         return ErrorCode;
447 }
448
449 ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData)
450 {
451
452         unsigned long ulWStart = ulStart;
453         long lWCount = lCount, lWriteCount;
454         long *pnWriteCount = &lWriteCount;
455
456         ERROR_CODE ErrorCode = NO_ERR;
457
458         while (lWCount != 0) {
459                 ErrorCode = WriteFlash(ulWStart, lWCount, pnData, pnWriteCount);
460
461                 /* After each function call of WriteFlash the counter must be adjusted */
462                 lWCount -= *pnWriteCount;
463
464                 /* Also, both address pointers must be recalculated. */
465                 ulWStart += *pnWriteCount;
466                 pnData += *pnWriteCount / 4;
467         }
468
469         /* return the appropriate error code */
470         return ErrorCode;
471 }
472
473 #endif                          /* CONFIG_SPI */