Merge pull request #3 in PROCESSOR-SDK/ibl from PRSDK-5675 to master
[keystone-rtos/ibl.git] / src / device / c66xk2x / c66xk2xinit.c
1 /*
2  *
3  * Copyright (C) 2010-2012 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 c66xk2xinit.c
38  *
39  * @brief
40  *              c66xk2x functions used during the initial stage of the ibl load
41  *
42  */
43 #include "ibl.h"
44 #include "iblloc.h"
45 #include "device.h"
46 #include "pllapi.h"
47 #include "spi_api.h"
48 #include "spi_loc.h"
49 #include "tiboot_c66xk2x.h"
52 /**
53  * @brief Configure the PLLs
54  *
55  * @details
56  *   The three PLLs are enabled. Only the main PLL has the ability to configure
57  *   the multiplier and dividers.
58  */
59 void devicePllConfig (void)
60 {
61     /* Unlock the chip registers and leave them unlocked */
62     *((Uint32 *)0x2620038) = 0x83e70b13;
63     *((Uint32 *)0x262003c) = 0x95a4f1e0;
65     if (ibl.pllConfig[ibl_MAIN_PLL].doEnable == TRUE)
66         hwPllSetPll (MAIN_PLL,
67                      ibl.pllConfig[ibl_MAIN_PLL].prediv,
68                      ibl.pllConfig[ibl_MAIN_PLL].mult,
69                      ibl.pllConfig[ibl_MAIN_PLL].postdiv);
71     if (ibl.pllConfig[ibl_NET_PLL].doEnable == TRUE)
72         hwPllSetCfgPll (DEVICE_PLL_BASE(NET_PLL),
73                         ibl.pllConfig[ibl_NET_PLL].prediv,
74                         ibl.pllConfig[ibl_NET_PLL].mult,
75                         ibl.pllConfig[ibl_NET_PLL].postdiv,
76                         ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz,
77                         ibl.pllConfig[ibl_NET_PLL].pllOutFreqMhz);
79     if (ibl.pllConfig[ibl_DDR_PLL].doEnable == TRUE)
80         hwPllSetCfg2Pll (DEVICE_PLL_BASE(DDR_PLL),
81                          ibl.pllConfig[ibl_DDR_PLL].prediv,
82                          ibl.pllConfig[ibl_DDR_PLL].mult,
83                          ibl.pllConfig[ibl_DDR_PLL].postdiv,
84                          ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz,
85                          ibl.pllConfig[ibl_DDR_PLL].pllOutFreqMhz);
87 }
90 /**
91  * @brief
92  *  Return the endian status of the device
93  *
94  * @details
95  *  Returns true if the device is executing in little endian mode
96  */
97 extern cregister volatile unsigned int CSR;
99 bool deviceIsLittleEndian (void)
101     if ((CSR & (1 << 8)) == 0)
102         return (FALSE);
104     return (TRUE);
109 /**
110  *  @brief
111  *      Return the device used for the second stage program load.
112  *      For SPI NAND a second stage loader is required and this
113  *      function must be changed to locate that fingerprint.
114  */
115 int32 deviceReadBootDevice (void)
117     uint32 v;
118     int32  w;
120     BOOT_PARAMS_COMMON_T *params;
122 #if  (defined(EXCLUDE_NOR_SPI) && defined(EXCLUDE_NAND_SPI) && !defined(EXCLUDE_I2C))
124     return (BOOT_DEVICE_I2C);
126 #elif (defined(EXCLUDE_NOR_SPI) && !defined(EXCLUDE_NAND_SPI) && defined(EXCLUDE_I2C))
128     return (BOOT_DEVICE_NAND_SPI);
130 #elif (!defined(EXCLUDE_NOR_SPI) && defined(EXCLUDE_NAND_SPI) && defined(EXCLUDE_I2C))
132     return (BOOT_DEVICE_NOR_SPI);
134 #endif
136     v = *((Uint32 *)DEVICE_JTAG_ID_REG);
137     v &= DEVICE_JTAG_ID_MASK;
139     if (v == DEVICE_TCI6636K2H_JTAG_ID_VAL)
140         params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_TCI6634K2K;
142     switch (params->boot_mode)  {
144 #ifndef EXCLUDE_I2C
145         case BOOT_MODE_I2C:   w = BOOT_DEVICE_I2C;
146                               break;
147 #endif
149 #ifndef EXCLUDE_NOR_SPI
150         case BOOT_MODE_SPI:   w = BOOT_DEVICE_SPI_NOR;
151                               break;
152 #endif
154         default:              w = BOOT_DEVICE_INVALID;
155                               break;
157     }
159     return (w);
162 #define L1PEDCMD            0x01846408
163 #define L2EDCEN             0x01846030
164 #define L2EDCMD             0x01846008
165 #define SMEDCC              0x0BC00010
166 /**
167  *  @brief
168  *      Enable the EDC for the local memory
169  */
170 void iblEnableEDC ()
172     /* Enable L1P EDC */
173     *(volatile unsigned int *)(L1PEDCMD) = 0x1; //Set EN(bit0)=1
175     /* Enable EDC L2EDCEN, set DL2CEN(bit0),PL2CEN(bit1),DL2SEN(bit2),PL2SEN(bit3),SDMAEN(bit4)=1 */
176         *(volatile unsigned int *)(L2EDCEN) |= 0x1F;
178     /* Enalble L2 EDC */
179     *(volatile unsigned int *)(L2EDCMD) = 0x1;
181     /* Enalbe MSMC EDC */
182     *(volatile unsigned int *)(SMEDCC) &= 0x7FFFFFFF;   //Clear SEN(bit31)=0
183         *(volatile unsigned int *)(SMEDCC) |= 0x40000000;       //Set ECM(bit30)=1
186 #ifdef IBL_ENABLE_PCIE_WORKAROUND
188 /* undocumented register in data manual
189  * Bit 0 of this register is supposed to give the status of PCIe PLL lock*/
190 #define PCIE_STS_REG    0x262015C
192 /* Workaround for PCIe boot mode support for C6678/C6670 */
193 /* This is a temporary workaround should be removed once fixed in RBL */
195 /* PCIe Config register base on C6678/C6670 */
196 #define PCIE_BASE_ADDR 0x21800000
198 /* PCIe Application registers */
199 #define PCIE_APP_CMD_STATUS  0x4
200 #define PCIE_APP_OB_SIZE     0x30
201 #define PCIE_APP_SERDES_CFG0 0x390
202 #define PCIE_APP_SERDES_CFG1 0x394
204 /* PCIe Local Configuration registers */
205 #define PCIE_VENDER_DEVICE_ID   0x1000
206 #define PCIE_STATUS_CMD         0x1004
207 #define PCIE_CLASSCODE_REVID    0x1008
208 #define PCIE_BAR0               0x1010
209 #define PCIE_BAR1               0x1014
210 #define PCIE_BAR2               0x1018
211 #define PCIE_BAR3               0x101c
212 #define PCIE_DEVICE_CAP         0x1074
213 #define PCIE_DEV_STAT_CTRL      0x1078
214 #define PCIE_LINK_STAT_CTRL     0x1080
215 #define PCIE_ACCR                   0x1118
216 #define PCIE_DEBUG0             0x1728
217 #define PCIE_PL_GEN2            0x180C
219 /* SERDES Configuration registers */
220 #define PCIE_SERDES_CFG_PLL 0x2620358
222 void waitForBoot(UINT32 MAGIC_ADDR)
224     void (*exit)();
225     UINT32 i, entry_addr;
227     while(1)
228     {
229         entry_addr = DEVICE_REG32_R(MAGIC_ADDR);
230         if (entry_addr != 0)
231         {
232             /* jump to the exit point, which will be the entry point for the full IBL */
233             exit = (void (*)())entry_addr;
234             (*exit)();
235         }
236         for (i=0; i < 100; i++)
237             asm("nop");
238         }
241 void iblPCIeWorkaround()
243     UINT32  v, flag_k2k = 0, MAGIC_ADDR;
244     UINT32  i;
246      /* Power up PCIe */
247     devicePowerPeriph (TARGET_PWR_PCIE);
248     for(i=0; i<1000; i++) asm (" NOP");
250     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_SERDES_CFG0), 0x00062320);  /* ss clock */
251     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_SERDES_CFG1), 0x00022320);  /* ss clock */
253     /* Wait for PCIe PLL lock */
254     while(!(DEVICE_REG32_R(PCIE_STS_REG) & 1));
256     v = *((Uint32 *)DEVICE_JTAG_ID_REG);
257     v &= DEVICE_JTAG_ID_MASK;
259     if (v == DEVICE_TCI6636K2H_JTAG_ID_VAL)
260     {
261         MAGIC_ADDR = 0x8ffffc;
262                 flag_k2k = 1;
263         }
265     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_CLASSCODE_REVID), 0x04800001);  /* class 0x04, sub-class 0x80, Prog I/F 0x00, Other multimedia device */
266     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_LINK_STAT_CTRL), 0x10110080);  /* extended sync, slot_clk_cfg = 1 */
268     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_VENDER_DEVICE_ID), 0xb005104c);  /* Vendor and Device ID */
269     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_DEVICE_CAP), 0x288701); /* L0 = 4, L1 = 3 */
271         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_OB_SIZE), 0x00000003);     /* OB_SIZE = 8M */
272         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_PL_GEN2), 0x0000000F);   /* num_fts = 0xF*/
274     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0020); /* Set dbi_cs2 to allow access to the BAR registers */
276         if (flag_k2k)  {
277                 /* TCI6634K2K TBD */
278                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0x00000FFF);   /* 4K */
279                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR1), 0x000FFFFF);   /* 1M */
280                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR2), 0x001FFFFF);   /* 2M */
281                 DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR3), 0x00FFFFFF);   /* 16M */
282     }
284         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0);    /* dbi_cs2=0 */
286         DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_STATUS_CMD), 0x00100146); /* ENABLE mem access */
287     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_DEV_STAT_CTRL), 0x0000281F); /* Error control */
288     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_ACCR), 0x000001E0); /* Error control */
289     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_BAR0), 0); /* non-prefetch, 32-bit, mem bar */
291     DEVICE_REG32_W ((PCIE_BASE_ADDR + PCIE_APP_CMD_STATUS), 0x0000007);    /* enable LTSSM, IN, OB */
292     while((DEVICE_REG32_R(PCIE_BASE_ADDR + PCIE_DEBUG0) & 0x11)!=0x11);    /* Wait for training to complete */
294     /* Wait for the Boot from Host */
295     DEVICE_REG32_W(MAGIC_ADDR, 0);
296         waitForBoot(MAGIC_ADDR);
298     /* Will never reach here */
299     return;
302 #endif
304 #define FPGA_BM_GPI_STATUS_LO_REG           4   /* Boot Mode GPI Status (07-00 Low Byte) Register */
305 #define FPGA_BM_GPI_STATUS_HI_REG           5   /* Boot Mode GPI Status (15-08 High Byte) Register */
306 #define FPGA_ICS557_SEL_CTRL_REG            0x50 /* ICS 557 Clock Selection
307                                                     Control Register*/
308 #define FPGA_READ_REG_CMD(x)                ((x | 0x80) << 8)
309 #define FPGA_WRITE_REG_CMD(addr,byte)       (((addr & 0x7f) << 8) | (byte & 0xff))
311 /**
312  * @brief
313  *      Enter the ROM boot loader if the FPGA boot register
314  *      indicates it was not I2C address 0x51 boot, this is necessary
315  *      to apply the PLL workaround for non-I2C boot modes
316  */
317 void iblEnterRom ()
319     uint32      v, dev_stat, bm_lo, bm_hi;
320     void        (*exit)();
322     /* Power up the SPI */
323     devicePowerPeriph (TARGET_PWR_SPI);
325     /* Reset SPI */
326     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
328     /* Release Reset */
329     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_ENABLE);
331     /* CS1, CLK, in and out are functional pins, FPGA uses SPI CS1 */
332     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIPC0, 0xe02);
334     /* prescale=7, char len=16 */
335     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIFMT(0), 0x710);
337     /* C2TDELAY=0x6, T2CDELAY=0x3 */
338     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIDELAY, 0x6030000);
340     /* Clear the SPIDAT0 */
341     //DEVICE_REG32_R (DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0);
343     /* Master mode, enable SPI */
344     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR1, 0x01000003);
346     /* Read the BM status lo register */
347         DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0, FPGA_READ_REG_CMD(FPGA_BM_GPI_STATUS_LO_REG));
348     chipDelay32(10000);
349     v = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIFLG);
350     if ( v & 0x100)
351     {
352         bm_lo = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIBUF) & 0xff;
353     }
354     else
355     {
356         return;
357     }
359     /* Read the BM status hi register */
360         DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0, FPGA_READ_REG_CMD(FPGA_BM_GPI_STATUS_HI_REG));
361     chipDelay32(10000);
362     v = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIFLG);
363     if ( v & 0x100)
364     {
365         bm_hi = DEVICE_REG32_R(DEVICE_SPI_BASE(0) + SPI_REG_SPIBUF) & 0xff;
366     }
367     else
368     {
369         return;
370     }
373     if ( (BOOT_READ_BITFIELD(bm_lo,3,1) != 0x5)     ||
374          (BOOT_READ_BITFIELD(bm_hi,3,3) == 0x0) )
375     {
376         /* Not i2c boot or i2c boot with address 0x50 */
378         /* Update the DEVSTAT to v1 */
379         dev_stat = DEVICE_REG32_R(DEVICE_REG_DEVSTAT );
380         dev_stat &= ~(0x0000080E);
381         dev_stat |= ((bm_hi << 8) | bm_lo);
383         /* Update the DEVSTAT register for the intended Boot Device and i2c Addr */
384         DEVICE_REG32_W (DEVICE_REG_DEVSTAT, dev_stat);
386 #ifdef IBL_ENABLE_PCIE_WORKAROUND /* TBD */
387 #define BOOT_DEVICE_MASK    0xE
388 #define DEVSTAT_BOOTDEVICE_SHIFT    1
389 #define PCI_BOOT_MODE   0x4
391         if (((dev_stat & BOOT_DEVICE_MASK)>>DEVSTAT_BOOTDEVICE_SHIFT) == PCI_BOOT_MODE) {
392             /* Write ICS 557 Clock Selection Control Register in the FPGA */
393             /* 1 : FPGA_ICS557_SEL s driven high */
394                 DEVICE_REG32_W(DEVICE_SPI_BASE(0) + SPI_REG_SPIDAT0,
395                            FPGA_WRITE_REG_CMD(FPGA_ICS557_SEL_CTRL_REG,1));
396             chipDelay32(10000);
397             /* Reset SPI */
398             DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
400             iblPCIeWorkaround();
401             /* Will never reach here */
402         }
403 #endif
404         /* Reset SPI */
405         DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
407         exit = (void (*)())BOOT_ROM_ENTER_ADDRESS;
408         (*exit)();
409     }
410     else
411     {
412         /* Update the DEVSTAT register for the actual boot configuration */
413         DEVICE_REG32_W (DEVICE_REG_DEVSTAT, ((bm_hi << 8) | bm_lo));
414     }
416     /* Reset SPI */
417     DEVICE_REG32_W (DEVICE_SPI_BASE(0) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
420 #if (!defined(EXCLUDE_NOR_SPI) || !defined(EXCLUDE_NAND_SPI))
421 /**
422  *  @brief
423  *      Return the default hardware configuration for SPI. If this information
424  *      is available in the boot ROM it is used, otherwise defaults are used.
425  */
426 void deviceLoadInitSpiConfig (void *vcfg)
428     uint32 v;
430     spiConfig_t *cfg = (spiConfig_t *)vcfg;
432     BOOT_PARAMS_COMMON_T *params;
433     BOOT_PARAMS_SPI_T    *spip;
435     v = *((Uint32 *)DEVICE_JTAG_ID_REG);
436     v &= DEVICE_JTAG_ID_MASK;
438     if (v == DEVICE_TCI6636K2H_JTAG_ID_VAL)
439         params = (BOOT_PARAMS_COMMON_T *)ROM_BOOT_PARAMS_ADDR_TCI6634K2K;
441     /* SPI_ROM is a constant defined during make which enables the use of the
442      * parameters from the ROM boot loader */
443     if ((SPI_ROM == 1) && (params->boot_mode == BOOT_MODE_SPI))  {
445         spip = (BOOT_PARAMS_SPI_T *)params;
447         cfg->port      = 0;
448         cfg->mode      = spip->mode;
449         cfg->addrWidth = spip->addrWidth;
450         cfg->npin      = spip->nPins;
451         cfg->csel      = spip->csel;
452         cfg->c2tdelay  = spip->c2tdelay;
454         v = (UINT32)spip->cpuFreqMhz * 1000;  /* CPU frequency in kHz */
455         v = v / (DEVICE_SPI_MOD_DIVIDER * (((UINT32)(spip->busFreqMhz) * 1000) + spip->busFreqKhz));
457         if (v > DEVICE_SPI_MAX_DIVIDER)
458             v = DEVICE_SPI_MAX_DIVIDER;
460         cfg->clkdiv = v;
462     }  else  {
464         cfg->port      = 0;
465         cfg->mode      = SPI_MODE;
466         cfg->addrWidth = SPI_ADDR_WIDTH;
467         cfg->npin      = SPI_NPIN;
468         cfg->csel      = SPI_CSEL;
469         cfg->c2tdelay  = SPI_C2TDEL;
470         cfg->clkdiv    = SPI_CLKDIV;
472     }
475 #endif