1 /**
2 * @file c661xinit.c
3 *
4 * @brief
5 * c661x functions used during the initial stage of the ibl load
6 *
7 */
8 #include "ibl.h"
9 #include "iblloc.h"
10 #include "device.h"
11 #include "pllapi.h"
12 #include "spi_api.h"
13 #include "spi_loc.h"
14 #include "tiboot_c661x.h"
17 /**
18 * @brief Configure the PLLs
19 *
20 * @details
21 * The three PLLs are enabled. Only the main PLL has the ability to configure
22 * the multiplier and dividers.
23 */
24 void devicePllConfig (void)
25 {
27 /* Unlock the chip registers and leave them unlocked */
28 *((Uint32 *)0x2620038) = 0x83e70b13;
29 *((Uint32 *)0x262003c) = 0x95a4f1e0;
31 if (ibl.pllConfig[ibl_MAIN_PLL].doEnable == TRUE)
32 hwPllSetPll (MAIN_PLL,
33 ibl.pllConfig[ibl_MAIN_PLL].prediv,
34 ibl.pllConfig[ibl_MAIN_PLL].mult,
35 ibl.pllConfig[ibl_MAIN_PLL].postdiv);
37 if (ibl.pllConfig[ibl_DDR_PLL].doEnable == TRUE)
38 hwPllSetCfg2Pll (DEVICE_PLL_BASE(DDR_PLL),
39 ibl.pllConfig[ibl_DDR_PLL].prediv,
40 ibl.pllConfig[ibl_DDR_PLL].mult,
41 ibl.pllConfig[ibl_DDR_PLL].postdiv,
42 ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz,
43 ibl.pllConfig[ibl_DDR_PLL].pllOutFreqMhz);
45 if (ibl.pllConfig[ibl_NET_PLL].doEnable == TRUE)
46 hwPllSetCfgPll (DEVICE_PLL_BASE(NET_PLL),
47 ibl.pllConfig[ibl_NET_PLL].prediv,
48 ibl.pllConfig[ibl_NET_PLL].mult,
49 ibl.pllConfig[ibl_NET_PLL].postdiv,
50 ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz,
51 ibl.pllConfig[ibl_NET_PLL].pllOutFreqMhz);
54 }
57 /**
58 * @brief
59 * Return the endian status of the device
60 *
61 * @details
62 * Returns true if the device is executing in little endian mode
63 */
64 extern cregister volatile unsigned int CSR;
66 bool deviceIsLittleEndian (void)
67 {
68 if ((CSR & (1 << 8)) == 0)
69 return (FALSE);
71 return (TRUE);
73 }
76 /**
77 * @brief
78 * Return the device used for the second stage program load.
79 * For SPI NAND a second stage loader is required and this
80 * function must be changed to locate that fingerprint.
81 */
82 int32 deviceReadBootDevice (void)
83 {
84 uint32 v;
85 int32 w;
87 BOOT_PARAMS_COMMON_T *params;
89 #if (defined(EXCLUDE_NOR_SPI) && defined(EXCLUDE_NAND_SPI) && !defined(EXCLUDE_I2C))
91 return (BOOT_DEVICE_I2C);
93 #elif (defined(EXCLUDE_NOR_SPI) && !defined(EXCLUDE_NAND_SPI) && defined(EXCLUDE_I2C))
95 return (BOOT_DEVICE_NAND_SPI);
97 #elif (!defined(EXCLUDE_NOR_SPI) && defined(EXCLUDE_NAND_SPI) && defined(EXCLUDE_I2C))
99 return (BOOT_DEVICE_NOR_SPI);
101 #endif
103 v = *((Uint32 *)DEVICE_JTAG_ID_REG);
104 v &= DEVICE_JTAG_ID_MASK;
106 if (v == DEVICE_C6678_JTAG_ID_VAL)
107 params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6678;
108 else
109 params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6670;
111 switch (params->boot_mode) {
113 #ifndef EXCLUDE_I2C
114 case BOOT_MODE_I2C: w = BOOT_DEVICE_I2C;
115 break;
116 #endif
118 #ifndef EXCLUDE_NOR_SPI
119 case BOOT_MODE_SPI: w = BOOT_DEVICE_SPI_NOR;
120 break;
121 #endif
123 default: w = BOOT_DEVICE_INVALID;
124 break;
126 }
128 return (w);
129 }
131 #define L1PEDCMD 0x01846408
132 #define L2EDCEN 0x01846030
133 #define L2EDCMD 0x01846008
134 #define SMEDCC 0x0BC00010
135 /**
136 * @brief
137 * Enable the EDC for the local memory
138 */
139 void iblEnableEDC ()
140 {
141 /* Enable L1P EDC */
142 *(volatile unsigned int *)(L1PEDCMD) = 0x1; //Set EN(bit0)=1
144 /* Enable EDC L2EDCEN, set DL2CEN(bit0),PL2CEN(bit1),DL2SEN(bit2),PL2SEN(bit3),SDMAEN(bit4)=1 */
145 *(volatile unsigned int *)(L2EDCEN) |= 0x1F;
147 /* Enalble L2 EDC */
148 *(volatile unsigned int *)(L2EDCMD) = 0x1;
150 /* Enalbe MSMC EDC */
151 *(volatile unsigned int *)(SMEDCC) &= 0x7FFFFFFF; //Clear SEN(bit31)=0
152 *(volatile unsigned int *)(SMEDCC) |= 0x40000000; //Set ECM(bit30)=1
153 }
155 #define FPGA_BM_GPI_STATUS_LO_REG 4 /* Boot Mode GPI Status (07-00 Low Byte) Register */
156 #define FPGA_BM_GPI_STATUS_HI_REG 5 /* Boot Mode GPI Status (15-08 High Byte) Register */
157 #define FPGA_READ_REG_CMD(x) ((x | 0x80) << 8)
158 /**
159 * @brief
160 * Enter the ROM boot loader if the FPGA boot register
161 * indicates it was not I2C address 0x51 boot, this is necessary
162 * to apply the PLL workaround for non-I2C boot modes
163 */
164 void iblEnterRom ()
165 {
166 uint32 reg = DEVICE_REG32_R (DEVICE_REG_DEVSTAT);
167 uint32 v, dev_stat, bm_lo, bm_hi;
168 void (*exit)();
170 /* Power up the SPI */
171 devicePowerPeriph (TARGET_PWR_SPI);
173 /* Reset SPI */
174 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
176 /* Release Reset */
177 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_ENABLE);
179 /* CS1, CLK, in and out are functional pins, FPGA uses SPI CS1 */
180 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIPC0, 0xe02);
182 /* prescale=7, char len=16 */
183 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIFMT(0), 0x710);
185 /* C2TDELAY=0x6, T2CDELAY=0x3 */
186 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIDELAY, 0x6030000);
188 /* Clear the SPIDAT0 */
189 //DEVICE_REG32_R (DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0);
191 /* Master mode, enable SPI */
192 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR1, 0x01000003);
194 /* Read the BM status lo register */
195 DEVICE_REG32_W(DEVICE_SPI_BASE(0) + 0x38, FPGA_READ_REG_CMD(FPGA_BM_GPI_STATUS_LO_REG));
196 chipDelay32(10000);
197 v = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIFLG);
198 if ( v & 0x100)
199 {
200 bm_lo = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIBUF) & 0xff;
201 }
202 else
203 {
204 return;
205 }
207 /* Read the BM status hi register */
208 DEVICE_REG32_W(DEVICE_SPI_BASE(0) + 0x38, FPGA_READ_REG_CMD(FPGA_BM_GPI_STATUS_HI_REG));
209 chipDelay32(10000);
210 v = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIFLG);
211 if ( v & 0x100)
212 {
213 bm_hi = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIBUF) & 0xff;
214 }
215 else
216 {
217 return;
218 }
220 /* Reset SPI */
221 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
223 if ( (BOOT_READ_BITFIELD(bm_lo,3,1) != 0x5) ||
224 (BOOT_READ_BITFIELD(bm_hi,3,3) == 0x0) )
225 {
226 /* Not i2c boot or i2c boot with address 0x50 */
228 /* Update the DEVSTAT to v1 */
229 dev_stat = DEVICE_REG32_R(DEVICE_REG_DEVSTAT );
230 dev_stat &= ~(0x0000080E);
231 dev_stat |= ((bm_hi << 8) | bm_lo);
233 /* Update the DEVSTAT register for the intended Boot Device and i2c Addr */
234 DEVICE_REG32_W (DEVICE_REG_DEVSTAT, dev_stat);
236 exit = (void (*)())BOOT_ROM_ENTER_ADDRESS;
237 (*exit)();
238 }
239 else
240 {
241 /* Update the DEVSTAT register for the actual boot configuration */
242 DEVICE_REG32_W (DEVICE_REG_DEVSTAT, ((bm_hi << 8) | bm_lo));
243 }
244 }
246 #if (!defined(EXCLUDE_NOR_SPI) || !defined(EXCLUDE_NAND_SPI))
247 /**
248 * @brief
249 * Return the default hardware configuration for SPI. If this information
250 * is available in the boot ROM it is used, otherwise defaults are used.
251 */
252 void deviceLoadInitSpiConfig (void *vcfg)
253 {
254 uint32 v;
256 spiConfig_t *cfg = (spiConfig_t *)vcfg;
258 BOOT_PARAMS_COMMON_T *params;
259 BOOT_PARAMS_SPI_T *spip;
261 v = *((Uint32 *)DEVICE_JTAG_ID_REG);
262 v &= DEVICE_JTAG_ID_MASK;
264 if (v == DEVICE_C6678_JTAG_ID_VAL)
265 params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6678;
266 else
267 params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6670;
270 /* SPI_ROM is a constant defined during make which enables the use of the
271 * parameters from the ROM boot loader */
272 if ((SPI_ROM == 1) && (params->boot_mode == BOOT_MODE_SPI)) {
274 spip = (BOOT_PARAMS_SPI_T *)params;
276 cfg->port = 0;
277 cfg->mode = spip->mode;
278 cfg->addrWidth = spip->addrWidth;
279 cfg->npin = spip->nPins;
280 cfg->csel = spip->csel;
281 cfg->c2tdelay = spip->c2tdelay;
283 v = (UINT32)spip->cpuFreqMhz * 1000; /* CPU frequency in kHz */
284 v = v / (DEVICE_SPI_MOD_DIVIDER * (((UINT32)(spip->busFreqMhz) * 1000) + spip->busFreqKhz));
286 if (v > DEVICE_SPI_MAX_DIVIDER)
287 v = DEVICE_SPI_MAX_DIVIDER;
289 cfg->clkdiv = v;
291 } else {
293 cfg->port = 0;
294 cfg->mode = SPI_MODE;
295 cfg->addrWidth = SPI_ADDR_WIDTH;
296 cfg->npin = SPI_NPIN;
297 cfg->csel = SPI_CSEL;
298 cfg->c2tdelay = SPI_C2TDEL;
299 cfg->clkdiv = SPI_CLKDIV;
301 }
303 }
307 #endif