Fix for IRs 81908, 81906, 81876, 81800
[keystone-rtos/ibl.git] / src / device / c66x / c66xinit.c
1 /**
2  * @file c66xinit.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_c66x.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;
125     
126     }
128     return (w);
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 ()
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      
155 #ifdef IBL_ENABLE_PCIE_WORKAROUND
157 /* undocumented register in data manual 
158  * Bit 0 of this register is supposed to give the status of PCIe PLL lock*/
159 #define PCIE_STS_REG    0x262015C
161 /* Workaround for PCIe boot mode support for C6678/C6670 */
162 /* This is a temporary workaround should be removed once fixed in RBL */
164 /* PCIe Config register base on C6678/C6670 */
165 #define PCIE_BASE_ADDR 0x21800000
167 /* PCIe Application registers */
168 #define PCIE_APP_CMD_STATUS  0x4
169 #define PCIE_OB_SIZE         0x30
170 #define PCIE_APP_SERDES_CFG0 0x390
171 #define PCIE_APP_SERDES_CFG1 0x394
173 /* PCIe Local Configuration registers */
174 #define PCIE_VENDER_DEVICE_ID   0x1000
175 #define PCIE_STATUS_CMD         0x1004
176 #define PCIE_CLASSCODE_REVID    0x1008
177 #define PCIE_BAR0               0x1010
178 #define PCIE_BAR1               0x1014
179 #define PCIE_BAR2               0x1018
180 #define PCIE_BAR3               0x101c
181 #define PCIE_DEVICE_CAP         0x1074
182 #define PCIE_DEV_STAT_CTRL      0x1078
183 #define PCIE_LINK_STAT_CTRL     0x1080
184 #define PCIE_ACCR                   0x1118
185 #define PCIE_DEBUG0             0x1728
186 #define PCIE_PL_GEN2            0x180C
188 /* SERDES Configuration registers */
189 #define PCIE_SERDES_CFG_PLL 0x2620358
191 #define MAGIC_ADDR (*(volatile unsigned int *)0x87fffc)
193 /* */
195 extern cregister volatile unsigned int IER;
197 void waitForBoot(void)
199     void (*escape)();
200     UINT32  i;
202     /* Disable interrupts */
203     IER = 1;
204         MAGIC_ADDR = 0;
206     do {
207         for (i=0; i < 100; i++)
208             asm("    nop");
209     } while (MAGIC_ADDR == 0);
211     escape = (void (*)())(MAGIC_ADDR);
212     (*escape)();
215 void iblPCIeWorkaround()
217     UINT32  cmd_stat;
218     UINT32  reg,i;
220      /* Power up PCIe */
221     devicePowerPeriph (TARGET_PWR_PCIE);
222     for(i=0; i<1000; i++) asm (" NOP");
224     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_SERDES_CFG0), 0x00062320);  /* ss clock */
225     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_SERDES_CFG1), 0x00022320);  /* ss clock */
226       
227     /* Wait for PCIe PLL lock */
228     while(!(DEVICE_REG32_R(PCIE_STS_REG) & 1));
230     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_CLASSCODE_REVID), 0x04800001);  /* class = 4 */ 
231     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_LINK_STAT_CTRL),  0x10110080);  /* extended synch */
233     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_VENDER_DEVICE_ID),  0x8888104c); 
234     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_DEVICE_CAP),  0x288701); 
236         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_OB_SIZE),  0x00000003);          /* OB_SIZE = 8M */ 
237         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_PL_GEN2),  0x0000000F);
239     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0020); /* Set dbi_cs2 to allow access to the BAR registers */ 
240     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0x00003FFF);
241     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR1), 0x0007FFFF);
242     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR2), 0x003FFFFF);
243     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR3), 0x00FFFFFF);
245         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0);          /* dbi_cs2=0 */
247         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_STATUS_CMD), 0x00100146);
248     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_DEV_STAT_CTRL), 0x0000281F);
249     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_ACCR), 0x000001E0);
250     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0);
252     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0000007);    /* enable LTSSM, IN, OB */
253     while((DEVICE_REG32_R(PCIE_BASE_ADDR + PCIE_DEBUG0) & 0x11)!=0x11);    /* Wait for training to complete */
254  
255     /* Wait for the Boot from Host */
256     waitForBoot();
258     /* Will never reach here */
259     return;
262 #endif
264 #define FPGA_BM_GPI_STATUS_LO_REG           4   /* Boot Mode GPI Status (07-00 Low Byte) Register */
265 #define FPGA_BM_GPI_STATUS_HI_REG           5   /* Boot Mode GPI Status (15-08 High Byte) Register */
266 #define FPGA_ICS557_SEL_CTRL_REG            0x50 /* ICS 557 Clock Selection
267                                                     Control Register*/
268 #define FPGA_READ_REG_CMD(x)                ((x | 0x80) << 8)
269 #define FPGA_WRITE_REG_CMD(addr,byte)       (((addr & 0x7f) << 8) | (byte & 0xff))
271 /**
272  * @brief
273  *      Enter the ROM boot loader if the FPGA boot register
274  *      indicates it was not I2C address 0x51 boot, this is necessary
275  *      to apply the PLL workaround for non-I2C boot modes
276  */
277 void iblEnterRom ()
279     uint32      v, dev_stat, bm_lo, bm_hi;
280     void        (*exit)();
282     /* Power up the SPI */
283     devicePowerPeriph (TARGET_PWR_SPI);
285     /* Reset SPI */
286     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
288     /* Release Reset */
289     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_ENABLE);
291     /* CS1, CLK, in and out are functional pins, FPGA uses SPI CS1 */
292     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIPC0, 0xe02);
294     /* prescale=7, char len=16 */
295     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIFMT(0), 0x710);
297     /* C2TDELAY=0x6, T2CDELAY=0x3 */
298     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIDELAY, 0x6030000);
300     /* Clear the SPIDAT0 */
301     //DEVICE_REG32_R (DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0);
303     /* Master mode, enable SPI */
304     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR1, 0x01000003);
306     /* Read the BM status lo register */
307         DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0, FPGA_READ_REG_CMD(FPGA_BM_GPI_STATUS_LO_REG));
308     chipDelay32(10000);
309     v = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIFLG);
310     if ( v & 0x100)
311     {
312         bm_lo = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIBUF) & 0xff;
313     }
314     else
315     {
316         return;
317     }
319     /* Read the BM status hi register */
320         DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0, FPGA_READ_REG_CMD(FPGA_BM_GPI_STATUS_HI_REG));
321     chipDelay32(10000);
322     v = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIFLG);
323     if ( v & 0x100)
324     {
325         bm_hi = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIBUF) & 0xff;
326     }
327     else
328     {
329         return;
330     }
333     if ( (BOOT_READ_BITFIELD(bm_lo,3,1) != 0x5)     ||
334          (BOOT_READ_BITFIELD(bm_hi,3,3) == 0x0) )    
335     { 
336         /* Not i2c boot or i2c boot with address 0x50 */
338         /* Update the DEVSTAT to v1 */
339         dev_stat = DEVICE_REG32_R(DEVICE_REG_DEVSTAT );
340         dev_stat &= ~(0x0000080E);
341         dev_stat |= ((bm_hi << 8) | bm_lo);
342         
343         /* Update the DEVSTAT register for the intended Boot Device and i2c Addr */
344         DEVICE_REG32_W (DEVICE_REG_DEVSTAT, dev_stat);
346 #ifdef IBL_ENABLE_PCIE_WORKAROUND
347 #define BOOT_DEVICE_MASK    0xE
348 #define DEVSTAT_BOOTDEVICE_SHIFT    1
349 #define PCI_BOOT_MODE   0x4
351         if (((dev_stat & BOOT_DEVICE_MASK)>>DEVSTAT_BOOTDEVICE_SHIFT) == PCI_BOOT_MODE) {
352             /* Write ICS 557 Clock Selection Control Register in the FPGA */
353             /* 1 : FPGA_ICS557_SEL s driven high */
354                 DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0,
355                            FPGA_WRITE_REG_CMD(FPGA_ICS557_SEL_CTRL_REG,1));
356             chipDelay32(10000);
357             /* Reset SPI */
358             DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
360             iblPCIeWorkaround();
361             /* Will never reach here */
362         }
363 #endif
364         /* Reset SPI */
365         DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
367         exit = (void (*)())BOOT_ROM_ENTER_ADDRESS;
368         (*exit)();        
369     }
370     else
371     {
372         /* Update the DEVSTAT register for the actual boot configuration */
373         DEVICE_REG32_W (DEVICE_REG_DEVSTAT, ((bm_hi << 8) | bm_lo));
374     }
376     /* Reset SPI */
377     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
380 #if (!defined(EXCLUDE_NOR_SPI) || !defined(EXCLUDE_NAND_SPI))
381 /**
382  *  @brief
383  *      Return the default hardware configuration for SPI. If this information
384  *      is available in the boot ROM it is used, otherwise defaults are used.
385  */
386 void deviceLoadInitSpiConfig (void *vcfg)
388     uint32 v;
390     spiConfig_t *cfg = (spiConfig_t *)vcfg;
392     BOOT_PARAMS_COMMON_T *params;
393     BOOT_PARAMS_SPI_T    *spip;
395     v = *((Uint32 *)DEVICE_JTAG_ID_REG);
396     v &= DEVICE_JTAG_ID_MASK;
398     if (v == DEVICE_C6678_JTAG_ID_VAL)
399         params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6678;
400     else
401         params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6670;
404     /* SPI_ROM is a constant defined during make which enables the use of the
405      * parameters from the ROM boot loader */
406     if ((SPI_ROM == 1) && (params->boot_mode == BOOT_MODE_SPI))  {
408         spip = (BOOT_PARAMS_SPI_T *)params;
410         cfg->port      = 0;
411         cfg->mode      = spip->mode;
412         cfg->addrWidth = spip->addrWidth;
413         cfg->npin      = spip->nPins;
414         cfg->csel      = spip->csel;
415         cfg->c2tdelay  = spip->c2tdelay;
417         v = (UINT32)spip->cpuFreqMhz * 1000;  /* CPU frequency in kHz */
418         v = v / (DEVICE_SPI_MOD_DIVIDER * (((UINT32)(spip->busFreqMhz) * 1000) + spip->busFreqKhz));
420         if (v > DEVICE_SPI_MAX_DIVIDER)
421             v = DEVICE_SPI_MAX_DIVIDER;
423         cfg->clkdiv = v;
425     }  else  {
427         cfg->port      = 0;
428         cfg->mode      = SPI_MODE;
429         cfg->addrWidth = SPI_ADDR_WIDTH;
430         cfg->npin      = SPI_NPIN;
431         cfg->csel      = SPI_CSEL;
432         cfg->c2tdelay  = SPI_C2TDEL;
433         cfg->clkdiv    = SPI_CLKDIV;
435     }
438 #endif