]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/ibl.git/blob - src/main/iblinit.c
Added NOR over I2C and POST I2C boot
[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);
207     if (targetEmifType() == ibl_EMIF_TYPE_31)  { 
208         ibl.ddrConfig.uEmif.emif3p1.sdcfg  = swap32val(ibl.ddrConfig.uEmif.emif3p1.sdcfg);
209         ibl.ddrConfig.uEmif.emif3p1.sdrfc  = swap32val(ibl.ddrConfig.uEmif.emif3p1.sdrfc);
210         ibl.ddrConfig.uEmif.emif3p1.sdtim1 = swap32val(ibl.ddrConfig.uEmif.emif3p1.sdtim1);
211         ibl.ddrConfig.uEmif.emif3p1.sdtim2 = swap32val(ibl.ddrConfig.uEmif.emif3p1.sdtim2);
212         ibl.ddrConfig.uEmif.emif3p1.dmcctl = swap32val(ibl.ddrConfig.uEmif.emif3p1.dmcctl);
213        
214     } else if (targetEmifType() == ibl_EMIF_TYPE_40)  {
215         ibl.ddrConfig.uEmif.emif4p0.registerMask          = swap32val(ibl.ddrConfig.uEmif.emif4p0.registerMask);
216         ibl.ddrConfig.uEmif.emif4p0.sdRamConfig           = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamConfig);
217         ibl.ddrConfig.uEmif.emif4p0.sdRamConfig2          = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamConfig2);
218         ibl.ddrConfig.uEmif.emif4p0.sdRamRefreshCtl       = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamRefreshCtl);
219         ibl.ddrConfig.uEmif.emif4p0.sdRamTiming1          = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamTiming1);
220         ibl.ddrConfig.uEmif.emif4p0.sdRamTiming2          = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamTiming2);
221         ibl.ddrConfig.uEmif.emif4p0.sdRamTiming3          = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamTiming3);
222         ibl.ddrConfig.uEmif.emif4p0.lpDdrNvmTiming        = swap32val(ibl.ddrConfig.uEmif.emif4p0.lpDdrNvmTiming);
223         ibl.ddrConfig.uEmif.emif4p0.powerManageCtl        = swap32val(ibl.ddrConfig.uEmif.emif4p0.powerManageCtl);
224         ibl.ddrConfig.uEmif.emif4p0.iODFTTestLogic        = swap32val(ibl.ddrConfig.uEmif.emif4p0.iODFTTestLogic);
225         ibl.ddrConfig.uEmif.emif4p0.performCountCfg       = swap32val(ibl.ddrConfig.uEmif.emif4p0.performCountCfg);
226         ibl.ddrConfig.uEmif.emif4p0.performCountMstRegSel = swap32val(ibl.ddrConfig.uEmif.emif4p0.performCountMstRegSel);
227         ibl.ddrConfig.uEmif.emif4p0.readIdleCtl           = swap32val(ibl.ddrConfig.uEmif.emif4p0.readIdleCtl);
228         ibl.ddrConfig.uEmif.emif4p0.sysVbusmIntEnSet      = swap32val(ibl.ddrConfig.uEmif.emif4p0.sysVbusmIntEnSet);
229         ibl.ddrConfig.uEmif.emif4p0.sdRamOutImpdedCalCfg  = swap32val(ibl.ddrConfig.uEmif.emif4p0.sdRamOutImpdedCalCfg);
230         ibl.ddrConfig.uEmif.emif4p0.tempAlterCfg          = swap32val(ibl.ddrConfig.uEmif.emif4p0.tempAlterCfg);
231         ibl.ddrConfig.uEmif.emif4p0.ddrPhyCtl1            = swap32val(ibl.ddrConfig.uEmif.emif4p0.ddrPhyCtl1);
232         ibl.ddrConfig.uEmif.emif4p0.ddrPhyCtl2            = swap32val(ibl.ddrConfig.uEmif.emif4p0.ddrPhyCtl2);
233         ibl.ddrConfig.uEmif.emif4p0.priClassSvceMap       = swap32val(ibl.ddrConfig.uEmif.emif4p0.priClassSvceMap);
234         ibl.ddrConfig.uEmif.emif4p0.mstId2ClsSvce1Map     = swap32val(ibl.ddrConfig.uEmif.emif4p0.mstId2ClsSvce1Map);
235         ibl.ddrConfig.uEmif.emif4p0.mstId2ClsSvce2Map     = swap32val(ibl.ddrConfig.uEmif.emif4p0.mstId2ClsSvce2Map);
236         ibl.ddrConfig.uEmif.emif4p0.eccCtl                = swap32val(ibl.ddrConfig.uEmif.emif4p0.eccCtl);
237         ibl.ddrConfig.uEmif.emif4p0.eccRange1             = swap32val(ibl.ddrConfig.uEmif.emif4p0.eccRange1);
238         ibl.ddrConfig.uEmif.emif4p0.eccRange2             = swap32val(ibl.ddrConfig.uEmif.emif4p0.eccRange2);
239         ibl.ddrConfig.uEmif.emif4p0.rdWrtExcThresh        = swap32val(ibl.ddrConfig.uEmif.emif4p0.rdWrtExcThresh);
240     }
243     for (i = 0; i < ibl_N_ETH_PORTS; i++)  {
244         ibl.sgmiiConfig[i].configure     = swap32val(ibl.sgmiiConfig[i].configure);
245         ibl.sgmiiConfig[i].adviseAbility = swap32val(ibl.sgmiiConfig[i].adviseAbility);
246         ibl.sgmiiConfig[i].control       = swap32val(ibl.sgmiiConfig[i].control);
247         ibl.sgmiiConfig[i].txConfig      = swap32val(ibl.sgmiiConfig[i].txConfig);
248         ibl.sgmiiConfig[i].rxConfig      = swap32val(ibl.sgmiiConfig[i].rxConfig);
249         ibl.sgmiiConfig[i].auxConfig     = swap32val(ibl.sgmiiConfig[i].auxConfig);
250     }
251     
253     ibl.mdioConfig.nMdioOps   = swap16val (ibl.mdioConfig.nMdioOps);
254     ibl.mdioConfig.mdioClkDiv = swap16val (ibl.mdioConfig.mdioClkDiv);
255     ibl.mdioConfig.interDelay = swap32val (ibl.mdioConfig.interDelay);
257     for (i = 0; i < ibl_N_MDIO_CFGS; i++)
258         ibl.mdioConfig.mdio[i] = swap32val (ibl.mdioConfig.mdio[i]);
261     ibl.spiConfig.addrWidth  = swap16val(ibl.spiConfig.addrWidth);
262     ibl.spiConfig.nPins      = swap16val(ibl.spiConfig.nPins);
263     ibl.spiConfig.mode       = swap16val(ibl.spiConfig.mode);
264     ibl.spiConfig.csel       = swap16val(ibl.spiConfig.csel);
265     ibl.spiConfig.c2tdelay   = swap16val(ibl.spiConfig.c2tdelay);
266     ibl.spiConfig.busFreqMHz = swap16val(ibl.spiConfig.busFreqMHz);
268     for (i = 0; i < ibl_MAX_EMIF_PMEM; i++)  {
269         ibl.emifConfig[i].csSpace    = swap16val(ibl.emifConfig[i].csSpace);
270         ibl.emifConfig[i].busWidth   = swap16val(ibl.emifConfig[i].busWidth);
271         ibl.emifConfig[i].waitEnable = swap32val(ibl.emifConfig[i].waitEnable);
272     }
275     for (i = 0; i < ibl_N_BOOT_MODES; i++)  {
276         ibl.bootModes[i].bootMode = swap32val(ibl.bootModes[i].bootMode);
277         ibl.bootModes[i].priority = swap32val(ibl.bootModes[i].priority);
278         ibl.bootModes[i].port     = swap32val(ibl.bootModes[i].port);
280         if (ibl.bootModes[i].bootMode == ibl_BOOT_MODE_TFTP)  {
281             ibl.bootModes[i].u.ethBoot.doBootp            = swap32val(ibl.bootModes[i].u.ethBoot.doBootp);
282             ibl.bootModes[i].u.ethBoot.useBootpServerIp   = swap32val(ibl.bootModes[i].u.ethBoot.useBootpServerIp);
283             ibl.bootModes[i].u.ethBoot.useBootpFileName   = swap32val(ibl.bootModes[i].u.ethBoot.useBootpFileName);
284             ibl.bootModes[i].u.ethBoot.bootFormat         = swap32val(ibl.bootModes[i].u.ethBoot.bootFormat);
285             ibl.bootModes[i].u.ethBoot.blob.startAddress  = swap32val(ibl.bootModes[i].u.ethBoot.blob.startAddress);
286             ibl.bootModes[i].u.ethBoot.blob.sizeBytes     = swap32val(ibl.bootModes[i].u.ethBoot.blob.sizeBytes);
287             ibl.bootModes[i].u.ethBoot.blob.branchAddress = swap32val(ibl.bootModes[i].u.ethBoot.blob.branchAddress);
289         }  else if (ibl.bootModes[i].bootMode == ibl_BOOT_MODE_NAND)  {
290             ibl.bootModes[i].u.nandBoot.bootFormat             = swap32val(ibl.bootModes[i].u.nandBoot.bootFormat);
291             ibl.bootModes[i].u.nandBoot.bootAddress            = swap32val(ibl.bootModes[i].u.nandBoot.bootAddress);
292             ibl.bootModes[i].u.nandBoot.interface              = swap32val(ibl.bootModes[i].u.nandBoot.interface);
293             ibl.bootModes[i].u.nandBoot.blob.startAddress      = swap32val(ibl.bootModes[i].u.nandBoot.blob.startAddress);
294             ibl.bootModes[i].u.nandBoot.blob.sizeBytes         = swap32val(ibl.bootModes[i].u.nandBoot.blob.sizeBytes);
295             ibl.bootModes[i].u.nandBoot.blob.branchAddress     = swap32val(ibl.bootModes[i].u.nandBoot.blob.branchAddress);
296             ibl.bootModes[i].u.nandBoot.nandInfo.busWidthBits  = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.busWidthBits);
297             ibl.bootModes[i].u.nandBoot.nandInfo.pageSizeBytes = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.pageSizeBytes);
298             ibl.bootModes[i].u.nandBoot.nandInfo.pageEccBytes  = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.pageEccBytes);
299             ibl.bootModes[i].u.nandBoot.nandInfo.pagesPerBlock = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.pagesPerBlock);
300             ibl.bootModes[i].u.nandBoot.nandInfo.totalBlocks   = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.totalBlocks);
301             ibl.bootModes[i].u.nandBoot.nandInfo.addressBytes  = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.addressBytes);
302             ibl.bootModes[i].u.nandBoot.nandInfo.lsbFirst      = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.lsbFirst);
303             ibl.bootModes[i].u.nandBoot.nandInfo.blockOffset   = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.blockOffset);
304             ibl.bootModes[i].u.nandBoot.nandInfo.pageOffset    = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.pageOffset);
305             ibl.bootModes[i].u.nandBoot.nandInfo.columnOffset  = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.columnOffset);
306             ibl.bootModes[i].u.nandBoot.nandInfo.postCommand   = swap32val(ibl.bootModes[i].u.nandBoot.nandInfo.postCommand);
308         }  else if (ibl.bootModes[i].bootMode == ibl_BOOT_MODE_NOR)  {
309             ibl.bootModes[i].u.norBoot.bootFormat         = swap32val(ibl.bootModes[i].u.norBoot.bootFormat);
310             ibl.bootModes[i].u.norBoot.bootAddress        = swap32val(ibl.bootModes[i].u.norBoot.bootAddress);
311             ibl.bootModes[i].u.norBoot.interface          = swap32val(ibl.bootModes[i].u.norBoot.interface);
312             ibl.bootModes[i].u.norBoot.blob.startAddress  = swap32val(ibl.bootModes[i].u.norBoot.blob.startAddress);
313             ibl.bootModes[i].u.norBoot.blob.sizeBytes     = swap32val(ibl.bootModes[i].u.norBoot.blob.sizeBytes);
314             ibl.bootModes[i].u.norBoot.blob.branchAddress = swap32val(ibl.bootModes[i].u.norBoot.blob.branchAddress);
316         }
318     }
320     ibl.chkSum = swap16val (ibl.chkSum);
323         
325 /**
326  *  @brief
327  *      The init load context consists of the address of the next block 
328  *      to read, and a simple fifo-ish structure holding any existing data.
329  *
330  *      A full fifo is not defined here. The individual init load blocks
331  *      (I2C, SPI NOR, SPI NAND) will poke the structure values directly
332  *      to minimize the compiled code size. Most notably is the absence
333  *      of the write function. This fifo will always be completely emptied
334  *      before any writes are done, so writes are always done from the top.
335  */
336 uint32 iFifoIn  = 0;
337 uint32 iFifoOut = 0;
338 uint8  iData[I_MAX_BLOCK_SIZE];
340 /**
341  *  @brief
342  *      Checkum calculation. 16 bit values constructed from received bytes
343  *      always in big endian format, regardless of the endianness of the device 
344  */
345 uint16 iSum[I_MAX_BLOCK_SIZE >> 1];
348 /**
349  *  @brief
350  *      Return the number of elements in the fifo
351  */
352 Uint32 iFifoCount (void)
354     Int32 count;
356     if (iFifoIn >= iFifoOut)
357         count = iFifoIn - iFifoOut;
358     else
359         count = iFifoIn + I_MAX_BLOCK_SIZE - iFifoOut;
361     return (count);
365     
366 /**
367  *  @brief
368  *      Read a byte from the fifo
369  */
370 Uint8 iFifoRead(void)
372     Uint8 v;
374     v = iData[iFifoOut];
376     iFifoOut += 1;
378     if (iFifoOut == iFifoIn)
379         iFifoOut = iFifoIn = 0;
381     if (iFifoOut >= I_MAX_BLOCK_SIZE)
382         iFifoOut = 0;
384     return (v);
389 #define iblBITMASK(x,y)      (   (   (  ((UINT32)1 << (((UINT32)x)-((UINT32)y)+(UINT32)1) ) - (UINT32)1 )   )   <<  ((UINT32)y)   )
390 #define iblREAD_BITFIELD(z,x,y)   (((UINT32)z) & iblBITMASK(x,y)) >> (y)
391 /**
392  *  @brief
393  *      Return the lower 16 bits of a 32 bit value. A function is used (with cross-function optomization off)
394  *      which results in an endian independent version
395  */
396 uint16 readLower16 (uint32 v)
398     return (iblREAD_BITFIELD(v,15,0));
402 /**
403  * @brief
404  *      Return the upper 16 bits of a 32 bit value. A function is used to force an endian independent version
405  */
406 uint16 readUpper16 (uint32 v)
408   return (iblREAD_BITFIELD(v,31,16));
413 /**
414  *  @brief
415  *      The main function
416  *
417  *  @details
418  *      The ibl configuration parameters are read from the i2c, 
419  *      followed by the i2c mapping information. The second stage
420  *      of the IBL is then loaded, and execution transferred 
421  *      to the second stage.
422  */
423 void main (void)
426     int32        bootDevice;
427     uint32       entry;
428     void         (*exit)();
430     BOOT_MODULE_FXN_TABLE *bFxnTbl;
432     memset (&iblStatus, 0, sizeof(iblStatus_t));
433     iblStatus.iblMagic     = ibl_MAGIC_VALUE;
434     iblStatus.iblVersion   = ibl_VERSION;
435     iblStatus.activeDevice = ibl_ACTIVE_DEVICE_I2C;
438     /* Determine the boot device to read from */
439     bootDevice = deviceReadBootDevice();
441     switch (bootDevice)  {
443 #ifndef EXCLUDE_I2C
444     case BOOT_DEVICE_I2C:       bFxnTbl = iblInitI2c ();
445                                 break;
446 #endif
448 #ifndef EXCLUDE_NOR_SPI
449     case BOOT_DEVICE_SPI_NOR:   bFxnTbl = iblInitSpiNor ();
450                                 break;
451 #endif
454     default:                    iblStatus.iblFail = ibl_FAIL_CODE_INVALID_INIT_DEVICE;
455                                 for (;;);
457     }
458     
460     /* Pll configuration is device specific */
461     devicePllConfig ();
463     /* iblReEnterRom () */
464     if (IBL_REENTER_ROM)
465     {
466         iblReEnterRom ();
467     }
469     /* Pass control to the boot table processor */
470     iblBootBtbl (bFxnTbl, &entry);
472     if (btblWrapEcode != 0)  {
473         iblStatus.iblFail = ibl_FAIL_CODE_BTBL_FAIL;
474         for (;;);
475     }
477     /* jump to the exit point, which will be the entry point for the full IBL */
478     exit = (void (*)())entry;
479     (*exit)();