]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/ibl.git/blob - src/main/iblmain.c
UART: Start adding UART code
[keystone-rtos/ibl.git] / src / main / iblmain.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 */
38 /*****************************************************************************************
39  * FILE PURPOSE: Perform the top level boot
40  *****************************************************************************************
41  * FILE NAME: iblmain.c
42  *
43  * DESCRIPTION: The top level boot examines the boot configuration and performs boot
44  *                              based on this configuration
45  *
46  * @file iblmain.c
47  *
48  * @brief
49  *   This file is used to launch a boot based on the boot configuration structure
50  *
51  *****************************************************************************************/
52 #include "ibl.h"
53 #include "iblloc.h"
54 #include "iblcfg.h"
55 #include "device.h"
56 #include "ethboot.h"
57 #include "nandboot.h"
58 #include "norboot.h"
59 #include "bis.h"
60 #include "coffwrap.h"
61 #include "iblbtbl.h"
62 #include "iblblob.h"
63 #include "timer.h"
64 #include "i2c.h"
65 #include "spi_api.h"
66 #include "ibl_elf.h"
67 #include <string.h>
69 extern cregister unsigned int IER;
71 uint32 iblEndianIdx = 0;
72 uint32 iblImageIdx = 0;
74 /**
75  *  @brief
76  *      Data structures shared between the 1st and 2nd stage IBL load
77  *      are declared in a single header file, included in both stages
78  */
79 #include "iblStage.h"
83 /* Eat printfs */
84 void mprintf(char *x, ...) { }
86 /**
87  * @b Description
88  * @n
89  *
90  *  Returns TRUE if the input priority is valid and enabled
91  */
92 BOOL iblPriorityIsValid (uint32 priority)
93 {
94     if ( (priority >= ibl_HIGHEST_PRIORITY)  &&
95          (priority <= ibl_LOWEST_PRIORITY)   )
97         return (TRUE);
100     return (FALSE);
104 /**
105  * @b Description
106  * @n
107  *
108  *  Returns TRUE if the mac address is 0
109  */
110 BOOL iblMacAddrIsZero (uint8 *maddr)
112     int32 i;
114     for (i = 0; i < 6; i++)
115         if (maddr[i] != 0)
116             return (FALSE);
118     return (TRUE);
122 /**
123  *  @b Description
124  *  @n
125  *  
126  *  For NAND and NOR boots, configure the specified peripheral or memory interface
127  */
128 void iblPmemCfg (int32 interface, int32 port, bool enableNand)
130     int32 ret;
132     switch (interface)  {
134         #if (!defined(EXCLUDE_NAND_GPIO))
136         case ibl_PMEM_IF_GPIO:
137                 ret = devicePowerPeriph (TARGET_PWR_GPIO);
138                 break;
139         #endif
141         #if (!defined(EXCLUDE_NOR_SPI) && !defined(EXCLUDE_NAND_SPI))
143             case ibl_PMEM_IF_SPI:  {
145                     Uint32      v;
146                     spiConfig_t cfg;
148                     ret = devicePowerPeriph (TARGET_PWR_SPI);
149                     if (ret != 0)
150                         break;
152                     cfg.port      = port;
153                     cfg.mode      = ibl.spiConfig.mode;
154                     cfg.addrWidth = ibl.spiConfig.addrWidth;
155                     cfg.npin      = ibl.spiConfig.nPins;
156                     cfg.csel      = ibl.spiConfig.csel;
157                     cfg.c2tdelay  = ibl.spiConfig.c2tdelay;
159                     /* On c66x devices the PLL module has a built in divide by 6, and the SPI
160                      * has a maximum clock divider value of 0xff */
161                     v = ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz / (DEVICE_SPI_MOD_DIVIDER * ibl.spiConfig.busFreqMHz);
162                     if (v > 0xff)
163                         v = 0xff;
165                     cfg.clkdiv =  (UINT16) v;
167                     ret = hwSpiConfig (&cfg);
168                     if (ret != 0)  {
169                         iblStatus.iblFail = ibl_FAIL_CODE_SPI_PARAMS;
170                         return;
171                     }
173                 }
174                 break;
175         #endif
177         #if (!defined(EXCLUDE_NOR_EMIF) || !defined(EXCLUDE_NAND_EMIF))
179             case ibl_PMEM_IF_CHIPSEL_2:
180             case ibl_PMEM_IF_CHIPSEL_3:
181             case ibl_PMEM_IF_CHIPSEL_4:
182             case ibl_PMEM_IF_CHIPSEL_5:  {
184                     int i;
186                     /* Locate the configuration corresponding to this chip select space */
187                     for (i = 0; i < ibl_MAX_EMIF_PMEM; i++) 
188                         if (ibl.emifConfig[i].csSpace == interface)
189                             break;
190                         
191                     if (i == ibl_MAX_EMIF_PMEM)  {
192                         iblStatus.iblFail = ibl_FAIL_CODE_NO_EMIF_CFG;
193                         return;
194                     }
196                     ret = devicePowerPeriph (TARGET_PWR_EMIF);
197                     if (ret != 0)
198                         break;
200                     if (hwEmif25Init (interface, ibl.emifConfig[i].busWidth, ibl.emifConfig[i].waitEnable, enableNand) != 0)
201                         iblStatus.iblFail = ibl_FAIL_CODE_EMIF_CFG_FAIL;
203                 }
204                 break;
206             #endif
208             default:
212                 iblStatus.iblFail = ibl_FAIL_CODE_INVALID_NAND_PERIPH;
213                 return;
214     }
216     if (ret != 0)  {
217         iblStatus.iblFail = ibl_FAIL_CODE_PERIPH_POWER_UP;
218         return;
219     }
225 /**
226  * @b Description
227  * @n
228  *
229  * The main function kicks off the boot. If it does not find the magic value in the
230  *     configuration array then default values are loaded. This default load
231  *     is done only once at the start of boot. 
232  *
233  * @retval
234  *  None
235  */
236 void main (void)
238     int32 i, j;
239     UINT32 v, boot_mode_idx, boot_para_idx;
241     /* Initialize the status structure */
242     iblMemset (&iblStatus, 0, sizeof(iblStatus_t));
243     iblStatus.iblMagic   = ibl_MAGIC_VALUE;
244     iblStatus.iblVersion = ibl_VERSION;
247     /* Power up the timer */
248     devicePowerPeriph (TARGET_PWR_TIMER_0);
250     /* Initialize the system timer (software tracking of the hardware timer state) */
251     timer_init ();
253     /* Load default mac addresses for ethernet boot if requested */
254     for (i = 0; i < ibl_N_BOOT_MODES; i++)  {
256         if (ibl.bootModes[i].bootMode == ibl_BOOT_MODE_TFTP)  {
258             if (iblMacAddrIsZero (ibl.bootModes[i].u.ethBoot.ethInfo.hwAddress))
260                 deviceLoadDefaultEthAddress (ibl.bootModes[i].u.ethBoot.ethInfo.hwAddress);
261         }
262     }
265     /* DDR configuration is device specific */
266     deviceDdrConfig ();
268     /* Try booting forever */
269     for (;;)  {
271 #ifndef EXCLUDE_MULTI_BOOT
272         v = DEVICE_REG32_R(DEVICE_JTAG_ID_REG);
273         v &= DEVICE_JTAG_ID_MASK;
274         if (
275             (v == DEVICE_C6678_JTAG_ID_VAL)         || 
276             (v == DEVICE_C6670_JTAG_ID_VAL)
277            )
278         {
279             IER = 0;
281             /* For C66x devices, check the DEVSTAT register to find which image on which device to boot. */
282             v = DEVICE_REG32_R(DEVICE_REG_DEVSTAT);
283             
284             /* Get the Endianness */
285             if (ibl_N_ENDIANS == 1)
286             {
287                 iblEndianIdx = 0;
288             }
289             else
290             {
291                 if (v & ibl_ENDIAN_LITTLE)
292                 {
293                     iblEndianIdx = 0;
294                 }
295                 else
296                 {
297                     iblEndianIdx = 1;
298                 }
299             }
301             /* Get the boot mode index */
302             boot_para_idx = BOOT_READ_BITFIELD(v,8,4);
304             /* Only 1 image supported for TFTP boot */
305             if (boot_para_idx > (ibl_N_IMAGES*(ibl_N_BOOT_MODES-1)))
306             {
307                 /* boot parameter index not supported */
308                 continue;
309             }
310             boot_mode_idx = boot_para_idx/ibl_N_IMAGES;
311             /* Get the boot image index */
312             iblImageIdx = boot_para_idx & (ibl_N_IMAGES - 1);
314             iblStatus.activeBoot = ibl.bootModes[boot_mode_idx].bootMode;
316             switch (ibl.bootModes[boot_mode_idx].bootMode)  
317             {
318 #ifndef EXCLUDE_ETH
319             case ibl_BOOT_MODE_TFTP:
320                 iblStatus.activeDevice = ibl_ACTIVE_DEVICE_ETH;
321                 iblMemcpy (&iblStatus.ethParams, &ibl.bootModes[boot_mode_idx].u.ethBoot.ethInfo, sizeof(iblEthBootInfo_t));
322                 iblEthBoot (boot_mode_idx);
323                 break;
324 #endif
325                 
326 #if ((!defined(EXCLUDE_NAND_EMIF)) || (!defined(EXCLUDE_NAND_GPIO)))
327             case ibl_BOOT_MODE_NAND:
328                 iblPmemCfg (ibl.bootModes[boot_mode_idx].u.nandBoot.interface, ibl.bootModes[boot_mode_idx].port, TRUE);
329                 memset ((void *)0x80000000, 0, 0x20000000);
330                 iblNandBoot (boot_mode_idx);
331                 break;
332 #endif
333                 
334 #if (!defined(EXCLUDE_NOR_EMIF) && !defined(EXCLUDE_NOR_SPI))
335             case ibl_BOOT_MODE_NOR:
336                 iblPmemCfg (ibl.bootModes[boot_mode_idx].u.norBoot.interface, ibl.bootModes[boot_mode_idx].port, TRUE);
337                 iblNorBoot (boot_mode_idx);
338                 break;
339 #endif
340             }
341             iblStatus.heartBeat += 1;
342         }
343         else
344 #endif
345         {
346             
347            /* For C64x devices, loop through the boot modes to find the one with the highest priority
348             * value, and try to boot it. */
349             for (i = ibl_HIGHEST_PRIORITY; i < ibl_LOWEST_PRIORITY; i++)  {
350                 
351                 for (j = 0; j < ibl_N_BOOT_MODES; j++)  {
352                     
353                     if (ibl.bootModes[j].priority == i)  {
354                         
355                         iblStatus.activeBoot = ibl.bootModes[j].bootMode;
356                         
357                         switch (ibl.bootModes[j].bootMode)  {
358                             
359                             
360 #ifndef EXCLUDE_ETH
361                         case ibl_BOOT_MODE_TFTP:
362                             iblStatus.activeDevice = ibl_ACTIVE_DEVICE_ETH;
363                             iblMemcpy (&iblStatus.ethParams, &ibl.bootModes[j].u.ethBoot.ethInfo, sizeof(iblEthBootInfo_t));
364                             iblEthBoot (j);
365                             break;
366 #endif
367                             
368 #if ((!defined(EXCLUDE_NAND_EMIF)) || (!defined(EXCLUDE_NAND_GPIO)))
369                         case ibl_BOOT_MODE_NAND:
370                             iblPmemCfg (ibl.bootModes[j].u.nandBoot.interface, ibl.bootModes[j].port, TRUE);
371                             iblNandBoot (j);
372                             break;
373 #endif
374                             
375 #if (!defined(EXCLUDE_NOR_EMIF) && !defined(EXCLUDE_NOR_SPI))
376                         case ibl_BOOT_MODE_NOR:
377                             iblPmemCfg (ibl.bootModes[j].u.norBoot.interface, ibl.bootModes[j].port, TRUE);
378                             iblNorBoot (j);
379                             break;
380 #endif
381                             
382                         }
383                     }
384                     
385                     iblStatus.heartBeat += 1;
386                     
387                 }
388             }
389         }
390     }
393 } /* main */
396     
397 /**
398  * @b Description
399  * @n
400  * 
401  * The ibl boot function links a device to a data format. The data format
402  * parser pulls data from the boot device
403  *
404  * @param[in] bootFxn      The structure containing the boot device functions
405  *
406  * @retval
407  *  None
408  */
409 Uint32 iblBoot (BOOT_MODULE_FXN_TABLE *bootFxn, Int32 dataFormat, void *formatParams)
410
411     Uint32  entry = 0;
412     Uint32  value32;
413     Uint8   dataBuf[4];   
414     Uint16  value16;
416     /* Determine the data format if required */
417     if (dataFormat == ibl_BOOT_FORMAT_AUTO)  {
419         (*bootFxn->peek)(dataBuf, sizeof(dataBuf));
420         value32 = (dataBuf[0] << 24) | (dataBuf[1] << 16) | (dataBuf[2] << 8) | (dataBuf[3] << 0);
421         value16 = (dataBuf[0] <<  8) | (dataBuf[1] <<  0);
423         /* BIS */
424 #ifndef EXCLUDE_BIS
425         if (value32 == BIS_MAGIC_NUMBER)
426             dataFormat = ibl_BOOT_FORMAT_BIS;
427 #endif
429 #ifndef EXCLUDE_COFF
430         if (iblIsCoff (value16))
431             dataFormat = ibl_BOOT_FORMAT_COFF;
432 #endif
434 #ifndef EXCLUDE_ELF
435         if (iblIsElf (dataBuf))
436             dataFormat = ibl_BOOT_FORMAT_ELF;
437 #endif
439         if (dataFormat == ibl_BOOT_FORMAT_AUTO)  {
440             iblStatus.autoDetectFailCnt += 1;
441             return (0);
442         }
443     }        
446     iblStatus.activeFileFormat = dataFormat;
449     /* Invoke the parser */
450     switch (dataFormat)  {
452 #ifndef EXCLUDE_BIS
453         case ibl_BOOT_FORMAT_BIS:
454             iblBootBis (bootFxn, &entry);
455             break;
456 #endif
458 #ifndef EXCLUDE_COFF
459         case ibl_BOOT_FORMAT_COFF:
460             iblBootCoff (bootFxn, &entry);
461             break;
462 #endif
464         case ibl_BOOT_FORMAT_BTBL:
465             iblBootBtbl (bootFxn, &entry);
466             break;
468 #ifndef EXCLUDE_BLOB
469         case ibl_BOOT_FORMAT_BBLOB:
470             iblBootBlob (bootFxn, &entry, formatParams);
471             break;
472 #endif
474 #ifndef EXCLUDE_ELF
475         case ibl_BOOT_FORMAT_ELF:
476             iblBootElf (bootFxn, &entry);
477             break;
478 #endif
480         default:
481             iblStatus.invalidDataFormatSpec += 1;
482             break;
484     }
485     
487     return (entry);