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