source: svn/trunk/newcon3bcm2_21bu/dta/src/bspi_flash.c @ 2

Last change on this file since 2 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 14.7 KB
Line 
1/***************************************************************
2**
3**  Broadcom Corp. Confidential
4**  Copyright 2007 Broadcom Corp.  All Rights Reserved.
5**
6**  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED
7**  SOFTWARE LICENSE AGREEMENT  BETWEEN THE USER AND BROADCOM. 
8**  YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT
9**  SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
10**
11**  File:         bspi_flash.c
12**  Description:  Serial flash mgmt
13**  Created:      Wed Mar 21 13:31:21 PDT 2007 - Jeffrey P. Fisher     
14**
15****************************************************************/
16
17#include "bspi_flash.h"
18#include "ministd.h"
19#include "bchp_hif_mspi.h"
20#include "bchp_bspi.h"
21#include "bcm_mips_defs.h"
22#include "gist.h"
23#include "bstd.h"
24
25BDBG_MODULE(bspi_flash);                /* Register software module with debug interface */
26
27#ifndef WriteReg32
28        #define WriteReg32(reg,val) BREG_Write32(GetREG(),reg,val)
29#endif
30#ifndef ReadReg32
31        #define ReadReg32(reg) BREG_Read32(GetREG(),reg)
32#endif
33
34/***************************************************************************
35Summary:
36        The SPI flash interface handle.
37****************************************************************************/
38struct bspi
39{
40        bool initialized;
41        unsigned char max_write;
42        bspi_settings_t settings;
43};
44
45/*
46 * Map 700x and 354x MSPI register definitions to 75xx MSPI definitions
47 */
48
49#define BCHP_MSPI_SPCR0_LSB                      BCHP_HIF_MSPI_SPCR0_LSB
50#define BCHP_MSPI_SPCR0_MSB                      BCHP_HIF_MSPI_SPCR0_MSB
51#define BCHP_MSPI_SPCR1_LSB                      BCHP_HIF_MSPI_SPCR1_LSB
52#define BCHP_MSPI_SPCR1_MSB                      BCHP_HIF_MSPI_SPCR1_MSB
53#define BCHP_MSPI_NEWQP                          BCHP_HIF_MSPI_NEWQP
54#define BCHP_MSPI_ENDQP                          BCHP_HIF_MSPI_ENDQP
55#define BCHP_MSPI_SPCR2                          BCHP_HIF_MSPI_SPCR2
56#define BCHP_MSPI_MSPI_STATUS                    BCHP_HIF_MSPI_MSPI_STATUS
57#define BCHP_MSPI_CPTQP                          BCHP_HIF_MSPI_CPTQP
58#define BCHP_MSPI_TXRAM00                        BCHP_HIF_MSPI_TXRAM00
59#define BCHP_MSPI_RXRAM00                        BCHP_HIF_MSPI_RXRAM00
60#define BCHP_MSPI_RXRAM01                        BCHP_HIF_MSPI_RXRAM01
61#define BCHP_MSPI_CDRAM00                        BCHP_HIF_MSPI_CDRAM00
62
63#define BCHP_MSPI_MSPI_STATUS_reserved0_MASK     BCHP_HIF_MSPI_MSPI_STATUS_reserved0_MASK
64#define BCHP_MSPI_MSPI_STATUS_reserved0_SHIFT    BCHP_HIF_MSPI_MSPI_STATUS_reserved0_SHIFT
65#define BCHP_MSPI_MSPI_STATUS_HALTA_MASK         BCHP_HIF_MSPI_MSPI_STATUS_HALTA_MASK
66#define BCHP_MSPI_MSPI_STATUS_HALTA_SHIFT        BCHP_HIF_MSPI_MSPI_STATUS_HALTA_SHIFT
67#define BCHP_MSPI_MSPI_STATUS_SPIF_MASK          BCHP_HIF_MSPI_MSPI_STATUS_SPIF_MASK
68#define BCHP_MSPI_MSPI_STATUS_SPIF_SHIFT         BCHP_HIF_MSPI_MSPI_STATUS_SPIF_SHIFT
69#define BCHP_MSPI_SPCR0_MSB_CPOL_MASK            BCHP_HIF_MSPI_SPCR0_MSB_CPOL_MASK
70#define BCHP_MSPI_SPCR0_MSB_CPHA_MASK            BCHP_HIF_MSPI_SPCR0_MSB_CPHA_MASK
71#define BCHP_MSPI_SPCR0_MSB_MSTR_MASK            BCHP_HIF_MSPI_SPCR0_MSB_MSTR_MASK
72#define BCHP_MSPI_SPCR2_spe_MASK                 BCHP_HIF_MSPI_SPCR2_spe_MASK
73
74#define SPI_WREN_CMD        (0x06)
75#define SPI_WRDI_CMD        (0x04)
76#define SPI_RDSR_CMD        (0x05)
77#define SPI_READ_CMD        (0x03)
78#define SPI_BE64_CMD        (0xD8)
79#define SPI_SE4_CMD         (0x20)
80#define SPI_PP_CMD          (0x02)
81#define SPI_RDID_CMD        (0x9f)
82#define SPI_POLLING_INTERVAL            10              /* in usecs */
83#define BSPI_Pcs_eUpgSpiPcs0            0
84#define SPI_CDRAM_CONT                          0x80
85                                                                                                   
86#define SPI_CDRAM_PCS_PCS0                      0x01
87#define SPI_CDRAM_PCS_PCS1                      0x02
88#define SPI_CDRAM_PCS_PCS2                      0x04
89#define SPI_CDRAM_PCS_PCS3                      0x08
90#define SPI_CDRAM_PCS_DISABLE_ALL       (SPI_CDRAM_PCS_PCS0 | SPI_CDRAM_PCS_PCS1 | SPI_CDRAM_PCS_PCS2 | SPI_CDRAM_PCS_PCS3)
91
92#define SPI_SYSTEM_CLK          27000000        /* 27 MHz */
93#define MAX_SPI_BAUD            1687500         /* SPBR = 8, 27MHZ */
94#if SUPPORT_DST_PLATFORM //BKTODO check
95#define BSPI_MAX_WRITE          12                      //12byte -> 8byte ¼öÁ¤
96#else
97#define BSPI_MAX_WRITE          12
98#endif
99#define BSPI_SECTOR_64K     0x10000
100#define BSPI_SECTOR_4K      0x1000
101#define BSPI_PAGE_1                     0x100
102
103#define MSPI_CALC_TIMEOUT(bytes,baud)    ((((bytes * 9000)/baud) * 110)/100 + 1)
104
105
106static struct bspi s_spi = { false, BSPI_MAX_WRITE, { SPI_SE4_CMD, BSPI_SECTOR_4K}};
107
108/*
109Summary:
110        Performs small delays in microseconds
111*/
112void bspi_udelay(int microseconds)
113{
114        unsigned int mips_cycles,end_cycles;
115        mips_cycles = bcm_read_cp0($9,0);
116        end_cycles = mips_cycles + (g_ticks_per_second * g_cycles_per_tick * microseconds) /1000000;
117
118        do{
119                __asm__ volatile ("mfc0 %0, $9":"=r"(mips_cycles));
120        }while(0 == ((end_cycles - mips_cycles) & 0x80000000));
121}
122
123/*
124Summary:
125        Disables BSPI (memory mapped SPI interface) temporarily.
126*/
127
128static unsigned int bspi_disable_bspi(void)
129{
130        while (ReadReg32(BCHP_BSPI_BUSY_STATUS))
131                ;
132
133        WriteReg32(BCHP_BSPI_MAST_N_BOOT_CTRL,1);
134        return 0;
135}
136
137/*
138Summary:
139        Enabled BSPI (memory mapped SPI interface), disabled by bspi_enter_critical.
140*/
141
142static void bspi_enable_bspi(unsigned int flags)
143{
144        WriteReg32(BCHP_BSPI_MAST_N_BOOT_CTRL,0);
145        bspi_udelay(100);
146}
147
148/*
149Summary:
150        poll for completion.
151*/
152
153static int mspi_wait(unsigned int timeout_ms)
154{
155        unsigned int loopCnt,lval;
156        /*
157         * Polling mode
158         */
159        BDBG_MSG(("%s:%d(%d)\n",__FUNCTION__,__LINE__,timeout_ms));
160        loopCnt = ((timeout_ms * 1000) / SPI_POLLING_INTERVAL) + 1;
161        while (1)
162        {
163                lval = ReadReg32(BCHP_MSPI_MSPI_STATUS);
164                if (lval & BCHP_MSPI_MSPI_STATUS_SPIF_MASK)
165                {
166                        BDBG_MSG(("%s:%d status done 0x%08x\n",__FUNCTION__,__LINE__,lval));
167                        break;
168                }
169
170                if (loopCnt == 0)
171                {
172                        /* Transfer finished, clear SPIF bit */
173                        WriteReg32( BCHP_MSPI_MSPI_STATUS, 0);
174                        BDBG_MSG(("%s:%d timeout = %d\n",__FUNCTION__,__LINE__,timeout_ms));
175                        return -1;
176                }
177                bspi_udelay(SPI_POLLING_INTERVAL);
178                loopCnt--;
179        }
180        /* Transfer finished, clear SPIF bit */
181        WriteReg32( BCHP_MSPI_MSPI_STATUS, 0);
182        return 0;
183}
184
185/*
186Summary:
187        SPI transactionn.
188*/
189
190static bresult mspi_transaction( unsigned char *w_buf,
191                                                                 unsigned char write_len,
192                                                                 unsigned char *r_buf,
193                                                                 unsigned char read_len)
194{       
195        unsigned int lval;
196        unsigned char i, len;
197        static int s_init = 0;
198
199        /* set up clock once */
200        if (!s_init)
201        {
202                s_init = 1;
203                lval = SPI_SYSTEM_CLK / (2 * MAX_SPI_BAUD);
204                WriteReg32(BCHP_MSPI_SPCR0_LSB, lval );
205
206                /* Configure the clock */
207                lval = ReadReg32(BCHP_MSPI_SPCR0_MSB);
208                lval &= ~(BCHP_MSPI_SPCR0_MSB_CPOL_MASK | BCHP_MSPI_SPCR0_MSB_CPHA_MASK);
209                lval |= (BCHP_MSPI_SPCR0_MSB_MSTR_MASK | (BCHP_MSPI_SPCR0_MSB_CPOL_MASK | BCHP_MSPI_SPCR0_MSB_CPHA_MASK));
210                WriteReg32(BCHP_MSPI_SPCR0_MSB, lval );
211        }
212
213        len = write_len + read_len;
214        for (i = 0; i < len; ++i)
215        {
216                if (i < write_len)
217                {
218                        WriteReg32( BCHP_MSPI_TXRAM00 + (i * 8), (unsigned int)w_buf[i] );
219                }
220                lval = SPI_CDRAM_CONT | SPI_CDRAM_PCS_DISABLE_ALL;
221                lval &= ~(1 << BSPI_Pcs_eUpgSpiPcs0);       
222                WriteReg32( BCHP_MSPI_CDRAM00 + (i * 4) , lval );
223
224        }
225
226        lval = SPI_CDRAM_PCS_DISABLE_ALL;
227        lval &= ~(1 << BSPI_Pcs_eUpgSpiPcs0);       
228        WriteReg32( BCHP_MSPI_CDRAM00 + ((len - 1) * 4), lval );
229
230        /* Set queue pointers */
231        WriteReg32(  BCHP_MSPI_NEWQP, 0 );
232        WriteReg32(  BCHP_MSPI_ENDQP,  len - 1 );
233
234        /* Start SPI transfer */
235        lval = ReadReg32( BCHP_MSPI_SPCR2);
236        lval |= BCHP_MSPI_SPCR2_spe_MASK;
237        WriteReg32(BCHP_MSPI_SPCR2, lval);
238
239        /* Wait for SPI to finish */
240        if (mspi_wait(MSPI_CALC_TIMEOUT(len,MAX_SPI_BAUD)) != 0)
241        {
242                return berr_timeout;
243        }
244
245        for (i = write_len; i < len; ++i)
246        {
247                r_buf[i-write_len] = (unsigned char)ReadReg32( BCHP_MSPI_RXRAM01 + (i * 8));
248        }
249
250        return b_ok;
251}
252
253/***************************************************************************
254Summary:
255        Initialize and return SPI interface handle.
256
257Description:
258        Initialize and return a SPI interface handle.  This function
259        expects the bspi_settings_t structure to be initialized.
260
261Returns:
262        SPI interface handle, non-zero on failure.
263
264See Also:
265        bspi_close(), bspi_identify(),
266
267****************************************************************************/
268bresult bspi_open(
269                                        bspi_t *h_spi,  /* [out] Return SPI handle */
270                                        bspi_settings_t *p_settings  /* [in] SPI flash settings */
271                                        )
272{
273        *h_spi = NULL;
274        if (s_spi.initialized)
275        {
276                return berr_invalid_parameter;
277        }
278
279        s_spi.settings = *p_settings;
280        s_spi.initialized = true;
281        *h_spi = &s_spi;
282        return b_ok;
283}
284/***************************************************************************
285Summary:
286        Release SPI interface handle.
287
288Description:
289        Release SPI interface handle and any other SPI flash resources.
290
291Returns:
292        non-zero on failure.
293
294See Also:
295        bspi_open(),
296
297****************************************************************************/
298bresult bspi_close(
299                                        bspi_t h_spi    /* [in] SPI handle */
300                                        )
301{
302        if (!s_spi.initialized)
303        {
304                return berr_invalid_parameter;
305        }
306        s_spi.initialized = false;
307        return b_ok;
308}
309/***************************************************************************
310Summary:
311        Reads a single byte from flash using the SPI interface, not memory mapped spi.
312****************************************************************************/
313bresult bspi_read(
314                                        bspi_t h_spi,        /* [in] SPI handle */
315                                        unsigned int offset, /* [in] Offset in bytes */
316                                        unsigned char *data  /* [out] buffer to receive data */
317                                        )
318{
319        unsigned char cmd[4];
320        bresult result;
321        unsigned int flags;
322
323        cmd[0] = SPI_READ_CMD;
324        cmd[1] = ((unsigned char*)&offset)[2];
325        cmd[2] = ((unsigned char*)&offset)[1];
326        cmd[3] = ((unsigned char*)&offset)[0];
327        flags = bspi_disable_bspi();
328        result = mspi_transaction(cmd,4,data,1);
329        bspi_enable_bspi(flags);
330        return result;
331}
332/***************************************************************************
333Summary:
334        Erase flash sector at offset.
335****************************************************************************/
336bresult bspi_sector_erase(
337                                                 bspi_t h_spi,            /* [in] SPI handle */
338                                                 unsigned int offset  /* [in] Offset in bytes */
339                                                 )
340{
341        bresult result;
342        unsigned char cmd[4];
343        unsigned char data;
344        unsigned int flags;
345
346        flags = bspi_disable_bspi();
347        cmd[0] = SPI_WREN_CMD;
348        if ((result = mspi_transaction(cmd,1,NULL,0)) != b_ok)
349                goto done;
350
351        cmd[0] = h_spi->settings.se_cmd;
352        cmd[1] = ((unsigned char*)&offset)[2];
353        cmd[2] = ((unsigned char*)&offset)[1];
354        cmd[3] = ((unsigned char*)&offset)[0];
355        if ((result = mspi_transaction(cmd,4,NULL,0)) != b_ok)
356                goto done;
357#ifndef CONFIG_ROM_EMULATOR
358        do
359        {
360                cmd[0] = SPI_RDSR_CMD;
361                if ((result = mspi_transaction(cmd,1,&data,1)) != b_ok)
362                        goto done;
363        }while (data & 0x01/* busy*/);
364#else
365        bspi_udelay(100);
366#endif
367
368        cmd[0] = SPI_WRDI_CMD;
369        result = mspi_transaction(cmd,1,NULL,0);
370        done:
371        bspi_enable_bspi(flags);
372
373        return result;
374}
375
376/***************************************************************************
377Summary:
378        Program the flash page at offset with the data provided in the buffer.
379****************************************************************************/
380
381static bresult bspi_program(
382                                                        bspi_t h_spi,             /* [in] SPI handle */
383                                                         unsigned int offset, /* [in] Offset in bytes */
384                                                         unsigned char *buf,  /* [in] Data buffer to program */
385                                                         int len                          /* [in] Size in bytes of data buffer */
386                                                         )
387{
388        bresult result;
389        static unsigned char cmd[16];
390        unsigned char data;
391        unsigned int flags;
392
393        if (len > 12) /* Max bytes per transaction */
394                return berr_invalid_parameter;
395
396        flags = bspi_disable_bspi();
397
398        cmd[0] = SPI_WREN_CMD;
399        if ((result = mspi_transaction(cmd,1,NULL,0)) != b_ok)
400                goto done;
401
402        cmd[0] = SPI_PP_CMD;
403        cmd[1] = ((unsigned char*)&offset)[2];
404        cmd[2] = ((unsigned char*)&offset)[1];
405        cmd[3] = ((unsigned char*)&offset)[0];
406        memcpy(&(cmd[4]),buf,len);
407
408        if ((result = mspi_transaction(cmd,len + 4,NULL,0)) != b_ok)
409                goto done;
410
411#ifndef CONFIG_ROM_EMULATOR
412        do
413        {
414                cmd[0] = SPI_RDSR_CMD;
415                if ((result = mspi_transaction(cmd,1,&data,1)) != b_ok)
416                        goto done;
417        }while (data & 0x01/* busy*/);
418#else
419        bspi_udelay(100);
420#endif
421
422        cmd[0] = SPI_WRDI_CMD;
423        result = mspi_transaction(cmd,1,NULL,0);
424done:
425        bspi_enable_bspi(flags);
426        return result;
427}
428
429/***************************************************************************
430Summary:
431        Program the flash page at offset with the data provided in the buffer.
432****************************************************************************/
433bresult bspi_page_program(
434                                         bspi_t h_spi,            /* [in] SPI handle */
435                                         unsigned int offset, /* [in] Offset in bytes */
436                                         unsigned char *buf,  /* [in] Data buffer to program */
437                                         int len                          /* [in] Size in bytes of data buffer */
438                                         )
439{
440        int res;
441        bresult bres;
442        unsigned int block_count;
443
444        block_count = len / h_spi->max_write;
445
446        bres = b_ok;
447        while (block_count > 0)
448        {
449                bres = bspi_program(h_spi, offset, buf, h_spi->max_write);
450                if (b_ok != bres)
451                {
452                        goto ExitFunc;
453                }
454                buf = (void*)(((unsigned int)buf) + h_spi->max_write);
455                offset = offset + h_spi->max_write;
456                block_count--;
457        }
458
459        block_count = len % h_spi->max_write;
460        if (block_count != 0)
461        {
462                bres = bspi_program(h_spi, offset, buf, block_count);
463                if (b_ok != bres)
464                {
465                        goto ExitFunc;
466                }
467                buf = (void*)(((unsigned int)buf) + block_count);
468                offset = offset + block_count;
469        }
470
471        bspi_flush();
472
473ExitFunc:
474        res = (b_ok == bres) ? b_ok : berr_timeout;
475        return res;
476}
477
478/***************************************************************************
479Summary:
480        Flush BSPI interface.
481****************************************************************************/
482
483void bspi_flush(void)
484{
485        WriteReg32(BCHP_BSPI_B0_CTRL, 1);
486        WriteReg32(BCHP_BSPI_B1_CTRL, 1);
487        WriteReg32(BCHP_BSPI_B0_CTRL, 0);
488        WriteReg32(BCHP_BSPI_B1_CTRL, 0);
489}
490
491/***************************************************************************
492Summary:
493        Use RDID command to determine flash settings.
494****************************************************************************/
495
496bresult bspi_identify(
497                                         bspi_settings_t *p_settings   /* [out] SPI flash settings structure */
498                                         )
499{
500        bresult res;
501        unsigned int flags;
502        unsigned char cmd[1];
503        unsigned char data[3];
504        unsigned fid;
505
506        cmd[0] = SPI_RDID_CMD;
507
508        flags = bspi_disable_bspi();
509
510        if (b_ok != (res = mspi_transaction(cmd, 1, data, 3)))
511        {
512                data[0] = data[1] = data[2] = 0;
513                res = b_ok;
514        }
515
516        bspi_enable_bspi(flags);
517
518        fid = (data[0] << 16) | (data[1] << 8) | data[2];
519        printf("fid = 0x%X\n", fid);
520        switch (fid)
521        {
522                case 0xc22017/* MX25L6406E */  //megakiss 20140412    MX25L6406E SE ¸í·É¾î Å©±â¸¦ 64K¿¡¼­ 4K·Î º¯°æ
523                        s_spi.settings.se_cmd = SPI_SE4_CMD;
524                        s_spi.settings.sector_size = BSPI_SECTOR_4K;
525                        p_settings->total_size  = 8*1024*1024;
526                        break;
527                       
528                case 0x1c3016/* CFEON EN25Q31B1 */
529                        s_spi.settings.se_cmd = SPI_SE4_CMD;
530                        s_spi.settings.sector_size = BSPI_SECTOR_4K;
531                        p_settings->total_size  = 4*1024*1024;
532                        break;
533                       
534                default:
535                        s_spi.settings.se_cmd = SPI_SE4_CMD;
536                        s_spi.settings.sector_size = BSPI_SECTOR_4K;
537                        p_settings->total_size  = 4*1024*1024;
538                        break;
539        }
540
541        p_settings->sector_size = s_spi.settings.sector_size;
542        p_settings->se_cmd = s_spi.settings.se_cmd;
543        p_settings->page_size = BSPI_PAGE_1;
544        return res;
545}
546
547
Note: See TracBrowser for help on using the repository browser.