]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/ibl.git/blob - src/main/iblinit.c
Added loading of second stage through SPI
[keystone-rtos/ibl.git] / src / main / iblinit.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 /**
37  *  @file iblinit.c
38  *
39  *  @brief
40  *              This file contains code which runs prior to loading the full IBL
41  *
42  *  @details
43  *              The IBL loads itself in a two stage process. The ROM boot loader
44  *              loads this first stage IBL first. This entire program must be
45  *              endian independent in execution.
46  *
47  *      This first loader reads the IBL parameters, and will endian
48  *      switch them if required. The PLL is configured if indicated
49  *      by the parameters.
50  *
51  *      The I2C block which contains the I2C EEPROM address for both
52  *      the big and little endian images is then read. Based on the
53  *      endianness of the device the rest of the IBL is read from
54  *      the I2C EEPROM, and execution is transferred to the full
55  *      IBL.
56  *
57  *      The subsequent reads are allowed to cross 16 bit i2c EEPROM
58  *      addresses. When the boundary is crossed the i2c address
59  *      field is incremented.
60  *
61  */
63 #include "ibl.h"
64 #include "iblloc.h"
65 #include "iblcfg.h"
66 #include "device.h"
67 #include "iblbtbl.h"
68 #include "iblinit.h"
69 #include <string.h>
72 /**
73  *  @brief
74  *      Data structures shared between the 1st and 2nd stage IBL load
75  *      are declared in a single header file, included in both stages
76  */
77 #include "iblStage.h"
79 /**
80  *  @brief
81  *      The boot table processing status is declared in the boot table wrapper,
82  *      and used here in the main status fields.
83  */
84 extern Int32 btblWrapEcode;
86 /**
87  *  @brief
88  *      The malloc function used for both boot stages of the ibl
89  */
90 void *iblMalloc (Uint32 size)
91 {
92     return (malloc (size));
93 }
95 /**
96  *  @brief
97  *      The free function used for both stages of the ibl
98  */
99 void iblFree (void *mem)
101     free (mem);
104 /**
105  *  @brief
106  *      The memset function used for both stages of the ibl
107  */
108 void *iblMemset (void *mem, Int32 ch, Uint32 n)
110     return (memset (mem, ch, n));
113 /**
114  *  @brief
115  *      The memcpy function used for both stages of the ibl
116  */
117 void *iblMemcpy (void *s1, const void *s2, Uint32 n)
119     return (memcpy (s1, s2, n));
123 /**
124  *  @brief
125  *      Ones complement addition
126  */
127 inline uint16 onesComplementAdd (uint16 value1, uint16 value2)
129   uint32 result;
131   result = (uint32)value1 + (uint32)value2;
133   result = (result >> 16) + (result & 0xFFFF); /* add in carry   */
134   result += (result >> 16);                    /* maybe one more */
135   return ((uint16)result);
139 /**
140  *  @brief
141  *      Ones complement checksum computation 
142  */
143 uint16 onesComplementChksum (uint16 * restrict p_data, uint16 len)
145   uint16 chksum = 0;
147   while (len > 0)
148   {
149     chksum = onesComplementAdd(chksum, *p_data);
150     p_data++;
151     len--;
152   }
153   return (chksum);
154
158 /**
159  *  @brief
160  *      Do a 4 byte endian swap
161  */
162 uint32 swap32val (uint32 v)
164     v =  (((v >> 24) & 0xff) <<  0)  |
165          (((v >> 16) & 0xff) <<  8)  |
166          (((v >>  8) & 0xff) << 16)  |
167          (((v >>  0) & 0xff) << 24);
169     return (v);
173 /**
174  *  @brief
175  *      Do a 2 byte endian swap
176  */
177 uint16 swap16val (uint16 v)
179     v = (((v >> 8) & 0xff) << 0)  |
180         (((v >> 0) & 0xff) << 8);
182     return (v);
186 /**
187  *  @brief
188  *  Do an endian swap on the ibl structure
189  */
190 void iblSwap (void)
192     int i;
194     ibl.iblMagic = swap32val (ibl.iblMagic);
196     for (i = 0; i < ibl_N_PLL_CFGS; i++)  {
197         ibl.pllConfig[i].doEnable      = swap16val (ibl.pllConfig[i].doEnable);
198         ibl.pllConfig[i].prediv        = swap32val (ibl.pllConfig[i].prediv);
199         ibl.pllConfig[i].mult          = swap32val (ibl.pllConfig[i].mult);
200         ibl.pllConfig[i].postdiv       = swap32val (ibl.pllConfig[i].postdiv);
201         ibl.pllConfig[i].pllOutFreqMhz = swap32val (ibl.pllConfig[i].pllOutFreqMhz);
202     }
204     ibl.ddrConfig.configDdr = swap16val (ibl.ddrConfig.configDdr);
206 #define targetEmifType()   ibl_EMIF_TYPE_40
208     if (targetEmifType() == ibl_EMIF_TYPE_31)  { 
209         ibl.ddrConfig.uEmif.emif3p1.sdcfg  = swap32val(ibl.ddrConfig.uEmif.emif3p1.sdcfg);
210         ibl.ddrConfig.uEmif.emif3p1.sdrfc  = swap32val(ibl.ddrConfig.uEmif.emif3p1.sdrfc);
211         ibl.ddrConfig.uEmif.emif3p1.sdtim1 = swap32val(ibl.ddrConfig.uEmif.emif3p1.sdtim1);
212         ibl.ddrConfig.uEmif.emif3p1.sdtim2 = swap32val(ibl.ddrConfig.uEmif.emif3p1.sdtim2);
213         ibl.ddrConfig.uEmif.emif3p1.dmcctl = swap32val(ibl.ddrConfig.uEmif.emif3p1.dmcctl);
214        
215     } else if (targetEmifType() == ibl_EMIF_TYPE_40)  {
216         ibl.ddrConfig.uEmif.emif4p0.registerMask          = swap32val(ibl.ddrConfig.uEmif.emif4p0.registerMask);
217         ibl.ddrConfig.uEmif.emif4p0.sdRamConfig           = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamConfig);
218         ibl.ddrConfig.uEmif.emif4p0.sdRamConfig2          = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamConfig2);
219         ibl.ddrConfig.uEmif.emif4p0.sdRamRefreshCtl       = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamRefreshCtl);
220         ibl.ddrConfig.uEmif.emif4p0.sdRamTiming1          = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamTiming1);
221         ibl.ddrConfig.uEmif.emif4p0.sdRamTiming2          = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamTiming2);
222         ibl.ddrConfig.uEmif.emif4p0.sdRamTiming3          = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamTiming3);
223         ibl.ddrConfig.uEmif.emif4p0.lpDdrNvmTiming        = swap32val(ibl.ddrConfig.uEmif.emif4p0.lpDdrNvmTiming);
224         ibl.ddrConfig.uEmif.emif4p0.powerManageCtl        = swap32val(ibl.ddrConfig.uEmif.emif4p0.powerManageCtl);
225         ibl.ddrConfig.uEmif.emif4p0.iODFTTestLogic        = swap32val(ibl.ddrConfig.uEmif.emif4p0.iODFTTestLogic);
226         ibl.ddrConfig.uEmif.emif4p0.performCountCfg       = swap32val(ibl.ddrConfig.uEmif.emif4p0.performCountCfg);
227         ibl.ddrConfig.uEmif.emif4p0.performCountMstRegSel = swap32val(ibl.ddrConfig.uEmif.emif4p0.performCountMstRegSel);
228         ibl.ddrConfig.uEmif.emif4p0.readIdleCtl           = swap32val(ibl.ddrConfig.uEmif.emif4p0.readIdleCtl);
229         ibl.ddrConfig.uEmif.emif4p0.sysVbusmIntEnSet      = swap32val(ibl.ddrConfig.uEmif.emif4p0.sysVbusmIntEnSet);
230         ibl.ddrConfig.uEmif.emif4p0.sdRamOutImpdedCalCfg  = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamOutImpdedCalCfg);
231         ibl.ddrConfig.uEmif.emif4p0.tempAlterCfg          = swap32val(ibl.ddrConfig.uEmif.emif4p0.tempAlterCfg);
232         ibl.ddrConfig.uEmif.emif4p0.ddrPhyCtl1            = swap32val(ibl.ddrConfig.uEmif.emif4p0.ddrPhyCtl1);
233         ibl.ddrConfig.uEmif.emif4p0.ddrPhyCtl2            = swap32val(ibl.ddrConfig.uEmif.emif4p0.ddrPhyCtl2);
234         ibl.ddrConfig.uEmif.emif4p0.priClassSvceMap       = swap32val(ibl.ddrConfig.uEmif.emif4p0.priClassSvceMap);
235         ibl.ddrConfig.uEmif.emif4p0.mstId2ClsSvce1Map     = swap32val(ibl.ddrConfig.uEmif.emif4p0.mstId2ClsSvce1Map);
236         ibl.ddrConfig.uEmif.emif4p0.mstId2ClsSvce2Map     = swap32val(ibl.ddrConfig.uEmif.emif4p0.mstId2ClsSvce2Map);
237         ibl.ddrConfig.uEmif.emif4p0.eccCtl                = swap32val(ibl.ddrConfig.uEmif.emif4p0.eccCtl);
238         ibl.ddrConfig.uEmif.emif4p0.eccRange1             = swap32val(ibl.ddrConfig.uEmif.emif4p0.eccRange1);
239         ibl.ddrConfig.uEmif.emif4p0.eccRange2             = swap32val(ibl.ddrConfig.uEmif.emif4p0.eccRange2);
240         ibl.ddrConfig.uEmif.emif4p0.rdWrtExcThresh        = swap32val(ibl.ddrConfig.uEmif.emif4p0.rdWrtExcThresh);
241     }
242     
244     for (i = 0; i < ibl_N_ETH_PORTS; i++)  {
245         ibl.ethConfig[i].ethPriority        = swap32val (ibl.ethConfig[i].ethPriority);
246         ibl.ethConfig[i].port               = swap32val (ibl.ethConfig[i].port);
247         ibl.ethConfig[i].doBootp            = swap16val (ibl.ethConfig[i].doBootp);
248         ibl.ethConfig[i].useBootpServerIp   = swap16val (ibl.ethConfig[i].useBootpServerIp);
249         ibl.ethConfig[i].useBootpFileName   = swap16val (ibl.ethConfig[i].useBootpFileName);
250         ibl.ethConfig[i].bootFormat         = swap32val (ibl.ethConfig[i].bootFormat);
251         ibl.ethConfig[i].blob.startAddress  = swap32val (ibl.ethConfig[i].blob.startAddress);
252         ibl.ethConfig[i].blob.sizeBytes     = swap32val (ibl.ethConfig[i].blob.sizeBytes);
253         ibl.ethConfig[i].blob.branchAddress = swap32val (ibl.ethConfig[i].blob.branchAddress);
255         ibl.sgmiiConfig[i].adviseAbility = swap32val (ibl.sgmiiConfig[i].adviseAbility);
256         ibl.sgmiiConfig[i].control       = swap32val (ibl.sgmiiConfig[i].control);
257         ibl.sgmiiConfig[i].txConfig      = swap32val (ibl.sgmiiConfig[i].txConfig);
258         ibl.sgmiiConfig[i].rxConfig      = swap32val (ibl.sgmiiConfig[i].rxConfig);
259         ibl.sgmiiConfig[i].auxConfig     = swap32val (ibl.sgmiiConfig[i].auxConfig);
260     }
262     ibl.mdioConfig.nMdioOps   = swap16val (ibl.mdioConfig.nMdioOps);
263     ibl.mdioConfig.mdioClkDiv = swap16val (ibl.mdioConfig.mdioClkDiv);
264     ibl.mdioConfig.interDelay = swap32val (ibl.mdioConfig.interDelay);
266     for (i = 0; i < ibl_N_MDIO_CFGS; i++)
267         ibl.mdioConfig.mdio[i] = swap32val (ibl.mdioConfig.mdio[i]);
269     ibl.nandConfig.nandPriority       = swap32val (ibl.nandConfig.nandPriority);
270     ibl.nandConfig.bootFormat         = swap32val (ibl.nandConfig.bootFormat);
271     ibl.nandConfig.interface          = swap32val (ibl.nandConfig.interface);
272     ibl.nandConfig.blob.startAddress  = swap32val (ibl.nandConfig.blob.startAddress);
273     ibl.nandConfig.blob.sizeBytes     = swap32val (ibl.nandConfig.blob.sizeBytes);
274     ibl.nandConfig.blob.branchAddress = swap32val (ibl.nandConfig.blob.branchAddress);
276     ibl.nandConfig.nandInfo.busWidthBits  = swap32val (ibl.nandConfig.nandInfo.busWidthBits);
277     ibl.nandConfig.nandInfo.pageSizeBytes = swap32val (ibl.nandConfig.nandInfo.pageSizeBytes);
278     ibl.nandConfig.nandInfo.pageEccBytes  = swap32val (ibl.nandConfig.nandInfo.pageEccBytes);
279     ibl.nandConfig.nandInfo.pagesPerBlock = swap32val (ibl.nandConfig.nandInfo.pagesPerBlock);
280     ibl.nandConfig.nandInfo.totalBlocks   = swap32val (ibl.nandConfig.nandInfo.totalBlocks);
281     ibl.nandConfig.nandInfo.addressBytes  = swap32val (ibl.nandConfig.nandInfo.addressBytes);
282     ibl.nandConfig.nandInfo.lsbFirst      = swap16val (ibl.nandConfig.nandInfo.lsbFirst);
283     ibl.nandConfig.nandInfo.blockOffset   = swap32val (ibl.nandConfig.nandInfo.blockOffset);
284     ibl.nandConfig.nandInfo.pageOffset    = swap32val (ibl.nandConfig.nandInfo.pageOffset);
285     ibl.nandConfig.nandInfo.columnOffset  = swap32val (ibl.nandConfig.nandInfo.columnOffset);
286     ibl.nandConfig.nandInfo.postCommand   = swap16val (ibl.nandConfig.nandInfo.postCommand);
288     ibl.spiConfig.addrWidth  = swap16val (ibl.spiConfig.addrWidth);
289     ibl.spiConfig.nPins      = swap16val (ibl.spiConfig.nPins);
290     ibl.spiConfig.csel       = swap16val (ibl.spiConfig.csel);
291     ibl.spiConfig.c2tdelay   = swap16val (ibl.spiConfig.c2tdelay);
292     ibl.spiConfig.busFreqMHz = swap16val (ibl.spiConfig.busFreqMHz);
294     ibl.chkSum = swap16val (ibl.chkSum);
297         
299 /**
300  *  @brief
301  *      The init load context consists of the address of the next block 
302  *      to read, and a simple fifo-ish structure holding any existing data.
303  *
304  *      A full fifo is not defined here. The individual init load blocks
305  *      (I2C, SPI NOR, SPI NAND) will poke the structure values directly
306  *      to minimize the compiled code size. Most notably is the absence
307  *      of the write function. This fifo will always be completely emptied
308  *      before any writes are done, so writes are always done from the top.
309  */
310 uint32 iFifoIn  = 0;
311 uint32 iFifoOut = 0;
312 uint8  iData[I_MAX_BLOCK_SIZE];
314 /**
315  *  @brief
316  *      Checkum calculation. 16 bit values constructed from received bytes
317  *      always in big endian format, regardless of the endianness of the device 
318  */
319 uint16 iSum[I_MAX_BLOCK_SIZE >> 1];
322 /**
323  *  @brief
324  *      Return the number of elements in the fifo
325  */
326 Uint32 iFifoCount (void)
328     Int32 count;
330     if (iFifoIn >= iFifoOut)
331         count = iFifoIn - iFifoOut;
332     else
333         count = iFifoIn + I_MAX_BLOCK_SIZE - iFifoOut;
335     return (count);
339     
340 /**
341  *  @brief
342  *      Read a byte from the fifo
343  */
344 Uint8 iFifoRead(void)
346     Uint8 v;
348     v = iData[iFifoOut];
350     iFifoOut += 1;
352     if (iFifoOut == iFifoIn)
353         iFifoOut = iFifoIn = 0;
355     if (iFifoOut >= I_MAX_BLOCK_SIZE)
356         iFifoOut = 0;
358     return (v);
363 #define iblBITMASK(x,y)      (   (   (  ((UINT32)1 << (((UINT32)x)-((UINT32)y)+(UINT32)1) ) - (UINT32)1 )   )   <<  ((UINT32)y)   )
364 #define iblREAD_BITFIELD(z,x,y)   (((UINT32)z) & iblBITMASK(x,y)) >> (y)
365 /**
366  *  @brief
367  *      Return the lower 16 bits of a 32 bit value. A function is used (with cross-function optomization off)
368  *      which results in an endian independent version
369  */
370 uint16 readLower16 (uint32 v)
372     return (iblREAD_BITFIELD(v,15,0));
376 /**
377  * @brief
378  *      Return the upper 16 bits of a 32 bit value. A function is used to force an endian independent version
379  */
380 uint16 readUpper16 (uint32 v)
382   return (iblREAD_BITFIELD(v,31,16));
387 /**
388  *  @brief
389  *      The main function
390  *
391  *  @details
392  *      The ibl configuration parameters are read from the i2c, 
393  *      followed by the i2c mapping information. The second stage
394  *      of the IBL is then loaded, and execution transferred 
395  *      to the second stage.
396  */
397 void main (void)
400     int32        bootDevice;
401     uint32       entry;
402     void         (*exit)();
404     BOOT_MODULE_FXN_TABLE *bFxnTbl;
406     memset (&iblStatus, 0, sizeof(iblStatus_t));
407     iblStatus.iblMagic     = ibl_MAGIC_VALUE;
408     iblStatus.iblVersion   = ibl_VERSION;
409     iblStatus.activePeriph = ibl_ACTIVE_PERIPH_I2C;
412     /* Determine the boot device to read from */
413     bootDevice = deviceReadBootDevice();
415     switch (bootDevice)  {
417 #ifndef EXCLUDE_I2C
418     case BOOT_DEVICE_I2C:       bFxnTbl = iblInitI2c ();
419                                 break;
420 #endif
422 #ifndef EXCLUDE_NOR_SPI
423     case BOOT_DEVICE_SPI_NOR:   bFxnTbl = iblInitSpiNor ();
424                                 break;
425 #endif
427 #ifndef EXCLUDE_NAND_SPI
428     case BOOT_DEVICE_SPI_NAND:  bFxnTbl = iblInitSpiNand ();
429                                 break;
430 #endif
432     default:                    iblStatus.iblFail = ibl_FAIL_CODE_INVALID_INIT_DEVICE;
433                                 for (;;);
435     }
436     
438     /* Pll configuration is device specific */
439     devicePllConfig ();
442     /* Pass control to the boot table processor */
443     iblBootBtbl (bFxnTbl, &entry);
445     if (btblWrapEcode != 0)  {
446         iblStatus.iblFail = ibl_FAIL_CODE_BTBL_FAIL;
447         for (;;);
448     }
450     /* jump to the exit point, which will be the entry point for the full IBL */
451     exit = (void (*)())entry;
452     (*exit)();