1 /**
2 * @file c665xinit.c
3 *
4 * @brief
5 * c66x 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_c665x.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 {
26 /* Unlock the chip registers and leave them unlocked */
27 *((Uint32 *)0x2620038) = 0x83e70b13;
28 *((Uint32 *)0x262003c) = 0x95a4f1e0;
30 if (ibl.pllConfig[ibl_MAIN_PLL].doEnable == TRUE)
31 hwPllSetPll (MAIN_PLL,
32 ibl.pllConfig[ibl_MAIN_PLL].prediv,
33 ibl.pllConfig[ibl_MAIN_PLL].mult,
34 ibl.pllConfig[ibl_MAIN_PLL].postdiv);
36 if (ibl.pllConfig[ibl_DDR_PLL].doEnable == TRUE)
37 hwPllSetCfg2Pll (DEVICE_PLL_BASE(DDR_PLL),
38 ibl.pllConfig[ibl_DDR_PLL].prediv,
39 ibl.pllConfig[ibl_DDR_PLL].mult,
40 ibl.pllConfig[ibl_DDR_PLL].postdiv,
41 ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz,
42 ibl.pllConfig[ibl_DDR_PLL].pllOutFreqMhz);
44 }
47 /**
48 * @brief
49 * Return the endian status of the device
50 *
51 * @details
52 * Returns true if the device is executing in little endian mode
53 */
54 extern cregister volatile unsigned int CSR;
56 bool deviceIsLittleEndian (void)
57 {
58 if ((CSR & (1 << 8)) == 0)
59 return (FALSE);
61 return (TRUE);
63 }
66 /**
67 * @brief
68 * Return the device used for the second stage program load.
69 * For SPI NAND a second stage loader is required and this
70 * function must be changed to locate that fingerprint.
71 */
72 int32 deviceReadBootDevice (void)
73 {
74 uint32 v;
75 int32 w;
77 BOOT_PARAMS_COMMON_T *params;
79 #if (defined(EXCLUDE_NOR_SPI) && defined(EXCLUDE_NAND_SPI) && !defined(EXCLUDE_I2C))
81 return (BOOT_DEVICE_I2C);
83 #elif (defined(EXCLUDE_NOR_SPI) && !defined(EXCLUDE_NAND_SPI) && defined(EXCLUDE_I2C))
85 return (BOOT_DEVICE_NAND_SPI);
87 #elif (!defined(EXCLUDE_NOR_SPI) && defined(EXCLUDE_NAND_SPI) && defined(EXCLUDE_I2C))
89 return (BOOT_DEVICE_NOR_SPI);
91 #endif
93 v = *((Uint32 *)DEVICE_JTAG_ID_REG);
94 v &= DEVICE_JTAG_ID_MASK;
96 if (v == DEVICE_C6657_JTAG_ID_VAL)
97 params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6657;
99 switch (params->boot_mode) {
101 #ifndef EXCLUDE_I2C
102 case BOOT_MODE_I2C: w = BOOT_DEVICE_I2C;
103 break;
104 #endif
106 #ifndef EXCLUDE_NOR_SPI
107 case BOOT_MODE_SPI: w = BOOT_DEVICE_SPI_NOR;
108 break;
109 #endif
111 default: w = BOOT_DEVICE_INVALID;
112 break;
114 }
116 return (w);
117 }
119 #define L1PEDCMD 0x01846408
120 #define L2EDCEN 0x01846030
121 #define L2EDCMD 0x01846008
122 #define SMEDCC 0x0BC00010
123 /**
124 * @brief
125 * Enable the EDC for the local memory
126 */
127 void iblEnableEDC ()
128 {
129 /* Enable L1P EDC */
130 *(volatile unsigned int *)(L1PEDCMD) = 0x1; //Set EN(bit0)=1
132 /* Enable EDC L2EDCEN, set DL2CEN(bit0),PL2CEN(bit1),DL2SEN(bit2),PL2SEN(bit3),SDMAEN(bit4)=1 */
133 *(volatile unsigned int *)(L2EDCEN) |= 0x1F;
135 /* Enalble L2 EDC */
136 *(volatile unsigned int *)(L2EDCMD) = 0x1;
138 /* Enalbe MSMC EDC */
139 *(volatile unsigned int *)(SMEDCC) &= 0x7FFFFFFF; //Clear SEN(bit31)=0
140 *(volatile unsigned int *)(SMEDCC) |= 0x40000000; //Set ECM(bit30)=1
141 }
143 #ifdef IBL_ENABLE_PCIE_WORKAROUND
145 /* undocumented register in data manual
146 * Bit 0 of this register is supposed to give the status of PCIe PLL lock*/
147 #define PCIE_STS_REG 0x262015C
149 /* Workaround for PCIe boot mode support for C6678/C6670 */
150 /* This is a temporary workaround should be removed once fixed in RBL */
152 /* PCIe Config register base on C6678/C6670 */
153 #define PCIE_BASE_ADDR 0x21800000
155 /* PCIe Application registers */
156 #define PCIE_APP_CMD_STATUS 0x4
157 #define PCIE_APP_OB_SIZE 0x30
158 #define PCIE_APP_SERDES_CFG0 0x390
159 #define PCIE_APP_SERDES_CFG1 0x394
161 /* PCIe Local Configuration registers */
162 #define PCIE_VENDER_DEVICE_ID 0x1000
163 #define PCIE_STATUS_CMD 0x1004
164 #define PCIE_CLASSCODE_REVID 0x1008
165 #define PCIE_BAR0 0x1010
166 #define PCIE_BAR1 0x1014
167 #define PCIE_BAR2 0x1018
168 #define PCIE_BAR3 0x101c
169 #define PCIE_DEVICE_CAP 0x1074
170 #define PCIE_DEV_STAT_CTRL 0x1078
171 #define PCIE_LINK_STAT_CTRL 0x1080
172 #define PCIE_ACCR 0x1118
173 #define PCIE_DEBUG0 0x1728
174 #define PCIE_PL_GEN2 0x180C
176 /* SERDES Configuration registers */
177 #define PCIE_SERDES_CFG_PLL 0x2620358
179 void waitForBoot(UINT32 MAGIC_ADDR)
180 {
181 void (*exit)();
182 UINT32 i, entry_addr;
184 while(1)
185 {
186 entry_addr = DEVICE_REG32_R(MAGIC_ADDR);
187 if (entry_addr != 0)
188 {
189 /* jump to the exit point, which will be the entry point for the full IBL */
190 exit = (void (*)())entry_addr;
191 (*exit)();
192 }
193 for (i=0; i < 100; i++)
194 asm("nop");
195 }
196 }
198 void iblPCIeWorkaround()
199 {
200 UINT32 v, flag_6678 = 0, flag_6670 = 0, flag_6657 = 0, MAGIC_ADDR;
201 UINT32 i;
203 /* Power up PCIe */
204 devicePowerPeriph (TARGET_PWR_PCIE);
205 for(i=0; i<1000; i++) asm (" NOP");
207 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_SERDES_CFG0), 0x00062320); /* ss clock */
208 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_SERDES_CFG1), 0x00022320); /* ss clock */
210 /* Wait for PCIe PLL lock */
211 while(!(DEVICE_REG32_R(PCIE_STS_REG) & 1));
213 /* Determine 6670 or 6678 */
214 v = *((Uint32 *)DEVICE_JTAG_ID_REG);
215 v &= DEVICE_JTAG_ID_MASK;
217 if (v == DEVICE_C6678_JTAG_ID_VAL) {
218 MAGIC_ADDR = 0x87fffc;
219 flag_6678 = 1;
220 }
221 if (v == DEVICE_C6670_JTAG_ID_VAL) {
222 MAGIC_ADDR = 0x8ffffc;
223 flag_6670 = 1;
224 }
225 if (v == DEVICE_C6657_JTAG_ID_VAL) {
226 MAGIC_ADDR = 0x8ffffc;
227 flag_6657 = 1;
228 }
231 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_CLASSCODE_REVID), 0x04800001); /* class 0x04, sub-class 0x80, Prog I/F 0x00, Other multimedia device */
232 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_LINK_STAT_CTRL), 0x10110080); /* extended sync, slot_clk_cfg = 1 */
234 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_VENDER_DEVICE_ID), 0xb005104c); /* Vendor and Device ID */
235 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_DEVICE_CAP), 0x288701); /* L0 = 4, L1 = 3 */
237 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_OB_SIZE), 0x00000003); /* OB_SIZE = 8M */
238 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_PL_GEN2), 0x0000000F); /* num_fts = 0xF*/
240 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0020); /* Set dbi_cs2 to allow access to the BAR registers */
242 if (flag_6678) {
243 /* 6678 */
244 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0x00000FFF); /* 4K */
245 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR1), 0x0007FFFF); /* 512K */
246 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR2), 0x003FFFFF); /* 4M */
247 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR3), 0x00FFFFFF); /* 16M */
248 }
250 if (flag_6670) {
251 /* 6670 */
252 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0x00000FFF); /* 4K */
253 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR1), 0x000FFFFF); /* 1M */
254 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR2), 0x001FFFFF); /* 2M */
255 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR3), 0x00FFFFFF); /* 16M */
256 }
257 if (flag_6657) {
258 /* 6657 */
259 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0x00000FFF); /* 4K */
260 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR1), 0x000FFFFF); /* 1M */
261 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR2), 0x000FFFFF); /* 1M */
262 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR3), 0x00FFFFFF); /* 16M */
263 }
264 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0); /* dbi_cs2=0 */
266 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_STATUS_CMD), 0x00100146); /* ENABLE mem access */
267 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_DEV_STAT_CTRL), 0x0000281F); /* Error control */
268 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_ACCR), 0x000001E0); /* Error control */
269 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0); /* non-prefetch, 32-bit, mem bar */
271 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0000007); /* enable LTSSM, IN, OB */
272 while((DEVICE_REG32_R(PCIE_BASE_ADDR + PCIE_DEBUG0) & 0x11)!=0x11); /* Wait for training to complete */
274 /* Wait for the Boot from Host */
275 DEVICE_REG32_W(MAGIC_ADDR, 0);
276 waitForBoot(MAGIC_ADDR);
278 /* Will never reach here */
279 return;
280 }
282 #endif
284 #define FPGA_BM_GPI_STATUS_LO_REG 4 /* Boot Mode GPI Status (07-00 Low Byte) Register */
285 #define FPGA_BM_GPI_STATUS_HI_REG 5 /* Boot Mode GPI Status (15-08 High Byte) Register */
286 #define FPGA_ICS557_SEL_CTRL_REG 0x50 /* ICS 557 Clock Selection
287 Control Register*/
288 #define FPGA_READ_REG_CMD(x) ((x | 0x80) << 8)
289 #define FPGA_WRITE_REG_CMD(addr,byte) (((addr & 0x7f) << 8) | (byte & 0xff))
291 /**
292 * @brief
293 * Enter the ROM boot loader if the FPGA boot register
294 * indicates it was not I2C address 0x51 boot, this is necessary
295 * to apply the PLL workaround for non-I2C boot modes
296 */
297 void iblEnterRom ()
298 {
299 uint32 v, dev_stat, bm_lo, bm_hi;
300 void (*exit)();
303 /* Reset SPI */
304 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
306 /* Release Reset */
307 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_ENABLE);
309 /* CS1, CLK, in and out are functional pins, FPGA uses SPI CS1 */
310 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIPC0, 0xe02);
312 /* prescale=7, char len=16 */
313 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIFMT(0), 0x710);
315 /* C2TDELAY=0x6, T2CDELAY=0x3 */
316 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIDELAY, 0x6030000);
318 /* Clear the SPIDAT0 */
319 //DEVICE_REG32_R (DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0);
321 /* Master mode, enable SPI */
322 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR1, 0x01000003);
324 /* Read the BM status lo register */
325 DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0, FPGA_READ_REG_CMD(FPGA_BM_GPI_STATUS_LO_REG));
326 chipDelay32(10000);
327 v = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIFLG);
328 if ( v & 0x100)
329 {
330 bm_lo = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIBUF) & 0xff;
331 }
332 else
333 {
334 return;
335 }
337 /* Read the BM status hi register */
338 DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0, FPGA_READ_REG_CMD(FPGA_BM_GPI_STATUS_HI_REG));
339 chipDelay32(10000);
340 v = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIFLG);
341 if ( v & 0x100)
342 {
343 bm_hi = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIBUF) & 0xff;
344 }
345 else
346 {
347 return;
348 }
351 if ( (BOOT_READ_BITFIELD(bm_lo,3,1) != 0x5) ||
352 (BOOT_READ_BITFIELD(bm_hi,3,3) == 0x0) )
353 {
354 /* Not i2c boot or i2c boot with address 0x50 */
356 /* Update the DEVSTAT to v1 */
357 dev_stat = DEVICE_REG32_R(DEVICE_REG_DEVSTAT );
358 dev_stat &= ~(0x0000080E);
359 dev_stat |= ((bm_hi << 8) | bm_lo);
361 /* Update the DEVSTAT register for the intended Boot Device and i2c Addr */
362 DEVICE_REG32_W (DEVICE_REG_DEVSTAT, dev_stat);
364 #ifdef IBL_ENABLE_PCIE_WORKAROUND
365 #define BOOT_DEVICE_MASK 0xE
366 #define DEVSTAT_BOOTDEVICE_SHIFT 1
367 #define PCI_BOOT_MODE 0x4
369 if (((dev_stat & BOOT_DEVICE_MASK)>>DEVSTAT_BOOTDEVICE_SHIFT) == PCI_BOOT_MODE) {
370 /* Write ICS 557 Clock Selection Control Register in the FPGA */
371 /* 1 : FPGA_ICS557_SEL s driven high */
372 DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0,
373 FPGA_WRITE_REG_CMD(FPGA_ICS557_SEL_CTRL_REG,1));
374 chipDelay32(10000);
375 /* Reset SPI */
376 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
378 iblPCIeWorkaround();
379 /* Will never reach here */
380 }
381 #endif
382 /* Reset SPI */
383 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
385 exit = (void (*)())BOOT_ROM_ENTER_ADDRESS;
386 (*exit)();
387 }
388 else
389 {
390 /* Update the DEVSTAT register for the actual boot configuration */
391 DEVICE_REG32_W (DEVICE_REG_DEVSTAT, ((bm_hi << 8) | bm_lo));
392 }
394 /* Reset SPI */
395 DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
396 }
398 #if (!defined(EXCLUDE_NOR_SPI) || !defined(EXCLUDE_NAND_SPI))
399 /**
400 * @brief
401 * Return the default hardware configuration for SPI. If this information
402 * is available in the boot ROM it is used, otherwise defaults are used.
403 */
404 void deviceLoadInitSpiConfig (void *vcfg)
405 {
406 uint32 v;
408 spiConfig_t *cfg = (spiConfig_t *)vcfg;
410 BOOT_PARAMS_COMMON_T *params;
411 BOOT_PARAMS_SPI_T *spip;
413 v = *((Uint32 *)DEVICE_JTAG_ID_REG);
414 v &= DEVICE_JTAG_ID_MASK;
416 if (v == DEVICE_C6657_JTAG_ID_VAL)
417 params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6657;
420 /* SPI_ROM is a constant defined during make which enables the use of the
421 * parameters from the ROM boot loader */
422 if ((SPI_ROM == 1) && (params->boot_mode == BOOT_MODE_SPI)) {
424 spip = (BOOT_PARAMS_SPI_T *)params;
426 cfg->port = 0;
427 cfg->mode = spip->mode;
428 cfg->addrWidth = spip->addrWidth;
429 cfg->npin = spip->nPins;
430 cfg->csel = spip->csel;
431 cfg->c2tdelay = spip->c2tdelay;
433 /* TODO:cpufreqMhz need update */
434 v = (UINT32)spip->cpuFreqMhz * 1000; /* CPU frequency in kHz */
435 v = v / (DEVICE_SPI_MOD_DIVIDER * (((UINT32)(spip->busFreqMhz) * 1000) + spip->busFreqKhz));
437 if (v > DEVICE_SPI_MAX_DIVIDER)
438 v = DEVICE_SPI_MAX_DIVIDER;
440 cfg->clkdiv = v;
442 } else {
444 cfg->port = 0;
445 cfg->mode = SPI_MODE;
446 cfg->addrWidth = SPI_ADDR_WIDTH;
447 cfg->npin = SPI_NPIN;
448 cfg->csel = SPI_CSEL;
449 cfg->c2tdelay = SPI_C2TDEL;
450 cfg->clkdiv = SPI_CLKDIV;
452 }
454 }
455 #endif