]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/ibl.git/blob - src/main/iblinitspinor.c
Merge pull request #3 in PROCESSOR-SDK/ibl from PRSDK-5675 to master
[keystone-rtos/ibl.git] / src / main / iblinitspinor.c
1 /*
2  *
3  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 
4  * 
5  * 
6  *  Redistribution and use in source and binary forms, with or without 
7  *  modification, are permitted provided that the following conditions 
8  *  are met:
9  *
10  *    Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  *    Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the 
15  *    documentation and/or other materials provided with the   
16  *    distribution.
17  *
18  *    Neither the name of Texas Instruments Incorporated nor the names of
19  *    its contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
26  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
27  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
28  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
31  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
32  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34 */
36 #include "ibl.h"
37 #include "iblloc.h"
38 #include "iblcfg.h"
39 #include "device.h"
40 #include "iblbtbl.h"
41 #include "spi_api.h"
42 #include "iblinit.h"
43 #include <string.h>
45 #if (!defined(EXCLUDE_NOR_SPI) || !defined(EXCLUDE_NAND_SPI))
47 /**
48  *  @brief
49  *      The next read address on the SPI flash is stored in a global for
50  *      access through the boot call chain.
51  */
52 uint32 spiReadAddress;
54 /**
55  *  @brief
56  *      Read a block of data from the SPI eeprom and put it in the fifo
57  */
58 void spiReadBlock (void)
59 {
60     uint16 len;
61     int32  i, j;
62     uint32 v;
64     for (;;) {
65         while (hwSpiRead  (spiReadAddress,    /* The address on the eeprom of the table */
66                            4,                 /* The number of bytes to read */
67                            iData)             /* Where to store the bytes */
68     
69              != 0)  {
71             iblStatus.spiDataRetries += 1;
72         }
74         /* Form the length. The received bytes are always in big endian format */
75         len    = (iData[0] << 8) | iData[1];
78         if (len > I_MAX_BLOCK_SIZE)
79             continue;
82         while (hwSpiRead (spiReadAddress,    /* The address on the eeprom of the table */
83                           len,               /* The number of bytes to read */
84                           iData)             /* Where to store the bytes */
85     
86              != 0)  {
88             iblStatus.spiDataRetries += 1;
89         }
92         /* Must do endian conversion to verify the checksum */
93         for (i = j = 0; i < len; i += 2, j += 1) 
94             iSum[j] = (iData[i+0] << 8) | iData[i+1];
96         v = onesComplementChksum (iSum, j);
97         if ((v == 0) || (v == 0xffff))
98             break;
100         
101         iblStatus.spiDataRetries += 1;
103     }
106     spiReadAddress += len;
107     
108     iFifoIn  = len;
109     iFifoOut = 4;    /* The spi header is effectively removed */
113              
115 /**
116  *  @brief
117  *      Read data from the SPI to pass to the interpreter
118  */
119 Int32 iblSpiRead (Uint8 *buf, Uint32 num_bytes)
121     int i;
123     for (i = 0; i < num_bytes; i++)  {
125         if (iFifoCount() == 0)
126             spiReadBlock ();
128         buf[i] = iFifoRead();
129     }
131     return (0);
136 /**
137  *  @brief
138  *      The module function table used for boot from spi
139  */
140 BOOT_MODULE_FXN_TABLE spiinit_boot_module = 
142     NULL,           /* Open  API */
143     NULL,           /* Close API */
144     iblSpiRead,     /* Read  API */
145     NULL,           /* Write API */
146     NULL,           /* Peek  API */
147     NULL,           /* Seek  API */
148     NULL            /* Query API */
149 };
154 /**
155  *  @brief
156  *      Configure the SPI, then read the parameters from the SPI and
157  *      pass them to the second stage boot
158  */
159 BOOT_MODULE_FXN_TABLE *iblInitSpiNor (void)
161     iblBootMap_t  map;
162     spiConfig_t   cfg;
163     uint32        configAddr;
165     bool          littleEndian;
166     uint16        v;
168     /* Read the endianness of the device */
169     littleEndian = deviceIsLittleEndian();
171     /* Load the default configuration table from the SPI. The actual speed of 
172      * the device isn't really known here, since it is part of the table, so a
173      * compile time value is used (the pll may have been configured during the initial load) */
174     deviceLoadInitSpiConfig ((void *)&cfg);
176     if (hwSpiConfig (&cfg) != 0)  {
178         iblStatus.iblFail = ibl_FAIL_CODE_SPI_PARAMS;
179         for (;;);
181     }
184     /* Read the SPI mapping information from the nor flash */
185     for (;;)  {
187         if (hwSpiRead ((IBL_CFG_SPI_MAP_TABLE_DATA_ADDR_MSW << 16) |   /* The address on the flash of the data mapping */
188                         IBL_CFG_SPI_MAP_TABLE_DATA_ADDR_LSW,
189                        sizeof(iblBootMap_t),                           /* The number of bytes to read */
190                        (UINT8 *)&map)                                  /* Where to store the data */
192           == 0)  {
194             /* On the flash the table is always formatted with the most significant 
195              * byte first. So if the device is running little endian, the endian
196              * must be swapped */
197             if (littleEndian == TRUE)  {
198                 map.length   = swap16val (map.length);
199                 map.chkSum   = swap16val (map.chkSum);
200                 map.addrLe   = swap32val (map.addrLe);
201                 map.configLe = swap32val (map.configLe);
202                 map.addrBe   = swap32val (map.addrBe);
203                 map.configBe = swap32val (map.configBe);
205                 configAddr     = map.configLe;
206                 spiReadAddress = map.addrLe;
208             }  else  {
210                 configAddr     = map.configBe;
211                 spiReadAddress = map.addrBe;
213             }
214             
216             if (map.length != sizeof(iblBootMap_t))  {
217                 iblStatus.mapSizeFail += 1;
218                 continue;
219             }
221             if (map.chkSum != 0)  {
223                 v = onesComplementChksum ((UINT16 *)&map, sizeof(iblBootMap_t));
224                 if ((v != 0) && (v != 0xffff))  {
225                     iblStatus.mapRetries += 1;
226                     continue;
227                 }
228             }
230             break;
232         }
234         iblStatus.mapRetries += 1;
236     }
237         
239     /* Read the SPI configuration tables until the checksum passes and the magic
240      * number matches. The checksum must be verified before the endian re-ordering */
241     for (;;)  {
243         if (hwSpiRead (configAddr,          /* The address on the flash of the table */
244                        sizeof(ibl_t),       /* The number of bytes to read */
245                        (UINT8 *)&ibl)       /* Where to store the bytes */
246              == 0)  {
248             if (ibl.chkSum != 0)  {
250                 v = onesComplementChksum ((UINT16 *)&ibl, sizeof(ibl_t) / sizeof(UINT16));
251                 if ((v != 0) && (v != 0xffff))  {
252                     iblStatus.spiRetries += 1;
253                     continue;
254                 }
255             }
257             if (ibl.iblMagic == ibl_MAGIC_VALUE)
258                 break;
260             if (swap32val (ibl.iblMagic) == ibl_MAGIC_VALUE)  {
261                 iblSwap ();
262                 break;
263             }
265             iblStatus.magicRetries += 1;
267         }
269         iblStatus.spiRetries += 1;
271     }
274     /* the rest of the IBL is in boot table format. Read and process the data */
275     if (spiReadAddress == 0xffffffff)  {
276         iblStatus.iblFail = ibl_FAIL_CODE_INVALID_SPI_ADDRESS;
277         for (;;);
278     }
280     return (&spiinit_boot_module);
285 #endif /* (!defined(EXCLUDE_NOR_SPI) || !defined(EXCLUDE_NAND_SPI)) */