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)
100 {
101 free (mem);
102 }
104 /**
105 * @brief
106 * The memset function used for both stages of the ibl
107 */
108 void *iblMemset (void *mem, Int32 ch, Uint32 n)
109 {
110 return (memset (mem, ch, n));
111 }
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)
118 {
119 return (memcpy (s1, s2, n));
121 }
123 /**
124 * @brief
125 * Ones complement addition
126 */
127 inline uint16 onesComplementAdd (uint16 value1, uint16 value2)
128 {
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);
136 }
139 /**
140 * @brief
141 * Ones complement checksum computation
142 */
143 uint16 onesComplementChksum (uint16 * restrict p_data, uint16 len)
144 {
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)
163 {
164 v = (((v >> 24) & 0xff) << 0) |
165 (((v >> 16) & 0xff) << 8) |
166 (((v >> 8) & 0xff) << 16) |
167 (((v >> 0) & 0xff) << 24);
169 return (v);
171 }
173 /**
174 * @brief
175 * Do a 2 byte endian swap
176 */
177 uint16 swap16val (uint16 v)
178 {
179 v = (((v >> 8) & 0xff) << 0) |
180 (((v >> 0) & 0xff) << 8);
182 return (v);
184 }
186 /**
187 * @brief
188 * Do an endian swap on the ibl structure
189 */
190 void iblSwap (void)
191 {
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);
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 }
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);
295 }
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)
327 {
328 Int32 count;
330 if (iFifoIn >= iFifoOut)
331 count = iFifoIn - iFifoOut;
332 else
333 count = iFifoIn + I_MAX_BLOCK_SIZE - iFifoOut;
335 return (count);
337 }
340 /**
341 * @brief
342 * Read a byte from the fifo
343 */
344 Uint8 iFifoRead(void)
345 {
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);
360 }
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)
371 {
372 return (iblREAD_BITFIELD(v,15,0));
374 }
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)
381 {
382 return (iblREAD_BITFIELD(v,31,16));
383 }
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)
398 {
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 }
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)();
455 }