c66x: Use DDR3 PLL driver
[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 #define CHIP_LEVEL_REG          0x02620000
18 #define DDR3PLLCTL0             *(volatile unsigned int*)(CHIP_LEVEL_REG + 0x0330)
19 #define DDR3PLLCTL1             *(volatile unsigned int*)(CHIP_LEVEL_REG + 0x0334)
21 static void ddr3_delay (uint32 del)
22 {
23     volatile unsigned int i;
25     for (i = 0; i < del; i++);
27 }
29 /**
30  * @brief Configure the PLLs
31  *
32  * @details
33  *   The three PLLs are enabled. Only the main PLL has the ability to configure
34  *   the multiplier and dividers.
35  */
36 void devicePllConfig (void)
37 {
38         unsigned int i;
40     /* Unlock the chip registers and leave them unlocked */
41     *((Uint32 *)0x2620038) = 0x83e70b13;
42     *((Uint32 *)0x262003c) = 0x95a4f1e0;
44     if (ibl.pllConfig[ibl_MAIN_PLL].doEnable == TRUE)
45         hwPllSetPll (MAIN_PLL, 
46                      ibl.pllConfig[ibl_MAIN_PLL].prediv,
47                      ibl.pllConfig[ibl_MAIN_PLL].mult,
48                      ibl.pllConfig[ibl_MAIN_PLL].postdiv);
51     if (ibl.pllConfig[ibl_DDR_PLL].doEnable == TRUE)
52         hwPllSetCfg2Pll (DEVICE_PLL_BASE(DDR_PLL),
53                          ibl.pllConfig[ibl_DDR_PLL].prediv,
54                          ibl.pllConfig[ibl_DDR_PLL].mult,
55                          ibl.pllConfig[ibl_DDR_PLL].postdiv,
56                          ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz,
57                          ibl.pllConfig[ibl_DDR_PLL].pllOutFreqMhz);
60     if (ibl.pllConfig[ibl_NET_PLL].doEnable == TRUE)
61         hwPllSetCfgPll (DEVICE_PLL_BASE(NET_PLL),
62                         ibl.pllConfig[ibl_NET_PLL].prediv,
63                         ibl.pllConfig[ibl_NET_PLL].mult,
64                         ibl.pllConfig[ibl_NET_PLL].postdiv,
65                         ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz,
66                         ibl.pllConfig[ibl_NET_PLL].pllOutFreqMhz);
68 }
71 /**
72  * @brief
73  *  Return the endian status of the device
74  *
75  * @details
76  *  Returns true if the device is executing in little endian mode
77  */
78 extern cregister volatile unsigned int CSR;
80 bool deviceIsLittleEndian (void)
81 {
82     if ((CSR & (1 << 8)) == 0)    
83         return (FALSE);
85     return (TRUE);
87 }
90 /**
91  *  @brief
92  *      Return the device used for the second stage program load.
93  *      For SPI NAND a second stage loader is required and this
94  *      function must be changed to locate that fingerprint.
95  */
96 int32 deviceReadBootDevice (void)
97 {
98     uint32 v;
99     int32  w;
101     BOOT_PARAMS_COMMON_T *params;
103 #if  (defined(EXCLUDE_NOR_SPI) && defined(EXCLUDE_NAND_SPI) && !defined(EXCLUDE_I2C))
105     return (BOOT_DEVICE_I2C);
107 #elif (defined(EXCLUDE_NOR_SPI) && !defined(EXCLUDE_NAND_SPI) && defined(EXCLUDE_I2C))
109     return (BOOT_DEVICE_NAND_SPI);
111 #elif (!defined(EXCLUDE_NOR_SPI) && defined(EXCLUDE_NAND_SPI) && defined(EXCLUDE_I2C))
113     return (BOOT_DEVICE_NOR_SPI);
115 #endif
117     v = *((Uint32 *)DEVICE_JTAG_ID_REG);
118     v &= DEVICE_JTAG_ID_MASK;
120     if (v == DEVICE_C6678_JTAG_ID_VAL)
121         params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6678;
122     else
123         params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6670;
125     switch (params->boot_mode)  {
127 #ifndef EXCLUDE_I2C
128         case BOOT_MODE_I2C:   w = BOOT_DEVICE_I2C;
129                               break;
130 #endif
132 #ifndef EXCLUDE_NOR_SPI
133         case BOOT_MODE_SPI:   w = BOOT_DEVICE_SPI_NOR;
134                               break;
135 #endif
137         default:              w = BOOT_DEVICE_INVALID;
138                               break;
139     
140     }
142     return (w);
145 #define L1PEDCMD            0x01846408
146 #define L2EDCEN             0x01846030
147 #define L2EDCMD             0x01846008
148 #define SMEDCC              0x0BC00010
149 /**
150  *  @brief
151  *      Enable the EDC for the local memory 
152  */
153 void iblEnableEDC ()
155     /* Enable L1P EDC */
156     *(volatile unsigned int *)(L1PEDCMD) = 0x1; //Set EN(bit0)=1        
158     /* Enable EDC L2EDCEN, set DL2CEN(bit0),PL2CEN(bit1),DL2SEN(bit2),PL2SEN(bit3),SDMAEN(bit4)=1 */
159         *(volatile unsigned int *)(L2EDCEN) |= 0x1F;    
161     /* Enalble L2 EDC */
162     *(volatile unsigned int *)(L2EDCMD) = 0x1;
164     /* Enalbe MSMC EDC */
165     *(volatile unsigned int *)(SMEDCC) &= 0x7FFFFFFF;   //Clear SEN(bit31)=0    
166         *(volatile unsigned int *)(SMEDCC) |= 0x40000000;       //Set ECM(bit30)=1      
169 #ifdef IBL_ENABLE_PCIE_WORKAROUND
171 /* undocumented register in data manual 
172  * Bit 0 of this register is supposed to give the status of PCIe PLL lock*/
173 #define PCIE_STS_REG    0x262015C
175 /* Workaround for PCIe boot mode support for C6678/C6670 */
176 /* This is a temporary workaround should be removed once fixed in RBL */
178 /* PCIe Config register base on C6678/C6670 */
179 #define PCIE_BASE_ADDR 0x21800000
181 /* PCIe Application registers */
182 #define PCIE_APP_CMD_STATUS  0x4
183 #define PCIE_APP_OB_SIZE     0x30
184 #define PCIE_APP_SERDES_CFG0 0x390
185 #define PCIE_APP_SERDES_CFG1 0x394
187 /* PCIe Local Configuration registers */
188 #define PCIE_VENDER_DEVICE_ID   0x1000
189 #define PCIE_STATUS_CMD         0x1004
190 #define PCIE_CLASSCODE_REVID    0x1008
191 #define PCIE_BAR0               0x1010
192 #define PCIE_BAR1               0x1014
193 #define PCIE_BAR2               0x1018
194 #define PCIE_BAR3               0x101c
195 #define PCIE_DEVICE_CAP         0x1074
196 #define PCIE_DEV_STAT_CTRL      0x1078
197 #define PCIE_LINK_STAT_CTRL     0x1080
198 #define PCIE_ACCR                   0x1118
199 #define PCIE_DEBUG0             0x1728
200 #define PCIE_PL_GEN2            0x180C
202 /* SERDES Configuration registers */
203 #define PCIE_SERDES_CFG_PLL 0x2620358
205 void waitForBoot(UINT32 MAGIC_ADDR)
207     void (*exit)();
208     UINT32 i, entry_addr;
209         
210     while(1)
211     {
212         entry_addr = DEVICE_REG32_R(MAGIC_ADDR);
213         if (entry_addr != 0)
214         {
215             /* jump to the exit point, which will be the entry point for the full IBL */
216             exit = (void (*)())entry_addr;
217             (*exit)();
218         }
219         for (i=0; i < 100; i++)
220             asm("nop");
221         }
224 void iblPCIeWorkaround()
226     UINT32  v, flag_6678 = 0, flag_6670 = 0, MAGIC_ADDR;
227     UINT32  i;
229      /* Power up PCIe */
230     devicePowerPeriph (TARGET_PWR_PCIE);
231     for(i=0; i<1000; i++) asm (" NOP");
233     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_SERDES_CFG0), 0x00062320);  /* ss clock */
234     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_SERDES_CFG1), 0x00022320);  /* ss clock */
235       
236     /* Wait for PCIe PLL lock */
237     while(!(DEVICE_REG32_R(PCIE_STS_REG) & 1));
239         /* Determine 6670 or 6678 */
240     v = *((Uint32 *)DEVICE_JTAG_ID_REG);
241     v &= DEVICE_JTAG_ID_MASK;
242         
243     if (v == DEVICE_C6678_JTAG_ID_VAL) {
244                 MAGIC_ADDR = 0x87fffc;
245                 flag_6678 = 1;
246         } 
247         if (v == DEVICE_C6670_JTAG_ID_VAL) {
248         MAGIC_ADDR = 0x8ffffc;
249                 flag_6670 = 1;
250         }
252     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_CLASSCODE_REVID), 0x04800001);  /* class 0x04, sub-class 0x80, Prog I/F 0x00, Other multimedia device */ 
253     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_LINK_STAT_CTRL), 0x10110080);  /* extended sync, slot_clk_cfg = 1 */
255     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_VENDER_DEVICE_ID), 0xb005104c);  /* Vendor and Device ID */
256     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_DEVICE_CAP), 0x288701); /* L0 = 4, L1 = 3 */
258         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_OB_SIZE), 0x00000003);     /* OB_SIZE = 8M */ 
259         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_PL_GEN2), 0x0000000F);   /* num_fts = 0xF*/
261     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0020); /* Set dbi_cs2 to allow access to the BAR registers */ 
262  
263         if (flag_6678)  {
264                 /* 6678 */
265                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0x00000FFF);   /* 4K */
266                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR1), 0x0007FFFF);   /* 512K */
267                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR2), 0x003FFFFF);   /* 4M */
268                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR3), 0x00FFFFFF);   /* 16M */
269         } 
271         if (flag_6670)  {
272                 /* 6670 */
273                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0x00000FFF);   /* 4K */
274                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR1), 0x000FFFFF);   /* 1M */
275                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR2), 0x001FFFFF);   /* 2M */
276                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR3), 0x00FFFFFF);   /* 16M */
277     }
279         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0);    /* dbi_cs2=0 */
281         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_STATUS_CMD), 0x00100146); /* ENABLE mem access */
282     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_DEV_STAT_CTRL), 0x0000281F); /* Error control */
283     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_ACCR), 0x000001E0); /* Error control */
284     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0); /* non-prefetch, 32-bit, mem bar */
286     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0000007);    /* enable LTSSM, IN, OB */
287     while((DEVICE_REG32_R(PCIE_BASE_ADDR + PCIE_DEBUG0) & 0x11)!=0x11);    /* Wait for training to complete */
288  
289     /* Wait for the Boot from Host */
290     DEVICE_REG32_W(MAGIC_ADDR, 0);
291         waitForBoot(MAGIC_ADDR);
293     /* Will never reach here */
294     return;
297 #endif
299 #define FPGA_BM_GPI_STATUS_LO_REG           4   /* Boot Mode GPI Status (07-00 Low Byte) Register */
300 #define FPGA_BM_GPI_STATUS_HI_REG           5   /* Boot Mode GPI Status (15-08 High Byte) Register */
301 #define FPGA_ICS557_SEL_CTRL_REG            0x50 /* ICS 557 Clock Selection
302                                                     Control Register*/
303 #define FPGA_READ_REG_CMD(x)                ((x | 0x80) << 8)
304 #define FPGA_WRITE_REG_CMD(addr,byte)       (((addr & 0x7f) << 8) | (byte & 0xff))
306 /**
307  * @brief
308  *      Enter the ROM boot loader if the FPGA boot register
309  *      indicates it was not I2C address 0x51 boot, this is necessary
310  *      to apply the PLL workaround for non-I2C boot modes
311  */
312 void iblEnterRom ()
314     uint32      v, dev_stat, bm_lo, bm_hi;
315     void        (*exit)();
317     /* Power up the SPI */
318     devicePowerPeriph (TARGET_PWR_SPI);
320     /* Reset SPI */
321     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
323     /* Release Reset */
324     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_ENABLE);
326     /* CS1, CLK, in and out are functional pins, FPGA uses SPI CS1 */
327     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIPC0, 0xe02);
329     /* prescale=7, char len=16 */
330     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIFMT(0), 0x710);
332     /* C2TDELAY=0x6, T2CDELAY=0x3 */
333     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIDELAY, 0x6030000);
335     /* Clear the SPIDAT0 */
336     //DEVICE_REG32_R (DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0);
338     /* Master mode, enable SPI */
339     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR1, 0x01000003);
341     /* Read the BM status lo register */
342         DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0, FPGA_READ_REG_CMD(FPGA_BM_GPI_STATUS_LO_REG));
343     chipDelay32(10000);
344     v = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIFLG);
345     if ( v & 0x100)
346     {
347         bm_lo = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIBUF) & 0xff;
348     }
349     else
350     {
351         return;
352     }
354     /* Read the BM status hi register */
355         DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0, FPGA_READ_REG_CMD(FPGA_BM_GPI_STATUS_HI_REG));
356     chipDelay32(10000);
357     v = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIFLG);
358     if ( v & 0x100)
359     {
360         bm_hi = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIBUF) & 0xff;
361     }
362     else
363     {
364         return;
365     }
368     if ( (BOOT_READ_BITFIELD(bm_lo,3,1) != 0x5)     ||
369          (BOOT_READ_BITFIELD(bm_hi,3,3) == 0x0) )    
370     { 
371         /* Not i2c boot or i2c boot with address 0x50 */
373         /* Update the DEVSTAT to v1 */
374         dev_stat = DEVICE_REG32_R(DEVICE_REG_DEVSTAT );
375         dev_stat &= ~(0x0000080E);
376         dev_stat |= ((bm_hi << 8) | bm_lo);
377         
378         /* Update the DEVSTAT register for the intended Boot Device and i2c Addr */
379         DEVICE_REG32_W (DEVICE_REG_DEVSTAT, dev_stat);
381 #ifdef IBL_ENABLE_PCIE_WORKAROUND
382 #define BOOT_DEVICE_MASK    0xE
383 #define DEVSTAT_BOOTDEVICE_SHIFT    1
384 #define PCI_BOOT_MODE   0x4
386         if (((dev_stat & BOOT_DEVICE_MASK)>>DEVSTAT_BOOTDEVICE_SHIFT) == PCI_BOOT_MODE) {
387             /* Write ICS 557 Clock Selection Control Register in the FPGA */
388             /* 1 : FPGA_ICS557_SEL s driven high */
389                 DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0,
390                            FPGA_WRITE_REG_CMD(FPGA_ICS557_SEL_CTRL_REG,1));
391             chipDelay32(10000);
392             /* Reset SPI */
393             DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
395             iblPCIeWorkaround();
396             /* Will never reach here */
397         }
398 #endif
399         /* Reset SPI */
400         DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
402         exit = (void (*)())BOOT_ROM_ENTER_ADDRESS;
403         (*exit)();        
404     }
405     else
406     {
407         /* Update the DEVSTAT register for the actual boot configuration */
408         DEVICE_REG32_W (DEVICE_REG_DEVSTAT, ((bm_hi << 8) | bm_lo));
409     }
411     /* Reset SPI */
412     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
415 #if (!defined(EXCLUDE_NOR_SPI) || !defined(EXCLUDE_NAND_SPI))
416 /**
417  *  @brief
418  *      Return the default hardware configuration for SPI. If this information
419  *      is available in the boot ROM it is used, otherwise defaults are used.
420  */
421 void deviceLoadInitSpiConfig (void *vcfg)
423     uint32 v;
425     spiConfig_t *cfg = (spiConfig_t *)vcfg;
427     BOOT_PARAMS_COMMON_T *params;
428     BOOT_PARAMS_SPI_T    *spip;
430     v = *((Uint32 *)DEVICE_JTAG_ID_REG);
431     v &= DEVICE_JTAG_ID_MASK;
433     if (v == DEVICE_C6678_JTAG_ID_VAL)
434         params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6678;
435     else
436         params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_C6670;
439     /* SPI_ROM is a constant defined during make which enables the use of the
440      * parameters from the ROM boot loader */
441     if ((SPI_ROM == 1) && (params->boot_mode == BOOT_MODE_SPI))  {
443         spip = (BOOT_PARAMS_SPI_T *)params;
445         cfg->port      = 0;
446         cfg->mode      = spip->mode;
447         cfg->addrWidth = spip->addrWidth;
448         cfg->npin      = spip->nPins;
449         cfg->csel      = spip->csel;
450         cfg->c2tdelay  = spip->c2tdelay;
452         v = (UINT32)spip->cpuFreqMhz * 1000;  /* CPU frequency in kHz */
453         v = v / (DEVICE_SPI_MOD_DIVIDER * (((UINT32)(spip->busFreqMhz) * 1000) + spip->busFreqKhz));
455         if (v > DEVICE_SPI_MAX_DIVIDER)
456             v = DEVICE_SPI_MAX_DIVIDER;
458         cfg->clkdiv = v;
460     }  else  {
462         cfg->port      = 0;
463         cfg->mode      = SPI_MODE;
464         cfg->addrWidth = SPI_ADDR_WIDTH;
465         cfg->npin      = SPI_NPIN;
466         cfg->csel      = SPI_CSEL;
467         cfg->c2tdelay  = SPI_C2TDEL;
468         cfg->clkdiv    = SPI_CLKDIV;
470     }
473 #endif