source: svn/trunk/newcon3bcm2_21bu/dta/src/jflu/jflu_spi.c @ 29

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

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 9.6 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2011, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: $
11 * $brcm_Revision: $
12 * $brcm_Date: $
13 *
14 * Module Description: spi interface for jtag flash programmer.
15 *
16 * Revision History:
17 *
18 * $brcm_Log: $
19 *
20 *
21 ***************************************************************************/
22#include "bstd.h"
23#include "bchp_hif_mspi.h"
24#include "bchp_timer.h"
25#include "bchp_bspi.h"
26#include "bchp_sun_top_ctrl.h"
27
28#include "jflu_spi.h"
29
30#define SPI_WREN_CMD        (0x06)
31#define SPI_WRDI_CMD        (0x04)
32#define SPI_RDSR_CMD        (0x05)
33#define SPI_READ_CMD        (0x03)
34#define SPI_BE64_CMD        (0xD8)
35#define SPI_SE4_CMD         (0x20)
36#define SPI_PP_CMD          (0x02)
37#define SPI_RDID_CMD        (0x9f)
38#define SPI_POLLING_INTERVAL        10      /* in usecs */
39#define SPI_CDRAM_CONT              0x80
40
41#define SPI_CDRAM_PCS_PCS0                      0x01
42#define SPI_CDRAM_PCS_PCS1                      0x02
43#define SPI_CDRAM_PCS_PCS2                      0x04
44#define SPI_CDRAM_PCS_PCS3                      0x08
45#define SPI_CDRAM_PCS_DISABLE_ALL       (SPI_CDRAM_PCS_PCS0 | SPI_CDRAM_PCS_PCS1)
46/* | SPI_CDRAM_PCS_PCS2 | SPI_CDRAM_PCS_PCS3)*/
47
48#define SPI_PAGE_SIZE 0x100
49#define SPI_SECTOR_64K     0x10000
50#define SPI_SECTOR_4K      0x1000
51
52#define SPI_SYSTEM_CLK      27000000    /* 27 MHz */
53#define MAX_SPI_BAUD        1687500     /* SPBR = 8, 27MHZ */
54#define SPI_CALC_TIMEOUT(bytes,baud)     ((((bytes * 9000)/baud) * 110)/100 + 1)
55
56#define SPI_OK 0
57#define SPI_ERROR 1
58
59#define REG_BASE 0xb0000000
60#define ReadReg32(reg) (*((volatile uint32_t *)((unsigned int)(reg) + REG_BASE)))
61#define WriteReg32(reg, data) (*((volatile uint32_t *)((unsigned int)(reg) + REG_BASE)) = (data))
62
63typedef enum spi_transfer_t {
64    SPI_TRAN_MULTI,             /* start of multipart transfer */
65    SPI_TRAN_FINAL,             /* end of multipart transfer */
66} spi_transfer_t;
67
68void udelay(int microseconds);
69
70static unsigned int disable_bspi(void)
71{
72    while (ReadReg32(BCHP_BSPI_BUSY_STATUS));
73    WriteReg32(BCHP_BSPI_MAST_N_BOOT_CTRL,1);
74    return 0;
75}
76
77static void enable_bspi(unsigned int flags)
78{
79    WriteReg32(BCHP_BSPI_MAST_N_BOOT_CTRL,0);
80    udelay(100);
81}
82
83#define COUNT_PER_TICK 500000
84void udelay(int microseconds)
85{
86    unsigned int mips_cycles,end_cycles;
87    unsigned int clock;
88    __asm__("mfc0 %0, $9":"=r"(mips_cycles));
89    end_cycles = mips_cycles + ((200 * COUNT_PER_TICK) / 1000000) * microseconds;
90
91    if (end_cycles < mips_cycles) { 
92        do {
93            __asm__ volatile ("mfc0 %0, $9":"=r"(clock));
94        } while(clock > end_cycles);
95    }
96    do {
97        __asm__ volatile ("mfc0 %0, $9":"=r"(clock));
98    } while(clock < end_cycles);
99}
100
101static int spi_wait(unsigned int timeout_ms)
102{
103    unsigned int loopCnt,lval;
104    /*
105     * Polling mode
106     */
107    loopCnt = ((timeout_ms * 1000) / SPI_POLLING_INTERVAL) + 1;
108    while (1)
109    {
110        lval = ReadReg32(BCHP_HIF_MSPI_MSPI_STATUS);
111        if (lval & BCHP_HIF_MSPI_MSPI_STATUS_SPIF_MASK)
112        {
113            break;
114        }
115
116        if (loopCnt == 0)
117        {
118            /* Transfer finished, clear SPIF bit */
119            WriteReg32( BCHP_HIF_MSPI_MSPI_STATUS, 0);
120            return SPI_ERROR;
121        }
122        udelay(SPI_POLLING_INTERVAL);
123        loopCnt--;
124    }
125    /* Transfer finished, clear SPIF bit */
126    WriteReg32( BCHP_HIF_MSPI_MSPI_STATUS, 0);
127    return SPI_OK;
128}
129
130void jflu_spi_init(spi_flash_t * flash)
131{
132    unsigned int lval;
133    lval = SPI_SYSTEM_CLK / (2 * MAX_SPI_BAUD);
134    WriteReg32(BCHP_HIF_MSPI_SPCR0_LSB, lval );
135
136    /* Configure the clock */
137    lval = ReadReg32(BCHP_HIF_MSPI_SPCR0_MSB);
138    lval &= ~(BCHP_HIF_MSPI_SPCR0_MSB_CPOL_MASK | BCHP_HIF_MSPI_SPCR0_MSB_CPHA_MASK);
139    lval |= (BCHP_HIF_MSPI_SPCR0_MSB_MSTR_MASK | (BCHP_HIF_MSPI_SPCR0_MSB_CPOL_MASK | BCHP_HIF_MSPI_SPCR0_MSB_CPHA_MASK));
140    WriteReg32(BCHP_HIF_MSPI_SPCR0_MSB, lval );
141
142    flash->se_cmd = 0;
143    flash->sector_size = 0;
144    flash->page_size = 0;
145}
146
147static int spi_transfer(unsigned char * w_buf, unsigned int w_len, unsigned char *r_buf, unsigned int r_len, spi_transfer_t tran)
148{
149    unsigned int lval;
150    unsigned char i, len;
151
152    len = w_len + r_len;
153    for (i = 0; i < len; i++)
154    {
155        if (i < w_len)
156            WriteReg32((BCHP_HIF_MSPI_TXRAM00 + (i * 8)), (unsigned int)w_buf[i] );
157        lval = SPI_CDRAM_CONT | SPI_CDRAM_PCS_DISABLE_ALL;
158        lval &= ~(SPI_CDRAM_PCS_PCS0); 
159        WriteReg32((BCHP_HIF_MSPI_CDRAM00 + (i * 4)), lval );
160    }
161    if(SPI_TRAN_FINAL == tran){
162        lval = SPI_CDRAM_PCS_DISABLE_ALL;
163        lval &= ~(SPI_CDRAM_PCS_PCS0);       
164        WriteReg32( BCHP_HIF_MSPI_CDRAM00 + ((len - 1) * 4), lval );
165    }
166    /* Set queue pointers */
167    WriteReg32(BCHP_HIF_MSPI_NEWQP, 0);
168    WriteReg32(BCHP_HIF_MSPI_ENDQP, len - 1);
169
170    /* Start SPI transfer */
171    lval = ReadReg32(BCHP_HIF_MSPI_SPCR2);
172    if(SPI_TRAN_FINAL == tran){
173        lval &= ~(BCHP_HIF_MSPI_SPCR2_cont_after_cmd_MASK);
174    }else{
175        /* set WriteLock bit before starting transaction and keep it set
176           during all SPI_TRAN_MULTI transactions */
177        WriteReg32(BCHP_HIF_MSPI_WRITE_LOCK, 1);
178        lval |= BCHP_HIF_MSPI_SPCR2_cont_after_cmd_MASK;
179    }
180    lval |= BCHP_HIF_MSPI_SPCR2_spe_MASK;
181    WriteReg32(BCHP_HIF_MSPI_SPCR2, lval);
182    /* Wait for SPI to finish */
183    if (spi_wait(SPI_CALC_TIMEOUT(len,MAX_SPI_BAUD)) != 0) {
184        return 1;
185    }
186
187    if(SPI_TRAN_FINAL == tran){
188        /* clear WriteLock bit after completing final transation */
189        WriteReg32(BCHP_HIF_MSPI_WRITE_LOCK, 0);
190    }
191
192    for (i = w_len; i < len; ++i) {
193        r_buf[i-w_len] = (unsigned char)ReadReg32( BCHP_HIF_MSPI_RXRAM01 + (i * 8));
194    }
195
196    return 0;
197}
198
199/*
200Summary:
201    Erase the spi flash sector at offset.
202*/
203int jflu_spi_sector_erase(spi_flash_t * flash, unsigned int offset)
204{
205    int result;
206    unsigned char cmd[4];
207    unsigned char data;
208    unsigned int flags;
209
210    flags = disable_bspi();
211
212    cmd[0] = SPI_WREN_CMD;
213    if ((result = spi_transfer(cmd,1,NULL,0, SPI_TRAN_FINAL)) != SPI_OK)
214        goto done;
215
216    cmd[0] = flash->se_cmd;
217    cmd[1] = ((unsigned char*)&offset)[2];
218    cmd[2] = ((unsigned char*)&offset)[1];
219    cmd[3] = ((unsigned char*)&offset)[0];
220    if ((result = spi_transfer(cmd,4,NULL,0, SPI_TRAN_FINAL)) != SPI_OK)
221        goto done;
222
223    do
224    {
225        cmd[0] = SPI_RDSR_CMD;
226        if ((result = spi_transfer(cmd,1,&data,1, SPI_TRAN_FINAL)) != SPI_OK)
227            goto done;
228    }while(data & 0x01/* busy*/);
229
230
231    cmd[0] = SPI_WRDI_CMD;
232    result = spi_transfer(cmd,1,NULL,0, SPI_TRAN_FINAL);
233
234    enable_bspi(flags);
235
236done:
237
238    return result;
239}
240
241int jflu_spi_page_program(spi_flash_t * flash, unsigned int offset, unsigned char *buf, int len)
242{
243    int result;
244    static unsigned char cmd[SPI_PAGE_SIZE + 4];
245    int i,len_total;
246    unsigned char data;
247    unsigned int flags;
248
249    if (len > flash->page_size){ /* Max bytes per transaction */
250        result = SPI_ERROR;
251        goto done;
252    }
253
254    flags = disable_bspi();
255
256    cmd[0] = SPI_WREN_CMD;
257    if ((result = spi_transfer(cmd,1,NULL,0,SPI_TRAN_FINAL)) != SPI_OK)
258        goto done;
259
260    cmd[0] = SPI_PP_CMD;
261    cmd[1] = ((unsigned char*)&offset)[2];
262    cmd[2] = ((unsigned char*)&offset)[1];
263    cmd[3] = ((unsigned char*)&offset)[0];
264    /* transfer command */
265    if ((result = spi_transfer(cmd,4,NULL,0,SPI_TRAN_MULTI)) != SPI_OK)
266        goto done;
267    /* transfer buffer in 16 byte chunks */
268    i = 0;
269    len_total = len;
270    while (len_total > 16){
271        if ((result = spi_transfer(buf+i,16,NULL,0,SPI_TRAN_MULTI)) != SPI_OK)
272              goto done;
273        i+=16;
274        len_total -= 16;
275    }
276    /* transfer last chunk of the buffer */
277    if(len_total <= 16 && len_total > 0)
278    { 
279        if ((result = spi_transfer(buf + i,len_total,NULL,0,SPI_TRAN_FINAL)) != SPI_OK)
280            goto done;
281    }
282    /* read status */
283    do
284    {
285        cmd[0] = SPI_RDSR_CMD;
286        if ((result = spi_transfer(cmd,1,&data,1,SPI_TRAN_FINAL)) != SPI_OK)
287            goto done;
288    }while(data & 0x01/* busy*/);
289
290    cmd[0] = SPI_WRDI_CMD;
291    result = spi_transfer(cmd,1,NULL,0,SPI_TRAN_FINAL);
292
293    enable_bspi(flags);
294done:
295    return result;
296}
297
298int jflu_spi_identify(spi_flash_t * flash)
299{
300    int res;
301    unsigned int flags;
302    unsigned char cmd[1];
303    unsigned char data[3];
304    unsigned fid;
305
306    cmd[0] = SPI_RDID_CMD;
307
308    flags = disable_bspi();
309
310    if (0 != (res = spi_transfer(cmd, 1, data, 3,SPI_TRAN_FINAL)))
311    {
312        data[0] = data[1] = data[2] = 0;
313        res = 0;
314    }
315
316    enable_bspi(flags);
317
318    fid = (data[0] << 16) | (data[1] << 8) | data[2];
319    switch (fid)
320    {
321    case 0x010213:
322    case 0x010214:
323    case 0x010215:
324    case 0x010216:
325    case 0x012018/* Spansion S25FL 129P (Model 00) */
326        /* spansion S25FL01XA */
327        flash->se_cmd = SPI_BE64_CMD;
328        flash->sector_size = SPI_SECTOR_64K;
329        break;
330
331    case 0xc22015/* MX25L1606E */ 
332    case 0xc22016/* MX25L3206E */ 
333    case 0xc22017/* MX25L6406E */ 
334        flash->se_cmd = SPI_BE64_CMD;
335        flash->sector_size = SPI_SECTOR_64K;
336        break;
337
338    case 0xc22013/* MX25L8004 */
339    case 0xc22014/* MX25L8008 */
340    case 0xef4017/* S25FL060K */
341    default:
342        flash->se_cmd = SPI_SE4_CMD;
343        flash->sector_size = SPI_SECTOR_4K;
344        break;
345    }
346    flash->page_size = SPI_PAGE_SIZE;
347    return res;
348}
349
350/* Please do not remove! */
351/* Local Variables: */
352/* mode: C */
353/* indent-tabs-mode: nil */
354/* End: */
Note: See TracBrowser for help on using the repository browser.